@@ -0,0 +1 @@ | |||
Christian Grothoff |
@@ -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>. |
@@ -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. | |||
@@ -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. | |||
@@ -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 +1 @@ | |||
Experimental code for SecuShare. |
@@ -0,0 +1,8 @@ | |||
#!/bin/sh | |||
libtoolize --automake --copy --force | |||
aclocal -I m4 | |||
autoheader | |||
autoconf | |||
automake --add-missing --copy | |||
@@ -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 |
@@ -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 | |||
]) |
@@ -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 | |||
]) |
@@ -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], []) |
@@ -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 | |||
]) |
@@ -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 | |||
]) |
@@ -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]) | |||
]) |
@@ -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" | |||
]) |
@@ -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])]) |
@@ -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 | |||
]) |
@@ -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) | |||
]) |
@@ -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])]) |
@@ -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]) | |||
]) |
@@ -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 | |||
]) | |||
@@ -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" | |||
]) |
@@ -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 | |||
]) |
@@ -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 |
@@ -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} |
@@ -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} |
@@ -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} |
@@ -0,0 +1,6 @@ | |||
Makefile.in | |||
Makefile | |||
POTFILES | |||
gnunet-ext.pot | |||
remove-potcdate.sed | |||
stamp-po |
@@ -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. | |||
@@ -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: |
@@ -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 = |
@@ -0,0 +1,2 @@ | |||
# List of source files which contain translatable strings. | |||
src/ext/gnunet-ext.c |
@@ -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 |
@@ -0,0 +1,10 @@ | |||
s/"\([^"]*\)"/“\1”/g | |||
s/`\([^`']*\)'/‘\1’/g | |||
s/ '\([^`']*\)' / ‘\1’ /g | |||
s/ '\([^`']*\)'$/ ‘\1’/g | |||
s/^'\([^`']*\)' /‘\1’ /g | |||
s/“”/""/g | |||
s/“/“[1m/g | |||
s/”/[0m”/g | |||
s/‘/‘[1m/g | |||
s/’/[0m’/g |
@@ -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. | |||
# |
@@ -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. | |||
# |
@@ -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 | |||
} |
@@ -0,0 +1,6 @@ | |||
s/"\([^"]*\)"/“\1”/g | |||
s/`\([^`']*\)'/‘\1’/g | |||
s/ '\([^`']*\)' / ‘\1’ /g | |||
s/ '\([^`']*\)'$/ ‘\1’/g | |||
s/^'\([^`']*\)' /‘\1’ /g | |||
s/“”/""/g |
@@ -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 | |||
} |
@@ -0,0 +1,2 @@ | |||
Makefile | |||
Makefile.in |
@@ -0,0 +1,7 @@ | |||
# This Makefile.am is in the public domain | |||
SUBDIRS = include \ | |||
multicast \ | |||
psycutil \ | |||
psycstore \ | |||
psyc \ | |||
social |
@@ -0,0 +1,2 @@ | |||
Makefile | |||
Makefile.in |
@@ -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 |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 |
@@ -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 */ |
@@ -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 */ |
@@ -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 |
@@ -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 |
@@ -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 */ |
@@ -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 = |
@@ -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 */ |
@@ -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 */ |
@@ -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 |
@@ -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, | |||
¬ify, | |||
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 */ |
@@ -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 |
@@ -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 */ |
@@ -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 | |||
@@ -0,0 +1,2 @@ | |||
gnunet-service-psyc | |||
test_psyc |
@@ -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 |
@@ -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; |
@@ -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 |
@@ -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; | |||
@@ -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 */ |
@@ -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 */ |
@@ -0,0 +1,5 @@ | |||
gnunet-service-psycstore | |||
test_plugin_psycstore_mysql | |||
test_plugin_psycstore_sqlite | |||
test_plugin_psycstore_postgres | |||
test_psycstore |
@@ -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 | |||
@@ -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 |
@@ -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 |
@@ -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 */ |
@@ -0,0 +1,7 @@ | |||
[psycstore-mysql] | |||
DATABASE = test | |||
# CONFIG = ~/.my.cnf | |||
# USER = gnunet | |||
# PASSWORD = | |||
# HOST = localhost | |||
# PORT = 3306 |
@@ -0,0 +1,2 @@ | |||
[psycstore-postgres] | |||
CONFIG = connect_timeout=10; dbname=template1 |
@@ -0,0 +1,2 @@ | |||
[psycstore-sqlite] | |||
FILENAME = $GNUNET_TMP/gnunet-test-plugin-psycstore-sqlite/sqlite.db |
@@ -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 */ |
@@ -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 |
@@ -0,0 +1 @@ | |||
test_psyc_env |
@@ -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 |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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; | |||
} |
@@ -0,0 +1,3 @@ | |||
gnunet-social | |||
gnunet-service-social | |||
test_social |