Browse Source

initial import from gnunet.git

master
Christian Grothoff 5 years ago
commit
1f59e703d8
No known key found for this signature in database GPG Key ID: 939E6BE1E29FC3CC
100 changed files with 45812 additions and 0 deletions
  1. +1282
    -0
      ABOUT-NLS
  2. +1
    -0
      AUTHORS
  3. +674
    -0
      COPYING
  4. +14
    -0
      ChangeLog
  5. +365
    -0
      INSTALL
  6. +9
    -0
      Makefile.am
  7. +0
    -0
      NEWS
  8. +1
    -0
      README
  9. +8
    -0
      bootstrap
  10. +672
    -0
      config.rpath
  11. +221
    -0
      configure.ac
  12. +35
    -0
      m4/ac_define_dir.m4
  13. +383
    -0
      m4/gettext.m4
  14. +214
    -0
      m4/iconv.m4
  15. +110
    -0
      m4/lib-ld.m4
  16. +774
    -0
      m4/lib-link.m4
  17. +224
    -0
      m4/lib-prefix.m4
  18. +8387
    -0
      m4/libtool.m4
  19. +437
    -0
      m4/ltoptions.m4
  20. +124
    -0
      m4/ltsugar.m4
  21. +23
    -0
      m4/ltversion.m4
  22. +99
    -0
      m4/lt~obsolete.m4
  23. +32
    -0
      m4/nls.m4
  24. +57
    -0
      m4/pkg.m4
  25. +449
    -0
      m4/po.m4
  26. +92
    -0
      m4/progtest.m4
  27. +25
    -0
      pkgconfig/Makefile.am
  28. +12
    -0
      pkgconfig/gnunetmulticast.pc.in
  29. +12
    -0
      pkgconfig/gnunetpsyc.pc.in
  30. +12
    -0
      pkgconfig/gnunetpsycstore.pc.in
  31. +6
    -0
      po/.gitignore
  32. +12
    -0
      po/ChangeLog
  33. +444
    -0
      po/Makefile.in.in
  34. +41
    -0
      po/Makevars
  35. +2
    -0
      po/POTFILES.in
  36. +47
    -0
      po/Rules-quot
  37. +10
    -0
      po/boldquot.sed
  38. +25
    -0
      po/en@boldquot.header
  39. +22
    -0
      po/en@quot.header
  40. +23
    -0
      po/insert-header.sin
  41. +6
    -0
      po/quot.sed
  42. +19
    -0
      po/remove-potcdate.sin
  43. +2
    -0
      src/.gitignore
  44. +7
    -0
      src/Makefile.am
  45. +2
    -0
      src/include/.gitignore
  46. +15
    -0
      src/include/Makefile.am
  47. +925
    -0
      src/include/gnunet_multicast_service.h
  48. +340
    -0
      src/include/gnunet_psyc_env.h
  49. +278
    -0
      src/include/gnunet_psyc_message.h
  50. +1364
    -0
      src/include/gnunet_psyc_service.h
  51. +378
    -0
      src/include/gnunet_psyc_slicer.h
  52. +53
    -0
      src/include/gnunet_psyc_util_lib.h
  53. +383
    -0
      src/include/gnunet_psycstore_plugin.h
  54. +701
    -0
      src/include/gnunet_psycstore_service.h
  55. +1344
    -0
      src/include/gnunet_social_service.h
  56. +7
    -0
      src/multicast/.gitignore
  57. +79
    -0
      src/multicast/Makefile.am
  58. +79
    -0
      src/multicast/gnunet-multicast.c
  59. +2234
    -0
      src/multicast/gnunet-service-multicast.c
  60. +22
    -0
      src/multicast/multicast.conf.in
  61. +303
    -0
      src/multicast/multicast.h
  62. +1399
    -0
      src/multicast/multicast_api.c
  63. +758
    -0
      src/multicast/test_multicast.c
  64. +56
    -0
      src/multicast/test_multicast.conf
  65. +520
    -0
      src/multicast/test_multicast_2peers.c
  66. +63
    -0
      src/multicast/test_multicast_line.conf
  67. +643
    -0
      src/multicast/test_multicast_multipeer.c
  68. +64
    -0
      src/multicast/test_multicast_star.conf
  69. +2
    -0
      src/psyc/.gitignore
  70. +77
    -0
      src/psyc/Makefile.am
  71. +2860
    -0
      src/psyc/gnunet-service-psyc.c
  72. +12
    -0
      src/psyc/psyc.conf.in
  73. +178
    -0
      src/psyc/psyc.h
  74. +1584
    -0
      src/psyc/psyc_api.c
  75. +67
    -0
      src/psyc/psyc_test_lib.h
  76. +1018
    -0
      src/psyc/test_psyc.c
  77. +284
    -0
      src/psyc/test_psyc2.c
  78. +282
    -0
      src/psyc/test_psyc_api_join.c
  79. +5
    -0
      src/psycstore/.gitignore
  80. +155
    -0
      src/psycstore/Makefile.am
  81. +1049
    -0
      src/psycstore/gnunet-service-psycstore.c
  82. +1960
    -0
      src/psycstore/plugin_psycstore_mysql.c
  83. +1530
    -0
      src/psycstore/plugin_psycstore_postgres.c
  84. +1948
    -0
      src/psycstore/plugin_psycstore_sqlite.c
  85. +28
    -0
      src/psycstore/psycstore.conf.in
  86. +520
    -0
      src/psycstore/psycstore.h
  87. +1285
    -0
      src/psycstore/psycstore_api.c
  88. +532
    -0
      src/psycstore/test_plugin_psycstore.c
  89. +7
    -0
      src/psycstore/test_plugin_psycstore_mysql.conf
  90. +2
    -0
      src/psycstore/test_plugin_psycstore_postgres.conf
  91. +2
    -0
      src/psycstore/test_plugin_psycstore_sqlite.conf
  92. +586
    -0
      src/psycstore/test_psycstore.c
  93. +8
    -0
      src/psycstore/test_psycstore.conf
  94. +1
    -0
      src/psycutil/.gitignore
  95. +45
    -0
      src/psycutil/Makefile.am
  96. +196
    -0
      src/psycutil/psyc_env.c
  97. +1355
    -0
      src/psycutil/psyc_message.c
  98. +711
    -0
      src/psycutil/psyc_slicer.c
  99. +96
    -0
      src/psycutil/test_psyc_env.c
  100. +3
    -0
      src/social/.gitignore

+ 1282
- 0
ABOUT-NLS
File diff suppressed because it is too large
View File


+ 1
- 0
AUTHORS View File

@@ -0,0 +1 @@
Christian Grothoff

+ 674
- 0
COPYING View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007

Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
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.

<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>

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 <http://www.gnu.org/licenses/>.

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:

<program> Copyright (C) <year> <name of author>
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
<http://www.gnu.org/licenses/>.

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
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

+ 14
- 0
ChangeLog View File

@@ -0,0 +1,14 @@
2012-03-07 gettextize <bug-gnu-gettext@gnu.org>

* m4/gettext.m4: New file, from gettext-0.18.1.
* m4/iconv.m4: New file, from gettext-0.18.1.
* m4/lib-ld.m4: New file, from gettext-0.18.1.
* m4/lib-link.m4: New file, from gettext-0.18.1.
* m4/lib-prefix.m4: New file, from gettext-0.18.1.
* m4/nls.m4: New file, from gettext-0.18.1.
* m4/po.m4: New file, from gettext-0.18.1.
* m4/progtest.m4: New file, from gettext-0.18.1.
* Makefile.am (SUBDIRS): Add po.
* configure.ac (AC_OUTPUT): Add po/Makefile.in.
(AM_GNU_GETTEXT_VERSION): Bump to 0.18.1.


+ 365
- 0
INSTALL View File

@@ -0,0 +1,365 @@
Installation Instructions
*************************

Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006, 2007, 2008, 2009 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 commands `./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.

On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' 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 bug. Until the bug is fixed you can use this workaround:

CONFIG_SHELL=/bin/bash /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.


+ 9
- 0
Makefile.am View File

@@ -0,0 +1,9 @@
# This Makefile.am is in the public domain
## Process this file with automake to produce Makefile.in

SUBDIRS = src po pkgconfig

EXTRA_DIST = config.rpath \
install-sh

ACLOCAL_AMFLAGS = -I m4

+ 0
- 0
NEWS View File


+ 1
- 0
README View File

@@ -0,0 +1 @@
Experimental code for SecuShare.

+ 8
- 0
bootstrap View File

@@ -0,0 +1,8 @@
#!/bin/sh

libtoolize --automake --copy --force
aclocal -I m4
autoheader
autoconf
automake --add-missing --copy


+ 672
- 0
config.rpath View File

@@ -0,0 +1,672 @@
#! /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-2010 Free Software Foundation, Inc.
# Taken from GNU libtool, 2001
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 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 _LT_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* | cygwin* | pw32* | os2* | cegcc*)
;;
hpux9* | hpux10* | hpux11*)
wl='-Wl,'
;;
irix5* | irix6* | nonstopux*)
wl='-Wl,'
;;
newsos6)
;;
linux* | k*bsd*-gnu)
case $cc_basename in
ecc*)
wl='-Wl,'
;;
icc* | ifort*)
wl='-Wl,'
;;
lf95*)
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,'
;;
rdos*)
;;
solaris*)
wl='-Wl,'
;;
sunos4*)
wl='-Qoption ld '
;;
sysv4 | sysv4.2uw2* | sysv4.3*)
wl='-Wl,'
;;
sysv4*MP*)
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
wl='-Wl,'
;;
unicos*)
wl='-Wl,'
;;
uts4*)
;;
esac
fi

# Code taken from libtool.m4's _LT_LINKER_SHLIBS.

hardcode_libdir_flag_spec=
hardcode_libdir_separator=
hardcode_direct=no
hardcode_minus_L=no

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
;;
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
aix[3-9]*)
# 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 <kc5tja@dolphin.openprojects.net> 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* | cegcc*)
# 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
;;
interix[3-9]*)
hardcode_direct=no
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
;;
gnu* | linux* | k*bsd*-gnu)
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
;;
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
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
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
:
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* | 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.
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* | 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*)
if test -f /usr/libexec/ld.so; then
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
else
ld_shlibs=no
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* | sco3.2v5.0.[024]*)
;;
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 _LT_SYS_DYNAMIC_LINKER.
# Unlike libtool.m4, here we don't care about _all_ names of the library, but
# only about the one the linker finds when passed -lNAME. This is the last
# element of library_names_spec in libtool.m4, or possibly two of them if the
# linker has special search rules.
library_names_spec= # the last element of library_names_spec in libtool.m4
libname_spec='lib$name'
case "$host_os" in
aix3*)
library_names_spec='$libname.a'
;;
aix[4-9]*)
library_names_spec='$libname$shrext'
;;
amigaos*)
library_names_spec='$libname.a'
;;
beos*)
library_names_spec='$libname$shrext'
;;
bsdi[45]*)
library_names_spec='$libname$shrext'
;;
cygwin* | mingw* | pw32* | cegcc*)
shrext=.dll
library_names_spec='$libname.dll.a $libname.lib'
;;
darwin* | rhapsody*)
shrext=.dylib
library_names_spec='$libname$shrext'
;;
dgux*)
library_names_spec='$libname$shrext'
;;
freebsd1*)
;;
freebsd* | dragonfly*)
case "$host_os" in
freebsd[123]*)
library_names_spec='$libname$shrext$versuffix' ;;
*)
library_names_spec='$libname$shrext' ;;
esac
;;
gnu*)
library_names_spec='$libname$shrext'
;;
hpux9* | hpux10* | hpux11*)
case $host_cpu in
ia64*)
shrext=.so
;;
hppa*64*)
shrext=.sl
;;
*)
shrext=.sl
;;
esac
library_names_spec='$libname$shrext'
;;
interix[3-9]*)
library_names_spec='$libname$shrext'
;;
irix5* | irix6* | nonstopux*)
library_names_spec='$libname$shrext'
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* | k*bsd*-gnu)
library_names_spec='$libname$shrext'
;;
knetbsd*-gnu)
library_names_spec='$libname$shrext'
;;
netbsd*)
library_names_spec='$libname$shrext'
;;
newsos6)
library_names_spec='$libname$shrext'
;;
nto-qnx*)
library_names_spec='$libname$shrext'
;;
openbsd*)
library_names_spec='$libname$shrext$versuffix'
;;
os2*)
libname_spec='$name'
shrext=.dll
library_names_spec='$libname.a'
;;
osf3* | osf4* | osf5*)
library_names_spec='$libname$shrext'
;;
rdos*)
;;
solaris*)
library_names_spec='$libname$shrext'
;;
sunos4*)
library_names_spec='$libname$shrext$versuffix'
;;
sysv4 | sysv4.3*)
library_names_spec='$libname$shrext'
;;
sysv4*MP*)
library_names_spec='$libname$shrext'
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
library_names_spec='$libname$shrext'
;;
uts4*)
library_names_spec='$libname$shrext'
;;
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_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
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=/' <<EOF

# How to pass a linker flag through the compiler.
wl="$escaped_wl"

# Static library suffix (normally "a").
libext="$libext"

# Shared library suffix (normally "so").
shlibext="$shlibext"

# Format of library name prefix.
libname_spec="$escaped_libname_spec"

# Library names that the linker finds when passed -lNAME.
library_names_spec="$escaped_library_names_spec"

# Flag to hardcode \$libdir into a binary during linking.
# This must work even if \$libdir does not exist.
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"

# Whether we need a single -rpath flag with a separated argument.
hardcode_libdir_separator="$hardcode_libdir_separator"

# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
# resulting binary.
hardcode_direct="$hardcode_direct"

# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
# resulting binary.
hardcode_minus_L="$hardcode_minus_L"

EOF

+ 221
- 0
configure.ac View File

@@ -0,0 +1,221 @@
# This file is part of GNUnet.
# (C) 2001-2019 Christian Grothoff (and other contributing authors)
#
# GNUnet is free software; you can 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., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
#
# Process this file with autoconf to produce a configure script.
#
AC_PREREQ(2.61)
AC_INIT([gnunet-secushare],[0.0.0],[bug-gnunet@gnu.org])
AM_INIT_AUTOMAKE([gnunet-secushare], [0.0.0])
AM_CONFIG_HEADER(gnunet_secushare_config.h)

AH_TOP([#define _GNU_SOURCE 1])

AC_ISC_POSIX
AC_PROG_AWK
AC_PROG_CC

AC_PROG_MKDIR_P
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_LIBTOOL_WIN32_DLL
AC_PROG_CC
AM_PROG_CC_STDC
AC_HEADER_STDC
AC_CANONICAL_HOST

# dynamic libraries/plugins
AC_DISABLE_STATIC
AC_PROG_LIBTOOL

AC_SYS_LARGEFILE
AC_FUNC_FSEEKO

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


# Check system type
case "$host_os" in
*darwin* | *rhapsody* | *macosx*)
AC_DEFINE_UNQUOTED(OSX,1,[This is an OS X system])
CFLAGS="-no-cpp-precomp $CFLAGS"
LDFLAGS="-flat_namespace -undefined suppress $LDFLAGS"
;;
linux*)
AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux system])
;;
freebsd*)
AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
AC_DEFINE_UNQUOTED(FREEBSD,1,[This is a FreeBSD system])
;;
openbsd*)
AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
AC_DEFINE_UNQUOTED(OPENBSD,1,[This is an OpenBSD system])
;;
netbsd*)
AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
AC_DEFINE_UNQUOTED(NETBSD,1,[This is a NetBSD system])
;;
*solaris*)
AC_DEFINE_UNQUOTED(SOLARIS,1,[This is a Solaris system])
AC_DEFINE_UNQUOTED(_REENTRANT,1,[Need with solaris or errno doesnt work])
build_target="solaris"
;;
*arm-linux*)
AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux system])
;;
*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)
LDFLAGS="$LDFLAGS -no-undefined"
build_target="cygwin"
;;
*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 -no-undefined -Wl,--export-all-symbols -lws2_32"
CFLAGS="-mms-bitfields $CFLAGS"
build_target="mingw"
;;
*)
AC_MSG_RESULT(Unrecognised OS $host_os)
AC_DEFINE_UNQUOTED(OTHEROS,1,[Some strange OS])
;;
esac

AM_CONDITIONAL(MINGW, test "$build_target" = "mingw")

# check for gettext
AM_GNU_GETTEXT_VERSION([0.18.1])
AM_GNU_GETTEXT([external])

AC_CHECK_HEADERS([errno.h stdio.h unistd.h locale.h sys/stat.h sys/types.h langinfo.h libintl.h unistd.h stddef.h argz.h sys/socket.h netinet/in.h stdarg.h])

# test for GNUnet core
gnunet=0
lookin=${prefix}
backup_LDFLAGS="$LDFLAGS"
backup_CPPFLAGS="$CPPFLAGS"
GNUNET_LDFLAGS=""
GNUNET_CPPFLAGS=""
AC_MSG_CHECKING(for GNUnet core)
AC_ARG_WITH(gnunet,
[ --with-gnunet=PFX Base of GNUnet installation],
[AC_MSG_RESULT([$with_gnunet])
case $with_gnunet in
no)
lookin=""
;;
yes)
lookin="${prefix}"
;;
*)
lookin="$with_gnunet"
;;
esac
],
[
AC_MSG_RESULT([--with-gnunet not specified])
PKG_CHECK_MODULES([GNUNET], [gnunetutil >= 0.9.0], gnunet=1)
]
)

if test "x$gnunet" == "x0" -a ! "x$lookin" == "x"
then
AC_MSG_CHECKING(for GNUnet util library in $lookin)
GNUNET_LDFLAGS="-L${lookin}/lib"
GNUNET_CPPFLAGS="-I${lookin}/include"
LDFLAGS="$GNUNET_LDFLAGS $backup_LDFLAGS"
CPPFLAGS="$GNUNET_CPPFLAGS $backup_CPPFLAGS"
AC_CHECK_HEADERS([gnunet/gnunet_util_lib.h],
AC_CHECK_LIB([gnunetutil], [GNUNET_xfree_],
[
gnunet=1
EXT_LIB_PATH="-L${lookin}/lib $EXT_LIB_PATH"
]
),,[#include <gnunet/platform.h>]
)
fi

if test "x$gnunet" == "x0"
then
AC_MSG_ERROR([gnunet-ext requires GNUnet])
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])


AC_SUBST(GNUNET_CPPFLAGS)
AC_SUBST(GNUNET_LDFLAGS)
LDFLAGS="$backup_LDFLAGS"
CPPFLAGS="$backup_CPPFLAGS"

AC_DEFINE_DIR([PACKAGE_DATA], [datarootdir], [The directory for installing read-only architecture-independent data])

# Set PACKAGE_SOURCE_DIR in gnunet_ext_config.h.
packagesrcdir=`cd $srcdir && pwd`
AC_DEFINE_UNQUOTED(PACKAGE_SOURCE_DIR, "${packagesrcdir}", [source dir])

AC_OUTPUT([ po/Makefile.in
Makefile
pkgconfig/Makefile
src/Makefile
src/include/Makefile
src/multicast/Makefile
src/multicast/multicast.conf
src/psycutil/Makefile
src/psyc/Makefile
src/psyc/psyc.conf
src/psycstore/Makefile
src/psycstore/psycstore.conf
src/social/Makefile
src/social/social.conf
pkgconfig/gnunetmulticast.pc
pkgconfig/gnunetpsyc.pc
pkgconfig/gnunetpsycstore.pc
pkgconfig/gnunetsocial.pc
])

+ 35
- 0
m4/ac_define_dir.m4 View File

@@ -0,0 +1,35 @@
dnl @synopsis AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION])
dnl
dnl This macro _AC_DEFINEs VARNAME to the expansion of the DIR
dnl variable, taking care of fixing up ${prefix} and such.
dnl
dnl VARNAME is offered as both a C preprocessor symbol, and an output
dnl variable.
dnl
dnl Note that the 3 argument form is only supported with autoconf 2.13
dnl and later (i.e. only where _AC_DEFINE supports 3 arguments).
dnl
dnl Examples:
dnl
dnl AC_DEFINE_DIR(DATADIR, datadir)
dnl AC_DEFINE_DIR(PROG_PATH, bindir, [Location of installed binaries])
dnl
dnl @category Misc
dnl @author Stepan Kasal <kasal@ucw.cz>
dnl @author Andreas Schwab <schwab@suse.de>
dnl @author Guido Draheim <guidod@gmx.de>
dnl @author Alexandre Oliva
dnl @version 2005-01-17
dnl @license AllPermissive
AC_DEFUN([AC_DEFINE_DIR], [
prefix_NONE=
exec_prefix_NONE=
test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
eval ac_define_dir="\"[$]$2\""
AC_SUBST($1, "$ac_define_dir")
AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
test "$prefix_NONE" && prefix=NONE
test "$exec_prefix_NONE" && exec_prefix=NONE
])

+ 383
- 0
m4/gettext.m4 View File

@@ -0,0 +1,383 @@
# gettext.m4 serial 63 (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 <drepper@cygnus.com>, 1995-2000.
dnl Bruno Haible <haible@clisp.cons.org>, 2000-2006, 2008-2010.

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 <inttypes.h> 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(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old],
[AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])])
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 <libintl.h>
$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 <libintl.h>
$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 <libintl.h>
$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 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], [])

+ 214
- 0
m4/iconv.m4 View File

@@ -0,0 +1,214 @@
# iconv.m4 serial 11 (gettext-0.18.1)
dnl Copyright (C) 2000-2002, 2007-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 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).
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles

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 <stdlib.h>
#include <iconv.h>],
[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 <stdlib.h>
#include <iconv.h>],
[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_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [
dnl This tests against bugs in AIX 5.1, HP-UX 11.11, Solaris 10.
am_save_LIBS="$LIBS"
if test $am_cv_lib_iconv = yes; then
LIBS="$LIBS $LIBICONV"
fi
AC_TRY_RUN([
#include <iconv.h>
#include <string.h>
int main ()
{
/* Test against AIX 5.1 bug: Failures are not distinguishable from successful
returns. */
{
iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
if (cd_utf8_to_88591 != (iconv_t)(-1))
{
static const char input[] = "\342\202\254"; /* EURO SIGN */
char buf[10];
const char *inptr = input;
size_t inbytesleft = strlen (input);
char *outptr = buf;
size_t outbytesleft = sizeof (buf);
size_t res = iconv (cd_utf8_to_88591,
(char **) &inptr, &inbytesleft,
&outptr, &outbytesleft);
if (res == 0)
return 1;
}
}
/* Test against Solaris 10 bug: Failures are not distinguishable from
successful returns. */
{
iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
if (cd_ascii_to_88591 != (iconv_t)(-1))
{
static const char input[] = "\263";
char buf[10];
const char *inptr = input;
size_t inbytesleft = strlen (input);
char *outptr = buf;
size_t outbytesleft = sizeof (buf);
size_t res = iconv (cd_ascii_to_88591,
(char **) &inptr, &inbytesleft,
&outptr, &outbytesleft);
if (res == 0)
return 1;
}
}
#if 0 /* This bug could be worked around by the caller. */
/* Test against HP-UX 11.11 bug: Positive return value instead of 0. */
{
iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
if (cd_88591_to_utf8 != (iconv_t)(-1))
{
static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
char buf[50];
const char *inptr = input;
size_t inbytesleft = strlen (input);
char *outptr = buf;
size_t outbytesleft = sizeof (buf);
size_t res = iconv (cd_88591_to_utf8,
(char **) &inptr, &inbytesleft,
&outptr, &outbytesleft);
if ((int)res > 0)
return 1;
}
}
#endif
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
provided. */
if (/* Try standardized names. */
iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
/* Try IRIX, OSF/1 names. */
&& iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
/* Try AIX names. */
&& iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
/* Try HP-UX names. */
&& iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
return 1;
return 0;
}], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no],
[case "$host_os" in
aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
*) am_cv_func_iconv_works="guessing yes" ;;
esac])
LIBS="$am_save_LIBS"
])
case "$am_cv_func_iconv_works" in
*no) am_func_iconv=no am_cv_lib_iconv=no ;;
*) am_func_iconv=yes ;;
esac
else
am_func_iconv=no am_cv_lib_iconv=no
fi
if test "$am_func_iconv" = yes; then
AC_DEFINE([HAVE_ICONV], [1],
[Define if you have the iconv() function and it works.])
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])
])

dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
dnl avoid warnings like
dnl "warning: AC_REQUIRE: `AM_ICONV' 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_iconv_AC_DEFUN],
m4_version_prereq([2.64],
[[AC_DEFUN_ONCE(
[$1], [$2])]],
[[AC_DEFUN(
[$1], [$2])]]))
gl_iconv_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 <stdlib.h>
#include <iconv.h>
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([
$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
])

+ 110
- 0
m4/lib-ld.m4 View File

@@ -0,0 +1,110 @@
# lib-ld.m4 serial 4 (gettext-0.18)
dnl Copyright (C) 1996-2003, 2009-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 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 </dev/null` in
*GNU* | *'with BFD'*)
acl_cv_prog_gnu_ld=yes ;;
*)
acl_cv_prog_gnu_ld=no ;;
esac])
with_gnu_ld=$acl_cv_prog_gnu_ld
])

dnl From libtool-1.4. Sets the variable LD.
AC_DEFUN([AC_LIB_PROG_LD],
[AC_ARG_WITH([gnu-ld],
[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
# 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.
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
])

+ 774
- 0
m4/lib-link.m4 View File

@@ -0,0 +1,774 @@
# lib-link.m4 serial 21 (gettext-0.18)
dnl Copyright (C) 2001-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 Bruno Haible.

AC_PREREQ([2.54])

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.
dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
AC_DEFUN([AC_LIB_LINKFLAGS],
[
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
AC_REQUIRE([AC_LIB_RPATH])
pushdef([Name],[translit([$1],[./-], [___])])
pushdef([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"
ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
])
LIB[]NAME="$ac_cv_lib[]Name[]_libs"
LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
AC_SUBST([LIB]NAME)
AC_SUBST([LTLIB]NAME)
AC_SUBST([LIB]NAME[_PREFIX])
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
popdef([NAME])
popdef([Name])
])

dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message])
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. The missing-message
dnl defaults to 'no' and may contain additional hints for the user.
dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME}
dnl and 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.
dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
[
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
AC_REQUIRE([AC_LIB_RPATH])
pushdef([Name],[translit([$1],[./-], [___])])
pushdef([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"
dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS,
dnl because these -l options might require -L options that are present in
dnl LIBS. -l options benefit only from the -L options listed before it.
dnl Otherwise, add it to the front of LIBS, because it may be a static
dnl library that depends on another static library that is present in LIBS.
dnl Static libraries benefit only from the static libraries listed after
dnl it.
case " $LIB[]NAME" in
*" -l"*) LIBS="$LIBS $LIB[]NAME" ;;
*) LIBS="$LIB[]NAME $LIBS" ;;
esac
AC_TRY_LINK([$3], [$4],
[ac_cv_lib[]Name=yes],
[ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])'])
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 lib][$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=
LIB[]NAME[]_PREFIX=
fi
AC_SUBST([HAVE_LIB]NAME)
AC_SUBST([LIB]NAME)
AC_SUBST([LTLIB]NAME)
AC_SUBST([LIB]NAME[_PREFIX])
popdef([NAME])
popdef([Name])
])

dnl Determine the platform dependent parameters needed to use rpath:
dnl acl_libext,
dnl acl_shlibext,
dnl acl_hardcode_libdir_flag_spec,
dnl acl_hardcode_libdir_separator,
dnl acl_hardcode_direct,
dnl acl_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"
acl_libext="$acl_cv_libext"
acl_shlibext="$acl_cv_shlibext"
acl_libname_spec="$acl_cv_libname_spec"
acl_library_names_spec="$acl_cv_library_names_spec"
acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
acl_hardcode_direct="$acl_cv_hardcode_direct"
acl_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_FROMPACKAGE(name, package)
dnl declares that libname comes from the given package. The configure file
dnl will then not have a --with-libname-prefix option but a
dnl --with-package-prefix option. Several libraries can come from the same
dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar
dnl macro call that searches for libname.
AC_DEFUN([AC_LIB_FROMPACKAGE],
[
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
define([acl_frompackage_]NAME, [$2])
popdef([NAME])
pushdef([PACK],[$2])
pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
define([acl_libsinpackage_]PACKUP,
m4_ifdef([acl_libsinpackage_]PACKUP, [acl_libsinpackage_]PACKUP[[, ]],)[lib$1])
popdef([PACKUP])
popdef([PACK])
])

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.
dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
[
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])])
pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])])
dnl Autoconf >= 2.61 supports dots in --with options.
pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit(PACK,[.],[_])],PACK)])
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_ARG_WITH(P_A_C_K[-prefix],
[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib
--without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ 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"
if test "$acl_libdirstem2" != "$acl_libdirstem" \
&& ! test -d "$withval/$acl_libdirstem"; then
additional_libdir="$withval/$acl_libdirstem2"
fi
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=
LIB[]NAME[]_PREFIX=
dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been
dnl computed. So it has to be reset here.
HAVE_LIB[]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=
eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
if test -n "$acl_shlibext"; then
shrext=".$acl_shlibext" # typically: shrext=.so
else
shrext=
fi
if test $use_additional = yes; then
dir="$additional_libdir"
dnl The same code as in the loop below:
dnl First look for a shared library.
if test -n "$acl_shlibext"; then
if test -f "$dir/$libname$shrext"; then
found_dir="$dir"
found_so="$dir/$libname$shrext"
else
if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
ver=`(cd "$dir" && \
for f in "$libname$shrext".*; do echo "$f"; done \
| sed -e "s,^$libname$shrext\\\\.,," \
| sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
| sed 1q ) 2>/dev/null`
if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
found_dir="$dir"
found_so="$dir/$libname$shrext.$ver"
fi
else
eval library_names=\"$acl_library_names_spec\"
for f in $library_names; do
if test -f "$dir/$f"; then
found_dir="$dir"
found_so="$dir/$f"
break
fi
done
fi
fi
fi
dnl Then look for a static library.
if test "X$found_dir" = "X"; then
if test -f "$dir/$libname.$acl_libext"; then
found_dir="$dir"
found_a="$dir/$libname.$acl_libext"
fi
fi
if test "X$found_dir" != "X"; then
if test -f "$dir/$libname.la"; then
found_la="$dir/$libname.la"
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//'`
dnl First look for a shared library.
if test -n "$acl_shlibext"; then
if test -f "$dir/$libname$shrext"; then
found_dir="$dir"
found_so="$dir/$libname$shrext"
else
if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
ver=`(cd "$dir" && \
for f in "$libname$shrext".*; do echo "$f"; done \
| sed -e "s,^$libname$shrext\\\\.,," \
| sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
| sed 1q ) 2>/dev/null`
if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
found_dir="$dir"
found_so="$dir/$libname$shrext.$ver"
fi
else
eval library_names=\"$acl_library_names_spec\"
for f in $library_names; do
if test -f "$dir/$f"; then
found_dir="$dir"
found_so="$dir/$f"
break
fi
done
fi
fi
fi
dnl Then look for a static library.
if test "X$found_dir" = "X"; then
if test -f "$dir/$libname.$acl_libext"; then
found_dir="$dir"
found_a="$dir/$libname.$acl_libext"
fi
fi
if test "X$found_dir" != "X"; then
if test -f "$dir/$libname.la"; then
found_la="$dir/$libname.la"
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" \
|| test "X$found_dir" = "X/usr/$acl_libdirstem2"; 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 "$acl_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 "$acl_hardcode_libdir_flag_spec" && test "$acl_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 "$acl_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 $acl_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/"'*$,,'`
if test "$name" = '$1'; then
LIB[]NAME[]_PREFIX="$basedir"
fi
additional_includedir="$basedir/include"
;;
*/$acl_libdirstem2 | */$acl_libdirstem2/)
basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'`
if test "$name" = '$1'; then
LIB[]NAME[]_PREFIX="$basedir"
fi
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" \
&& test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then
haveit=
if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \
|| test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; 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 "$acl_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:+$acl_hardcode_libdir_separator}$found_dir"
done
dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
acl_save_libdir="$libdir"
libdir="$alldirs"
eval flag=\"$acl_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=\"$acl_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
popdef([P_A_C_K])
popdef([PACKLIBS])
popdef([PACKUP])
popdef([PACK])
popdef([NAME])
])

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 "$acl_hardcode_libdir_flag_spec" && test "$acl_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" \
&& test "X$dir" != "X/usr/$acl_libdirstem2"; 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" \
&& test "X$dir" != "X/usr/$acl_libdirstem2"; 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 "$acl_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:+$acl_hardcode_libdir_separator}$dir"
done
acl_save_libdir="$libdir"
libdir="$alldirs"
eval flag=\"$acl_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=\"$acl_hardcode_libdir_flag_spec\"
libdir="$acl_save_libdir"
$1="${$1}${$1:+ }$flag"
done
fi
fi
fi
fi
fi
AC_SUBST([$1])
])

+ 224
- 0
m4/lib-prefix.m4 View File

@@ -0,0 +1,224 @@
# lib-prefix.m4 serial 7 (gettext-0.18)
dnl Copyright (C) 2001-2005, 2008-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 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
dnl - a variable acl_libdirstem, containing the basename of the libdir, either
dnl "lib" or "lib64" or "lib/64",
dnl - a variable acl_libdirstem2, as a secondary possible value for
dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or
dnl "lib/amd64".
AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
[
dnl There is no formal standard regarding lib and lib64.
dnl On glibc systems, the current practice is that on a system supporting
dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine
dnl the compiler's default mode by looking at the compiler's library search
dnl path. If at least one of its elements ends in /lib64 or points to a
dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI.
dnl Otherwise we use the default, namely "lib".
dnl On Solaris systems, the current practice is that on a system supporting
dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or
dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib.
AC_REQUIRE([AC_CANONICAL_HOST])
acl_libdirstem=lib
acl_libdirstem2=
case "$host_os" in
solaris*)
dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment
dnl <http://docs.sun.com/app/docs/doc/816-5138/dev-env?l=en&a=view>.
dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link."
dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the
dnl symlink is missing, so we set acl_libdirstem2 too.
AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit],
[AC_EGREP_CPP([sixtyfour bits], [
#ifdef _LP64
sixtyfour bits
#endif
], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no])
])
if test $gl_cv_solaris_64bit = yes; then
acl_libdirstem=lib/64
case "$host_cpu" in
sparc*) acl_libdirstem2=lib/sparcv9 ;;
i*86 | x86_64) acl_libdirstem2=lib/amd64 ;;
esac
fi
;;
*)
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 ;;
*/../ | */.. )
# Better ignore directories of this form. They are misleading.
;;
*) searchdir=`cd "$searchdir" && pwd`
case "$searchdir" in
*/lib64 ) acl_libdirstem=lib64 ;;
esac ;;
esac
fi
done
IFS="$acl_save_IFS"
fi
;;
esac
test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem"
])

+ 8387
- 0
m4/libtool.m4
File diff suppressed because it is too large
View File


+ 437
- 0
m4/ltoptions.m4 View File

@@ -0,0 +1,437 @@
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004-2005, 2007-2009, 2011-2015 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 8 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_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
[_LT_WITH_AIX_SONAME([aix])])
])
])# _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_AIX_SONAME([DEFAULT])
# ----------------------------------
# implement the --with-aix-soname flag, and support the `aix-soname=aix'
# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
m4_define([_LT_WITH_AIX_SONAME],
[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
shared_archive_member_spec=
case $host,$enable_shared in
power*-*-aix[[5-9]]*,yes)
AC_MSG_CHECKING([which variant of shared library versioning to provide])
AC_ARG_WITH([aix-soname],
[AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
[shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
[case $withval in
aix|svr4|both)
;;
*)
AC_MSG_ERROR([Unknown argument to --with-aix-soname])
;;
esac
lt_cv_with_aix_soname=$with_aix_soname],
[AC_CACHE_VAL([lt_cv_with_aix_soname],
[lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
with_aix_soname=$lt_cv_with_aix_soname])
AC_MSG_RESULT([$with_aix_soname])
if test aix != "$with_aix_soname"; then
# For the AIX way of multilib, we name the shared archive member
# based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
# and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
# Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
# the AIX toolchain works better with OBJECT_MODE set (default 32).
if test 64 = "${OBJECT_MODE-32}"; then
shared_archive_member_spec=shr_64
else
shared_archive_member_spec=shr
fi
fi
;;
*)
with_aix_soname=aix
;;
esac

_LT_DECL([], [shared_archive_member_spec], [0],
[Shared archive member basename, for filename based shared library versioning on AIX])dnl
])# _LT_WITH_AIX_SONAME

LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])


# _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=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])])

+ 124
- 0
m4/ltsugar.m4 View File

@@ -0,0 +1,124 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007-2008, 2011-2015 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
])

+ 23
- 0
m4/ltversion.m4 View File

@@ -0,0 +1,23 @@
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004, 2011-2015 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 4179 ltversion.m4
# This file is part of GNU Libtool

m4_define([LT_PACKAGE_VERSION], [2.4.6])
m4_define([LT_PACKAGE_REVISION], [2.4.6])

AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.6'
macro_revision='2.4.6'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])

+ 99
- 0
m4/lt~obsolete.m4 View File

@@ -0,0 +1,99 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 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])])

+ 32
- 0
m4/nls.m4 View File

@@ -0,0 +1,32 @@
# nls.m4 serial 5 (gettext-0.18)
dnl Copyright (C) 1995-2003, 2005-2006, 2008-2010 Free Software Foundation,
dnl 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 <drepper@cygnus.com>, 1995-2000.
dnl Bruno Haible <haible@clisp.cons.org>, 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])
])

+ 57
- 0
m4/pkg.m4 View File

@@ -0,0 +1,57 @@

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
])



+ 449
- 0
m4/po.m4 View File

@@ -0,0 +1,449 @@
# 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 <drepper@cygnus.com>, 1995-2000.
dnl Bruno Haible <haible@clisp.cons.org>, 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 <<EOT
$*
EOT
}
gt_echo='echo_func'
fi
fi

# A sed script that extracts the value of VARIABLE from a Makefile.
sed_x_variable='
# Test if the hold space is empty.
x
s/P/P/
x
ta
# Yes it was empty. Look if we have the expected variable definition.
/^[ ]*VARIABLE[ ]*=/{
# Seen the first line of the variable definition.
s/^[ ]*VARIABLE[ ]*=//
ba
}
bd
:a
# Here we are processing a line from the variable definition.
# Remove comment, more precisely replace it with a space.
s/#.*$/ /
# See if the line ends in a backslash.
tb
:b
s/\\$//
# Print the line, without the trailing backslash.
p
tc
# There was no trailing backslash. The end of the variable definition is
# reached. Clear the hold space.
s/^.*$//
x
bd
:c
# A trailing backslash means that the variable definition continues in the
# next line. Put a nonempty string into the hold space to indicate this.
s/^.*$/P/
x
:d
'
changequote([,])dnl

# Set POTFILES to the value of the Makefile variable POTFILES.
sed_x_POTFILES=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/POTFILES/g'`
POTFILES=`sed -n -e "$sed_x_POTFILES" < "$ac_file"`
# Compute POTFILES_DEPS as
# $(foreach file, $(POTFILES), $(top_srcdir)/$(file))
POTFILES_DEPS=
for file in $POTFILES; do
POTFILES_DEPS="$POTFILES_DEPS "'$(top_srcdir)/'"$file"
done
POMAKEFILEDEPS=""

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
if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
# The LINGUAS file contains the set of available languages.
ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
else
# Set ALL_LINGUAS to the value of the Makefile variable LINGUAS.
sed_x_LINGUAS=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'`
ALL_LINGUAS_=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"`
fi
# Hide the ALL_LINGUAS assigment from automake < 1.5.
eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
# 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)
# Compute PROPERTIESFILES
# as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).properties)
# Compute CLASSFILES
# as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).class)
# Compute QMFILES
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm)
# Compute MSGFILES
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg)
# Compute RESOURCESDLLFILES
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll)
case "$ac_given_srcdir" in
.) srcdirpre= ;;
*) srcdirpre='$(srcdir)/' ;;
esac
POFILES=
UPDATEPOFILES=
DUMMYPOFILES=
GMOFILES=
PROPERTIESFILES=
CLASSFILES=
QMFILES=
MSGFILES=
RESOURCESDLLFILES=
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"
PROPERTIESFILES="$PROPERTIESFILES \$(top_srcdir)/\$(DOMAIN)_$lang.properties"
CLASSFILES="$CLASSFILES \$(top_srcdir)/\$(DOMAIN)_$lang.class"
QMFILES="$QMFILES $srcdirpre$lang.qm"
frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
MSGFILES="$MSGFILES $srcdirpre$frobbedlang.msg"
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/'`
RESOURCESDLLFILES="$RESOURCESDLLFILES $srcdirpre$frobbedlang/\$(DOMAIN).resources.dll"
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=
JAVACATALOGS=
QTCATALOGS=
TCLCATALOGS=
CSHARPCATALOGS=
if test -n "$INST_LINGUAS"; then
for lang in $INST_LINGUAS; do
CATALOGS="$CATALOGS $lang.gmo"
JAVACATALOGS="$JAVACATALOGS \$(DOMAIN)_$lang.properties"
QTCATALOGS="$QTCATALOGS $lang.qm"
frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
TCLCATALOGS="$TCLCATALOGS $frobbedlang.msg"
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/'`
CSHARPCATALOGS="$CSHARPCATALOGS $frobbedlang/\$(DOMAIN).resources.dll"
done
fi

sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e "s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e "s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$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" <<EOF
$frobbedlang.msg: $lang.po
@echo "\$(MSGFMT) -c --tcl -d \$(srcdir) -l $lang $srcdirpre$lang.po"; \
\$(MSGFMT) -c --tcl -d "\$(srcdir)" -l $lang $srcdirpre$lang.po || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
EOF
done
fi
if grep -l '@CSHARPCATALOGS@' "$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/_/-/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" <<EOF
$frobbedlang/\$(DOMAIN).resources.dll: $lang.po
@echo "\$(MSGFMT) -c --csharp -d \$(srcdir) -l $lang $srcdirpre$lang.po -r \$(DOMAIN)"; \
\$(MSGFMT) -c --csharp -d "\$(srcdir)" -l $lang $srcdirpre$lang.po -r "\$(DOMAIN)" || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
EOF
done
fi
if test -n "$POMAKEFILEDEPS"; then
cat >> "$ac_file.tmp" <<EOF
Makefile: $POMAKEFILEDEPS
EOF
fi
mv "$ac_file.tmp" "$ac_file"
])

dnl Initializes the accumulator used by AM_XGETTEXT_OPTION.
AC_DEFUN([AM_XGETTEXT_OPTION_INIT],
[
XGETTEXT_EXTRA_OPTIONS=
])

dnl Registers an option to be passed to xgettext in the po subdirectory.
AC_DEFUN([AM_XGETTEXT_OPTION],
[
AC_REQUIRE([AM_XGETTEXT_OPTION_INIT])
XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS $1"
])

+ 92
- 0
m4/progtest.m4 View File

@@ -0,0 +1,92 @@
# progtest.m4 serial 6 (gettext-0.18)
dnl Copyright (C) 1996-2003, 2005, 2008-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 <drepper@cygnus.com>, 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
])

+ 25
- 0
pkgconfig/Makefile.am View File

@@ -0,0 +1,25 @@
# This Makefile.am is in the public domain
pcfiles = \
gnunetmulticast.pc \
gnunetpsyc.pc \
gnunetpsycstore.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 = \
gnunetmulticast.pc.in \
gnunetpsyc.pc.in \
gnunetpsycstore.pc.in

CLEANFILES = $(pcfiles)
AM_CPPFLAGS = -I$(top_srcdir)/src/include

+ 12
- 0
pkgconfig/gnunetmulticast.pc.in View File

@@ -0,0 +1,12 @@
prefix=@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}

+ 12
- 0
pkgconfig/gnunetpsyc.pc.in View File

@@ -0,0 +1,12 @@
prefix=@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}

+ 12
- 0
pkgconfig/gnunetpsycstore.pc.in View File

@@ -0,0 +1,12 @@
prefix=@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}

+ 6
- 0
po/.gitignore View File

@@ -0,0 +1,6 @@
Makefile.in
Makefile
POTFILES
gnunet-ext.pot
remove-potcdate.sed
stamp-po

+ 12
- 0
po/ChangeLog View File

@@ -0,0 +1,12 @@
2012-03-07 gettextize <bug-gnu-gettext@gnu.org>

* Makefile.in.in: New file, from gettext-0.18.1.
* Rules-quot: New file, from gettext-0.18.1.
* boldquot.sed: New file, from gettext-0.18.1.
* en@boldquot.header: New file, from gettext-0.18.1.
* en@quot.header: New file, from gettext-0.18.1.
* insert-header.sin: New file, from gettext-0.18.1.
* quot.sed: New file, from gettext-0.18.1.
* remove-potcdate.sin: New file, from gettext-0.18.1.
* POTFILES.in: New file.


+ 444
- 0
po/Makefile.in.in View File

@@ -0,0 +1,444 @@
# Makefile for PO directory in any package using GNU gettext.
# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
#
# 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.18
GETTEXT_MACRO_VERSION = 0.18

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 --verbose -o $${lang}.gmo $${lang}.po"; \
cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo

.sin.sed:
sed -e '/^#/d' $< > t-$@
mv t-$@ $@


all: check-macro-version all-@USE_NLS@

all-yes: stamp-po
all-no:

# Ensure that the gettext macros and this Makefile.in.in are in sync.
check-macro-version:
@test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \
|| { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \
exit 1; \
}

# $(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 LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null | grep -v 'libtool:' >/dev/null; then \
package_gnu='GNU '; \
else \
package_gnu=''; \
fi; \
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; \
case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
--files-from=$(srcdir)/POTFILES.in \
--copyright-holder='$(COPYRIGHT_HOLDER)' \
--msgid-bugs-address="$$msgid_bugs_address" \
;; \
*) \
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
--files-from=$(srcdir)/POTFILES.in \
--copyright-holder='$(COPYRIGHT_HOLDER)' \
--package-name="$${package_gnu}@PACKAGE@" \
--package-version='@VERSION@' \
--msgid-bugs-address="$$msgid_bugs_address" \
;; \
esac
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) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \
cd $(srcdir) \
&& { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
*) \
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \
esac; \
}; \
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
@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:
@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) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
cd $(srcdir); \
if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \
$(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
*) \
$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
esac; \
}; 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)
@:

# Recreate Makefile by invoking config.status. Explicitly invoke the shell,
# because execution permission bits may not work on the current file system.
# Use @SHELL@, which is the shell determined by autoconf for the use by its
# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient.
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:

+ 41
- 0
po/Makevars View File

@@ -0,0 +1,41 @@
# 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_

# 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 = Free Software Foundation, Inc.

# 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 =

# 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 =

+ 2
- 0
po/POTFILES.in View File

@@ -0,0 +1,2 @@
# List of source files which contain translatable strings.
src/ext/gnunet-ext.c

+ 47
- 0
po/Rules-quot View File

@@ -0,0 +1,47 @@
# 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 $$lang -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

+ 10
- 0
po/boldquot.sed View File

@@ -0,0 +1,10 @@
s/"\([^"]*\)"/“\1”/g
s/`\([^`']*\)'/‘\1’/g
s/ '\([^`']*\)' / ‘\1’ /g
s/ '\([^`']*\)'$/ ‘\1’/g
s/^'\([^`']*\)' /‘\1’ /g
s/“”/""/g
s/“/“/g
s/”/”/g
s/‘/‘/g
s/’/’/g

+ 25
- 0
po/en@boldquot.header View File

@@ -0,0 +1,25 @@
# 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.
#

+ 22
- 0
po/en@quot.header View File

@@ -0,0 +1,22 @@
# 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.
#

+ 23
- 0
po/insert-header.sin View File

@@ -0,0 +1,23 @@
# 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
}

+ 6
- 0
po/quot.sed View File

@@ -0,0 +1,6 @@
s/"\([^"]*\)"/“\1”/g
s/`\([^`']*\)'/‘\1’/g
s/ '\([^`']*\)' / ‘\1’ /g
s/ '\([^`']*\)'$/ ‘\1’/g
s/^'\([^`']*\)' /‘\1’ /g
s/“”/""/g

+ 19
- 0
po/remove-potcdate.sin View File

@@ -0,0 +1,19 @@
# 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
}

+ 2
- 0
src/.gitignore View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

+ 7
- 0
src/Makefile.am View File

@@ -0,0 +1,7 @@
# This Makefile.am is in the public domain
SUBDIRS = include \
multicast \
psycutil \
psycstore \
psyc \
social

+ 2
- 0
src/include/.gitignore View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

+ 15
- 0
src/include/Makefile.am View File

@@ -0,0 +1,15 @@
# This Makefile.am is in the public domain
SUBDIRS = .

gnunetincludedir = $(includedir)/gnunet

gnunetinclude_HEADERS = \
gnunet_multicast_service.h \
gnunet_psycstore_plugin.h \
gnunet_psycstore_service.h \
gnunet_psyc_service.h \
gnunet_psyc_util_lib.h \
gnunet_psyc_env.h \
gnunet_psyc_message.h \
gnunet_psyc_slicer.h \
gnunet_social_service.h

+ 925
- 0
src/include/gnunet_multicast_service.h View File

@@ -0,0 +1,925 @@
/*
This file is part of GNUnet.
Copyright (C) 2012, 2013 GNUnet e.V.

GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.

GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
* @author Christian Grothoff
*
* @file
* Multicast service; multicast messaging via CADET
*
* @defgroup multicast Multicast service
* Multicast messaging via CADET.
* @{
*/

#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_EcdsaPublicKey member_pub_key;

/**
* ECC signature of the request fragment.
*
* Signature must match the public key of the multicast group.
*/
struct GNUNET_CRYPTO_EcdsaSignature 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_JoinRequestCallback 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_JoinRequestCallback.
*
* @param jh
* Join request handle.
* @param is_admitted
* #GNUNET_YES if the join is approved,
* #GNUNET_NO if it is disapproved,
* #GNUNET_SYSERR if we cannot answer the request.
* @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_resp
* 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,
uint16_t relay_count,
const struct GNUNET_PeerIdentity *relays,
const struct GNUNET_MessageHeader *join_resp);


/**
* 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 member_pub_key
* Public key of the member requesting join.
* @param join_msg
* Application-dependent join message from the new member.
* @param jh
* Join handle to pass to GNUNET_MULTICAST_join_decison().
*/
typedef void
(*GNUNET_MULTICAST_JoinRequestCallback) (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
const struct GNUNET_MessageHeader *join_msg,
struct GNUNET_MULTICAST_JoinHandle *jh);


/**
* Method called to inform about the decision in response to a join request.
*
* If @a is_admitted is not #GNUNET_YES, then the multicast service disconnects
* the client and the multicast member handle returned by
* GNUNET_MULTICAST_member_join() is invalidated.
*
* @param cls
* Closure.
* @param is_admitted
* #GNUNET_YES or #GNUNET_NO or #GNUNET_SYSERR
* @param peer
* The peer we are connected to and the join decision is from.
* @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. If empty, only the origin can
* be used to connect to the group.
* @param join_msg
* Application-dependent join message from the origin.
*/
typedef void
(*GNUNET_MULTICAST_JoinDecisionCallback) (void *cls,
int is_admitted,
const struct GNUNET_PeerIdentity *peer,
uint16_t relay_count,
const struct GNUNET_PeerIdentity *relays,
const struct GNUNET_MessageHeader *join_msg);


/**
* 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_MULTICAST_RequestHeader *req);


/**
* 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_MULTICAST_MessageHeader *msg);


/**
* 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_pub_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_EcdsaPublicKey *member_pub_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_pub_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_EcdsaPublicKey *member_pub_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 not found / an error occurred.
* @param ec
* Error code. See enum GNUNET_MULTICAST_ReplayErrorCode
* If not #GNUNET_MULTICAST_REC_OK, the replay handle is invalidated.
*/
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.
*
* Peers that issue GNUNET_MULTICAST_member_join() can 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.
*
* TODO: This function could optionally offer to advertise the origin in the
* P2P overlay network(where?) under the respective public key so that other
* peers can find an alternate PeerId to join it. Higher level protocols may
* however provide other means of solving the problem of the offline host
* (see secushare specs about that) and therefore merely need a way to provide
* a list of possible PeerIds.
*
* @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 max_fragment_id
* Maximum fragment ID already sent to the group.
* 0 for a new group.
* @param join_request_cb
* Function called to approve / disapprove joining of a peer.
* @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 max_fragment_id,
GNUNET_MULTICAST_JoinRequestCallback join_request_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)
* @deprecated should move to MQ-style API!
*/
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_OriginTransmitHandle;


/**
* 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).
* @deprecated should move to MQ-style API!
*/
struct GNUNET_MULTICAST_OriginTransmitHandle *
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 th Transmission to cancel.
*/
void
GNUNET_MULTICAST_origin_to_all_resume (struct GNUNET_MULTICAST_OriginTransmitHandle *th);


/**
* Cancel request for message transmission to multicast group.
*
* @param th Transmission to cancel.
*/
void
GNUNET_MULTICAST_origin_to_all_cancel (struct GNUNET_MULTICAST_OriginTransmitHandle *th);


/**
* Stop a multicast group.
*
* @param origin Multicast group to stop.
*/
void
GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *origin,
GNUNET_ContinuationCallback stop_cb,
void *stop_cls);


/**
* Join a multicast group.
*
* The entity joining is always the local peer. Further information about the
* candidate can be provided in @a join_msg. 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_pub_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_msg
* Application-dependent join message to be passed to the peer @a origin.
* @param join_request_cb
* Function called to approve / disapprove joining of a peer.
* @param join_decision_cb
* Function called to inform about the join decision.
* @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_EcdsaPrivateKey *member_pub_key,
const struct GNUNET_PeerIdentity *origin,
uint16_t relay_count,
const struct GNUNET_PeerIdentity *relays,
const struct GNUNET_MessageHeader *join_request,
GNUNET_MULTICAST_JoinRequestCallback join_request_cb,
GNUNET_MULTICAST_JoinDecisionCallback join_decision_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 GNUNET_MULTICAST_ReplayFragmentCallback
*
* @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 GNUNET_MULTICAST_ReplayMessageCallback
*
* @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);


/**
* 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,
GNUNET_ContinuationCallback part_cb,
void *part_cls);


/**
* 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)
* @deprecated should move to MQ-style API!
*/
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_MemberTransmitHandle;


/**
* 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).
* @deprecated should move to MQ-style API!
*/
struct GNUNET_MULTICAST_MemberTransmitHandle *
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 th
* Transmission to cancel.
*/
void
GNUNET_MULTICAST_member_to_origin_resume (struct GNUNET_MULTICAST_MemberTransmitHandle *th);


/**
* Cancel request for message transmission to origin.
*
* @param th
* Transmission to cancel.
*/
void
GNUNET_MULTICAST_member_to_origin_cancel (struct GNUNET_MULTICAST_MemberTransmitHandle *th);


#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
#ifdef __cplusplus
}
#endif

/* ifndef GNUNET_MULTICAST_SERVICE_H */
#endif

/** @} */ /* end of group */

+ 340
- 0
src/include/gnunet_psyc_env.h View File

@@ -0,0 +1,340 @@
/*
* This file is part of GNUnet.
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
*
* @file
* PSYC Environment library
*
* @defgroup psyc-util-env PSYC Utilities library: Environment
* Environment data structure operations for PSYC and Social messages.
*
* Library providing operations for the @e environment of
* PSYC and Social messages, and for (de)serializing variable values.
*
* @{
*/


#ifndef GNUNET_PSYC_ENV_H
#define GNUNET_PSYC_ENV_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_PSYC_Operator
{
/**
* Set value of a transient variable.
*/
GNUNET_PSYC_OP_SET = ':',

/**
* Assign value for a persistent state variable.
*
* If an assigned value is NULL, the variable is deleted.
*/
GNUNET_PSYC_OP_ASSIGN = '=',

/**
* Augment state variable.
*
* Used for appending strings, adding numbers, and adding new items to a list or dictionary.
*/
GNUNET_PSYC_OP_AUGMENT = '+',

/**
* Diminish state variable.
*
* Used for subtracting numbers, and removing items from a list or dictionary.
*/
GNUNET_PSYC_OP_DIMINISH = '-',

/**
* Update state variable.
*
* Used for modifying a single item of a list or dictionary.
*/
GNUNET_PSYC_OP_UPDATE = '@',
};


/**
* PSYC variable types.
*/
enum GNUNET_PSYC_Type
{
GNUNET_PSYC_TYPE_DATA = 0,
GNUNET_PSYC_TYPE_NUMBER,
GNUNET_PSYC_TYPE_LIST,
GNUNET_PSYC_TYPE_DICT
};


/**
* PSYC state modifier.
*/
struct GNUNET_PSYC_Modifier
{
/**
* State operation.
*/
enum GNUNET_PSYC_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_PSYC_Modifier *next;

/**
* Previous modifier.
*/
struct GNUNET_PSYC_Modifier *prev;
};


/**
* Environment for a message.
*
* Contains modifiers.
*/
struct GNUNET_PSYC_Environment;


/**
* Create an environment.
*
* @return A newly allocated environment.
*/
struct GNUNET_PSYC_Environment *
GNUNET_PSYC_env_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_PSYC_env_add (struct GNUNET_PSYC_Environment *env,
enum GNUNET_PSYC_Operator oper, const char *name,
const void *value, size_t value_size);


/**
* Get the first modifier of the environment.
*/
struct GNUNET_PSYC_Modifier *
GNUNET_PSYC_env_head (const struct GNUNET_PSYC_Environment *env);



/**
* Get the last modifier of the environment.
*/
struct GNUNET_PSYC_Modifier *
GNUNET_PSYC_env_tail (const struct GNUNET_PSYC_Environment *env);


/**
* Remove a modifier from the environment.
*/
void
GNUNET_PSYC_env_remove (struct GNUNET_PSYC_Environment *env,
struct GNUNET_PSYC_Modifier *mod);


/**
* Remove a modifier at the beginning of the environment.
*/
int
GNUNET_PSYC_env_shift (struct GNUNET_PSYC_Environment *env,
enum GNUNET_PSYC_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_PSYC_Iterator) (void *cls, enum GNUNET_PSYC_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_PSYC_env_iterate (const struct GNUNET_PSYC_Environment *env,
GNUNET_PSYC_Iterator it, void *it_cls);


/**
* Get the number of modifiers in the environment.
*
* @param env The environment.
*
* @return Number of modifiers.
*/
size_t
GNUNET_PSYC_env_get_count (const struct GNUNET_PSYC_Environment *env);


/**
* Destroy an environment.
*
* @param env The environment to destroy.
*/
void
GNUNET_PSYC_env_destroy (struct GNUNET_PSYC_Environment *env);


/**
* Get the type of variable.
*
* @param name Name of the variable.
*
* @return Variable type.
*/
enum GNUNET_PSYC_Type
GNUNET_PSYC_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_PSYC_operation (char *name, void *current_value, size_t current_value_size,
enum GNUNET_PSYC_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_PSYC_value_to_number (size_t size, const void *value, int64_t *number);


/**
* 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_PSYC_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_PSYC_value_from_number (int64_t number, 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_PSYC_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_PSYC_ENV_H */
#endif

/** @} */ /* end of group */

+ 278
- 0
src/include/gnunet_psyc_message.h View File

@@ -0,0 +1,278 @@
/*
This file is part of GNUnet.
Copyright (C) 2012, 2013 GNUnet e.V.

GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.

GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
*
* @file
* PSYC message utilities; receiving/transmitting/logging PSYC messages
*
* @defgroup psyc-util-message PSYC Utilities library: Messages
* Receiving, transmitting, logging PSYC messages.
* @{
*/

#ifndef GNUNET_PSYC_MESSAGE_H
#define GNUNET_PSYC_MESSAGE_H

#ifdef __cplusplus
extern "C"
{
#if 0 /* keep Emacsens' auto-indent happy */
}
#endif
#endif


#include "gnunet_util_lib.h"
#include "gnunet_psyc_util_lib.h"
#include "gnunet_psyc_service.h"


/**
* Create a PSYC message.
*
* @param method_name
* PSYC method for the message.
* @param env
* Environment for the message.
* @param data
* Data payload for the message.
* @param data_size
* Size of @a data.
*
* @return Message header with size information,
* followed by the message parts.
*
* FIXME: arg order
*/
struct GNUNET_PSYC_Message *
GNUNET_PSYC_message_create (const char *method_name,
const struct GNUNET_PSYC_Environment *env,
const void *data,
size_t data_size);

/**
* Parse PSYC message.
*
* @param msg
* The PSYC message to parse.
* @param env
* The environment for the message with a list of modifiers.
* @param[out] method_name
* Pointer to the method name inside @a pmsg.
* @param[out] data
* Pointer to data inside @a pmsg.
* @param[out] data_size
* Size of @data is written here.
*
* @return #GNUNET_OK on success,
* #GNUNET_SYSERR on parse error.
*
* FIXME: arg order
*/
int
GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_MessageHeader *msg,
const char **method_name,
struct GNUNET_PSYC_Environment *env,
const void **data,
uint16_t *data_size);


void
GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind,
const struct GNUNET_MessageHeader *msg);


struct GNUNET_PSYC_TransmitHandle;

/**
* Create a transmission handle.
*/
struct GNUNET_PSYC_TransmitHandle *
GNUNET_PSYC_transmit_create (struct GNUNET_MQ_Handle *mq);


/**
* Destroy a transmission handle.
*/
void
GNUNET_PSYC_transmit_destroy (struct GNUNET_PSYC_TransmitHandle *tmit);


/**
* Transmit a message.
*
* @param tmit
* Transmission handle.
* @param method_name
* Which method should be invoked.
* @param env
* Environment for the message.
* Should stay available until the first call to notify_data.
* Can be NULL if there are no modifiers or @a notify_mod is
* provided instead.
* @param notify_mod
* Function to call to obtain modifiers.
* Can be NULL if there are no modifiers or @a env is provided instead.
* @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 #GNUNET_OK if the transmission was started.
* #GNUNET_SYSERR if another transmission is already going on.
*/
int
GNUNET_PSYC_transmit_message (struct GNUNET_PSYC_TransmitHandle *tmit,
const char *method_name,
const struct GNUNET_PSYC_Environment *env,
GNUNET_PSYC_TransmitNotifyModifier notify_mod,
GNUNET_PSYC_TransmitNotifyData notify_data,
void *notify_cls,
uint32_t flags);


/**
* Resume transmission.
*
* @param tmit Transmission handle.
*/
void
GNUNET_PSYC_transmit_resume (struct GNUNET_PSYC_TransmitHandle *tmit);


/**
* Abort transmission request.
*
* @param tmit Transmission handle.
*/
void
GNUNET_PSYC_transmit_cancel (struct GNUNET_PSYC_TransmitHandle *tmit);


/**
* Got acknowledgement of a transmitted message part, continue transmission.
*
* @param tmit Transmission handle.
*/
void
GNUNET_PSYC_transmit_got_ack (struct GNUNET_PSYC_TransmitHandle *tmit);


struct GNUNET_PSYC_ReceiveHandle;


/**
* Create handle for receiving messages.
*/
struct GNUNET_PSYC_ReceiveHandle *
GNUNET_PSYC_receive_create (GNUNET_PSYC_MessageCallback message_cb,
GNUNET_PSYC_MessagePartCallback message_part_cb,
void *cb_cls);


/**
* Destroy handle for receiving messages.
*/
void
GNUNET_PSYC_receive_destroy (struct GNUNET_PSYC_ReceiveHandle *recv);


/**
* Reset stored data related to the last received message.
*/
void
GNUNET_PSYC_receive_reset (struct GNUNET_PSYC_ReceiveHandle *recv);


/**
* Handle incoming PSYC message.
*
* @param recv
* Receive handle.
* @param msg
* The message.
*
* @return #GNUNET_OK on success,
* #GNUNET_SYSERR on receive error.
*/
int
GNUNET_PSYC_receive_message (struct GNUNET_PSYC_ReceiveHandle *recv,
const struct GNUNET_PSYC_MessageHeader *msg);


/**
* Check if @a data contains a series of valid message parts.
*
* @param data_size
* Size of @a data.
* @param data
* Data.
* @param[out] first_ptype
* Type of first message part.
* @param[out] last_ptype
* Type of last message part.
*
* @return Number of message parts found in @a data.
* or GNUNET_SYSERR if the message contains invalid parts.
*/
int
GNUNET_PSYC_receive_check_parts (uint16_t data_size, const char *data,
uint16_t *first_ptype, uint16_t *last_ptype);


/**
* Initialize PSYC message header.
*/
void
GNUNET_PSYC_message_header_init (struct GNUNET_PSYC_MessageHeader *pmsg,
const struct GNUNET_MULTICAST_MessageHeader *mmsg,
uint32_t flags);


/**
* Create a new PSYC message header from a multicast message for sending it to clients.
*/
struct GNUNET_PSYC_MessageHeader *
GNUNET_PSYC_message_header_create (const struct GNUNET_MULTICAST_MessageHeader *mmsg,
uint32_t flags);


/**
* Create a new PSYC message header from a PSYC message.
*/
struct GNUNET_PSYC_MessageHeader *
GNUNET_PSYC_message_header_create_from_psyc (const struct GNUNET_PSYC_Message *msg);


#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
#ifdef __cplusplus
}
#endif

/* ifndef GNUNET_PSYC_MESSAGE_H */
#endif

/** @} */ /* end of group */

+ 1364
- 0
src/include/gnunet_psyc_service.h
File diff suppressed because it is too large
View File


+ 378
- 0
src/include/gnunet_psyc_slicer.h View File

@@ -0,0 +1,378 @@
/*
This file is part of GNUnet.
Copyright (C) 2013 GNUnet e.V.

GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.

GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
* @author Christian Grothoff
*
* @file
* PSYC Slicer library
*
* @defgroup psyc-util-slicer PSYC Utilities library: Slicer
* Try-and-slice processing of PSYC method names and environment.
* @{
*/

#ifndef GNUNET_PSYC_SLICER_H
#define GNUNET_PSYC_SLICER_H


#ifdef __cplusplus
extern "C"
{
#if 0 /* keep Emacsens' auto-indent happy */
}
#endif
#endif

#include "gnunet_util_lib.h"


/**
* Handle to an implementation of try-and-slice.
*/
struct GNUNET_PSYC_Slicer;


/**
* Function called upon receiving a message indicating a call to a @e method.
*
* This function is called one or more times for each message until all data
* fragments arrive from the network.
*
* @param cls
* Closure.
* @param msg
* Message part, as it arrived from the network.
* @param message_id
* Message counter, monotonically increasing from 1.
* @param flags
* OR'ed GNUNET_PSYC_MessageFlags
* @param fragment_offset
* Multicast message fragment offset.
* @param tmit_flags
* OR'ed GNUNET_PSYC_MasterTransmitFlags
* @param nym
* The sender of the message.
* Can be NULL if the message is not connected to a pseudonym.
* @param method_name
* Original method name from PSYC.
* May be more specific than the registered method name due to
* try-and-slice matching.
*/
typedef void
(*GNUNET_PSYC_MethodCallback) (void *cls,
const struct GNUNET_PSYC_MessageHeader *msg,
const struct GNUNET_PSYC_MessageMethod *meth,
uint64_t message_id,
const char *method_name);


/**
* Function called upon receiving a modifier of a message.
*
* @param cls
* Closure.
* @param message_id
* Message ID this data fragment belongs to.
* @param flags
* OR'ed GNUNET_PSYC_MessageFlags
* @param fragment_offset
* Multicast message fragment offset.
* @param msg
* Message part, as it arrived from the network.
* @param oper
* Operation to perform.
* 0 in case of a modifier continuation.
* @param name
* Name of the modifier.
* NULL in case of a modifier continuation.
* @param value
* Value of the modifier.
* @param value_size
* Size of @value.
*/
typedef void
(*GNUNET_PSYC_ModifierCallback) (void *cls,
const struct GNUNET_PSYC_MessageHeader *msg,
const struct GNUNET_MessageHeader *pmsg,
uint64_t message_id,
enum GNUNET_PSYC_Operator oper,
const char *name,
const void *value,
uint16_t value_size,
uint16_t full_value_size);


/**
* Function called upon receiving a data fragment of a message.
*
* @param cls
* Closure.
* @param msg
* Message part, as it arrived from the network.
* @param message_id
* Message ID this data fragment belongs to.
* @param flags
* OR'ed GNUNET_PSYC_MessageFlags
* @param fragment_offset
* Multicast message fragment offset.
* @param data
* Data stream given to the method.
* @param data_size
* Number of bytes in @a data.
* @param end
* End of message?
* #GNUNET_NO if there are further fragments,
* #GNUNET_YES if this is the last fragment,
* #GNUNET_SYSERR indicates the message was cancelled by the sender.
*/
typedef void
(*GNUNET_PSYC_DataCallback) (void *cls,
const struct GNUNET_PSYC_MessageHeader *msg,
const struct GNUNET_MessageHeader *pmsg,
uint64_t message_id,
const void *data,
uint16_t data_size);


/**
* End of message.
*
* @param cls
* Closure.
* @param msg
* Message part, as it arrived from the network.
* @param message_id
* Message ID this data fragment belongs to.
* @param flags
* OR'ed GNUNET_PSYC_MessageFlags
* @param fragment_offset
* Multicast message fragment offset.
* @param cancelled
* #GNUNET_YES if the message was cancelled,
* #GNUNET_NO if the message is complete.
*/
typedef void
(*GNUNET_PSYC_EndOfMessageCallback) (void *cls,
const struct GNUNET_PSYC_MessageHeader *msg,
const struct GNUNET_MessageHeader *pmsg,
uint64_t message_id,
uint8_t is_cancelled);


/**
* Create a try-and-slice instance.
*
* A slicer processes incoming messages and notifies callbacks about matching
* methods or modifiers encountered.
*
* @return A new try-and-slice construct.
*/
struct GNUNET_PSYC_Slicer *
GNUNET_PSYC_slicer_create (void);


/**
* Add a method to the try-and-slice instance.
*
* The callbacks are called for messages with a matching @a method_name prefix.
*
* @param slicer
* The try-and-slice instance to extend.
* @param method_name
* Name of the given method, use empty string to match all.
* @param method_cb
* Method handler invoked upon a matching message.
* @param modifier_cb
* Modifier handler, invoked after @a method_cb
* for each modifier in the message.
* @param data_cb
* Data handler, invoked after @a modifier_cb for each data fragment.
* @param eom_cb
* Invoked upon reaching the end of a matching message.
* @param cls
* Closure for the callbacks.
*/
void
GNUNET_PSYC_slicer_method_add (struct GNUNET_PSYC_Slicer *slicer,
const char *method_name,
GNUNET_PSYC_MessageCallback msg_cb,
GNUNET_PSYC_MethodCallback method_cb,
GNUNET_PSYC_ModifierCallback modifier_cb,
GNUNET_PSYC_DataCallback data_cb,
GNUNET_PSYC_EndOfMessageCallback eom_cb,
void *cls);

/**
* Remove a registered method from the try-and-slice instance.
*
* Removes one matching handler registered with the given
* @a method_name and callbacks.
*
* @param slicer
* The try-and-slice instance.
* @param method_name
* Name of the method to remove.
* @param method_cb
* Only remove matching method handler, or NULL.
* @param modifier_cb
* Only remove matching modifier handler, or NULL.
* @param data_cb
* Only remove matching data handler, or NULL.
* @param eom_cb
* Only remove matching End of Message handler, or NULL.
*
* @return #GNUNET_OK if a method handler was removed,
* #GNUNET_NO if no handler matched the given method name and callbacks.
*/
int
GNUNET_PSYC_slicer_method_remove (struct GNUNET_PSYC_Slicer *slicer,
const char *method_name,
GNUNET_PSYC_MessageCallback msg_cb,
GNUNET_PSYC_MethodCallback method_cb,
GNUNET_PSYC_ModifierCallback modifier_cb,
GNUNET_PSYC_DataCallback data_cb,
GNUNET_PSYC_EndOfMessageCallback eom_cb);


/**
* Watch a place for changed objects.
*
* @param slicer
* The try-and-slice instance.
* @param object_filter
* Object prefix to match.
* @param modifier_cb
* Function to call when encountering a state modifier.
* @param cls
* Closure for callback.
*/
void
GNUNET_PSYC_slicer_modifier_add (struct GNUNET_PSYC_Slicer *slicer,
const char *object_filter,
GNUNET_PSYC_ModifierCallback modifier_cb,
void *cls);


/**
* Remove a registered modifier from the try-and-slice instance.
*
* Removes one matching handler registered with the given
* @a object_filter and callback.
*
* @param slicer
* The try-and-slice instance.
* @param object_filter
* Object prefix to match.
* @param modifier_cb
* Function to call when encountering a state modifier changes.
*/
int
GNUNET_PSYC_slicer_modifier_remove (struct GNUNET_PSYC_Slicer *slicer,
const char *object_filter,
GNUNET_PSYC_ModifierCallback modifier_cb);


/**
* Process an incoming message and call matching handlers.
*
* @param slicer
* The slicer to use.
* @param msg
* The message as it arrived from the network.
*/
void
GNUNET_PSYC_slicer_message (struct GNUNET_PSYC_Slicer *slicer,
const struct GNUNET_PSYC_MessageHeader *msg);


/**
* Process an incoming message part and call matching handlers.
*
* @param slicer
* The slicer to use.
* @param message_id
* ID of the message.
* @param flags
* Flags for the message.
* @see enum GNUNET_PSYC_MessageFlags
* @param fragment offset
* Fragment offset of the message.
* @param msg
* The message part as it arrived from the network.
*/
void
GNUNET_PSYC_slicer_message_part (struct GNUNET_PSYC_Slicer *slicer,
const struct GNUNET_PSYC_MessageHeader *msg,
const struct GNUNET_MessageHeader *pmsg);


/**
* Remove all registered method handlers.
*
* @param slicer
* Slicer to clear.
*/
void
GNUNET_PSYC_slicer_method_clear (struct GNUNET_PSYC_Slicer *slicer);


/**
* Remove all registered modifier handlers.
*
* @param slicer
* Slicer to clear.
*/
void
GNUNET_PSYC_slicer_modifier_clear (struct GNUNET_PSYC_Slicer *slicer);


/**
* Remove all registered method & modifier handlers.
*
* @param slicer
* Slicer to clear.
*/
void
GNUNET_PSYC_slicer_clear (struct GNUNET_PSYC_Slicer *slicer);


/**
* Destroy a given try-and-slice instance.
*
* @param slicer
* Slicer to destroy
*/
void
GNUNET_PSYC_slicer_destroy (struct GNUNET_PSYC_Slicer *slicer);


#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
#ifdef __cplusplus
}
#endif

/* ifndef GNUNET_PSYC_SLICER_H */
#endif

/** @} */ /* end of group */

+ 53
- 0
src/include/gnunet_psyc_util_lib.h View File

@@ -0,0 +1,53 @@
/*
This file is part of GNUnet.
Copyright (C) 2012, 2013 GNUnet e.V.

GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.

GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
*
* @file
* PSYC utilities: messages, environment, slicer
*/

#ifndef GNUNET_PSYC_UTIL_LIB_H
#define GNUNET_PSYC_UTIL_LIB_H

#ifdef __cplusplus
extern "C"
{
#if 0 /* keep Emacsens' auto-indent happy */
}
#endif
#endif


#include "gnunet_psyc_env.h"
#include "gnunet_psyc_message.h"
#include "gnunet_psyc_slicer.h"


#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
#ifdef __cplusplus
}
#endif

/* ifndef GNUNET_PSYC_UTIL_LIB_H */
#endif

+ 383
- 0
src/include/gnunet_psycstore_plugin.h View File

@@ -0,0 +1,383 @@
/*
This file is part of GNUnet
Copyright (C) 2013 GNUnet e.V.

GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.

GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
*
* @file
* Plugin API for the PSYCstore database backend
*
* @defgroup psycstore-plugin PSYC Store plugin API
* Plugin API for the PSYC Store database backend
* @{
*/
#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_EcdsaPublicKey *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_EcdsaPublicKey *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,
uint32_t psycstore_flags);

/**
* Retrieve a message fragment range 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 first_fragment_id,
uint64_t last_fragment_id,
uint64_t *returned_fragments,
GNUNET_PSYCSTORE_FragmentCallback cb,
void *cb_cls);

/**
* Retrieve latest message fragments.
*
* @see GNUNET_PSYCSTORE_fragment_get()
*
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
*/
int
(*fragment_get_latest) (void *cls,
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
uint64_t fragment_limit,
uint64_t *returned_fragments,
GNUNET_PSYCSTORE_FragmentCallback cb,
void *cb_cls);

/**
* Retrieve all fragments of a message ID range.
*
* @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 first_fragment_id,
uint64_t last_fragment_id,
uint64_t fragment_limit,
uint64_t *returned_fragments,
GNUNET_PSYCSTORE_FragmentCallback cb,
void *cb_cls);

/**
* Retrieve all fragments of the latest messages.
*
* @see GNUNET_PSYCSTORE_message_get()
*
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
*/
int
(*message_get_latest) (void *cls,
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
uint64_t fragment_limit,
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_op) (void *cls,
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
enum GNUNET_PSYC_Operator op,
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);

/**
* Assign 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 using state_sync_end().
*
* @see GNUNET_PSYCSTORE_state_sync()
*
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
*/
int
(*state_sync_assign) (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 max_state_message_id,
uint64_t state_hash_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

#endif

/** @} */ /* end of group */

+ 701
- 0
src/include/gnunet_psycstore_service.h View File

@@ -0,0 +1,701 @@
/*
This file is part of GNUnet.
Copyright (C) 2013 GNUnet e.V.

GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.

GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
* @author Christian Grothoff
*
* @file
* PSYCstore service; implements persistent storage for the PSYC service
*
* @defgroup psycstore PSYC Store service
* Persistent storage for the PSYC service.
* @{
*/
#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_psyc_util_lib.h"
#include "gnunet_multicast_service.h"
#include "gnunet_psyc_service.h"

/**
* Version number of GNUnet PSYCstore API.
*/
#define GNUNET_PSYCSTORE_VERSION 0x00000000

/**
* Membership test failed.
*/
#define GNUNET_PSYCSTORE_MEMBERSHIP_TEST_FAILED -2

/**
* 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 cls
* Closure.
* @param result
* Result of the operation.
* @param err_msg
* Error message, or NULL if there's no error.
* @param err_msg_size
* Size of @a err_msg
*/
typedef void
(*GNUNET_PSYCSTORE_ResultCallback) (void *cls,
int64_t result,
const char *err_msg,
uint16_t err_msg_size);


/**
* 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 result_cb
* Callback to call with the result of the storage operation.
* @param 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_EcdsaPublicKey *slave_key,
int did_join,
uint64_t announced_at,
uint64_t effective_since,
uint64_t group_generation,
GNUNET_PSYCSTORE_ResultCallback result_cb,
void *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 result_cb
* Callback to call with the test result.
* @param 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_EcdsaPublicKey *slave_key,
uint64_t message_id,
uint64_t group_generation,
GNUNET_PSYCSTORE_ResultCallback result_cb,
void *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 msg Message to store.
* @param psycstore_flags Flags indicating whether the PSYC message contains
* state modifiers.
* @param result_cb Callback to call with the result of the operation.
* @param 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 *msg,
enum GNUNET_PSYCSTORE_MessageFlags psycstore_flags,
GNUNET_PSYCSTORE_ResultCallback result_cb,
void *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 message fragments by fragment ID range.
*
* @param h
* Handle for the PSYCstore.
* @param channel_key
* The channel we are interested in.
* @param slave_key
* The slave requesting the fragment. If not NULL, a membership test is
* performed first and the fragment is only returned if the slave has
* access to it.
* @param first_fragment_id
* First fragment ID to retrieve.
* Use 0 to get the latest message fragment.
* @param last_fragment_id
* Last consecutive fragment ID to retrieve.
* Use 0 to get the latest message fragment.
* @param fragment_cb
* Callback to call with the retrieved fragments.
* @param result_cb
* 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,
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
uint64_t first_message_id,
uint64_t last_message_id,
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
GNUNET_PSYCSTORE_ResultCallback result_cb,
void *cls);


/**
* Retrieve latest message fragments.
*
* @param h
* Handle for the PSYCstore.
* @param channel_key
* The channel we are interested in.
* @param slave_key
* The slave requesting the fragment. If not NULL, a membership test is
* performed first and the fragment is only returned if the slave has
* access to it.
* @param first_fragment_id
* First fragment ID to retrieve.
* Use 0 to get the latest message fragment.
* @param last_fragment_id
* Last consecutive fragment ID to retrieve.
* Use 0 to get the latest message fragment.
* @param fragment_limit
* Maximum number of fragments to retrieve.
* @param fragment_cb
* Callback to call with the retrieved fragments.
* @param result_cb
* 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_latest (struct GNUNET_PSYCSTORE_Handle *h,
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
uint64_t fragment_limit,
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
GNUNET_PSYCSTORE_ResultCallback result_cb,
void *cls);


/**
* Retrieve all fragments of messages in a message ID range.
*
* @param h
* Handle for the PSYCstore.
* @param channel_key
* The channel we are interested in.
* @param slave_key
* The slave requesting the message.
* If not NULL, a membership test is performed first
* and the message is only returned if the slave has access to it.
* @param first_message_id
* First message ID to retrieve.
* @param last_message_id
* Last consecutive message ID to retrieve.
* @param fragment_limit
* Maximum number of fragments to retrieve.
* @param method_prefix
* Retrieve only messages with a matching method prefix.
* @param fragment_cb
* Callback to call with the retrieved fragments.
* @param result_cb
* 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,
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
uint64_t first_message_id,
uint64_t last_message_id,
uint64_t fragment_limit,
const char *method_prefix,
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
GNUNET_PSYCSTORE_ResultCallback result_cb,
void *cls);


/**
* Retrieve all fragments of the latest messages.
*
* @param h
* Handle for the PSYCstore.
* @param channel_key
* The channel we are interested in.
* @param slave_key
* The slave requesting the message.
* If not NULL, a membership test is performed first
* and the message is only returned if the slave has access to it.
* @param message_limit
* Maximum number of messages to retrieve.
* @param method_prefix
* Retrieve only messages with a matching method prefix.
* @param fragment_cb
* Callback to call with the retrieved fragments.
* @param result_cb
* 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_latest (struct GNUNET_PSYCSTORE_Handle *h,
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
uint64_t message_limit,
const char *method_prefix,
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
GNUNET_PSYCSTORE_ResultCallback result_cb,
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 slave_key
* The slave requesting the message fragment. If not NULL, a membership
* test is performed first and the message fragment is only returned
* if the slave has access to it.
* @param message_id
* Message ID to retrieve. Use 0 to get the latest message.
* @param fragment_offset
* Offset of the fragment to retrieve.
* @param fragment_cb
* Callback to call with the retrieved fragments.
* @param result_cb
* 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,
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
uint64_t message_id,
uint64_t fragment_offset,
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
GNUNET_PSYCSTORE_ResultCallback result_cb,
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 counters_cb
* Callback to call with the result.
* @param 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 counters_cb,
void *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 result_cb
* Callback to call with the result of the operation.
* @param cls
* Closure for the @a result_cb 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,
GNUNET_PSYCSTORE_ResultCallback result_cb,
void *cls);


/**
* Store synchronized state.
*
* @param h
* Handle for the PSYCstore.
* @param channel_key
* The channel we are interested in.
* @param max_state_message_id
* ID of the last stateful message before @a state_hash_message_id.
* @param state_hash_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 result_cb
* Callback to call with the result of the operation.
* @param 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 max_state_message_id,
uint64_t state_hash_message_id,
size_t modifier_count,
const struct GNUNET_PSYC_Modifier *modifiers,
GNUNET_PSYCSTORE_ResultCallback result_cb,
void *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 result_cb
* Callback to call with the result of the operation.
* @param 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 result_cb,
void *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 result_cb
* Callback to call with the result of the operation.
* @param 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 result_cb,
void *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, uint32_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 state_cb
* Callback to return the matching state variable.
* @param result_cb
* 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 state_cb,
GNUNET_PSYCSTORE_ResultCallback result_cb,
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 state_cb
* Callback to return matching state variables.
* @param result_cb
* 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 state_cb,
GNUNET_PSYCSTORE_ResultCallback result_cb,
void *cls);


/**
* Cancel an operation.
*
* @param op Handle for the operation to cancel.
*/
int
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 group */

+ 1344
- 0
src/include/gnunet_social_service.h
File diff suppressed because it is too large
View File


+ 7
- 0
src/multicast/.gitignore View File

@@ -0,0 +1,7 @@
gnunet-service-multicast
gnunet-multicast
test_multicast
test_multicast_multipeer
test_multicast_2peers
test_multicast_multipeer_line
test_multicast_multipeer_star

+ 79
- 0
src/multicast/Makefile.am View File

@@ -0,0 +1,79 @@
# This Makefile.am is in the public domain
AM_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 \
$(EXP_LIBEXEC)

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 \
$(top_builddir)/src/cadet/libgnunetcadet.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(GN_LIBINTL)

check_PROGRAMS = \
test_multicast \
test_multicast_multipeer_star \
test_multicast_multipeer_line

if ENABLE_TEST_RUN
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@}; export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; unset XDG_DATA_HOME; unset XDG_CONFIG_HOME;
TESTS = $(check_PROGRAMS)
endif

test_multicast_SOURCES = \
test_multicast.c
test_multicast_LDADD = \
libgnunetmulticast.la \
$(top_builddir)/src/testing/libgnunettesting.la \
$(top_builddir)/src/util/libgnunetutil.la
test_multicast_multipeer_star_SOURCES = \
test_multicast_multipeer.c
test_multicast_multipeer_star_LDADD = \
libgnunetmulticast.la \
$(top_builddir)/src/testbed/libgnunettestbed.la \
$(top_builddir)/src/util/libgnunetutil.la
test_multicast_multipeer_line_SOURCES = \
test_multicast_multipeer.c
test_multicast_multipeer_line_LDADD = \
libgnunetmulticast.la \
$(top_builddir)/src/testbed/libgnunettestbed.la \
$(top_builddir)/src/util/libgnunetutil.la

+ 79
- 0
src/multicast/gnunet-multicast.c View File

@@ -0,0 +1,79 @@
/*
This file is part of GNUnet.
Copyright (C) 2013 GNUnet e.V.

GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.

GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @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 */
puts( gettext_noop ("This command doesn't do anything yet.") );
ret = -1;
}


/**
* 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 ("This command doesn't do anything yet."),
options, &run,
NULL)) ? ret : 1;
GNUNET_free ((void*) argv);
return ret;
}

/* end of gnunet-multicast.c */

+ 2234
- 0
src/multicast/gnunet-service-multicast.c
File diff suppressed because it is too large
View File


+ 22
- 0
src/multicast/multicast.conf.in View File

@@ -0,0 +1,22 @@
[multicast]
START_ON_DEMAND = @START_ON_DEMAND@
BINARY = gnunet-service-multicast

UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock
UNIX_MATCH_UID = YES
UNIX_MATCH_GID = YES

@UNIXONLY@PORT = 2109
HOSTNAME = localhost
ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;

# DISABLE_SOCKET_FORWARDING = NO
# USERNAME =
# MAXBUF =
# TIMEOUT =
# DISABLEV6 =
# BINDTO =
# REJECT_FROM =
# REJECT_FROM6 =
# PREFIX =

+ 303
- 0
src/multicast/multicast.h View File

@@ -0,0 +1,303 @@
/*
This file is part of GNUnet.
Copyright (C) 2012, 2013 GNUnet e.V.

GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.

GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @file multicast/multicast.h
* @brief multicast IPC messages
* @author Christian Grothoff
* @author Gabor X Toth
*/
#ifndef MULTICAST_H
#define MULTICAST_H

#include "platform.h"
#include "gnunet_multicast_service.h"

GNUNET_NETWORK_STRUCT_BEGIN


/**
* Header of a join request sent to the origin or another member.
*/
struct MulticastJoinRequestMessage
{
/**
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST
*/
struct GNUNET_MessageHeader header;

/**
* Always zero.
*/
uint32_t reserved;

/**
* 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_EcdsaSignature 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_pub_key;

/**
* Public key of the joining member.
*/
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;

/**
* Peer identity of the joining member.
*/
struct GNUNET_PeerIdentity peer;

/* Followed by struct GNUNET_MessageHeader join_message */
};


/**
* Header of a join decision message sent to a peer requesting join.
*/
struct MulticastJoinDecisionMessage
{
/**
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION
*/
struct GNUNET_MessageHeader header;

/**
* #GNUNET_YES if the peer was admitted
* #GNUNET_NO if entry was refused,
* #GNUNET_SYSERR if the request could not be answered.
*/
int32_t is_admitted;

/**
* Number of relays given.
*/
uint32_t relay_count;

/* Followed by relay_count peer identities */

/* Followed by the join response message */
};


/**
* Header added to a struct MulticastJoinDecisionMessage
* when sent between the client and service.
*/
struct MulticastJoinDecisionMessageHeader
{
/**
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION
*/
struct GNUNET_MessageHeader header;

/**
* C->S: Peer to send the join decision to.
* S->C: Peer we received the join decision from.
*/
struct GNUNET_PeerIdentity peer;

/**
* C->S: Public key of the member requesting join.
* S->C: Unused.
*/
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;

/* Followed by struct MulticastJoinDecisionMessage */
};


/**
* Message sent from the client to the service to notify the service
* about the result of a membership test.
*/
struct MulticastMembershipTestResultMessage
{
/**
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_MEMBERSHIP_TEST_RESULT
*/
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 is not a member,
* #GNUNET_SYSERR if the test could not be answered.
*/
int32_t is_admitted;
};


/**
* 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 should be
* #GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST.
*/
struct GNUNET_MessageHeader header;

/**
* S->C: Public key of the member requesting replay.
* C->S: Unused.
*/
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;

/**
* ID of the message that is being requested.
*/
uint64_t fragment_id;

/**
* 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;

/**
* Replay request ID.
*/
uint32_t uid;
};


/**
* Message sent from the client to the service to give the service
* a replayed message.
*/
struct MulticastReplayResponseMessage
{

/**
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE
* or GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END
*/
struct GNUNET_MessageHeader header;

/**
* ID of the message that is being requested.
*/
uint64_t fragment_id;

/**
* 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;

/**
* 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 starting of a multicast group with this peers as its origin.
*/
struct MulticastOriginStartMessage
{
/**
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START
*/
struct GNUNET_MessageHeader header;

/**
* Always zero.
*/
uint32_t reserved;

/**
* Private, non-ephemeral key for the multicast group.
*/
struct GNUNET_CRYPTO_EddsaPrivateKey group_key;

/**
* Last fragment ID sent to the group, used to continue counting fragments if
* we resume operating * a group.
*/
uint64_t max_fragment_id;
};


struct MulticastMemberJoinMessage
{
/**
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN
*/
struct GNUNET_MessageHeader header;

uint32_t relay_count GNUNET_PACKED;

struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;

struct GNUNET_CRYPTO_EcdsaPrivateKey member_key;

struct GNUNET_PeerIdentity origin;

/* Followed by struct GNUNET_PeerIdentity relays[relay_count] */

/* Followed by struct GNUNET_MessageHeader join_msg */
};


GNUNET_NETWORK_STRUCT_END

#endif
/* end of multicast.h */

+ 1399
- 0
src/multicast/multicast_api.c
File diff suppressed because it is too large
View File


+ 758
- 0
src/multicast/test_multicast.c View File

@@ -0,0 +1,758 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @file multicast/test_multicast.c
* @brief Tests for the Multicast API.
* @author Gabor X Toth
*/

#include <inttypes.h>

#include "platform.h"
#include "gnunet_crypto_lib.h"
#include "gnunet_common.h"
#include "gnunet_util_lib.h"
#include "gnunet_testing_lib.h"
#include "gnunet_multicast_service.h"

#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)

/**
* Return value from 'main'.
*/
static int res;

/**
* Handle for task for timeout termination.
*/
static struct GNUNET_SCHEDULER_Task * end_badly_task;

static const struct GNUNET_CONFIGURATION_Handle *cfg;

struct GNUNET_PeerIdentity this_peer;

struct GNUNET_MULTICAST_Origin *origin;
struct GNUNET_MULTICAST_Member *member;

struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;

struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key;
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;

struct TransmitClosure {
struct GNUNET_MULTICAST_OriginTransmitHandle *orig_tmit;
struct GNUNET_MULTICAST_MemberTransmitHandle *mem_tmit;
char * data[16];
uint8_t data_delay[16];
uint8_t data_count;
uint8_t paused;
uint8_t n;
} tmit_cls;

struct OriginClosure {
uint8_t msgs_expected;
uint8_t n;
} origin_cls;

struct MemberClosure {
uint8_t msgs_expected;
size_t n;
} member_cls;

struct GNUNET_MessageHeader *join_req, *join_resp;

enum
{
TEST_NONE = 0,
TEST_ORIGIN_START = 1,
TEST_MEMBER_JOIN_REFUSE = 2,
TEST_MEMBER_JOIN_ADMIT = 3,
TEST_ORIGIN_TO_ALL = 4,
TEST_ORIGIN_TO_ALL_RECV = 5,
TEST_MEMBER_TO_ORIGIN = 6,
TEST_MEMBER_REPLAY_ERROR = 7,
TEST_MEMBER_REPLAY_OK = 8,
TEST_MEMBER_PART = 9,
TEST_ORIGIN_STOP = 10,
} test;

uint64_t replay_fragment_id;
uint64_t replay_flags;

static void
member_join (int t);


/**
* Clean up all resources used.
*/
static void
cleanup ()
{
if (NULL != member)
{
GNUNET_MULTICAST_member_part (member, NULL, NULL);
member = NULL;
}
if (NULL != origin)
{
GNUNET_MULTICAST_origin_stop (origin, NULL, NULL);
origin = NULL;
}
}


/**
* Terminate the test case (failure).
*
* @param cls NULL
*/
static void
end_badly (void *cls)
{
res = 1;
cleanup ();
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test FAILED.\n");
}


/**
* Terminate the test case (success).
*
* @param cls NULL
*/
static void
end_normally (void *cls)
{
res = 0;
cleanup ();
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test PASSED.\n");
}


/**
* Finish the test case (successfully).
*/
static void
end ()
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n");

if (end_badly_task != NULL)
{
GNUNET_SCHEDULER_cancel (end_badly_task);
end_badly_task = NULL;
}
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
&end_normally, NULL);
}


static void
tmit_resume (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n");
struct TransmitClosure *tmit = cls;
if (NULL != tmit->orig_tmit)
GNUNET_MULTICAST_origin_to_all_resume (tmit->orig_tmit);
else if (NULL != tmit->mem_tmit)
GNUNET_MULTICAST_member_to_origin_resume (tmit->mem_tmit);
}


static int
tmit_notify (void *cls, size_t *data_size, void *data)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Test #%u: origin_tmit_notify()\n", test);
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",
(unsigned int) *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]),
tmit_resume, tmit);
*data_size = 0;
return GNUNET_NO;
}
tmit->paused = GNUNET_NO;

*data_size = size;
GNUNET_memcpy (data, tmit->data[tmit->n], size);

return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES;
}


static void
member_recv_join_request (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
const struct GNUNET_MessageHeader *join_msg,
struct GNUNET_MULTICAST_JoinHandle *jh)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_recv_join_request()\n", test);
}


static void
origin_stopped (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: origin_stopped()\n", test);
end ();
}


static void
schedule_origin_stop (void *cls)
{
test = TEST_ORIGIN_STOP;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: origin_stop()\n", test);
GNUNET_MULTICAST_origin_stop (origin, origin_stopped, NULL);
origin = NULL;
}


static void
member_parted (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_parted()\n", test);
member = NULL;

switch (test)
{
case TEST_MEMBER_JOIN_REFUSE:
// Test 3 starts here
member_join (TEST_MEMBER_JOIN_ADMIT);
break;

case TEST_MEMBER_PART:
GNUNET_SCHEDULER_add_now (&schedule_origin_stop, NULL);
break;

default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid test #%d in member_parted()\n", test);
GNUNET_assert (0);
}
}


static void
schedule_member_part (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: schedule_member_part()\n", test);
GNUNET_MULTICAST_member_part (member, member_parted, NULL);
}


static void
member_part ()
{
test = TEST_MEMBER_PART;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_part()\n", test);
// Test 10 starts here
GNUNET_SCHEDULER_add_now (&schedule_member_part, NULL);
}


static void
member_replay_ok ()
{
// Execution of test 8 here
test = TEST_MEMBER_REPLAY_OK;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_replay_ok()\n", test);
replay_fragment_id = 1;
replay_flags = 1 | 1<<11;
GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id,
replay_flags);
}


static void
member_replay_error ()
{
test = TEST_MEMBER_REPLAY_ERROR;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_replay_error()\n", test);
replay_fragment_id = 1234;
replay_flags = 11 | 1<<11;
GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id,
replay_flags);
}


static void
origin_recv_replay_msg (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
uint64_t message_id,
uint64_t fragment_offset,
uint64_t flags,
struct GNUNET_MULTICAST_ReplayHandle *rh)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: origin_recv_replay_msg()\n", test);
GNUNET_assert (0);
}


static void
member_recv_replay_msg (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
uint64_t message_id,
uint64_t fragment_offset,
uint64_t flags,
struct GNUNET_MULTICAST_ReplayHandle *rh)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_recv_replay_msg()\n", test);
GNUNET_assert (0);
}


static void
origin_recv_replay_frag (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
uint64_t fragment_id,
uint64_t flags,
struct GNUNET_MULTICAST_ReplayHandle *rh)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: origin_recv_replay_frag()"
" - fragment_id=%" PRIu64 " flags=%" PRIu64 "\n",
test, fragment_id, flags);
GNUNET_assert (replay_fragment_id == fragment_id && replay_flags == flags);
switch (test)
{
case TEST_MEMBER_REPLAY_ERROR:
// Test 8 starts here
GNUNET_MULTICAST_replay_response (rh, NULL, GNUNET_SYSERR);
member_replay_ok ();
break;

case TEST_MEMBER_REPLAY_OK:
{
struct GNUNET_MULTICAST_MessageHeader mmsg = {
.header = {
.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE),
.size = htons (sizeof (mmsg)),
},
.fragment_id = GNUNET_htonll (1),
.message_id = GNUNET_htonll (1),
.fragment_offset = 0,
.group_generation = GNUNET_htonll (1),
.flags = 0,
};
member_cls.n = 0;
member_cls.msgs_expected = 1;
GNUNET_MULTICAST_replay_response (rh, &mmsg.header, GNUNET_MULTICAST_REC_OK);
GNUNET_MULTICAST_replay_response_end (rh);
break;
}

default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid test #%d in origin_recv_replay_frag()\n", test);
GNUNET_assert (0);
}
}


static void
member_recv_replay_frag (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
uint64_t fragment_id,
uint64_t flags,
struct GNUNET_MULTICAST_ReplayHandle *rh)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_recv_replay_frag()\n", test);
GNUNET_assert (0);
}


static void
origin_recv_request (void *cls,
const struct GNUNET_MULTICAST_RequestHeader *req)
{
struct OriginClosure *ocls = cls;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: origin_recv_request()\n", test);
if (++ocls->n != ocls->msgs_expected)
return;

GNUNET_assert (0 == memcmp (&req->member_pub_key,
&member_pub_key, sizeof (member_pub_key)));

GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Test #%u: verify message content, take first 3 bytes: %.3s\n",
test, (char *)&req[1]);
GNUNET_assert (0 == memcmp (&req[1], "abc", 3));

// Test 7 starts here
member_replay_error ();
}


static void
member_to_origin ()
{
test = TEST_MEMBER_TO_ORIGIN;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_to_origin()\n", test);

struct TransmitClosure *tmit = &tmit_cls;
*tmit = (struct TransmitClosure) {};
tmit->data[0] = "abc def";
tmit->data[1] = "ghi jkl mno";
tmit->data_delay[1] = 2;
tmit->data[2] = "pqr stuw xyz";
tmit->data_count = 3;

origin_cls.n = 0;
origin_cls.msgs_expected = 1;

tmit->mem_tmit = GNUNET_MULTICAST_member_to_origin (member, 1,
tmit_notify, tmit);
}


static void
member_recv_message (void *cls,
const struct GNUNET_MULTICAST_MessageHeader *msg)
{
struct MemberClosure *mcls = cls;

// Test 5 starts here after message has been received from origin
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Test #%u: member_recv_message() %u/%u\n",
test,
(unsigned int) (mcls->n + 1),
mcls->msgs_expected);
if (++mcls->n != mcls->msgs_expected)
return;

// FIXME: check message content

switch (test)
{
case TEST_ORIGIN_TO_ALL:
test = TEST_ORIGIN_TO_ALL_RECV;
break;

case TEST_ORIGIN_TO_ALL_RECV:
// Test 6 starts here
member_to_origin ();
break;

case TEST_MEMBER_REPLAY_OK:
// Test 9 starts here
GNUNET_assert (replay_fragment_id == GNUNET_ntohll (msg->fragment_id));
member_part ();
break;

default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid test #%d in origin_recv_message()\n", test);
GNUNET_assert (0);
}
}


static void
origin_recv_message (void *cls,
const struct GNUNET_MULTICAST_MessageHeader *msg)
{
struct OriginClosure *ocls = cls;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: origin_recv_message() %u/%u\n",
test, ocls->n + 1, ocls->msgs_expected);
if (++ocls->n != ocls->msgs_expected)
return;

// FIXME: check message content

switch (test)
{
case TEST_ORIGIN_TO_ALL:
// Prepare to execute test 5
test = TEST_ORIGIN_TO_ALL_RECV;
break;

case TEST_ORIGIN_TO_ALL_RECV:
// Test 6 starts here
member_to_origin ();
break;

default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid test #%d in origin_recv_message()\n", test);
GNUNET_assert (0);
}
}


static void
origin_to_all ()
{
test = TEST_ORIGIN_TO_ALL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: origin_to_all()\n", test);

struct TransmitClosure *tmit = &tmit_cls;
*tmit = (struct TransmitClosure) {};
tmit->data[0] = "ABC DEF";
tmit->data[1] = GNUNET_malloc (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD + 1);
uint16_t i;
for (i = 0; i < GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD; i++)
tmit->data[1][i] = (0 == i % 10000) ? '0' + i / 10000 : '_';
tmit->data[2] = "GHI JKL MNO";
tmit->data_delay[2] = 2;
tmit->data[3] = "PQR STUW XYZ";
tmit->data_count = 4;

origin_cls.n = member_cls.n = 0;
origin_cls.msgs_expected = member_cls.msgs_expected = tmit->data_count;

tmit->orig_tmit = GNUNET_MULTICAST_origin_to_all (origin, 1, 1,
tmit_notify, tmit);
}


static void
member_recv_join_decision (void *cls,
int is_admitted,
const struct GNUNET_PeerIdentity *peer,
uint16_t relay_count,
const struct GNUNET_PeerIdentity *relays,
const struct GNUNET_MessageHeader *join_msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_recv_join_decision() - is_admitted: %d\n",
test, is_admitted);

GNUNET_assert (join_msg->size == join_resp->size);
GNUNET_assert (join_msg->type == join_resp->type);
GNUNET_assert (0 == memcmp (join_msg, join_resp, ntohs (join_resp->size)));

switch (test)
{
case TEST_MEMBER_JOIN_REFUSE:
GNUNET_assert (0 == relay_count);
// Test 3 starts here
GNUNET_SCHEDULER_add_now (&schedule_member_part, NULL);
break;

case TEST_MEMBER_JOIN_ADMIT:
GNUNET_assert (1 == relay_count);
GNUNET_assert (0 == memcmp (relays, &this_peer, sizeof (this_peer)));
// Test 4 starts here
origin_to_all ();
break;

default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid test #%d in member_recv_join_decision()\n", test);
GNUNET_assert (0);
}
}

/**
* Test: origin receives join request
*/
static void
origin_recv_join_request (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *mem_key,
const struct GNUNET_MessageHeader *join_msg,
struct GNUNET_MULTICAST_JoinHandle *jh)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: origin_recv_join_request()\n", test);

GNUNET_assert (0 == memcmp (mem_key, &member_pub_key, sizeof (member_pub_key)));
GNUNET_assert (join_msg->size == join_req->size);
GNUNET_assert (join_msg->type == join_req->type);
GNUNET_assert (0 == memcmp (join_msg, join_req, ntohs (join_req->size)));

char data[] = "here's the decision";
uint8_t data_size = strlen (data) + 1;
join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
join_resp->size = htons (sizeof (join_resp) + data_size);
join_resp->type = htons (456);
GNUNET_memcpy (&join_resp[1], data, data_size);

switch (test)
{
case TEST_MEMBER_JOIN_REFUSE:
// Test 3 starts here
GNUNET_MULTICAST_join_decision (jh, GNUNET_NO, 0, NULL, join_resp);
break;

case TEST_MEMBER_JOIN_ADMIT:
// Test 3 is running
GNUNET_MULTICAST_join_decision (jh, GNUNET_YES, 1, &this_peer, join_resp);
break;

default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Invalid test #%d in origin_recv_join_request()\n", test);
GNUNET_assert (0);
break;
}
}

/**
* Test: member joins multicast group
*/
static void
member_join (int t)
{
test = t;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: member_join()\n", test);

member_key = GNUNET_CRYPTO_ecdsa_key_create ();
GNUNET_CRYPTO_ecdsa_key_get_public (member_key, &member_pub_key);

if (NULL != join_req)
GNUNET_free (join_req);

char data[] = "let me in!";
uint8_t data_size = strlen (data) + 1;
join_req = GNUNET_malloc (sizeof (join_req) + data_size);
join_req->size = htons (sizeof (join_req) + data_size);
join_req->type = htons (123);
GNUNET_memcpy (&join_req[1], data, data_size);

member = GNUNET_MULTICAST_member_join (cfg, &group_pub_key, member_key,
&this_peer, 1, &this_peer, join_req,
member_recv_join_request,
member_recv_join_decision,
member_recv_replay_frag,
member_recv_replay_msg,
member_recv_message,
&member_cls);
}

/**
* Test: Start a multicast group as origin
*/
static void
origin_start ()
{
test = TEST_ORIGIN_START;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Test #%u: origin_start()\n", test);

group_key = GNUNET_CRYPTO_eddsa_key_create ();
GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);

origin = GNUNET_MULTICAST_origin_start (cfg, group_key, 0,
origin_recv_join_request,
origin_recv_replay_frag,
origin_recv_replay_msg,
origin_recv_request,
origin_recv_message,
&origin_cls);
// Test 2 starts here
member_join (TEST_MEMBER_JOIN_REFUSE);
}


/**
* Main function of the test, run from scheduler.
*
* @param cls NULL
* @param cfg configuration we use (also to connect to Multicast service)
* @param peer handle to access more of the peer (not used)
*/
static void
#if DEBUG_TEST_MULTICAST
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);
GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);

// Test 1 starts here
origin_start ();
}


int
main (int argc, char *argv[])
{
res = 1;
#if DEBUG_TEST_MULTICAST
const struct GNUNET_GETOPT_CommandLineOption opts[] = {
GNUNET_GETOPT_OPTION_END
};
if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-multicast",
"test-multicast [options]",
opts, &run, NULL))
return 1;
#else
if (0 != GNUNET_TESTING_peer_run ("test-multicast", "test_multicast.conf", &run, NULL))
return 1;
#endif
return res;
}

/* end of test_multicast.c */

+ 56
- 0
src/multicast/test_multicast.conf View File

@@ -0,0 +1,56 @@
[testbed]
HOSTNAME = localhost

[arm]
GLOBAL_POSTFIX=-L ERROR

[multicast]
#PREFIX = tmux new-window gdb -x ./cmd.gdb --args
#PREFIX = valgrind --leak-check=full
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock

[vpn]
START_ON_DEMAND = NO

[peerinfo]
# Do not use shipped gnunet HELLOs
USE_INCLUDED_HELLOS = NO

# Option to disable all disk IO; only useful for testbed runs
# (large-scale experiments); disables persistence of HELLOs!
NO_IO = YES

[hostlist]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[nat]
ENABLE_UPNP = NO

[fs]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[vpn]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[revocation]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[gns]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[namestore]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[namecache]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[topology]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

+ 520
- 0
src/multicast/test_multicast_2peers.c View File

@@ -0,0 +1,520 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @file multicast/test_multicast_2peers.c
* @brief Tests for the Multicast API with two peers doing the ping
* pong test.
* @author xrs
*/

#include <inttypes.h>

#include "platform.h"
#include "gnunet_crypto_lib.h"
#include "gnunet_common.h"
#include "gnunet_util_lib.h"
#include "gnunet_testbed_service.h"
#include "gnunet_multicast_service.h"

#define NUM_PEERS 2

static struct GNUNET_TESTBED_Operation *op0;
static struct GNUNET_TESTBED_Operation *op1;
static struct GNUNET_TESTBED_Operation *pi_op0;
static struct GNUNET_TESTBED_Operation *pi_op1;

static struct GNUNET_TESTBED_Peer **peers;
const struct GNUNET_PeerIdentity *peer_id[2];

static struct GNUNET_SCHEDULER_Task *timeout_tid;

static struct GNUNET_MULTICAST_Origin *origin;
static struct GNUNET_MULTICAST_Member *member;

struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;

struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key;
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;

/**
* Global result for testcase.
*/
static int result;


/**
* Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
* Cleans up.
*/
static void
shutdown_task (void *cls)
{
if (NULL != op0)
{
GNUNET_TESTBED_operation_done (op0);
op0 = NULL;
}
if (NULL != op1)
{
GNUNET_TESTBED_operation_done (op1);
op1 = NULL;
}
if (NULL != pi_op0)
{
GNUNET_TESTBED_operation_done (pi_op0);
pi_op0 = NULL;
}
if (NULL != pi_op1)
{
GNUNET_TESTBED_operation_done (pi_op1);
pi_op1 = NULL;
}
if (NULL != timeout_tid)
{
GNUNET_SCHEDULER_cancel (timeout_tid);
timeout_tid = NULL;
}
}


static void
timeout_task (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Timeout!\n");
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}


static void
member_join_request (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
const struct GNUNET_MessageHeader *join_msg,
struct GNUNET_MULTICAST_JoinHandle *jh)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Member sent a join request.\n");

}


static int
notify (void *cls,
size_t *data_size,
void *data)
{

char text[] = "ping";
*data_size = strlen(text)+1;
GNUNET_memcpy(data, text, *data_size);

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Member sents message to origin: %s\n", text);

return GNUNET_YES;
}


static void
member_join_decision (void *cls,
int is_admitted,
const struct GNUNET_PeerIdentity *peer,
uint16_t relay_count,
const struct GNUNET_PeerIdentity *relays,
const struct GNUNET_MessageHeader *join_msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Member received a decision from origin: %s\n",
(GNUNET_YES == is_admitted)
? "accepted"
: "rejected");

if (GNUNET_YES == is_admitted)
{
struct GNUNET_MULTICAST_MemberTransmitHandle *req;

// FIXME: move to MQ-style API!
req = GNUNET_MULTICAST_member_to_origin (member,
0,
&notify,
NULL);
}
}


static void
member_message (void *cls,
const struct GNUNET_MULTICAST_MessageHeader *msg)
{
if (0 != strncmp ("pong", (char *)&msg[1], 4))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "member did not receive pong\n");
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"member receives: %s\n", (char *)&msg[1]);

// Testcase ends here.
result = GNUNET_YES;
GNUNET_SCHEDULER_shutdown ();
}


static void
origin_join_request (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
const struct GNUNET_MessageHeader *join_msg,
struct GNUNET_MULTICAST_JoinHandle *jh)
{
struct GNUNET_MessageHeader *join_resp;

uint8_t data_size = ntohs (join_msg->size);

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"origin got a join request...\n");
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"origin receives: '%s'\n", (char *)&join_msg[1]);

const char data[] = "Come in!";
data_size = strlen (data) + 1;
join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
join_resp->size = htons (sizeof (join_resp) + data_size);
join_resp->type = htons (123);
GNUNET_memcpy (&join_resp[1], data, data_size);

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"origin sends: '%s'\n", data);

GNUNET_MULTICAST_join_decision (jh,
GNUNET_YES,
0,
NULL,
join_resp);
GNUNET_free (join_resp);
result = GNUNET_OK;
}


int
origin_notify (void *cls,
size_t *data_size,
void *data)
{
char text[] = "pong";

*data_size = strlen(text)+1;
GNUNET_memcpy (data,
text,
*data_size);

GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends (to all): %s\n", text);

return GNUNET_YES;
}


static void
origin_request (void *cls,
const struct GNUNET_MULTICAST_RequestHeader *req)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives: %s\n", (char *)&req[1]);

if (0 != strncmp ("ping", (char *)&req[1], 4))
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request");

GNUNET_MULTICAST_origin_to_all (origin,
0,
0,
origin_notify,
NULL);
}


static void
origin_message (void *cls,
const struct GNUNET_MULTICAST_MessageHeader *msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
}


static void
service_connect1 (void *cls,
struct GNUNET_TESTBED_Operation *op,
void *ca_result,
const char *emsg)
{
member = ca_result;

if (NULL == member)
{
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}
else
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to multicast service of member\n");
}
}


static void
multicast_da1 (void *cls,
void * op_result)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Member parting from multicast group\n");

GNUNET_MULTICAST_member_part (member, NULL, NULL);
}


static void *
multicast_ca1 (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct GNUNET_MessageHeader *join_msg;
void *ret;

// Get members keys
member_key = GNUNET_CRYPTO_ecdsa_key_create ();
GNUNET_CRYPTO_ecdsa_key_get_public (member_key, &member_pub_key);

char data[] = "Hi, can I enter?";
uint8_t data_size = strlen (data) + 1;
join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
join_msg->size = htons (sizeof (join_msg) + data_size);
join_msg->type = htons (123);
GNUNET_memcpy (&join_msg[1], data, data_size);

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Members tries to join multicast group\n");

ret = GNUNET_MULTICAST_member_join (cfg,
&group_pub_key,
member_key,
peer_id[0],
0,
NULL,
join_msg, /* join message */
member_join_request,
member_join_decision,
NULL, /* no test for member_replay_frag */
NULL, /* no test for member_replay_msg */
member_message,
NULL);
GNUNET_free (join_msg);
return ret;
}


static void
peer_information_cb (void *cls,
struct GNUNET_TESTBED_Operation *op,
const struct GNUNET_TESTBED_PeerInformation *pinfo,
const char *emsg)
{
int i = (int) (long) cls;

if (NULL == pinfo)
{
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}

peer_id[i] = pinfo->result.id;

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Got peer information of %s (%s)\n", (0==i)?"origin":"member" ,GNUNET_i2s(pinfo->result.id));

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Create member peer\n");

if (0 == i)
{
/* connect to multicast service of member */
op1 = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */
peers[1], /* The peer whose service to connect to */
"multicast", /* The name of the service */
service_connect1, /* callback to call after a handle to service
is opened */
NULL, /* closure for the above callback */
multicast_ca1, /* callback to call with peer's configuration;
this should open the needed service connection */
multicast_da1, /* callback to be called when closing the
opened service connection */
NULL); /* closure for the above two callbacks */
}
}


/**
* Test logic of peer "0" being origin starts here.
*
* @param cls closure, for the example: NULL
* @param op should be equal to "dht_op"
* @param ca_result result of the connect operation, the
* connection to the DHT service
* @param emsg error message, if testbed somehow failed to
* connect to the DHT.
*/
static void
service_connect0 (void *cls,
struct GNUNET_TESTBED_Operation *op,
void *ca_result,
const char *emsg)
{
origin = ca_result;

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Connected to multicast service of origin\n");

// Get GNUnet identity of origin
pi_op0 = GNUNET_TESTBED_peer_get_information (peers[0],
GNUNET_TESTBED_PIT_IDENTITY,
peer_information_cb,
(void *) 0);
// Get GNUnet identity of member
pi_op1 = GNUNET_TESTBED_peer_get_information (peers[1],
GNUNET_TESTBED_PIT_IDENTITY,
peer_information_cb,
(void *) 1);

/* Connection to service successful. Here we'd usually do something with
* the service. */
result = GNUNET_OK;
//GNUNET_SCHEDULER_shutdown (); /* Also kills the testbed */
}



/**
* Function run when service multicast has started and is providing us
* with a configuration file.
*/
static void *
multicast_ca0 (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
group_key = GNUNET_CRYPTO_eddsa_key_create ();
GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);

return GNUNET_MULTICAST_origin_start (cfg,
group_key,
0,
origin_join_request,
NULL, /* no test for origin_replay_frag */
NULL, /* no test for origin_replay_msg */
origin_request,
origin_message,
NULL);
}

static void
multicast_da0 (void *cls,
void *op_result)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Origin closes multicast group\n");

GNUNET_MULTICAST_origin_stop (origin, NULL, NULL);
}


/**
* Main function inovked from TESTBED once all of the
* peers are up and running. This one then connects
* just to the multicast service of peer 0 and 1.
* Peer 0 is going to be origin.
* Peer 1 is going to be one member.
* Origin will start a multicast group and the member will try to join it.
* After that we execute some multicast test.
*
* @param cls closure
* @param h the run handle
* @param peers started peers for the test
* @param num_peers size of the 'peers' array
* @param links_succeeded number of links between peers that were created
* @param links_failed number of links testbed was unable to establish
*/
static void
testbed_master (void *cls,
struct GNUNET_TESTBED_RunHandle *h,
unsigned int num_peers,
struct GNUNET_TESTBED_Peer **p,
unsigned int links_succeeded,
unsigned int links_failed)
{
/* Testbed is ready with peers running and connected in a pre-defined overlay
topology (FIXME) */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Connected to testbed_master()\n");

peers = p;

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Create origin peer\n");
op0 = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */
peers[0], /* The peer whose service to connect to */
"multicast", /* The name of the service */
service_connect0, /* callback to call after a handle to service
is opened */
NULL, /* closure for the above callback */
multicast_ca0, /* callback to call with peer's configuration;
this should open the needed service connection */
multicast_da0, /* callback to be called when closing the
opened service connection */
NULL); /* closure for the above two callbacks */

GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */

/* Schedule the shutdown task with a delay of a few Seconds */
timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 50),
&timeout_task, NULL);
}


int
main (int argc, char *argv[])
{
int ret;

result = GNUNET_SYSERR;
ret = GNUNET_TESTBED_test_run
("test-multicast-2peers", /* test case name */
"test_multicast.conf", /* template configuration */
NUM_PEERS, /* number of peers to start */
0LL, /* Event mask - set to 0 for no event notifications */
NULL, /* Controller event callback */
NULL, /* Closure for controller event callback */
testbed_master, /* continuation callback to be called when testbed setup is complete */
NULL); /* Closure for the test_master callback */
if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
return 1;
return 0;
}


/* end of test_multicast_2peers.c */

+ 63
- 0
src/multicast/test_multicast_line.conf View File

@@ -0,0 +1,63 @@
[testbed]
HOSTNAME = localhost
OVERLAY_TOPOLOGY = LINE

[arm]
GLOBAL_POSTFIX=-L ERROR

[multicast]
#PREFIX = tmux new-window gdb -x ./cmd.gdb --args
#PREFIX = valgrind --leak-check=full
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock

[vpn]
START_ON_DEMAND = NO

[peerinfo]
# Do not use shipped gnunet HELLOs
USE_INCLUDED_HELLOS = NO

# Option to disable all disk IO; only useful for testbed runs
# (large-scale experiments); disables persistence of HELLOs!
NO_IO = YES

[cadet]
ID_ANNOUNCE_TIME = 5 s

[hostlist]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[nat]
ENABLE_UPNP = NO

[fs]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[vpn]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[revocation]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[gns]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[namestore]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[namecache]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[topology]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[nse]
WORKBITS = 0

+ 643
- 0
src/multicast/test_multicast_multipeer.c View File

@@ -0,0 +1,643 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @file multicast/test_multicast_multipeers.c
* @brief Tests for the Multicast API with multiple peers.
* @author xrs
*/

#include <inttypes.h>

#include "platform.h"
#include "gnunet_crypto_lib.h"
#include "gnunet_common.h"
#include "gnunet_util_lib.h"
#include "gnunet_testbed_service.h"
#include "gnunet_multicast_service.h"

#define PEERS_REQUESTED 12

struct MulticastPeerContext
{
int peer; /* peer number */
struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
const struct GNUNET_PeerIdentity *id;
struct GNUNET_TESTBED_Operation *op; /* not yet in use */
struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */
int test_ok;
};

enum pingpong
{
PING = 1,
PONG = 2
};

struct pingpong_msg
{
int peer;
enum pingpong msg;
};

static void service_connect (void *cls,
struct GNUNET_TESTBED_Operation *op,
void *ca_result,
const char *emsg);

static struct MulticastPeerContext **multicast_peers;
static struct GNUNET_TESTBED_Peer **peers;

static struct GNUNET_TESTBED_Operation *op[PEERS_REQUESTED];
static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED];

static struct GNUNET_MULTICAST_Origin *origin;
static struct GNUNET_MULTICAST_Member *members[PEERS_REQUESTED]; /* first element always empty */

static struct GNUNET_SCHEDULER_Task *timeout_tid;

static struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
static struct GNUNET_HashCode group_pub_key_hash;

/**
* Global result for testcase.
*/
static int result;

/**
* Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
* Cleans up.
*/
static void
shutdown_task (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"shutdown_task!\n");
for (int i=0;i<PEERS_REQUESTED;i++)
{
if (NULL != op[i])
{
GNUNET_TESTBED_operation_done(op[i]);
op[i] = NULL;
}
if (NULL != pi_op[i])
{
GNUNET_TESTBED_operation_done (pi_op[i]);
pi_op[i] = NULL;
}
}

if (NULL != multicast_peers)
{
for (int i=0; i < PEERS_REQUESTED; i++)
{
GNUNET_free_non_null (multicast_peers[i]->key);
GNUNET_free (multicast_peers[i]);
multicast_peers[i] = NULL;
}
GNUNET_free (multicast_peers);
multicast_peers = NULL;
}

if (NULL != timeout_tid)
{
GNUNET_SCHEDULER_cancel (timeout_tid);
timeout_tid = NULL;
}
}


static void
timeout_task (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Timeout!\n");
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}


static void
member_join_request (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
const struct GNUNET_MessageHeader *join_msg,
struct GNUNET_MULTICAST_JoinHandle *jh)
{
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Peer #%u (%s) sent a join request.\n",
mc_peer->peer,
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
}


static int
notify (void *cls,
size_t *data_size,
void *data)
{
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;

struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
pp_msg->peer = mc_peer->peer;
pp_msg->msg = PING;

*data_size = sizeof (struct pingpong_msg);
GNUNET_memcpy(data, pp_msg, *data_size);
GNUNET_free (pp_msg);

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Peer #%u sents ping to origin\n", mc_peer->peer);

return GNUNET_YES;
}


static void
member_join_decision (void *cls,
int is_admitted,
const struct GNUNET_PeerIdentity *peer,
uint16_t relay_count,
const struct GNUNET_PeerIdentity *relays,
const struct GNUNET_MessageHeader *join_msg)
{
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Peer #%u (%s) received a decision from origin: %s\n",
mc_peer->peer,
GNUNET_i2s (multicast_peers[mc_peer->peer]->id),
(GNUNET_YES == is_admitted)?"accepted":"rejected");

if (GNUNET_YES == is_admitted)
{
GNUNET_MULTICAST_member_to_origin (members[mc_peer->peer],
0,
notify,
cls);

}
}


static void
member_replay_frag ()
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"member replay frag...\n");
}


static void
member_replay_msg ()
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"member replay msg...\n");
}


static void
origin_disconnected_cb (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Origin disconnected. Shutting down.\n");
result = GNUNET_YES;
GNUNET_SCHEDULER_shutdown ();
}


static void
member_disconnected_cb (void *cls)
{
for (int i = 1; i < PEERS_REQUESTED; ++i)
if (GNUNET_NO == multicast_peers[i]->test_ok)
return;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"All member disconnected. Stopping origin.\n");
GNUNET_MULTICAST_origin_stop (origin, origin_disconnected_cb, cls);
}


static void
member_message (void *cls,
const struct GNUNET_MULTICAST_MessageHeader *msg)
{
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]);

if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"peer #%i (%s) receives a pong\n",
mc_peer->peer,
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
mc_peer->test_ok = GNUNET_OK;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"peer #%u (%s) parting from multicast group\n",
mc_peer->peer,
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));

GNUNET_MULTICAST_member_part (members[mc_peer->peer], member_disconnected_cb, cls);
}
}


static void
origin_join_request (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
const struct GNUNET_MessageHeader *join_msg,
struct GNUNET_MULTICAST_JoinHandle *jh)
{
struct GNUNET_MessageHeader *join_resp;

uint8_t data_size = ntohs (join_msg->size);

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"origin got a join request...\n");
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"origin receives: '%s'\n", (char *)&join_msg[1]);

char data[] = "Come in!";
data_size = strlen (data) + 1;
join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
join_resp->size = htons (sizeof (join_resp) + data_size);
join_resp->type = htons (123);
GNUNET_memcpy (&join_resp[1], data, data_size);

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"origin sends: '%s'\n", data);

GNUNET_MULTICAST_join_decision (jh,
GNUNET_YES,
0,
NULL,
join_resp);

result = GNUNET_OK;
}


static void
origin_replay_frag (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
uint64_t fragment_id,
uint64_t flags,
struct GNUNET_MULTICAST_ReplayHandle *rh)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay fraq msg\n");
}


static void
origin_replay_msg (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
uint64_t message_id,
uint64_t fragment_offset,
uint64_t flags,
struct GNUNET_MULTICAST_ReplayHandle *rh)
{

GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay msg\n");
}


static int
origin_notify (void *cls,
size_t *data_size,
void *data)
{
struct pingpong_msg *rcv_pp_msg = (struct pingpong_msg*)cls;
struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);

pp_msg->peer = rcv_pp_msg->peer;
pp_msg->msg = PONG;
*data_size = sizeof (struct pingpong_msg);
GNUNET_memcpy(data, pp_msg, *data_size);
GNUNET_free (pp_msg);

GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends pong\n");

return GNUNET_YES;
}


static void
origin_request (void *cls,
const struct GNUNET_MULTICAST_RequestHeader *req)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives a msg\n");

req++;
struct pingpong_msg *pp_msg = (struct pingpong_msg *) req;

if (1 != pp_msg->msg) {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request");
}

GNUNET_MULTICAST_origin_to_all (origin,
0,
0,
origin_notify,
pp_msg);
}


static void
origin_message (void *cls,
const struct GNUNET_MULTICAST_MessageHeader *msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
}


static void
multicast_disconnect (void *cls,
void *op_result)
{

}


static void *
multicast_connect (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct MulticastPeerContext *multicast_peer = cls;
struct GNUNET_MessageHeader *join_msg;
char data[64];

if (0 == multicast_peer->peer)
{
group_key = GNUNET_CRYPTO_eddsa_key_create ();
GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);

GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash);
origin = GNUNET_MULTICAST_origin_start (cfg,
group_key,
0,
origin_join_request,
origin_replay_frag,
origin_replay_msg,
origin_request,
origin_message,
cls);
if (NULL == origin)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Peer #%u could not create a multicast group",
multicast_peer->peer);
return NULL;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Peer #%u connected as origin to group %s\n",
multicast_peer->peer,
GNUNET_h2s (&group_pub_key_hash));
return origin;
}
else
{
multicast_peer->key = GNUNET_CRYPTO_ecdsa_key_create ();

sprintf(data, "Hi, I am peer #%u (%s). Can I enter?",
multicast_peer->peer,
GNUNET_i2s (multicast_peers[multicast_peer->peer]->id));
uint8_t data_size = strlen (data) + 1;
join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
join_msg->size = htons (sizeof (join_msg) + data_size);
join_msg->type = htons (123);
GNUNET_memcpy (&join_msg[1], data, data_size);

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Peer #%u (%s) tries to join multicast group %s\n",
multicast_peer->peer,
GNUNET_i2s (multicast_peers[multicast_peer->peer]->id),
GNUNET_h2s (&group_pub_key_hash));

members[multicast_peer->peer] =
GNUNET_MULTICAST_member_join (cfg,
&group_pub_key,
multicast_peer->key,
multicast_peers[0]->id,
0,
NULL,
join_msg, /* join message */
member_join_request,
member_join_decision,
member_replay_frag,
member_replay_msg,
member_message,
cls);
return members[multicast_peer->peer];
}
}


static void
peer_information_cb (void *cls,
struct GNUNET_TESTBED_Operation *operation,
const struct GNUNET_TESTBED_PeerInformation *pinfo,
const char *emsg)
{
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;

if (NULL == pinfo) {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n");
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}

multicast_peers[mc_peer->peer]->id = pinfo->result.id;

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Got peer information of %s (%s)\n",
(0 == mc_peer->peer)? "origin" : "member",
GNUNET_i2s (pinfo->result.id));

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Create peer #%u (%s)\n",
mc_peer->peer,
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));

if (0 != mc_peer->peer)
{
/* connect to multicast service of members */
op[mc_peer->peer] =
GNUNET_TESTBED_service_connect (/* Closure for operation */
NULL,
/* The peer whose service to connect to */
peers[mc_peer->peer],
/* The name of the service */
"multicast",
/* called after a handle to service is opened */
service_connect,
/* closure for the above callback */
cls,
/* called when opening the service connection */
multicast_connect,
/* called when closing the service connection */
multicast_disconnect,
/* closure for the above two callbacks */
cls);
}
}


static void
service_connect (void *cls,
struct GNUNET_TESTBED_Operation *op,
void *ca_result,
const char *emsg)
{
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;

if (NULL == ca_result)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Connection adapter not created for peer #%u (%s)\n",
mc_peer->peer,
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));

result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown();
}

if (0 == mc_peer->peer)
{
// Get GNUnet identity of members
for (int i = 0; i<PEERS_REQUESTED; i++)
{
pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i],
GNUNET_TESTBED_PIT_IDENTITY,
peer_information_cb,
multicast_peers[i]);
}
}
}



/**
* Main function inovked from TESTBED once all of the
* peers are up and running. This one then connects
* just to the multicast service of peer 0 and 1.
* Peer 0 is going to be origin.
* Peer 1 is going to be one member.
* Origin will start a multicast group and the member will try to join it.
* After that we execute some multicast test.
*
* @param cls closure
* @param h the run handle
* @param peers started peers for the test
* @param PEERS_REQUESTED size of the 'peers' array
* @param links_succeeded number of links between peers that were created
* @param links_failed number of links testbed was unable to establish
*/
static void
testbed_master (void *cls,
struct GNUNET_TESTBED_RunHandle *h,
unsigned int num_peers,
struct GNUNET_TESTBED_Peer **p,
unsigned int links_succeeded,
unsigned int links_failed)
{
/* Testbed is ready with peers running and connected in a pre-defined overlay
topology (FIXME) */
peers = p;
multicast_peers = GNUNET_new_array (PEERS_REQUESTED, struct MulticastPeerContext*);

// Create test contexts for members
for (int i = 0; i<PEERS_REQUESTED; i++)
{
multicast_peers[i] = GNUNET_new (struct MulticastPeerContext);
multicast_peers[i]->peer = i;
multicast_peers[i]->test_ok = GNUNET_NO;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Create origin peer\n");
op[0] =
GNUNET_TESTBED_service_connect (/* Closure for operation */
NULL,
/* The peer whose service to connect to */
peers[0],
/* The name of the service */
"multicast",
/* called after a handle to service is opened */
service_connect,
/* closure for the above callback */
multicast_peers[0],
/* called when opening the service connection */
multicast_connect,
/* called when closing the service connection */
multicast_disconnect,
/* closure for the above two callbacks */
multicast_peers[0]);
/* Schedule a new task on shutdown */
GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
/* Schedule the shutdown task with a delay of a few Seconds */
timeout_tid =
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 400),
&timeout_task,
NULL);
}


int
main (int argc, char *argv[])
{
int ret;
char const *config_file;

if (strstr (argv[0], "_line") != NULL)
{
config_file = "test_multicast_line.conf";
}
else if (strstr(argv[0], "_star") != NULL)
{
config_file = "test_multicast_star.conf";
}
else
{
config_file = "test_multicast_star.conf";
}

result = GNUNET_SYSERR;
ret =
GNUNET_TESTBED_test_run ("test-multicast-multipeer",
config_file,
/* number of peers to start */
PEERS_REQUESTED,
/* Event mask - set to 0 for no event notifications */
0LL,
/* Controller event callback */
NULL,
/* Closure for controller event callback */
NULL,
/* called when testbed setup is complete */
testbed_master,
/* Closure for the test_master callback */
NULL);
if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
return 1;
return 0;
}

/* end of test_multicast_multipeer.c */

+ 64
- 0
src/multicast/test_multicast_star.conf View File

@@ -0,0 +1,64 @@
[testbed]
HOSTNAME = localhost
OVERLAY_TOPOLOGY = STAR

[arm]
GLOBAL_POSTFIX=-L ERROR

[multicast]
#PREFIX = tmux new-window gdb -x ./cmd.gdb --args
#PREFIX = valgrind --leak-check=full
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock

[vpn]
START_ON_DEMAND = NO

[peerinfo]
# Do not use shipped gnunet HELLOs
USE_INCLUDED_HELLOS = NO

# Option to disable all disk IO; only useful for testbed runs
# (large-scale experiments); disables persistence of HELLOs!
NO_IO = YES

[cadet]
ID_ANNOUNCE_TIME = 5 s

[hostlist]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[nat]
ENABLE_UPNP = NO

[fs]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[vpn]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[revocation]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[gns]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[namestore]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[namecache]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[topology]
IMMEDIATE_START = NO
START_ON_DEMAND = NO

[nse]
WORKBITS = 0


+ 2
- 0
src/psyc/.gitignore View File

@@ -0,0 +1,2 @@
gnunet-service-psyc
test_psyc

+ 77
- 0
src/psyc/Makefile.am View File

@@ -0,0 +1,77 @@
# This Makefile.am is in the public domain
AM_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
libgnunetpsyc_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/psycutil/libgnunetpsycutil.la \
$(GN_LIBINTL) $(XLIB)
libgnunetpsyc_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
-version-info 0:0:0

bin_PROGRAMS =

libexec_PROGRAMS = \
gnunet-service-psyc

gnunet_service_psyc_SOURCES = \
gnunet-service-psyc.c
gnunet_service_psyc_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/multicast/libgnunetmulticast.la \
$(top_builddir)/src/psycstore/libgnunetpsycstore.la \
$(top_builddir)/src/psycutil/libgnunetpsycutil.la \
$(GN_LIBINTL)
gnunet_service_psyc_CFLAGS = $(AM_CFLAGS)


if HAVE_TESTING
check_PROGRAMS = \
test_psyc
# test_psyc2
endif

if ENABLE_TEST_RUN
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
TESTS = $(check_PROGRAMS)
endif

test_psyc_SOURCES = \
test_psyc.c
test_psyc_LDADD = \
libgnunetpsyc.la \
$(top_builddir)/src/psycutil/libgnunetpsycutil.la \
$(top_builddir)/src/testing/libgnunettesting.la \
$(top_builddir)/src/util/libgnunetutil.la
#test_psyc2_SOURCES = \
# test_psyc2.c
#test_psyc2_LDADD = \
# libgnunetpsyc.la \
# $(top_builddir)/src/psycutil/libgnunetpsycutil.la \
# $(top_builddir)/src/testbed/libgnunettestbed.la \
# $(top_builddir)/src/util/libgnunetutil.la

EXTRA_DIST = \
test_psyc.conf

+ 2860
- 0
src/psyc/gnunet-service-psyc.c
File diff suppressed because it is too large
View File


+ 12
- 0
src/psyc/psyc.conf.in View File

@@ -0,0 +1,12 @@
[psyc]
START_ON_DEMAND = @START_ON_DEMAND@
BINARY = gnunet-service-psyc

UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-psyc.sock
UNIX_MATCH_UID = YES
UNIX_MATCH_GID = YES

@UNIXONLY@PORT = 2115
HOSTNAME = localhost
ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;

+ 178
- 0
src/psyc/psyc.h View File

@@ -0,0 +1,178 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @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"


int
GNUNET_PSYC_check_message_parts (uint16_t data_size, const char *data,
uint16_t *first_ptype, uint16_t *last_ptype);

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,
MSG_STATE_ERROR = 8,
};


enum MessageFragmentState
{
MSG_FRAG_STATE_START = 0,
MSG_FRAG_STATE_HEADER = 1,
MSG_FRAG_STATE_DATA = 2,
MSG_FRAG_STATE_END = 3,
MSG_FRAG_STATE_CANCEL = 4,
MSG_FRAG_STATE_DROP = 5,
};


GNUNET_NETWORK_STRUCT_BEGIN


/**** library -> service ****/


struct MasterStartRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYC_MASTER_START
*/
struct GNUNET_MessageHeader header;

uint32_t policy GNUNET_PACKED;

struct GNUNET_CRYPTO_EddsaPrivateKey channel_key;
};


struct SlaveJoinRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN
*/
struct GNUNET_MessageHeader header;

uint32_t relay_count GNUNET_PACKED;

struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;

struct GNUNET_CRYPTO_EcdsaPrivateKey slave_key;

struct GNUNET_PeerIdentity origin;

uint32_t flags GNUNET_PACKED;

/* Followed by struct GNUNET_PeerIdentity relays[relay_count] */

/* Followed by struct GNUNET_MessageHeader join_msg */
};


struct ChannelMembershipStoreRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_MEMBERSHIP_STORE
*/
struct GNUNET_MessageHeader header;

uint32_t reserved GNUNET_PACKED;

uint64_t op_id GNUNET_PACKED;

struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;

uint64_t announced_at GNUNET_PACKED;

uint64_t effective_since GNUNET_PACKED;

uint8_t did_join;
};


struct HistoryRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_HISTORY_REQUEST
*/
struct GNUNET_MessageHeader header;

uint32_t reserved GNUNET_PACKED;

/**
* ID for this operation.
*/
uint64_t op_id GNUNET_PACKED;

uint64_t start_message_id GNUNET_PACKED;

uint64_t end_message_id GNUNET_PACKED;

uint64_t message_limit GNUNET_PACKED;
};


struct StateRequest
{
/**
* Types:
* - GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STATE_GET
* - GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STATE_GET_PREFIX
*/
struct GNUNET_MessageHeader header;

uint32_t reserved GNUNET_PACKED;

/**
* ID for this operation.
*/
uint64_t op_id GNUNET_PACKED;

/* Followed by NUL-terminated name. */
};


/**** service -> library ****/


GNUNET_NETWORK_STRUCT_END

#endif

+ 1584
- 0
src/psyc/psyc_api.c
File diff suppressed because it is too large
View File


+ 67
- 0
src/psyc/psyc_test_lib.h View File

@@ -0,0 +1,67 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @file psyc/test_psyc_api_join.c
* @brief library for writing psyc tests
* @author xrs
*/

#define MAX_TESTBED_OPS 32

struct pctx
{
int idx;
struct GNUNET_TESTBED_Peer *testbed_peer;
const struct GNUNET_PeerIdentity *peer_id;

const struct GNUNET_PeerIdentity *peer_id_master;

/**
* Used to simulate egos (not peerid)
*/
const struct GNUNET_CRYPTO_EcdsaPrivateKey *id_key;

const struct GNUNET_CRYPTO_EcdsaPublicKey *id_pub_key;

/**
* Used to store either GNUNET_PSYC_Master or GNUNET_PSYC_Slave handle
*/
void *psyc;

struct GNUNET_PSYC_Channel *channel;

const struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;

struct GNUNET_CRYPTO_EddsaPublicKey *channel_pub_key;

int test_ok;
};

static struct GNUNET_SCHEDULER_Task *timeout_task_id;

static int result = GNUNET_SYSERR;

static struct GNUNET_TESTBED_Operation *op[MAX_TESTBED_OPS];

static int op_cnt = 0;


+ 1018
- 0
src/psyc/test_psyc.c
File diff suppressed because it is too large
View File


+ 284
- 0
src/psyc/test_psyc2.c View File

@@ -0,0 +1,284 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @file psyc/test_psyc2.c
* @brief Testbed test for the PSYC API.
* @author xrs
*/

#include "platform.h"
#include "gnunet_crypto_lib.h"
#include "gnunet_common.h"
#include "gnunet_util_lib.h"
#include "gnunet_testbed_service.h"
#include "gnunet_psyc_util_lib.h"
#include "gnunet_psyc_service.h"

#define PEERS_REQUESTED 2

static int result;

static struct GNUNET_SCHEDULER_Task *timeout_tid;
static struct pctx **pctx;

static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;

static struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key;
static struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;

/**
* Task To perform tests
*/
static struct GNUNET_SCHEDULER_Task *test_task;

/**
* Peer id couter
*/
static unsigned int pids;

struct pctx
{
int idx;
struct GNUNET_TESTBED_Peer *peer;
const struct GNUNET_PeerIdentity *id;

struct GNUNET_TESTBED_Operation *op;

/**
* psyc service handle
*/
void *psyc;
struct GNUNET_PSYC_Master *mst;
struct GNUNET_PSYC_Slave *slv;

/**
* result for test on peer
*/
int test_ok;
};

static void
shutdown_task (void *cls)
{
if (NULL != pctx)
{
if (NULL != pctx[0]->mst)
GNUNET_PSYC_master_stop (pctx[0]->mst, GNUNET_NO, NULL, NULL);

for (int i=0; i < PEERS_REQUESTED; i++)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Operation done.\n");
GNUNET_TESTBED_operation_done (pctx[i]->op);
GNUNET_free_non_null (pctx[i]);
}
GNUNET_free (pctx);
}

if (NULL != timeout_tid)
GNUNET_SCHEDULER_cancel (timeout_tid);
}

static void
timeout_task (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout!\n");
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}

static void
start_test (void *cls)
{
}

static void
pinfo_cb (void *cls,
struct GNUNET_TESTBED_Operation *operation,
const struct GNUNET_TESTBED_PeerInformation *pinfo,
const char *emsg)
{
struct pctx *pc = (struct pctx*) cls;

pc->id = pinfo->result.id;

pids++;
if (pids < (PEERS_REQUESTED - 1))
return;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL);
}

static void
mst_start_cb ()
{
}

static void
join_request_cb ()
{
}

static void
mst_message_cb ()
{
}

static void
mst_message_part_cb ()
{
}

static void
slv_message_cb ()
{
}

static void
slv_message_part_cb ()
{
}

static void
slv_connect_cb ()
{
}

static void
join_decision_cb ()
{
}

static void *
psyc_ca (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct GNUNET_PSYC_Message *join_msg = NULL;
struct pctx *pc = (struct pctx *) cls;

if (0 == pc->idx)
{
pc->mst = GNUNET_PSYC_master_start (cfg, channel_key,
GNUNET_PSYC_CHANNEL_PRIVATE,
&mst_start_cb, &join_request_cb,
&mst_message_cb, &mst_message_part_cb,
NULL);
return pc->mst;
}

pc->slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key,
GNUNET_PSYC_SLAVE_JOIN_NONE,
&pid, 0, NULL, &slv_message_cb,
&slv_message_part_cb,
&slv_connect_cb, &join_decision_cb,
NULL, join_msg);
return pc->slv;
}

static void
psyc_da (void *cls,
void *op_result)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disconnected from service.\n");
}

static void
service_connect (void *cls,
struct GNUNET_TESTBED_Operation *op,
void *ca_result,
const char *emsg)
{
struct pctx *pc = (struct pctx *) cls;

GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Connected to service\n");

GNUNET_assert (NULL != ca_result);

// FIXME: we need a simple service handle to connect to the service, then
// get peer information and AFTER that make PSYC ops. Compare to CADET.
pc->psyc = ca_result;

GNUNET_TESTBED_peer_get_information (pc->peer,
GNUNET_TESTBED_PIT_IDENTITY,
pinfo_cb, pc);
}

static void
testbed_master (void *cls,
struct GNUNET_TESTBED_RunHandle *h,
unsigned int num_peers,
struct GNUNET_TESTBED_Peer **p,
unsigned int links_succeeded,
unsigned int links_failed)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to testbed_master()\n");

// Create ctx for peers
pctx = GNUNET_new_array (PEERS_REQUESTED, struct pctx*);
for (int i = 0; i<PEERS_REQUESTED; i++)
{
pctx[i] = GNUNET_new (struct pctx);
pctx[i]->idx = i;
pctx[i]->peer = p[i];
pctx[i]->id = NULL;
pctx[i]->mst = NULL;
pctx[i]->op = NULL;
pctx[i]->test_ok = GNUNET_NO;
}

channel_key = GNUNET_CRYPTO_eddsa_key_create ();
slave_key = GNUNET_CRYPTO_ecdsa_key_create ();

GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);

pctx[0]->op =
GNUNET_TESTBED_service_connect (NULL, p[0], "psyc", service_connect,
pctx[0], psyc_ca, psyc_da, pctx[0]);

GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);

timeout_tid =
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5),
&timeout_task, NULL);
}

int
main (int argc, char *argv[])
{
int ret;

GNUNET_log (GNUNET_ERROR_TYPE_INFO, "test\n");

result = GNUNET_SYSERR;

ret = GNUNET_TESTBED_test_run ("test-psyc2", "test_psyc.conf",
PEERS_REQUESTED, 0LL, NULL, NULL,
testbed_master, NULL);

if ((GNUNET_OK != ret) || (GNUNET_OK != result))
return 1;

return 0;
}

/* end of test-psyc2.c */

+ 282
- 0
src/psyc/test_psyc_api_join.c View File

@@ -0,0 +1,282 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @file psyc/test_psyc_api_join.c
* @brief Testbed test for the PSYC API.
* @author xrs
*/

/**
* Lessons Learned:
* - define topology in config
* - psyc slave join needs part to end (same with master)
* - GNUNET_SCHEDULER_add_delayed return value will outdate at call time
* - main can not contain GNUNET_log()
*/

#include "platform.h"
#include "gnunet_crypto_lib.h"
#include "gnunet_common.h"
#include "gnunet_util_lib.h"
#include "gnunet_testbed_service.h"
#include "gnunet_psyc_util_lib.h"
#include "gnunet_psyc_service.h"
#include "psyc_test_lib.h"

static struct pctx PEERS[2];

static int pids;


static void
shutdown_task (void *cls)
{
if (NULL != timeout_task_id) {
GNUNET_SCHEDULER_cancel (timeout_task_id);
timeout_task_id = NULL;
}

for (int i=0;i<2;i++) {
GNUNET_free (PEERS[i].channel_pub_key);

if (NULL != PEERS[i].psyc)
{
if (0 == i)
GNUNET_PSYC_master_stop (PEERS[i].psyc, GNUNET_NO, NULL, NULL);
else
GNUNET_PSYC_slave_part (PEERS[i].psyc, GNUNET_NO, NULL, NULL);
}
}

for (int i=0;i<MAX_TESTBED_OPS;i++)
if (NULL != op[i])
GNUNET_TESTBED_operation_done (op[i]);

GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shut down!\n");
}

static void
timeout_task (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Timeout!\n");

timeout_task_id = NULL;

result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}

static void
join_decision_cb (void *cls,
const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
int is_admitted,
const struct GNUNET_PSYC_Message *join_msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"slave: got join decision: %s\n",
(GNUNET_YES == is_admitted) ? "admitted":"rejected");

result = (GNUNET_YES == is_admitted) ? GNUNET_OK : GNUNET_SYSERR;

GNUNET_SCHEDULER_shutdown ();
}

static void
join_request_cb (void *cls,
const struct GNUNET_PSYC_JoinRequestMessage *req,
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
const struct GNUNET_PSYC_Message *join_msg,
struct GNUNET_PSYC_JoinHandle *jh)
{
struct GNUNET_HashCode slave_key_hash;

GNUNET_log (GNUNET_ERROR_TYPE_INFO, "master: got join request.\n");

GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);

GNUNET_PSYC_join_decision (jh, GNUNET_YES, 0, NULL, NULL);
}

static void
psyc_da ()
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "disconnect form PSYC service\n");
}

static void *
psyc_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct pctx *peer = (struct pctx*) cls;

// Case: master role
if (0 == peer->idx) {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to PSYC as master ...\n");

peer->psyc = (struct GNUNET_PSYC_Master *)
GNUNET_PSYC_master_start (cfg,
peer->channel_key,
GNUNET_PSYC_CHANNEL_PRIVATE,
NULL,
join_request_cb,
NULL,
NULL,
cls);
return peer->psyc;
}

GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to PSYC as slave ...\n");

struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo", "bar baz", 7);
GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo_bar", "foo bar baz", 11);

struct GNUNET_PSYC_Message *
join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 40);

peer->psyc = (struct GNUNET_PSYC_Slave *)
GNUNET_PSYC_slave_join (cfg,
peer->channel_pub_key,
peer->id_key,
GNUNET_PSYC_SLAVE_JOIN_NONE,
peer->peer_id_master,
0,
NULL,
NULL,
NULL,
NULL,
join_decision_cb,
cls,
join_msg);

GNUNET_free (join_msg);
peer->channel = GNUNET_PSYC_slave_get_channel (peer->psyc);
GNUNET_PSYC_env_destroy (env);

return peer->psyc;
}

static void
service_connect (void *cls,
struct GNUNET_TESTBED_Operation *op,
void *ca_result,
const char *emsg)
{
GNUNET_assert (NULL != ca_result);

GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to the service\n");
}

static void
connect_to_services (void *cls)
{
for (int i = 0; i < 2; i++)
{
PEERS[i].peer_id_master = PEERS[0].peer_id;

op[op_cnt++] =
GNUNET_TESTBED_service_connect (NULL, PEERS[i].testbed_peer, "psyc",
&service_connect, &PEERS[i], &psyc_ca,
&psyc_da, &PEERS[i]);
}
}

static void
pinfo_cb (void *cls,
struct GNUNET_TESTBED_Operation *operation,
const struct GNUNET_TESTBED_PeerInformation *pinfo,
const char *emsg)
{
struct pctx *peer = (struct pctx*) cls;

peer->peer_id = pinfo->result.id;

pids++;
if (pids < 2)
return;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting test\n");

GNUNET_SCHEDULER_add_now (&connect_to_services, NULL);
}

static void
testbed_master (void *cls,
struct GNUNET_TESTBED_RunHandle *h,
unsigned int num_peers,
struct GNUNET_TESTBED_Peer **p,
unsigned int links_succeeded,
unsigned int links_failed)
{
struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key = NULL;

GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to testbed_master\n");

// Set up shutdown logic
GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
timeout_task_id =
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 15),
&timeout_task, NULL);
GNUNET_assert (NULL != timeout_task_id);

// Set up channel key
channel_key = GNUNET_CRYPTO_eddsa_key_create ();
GNUNET_assert (NULL != channel_key);
// Set up information contexts for peers
for (int i=0 ; i < 2 ; i++)
{
PEERS[i].idx = i;
PEERS[i].testbed_peer = p[i];

// Create "egos"
PEERS[i].id_key = GNUNET_CRYPTO_ecdsa_key_create ();

// Set up channel keys shared by master and slave
PEERS[i].channel_key = channel_key;

PEERS[i].channel_pub_key =
GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
// Get public key
GNUNET_CRYPTO_eddsa_key_get_public (PEERS[i].channel_key,
PEERS[i].channel_pub_key);
// Get peerinfo
op[op_cnt++] =
GNUNET_TESTBED_peer_get_information (p[i],
GNUNET_TESTBED_PIT_IDENTITY,
pinfo_cb, &PEERS[i]);
}
}

int
main (int argc, char *argv[])
{
int ret;

ret = GNUNET_TESTBED_test_run ("test_psyc_api_join", "test_psyc.conf",
2, 0LL, NULL, NULL,
&testbed_master, NULL);

if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
return 1;

return 0;
}

/* end of test_psyc_api_join.c */

+ 5
- 0
src/psycstore/.gitignore View File

@@ -0,0 +1,5 @@
gnunet-service-psycstore
test_plugin_psycstore_mysql
test_plugin_psycstore_sqlite
test_plugin_psycstore_postgres
test_psycstore

+ 155
- 0
src/psycstore/Makefile.am View File

@@ -0,0 +1,155 @@
# This Makefile.am is in the public domain
AM_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_MYSQL
MYSQL_PLUGIN = libgnunet_plugin_psycstore_mysql.la
if HAVE_TESTING
MYSQL_TESTS = test_plugin_psycstore_mysql
endif
endif

if HAVE_POSTGRESQL
POSTGRES_PLUGIN = libgnunet_plugin_psycstore_postgres.la
if HAVE_TESTING
POSTGRES_TESTS = test_plugin_psycstore_postgres
endif
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

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 \
$(top_builddir)/src/psycutil/libgnunetpsycutil.la \
$(GN_LIBINTL)

plugin_LTLIBRARIES = \
$(SQLITE_PLUGIN) \
$(MYSQL_PLUGIN) \
$(POSTGRES_PLUGIN)


libgnunet_plugin_psycstore_mysql_la_SOURCES = \
plugin_psycstore_mysql.c
libgnunet_plugin_psycstore_mysql_la_LIBADD = \
libgnunetpsycstore.la \
$(top_builddir)/src/my/libgnunetmy.la \
$(top_builddir)/src/mysql/libgnunetmysql.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
$(LTLIBINTL)
libgnunet_plugin_psycstore_mysql_la_LDFLAGS = \
$(GN_PLUGIN_LDFLAGS)

libgnunet_plugin_psycstore_postgres_la_SOURCES = \
plugin_psycstore_postgres.c
libgnunet_plugin_psycstore_postgres_la_LIBADD = \
libgnunetpsycstore.la \
$(top_builddir)/src/pq/libgnunetpq.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \
$(LTLIBINTL)
libgnunet_plugin_psycstore_postgres_la_LDFLAGS = \
$(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS)
libgnunet_plugin_psycstore_postgres_la_CPPFLAGS = \
$(POSTGRESQL_CPPFLAGS) $(AM_CPPFLAGS)


libgnunet_plugin_psycstore_sqlite_la_SOURCES = \
plugin_psycstore_sqlite.c
libgnunet_plugin_psycstore_sqlite_la_LIBADD = \
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)


if HAVE_SQLITE
if HAVE_TESTING
check_PROGRAMS = \
$(SQLITE_TESTS) \
$(MYSQL_TESTS) \
$(POSTGRES_TESTS) \
test_psycstore
endif
endif

if ENABLE_TEST_RUN
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
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

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

test_plugin_psycstore_mysql_SOURCES = \
test_plugin_psycstore.c
test_plugin_psycstore_mysql_LDADD = \
$(top_builddir)/src/testing/libgnunettesting.la \
$(top_builddir)/src/util/libgnunetutil.la

test_plugin_psycstore_postgres_SOURCES = \
test_plugin_psycstore.c
test_plugin_psycstore_postgres_LDADD = \
$(top_builddir)/src/testing/libgnunettesting.la \
$(top_builddir)/src/util/libgnunetutil.la


+ 1049
- 0
src/psycstore/gnunet-service-psycstore.c
File diff suppressed because it is too large
View File


+ 1960
- 0
src/psycstore/plugin_psycstore_mysql.c
File diff suppressed because it is too large
View File


+ 1530
- 0
src/psycstore/plugin_psycstore_postgres.c
File diff suppressed because it is too large
View File


+ 1948
- 0
src/psycstore/plugin_psycstore_sqlite.c
File diff suppressed because it is too large
View File


+ 28
- 0
src/psycstore/psycstore.conf.in View File

@@ -0,0 +1,28 @@
[psycstore]
START_ON_DEMAND = @START_ON_DEMAND@
BINARY = gnunet-service-psycstore

UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-psycstore.sock
UNIX_MATCH_UID = YES
UNIX_MATCH_GID = YES

@UNIXONLY@PORT = 2111
HOSTNAME = localhost
ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;

DATABASE = sqlite

[psycstore-sqlite]
FILENAME = $GNUNET_DATA_HOME/psycstore/sqlite.db

[psycstore-mysql]
DATABASE = gnunet
CONFIG = ~/.my.cnf
# USER = gnunet
# PASSWORD =
# HOST = localhost
# PORT = 3306

[psycstore-postgres]
CONFIG = connect_timeout=10; dbname=gnunet

+ 520
- 0
src/psycstore/psycstore.h View File

@@ -0,0 +1,520 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @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;

uint32_t reserved GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_t op_id GNUNET_PACKED;

/**lowed by
* Status code for the operation.
*/
uint64_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;

/**
* 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.
*/
uint32_t result_code GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_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;
};


/**
* Answer from service to client containing a message fragment.
*/
struct FragmentResult
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE
*/
struct GNUNET_MessageHeader header;

uint32_t psycstore_flags GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_t op_id 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;

uint16_t name_size GNUNET_PACKED;

uint16_t reserved GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_t op_id GNUNET_PACKED;

/* Followed by name and value */
};


/**
* Generic operation request.
*/
struct OperationRequest
{
struct GNUNET_MessageHeader header;

uint32_t reserved GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_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;

uint32_t reserved GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_t op_id GNUNET_PACKED;

/**
* Channel's public key.
*/
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;

/**
* Slave's public key.
*/
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;

uint64_t announced_at GNUNET_PACKED;
uint64_t effective_since GNUNET_PACKED;
uint64_t group_generation GNUNET_PACKED;
uint8_t did_join;
};


/**
* @see GNUNET_PSYCSTORE_membership_test()
*/
struct MembershipTestRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST
*/
struct GNUNET_MessageHeader header;

uint32_t reserved GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_t op_id GNUNET_PACKED;

/**
* Channel's public key.
*/
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;

/**
* Slave's public key.
*/
struct GNUNET_CRYPTO_EcdsaPublicKey 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;

/**
* enum GNUNET_PSYCSTORE_MessageFlags
*/
uint32_t psycstore_flags GNUNET_PACKED;

/**
* Channel's public key.
*/
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;

/**
* Operation ID.
*/
uint64_t op_id;

/* Followed by fragment */
};


/**
* @see GNUNET_PSYCSTORE_fragment_get()
*/
struct FragmentGetRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET
*/
struct GNUNET_MessageHeader header;

uint32_t reserved GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_t op_id GNUNET_PACKED;

/**
* Channel's public key.
*/
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;

/**
* Slave's public key.
*/
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;

/**
* First fragment ID to request.
*/
uint64_t first_fragment_id GNUNET_PACKED;

/**
* Last fragment ID to request.
*/
uint64_t last_fragment_id GNUNET_PACKED;

/**
* Maximum number of fragments to retrieve.
*/
uint64_t fragment_limit GNUNET_PACKED;

/**
* Do membership test with @a slave_key before returning fragment?
* #GNUNET_YES or #GNUNET_NO
*/
uint8_t do_membership_test;
};


/**
* @see GNUNET_PSYCSTORE_message_get()
*/
struct MessageGetRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET
*/
struct GNUNET_MessageHeader header;

uint32_t reserved GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_t op_id GNUNET_PACKED;

/**
* Channel's public key.
*/
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;

/**
* Slave's public key.
*/
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;

/**
* First message ID to request.
*/
uint64_t first_message_id GNUNET_PACKED;

/**
* Last message ID to request.
*/
uint64_t last_message_id GNUNET_PACKED;

/**
* Maximum number of messages to retrieve.
*/
uint64_t message_limit GNUNET_PACKED;

/**
* Maximum number of fragments to retrieve.
*/
uint64_t fragment_limit GNUNET_PACKED;

/**
* Do membership test with @a slave_key before returning fragment?
* #GNUNET_YES or #GNUNET_NO
*/
uint8_t do_membership_test;

/* Followed by method_prefix */
};


/**
* @see GNUNET_PSYCSTORE_message_get_fragment()
*/
struct MessageGetFragmentRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_FRAGMENT_GET
*/
struct GNUNET_MessageHeader header;

uint32_t reserved GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_t op_id GNUNET_PACKED;

/**
* Channel's public key.
*/
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;

/**
* Slave's public key.
*/
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;

/**
* Requested message ID.
*/
uint64_t message_id GNUNET_PACKED;

/**
* Requested fragment offset.
*/
uint64_t fragment_offset GNUNET_PACKED;

/**
* Do membership test with @a slave_key before returning fragment?
* #GNUNET_YES or #GNUNET_NO
*/
uint8_t do_membership_test;
};


/**
* @see GNUNET_PSYCSTORE_state_hash_update()
*/
struct StateHashUpdateRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_HASH_UPDATE
*/
struct GNUNET_MessageHeader header;

uint32_t reserved GNUNET_PACKED;

/**
* Operation ID.
*/
uint64_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.
*/
uint64_t op_id GNUNET_PACKED;

/**
* ID of the message to apply the state changes in.
*/
uint64_t message_id GNUNET_PACKED;

/**
* State delta of the message with ID @a message_id.
*/
uint64_t state_delta GNUNET_PACKED;

/**
* Channel's public key.
*/
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
};


/**
* @see GNUNET_PSYCSTORE_state_sync()
*/
struct StateSyncRequest
{
/**
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC
*/
struct GNUNET_MessageHeader header;

/**
* Size of name, including NUL terminator.
*/
uint16_t name_size GNUNET_PACKED;

/**
* OR'd StateOpFlags
*/
uint8_t flags;

uint8_t reserved;

/**
* Operation ID.
*/
uint64_t op_id GNUNET_PACKED;

/**
* ID of the message that contains the state_hash PSYC header variable.
*/
uint64_t state_hash_message_id GNUNET_PACKED;

/**
* ID of the last stateful message before @a state_hash_message_id.
*/
uint64_t max_state_message_id GNUNET_PACKED;

/**
* Channel's public key.
*/
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;

/* Followed by NUL-terminated name, then the value. */
};


GNUNET_NETWORK_STRUCT_END

#endif

+ 1285
- 0
src/psycstore/psycstore_api.c
File diff suppressed because it is too large
View File


+ 532
- 0
src/psycstore/test_plugin_psycstore.c View File

@@ -0,0 +1,532 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
* @author Christian Grothoff
*
* @file
* Test for the PSYCstore plugins.
*/

#include <inttypes.h>

#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_EcdsaPrivateKey *slave_key;

static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
static struct GNUNET_CRYPTO_EcdsaPublicKey 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;
}


#define MAX_MSG 16

struct FragmentClosure
{
uint8_t n;
uint64_t flags[MAX_MSG];
struct GNUNET_MULTICAST_MessageHeader *msg[MAX_MSG];
};

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;
uint64_t flags1;
int ret;

if (fcls->n >= MAX_MSG)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
msg1 = fcls->msg[fcls->n];
flags1 = fcls->flags[fcls->n++];
if (NULL == msg1)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}

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, uint32_t value_size)
{
struct StateClosure *scls = cls;
const void *val = scls->value[scls->n]; // FIXME: check for n out-of-bounds FIRST!
size_t val_size = scls->value_size[scls->n++];

/* FIXME: check name */

LOG (GNUNET_ERROR_TYPE_DEBUG,
" name = %s, value_size = %u\n",
name, value_size);

return GNUNET_YES;
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");
ok = 77;
return;
}

/* Store & test membership */

LOG (GNUNET_ERROR_TYPE_INFO, "MEMBERSHIP\n");

channel_key = GNUNET_CRYPTO_eddsa_key_create ();
slave_key = GNUNET_CRYPTO_ecdsa_key_create ();

GNUNET_CRYPTO_eddsa_key_get_public (channel_key,
&channel_pub_key);
GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);

LOG (GNUNET_ERROR_TYPE_INFO, "membership_store()\n");

GNUNET_assert (GNUNET_OK == db->membership_store (db->cls, &channel_pub_key,
&slave_pub_key, GNUNET_YES,
4, 2, 1));

LOG (GNUNET_ERROR_TYPE_INFO, "membership_test()\n");

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 */

LOG (GNUNET_ERROR_TYPE_INFO, "MESSAGES\n");

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));

uint64_t fragment_id = INT64_MAX - 1;
msg->fragment_id = GNUNET_htonll (fragment_id);

uint64_t message_id = INT64_MAX - 10;
msg->message_id = GNUNET_htonll (message_id);

uint64_t group_generation = INT64_MAX - 3;
msg->group_generation = GNUNET_htonll (group_generation);

msg->hop_counter = htonl (9);
msg->fragment_offset = GNUNET_htonll (0);
msg->flags = htonl (GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT);

GNUNET_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 (channel_key, &msg->purpose, &msg->signature));

LOG (GNUNET_ERROR_TYPE_INFO, "fragment_store()\n");

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]));

LOG (GNUNET_ERROR_TYPE_INFO, "fragment_get(%" PRIu64 ")\n", fragment_id);

uint64_t ret_frags = 0;
GNUNET_assert (
GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key,
fragment_id, fragment_id,
&ret_frags, fragment_cb, &fcls));
GNUNET_assert (fcls.n == 1);

LOG (GNUNET_ERROR_TYPE_INFO, "message_get_fragment()\n");

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);

LOG (GNUNET_ERROR_TYPE_INFO, "message_add_flags()\n");
GNUNET_assert (
GNUNET_OK == db->message_add_flags (db->cls, &channel_pub_key,
GNUNET_ntohll (msg->message_id),
GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED));
LOG (GNUNET_ERROR_TYPE_INFO, "fragment_get(%" PRIu64 ")\n", fragment_id);

fcls.n = 0;
fcls.flags[0] |= GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED;

GNUNET_assert (
GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key,
fragment_id, fragment_id,
&ret_frags, fragment_cb, &fcls));

GNUNET_assert (fcls.n == 1);

LOG (GNUNET_ERROR_TYPE_INFO, "fragment_store()\n");

struct GNUNET_MULTICAST_MessageHeader *msg1
= GNUNET_malloc (sizeof (*msg1) + sizeof (channel_pub_key));

GNUNET_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]));

LOG (GNUNET_ERROR_TYPE_INFO, "message_get()\n");

GNUNET_assert (
GNUNET_OK == db->message_get (db->cls, &channel_pub_key,
message_id, message_id, 0,
&ret_frags, fragment_cb, &fcls));
GNUNET_assert (fcls.n == 2 && ret_frags == 2);

/* Message counters */

LOG (GNUNET_ERROR_TYPE_INFO, "counters_message_get()\n");

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 */

LOG (GNUNET_ERROR_TYPE_INFO, "STATE\n");

LOG (GNUNET_ERROR_TYPE_INFO, "state_modify_*()\n");

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, 0));

GNUNET_assert (GNUNET_OK == db->state_modify_op (db->cls, &channel_pub_key,
GNUNET_PSYC_OP_ASSIGN,
"_foo",
C2ARG("one two three")));

GNUNET_assert (GNUNET_OK == db->state_modify_op (db->cls, &channel_pub_key,
GNUNET_PSYC_OP_ASSIGN,
"_foo_bar", slave_key,
sizeof (*slave_key)));

GNUNET_assert (GNUNET_OK == db->state_modify_end (db->cls, &channel_pub_key,
message_id));

LOG (GNUNET_ERROR_TYPE_INFO, "state_get()\n");

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);

LOG (GNUNET_ERROR_TYPE_INFO, "state_get_prefix()\n");

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);

LOG (GNUNET_ERROR_TYPE_INFO, "state_get_signed()\n");

scls.n = 0;
GNUNET_assert (GNUNET_NO == db->state_get_signed (db->cls, &channel_pub_key,
state_cb, &scls));
GNUNET_assert (scls.n == 0);

LOG (GNUNET_ERROR_TYPE_INFO, "state_update_signed()\n");

GNUNET_assert (GNUNET_OK == db->state_update_signed (db->cls,
&channel_pub_key));

LOG (GNUNET_ERROR_TYPE_INFO, "state_get_signed()\n");

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 */

LOG (GNUNET_ERROR_TYPE_INFO, "counters_state_get()\n");

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 */

LOG (GNUNET_ERROR_TYPE_INFO, "state_sync_*()\n");

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_assign (db->cls, &channel_pub_key,
"_sync_bar", scls.value[0],
scls.value_size[0]));

GNUNET_assert (GNUNET_OK == db->state_sync_assign (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,
max_state_msg_id,
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 */

LOG (GNUNET_ERROR_TYPE_INFO, "state_modify_*()\n");

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,
message_id - max_state_msg_id));

GNUNET_assert (GNUNET_OK == db->state_modify_op (db->cls, &channel_pub_key,
GNUNET_PSYC_OP_ASSIGN,
"_sync_foo",
C2ARG("five six seven")));

GNUNET_assert (GNUNET_OK == db->state_modify_end (db->cls, &channel_pub_key,
message_id));

/* Reset state */

LOG (GNUNET_ERROR_TYPE_INFO, "state_reset()\n");

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 ( (0 != ok) &&
(77 != ok) )
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 */

+ 7
- 0
src/psycstore/test_plugin_psycstore_mysql.conf View File

@@ -0,0 +1,7 @@
[psycstore-mysql]
DATABASE = test
# CONFIG = ~/.my.cnf
# USER = gnunet
# PASSWORD =
# HOST = localhost
# PORT = 3306

+ 2
- 0
src/psycstore/test_plugin_psycstore_postgres.conf View File

@@ -0,0 +1,2 @@
[psycstore-postgres]
CONFIG = connect_timeout=10; dbname=template1

+ 2
- 0
src/psycstore/test_plugin_psycstore_sqlite.conf View File

@@ -0,0 +1,2 @@
[psycstore-sqlite]
FILENAME = $GNUNET_TMP/gnunet-test-plugin-psycstore-sqlite/sqlite.db

+ 586
- 0
src/psycstore/test_psycstore.c View File

@@ -0,0 +1,586 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @file psycstore/test_psycstore.c
* @brief Test for the PSYCstore service.
* @author Gabor X Toth
* @author Christian Grothoff
*/

#include <inttypes.h>

#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, 30)


/**
* 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 struct GNUNET_SCHEDULER_Task *end_badly_task;

static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
static struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key;

static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
static struct GNUNET_CRYPTO_EcdsaPublicKey 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_PSYC_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
*/
static void
end_badly (void *cls)
{
res = 1;
cleanup ();
}


/**
* Terminate the testcase (success).
*
* @param cls NULL
*/
static void
end_normally (void *cls)
{
res = 0;
cleanup ();
}


/**
* Finish the testcase (successfully).
*/
static void
end ()
{
if (NULL != end_badly_task)
{
GNUNET_SCHEDULER_cancel (end_badly_task);
end_badly_task = NULL;
}
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
&end_normally, NULL);
}


static void
state_reset_result (void *cls,
int64_t result,
const char *err_msg,
uint16_t err_msg_size)
{
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"state_reset_result:\t%d\n",
(int) 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,
uint32_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, (int) value_size, (char*) value, (int) val_size, (char*) val);
GNUNET_assert (0);
return GNUNET_SYSERR;
}
}


static void
state_get_prefix_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
struct StateClosure *scls = cls;
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_prefix_result:\t%ld\n", (long int) result);
GNUNET_assert (GNUNET_OK == result && 2 == scls->n);

op = GNUNET_PSYCSTORE_state_reset (h, &channel_pub_key,
&state_reset_result, cls);
}


static void
state_get_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_result:\t%ld\n", (long int) 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] = "three two one";
scls.value_size[1] = sizeof ("three two one") - 1;

op = GNUNET_PSYCSTORE_state_get_prefix (h, &channel_pub_key, "_sync",
&state_result,
&state_get_prefix_result, &scls);
}


static 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] = "_sync_bar";
scls.value[0] = "ten eleven twelve";
scls.value_size[0] = sizeof ("ten eleven twelve") - 1;

op = GNUNET_PSYCSTORE_state_get (h, &channel_pub_key, "_sync_bar_x_yy_zzz",
&state_result, &state_get_result, &scls);
}


static void
state_modify_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_modify_result:\t%ld\n", (long int) result);
GNUNET_assert (GNUNET_OK == result);

op = GNUNET_PSYCSTORE_counters_get (h, &channel_pub_key,
&counters_result, cls);
}


static void
state_sync_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
struct FragmentClosure *fcls = cls;
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_sync_result:\t%ld\n", (long int) result);
GNUNET_assert (GNUNET_OK == result);

op = GNUNET_PSYCSTORE_state_modify (h, &channel_pub_key,
GNUNET_ntohll (fcls->msg[0]->message_id),
0, state_modify_result, fcls);
}


static int
fragment_result (void *cls,
struct GNUNET_MULTICAST_MessageHeader *msg,
enum GNUNET_PSYCSTORE_MessageFlags flags)
{
struct FragmentClosure *fcls = cls;
GNUNET_assert (fcls->n < fcls->n_expected);
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 %" PRIu64 " matches\n",
GNUNET_ntohll (msg->fragment_id));
return GNUNET_YES;
}
else
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
" fragment differs: expected %" PRIu64 ", got %" PRIu64 "\n",
GNUNET_ntohll (msg0->fragment_id),
GNUNET_ntohll (msg->fragment_id));
GNUNET_assert (0);
return GNUNET_SYSERR;
}
}


static void
message_get_latest_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
struct FragmentClosure *fcls = cls;
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_latest:\t%ld\n", (long int) result);
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);

modifiers[0] = (struct GNUNET_PSYC_Modifier) {
.oper = '=',
.name = "_sync_foo",
.value = "three two one",
.value_size = sizeof ("three two one") - 1
};
modifiers[1] = (struct GNUNET_PSYC_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,
GNUNET_ntohll (fcls->msg[0]->message_id) + 2,
2, modifiers, state_sync_result, fcls);
}


static void
message_get_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
struct FragmentClosure *fcls = cls;
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get:\t%ld\n", (long int) result);
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);

fcls->n = 0;
fcls->n_expected = 3;
op = GNUNET_PSYCSTORE_message_get_latest (h, &channel_pub_key, &slave_pub_key,
1, "", &fragment_result,
&message_get_latest_result, fcls);
}


static void
message_get_fragment_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
struct FragmentClosure *fcls = cls;
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_fragment:\t%ld\n", (long int) result);
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);

fcls->n = 0;
fcls->n_expected = 3;
uint64_t message_id = GNUNET_ntohll (fcls->msg[0]->message_id);
op = GNUNET_PSYCSTORE_message_get (h, &channel_pub_key, &slave_pub_key,
message_id, message_id, 0, "",
&fragment_result,
&message_get_result, fcls);
}


static void
fragment_get_latest_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
struct FragmentClosure *fcls = cls;
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_get_latest:\t%ld\n", (long int) result);
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);

fcls->n = 1;
fcls->n_expected = 2;
op = GNUNET_PSYCSTORE_message_get_fragment (h, &channel_pub_key, &slave_pub_key,
GNUNET_ntohll (fcls->msg[1]->message_id),
GNUNET_ntohll (fcls->msg[1]->fragment_offset),
&fragment_result,
&message_get_fragment_result, fcls);
}


static void
fragment_get_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
struct FragmentClosure *fcls = cls;
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"fragment_get:\t%d\n",
(int) result);
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);

fcls->n = 0;
fcls->n_expected = 3;
op = GNUNET_PSYCSTORE_fragment_get_latest (h, &channel_pub_key,
&slave_pub_key, fcls->n_expected,
&fragment_result,
&fragment_get_latest_result, fcls);
}


static void
fragment_store_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_store:\t%ld\n", (long int) result);
GNUNET_assert (GNUNET_OK == result);

if ((intptr_t) cls == GNUNET_YES)
{ /* last fragment */
fcls.n = 0;
fcls.n_expected = 1;
uint64_t fragment_id = GNUNET_ntohll (fcls.msg[0]->fragment_id);
op = GNUNET_PSYCSTORE_fragment_get (h, &channel_pub_key, &slave_pub_key,
fragment_id, fragment_id,
&fragment_result,
&fragment_get_result, &fcls);
}
}


static void
fragment_store ()
{
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);

GNUNET_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 (channel_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));
GNUNET_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));
GNUNET_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);
}


static void
membership_test_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_test:\t%ld\n", (long int) result);
GNUNET_assert (GNUNET_OK == result);

fragment_store ();
}


static void
membership_store_result (void *cls, int64_t result,
const char *err_msg, uint16_t err_msg_size)
{
op = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_store:\t%ld\n", (long int) result);
GNUNET_assert (GNUNET_OK == result);

op = GNUNET_PSYCSTORE_membership_test (h, &channel_pub_key, &slave_pub_key,
INT64_MAX - 10, 2,
&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_TEST_PSYCSTORE
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_ecdsa_key_create ();

GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);

op = GNUNET_PSYCSTORE_membership_store (h, &channel_pub_key, &slave_pub_key,
GNUNET_YES, INT64_MAX - 5,
INT64_MAX - 10, 2,
&membership_store_result, NULL);
}


int
main (int argc, char *argv[])
{
res = 1;
#if DEBUG_TEST_PSYCSTORE
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 */

+ 8
- 0
src/psycstore/test_psycstore.conf View File

@@ -0,0 +1,8 @@
[PATHS]
GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-psycstore/

[psycstore]
DATABASE = sqlite

[psycstore-sqlite]
FILENAME = $GNUNET_TEST_HOME/psycstore/sqlite.db

+ 1
- 0
src/psycutil/.gitignore View File

@@ -0,0 +1 @@
test_psyc_env

+ 45
- 0
src/psycutil/Makefile.am View File

@@ -0,0 +1,45 @@
# This Makefile.am is in the public domain
AM_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 = libgnunetpsycutil.la

libgnunetpsycutil_la_SOURCES = \
psyc_env.c \
psyc_message.c \
psyc_slicer.c
libgnunetpsycutil_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(GN_LIBINTL) $(XLIB)
libgnunetpsycutil_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
-version-info 0:0:0

if HAVE_TESTING
check_PROGRAMS = \
test_psyc_env
endif

if ENABLE_TEST_RUN
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
TESTS = $(check_PROGRAMS)
endif

test_psyc_env_SOURCES = \
test_psyc_env.c
test_psyc_env_LDADD = \
libgnunetpsycutil.la \
$(top_builddir)/src/testing/libgnunettesting.la \
$(top_builddir)/src/util/libgnunetutil.la

+ 196
- 0
src/psycutil/psyc_env.c View File

@@ -0,0 +1,196 @@
/*
* This file is part of GNUnet.
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
*
* @file
* Library providing operations for the @e environment of
* PSYC and Social messages.
*/

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_psyc_env.h"

/**
* Environment for a message.
*
* Contains modifiers.
*/
struct GNUNET_PSYC_Environment
{
struct GNUNET_PSYC_Modifier *mod_head;
struct GNUNET_PSYC_Modifier *mod_tail;
size_t mod_count;
};


/**
* Create an environment.
*
* @return A newly allocated environment.
*/
struct GNUNET_PSYC_Environment *
GNUNET_PSYC_env_create ()
{
return GNUNET_new (struct GNUNET_PSYC_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_PSYC_env_add (struct GNUNET_PSYC_Environment *env,
enum GNUNET_PSYC_Operator oper, const char *name,
const void *value, size_t value_size)
{
struct GNUNET_PSYC_Modifier *mod = GNUNET_new (struct GNUNET_PSYC_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 first modifier of the environment.
*/
struct GNUNET_PSYC_Modifier *
GNUNET_PSYC_env_head (const struct GNUNET_PSYC_Environment *env)
{
return env->mod_head;
}


/**
* Get the last modifier of the environment.
*/
struct GNUNET_PSYC_Modifier *
GNUNET_PSYC_env_tail (const struct GNUNET_PSYC_Environment *env)
{
return env->mod_tail;
}


/**
* Remove a modifier from the environment.
*/
void
GNUNET_PSYC_env_remove (struct GNUNET_PSYC_Environment *env,
struct GNUNET_PSYC_Modifier *mod)
{
GNUNET_CONTAINER_DLL_remove (env->mod_head, env->mod_tail, mod);
}


/**
* 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_PSYC_env_shift (struct GNUNET_PSYC_Environment *env,
enum GNUNET_PSYC_Operator *oper, const char **name,
const void **value, size_t *value_size)
{
if (NULL == env->mod_head)
return GNUNET_NO;

struct GNUNET_PSYC_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_PSYC_env_iterate (const struct GNUNET_PSYC_Environment *env,
GNUNET_PSYC_Iterator it, void *it_cls)
{
struct GNUNET_PSYC_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_PSYC_env_get_count (const struct GNUNET_PSYC_Environment *env)
{
return env->mod_count;
}


/**
* Destroy an environment.
*
* @param env The environment to destroy.
*/
void
GNUNET_PSYC_env_destroy (struct GNUNET_PSYC_Environment *env)
{
struct GNUNET_PSYC_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);
}

+ 1355
- 0
src/psycutil/psyc_message.c
File diff suppressed because it is too large
View File


+ 711
- 0
src/psycutil/psyc_slicer.c View File

@@ -0,0 +1,711 @@
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
*
* @file
* PSYC Slicer API
*/

#include <inttypes.h>

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_psyc_util_lib.h"

#define LOG(kind,...) GNUNET_log_from (kind, "psyc-util-slicer",__VA_ARGS__)


/**
* Handle for a try-and-slice instance.
*/
struct GNUNET_PSYC_Slicer
{
/**
* Method handlers: H(method_name) -> SlicerMethodCallbacks
*/
struct GNUNET_CONTAINER_MultiHashMap *method_handlers;

/**
* Modifier handlers: H(modifier_name) -> SlicerModifierCallbacks
*/
struct GNUNET_CONTAINER_MultiHashMap *modifier_handlers;

/**
* Receive handle for incoming messages.
*/
struct GNUNET_PSYC_ReceiveHandle *recv;

/**
* Currently being processed message.
*/
const struct GNUNET_PSYC_MessageHeader *msg;

/**
* Currently being processed message part.
*/
const struct GNUNET_MessageHeader *pmsg;

/**
* ID of currently being received message.
*/
uint64_t message_id;

/**
* Fragment offset of currently being received message.
*/
uint64_t fragment_offset;

/**
* Flags of currently being received message.
*/
uint32_t flags;

/**
* Method name of currently being received message.
*/
char *method_name;

/**
* Name of currently processed modifier.
*/
char *mod_name;

/**
* Value of currently processed modifier.
*/
char *mod_value;

/**
* Public key of the nym the current message originates from.
*/
struct GNUNET_CRYPTO_EcdsaPublicKey nym_pub_key;

/**
* Size of @a method_name (including terminating \0).
*/
uint16_t method_name_size;

/**
* Size of @a modifier_name (including terminating \0).
*/
uint16_t mod_name_size;

/**
* Size of modifier value fragment.
*/
uint16_t mod_value_size;

/**
* Full size of modifier value.
*/
uint16_t mod_full_value_size;

/**
* Remaining bytes from the value of the current modifier.
*/
uint16_t mod_value_remaining;

/**
* Operator of currently processed modifier.
*/
uint8_t mod_oper;
};


/**
* Callbacks for a slicer method handler.
*/
struct SlicerMethodCallbacks
{
GNUNET_PSYC_MessageCallback msg_cb;
GNUNET_PSYC_MethodCallback method_cb;
GNUNET_PSYC_ModifierCallback modifier_cb;
GNUNET_PSYC_DataCallback data_cb;
GNUNET_PSYC_EndOfMessageCallback eom_cb;
void *cls;
};


struct SlicerMethodRemoveClosure
{
struct GNUNET_PSYC_Slicer *slicer;
struct SlicerMethodCallbacks rm_cbs;
};


/**
* Callbacks for a slicer method handler.
*/
struct SlicerModifierCallbacks
{
GNUNET_PSYC_ModifierCallback modifier_cb;
void *cls;
};


struct SlicerModifierRemoveClosure
{
struct GNUNET_PSYC_Slicer *slicer;
struct SlicerModifierCallbacks rm_cbs;
};


/**
* Call a method handler for an incoming message part.
*/
static int
slicer_method_handler_notify (void *cls, const struct GNUNET_HashCode *key,
void *value)
{
struct GNUNET_PSYC_Slicer *slicer = cls;
const struct GNUNET_MessageHeader *pmsg = slicer->pmsg;
struct SlicerMethodCallbacks *cbs = value;

uint16_t ptype = ntohs (pmsg->type);
switch (ptype)
{
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD:
{
if (NULL != cbs->msg_cb)
cbs->msg_cb (cbs->cls, slicer->msg);
if (NULL == cbs->method_cb)
break;
struct GNUNET_PSYC_MessageMethod *
meth = (struct GNUNET_PSYC_MessageMethod *) pmsg;
cbs->method_cb (cbs->cls, slicer->msg, meth, slicer->message_id,
slicer->method_name);
break;
}

case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
{
if (NULL == cbs->modifier_cb)
break;
struct GNUNET_PSYC_MessageModifier *
mod = (struct GNUNET_PSYC_MessageModifier *) pmsg;
cbs->modifier_cb (cbs->cls, slicer->msg, &mod->header, slicer->message_id,
mod->oper, (const char *) &mod[1],
(const void *) &mod[1] + ntohs (mod->name_size),
ntohs (mod->header.size) - sizeof (*mod) - ntohs (mod->name_size),
ntohs (mod->value_size));
break;
}

case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
{
if (NULL == cbs->modifier_cb)
break;
cbs->modifier_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id,
slicer->mod_oper, slicer->mod_name, &pmsg[1],
ntohs (pmsg->size) - sizeof (*pmsg),
slicer->mod_full_value_size);
break;
}

case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
{
if (NULL == cbs->data_cb)
break;
cbs->data_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id,
&pmsg[1], ntohs (pmsg->size) - sizeof (*pmsg));
break;
}

case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
if (NULL == cbs->eom_cb)
break;
cbs->eom_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id, GNUNET_NO);
break;

case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
if (NULL == cbs->eom_cb)
break;
cbs->eom_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id, GNUNET_YES);
break;
}
return GNUNET_YES;
}


/**
* Call a method handler for an incoming message part.
*/
static int
slicer_modifier_handler_notify (void *cls, const struct GNUNET_HashCode *key,
void *value)
{
struct GNUNET_PSYC_Slicer *slicer = cls;
struct SlicerModifierCallbacks *cbs = value;

cbs->modifier_cb (cbs->cls, slicer->msg, slicer->pmsg, slicer->message_id,
slicer->mod_oper, slicer->mod_name, slicer->mod_value,
slicer->mod_value_size, slicer->mod_full_value_size);
return GNUNET_YES;
}


/**
* Process an incoming message and call matching handlers.
*
* @param slicer
* The slicer to use.
* @param msg
* The message as it arrived from the network.
*/
void
GNUNET_PSYC_slicer_message (struct GNUNET_PSYC_Slicer *slicer,
const struct GNUNET_PSYC_MessageHeader *msg)
{
GNUNET_PSYC_receive_message (slicer->recv, msg);
}


/**
* Process an incoming message part and call matching handlers.
*
* @param cls
* Closure.
* @param message_id
* ID of the message.
* @param flags
* Flags for the message.
* @see enum GNUNET_PSYC_MessageFlags
* @param msg
* The message part. as it arrived from the network.
*/
void
GNUNET_PSYC_slicer_message_part (struct GNUNET_PSYC_Slicer *slicer,
const struct GNUNET_PSYC_MessageHeader *msg,
const struct GNUNET_MessageHeader *pmsg)
{
slicer->msg = msg;
slicer->pmsg = pmsg;

uint64_t message_id = GNUNET_ntohll (msg->message_id);

uint16_t ptype = ntohs (pmsg->type);
if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype)
{
struct GNUNET_PSYC_MessageMethod *
meth = (struct GNUNET_PSYC_MessageMethod *) pmsg;
slicer->method_name_size = ntohs (meth->header.size) - sizeof (*meth);
slicer->method_name = GNUNET_malloc (slicer->method_name_size);
GNUNET_memcpy (slicer->method_name, &meth[1], slicer->method_name_size);
slicer->message_id = message_id;
}
else
{
GNUNET_assert (message_id == slicer->message_id);
}

char *nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&msg->slave_pub_key);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Slicer received message of type %u and size %u, "
"with ID %" PRIu64 " and method %s from %s\n",
ptype, ntohs (pmsg->size), message_id, slicer->method_name, nym_str);
GNUNET_free (nym_str);

/* try-and-slice modifier */

switch (ptype)
{
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
{
struct GNUNET_PSYC_MessageModifier *
mod = (struct GNUNET_PSYC_MessageModifier *) pmsg;
slicer->mod_oper = mod->oper;
slicer->mod_name_size = ntohs (mod->name_size);
slicer->mod_name = GNUNET_malloc (slicer->mod_name_size);
GNUNET_memcpy (slicer->mod_name, &mod[1], slicer->mod_name_size);
slicer->mod_value = (char *) &mod[1] + slicer->mod_name_size;
slicer->mod_full_value_size = ntohs (mod->value_size);
slicer->mod_value_remaining = slicer->mod_full_value_size;
slicer->mod_value_size
= ntohs (mod->header.size) - sizeof (*mod) - slicer->mod_name_size;
// fall through
}
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
if (ptype == GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT)
{
slicer->mod_value = (char *) &pmsg[1];
slicer->mod_value_size = ntohs (pmsg->size) - sizeof (*pmsg);
}
slicer->mod_value_remaining -= slicer->mod_value_size;
char *name = GNUNET_malloc (slicer->mod_name_size);
GNUNET_memcpy (name, slicer->mod_name, slicer->mod_name_size);
do
{
struct GNUNET_HashCode key;
uint16_t name_len = strlen (name);
GNUNET_CRYPTO_hash (name, name_len, &key);
GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key,
slicer_modifier_handler_notify,
slicer);
char *p = strrchr (name, '_');
if (NULL == p)
break;
*p = '\0';
} while (1);
GNUNET_free (name);
}

/* try-and-slice method */

char *name = GNUNET_malloc (slicer->method_name_size);
GNUNET_memcpy (name, slicer->method_name, slicer->method_name_size);
do
{
struct GNUNET_HashCode key;
uint16_t name_len = strlen (name);
GNUNET_CRYPTO_hash (name, name_len, &key);
GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key,
slicer_method_handler_notify,
slicer);
char *p = strrchr (name, '_');
if (NULL == p)
break;
*p = '\0';
} while (1);
GNUNET_free (name);

if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
GNUNET_free (slicer->method_name);

if (0 == slicer->mod_value_remaining && NULL != slicer->mod_name)
{
GNUNET_free (slicer->mod_name);
slicer->mod_name = NULL;
slicer->mod_name_size = 0;
slicer->mod_value_size = 0;
slicer->mod_full_value_size = 0;
slicer->mod_oper = 0;
}

slicer->msg = NULL;
slicer->pmsg = NULL;
}


/**
* Create a try-and-slice instance.
*
* A slicer processes incoming messages and notifies callbacks about matching
* methods or modifiers encountered.
*
* @return A new try-and-slice construct.
*/
struct GNUNET_PSYC_Slicer *
GNUNET_PSYC_slicer_create (void)
{
struct GNUNET_PSYC_Slicer *slicer = GNUNET_malloc (sizeof (*slicer));
slicer->method_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
slicer->modifier_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
slicer->recv = GNUNET_PSYC_receive_create (NULL,
(GNUNET_PSYC_MessagePartCallback)
GNUNET_PSYC_slicer_message_part,
slicer);
return slicer;
}


/**
* Add a method to the try-and-slice instance.
*
* The callbacks are called for messages with a matching @a method_name prefix.
*
* @param slicer
* The try-and-slice instance to extend.
* @param method_name
* Name of the given method, use empty string to match all.
* @param method_cb
* Method handler invoked upon a matching message.
* @param modifier_cb
* Modifier handler, invoked after @a method_cb
* for each modifier in the message.
* @param data_cb
* Data handler, invoked after @a modifier_cb for each data fragment.
* @param eom_cb
* Invoked upon reaching the end of a matching message.
* @param cls
* Closure for the callbacks.
*/
void
GNUNET_PSYC_slicer_method_add (struct GNUNET_PSYC_Slicer *slicer,
const char *method_name,
GNUNET_PSYC_MessageCallback msg_cb,
GNUNET_PSYC_MethodCallback method_cb,
GNUNET_PSYC_ModifierCallback modifier_cb,
GNUNET_PSYC_DataCallback data_cb,
GNUNET_PSYC_EndOfMessageCallback eom_cb,
void *cls)
{
struct GNUNET_HashCode key;
GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);

struct SlicerMethodCallbacks *cbs = GNUNET_malloc (sizeof (*cbs));
cbs->msg_cb = msg_cb,
cbs->method_cb = method_cb;
cbs->modifier_cb = modifier_cb;
cbs->data_cb = data_cb;
cbs->eom_cb = eom_cb;
cbs->cls = cls;

GNUNET_CONTAINER_multihashmap_put (slicer->method_handlers, &key, cbs,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
}


static int
slicer_method_remove (void *cls, const struct GNUNET_HashCode *key, void *value)
{
struct SlicerMethodRemoveClosure *rm_cls = cls;
struct GNUNET_PSYC_Slicer *slicer = rm_cls->slicer;
struct SlicerMethodCallbacks *rm_cbs = &rm_cls->rm_cbs;
struct SlicerMethodCallbacks *cbs = value;

if ((NULL == rm_cbs->msg_cb || cbs->msg_cb == rm_cbs->msg_cb)
&& (NULL == rm_cbs->method_cb || cbs->method_cb == rm_cbs->method_cb)
&& (NULL == rm_cbs->modifier_cb || cbs->modifier_cb == rm_cbs->modifier_cb)
&& (NULL == rm_cbs->data_cb || cbs->data_cb == rm_cbs->data_cb)
&& (NULL == rm_cbs->eom_cb || cbs->eom_cb == rm_cbs->eom_cb))
{
GNUNET_CONTAINER_multihashmap_remove (slicer->method_handlers, key, cbs);
GNUNET_free (cbs);
return GNUNET_NO;
}
return GNUNET_YES;
}


/**
* Remove a registered method from the try-and-slice instance.
*
* Removes one matching handler registered with the given
* @a method_name and callbacks.
*
* @param slicer
* The try-and-slice instance.
* @param method_name
* Name of the method to remove.
* @param method_cb
* Method handler.
* @param modifier_cb
* Modifier handler.
* @param data_cb
* Data handler.
* @param eom_cb
* End of message handler.
*
* @return #GNUNET_OK if a method handler was removed,
* #GNUNET_NO if no handler matched the given method name and callbacks.
*/
int
GNUNET_PSYC_slicer_method_remove (struct GNUNET_PSYC_Slicer *slicer,
const char *method_name,
GNUNET_PSYC_MessageCallback msg_cb,
GNUNET_PSYC_MethodCallback method_cb,
GNUNET_PSYC_ModifierCallback modifier_cb,
GNUNET_PSYC_DataCallback data_cb,
GNUNET_PSYC_EndOfMessageCallback eom_cb)
{
struct GNUNET_HashCode key;
GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);

struct SlicerMethodRemoveClosure rm_cls;
rm_cls.slicer = slicer;
struct SlicerMethodCallbacks *rm_cbs = &rm_cls.rm_cbs;
rm_cbs->msg_cb = msg_cb;
rm_cbs->method_cb = method_cb;
rm_cbs->modifier_cb = modifier_cb;
rm_cbs->data_cb = data_cb;
rm_cbs->eom_cb = eom_cb;

return
(GNUNET_SYSERR
== GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key,
slicer_method_remove,
&rm_cls))
? GNUNET_NO
: GNUNET_OK;
}


/**
* Watch a place for changed objects.
*
* @param slicer
* The try-and-slice instance.
* @param object_filter
* Object prefix to match.
* @param modifier_cb
* Function to call when encountering a state modifier.
* @param cls
* Closure for callback.
*/
void
GNUNET_PSYC_slicer_modifier_add (struct GNUNET_PSYC_Slicer *slicer,
const char *object_filter,
GNUNET_PSYC_ModifierCallback modifier_cb,
void *cls)
{
struct SlicerModifierCallbacks *cbs = GNUNET_malloc (sizeof *cbs);
cbs->modifier_cb = modifier_cb;
cbs->cls = cls;

struct GNUNET_HashCode key;
GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key);
GNUNET_CONTAINER_multihashmap_put (slicer->modifier_handlers, &key, cbs,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
}


static int
slicer_modifier_remove (void *cls, const struct GNUNET_HashCode *key, void *value)
{
struct SlicerModifierRemoveClosure *rm_cls = cls;
struct GNUNET_PSYC_Slicer *slicer = rm_cls->slicer;
struct SlicerModifierCallbacks *rm_cbs = &rm_cls->rm_cbs;
struct SlicerModifierCallbacks *cbs = value;

if (cbs->modifier_cb == rm_cbs->modifier_cb)
{
GNUNET_CONTAINER_multihashmap_remove (slicer->modifier_handlers, key, cbs);
GNUNET_free (cbs);
return GNUNET_NO;
}
return GNUNET_YES;
}


/**
* Remove a registered modifier from the try-and-slice instance.
*
* Removes one matching handler registered with the given
* @a object_filter and @a modifier_cb.
*
* @param slicer
* The try-and-slice instance.
* @param object_filter
* Object prefix to match.
* @param modifier_cb
* Function to call when encountering a state modifier changes.
*/
int
GNUNET_PSYC_slicer_modifier_remove (struct GNUNET_PSYC_Slicer *slicer,
const char *object_filter,
GNUNET_PSYC_ModifierCallback modifier_cb)
{
struct GNUNET_HashCode key;
GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key);

struct SlicerModifierRemoveClosure rm_cls;
rm_cls.slicer = slicer;
struct SlicerModifierCallbacks *rm_cbs = &rm_cls.rm_cbs;
rm_cbs->modifier_cb = modifier_cb;

return
(GNUNET_SYSERR
== GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key,
slicer_modifier_remove,
&rm_cls))
? GNUNET_NO
: GNUNET_OK;
}


static int
slicer_method_free (void *cls, const struct GNUNET_HashCode *key, void *value)
{
struct SlicerMethodCallbacks *cbs = value;
GNUNET_free (cbs);
return GNUNET_YES;
}


static int
slicer_modifier_free (void *cls, const struct GNUNET_HashCode *key, void *value)
{
struct SlicerModifierCallbacks *cbs = value;
GNUNET_free (cbs);
return GNUNET_YES;
}


/**
* Remove all registered method handlers.
*
* @param slicer
* Slicer to clear.
*/
void
GNUNET_PSYC_slicer_method_clear (struct GNUNET_PSYC_Slicer *slicer)
{
GNUNET_CONTAINER_multihashmap_iterate (slicer->method_handlers,
slicer_method_free, NULL);
GNUNET_CONTAINER_multihashmap_clear (slicer->method_handlers);
}


/**
* Remove all registered modifier handlers.
*
* @param slicer
* Slicer to clear.
*/
void
GNUNET_PSYC_slicer_modifier_clear (struct GNUNET_PSYC_Slicer *slicer)
{
GNUNET_CONTAINER_multihashmap_iterate (slicer->modifier_handlers,
slicer_modifier_free, NULL);
GNUNET_CONTAINER_multihashmap_clear (slicer->modifier_handlers);
}


/**
* Remove all registered method & modifier handlers.
*
* @param slicer
* Slicer to clear.
*/
void
GNUNET_PSYC_slicer_clear (struct GNUNET_PSYC_Slicer *slicer)
{
GNUNET_PSYC_slicer_method_clear (slicer);
GNUNET_PSYC_slicer_modifier_clear (slicer);
}


/**
* Destroy a given try-and-slice instance.
*
* @param slicer
* Slicer to destroy
*/
void
GNUNET_PSYC_slicer_destroy (struct GNUNET_PSYC_Slicer *slicer)
{
GNUNET_PSYC_slicer_clear (slicer);
GNUNET_CONTAINER_multihashmap_destroy (slicer->method_handlers);
GNUNET_CONTAINER_multihashmap_destroy (slicer->modifier_handlers);
GNUNET_PSYC_receive_destroy (slicer->recv);
GNUNET_free (slicer);
}

+ 96
- 0
src/psycutil/test_psyc_env.c View File

@@ -0,0 +1,96 @@
/*
* This file is part of GNUnet.
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* GNUnet is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
* @author Gabor X Toth
*
* @file
* Tests for the environment library.
*/

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_testing_lib.h"
#include "gnunet_psyc_util_lib.h"

struct GNUNET_PSYC_Modifier mods[] = {
{ .oper = GNUNET_PSYC_OP_SET,
.name = "_foo", .value = "foo", .value_size = 3 },

{ .oper = GNUNET_PSYC_OP_ASSIGN,
.name = "_foo_bar", .value = "foo bar", .value_size = 7 },

{ .oper = GNUNET_PSYC_OP_AUGMENT,
.name = "_foo_bar_baz", .value = "foo bar baz", .value_size = 11 }
};

struct ItCls
{
size_t n;
};

int
iterator (void *cls, enum GNUNET_PSYC_Operator oper,
const char *name, const char *value, uint32_t value_size)
{
struct ItCls *it_cls = cls;
struct GNUNET_PSYC_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_PSYC_Environment *env = GNUNET_PSYC_env_create ();
GNUNET_assert (NULL != env);
int i, len = 3;

for (i = 0; i < len; i++)
{
GNUNET_PSYC_env_add (env, mods[i].oper, mods[i].name,
mods[i].value, mods[i].value_size);
}

struct ItCls it_cls = { .n = 0 };
GNUNET_PSYC_env_iterate (env, iterator, &it_cls);
GNUNET_assert (len == it_cls.n);

for (i = 0; i < len; i++)
{
enum GNUNET_PSYC_Operator oper;
const char *name;
const void *value;
size_t value_size;
GNUNET_PSYC_env_shift (env, &oper, &name, &value, &value_size);
GNUNET_assert (len - i - 1 == GNUNET_PSYC_env_get_count (env));
}

GNUNET_PSYC_env_destroy (env);

return 0;
}

+ 3
- 0
src/social/.gitignore View File

@@ -0,0 +1,3 @@
gnunet-social
gnunet-service-social
test_social

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save