initial import from gnunet.git
This commit is contained in:
commit
1f59e703d8
674
COPYING
Normal file
674
COPYING
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
14
ChangeLog
Normal file
14
ChangeLog
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
2012-03-07 gettextize <bug-gnu-gettext@gnu.org>
|
||||||
|
|
||||||
|
* m4/gettext.m4: New file, from gettext-0.18.1.
|
||||||
|
* m4/iconv.m4: New file, from gettext-0.18.1.
|
||||||
|
* m4/lib-ld.m4: New file, from gettext-0.18.1.
|
||||||
|
* m4/lib-link.m4: New file, from gettext-0.18.1.
|
||||||
|
* m4/lib-prefix.m4: New file, from gettext-0.18.1.
|
||||||
|
* m4/nls.m4: New file, from gettext-0.18.1.
|
||||||
|
* m4/po.m4: New file, from gettext-0.18.1.
|
||||||
|
* m4/progtest.m4: New file, from gettext-0.18.1.
|
||||||
|
* Makefile.am (SUBDIRS): Add po.
|
||||||
|
* configure.ac (AC_OUTPUT): Add po/Makefile.in.
|
||||||
|
(AM_GNU_GETTEXT_VERSION): Bump to 0.18.1.
|
||||||
|
|
365
INSTALL
Normal file
365
INSTALL
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
Installation Instructions
|
||||||
|
*************************
|
||||||
|
|
||||||
|
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||||
|
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. This file is offered as-is,
|
||||||
|
without warranty of any kind.
|
||||||
|
|
||||||
|
Basic Installation
|
||||||
|
==================
|
||||||
|
|
||||||
|
Briefly, the shell commands `./configure; make; make install' should
|
||||||
|
configure, build, and install this package. The following
|
||||||
|
more-detailed instructions are generic; see the `README' file for
|
||||||
|
instructions specific to this package. Some packages provide this
|
||||||
|
`INSTALL' file but do not implement all of the features documented
|
||||||
|
below. The lack of an optional feature in a given package is not
|
||||||
|
necessarily a bug. More recommendations for GNU packages can be found
|
||||||
|
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||||
|
|
||||||
|
The `configure' shell script attempts to guess correct values for
|
||||||
|
various system-dependent variables used during compilation. It uses
|
||||||
|
those values to create a `Makefile' in each directory of the package.
|
||||||
|
It may also create one or more `.h' files containing system-dependent
|
||||||
|
definitions. Finally, it creates a shell script `config.status' that
|
||||||
|
you can run in the future to recreate the current configuration, and a
|
||||||
|
file `config.log' containing compiler output (useful mainly for
|
||||||
|
debugging `configure').
|
||||||
|
|
||||||
|
It can also use an optional file (typically called `config.cache'
|
||||||
|
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||||
|
the results of its tests to speed up reconfiguring. Caching is
|
||||||
|
disabled by default to prevent problems with accidental use of stale
|
||||||
|
cache files.
|
||||||
|
|
||||||
|
If you need to do unusual things to compile the package, please try
|
||||||
|
to figure out how `configure' could check whether to do them, and mail
|
||||||
|
diffs or instructions to the address given in the `README' so they can
|
||||||
|
be considered for the next release. If you are using the cache, and at
|
||||||
|
some point `config.cache' contains results you don't want to keep, you
|
||||||
|
may remove or edit it.
|
||||||
|
|
||||||
|
The file `configure.ac' (or `configure.in') is used to create
|
||||||
|
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||||
|
you want to change it or regenerate `configure' using a newer version
|
||||||
|
of `autoconf'.
|
||||||
|
|
||||||
|
The simplest way to compile this package is:
|
||||||
|
|
||||||
|
1. `cd' to the directory containing the package's source code and type
|
||||||
|
`./configure' to configure the package for your system.
|
||||||
|
|
||||||
|
Running `configure' might take a while. While running, it prints
|
||||||
|
some messages telling which features it is checking for.
|
||||||
|
|
||||||
|
2. Type `make' to compile the package.
|
||||||
|
|
||||||
|
3. Optionally, type `make check' to run any self-tests that come with
|
||||||
|
the package, generally using the just-built uninstalled binaries.
|
||||||
|
|
||||||
|
4. Type `make install' to install the programs and any data files and
|
||||||
|
documentation. When installing into a prefix owned by root, it is
|
||||||
|
recommended that the package be configured and built as a regular
|
||||||
|
user, and only the `make install' phase executed with root
|
||||||
|
privileges.
|
||||||
|
|
||||||
|
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||||
|
this time using the binaries in their final installed location.
|
||||||
|
This target does not install anything. Running this target as a
|
||||||
|
regular user, particularly if the prior `make install' required
|
||||||
|
root privileges, verifies that the installation completed
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
6. You can remove the program binaries and object files from the
|
||||||
|
source code directory by typing `make clean'. To also remove the
|
||||||
|
files that `configure' created (so you can compile the package for
|
||||||
|
a different kind of computer), type `make distclean'. There is
|
||||||
|
also a `make maintainer-clean' target, but that is intended mainly
|
||||||
|
for the package's developers. If you use it, you may have to get
|
||||||
|
all sorts of other programs in order to regenerate files that came
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
7. Often, you can also type `make uninstall' to remove the installed
|
||||||
|
files again. In practice, not all packages have tested that
|
||||||
|
uninstallation works correctly, even though it is required by the
|
||||||
|
GNU Coding Standards.
|
||||||
|
|
||||||
|
8. Some packages, particularly those that use Automake, provide `make
|
||||||
|
distcheck', which can by used by developers to test that all other
|
||||||
|
targets like `make install' and `make uninstall' work correctly.
|
||||||
|
This target is generally not run by end users.
|
||||||
|
|
||||||
|
Compilers and Options
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Some systems require unusual options for compilation or linking that
|
||||||
|
the `configure' script does not know about. Run `./configure --help'
|
||||||
|
for details on some of the pertinent environment variables.
|
||||||
|
|
||||||
|
You can give `configure' initial values for configuration parameters
|
||||||
|
by setting variables in the command line or in the environment. Here
|
||||||
|
is an example:
|
||||||
|
|
||||||
|
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||||
|
|
||||||
|
*Note Defining Variables::, for more details.
|
||||||
|
|
||||||
|
Compiling For Multiple Architectures
|
||||||
|
====================================
|
||||||
|
|
||||||
|
You can compile the package for more than one kind of computer at the
|
||||||
|
same time, by placing the object files for each architecture in their
|
||||||
|
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||||
|
directory where you want the object files and executables to go and run
|
||||||
|
the `configure' script. `configure' automatically checks for the
|
||||||
|
source code in the directory that `configure' is in and in `..'. This
|
||||||
|
is known as a "VPATH" build.
|
||||||
|
|
||||||
|
With a non-GNU `make', it is safer to compile the package for one
|
||||||
|
architecture at a time in the source code directory. After you have
|
||||||
|
installed the package for one architecture, use `make distclean' before
|
||||||
|
reconfiguring for another architecture.
|
||||||
|
|
||||||
|
On MacOS X 10.5 and later systems, you can create libraries and
|
||||||
|
executables that work on multiple system types--known as "fat" or
|
||||||
|
"universal" binaries--by specifying multiple `-arch' options to the
|
||||||
|
compiler but only a single `-arch' option to the preprocessor. Like
|
||||||
|
this:
|
||||||
|
|
||||||
|
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CPP="gcc -E" CXXCPP="g++ -E"
|
||||||
|
|
||||||
|
This is not guaranteed to produce working output in all cases, you
|
||||||
|
may have to build one architecture at a time and combine the results
|
||||||
|
using the `lipo' tool if you have problems.
|
||||||
|
|
||||||
|
Installation Names
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, `make install' installs the package's commands under
|
||||||
|
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||||
|
can specify an installation prefix other than `/usr/local' by giving
|
||||||
|
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||||
|
absolute file name.
|
||||||
|
|
||||||
|
You can specify separate installation prefixes for
|
||||||
|
architecture-specific files and architecture-independent files. If you
|
||||||
|
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||||
|
PREFIX as the prefix for installing programs and libraries.
|
||||||
|
Documentation and other data files still use the regular prefix.
|
||||||
|
|
||||||
|
In addition, if you use an unusual directory layout you can give
|
||||||
|
options like `--bindir=DIR' to specify different values for particular
|
||||||
|
kinds of files. Run `configure --help' for a list of the directories
|
||||||
|
you can set and what kinds of files go in them. In general, the
|
||||||
|
default for these options is expressed in terms of `${prefix}', so that
|
||||||
|
specifying just `--prefix' will affect all of the other directory
|
||||||
|
specifications that were not explicitly provided.
|
||||||
|
|
||||||
|
The most portable way to affect installation locations is to pass the
|
||||||
|
correct locations to `configure'; however, many packages provide one or
|
||||||
|
both of the following shortcuts of passing variable assignments to the
|
||||||
|
`make install' command line to change installation locations without
|
||||||
|
having to reconfigure or recompile.
|
||||||
|
|
||||||
|
The first method involves providing an override variable for each
|
||||||
|
affected directory. For example, `make install
|
||||||
|
prefix=/alternate/directory' will choose an alternate location for all
|
||||||
|
directory configuration variables that were expressed in terms of
|
||||||
|
`${prefix}'. Any directories that were specified during `configure',
|
||||||
|
but not in terms of `${prefix}', must each be overridden at install
|
||||||
|
time for the entire installation to be relocated. The approach of
|
||||||
|
makefile variable overrides for each directory variable is required by
|
||||||
|
the GNU Coding Standards, and ideally causes no recompilation.
|
||||||
|
However, some platforms have known limitations with the semantics of
|
||||||
|
shared libraries that end up requiring recompilation when using this
|
||||||
|
method, particularly noticeable in packages that use GNU Libtool.
|
||||||
|
|
||||||
|
The second method involves providing the `DESTDIR' variable. For
|
||||||
|
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||||
|
`/alternate/directory' before all installation names. The approach of
|
||||||
|
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||||
|
does not work on platforms that have drive letters. On the other hand,
|
||||||
|
it does better at avoiding recompilation issues, and works well even
|
||||||
|
when some directory options were not specified in terms of `${prefix}'
|
||||||
|
at `configure' time.
|
||||||
|
|
||||||
|
Optional Features
|
||||||
|
=================
|
||||||
|
|
||||||
|
If the package supports it, you can cause programs to be installed
|
||||||
|
with an extra prefix or suffix on their names by giving `configure' the
|
||||||
|
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||||
|
|
||||||
|
Some packages pay attention to `--enable-FEATURE' options to
|
||||||
|
`configure', where FEATURE indicates an optional part of the package.
|
||||||
|
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||||
|
is something like `gnu-as' or `x' (for the X Window System). The
|
||||||
|
`README' should mention any `--enable-' and `--with-' options that the
|
||||||
|
package recognizes.
|
||||||
|
|
||||||
|
For packages that use the X Window System, `configure' can usually
|
||||||
|
find the X include and library files automatically, but if it doesn't,
|
||||||
|
you can use the `configure' options `--x-includes=DIR' and
|
||||||
|
`--x-libraries=DIR' to specify their locations.
|
||||||
|
|
||||||
|
Some packages offer the ability to configure how verbose the
|
||||||
|
execution of `make' will be. For these packages, running `./configure
|
||||||
|
--enable-silent-rules' sets the default to minimal output, which can be
|
||||||
|
overridden with `make V=1'; while running `./configure
|
||||||
|
--disable-silent-rules' sets the default to verbose, which can be
|
||||||
|
overridden with `make V=0'.
|
||||||
|
|
||||||
|
Particular systems
|
||||||
|
==================
|
||||||
|
|
||||||
|
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||||
|
CC is not installed, it is recommended to use the following options in
|
||||||
|
order to use an ANSI C compiler:
|
||||||
|
|
||||||
|
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||||
|
|
||||||
|
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||||
|
|
||||||
|
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||||
|
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||||
|
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||||
|
to try
|
||||||
|
|
||||||
|
./configure CC="cc"
|
||||||
|
|
||||||
|
and if that doesn't work, try
|
||||||
|
|
||||||
|
./configure CC="cc -nodtk"
|
||||||
|
|
||||||
|
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||||
|
directory contains several dysfunctional programs; working variants of
|
||||||
|
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||||
|
in your `PATH', put it _after_ `/usr/bin'.
|
||||||
|
|
||||||
|
On Haiku, software installed for all users goes in `/boot/common',
|
||||||
|
not `/usr/local'. It is recommended to use the following options:
|
||||||
|
|
||||||
|
./configure --prefix=/boot/common
|
||||||
|
|
||||||
|
Specifying the System Type
|
||||||
|
==========================
|
||||||
|
|
||||||
|
There may be some features `configure' cannot figure out
|
||||||
|
automatically, but needs to determine by the type of machine the package
|
||||||
|
will run on. Usually, assuming the package is built to be run on the
|
||||||
|
_same_ architectures, `configure' can figure that out, but if it prints
|
||||||
|
a message saying it cannot guess the machine type, give it the
|
||||||
|
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||||
|
type, such as `sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
|
CPU-COMPANY-SYSTEM
|
||||||
|
|
||||||
|
where SYSTEM can have one of these forms:
|
||||||
|
|
||||||
|
OS
|
||||||
|
KERNEL-OS
|
||||||
|
|
||||||
|
See the file `config.sub' for the possible values of each field. If
|
||||||
|
`config.sub' isn't included in this package, then this package doesn't
|
||||||
|
need to know the machine type.
|
||||||
|
|
||||||
|
If you are _building_ compiler tools for cross-compiling, you should
|
||||||
|
use the option `--target=TYPE' to select the type of system they will
|
||||||
|
produce code for.
|
||||||
|
|
||||||
|
If you want to _use_ a cross compiler, that generates code for a
|
||||||
|
platform different from the build platform, you should specify the
|
||||||
|
"host" platform (i.e., that on which the generated programs will
|
||||||
|
eventually be run) with `--host=TYPE'.
|
||||||
|
|
||||||
|
Sharing Defaults
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to set default values for `configure' scripts to share,
|
||||||
|
you can create a site shell script called `config.site' that gives
|
||||||
|
default values for variables like `CC', `cache_file', and `prefix'.
|
||||||
|
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||||
|
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
|
`CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
A warning: not all `configure' scripts look for a site script.
|
||||||
|
|
||||||
|
Defining Variables
|
||||||
|
==================
|
||||||
|
|
||||||
|
Variables not defined in a site shell script can be set in the
|
||||||
|
environment passed to `configure'. However, some packages may run
|
||||||
|
configure again during the build, and the customized values of these
|
||||||
|
variables may be lost. In order to avoid this problem, you should set
|
||||||
|
them in the `configure' command line, using `VAR=value'. For example:
|
||||||
|
|
||||||
|
./configure CC=/usr/local2/bin/gcc
|
||||||
|
|
||||||
|
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||||
|
overridden in the site shell script).
|
||||||
|
|
||||||
|
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||||
|
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||||
|
|
||||||
|
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||||
|
|
||||||
|
`configure' Invocation
|
||||||
|
======================
|
||||||
|
|
||||||
|
`configure' recognizes the following options to control how it
|
||||||
|
operates.
|
||||||
|
|
||||||
|
`--help'
|
||||||
|
`-h'
|
||||||
|
Print a summary of all of the options to `configure', and exit.
|
||||||
|
|
||||||
|
`--help=short'
|
||||||
|
`--help=recursive'
|
||||||
|
Print a summary of the options unique to this package's
|
||||||
|
`configure', and exit. The `short' variant lists options used
|
||||||
|
only in the top level, while the `recursive' variant lists options
|
||||||
|
also present in any nested packages.
|
||||||
|
|
||||||
|
`--version'
|
||||||
|
`-V'
|
||||||
|
Print the version of Autoconf used to generate the `configure'
|
||||||
|
script, and exit.
|
||||||
|
|
||||||
|
`--cache-file=FILE'
|
||||||
|
Enable the cache: use and save the results of the tests in FILE,
|
||||||
|
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||||
|
disable caching.
|
||||||
|
|
||||||
|
`--config-cache'
|
||||||
|
`-C'
|
||||||
|
Alias for `--cache-file=config.cache'.
|
||||||
|
|
||||||
|
`--quiet'
|
||||||
|
`--silent'
|
||||||
|
`-q'
|
||||||
|
Do not print messages saying which checks are being made. To
|
||||||
|
suppress all normal output, redirect it to `/dev/null' (any error
|
||||||
|
messages will still be shown).
|
||||||
|
|
||||||
|
`--srcdir=DIR'
|
||||||
|
Look for the package's source code in directory DIR. Usually
|
||||||
|
`configure' can determine that directory automatically.
|
||||||
|
|
||||||
|
`--prefix=DIR'
|
||||||
|
Use DIR as the installation prefix. *note Installation Names::
|
||||||
|
for more details, including other options available for fine-tuning
|
||||||
|
the installation locations.
|
||||||
|
|
||||||
|
`--no-create'
|
||||||
|
`-n'
|
||||||
|
Run the configure checks, but stop before creating any output
|
||||||
|
files.
|
||||||
|
|
||||||
|
`configure' also accepts some other, not widely useful, options. Run
|
||||||
|
`configure --help' for more details.
|
||||||
|
|
9
Makefile.am
Normal file
9
Makefile.am
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# This Makefile.am is in the public domain
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
SUBDIRS = src po pkgconfig
|
||||||
|
|
||||||
|
EXTRA_DIST = config.rpath \
|
||||||
|
install-sh
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
8
bootstrap
Executable file
8
bootstrap
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
libtoolize --automake --copy --force
|
||||||
|
aclocal -I m4
|
||||||
|
autoheader
|
||||||
|
autoconf
|
||||||
|
automake --add-missing --copy
|
||||||
|
|
672
config.rpath
Executable file
672
config.rpath
Executable file
@ -0,0 +1,672 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# Output a system dependent set of variables, describing how to set the
|
||||||
|
# run time search path of shared libraries in an executable.
|
||||||
|
#
|
||||||
|
# Copyright 1996-2010 Free Software Foundation, Inc.
|
||||||
|
# Taken from GNU libtool, 2001
|
||||||
|
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
#
|
||||||
|
# The first argument passed to this file is the canonical host specification,
|
||||||
|
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
|
||||||
|
# or
|
||||||
|
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
|
||||||
|
# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
|
||||||
|
# should be set by the caller.
|
||||||
|
#
|
||||||
|
# The set of defined variables is at the end of this script.
|
||||||
|
|
||||||
|
# Known limitations:
|
||||||
|
# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
|
||||||
|
# than 256 bytes, otherwise the compiler driver will dump core. The only
|
||||||
|
# known workaround is to choose shorter directory names for the build
|
||||||
|
# directory and/or the installation directory.
|
||||||
|
|
||||||
|
# All known linkers require a `.a' archive for static linking (except MSVC,
|
||||||
|
# which needs '.lib').
|
||||||
|
libext=a
|
||||||
|
shrext=.so
|
||||||
|
|
||||||
|
host="$1"
|
||||||
|
host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
|
||||||
|
host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
|
||||||
|
host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
|
||||||
|
|
||||||
|
# Code taken from libtool.m4's _LT_CC_BASENAME.
|
||||||
|
|
||||||
|
for cc_temp in $CC""; do
|
||||||
|
case $cc_temp in
|
||||||
|
compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
|
||||||
|
distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
|
||||||
|
\-*) ;;
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
|
||||||
|
|
||||||
|
# Code taken from libtool.m4's _LT_COMPILER_PIC.
|
||||||
|
|
||||||
|
wl=
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
wl='-Wl,'
|
||||||
|
else
|
||||||
|
case "$host_os" in
|
||||||
|
aix*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
darwin*)
|
||||||
|
case $cc_basename in
|
||||||
|
xlc*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
mingw* | cygwin* | pw32* | os2* | cegcc*)
|
||||||
|
;;
|
||||||
|
hpux9* | hpux10* | hpux11*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
irix5* | irix6* | nonstopux*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
newsos6)
|
||||||
|
;;
|
||||||
|
linux* | k*bsd*-gnu)
|
||||||
|
case $cc_basename in
|
||||||
|
ecc*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
icc* | ifort*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
lf95*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
pgcc | pgf77 | pgf90)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
ccc*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
como)
|
||||||
|
wl='-lopt='
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case `$CC -V 2>&1 | sed 5q` in
|
||||||
|
*Sun\ C*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
osf3* | osf4* | osf5*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
rdos*)
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
wl='-Qoption ld '
|
||||||
|
;;
|
||||||
|
sysv4 | sysv4.2uw2* | sysv4.3*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
sysv4*MP*)
|
||||||
|
;;
|
||||||
|
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
unicos*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
uts4*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Code taken from libtool.m4's _LT_LINKER_SHLIBS.
|
||||||
|
|
||||||
|
hardcode_libdir_flag_spec=
|
||||||
|
hardcode_libdir_separator=
|
||||||
|
hardcode_direct=no
|
||||||
|
hardcode_minus_L=no
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
cygwin* | mingw* | pw32* | cegcc*)
|
||||||
|
# FIXME: the MSVC++ port hasn't been tested in a loooong time
|
||||||
|
# When not using gcc, we currently assume that we are using
|
||||||
|
# Microsoft Visual C++.
|
||||||
|
if test "$GCC" != yes; then
|
||||||
|
with_gnu_ld=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
interix*)
|
||||||
|
# we just hope/assume this is gcc and not c89 (= MSVC++)
|
||||||
|
with_gnu_ld=yes
|
||||||
|
;;
|
||||||
|
openbsd*)
|
||||||
|
with_gnu_ld=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ld_shlibs=yes
|
||||||
|
if test "$with_gnu_ld" = yes; then
|
||||||
|
# Set some defaults for GNU ld with shared library support. These
|
||||||
|
# are reset later if shared libraries are not supported. Putting them
|
||||||
|
# here allows them to be overridden if necessary.
|
||||||
|
# Unlike libtool, we use -rpath here, not --rpath, since the documented
|
||||||
|
# option of GNU ld is called -rpath, not --rpath.
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
case "$host_os" in
|
||||||
|
aix[3-9]*)
|
||||||
|
# On AIX/PPC, the GNU linker is very broken
|
||||||
|
if test "$host_cpu" != ia64; then
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
amigaos*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
# Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
|
||||||
|
# that the semantics of dynamic libraries on AmigaOS, at least up
|
||||||
|
# to version 4, is to share data among multiple programs linked
|
||||||
|
# with the same dynamic library. Since this doesn't match the
|
||||||
|
# behavior of shared libraries on other platforms, we cannot use
|
||||||
|
# them.
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
beos*)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
cygwin* | mingw* | pw32* | cegcc*)
|
||||||
|
# hardcode_libdir_flag_spec is actually meaningless, as there is
|
||||||
|
# no search path for DLLs.
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
interix[3-9]*)
|
||||||
|
hardcode_direct=no
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||||
|
;;
|
||||||
|
gnu* | linux* | k*bsd*-gnu)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
|
||||||
|
ld_shlibs=no
|
||||||
|
elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
|
||||||
|
case `$LD -v 2>&1` in
|
||||||
|
*\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if test "$ld_shlibs" = no; then
|
||||||
|
hardcode_libdir_flag_spec=
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
case "$host_os" in
|
||||||
|
aix3*)
|
||||||
|
# Note: this linker hardcodes the directories in LIBPATH if there
|
||||||
|
# are no directories specified by -L.
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
# Neither direct hardcoding nor static linking is supported with a
|
||||||
|
# broken collect2.
|
||||||
|
hardcode_direct=unsupported
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
aix[4-9]*)
|
||||||
|
if test "$host_cpu" = ia64; then
|
||||||
|
# On IA64, the linker does run time linking by default, so we don't
|
||||||
|
# have to do anything special.
|
||||||
|
aix_use_runtimelinking=no
|
||||||
|
else
|
||||||
|
aix_use_runtimelinking=no
|
||||||
|
# Test if we are trying to use run time linking or normal
|
||||||
|
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
|
||||||
|
# need to do runtime linking.
|
||||||
|
case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
|
||||||
|
for ld_flag in $LDFLAGS; do
|
||||||
|
if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
|
||||||
|
aix_use_runtimelinking=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_libdir_separator=':'
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
case $host_os in aix4.[012]|aix4.[012].*)
|
||||||
|
collect2name=`${CC} -print-prog-name=collect2`
|
||||||
|
if test -f "$collect2name" && \
|
||||||
|
strings "$collect2name" | grep resolve_lib_name >/dev/null
|
||||||
|
then
|
||||||
|
# We have reworked collect2
|
||||||
|
:
|
||||||
|
else
|
||||||
|
# We have old collect2
|
||||||
|
hardcode_direct=unsupported
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_libdir_separator=
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
# Begin _LT_AC_SYS_LIBPATH_AIX.
|
||||||
|
echo 'int main () { return 0; }' > conftest.c
|
||||||
|
${CC} ${LDFLAGS} conftest.c -o conftest
|
||||||
|
aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||||
|
}'`
|
||||||
|
if test -z "$aix_libpath"; then
|
||||||
|
aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||||
|
}'`
|
||||||
|
fi
|
||||||
|
if test -z "$aix_libpath"; then
|
||||||
|
aix_libpath="/usr/lib:/lib"
|
||||||
|
fi
|
||||||
|
rm -f conftest.c conftest
|
||||||
|
# End _LT_AC_SYS_LIBPATH_AIX.
|
||||||
|
if test "$aix_use_runtimelinking" = yes; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||||
|
else
|
||||||
|
if test "$host_cpu" = ia64; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
|
||||||
|
else
|
||||||
|
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
amigaos*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
# see comment about different semantics on the GNU ld section
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
bsdi[45]*)
|
||||||
|
;;
|
||||||
|
cygwin* | mingw* | pw32* | cegcc*)
|
||||||
|
# When not using gcc, we currently assume that we are using
|
||||||
|
# Microsoft Visual C++.
|
||||||
|
# hardcode_libdir_flag_spec is actually meaningless, as there is
|
||||||
|
# no search path for DLLs.
|
||||||
|
hardcode_libdir_flag_spec=' '
|
||||||
|
libext=lib
|
||||||
|
;;
|
||||||
|
darwin* | rhapsody*)
|
||||||
|
hardcode_direct=no
|
||||||
|
if test "$GCC" = yes ; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
case $cc_basename in
|
||||||
|
xlc*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
dgux*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
;;
|
||||||
|
freebsd1*)
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
freebsd2.2*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
freebsd2*)
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
freebsd* | dragonfly*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
hpux9*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
hardcode_direct=yes
|
||||||
|
# hardcode_minus_L: Not really in the search PATH,
|
||||||
|
# but as the default location of the library.
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
hpux10*)
|
||||||
|
if test "$with_gnu_ld" = no; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
hardcode_direct=yes
|
||||||
|
# hardcode_minus_L: Not really in the search PATH,
|
||||||
|
# but as the default location of the library.
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
hpux11*)
|
||||||
|
if test "$with_gnu_ld" = no; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
case $host_cpu in
|
||||||
|
hppa*64*|ia64*)
|
||||||
|
hardcode_direct=no
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
hardcode_direct=yes
|
||||||
|
# hardcode_minus_L: Not really in the search PATH,
|
||||||
|
# but as the default location of the library.
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
irix5* | irix6* | nonstopux*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
newsos6)
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
openbsd*)
|
||||||
|
if test -f /usr/libexec/ld.so; then
|
||||||
|
hardcode_direct=yes
|
||||||
|
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||||
|
else
|
||||||
|
case "$host_os" in
|
||||||
|
openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
os2*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
osf3*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
osf4* | osf5*)
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
else
|
||||||
|
# Both cc and cxx compiler support -rpath directly
|
||||||
|
hardcode_libdir_flag_spec='-rpath $libdir'
|
||||||
|
fi
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
sysv4)
|
||||||
|
case $host_vendor in
|
||||||
|
sni)
|
||||||
|
hardcode_direct=yes # is this really true???
|
||||||
|
;;
|
||||||
|
siemens)
|
||||||
|
hardcode_direct=no
|
||||||
|
;;
|
||||||
|
motorola)
|
||||||
|
hardcode_direct=no #Motorola manual says yes, but my tests say they lie
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
sysv4.3*)
|
||||||
|
;;
|
||||||
|
sysv4*MP*)
|
||||||
|
if test -d /usr/nec; then
|
||||||
|
ld_shlibs=yes
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
|
||||||
|
;;
|
||||||
|
sysv5* | sco3.2v5* | sco5v6*)
|
||||||
|
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
|
||||||
|
hardcode_libdir_separator=':'
|
||||||
|
;;
|
||||||
|
uts4*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check dynamic linker characteristics
|
||||||
|
# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER.
|
||||||
|
# Unlike libtool.m4, here we don't care about _all_ names of the library, but
|
||||||
|
# only about the one the linker finds when passed -lNAME. This is the last
|
||||||
|
# element of library_names_spec in libtool.m4, or possibly two of them if the
|
||||||
|
# linker has special search rules.
|
||||||
|
library_names_spec= # the last element of library_names_spec in libtool.m4
|
||||||
|
libname_spec='lib$name'
|
||||||
|
case "$host_os" in
|
||||||
|
aix3*)
|
||||||
|
library_names_spec='$libname.a'
|
||||||
|
;;
|
||||||
|
aix[4-9]*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
amigaos*)
|
||||||
|
library_names_spec='$libname.a'
|
||||||
|
;;
|
||||||
|
beos*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
bsdi[45]*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
cygwin* | mingw* | pw32* | cegcc*)
|
||||||
|
shrext=.dll
|
||||||
|
library_names_spec='$libname.dll.a $libname.lib'
|
||||||
|
;;
|
||||||
|
darwin* | rhapsody*)
|
||||||
|
shrext=.dylib
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
dgux*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
freebsd1*)
|
||||||
|
;;
|
||||||
|
freebsd* | dragonfly*)
|
||||||
|
case "$host_os" in
|
||||||
|
freebsd[123]*)
|
||||||
|
library_names_spec='$libname$shrext$versuffix' ;;
|
||||||
|
*)
|
||||||
|
library_names_spec='$libname$shrext' ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
gnu*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
hpux9* | hpux10* | hpux11*)
|
||||||
|
case $host_cpu in
|
||||||
|
ia64*)
|
||||||
|
shrext=.so
|
||||||
|
;;
|
||||||
|
hppa*64*)
|
||||||
|
shrext=.sl
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
shrext=.sl
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
interix[3-9]*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
irix5* | irix6* | nonstopux*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
case "$host_os" in
|
||||||
|
irix5* | nonstopux*)
|
||||||
|
libsuff= shlibsuff=
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case $LD in
|
||||||
|
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
|
||||||
|
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
|
||||||
|
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
|
||||||
|
*) libsuff= shlibsuff= ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
linux*oldld* | linux*aout* | linux*coff*)
|
||||||
|
;;
|
||||||
|
linux* | k*bsd*-gnu)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
knetbsd*-gnu)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
newsos6)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
nto-qnx*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
openbsd*)
|
||||||
|
library_names_spec='$libname$shrext$versuffix'
|
||||||
|
;;
|
||||||
|
os2*)
|
||||||
|
libname_spec='$name'
|
||||||
|
shrext=.dll
|
||||||
|
library_names_spec='$libname.a'
|
||||||
|
;;
|
||||||
|
osf3* | osf4* | osf5*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
rdos*)
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
library_names_spec='$libname$shrext$versuffix'
|
||||||
|
;;
|
||||||
|
sysv4 | sysv4.3*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
sysv4*MP*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
uts4*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
|
||||||
|
escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
|
||||||
|
escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
|
||||||
|
LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
|
||||||
|
|
||||||
|
# How to pass a linker flag through the compiler.
|
||||||
|
wl="$escaped_wl"
|
||||||
|
|
||||||
|
# Static library suffix (normally "a").
|
||||||
|
libext="$libext"
|
||||||
|
|
||||||
|
# Shared library suffix (normally "so").
|
||||||
|
shlibext="$shlibext"
|
||||||
|
|
||||||
|
# Format of library name prefix.
|
||||||
|
libname_spec="$escaped_libname_spec"
|
||||||
|
|
||||||
|
# Library names that the linker finds when passed -lNAME.
|
||||||
|
library_names_spec="$escaped_library_names_spec"
|
||||||
|
|
||||||
|
# Flag to hardcode \$libdir into a binary during linking.
|
||||||
|
# This must work even if \$libdir does not exist.
|
||||||
|
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
|
||||||
|
|
||||||
|
# Whether we need a single -rpath flag with a separated argument.
|
||||||
|
hardcode_libdir_separator="$hardcode_libdir_separator"
|
||||||
|
|
||||||
|
# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
|
||||||
|
# resulting binary.
|
||||||
|
hardcode_direct="$hardcode_direct"
|
||||||
|
|
||||||
|
# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
|
||||||
|
# resulting binary.
|
||||||
|
hardcode_minus_L="$hardcode_minus_L"
|
||||||
|
|
||||||
|
EOF
|
221
configure.ac
Normal file
221
configure.ac
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
# This file is part of GNUnet.
|
||||||
|
# (C) 2001-2019 Christian Grothoff (and other contributing authors)
|
||||||
|
#
|
||||||
|
# GNUnet is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published
|
||||||
|
# by the Free Software Foundation; either version 2, or (at your
|
||||||
|
# option) any later version.
|
||||||
|
#
|
||||||
|
# GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with GNUnet; see the file COPYING. If not, write to the
|
||||||
|
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
# Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
#
|
||||||
|
AC_PREREQ(2.61)
|
||||||
|
AC_INIT([gnunet-secushare],[0.0.0],[bug-gnunet@gnu.org])
|
||||||
|
AM_INIT_AUTOMAKE([gnunet-secushare], [0.0.0])
|
||||||
|
AM_CONFIG_HEADER(gnunet_secushare_config.h)
|
||||||
|
|
||||||
|
AH_TOP([#define _GNU_SOURCE 1])
|
||||||
|
|
||||||
|
AC_ISC_POSIX
|
||||||
|
AC_PROG_AWK
|
||||||
|
AC_PROG_CC
|
||||||
|
|
||||||
|
AC_PROG_MKDIR_P
|
||||||
|
AC_PROG_CPP
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_LN_S
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
AC_LIBTOOL_WIN32_DLL
|
||||||
|
AC_PROG_CC
|
||||||
|
AM_PROG_CC_STDC
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
|
||||||
|
# dynamic libraries/plugins
|
||||||
|
AC_DISABLE_STATIC
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
|
AC_SYS_LARGEFILE
|
||||||
|
AC_FUNC_FSEEKO
|
||||||
|
|
||||||
|
CFLAGS="-Wall $CFLAGS"
|
||||||
|
# use '-fno-strict-aliasing', but only if the compiler can take it
|
||||||
|
if gcc -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1;
|
||||||
|
then
|
||||||
|
CFLAGS="-fno-strict-aliasing $CFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Check system type
|
||||||
|
case "$host_os" in
|
||||||
|
*darwin* | *rhapsody* | *macosx*)
|
||||||
|
AC_DEFINE_UNQUOTED(OSX,1,[This is an OS X system])
|
||||||
|
CFLAGS="-no-cpp-precomp $CFLAGS"
|
||||||
|
LDFLAGS="-flat_namespace -undefined suppress $LDFLAGS"
|
||||||
|
;;
|
||||||
|
linux*)
|
||||||
|
AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux system])
|
||||||
|
;;
|
||||||
|
freebsd*)
|
||||||
|
AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
|
||||||
|
AC_DEFINE_UNQUOTED(FREEBSD,1,[This is a FreeBSD system])
|
||||||
|
;;
|
||||||
|
openbsd*)
|
||||||
|
AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
|
||||||
|
AC_DEFINE_UNQUOTED(OPENBSD,1,[This is an OpenBSD system])
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
|
||||||
|
AC_DEFINE_UNQUOTED(NETBSD,1,[This is a NetBSD system])
|
||||||
|
;;
|
||||||
|
*solaris*)
|
||||||
|
AC_DEFINE_UNQUOTED(SOLARIS,1,[This is a Solaris system])
|
||||||
|
AC_DEFINE_UNQUOTED(_REENTRANT,1,[Need with solaris or errno doesnt work])
|
||||||
|
build_target="solaris"
|
||||||
|
;;
|
||||||
|
*arm-linux*)
|
||||||
|
AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux system])
|
||||||
|
;;
|
||||||
|
*cygwin*)
|
||||||
|
AC_DEFINE_UNQUOTED(CYGWIN,1,[This is a Cygwin system])
|
||||||
|
AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system])
|
||||||
|
AC_CHECK_LIB(intl, gettext)
|
||||||
|
LDFLAGS="$LDFLAGS -no-undefined"
|
||||||
|
build_target="cygwin"
|
||||||
|
;;
|
||||||
|
*mingw*)
|
||||||
|
AC_DEFINE_UNQUOTED(MINGW,1,[This is a MinGW system])
|
||||||
|
AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system])
|
||||||
|
AC_DEFINE_UNQUOTED(_WIN32,1,[This is a Windows system])
|
||||||
|
AC_CHECK_LIB(intl, gettext)
|
||||||
|
LDFLAGS="$LDFLAGS -no-undefined -Wl,--export-all-symbols -lws2_32"
|
||||||
|
CFLAGS="-mms-bitfields $CFLAGS"
|
||||||
|
build_target="mingw"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_RESULT(Unrecognised OS $host_os)
|
||||||
|
AC_DEFINE_UNQUOTED(OTHEROS,1,[Some strange OS])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
AM_CONDITIONAL(MINGW, test "$build_target" = "mingw")
|
||||||
|
|
||||||
|
# check for gettext
|
||||||
|
AM_GNU_GETTEXT_VERSION([0.18.1])
|
||||||
|
AM_GNU_GETTEXT([external])
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([errno.h stdio.h unistd.h locale.h sys/stat.h sys/types.h langinfo.h libintl.h unistd.h stddef.h argz.h sys/socket.h netinet/in.h stdarg.h])
|
||||||
|
|
||||||
|
# test for GNUnet core
|
||||||
|
gnunet=0
|
||||||
|
lookin=${prefix}
|
||||||
|
backup_LDFLAGS="$LDFLAGS"
|
||||||
|
backup_CPPFLAGS="$CPPFLAGS"
|
||||||
|
GNUNET_LDFLAGS=""
|
||||||
|
GNUNET_CPPFLAGS=""
|
||||||
|
AC_MSG_CHECKING(for GNUnet core)
|
||||||
|
AC_ARG_WITH(gnunet,
|
||||||
|
[ --with-gnunet=PFX Base of GNUnet installation],
|
||||||
|
[AC_MSG_RESULT([$with_gnunet])
|
||||||
|
case $with_gnunet in
|
||||||
|
no)
|
||||||
|
lookin=""
|
||||||
|
;;
|
||||||
|
yes)
|
||||||
|
lookin="${prefix}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
lookin="$with_gnunet"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
],
|
||||||
|
[
|
||||||
|
AC_MSG_RESULT([--with-gnunet not specified])
|
||||||
|
PKG_CHECK_MODULES([GNUNET], [gnunetutil >= 0.9.0], gnunet=1)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "x$gnunet" == "x0" -a ! "x$lookin" == "x"
|
||||||
|
then
|
||||||
|
AC_MSG_CHECKING(for GNUnet util library in $lookin)
|
||||||
|
GNUNET_LDFLAGS="-L${lookin}/lib"
|
||||||
|
GNUNET_CPPFLAGS="-I${lookin}/include"
|
||||||
|
LDFLAGS="$GNUNET_LDFLAGS $backup_LDFLAGS"
|
||||||
|
CPPFLAGS="$GNUNET_CPPFLAGS $backup_CPPFLAGS"
|
||||||
|
AC_CHECK_HEADERS([gnunet/gnunet_util_lib.h],
|
||||||
|
AC_CHECK_LIB([gnunetutil], [GNUNET_xfree_],
|
||||||
|
[
|
||||||
|
gnunet=1
|
||||||
|
EXT_LIB_PATH="-L${lookin}/lib $EXT_LIB_PATH"
|
||||||
|
]
|
||||||
|
),,[#include <gnunet/platform.h>]
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$gnunet" == "x0"
|
||||||
|
then
|
||||||
|
AC_MSG_ERROR([gnunet-ext requires GNUnet])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Linker hardening options
|
||||||
|
# Currently these options are ELF specific - you can't use this with MacOSX
|
||||||
|
AC_ARG_ENABLE(linker-hardening,
|
||||||
|
AS_HELP_STRING(--enable-linker-hardening, enable linker security fixups),
|
||||||
|
[if test x$enableval = xyes; then
|
||||||
|
LDFLAGS="$LDFLAGS -z relro -z now"
|
||||||
|
fi])
|
||||||
|
|
||||||
|
|
||||||
|
extra_logging=GNUNET_NO
|
||||||
|
AC_ARG_ENABLE([logging],
|
||||||
|
AS_HELP_STRING([--enable-logging@<:@=value@:>@],[Enable logging calls. Possible values: yes,no,verbose,veryverbose ('yes' is the default)]),
|
||||||
|
[AS_IF([test "x$enableval" = "xyes"], [],
|
||||||
|
[test "x$enableval" = "xno"], [AC_DEFINE([GNUNET_CULL_LOGGING],[],[Define to cull all logging calls])],
|
||||||
|
[test "x$enableval" = "xverbose"], [extra_logging=GNUNET_YES]
|
||||||
|
[test "x$enableval" = "xveryverbose"], [extra_logging=\(GNUNET_YES+1\)])
|
||||||
|
], [])
|
||||||
|
AC_DEFINE_UNQUOTED([GNUNET_EXTRA_LOGGING],[$extra_logging],[1 if extra logging is enabled, 2 for very verbose extra logging, 0 otherwise])
|
||||||
|
|
||||||
|
|
||||||
|
AC_SUBST(GNUNET_CPPFLAGS)
|
||||||
|
AC_SUBST(GNUNET_LDFLAGS)
|
||||||
|
LDFLAGS="$backup_LDFLAGS"
|
||||||
|
CPPFLAGS="$backup_CPPFLAGS"
|
||||||
|
|
||||||
|
AC_DEFINE_DIR([PACKAGE_DATA], [datarootdir], [The directory for installing read-only architecture-independent data])
|
||||||
|
|
||||||
|
# Set PACKAGE_SOURCE_DIR in gnunet_ext_config.h.
|
||||||
|
packagesrcdir=`cd $srcdir && pwd`
|
||||||
|
AC_DEFINE_UNQUOTED(PACKAGE_SOURCE_DIR, "${packagesrcdir}", [source dir])
|
||||||
|
|
||||||
|
AC_OUTPUT([ po/Makefile.in
|
||||||
|
Makefile
|
||||||
|
pkgconfig/Makefile
|
||||||
|
src/Makefile
|
||||||
|
src/include/Makefile
|
||||||
|
src/multicast/Makefile
|
||||||
|
src/multicast/multicast.conf
|
||||||
|
src/psycutil/Makefile
|
||||||
|
src/psyc/Makefile
|
||||||
|
src/psyc/psyc.conf
|
||||||
|
src/psycstore/Makefile
|
||||||
|
src/psycstore/psycstore.conf
|
||||||
|
src/social/Makefile
|
||||||
|
src/social/social.conf
|
||||||
|
pkgconfig/gnunetmulticast.pc
|
||||||
|
pkgconfig/gnunetpsyc.pc
|
||||||
|
pkgconfig/gnunetpsycstore.pc
|
||||||
|
pkgconfig/gnunetsocial.pc
|
||||||
|
])
|
35
m4/ac_define_dir.m4
Normal file
35
m4/ac_define_dir.m4
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
dnl @synopsis AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION])
|
||||||
|
dnl
|
||||||
|
dnl This macro _AC_DEFINEs VARNAME to the expansion of the DIR
|
||||||
|
dnl variable, taking care of fixing up ${prefix} and such.
|
||||||
|
dnl
|
||||||
|
dnl VARNAME is offered as both a C preprocessor symbol, and an output
|
||||||
|
dnl variable.
|
||||||
|
dnl
|
||||||
|
dnl Note that the 3 argument form is only supported with autoconf 2.13
|
||||||
|
dnl and later (i.e. only where _AC_DEFINE supports 3 arguments).
|
||||||
|
dnl
|
||||||
|
dnl Examples:
|
||||||
|
dnl
|
||||||
|
dnl AC_DEFINE_DIR(DATADIR, datadir)
|
||||||
|
dnl AC_DEFINE_DIR(PROG_PATH, bindir, [Location of installed binaries])
|
||||||
|
dnl
|
||||||
|
dnl @category Misc
|
||||||
|
dnl @author Stepan Kasal <kasal@ucw.cz>
|
||||||
|
dnl @author Andreas Schwab <schwab@suse.de>
|
||||||
|
dnl @author Guido Draheim <guidod@gmx.de>
|
||||||
|
dnl @author Alexandre Oliva
|
||||||
|
dnl @version 2005-01-17
|
||||||
|
dnl @license AllPermissive
|
||||||
|
|
||||||
|
AC_DEFUN([AC_DEFINE_DIR], [
|
||||||
|
prefix_NONE=
|
||||||
|
exec_prefix_NONE=
|
||||||
|
test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
|
||||||
|
test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
|
||||||
|
eval ac_define_dir="\"[$]$2\""
|
||||||
|
AC_SUBST($1, "$ac_define_dir")
|
||||||
|
AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
|
||||||
|
test "$prefix_NONE" && prefix=NONE
|
||||||
|
test "$exec_prefix_NONE" && exec_prefix=NONE
|
||||||
|
])
|
383
m4/gettext.m4
Normal file
383
m4/gettext.m4
Normal file
@ -0,0 +1,383 @@
|
|||||||
|
# gettext.m4 serial 63 (gettext-0.18)
|
||||||
|
dnl Copyright (C) 1995-2010 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
dnl
|
||||||
|
dnl This file can can be used in projects which are not available under
|
||||||
|
dnl the GNU General Public License or the GNU Library General Public
|
||||||
|
dnl License but which still want to provide support for the GNU gettext
|
||||||
|
dnl functionality.
|
||||||
|
dnl Please note that the actual code of the GNU gettext library is covered
|
||||||
|
dnl by the GNU Library General Public License, and the rest of the GNU
|
||||||
|
dnl gettext package package is covered by the GNU General Public License.
|
||||||
|
dnl They are *not* in the public domain.
|
||||||
|
|
||||||
|
dnl Authors:
|
||||||
|
dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
|
||||||
|
dnl Bruno Haible <haible@clisp.cons.org>, 2000-2006, 2008-2010.
|
||||||
|
|
||||||
|
dnl Macro to add for using GNU gettext.
|
||||||
|
|
||||||
|
dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]).
|
||||||
|
dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The
|
||||||
|
dnl default (if it is not specified or empty) is 'no-libtool'.
|
||||||
|
dnl INTLSYMBOL should be 'external' for packages with no intl directory,
|
||||||
|
dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory.
|
||||||
|
dnl If INTLSYMBOL is 'use-libtool', then a libtool library
|
||||||
|
dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static,
|
||||||
|
dnl depending on --{enable,disable}-{shared,static} and on the presence of
|
||||||
|
dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library
|
||||||
|
dnl $(top_builddir)/intl/libintl.a will be created.
|
||||||
|
dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext
|
||||||
|
dnl implementations (in libc or libintl) without the ngettext() function
|
||||||
|
dnl will be ignored. If NEEDSYMBOL is specified and is
|
||||||
|
dnl 'need-formatstring-macros', then GNU gettext implementations that don't
|
||||||
|
dnl support the ISO C 99 <inttypes.h> formatstring macros will be ignored.
|
||||||
|
dnl INTLDIR is used to find the intl libraries. If empty,
|
||||||
|
dnl the value `$(top_builddir)/intl/' is used.
|
||||||
|
dnl
|
||||||
|
dnl The result of the configuration is one of three cases:
|
||||||
|
dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled
|
||||||
|
dnl and used.
|
||||||
|
dnl Catalog format: GNU --> install in $(datadir)
|
||||||
|
dnl Catalog extension: .mo after installation, .gmo in source tree
|
||||||
|
dnl 2) GNU gettext has been found in the system's C library.
|
||||||
|
dnl Catalog format: GNU --> install in $(datadir)
|
||||||
|
dnl Catalog extension: .mo after installation, .gmo in source tree
|
||||||
|
dnl 3) No internationalization, always use English msgid.
|
||||||
|
dnl Catalog format: none
|
||||||
|
dnl Catalog extension: none
|
||||||
|
dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur.
|
||||||
|
dnl The use of .gmo is historical (it was needed to avoid overwriting the
|
||||||
|
dnl GNU format catalogs when building on a platform with an X/Open gettext),
|
||||||
|
dnl but we keep it in order not to force irrelevant filename changes on the
|
||||||
|
dnl maintainers.
|
||||||
|
dnl
|
||||||
|
AC_DEFUN([AM_GNU_GETTEXT],
|
||||||
|
[
|
||||||
|
dnl Argument checking.
|
||||||
|
ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], ,
|
||||||
|
[errprint([ERROR: invalid first argument to AM_GNU_GETTEXT
|
||||||
|
])])])])])
|
||||||
|
ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old],
|
||||||
|
[AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])])
|
||||||
|
ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], ,
|
||||||
|
[errprint([ERROR: invalid second argument to AM_GNU_GETTEXT
|
||||||
|
])])])])
|
||||||
|
define([gt_included_intl],
|
||||||
|
ifelse([$1], [external],
|
||||||
|
ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]),
|
||||||
|
[yes]))
|
||||||
|
define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], []))
|
||||||
|
gt_NEEDS_INIT
|
||||||
|
AM_GNU_GETTEXT_NEED([$2])
|
||||||
|
|
||||||
|
AC_REQUIRE([AM_PO_SUBDIRS])dnl
|
||||||
|
ifelse(gt_included_intl, yes, [
|
||||||
|
AC_REQUIRE([AM_INTL_SUBDIR])dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
|
||||||
|
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||||
|
AC_REQUIRE([AC_LIB_RPATH])
|
||||||
|
|
||||||
|
dnl Sometimes libintl requires libiconv, so first search for libiconv.
|
||||||
|
dnl Ideally we would do this search only after the
|
||||||
|
dnl if test "$USE_NLS" = "yes"; then
|
||||||
|
dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then
|
||||||
|
dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT
|
||||||
|
dnl the configure script would need to contain the same shell code
|
||||||
|
dnl again, outside any 'if'. There are two solutions:
|
||||||
|
dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'.
|
||||||
|
dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE.
|
||||||
|
dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not
|
||||||
|
dnl documented, we avoid it.
|
||||||
|
ifelse(gt_included_intl, yes, , [
|
||||||
|
AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation.
|
||||||
|
gt_INTL_MACOSX
|
||||||
|
|
||||||
|
dnl Set USE_NLS.
|
||||||
|
AC_REQUIRE([AM_NLS])
|
||||||
|
|
||||||
|
ifelse(gt_included_intl, yes, [
|
||||||
|
BUILD_INCLUDED_LIBINTL=no
|
||||||
|
USE_INCLUDED_LIBINTL=no
|
||||||
|
])
|
||||||
|
LIBINTL=
|
||||||
|
LTLIBINTL=
|
||||||
|
POSUB=
|
||||||
|
|
||||||
|
dnl Add a version number to the cache macros.
|
||||||
|
case " $gt_needs " in
|
||||||
|
*" need-formatstring-macros "*) gt_api_version=3 ;;
|
||||||
|
*" need-ngettext "*) gt_api_version=2 ;;
|
||||||
|
*) gt_api_version=1 ;;
|
||||||
|
esac
|
||||||
|
gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc"
|
||||||
|
gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl"
|
||||||
|
|
||||||
|
dnl If we use NLS figure out what method
|
||||||
|
if test "$USE_NLS" = "yes"; then
|
||||||
|
gt_use_preinstalled_gnugettext=no
|
||||||
|
ifelse(gt_included_intl, yes, [
|
||||||
|
AC_MSG_CHECKING([whether included gettext is requested])
|
||||||
|
AC_ARG_WITH([included-gettext],
|
||||||
|
[ --with-included-gettext use the GNU gettext library included here],
|
||||||
|
nls_cv_force_use_gnu_gettext=$withval,
|
||||||
|
nls_cv_force_use_gnu_gettext=no)
|
||||||
|
AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext])
|
||||||
|
|
||||||
|
nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
|
||||||
|
if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
|
||||||
|
])
|
||||||
|
dnl User does not insist on using GNU NLS library. Figure out what
|
||||||
|
dnl to use. If GNU gettext is available we use this. Else we have
|
||||||
|
dnl to fall back to GNU NLS library.
|
||||||
|
|
||||||
|
if test $gt_api_version -ge 3; then
|
||||||
|
gt_revision_test_code='
|
||||||
|
#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
|
||||||
|
#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1)
|
||||||
|
#endif
|
||||||
|
changequote(,)dnl
|
||||||
|
typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1];
|
||||||
|
changequote([,])dnl
|
||||||
|
'
|
||||||
|
else
|
||||||
|
gt_revision_test_code=
|
||||||
|
fi
|
||||||
|
if test $gt_api_version -ge 2; then
|
||||||
|
gt_expression_test_code=' + * ngettext ("", "", 0)'
|
||||||
|
else
|
||||||
|
gt_expression_test_code=
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc],
|
||||||
|
[AC_TRY_LINK([#include <libintl.h>
|
||||||
|
$gt_revision_test_code
|
||||||
|
extern int _nl_msg_cat_cntr;
|
||||||
|
extern int *_nl_domain_bindings;],
|
||||||
|
[bindtextdomain ("", "");
|
||||||
|
return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings],
|
||||||
|
[eval "$gt_func_gnugettext_libc=yes"],
|
||||||
|
[eval "$gt_func_gnugettext_libc=no"])])
|
||||||
|
|
||||||
|
if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then
|
||||||
|
dnl Sometimes libintl requires libiconv, so first search for libiconv.
|
||||||
|
ifelse(gt_included_intl, yes, , [
|
||||||
|
AM_ICONV_LINK
|
||||||
|
])
|
||||||
|
dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL
|
||||||
|
dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv])
|
||||||
|
dnl because that would add "-liconv" to LIBINTL and LTLIBINTL
|
||||||
|
dnl even if libiconv doesn't exist.
|
||||||
|
AC_LIB_LINKFLAGS_BODY([intl])
|
||||||
|
AC_CACHE_CHECK([for GNU gettext in libintl],
|
||||||
|
[$gt_func_gnugettext_libintl],
|
||||||
|
[gt_save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS $INCINTL"
|
||||||
|
gt_save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $LIBINTL"
|
||||||
|
dnl Now see whether libintl exists and does not depend on libiconv.
|
||||||
|
AC_TRY_LINK([#include <libintl.h>
|
||||||
|
$gt_revision_test_code
|
||||||
|
extern int _nl_msg_cat_cntr;
|
||||||
|
extern
|
||||||
|
#ifdef __cplusplus
|
||||||
|
"C"
|
||||||
|
#endif
|
||||||
|
const char *_nl_expand_alias (const char *);],
|
||||||
|
[bindtextdomain ("", "");
|
||||||
|
return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")],
|
||||||
|
[eval "$gt_func_gnugettext_libintl=yes"],
|
||||||
|
[eval "$gt_func_gnugettext_libintl=no"])
|
||||||
|
dnl Now see whether libintl exists and depends on libiconv.
|
||||||
|
if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then
|
||||||
|
LIBS="$LIBS $LIBICONV"
|
||||||
|
AC_TRY_LINK([#include <libintl.h>
|
||||||
|
$gt_revision_test_code
|
||||||
|
extern int _nl_msg_cat_cntr;
|
||||||
|
extern
|
||||||
|
#ifdef __cplusplus
|
||||||
|
"C"
|
||||||
|
#endif
|
||||||
|
const char *_nl_expand_alias (const char *);],
|
||||||
|
[bindtextdomain ("", "");
|
||||||
|
return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")],
|
||||||
|
[LIBINTL="$LIBINTL $LIBICONV"
|
||||||
|
LTLIBINTL="$LTLIBINTL $LTLIBICONV"
|
||||||
|
eval "$gt_func_gnugettext_libintl=yes"
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
CPPFLAGS="$gt_save_CPPFLAGS"
|
||||||
|
LIBS="$gt_save_LIBS"])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl If an already present or preinstalled GNU gettext() is found,
|
||||||
|
dnl use it. But if this macro is used in GNU gettext, and GNU
|
||||||
|
dnl gettext is already preinstalled in libintl, we update this
|
||||||
|
dnl libintl. (Cf. the install rule in intl/Makefile.in.)
|
||||||
|
if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \
|
||||||
|
|| { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \
|
||||||
|
&& test "$PACKAGE" != gettext-runtime \
|
||||||
|
&& test "$PACKAGE" != gettext-tools; }; then
|
||||||
|
gt_use_preinstalled_gnugettext=yes
|
||||||
|
else
|
||||||
|
dnl Reset the values set by searching for libintl.
|
||||||
|
LIBINTL=
|
||||||
|
LTLIBINTL=
|
||||||
|
INCINTL=
|
||||||
|
fi
|
||||||
|
|
||||||
|
ifelse(gt_included_intl, yes, [
|
||||||
|
if test "$gt_use_preinstalled_gnugettext" != "yes"; then
|
||||||
|
dnl GNU gettext is not found in the C library.
|
||||||
|
dnl Fall back on included GNU gettext library.
|
||||||
|
nls_cv_use_gnu_gettext=yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||||
|
dnl Mark actions used to generate GNU NLS library.
|
||||||
|
BUILD_INCLUDED_LIBINTL=yes
|
||||||
|
USE_INCLUDED_LIBINTL=yes
|
||||||
|
LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD"
|
||||||
|
LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD"
|
||||||
|
LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'`
|
||||||
|
fi
|
||||||
|
|
||||||
|
CATOBJEXT=
|
||||||
|
if test "$gt_use_preinstalled_gnugettext" = "yes" \
|
||||||
|
|| test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||||
|
dnl Mark actions to use GNU gettext tools.
|
||||||
|
CATOBJEXT=.gmo
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
if test -n "$INTL_MACOSX_LIBS"; then
|
||||||
|
if test "$gt_use_preinstalled_gnugettext" = "yes" \
|
||||||
|
|| test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||||
|
dnl Some extra flags are needed during linking.
|
||||||
|
LIBINTL="$LIBINTL $INTL_MACOSX_LIBS"
|
||||||
|
LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$gt_use_preinstalled_gnugettext" = "yes" \
|
||||||
|
|| test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||||
|
AC_DEFINE([ENABLE_NLS], [1],
|
||||||
|
[Define to 1 if translation of program messages to the user's native language
|
||||||
|
is requested.])
|
||||||
|
else
|
||||||
|
USE_NLS=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to use NLS])
|
||||||
|
AC_MSG_RESULT([$USE_NLS])
|
||||||
|
if test "$USE_NLS" = "yes"; then
|
||||||
|
AC_MSG_CHECKING([where the gettext function comes from])
|
||||||
|
if test "$gt_use_preinstalled_gnugettext" = "yes"; then
|
||||||
|
if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then
|
||||||
|
gt_source="external libintl"
|
||||||
|
else
|
||||||
|
gt_source="libc"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
gt_source="included intl directory"
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT([$gt_source])
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$USE_NLS" = "yes"; then
|
||||||
|
|
||||||
|
if test "$gt_use_preinstalled_gnugettext" = "yes"; then
|
||||||
|
if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then
|
||||||
|
AC_MSG_CHECKING([how to link with libintl])
|
||||||
|
AC_MSG_RESULT([$LIBINTL])
|
||||||
|
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl For backward compatibility. Some packages may be using this.
|
||||||
|
AC_DEFINE([HAVE_GETTEXT], [1],
|
||||||
|
[Define if the GNU gettext() function is already present or preinstalled.])
|
||||||
|
AC_DEFINE([HAVE_DCGETTEXT], [1],
|
||||||
|
[Define if the GNU dcgettext() function is already present or preinstalled.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl We need to process the po/ directory.
|
||||||
|
POSUB=po
|
||||||
|
fi
|
||||||
|
|
||||||
|
ifelse(gt_included_intl, yes, [
|
||||||
|
dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL
|
||||||
|
dnl to 'yes' because some of the testsuite requires it.
|
||||||
|
if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then
|
||||||
|
BUILD_INCLUDED_LIBINTL=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Make all variables we use known to autoconf.
|
||||||
|
AC_SUBST([BUILD_INCLUDED_LIBINTL])
|
||||||
|
AC_SUBST([USE_INCLUDED_LIBINTL])
|
||||||
|
AC_SUBST([CATOBJEXT])
|
||||||
|
|
||||||
|
dnl For backward compatibility. Some configure.ins may be using this.
|
||||||
|
nls_cv_header_intl=
|
||||||
|
nls_cv_header_libgt=
|
||||||
|
|
||||||
|
dnl For backward compatibility. Some Makefiles may be using this.
|
||||||
|
DATADIRNAME=share
|
||||||
|
AC_SUBST([DATADIRNAME])
|
||||||
|
|
||||||
|
dnl For backward compatibility. Some Makefiles may be using this.
|
||||||
|
INSTOBJEXT=.mo
|
||||||
|
AC_SUBST([INSTOBJEXT])
|
||||||
|
|
||||||
|
dnl For backward compatibility. Some Makefiles may be using this.
|
||||||
|
GENCAT=gencat
|
||||||
|
AC_SUBST([GENCAT])
|
||||||
|
|
||||||
|
dnl For backward compatibility. Some Makefiles may be using this.
|
||||||
|
INTLOBJS=
|
||||||
|
if test "$USE_INCLUDED_LIBINTL" = yes; then
|
||||||
|
INTLOBJS="\$(GETTOBJS)"
|
||||||
|
fi
|
||||||
|
AC_SUBST([INTLOBJS])
|
||||||
|
|
||||||
|
dnl Enable libtool support if the surrounding package wishes it.
|
||||||
|
INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix
|
||||||
|
AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl For backward compatibility. Some Makefiles may be using this.
|
||||||
|
INTLLIBS="$LIBINTL"
|
||||||
|
AC_SUBST([INTLLIBS])
|
||||||
|
|
||||||
|
dnl Make all documented variables known to autoconf.
|
||||||
|
AC_SUBST([LIBINTL])
|
||||||
|
AC_SUBST([LTLIBINTL])
|
||||||
|
AC_SUBST([POSUB])
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized.
|
||||||
|
m4_define([gt_NEEDS_INIT],
|
||||||
|
[
|
||||||
|
m4_divert_text([DEFAULTS], [gt_needs=])
|
||||||
|
m4_define([gt_NEEDS_INIT], [])
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL])
|
||||||
|
AC_DEFUN([AM_GNU_GETTEXT_NEED],
|
||||||
|
[
|
||||||
|
m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"])
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version])
|
||||||
|
AC_DEFUN([AM_GNU_GETTEXT_VERSION], [])
|
214
m4/iconv.m4
Normal file
214
m4/iconv.m4
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
# iconv.m4 serial 11 (gettext-0.18.1)
|
||||||
|
dnl Copyright (C) 2000-2002, 2007-2010 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
dnl From Bruno Haible.
|
||||||
|
|
||||||
|
AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
|
||||||
|
[
|
||||||
|
dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
|
||||||
|
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||||
|
AC_REQUIRE([AC_LIB_RPATH])
|
||||||
|
|
||||||
|
dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
|
||||||
|
dnl accordingly.
|
||||||
|
AC_LIB_LINKFLAGS_BODY([iconv])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([AM_ICONV_LINK],
|
||||||
|
[
|
||||||
|
dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
|
||||||
|
dnl those with the standalone portable GNU libiconv installed).
|
||||||
|
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
|
||||||
|
|
||||||
|
dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
|
||||||
|
dnl accordingly.
|
||||||
|
AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
|
||||||
|
|
||||||
|
dnl Add $INCICONV to CPPFLAGS before performing the following checks,
|
||||||
|
dnl because if the user has installed libiconv and not disabled its use
|
||||||
|
dnl via --without-libiconv-prefix, he wants to use it. The first
|
||||||
|
dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed.
|
||||||
|
am_save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [
|
||||||
|
am_cv_func_iconv="no, consider installing GNU libiconv"
|
||||||
|
am_cv_lib_iconv=no
|
||||||
|
AC_TRY_LINK([#include <stdlib.h>
|
||||||
|
#include <iconv.h>],
|
||||||
|
[iconv_t cd = iconv_open("","");
|
||||||
|
iconv(cd,NULL,NULL,NULL,NULL);
|
||||||
|
iconv_close(cd);],
|
||||||
|
[am_cv_func_iconv=yes])
|
||||||
|
if test "$am_cv_func_iconv" != yes; then
|
||||||
|
am_save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $LIBICONV"
|
||||||
|
AC_TRY_LINK([#include <stdlib.h>
|
||||||
|
#include <iconv.h>],
|
||||||
|
[iconv_t cd = iconv_open("","");
|
||||||
|
iconv(cd,NULL,NULL,NULL,NULL);
|
||||||
|
iconv_close(cd);],
|
||||||
|
[am_cv_lib_iconv=yes]
|
||||||
|
[am_cv_func_iconv=yes])
|
||||||
|
LIBS="$am_save_LIBS"
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
if test "$am_cv_func_iconv" = yes; then
|
||||||
|
AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [
|
||||||
|
dnl This tests against bugs in AIX 5.1, HP-UX 11.11, Solaris 10.
|
||||||
|
am_save_LIBS="$LIBS"
|
||||||
|
if test $am_cv_lib_iconv = yes; then
|
||||||
|
LIBS="$LIBS $LIBICONV"
|
||||||
|
fi
|
||||||
|
AC_TRY_RUN([
|
||||||
|
#include <iconv.h>
|
||||||
|
#include <string.h>
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
/* Test against AIX 5.1 bug: Failures are not distinguishable from successful
|
||||||
|
returns. */
|
||||||
|
{
|
||||||
|
iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
|
||||||
|
if (cd_utf8_to_88591 != (iconv_t)(-1))
|
||||||
|
{
|
||||||
|
static const char input[] = "\342\202\254"; /* EURO SIGN */
|
||||||
|
char buf[10];
|
||||||
|
const char *inptr = input;
|
||||||
|
size_t inbytesleft = strlen (input);
|
||||||
|
char *outptr = buf;
|
||||||
|
size_t outbytesleft = sizeof (buf);
|
||||||
|
size_t res = iconv (cd_utf8_to_88591,
|
||||||
|
(char **) &inptr, &inbytesleft,
|
||||||
|
&outptr, &outbytesleft);
|
||||||
|
if (res == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Test against Solaris 10 bug: Failures are not distinguishable from
|
||||||
|
successful returns. */
|
||||||
|
{
|
||||||
|
iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
|
||||||
|
if (cd_ascii_to_88591 != (iconv_t)(-1))
|
||||||
|
{
|
||||||
|
static const char input[] = "\263";
|
||||||
|
char buf[10];
|
||||||
|
const char *inptr = input;
|
||||||
|
size_t inbytesleft = strlen (input);
|
||||||
|
char *outptr = buf;
|
||||||
|
size_t outbytesleft = sizeof (buf);
|
||||||
|
size_t res = iconv (cd_ascii_to_88591,
|
||||||
|
(char **) &inptr, &inbytesleft,
|
||||||
|
&outptr, &outbytesleft);
|
||||||
|
if (res == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 0 /* This bug could be worked around by the caller. */
|
||||||
|
/* Test against HP-UX 11.11 bug: Positive return value instead of 0. */
|
||||||
|
{
|
||||||
|
iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
|
||||||
|
if (cd_88591_to_utf8 != (iconv_t)(-1))
|
||||||
|
{
|
||||||
|
static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
|
||||||
|
char buf[50];
|
||||||
|
const char *inptr = input;
|
||||||
|
size_t inbytesleft = strlen (input);
|
||||||
|
char *outptr = buf;
|
||||||
|
size_t outbytesleft = sizeof (buf);
|
||||||
|
size_t res = iconv (cd_88591_to_utf8,
|
||||||
|
(char **) &inptr, &inbytesleft,
|
||||||
|
&outptr, &outbytesleft);
|
||||||
|
if ((int)res > 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
|
||||||
|
provided. */
|
||||||
|
if (/* Try standardized names. */
|
||||||
|
iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
|
||||||
|
/* Try IRIX, OSF/1 names. */
|
||||||
|
&& iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
|
||||||
|
/* Try AIX names. */
|
||||||
|
&& iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
|
||||||
|
/* Try HP-UX names. */
|
||||||
|
&& iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no],
|
||||||
|
[case "$host_os" in
|
||||||
|
aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
|
||||||
|
*) am_cv_func_iconv_works="guessing yes" ;;
|
||||||
|
esac])
|
||||||
|
LIBS="$am_save_LIBS"
|
||||||
|
])
|
||||||
|
case "$am_cv_func_iconv_works" in
|
||||||
|
*no) am_func_iconv=no am_cv_lib_iconv=no ;;
|
||||||
|
*) am_func_iconv=yes ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
am_func_iconv=no am_cv_lib_iconv=no
|
||||||
|
fi
|
||||||
|
if test "$am_func_iconv" = yes; then
|
||||||
|
AC_DEFINE([HAVE_ICONV], [1],
|
||||||
|
[Define if you have the iconv() function and it works.])
|
||||||
|
fi
|
||||||
|
if test "$am_cv_lib_iconv" = yes; then
|
||||||
|
AC_MSG_CHECKING([how to link with libiconv])
|
||||||
|
AC_MSG_RESULT([$LIBICONV])
|
||||||
|
else
|
||||||
|
dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
|
||||||
|
dnl either.
|
||||||
|
CPPFLAGS="$am_save_CPPFLAGS"
|
||||||
|
LIBICONV=
|
||||||
|
LTLIBICONV=
|
||||||
|
fi
|
||||||
|
AC_SUBST([LIBICONV])
|
||||||
|
AC_SUBST([LTLIBICONV])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
|
||||||
|
dnl avoid warnings like
|
||||||
|
dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
|
||||||
|
dnl This is tricky because of the way 'aclocal' is implemented:
|
||||||
|
dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
|
||||||
|
dnl Otherwise aclocal's initial scan pass would miss the macro definition.
|
||||||
|
dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
|
||||||
|
dnl Otherwise aclocal would emit many "Use of uninitialized value $1"
|
||||||
|
dnl warnings.
|
||||||
|
m4_define([gl_iconv_AC_DEFUN],
|
||||||
|
m4_version_prereq([2.64],
|
||||||
|
[[AC_DEFUN_ONCE(
|
||||||
|
[$1], [$2])]],
|
||||||
|
[[AC_DEFUN(
|
||||||
|
[$1], [$2])]]))
|
||||||
|
gl_iconv_AC_DEFUN([AM_ICONV],
|
||||||
|
[
|
||||||
|
AM_ICONV_LINK
|
||||||
|
if test "$am_cv_func_iconv" = yes; then
|
||||||
|
AC_MSG_CHECKING([for iconv declaration])
|
||||||
|
AC_CACHE_VAL([am_cv_proto_iconv], [
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iconv.h>
|
||||||
|
extern
|
||||||
|
#ifdef __cplusplus
|
||||||
|
"C"
|
||||||
|
#endif
|
||||||
|
#if defined(__STDC__) || defined(__cplusplus)
|
||||||
|
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||||
|
#else
|
||||||
|
size_t iconv();
|
||||||
|
#endif
|
||||||
|
], [], [am_cv_proto_iconv_arg1=""], [am_cv_proto_iconv_arg1="const"])
|
||||||
|
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||||
|
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||||
|
AC_MSG_RESULT([
|
||||||
|
$am_cv_proto_iconv])
|
||||||
|
AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
|
||||||
|
[Define as const if the declaration of iconv() needs const.])
|
||||||
|
fi
|
||||||
|
])
|
110
m4/lib-ld.m4
Normal file
110
m4/lib-ld.m4
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
# lib-ld.m4 serial 4 (gettext-0.18)
|
||||||
|
dnl Copyright (C) 1996-2003, 2009-2010 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
dnl Subroutines of libtool.m4,
|
||||||
|
dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
|
||||||
|
dnl with libtool.m4.
|
||||||
|
|
||||||
|
dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
|
||||||
|
AC_DEFUN([AC_LIB_PROG_LD_GNU],
|
||||||
|
[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld],
|
||||||
|
[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
|
||||||
|
case `$LD -v 2>&1 </dev/null` in
|
||||||
|
*GNU* | *'with BFD'*)
|
||||||
|
acl_cv_prog_gnu_ld=yes ;;
|
||||||
|
*)
|
||||||
|
acl_cv_prog_gnu_ld=no ;;
|
||||||
|
esac])
|
||||||
|
with_gnu_ld=$acl_cv_prog_gnu_ld
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl From libtool-1.4. Sets the variable LD.
|
||||||
|
AC_DEFUN([AC_LIB_PROG_LD],
|
||||||
|
[AC_ARG_WITH([gnu-ld],
|
||||||
|
[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
|
||||||
|
test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
|
||||||
|
AC_REQUIRE([AC_PROG_CC])dnl
|
||||||
|
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||||
|
# Prepare PATH_SEPARATOR.
|
||||||
|
# The user is always right.
|
||||||
|
if test "${PATH_SEPARATOR+set}" != set; then
|
||||||
|
echo "#! /bin/sh" >conf$$.sh
|
||||||
|
echo "exit 0" >>conf$$.sh
|
||||||
|
chmod +x conf$$.sh
|
||||||
|
if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
|
||||||
|
PATH_SEPARATOR=';'
|
||||||
|
else
|
||||||
|
PATH_SEPARATOR=:
|
||||||
|
fi
|
||||||
|
rm -f conf$$.sh
|
||||||
|
fi
|
||||||
|
ac_prog=ld
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
# Check if gcc -print-prog-name=ld gives a path.
|
||||||
|
AC_MSG_CHECKING([for ld used by GCC])
|
||||||
|
case $host in
|
||||||
|
*-*-mingw*)
|
||||||
|
# gcc leaves a trailing carriage return which upsets mingw
|
||||||
|
ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
|
||||||
|
*)
|
||||||
|
ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
|
||||||
|
esac
|
||||||
|
case $ac_prog in
|
||||||
|
# Accept absolute paths.
|
||||||
|
[[\\/]* | [A-Za-z]:[\\/]*)]
|
||||||
|
[re_direlt='/[^/][^/]*/\.\./']
|
||||||
|
# Canonicalize the path of ld
|
||||||
|
ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
|
||||||
|
while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
|
||||||
|
ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
|
||||||
|
done
|
||||||
|
test -z "$LD" && LD="$ac_prog"
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
# If it fails, then pretend we aren't using GCC.
|
||||||
|
ac_prog=ld
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# If it is relative, then search for the first ld in PATH.
|
||||||
|
with_gnu_ld=unknown
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
elif test "$with_gnu_ld" = yes; then
|
||||||
|
AC_MSG_CHECKING([for GNU ld])
|
||||||
|
else
|
||||||
|
AC_MSG_CHECKING([for non-GNU ld])
|
||||||
|
fi
|
||||||
|
AC_CACHE_VAL([acl_cv_path_LD],
|
||||||
|
[if test -z "$LD"; then
|
||||||
|
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
|
||||||
|
for ac_dir in $PATH; do
|
||||||
|
test -z "$ac_dir" && ac_dir=.
|
||||||
|
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
|
||||||
|
acl_cv_path_LD="$ac_dir/$ac_prog"
|
||||||
|
# Check to see if the program is GNU ld. I'd rather use --version,
|
||||||
|
# but apparently some GNU ld's only accept -v.
|
||||||
|
# Break only if it was the GNU/non-GNU ld that we prefer.
|
||||||
|
case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
|
||||||
|
*GNU* | *'with BFD'*)
|
||||||
|
test "$with_gnu_ld" != no && break ;;
|
||||||
|
*)
|
||||||
|
test "$with_gnu_ld" != yes && break ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS="$ac_save_ifs"
|
||||||
|
else
|
||||||
|
acl_cv_path_LD="$LD" # Let the user override the test with a path.
|
||||||
|
fi])
|
||||||
|
LD="$acl_cv_path_LD"
|
||||||
|
if test -n "$LD"; then
|
||||||
|
AC_MSG_RESULT([$LD])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
fi
|
||||||
|
test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
|
||||||
|
AC_LIB_PROG_LD_GNU
|
||||||
|
])
|
774
m4/lib-link.m4
Normal file
774
m4/lib-link.m4
Normal file
@ -0,0 +1,774 @@
|
|||||||
|
# lib-link.m4 serial 21 (gettext-0.18)
|
||||||
|
dnl Copyright (C) 2001-2010 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
dnl From Bruno Haible.
|
||||||
|
|
||||||
|
AC_PREREQ([2.54])
|
||||||
|
|
||||||
|
dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
|
||||||
|
dnl the libraries corresponding to explicit and implicit dependencies.
|
||||||
|
dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
|
||||||
|
dnl augments the CPPFLAGS variable.
|
||||||
|
dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
|
||||||
|
dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
|
||||||
|
AC_DEFUN([AC_LIB_LINKFLAGS],
|
||||||
|
[
|
||||||
|
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||||
|
AC_REQUIRE([AC_LIB_RPATH])
|
||||||
|
pushdef([Name],[translit([$1],[./-], [___])])
|
||||||
|
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
|
||||||
|
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
|
||||||
|
AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
|
||||||
|
AC_LIB_LINKFLAGS_BODY([$1], [$2])
|
||||||
|
ac_cv_lib[]Name[]_libs="$LIB[]NAME"
|
||||||
|
ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
|
||||||
|
ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
|
||||||
|
ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
|
||||||
|
])
|
||||||
|
LIB[]NAME="$ac_cv_lib[]Name[]_libs"
|
||||||
|
LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
|
||||||
|
INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
|
||||||
|
LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
|
||||||
|
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
|
||||||
|
AC_SUBST([LIB]NAME)
|
||||||
|
AC_SUBST([LTLIB]NAME)
|
||||||
|
AC_SUBST([LIB]NAME[_PREFIX])
|
||||||
|
dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
|
||||||
|
dnl results of this search when this library appears as a dependency.
|
||||||
|
HAVE_LIB[]NAME=yes
|
||||||
|
popdef([NAME])
|
||||||
|
popdef([Name])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message])
|
||||||
|
dnl searches for libname and the libraries corresponding to explicit and
|
||||||
|
dnl implicit dependencies, together with the specified include files and
|
||||||
|
dnl the ability to compile and link the specified testcode. The missing-message
|
||||||
|
dnl defaults to 'no' and may contain additional hints for the user.
|
||||||
|
dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME}
|
||||||
|
dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and
|
||||||
|
dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
|
||||||
|
dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
|
||||||
|
dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
|
||||||
|
dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
|
||||||
|
AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
|
||||||
|
[
|
||||||
|
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||||
|
AC_REQUIRE([AC_LIB_RPATH])
|
||||||
|
pushdef([Name],[translit([$1],[./-], [___])])
|
||||||
|
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
|
||||||
|
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
|
||||||
|
|
||||||
|
dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
|
||||||
|
dnl accordingly.
|
||||||
|
AC_LIB_LINKFLAGS_BODY([$1], [$2])
|
||||||
|
|
||||||
|
dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
|
||||||
|
dnl because if the user has installed lib[]Name and not disabled its use
|
||||||
|
dnl via --without-lib[]Name-prefix, he wants to use it.
|
||||||
|
ac_save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
|
||||||
|
ac_save_LIBS="$LIBS"
|
||||||
|
dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS,
|
||||||
|
dnl because these -l options might require -L options that are present in
|
||||||
|
dnl LIBS. -l options benefit only from the -L options listed before it.
|
||||||
|
dnl Otherwise, add it to the front of LIBS, because it may be a static
|
||||||
|
dnl library that depends on another static library that is present in LIBS.
|
||||||
|
dnl Static libraries benefit only from the static libraries listed after
|
||||||
|
dnl it.
|
||||||
|
case " $LIB[]NAME" in
|
||||||
|
*" -l"*) LIBS="$LIBS $LIB[]NAME" ;;
|
||||||
|
*) LIBS="$LIB[]NAME $LIBS" ;;
|
||||||
|
esac
|
||||||
|
AC_TRY_LINK([$3], [$4],
|
||||||
|
[ac_cv_lib[]Name=yes],
|
||||||
|
[ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])'])
|
||||||
|
LIBS="$ac_save_LIBS"
|
||||||
|
])
|
||||||
|
if test "$ac_cv_lib[]Name" = yes; then
|
||||||
|
HAVE_LIB[]NAME=yes
|
||||||
|
AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.])
|
||||||
|
AC_MSG_CHECKING([how to link with lib[]$1])
|
||||||
|
AC_MSG_RESULT([$LIB[]NAME])
|
||||||
|
else
|
||||||
|
HAVE_LIB[]NAME=no
|
||||||
|
dnl If $LIB[]NAME didn't lead to a usable library, we don't need
|
||||||
|
dnl $INC[]NAME either.
|
||||||
|
CPPFLAGS="$ac_save_CPPFLAGS"
|
||||||
|
LIB[]NAME=
|
||||||
|
LTLIB[]NAME=
|
||||||
|
LIB[]NAME[]_PREFIX=
|
||||||
|
fi
|
||||||
|
AC_SUBST([HAVE_LIB]NAME)
|
||||||
|
AC_SUBST([LIB]NAME)
|
||||||
|
AC_SUBST([LTLIB]NAME)
|
||||||
|
AC_SUBST([LIB]NAME[_PREFIX])
|
||||||
|
popdef([NAME])
|
||||||
|
popdef([Name])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Determine the platform dependent parameters needed to use rpath:
|
||||||
|
dnl acl_libext,
|
||||||
|
dnl acl_shlibext,
|
||||||
|
dnl acl_hardcode_libdir_flag_spec,
|
||||||
|
dnl acl_hardcode_libdir_separator,
|
||||||
|
dnl acl_hardcode_direct,
|
||||||
|
dnl acl_hardcode_minus_L.
|
||||||
|
AC_DEFUN([AC_LIB_RPATH],
|
||||||
|
[
|
||||||
|
dnl Tell automake >= 1.10 to complain if config.rpath is missing.
|
||||||
|
m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
|
||||||
|
AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
|
||||||
|
AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
|
||||||
|
AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
|
||||||
|
AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
|
||||||
|
AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [
|
||||||
|
CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
|
||||||
|
${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
|
||||||
|
. ./conftest.sh
|
||||||
|
rm -f ./conftest.sh
|
||||||
|
acl_cv_rpath=done
|
||||||
|
])
|
||||||
|
wl="$acl_cv_wl"
|
||||||
|
acl_libext="$acl_cv_libext"
|
||||||
|
acl_shlibext="$acl_cv_shlibext"
|
||||||
|
acl_libname_spec="$acl_cv_libname_spec"
|
||||||
|
acl_library_names_spec="$acl_cv_library_names_spec"
|
||||||
|
acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
|
||||||
|
acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
|
||||||
|
acl_hardcode_direct="$acl_cv_hardcode_direct"
|
||||||
|
acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
|
||||||
|
dnl Determine whether the user wants rpath handling at all.
|
||||||
|
AC_ARG_ENABLE([rpath],
|
||||||
|
[ --disable-rpath do not hardcode runtime library paths],
|
||||||
|
:, enable_rpath=yes)
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl AC_LIB_FROMPACKAGE(name, package)
|
||||||
|
dnl declares that libname comes from the given package. The configure file
|
||||||
|
dnl will then not have a --with-libname-prefix option but a
|
||||||
|
dnl --with-package-prefix option. Several libraries can come from the same
|
||||||
|
dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar
|
||||||
|
dnl macro call that searches for libname.
|
||||||
|
AC_DEFUN([AC_LIB_FROMPACKAGE],
|
||||||
|
[
|
||||||
|
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
|
||||||
|
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
|
||||||
|
define([acl_frompackage_]NAME, [$2])
|
||||||
|
popdef([NAME])
|
||||||
|
pushdef([PACK],[$2])
|
||||||
|
pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-],
|
||||||
|
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
|
||||||
|
define([acl_libsinpackage_]PACKUP,
|
||||||
|
m4_ifdef([acl_libsinpackage_]PACKUP, [acl_libsinpackage_]PACKUP[[, ]],)[lib$1])
|
||||||
|
popdef([PACKUP])
|
||||||
|
popdef([PACK])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
|
||||||
|
dnl the libraries corresponding to explicit and implicit dependencies.
|
||||||
|
dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
|
||||||
|
dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
|
||||||
|
dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
|
||||||
|
AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
|
||||||
|
[
|
||||||
|
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
|
||||||
|
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
|
||||||
|
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
|
||||||
|
pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])])
|
||||||
|
pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-],
|
||||||
|
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
|
||||||
|
pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])])
|
||||||
|
dnl Autoconf >= 2.61 supports dots in --with options.
|
||||||
|
pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit(PACK,[.],[_])],PACK)])
|
||||||
|
dnl By default, look in $includedir and $libdir.
|
||||||
|
use_additional=yes
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([
|
||||||
|
eval additional_includedir=\"$includedir\"
|
||||||
|
eval additional_libdir=\"$libdir\"
|
||||||
|
])
|
||||||
|
AC_ARG_WITH(P_A_C_K[-prefix],
|
||||||
|
[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib
|
||||||
|
--without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]],
|
||||||
|
[
|
||||||
|
if test "X$withval" = "Xno"; then
|
||||||
|
use_additional=no
|
||||||
|
else
|
||||||
|
if test "X$withval" = "X"; then
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([
|
||||||
|
eval additional_includedir=\"$includedir\"
|
||||||
|
eval additional_libdir=\"$libdir\"
|
||||||
|
])
|
||||||
|
else
|
||||||
|
additional_includedir="$withval/include"
|
||||||
|
additional_libdir="$withval/$acl_libdirstem"
|
||||||
|
if test "$acl_libdirstem2" != "$acl_libdirstem" \
|
||||||
|
&& ! test -d "$withval/$acl_libdirstem"; then
|
||||||
|
additional_libdir="$withval/$acl_libdirstem2"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
dnl Search the library and its dependencies in $additional_libdir and
|
||||||
|
dnl $LDFLAGS. Using breadth-first-seach.
|
||||||
|
LIB[]NAME=
|
||||||
|
LTLIB[]NAME=
|
||||||
|
INC[]NAME=
|
||||||
|
LIB[]NAME[]_PREFIX=
|
||||||
|
dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been
|
||||||
|
dnl computed. So it has to be reset here.
|
||||||
|
HAVE_LIB[]NAME=
|
||||||
|
rpathdirs=
|
||||||
|
ltrpathdirs=
|
||||||
|
names_already_handled=
|
||||||
|
names_next_round='$1 $2'
|
||||||
|
while test -n "$names_next_round"; do
|
||||||
|
names_this_round="$names_next_round"
|
||||||
|
names_next_round=
|
||||||
|
for name in $names_this_round; do
|
||||||
|
already_handled=
|
||||||
|
for n in $names_already_handled; do
|
||||||
|
if test "$n" = "$name"; then
|
||||||
|
already_handled=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$already_handled"; then
|
||||||
|
names_already_handled="$names_already_handled $name"
|
||||||
|
dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
|
||||||
|
dnl or AC_LIB_HAVE_LINKFLAGS call.
|
||||||
|
uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
|
||||||
|
eval value=\"\$HAVE_LIB$uppername\"
|
||||||
|
if test -n "$value"; then
|
||||||
|
if test "$value" = yes; then
|
||||||
|
eval value=\"\$LIB$uppername\"
|
||||||
|
test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
|
||||||
|
eval value=\"\$LTLIB$uppername\"
|
||||||
|
test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
|
||||||
|
else
|
||||||
|
dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
|
||||||
|
dnl that this library doesn't exist. So just drop it.
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
dnl Search the library lib$name in $additional_libdir and $LDFLAGS
|
||||||
|
dnl and the already constructed $LIBNAME/$LTLIBNAME.
|
||||||
|
found_dir=
|
||||||
|
found_la=
|
||||||
|
found_so=
|
||||||
|
found_a=
|
||||||
|
eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
|
||||||
|
if test -n "$acl_shlibext"; then
|
||||||
|
shrext=".$acl_shlibext" # typically: shrext=.so
|
||||||
|
else
|
||||||
|
shrext=
|
||||||
|
fi
|
||||||
|
if test $use_additional = yes; then
|
||||||
|
dir="$additional_libdir"
|
||||||
|
dnl The same code as in the loop below:
|
||||||
|
dnl First look for a shared library.
|
||||||
|
if test -n "$acl_shlibext"; then
|
||||||
|
if test -f "$dir/$libname$shrext"; then
|
||||||
|
found_dir="$dir"
|
||||||
|
found_so="$dir/$libname$shrext"
|
||||||
|
else
|
||||||
|
if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
|
||||||
|
ver=`(cd "$dir" && \
|
||||||
|
for f in "$libname$shrext".*; do echo "$f"; done \
|
||||||
|
| sed -e "s,^$libname$shrext\\\\.,," \
|
||||||
|
| sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
|
||||||
|
| sed 1q ) 2>/dev/null`
|
||||||
|
if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
|
||||||
|
found_dir="$dir"
|
||||||
|
found_so="$dir/$libname$shrext.$ver"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
eval library_names=\"$acl_library_names_spec\"
|
||||||
|
for f in $library_names; do
|
||||||
|
if test -f "$dir/$f"; then
|
||||||
|
found_dir="$dir"
|
||||||
|
found_so="$dir/$f"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
dnl Then look for a static library.
|
||||||
|
if test "X$found_dir" = "X"; then
|
||||||
|
if test -f "$dir/$libname.$acl_libext"; then
|
||||||
|
found_dir="$dir"
|
||||||
|
found_a="$dir/$libname.$acl_libext"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "X$found_dir" != "X"; then
|
||||||
|
if test -f "$dir/$libname.la"; then
|
||||||
|
found_la="$dir/$libname.la"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "X$found_dir" = "X"; then
|
||||||
|
for x in $LDFLAGS $LTLIB[]NAME; do
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||||
|
case "$x" in
|
||||||
|
-L*)
|
||||||
|
dir=`echo "X$x" | sed -e 's/^X-L//'`
|
||||||
|
dnl First look for a shared library.
|
||||||
|
if test -n "$acl_shlibext"; then
|
||||||
|
if test -f "$dir/$libname$shrext"; then
|
||||||
|
found_dir="$dir"
|
||||||
|
found_so="$dir/$libname$shrext"
|
||||||
|
else
|
||||||
|
if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
|
||||||
|
ver=`(cd "$dir" && \
|
||||||
|
for f in "$libname$shrext".*; do echo "$f"; done \
|
||||||
|
| sed -e "s,^$libname$shrext\\\\.,," \
|
||||||
|
| sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
|
||||||
|
| sed 1q ) 2>/dev/null`
|
||||||
|
if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
|
||||||
|
found_dir="$dir"
|
||||||
|
found_so="$dir/$libname$shrext.$ver"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
eval library_names=\"$acl_library_names_spec\"
|
||||||
|
for f in $library_names; do
|
||||||
|
if test -f "$dir/$f"; then
|
||||||
|
found_dir="$dir"
|
||||||
|
found_so="$dir/$f"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
dnl Then look for a static library.
|
||||||
|
if test "X$found_dir" = "X"; then
|
||||||
|
if test -f "$dir/$libname.$acl_libext"; then
|
||||||
|
found_dir="$dir"
|
||||||
|
found_a="$dir/$libname.$acl_libext"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "X$found_dir" != "X"; then
|
||||||
|
if test -f "$dir/$libname.la"; then
|
||||||
|
found_la="$dir/$libname.la"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if test "X$found_dir" != "X"; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if test "X$found_dir" != "X"; then
|
||||||
|
dnl Found the library.
|
||||||
|
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
|
||||||
|
if test "X$found_so" != "X"; then
|
||||||
|
dnl Linking with a shared library. We attempt to hardcode its
|
||||||
|
dnl directory into the executable's runpath, unless it's the
|
||||||
|
dnl standard /usr/lib.
|
||||||
|
if test "$enable_rpath" = no \
|
||||||
|
|| test "X$found_dir" = "X/usr/$acl_libdirstem" \
|
||||||
|
|| test "X$found_dir" = "X/usr/$acl_libdirstem2"; then
|
||||||
|
dnl No hardcoding is needed.
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
|
||||||
|
else
|
||||||
|
dnl Use an explicit option to hardcode DIR into the resulting
|
||||||
|
dnl binary.
|
||||||
|
dnl Potentially add DIR to ltrpathdirs.
|
||||||
|
dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
|
||||||
|
haveit=
|
||||||
|
for x in $ltrpathdirs; do
|
||||||
|
if test "X$x" = "X$found_dir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
ltrpathdirs="$ltrpathdirs $found_dir"
|
||||||
|
fi
|
||||||
|
dnl The hardcoding into $LIBNAME is system dependent.
|
||||||
|
if test "$acl_hardcode_direct" = yes; then
|
||||||
|
dnl Using DIR/libNAME.so during linking hardcodes DIR into the
|
||||||
|
dnl resulting binary.
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
|
||||||
|
else
|
||||||
|
if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
|
||||||
|
dnl Use an explicit option to hardcode DIR into the resulting
|
||||||
|
dnl binary.
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
|
||||||
|
dnl Potentially add DIR to rpathdirs.
|
||||||
|
dnl The rpathdirs will be appended to $LIBNAME at the end.
|
||||||
|
haveit=
|
||||||
|
for x in $rpathdirs; do
|
||||||
|
if test "X$x" = "X$found_dir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
rpathdirs="$rpathdirs $found_dir"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
dnl Rely on "-L$found_dir".
|
||||||
|
dnl But don't add it if it's already contained in the LDFLAGS
|
||||||
|
dnl or the already constructed $LIBNAME
|
||||||
|
haveit=
|
||||||
|
for x in $LDFLAGS $LIB[]NAME; do
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||||
|
if test "X$x" = "X-L$found_dir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
|
||||||
|
fi
|
||||||
|
if test "$acl_hardcode_minus_L" != no; then
|
||||||
|
dnl FIXME: Not sure whether we should use
|
||||||
|
dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
|
||||||
|
dnl here.
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
|
||||||
|
else
|
||||||
|
dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
|
||||||
|
dnl here, because this doesn't fit in flags passed to the
|
||||||
|
dnl compiler. So give up. No hardcoding. This affects only
|
||||||
|
dnl very old systems.
|
||||||
|
dnl FIXME: Not sure whether we should use
|
||||||
|
dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
|
||||||
|
dnl here.
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if test "X$found_a" != "X"; then
|
||||||
|
dnl Linking with a static library.
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
|
||||||
|
else
|
||||||
|
dnl We shouldn't come here, but anyway it's good to have a
|
||||||
|
dnl fallback.
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
dnl Assume the include files are nearby.
|
||||||
|
additional_includedir=
|
||||||
|
case "$found_dir" in
|
||||||
|
*/$acl_libdirstem | */$acl_libdirstem/)
|
||||||
|
basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
|
||||||
|
if test "$name" = '$1'; then
|
||||||
|
LIB[]NAME[]_PREFIX="$basedir"
|
||||||
|
fi
|
||||||
|
additional_includedir="$basedir/include"
|
||||||
|
;;
|
||||||
|
*/$acl_libdirstem2 | */$acl_libdirstem2/)
|
||||||
|
basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'`
|
||||||
|
if test "$name" = '$1'; then
|
||||||
|
LIB[]NAME[]_PREFIX="$basedir"
|
||||||
|
fi
|
||||||
|
additional_includedir="$basedir/include"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if test "X$additional_includedir" != "X"; then
|
||||||
|
dnl Potentially add $additional_includedir to $INCNAME.
|
||||||
|
dnl But don't add it
|
||||||
|
dnl 1. if it's the standard /usr/include,
|
||||||
|
dnl 2. if it's /usr/local/include and we are using GCC on Linux,
|
||||||
|
dnl 3. if it's already present in $CPPFLAGS or the already
|
||||||
|
dnl constructed $INCNAME,
|
||||||
|
dnl 4. if it doesn't exist as a directory.
|
||||||
|
if test "X$additional_includedir" != "X/usr/include"; then
|
||||||
|
haveit=
|
||||||
|
if test "X$additional_includedir" = "X/usr/local/include"; then
|
||||||
|
if test -n "$GCC"; then
|
||||||
|
case $host_os in
|
||||||
|
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
for x in $CPPFLAGS $INC[]NAME; do
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||||
|
if test "X$x" = "X-I$additional_includedir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
if test -d "$additional_includedir"; then
|
||||||
|
dnl Really add $additional_includedir to $INCNAME.
|
||||||
|
INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
dnl Look for dependencies.
|
||||||
|
if test -n "$found_la"; then
|
||||||
|
dnl Read the .la file. It defines the variables
|
||||||
|
dnl dlname, library_names, old_library, dependency_libs, current,
|
||||||
|
dnl age, revision, installed, dlopen, dlpreopen, libdir.
|
||||||
|
save_libdir="$libdir"
|
||||||
|
case "$found_la" in
|
||||||
|
*/* | *\\*) . "$found_la" ;;
|
||||||
|
*) . "./$found_la" ;;
|
||||||
|
esac
|
||||||
|
libdir="$save_libdir"
|
||||||
|
dnl We use only dependency_libs.
|
||||||
|
for dep in $dependency_libs; do
|
||||||
|
case "$dep" in
|
||||||
|
-L*)
|
||||||
|
additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
|
||||||
|
dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
|
||||||
|
dnl But don't add it
|
||||||
|
dnl 1. if it's the standard /usr/lib,
|
||||||
|
dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
|
||||||
|
dnl 3. if it's already present in $LDFLAGS or the already
|
||||||
|
dnl constructed $LIBNAME,
|
||||||
|
dnl 4. if it doesn't exist as a directory.
|
||||||
|
if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \
|
||||||
|
&& test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then
|
||||||
|
haveit=
|
||||||
|
if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \
|
||||||
|
|| test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then
|
||||||
|
if test -n "$GCC"; then
|
||||||
|
case $host_os in
|
||||||
|
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
haveit=
|
||||||
|
for x in $LDFLAGS $LIB[]NAME; do
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||||
|
if test "X$x" = "X-L$additional_libdir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
if test -d "$additional_libdir"; then
|
||||||
|
dnl Really add $additional_libdir to $LIBNAME.
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
haveit=
|
||||||
|
for x in $LDFLAGS $LTLIB[]NAME; do
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||||
|
if test "X$x" = "X-L$additional_libdir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
if test -d "$additional_libdir"; then
|
||||||
|
dnl Really add $additional_libdir to $LTLIBNAME.
|
||||||
|
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
-R*)
|
||||||
|
dir=`echo "X$dep" | sed -e 's/^X-R//'`
|
||||||
|
if test "$enable_rpath" != no; then
|
||||||
|
dnl Potentially add DIR to rpathdirs.
|
||||||
|
dnl The rpathdirs will be appended to $LIBNAME at the end.
|
||||||
|
haveit=
|
||||||
|
for x in $rpathdirs; do
|
||||||
|
if test "X$x" = "X$dir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
rpathdirs="$rpathdirs $dir"
|
||||||
|
fi
|
||||||
|
dnl Potentially add DIR to ltrpathdirs.
|
||||||
|
dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
|
||||||
|
haveit=
|
||||||
|
for x in $ltrpathdirs; do
|
||||||
|
if test "X$x" = "X$dir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
ltrpathdirs="$ltrpathdirs $dir"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
-l*)
|
||||||
|
dnl Handle this in the next round.
|
||||||
|
names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
|
||||||
|
;;
|
||||||
|
*.la)
|
||||||
|
dnl Handle this in the next round. Throw away the .la's
|
||||||
|
dnl directory; it is already contained in a preceding -L
|
||||||
|
dnl option.
|
||||||
|
names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
dnl Most likely an immediate library name.
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
|
||||||
|
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
dnl Didn't find the library; assume it is in the system directories
|
||||||
|
dnl known to the linker and runtime loader. (All the system
|
||||||
|
dnl directories known to the linker should also be known to the
|
||||||
|
dnl runtime loader, otherwise the system is severely misconfigured.)
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
|
||||||
|
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
if test "X$rpathdirs" != "X"; then
|
||||||
|
if test -n "$acl_hardcode_libdir_separator"; then
|
||||||
|
dnl Weird platform: only the last -rpath option counts, the user must
|
||||||
|
dnl pass all path elements in one option. We can arrange that for a
|
||||||
|
dnl single library, but not when more than one $LIBNAMEs are used.
|
||||||
|
alldirs=
|
||||||
|
for found_dir in $rpathdirs; do
|
||||||
|
alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
|
||||||
|
done
|
||||||
|
dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
|
||||||
|
acl_save_libdir="$libdir"
|
||||||
|
libdir="$alldirs"
|
||||||
|
eval flag=\"$acl_hardcode_libdir_flag_spec\"
|
||||||
|
libdir="$acl_save_libdir"
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
|
||||||
|
else
|
||||||
|
dnl The -rpath options are cumulative.
|
||||||
|
for found_dir in $rpathdirs; do
|
||||||
|
acl_save_libdir="$libdir"
|
||||||
|
libdir="$found_dir"
|
||||||
|
eval flag=\"$acl_hardcode_libdir_flag_spec\"
|
||||||
|
libdir="$acl_save_libdir"
|
||||||
|
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "X$ltrpathdirs" != "X"; then
|
||||||
|
dnl When using libtool, the option that works for both libraries and
|
||||||
|
dnl executables is -R. The -R options are cumulative.
|
||||||
|
for found_dir in $ltrpathdirs; do
|
||||||
|
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
popdef([P_A_C_K])
|
||||||
|
popdef([PACKLIBS])
|
||||||
|
popdef([PACKUP])
|
||||||
|
popdef([PACK])
|
||||||
|
popdef([NAME])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
|
||||||
|
dnl unless already present in VAR.
|
||||||
|
dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
|
||||||
|
dnl contains two or three consecutive elements that belong together.
|
||||||
|
AC_DEFUN([AC_LIB_APPENDTOVAR],
|
||||||
|
[
|
||||||
|
for element in [$2]; do
|
||||||
|
haveit=
|
||||||
|
for x in $[$1]; do
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||||
|
if test "X$x" = "X$element"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
[$1]="${[$1]}${[$1]:+ }$element"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl For those cases where a variable contains several -L and -l options
|
||||||
|
dnl referring to unknown libraries and directories, this macro determines the
|
||||||
|
dnl necessary additional linker options for the runtime path.
|
||||||
|
dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
|
||||||
|
dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
|
||||||
|
dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
|
||||||
|
dnl otherwise linking without libtool is assumed.
|
||||||
|
AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
|
||||||
|
[
|
||||||
|
AC_REQUIRE([AC_LIB_RPATH])
|
||||||
|
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
|
||||||
|
$1=
|
||||||
|
if test "$enable_rpath" != no; then
|
||||||
|
if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
|
||||||
|
dnl Use an explicit option to hardcode directories into the resulting
|
||||||
|
dnl binary.
|
||||||
|
rpathdirs=
|
||||||
|
next=
|
||||||
|
for opt in $2; do
|
||||||
|
if test -n "$next"; then
|
||||||
|
dir="$next"
|
||||||
|
dnl No need to hardcode the standard /usr/lib.
|
||||||
|
if test "X$dir" != "X/usr/$acl_libdirstem" \
|
||||||
|
&& test "X$dir" != "X/usr/$acl_libdirstem2"; then
|
||||||
|
rpathdirs="$rpathdirs $dir"
|
||||||
|
fi
|
||||||
|
next=
|
||||||
|
else
|
||||||
|
case $opt in
|
||||||
|
-L) next=yes ;;
|
||||||
|
-L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
|
||||||
|
dnl No need to hardcode the standard /usr/lib.
|
||||||
|
if test "X$dir" != "X/usr/$acl_libdirstem" \
|
||||||
|
&& test "X$dir" != "X/usr/$acl_libdirstem2"; then
|
||||||
|
rpathdirs="$rpathdirs $dir"
|
||||||
|
fi
|
||||||
|
next= ;;
|
||||||
|
*) next= ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test "X$rpathdirs" != "X"; then
|
||||||
|
if test -n ""$3""; then
|
||||||
|
dnl libtool is used for linking. Use -R options.
|
||||||
|
for dir in $rpathdirs; do
|
||||||
|
$1="${$1}${$1:+ }-R$dir"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
dnl The linker is used for linking directly.
|
||||||
|
if test -n "$acl_hardcode_libdir_separator"; then
|
||||||
|
dnl Weird platform: only the last -rpath option counts, the user
|
||||||
|
dnl must pass all path elements in one option.
|
||||||
|
alldirs=
|
||||||
|
for dir in $rpathdirs; do
|
||||||
|
alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
|
||||||
|
done
|
||||||
|
acl_save_libdir="$libdir"
|
||||||
|
libdir="$alldirs"
|
||||||
|
eval flag=\"$acl_hardcode_libdir_flag_spec\"
|
||||||
|
libdir="$acl_save_libdir"
|
||||||
|
$1="$flag"
|
||||||
|
else
|
||||||
|
dnl The -rpath options are cumulative.
|
||||||
|
for dir in $rpathdirs; do
|
||||||
|
acl_save_libdir="$libdir"
|
||||||
|
libdir="$dir"
|
||||||
|
eval flag=\"$acl_hardcode_libdir_flag_spec\"
|
||||||
|
libdir="$acl_save_libdir"
|
||||||
|
$1="${$1}${$1:+ }$flag"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AC_SUBST([$1])
|
||||||
|
])
|
224
m4/lib-prefix.m4
Normal file
224
m4/lib-prefix.m4
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
# lib-prefix.m4 serial 7 (gettext-0.18)
|
||||||
|
dnl Copyright (C) 2001-2005, 2008-2010 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
dnl From Bruno Haible.
|
||||||
|
|
||||||
|
dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
|
||||||
|
dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
|
||||||
|
dnl require excessive bracketing.
|
||||||
|
ifdef([AC_HELP_STRING],
|
||||||
|
[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
|
||||||
|
[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
|
||||||
|
|
||||||
|
dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
|
||||||
|
dnl to access previously installed libraries. The basic assumption is that
|
||||||
|
dnl a user will want packages to use other packages he previously installed
|
||||||
|
dnl with the same --prefix option.
|
||||||
|
dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
|
||||||
|
dnl libraries, but is otherwise very convenient.
|
||||||
|
AC_DEFUN([AC_LIB_PREFIX],
|
||||||
|
[
|
||||||
|
AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
|
||||||
|
AC_REQUIRE([AC_PROG_CC])
|
||||||
|
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||||
|
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
|
||||||
|
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||||
|
dnl By default, look in $includedir and $libdir.
|
||||||
|
use_additional=yes
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([
|
||||||
|
eval additional_includedir=\"$includedir\"
|
||||||
|
eval additional_libdir=\"$libdir\"
|
||||||
|
])
|
||||||
|
AC_LIB_ARG_WITH([lib-prefix],
|
||||||
|
[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
|
||||||
|
--without-lib-prefix don't search for libraries in includedir and libdir],
|
||||||
|
[
|
||||||
|
if test "X$withval" = "Xno"; then
|
||||||
|
use_additional=no
|
||||||
|
else
|
||||||
|
if test "X$withval" = "X"; then
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([
|
||||||
|
eval additional_includedir=\"$includedir\"
|
||||||
|
eval additional_libdir=\"$libdir\"
|
||||||
|
])
|
||||||
|
else
|
||||||
|
additional_includedir="$withval/include"
|
||||||
|
additional_libdir="$withval/$acl_libdirstem"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
if test $use_additional = yes; then
|
||||||
|
dnl Potentially add $additional_includedir to $CPPFLAGS.
|
||||||
|
dnl But don't add it
|
||||||
|
dnl 1. if it's the standard /usr/include,
|
||||||
|
dnl 2. if it's already present in $CPPFLAGS,
|
||||||
|
dnl 3. if it's /usr/local/include and we are using GCC on Linux,
|
||||||
|
dnl 4. if it doesn't exist as a directory.
|
||||||
|
if test "X$additional_includedir" != "X/usr/include"; then
|
||||||
|
haveit=
|
||||||
|
for x in $CPPFLAGS; do
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||||
|
if test "X$x" = "X-I$additional_includedir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
if test "X$additional_includedir" = "X/usr/local/include"; then
|
||||||
|
if test -n "$GCC"; then
|
||||||
|
case $host_os in
|
||||||
|
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
if test -d "$additional_includedir"; then
|
||||||
|
dnl Really add $additional_includedir to $CPPFLAGS.
|
||||||
|
CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
dnl Potentially add $additional_libdir to $LDFLAGS.
|
||||||
|
dnl But don't add it
|
||||||
|
dnl 1. if it's the standard /usr/lib,
|
||||||
|
dnl 2. if it's already present in $LDFLAGS,
|
||||||
|
dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
|
||||||
|
dnl 4. if it doesn't exist as a directory.
|
||||||
|
if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
|
||||||
|
haveit=
|
||||||
|
for x in $LDFLAGS; do
|
||||||
|
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||||
|
if test "X$x" = "X-L$additional_libdir"; then
|
||||||
|
haveit=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
|
||||||
|
if test -n "$GCC"; then
|
||||||
|
case $host_os in
|
||||||
|
linux*) haveit=yes;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test -z "$haveit"; then
|
||||||
|
if test -d "$additional_libdir"; then
|
||||||
|
dnl Really add $additional_libdir to $LDFLAGS.
|
||||||
|
LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
|
||||||
|
dnl acl_final_exec_prefix, containing the values to which $prefix and
|
||||||
|
dnl $exec_prefix will expand at the end of the configure script.
|
||||||
|
AC_DEFUN([AC_LIB_PREPARE_PREFIX],
|
||||||
|
[
|
||||||
|
dnl Unfortunately, prefix and exec_prefix get only finally determined
|
||||||
|
dnl at the end of configure.
|
||||||
|
if test "X$prefix" = "XNONE"; then
|
||||||
|
acl_final_prefix="$ac_default_prefix"
|
||||||
|
else
|
||||||
|
acl_final_prefix="$prefix"
|
||||||
|
fi
|
||||||
|
if test "X$exec_prefix" = "XNONE"; then
|
||||||
|
acl_final_exec_prefix='${prefix}'
|
||||||
|
else
|
||||||
|
acl_final_exec_prefix="$exec_prefix"
|
||||||
|
fi
|
||||||
|
acl_save_prefix="$prefix"
|
||||||
|
prefix="$acl_final_prefix"
|
||||||
|
eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
|
||||||
|
prefix="$acl_save_prefix"
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
|
||||||
|
dnl variables prefix and exec_prefix bound to the values they will have
|
||||||
|
dnl at the end of the configure script.
|
||||||
|
AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
|
||||||
|
[
|
||||||
|
acl_save_prefix="$prefix"
|
||||||
|
prefix="$acl_final_prefix"
|
||||||
|
acl_save_exec_prefix="$exec_prefix"
|
||||||
|
exec_prefix="$acl_final_exec_prefix"
|
||||||
|
$1
|
||||||
|
exec_prefix="$acl_save_exec_prefix"
|
||||||
|
prefix="$acl_save_prefix"
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl AC_LIB_PREPARE_MULTILIB creates
|
||||||
|
dnl - a variable acl_libdirstem, containing the basename of the libdir, either
|
||||||
|
dnl "lib" or "lib64" or "lib/64",
|
||||||
|
dnl - a variable acl_libdirstem2, as a secondary possible value for
|
||||||
|
dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or
|
||||||
|
dnl "lib/amd64".
|
||||||
|
AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
|
||||||
|
[
|
||||||
|
dnl There is no formal standard regarding lib and lib64.
|
||||||
|
dnl On glibc systems, the current practice is that on a system supporting
|
||||||
|
dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
|
||||||
|
dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine
|
||||||
|
dnl the compiler's default mode by looking at the compiler's library search
|
||||||
|
dnl path. If at least one of its elements ends in /lib64 or points to a
|
||||||
|
dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI.
|
||||||
|
dnl Otherwise we use the default, namely "lib".
|
||||||
|
dnl On Solaris systems, the current practice is that on a system supporting
|
||||||
|
dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
|
||||||
|
dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or
|
||||||
|
dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib.
|
||||||
|
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||||
|
acl_libdirstem=lib
|
||||||
|
acl_libdirstem2=
|
||||||
|
case "$host_os" in
|
||||||
|
solaris*)
|
||||||
|
dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment
|
||||||
|
dnl <http://docs.sun.com/app/docs/doc/816-5138/dev-env?l=en&a=view>.
|
||||||
|
dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link."
|
||||||
|
dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the
|
||||||
|
dnl symlink is missing, so we set acl_libdirstem2 too.
|
||||||
|
AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit],
|
||||||
|
[AC_EGREP_CPP([sixtyfour bits], [
|
||||||
|
#ifdef _LP64
|
||||||
|
sixtyfour bits
|
||||||
|
#endif
|
||||||
|
], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no])
|
||||||
|
])
|
||||||
|
if test $gl_cv_solaris_64bit = yes; then
|
||||||
|
acl_libdirstem=lib/64
|
||||||
|
case "$host_cpu" in
|
||||||
|
sparc*) acl_libdirstem2=lib/sparcv9 ;;
|
||||||
|
i*86 | x86_64) acl_libdirstem2=lib/amd64 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
|
||||||
|
if test -n "$searchpath"; then
|
||||||
|
acl_save_IFS="${IFS= }"; IFS=":"
|
||||||
|
for searchdir in $searchpath; do
|
||||||
|
if test -d "$searchdir"; then
|
||||||
|
case "$searchdir" in
|
||||||
|
*/lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
|
||||||
|
*/../ | */.. )
|
||||||
|
# Better ignore directories of this form. They are misleading.
|
||||||
|
;;
|
||||||
|
*) searchdir=`cd "$searchdir" && pwd`
|
||||||
|
case "$searchdir" in
|
||||||
|
*/lib64 ) acl_libdirstem=lib64 ;;
|
||||||
|
esac ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS="$acl_save_IFS"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem"
|
||||||
|
])
|
8387
m4/libtool.m4
vendored
Normal file
8387
m4/libtool.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
437
m4/ltoptions.m4
vendored
Normal file
437
m4/ltoptions.m4
vendored
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
# Helper functions for option handling. -*- Autoconf -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
|
||||||
|
# Foundation, Inc.
|
||||||
|
# Written by Gary V. Vaughan, 2004
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# serial 8 ltoptions.m4
|
||||||
|
|
||||||
|
# This is to help aclocal find these macros, as it can't see m4_define.
|
||||||
|
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
|
||||||
|
# ------------------------------------------
|
||||||
|
m4_define([_LT_MANGLE_OPTION],
|
||||||
|
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
|
||||||
|
# ---------------------------------------
|
||||||
|
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
|
||||||
|
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
|
||||||
|
# saved as a flag.
|
||||||
|
m4_define([_LT_SET_OPTION],
|
||||||
|
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
|
||||||
|
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
|
||||||
|
_LT_MANGLE_DEFUN([$1], [$2]),
|
||||||
|
[m4_warning([Unknown $1 option '$2'])])[]dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
|
||||||
|
m4_define([_LT_IF_OPTION],
|
||||||
|
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
|
||||||
|
# -------------------------------------------------------
|
||||||
|
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
|
||||||
|
# are set.
|
||||||
|
m4_define([_LT_UNLESS_OPTIONS],
|
||||||
|
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
|
||||||
|
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
|
||||||
|
[m4_define([$0_found])])])[]dnl
|
||||||
|
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
|
||||||
|
])[]dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
|
||||||
|
# ----------------------------------------
|
||||||
|
# OPTION-LIST is a space-separated list of Libtool options associated
|
||||||
|
# with MACRO-NAME. If any OPTION has a matching handler declared with
|
||||||
|
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
|
||||||
|
# the unknown option and exit.
|
||||||
|
m4_defun([_LT_SET_OPTIONS],
|
||||||
|
[# Set options
|
||||||
|
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
|
||||||
|
[_LT_SET_OPTION([$1], _LT_Option)])
|
||||||
|
|
||||||
|
m4_if([$1],[LT_INIT],[
|
||||||
|
dnl
|
||||||
|
dnl Simply set some default values (i.e off) if boolean options were not
|
||||||
|
dnl specified:
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
|
||||||
|
])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
|
||||||
|
])
|
||||||
|
dnl
|
||||||
|
dnl If no reference was made to various pairs of opposing options, then
|
||||||
|
dnl we run the default mode handler for the pair. For example, if neither
|
||||||
|
dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
|
||||||
|
dnl archives by default:
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
|
||||||
|
[_LT_ENABLE_FAST_INSTALL])
|
||||||
|
_LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
|
||||||
|
[_LT_WITH_AIX_SONAME([aix])])
|
||||||
|
])
|
||||||
|
])# _LT_SET_OPTIONS
|
||||||
|
|
||||||
|
|
||||||
|
## --------------------------------- ##
|
||||||
|
## Macros to handle LT_INIT options. ##
|
||||||
|
## --------------------------------- ##
|
||||||
|
|
||||||
|
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
|
||||||
|
# -----------------------------------------
|
||||||
|
m4_define([_LT_MANGLE_DEFUN],
|
||||||
|
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
|
||||||
|
|
||||||
|
|
||||||
|
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
|
||||||
|
# -----------------------------------------------
|
||||||
|
m4_define([LT_OPTION_DEFINE],
|
||||||
|
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
|
||||||
|
])# LT_OPTION_DEFINE
|
||||||
|
|
||||||
|
|
||||||
|
# dlopen
|
||||||
|
# ------
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
|
||||||
|
])
|
||||||
|
|
||||||
|
AU_DEFUN([AC_LIBTOOL_DLOPEN],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [dlopen])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you
|
||||||
|
put the 'dlopen' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
|
||||||
|
|
||||||
|
|
||||||
|
# win32-dll
|
||||||
|
# ---------
|
||||||
|
# Declare package support for building win32 dll's.
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
|
||||||
|
[enable_win32_dll=yes
|
||||||
|
|
||||||
|
case $host in
|
||||||
|
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
|
||||||
|
AC_CHECK_TOOL(AS, as, false)
|
||||||
|
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
|
||||||
|
AC_CHECK_TOOL(OBJDUMP, objdump, false)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
test -z "$AS" && AS=as
|
||||||
|
_LT_DECL([], [AS], [1], [Assembler program])dnl
|
||||||
|
|
||||||
|
test -z "$DLLTOOL" && DLLTOOL=dlltool
|
||||||
|
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
|
||||||
|
|
||||||
|
test -z "$OBJDUMP" && OBJDUMP=objdump
|
||||||
|
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
|
||||||
|
])# win32-dll
|
||||||
|
|
||||||
|
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
|
||||||
|
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||||
|
_LT_SET_OPTION([LT_INIT], [win32-dll])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you
|
||||||
|
put the 'win32-dll' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_ENABLE_SHARED([DEFAULT])
|
||||||
|
# ----------------------------
|
||||||
|
# implement the --enable-shared flag, and supports the 'shared' and
|
||||||
|
# 'disable-shared' LT_INIT options.
|
||||||
|
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
|
||||||
|
m4_define([_LT_ENABLE_SHARED],
|
||||||
|
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
|
||||||
|
AC_ARG_ENABLE([shared],
|
||||||
|
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
|
||||||
|
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
|
||||||
|
[p=${PACKAGE-default}
|
||||||
|
case $enableval in
|
||||||
|
yes) enable_shared=yes ;;
|
||||||
|
no) enable_shared=no ;;
|
||||||
|
*)
|
||||||
|
enable_shared=no
|
||||||
|
# Look at the argument we got. We use all the common list separators.
|
||||||
|
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
|
||||||
|
for pkg in $enableval; do
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
if test "X$pkg" = "X$p"; then
|
||||||
|
enable_shared=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
;;
|
||||||
|
esac],
|
||||||
|
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
|
||||||
|
|
||||||
|
_LT_DECL([build_libtool_libs], [enable_shared], [0],
|
||||||
|
[Whether or not to build shared libraries])
|
||||||
|
])# _LT_ENABLE_SHARED
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
|
||||||
|
|
||||||
|
# Old names:
|
||||||
|
AC_DEFUN([AC_ENABLE_SHARED],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([AC_DISABLE_SHARED],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [disable-shared])
|
||||||
|
])
|
||||||
|
|
||||||
|
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
|
||||||
|
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
|
||||||
|
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_ENABLE_STATIC([DEFAULT])
|
||||||
|
# ----------------------------
|
||||||
|
# implement the --enable-static flag, and support the 'static' and
|
||||||
|
# 'disable-static' LT_INIT options.
|
||||||
|
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
|
||||||
|
m4_define([_LT_ENABLE_STATIC],
|
||||||
|
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
|
||||||
|
AC_ARG_ENABLE([static],
|
||||||
|
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
|
||||||
|
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
|
||||||
|
[p=${PACKAGE-default}
|
||||||
|
case $enableval in
|
||||||
|
yes) enable_static=yes ;;
|
||||||
|
no) enable_static=no ;;
|
||||||
|
*)
|
||||||
|
enable_static=no
|
||||||
|
# Look at the argument we got. We use all the common list separators.
|
||||||
|
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
|
||||||
|
for pkg in $enableval; do
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
if test "X$pkg" = "X$p"; then
|
||||||
|
enable_static=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
;;
|
||||||
|
esac],
|
||||||
|
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
|
||||||
|
|
||||||
|
_LT_DECL([build_old_libs], [enable_static], [0],
|
||||||
|
[Whether or not to build static libraries])
|
||||||
|
])# _LT_ENABLE_STATIC
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
|
||||||
|
|
||||||
|
# Old names:
|
||||||
|
AC_DEFUN([AC_ENABLE_STATIC],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([AC_DISABLE_STATIC],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [disable-static])
|
||||||
|
])
|
||||||
|
|
||||||
|
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
|
||||||
|
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
|
||||||
|
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
|
||||||
|
# ----------------------------------
|
||||||
|
# implement the --enable-fast-install flag, and support the 'fast-install'
|
||||||
|
# and 'disable-fast-install' LT_INIT options.
|
||||||
|
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
|
||||||
|
m4_define([_LT_ENABLE_FAST_INSTALL],
|
||||||
|
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
|
||||||
|
AC_ARG_ENABLE([fast-install],
|
||||||
|
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
|
||||||
|
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
|
||||||
|
[p=${PACKAGE-default}
|
||||||
|
case $enableval in
|
||||||
|
yes) enable_fast_install=yes ;;
|
||||||
|
no) enable_fast_install=no ;;
|
||||||
|
*)
|
||||||
|
enable_fast_install=no
|
||||||
|
# Look at the argument we got. We use all the common list separators.
|
||||||
|
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
|
||||||
|
for pkg in $enableval; do
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
if test "X$pkg" = "X$p"; then
|
||||||
|
enable_fast_install=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
;;
|
||||||
|
esac],
|
||||||
|
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
|
||||||
|
|
||||||
|
_LT_DECL([fast_install], [enable_fast_install], [0],
|
||||||
|
[Whether or not to optimize for fast installation])dnl
|
||||||
|
])# _LT_ENABLE_FAST_INSTALL
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
|
||||||
|
|
||||||
|
# Old names:
|
||||||
|
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
|
||||||
|
the 'fast-install' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
|
||||||
|
the 'disable-fast-install' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
|
||||||
|
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_WITH_AIX_SONAME([DEFAULT])
|
||||||
|
# ----------------------------------
|
||||||
|
# implement the --with-aix-soname flag, and support the `aix-soname=aix'
|
||||||
|
# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
|
||||||
|
# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
|
||||||
|
m4_define([_LT_WITH_AIX_SONAME],
|
||||||
|
[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
|
||||||
|
shared_archive_member_spec=
|
||||||
|
case $host,$enable_shared in
|
||||||
|
power*-*-aix[[5-9]]*,yes)
|
||||||
|
AC_MSG_CHECKING([which variant of shared library versioning to provide])
|
||||||
|
AC_ARG_WITH([aix-soname],
|
||||||
|
[AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
|
||||||
|
[shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
|
||||||
|
[case $withval in
|
||||||
|
aix|svr4|both)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([Unknown argument to --with-aix-soname])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
lt_cv_with_aix_soname=$with_aix_soname],
|
||||||
|
[AC_CACHE_VAL([lt_cv_with_aix_soname],
|
||||||
|
[lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
|
||||||
|
with_aix_soname=$lt_cv_with_aix_soname])
|
||||||
|
AC_MSG_RESULT([$with_aix_soname])
|
||||||
|
if test aix != "$with_aix_soname"; then
|
||||||
|
# For the AIX way of multilib, we name the shared archive member
|
||||||
|
# based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
|
||||||
|
# and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
|
||||||
|
# Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
|
||||||
|
# the AIX toolchain works better with OBJECT_MODE set (default 32).
|
||||||
|
if test 64 = "${OBJECT_MODE-32}"; then
|
||||||
|
shared_archive_member_spec=shr_64
|
||||||
|
else
|
||||||
|
shared_archive_member_spec=shr
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
with_aix_soname=aix
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
_LT_DECL([], [shared_archive_member_spec], [0],
|
||||||
|
[Shared archive member basename, for filename based shared library versioning on AIX])dnl
|
||||||
|
])# _LT_WITH_AIX_SONAME
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
|
||||||
|
|
||||||
|
|
||||||
|
# _LT_WITH_PIC([MODE])
|
||||||
|
# --------------------
|
||||||
|
# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
|
||||||
|
# LT_INIT options.
|
||||||
|
# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
|
||||||
|
m4_define([_LT_WITH_PIC],
|
||||||
|
[AC_ARG_WITH([pic],
|
||||||
|
[AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
|
||||||
|
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
|
||||||
|
[lt_p=${PACKAGE-default}
|
||||||
|
case $withval in
|
||||||
|
yes|no) pic_mode=$withval ;;
|
||||||
|
*)
|
||||||
|
pic_mode=default
|
||||||
|
# Look at the argument we got. We use all the common list separators.
|
||||||
|
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
|
||||||
|
for lt_pkg in $withval; do
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
if test "X$lt_pkg" = "X$lt_p"; then
|
||||||
|
pic_mode=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$lt_save_ifs
|
||||||
|
;;
|
||||||
|
esac],
|
||||||
|
[pic_mode=m4_default([$1], [default])])
|
||||||
|
|
||||||
|
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
|
||||||
|
])# _LT_WITH_PIC
|
||||||
|
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
|
||||||
|
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
|
||||||
|
|
||||||
|
# Old name:
|
||||||
|
AU_DEFUN([AC_LIBTOOL_PICMODE],
|
||||||
|
[_LT_SET_OPTION([LT_INIT], [pic-only])
|
||||||
|
AC_DIAGNOSE([obsolete],
|
||||||
|
[$0: Remove this warning and the call to _LT_SET_OPTION when you
|
||||||
|
put the 'pic-only' option into LT_INIT's first parameter.])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl aclocal-1.4 backwards compatibility:
|
||||||
|
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
|
||||||
|
|
||||||
|
## ----------------- ##
|
||||||
|
## LTDL_INIT Options ##
|
||||||
|
## ----------------- ##
|
||||||
|
|
||||||
|
m4_define([_LTDL_MODE], [])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
|
||||||
|
[m4_define([_LTDL_MODE], [nonrecursive])])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
|
||||||
|
[m4_define([_LTDL_MODE], [recursive])])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
|
||||||
|
[m4_define([_LTDL_MODE], [subproject])])
|
||||||
|
|
||||||
|
m4_define([_LTDL_TYPE], [])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [installable],
|
||||||
|
[m4_define([_LTDL_TYPE], [installable])])
|
||||||
|
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
|
||||||
|
[m4_define([_LTDL_TYPE], [convenience])])
|
124
m4/ltsugar.m4
vendored
Normal file
124
m4/ltsugar.m4
vendored
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
|
||||||
|
# Foundation, Inc.
|
||||||
|
# Written by Gary V. Vaughan, 2004
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# serial 6 ltsugar.m4
|
||||||
|
|
||||||
|
# This is to help aclocal find these macros, as it can't see m4_define.
|
||||||
|
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_join(SEP, ARG1, [ARG2...])
|
||||||
|
# -----------------------------
|
||||||
|
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
|
||||||
|
# associated separator.
|
||||||
|
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
|
||||||
|
# versions in m4sugar had bugs.
|
||||||
|
m4_define([lt_join],
|
||||||
|
[m4_if([$#], [1], [],
|
||||||
|
[$#], [2], [[$2]],
|
||||||
|
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
|
||||||
|
m4_define([_lt_join],
|
||||||
|
[m4_if([$#$2], [2], [],
|
||||||
|
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_car(LIST)
|
||||||
|
# lt_cdr(LIST)
|
||||||
|
# ------------
|
||||||
|
# Manipulate m4 lists.
|
||||||
|
# These macros are necessary as long as will still need to support
|
||||||
|
# Autoconf-2.59, which quotes differently.
|
||||||
|
m4_define([lt_car], [[$1]])
|
||||||
|
m4_define([lt_cdr],
|
||||||
|
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
|
||||||
|
[$#], 1, [],
|
||||||
|
[m4_dquote(m4_shift($@))])])
|
||||||
|
m4_define([lt_unquote], $1)
|
||||||
|
|
||||||
|
|
||||||
|
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
|
||||||
|
# ------------------------------------------
|
||||||
|
# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
|
||||||
|
# Note that neither SEPARATOR nor STRING are expanded; they are appended
|
||||||
|
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
|
||||||
|
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
|
||||||
|
# than defined and empty).
|
||||||
|
#
|
||||||
|
# This macro is needed until we can rely on Autoconf 2.62, since earlier
|
||||||
|
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
|
||||||
|
m4_define([lt_append],
|
||||||
|
[m4_define([$1],
|
||||||
|
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# Produce a SEP delimited list of all paired combinations of elements of
|
||||||
|
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
|
||||||
|
# has the form PREFIXmINFIXSUFFIXn.
|
||||||
|
# Needed until we can rely on m4_combine added in Autoconf 2.62.
|
||||||
|
m4_define([lt_combine],
|
||||||
|
[m4_if(m4_eval([$# > 3]), [1],
|
||||||
|
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
|
||||||
|
[[m4_foreach([_Lt_prefix], [$2],
|
||||||
|
[m4_foreach([_Lt_suffix],
|
||||||
|
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
|
||||||
|
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
|
||||||
|
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
|
||||||
|
m4_define([lt_if_append_uniq],
|
||||||
|
[m4_ifdef([$1],
|
||||||
|
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
|
||||||
|
[lt_append([$1], [$2], [$3])$4],
|
||||||
|
[$5])],
|
||||||
|
[lt_append([$1], [$2], [$3])$4])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_dict_add(DICT, KEY, VALUE)
|
||||||
|
# -----------------------------
|
||||||
|
m4_define([lt_dict_add],
|
||||||
|
[m4_define([$1($2)], [$3])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
|
||||||
|
# --------------------------------------------
|
||||||
|
m4_define([lt_dict_add_subkey],
|
||||||
|
[m4_define([$1($2:$3)], [$4])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_dict_fetch(DICT, KEY, [SUBKEY])
|
||||||
|
# ----------------------------------
|
||||||
|
m4_define([lt_dict_fetch],
|
||||||
|
[m4_ifval([$3],
|
||||||
|
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
|
||||||
|
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
m4_define([lt_if_dict_fetch],
|
||||||
|
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
|
||||||
|
[$5],
|
||||||
|
[$6])])
|
||||||
|
|
||||||
|
|
||||||
|
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
|
||||||
|
# --------------------------------------------------------------
|
||||||
|
m4_define([lt_dict_filter],
|
||||||
|
[m4_if([$5], [], [],
|
||||||
|
[lt_join(m4_quote(m4_default([$4], [[, ]])),
|
||||||
|
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
|
||||||
|
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
|
||||||
|
])
|
23
m4/ltversion.m4
vendored
Normal file
23
m4/ltversion.m4
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# ltversion.m4 -- version numbers -*- Autoconf -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
|
||||||
|
# Written by Scott James Remnant, 2004
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# serial 4179 ltversion.m4
|
||||||
|
# This file is part of GNU Libtool
|
||||||
|
|
||||||
|
m4_define([LT_PACKAGE_VERSION], [2.4.6])
|
||||||
|
m4_define([LT_PACKAGE_REVISION], [2.4.6])
|
||||||
|
|
||||||
|
AC_DEFUN([LTVERSION_VERSION],
|
||||||
|
[macro_version='2.4.6'
|
||||||
|
macro_revision='2.4.6'
|
||||||
|
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
|
||||||
|
_LT_DECL(, macro_revision, 0)
|
||||||
|
])
|
99
m4/lt~obsolete.m4
vendored
Normal file
99
m4/lt~obsolete.m4
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
|
||||||
|
# Foundation, Inc.
|
||||||
|
# Written by Scott James Remnant, 2004.
|
||||||
|
#
|
||||||
|
# This file is free software; the Free Software Foundation gives
|
||||||
|
# unlimited permission to copy and/or distribute it, with or without
|
||||||
|
# modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# serial 5 lt~obsolete.m4
|
||||||
|
|
||||||
|
# These exist entirely to fool aclocal when bootstrapping libtool.
|
||||||
|
#
|
||||||
|
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
|
||||||
|
# which have later been changed to m4_define as they aren't part of the
|
||||||
|
# exported API, or moved to Autoconf or Automake where they belong.
|
||||||
|
#
|
||||||
|
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
|
||||||
|
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
|
||||||
|
# using a macro with the same name in our local m4/libtool.m4 it'll
|
||||||
|
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
|
||||||
|
# and doesn't know about Autoconf macros at all.)
|
||||||
|
#
|
||||||
|
# So we provide this file, which has a silly filename so it's always
|
||||||
|
# included after everything else. This provides aclocal with the
|
||||||
|
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
|
||||||
|
# because those macros already exist, or will be overwritten later.
|
||||||
|
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
|
||||||
|
#
|
||||||
|
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
|
||||||
|
# Yes, that means every name once taken will need to remain here until
|
||||||
|
# we give up compatibility with versions before 1.7, at which point
|
||||||
|
# we need to keep only those names which we still refer to.
|
||||||
|
|
||||||
|
# This is to help aclocal find these macros, as it can't see m4_define.
|
||||||
|
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
|
||||||
|
|
||||||
|
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
|
||||||
|
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
|
||||||
|
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
|
||||||
|
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
|
||||||
|
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
|
||||||
|
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
|
||||||
|
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
|
||||||
|
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
|
||||||
|
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
|
||||||
|
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
|
||||||
|
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
|
||||||
|
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
|
||||||
|
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
|
||||||
|
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
|
||||||
|
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
|
||||||
|
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
|
||||||
|
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
|
||||||
|
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
|
||||||
|
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
|
||||||
|
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
|
||||||
|
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
|
||||||
|
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
|
||||||
|
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
|
||||||
|
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
|
||||||
|
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
|
||||||
|
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
|
||||||
|
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
|
||||||
|
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
|
||||||
|
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
|
||||||
|
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
|
||||||
|
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
|
||||||
|
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
|
||||||
|
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
|
||||||
|
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
|
||||||
|
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
|
32
m4/nls.m4
Normal file
32
m4/nls.m4
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# nls.m4 serial 5 (gettext-0.18)
|
||||||
|
dnl Copyright (C) 1995-2003, 2005-2006, 2008-2010 Free Software Foundation,
|
||||||
|
dnl Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
dnl
|
||||||
|
dnl This file can can be used in projects which are not available under
|
||||||
|
dnl the GNU General Public License or the GNU Library General Public
|
||||||
|
dnl License but which still want to provide support for the GNU gettext
|
||||||
|
dnl functionality.
|
||||||
|
dnl Please note that the actual code of the GNU gettext library is covered
|
||||||
|
dnl by the GNU Library General Public License, and the rest of the GNU
|
||||||
|
dnl gettext package package is covered by the GNU General Public License.
|
||||||
|
dnl They are *not* in the public domain.
|
||||||
|
|
||||||
|
dnl Authors:
|
||||||
|
dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
|
||||||
|
dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
|
||||||
|
|
||||||
|
AC_PREREQ([2.50])
|
||||||
|
|
||||||
|
AC_DEFUN([AM_NLS],
|
||||||
|
[
|
||||||
|
AC_MSG_CHECKING([whether NLS is requested])
|
||||||
|
dnl Default is enabled NLS
|
||||||
|
AC_ARG_ENABLE([nls],
|
||||||
|
[ --disable-nls do not use Native Language Support],
|
||||||
|
USE_NLS=$enableval, USE_NLS=yes)
|
||||||
|
AC_MSG_RESULT([$USE_NLS])
|
||||||
|
AC_SUBST([USE_NLS])
|
||||||
|
])
|
57
m4/pkg.m4
Normal file
57
m4/pkg.m4
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
|
||||||
|
dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
|
||||||
|
dnl also defines GSTUFF_PKG_ERRORS on error
|
||||||
|
AC_DEFUN([PKG_CHECK_MODULES], [
|
||||||
|
succeeded=no
|
||||||
|
|
||||||
|
if test -z "$PKG_CONFIG"; then
|
||||||
|
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$PKG_CONFIG" = "no" ; then
|
||||||
|
echo "*** The pkg-config script could not be found. Make sure it is"
|
||||||
|
echo "*** in your path, or set the PKG_CONFIG environment variable"
|
||||||
|
echo "*** to the full path to pkg-config."
|
||||||
|
echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
|
||||||
|
else
|
||||||
|
PKG_CONFIG_MIN_VERSION=0.9.0
|
||||||
|
if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
|
||||||
|
AC_MSG_CHECKING(for $2)
|
||||||
|
|
||||||
|
if $PKG_CONFIG --exists "$2" ; then
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
succeeded=yes
|
||||||
|
|
||||||
|
AC_MSG_CHECKING($1_CFLAGS)
|
||||||
|
$1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
|
||||||
|
AC_MSG_RESULT($$1_CFLAGS)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING($1_LIBS)
|
||||||
|
$1_LIBS=`$PKG_CONFIG --libs "$2"`
|
||||||
|
AC_MSG_RESULT($$1_LIBS)
|
||||||
|
else
|
||||||
|
$1_CFLAGS=""
|
||||||
|
$1_LIBS=""
|
||||||
|
## If we have a custom action on failure, don't print errors, but
|
||||||
|
## do set a variable so people can do so.
|
||||||
|
$1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
|
||||||
|
ifelse([$4], ,echo $$1_PKG_ERRORS,)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST($1_CFLAGS)
|
||||||
|
AC_SUBST($1_LIBS)
|
||||||
|
else
|
||||||
|
echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
|
||||||
|
echo "*** See http://www.freedesktop.org/software/pkgconfig"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $succeeded = yes; then
|
||||||
|
ifelse([$3], , :, [$3])
|
||||||
|
else
|
||||||
|
ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
|
449
m4/po.m4
Normal file
449
m4/po.m4
Normal file
@ -0,0 +1,449 @@
|
|||||||
|
# po.m4 serial 17 (gettext-0.18)
|
||||||
|
dnl Copyright (C) 1995-2010 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
dnl
|
||||||
|
dnl This file can can be used in projects which are not available under
|
||||||
|
dnl the GNU General Public License or the GNU Library General Public
|
||||||
|
dnl License but which still want to provide support for the GNU gettext
|
||||||
|
dnl functionality.
|
||||||
|
dnl Please note that the actual code of the GNU gettext library is covered
|
||||||
|
dnl by the GNU Library General Public License, and the rest of the GNU
|
||||||
|
dnl gettext package package is covered by the GNU General Public License.
|
||||||
|
dnl They are *not* in the public domain.
|
||||||
|
|
||||||
|
dnl Authors:
|
||||||
|
dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
|
||||||
|
dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
|
||||||
|
|
||||||
|
AC_PREREQ([2.50])
|
||||||
|
|
||||||
|
dnl Checks for all prerequisites of the po subdirectory.
|
||||||
|
AC_DEFUN([AM_PO_SUBDIRS],
|
||||||
|
[
|
||||||
|
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
|
||||||
|
AC_REQUIRE([AC_PROG_INSTALL])dnl
|
||||||
|
AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake
|
||||||
|
AC_REQUIRE([AM_NLS])dnl
|
||||||
|
|
||||||
|
dnl Release version of the gettext macros. This is used to ensure that
|
||||||
|
dnl the gettext macros and po/Makefile.in.in are in sync.
|
||||||
|
AC_SUBST([GETTEXT_MACRO_VERSION], [0.18])
|
||||||
|
|
||||||
|
dnl Perform the following tests also if --disable-nls has been given,
|
||||||
|
dnl because they are needed for "make dist" to work.
|
||||||
|
|
||||||
|
dnl Search for GNU msgfmt in the PATH.
|
||||||
|
dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions.
|
||||||
|
dnl The second test excludes FreeBSD msgfmt.
|
||||||
|
AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
|
||||||
|
[$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 &&
|
||||||
|
(if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
|
||||||
|
:)
|
||||||
|
AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT])
|
||||||
|
|
||||||
|
dnl Test whether it is GNU msgfmt >= 0.15.
|
||||||
|
changequote(,)dnl
|
||||||
|
case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
|
||||||
|
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;;
|
||||||
|
*) MSGFMT_015=$MSGFMT ;;
|
||||||
|
esac
|
||||||
|
changequote([,])dnl
|
||||||
|
AC_SUBST([MSGFMT_015])
|
||||||
|
changequote(,)dnl
|
||||||
|
case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
|
||||||
|
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;;
|
||||||
|
*) GMSGFMT_015=$GMSGFMT ;;
|
||||||
|
esac
|
||||||
|
changequote([,])dnl
|
||||||
|
AC_SUBST([GMSGFMT_015])
|
||||||
|
|
||||||
|
dnl Search for GNU xgettext 0.12 or newer in the PATH.
|
||||||
|
dnl The first test excludes Solaris xgettext and early GNU xgettext versions.
|
||||||
|
dnl The second test excludes FreeBSD xgettext.
|
||||||
|
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
|
||||||
|
[$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 &&
|
||||||
|
(if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
|
||||||
|
:)
|
||||||
|
dnl Remove leftover from FreeBSD xgettext call.
|
||||||
|
rm -f messages.po
|
||||||
|
|
||||||
|
dnl Test whether it is GNU xgettext >= 0.15.
|
||||||
|
changequote(,)dnl
|
||||||
|
case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
|
||||||
|
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;;
|
||||||
|
*) XGETTEXT_015=$XGETTEXT ;;
|
||||||
|
esac
|
||||||
|
changequote([,])dnl
|
||||||
|
AC_SUBST([XGETTEXT_015])
|
||||||
|
|
||||||
|
dnl Search for GNU msgmerge 0.11 or newer in the PATH.
|
||||||
|
AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge,
|
||||||
|
[$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :)
|
||||||
|
|
||||||
|
dnl Installation directories.
|
||||||
|
dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we
|
||||||
|
dnl have to define it here, so that it can be used in po/Makefile.
|
||||||
|
test -n "$localedir" || localedir='${datadir}/locale'
|
||||||
|
AC_SUBST([localedir])
|
||||||
|
|
||||||
|
dnl Support for AM_XGETTEXT_OPTION.
|
||||||
|
test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS=
|
||||||
|
AC_SUBST([XGETTEXT_EXTRA_OPTIONS])
|
||||||
|
|
||||||
|
AC_CONFIG_COMMANDS([po-directories], [[
|
||||||
|
for ac_file in $CONFIG_FILES; do
|
||||||
|
# Support "outfile[:infile[:infile...]]"
|
||||||
|
case "$ac_file" in
|
||||||
|
*:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
|
||||||
|
esac
|
||||||
|
# PO directories have a Makefile.in generated from Makefile.in.in.
|
||||||
|
case "$ac_file" in */Makefile.in)
|
||||||
|
# Adjust a relative srcdir.
|
||||||
|
ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
|
||||||
|
ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`"
|
||||||
|
ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
|
||||||
|
# In autoconf-2.13 it is called $ac_given_srcdir.
|
||||||
|
# In autoconf-2.50 it is called $srcdir.
|
||||||
|
test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
|
||||||
|
case "$ac_given_srcdir" in
|
||||||
|
.) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
|
||||||
|
/*) top_srcdir="$ac_given_srcdir" ;;
|
||||||
|
*) top_srcdir="$ac_dots$ac_given_srcdir" ;;
|
||||||
|
esac
|
||||||
|
# Treat a directory as a PO directory if and only if it has a
|
||||||
|
# POTFILES.in file. This allows packages to have multiple PO
|
||||||
|
# directories under different names or in different locations.
|
||||||
|
if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then
|
||||||
|
rm -f "$ac_dir/POTFILES"
|
||||||
|
test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES"
|
||||||
|
cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES"
|
||||||
|
POMAKEFILEDEPS="POTFILES.in"
|
||||||
|
# ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend
|
||||||
|
# on $ac_dir but don't depend on user-specified configuration
|
||||||
|
# parameters.
|
||||||
|
if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
|
||||||
|
# The LINGUAS file contains the set of available languages.
|
||||||
|
if test -n "$OBSOLETE_ALL_LINGUAS"; then
|
||||||
|
test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
|
||||||
|
fi
|
||||||
|
ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
|
||||||
|
# Hide the ALL_LINGUAS assigment from automake < 1.5.
|
||||||
|
eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
|
||||||
|
POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
|
||||||
|
else
|
||||||
|
# The set of available languages was given in configure.in.
|
||||||
|
# Hide the ALL_LINGUAS assigment from automake < 1.5.
|
||||||
|
eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS'
|
||||||
|
fi
|
||||||
|
# Compute POFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
|
||||||
|
# Compute UPDATEPOFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
|
||||||
|
# Compute DUMMYPOFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
|
||||||
|
# Compute GMOFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
|
||||||
|
case "$ac_given_srcdir" in
|
||||||
|
.) srcdirpre= ;;
|
||||||
|
*) srcdirpre='$(srcdir)/' ;;
|
||||||
|
esac
|
||||||
|
POFILES=
|
||||||
|
UPDATEPOFILES=
|
||||||
|
DUMMYPOFILES=
|
||||||
|
GMOFILES=
|
||||||
|
for lang in $ALL_LINGUAS; do
|
||||||
|
POFILES="$POFILES $srcdirpre$lang.po"
|
||||||
|
UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
|
||||||
|
DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
|
||||||
|
GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
|
||||||
|
done
|
||||||
|
# CATALOGS depends on both $ac_dir and the user's LINGUAS
|
||||||
|
# environment variable.
|
||||||
|
INST_LINGUAS=
|
||||||
|
if test -n "$ALL_LINGUAS"; then
|
||||||
|
for presentlang in $ALL_LINGUAS; do
|
||||||
|
useit=no
|
||||||
|
if test "%UNSET%" != "$LINGUAS"; then
|
||||||
|
desiredlanguages="$LINGUAS"
|
||||||
|
else
|
||||||
|
desiredlanguages="$ALL_LINGUAS"
|
||||||
|
fi
|
||||||
|
for desiredlang in $desiredlanguages; do
|
||||||
|
# Use the presentlang catalog if desiredlang is
|
||||||
|
# a. equal to presentlang, or
|
||||||
|
# b. a variant of presentlang (because in this case,
|
||||||
|
# presentlang can be used as a fallback for messages
|
||||||
|
# which are not translated in the desiredlang catalog).
|
||||||
|
case "$desiredlang" in
|
||||||
|
"$presentlang"*) useit=yes;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if test $useit = yes; then
|
||||||
|
INST_LINGUAS="$INST_LINGUAS $presentlang"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
CATALOGS=
|
||||||
|
if test -n "$INST_LINGUAS"; then
|
||||||
|
for lang in $INST_LINGUAS; do
|
||||||
|
CATALOGS="$CATALOGS $lang.gmo"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile"
|
||||||
|
sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile"
|
||||||
|
for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do
|
||||||
|
if test -f "$f"; then
|
||||||
|
case "$f" in
|
||||||
|
*.orig | *.bak | *~) ;;
|
||||||
|
*) cat "$f" >> "$ac_dir/Makefile" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done]],
|
||||||
|
[# Capture the value of obsolete ALL_LINGUAS because we need it to compute
|
||||||
|
# POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it
|
||||||
|
# from automake < 1.5.
|
||||||
|
eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"'
|
||||||
|
# Capture the value of LINGUAS because we need it to compute CATALOGS.
|
||||||
|
LINGUAS="${LINGUAS-%UNSET%}"
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Postprocesses a Makefile in a directory containing PO files.
|
||||||
|
AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE],
|
||||||
|
[
|
||||||
|
# When this code is run, in config.status, two variables have already been
|
||||||
|
# set:
|
||||||
|
# - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in,
|
||||||
|
# - LINGUAS is the value of the environment variable LINGUAS at configure
|
||||||
|
# time.
|
||||||
|
|
||||||
|
changequote(,)dnl
|
||||||
|
# Adjust a relative srcdir.
|
||||||
|
ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
|
||||||
|
ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`"
|
||||||
|
ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
|
||||||
|
# In autoconf-2.13 it is called $ac_given_srcdir.
|
||||||
|
# In autoconf-2.50 it is called $srcdir.
|
||||||
|
test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
|
||||||
|
case "$ac_given_srcdir" in
|
||||||
|
.) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
|
||||||
|
/*) top_srcdir="$ac_given_srcdir" ;;
|
||||||
|
*) top_srcdir="$ac_dots$ac_given_srcdir" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Find a way to echo strings without interpreting backslash.
|
||||||
|
if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then
|
||||||
|
gt_echo='echo'
|
||||||
|
else
|
||||||
|
if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then
|
||||||
|
gt_echo='printf %s\n'
|
||||||
|
else
|
||||||
|
echo_func () {
|
||||||
|
cat <<EOT
|
||||||
|
$*
|
||||||
|
EOT
|
||||||
|
}
|
||||||
|
gt_echo='echo_func'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A sed script that extracts the value of VARIABLE from a Makefile.
|
||||||
|
sed_x_variable='
|
||||||
|
# Test if the hold space is empty.
|
||||||
|
x
|
||||||
|
s/P/P/
|
||||||
|
x
|
||||||
|
ta
|
||||||
|
# Yes it was empty. Look if we have the expected variable definition.
|
||||||
|
/^[ ]*VARIABLE[ ]*=/{
|
||||||
|
# Seen the first line of the variable definition.
|
||||||
|
s/^[ ]*VARIABLE[ ]*=//
|
||||||
|
ba
|
||||||
|
}
|
||||||
|
bd
|
||||||
|
:a
|
||||||
|
# Here we are processing a line from the variable definition.
|
||||||
|
# Remove comment, more precisely replace it with a space.
|
||||||
|
s/#.*$/ /
|
||||||
|
# See if the line ends in a backslash.
|
||||||
|
tb
|
||||||
|
:b
|
||||||
|
s/\\$//
|
||||||
|
# Print the line, without the trailing backslash.
|
||||||
|
p
|
||||||
|
tc
|
||||||
|
# There was no trailing backslash. The end of the variable definition is
|
||||||
|
# reached. Clear the hold space.
|
||||||
|
s/^.*$//
|
||||||
|
x
|
||||||
|
bd
|
||||||
|
:c
|
||||||
|
# A trailing backslash means that the variable definition continues in the
|
||||||
|
# next line. Put a nonempty string into the hold space to indicate this.
|
||||||
|
s/^.*$/P/
|
||||||
|
x
|
||||||
|
:d
|
||||||
|
'
|
||||||
|
changequote([,])dnl
|
||||||
|
|
||||||
|
# Set POTFILES to the value of the Makefile variable POTFILES.
|
||||||
|
sed_x_POTFILES=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/POTFILES/g'`
|
||||||
|
POTFILES=`sed -n -e "$sed_x_POTFILES" < "$ac_file"`
|
||||||
|
# Compute POTFILES_DEPS as
|
||||||
|
# $(foreach file, $(POTFILES), $(top_srcdir)/$(file))
|
||||||
|
POTFILES_DEPS=
|
||||||
|
for file in $POTFILES; do
|
||||||
|
POTFILES_DEPS="$POTFILES_DEPS "'$(top_srcdir)/'"$file"
|
||||||
|
done
|
||||||
|
POMAKEFILEDEPS=""
|
||||||
|
|
||||||
|
if test -n "$OBSOLETE_ALL_LINGUAS"; then
|
||||||
|
test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
|
||||||
|
fi
|
||||||
|
if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
|
||||||
|
# The LINGUAS file contains the set of available languages.
|
||||||
|
ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
|
||||||
|
POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
|
||||||
|
else
|
||||||
|
# Set ALL_LINGUAS to the value of the Makefile variable LINGUAS.
|
||||||
|
sed_x_LINGUAS=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'`
|
||||||
|
ALL_LINGUAS_=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"`
|
||||||
|
fi
|
||||||
|
# Hide the ALL_LINGUAS assigment from automake < 1.5.
|
||||||
|
eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
|
||||||
|
# Compute POFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
|
||||||
|
# Compute UPDATEPOFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
|
||||||
|
# Compute DUMMYPOFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
|
||||||
|
# Compute GMOFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
|
||||||
|
# Compute PROPERTIESFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).properties)
|
||||||
|
# Compute CLASSFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).class)
|
||||||
|
# Compute QMFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm)
|
||||||
|
# Compute MSGFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg)
|
||||||
|
# Compute RESOURCESDLLFILES
|
||||||
|
# as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll)
|
||||||
|
case "$ac_given_srcdir" in
|
||||||
|
.) srcdirpre= ;;
|
||||||
|
*) srcdirpre='$(srcdir)/' ;;
|
||||||
|
esac
|
||||||
|
POFILES=
|
||||||
|
UPDATEPOFILES=
|
||||||
|
DUMMYPOFILES=
|
||||||
|
GMOFILES=
|
||||||
|
PROPERTIESFILES=
|
||||||
|
CLASSFILES=
|
||||||
|
QMFILES=
|
||||||
|
MSGFILES=
|
||||||
|
RESOURCESDLLFILES=
|
||||||
|
for lang in $ALL_LINGUAS; do
|
||||||
|
POFILES="$POFILES $srcdirpre$lang.po"
|
||||||
|
UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
|
||||||
|
DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
|
||||||
|
GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
|
||||||
|
PROPERTIESFILES="$PROPERTIESFILES \$(top_srcdir)/\$(DOMAIN)_$lang.properties"
|
||||||
|
CLASSFILES="$CLASSFILES \$(top_srcdir)/\$(DOMAIN)_$lang.class"
|
||||||
|
QMFILES="$QMFILES $srcdirpre$lang.qm"
|
||||||
|
frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
|
||||||
|
MSGFILES="$MSGFILES $srcdirpre$frobbedlang.msg"
|
||||||
|
frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
|
||||||
|
RESOURCESDLLFILES="$RESOURCESDLLFILES $srcdirpre$frobbedlang/\$(DOMAIN).resources.dll"
|
||||||
|
done
|
||||||
|
# CATALOGS depends on both $ac_dir and the user's LINGUAS
|
||||||
|
# environment variable.
|
||||||
|
INST_LINGUAS=
|
||||||
|
if test -n "$ALL_LINGUAS"; then
|
||||||
|
for presentlang in $ALL_LINGUAS; do
|
||||||
|
useit=no
|
||||||
|
if test "%UNSET%" != "$LINGUAS"; then
|
||||||
|
desiredlanguages="$LINGUAS"
|
||||||
|
else
|
||||||
|
desiredlanguages="$ALL_LINGUAS"
|
||||||
|
fi
|
||||||
|
for desiredlang in $desiredlanguages; do
|
||||||
|
# Use the presentlang catalog if desiredlang is
|
||||||
|
# a. equal to presentlang, or
|
||||||
|
# b. a variant of presentlang (because in this case,
|
||||||
|
# presentlang can be used as a fallback for messages
|
||||||
|
# which are not translated in the desiredlang catalog).
|
||||||
|
case "$desiredlang" in
|
||||||
|
"$presentlang"*) useit=yes;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if test $useit = yes; then
|
||||||
|
INST_LINGUAS="$INST_LINGUAS $presentlang"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
CATALOGS=
|
||||||
|
JAVACATALOGS=
|
||||||
|
QTCATALOGS=
|
||||||
|
TCLCATALOGS=
|
||||||
|
CSHARPCATALOGS=
|
||||||
|
if test -n "$INST_LINGUAS"; then
|
||||||
|
for lang in $INST_LINGUAS; do
|
||||||
|
CATALOGS="$CATALOGS $lang.gmo"
|
||||||
|
JAVACATALOGS="$JAVACATALOGS \$(DOMAIN)_$lang.properties"
|
||||||
|
QTCATALOGS="$QTCATALOGS $lang.qm"
|
||||||
|
frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
|
||||||
|
TCLCATALOGS="$TCLCATALOGS $frobbedlang.msg"
|
||||||
|
frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
|
||||||
|
CSHARPCATALOGS="$CSHARPCATALOGS $frobbedlang/\$(DOMAIN).resources.dll"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e "s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e "s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$ac_file.tmp"
|
||||||
|
if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then
|
||||||
|
# Add dependencies that cannot be formulated as a simple suffix rule.
|
||||||
|
for lang in $ALL_LINGUAS; do
|
||||||
|
frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
|
||||||
|
cat >> "$ac_file.tmp" <<EOF
|
||||||
|
$frobbedlang.msg: $lang.po
|
||||||
|
@echo "\$(MSGFMT) -c --tcl -d \$(srcdir) -l $lang $srcdirpre$lang.po"; \
|
||||||
|
\$(MSGFMT) -c --tcl -d "\$(srcdir)" -l $lang $srcdirpre$lang.po || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if grep -l '@CSHARPCATALOGS@' "$ac_file" > /dev/null; then
|
||||||
|
# Add dependencies that cannot be formulated as a simple suffix rule.
|
||||||
|
for lang in $ALL_LINGUAS; do
|
||||||
|
frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
|
||||||
|
cat >> "$ac_file.tmp" <<EOF
|
||||||
|
$frobbedlang/\$(DOMAIN).resources.dll: $lang.po
|
||||||
|
@echo "\$(MSGFMT) -c --csharp -d \$(srcdir) -l $lang $srcdirpre$lang.po -r \$(DOMAIN)"; \
|
||||||
|
\$(MSGFMT) -c --csharp -d "\$(srcdir)" -l $lang $srcdirpre$lang.po -r "\$(DOMAIN)" || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
|
||||||
|
EOF
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if test -n "$POMAKEFILEDEPS"; then
|
||||||
|
cat >> "$ac_file.tmp" <<EOF
|
||||||
|
Makefile: $POMAKEFILEDEPS
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
mv "$ac_file.tmp" "$ac_file"
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Initializes the accumulator used by AM_XGETTEXT_OPTION.
|
||||||
|
AC_DEFUN([AM_XGETTEXT_OPTION_INIT],
|
||||||
|
[
|
||||||
|
XGETTEXT_EXTRA_OPTIONS=
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Registers an option to be passed to xgettext in the po subdirectory.
|
||||||
|
AC_DEFUN([AM_XGETTEXT_OPTION],
|
||||||
|
[
|
||||||
|
AC_REQUIRE([AM_XGETTEXT_OPTION_INIT])
|
||||||
|
XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS $1"
|
||||||
|
])
|
92
m4/progtest.m4
Normal file
92
m4/progtest.m4
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
# progtest.m4 serial 6 (gettext-0.18)
|
||||||
|
dnl Copyright (C) 1996-2003, 2005, 2008-2010 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
dnl
|
||||||
|
dnl This file can can be used in projects which are not available under
|
||||||
|
dnl the GNU General Public License or the GNU Library General Public
|
||||||
|
dnl License but which still want to provide support for the GNU gettext
|
||||||
|
dnl functionality.
|
||||||
|
dnl Please note that the actual code of the GNU gettext library is covered
|
||||||
|
dnl by the GNU Library General Public License, and the rest of the GNU
|
||||||
|
dnl gettext package package is covered by the GNU General Public License.
|
||||||
|
dnl They are *not* in the public domain.
|
||||||
|
|
||||||
|
dnl Authors:
|
||||||
|
dnl Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||||
|
|
||||||
|
AC_PREREQ([2.50])
|
||||||
|
|
||||||
|
# Search path for a program which passes the given test.
|
||||||
|
|
||||||
|
dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
|
||||||
|
dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
|
||||||
|
AC_DEFUN([AM_PATH_PROG_WITH_TEST],
|
||||||
|
[
|
||||||
|
# Prepare PATH_SEPARATOR.
|
||||||
|
# The user is always right.
|
||||||
|
if test "${PATH_SEPARATOR+set}" != set; then
|
||||||
|
echo "#! /bin/sh" >conf$$.sh
|
||||||
|
echo "exit 0" >>conf$$.sh
|
||||||
|
chmod +x conf$$.sh
|
||||||
|
if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
|
||||||
|
PATH_SEPARATOR=';'
|
||||||
|
else
|
||||||
|
PATH_SEPARATOR=:
|
||||||
|
fi
|
||||||
|
rm -f conf$$.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find out how to test for executable files. Don't use a zero-byte file,
|
||||||
|
# as systems may use methods other than mode bits to determine executability.
|
||||||
|
cat >conf$$.file <<_ASEOF
|
||||||
|
#! /bin/sh
|
||||||
|
exit 0
|
||||||
|
_ASEOF
|
||||||
|
chmod +x conf$$.file
|
||||||
|
if test -x conf$$.file >/dev/null 2>&1; then
|
||||||
|
ac_executable_p="test -x"
|
||||||
|
else
|
||||||
|
ac_executable_p="test -f"
|
||||||
|
fi
|
||||||
|
rm -f conf$$.file
|
||||||
|
|
||||||
|
# Extract the first word of "$2", so it can be a program name with args.
|
||||||
|
set dummy $2; ac_word=[$]2
|
||||||
|
AC_MSG_CHECKING([for $ac_word])
|
||||||
|
AC_CACHE_VAL([ac_cv_path_$1],
|
||||||
|
[case "[$]$1" in
|
||||||
|
[[\\/]]* | ?:[[\\/]]*)
|
||||||
|
ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR
|
||||||
|
for ac_dir in ifelse([$5], , $PATH, [$5]); do
|
||||||
|
IFS="$ac_save_IFS"
|
||||||
|
test -z "$ac_dir" && ac_dir=.
|
||||||
|
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||||
|
if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then
|
||||||
|
echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD
|
||||||
|
if [$3]; then
|
||||||
|
ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext"
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
IFS="$ac_save_IFS"
|
||||||
|
dnl If no 4th arg is given, leave the cache variable unset,
|
||||||
|
dnl so AC_PATH_PROGS will keep looking.
|
||||||
|
ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
|
||||||
|
])dnl
|
||||||
|
;;
|
||||||
|
esac])dnl
|
||||||
|
$1="$ac_cv_path_$1"
|
||||||
|
if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
|
||||||
|
AC_MSG_RESULT([$][$1])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
fi
|
||||||
|
AC_SUBST([$1])dnl
|
||||||
|
])
|
25
pkgconfig/Makefile.am
Normal file
25
pkgconfig/Makefile.am
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# This Makefile.am is in the public domain
|
||||||
|
pcfiles = \
|
||||||
|
gnunetmulticast.pc \
|
||||||
|
gnunetpsyc.pc \
|
||||||
|
gnunetpsycstore.pc
|
||||||
|
|
||||||
|
all-local: $(pcfiles)
|
||||||
|
|
||||||
|
cp_verbose = $(cp_verbose_$(V))
|
||||||
|
cp_verbose_ = $(cp_verbose_$(AM_DEFAULT_VERBOSITY))
|
||||||
|
cp_verbose_0 = @echo " CP $@";
|
||||||
|
|
||||||
|
%.pc: %.pc
|
||||||
|
$(cp_verbose_0)cp $< $@
|
||||||
|
|
||||||
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
pkgconfig_DATA = $(pcfiles)
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
gnunetmulticast.pc.in \
|
||||||
|
gnunetpsyc.pc.in \
|
||||||
|
gnunetpsycstore.pc.in
|
||||||
|
|
||||||
|
CLEANFILES = $(pcfiles)
|
||||||
|
AM_CPPFLAGS = -I$(top_srcdir)/src/include
|
12
pkgconfig/gnunetmulticast.pc.in
Normal file
12
pkgconfig/gnunetmulticast.pc.in
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: GNUnet MULTICAST
|
||||||
|
Description: library to multicast messages to a group of peers
|
||||||
|
URL: https://gnunet.org
|
||||||
|
Version: @VERSION@
|
||||||
|
Requires:
|
||||||
|
Libs: -L${libdir} -lgnunetmulticast
|
||||||
|
Cflags: -I${includedir}
|
12
pkgconfig/gnunetpsyc.pc.in
Normal file
12
pkgconfig/gnunetpsyc.pc.in
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: GNUnet PSYC
|
||||||
|
Description: library for PSYC multicast channel management
|
||||||
|
URL: https://gnunet.org
|
||||||
|
Version: @VERSION@
|
||||||
|
Requires:
|
||||||
|
Libs: -L${libdir} -lgnunetpsyc
|
||||||
|
Cflags: -I${includedir}
|
12
pkgconfig/gnunetpsycstore.pc.in
Normal file
12
pkgconfig/gnunetpsycstore.pc.in
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: GNUnet PSYCSTORE
|
||||||
|
Description: library to for persistent storage of PSYC messages
|
||||||
|
URL: https://gnunet.org
|
||||||
|
Version: @VERSION@
|
||||||
|
Requires:
|
||||||
|
Libs: -L${libdir} -lgnunetpsycstore
|
||||||
|
Cflags: -I${includedir}
|
6
po/.gitignore
vendored
Normal file
6
po/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Makefile.in
|
||||||
|
Makefile
|
||||||
|
POTFILES
|
||||||
|
gnunet-ext.pot
|
||||||
|
remove-potcdate.sed
|
||||||
|
stamp-po
|
12
po/ChangeLog
Normal file
12
po/ChangeLog
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
2012-03-07 gettextize <bug-gnu-gettext@gnu.org>
|
||||||
|
|
||||||
|
* Makefile.in.in: New file, from gettext-0.18.1.
|
||||||
|
* Rules-quot: New file, from gettext-0.18.1.
|
||||||
|
* boldquot.sed: New file, from gettext-0.18.1.
|
||||||
|
* en@boldquot.header: New file, from gettext-0.18.1.
|
||||||
|
* en@quot.header: New file, from gettext-0.18.1.
|
||||||
|
* insert-header.sin: New file, from gettext-0.18.1.
|
||||||
|
* quot.sed: New file, from gettext-0.18.1.
|
||||||
|
* remove-potcdate.sin: New file, from gettext-0.18.1.
|
||||||
|
* POTFILES.in: New file.
|
||||||
|
|
444
po/Makefile.in.in
Normal file
444
po/Makefile.in.in
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
# Makefile for PO directory in any package using GNU gettext.
|
||||||
|
# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||||
|
#
|
||||||
|
# This file can be copied and used freely without restrictions. It can
|
||||||
|
# be used in projects which are not available under the GNU General Public
|
||||||
|
# License but which still want to provide support for the GNU gettext
|
||||||
|
# functionality.
|
||||||
|
# Please note that the actual code of GNU gettext is covered by the GNU
|
||||||
|
# General Public License and is *not* in the public domain.
|
||||||
|
#
|
||||||
|
# Origin: gettext-0.18
|
||||||
|
GETTEXT_MACRO_VERSION = 0.18
|
||||||
|
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
srcdir = @srcdir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
prefix = @prefix@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
datadir = @datadir@
|
||||||
|
localedir = @localedir@
|
||||||
|
gettextsrcdir = $(datadir)/gettext/po
|
||||||
|
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
|
||||||
|
# We use $(mkdir_p).
|
||||||
|
# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as
|
||||||
|
# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions,
|
||||||
|
# @install_sh@ does not start with $(SHELL), so we add it.
|
||||||
|
# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined
|
||||||
|
# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake
|
||||||
|
# versions, $(mkinstalldirs) and $(install_sh) are unused.
|
||||||
|
mkinstalldirs = $(SHELL) @install_sh@ -d
|
||||||
|
install_sh = $(SHELL) @install_sh@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
|
||||||
|
GMSGFMT_ = @GMSGFMT@
|
||||||
|
GMSGFMT_no = @GMSGFMT@
|
||||||
|
GMSGFMT_yes = @GMSGFMT_015@
|
||||||
|
GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT))
|
||||||
|
MSGFMT_ = @MSGFMT@
|
||||||
|
MSGFMT_no = @MSGFMT@
|
||||||
|
MSGFMT_yes = @MSGFMT_015@
|
||||||
|
MSGFMT = $(MSGFMT_$(USE_MSGCTXT))
|
||||||
|
XGETTEXT_ = @XGETTEXT@
|
||||||
|
XGETTEXT_no = @XGETTEXT@
|
||||||
|
XGETTEXT_yes = @XGETTEXT_015@
|
||||||
|
XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
|
||||||
|
MSGMERGE = msgmerge
|
||||||
|
MSGMERGE_UPDATE = @MSGMERGE@ --update
|
||||||
|
MSGINIT = msginit
|
||||||
|
MSGCONV = msgconv
|
||||||
|
MSGFILTER = msgfilter
|
||||||
|
|
||||||
|
POFILES = @POFILES@
|
||||||
|
GMOFILES = @GMOFILES@
|
||||||
|
UPDATEPOFILES = @UPDATEPOFILES@
|
||||||
|
DUMMYPOFILES = @DUMMYPOFILES@
|
||||||
|
DISTFILES.common = Makefile.in.in remove-potcdate.sin \
|
||||||
|
$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3)
|
||||||
|
DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \
|
||||||
|
$(POFILES) $(GMOFILES) \
|
||||||
|
$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3)
|
||||||
|
|
||||||
|
POTFILES = \
|
||||||
|
|
||||||
|
CATALOGS = @CATALOGS@
|
||||||
|
|
||||||
|
# Makevars gets inserted here. (Don't remove this line!)
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update
|
||||||
|
|
||||||
|
.po.mo:
|
||||||
|
@echo "$(MSGFMT) -c -o $@ $<"; \
|
||||||
|
$(MSGFMT) -c -o t-$@ $< && mv t-$@ $@
|
||||||
|
|
||||||
|
.po.gmo:
|
||||||
|
@lang=`echo $* | sed -e 's,.*/,,'`; \
|
||||||
|
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||||
|
echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \
|
||||||
|
cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo
|
||||||
|
|
||||||
|
.sin.sed:
|
||||||
|
sed -e '/^#/d' $< > t-$@
|
||||||
|
mv t-$@ $@
|
||||||
|
|
||||||
|
|
||||||
|
all: check-macro-version all-@USE_NLS@
|
||||||
|
|
||||||
|
all-yes: stamp-po
|
||||||
|
all-no:
|
||||||
|
|
||||||
|
# Ensure that the gettext macros and this Makefile.in.in are in sync.
|
||||||
|
check-macro-version:
|
||||||
|
@test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \
|
||||||
|
|| { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \
|
||||||
|
exit 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no
|
||||||
|
# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because
|
||||||
|
# we don't want to bother translators with empty POT files). We assume that
|
||||||
|
# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty.
|
||||||
|
# In this case, stamp-po is a nop (i.e. a phony target).
|
||||||
|
|
||||||
|
# stamp-po is a timestamp denoting the last time at which the CATALOGS have
|
||||||
|
# been loosely updated. Its purpose is that when a developer or translator
|
||||||
|
# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS,
|
||||||
|
# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent
|
||||||
|
# invocations of "make" will do nothing. This timestamp would not be necessary
|
||||||
|
# if updating the $(CATALOGS) would always touch them; however, the rule for
|
||||||
|
# $(POFILES) has been designed to not touch files that don't need to be
|
||||||
|
# changed.
|
||||||
|
stamp-po: $(srcdir)/$(DOMAIN).pot
|
||||||
|
test ! -f $(srcdir)/$(DOMAIN).pot || \
|
||||||
|
test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
|
||||||
|
@test ! -f $(srcdir)/$(DOMAIN).pot || { \
|
||||||
|
echo "touch stamp-po" && \
|
||||||
|
echo timestamp > stamp-poT && \
|
||||||
|
mv stamp-poT stamp-po; \
|
||||||
|
}
|
||||||
|
|
||||||
|
# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update',
|
||||||
|
# otherwise packages like GCC can not be built if only parts of the source
|
||||||
|
# have been downloaded.
|
||||||
|
|
||||||
|
# This target rebuilds $(DOMAIN).pot; it is an expensive operation.
|
||||||
|
# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed.
|
||||||
|
$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
|
||||||
|
if LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null | grep -v 'libtool:' >/dev/null; then \
|
||||||
|
package_gnu='GNU '; \
|
||||||
|
else \
|
||||||
|
package_gnu=''; \
|
||||||
|
fi; \
|
||||||
|
if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \
|
||||||
|
msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \
|
||||||
|
else \
|
||||||
|
msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \
|
||||||
|
fi; \
|
||||||
|
case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||||
|
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \
|
||||||
|
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
|
||||||
|
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
|
||||||
|
--files-from=$(srcdir)/POTFILES.in \
|
||||||
|
--copyright-holder='$(COPYRIGHT_HOLDER)' \
|
||||||
|
--msgid-bugs-address="$$msgid_bugs_address" \
|
||||||
|
;; \
|
||||||
|
*) \
|
||||||
|
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
|
||||||
|
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
|
||||||
|
--files-from=$(srcdir)/POTFILES.in \
|
||||||
|
--copyright-holder='$(COPYRIGHT_HOLDER)' \
|
||||||
|
--package-name="$${package_gnu}@PACKAGE@" \
|
||||||
|
--package-version='@VERSION@' \
|
||||||
|
--msgid-bugs-address="$$msgid_bugs_address" \
|
||||||
|
;; \
|
||||||
|
esac
|
||||||
|
test ! -f $(DOMAIN).po || { \
|
||||||
|
if test -f $(srcdir)/$(DOMAIN).pot; then \
|
||||||
|
sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
|
||||||
|
sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \
|
||||||
|
if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \
|
||||||
|
rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \
|
||||||
|
else \
|
||||||
|
rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \
|
||||||
|
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
|
||||||
|
fi; \
|
||||||
|
else \
|
||||||
|
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
|
||||||
|
fi; \
|
||||||
|
}
|
||||||
|
|
||||||
|
# This rule has no dependencies: we don't need to update $(DOMAIN).pot at
|
||||||
|
# every "make" invocation, only create it when it is missing.
|
||||||
|
# Only "make $(DOMAIN).pot-update" or "make dist" will force an update.
|
||||||
|
$(srcdir)/$(DOMAIN).pot:
|
||||||
|
$(MAKE) $(DOMAIN).pot-update
|
||||||
|
|
||||||
|
# This target rebuilds a PO file if $(DOMAIN).pot has changed.
|
||||||
|
# Note that a PO file is not touched if it doesn't need to be changed.
|
||||||
|
$(POFILES): $(srcdir)/$(DOMAIN).pot
|
||||||
|
@lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
|
||||||
|
if test -f "$(srcdir)/$${lang}.po"; then \
|
||||||
|
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||||
|
echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \
|
||||||
|
cd $(srcdir) \
|
||||||
|
&& { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||||
|
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \
|
||||||
|
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
|
||||||
|
*) \
|
||||||
|
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \
|
||||||
|
esac; \
|
||||||
|
}; \
|
||||||
|
else \
|
||||||
|
$(MAKE) $${lang}.po-create; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
install: install-exec install-data
|
||||||
|
install-exec:
|
||||||
|
install-data: install-data-@USE_NLS@
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||||
|
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
|
||||||
|
for file in $(DISTFILES.common) Makevars.template; do \
|
||||||
|
$(INSTALL_DATA) $(srcdir)/$$file \
|
||||||
|
$(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||||
|
done; \
|
||||||
|
for file in Makevars; do \
|
||||||
|
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||||
|
done; \
|
||||||
|
else \
|
||||||
|
: ; \
|
||||||
|
fi
|
||||||
|
install-data-no: all
|
||||||
|
install-data-yes: all
|
||||||
|
@catalogs='$(CATALOGS)'; \
|
||||||
|
for cat in $$catalogs; do \
|
||||||
|
cat=`basename $$cat`; \
|
||||||
|
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||||
|
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||||
|
$(mkdir_p) $(DESTDIR)$$dir; \
|
||||||
|
if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \
|
||||||
|
$(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \
|
||||||
|
echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \
|
||||||
|
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
|
||||||
|
if test -n "$$lc"; then \
|
||||||
|
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
|
||||||
|
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
|
||||||
|
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||||
|
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
|
||||||
|
for file in *; do \
|
||||||
|
if test -f $$file; then \
|
||||||
|
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
|
||||||
|
fi; \
|
||||||
|
done); \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||||
|
else \
|
||||||
|
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
|
||||||
|
:; \
|
||||||
|
else \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||||
|
ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
|
||||||
|
ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
|
||||||
|
cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||||
|
echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
|
||||||
|
install-strip: install
|
||||||
|
|
||||||
|
installdirs: installdirs-exec installdirs-data
|
||||||
|
installdirs-exec:
|
||||||
|
installdirs-data: installdirs-data-@USE_NLS@
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||||
|
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
|
||||||
|
else \
|
||||||
|
: ; \
|
||||||
|
fi
|
||||||
|
installdirs-data-no:
|
||||||
|
installdirs-data-yes:
|
||||||
|
@catalogs='$(CATALOGS)'; \
|
||||||
|
for cat in $$catalogs; do \
|
||||||
|
cat=`basename $$cat`; \
|
||||||
|
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||||
|
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||||
|
$(mkdir_p) $(DESTDIR)$$dir; \
|
||||||
|
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
|
||||||
|
if test -n "$$lc"; then \
|
||||||
|
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
|
||||||
|
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
|
||||||
|
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||||
|
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
|
||||||
|
for file in *; do \
|
||||||
|
if test -f $$file; then \
|
||||||
|
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
|
||||||
|
fi; \
|
||||||
|
done); \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||||
|
else \
|
||||||
|
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
|
||||||
|
:; \
|
||||||
|
else \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
|
||||||
|
# Define this as empty until I found a useful application.
|
||||||
|
installcheck:
|
||||||
|
|
||||||
|
uninstall: uninstall-exec uninstall-data
|
||||||
|
uninstall-exec:
|
||||||
|
uninstall-data: uninstall-data-@USE_NLS@
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||||
|
for file in $(DISTFILES.common) Makevars.template; do \
|
||||||
|
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||||
|
done; \
|
||||||
|
else \
|
||||||
|
: ; \
|
||||||
|
fi
|
||||||
|
uninstall-data-no:
|
||||||
|
uninstall-data-yes:
|
||||||
|
catalogs='$(CATALOGS)'; \
|
||||||
|
for cat in $$catalogs; do \
|
||||||
|
cat=`basename $$cat`; \
|
||||||
|
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||||
|
for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
|
||||||
|
check: all
|
||||||
|
|
||||||
|
info dvi ps pdf html tags TAGS ctags CTAGS ID:
|
||||||
|
|
||||||
|
mostlyclean:
|
||||||
|
rm -f remove-potcdate.sed
|
||||||
|
rm -f stamp-poT
|
||||||
|
rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
|
||||||
|
rm -fr *.o
|
||||||
|
|
||||||
|
clean: mostlyclean
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
rm -f Makefile Makefile.in POTFILES *.mo
|
||||||
|
|
||||||
|
maintainer-clean: distclean
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
rm -f stamp-po $(GMOFILES)
|
||||||
|
|
||||||
|
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||||
|
dist distdir:
|
||||||
|
$(MAKE) update-po
|
||||||
|
@$(MAKE) dist2
|
||||||
|
# This is a separate target because 'update-po' must be executed before.
|
||||||
|
dist2: stamp-po $(DISTFILES)
|
||||||
|
dists="$(DISTFILES)"; \
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||||
|
dists="$$dists Makevars.template"; \
|
||||||
|
fi; \
|
||||||
|
if test -f $(srcdir)/$(DOMAIN).pot; then \
|
||||||
|
dists="$$dists $(DOMAIN).pot stamp-po"; \
|
||||||
|
fi; \
|
||||||
|
if test -f $(srcdir)/ChangeLog; then \
|
||||||
|
dists="$$dists ChangeLog"; \
|
||||||
|
fi; \
|
||||||
|
for i in 0 1 2 3 4 5 6 7 8 9; do \
|
||||||
|
if test -f $(srcdir)/ChangeLog.$$i; then \
|
||||||
|
dists="$$dists ChangeLog.$$i"; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \
|
||||||
|
for file in $$dists; do \
|
||||||
|
if test -f $$file; then \
|
||||||
|
cp -p $$file $(distdir) || exit 1; \
|
||||||
|
else \
|
||||||
|
cp -p $(srcdir)/$$file $(distdir) || exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
update-po: Makefile
|
||||||
|
$(MAKE) $(DOMAIN).pot-update
|
||||||
|
test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
|
||||||
|
$(MAKE) update-gmo
|
||||||
|
|
||||||
|
# General rule for creating PO files.
|
||||||
|
|
||||||
|
.nop.po-create:
|
||||||
|
@lang=`echo $@ | sed -e 's/\.po-create$$//'`; \
|
||||||
|
echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
# General rule for updating PO files.
|
||||||
|
|
||||||
|
.nop.po-update:
|
||||||
|
@lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \
|
||||||
|
tmpdir=`pwd`; \
|
||||||
|
echo "$$lang:"; \
|
||||||
|
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||||
|
echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
|
||||||
|
cd $(srcdir); \
|
||||||
|
if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||||
|
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \
|
||||||
|
$(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
|
||||||
|
*) \
|
||||||
|
$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
|
||||||
|
esac; \
|
||||||
|
}; then \
|
||||||
|
if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
|
||||||
|
rm -f $$tmpdir/$$lang.new.po; \
|
||||||
|
else \
|
||||||
|
if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
|
||||||
|
:; \
|
||||||
|
else \
|
||||||
|
echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
else \
|
||||||
|
echo "msgmerge for $$lang.po failed!" 1>&2; \
|
||||||
|
rm -f $$tmpdir/$$lang.new.po; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
$(DUMMYPOFILES):
|
||||||
|
|
||||||
|
update-gmo: Makefile $(GMOFILES)
|
||||||
|
@:
|
||||||
|
|
||||||
|
# Recreate Makefile by invoking config.status. Explicitly invoke the shell,
|
||||||
|
# because execution permission bits may not work on the current file system.
|
||||||
|
# Use @SHELL@, which is the shell determined by autoconf for the use by its
|
||||||
|
# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient.
|
||||||
|
Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@
|
||||||
|
cd $(top_builddir) \
|
||||||
|
&& @SHELL@ ./config.status $(subdir)/$@.in po-directories
|
||||||
|
|
||||||
|
force:
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make not to export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
41
po/Makevars
Normal file
41
po/Makevars
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Makefile variables for PO directory in any package using GNU gettext.
|
||||||
|
|
||||||
|
# Usually the message domain is the same as the package name.
|
||||||
|
DOMAIN = $(PACKAGE)
|
||||||
|
|
||||||
|
# These two variables depend on the location of this directory.
|
||||||
|
subdir = po
|
||||||
|
top_builddir = ..
|
||||||
|
|
||||||
|
# These options get passed to xgettext.
|
||||||
|
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
|
||||||
|
|
||||||
|
# This is the copyright holder that gets inserted into the header of the
|
||||||
|
# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
|
||||||
|
# package. (Note that the msgstr strings, extracted from the package's
|
||||||
|
# sources, belong to the copyright holder of the package.) Translators are
|
||||||
|
# expected to transfer the copyright for their translations to this person
|
||||||
|
# or entity, or to disclaim their copyright. The empty string stands for
|
||||||
|
# the public domain; in this case the translators are expected to disclaim
|
||||||
|
# their copyright.
|
||||||
|
COPYRIGHT_HOLDER = Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This is the email address or URL to which the translators shall report
|
||||||
|
# bugs in the untranslated strings:
|
||||||
|
# - Strings which are not entire sentences, see the maintainer guidelines
|
||||||
|
# in the GNU gettext documentation, section 'Preparing Strings'.
|
||||||
|
# - Strings which use unclear terms or require additional context to be
|
||||||
|
# understood.
|
||||||
|
# - Strings which make invalid assumptions about notation of date, time or
|
||||||
|
# money.
|
||||||
|
# - Pluralisation problems.
|
||||||
|
# - Incorrect English spelling.
|
||||||
|
# - Incorrect formatting.
|
||||||
|
# It can be your email address, or a mailing list address where translators
|
||||||
|
# can write to without being subscribed, or the URL of a web page through
|
||||||
|
# which the translators can contact you.
|
||||||
|
MSGID_BUGS_ADDRESS =
|
||||||
|
|
||||||
|
# This is the list of locale categories, beyond LC_MESSAGES, for which the
|
||||||
|
# message catalogs shall be used. It is usually empty.
|
||||||
|
EXTRA_LOCALE_CATEGORIES =
|
2
po/POTFILES.in
Normal file
2
po/POTFILES.in
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# List of source files which contain translatable strings.
|
||||||
|
src/ext/gnunet-ext.c
|
47
po/Rules-quot
Normal file
47
po/Rules-quot
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# Special Makefile rules for English message catalogs with quotation marks.
|
||||||
|
|
||||||
|
DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot
|
||||||
|
|
||||||
|
.SUFFIXES: .insert-header .po-update-en
|
||||||
|
|
||||||
|
en@quot.po-create:
|
||||||
|
$(MAKE) en@quot.po-update
|
||||||
|
en@boldquot.po-create:
|
||||||
|
$(MAKE) en@boldquot.po-update
|
||||||
|
|
||||||
|
en@quot.po-update: en@quot.po-update-en
|
||||||
|
en@boldquot.po-update: en@boldquot.po-update-en
|
||||||
|
|
||||||
|
.insert-header.po-update-en:
|
||||||
|
@lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \
|
||||||
|
if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \
|
||||||
|
tmpdir=`pwd`; \
|
||||||
|
echo "$$lang:"; \
|
||||||
|
ll=`echo $$lang | sed -e 's/@.*//'`; \
|
||||||
|
LC_ALL=C; export LC_ALL; \
|
||||||
|
cd $(srcdir); \
|
||||||
|
if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \
|
||||||
|
if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
|
||||||
|
rm -f $$tmpdir/$$lang.new.po; \
|
||||||
|
else \
|
||||||
|
if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
|
||||||
|
:; \
|
||||||
|
else \
|
||||||
|
echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
else \
|
||||||
|
echo "creation of $$lang.po failed!" 1>&2; \
|
||||||
|
rm -f $$tmpdir/$$lang.new.po; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
en@quot.insert-header: insert-header.sin
|
||||||
|
sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header
|
||||||
|
|
||||||
|
en@boldquot.insert-header: insert-header.sin
|
||||||
|
sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-quot
|
||||||
|
mostlyclean-quot:
|
||||||
|
rm -f *.insert-header
|
10
po/boldquot.sed
Normal file
10
po/boldquot.sed
Normal file
@ -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
|
25
po/en@boldquot.header
Normal file
25
po/en@boldquot.header
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# All this catalog "translates" are quotation characters.
|
||||||
|
# The msgids must be ASCII and therefore cannot contain real quotation
|
||||||
|
# characters, only substitutes like grave accent (0x60), apostrophe (0x27)
|
||||||
|
# and double quote (0x22). These substitutes look strange; see
|
||||||
|
# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html
|
||||||
|
#
|
||||||
|
# This catalog translates grave accent (0x60) and apostrophe (0x27) to
|
||||||
|
# left single quotation mark (U+2018) and right single quotation mark (U+2019).
|
||||||
|
# It also translates pairs of apostrophe (0x27) to
|
||||||
|
# left single quotation mark (U+2018) and right single quotation mark (U+2019)
|
||||||
|
# and pairs of quotation mark (0x22) to
|
||||||
|
# left double quotation mark (U+201C) and right double quotation mark (U+201D).
|
||||||
|
#
|
||||||
|
# When output to an UTF-8 terminal, the quotation characters appear perfectly.
|
||||||
|
# When output to an ISO-8859-1 terminal, the single quotation marks are
|
||||||
|
# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to
|
||||||
|
# grave/acute accent (by libiconv), and the double quotation marks are
|
||||||
|
# transliterated to 0x22.
|
||||||
|
# When output to an ASCII terminal, the single quotation marks are
|
||||||
|
# transliterated to apostrophes, and the double quotation marks are
|
||||||
|
# transliterated to 0x22.
|
||||||
|
#
|
||||||
|
# This catalog furthermore displays the text between the quotation marks in
|
||||||
|
# bold face, assuming the VT100/XTerm escape sequences.
|
||||||
|
#
|
22
po/en@quot.header
Normal file
22
po/en@quot.header
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# All this catalog "translates" are quotation characters.
|
||||||
|
# The msgids must be ASCII and therefore cannot contain real quotation
|
||||||
|
# characters, only substitutes like grave accent (0x60), apostrophe (0x27)
|
||||||
|
# and double quote (0x22). These substitutes look strange; see
|
||||||
|
# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html
|
||||||
|
#
|
||||||
|
# This catalog translates grave accent (0x60) and apostrophe (0x27) to
|
||||||
|
# left single quotation mark (U+2018) and right single quotation mark (U+2019).
|
||||||
|
# It also translates pairs of apostrophe (0x27) to
|
||||||
|
# left single quotation mark (U+2018) and right single quotation mark (U+2019)
|
||||||
|
# and pairs of quotation mark (0x22) to
|
||||||
|
# left double quotation mark (U+201C) and right double quotation mark (U+201D).
|
||||||
|
#
|
||||||
|
# When output to an UTF-8 terminal, the quotation characters appear perfectly.
|
||||||
|
# When output to an ISO-8859-1 terminal, the single quotation marks are
|
||||||
|
# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to
|
||||||
|
# grave/acute accent (by libiconv), and the double quotation marks are
|
||||||
|
# transliterated to 0x22.
|
||||||
|
# When output to an ASCII terminal, the single quotation marks are
|
||||||
|
# transliterated to apostrophes, and the double quotation marks are
|
||||||
|
# transliterated to 0x22.
|
||||||
|
#
|
23
po/insert-header.sin
Normal file
23
po/insert-header.sin
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Sed script that inserts the file called HEADER before the header entry.
|
||||||
|
#
|
||||||
|
# At each occurrence of a line starting with "msgid ", we execute the following
|
||||||
|
# commands. At the first occurrence, insert the file. At the following
|
||||||
|
# occurrences, do nothing. The distinction between the first and the following
|
||||||
|
# occurrences is achieved by looking at the hold space.
|
||||||
|
/^msgid /{
|
||||||
|
x
|
||||||
|
# Test if the hold space is empty.
|
||||||
|
s/m/m/
|
||||||
|
ta
|
||||||
|
# Yes it was empty. First occurrence. Read the file.
|
||||||
|
r HEADER
|
||||||
|
# Output the file's contents by reading the next line. But don't lose the
|
||||||
|
# current line while doing this.
|
||||||
|
g
|
||||||
|
N
|
||||||
|
bb
|
||||||
|
:a
|
||||||
|
# The hold space was nonempty. Following occurrences. Do nothing.
|
||||||
|
x
|
||||||
|
:b
|
||||||
|
}
|
6
po/quot.sed
Normal file
6
po/quot.sed
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
s/"\([^"]*\)"/“\1”/g
|
||||||
|
s/`\([^`']*\)'/‘\1’/g
|
||||||
|
s/ '\([^`']*\)' / ‘\1’ /g
|
||||||
|
s/ '\([^`']*\)'$/ ‘\1’/g
|
||||||
|
s/^'\([^`']*\)' /‘\1’ /g
|
||||||
|
s/“”/""/g
|
19
po/remove-potcdate.sin
Normal file
19
po/remove-potcdate.sin
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Sed script that remove the POT-Creation-Date line in the header entry
|
||||||
|
# from a POT file.
|
||||||
|
#
|
||||||
|
# The distinction between the first and the following occurrences of the
|
||||||
|
# pattern is achieved by looking at the hold space.
|
||||||
|
/^"POT-Creation-Date: .*"$/{
|
||||||
|
x
|
||||||
|
# Test if the hold space is empty.
|
||||||
|
s/P/P/
|
||||||
|
ta
|
||||||
|
# Yes it was empty. First occurrence. Remove the line.
|
||||||
|
g
|
||||||
|
d
|
||||||
|
bb
|
||||||
|
:a
|
||||||
|
# The hold space was nonempty. Following occurrences. Do nothing.
|
||||||
|
x
|
||||||
|
:b
|
||||||
|
}
|
2
src/.gitignore
vendored
Normal file
2
src/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Makefile
|
||||||
|
Makefile.in
|
7
src/Makefile.am
Normal file
7
src/Makefile.am
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# This Makefile.am is in the public domain
|
||||||
|
SUBDIRS = include \
|
||||||
|
multicast \
|
||||||
|
psycutil \
|
||||||
|
psycstore \
|
||||||
|
psyc \
|
||||||
|
social
|
2
src/include/.gitignore
vendored
Normal file
2
src/include/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Makefile
|
||||||
|
Makefile.in
|
15
src/include/Makefile.am
Normal file
15
src/include/Makefile.am
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# This Makefile.am is in the public domain
|
||||||
|
SUBDIRS = .
|
||||||
|
|
||||||
|
gnunetincludedir = $(includedir)/gnunet
|
||||||
|
|
||||||
|
gnunetinclude_HEADERS = \
|
||||||
|
gnunet_multicast_service.h \
|
||||||
|
gnunet_psycstore_plugin.h \
|
||||||
|
gnunet_psycstore_service.h \
|
||||||
|
gnunet_psyc_service.h \
|
||||||
|
gnunet_psyc_util_lib.h \
|
||||||
|
gnunet_psyc_env.h \
|
||||||
|
gnunet_psyc_message.h \
|
||||||
|
gnunet_psyc_slicer.h \
|
||||||
|
gnunet_social_service.h
|
925
src/include/gnunet_multicast_service.h
Normal file
925
src/include/gnunet_multicast_service.h
Normal file
@ -0,0 +1,925 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNUnet.
|
||||||
|
Copyright (C) 2012, 2013 GNUnet e.V.
|
||||||
|
|
||||||
|
GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* Multicast service; multicast messaging via CADET
|
||||||
|
*
|
||||||
|
* @defgroup multicast Multicast service
|
||||||
|
* Multicast messaging via CADET.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNUNET_MULTICAST_SERVICE_H
|
||||||
|
#define GNUNET_MULTICAST_SERVICE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_transport_service.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version number of GNUnet-multicast API.
|
||||||
|
*/
|
||||||
|
#define GNUNET_MULTICAST_VERSION 0x00000000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opaque handle for a multicast group member.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_Member;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for the origin of a multicast group.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_Origin;
|
||||||
|
|
||||||
|
|
||||||
|
enum GNUNET_MULTICAST_MessageFlags
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* First fragment of a message.
|
||||||
|
*/
|
||||||
|
GNUNET_MULTICAST_MESSAGE_FIRST_FRAGMENT = 1 << 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last fragment of a message.
|
||||||
|
*/
|
||||||
|
GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT = 1 << 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OR'ed flags if message is not fragmented.
|
||||||
|
*/
|
||||||
|
GNUNET_MULTICAST_MESSAGE_NOT_FRAGMENTED
|
||||||
|
= GNUNET_MULTICAST_MESSAGE_FIRST_FRAGMENT
|
||||||
|
| GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Historic message, used only locally when replaying messages from local
|
||||||
|
* storage.
|
||||||
|
*/
|
||||||
|
GNUNET_MULTICAST_MESSAGE_HISTORIC = 1 << 30
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header of a multicast message fragment.
|
||||||
|
*
|
||||||
|
* This format is public as the replay mechanism must replay message fragments using the
|
||||||
|
* same format. This is needed as we want to integrity-check message fragments within
|
||||||
|
* the multicast layer to avoid multicasting mal-formed messages.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header for all multicast message fragments from the origin.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of hops this message fragment has taken since the origin.
|
||||||
|
*
|
||||||
|
* Helpful to determine shortest paths to the origin among honest peers for
|
||||||
|
* unicast requests from members. Updated at each hop and thus not signed and
|
||||||
|
* not secure.
|
||||||
|
*/
|
||||||
|
uint32_t hop_counter GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ECC signature of the message fragment.
|
||||||
|
*
|
||||||
|
* Signature must match the public key of the multicast group.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaSignature signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purpose for the signature and size of the signed data.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of the message fragment, monotonically increasing starting from 1.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte offset of this @e fragment of the @e message.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_offset GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of the message this fragment belongs to.
|
||||||
|
*
|
||||||
|
* Set in GNUNET_MULTICAST_origin_to_all().
|
||||||
|
*/
|
||||||
|
uint64_t message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counter that monotonically increases whenever a member parts the group.
|
||||||
|
*
|
||||||
|
* Set in GNUNET_MULTICAST_origin_to_all().
|
||||||
|
*
|
||||||
|
* It has significance in case of replay requests: when a member has missed
|
||||||
|
* messages and gets a replay request: in this case if the @a group_generation
|
||||||
|
* is still the same before and after the missed messages, it means that no
|
||||||
|
* @e join or @e part operations happened during the missed messages.
|
||||||
|
*/
|
||||||
|
uint64_t group_generation GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags for this message fragment.
|
||||||
|
*
|
||||||
|
* @see enum GNUNET_MULTICAST_MessageFlags
|
||||||
|
*/
|
||||||
|
uint32_t flags GNUNET_PACKED;
|
||||||
|
|
||||||
|
/* Followed by message body. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header of a request from a member to the origin.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_RequestHeader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Header for all requests from a member to the origin.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key of the sending member.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ECC signature of the request fragment.
|
||||||
|
*
|
||||||
|
* Signature must match the public key of the multicast group.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaSignature signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purpose for the signature and size of the signed data.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of the request fragment.
|
||||||
|
* Monotonically increasing from 1.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte offset of this @e fragment of the @e request.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_offset GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of the request this fragment belongs to.
|
||||||
|
*
|
||||||
|
* Set in GNUNET_MULTICAST_origin_to_all().
|
||||||
|
*/
|
||||||
|
uint64_t request_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags for this request.
|
||||||
|
*/
|
||||||
|
enum GNUNET_MULTICAST_MessageFlags flags GNUNET_PACKED;
|
||||||
|
|
||||||
|
/* Followed by request body. */
|
||||||
|
};
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_END
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum size of a multicast message fragment.
|
||||||
|
*/
|
||||||
|
#define GNUNET_MULTICAST_FRAGMENT_MAX_SIZE (63 * 1024)
|
||||||
|
|
||||||
|
#define GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD \
|
||||||
|
(GNUNET_MULTICAST_FRAGMENT_MAX_SIZE \
|
||||||
|
- sizeof (struct GNUNET_MULTICAST_MessageHeader))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle that identifies a join request.
|
||||||
|
*
|
||||||
|
* Used to match calls to #GNUNET_MULTICAST_JoinRequestCallback to the
|
||||||
|
* corresponding calls to #GNUNET_MULTICAST_join_decision().
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_JoinHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to call with the decision made for a join request.
|
||||||
|
*
|
||||||
|
* Must be called once and only once in response to an invocation of the
|
||||||
|
* #GNUNET_MULTICAST_JoinRequestCallback.
|
||||||
|
*
|
||||||
|
* @param jh
|
||||||
|
* Join request handle.
|
||||||
|
* @param is_admitted
|
||||||
|
* #GNUNET_YES if the join is approved,
|
||||||
|
* #GNUNET_NO if it is disapproved,
|
||||||
|
* #GNUNET_SYSERR if we cannot answer the request.
|
||||||
|
* @param relay_count
|
||||||
|
* Number of relays given.
|
||||||
|
* @param relays
|
||||||
|
* Array of suggested peers that might be useful relays to use
|
||||||
|
* when joining the multicast group (essentially a list of peers that
|
||||||
|
* are already part of the multicast group and might thus be willing
|
||||||
|
* to help with routing). If empty, only this local peer (which must
|
||||||
|
* be the multicast origin) is a good candidate for building the
|
||||||
|
* multicast tree. Note that it is unnecessary to specify our own
|
||||||
|
* peer identity in this array.
|
||||||
|
* @param join_resp
|
||||||
|
* Message to send in response to the joining peer;
|
||||||
|
* can also be used to redirect the peer to a different group at the
|
||||||
|
* application layer; this response is to be transmitted to the
|
||||||
|
* peer that issued the request even if admission is denied.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle *
|
||||||
|
GNUNET_MULTICAST_join_decision (struct GNUNET_MULTICAST_JoinHandle *jh,
|
||||||
|
int is_admitted,
|
||||||
|
uint16_t relay_count,
|
||||||
|
const struct GNUNET_PeerIdentity *relays,
|
||||||
|
const struct GNUNET_MessageHeader *join_resp);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called whenever another peer wants to join the multicast group.
|
||||||
|
*
|
||||||
|
* Implementations of this function must call GNUNET_MULTICAST_join_decision()
|
||||||
|
* with the decision.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param member_pub_key
|
||||||
|
* Public key of the member requesting join.
|
||||||
|
* @param join_msg
|
||||||
|
* Application-dependent join message from the new member.
|
||||||
|
* @param jh
|
||||||
|
* Join handle to pass to GNUNET_MULTICAST_join_decison().
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_MULTICAST_JoinRequestCallback) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg,
|
||||||
|
struct GNUNET_MULTICAST_JoinHandle *jh);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called to inform about the decision in response to a join request.
|
||||||
|
*
|
||||||
|
* If @a is_admitted is not #GNUNET_YES, then the multicast service disconnects
|
||||||
|
* the client and the multicast member handle returned by
|
||||||
|
* GNUNET_MULTICAST_member_join() is invalidated.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param is_admitted
|
||||||
|
* #GNUNET_YES or #GNUNET_NO or #GNUNET_SYSERR
|
||||||
|
* @param peer
|
||||||
|
* The peer we are connected to and the join decision is from.
|
||||||
|
* @param relay_count
|
||||||
|
* Number of peers in the @a relays array.
|
||||||
|
* @param relays
|
||||||
|
* Peer identities of members of the group, which serve as relays
|
||||||
|
* and can be used to join the group at. If empty, only the origin can
|
||||||
|
* be used to connect to the group.
|
||||||
|
* @param join_msg
|
||||||
|
* Application-dependent join message from the origin.
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_MULTICAST_JoinDecisionCallback) (void *cls,
|
||||||
|
int is_admitted,
|
||||||
|
const struct GNUNET_PeerIdentity *peer,
|
||||||
|
uint16_t relay_count,
|
||||||
|
const struct GNUNET_PeerIdentity *relays,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called whenever a group member has transmitted a request
|
||||||
|
* to the origin (other than joining or leaving).
|
||||||
|
*
|
||||||
|
* FIXME: need to distinguish between origin cancelling a message (some fragments
|
||||||
|
* were sent, then the rest 'discarded') and the case where we got disconnected;
|
||||||
|
* right now, both would mean 'msg' is NULL, but they could be quite different...
|
||||||
|
* So the semantics from the receiver side of
|
||||||
|
* GNUNET_MULTICAST_member_to_origin_cancel() are not clear here. Maybe we
|
||||||
|
* should do something with the flags in this case?
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure (set from GNUNET_MULTICAST_origin_start).
|
||||||
|
* @param sender
|
||||||
|
* Identity of the sender.
|
||||||
|
* @param req
|
||||||
|
* Request to the origin.
|
||||||
|
* @param flags
|
||||||
|
* Flags for the request.
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_MULTICAST_RequestCallback) (void *cls,
|
||||||
|
const struct GNUNET_MULTICAST_RequestHeader *req);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called whenever a group member is receiving a message fragment from
|
||||||
|
* the origin.
|
||||||
|
*
|
||||||
|
* If admission to the group is denied, this function is called once with the
|
||||||
|
* response of the @e origin (as given to GNUNET_MULTICAST_join_decision()) and
|
||||||
|
* then a second time with NULL to indicate that the connection failed for good.
|
||||||
|
*
|
||||||
|
* FIXME: need to distinguish between origin cancelling a message (some fragments
|
||||||
|
* were sent, then the rest 'discarded') and the case where we got disconnected;
|
||||||
|
* right now, both would mean 'msg' is NULL, but they could be quite different...
|
||||||
|
* So the semantics from the receiver side of
|
||||||
|
* GNUNET_MULTICAST_origin_to_all_cancel() are not clear here.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure (set from GNUNET_MULTICAST_member_join())
|
||||||
|
* @param msg
|
||||||
|
* Message from the origin, NULL if the origin shut down
|
||||||
|
* (or we were kicked out, and we should thus call
|
||||||
|
* GNUNET_MULTICAST_member_part() next)
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_MULTICAST_MessageCallback) (void *cls,
|
||||||
|
const struct GNUNET_MULTICAST_MessageHeader *msg);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opaque handle to a replay request from the multicast service.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions with this signature are called whenever the multicast service needs
|
||||||
|
* a message fragment to be replayed by fragment_id.
|
||||||
|
*
|
||||||
|
* Implementations of this function MUST call GNUNET_MULTICAST_replay() ONCE
|
||||||
|
* (with a message or an error); however, if the origin is destroyed or the
|
||||||
|
* group is left, the replay handle must no longer be used.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure (set from GNUNET_MULTICAST_origin_start()
|
||||||
|
* or GNUNET_MULTICAST_member_join()).
|
||||||
|
* @param member_pub_key
|
||||||
|
* The member requesting replay.
|
||||||
|
* @param fragment_id
|
||||||
|
* Which message fragment should be replayed.
|
||||||
|
* @param flags
|
||||||
|
* Flags for the replay.
|
||||||
|
* @param rh
|
||||||
|
* Handle to pass to message transmit function.
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_MULTICAST_ReplayFragmentCallback) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
|
||||||
|
uint64_t fragment_id,
|
||||||
|
uint64_t flags,
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle *rh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions with this signature are called whenever the multicast service needs
|
||||||
|
* a message fragment to be replayed by message_id and fragment_offset.
|
||||||
|
*
|
||||||
|
* Implementations of this function MUST call GNUNET_MULTICAST_replay() ONCE
|
||||||
|
* (with a message or an error); however, if the origin is destroyed or the
|
||||||
|
* group is left, the replay handle must no longer be used.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure (set from GNUNET_MULTICAST_origin_start()
|
||||||
|
* or GNUNET_MULTICAST_member_join()).
|
||||||
|
* @param member_pub_key
|
||||||
|
* The member requesting replay.
|
||||||
|
* @param message_id
|
||||||
|
* Which message should be replayed.
|
||||||
|
* @param fragment_offset
|
||||||
|
* Offset of the fragment within of @a message_id to be replayed.
|
||||||
|
* @param flags
|
||||||
|
* Flags for the replay.
|
||||||
|
* @param rh
|
||||||
|
* Handle to pass to message transmit function.
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_MULTICAST_ReplayMessageCallback) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t fragment_offset,
|
||||||
|
uint64_t flags,
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle *rh);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible error codes during replay.
|
||||||
|
*/
|
||||||
|
enum GNUNET_MULTICAST_ReplayErrorCode
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Everything is fine.
|
||||||
|
*/
|
||||||
|
GNUNET_MULTICAST_REC_OK = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message fragment not found in the message store.
|
||||||
|
*
|
||||||
|
* Either discarded if it is too old, or not arrived yet if this member has
|
||||||
|
* missed some messages.
|
||||||
|
*/
|
||||||
|
GNUNET_MULTICAST_REC_NOT_FOUND = 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment ID counter was larger than the highest counter this
|
||||||
|
* replay function has ever encountered; thus it is likely the
|
||||||
|
* origin never sent it and we're at the HEAD of the multicast
|
||||||
|
* stream as far as this node is concerned.
|
||||||
|
*
|
||||||
|
* FIXME: needed?
|
||||||
|
*/
|
||||||
|
GNUNET_MULTICAST_REC_PAST_HEAD = 2,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access is denied to the requested fragment, membership test did not pass.
|
||||||
|
*/
|
||||||
|
GNUNET_MULTICAST_REC_ACCESS_DENIED = 3,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal error (i.e. database error). Try some other peer.
|
||||||
|
*/
|
||||||
|
GNUNET_MULTICAST_REC_INTERNAL_ERROR = 4
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replay a message fragment for the multicast group.
|
||||||
|
*
|
||||||
|
* @param rh
|
||||||
|
* Replay handle identifying which replay operation was requested.
|
||||||
|
* @param msg
|
||||||
|
* Replayed message fragment, NULL if not found / an error occurred.
|
||||||
|
* @param ec
|
||||||
|
* Error code. See enum GNUNET_MULTICAST_ReplayErrorCode
|
||||||
|
* If not #GNUNET_MULTICAST_REC_OK, the replay handle is invalidated.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_replay_response (struct GNUNET_MULTICAST_ReplayHandle *rh,
|
||||||
|
const struct GNUNET_MessageHeader *msg,
|
||||||
|
enum GNUNET_MULTICAST_ReplayErrorCode ec);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate the end of the replay session.
|
||||||
|
*
|
||||||
|
* Invalidates the replay handle.
|
||||||
|
*
|
||||||
|
* @param rh Replay session to end.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_replay_response_end (struct GNUNET_MULTICAST_ReplayHandle *rh);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called to provide data for a transmission for a replay.
|
||||||
|
*
|
||||||
|
* @see GNUNET_MULTICAST_replay2()
|
||||||
|
*/
|
||||||
|
typedef int
|
||||||
|
(*GNUNET_MULTICAST_ReplayTransmitNotify) (void *cls,
|
||||||
|
size_t *data_size,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replay a message for the multicast group.
|
||||||
|
*
|
||||||
|
* @param rh
|
||||||
|
* Replay handle identifying which replay operation was requested.
|
||||||
|
* @param notify
|
||||||
|
* Function to call to get the message.
|
||||||
|
* @param notify_cls
|
||||||
|
* Closure for @a notify.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_replay_response2 (struct GNUNET_MULTICAST_ReplayHandle *rh,
|
||||||
|
GNUNET_MULTICAST_ReplayTransmitNotify notify,
|
||||||
|
void *notify_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a multicast group.
|
||||||
|
*
|
||||||
|
* Peers that issue GNUNET_MULTICAST_member_join() can transmit a join request
|
||||||
|
* to either an existing group member or to the origin. If the joining is
|
||||||
|
* approved, the member is cleared for @e replay and will begin to receive
|
||||||
|
* messages transmitted to the group. If joining is disapproved, the failed
|
||||||
|
* candidate will be given a response. Members in the group can send messages
|
||||||
|
* to the origin.
|
||||||
|
*
|
||||||
|
* TODO: This function could optionally offer to advertise the origin in the
|
||||||
|
* P2P overlay network(where?) under the respective public key so that other
|
||||||
|
* peers can find an alternate PeerId to join it. Higher level protocols may
|
||||||
|
* however provide other means of solving the problem of the offline host
|
||||||
|
* (see secushare specs about that) and therefore merely need a way to provide
|
||||||
|
* a list of possible PeerIds.
|
||||||
|
*
|
||||||
|
* @param cfg
|
||||||
|
* Configuration to use.
|
||||||
|
* @param priv_key
|
||||||
|
* ECC key that will be used to sign messages for this
|
||||||
|
* multicast session; public key is used to identify the multicast group;
|
||||||
|
* @param max_fragment_id
|
||||||
|
* Maximum fragment ID already sent to the group.
|
||||||
|
* 0 for a new group.
|
||||||
|
* @param join_request_cb
|
||||||
|
* Function called to approve / disapprove joining of a peer.
|
||||||
|
* @param replay_frag_cb
|
||||||
|
* Function that can be called to replay a message fragment.
|
||||||
|
* @param replay_msg_cb
|
||||||
|
* Function that can be called to replay a message.
|
||||||
|
* @param request_cb
|
||||||
|
* Function called with message fragments from group members.
|
||||||
|
* @param message_cb
|
||||||
|
* Function called with the message fragments sent to the
|
||||||
|
* network by GNUNET_MULTICAST_origin_to_all(). These message fragments
|
||||||
|
* should be stored for answering replay requests later.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the various callbacks that follow.
|
||||||
|
*
|
||||||
|
* @return Handle for the origin, NULL on error.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_Origin *
|
||||||
|
GNUNET_MULTICAST_origin_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPrivateKey *priv_key,
|
||||||
|
uint64_t max_fragment_id,
|
||||||
|
GNUNET_MULTICAST_JoinRequestCallback join_request_cb,
|
||||||
|
GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb,
|
||||||
|
GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb,
|
||||||
|
GNUNET_MULTICAST_RequestCallback request_cb,
|
||||||
|
GNUNET_MULTICAST_MessageCallback message_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called to provide data for a transmission from the origin to all
|
||||||
|
* members.
|
||||||
|
*
|
||||||
|
* Note that returning #GNUNET_OK or #GNUNET_SYSERR (but not #GNUNET_NO)
|
||||||
|
* invalidates the respective transmission handle.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param[in,out] data_size
|
||||||
|
* Initially set to the number of bytes available in
|
||||||
|
* @a data, should be set to the number of bytes written to data.
|
||||||
|
* @param[out] data
|
||||||
|
* Where to write the body of the message to give to the
|
||||||
|
* method. The function must copy at most @a data_size bytes to @a data.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_SYSERR on error (fatal, aborts transmission)
|
||||||
|
* #GNUNET_NO on success, if more data is to be transmitted later.
|
||||||
|
* Should be used if @a data_size was not big enough to take all the
|
||||||
|
* data. If 0 is returned in @a data_size the transmission is paused,
|
||||||
|
* and can be resumed with GNUNET_MULTICAST_origin_to_all_resume().
|
||||||
|
* #GNUNET_YES if this completes the transmission (all data supplied)
|
||||||
|
* @deprecated should move to MQ-style API!
|
||||||
|
*/
|
||||||
|
typedef int
|
||||||
|
(*GNUNET_MULTICAST_OriginTransmitNotify) (void *cls,
|
||||||
|
size_t *data_size,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for a request to send a message to all multicast group members
|
||||||
|
* (from the origin).
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_OriginTransmitHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to the multicast group.
|
||||||
|
*
|
||||||
|
* @param origin
|
||||||
|
* Handle to the multicast group.
|
||||||
|
* @param message_id
|
||||||
|
* Application layer ID for the message. Opaque to multicast.
|
||||||
|
* @param group_generation
|
||||||
|
* Group generation of the message. Documented in
|
||||||
|
* struct GNUNET_MULTICAST_MessageHeader.
|
||||||
|
* @param notify
|
||||||
|
* Function to call to get the message.
|
||||||
|
* @param notify_cls
|
||||||
|
* Closure for @a notify.
|
||||||
|
*
|
||||||
|
* @return NULL on error (i.e. request already pending).
|
||||||
|
* @deprecated should move to MQ-style API!
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_OriginTransmitHandle *
|
||||||
|
GNUNET_MULTICAST_origin_to_all (struct GNUNET_MULTICAST_Origin *origin,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t group_generation,
|
||||||
|
GNUNET_MULTICAST_OriginTransmitNotify notify,
|
||||||
|
void *notify_cls);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resume message transmission to multicast group.
|
||||||
|
*
|
||||||
|
* @param th Transmission to cancel.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_origin_to_all_resume (struct GNUNET_MULTICAST_OriginTransmitHandle *th);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel request for message transmission to multicast group.
|
||||||
|
*
|
||||||
|
* @param th Transmission to cancel.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_origin_to_all_cancel (struct GNUNET_MULTICAST_OriginTransmitHandle *th);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop a multicast group.
|
||||||
|
*
|
||||||
|
* @param origin Multicast group to stop.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *origin,
|
||||||
|
GNUNET_ContinuationCallback stop_cb,
|
||||||
|
void *stop_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join a multicast group.
|
||||||
|
*
|
||||||
|
* The entity joining is always the local peer. Further information about the
|
||||||
|
* candidate can be provided in @a join_msg. If the join fails, the
|
||||||
|
* @a message_cb is invoked with a (failure) response and then with NULL. If
|
||||||
|
* the join succeeds, outstanding (state) messages and ongoing multicast
|
||||||
|
* messages will be given to the @a message_cb until the member decides to part
|
||||||
|
* the group. The @a mem_test_cb and @a replay_cb functions may be called at
|
||||||
|
* anytime by the multicast service to support relaying messages to other
|
||||||
|
* members of the group.
|
||||||
|
*
|
||||||
|
* @param cfg
|
||||||
|
* Configuration to use.
|
||||||
|
* @param group_key
|
||||||
|
* ECC public key that identifies the group to join.
|
||||||
|
* @param member_pub_key
|
||||||
|
* ECC key that identifies the member
|
||||||
|
* and used to sign requests sent to the origin.
|
||||||
|
* @param origin
|
||||||
|
* Peer ID of the origin to send unicast requsets to. If NULL,
|
||||||
|
* unicast requests are sent back via multiple hops on the reverse path
|
||||||
|
* of multicast messages.
|
||||||
|
* @param relay_count
|
||||||
|
* Number of peers in the @a relays array.
|
||||||
|
* @param relays
|
||||||
|
* Peer identities of members of the group, which serve as relays
|
||||||
|
* and can be used to join the group at. and send the @a join_request to.
|
||||||
|
* If empty, the @a join_request is sent directly to the @a origin.
|
||||||
|
* @param join_msg
|
||||||
|
* Application-dependent join message to be passed to the peer @a origin.
|
||||||
|
* @param join_request_cb
|
||||||
|
* Function called to approve / disapprove joining of a peer.
|
||||||
|
* @param join_decision_cb
|
||||||
|
* Function called to inform about the join decision.
|
||||||
|
* @param replay_frag_cb
|
||||||
|
* Function that can be called to replay message fragments
|
||||||
|
* this peer already knows from this group. NULL if this
|
||||||
|
* client is unable to support replay.
|
||||||
|
* @param replay_msg_cb
|
||||||
|
* Function that can be called to replay message fragments
|
||||||
|
* this peer already knows from this group. NULL if this
|
||||||
|
* client is unable to support replay.
|
||||||
|
* @param message_cb
|
||||||
|
* Function to be called for all message fragments we
|
||||||
|
* receive from the group, excluding those our @a replay_cb
|
||||||
|
* already has.
|
||||||
|
* @param cls
|
||||||
|
* Closure for callbacks.
|
||||||
|
*
|
||||||
|
* @return Handle for the member, NULL on error.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_Member *
|
||||||
|
GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *group_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPrivateKey *member_pub_key,
|
||||||
|
const struct GNUNET_PeerIdentity *origin,
|
||||||
|
uint16_t relay_count,
|
||||||
|
const struct GNUNET_PeerIdentity *relays,
|
||||||
|
const struct GNUNET_MessageHeader *join_request,
|
||||||
|
GNUNET_MULTICAST_JoinRequestCallback join_request_cb,
|
||||||
|
GNUNET_MULTICAST_JoinDecisionCallback join_decision_cb,
|
||||||
|
GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb,
|
||||||
|
GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb,
|
||||||
|
GNUNET_MULTICAST_MessageCallback message_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for a replay request.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_MemberReplayHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request a fragment to be replayed by fragment ID.
|
||||||
|
*
|
||||||
|
* Useful if messages below the @e max_known_fragment_id given when joining are
|
||||||
|
* needed and not known to the client.
|
||||||
|
*
|
||||||
|
* @param member
|
||||||
|
* Membership handle.
|
||||||
|
* @param fragment_id
|
||||||
|
* ID of a message fragment that this client would like to see replayed.
|
||||||
|
* @param flags
|
||||||
|
* Additional flags for the replay request.
|
||||||
|
* It is used and defined by GNUNET_MULTICAST_ReplayFragmentCallback
|
||||||
|
*
|
||||||
|
* @return Replay request handle, NULL on error.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_MemberReplayHandle *
|
||||||
|
GNUNET_MULTICAST_member_replay_fragment (struct GNUNET_MULTICAST_Member *member,
|
||||||
|
uint64_t fragment_id,
|
||||||
|
uint64_t flags);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request a message fr to be replayed.
|
||||||
|
*
|
||||||
|
* Useful if messages below the @e max_known_fragment_id given when joining are
|
||||||
|
* needed and not known to the client.
|
||||||
|
*
|
||||||
|
* @param member
|
||||||
|
* Membership handle.
|
||||||
|
* @param message_id
|
||||||
|
* ID of the message this client would like to see replayed.
|
||||||
|
* @param fragment_offset
|
||||||
|
* Offset of the fragment within the message to replay.
|
||||||
|
* @param flags
|
||||||
|
* Additional flags for the replay request.
|
||||||
|
* It is used & defined by GNUNET_MULTICAST_ReplayMessageCallback
|
||||||
|
*
|
||||||
|
* @return Replay request handle, NULL on error.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_MemberReplayHandle *
|
||||||
|
GNUNET_MULTICAST_member_replay_message (struct GNUNET_MULTICAST_Member *member,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t fragment_offset,
|
||||||
|
uint64_t flags);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel a replay request.
|
||||||
|
*
|
||||||
|
* @param rh
|
||||||
|
* Request to cancel.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_member_replay_cancel (struct GNUNET_MULTICAST_MemberReplayHandle *rh);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Part a multicast group.
|
||||||
|
*
|
||||||
|
* Disconnects from all group members and invalidates the @a member handle.
|
||||||
|
*
|
||||||
|
* An application-dependent part message can be transmitted beforehand using
|
||||||
|
* #GNUNET_MULTICAST_member_to_origin())
|
||||||
|
*
|
||||||
|
* @param member
|
||||||
|
* Membership handle.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *member,
|
||||||
|
GNUNET_ContinuationCallback part_cb,
|
||||||
|
void *part_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called to provide data for a transmission from a member to the origin.
|
||||||
|
*
|
||||||
|
* Note that returning #GNUNET_OK or #GNUNET_SYSERR (but not #GNUNET_NO)
|
||||||
|
* invalidates the respective transmission handle.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param[in,out] data_size
|
||||||
|
* Initially set to the number of bytes available in
|
||||||
|
* @a data, should be set to the number of bytes written to data.
|
||||||
|
* @param[out] data
|
||||||
|
* Where to write the body of the message to give to the
|
||||||
|
* method. The function must copy at most @a data_size bytes to @a data.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_SYSERR on error (fatal, aborts transmission)
|
||||||
|
* #GNUNET_NO on success, if more data is to be transmitted later.
|
||||||
|
* Should be used if @a data_size was not big enough to take all the
|
||||||
|
* data. If 0 is returned in @a data_size the transmission is paused,
|
||||||
|
* and can be resumed with GNUNET_MULTICAST_member_to_origin_resume().
|
||||||
|
* #GNUNET_YES if this completes the transmission (all data supplied)
|
||||||
|
* @deprecated should move to MQ-style API!
|
||||||
|
*/
|
||||||
|
typedef int
|
||||||
|
(*GNUNET_MULTICAST_MemberTransmitNotify) (void *cls,
|
||||||
|
size_t *data_size,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for a message to be delivered from a member to the origin.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_MemberTransmitHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to the origin of the multicast group.
|
||||||
|
*
|
||||||
|
* @param member
|
||||||
|
* Membership handle.
|
||||||
|
* @param request_id
|
||||||
|
* Application layer ID for the request. Opaque to multicast.
|
||||||
|
* @param notify
|
||||||
|
* Callback to call to get the message.
|
||||||
|
* @param notify_cls
|
||||||
|
* Closure for @a notify.
|
||||||
|
*
|
||||||
|
* @return Handle to cancel request, NULL on error (i.e. request already pending).
|
||||||
|
* @deprecated should move to MQ-style API!
|
||||||
|
*/
|
||||||
|
struct GNUNET_MULTICAST_MemberTransmitHandle *
|
||||||
|
GNUNET_MULTICAST_member_to_origin (struct GNUNET_MULTICAST_Member *member,
|
||||||
|
uint64_t request_id,
|
||||||
|
GNUNET_MULTICAST_MemberTransmitNotify notify,
|
||||||
|
void *notify_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resume message transmission to origin.
|
||||||
|
*
|
||||||
|
* @param th
|
||||||
|
* Transmission to cancel.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_member_to_origin_resume (struct GNUNET_MULTICAST_MemberTransmitHandle *th);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel request for message transmission to origin.
|
||||||
|
*
|
||||||
|
* @param th
|
||||||
|
* Transmission to cancel.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_MULTICAST_member_to_origin_cancel (struct GNUNET_MULTICAST_MemberTransmitHandle *th);
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ifndef GNUNET_MULTICAST_SERVICE_H */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */ /* end of group */
|
340
src/include/gnunet_psyc_env.h
Normal file
340
src/include/gnunet_psyc_env.h
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet.
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* PSYC Environment library
|
||||||
|
*
|
||||||
|
* @defgroup psyc-util-env PSYC Utilities library: Environment
|
||||||
|
* Environment data structure operations for PSYC and Social messages.
|
||||||
|
*
|
||||||
|
* Library providing operations for the @e environment of
|
||||||
|
* PSYC and Social messages, and for (de)serializing variable values.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef GNUNET_PSYC_ENV_H
|
||||||
|
#define GNUNET_PSYC_ENV_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible operations on PSYC state (persistent) and transient variables (per message).
|
||||||
|
*/
|
||||||
|
enum GNUNET_PSYC_Operator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Set value of a transient variable.
|
||||||
|
*/
|
||||||
|
GNUNET_PSYC_OP_SET = ':',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign value for a persistent state variable.
|
||||||
|
*
|
||||||
|
* If an assigned value is NULL, the variable is deleted.
|
||||||
|
*/
|
||||||
|
GNUNET_PSYC_OP_ASSIGN = '=',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Augment state variable.
|
||||||
|
*
|
||||||
|
* Used for appending strings, adding numbers, and adding new items to a list or dictionary.
|
||||||
|
*/
|
||||||
|
GNUNET_PSYC_OP_AUGMENT = '+',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diminish state variable.
|
||||||
|
*
|
||||||
|
* Used for subtracting numbers, and removing items from a list or dictionary.
|
||||||
|
*/
|
||||||
|
GNUNET_PSYC_OP_DIMINISH = '-',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update state variable.
|
||||||
|
*
|
||||||
|
* Used for modifying a single item of a list or dictionary.
|
||||||
|
*/
|
||||||
|
GNUNET_PSYC_OP_UPDATE = '@',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PSYC variable types.
|
||||||
|
*/
|
||||||
|
enum GNUNET_PSYC_Type
|
||||||
|
{
|
||||||
|
GNUNET_PSYC_TYPE_DATA = 0,
|
||||||
|
GNUNET_PSYC_TYPE_NUMBER,
|
||||||
|
GNUNET_PSYC_TYPE_LIST,
|
||||||
|
GNUNET_PSYC_TYPE_DICT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PSYC state modifier.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Modifier
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* State operation.
|
||||||
|
*/
|
||||||
|
enum GNUNET_PSYC_Operator oper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variable name.
|
||||||
|
*/
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of @a value.
|
||||||
|
*/
|
||||||
|
size_t value_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of variable.
|
||||||
|
*/
|
||||||
|
const void *value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Next modifier.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Modifier *next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Previous modifier.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Modifier *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Environment for a message.
|
||||||
|
*
|
||||||
|
* Contains modifiers.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Environment;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an environment.
|
||||||
|
*
|
||||||
|
* @return A newly allocated environment.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Environment *
|
||||||
|
GNUNET_PSYC_env_create ();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a modifier to the environment.
|
||||||
|
*
|
||||||
|
* @param env The environment.
|
||||||
|
* @param oper Operation to perform.
|
||||||
|
* @param name Name of the variable.
|
||||||
|
* @param value Value of the variable.
|
||||||
|
* @param value_size Size of @a value.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_env_add (struct GNUNET_PSYC_Environment *env,
|
||||||
|
enum GNUNET_PSYC_Operator oper, const char *name,
|
||||||
|
const void *value, size_t value_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the first modifier of the environment.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Modifier *
|
||||||
|
GNUNET_PSYC_env_head (const struct GNUNET_PSYC_Environment *env);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last modifier of the environment.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Modifier *
|
||||||
|
GNUNET_PSYC_env_tail (const struct GNUNET_PSYC_Environment *env);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a modifier from the environment.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_env_remove (struct GNUNET_PSYC_Environment *env,
|
||||||
|
struct GNUNET_PSYC_Modifier *mod);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a modifier at the beginning of the environment.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_env_shift (struct GNUNET_PSYC_Environment *env,
|
||||||
|
enum GNUNET_PSYC_Operator *oper, const char **name,
|
||||||
|
const void **value, size_t *value_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator for modifiers in the environment.
|
||||||
|
*
|
||||||
|
* @param cls Closure.
|
||||||
|
* @param mod Modifier.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_YES to continue iterating,
|
||||||
|
* #GNUNET_NO to stop.
|
||||||
|
*/
|
||||||
|
typedef int
|
||||||
|
(*GNUNET_PSYC_Iterator) (void *cls, enum GNUNET_PSYC_Operator oper,
|
||||||
|
const char *name, const char *value,
|
||||||
|
uint32_t value_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate through all modifiers in the environment.
|
||||||
|
*
|
||||||
|
* @param env The environment.
|
||||||
|
* @param it Iterator.
|
||||||
|
* @param it_cls Closure for iterator.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_env_iterate (const struct GNUNET_PSYC_Environment *env,
|
||||||
|
GNUNET_PSYC_Iterator it, void *it_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of modifiers in the environment.
|
||||||
|
*
|
||||||
|
* @param env The environment.
|
||||||
|
*
|
||||||
|
* @return Number of modifiers.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
GNUNET_PSYC_env_get_count (const struct GNUNET_PSYC_Environment *env);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy an environment.
|
||||||
|
*
|
||||||
|
* @param env The environment to destroy.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_env_destroy (struct GNUNET_PSYC_Environment *env);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of variable.
|
||||||
|
*
|
||||||
|
* @param name Name of the variable.
|
||||||
|
*
|
||||||
|
* @return Variable type.
|
||||||
|
*/
|
||||||
|
enum GNUNET_PSYC_Type
|
||||||
|
GNUNET_PSYC_var_get_type (char *name);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an operation on a variable.
|
||||||
|
*
|
||||||
|
* @param name Name of variable.
|
||||||
|
* @param current_value Current value of variable.
|
||||||
|
* @param current_value_size Size of @a current_value.
|
||||||
|
* @param oper Operator.
|
||||||
|
* @param args Arguments for the operation.
|
||||||
|
* @param args_size Size of @a args.
|
||||||
|
* @param return_value Return value.
|
||||||
|
* @param return_value_size Size of @a return_value.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_operation (char *name, void *current_value, size_t current_value_size,
|
||||||
|
enum GNUNET_PSYC_Operator oper, void *args, size_t args_size,
|
||||||
|
void **return_value, size_t *return_value_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the variable's value as an integer.
|
||||||
|
*
|
||||||
|
* @param size Size of value.
|
||||||
|
* @param value Raw value of variable.
|
||||||
|
* @param[out] number Value converted to a 64-bit integer.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR if an error occurred (e.g. the value is invalid).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_value_to_number (size_t size, const void *value, int64_t *number);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the variable's value as a dictionary.
|
||||||
|
*
|
||||||
|
* @param size Size of value.
|
||||||
|
* @param value Raw value of variable.
|
||||||
|
* @param[out] dict A newly created hashmap holding the elements of the dictionary.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR if an error occurred (e.g. the value is invalid).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_value_to_dict (size_t size, const void *value, struct GNUNET_CONTAINER_MultiHashMap **dict);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a PSYC variable value from an integer.
|
||||||
|
*
|
||||||
|
* @param number The number to convert.
|
||||||
|
* @param[out] value_size Size of returned value.
|
||||||
|
*
|
||||||
|
* @return A newly allocated value or NULL on error.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
GNUNET_PSYC_value_from_number (int64_t number, size_t *value_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a PSYC variable value from a dictionary.
|
||||||
|
*
|
||||||
|
* @param dict The dict to convert.
|
||||||
|
* @param[out] value_size Size of returned value.
|
||||||
|
*
|
||||||
|
* @return A newly allocated value or NULL on error.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
GNUNET_PSYC_value_from_dict (struct GNUNET_CONTAINER_MultiHashMap *dict, size_t *value_size);
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ifndef GNUNET_PSYC_ENV_H */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */ /* end of group */
|
278
src/include/gnunet_psyc_message.h
Normal file
278
src/include/gnunet_psyc_message.h
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNUnet.
|
||||||
|
Copyright (C) 2012, 2013 GNUnet e.V.
|
||||||
|
|
||||||
|
GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* PSYC message utilities; receiving/transmitting/logging PSYC messages
|
||||||
|
*
|
||||||
|
* @defgroup psyc-util-message PSYC Utilities library: Messages
|
||||||
|
* Receiving, transmitting, logging PSYC messages.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNUNET_PSYC_MESSAGE_H
|
||||||
|
#define GNUNET_PSYC_MESSAGE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_psyc_util_lib.h"
|
||||||
|
#include "gnunet_psyc_service.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a PSYC message.
|
||||||
|
*
|
||||||
|
* @param method_name
|
||||||
|
* PSYC method for the message.
|
||||||
|
* @param env
|
||||||
|
* Environment for the message.
|
||||||
|
* @param data
|
||||||
|
* Data payload for the message.
|
||||||
|
* @param data_size
|
||||||
|
* Size of @a data.
|
||||||
|
*
|
||||||
|
* @return Message header with size information,
|
||||||
|
* followed by the message parts.
|
||||||
|
*
|
||||||
|
* FIXME: arg order
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Message *
|
||||||
|
GNUNET_PSYC_message_create (const char *method_name,
|
||||||
|
const struct GNUNET_PSYC_Environment *env,
|
||||||
|
const void *data,
|
||||||
|
size_t data_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse PSYC message.
|
||||||
|
*
|
||||||
|
* @param msg
|
||||||
|
* The PSYC message to parse.
|
||||||
|
* @param env
|
||||||
|
* The environment for the message with a list of modifiers.
|
||||||
|
* @param[out] method_name
|
||||||
|
* Pointer to the method name inside @a pmsg.
|
||||||
|
* @param[out] data
|
||||||
|
* Pointer to data inside @a pmsg.
|
||||||
|
* @param[out] data_size
|
||||||
|
* Size of @data is written here.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success,
|
||||||
|
* #GNUNET_SYSERR on parse error.
|
||||||
|
*
|
||||||
|
* FIXME: arg order
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_MessageHeader *msg,
|
||||||
|
const char **method_name,
|
||||||
|
struct GNUNET_PSYC_Environment *env,
|
||||||
|
const void **data,
|
||||||
|
uint16_t *data_size);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind,
|
||||||
|
const struct GNUNET_MessageHeader *msg);
|
||||||
|
|
||||||
|
|
||||||
|
struct GNUNET_PSYC_TransmitHandle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a transmission handle.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_TransmitHandle *
|
||||||
|
GNUNET_PSYC_transmit_create (struct GNUNET_MQ_Handle *mq);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a transmission handle.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_transmit_destroy (struct GNUNET_PSYC_TransmitHandle *tmit);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit a message.
|
||||||
|
*
|
||||||
|
* @param tmit
|
||||||
|
* Transmission handle.
|
||||||
|
* @param method_name
|
||||||
|
* Which method should be invoked.
|
||||||
|
* @param env
|
||||||
|
* Environment for the message.
|
||||||
|
* Should stay available until the first call to notify_data.
|
||||||
|
* Can be NULL if there are no modifiers or @a notify_mod is
|
||||||
|
* provided instead.
|
||||||
|
* @param notify_mod
|
||||||
|
* Function to call to obtain modifiers.
|
||||||
|
* Can be NULL if there are no modifiers or @a env is provided instead.
|
||||||
|
* @param notify_data
|
||||||
|
* Function to call to obtain fragments of the data.
|
||||||
|
* @param notify_cls
|
||||||
|
* Closure for @a notify_mod and @a notify_data.
|
||||||
|
* @param flags
|
||||||
|
* Flags for the message being transmitted.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK if the transmission was started.
|
||||||
|
* #GNUNET_SYSERR if another transmission is already going on.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_transmit_message (struct GNUNET_PSYC_TransmitHandle *tmit,
|
||||||
|
const char *method_name,
|
||||||
|
const struct GNUNET_PSYC_Environment *env,
|
||||||
|
GNUNET_PSYC_TransmitNotifyModifier notify_mod,
|
||||||
|
GNUNET_PSYC_TransmitNotifyData notify_data,
|
||||||
|
void *notify_cls,
|
||||||
|
uint32_t flags);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resume transmission.
|
||||||
|
*
|
||||||
|
* @param tmit Transmission handle.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_transmit_resume (struct GNUNET_PSYC_TransmitHandle *tmit);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abort transmission request.
|
||||||
|
*
|
||||||
|
* @param tmit Transmission handle.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_transmit_cancel (struct GNUNET_PSYC_TransmitHandle *tmit);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Got acknowledgement of a transmitted message part, continue transmission.
|
||||||
|
*
|
||||||
|
* @param tmit Transmission handle.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_transmit_got_ack (struct GNUNET_PSYC_TransmitHandle *tmit);
|
||||||
|
|
||||||
|
|
||||||
|
struct GNUNET_PSYC_ReceiveHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create handle for receiving messages.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_ReceiveHandle *
|
||||||
|
GNUNET_PSYC_receive_create (GNUNET_PSYC_MessageCallback message_cb,
|
||||||
|
GNUNET_PSYC_MessagePartCallback message_part_cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy handle for receiving messages.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_receive_destroy (struct GNUNET_PSYC_ReceiveHandle *recv);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset stored data related to the last received message.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_receive_reset (struct GNUNET_PSYC_ReceiveHandle *recv);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle incoming PSYC message.
|
||||||
|
*
|
||||||
|
* @param recv
|
||||||
|
* Receive handle.
|
||||||
|
* @param msg
|
||||||
|
* The message.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success,
|
||||||
|
* #GNUNET_SYSERR on receive error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_receive_message (struct GNUNET_PSYC_ReceiveHandle *recv,
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if @a data contains a series of valid message parts.
|
||||||
|
*
|
||||||
|
* @param data_size
|
||||||
|
* Size of @a data.
|
||||||
|
* @param data
|
||||||
|
* Data.
|
||||||
|
* @param[out] first_ptype
|
||||||
|
* Type of first message part.
|
||||||
|
* @param[out] last_ptype
|
||||||
|
* Type of last message part.
|
||||||
|
*
|
||||||
|
* @return Number of message parts found in @a data.
|
||||||
|
* or GNUNET_SYSERR if the message contains invalid parts.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_receive_check_parts (uint16_t data_size, const char *data,
|
||||||
|
uint16_t *first_ptype, uint16_t *last_ptype);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize PSYC message header.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_message_header_init (struct GNUNET_PSYC_MessageHeader *pmsg,
|
||||||
|
const struct GNUNET_MULTICAST_MessageHeader *mmsg,
|
||||||
|
uint32_t flags);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PSYC message header from a multicast message for sending it to clients.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_MessageHeader *
|
||||||
|
GNUNET_PSYC_message_header_create (const struct GNUNET_MULTICAST_MessageHeader *mmsg,
|
||||||
|
uint32_t flags);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PSYC message header from a PSYC message.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_MessageHeader *
|
||||||
|
GNUNET_PSYC_message_header_create_from_psyc (const struct GNUNET_PSYC_Message *msg);
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ifndef GNUNET_PSYC_MESSAGE_H */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */ /* end of group */
|
1364
src/include/gnunet_psyc_service.h
Normal file
1364
src/include/gnunet_psyc_service.h
Normal file
File diff suppressed because it is too large
Load Diff
378
src/include/gnunet_psyc_slicer.h
Normal file
378
src/include/gnunet_psyc_slicer.h
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNUnet.
|
||||||
|
Copyright (C) 2013 GNUnet e.V.
|
||||||
|
|
||||||
|
GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* PSYC Slicer library
|
||||||
|
*
|
||||||
|
* @defgroup psyc-util-slicer PSYC Utilities library: Slicer
|
||||||
|
* Try-and-slice processing of PSYC method names and environment.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNUNET_PSYC_SLICER_H
|
||||||
|
#define GNUNET_PSYC_SLICER_H
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle to an implementation of try-and-slice.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Slicer;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called upon receiving a message indicating a call to a @e method.
|
||||||
|
*
|
||||||
|
* This function is called one or more times for each message until all data
|
||||||
|
* fragments arrive from the network.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param msg
|
||||||
|
* Message part, as it arrived from the network.
|
||||||
|
* @param message_id
|
||||||
|
* Message counter, monotonically increasing from 1.
|
||||||
|
* @param flags
|
||||||
|
* OR'ed GNUNET_PSYC_MessageFlags
|
||||||
|
* @param fragment_offset
|
||||||
|
* Multicast message fragment offset.
|
||||||
|
* @param tmit_flags
|
||||||
|
* OR'ed GNUNET_PSYC_MasterTransmitFlags
|
||||||
|
* @param nym
|
||||||
|
* The sender of the message.
|
||||||
|
* Can be NULL if the message is not connected to a pseudonym.
|
||||||
|
* @param method_name
|
||||||
|
* Original method name from PSYC.
|
||||||
|
* May be more specific than the registered method name due to
|
||||||
|
* try-and-slice matching.
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_PSYC_MethodCallback) (void *cls,
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg,
|
||||||
|
const struct GNUNET_PSYC_MessageMethod *meth,
|
||||||
|
uint64_t message_id,
|
||||||
|
const char *method_name);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called upon receiving a modifier of a message.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param message_id
|
||||||
|
* Message ID this data fragment belongs to.
|
||||||
|
* @param flags
|
||||||
|
* OR'ed GNUNET_PSYC_MessageFlags
|
||||||
|
* @param fragment_offset
|
||||||
|
* Multicast message fragment offset.
|
||||||
|
* @param msg
|
||||||
|
* Message part, as it arrived from the network.
|
||||||
|
* @param oper
|
||||||
|
* Operation to perform.
|
||||||
|
* 0 in case of a modifier continuation.
|
||||||
|
* @param name
|
||||||
|
* Name of the modifier.
|
||||||
|
* NULL in case of a modifier continuation.
|
||||||
|
* @param value
|
||||||
|
* Value of the modifier.
|
||||||
|
* @param value_size
|
||||||
|
* Size of @value.
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_PSYC_ModifierCallback) (void *cls,
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg,
|
||||||
|
const struct GNUNET_MessageHeader *pmsg,
|
||||||
|
uint64_t message_id,
|
||||||
|
enum GNUNET_PSYC_Operator oper,
|
||||||
|
const char *name,
|
||||||
|
const void *value,
|
||||||
|
uint16_t value_size,
|
||||||
|
uint16_t full_value_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called upon receiving a data fragment of a message.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param msg
|
||||||
|
* Message part, as it arrived from the network.
|
||||||
|
* @param message_id
|
||||||
|
* Message ID this data fragment belongs to.
|
||||||
|
* @param flags
|
||||||
|
* OR'ed GNUNET_PSYC_MessageFlags
|
||||||
|
* @param fragment_offset
|
||||||
|
* Multicast message fragment offset.
|
||||||
|
* @param data
|
||||||
|
* Data stream given to the method.
|
||||||
|
* @param data_size
|
||||||
|
* Number of bytes in @a data.
|
||||||
|
* @param end
|
||||||
|
* End of message?
|
||||||
|
* #GNUNET_NO if there are further fragments,
|
||||||
|
* #GNUNET_YES if this is the last fragment,
|
||||||
|
* #GNUNET_SYSERR indicates the message was cancelled by the sender.
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_PSYC_DataCallback) (void *cls,
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg,
|
||||||
|
const struct GNUNET_MessageHeader *pmsg,
|
||||||
|
uint64_t message_id,
|
||||||
|
const void *data,
|
||||||
|
uint16_t data_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End of message.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param msg
|
||||||
|
* Message part, as it arrived from the network.
|
||||||
|
* @param message_id
|
||||||
|
* Message ID this data fragment belongs to.
|
||||||
|
* @param flags
|
||||||
|
* OR'ed GNUNET_PSYC_MessageFlags
|
||||||
|
* @param fragment_offset
|
||||||
|
* Multicast message fragment offset.
|
||||||
|
* @param cancelled
|
||||||
|
* #GNUNET_YES if the message was cancelled,
|
||||||
|
* #GNUNET_NO if the message is complete.
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_PSYC_EndOfMessageCallback) (void *cls,
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg,
|
||||||
|
const struct GNUNET_MessageHeader *pmsg,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint8_t is_cancelled);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a try-and-slice instance.
|
||||||
|
*
|
||||||
|
* A slicer processes incoming messages and notifies callbacks about matching
|
||||||
|
* methods or modifiers encountered.
|
||||||
|
*
|
||||||
|
* @return A new try-and-slice construct.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Slicer *
|
||||||
|
GNUNET_PSYC_slicer_create (void);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a method to the try-and-slice instance.
|
||||||
|
*
|
||||||
|
* The callbacks are called for messages with a matching @a method_name prefix.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The try-and-slice instance to extend.
|
||||||
|
* @param method_name
|
||||||
|
* Name of the given method, use empty string to match all.
|
||||||
|
* @param method_cb
|
||||||
|
* Method handler invoked upon a matching message.
|
||||||
|
* @param modifier_cb
|
||||||
|
* Modifier handler, invoked after @a method_cb
|
||||||
|
* for each modifier in the message.
|
||||||
|
* @param data_cb
|
||||||
|
* Data handler, invoked after @a modifier_cb for each data fragment.
|
||||||
|
* @param eom_cb
|
||||||
|
* Invoked upon reaching the end of a matching message.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callbacks.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_method_add (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const char *method_name,
|
||||||
|
GNUNET_PSYC_MessageCallback msg_cb,
|
||||||
|
GNUNET_PSYC_MethodCallback method_cb,
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb,
|
||||||
|
GNUNET_PSYC_DataCallback data_cb,
|
||||||
|
GNUNET_PSYC_EndOfMessageCallback eom_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a registered method from the try-and-slice instance.
|
||||||
|
*
|
||||||
|
* Removes one matching handler registered with the given
|
||||||
|
* @a method_name and callbacks.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The try-and-slice instance.
|
||||||
|
* @param method_name
|
||||||
|
* Name of the method to remove.
|
||||||
|
* @param method_cb
|
||||||
|
* Only remove matching method handler, or NULL.
|
||||||
|
* @param modifier_cb
|
||||||
|
* Only remove matching modifier handler, or NULL.
|
||||||
|
* @param data_cb
|
||||||
|
* Only remove matching data handler, or NULL.
|
||||||
|
* @param eom_cb
|
||||||
|
* Only remove matching End of Message handler, or NULL.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK if a method handler was removed,
|
||||||
|
* #GNUNET_NO if no handler matched the given method name and callbacks.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_slicer_method_remove (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const char *method_name,
|
||||||
|
GNUNET_PSYC_MessageCallback msg_cb,
|
||||||
|
GNUNET_PSYC_MethodCallback method_cb,
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb,
|
||||||
|
GNUNET_PSYC_DataCallback data_cb,
|
||||||
|
GNUNET_PSYC_EndOfMessageCallback eom_cb);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch a place for changed objects.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The try-and-slice instance.
|
||||||
|
* @param object_filter
|
||||||
|
* Object prefix to match.
|
||||||
|
* @param modifier_cb
|
||||||
|
* Function to call when encountering a state modifier.
|
||||||
|
* @param cls
|
||||||
|
* Closure for callback.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_modifier_add (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const char *object_filter,
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a registered modifier from the try-and-slice instance.
|
||||||
|
*
|
||||||
|
* Removes one matching handler registered with the given
|
||||||
|
* @a object_filter and callback.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The try-and-slice instance.
|
||||||
|
* @param object_filter
|
||||||
|
* Object prefix to match.
|
||||||
|
* @param modifier_cb
|
||||||
|
* Function to call when encountering a state modifier changes.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_slicer_modifier_remove (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const char *object_filter,
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an incoming message and call matching handlers.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The slicer to use.
|
||||||
|
* @param msg
|
||||||
|
* The message as it arrived from the network.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_message (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an incoming message part and call matching handlers.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The slicer to use.
|
||||||
|
* @param message_id
|
||||||
|
* ID of the message.
|
||||||
|
* @param flags
|
||||||
|
* Flags for the message.
|
||||||
|
* @see enum GNUNET_PSYC_MessageFlags
|
||||||
|
* @param fragment offset
|
||||||
|
* Fragment offset of the message.
|
||||||
|
* @param msg
|
||||||
|
* The message part as it arrived from the network.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_message_part (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg,
|
||||||
|
const struct GNUNET_MessageHeader *pmsg);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all registered method handlers.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* Slicer to clear.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_method_clear (struct GNUNET_PSYC_Slicer *slicer);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all registered modifier handlers.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* Slicer to clear.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_modifier_clear (struct GNUNET_PSYC_Slicer *slicer);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all registered method & modifier handlers.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* Slicer to clear.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_clear (struct GNUNET_PSYC_Slicer *slicer);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a given try-and-slice instance.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* Slicer to destroy
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_destroy (struct GNUNET_PSYC_Slicer *slicer);
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ifndef GNUNET_PSYC_SLICER_H */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */ /* end of group */
|
53
src/include/gnunet_psyc_util_lib.h
Normal file
53
src/include/gnunet_psyc_util_lib.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNUnet.
|
||||||
|
Copyright (C) 2012, 2013 GNUnet e.V.
|
||||||
|
|
||||||
|
GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* PSYC utilities: messages, environment, slicer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNUNET_PSYC_UTIL_LIB_H
|
||||||
|
#define GNUNET_PSYC_UTIL_LIB_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "gnunet_psyc_env.h"
|
||||||
|
#include "gnunet_psyc_message.h"
|
||||||
|
#include "gnunet_psyc_slicer.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ifndef GNUNET_PSYC_UTIL_LIB_H */
|
||||||
|
#endif
|
383
src/include/gnunet_psycstore_plugin.h
Normal file
383
src/include/gnunet_psycstore_plugin.h
Normal file
@ -0,0 +1,383 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNUnet
|
||||||
|
Copyright (C) 2013 GNUnet e.V.
|
||||||
|
|
||||||
|
GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* Plugin API for the PSYCstore database backend
|
||||||
|
*
|
||||||
|
* @defgroup psycstore-plugin PSYC Store plugin API
|
||||||
|
* Plugin API for the PSYC Store database backend
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#ifndef GNUNET_PSYCSTORE_PLUGIN_H
|
||||||
|
#define GNUNET_PSYCSTORE_PLUGIN_H
|
||||||
|
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_psycstore_service.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct returned by the initialization function of the plugin.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_PluginFunctions
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure to pass to all plugin functions.
|
||||||
|
*/
|
||||||
|
void *cls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store join/leave events for a PSYC channel in order to be able to answer
|
||||||
|
* membership test queries later.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_membership_store()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*membership_store) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
int did_join,
|
||||||
|
uint64_t announced_at,
|
||||||
|
uint64_t effective_since,
|
||||||
|
uint64_t group_generation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if a member was admitted to the channel at the given message ID.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_membership_test()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not,
|
||||||
|
* #GNUNET_SYSERR if there was en error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*membership_test) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
uint64_t message_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a message fragment sent to a channel.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_fragment_store()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*fragment_store) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_MULTICAST_MessageHeader *message,
|
||||||
|
uint32_t psycstore_flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set additional flags for a given message.
|
||||||
|
*
|
||||||
|
* They are OR'd with any existing flags set.
|
||||||
|
*
|
||||||
|
* @param cls Closure.
|
||||||
|
* @param channel_key Public key of the channel.
|
||||||
|
* @param message_id ID of the message.
|
||||||
|
* @param psycstore_flags OR'd GNUNET_PSYCSTORE_MessageFlags.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*message_add_flags) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint32_t psycstore_flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a message fragment range by fragment ID.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_fragment_get()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*fragment_get) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t first_fragment_id,
|
||||||
|
uint64_t last_fragment_id,
|
||||||
|
uint64_t *returned_fragments,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve latest message fragments.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_fragment_get()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*fragment_get_latest) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t fragment_limit,
|
||||||
|
uint64_t *returned_fragments,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all fragments of a message ID range.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_message_get()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*message_get) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t first_fragment_id,
|
||||||
|
uint64_t last_fragment_id,
|
||||||
|
uint64_t fragment_limit,
|
||||||
|
uint64_t *returned_fragments,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all fragments of the latest messages.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_message_get()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*message_get_latest) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t fragment_limit,
|
||||||
|
uint64_t *returned_fragments,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a fragment of message specified by its message ID and fragment
|
||||||
|
* offset.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_message_get_fragment()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*message_get_fragment) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t fragment_offset,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the max. values of message counters for a channel.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_counters_get()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*counters_message_get) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t *max_fragment_id,
|
||||||
|
uint64_t *max_message_id,
|
||||||
|
uint64_t *max_group_generation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the max. values of state counters for a channel.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_counters_get()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*counters_state_get) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t *max_state_message_id);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin modifying current state.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_state_modify()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_modify_begin) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t message_id, uint64_t state_delta);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current value of a state variable.
|
||||||
|
*
|
||||||
|
* The state modification process is started with state_modify_begin(),
|
||||||
|
* which is followed by one or more calls to this function,
|
||||||
|
* and finished with state_modify_end().
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_state_modify()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_modify_op) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
enum GNUNET_PSYC_Operator op,
|
||||||
|
const char *name, const void *value, size_t value_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End modifying current state.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_state_modify()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_modify_end) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t message_id);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin synchronizing state.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_state_sync()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_sync_begin) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign value of a state variable while synchronizing state.
|
||||||
|
*
|
||||||
|
* The state synchronization process is started with state_sync_begin(),
|
||||||
|
* which is followed by one or more calls to this function,
|
||||||
|
* and finished using state_sync_end().
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_state_sync()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_sync_assign) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const char *name, const void *value, size_t value_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End synchronizing state.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_state_sync()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_sync_end) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t max_state_message_id,
|
||||||
|
uint64_t state_hash_message_id);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the state of a channel.
|
||||||
|
*
|
||||||
|
* Delete all state variables stored for the given channel.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_state_reset()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_reset) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update signed state values from the current ones.
|
||||||
|
*
|
||||||
|
* Sets value_signed = value_current for each variable for the given channel.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_update_signed) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a state variable by name (exact match).
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_get) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const char *name,
|
||||||
|
GNUNET_PSYCSTORE_StateCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all state variables for a channel with the given prefix.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_state_get_prefix()
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_get_prefix) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const char *name,
|
||||||
|
GNUNET_PSYCSTORE_StateCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all signed state variables for a channel.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK on success, else #GNUNET_SYSERR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
(*state_get_signed) (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
GNUNET_PSYCSTORE_StateCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */ /* end of group */
|
701
src/include/gnunet_psycstore_service.h
Normal file
701
src/include/gnunet_psycstore_service.h
Normal file
@ -0,0 +1,701 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNUnet.
|
||||||
|
Copyright (C) 2013 GNUnet e.V.
|
||||||
|
|
||||||
|
GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* PSYCstore service; implements persistent storage for the PSYC service
|
||||||
|
*
|
||||||
|
* @defgroup psycstore PSYC Store service
|
||||||
|
* Persistent storage for the PSYC service.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#ifndef GNUNET_PSYCSTORE_SERVICE_H
|
||||||
|
#define GNUNET_PSYCSTORE_SERVICE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_psyc_util_lib.h"
|
||||||
|
#include "gnunet_multicast_service.h"
|
||||||
|
#include "gnunet_psyc_service.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version number of GNUnet PSYCstore API.
|
||||||
|
*/
|
||||||
|
#define GNUNET_PSYCSTORE_VERSION 0x00000000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Membership test failed.
|
||||||
|
*/
|
||||||
|
#define GNUNET_PSYCSTORE_MEMBERSHIP_TEST_FAILED -2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags for stored messages.
|
||||||
|
*/
|
||||||
|
enum GNUNET_PSYCSTORE_MessageFlags
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The message contains state modifiers.
|
||||||
|
*/
|
||||||
|
GNUNET_PSYCSTORE_MESSAGE_STATE = 1 << 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The state modifiers have been applied to the state store.
|
||||||
|
*/
|
||||||
|
GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED = 1 << 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message contains a state hash.
|
||||||
|
*/
|
||||||
|
GNUNET_PSYCSTORE_MESSAGE_STATE_HASH = 1 << 2
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for a PSYCstore
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_Handle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to the PSYCstore service.
|
||||||
|
*
|
||||||
|
* @param cfg Configuration to use.
|
||||||
|
*
|
||||||
|
* @return Handle for the connecton.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_Handle *
|
||||||
|
GNUNET_PSYCSTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnect from the PSYCstore service.
|
||||||
|
*
|
||||||
|
* @param h Handle for the connection.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYCSTORE_disconnect (struct GNUNET_PSYCSTORE_Handle *h);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for an operation on the PSYCSTORE (useful to cancel the operation).
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called with the result of an asynchronous operation.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param result
|
||||||
|
* Result of the operation.
|
||||||
|
* @param err_msg
|
||||||
|
* Error message, or NULL if there's no error.
|
||||||
|
* @param err_msg_size
|
||||||
|
* Size of @a err_msg
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_PSYCSTORE_ResultCallback) (void *cls,
|
||||||
|
int64_t result,
|
||||||
|
const char *err_msg,
|
||||||
|
uint16_t err_msg_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store join/leave events for a PSYC channel in order to be able to answer
|
||||||
|
* membership test queries later.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel where the event happened.
|
||||||
|
* @param slave_key
|
||||||
|
* Public key of joining/leaving slave.
|
||||||
|
* @param did_join
|
||||||
|
* #GNUNET_YES on join, #GNUNET_NO on part.
|
||||||
|
* @param announced_at
|
||||||
|
* ID of the message that announced the membership change.
|
||||||
|
* @param effective_since
|
||||||
|
* Message ID this membership change is in effect since.
|
||||||
|
* For joins it is <= announced_at, for parts it is always 0.
|
||||||
|
* @param group_generation
|
||||||
|
* In case of a part, the last group generation the slave has access to.
|
||||||
|
* It has relevance when a larger message have fragments with different
|
||||||
|
* group generations.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the storage operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callback.
|
||||||
|
*
|
||||||
|
* @return Operation handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_membership_store (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
int did_join,
|
||||||
|
uint64_t announced_at,
|
||||||
|
uint64_t effective_since,
|
||||||
|
uint64_t group_generation,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if a member was admitted to the channel at the given message ID.
|
||||||
|
*
|
||||||
|
* This is useful when relaying and replaying messages to check if a particular
|
||||||
|
* slave has access to the message fragment with a given group generation. It
|
||||||
|
* is also used when handling join requests to determine whether the slave is
|
||||||
|
* currently admitted to the channel.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param slave_key
|
||||||
|
* Public key of slave whose membership to check.
|
||||||
|
* @param message_id
|
||||||
|
* Message ID for which to do the membership test.
|
||||||
|
* @param group_generation
|
||||||
|
* Group generation of the fragment of the message to test.
|
||||||
|
* It has relevance if the message consists of multiple fragments with
|
||||||
|
* different group generations.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the test result.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callback.
|
||||||
|
*
|
||||||
|
* @return Operation handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_membership_test (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t group_generation,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a message fragment sent to a channel.
|
||||||
|
*
|
||||||
|
* @param h Handle for the PSYCstore.
|
||||||
|
* @param channel_key The channel the message belongs to.
|
||||||
|
* @param msg Message to store.
|
||||||
|
* @param psycstore_flags Flags indicating whether the PSYC message contains
|
||||||
|
* state modifiers.
|
||||||
|
* @param result_cb Callback to call with the result of the operation.
|
||||||
|
* @param cls Closure for the callback.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_fragment_store (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_MULTICAST_MessageHeader *msg,
|
||||||
|
enum GNUNET_PSYCSTORE_MessageFlags psycstore_flags,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called with one message fragment, as the result of a
|
||||||
|
* GNUNET_PSYCSTORE_fragment_get() or GNUNET_PSYCSTORE_message_get() call.
|
||||||
|
*
|
||||||
|
* @param cls Closure.
|
||||||
|
* @param message The retrieved message fragment. A NULL value indicates that
|
||||||
|
* there are no more results to be returned.
|
||||||
|
* @param psycstore_flags Flags stored with the message.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_NO to stop calling this callback with further fragments,
|
||||||
|
* #GNUNET_YES to continue.
|
||||||
|
*/
|
||||||
|
typedef int
|
||||||
|
(*GNUNET_PSYCSTORE_FragmentCallback) (void *cls,
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader *message,
|
||||||
|
enum GNUNET_PSYCSTORE_MessageFlags psycstore_flags);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve message fragments by fragment ID range.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param slave_key
|
||||||
|
* The slave requesting the fragment. If not NULL, a membership test is
|
||||||
|
* performed first and the fragment is only returned if the slave has
|
||||||
|
* access to it.
|
||||||
|
* @param first_fragment_id
|
||||||
|
* First fragment ID to retrieve.
|
||||||
|
* Use 0 to get the latest message fragment.
|
||||||
|
* @param last_fragment_id
|
||||||
|
* Last consecutive fragment ID to retrieve.
|
||||||
|
* Use 0 to get the latest message fragment.
|
||||||
|
* @param fragment_cb
|
||||||
|
* Callback to call with the retrieved fragments.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callbacks.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
uint64_t first_message_id,
|
||||||
|
uint64_t last_message_id,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve latest message fragments.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param slave_key
|
||||||
|
* The slave requesting the fragment. If not NULL, a membership test is
|
||||||
|
* performed first and the fragment is only returned if the slave has
|
||||||
|
* access to it.
|
||||||
|
* @param first_fragment_id
|
||||||
|
* First fragment ID to retrieve.
|
||||||
|
* Use 0 to get the latest message fragment.
|
||||||
|
* @param last_fragment_id
|
||||||
|
* Last consecutive fragment ID to retrieve.
|
||||||
|
* Use 0 to get the latest message fragment.
|
||||||
|
* @param fragment_limit
|
||||||
|
* Maximum number of fragments to retrieve.
|
||||||
|
* @param fragment_cb
|
||||||
|
* Callback to call with the retrieved fragments.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callbacks.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_fragment_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
uint64_t fragment_limit,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all fragments of messages in a message ID range.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param slave_key
|
||||||
|
* The slave requesting the message.
|
||||||
|
* If not NULL, a membership test is performed first
|
||||||
|
* and the message is only returned if the slave has access to it.
|
||||||
|
* @param first_message_id
|
||||||
|
* First message ID to retrieve.
|
||||||
|
* @param last_message_id
|
||||||
|
* Last consecutive message ID to retrieve.
|
||||||
|
* @param fragment_limit
|
||||||
|
* Maximum number of fragments to retrieve.
|
||||||
|
* @param method_prefix
|
||||||
|
* Retrieve only messages with a matching method prefix.
|
||||||
|
* @param fragment_cb
|
||||||
|
* Callback to call with the retrieved fragments.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callbacks.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
uint64_t first_message_id,
|
||||||
|
uint64_t last_message_id,
|
||||||
|
uint64_t fragment_limit,
|
||||||
|
const char *method_prefix,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all fragments of the latest messages.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param slave_key
|
||||||
|
* The slave requesting the message.
|
||||||
|
* If not NULL, a membership test is performed first
|
||||||
|
* and the message is only returned if the slave has access to it.
|
||||||
|
* @param message_limit
|
||||||
|
* Maximum number of messages to retrieve.
|
||||||
|
* @param method_prefix
|
||||||
|
* Retrieve only messages with a matching method prefix.
|
||||||
|
* @param fragment_cb
|
||||||
|
* Callback to call with the retrieved fragments.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callbacks.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_message_get_latest (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
uint64_t message_limit,
|
||||||
|
const char *method_prefix,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a fragment of message specified by its message ID and fragment
|
||||||
|
* offset.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param slave_key
|
||||||
|
* The slave requesting the message fragment. If not NULL, a membership
|
||||||
|
* test is performed first and the message fragment is only returned
|
||||||
|
* if the slave has access to it.
|
||||||
|
* @param message_id
|
||||||
|
* Message ID to retrieve. Use 0 to get the latest message.
|
||||||
|
* @param fragment_offset
|
||||||
|
* Offset of the fragment to retrieve.
|
||||||
|
* @param fragment_cb
|
||||||
|
* Callback to call with the retrieved fragments.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callbacks.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_message_get_fragment (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t fragment_offset,
|
||||||
|
GNUNET_PSYCSTORE_FragmentCallback fragment_cb,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback used to return the latest value of counters for the channel master.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_counters_get()
|
||||||
|
*
|
||||||
|
* @param cls Closure.
|
||||||
|
* @param result_code
|
||||||
|
* Status code for the operation:
|
||||||
|
* #GNUNET_OK: success, counter values are returned.
|
||||||
|
* #GNUNET_NO: no message has been sent to the channel yet.
|
||||||
|
* #GNUNET_SYSERR: an error occurred.
|
||||||
|
* @param max_fragment_id
|
||||||
|
* Latest message fragment ID, used by multicast.
|
||||||
|
* @param max_message_id
|
||||||
|
* Latest message ID, used by PSYC.
|
||||||
|
* @param max_group_generation
|
||||||
|
* Latest group generation, used by PSYC.
|
||||||
|
* @param max_state_message_id
|
||||||
|
* Latest message ID containing state modifiers that
|
||||||
|
* was applied to the state store. Used for the state sync process.
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*GNUNET_PSYCSTORE_CountersCallback) (void *cls,
|
||||||
|
int result_code,
|
||||||
|
uint64_t max_fragment_id,
|
||||||
|
uint64_t max_message_id,
|
||||||
|
uint64_t max_group_generation,
|
||||||
|
uint64_t max_state_message_id);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve latest values of counters for a channel.
|
||||||
|
*
|
||||||
|
* The current value of counters are needed
|
||||||
|
* - when a channel master is restarted, so that it can continue incrementing
|
||||||
|
* the counters from their last value.
|
||||||
|
* - when a channel slave rejoins and starts the state synchronization process.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* Public key that identifies the channel.
|
||||||
|
* @param counters_cb
|
||||||
|
* Callback to call with the result.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the @a ccb callback.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_counters_get (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
GNUNET_PSYCSTORE_CountersCallback counters_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply modifiers of a message to the current channel state.
|
||||||
|
*
|
||||||
|
* An error is returned if there are missing messages containing state
|
||||||
|
* operations before the current one.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param message_id
|
||||||
|
* ID of the message that contains the @a modifiers.
|
||||||
|
* @param state_delta
|
||||||
|
* Value of the @e state_delta PSYC header variable of the message.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the @a result_cb callback.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_state_modify (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t state_delta,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store synchronized state.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param max_state_message_id
|
||||||
|
* ID of the last stateful message before @a state_hash_message_id.
|
||||||
|
* @param state_hash_message_id
|
||||||
|
* ID of the message that contains the state_hash PSYC header variable.
|
||||||
|
* @param modifier_count
|
||||||
|
* Number of elements in the @a modifiers array.
|
||||||
|
* @param modifiers
|
||||||
|
* Full state to store.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callback.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_state_sync (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t max_state_message_id,
|
||||||
|
uint64_t state_hash_message_id,
|
||||||
|
size_t modifier_count,
|
||||||
|
const struct GNUNET_PSYC_Modifier *modifiers,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the state of a channel.
|
||||||
|
*
|
||||||
|
* Delete all state variables stored for the given channel.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callback.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_state_reset (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey
|
||||||
|
*channel_key,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update signed values of state variables in the state store.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param message_id
|
||||||
|
* Message ID that contained the state @a hash.
|
||||||
|
* @param hash
|
||||||
|
* Hash of the serialized full state.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callback.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_state_hash_update (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
const struct GNUNET_HashCode *hash,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called with the value of a state variable.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param name
|
||||||
|
* Name of the state variable. A NULL value indicates that there are no more
|
||||||
|
* state variables to be returned.
|
||||||
|
* @param value
|
||||||
|
* Value of the state variable.
|
||||||
|
* @param value_size
|
||||||
|
* Number of bytes in @a value.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_NO to stop calling this callback with further variables,
|
||||||
|
* #GNUNET_YES to continue.
|
||||||
|
*/;
|
||||||
|
typedef int
|
||||||
|
(*GNUNET_PSYCSTORE_StateCallback) (void *cls, const char *name,
|
||||||
|
const void *value, uint32_t value_size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the best matching state variable.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param name
|
||||||
|
* Name of variable to match, the returned variable might be less specific.
|
||||||
|
* @param state_cb
|
||||||
|
* Callback to return the matching state variable.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callbacks.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_state_get (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const char *name,
|
||||||
|
GNUNET_PSYCSTORE_StateCallback state_cb,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all state variables for a channel with the given prefix.
|
||||||
|
*
|
||||||
|
* @param h
|
||||||
|
* Handle for the PSYCstore.
|
||||||
|
* @param channel_key
|
||||||
|
* The channel we are interested in.
|
||||||
|
* @param name_prefix
|
||||||
|
* Prefix of state variable names to match.
|
||||||
|
* @param state_cb
|
||||||
|
* Callback to return matching state variables.
|
||||||
|
* @param result_cb
|
||||||
|
* Callback to call with the result of the operation.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callbacks.
|
||||||
|
*
|
||||||
|
* @return Handle that can be used to cancel the operation.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYCSTORE_OperationHandle *
|
||||||
|
GNUNET_PSYCSTORE_state_get_prefix (struct GNUNET_PSYCSTORE_Handle *h,
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
|
||||||
|
const char *name_prefix,
|
||||||
|
GNUNET_PSYCSTORE_StateCallback state_cb,
|
||||||
|
GNUNET_PSYCSTORE_ResultCallback result_cb,
|
||||||
|
void *cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel an operation.
|
||||||
|
*
|
||||||
|
* @param op Handle for the operation to cancel.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYCSTORE_operation_cancel (struct GNUNET_PSYCSTORE_OperationHandle *op);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ifndef GNUNET_PSYCSTORE_SERVICE_H */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */ /* end of group */
|
1344
src/include/gnunet_social_service.h
Normal file
1344
src/include/gnunet_social_service.h
Normal file
File diff suppressed because it is too large
Load Diff
7
src/multicast/.gitignore
vendored
Normal file
7
src/multicast/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
gnunet-service-multicast
|
||||||
|
gnunet-multicast
|
||||||
|
test_multicast
|
||||||
|
test_multicast_multipeer
|
||||||
|
test_multicast_2peers
|
||||||
|
test_multicast_multipeer_line
|
||||||
|
test_multicast_multipeer_star
|
79
src/multicast/Makefile.am
Normal file
79
src/multicast/Makefile.am
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# This Makefile.am is in the public domain
|
||||||
|
AM_CPPFLAGS = -I$(top_srcdir)/src/include
|
||||||
|
|
||||||
|
pkgcfgdir= $(pkgdatadir)/config.d/
|
||||||
|
|
||||||
|
libexecdir= $(pkglibdir)/libexec/
|
||||||
|
|
||||||
|
pkgcfg_DATA = \
|
||||||
|
multicast.conf
|
||||||
|
|
||||||
|
if MINGW
|
||||||
|
WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
|
||||||
|
endif
|
||||||
|
|
||||||
|
if USE_COVERAGE
|
||||||
|
AM_CFLAGS = -fprofile-arcs -ftest-coverage
|
||||||
|
endif
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libgnunetmulticast.la
|
||||||
|
|
||||||
|
libgnunetmulticast_la_SOURCES = \
|
||||||
|
multicast_api.c multicast.h
|
||||||
|
libgnunetmulticast_la_LIBADD = \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la \
|
||||||
|
$(GN_LIBINTL) $(XLIB)
|
||||||
|
libgnunetmulticast_la_LDFLAGS = \
|
||||||
|
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
|
||||||
|
-version-info 0:0:0
|
||||||
|
|
||||||
|
|
||||||
|
bin_PROGRAMS = \
|
||||||
|
gnunet-multicast
|
||||||
|
|
||||||
|
libexec_PROGRAMS = \
|
||||||
|
gnunet-service-multicast \
|
||||||
|
$(EXP_LIBEXEC)
|
||||||
|
|
||||||
|
gnunet_multicast_SOURCES = \
|
||||||
|
gnunet-multicast.c
|
||||||
|
gnunet_multicast_LDADD = \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la \
|
||||||
|
$(GN_LIBINTL)
|
||||||
|
|
||||||
|
gnunet_service_multicast_SOURCES = \
|
||||||
|
gnunet-service-multicast.c
|
||||||
|
gnunet_service_multicast_LDADD = \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la \
|
||||||
|
$(top_builddir)/src/cadet/libgnunetcadet.la \
|
||||||
|
$(top_builddir)/src/statistics/libgnunetstatistics.la \
|
||||||
|
$(GN_LIBINTL)
|
||||||
|
|
||||||
|
check_PROGRAMS = \
|
||||||
|
test_multicast \
|
||||||
|
test_multicast_multipeer_star \
|
||||||
|
test_multicast_multipeer_line
|
||||||
|
|
||||||
|
if ENABLE_TEST_RUN
|
||||||
|
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@}; export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; unset XDG_DATA_HOME; unset XDG_CONFIG_HOME;
|
||||||
|
TESTS = $(check_PROGRAMS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
test_multicast_SOURCES = \
|
||||||
|
test_multicast.c
|
||||||
|
test_multicast_LDADD = \
|
||||||
|
libgnunetmulticast.la \
|
||||||
|
$(top_builddir)/src/testing/libgnunettesting.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la
|
||||||
|
test_multicast_multipeer_star_SOURCES = \
|
||||||
|
test_multicast_multipeer.c
|
||||||
|
test_multicast_multipeer_star_LDADD = \
|
||||||
|
libgnunetmulticast.la \
|
||||||
|
$(top_builddir)/src/testbed/libgnunettestbed.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la
|
||||||
|
test_multicast_multipeer_line_SOURCES = \
|
||||||
|
test_multicast_multipeer.c
|
||||||
|
test_multicast_multipeer_line_LDADD = \
|
||||||
|
libgnunetmulticast.la \
|
||||||
|
$(top_builddir)/src/testbed/libgnunettestbed.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la
|
79
src/multicast/gnunet-multicast.c
Normal file
79
src/multicast/gnunet-multicast.c
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNUnet.
|
||||||
|
Copyright (C) 2013 GNUnet e.V.
|
||||||
|
|
||||||
|
GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file multicast/gnunet-multicast.c
|
||||||
|
* @brief multicast for writing a tool
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
/* #include "gnunet_multicast_service.h" */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Final status code.
|
||||||
|
*/
|
||||||
|
static int ret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main function that will be run by the scheduler.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param args remaining command-line arguments
|
||||||
|
* @param cfgfile name of the configuration file used (for saving, can be NULL!)
|
||||||
|
* @param cfg configuration
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
run (void *cls, char *const *args, const char *cfgfile,
|
||||||
|
const struct GNUNET_CONFIGURATION_Handle *cfg)
|
||||||
|
{
|
||||||
|
/* main code here */
|
||||||
|
puts( gettext_noop ("This command doesn't do anything yet.") );
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main function.
|
||||||
|
*
|
||||||
|
* @param argc number of arguments from the command line
|
||||||
|
* @param argv command line arguments
|
||||||
|
* @return 0 ok, 1 on error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
main (int argc, char *const *argv)
|
||||||
|
{
|
||||||
|
static const struct GNUNET_GETOPT_CommandLineOption options[] = {
|
||||||
|
/* FIMXE: add options here */
|
||||||
|
GNUNET_GETOPT_OPTION_END
|
||||||
|
};
|
||||||
|
if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
ret = (GNUNET_OK ==
|
||||||
|
GNUNET_PROGRAM_run (argc, argv, "gnunet-multicast",
|
||||||
|
gettext_noop ("This command doesn't do anything yet."),
|
||||||
|
options, &run,
|
||||||
|
NULL)) ? ret : 1;
|
||||||
|
GNUNET_free ((void*) argv);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of gnunet-multicast.c */
|
2234
src/multicast/gnunet-service-multicast.c
Normal file
2234
src/multicast/gnunet-service-multicast.c
Normal file
File diff suppressed because it is too large
Load Diff
22
src/multicast/multicast.conf.in
Normal file
22
src/multicast/multicast.conf.in
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[multicast]
|
||||||
|
START_ON_DEMAND = @START_ON_DEMAND@
|
||||||
|
BINARY = gnunet-service-multicast
|
||||||
|
|
||||||
|
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock
|
||||||
|
UNIX_MATCH_UID = YES
|
||||||
|
UNIX_MATCH_GID = YES
|
||||||
|
|
||||||
|
@UNIXONLY@PORT = 2109
|
||||||
|
HOSTNAME = localhost
|
||||||
|
ACCEPT_FROM = 127.0.0.1;
|
||||||
|
ACCEPT_FROM6 = ::1;
|
||||||
|
|
||||||
|
# DISABLE_SOCKET_FORWARDING = NO
|
||||||
|
# USERNAME =
|
||||||
|
# MAXBUF =
|
||||||
|
# TIMEOUT =
|
||||||
|
# DISABLEV6 =
|
||||||
|
# BINDTO =
|
||||||
|
# REJECT_FROM =
|
||||||
|
# REJECT_FROM6 =
|
||||||
|
# PREFIX =
|
303
src/multicast/multicast.h
Normal file
303
src/multicast/multicast.h
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNUnet.
|
||||||
|
Copyright (C) 2012, 2013 GNUnet e.V.
|
||||||
|
|
||||||
|
GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file multicast/multicast.h
|
||||||
|
* @brief multicast IPC messages
|
||||||
|
* @author Christian Grothoff
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*/
|
||||||
|
#ifndef MULTICAST_H
|
||||||
|
#define MULTICAST_H
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_multicast_service.h"
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header of a join request sent to the origin or another member.
|
||||||
|
*/
|
||||||
|
struct MulticastJoinRequestMessage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always zero.
|
||||||
|
*/
|
||||||
|
uint32_t reserved;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ECC signature of the rest of the fields of the join request.
|
||||||
|
*
|
||||||
|
* Signature must match the public key of the joining member.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaSignature signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purpose for the signature and size of the signed data.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key of the target group.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key of the joining member.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peer identity of the joining member.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PeerIdentity peer;
|
||||||
|
|
||||||
|
/* Followed by struct GNUNET_MessageHeader join_message */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header of a join decision message sent to a peer requesting join.
|
||||||
|
*/
|
||||||
|
struct MulticastJoinDecisionMessage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #GNUNET_YES if the peer was admitted
|
||||||
|
* #GNUNET_NO if entry was refused,
|
||||||
|
* #GNUNET_SYSERR if the request could not be answered.
|
||||||
|
*/
|
||||||
|
int32_t is_admitted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of relays given.
|
||||||
|
*/
|
||||||
|
uint32_t relay_count;
|
||||||
|
|
||||||
|
/* Followed by relay_count peer identities */
|
||||||
|
|
||||||
|
/* Followed by the join response message */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header added to a struct MulticastJoinDecisionMessage
|
||||||
|
* when sent between the client and service.
|
||||||
|
*/
|
||||||
|
struct MulticastJoinDecisionMessageHeader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C->S: Peer to send the join decision to.
|
||||||
|
* S->C: Peer we received the join decision from.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PeerIdentity peer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C->S: Public key of the member requesting join.
|
||||||
|
* S->C: Unused.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
|
||||||
|
|
||||||
|
/* Followed by struct MulticastJoinDecisionMessage */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message sent from the client to the service to notify the service
|
||||||
|
* about the result of a membership test.
|
||||||
|
*/
|
||||||
|
struct MulticastMembershipTestResultMessage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_MEMBERSHIP_TEST_RESULT
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique ID that identifies the associated membership test.
|
||||||
|
*/
|
||||||
|
uint32_t uid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #GNUNET_YES if the peer is a member
|
||||||
|
* #GNUNET_NO if peer is not a member,
|
||||||
|
* #GNUNET_SYSERR if the test could not be answered.
|
||||||
|
*/
|
||||||
|
int32_t is_admitted;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message sent from the client to the service OR the service to the
|
||||||
|
* client asking for a message fragment to be replayed.
|
||||||
|
*/
|
||||||
|
struct MulticastReplayRequestMessage
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message type should be
|
||||||
|
* #GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST.
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* S->C: Public key of the member requesting replay.
|
||||||
|
* C->S: Unused.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the message that is being requested.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the message that is being requested.
|
||||||
|
*/
|
||||||
|
uint64_t message_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset of the fragment that is being requested.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional flags for the request.
|
||||||
|
*/
|
||||||
|
uint64_t flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replay request ID.
|
||||||
|
*/
|
||||||
|
uint32_t uid;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message sent from the client to the service to give the service
|
||||||
|
* a replayed message.
|
||||||
|
*/
|
||||||
|
struct MulticastReplayResponseMessage
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE
|
||||||
|
* or GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the message that is being requested.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the message that is being requested.
|
||||||
|
*/
|
||||||
|
uint64_t message_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset of the fragment that is being requested.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional flags for the request.
|
||||||
|
*/
|
||||||
|
uint64_t flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An `enum GNUNET_MULTICAST_ReplayErrorCode` identifying issues (in NBO).
|
||||||
|
*/
|
||||||
|
int32_t error_code;
|
||||||
|
|
||||||
|
/* followed by replayed message */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message sent from the client to the service to notify the service
|
||||||
|
* about the starting of a multicast group with this peers as its origin.
|
||||||
|
*/
|
||||||
|
struct MulticastOriginStartMessage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always zero.
|
||||||
|
*/
|
||||||
|
uint32_t reserved;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private, non-ephemeral key for the multicast group.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPrivateKey group_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last fragment ID sent to the group, used to continue counting fragments if
|
||||||
|
* we resume operating * a group.
|
||||||
|
*/
|
||||||
|
uint64_t max_fragment_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct MulticastMemberJoinMessage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t relay_count GNUNET_PACKED;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPrivateKey member_key;
|
||||||
|
|
||||||
|
struct GNUNET_PeerIdentity origin;
|
||||||
|
|
||||||
|
/* Followed by struct GNUNET_PeerIdentity relays[relay_count] */
|
||||||
|
|
||||||
|
/* Followed by struct GNUNET_MessageHeader join_msg */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_END
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/* end of multicast.h */
|
1399
src/multicast/multicast_api.c
Normal file
1399
src/multicast/multicast_api.c
Normal file
File diff suppressed because it is too large
Load Diff
758
src/multicast/test_multicast.c
Normal file
758
src/multicast/test_multicast.c
Normal file
@ -0,0 +1,758 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file multicast/test_multicast.c
|
||||||
|
* @brief Tests for the Multicast API.
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_crypto_lib.h"
|
||||||
|
#include "gnunet_common.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_testing_lib.h"
|
||||||
|
#include "gnunet_multicast_service.h"
|
||||||
|
|
||||||
|
#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value from 'main'.
|
||||||
|
*/
|
||||||
|
static int res;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for task for timeout termination.
|
||||||
|
*/
|
||||||
|
static struct GNUNET_SCHEDULER_Task * end_badly_task;
|
||||||
|
|
||||||
|
static const struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||||
|
|
||||||
|
struct GNUNET_PeerIdentity this_peer;
|
||||||
|
|
||||||
|
struct GNUNET_MULTICAST_Origin *origin;
|
||||||
|
struct GNUNET_MULTICAST_Member *member;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key;
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
|
||||||
|
|
||||||
|
struct TransmitClosure {
|
||||||
|
struct GNUNET_MULTICAST_OriginTransmitHandle *orig_tmit;
|
||||||
|
struct GNUNET_MULTICAST_MemberTransmitHandle *mem_tmit;
|
||||||
|
char * data[16];
|
||||||
|
uint8_t data_delay[16];
|
||||||
|
uint8_t data_count;
|
||||||
|
uint8_t paused;
|
||||||
|
uint8_t n;
|
||||||
|
} tmit_cls;
|
||||||
|
|
||||||
|
struct OriginClosure {
|
||||||
|
uint8_t msgs_expected;
|
||||||
|
uint8_t n;
|
||||||
|
} origin_cls;
|
||||||
|
|
||||||
|
struct MemberClosure {
|
||||||
|
uint8_t msgs_expected;
|
||||||
|
size_t n;
|
||||||
|
} member_cls;
|
||||||
|
|
||||||
|
struct GNUNET_MessageHeader *join_req, *join_resp;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TEST_NONE = 0,
|
||||||
|
TEST_ORIGIN_START = 1,
|
||||||
|
TEST_MEMBER_JOIN_REFUSE = 2,
|
||||||
|
TEST_MEMBER_JOIN_ADMIT = 3,
|
||||||
|
TEST_ORIGIN_TO_ALL = 4,
|
||||||
|
TEST_ORIGIN_TO_ALL_RECV = 5,
|
||||||
|
TEST_MEMBER_TO_ORIGIN = 6,
|
||||||
|
TEST_MEMBER_REPLAY_ERROR = 7,
|
||||||
|
TEST_MEMBER_REPLAY_OK = 8,
|
||||||
|
TEST_MEMBER_PART = 9,
|
||||||
|
TEST_ORIGIN_STOP = 10,
|
||||||
|
} test;
|
||||||
|
|
||||||
|
uint64_t replay_fragment_id;
|
||||||
|
uint64_t replay_flags;
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_join (int t);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up all resources used.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cleanup ()
|
||||||
|
{
|
||||||
|
if (NULL != member)
|
||||||
|
{
|
||||||
|
GNUNET_MULTICAST_member_part (member, NULL, NULL);
|
||||||
|
member = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != origin)
|
||||||
|
{
|
||||||
|
GNUNET_MULTICAST_origin_stop (origin, NULL, NULL);
|
||||||
|
origin = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminate the test case (failure).
|
||||||
|
*
|
||||||
|
* @param cls NULL
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
end_badly (void *cls)
|
||||||
|
{
|
||||||
|
res = 1;
|
||||||
|
cleanup ();
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test FAILED.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminate the test case (success).
|
||||||
|
*
|
||||||
|
* @param cls NULL
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
end_normally (void *cls)
|
||||||
|
{
|
||||||
|
res = 0;
|
||||||
|
cleanup ();
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test PASSED.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish the test case (successfully).
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
end ()
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n");
|
||||||
|
|
||||||
|
if (end_badly_task != NULL)
|
||||||
|
{
|
||||||
|
GNUNET_SCHEDULER_cancel (end_badly_task);
|
||||||
|
end_badly_task = NULL;
|
||||||
|
}
|
||||||
|
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
|
||||||
|
&end_normally, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
tmit_resume (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n");
|
||||||
|
struct TransmitClosure *tmit = cls;
|
||||||
|
if (NULL != tmit->orig_tmit)
|
||||||
|
GNUNET_MULTICAST_origin_to_all_resume (tmit->orig_tmit);
|
||||||
|
else if (NULL != tmit->mem_tmit)
|
||||||
|
GNUNET_MULTICAST_member_to_origin_resume (tmit->mem_tmit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
tmit_notify (void *cls, size_t *data_size, void *data)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"Test #%u: origin_tmit_notify()\n", test);
|
||||||
|
struct TransmitClosure *tmit = cls;
|
||||||
|
|
||||||
|
if (0 == tmit->data_count)
|
||||||
|
{
|
||||||
|
*data_size = 0;
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t size = strlen (tmit->data[tmit->n]);
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"Transmit notify data: %u bytes available, processing fragment %u/%u (size %u).\n",
|
||||||
|
(unsigned int) *data_size,
|
||||||
|
tmit->n + 1,
|
||||||
|
tmit->data_count,
|
||||||
|
size);
|
||||||
|
if (*data_size < size)
|
||||||
|
{
|
||||||
|
*data_size = 0;
|
||||||
|
GNUNET_assert (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n])
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission paused.\n");
|
||||||
|
tmit->paused = GNUNET_YES;
|
||||||
|
GNUNET_SCHEDULER_add_delayed (
|
||||||
|
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
|
||||||
|
tmit->data_delay[tmit->n]),
|
||||||
|
tmit_resume, tmit);
|
||||||
|
*data_size = 0;
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
tmit->paused = GNUNET_NO;
|
||||||
|
|
||||||
|
*data_size = size;
|
||||||
|
GNUNET_memcpy (data, tmit->data[tmit->n], size);
|
||||||
|
|
||||||
|
return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_recv_join_request (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg,
|
||||||
|
struct GNUNET_MULTICAST_JoinHandle *jh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_recv_join_request()\n", test);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_stopped (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: origin_stopped()\n", test);
|
||||||
|
end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
schedule_origin_stop (void *cls)
|
||||||
|
{
|
||||||
|
test = TEST_ORIGIN_STOP;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: origin_stop()\n", test);
|
||||||
|
GNUNET_MULTICAST_origin_stop (origin, origin_stopped, NULL);
|
||||||
|
origin = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_parted (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_parted()\n", test);
|
||||||
|
member = NULL;
|
||||||
|
|
||||||
|
switch (test)
|
||||||
|
{
|
||||||
|
case TEST_MEMBER_JOIN_REFUSE:
|
||||||
|
// Test 3 starts here
|
||||||
|
member_join (TEST_MEMBER_JOIN_ADMIT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEST_MEMBER_PART:
|
||||||
|
GNUNET_SCHEDULER_add_now (&schedule_origin_stop, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Invalid test #%d in member_parted()\n", test);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
schedule_member_part (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: schedule_member_part()\n", test);
|
||||||
|
GNUNET_MULTICAST_member_part (member, member_parted, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_part ()
|
||||||
|
{
|
||||||
|
test = TEST_MEMBER_PART;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_part()\n", test);
|
||||||
|
// Test 10 starts here
|
||||||
|
GNUNET_SCHEDULER_add_now (&schedule_member_part, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_replay_ok ()
|
||||||
|
{
|
||||||
|
// Execution of test 8 here
|
||||||
|
test = TEST_MEMBER_REPLAY_OK;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_replay_ok()\n", test);
|
||||||
|
replay_fragment_id = 1;
|
||||||
|
replay_flags = 1 | 1<<11;
|
||||||
|
GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id,
|
||||||
|
replay_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_replay_error ()
|
||||||
|
{
|
||||||
|
test = TEST_MEMBER_REPLAY_ERROR;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_replay_error()\n", test);
|
||||||
|
replay_fragment_id = 1234;
|
||||||
|
replay_flags = 11 | 1<<11;
|
||||||
|
GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id,
|
||||||
|
replay_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_recv_replay_msg (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t fragment_offset,
|
||||||
|
uint64_t flags,
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle *rh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: origin_recv_replay_msg()\n", test);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_recv_replay_msg (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t fragment_offset,
|
||||||
|
uint64_t flags,
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle *rh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_recv_replay_msg()\n", test);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_recv_replay_frag (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
|
||||||
|
uint64_t fragment_id,
|
||||||
|
uint64_t flags,
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle *rh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: origin_recv_replay_frag()"
|
||||||
|
" - fragment_id=%" PRIu64 " flags=%" PRIu64 "\n",
|
||||||
|
test, fragment_id, flags);
|
||||||
|
GNUNET_assert (replay_fragment_id == fragment_id && replay_flags == flags);
|
||||||
|
switch (test)
|
||||||
|
{
|
||||||
|
case TEST_MEMBER_REPLAY_ERROR:
|
||||||
|
// Test 8 starts here
|
||||||
|
GNUNET_MULTICAST_replay_response (rh, NULL, GNUNET_SYSERR);
|
||||||
|
member_replay_ok ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEST_MEMBER_REPLAY_OK:
|
||||||
|
{
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader mmsg = {
|
||||||
|
.header = {
|
||||||
|
.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE),
|
||||||
|
.size = htons (sizeof (mmsg)),
|
||||||
|
},
|
||||||
|
.fragment_id = GNUNET_htonll (1),
|
||||||
|
.message_id = GNUNET_htonll (1),
|
||||||
|
.fragment_offset = 0,
|
||||||
|
.group_generation = GNUNET_htonll (1),
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
member_cls.n = 0;
|
||||||
|
member_cls.msgs_expected = 1;
|
||||||
|
GNUNET_MULTICAST_replay_response (rh, &mmsg.header, GNUNET_MULTICAST_REC_OK);
|
||||||
|
GNUNET_MULTICAST_replay_response_end (rh);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Invalid test #%d in origin_recv_replay_frag()\n", test);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_recv_replay_frag (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key,
|
||||||
|
uint64_t fragment_id,
|
||||||
|
uint64_t flags,
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle *rh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_recv_replay_frag()\n", test);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_recv_request (void *cls,
|
||||||
|
const struct GNUNET_MULTICAST_RequestHeader *req)
|
||||||
|
{
|
||||||
|
struct OriginClosure *ocls = cls;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: origin_recv_request()\n", test);
|
||||||
|
if (++ocls->n != ocls->msgs_expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GNUNET_assert (0 == memcmp (&req->member_pub_key,
|
||||||
|
&member_pub_key, sizeof (member_pub_key)));
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"Test #%u: verify message content, take first 3 bytes: %.3s\n",
|
||||||
|
test, (char *)&req[1]);
|
||||||
|
GNUNET_assert (0 == memcmp (&req[1], "abc", 3));
|
||||||
|
|
||||||
|
// Test 7 starts here
|
||||||
|
member_replay_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_to_origin ()
|
||||||
|
{
|
||||||
|
test = TEST_MEMBER_TO_ORIGIN;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_to_origin()\n", test);
|
||||||
|
|
||||||
|
struct TransmitClosure *tmit = &tmit_cls;
|
||||||
|
*tmit = (struct TransmitClosure) {};
|
||||||
|
tmit->data[0] = "abc def";
|
||||||
|
tmit->data[1] = "ghi jkl mno";
|
||||||
|
tmit->data_delay[1] = 2;
|
||||||
|
tmit->data[2] = "pqr stuw xyz";
|
||||||
|
tmit->data_count = 3;
|
||||||
|
|
||||||
|
origin_cls.n = 0;
|
||||||
|
origin_cls.msgs_expected = 1;
|
||||||
|
|
||||||
|
tmit->mem_tmit = GNUNET_MULTICAST_member_to_origin (member, 1,
|
||||||
|
tmit_notify, tmit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_recv_message (void *cls,
|
||||||
|
const struct GNUNET_MULTICAST_MessageHeader *msg)
|
||||||
|
{
|
||||||
|
struct MemberClosure *mcls = cls;
|
||||||
|
|
||||||
|
// Test 5 starts here after message has been received from origin
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"Test #%u: member_recv_message() %u/%u\n",
|
||||||
|
test,
|
||||||
|
(unsigned int) (mcls->n + 1),
|
||||||
|
mcls->msgs_expected);
|
||||||
|
if (++mcls->n != mcls->msgs_expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// FIXME: check message content
|
||||||
|
|
||||||
|
switch (test)
|
||||||
|
{
|
||||||
|
case TEST_ORIGIN_TO_ALL:
|
||||||
|
test = TEST_ORIGIN_TO_ALL_RECV;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEST_ORIGIN_TO_ALL_RECV:
|
||||||
|
// Test 6 starts here
|
||||||
|
member_to_origin ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEST_MEMBER_REPLAY_OK:
|
||||||
|
// Test 9 starts here
|
||||||
|
GNUNET_assert (replay_fragment_id == GNUNET_ntohll (msg->fragment_id));
|
||||||
|
member_part ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Invalid test #%d in origin_recv_message()\n", test);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_recv_message (void *cls,
|
||||||
|
const struct GNUNET_MULTICAST_MessageHeader *msg)
|
||||||
|
{
|
||||||
|
struct OriginClosure *ocls = cls;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: origin_recv_message() %u/%u\n",
|
||||||
|
test, ocls->n + 1, ocls->msgs_expected);
|
||||||
|
if (++ocls->n != ocls->msgs_expected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// FIXME: check message content
|
||||||
|
|
||||||
|
switch (test)
|
||||||
|
{
|
||||||
|
case TEST_ORIGIN_TO_ALL:
|
||||||
|
// Prepare to execute test 5
|
||||||
|
test = TEST_ORIGIN_TO_ALL_RECV;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEST_ORIGIN_TO_ALL_RECV:
|
||||||
|
// Test 6 starts here
|
||||||
|
member_to_origin ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Invalid test #%d in origin_recv_message()\n", test);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_to_all ()
|
||||||
|
{
|
||||||
|
test = TEST_ORIGIN_TO_ALL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: origin_to_all()\n", test);
|
||||||
|
|
||||||
|
struct TransmitClosure *tmit = &tmit_cls;
|
||||||
|
*tmit = (struct TransmitClosure) {};
|
||||||
|
tmit->data[0] = "ABC DEF";
|
||||||
|
tmit->data[1] = GNUNET_malloc (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD + 1);
|
||||||
|
uint16_t i;
|
||||||
|
for (i = 0; i < GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD; i++)
|
||||||
|
tmit->data[1][i] = (0 == i % 10000) ? '0' + i / 10000 : '_';
|
||||||
|
tmit->data[2] = "GHI JKL MNO";
|
||||||
|
tmit->data_delay[2] = 2;
|
||||||
|
tmit->data[3] = "PQR STUW XYZ";
|
||||||
|
tmit->data_count = 4;
|
||||||
|
|
||||||
|
origin_cls.n = member_cls.n = 0;
|
||||||
|
origin_cls.msgs_expected = member_cls.msgs_expected = tmit->data_count;
|
||||||
|
|
||||||
|
tmit->orig_tmit = GNUNET_MULTICAST_origin_to_all (origin, 1, 1,
|
||||||
|
tmit_notify, tmit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_recv_join_decision (void *cls,
|
||||||
|
int is_admitted,
|
||||||
|
const struct GNUNET_PeerIdentity *peer,
|
||||||
|
uint16_t relay_count,
|
||||||
|
const struct GNUNET_PeerIdentity *relays,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_recv_join_decision() - is_admitted: %d\n",
|
||||||
|
test, is_admitted);
|
||||||
|
|
||||||
|
GNUNET_assert (join_msg->size == join_resp->size);
|
||||||
|
GNUNET_assert (join_msg->type == join_resp->type);
|
||||||
|
GNUNET_assert (0 == memcmp (join_msg, join_resp, ntohs (join_resp->size)));
|
||||||
|
|
||||||
|
switch (test)
|
||||||
|
{
|
||||||
|
case TEST_MEMBER_JOIN_REFUSE:
|
||||||
|
GNUNET_assert (0 == relay_count);
|
||||||
|
// Test 3 starts here
|
||||||
|
GNUNET_SCHEDULER_add_now (&schedule_member_part, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEST_MEMBER_JOIN_ADMIT:
|
||||||
|
GNUNET_assert (1 == relay_count);
|
||||||
|
GNUNET_assert (0 == memcmp (relays, &this_peer, sizeof (this_peer)));
|
||||||
|
// Test 4 starts here
|
||||||
|
origin_to_all ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Invalid test #%d in member_recv_join_decision()\n", test);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test: origin receives join request
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
origin_recv_join_request (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *mem_key,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg,
|
||||||
|
struct GNUNET_MULTICAST_JoinHandle *jh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: origin_recv_join_request()\n", test);
|
||||||
|
|
||||||
|
GNUNET_assert (0 == memcmp (mem_key, &member_pub_key, sizeof (member_pub_key)));
|
||||||
|
GNUNET_assert (join_msg->size == join_req->size);
|
||||||
|
GNUNET_assert (join_msg->type == join_req->type);
|
||||||
|
GNUNET_assert (0 == memcmp (join_msg, join_req, ntohs (join_req->size)));
|
||||||
|
|
||||||
|
char data[] = "here's the decision";
|
||||||
|
uint8_t data_size = strlen (data) + 1;
|
||||||
|
join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
|
||||||
|
join_resp->size = htons (sizeof (join_resp) + data_size);
|
||||||
|
join_resp->type = htons (456);
|
||||||
|
GNUNET_memcpy (&join_resp[1], data, data_size);
|
||||||
|
|
||||||
|
switch (test)
|
||||||
|
{
|
||||||
|
case TEST_MEMBER_JOIN_REFUSE:
|
||||||
|
// Test 3 starts here
|
||||||
|
GNUNET_MULTICAST_join_decision (jh, GNUNET_NO, 0, NULL, join_resp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEST_MEMBER_JOIN_ADMIT:
|
||||||
|
// Test 3 is running
|
||||||
|
GNUNET_MULTICAST_join_decision (jh, GNUNET_YES, 1, &this_peer, join_resp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Invalid test #%d in origin_recv_join_request()\n", test);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test: member joins multicast group
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
member_join (int t)
|
||||||
|
{
|
||||||
|
test = t;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: member_join()\n", test);
|
||||||
|
|
||||||
|
member_key = GNUNET_CRYPTO_ecdsa_key_create ();
|
||||||
|
GNUNET_CRYPTO_ecdsa_key_get_public (member_key, &member_pub_key);
|
||||||
|
|
||||||
|
if (NULL != join_req)
|
||||||
|
GNUNET_free (join_req);
|
||||||
|
|
||||||
|
char data[] = "let me in!";
|
||||||
|
uint8_t data_size = strlen (data) + 1;
|
||||||
|
join_req = GNUNET_malloc (sizeof (join_req) + data_size);
|
||||||
|
join_req->size = htons (sizeof (join_req) + data_size);
|
||||||
|
join_req->type = htons (123);
|
||||||
|
GNUNET_memcpy (&join_req[1], data, data_size);
|
||||||
|
|
||||||
|
member = GNUNET_MULTICAST_member_join (cfg, &group_pub_key, member_key,
|
||||||
|
&this_peer, 1, &this_peer, join_req,
|
||||||
|
member_recv_join_request,
|
||||||
|
member_recv_join_decision,
|
||||||
|
member_recv_replay_frag,
|
||||||
|
member_recv_replay_msg,
|
||||||
|
member_recv_message,
|
||||||
|
&member_cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test: Start a multicast group as origin
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
origin_start ()
|
||||||
|
{
|
||||||
|
test = TEST_ORIGIN_START;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Test #%u: origin_start()\n", test);
|
||||||
|
|
||||||
|
group_key = GNUNET_CRYPTO_eddsa_key_create ();
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);
|
||||||
|
|
||||||
|
origin = GNUNET_MULTICAST_origin_start (cfg, group_key, 0,
|
||||||
|
origin_recv_join_request,
|
||||||
|
origin_recv_replay_frag,
|
||||||
|
origin_recv_replay_msg,
|
||||||
|
origin_recv_request,
|
||||||
|
origin_recv_message,
|
||||||
|
&origin_cls);
|
||||||
|
// Test 2 starts here
|
||||||
|
member_join (TEST_MEMBER_JOIN_REFUSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main function of the test, run from scheduler.
|
||||||
|
*
|
||||||
|
* @param cls NULL
|
||||||
|
* @param cfg configuration we use (also to connect to Multicast service)
|
||||||
|
* @param peer handle to access more of the peer (not used)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
#if DEBUG_TEST_MULTICAST
|
||||||
|
run (void *cls,
|
||||||
|
char *const *args,
|
||||||
|
const char *cfgfile,
|
||||||
|
const struct GNUNET_CONFIGURATION_Handle *c)
|
||||||
|
#else
|
||||||
|
run (void *cls,
|
||||||
|
const struct GNUNET_CONFIGURATION_Handle *c,
|
||||||
|
struct GNUNET_TESTING_Peer *peer)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
cfg = c;
|
||||||
|
end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
|
||||||
|
&end_badly, NULL);
|
||||||
|
GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
|
||||||
|
|
||||||
|
// Test 1 starts here
|
||||||
|
origin_start ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
res = 1;
|
||||||
|
#if DEBUG_TEST_MULTICAST
|
||||||
|
const struct GNUNET_GETOPT_CommandLineOption opts[] = {
|
||||||
|
GNUNET_GETOPT_OPTION_END
|
||||||
|
};
|
||||||
|
if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-multicast",
|
||||||
|
"test-multicast [options]",
|
||||||
|
opts, &run, NULL))
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
if (0 != GNUNET_TESTING_peer_run ("test-multicast", "test_multicast.conf", &run, NULL))
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of test_multicast.c */
|
56
src/multicast/test_multicast.conf
Normal file
56
src/multicast/test_multicast.conf
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
[testbed]
|
||||||
|
HOSTNAME = localhost
|
||||||
|
|
||||||
|
[arm]
|
||||||
|
GLOBAL_POSTFIX=-L ERROR
|
||||||
|
|
||||||
|
[multicast]
|
||||||
|
#PREFIX = tmux new-window gdb -x ./cmd.gdb --args
|
||||||
|
#PREFIX = valgrind --leak-check=full
|
||||||
|
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock
|
||||||
|
|
||||||
|
[vpn]
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[peerinfo]
|
||||||
|
# Do not use shipped gnunet HELLOs
|
||||||
|
USE_INCLUDED_HELLOS = NO
|
||||||
|
|
||||||
|
# Option to disable all disk IO; only useful for testbed runs
|
||||||
|
# (large-scale experiments); disables persistence of HELLOs!
|
||||||
|
NO_IO = YES
|
||||||
|
|
||||||
|
[hostlist]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[nat]
|
||||||
|
ENABLE_UPNP = NO
|
||||||
|
|
||||||
|
[fs]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[vpn]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[revocation]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[gns]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[namestore]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[namecache]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[topology]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
520
src/multicast/test_multicast_2peers.c
Normal file
520
src/multicast/test_multicast_2peers.c
Normal file
@ -0,0 +1,520 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file multicast/test_multicast_2peers.c
|
||||||
|
* @brief Tests for the Multicast API with two peers doing the ping
|
||||||
|
* pong test.
|
||||||
|
* @author xrs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_crypto_lib.h"
|
||||||
|
#include "gnunet_common.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_testbed_service.h"
|
||||||
|
#include "gnunet_multicast_service.h"
|
||||||
|
|
||||||
|
#define NUM_PEERS 2
|
||||||
|
|
||||||
|
static struct GNUNET_TESTBED_Operation *op0;
|
||||||
|
static struct GNUNET_TESTBED_Operation *op1;
|
||||||
|
static struct GNUNET_TESTBED_Operation *pi_op0;
|
||||||
|
static struct GNUNET_TESTBED_Operation *pi_op1;
|
||||||
|
|
||||||
|
static struct GNUNET_TESTBED_Peer **peers;
|
||||||
|
const struct GNUNET_PeerIdentity *peer_id[2];
|
||||||
|
|
||||||
|
static struct GNUNET_SCHEDULER_Task *timeout_tid;
|
||||||
|
|
||||||
|
static struct GNUNET_MULTICAST_Origin *origin;
|
||||||
|
static struct GNUNET_MULTICAST_Member *member;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key;
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global result for testcase.
|
||||||
|
*/
|
||||||
|
static int result;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
|
||||||
|
* Cleans up.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
shutdown_task (void *cls)
|
||||||
|
{
|
||||||
|
if (NULL != op0)
|
||||||
|
{
|
||||||
|
GNUNET_TESTBED_operation_done (op0);
|
||||||
|
op0 = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != op1)
|
||||||
|
{
|
||||||
|
GNUNET_TESTBED_operation_done (op1);
|
||||||
|
op1 = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != pi_op0)
|
||||||
|
{
|
||||||
|
GNUNET_TESTBED_operation_done (pi_op0);
|
||||||
|
pi_op0 = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != pi_op1)
|
||||||
|
{
|
||||||
|
GNUNET_TESTBED_operation_done (pi_op1);
|
||||||
|
pi_op1 = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != timeout_tid)
|
||||||
|
{
|
||||||
|
GNUNET_SCHEDULER_cancel (timeout_tid);
|
||||||
|
timeout_tid = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
timeout_task (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Timeout!\n");
|
||||||
|
result = GNUNET_SYSERR;
|
||||||
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_join_request (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg,
|
||||||
|
struct GNUNET_MULTICAST_JoinHandle *jh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Member sent a join request.\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
notify (void *cls,
|
||||||
|
size_t *data_size,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
char text[] = "ping";
|
||||||
|
*data_size = strlen(text)+1;
|
||||||
|
GNUNET_memcpy(data, text, *data_size);
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Member sents message to origin: %s\n", text);
|
||||||
|
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_join_decision (void *cls,
|
||||||
|
int is_admitted,
|
||||||
|
const struct GNUNET_PeerIdentity *peer,
|
||||||
|
uint16_t relay_count,
|
||||||
|
const struct GNUNET_PeerIdentity *relays,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Member received a decision from origin: %s\n",
|
||||||
|
(GNUNET_YES == is_admitted)
|
||||||
|
? "accepted"
|
||||||
|
: "rejected");
|
||||||
|
|
||||||
|
if (GNUNET_YES == is_admitted)
|
||||||
|
{
|
||||||
|
struct GNUNET_MULTICAST_MemberTransmitHandle *req;
|
||||||
|
|
||||||
|
// FIXME: move to MQ-style API!
|
||||||
|
req = GNUNET_MULTICAST_member_to_origin (member,
|
||||||
|
0,
|
||||||
|
¬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 */
|
63
src/multicast/test_multicast_line.conf
Normal file
63
src/multicast/test_multicast_line.conf
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
[testbed]
|
||||||
|
HOSTNAME = localhost
|
||||||
|
OVERLAY_TOPOLOGY = LINE
|
||||||
|
|
||||||
|
[arm]
|
||||||
|
GLOBAL_POSTFIX=-L ERROR
|
||||||
|
|
||||||
|
[multicast]
|
||||||
|
#PREFIX = tmux new-window gdb -x ./cmd.gdb --args
|
||||||
|
#PREFIX = valgrind --leak-check=full
|
||||||
|
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock
|
||||||
|
|
||||||
|
[vpn]
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[peerinfo]
|
||||||
|
# Do not use shipped gnunet HELLOs
|
||||||
|
USE_INCLUDED_HELLOS = NO
|
||||||
|
|
||||||
|
# Option to disable all disk IO; only useful for testbed runs
|
||||||
|
# (large-scale experiments); disables persistence of HELLOs!
|
||||||
|
NO_IO = YES
|
||||||
|
|
||||||
|
[cadet]
|
||||||
|
ID_ANNOUNCE_TIME = 5 s
|
||||||
|
|
||||||
|
[hostlist]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[nat]
|
||||||
|
ENABLE_UPNP = NO
|
||||||
|
|
||||||
|
[fs]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[vpn]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[revocation]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[gns]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[namestore]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[namecache]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[topology]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[nse]
|
||||||
|
WORKBITS = 0
|
643
src/multicast/test_multicast_multipeer.c
Normal file
643
src/multicast/test_multicast_multipeer.c
Normal file
@ -0,0 +1,643 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file multicast/test_multicast_multipeers.c
|
||||||
|
* @brief Tests for the Multicast API with multiple peers.
|
||||||
|
* @author xrs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_crypto_lib.h"
|
||||||
|
#include "gnunet_common.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_testbed_service.h"
|
||||||
|
#include "gnunet_multicast_service.h"
|
||||||
|
|
||||||
|
#define PEERS_REQUESTED 12
|
||||||
|
|
||||||
|
struct MulticastPeerContext
|
||||||
|
{
|
||||||
|
int peer; /* peer number */
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
|
||||||
|
const struct GNUNET_PeerIdentity *id;
|
||||||
|
struct GNUNET_TESTBED_Operation *op; /* not yet in use */
|
||||||
|
struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */
|
||||||
|
int test_ok;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum pingpong
|
||||||
|
{
|
||||||
|
PING = 1,
|
||||||
|
PONG = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pingpong_msg
|
||||||
|
{
|
||||||
|
int peer;
|
||||||
|
enum pingpong msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void service_connect (void *cls,
|
||||||
|
struct GNUNET_TESTBED_Operation *op,
|
||||||
|
void *ca_result,
|
||||||
|
const char *emsg);
|
||||||
|
|
||||||
|
static struct MulticastPeerContext **multicast_peers;
|
||||||
|
static struct GNUNET_TESTBED_Peer **peers;
|
||||||
|
|
||||||
|
static struct GNUNET_TESTBED_Operation *op[PEERS_REQUESTED];
|
||||||
|
static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED];
|
||||||
|
|
||||||
|
static struct GNUNET_MULTICAST_Origin *origin;
|
||||||
|
static struct GNUNET_MULTICAST_Member *members[PEERS_REQUESTED]; /* first element always empty */
|
||||||
|
|
||||||
|
static struct GNUNET_SCHEDULER_Task *timeout_tid;
|
||||||
|
|
||||||
|
static struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
|
||||||
|
static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
|
||||||
|
static struct GNUNET_HashCode group_pub_key_hash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global result for testcase.
|
||||||
|
*/
|
||||||
|
static int result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
|
||||||
|
* Cleans up.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
shutdown_task (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"shutdown_task!\n");
|
||||||
|
for (int i=0;i<PEERS_REQUESTED;i++)
|
||||||
|
{
|
||||||
|
if (NULL != op[i])
|
||||||
|
{
|
||||||
|
GNUNET_TESTBED_operation_done(op[i]);
|
||||||
|
op[i] = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != pi_op[i])
|
||||||
|
{
|
||||||
|
GNUNET_TESTBED_operation_done (pi_op[i]);
|
||||||
|
pi_op[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != multicast_peers)
|
||||||
|
{
|
||||||
|
for (int i=0; i < PEERS_REQUESTED; i++)
|
||||||
|
{
|
||||||
|
GNUNET_free_non_null (multicast_peers[i]->key);
|
||||||
|
GNUNET_free (multicast_peers[i]);
|
||||||
|
multicast_peers[i] = NULL;
|
||||||
|
}
|
||||||
|
GNUNET_free (multicast_peers);
|
||||||
|
multicast_peers = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != timeout_tid)
|
||||||
|
{
|
||||||
|
GNUNET_SCHEDULER_cancel (timeout_tid);
|
||||||
|
timeout_tid = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
timeout_task (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Timeout!\n");
|
||||||
|
result = GNUNET_SYSERR;
|
||||||
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_join_request (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg,
|
||||||
|
struct GNUNET_MULTICAST_JoinHandle *jh)
|
||||||
|
{
|
||||||
|
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Peer #%u (%s) sent a join request.\n",
|
||||||
|
mc_peer->peer,
|
||||||
|
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
notify (void *cls,
|
||||||
|
size_t *data_size,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
|
||||||
|
|
||||||
|
struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
|
||||||
|
pp_msg->peer = mc_peer->peer;
|
||||||
|
pp_msg->msg = PING;
|
||||||
|
|
||||||
|
*data_size = sizeof (struct pingpong_msg);
|
||||||
|
GNUNET_memcpy(data, pp_msg, *data_size);
|
||||||
|
GNUNET_free (pp_msg);
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Peer #%u sents ping to origin\n", mc_peer->peer);
|
||||||
|
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_join_decision (void *cls,
|
||||||
|
int is_admitted,
|
||||||
|
const struct GNUNET_PeerIdentity *peer,
|
||||||
|
uint16_t relay_count,
|
||||||
|
const struct GNUNET_PeerIdentity *relays,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg)
|
||||||
|
{
|
||||||
|
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Peer #%u (%s) received a decision from origin: %s\n",
|
||||||
|
mc_peer->peer,
|
||||||
|
GNUNET_i2s (multicast_peers[mc_peer->peer]->id),
|
||||||
|
(GNUNET_YES == is_admitted)?"accepted":"rejected");
|
||||||
|
|
||||||
|
if (GNUNET_YES == is_admitted)
|
||||||
|
{
|
||||||
|
GNUNET_MULTICAST_member_to_origin (members[mc_peer->peer],
|
||||||
|
0,
|
||||||
|
notify,
|
||||||
|
cls);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_replay_frag ()
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"member replay frag...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_replay_msg ()
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"member replay msg...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_disconnected_cb (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"Origin disconnected. Shutting down.\n");
|
||||||
|
result = GNUNET_YES;
|
||||||
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_disconnected_cb (void *cls)
|
||||||
|
{
|
||||||
|
for (int i = 1; i < PEERS_REQUESTED; ++i)
|
||||||
|
if (GNUNET_NO == multicast_peers[i]->test_ok)
|
||||||
|
return;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"All member disconnected. Stopping origin.\n");
|
||||||
|
GNUNET_MULTICAST_origin_stop (origin, origin_disconnected_cb, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
member_message (void *cls,
|
||||||
|
const struct GNUNET_MULTICAST_MessageHeader *msg)
|
||||||
|
{
|
||||||
|
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
|
||||||
|
struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]);
|
||||||
|
|
||||||
|
if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"peer #%i (%s) receives a pong\n",
|
||||||
|
mc_peer->peer,
|
||||||
|
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
|
||||||
|
mc_peer->test_ok = GNUNET_OK;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"peer #%u (%s) parting from multicast group\n",
|
||||||
|
mc_peer->peer,
|
||||||
|
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
|
||||||
|
|
||||||
|
GNUNET_MULTICAST_member_part (members[mc_peer->peer], member_disconnected_cb, cls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_join_request (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
|
||||||
|
const struct GNUNET_MessageHeader *join_msg,
|
||||||
|
struct GNUNET_MULTICAST_JoinHandle *jh)
|
||||||
|
{
|
||||||
|
struct GNUNET_MessageHeader *join_resp;
|
||||||
|
|
||||||
|
uint8_t data_size = ntohs (join_msg->size);
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"origin got a join request...\n");
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"origin receives: '%s'\n", (char *)&join_msg[1]);
|
||||||
|
|
||||||
|
char data[] = "Come in!";
|
||||||
|
data_size = strlen (data) + 1;
|
||||||
|
join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
|
||||||
|
join_resp->size = htons (sizeof (join_resp) + data_size);
|
||||||
|
join_resp->type = htons (123);
|
||||||
|
GNUNET_memcpy (&join_resp[1], data, data_size);
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"origin sends: '%s'\n", data);
|
||||||
|
|
||||||
|
GNUNET_MULTICAST_join_decision (jh,
|
||||||
|
GNUNET_YES,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
join_resp);
|
||||||
|
|
||||||
|
result = GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_replay_frag (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
|
||||||
|
uint64_t fragment_id,
|
||||||
|
uint64_t flags,
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle *rh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay fraq msg\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_replay_msg (void *cls,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
|
||||||
|
uint64_t message_id,
|
||||||
|
uint64_t fragment_offset,
|
||||||
|
uint64_t flags,
|
||||||
|
struct GNUNET_MULTICAST_ReplayHandle *rh)
|
||||||
|
{
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay msg\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
origin_notify (void *cls,
|
||||||
|
size_t *data_size,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct pingpong_msg *rcv_pp_msg = (struct pingpong_msg*)cls;
|
||||||
|
struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
|
||||||
|
|
||||||
|
pp_msg->peer = rcv_pp_msg->peer;
|
||||||
|
pp_msg->msg = PONG;
|
||||||
|
*data_size = sizeof (struct pingpong_msg);
|
||||||
|
GNUNET_memcpy(data, pp_msg, *data_size);
|
||||||
|
GNUNET_free (pp_msg);
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends pong\n");
|
||||||
|
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_request (void *cls,
|
||||||
|
const struct GNUNET_MULTICAST_RequestHeader *req)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives a msg\n");
|
||||||
|
|
||||||
|
req++;
|
||||||
|
struct pingpong_msg *pp_msg = (struct pingpong_msg *) req;
|
||||||
|
|
||||||
|
if (1 != pp_msg->msg) {
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request");
|
||||||
|
}
|
||||||
|
|
||||||
|
GNUNET_MULTICAST_origin_to_all (origin,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
origin_notify,
|
||||||
|
pp_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
origin_message (void *cls,
|
||||||
|
const struct GNUNET_MULTICAST_MessageHeader *msg)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
multicast_disconnect (void *cls,
|
||||||
|
void *op_result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
multicast_connect (void *cls,
|
||||||
|
const struct GNUNET_CONFIGURATION_Handle *cfg)
|
||||||
|
{
|
||||||
|
struct MulticastPeerContext *multicast_peer = cls;
|
||||||
|
struct GNUNET_MessageHeader *join_msg;
|
||||||
|
char data[64];
|
||||||
|
|
||||||
|
if (0 == multicast_peer->peer)
|
||||||
|
{
|
||||||
|
group_key = GNUNET_CRYPTO_eddsa_key_create ();
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);
|
||||||
|
|
||||||
|
GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash);
|
||||||
|
origin = GNUNET_MULTICAST_origin_start (cfg,
|
||||||
|
group_key,
|
||||||
|
0,
|
||||||
|
origin_join_request,
|
||||||
|
origin_replay_frag,
|
||||||
|
origin_replay_msg,
|
||||||
|
origin_request,
|
||||||
|
origin_message,
|
||||||
|
cls);
|
||||||
|
if (NULL == origin)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Peer #%u could not create a multicast group",
|
||||||
|
multicast_peer->peer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Peer #%u connected as origin to group %s\n",
|
||||||
|
multicast_peer->peer,
|
||||||
|
GNUNET_h2s (&group_pub_key_hash));
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
multicast_peer->key = GNUNET_CRYPTO_ecdsa_key_create ();
|
||||||
|
|
||||||
|
sprintf(data, "Hi, I am peer #%u (%s). Can I enter?",
|
||||||
|
multicast_peer->peer,
|
||||||
|
GNUNET_i2s (multicast_peers[multicast_peer->peer]->id));
|
||||||
|
uint8_t data_size = strlen (data) + 1;
|
||||||
|
join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
|
||||||
|
join_msg->size = htons (sizeof (join_msg) + data_size);
|
||||||
|
join_msg->type = htons (123);
|
||||||
|
GNUNET_memcpy (&join_msg[1], data, data_size);
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Peer #%u (%s) tries to join multicast group %s\n",
|
||||||
|
multicast_peer->peer,
|
||||||
|
GNUNET_i2s (multicast_peers[multicast_peer->peer]->id),
|
||||||
|
GNUNET_h2s (&group_pub_key_hash));
|
||||||
|
|
||||||
|
members[multicast_peer->peer] =
|
||||||
|
GNUNET_MULTICAST_member_join (cfg,
|
||||||
|
&group_pub_key,
|
||||||
|
multicast_peer->key,
|
||||||
|
multicast_peers[0]->id,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
join_msg, /* join message */
|
||||||
|
member_join_request,
|
||||||
|
member_join_decision,
|
||||||
|
member_replay_frag,
|
||||||
|
member_replay_msg,
|
||||||
|
member_message,
|
||||||
|
cls);
|
||||||
|
return members[multicast_peer->peer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
peer_information_cb (void *cls,
|
||||||
|
struct GNUNET_TESTBED_Operation *operation,
|
||||||
|
const struct GNUNET_TESTBED_PeerInformation *pinfo,
|
||||||
|
const char *emsg)
|
||||||
|
{
|
||||||
|
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
|
||||||
|
|
||||||
|
if (NULL == pinfo) {
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n");
|
||||||
|
result = GNUNET_SYSERR;
|
||||||
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
multicast_peers[mc_peer->peer]->id = pinfo->result.id;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Got peer information of %s (%s)\n",
|
||||||
|
(0 == mc_peer->peer)? "origin" : "member",
|
||||||
|
GNUNET_i2s (pinfo->result.id));
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Create peer #%u (%s)\n",
|
||||||
|
mc_peer->peer,
|
||||||
|
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
|
||||||
|
|
||||||
|
if (0 != mc_peer->peer)
|
||||||
|
{
|
||||||
|
/* connect to multicast service of members */
|
||||||
|
op[mc_peer->peer] =
|
||||||
|
GNUNET_TESTBED_service_connect (/* Closure for operation */
|
||||||
|
NULL,
|
||||||
|
/* The peer whose service to connect to */
|
||||||
|
peers[mc_peer->peer],
|
||||||
|
/* The name of the service */
|
||||||
|
"multicast",
|
||||||
|
/* called after a handle to service is opened */
|
||||||
|
service_connect,
|
||||||
|
/* closure for the above callback */
|
||||||
|
cls,
|
||||||
|
/* called when opening the service connection */
|
||||||
|
multicast_connect,
|
||||||
|
/* called when closing the service connection */
|
||||||
|
multicast_disconnect,
|
||||||
|
/* closure for the above two callbacks */
|
||||||
|
cls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
service_connect (void *cls,
|
||||||
|
struct GNUNET_TESTBED_Operation *op,
|
||||||
|
void *ca_result,
|
||||||
|
const char *emsg)
|
||||||
|
{
|
||||||
|
struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
|
||||||
|
|
||||||
|
if (NULL == ca_result)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Connection adapter not created for peer #%u (%s)\n",
|
||||||
|
mc_peer->peer,
|
||||||
|
GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
|
||||||
|
|
||||||
|
result = GNUNET_SYSERR;
|
||||||
|
GNUNET_SCHEDULER_shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == mc_peer->peer)
|
||||||
|
{
|
||||||
|
// Get GNUnet identity of members
|
||||||
|
for (int i = 0; i<PEERS_REQUESTED; i++)
|
||||||
|
{
|
||||||
|
pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i],
|
||||||
|
GNUNET_TESTBED_PIT_IDENTITY,
|
||||||
|
peer_information_cb,
|
||||||
|
multicast_peers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main function inovked from TESTBED once all of the
|
||||||
|
* peers are up and running. This one then connects
|
||||||
|
* just to the multicast service of peer 0 and 1.
|
||||||
|
* Peer 0 is going to be origin.
|
||||||
|
* Peer 1 is going to be one member.
|
||||||
|
* Origin will start a multicast group and the member will try to join it.
|
||||||
|
* After that we execute some multicast test.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param h the run handle
|
||||||
|
* @param peers started peers for the test
|
||||||
|
* @param PEERS_REQUESTED size of the 'peers' array
|
||||||
|
* @param links_succeeded number of links between peers that were created
|
||||||
|
* @param links_failed number of links testbed was unable to establish
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
testbed_master (void *cls,
|
||||||
|
struct GNUNET_TESTBED_RunHandle *h,
|
||||||
|
unsigned int num_peers,
|
||||||
|
struct GNUNET_TESTBED_Peer **p,
|
||||||
|
unsigned int links_succeeded,
|
||||||
|
unsigned int links_failed)
|
||||||
|
{
|
||||||
|
/* Testbed is ready with peers running and connected in a pre-defined overlay
|
||||||
|
topology (FIXME) */
|
||||||
|
peers = p;
|
||||||
|
multicast_peers = GNUNET_new_array (PEERS_REQUESTED, struct MulticastPeerContext*);
|
||||||
|
|
||||||
|
// Create test contexts for members
|
||||||
|
for (int i = 0; i<PEERS_REQUESTED; i++)
|
||||||
|
{
|
||||||
|
multicast_peers[i] = GNUNET_new (struct MulticastPeerContext);
|
||||||
|
multicast_peers[i]->peer = i;
|
||||||
|
multicast_peers[i]->test_ok = GNUNET_NO;
|
||||||
|
}
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Create origin peer\n");
|
||||||
|
op[0] =
|
||||||
|
GNUNET_TESTBED_service_connect (/* Closure for operation */
|
||||||
|
NULL,
|
||||||
|
/* The peer whose service to connect to */
|
||||||
|
peers[0],
|
||||||
|
/* The name of the service */
|
||||||
|
"multicast",
|
||||||
|
/* called after a handle to service is opened */
|
||||||
|
service_connect,
|
||||||
|
/* closure for the above callback */
|
||||||
|
multicast_peers[0],
|
||||||
|
/* called when opening the service connection */
|
||||||
|
multicast_connect,
|
||||||
|
/* called when closing the service connection */
|
||||||
|
multicast_disconnect,
|
||||||
|
/* closure for the above two callbacks */
|
||||||
|
multicast_peers[0]);
|
||||||
|
/* Schedule a new task on shutdown */
|
||||||
|
GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
|
||||||
|
/* Schedule the shutdown task with a delay of a few Seconds */
|
||||||
|
timeout_tid =
|
||||||
|
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
|
||||||
|
(GNUNET_TIME_UNIT_SECONDS, 400),
|
||||||
|
&timeout_task,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char const *config_file;
|
||||||
|
|
||||||
|
if (strstr (argv[0], "_line") != NULL)
|
||||||
|
{
|
||||||
|
config_file = "test_multicast_line.conf";
|
||||||
|
}
|
||||||
|
else if (strstr(argv[0], "_star") != NULL)
|
||||||
|
{
|
||||||
|
config_file = "test_multicast_star.conf";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config_file = "test_multicast_star.conf";
|
||||||
|
}
|
||||||
|
|
||||||
|
result = GNUNET_SYSERR;
|
||||||
|
ret =
|
||||||
|
GNUNET_TESTBED_test_run ("test-multicast-multipeer",
|
||||||
|
config_file,
|
||||||
|
/* number of peers to start */
|
||||||
|
PEERS_REQUESTED,
|
||||||
|
/* Event mask - set to 0 for no event notifications */
|
||||||
|
0LL,
|
||||||
|
/* Controller event callback */
|
||||||
|
NULL,
|
||||||
|
/* Closure for controller event callback */
|
||||||
|
NULL,
|
||||||
|
/* called when testbed setup is complete */
|
||||||
|
testbed_master,
|
||||||
|
/* Closure for the test_master callback */
|
||||||
|
NULL);
|
||||||
|
if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of test_multicast_multipeer.c */
|
64
src/multicast/test_multicast_star.conf
Normal file
64
src/multicast/test_multicast_star.conf
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
[testbed]
|
||||||
|
HOSTNAME = localhost
|
||||||
|
OVERLAY_TOPOLOGY = STAR
|
||||||
|
|
||||||
|
[arm]
|
||||||
|
GLOBAL_POSTFIX=-L ERROR
|
||||||
|
|
||||||
|
[multicast]
|
||||||
|
#PREFIX = tmux new-window gdb -x ./cmd.gdb --args
|
||||||
|
#PREFIX = valgrind --leak-check=full
|
||||||
|
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock
|
||||||
|
|
||||||
|
[vpn]
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[peerinfo]
|
||||||
|
# Do not use shipped gnunet HELLOs
|
||||||
|
USE_INCLUDED_HELLOS = NO
|
||||||
|
|
||||||
|
# Option to disable all disk IO; only useful for testbed runs
|
||||||
|
# (large-scale experiments); disables persistence of HELLOs!
|
||||||
|
NO_IO = YES
|
||||||
|
|
||||||
|
[cadet]
|
||||||
|
ID_ANNOUNCE_TIME = 5 s
|
||||||
|
|
||||||
|
[hostlist]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[nat]
|
||||||
|
ENABLE_UPNP = NO
|
||||||
|
|
||||||
|
[fs]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[vpn]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[revocation]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[gns]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[namestore]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[namecache]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[topology]
|
||||||
|
IMMEDIATE_START = NO
|
||||||
|
START_ON_DEMAND = NO
|
||||||
|
|
||||||
|
[nse]
|
||||||
|
WORKBITS = 0
|
||||||
|
|
2
src/psyc/.gitignore
vendored
Normal file
2
src/psyc/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
gnunet-service-psyc
|
||||||
|
test_psyc
|
77
src/psyc/Makefile.am
Normal file
77
src/psyc/Makefile.am
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# This Makefile.am is in the public domain
|
||||||
|
AM_CPPFLAGS = -I$(top_srcdir)/src/include
|
||||||
|
|
||||||
|
pkgcfgdir= $(pkgdatadir)/config.d/
|
||||||
|
|
||||||
|
libexecdir= $(pkglibdir)/libexec/
|
||||||
|
|
||||||
|
pkgcfg_DATA = \
|
||||||
|
psyc.conf
|
||||||
|
|
||||||
|
|
||||||
|
if MINGW
|
||||||
|
WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
|
||||||
|
endif
|
||||||
|
|
||||||
|
if USE_COVERAGE
|
||||||
|
AM_CFLAGS = --coverage -O0
|
||||||
|
XLIB = -lgcov
|
||||||
|
endif
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libgnunetpsyc.la
|
||||||
|
|
||||||
|
libgnunetpsyc_la_SOURCES = \
|
||||||
|
psyc_api.c psyc.h
|
||||||
|
libgnunetpsyc_la_LIBADD = \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la \
|
||||||
|
$(top_builddir)/src/psycutil/libgnunetpsycutil.la \
|
||||||
|
$(GN_LIBINTL) $(XLIB)
|
||||||
|
libgnunetpsyc_la_LDFLAGS = \
|
||||||
|
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
|
||||||
|
-version-info 0:0:0
|
||||||
|
|
||||||
|
bin_PROGRAMS =
|
||||||
|
|
||||||
|
libexec_PROGRAMS = \
|
||||||
|
gnunet-service-psyc
|
||||||
|
|
||||||
|
gnunet_service_psyc_SOURCES = \
|
||||||
|
gnunet-service-psyc.c
|
||||||
|
gnunet_service_psyc_LDADD = \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la \
|
||||||
|
$(top_builddir)/src/statistics/libgnunetstatistics.la \
|
||||||
|
$(top_builddir)/src/multicast/libgnunetmulticast.la \
|
||||||
|
$(top_builddir)/src/psycstore/libgnunetpsycstore.la \
|
||||||
|
$(top_builddir)/src/psycutil/libgnunetpsycutil.la \
|
||||||
|
$(GN_LIBINTL)
|
||||||
|
gnunet_service_psyc_CFLAGS = $(AM_CFLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
if HAVE_TESTING
|
||||||
|
check_PROGRAMS = \
|
||||||
|
test_psyc
|
||||||
|
# test_psyc2
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_TEST_RUN
|
||||||
|
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
|
||||||
|
TESTS = $(check_PROGRAMS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
test_psyc_SOURCES = \
|
||||||
|
test_psyc.c
|
||||||
|
test_psyc_LDADD = \
|
||||||
|
libgnunetpsyc.la \
|
||||||
|
$(top_builddir)/src/psycutil/libgnunetpsycutil.la \
|
||||||
|
$(top_builddir)/src/testing/libgnunettesting.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la
|
||||||
|
#test_psyc2_SOURCES = \
|
||||||
|
# test_psyc2.c
|
||||||
|
#test_psyc2_LDADD = \
|
||||||
|
# libgnunetpsyc.la \
|
||||||
|
# $(top_builddir)/src/psycutil/libgnunetpsycutil.la \
|
||||||
|
# $(top_builddir)/src/testbed/libgnunettestbed.la \
|
||||||
|
# $(top_builddir)/src/util/libgnunetutil.la
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
test_psyc.conf
|
2860
src/psyc/gnunet-service-psyc.c
Normal file
2860
src/psyc/gnunet-service-psyc.c
Normal file
File diff suppressed because it is too large
Load Diff
12
src/psyc/psyc.conf.in
Normal file
12
src/psyc/psyc.conf.in
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[psyc]
|
||||||
|
START_ON_DEMAND = @START_ON_DEMAND@
|
||||||
|
BINARY = gnunet-service-psyc
|
||||||
|
|
||||||
|
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-psyc.sock
|
||||||
|
UNIX_MATCH_UID = YES
|
||||||
|
UNIX_MATCH_GID = YES
|
||||||
|
|
||||||
|
@UNIXONLY@PORT = 2115
|
||||||
|
HOSTNAME = localhost
|
||||||
|
ACCEPT_FROM = 127.0.0.1;
|
||||||
|
ACCEPT_FROM6 = ::1;
|
178
src/psyc/psyc.h
Normal file
178
src/psyc/psyc.h
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file psyc/psyc.h
|
||||||
|
* @brief Common type definitions for the PSYC service and API.
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PSYC_H
|
||||||
|
#define PSYC_H
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_psyc_service.h"
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_check_message_parts (uint16_t data_size, const char *data,
|
||||||
|
uint16_t *first_ptype, uint16_t *last_ptype);
|
||||||
|
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind,
|
||||||
|
const struct GNUNET_MessageHeader *msg);
|
||||||
|
|
||||||
|
|
||||||
|
enum MessageState
|
||||||
|
{
|
||||||
|
MSG_STATE_START = 0,
|
||||||
|
MSG_STATE_HEADER = 1,
|
||||||
|
MSG_STATE_METHOD = 2,
|
||||||
|
MSG_STATE_MODIFIER = 3,
|
||||||
|
MSG_STATE_MOD_CONT = 4,
|
||||||
|
MSG_STATE_DATA = 5,
|
||||||
|
MSG_STATE_END = 6,
|
||||||
|
MSG_STATE_CANCEL = 7,
|
||||||
|
MSG_STATE_ERROR = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum MessageFragmentState
|
||||||
|
{
|
||||||
|
MSG_FRAG_STATE_START = 0,
|
||||||
|
MSG_FRAG_STATE_HEADER = 1,
|
||||||
|
MSG_FRAG_STATE_DATA = 2,
|
||||||
|
MSG_FRAG_STATE_END = 3,
|
||||||
|
MSG_FRAG_STATE_CANCEL = 4,
|
||||||
|
MSG_FRAG_STATE_DROP = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
/**** library -> service ****/
|
||||||
|
|
||||||
|
|
||||||
|
struct MasterStartRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYC_MASTER_START
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t policy GNUNET_PACKED;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EddsaPrivateKey channel_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct SlaveJoinRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t relay_count GNUNET_PACKED;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPrivateKey slave_key;
|
||||||
|
|
||||||
|
struct GNUNET_PeerIdentity origin;
|
||||||
|
|
||||||
|
uint32_t flags GNUNET_PACKED;
|
||||||
|
|
||||||
|
/* Followed by struct GNUNET_PeerIdentity relays[relay_count] */
|
||||||
|
|
||||||
|
/* Followed by struct GNUNET_MessageHeader join_msg */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ChannelMembershipStoreRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_MEMBERSHIP_STORE
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;
|
||||||
|
|
||||||
|
uint64_t announced_at GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t effective_since GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint8_t did_join;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct HistoryRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_HISTORY_REQUEST
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID for this operation.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t start_message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t end_message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t message_limit GNUNET_PACKED;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct StateRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Types:
|
||||||
|
* - GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STATE_GET
|
||||||
|
* - GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STATE_GET_PREFIX
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID for this operation.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/* Followed by NUL-terminated name. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**** service -> library ****/
|
||||||
|
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_END
|
||||||
|
|
||||||
|
#endif
|
1584
src/psyc/psyc_api.c
Normal file
1584
src/psyc/psyc_api.c
Normal file
File diff suppressed because it is too large
Load Diff
67
src/psyc/psyc_test_lib.h
Normal file
67
src/psyc/psyc_test_lib.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file psyc/test_psyc_api_join.c
|
||||||
|
* @brief library for writing psyc tests
|
||||||
|
* @author xrs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_TESTBED_OPS 32
|
||||||
|
|
||||||
|
struct pctx
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
struct GNUNET_TESTBED_Peer *testbed_peer;
|
||||||
|
|
||||||
|
const struct GNUNET_PeerIdentity *peer_id;
|
||||||
|
|
||||||
|
const struct GNUNET_PeerIdentity *peer_id_master;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to simulate egos (not peerid)
|
||||||
|
*/
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPrivateKey *id_key;
|
||||||
|
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *id_pub_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to store either GNUNET_PSYC_Master or GNUNET_PSYC_Slave handle
|
||||||
|
*/
|
||||||
|
void *psyc;
|
||||||
|
|
||||||
|
struct GNUNET_PSYC_Channel *channel;
|
||||||
|
|
||||||
|
const struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey *channel_pub_key;
|
||||||
|
|
||||||
|
int test_ok;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct GNUNET_SCHEDULER_Task *timeout_task_id;
|
||||||
|
|
||||||
|
static int result = GNUNET_SYSERR;
|
||||||
|
|
||||||
|
static struct GNUNET_TESTBED_Operation *op[MAX_TESTBED_OPS];
|
||||||
|
|
||||||
|
static int op_cnt = 0;
|
||||||
|
|
1018
src/psyc/test_psyc.c
Normal file
1018
src/psyc/test_psyc.c
Normal file
File diff suppressed because it is too large
Load Diff
284
src/psyc/test_psyc2.c
Normal file
284
src/psyc/test_psyc2.c
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file psyc/test_psyc2.c
|
||||||
|
* @brief Testbed test for the PSYC API.
|
||||||
|
* @author xrs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_crypto_lib.h"
|
||||||
|
#include "gnunet_common.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_testbed_service.h"
|
||||||
|
#include "gnunet_psyc_util_lib.h"
|
||||||
|
#include "gnunet_psyc_service.h"
|
||||||
|
|
||||||
|
#define PEERS_REQUESTED 2
|
||||||
|
|
||||||
|
static int result;
|
||||||
|
|
||||||
|
static struct GNUNET_SCHEDULER_Task *timeout_tid;
|
||||||
|
static struct pctx **pctx;
|
||||||
|
|
||||||
|
static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
|
||||||
|
static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
|
||||||
|
|
||||||
|
static struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key;
|
||||||
|
static struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task To perform tests
|
||||||
|
*/
|
||||||
|
static struct GNUNET_SCHEDULER_Task *test_task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peer id couter
|
||||||
|
*/
|
||||||
|
static unsigned int pids;
|
||||||
|
|
||||||
|
struct pctx
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
struct GNUNET_TESTBED_Peer *peer;
|
||||||
|
const struct GNUNET_PeerIdentity *id;
|
||||||
|
|
||||||
|
struct GNUNET_TESTBED_Operation *op;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* psyc service handle
|
||||||
|
*/
|
||||||
|
void *psyc;
|
||||||
|
struct GNUNET_PSYC_Master *mst;
|
||||||
|
struct GNUNET_PSYC_Slave *slv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* result for test on peer
|
||||||
|
*/
|
||||||
|
int test_ok;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
shutdown_task (void *cls)
|
||||||
|
{
|
||||||
|
if (NULL != pctx)
|
||||||
|
{
|
||||||
|
if (NULL != pctx[0]->mst)
|
||||||
|
GNUNET_PSYC_master_stop (pctx[0]->mst, GNUNET_NO, NULL, NULL);
|
||||||
|
|
||||||
|
for (int i=0; i < PEERS_REQUESTED; i++)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Operation done.\n");
|
||||||
|
GNUNET_TESTBED_operation_done (pctx[i]->op);
|
||||||
|
GNUNET_free_non_null (pctx[i]);
|
||||||
|
}
|
||||||
|
GNUNET_free (pctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != timeout_tid)
|
||||||
|
GNUNET_SCHEDULER_cancel (timeout_tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
timeout_task (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout!\n");
|
||||||
|
result = GNUNET_SYSERR;
|
||||||
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_test (void *cls)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pinfo_cb (void *cls,
|
||||||
|
struct GNUNET_TESTBED_Operation *operation,
|
||||||
|
const struct GNUNET_TESTBED_PeerInformation *pinfo,
|
||||||
|
const char *emsg)
|
||||||
|
{
|
||||||
|
struct pctx *pc = (struct pctx*) cls;
|
||||||
|
|
||||||
|
pc->id = pinfo->result.id;
|
||||||
|
|
||||||
|
pids++;
|
||||||
|
if (pids < (PEERS_REQUESTED - 1))
|
||||||
|
return;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
|
||||||
|
test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mst_start_cb ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
join_request_cb ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mst_message_cb ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mst_message_part_cb ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
slv_message_cb ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
slv_message_part_cb ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
slv_connect_cb ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
join_decision_cb ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
psyc_ca (void *cls,
|
||||||
|
const struct GNUNET_CONFIGURATION_Handle *cfg)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Message *join_msg = NULL;
|
||||||
|
struct pctx *pc = (struct pctx *) cls;
|
||||||
|
|
||||||
|
if (0 == pc->idx)
|
||||||
|
{
|
||||||
|
pc->mst = GNUNET_PSYC_master_start (cfg, channel_key,
|
||||||
|
GNUNET_PSYC_CHANNEL_PRIVATE,
|
||||||
|
&mst_start_cb, &join_request_cb,
|
||||||
|
&mst_message_cb, &mst_message_part_cb,
|
||||||
|
NULL);
|
||||||
|
return pc->mst;
|
||||||
|
}
|
||||||
|
|
||||||
|
pc->slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key,
|
||||||
|
GNUNET_PSYC_SLAVE_JOIN_NONE,
|
||||||
|
&pid, 0, NULL, &slv_message_cb,
|
||||||
|
&slv_message_part_cb,
|
||||||
|
&slv_connect_cb, &join_decision_cb,
|
||||||
|
NULL, join_msg);
|
||||||
|
return pc->slv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
psyc_da (void *cls,
|
||||||
|
void *op_result)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disconnected from service.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
service_connect (void *cls,
|
||||||
|
struct GNUNET_TESTBED_Operation *op,
|
||||||
|
void *ca_result,
|
||||||
|
const char *emsg)
|
||||||
|
{
|
||||||
|
struct pctx *pc = (struct pctx *) cls;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Connected to service\n");
|
||||||
|
|
||||||
|
GNUNET_assert (NULL != ca_result);
|
||||||
|
|
||||||
|
// FIXME: we need a simple service handle to connect to the service, then
|
||||||
|
// get peer information and AFTER that make PSYC ops. Compare to CADET.
|
||||||
|
pc->psyc = ca_result;
|
||||||
|
|
||||||
|
GNUNET_TESTBED_peer_get_information (pc->peer,
|
||||||
|
GNUNET_TESTBED_PIT_IDENTITY,
|
||||||
|
pinfo_cb, pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
testbed_master (void *cls,
|
||||||
|
struct GNUNET_TESTBED_RunHandle *h,
|
||||||
|
unsigned int num_peers,
|
||||||
|
struct GNUNET_TESTBED_Peer **p,
|
||||||
|
unsigned int links_succeeded,
|
||||||
|
unsigned int links_failed)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to testbed_master()\n");
|
||||||
|
|
||||||
|
// Create ctx for peers
|
||||||
|
pctx = GNUNET_new_array (PEERS_REQUESTED, struct pctx*);
|
||||||
|
for (int i = 0; i<PEERS_REQUESTED; i++)
|
||||||
|
{
|
||||||
|
pctx[i] = GNUNET_new (struct pctx);
|
||||||
|
pctx[i]->idx = i;
|
||||||
|
pctx[i]->peer = p[i];
|
||||||
|
pctx[i]->id = NULL;
|
||||||
|
pctx[i]->mst = NULL;
|
||||||
|
pctx[i]->op = NULL;
|
||||||
|
pctx[i]->test_ok = GNUNET_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel_key = GNUNET_CRYPTO_eddsa_key_create ();
|
||||||
|
slave_key = GNUNET_CRYPTO_ecdsa_key_create ();
|
||||||
|
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
|
||||||
|
GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);
|
||||||
|
|
||||||
|
pctx[0]->op =
|
||||||
|
GNUNET_TESTBED_service_connect (NULL, p[0], "psyc", service_connect,
|
||||||
|
pctx[0], psyc_ca, psyc_da, pctx[0]);
|
||||||
|
|
||||||
|
GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
|
||||||
|
|
||||||
|
timeout_tid =
|
||||||
|
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5),
|
||||||
|
&timeout_task, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "test\n");
|
||||||
|
|
||||||
|
result = GNUNET_SYSERR;
|
||||||
|
|
||||||
|
ret = GNUNET_TESTBED_test_run ("test-psyc2", "test_psyc.conf",
|
||||||
|
PEERS_REQUESTED, 0LL, NULL, NULL,
|
||||||
|
testbed_master, NULL);
|
||||||
|
|
||||||
|
if ((GNUNET_OK != ret) || (GNUNET_OK != result))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of test-psyc2.c */
|
282
src/psyc/test_psyc_api_join.c
Normal file
282
src/psyc/test_psyc_api_join.c
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file psyc/test_psyc_api_join.c
|
||||||
|
* @brief Testbed test for the PSYC API.
|
||||||
|
* @author xrs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lessons Learned:
|
||||||
|
* - define topology in config
|
||||||
|
* - psyc slave join needs part to end (same with master)
|
||||||
|
* - GNUNET_SCHEDULER_add_delayed return value will outdate at call time
|
||||||
|
* - main can not contain GNUNET_log()
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_crypto_lib.h"
|
||||||
|
#include "gnunet_common.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_testbed_service.h"
|
||||||
|
#include "gnunet_psyc_util_lib.h"
|
||||||
|
#include "gnunet_psyc_service.h"
|
||||||
|
#include "psyc_test_lib.h"
|
||||||
|
|
||||||
|
static struct pctx PEERS[2];
|
||||||
|
|
||||||
|
static int pids;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
shutdown_task (void *cls)
|
||||||
|
{
|
||||||
|
if (NULL != timeout_task_id) {
|
||||||
|
GNUNET_SCHEDULER_cancel (timeout_task_id);
|
||||||
|
timeout_task_id = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0;i<2;i++) {
|
||||||
|
GNUNET_free (PEERS[i].channel_pub_key);
|
||||||
|
|
||||||
|
if (NULL != PEERS[i].psyc)
|
||||||
|
{
|
||||||
|
if (0 == i)
|
||||||
|
GNUNET_PSYC_master_stop (PEERS[i].psyc, GNUNET_NO, NULL, NULL);
|
||||||
|
else
|
||||||
|
GNUNET_PSYC_slave_part (PEERS[i].psyc, GNUNET_NO, NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0;i<MAX_TESTBED_OPS;i++)
|
||||||
|
if (NULL != op[i])
|
||||||
|
GNUNET_TESTBED_operation_done (op[i]);
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shut down!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
timeout_task (void *cls)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Timeout!\n");
|
||||||
|
|
||||||
|
timeout_task_id = NULL;
|
||||||
|
|
||||||
|
result = GNUNET_SYSERR;
|
||||||
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
join_decision_cb (void *cls,
|
||||||
|
const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
|
||||||
|
int is_admitted,
|
||||||
|
const struct GNUNET_PSYC_Message *join_msg)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"slave: got join decision: %s\n",
|
||||||
|
(GNUNET_YES == is_admitted) ? "admitted":"rejected");
|
||||||
|
|
||||||
|
result = (GNUNET_YES == is_admitted) ? GNUNET_OK : GNUNET_SYSERR;
|
||||||
|
|
||||||
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
join_request_cb (void *cls,
|
||||||
|
const struct GNUNET_PSYC_JoinRequestMessage *req,
|
||||||
|
const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
|
||||||
|
const struct GNUNET_PSYC_Message *join_msg,
|
||||||
|
struct GNUNET_PSYC_JoinHandle *jh)
|
||||||
|
{
|
||||||
|
struct GNUNET_HashCode slave_key_hash;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "master: got join request.\n");
|
||||||
|
|
||||||
|
GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
|
||||||
|
|
||||||
|
GNUNET_PSYC_join_decision (jh, GNUNET_YES, 0, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
psyc_da ()
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "disconnect form PSYC service\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
psyc_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
|
||||||
|
{
|
||||||
|
struct pctx *peer = (struct pctx*) cls;
|
||||||
|
|
||||||
|
// Case: master role
|
||||||
|
if (0 == peer->idx) {
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to PSYC as master ...\n");
|
||||||
|
|
||||||
|
peer->psyc = (struct GNUNET_PSYC_Master *)
|
||||||
|
GNUNET_PSYC_master_start (cfg,
|
||||||
|
peer->channel_key,
|
||||||
|
GNUNET_PSYC_CHANNEL_PRIVATE,
|
||||||
|
NULL,
|
||||||
|
join_request_cb,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
cls);
|
||||||
|
return peer->psyc;
|
||||||
|
}
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to PSYC as slave ...\n");
|
||||||
|
|
||||||
|
struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
|
||||||
|
GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo", "bar baz", 7);
|
||||||
|
GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo_bar", "foo bar baz", 11);
|
||||||
|
|
||||||
|
struct GNUNET_PSYC_Message *
|
||||||
|
join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 40);
|
||||||
|
|
||||||
|
peer->psyc = (struct GNUNET_PSYC_Slave *)
|
||||||
|
GNUNET_PSYC_slave_join (cfg,
|
||||||
|
peer->channel_pub_key,
|
||||||
|
peer->id_key,
|
||||||
|
GNUNET_PSYC_SLAVE_JOIN_NONE,
|
||||||
|
peer->peer_id_master,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
join_decision_cb,
|
||||||
|
cls,
|
||||||
|
join_msg);
|
||||||
|
|
||||||
|
GNUNET_free (join_msg);
|
||||||
|
peer->channel = GNUNET_PSYC_slave_get_channel (peer->psyc);
|
||||||
|
GNUNET_PSYC_env_destroy (env);
|
||||||
|
|
||||||
|
return peer->psyc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
service_connect (void *cls,
|
||||||
|
struct GNUNET_TESTBED_Operation *op,
|
||||||
|
void *ca_result,
|
||||||
|
const char *emsg)
|
||||||
|
{
|
||||||
|
GNUNET_assert (NULL != ca_result);
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to the service\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
connect_to_services (void *cls)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
PEERS[i].peer_id_master = PEERS[0].peer_id;
|
||||||
|
|
||||||
|
op[op_cnt++] =
|
||||||
|
GNUNET_TESTBED_service_connect (NULL, PEERS[i].testbed_peer, "psyc",
|
||||||
|
&service_connect, &PEERS[i], &psyc_ca,
|
||||||
|
&psyc_da, &PEERS[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pinfo_cb (void *cls,
|
||||||
|
struct GNUNET_TESTBED_Operation *operation,
|
||||||
|
const struct GNUNET_TESTBED_PeerInformation *pinfo,
|
||||||
|
const char *emsg)
|
||||||
|
{
|
||||||
|
struct pctx *peer = (struct pctx*) cls;
|
||||||
|
|
||||||
|
peer->peer_id = pinfo->result.id;
|
||||||
|
|
||||||
|
pids++;
|
||||||
|
if (pids < 2)
|
||||||
|
return;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting test\n");
|
||||||
|
|
||||||
|
GNUNET_SCHEDULER_add_now (&connect_to_services, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
testbed_master (void *cls,
|
||||||
|
struct GNUNET_TESTBED_RunHandle *h,
|
||||||
|
unsigned int num_peers,
|
||||||
|
struct GNUNET_TESTBED_Peer **p,
|
||||||
|
unsigned int links_succeeded,
|
||||||
|
unsigned int links_failed)
|
||||||
|
{
|
||||||
|
struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key = NULL;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to testbed_master\n");
|
||||||
|
|
||||||
|
// Set up shutdown logic
|
||||||
|
GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
|
||||||
|
timeout_task_id =
|
||||||
|
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 15),
|
||||||
|
&timeout_task, NULL);
|
||||||
|
GNUNET_assert (NULL != timeout_task_id);
|
||||||
|
|
||||||
|
// Set up channel key
|
||||||
|
channel_key = GNUNET_CRYPTO_eddsa_key_create ();
|
||||||
|
GNUNET_assert (NULL != channel_key);
|
||||||
|
|
||||||
|
// Set up information contexts for peers
|
||||||
|
for (int i=0 ; i < 2 ; i++)
|
||||||
|
{
|
||||||
|
PEERS[i].idx = i;
|
||||||
|
PEERS[i].testbed_peer = p[i];
|
||||||
|
|
||||||
|
// Create "egos"
|
||||||
|
PEERS[i].id_key = GNUNET_CRYPTO_ecdsa_key_create ();
|
||||||
|
|
||||||
|
// Set up channel keys shared by master and slave
|
||||||
|
PEERS[i].channel_key = channel_key;
|
||||||
|
|
||||||
|
PEERS[i].channel_pub_key =
|
||||||
|
GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
|
||||||
|
// Get public key
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (PEERS[i].channel_key,
|
||||||
|
PEERS[i].channel_pub_key);
|
||||||
|
// Get peerinfo
|
||||||
|
op[op_cnt++] =
|
||||||
|
GNUNET_TESTBED_peer_get_information (p[i],
|
||||||
|
GNUNET_TESTBED_PIT_IDENTITY,
|
||||||
|
pinfo_cb, &PEERS[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = GNUNET_TESTBED_test_run ("test_psyc_api_join", "test_psyc.conf",
|
||||||
|
2, 0LL, NULL, NULL,
|
||||||
|
&testbed_master, NULL);
|
||||||
|
|
||||||
|
if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of test_psyc_api_join.c */
|
5
src/psycstore/.gitignore
vendored
Normal file
5
src/psycstore/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
gnunet-service-psycstore
|
||||||
|
test_plugin_psycstore_mysql
|
||||||
|
test_plugin_psycstore_sqlite
|
||||||
|
test_plugin_psycstore_postgres
|
||||||
|
test_psycstore
|
155
src/psycstore/Makefile.am
Normal file
155
src/psycstore/Makefile.am
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
# This Makefile.am is in the public domain
|
||||||
|
AM_CPPFLAGS = -I$(top_srcdir)/src/include
|
||||||
|
|
||||||
|
plugindir = $(libdir)/gnunet
|
||||||
|
|
||||||
|
pkgcfgdir= $(pkgdatadir)/config.d/
|
||||||
|
|
||||||
|
libexecdir= $(pkglibdir)/libexec/
|
||||||
|
|
||||||
|
pkgcfg_DATA = \
|
||||||
|
psycstore.conf
|
||||||
|
|
||||||
|
|
||||||
|
if MINGW
|
||||||
|
WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
|
||||||
|
endif
|
||||||
|
|
||||||
|
if USE_COVERAGE
|
||||||
|
AM_CFLAGS = --coverage -O0
|
||||||
|
XLIB = -lgcov
|
||||||
|
endif
|
||||||
|
|
||||||
|
if HAVE_MYSQL
|
||||||
|
MYSQL_PLUGIN = libgnunet_plugin_psycstore_mysql.la
|
||||||
|
if HAVE_TESTING
|
||||||
|
MYSQL_TESTS = test_plugin_psycstore_mysql
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if HAVE_POSTGRESQL
|
||||||
|
POSTGRES_PLUGIN = libgnunet_plugin_psycstore_postgres.la
|
||||||
|
if HAVE_TESTING
|
||||||
|
POSTGRES_TESTS = test_plugin_psycstore_postgres
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if HAVE_SQLITE
|
||||||
|
SQLITE_PLUGIN = libgnunet_plugin_psycstore_sqlite.la
|
||||||
|
if HAVE_TESTING
|
||||||
|
SQLITE_TESTS = test_plugin_psycstore_sqlite
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libgnunetpsycstore.la
|
||||||
|
|
||||||
|
libgnunetpsycstore_la_SOURCES = \
|
||||||
|
psycstore_api.c \
|
||||||
|
psycstore.h
|
||||||
|
libgnunetpsycstore_la_LIBADD = \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la \
|
||||||
|
$(GN_LIBINTL) $(XLIB)
|
||||||
|
libgnunetpsycstore_la_LDFLAGS = \
|
||||||
|
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
|
||||||
|
-version-info 0:0:0
|
||||||
|
|
||||||
|
bin_PROGRAMS =
|
||||||
|
|
||||||
|
libexec_PROGRAMS = \
|
||||||
|
gnunet-service-psycstore
|
||||||
|
|
||||||
|
gnunet_service_psycstore_SOURCES = \
|
||||||
|
gnunet-service-psycstore.c
|
||||||
|
gnunet_service_psycstore_LDADD = \
|
||||||
|
$(top_builddir)/src/statistics/libgnunetstatistics.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la \
|
||||||
|
$(top_builddir)/src/psycutil/libgnunetpsycutil.la \
|
||||||
|
$(GN_LIBINTL)
|
||||||
|
|
||||||
|
plugin_LTLIBRARIES = \
|
||||||
|
$(SQLITE_PLUGIN) \
|
||||||
|
$(MYSQL_PLUGIN) \
|
||||||
|
$(POSTGRES_PLUGIN)
|
||||||
|
|
||||||
|
|
||||||
|
libgnunet_plugin_psycstore_mysql_la_SOURCES = \
|
||||||
|
plugin_psycstore_mysql.c
|
||||||
|
libgnunet_plugin_psycstore_mysql_la_LIBADD = \
|
||||||
|
libgnunetpsycstore.la \
|
||||||
|
$(top_builddir)/src/my/libgnunetmy.la \
|
||||||
|
$(top_builddir)/src/mysql/libgnunetmysql.la \
|
||||||
|
$(top_builddir)/src/statistics/libgnunetstatistics.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
|
||||||
|
$(LTLIBINTL)
|
||||||
|
libgnunet_plugin_psycstore_mysql_la_LDFLAGS = \
|
||||||
|
$(GN_PLUGIN_LDFLAGS)
|
||||||
|
|
||||||
|
libgnunet_plugin_psycstore_postgres_la_SOURCES = \
|
||||||
|
plugin_psycstore_postgres.c
|
||||||
|
libgnunet_plugin_psycstore_postgres_la_LIBADD = \
|
||||||
|
libgnunetpsycstore.la \
|
||||||
|
$(top_builddir)/src/pq/libgnunetpq.la \
|
||||||
|
$(top_builddir)/src/statistics/libgnunetstatistics.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \
|
||||||
|
$(LTLIBINTL)
|
||||||
|
libgnunet_plugin_psycstore_postgres_la_LDFLAGS = \
|
||||||
|
$(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS)
|
||||||
|
libgnunet_plugin_psycstore_postgres_la_CPPFLAGS = \
|
||||||
|
$(POSTGRESQL_CPPFLAGS) $(AM_CPPFLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
libgnunet_plugin_psycstore_sqlite_la_SOURCES = \
|
||||||
|
plugin_psycstore_sqlite.c
|
||||||
|
libgnunet_plugin_psycstore_sqlite_la_LIBADD = \
|
||||||
|
libgnunetpsycstore.la \
|
||||||
|
$(top_builddir)/src/statistics/libgnunetstatistics.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
|
||||||
|
$(LTLIBINTL)
|
||||||
|
libgnunet_plugin_psycstore_sqlite_la_LDFLAGS = \
|
||||||
|
$(GN_PLUGIN_LDFLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
if HAVE_SQLITE
|
||||||
|
if HAVE_TESTING
|
||||||
|
check_PROGRAMS = \
|
||||||
|
$(SQLITE_TESTS) \
|
||||||
|
$(MYSQL_TESTS) \
|
||||||
|
$(POSTGRES_TESTS) \
|
||||||
|
test_psycstore
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_TEST_RUN
|
||||||
|
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
|
||||||
|
TESTS = $(check_PROGRAMS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
test_psycstore_SOURCES = \
|
||||||
|
test_psycstore.c
|
||||||
|
test_psycstore_LDADD = \
|
||||||
|
libgnunetpsycstore.la \
|
||||||
|
$(top_builddir)/src/testing/libgnunettesting.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
test_psycstore.conf
|
||||||
|
|
||||||
|
|
||||||
|
test_plugin_psycstore_sqlite_SOURCES = \
|
||||||
|
test_plugin_psycstore.c
|
||||||
|
test_plugin_psycstore_sqlite_LDADD = \
|
||||||
|
$(top_builddir)/src/testing/libgnunettesting.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la
|
||||||
|
|
||||||
|
test_plugin_psycstore_mysql_SOURCES = \
|
||||||
|
test_plugin_psycstore.c
|
||||||
|
test_plugin_psycstore_mysql_LDADD = \
|
||||||
|
$(top_builddir)/src/testing/libgnunettesting.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la
|
||||||
|
|
||||||
|
test_plugin_psycstore_postgres_SOURCES = \
|
||||||
|
test_plugin_psycstore.c
|
||||||
|
test_plugin_psycstore_postgres_LDADD = \
|
||||||
|
$(top_builddir)/src/testing/libgnunettesting.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la
|
||||||
|
|
1049
src/psycstore/gnunet-service-psycstore.c
Normal file
1049
src/psycstore/gnunet-service-psycstore.c
Normal file
File diff suppressed because it is too large
Load Diff
1960
src/psycstore/plugin_psycstore_mysql.c
Normal file
1960
src/psycstore/plugin_psycstore_mysql.c
Normal file
File diff suppressed because it is too large
Load Diff
1530
src/psycstore/plugin_psycstore_postgres.c
Normal file
1530
src/psycstore/plugin_psycstore_postgres.c
Normal file
File diff suppressed because it is too large
Load Diff
1948
src/psycstore/plugin_psycstore_sqlite.c
Normal file
1948
src/psycstore/plugin_psycstore_sqlite.c
Normal file
File diff suppressed because it is too large
Load Diff
28
src/psycstore/psycstore.conf.in
Normal file
28
src/psycstore/psycstore.conf.in
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[psycstore]
|
||||||
|
START_ON_DEMAND = @START_ON_DEMAND@
|
||||||
|
BINARY = gnunet-service-psycstore
|
||||||
|
|
||||||
|
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-psycstore.sock
|
||||||
|
UNIX_MATCH_UID = YES
|
||||||
|
UNIX_MATCH_GID = YES
|
||||||
|
|
||||||
|
@UNIXONLY@PORT = 2111
|
||||||
|
HOSTNAME = localhost
|
||||||
|
ACCEPT_FROM = 127.0.0.1;
|
||||||
|
ACCEPT_FROM6 = ::1;
|
||||||
|
|
||||||
|
DATABASE = sqlite
|
||||||
|
|
||||||
|
[psycstore-sqlite]
|
||||||
|
FILENAME = $GNUNET_DATA_HOME/psycstore/sqlite.db
|
||||||
|
|
||||||
|
[psycstore-mysql]
|
||||||
|
DATABASE = gnunet
|
||||||
|
CONFIG = ~/.my.cnf
|
||||||
|
# USER = gnunet
|
||||||
|
# PASSWORD =
|
||||||
|
# HOST = localhost
|
||||||
|
# PORT = 3306
|
||||||
|
|
||||||
|
[psycstore-postgres]
|
||||||
|
CONFIG = connect_timeout=10; dbname=gnunet
|
520
src/psycstore/psycstore.h
Normal file
520
src/psycstore/psycstore.h
Normal file
@ -0,0 +1,520 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file psycstore/psycstore.h
|
||||||
|
* @brief Common type definitions for the PSYCstore service and API.
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNUNET_PSYCSTORE_H
|
||||||
|
#define GNUNET_PSYCSTORE_H
|
||||||
|
|
||||||
|
#include "gnunet_common.h"
|
||||||
|
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer from service to client about last operation.
|
||||||
|
*/
|
||||||
|
struct OperationResult
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**lowed by
|
||||||
|
* Status code for the operation.
|
||||||
|
*/
|
||||||
|
uint64_t result_code GNUNET_PACKED;
|
||||||
|
|
||||||
|
/* followed by 0-terminated error message (on error) */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer from service to client about master counters.
|
||||||
|
*
|
||||||
|
* @see GNUNET_PSYCSTORE_counters_get()
|
||||||
|
*/
|
||||||
|
struct CountersResult
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status code for the operation:
|
||||||
|
* #GNUNET_OK: success, counter values are returned.
|
||||||
|
* #GNUNET_NO: no message has been sent to the channel yet.
|
||||||
|
* #GNUNET_SYSERR: an error occurred.
|
||||||
|
*/
|
||||||
|
uint32_t result_code GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t max_fragment_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t max_message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t max_group_generation GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t max_state_message_id GNUNET_PACKED;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer from service to client containing a message fragment.
|
||||||
|
*/
|
||||||
|
struct FragmentResult
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t psycstore_flags GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/* Followed by GNUNET_MULTICAST_MessageHeader */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer from service to client containing a state variable.
|
||||||
|
*/
|
||||||
|
struct StateResult
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint16_t name_size GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint16_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/* Followed by name and value */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic operation request.
|
||||||
|
*/
|
||||||
|
struct OperationRequest
|
||||||
|
{
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GNUNET_PSYCSTORE_membership_store()
|
||||||
|
*/
|
||||||
|
struct MembershipStoreRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slave's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
|
||||||
|
|
||||||
|
uint64_t announced_at GNUNET_PACKED;
|
||||||
|
uint64_t effective_since GNUNET_PACKED;
|
||||||
|
uint64_t group_generation GNUNET_PACKED;
|
||||||
|
uint8_t did_join;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GNUNET_PSYCSTORE_membership_test()
|
||||||
|
*/
|
||||||
|
struct MembershipTestRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slave's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
|
||||||
|
|
||||||
|
uint64_t message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
uint64_t group_generation GNUNET_PACKED;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GNUNET_PSYCSTORE_fragment_store()
|
||||||
|
*/
|
||||||
|
struct FragmentStoreRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_STORE
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum GNUNET_PSYCSTORE_MessageFlags
|
||||||
|
*/
|
||||||
|
uint32_t psycstore_flags GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id;
|
||||||
|
|
||||||
|
/* Followed by fragment */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GNUNET_PSYCSTORE_fragment_get()
|
||||||
|
*/
|
||||||
|
struct FragmentGetRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slave's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First fragment ID to request.
|
||||||
|
*/
|
||||||
|
uint64_t first_fragment_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last fragment ID to request.
|
||||||
|
*/
|
||||||
|
uint64_t last_fragment_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of fragments to retrieve.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_limit GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do membership test with @a slave_key before returning fragment?
|
||||||
|
* #GNUNET_YES or #GNUNET_NO
|
||||||
|
*/
|
||||||
|
uint8_t do_membership_test;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GNUNET_PSYCSTORE_message_get()
|
||||||
|
*/
|
||||||
|
struct MessageGetRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slave's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First message ID to request.
|
||||||
|
*/
|
||||||
|
uint64_t first_message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last message ID to request.
|
||||||
|
*/
|
||||||
|
uint64_t last_message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of messages to retrieve.
|
||||||
|
*/
|
||||||
|
uint64_t message_limit GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of fragments to retrieve.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_limit GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do membership test with @a slave_key before returning fragment?
|
||||||
|
* #GNUNET_YES or #GNUNET_NO
|
||||||
|
*/
|
||||||
|
uint8_t do_membership_test;
|
||||||
|
|
||||||
|
/* Followed by method_prefix */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GNUNET_PSYCSTORE_message_get_fragment()
|
||||||
|
*/
|
||||||
|
struct MessageGetFragmentRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_FRAGMENT_GET
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slave's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requested message ID.
|
||||||
|
*/
|
||||||
|
uint64_t message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requested fragment offset.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_offset GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do membership test with @a slave_key before returning fragment?
|
||||||
|
* #GNUNET_YES or #GNUNET_NO
|
||||||
|
*/
|
||||||
|
uint8_t do_membership_test;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GNUNET_PSYCSTORE_state_hash_update()
|
||||||
|
*/
|
||||||
|
struct StateHashUpdateRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_HASH_UPDATE
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
uint32_t reserved GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
|
||||||
|
struct GNUNET_HashCode hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum StateOpFlags
|
||||||
|
{
|
||||||
|
STATE_OP_FIRST = 1 << 0,
|
||||||
|
STATE_OP_LAST = 1 << 1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GNUNET_PSYCSTORE_state_modify()
|
||||||
|
*/
|
||||||
|
struct StateModifyRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the message to apply the state changes in.
|
||||||
|
*/
|
||||||
|
uint64_t message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State delta of the message with ID @a message_id.
|
||||||
|
*/
|
||||||
|
uint64_t state_delta GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GNUNET_PSYCSTORE_state_sync()
|
||||||
|
*/
|
||||||
|
struct StateSyncRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC
|
||||||
|
*/
|
||||||
|
struct GNUNET_MessageHeader header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of name, including NUL terminator.
|
||||||
|
*/
|
||||||
|
uint16_t name_size GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OR'd StateOpFlags
|
||||||
|
*/
|
||||||
|
uint8_t flags;
|
||||||
|
|
||||||
|
uint8_t reserved;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation ID.
|
||||||
|
*/
|
||||||
|
uint64_t op_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the message that contains the state_hash PSYC header variable.
|
||||||
|
*/
|
||||||
|
uint64_t state_hash_message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the last stateful message before @a state_hash_message_id.
|
||||||
|
*/
|
||||||
|
uint64_t max_state_message_id GNUNET_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EddsaPublicKey channel_key;
|
||||||
|
|
||||||
|
/* Followed by NUL-terminated name, then the value. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_END
|
||||||
|
|
||||||
|
#endif
|
1285
src/psycstore/psycstore_api.c
Normal file
1285
src/psycstore/psycstore_api.c
Normal file
File diff suppressed because it is too large
Load Diff
532
src/psycstore/test_plugin_psycstore.c
Normal file
532
src/psycstore/test_plugin_psycstore.c
Normal file
@ -0,0 +1,532 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* Test for the PSYCstore plugins.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_testing_lib.h"
|
||||||
|
#include "gnunet_psycstore_plugin.h"
|
||||||
|
#include "gnunet_psycstore_service.h"
|
||||||
|
#include "gnunet_multicast_service.h"
|
||||||
|
|
||||||
|
#define DEBUG_PSYCSTORE GNUNET_EXTRA_LOGGING
|
||||||
|
#if DEBUG_PSYCSTORE
|
||||||
|
# define LOG_LEVEL "DEBUG"
|
||||||
|
#else
|
||||||
|
# define LOG_LEVEL "WARNING"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define C2ARG(str) str, (sizeof (str) - 1)
|
||||||
|
|
||||||
|
#define LOG(kind,...) \
|
||||||
|
GNUNET_log_from (kind, "test-plugin-psycstore", __VA_ARGS__)
|
||||||
|
|
||||||
|
static int ok;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of plugin under test.
|
||||||
|
*/
|
||||||
|
static const char *plugin_name;
|
||||||
|
|
||||||
|
static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
|
||||||
|
static struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key;
|
||||||
|
|
||||||
|
static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
|
||||||
|
static struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called when the service shuts down. Unloads our psycstore
|
||||||
|
* plugin.
|
||||||
|
*
|
||||||
|
* @param api api to unload
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
unload_plugin (struct GNUNET_PSYCSTORE_PluginFunctions *api)
|
||||||
|
{
|
||||||
|
char *libname;
|
||||||
|
|
||||||
|
GNUNET_asprintf (&libname, "libgnunet_plugin_psycstore_%s", plugin_name);
|
||||||
|
GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api));
|
||||||
|
GNUNET_free (libname);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the psycstore plugin.
|
||||||
|
*
|
||||||
|
* @param cfg configuration to pass
|
||||||
|
* @return NULL on error
|
||||||
|
*/
|
||||||
|
static struct GNUNET_PSYCSTORE_PluginFunctions *
|
||||||
|
load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYCSTORE_PluginFunctions *ret;
|
||||||
|
char *libname;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Loading `%s' psycstore plugin\n"),
|
||||||
|
plugin_name);
|
||||||
|
GNUNET_asprintf (&libname, "libgnunet_plugin_psycstore_%s", plugin_name);
|
||||||
|
if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void*) cfg)))
|
||||||
|
{
|
||||||
|
FPRINTF (stderr, "Failed to load plugin `%s'!\n", plugin_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
GNUNET_free (libname);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_MSG 16
|
||||||
|
|
||||||
|
struct FragmentClosure
|
||||||
|
{
|
||||||
|
uint8_t n;
|
||||||
|
uint64_t flags[MAX_MSG];
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader *msg[MAX_MSG];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
fragment_cb (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg2,
|
||||||
|
enum GNUNET_PSYCSTORE_MessageFlags flags)
|
||||||
|
{
|
||||||
|
struct FragmentClosure *fcls = cls;
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader *msg1;
|
||||||
|
uint64_t flags1;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (fcls->n >= MAX_MSG)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
msg1 = fcls->msg[fcls->n];
|
||||||
|
flags1 = fcls->flags[fcls->n++];
|
||||||
|
if (NULL == msg1)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags1 == flags && msg1->header.size == msg2->header.size
|
||||||
|
&& 0 == memcmp (msg1, msg2, ntohs (msg1->header.size)))
|
||||||
|
{
|
||||||
|
LOG (GNUNET_ERROR_TYPE_DEBUG, "Fragment %llu matches\n",
|
||||||
|
GNUNET_ntohll (msg1->fragment_id));
|
||||||
|
ret = GNUNET_YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG (GNUNET_ERROR_TYPE_ERROR, "Fragment %llu differs\n",
|
||||||
|
GNUNET_ntohll (msg1->fragment_id));
|
||||||
|
ret = GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
GNUNET_free (msg2);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct StateClosure {
|
||||||
|
size_t n;
|
||||||
|
char *name[16];
|
||||||
|
void *value[16];
|
||||||
|
size_t value_size[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
state_cb (void *cls, const char *name, const void *value, uint32_t value_size)
|
||||||
|
{
|
||||||
|
struct StateClosure *scls = cls;
|
||||||
|
const void *val = scls->value[scls->n]; // FIXME: check for n out-of-bounds FIRST!
|
||||||
|
size_t val_size = scls->value_size[scls->n++];
|
||||||
|
|
||||||
|
/* FIXME: check name */
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
" name = %s, value_size = %u\n",
|
||||||
|
name, value_size);
|
||||||
|
|
||||||
|
return GNUNET_YES;
|
||||||
|
return value_size == val_size && 0 == memcmp (value, val, val_size)
|
||||||
|
? GNUNET_YES
|
||||||
|
: GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
run (void *cls, char *const *args, const char *cfgfile,
|
||||||
|
const struct GNUNET_CONFIGURATION_Handle *cfg)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYCSTORE_PluginFunctions *db;
|
||||||
|
|
||||||
|
ok = 1;
|
||||||
|
db = load_plugin (cfg);
|
||||||
|
if (NULL == db)
|
||||||
|
{
|
||||||
|
FPRINTF (stderr,
|
||||||
|
"%s",
|
||||||
|
"Failed to initialize PSYCstore. "
|
||||||
|
"Database likely not setup, skipping test.\n");
|
||||||
|
ok = 77;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store & test membership */
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "MEMBERSHIP\n");
|
||||||
|
|
||||||
|
channel_key = GNUNET_CRYPTO_eddsa_key_create ();
|
||||||
|
slave_key = GNUNET_CRYPTO_ecdsa_key_create ();
|
||||||
|
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (channel_key,
|
||||||
|
&channel_pub_key);
|
||||||
|
GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "membership_store()\n");
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->membership_store (db->cls, &channel_pub_key,
|
||||||
|
&slave_pub_key, GNUNET_YES,
|
||||||
|
4, 2, 1));
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "membership_test()\n");
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_YES == db->membership_test (db->cls, &channel_pub_key,
|
||||||
|
&slave_pub_key, 4));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_YES == db->membership_test (db->cls, &channel_pub_key,
|
||||||
|
&slave_pub_key, 2));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_NO == db->membership_test (db->cls, &channel_pub_key,
|
||||||
|
&slave_pub_key, 1));
|
||||||
|
|
||||||
|
/* Store & get messages */
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "MESSAGES\n");
|
||||||
|
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader *msg
|
||||||
|
= GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
|
||||||
|
GNUNET_assert (msg != NULL);
|
||||||
|
|
||||||
|
msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
|
||||||
|
msg->header.size = htons (sizeof (*msg) + sizeof (channel_pub_key));
|
||||||
|
|
||||||
|
uint64_t fragment_id = INT64_MAX - 1;
|
||||||
|
msg->fragment_id = GNUNET_htonll (fragment_id);
|
||||||
|
|
||||||
|
uint64_t message_id = INT64_MAX - 10;
|
||||||
|
msg->message_id = GNUNET_htonll (message_id);
|
||||||
|
|
||||||
|
uint64_t group_generation = INT64_MAX - 3;
|
||||||
|
msg->group_generation = GNUNET_htonll (group_generation);
|
||||||
|
|
||||||
|
msg->hop_counter = htonl (9);
|
||||||
|
msg->fragment_offset = GNUNET_htonll (0);
|
||||||
|
msg->flags = htonl (GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT);
|
||||||
|
|
||||||
|
GNUNET_memcpy (&msg[1], &channel_pub_key, sizeof (channel_pub_key));
|
||||||
|
|
||||||
|
msg->purpose.size = htonl (ntohs (msg->header.size)
|
||||||
|
- sizeof (msg->header)
|
||||||
|
- sizeof (msg->hop_counter)
|
||||||
|
- sizeof (msg->signature));
|
||||||
|
msg->purpose.purpose = htonl (234);
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
GNUNET_CRYPTO_eddsa_sign (channel_key, &msg->purpose, &msg->signature));
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "fragment_store()\n");
|
||||||
|
|
||||||
|
struct FragmentClosure fcls = { 0 };
|
||||||
|
fcls.n = 0;
|
||||||
|
fcls.msg[0] = msg;
|
||||||
|
fcls.flags[0] = GNUNET_PSYCSTORE_MESSAGE_STATE;
|
||||||
|
|
||||||
|
GNUNET_assert (
|
||||||
|
GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg,
|
||||||
|
fcls.flags[0]));
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "fragment_get(%" PRIu64 ")\n", fragment_id);
|
||||||
|
|
||||||
|
uint64_t ret_frags = 0;
|
||||||
|
GNUNET_assert (
|
||||||
|
GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key,
|
||||||
|
fragment_id, fragment_id,
|
||||||
|
&ret_frags, fragment_cb, &fcls));
|
||||||
|
GNUNET_assert (fcls.n == 1);
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "message_get_fragment()\n");
|
||||||
|
|
||||||
|
fcls.n = 0;
|
||||||
|
GNUNET_assert (
|
||||||
|
GNUNET_OK == db->message_get_fragment (db->cls, &channel_pub_key,
|
||||||
|
GNUNET_ntohll (msg->message_id),
|
||||||
|
GNUNET_ntohll (msg->fragment_offset),
|
||||||
|
fragment_cb, &fcls));
|
||||||
|
GNUNET_assert (fcls.n == 1);
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "message_add_flags()\n");
|
||||||
|
GNUNET_assert (
|
||||||
|
GNUNET_OK == db->message_add_flags (db->cls, &channel_pub_key,
|
||||||
|
GNUNET_ntohll (msg->message_id),
|
||||||
|
GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED));
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "fragment_get(%" PRIu64 ")\n", fragment_id);
|
||||||
|
|
||||||
|
fcls.n = 0;
|
||||||
|
fcls.flags[0] |= GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED;
|
||||||
|
|
||||||
|
GNUNET_assert (
|
||||||
|
GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key,
|
||||||
|
fragment_id, fragment_id,
|
||||||
|
&ret_frags, fragment_cb, &fcls));
|
||||||
|
|
||||||
|
GNUNET_assert (fcls.n == 1);
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "fragment_store()\n");
|
||||||
|
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader *msg1
|
||||||
|
= GNUNET_malloc (sizeof (*msg1) + sizeof (channel_pub_key));
|
||||||
|
|
||||||
|
GNUNET_memcpy (msg1, msg, sizeof (*msg1) + sizeof (channel_pub_key));
|
||||||
|
|
||||||
|
msg1->fragment_id = GNUNET_htonll (INT64_MAX);
|
||||||
|
msg1->fragment_offset = GNUNET_htonll (32768);
|
||||||
|
|
||||||
|
fcls.n = 0;
|
||||||
|
fcls.msg[1] = msg1;
|
||||||
|
fcls.flags[1] = GNUNET_PSYCSTORE_MESSAGE_STATE_HASH;
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg1,
|
||||||
|
fcls.flags[1]));
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "message_get()\n");
|
||||||
|
|
||||||
|
GNUNET_assert (
|
||||||
|
GNUNET_OK == db->message_get (db->cls, &channel_pub_key,
|
||||||
|
message_id, message_id, 0,
|
||||||
|
&ret_frags, fragment_cb, &fcls));
|
||||||
|
GNUNET_assert (fcls.n == 2 && ret_frags == 2);
|
||||||
|
|
||||||
|
/* Message counters */
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "counters_message_get()\n");
|
||||||
|
|
||||||
|
fragment_id = 0;
|
||||||
|
message_id = 0;
|
||||||
|
group_generation = 0;
|
||||||
|
GNUNET_assert (
|
||||||
|
GNUNET_OK == db->counters_message_get (db->cls, &channel_pub_key,
|
||||||
|
&fragment_id, &message_id,
|
||||||
|
&group_generation)
|
||||||
|
&& fragment_id == GNUNET_ntohll (msg1->fragment_id)
|
||||||
|
&& message_id == GNUNET_ntohll (msg1->message_id)
|
||||||
|
&& group_generation == GNUNET_ntohll (msg1->group_generation));
|
||||||
|
|
||||||
|
/* Modify state */
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "STATE\n");
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "state_modify_*()\n");
|
||||||
|
|
||||||
|
message_id = GNUNET_ntohll (fcls.msg[0]->message_id) + 1;
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_modify_begin (db->cls, &channel_pub_key,
|
||||||
|
message_id, 0));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_modify_op (db->cls, &channel_pub_key,
|
||||||
|
GNUNET_PSYC_OP_ASSIGN,
|
||||||
|
"_foo",
|
||||||
|
C2ARG("one two three")));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_modify_op (db->cls, &channel_pub_key,
|
||||||
|
GNUNET_PSYC_OP_ASSIGN,
|
||||||
|
"_foo_bar", slave_key,
|
||||||
|
sizeof (*slave_key)));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_modify_end (db->cls, &channel_pub_key,
|
||||||
|
message_id));
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "state_get()\n");
|
||||||
|
|
||||||
|
struct StateClosure scls = { 0 };
|
||||||
|
scls.n = 0;
|
||||||
|
scls.value[0] = "one two three";
|
||||||
|
scls.value_size[0] = strlen ("one two three");
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_get (db->cls, &channel_pub_key, "_foo",
|
||||||
|
state_cb, &scls));
|
||||||
|
GNUNET_assert (scls.n == 1);
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "state_get_prefix()\n");
|
||||||
|
|
||||||
|
scls.n = 0;
|
||||||
|
scls.value[1] = slave_key;
|
||||||
|
scls.value_size[1] = sizeof (*slave_key);
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_get_prefix (db->cls, &channel_pub_key,
|
||||||
|
"_foo", state_cb, &scls));
|
||||||
|
GNUNET_assert (scls.n == 2);
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "state_get_signed()\n");
|
||||||
|
|
||||||
|
scls.n = 0;
|
||||||
|
GNUNET_assert (GNUNET_NO == db->state_get_signed (db->cls, &channel_pub_key,
|
||||||
|
state_cb, &scls));
|
||||||
|
GNUNET_assert (scls.n == 0);
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "state_update_signed()\n");
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_update_signed (db->cls,
|
||||||
|
&channel_pub_key));
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "state_get_signed()\n");
|
||||||
|
|
||||||
|
scls.n = 0;
|
||||||
|
GNUNET_assert (GNUNET_YES == db->state_get_signed (db->cls, &channel_pub_key,
|
||||||
|
state_cb, &scls));
|
||||||
|
GNUNET_assert (scls.n == 2);
|
||||||
|
|
||||||
|
/* State counters */
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "counters_state_get()\n");
|
||||||
|
|
||||||
|
uint64_t max_state_msg_id = 0;
|
||||||
|
GNUNET_assert (GNUNET_OK == db->counters_state_get (db->cls, &channel_pub_key,
|
||||||
|
&max_state_msg_id)
|
||||||
|
&& max_state_msg_id == message_id);
|
||||||
|
|
||||||
|
/* State sync */
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "state_sync_*()\n");
|
||||||
|
|
||||||
|
scls.n = 0;
|
||||||
|
scls.value[0] = channel_key;
|
||||||
|
scls.value_size[0] = sizeof (*channel_key);
|
||||||
|
scls.value[1] = "three two one";
|
||||||
|
scls.value_size[1] = strlen ("three two one");
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_sync_begin (db->cls, &channel_pub_key));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_sync_assign (db->cls, &channel_pub_key,
|
||||||
|
"_sync_bar", scls.value[0],
|
||||||
|
scls.value_size[0]));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_sync_assign (db->cls, &channel_pub_key,
|
||||||
|
"_sync_foo", scls.value[1],
|
||||||
|
scls.value_size[1]));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_sync_end (db->cls, &channel_pub_key,
|
||||||
|
max_state_msg_id,
|
||||||
|
INT64_MAX - 5));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_NO == db->state_get_prefix (db->cls, &channel_pub_key,
|
||||||
|
"_foo", state_cb, &scls));
|
||||||
|
GNUNET_assert (scls.n == 0);
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_get_prefix (db->cls, &channel_pub_key,
|
||||||
|
"_sync", state_cb, &scls));
|
||||||
|
GNUNET_assert (scls.n == 2);
|
||||||
|
|
||||||
|
scls.n = 0;
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_get_signed (db->cls, &channel_pub_key,
|
||||||
|
state_cb, &scls));
|
||||||
|
GNUNET_assert (scls.n == 2);
|
||||||
|
|
||||||
|
/* Modify state after sync */
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "state_modify_*()\n");
|
||||||
|
|
||||||
|
message_id = GNUNET_ntohll (fcls.msg[0]->message_id) + 6;
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_modify_begin (db->cls, &channel_pub_key,
|
||||||
|
message_id,
|
||||||
|
message_id - max_state_msg_id));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_modify_op (db->cls, &channel_pub_key,
|
||||||
|
GNUNET_PSYC_OP_ASSIGN,
|
||||||
|
"_sync_foo",
|
||||||
|
C2ARG("five six seven")));
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_modify_end (db->cls, &channel_pub_key,
|
||||||
|
message_id));
|
||||||
|
|
||||||
|
/* Reset state */
|
||||||
|
|
||||||
|
LOG (GNUNET_ERROR_TYPE_INFO, "state_reset()\n");
|
||||||
|
|
||||||
|
scls.n = 0;
|
||||||
|
GNUNET_assert (GNUNET_OK == db->state_reset (db->cls, &channel_pub_key));
|
||||||
|
GNUNET_assert (scls.n == 0);
|
||||||
|
|
||||||
|
ok = 0;
|
||||||
|
|
||||||
|
if (NULL != channel_key)
|
||||||
|
{
|
||||||
|
GNUNET_free (channel_key);
|
||||||
|
channel_key = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != slave_key)
|
||||||
|
{
|
||||||
|
GNUNET_free (slave_key);
|
||||||
|
slave_key = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unload_plugin (db);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char cfg_name[128];
|
||||||
|
char *const xargv[] = {
|
||||||
|
"test-plugin-psycstore",
|
||||||
|
"-c", cfg_name,
|
||||||
|
"-L", LOG_LEVEL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
struct GNUNET_GETOPT_CommandLineOption options[] = {
|
||||||
|
GNUNET_GETOPT_OPTION_END
|
||||||
|
};
|
||||||
|
GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-psycstore-sqlite");
|
||||||
|
GNUNET_log_setup ("test-plugin-psycstore", LOG_LEVEL, NULL);
|
||||||
|
plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
|
||||||
|
GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_plugin_psycstore_%s.conf",
|
||||||
|
plugin_name);
|
||||||
|
GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv,
|
||||||
|
"test-plugin-psycstore", "nohelp", options, &run, NULL);
|
||||||
|
|
||||||
|
if ( (0 != ok) &&
|
||||||
|
(77 != ok) )
|
||||||
|
FPRINTF (stderr, "Missed some testcases: %d\n", ok);
|
||||||
|
|
||||||
|
#if ! DEBUG_PSYCSTORE
|
||||||
|
GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-psycstore-sqlite");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of test_plugin_psycstore.c */
|
7
src/psycstore/test_plugin_psycstore_mysql.conf
Normal file
7
src/psycstore/test_plugin_psycstore_mysql.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[psycstore-mysql]
|
||||||
|
DATABASE = test
|
||||||
|
# CONFIG = ~/.my.cnf
|
||||||
|
# USER = gnunet
|
||||||
|
# PASSWORD =
|
||||||
|
# HOST = localhost
|
||||||
|
# PORT = 3306
|
2
src/psycstore/test_plugin_psycstore_postgres.conf
Normal file
2
src/psycstore/test_plugin_psycstore_postgres.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[psycstore-postgres]
|
||||||
|
CONFIG = connect_timeout=10; dbname=template1
|
2
src/psycstore/test_plugin_psycstore_sqlite.conf
Normal file
2
src/psycstore/test_plugin_psycstore_sqlite.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[psycstore-sqlite]
|
||||||
|
FILENAME = $GNUNET_TMP/gnunet-test-plugin-psycstore-sqlite/sqlite.db
|
586
src/psycstore/test_psycstore.c
Normal file
586
src/psycstore/test_psycstore.c
Normal file
@ -0,0 +1,586 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file psycstore/test_psycstore.c
|
||||||
|
* @brief Test for the PSYCstore service.
|
||||||
|
* @author Gabor X Toth
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_common.h"
|
||||||
|
#include "gnunet_testing_lib.h"
|
||||||
|
#include "gnunet_psycstore_service.h"
|
||||||
|
|
||||||
|
#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value from 'main'.
|
||||||
|
*/
|
||||||
|
static int res;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle to PSYCstore service.
|
||||||
|
*/
|
||||||
|
static struct GNUNET_PSYCSTORE_Handle *h;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle to PSYCstore operation.
|
||||||
|
*/
|
||||||
|
static struct GNUNET_PSYCSTORE_OperationHandle *op;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for task for timeout termination.
|
||||||
|
*/
|
||||||
|
static struct GNUNET_SCHEDULER_Task *end_badly_task;
|
||||||
|
|
||||||
|
static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
|
||||||
|
static struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key;
|
||||||
|
|
||||||
|
static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
|
||||||
|
static struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;
|
||||||
|
|
||||||
|
static struct FragmentClosure
|
||||||
|
{
|
||||||
|
uint8_t n;
|
||||||
|
uint8_t n_expected;
|
||||||
|
uint64_t flags[16];
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader *msg[16];
|
||||||
|
} fcls;
|
||||||
|
|
||||||
|
struct StateClosure {
|
||||||
|
size_t n;
|
||||||
|
char *name[16];
|
||||||
|
void *value[16];
|
||||||
|
size_t value_size[16];
|
||||||
|
} scls;
|
||||||
|
|
||||||
|
static struct GNUNET_PSYC_Modifier modifiers[16];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up all resources used.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cleanup ()
|
||||||
|
{
|
||||||
|
if (NULL != op)
|
||||||
|
{
|
||||||
|
GNUNET_PSYCSTORE_operation_cancel (op);
|
||||||
|
op = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != h)
|
||||||
|
{
|
||||||
|
GNUNET_PSYCSTORE_disconnect (h);
|
||||||
|
h = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != channel_key)
|
||||||
|
{
|
||||||
|
GNUNET_free (channel_key);
|
||||||
|
channel_key = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != slave_key)
|
||||||
|
{
|
||||||
|
GNUNET_free (slave_key);
|
||||||
|
slave_key = NULL;
|
||||||
|
}
|
||||||
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminate the testcase (failure).
|
||||||
|
*
|
||||||
|
* @param cls NULL
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
end_badly (void *cls)
|
||||||
|
{
|
||||||
|
res = 1;
|
||||||
|
cleanup ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminate the testcase (success).
|
||||||
|
*
|
||||||
|
* @param cls NULL
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
end_normally (void *cls)
|
||||||
|
{
|
||||||
|
res = 0;
|
||||||
|
cleanup ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish the testcase (successfully).
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
end ()
|
||||||
|
{
|
||||||
|
if (NULL != end_badly_task)
|
||||||
|
{
|
||||||
|
GNUNET_SCHEDULER_cancel (end_badly_task);
|
||||||
|
end_badly_task = NULL;
|
||||||
|
}
|
||||||
|
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
|
||||||
|
&end_normally, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
state_reset_result (void *cls,
|
||||||
|
int64_t result,
|
||||||
|
const char *err_msg,
|
||||||
|
uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"state_reset_result:\t%d\n",
|
||||||
|
(int) result);
|
||||||
|
GNUNET_assert (GNUNET_OK == result);
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_state_reset (h, &channel_pub_key,
|
||||||
|
&state_reset_result, cls);
|
||||||
|
GNUNET_PSYCSTORE_operation_cancel (op);
|
||||||
|
op = NULL;
|
||||||
|
end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
state_result (void *cls,
|
||||||
|
const char *name,
|
||||||
|
const void *value,
|
||||||
|
uint32_t value_size)
|
||||||
|
{
|
||||||
|
struct StateClosure *scls = cls;
|
||||||
|
const char *nam = scls->name[scls->n];
|
||||||
|
const void *val = scls->value[scls->n];
|
||||||
|
size_t val_size = scls->value_size[scls->n++];
|
||||||
|
|
||||||
|
if (value_size == val_size
|
||||||
|
&& 0 == memcmp (value, val, val_size)
|
||||||
|
&& 0 == strcmp (name, nam))
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
" variable %s matches\n",
|
||||||
|
name);
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
" variable %s differs\nReceived: %.*s\nExpected: %.*s\n",
|
||||||
|
name, (int) value_size, (char*) value, (int) val_size, (char*) val);
|
||||||
|
GNUNET_assert (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
state_get_prefix_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
struct StateClosure *scls = cls;
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_prefix_result:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (GNUNET_OK == result && 2 == scls->n);
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_state_reset (h, &channel_pub_key,
|
||||||
|
&state_reset_result, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
state_get_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_result:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (GNUNET_OK == result);
|
||||||
|
|
||||||
|
scls.n = 0;
|
||||||
|
|
||||||
|
scls.name[0] = "_sync_bar";
|
||||||
|
scls.value[0] = "ten eleven twelve";
|
||||||
|
scls.value_size[0] = sizeof ("ten eleven twelve") - 1;
|
||||||
|
|
||||||
|
scls.name[1] = "_sync_foo";
|
||||||
|
scls.value[1] = "three two one";
|
||||||
|
scls.value_size[1] = sizeof ("three two one") - 1;
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_state_get_prefix (h, &channel_pub_key, "_sync",
|
||||||
|
&state_result,
|
||||||
|
&state_get_prefix_result, &scls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
counters_result (void *cls, int status, uint64_t max_fragment_id,
|
||||||
|
uint64_t max_message_id, uint64_t max_group_generation,
|
||||||
|
uint64_t max_state_message_id)
|
||||||
|
{
|
||||||
|
struct FragmentClosure *fcls = cls;
|
||||||
|
int result = 0;
|
||||||
|
op = NULL;
|
||||||
|
|
||||||
|
if (GNUNET_OK == status
|
||||||
|
&& max_fragment_id == GNUNET_ntohll (fcls->msg[2]->fragment_id)
|
||||||
|
&& max_message_id == GNUNET_ntohll (fcls->msg[2]->message_id)
|
||||||
|
&& max_group_generation == GNUNET_ntohll (fcls->msg[2]->group_generation)
|
||||||
|
&& max_state_message_id == GNUNET_ntohll (fcls->msg[0]->message_id))
|
||||||
|
result = 1;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "counters_get:\t%d\n", result);
|
||||||
|
GNUNET_assert (result == 1);
|
||||||
|
|
||||||
|
scls.n = 0;
|
||||||
|
scls.name[0] = "_sync_bar";
|
||||||
|
scls.value[0] = "ten eleven twelve";
|
||||||
|
scls.value_size[0] = sizeof ("ten eleven twelve") - 1;
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_state_get (h, &channel_pub_key, "_sync_bar_x_yy_zzz",
|
||||||
|
&state_result, &state_get_result, &scls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
state_modify_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_modify_result:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (GNUNET_OK == result);
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_counters_get (h, &channel_pub_key,
|
||||||
|
&counters_result, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
state_sync_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
struct FragmentClosure *fcls = cls;
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_sync_result:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (GNUNET_OK == result);
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_state_modify (h, &channel_pub_key,
|
||||||
|
GNUNET_ntohll (fcls->msg[0]->message_id),
|
||||||
|
0, state_modify_result, fcls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
fragment_result (void *cls,
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader *msg,
|
||||||
|
enum GNUNET_PSYCSTORE_MessageFlags flags)
|
||||||
|
{
|
||||||
|
struct FragmentClosure *fcls = cls;
|
||||||
|
GNUNET_assert (fcls->n < fcls->n_expected);
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader *msg0 = fcls->msg[fcls->n];
|
||||||
|
uint64_t flags0 = fcls->flags[fcls->n++];
|
||||||
|
|
||||||
|
if (flags == flags0 && msg->header.size == msg0->header.size
|
||||||
|
&& 0 == memcmp (msg, msg0, ntohs (msg->header.size)))
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " fragment %" PRIu64 " matches\n",
|
||||||
|
GNUNET_ntohll (msg->fragment_id));
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
" fragment differs: expected %" PRIu64 ", got %" PRIu64 "\n",
|
||||||
|
GNUNET_ntohll (msg0->fragment_id),
|
||||||
|
GNUNET_ntohll (msg->fragment_id));
|
||||||
|
GNUNET_assert (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
message_get_latest_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
struct FragmentClosure *fcls = cls;
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_latest:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
|
||||||
|
|
||||||
|
modifiers[0] = (struct GNUNET_PSYC_Modifier) {
|
||||||
|
.oper = '=',
|
||||||
|
.name = "_sync_foo",
|
||||||
|
.value = "three two one",
|
||||||
|
.value_size = sizeof ("three two one") - 1
|
||||||
|
};
|
||||||
|
modifiers[1] = (struct GNUNET_PSYC_Modifier) {
|
||||||
|
.oper = '=',
|
||||||
|
.name = "_sync_bar",
|
||||||
|
.value = "ten eleven twelve",
|
||||||
|
.value_size = sizeof ("ten eleven twelve") - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_state_sync (h, &channel_pub_key,
|
||||||
|
GNUNET_ntohll (fcls->msg[0]->message_id) + 1,
|
||||||
|
GNUNET_ntohll (fcls->msg[0]->message_id) + 2,
|
||||||
|
2, modifiers, state_sync_result, fcls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
message_get_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
struct FragmentClosure *fcls = cls;
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
|
||||||
|
|
||||||
|
fcls->n = 0;
|
||||||
|
fcls->n_expected = 3;
|
||||||
|
op = GNUNET_PSYCSTORE_message_get_latest (h, &channel_pub_key, &slave_pub_key,
|
||||||
|
1, "", &fragment_result,
|
||||||
|
&message_get_latest_result, fcls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
message_get_fragment_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
struct FragmentClosure *fcls = cls;
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_fragment:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
|
||||||
|
|
||||||
|
fcls->n = 0;
|
||||||
|
fcls->n_expected = 3;
|
||||||
|
uint64_t message_id = GNUNET_ntohll (fcls->msg[0]->message_id);
|
||||||
|
op = GNUNET_PSYCSTORE_message_get (h, &channel_pub_key, &slave_pub_key,
|
||||||
|
message_id, message_id, 0, "",
|
||||||
|
&fragment_result,
|
||||||
|
&message_get_result, fcls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
fragment_get_latest_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
struct FragmentClosure *fcls = cls;
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_get_latest:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
|
||||||
|
|
||||||
|
fcls->n = 1;
|
||||||
|
fcls->n_expected = 2;
|
||||||
|
op = GNUNET_PSYCSTORE_message_get_fragment (h, &channel_pub_key, &slave_pub_key,
|
||||||
|
GNUNET_ntohll (fcls->msg[1]->message_id),
|
||||||
|
GNUNET_ntohll (fcls->msg[1]->fragment_offset),
|
||||||
|
&fragment_result,
|
||||||
|
&message_get_fragment_result, fcls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
fragment_get_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
struct FragmentClosure *fcls = cls;
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"fragment_get:\t%d\n",
|
||||||
|
(int) result);
|
||||||
|
GNUNET_assert (0 < result && fcls->n == fcls->n_expected);
|
||||||
|
|
||||||
|
fcls->n = 0;
|
||||||
|
fcls->n_expected = 3;
|
||||||
|
op = GNUNET_PSYCSTORE_fragment_get_latest (h, &channel_pub_key,
|
||||||
|
&slave_pub_key, fcls->n_expected,
|
||||||
|
&fragment_result,
|
||||||
|
&fragment_get_latest_result, fcls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
fragment_store_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_store:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (GNUNET_OK == result);
|
||||||
|
|
||||||
|
if ((intptr_t) cls == GNUNET_YES)
|
||||||
|
{ /* last fragment */
|
||||||
|
fcls.n = 0;
|
||||||
|
fcls.n_expected = 1;
|
||||||
|
uint64_t fragment_id = GNUNET_ntohll (fcls.msg[0]->fragment_id);
|
||||||
|
op = GNUNET_PSYCSTORE_fragment_get (h, &channel_pub_key, &slave_pub_key,
|
||||||
|
fragment_id, fragment_id,
|
||||||
|
&fragment_result,
|
||||||
|
&fragment_get_result, &fcls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
fragment_store ()
|
||||||
|
{
|
||||||
|
struct GNUNET_MULTICAST_MessageHeader *msg;
|
||||||
|
fcls.flags[0] = GNUNET_PSYCSTORE_MESSAGE_STATE;
|
||||||
|
fcls.msg[0] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
|
||||||
|
GNUNET_assert (msg != NULL);
|
||||||
|
|
||||||
|
msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
|
||||||
|
msg->header.size = htons (sizeof (*msg) + sizeof (channel_pub_key));
|
||||||
|
|
||||||
|
msg->hop_counter = htonl (9);
|
||||||
|
msg->fragment_id = GNUNET_htonll (INT64_MAX - 8);
|
||||||
|
msg->fragment_offset = GNUNET_htonll (0);
|
||||||
|
msg->message_id = GNUNET_htonll (INT64_MAX - 10);
|
||||||
|
msg->group_generation = GNUNET_htonll (INT64_MAX - 3);
|
||||||
|
msg->flags = htonl (GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT);
|
||||||
|
|
||||||
|
GNUNET_memcpy (&msg[1], &channel_pub_key, sizeof (channel_pub_key));
|
||||||
|
|
||||||
|
msg->purpose.size = htonl (ntohs (msg->header.size)
|
||||||
|
- sizeof (msg->header)
|
||||||
|
- sizeof (msg->hop_counter)
|
||||||
|
- sizeof (msg->signature));
|
||||||
|
msg->purpose.purpose = htonl (234);
|
||||||
|
GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (channel_key, &msg->purpose,
|
||||||
|
&msg->signature));
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[0],
|
||||||
|
&fragment_store_result, GNUNET_NO);
|
||||||
|
|
||||||
|
fcls.flags[1] = GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED;
|
||||||
|
fcls.msg[1] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
|
||||||
|
GNUNET_memcpy (msg, fcls.msg[0], sizeof (*msg) + sizeof (channel_pub_key));
|
||||||
|
msg->fragment_id = GNUNET_htonll (INT64_MAX - 4);
|
||||||
|
msg->fragment_offset = GNUNET_htonll (1024);
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[1],
|
||||||
|
&fragment_store_result, GNUNET_NO);
|
||||||
|
|
||||||
|
fcls.flags[2] = GNUNET_PSYCSTORE_MESSAGE_STATE_HASH;
|
||||||
|
fcls.msg[2] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key));
|
||||||
|
GNUNET_memcpy (msg, fcls.msg[1], sizeof (*msg) + sizeof (channel_pub_key));
|
||||||
|
msg->fragment_id = GNUNET_htonll (INT64_MAX);
|
||||||
|
msg->fragment_offset = GNUNET_htonll (16384);
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[2],
|
||||||
|
&fragment_store_result, (void *) GNUNET_YES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
membership_test_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_test:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (GNUNET_OK == result);
|
||||||
|
|
||||||
|
fragment_store ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
membership_store_result (void *cls, int64_t result,
|
||||||
|
const char *err_msg, uint16_t err_msg_size)
|
||||||
|
{
|
||||||
|
op = NULL;
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_store:\t%ld\n", (long int) result);
|
||||||
|
GNUNET_assert (GNUNET_OK == result);
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_membership_test (h, &channel_pub_key, &slave_pub_key,
|
||||||
|
INT64_MAX - 10, 2,
|
||||||
|
&membership_test_result, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main function of the test, run from scheduler.
|
||||||
|
*
|
||||||
|
* @param cls NULL
|
||||||
|
* @param cfg configuration we use (also to connect to PSYCstore service)
|
||||||
|
* @param peer handle to access more of the peer (not used)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
#if DEBUG_TEST_PSYCSTORE
|
||||||
|
run (void *cls, char *const *args, const char *cfgfile,
|
||||||
|
const struct GNUNET_CONFIGURATION_Handle *cfg)
|
||||||
|
#else
|
||||||
|
run (void *cls,
|
||||||
|
const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||||
|
struct GNUNET_TESTING_Peer *peer)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
|
||||||
|
|
||||||
|
h = GNUNET_PSYCSTORE_connect (cfg);
|
||||||
|
GNUNET_assert (NULL != h);
|
||||||
|
|
||||||
|
channel_key = GNUNET_CRYPTO_eddsa_key_create ();
|
||||||
|
slave_key = GNUNET_CRYPTO_ecdsa_key_create ();
|
||||||
|
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
|
||||||
|
GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);
|
||||||
|
|
||||||
|
op = GNUNET_PSYCSTORE_membership_store (h, &channel_pub_key, &slave_pub_key,
|
||||||
|
GNUNET_YES, INT64_MAX - 5,
|
||||||
|
INT64_MAX - 10, 2,
|
||||||
|
&membership_store_result, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
res = 1;
|
||||||
|
#if DEBUG_TEST_PSYCSTORE
|
||||||
|
const struct GNUNET_GETOPT_CommandLineOption opts[] = {
|
||||||
|
GNUNET_GETOPT_OPTION_END
|
||||||
|
};
|
||||||
|
if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-psycstore",
|
||||||
|
"test-psycstore [options]",
|
||||||
|
opts, &run, NULL))
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
if (0 != GNUNET_TESTING_service_run ("test-psycstore", "psycstore",
|
||||||
|
"test_psycstore.conf", &run, NULL))
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of test_psycstore.c */
|
8
src/psycstore/test_psycstore.conf
Normal file
8
src/psycstore/test_psycstore.conf
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[PATHS]
|
||||||
|
GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-psycstore/
|
||||||
|
|
||||||
|
[psycstore]
|
||||||
|
DATABASE = sqlite
|
||||||
|
|
||||||
|
[psycstore-sqlite]
|
||||||
|
FILENAME = $GNUNET_TEST_HOME/psycstore/sqlite.db
|
1
src/psycutil/.gitignore
vendored
Normal file
1
src/psycutil/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
test_psyc_env
|
45
src/psycutil/Makefile.am
Normal file
45
src/psycutil/Makefile.am
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# This Makefile.am is in the public domain
|
||||||
|
AM_CPPFLAGS = -I$(top_srcdir)/src/include
|
||||||
|
|
||||||
|
pkgcfgdir= $(pkgdatadir)/config.d/
|
||||||
|
|
||||||
|
libexecdir= $(pkglibdir)/libexec/
|
||||||
|
|
||||||
|
if MINGW
|
||||||
|
WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
|
||||||
|
endif
|
||||||
|
|
||||||
|
if USE_COVERAGE
|
||||||
|
AM_CFLAGS = --coverage -O0
|
||||||
|
XLIB = -lgcov
|
||||||
|
endif
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libgnunetpsycutil.la
|
||||||
|
|
||||||
|
libgnunetpsycutil_la_SOURCES = \
|
||||||
|
psyc_env.c \
|
||||||
|
psyc_message.c \
|
||||||
|
psyc_slicer.c
|
||||||
|
libgnunetpsycutil_la_LIBADD = \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la \
|
||||||
|
$(GN_LIBINTL) $(XLIB)
|
||||||
|
libgnunetpsycutil_la_LDFLAGS = \
|
||||||
|
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
|
||||||
|
-version-info 0:0:0
|
||||||
|
|
||||||
|
if HAVE_TESTING
|
||||||
|
check_PROGRAMS = \
|
||||||
|
test_psyc_env
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ENABLE_TEST_RUN
|
||||||
|
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
|
||||||
|
TESTS = $(check_PROGRAMS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
test_psyc_env_SOURCES = \
|
||||||
|
test_psyc_env.c
|
||||||
|
test_psyc_env_LDADD = \
|
||||||
|
libgnunetpsycutil.la \
|
||||||
|
$(top_builddir)/src/testing/libgnunettesting.la \
|
||||||
|
$(top_builddir)/src/util/libgnunetutil.la
|
196
src/psycutil/psyc_env.c
Normal file
196
src/psycutil/psyc_env.c
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet.
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* Library providing operations for the @e environment of
|
||||||
|
* PSYC and Social messages.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_psyc_env.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Environment for a message.
|
||||||
|
*
|
||||||
|
* Contains modifiers.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Environment
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Modifier *mod_head;
|
||||||
|
struct GNUNET_PSYC_Modifier *mod_tail;
|
||||||
|
size_t mod_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an environment.
|
||||||
|
*
|
||||||
|
* @return A newly allocated environment.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Environment *
|
||||||
|
GNUNET_PSYC_env_create ()
|
||||||
|
{
|
||||||
|
return GNUNET_new (struct GNUNET_PSYC_Environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a modifier to the environment.
|
||||||
|
*
|
||||||
|
* @param env The environment.
|
||||||
|
* @param oper Operation to perform.
|
||||||
|
* @param name Name of the variable.
|
||||||
|
* @param value Value of the variable.
|
||||||
|
* @param value_size Size of @a value.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_env_add (struct GNUNET_PSYC_Environment *env,
|
||||||
|
enum GNUNET_PSYC_Operator oper, const char *name,
|
||||||
|
const void *value, size_t value_size)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Modifier *mod = GNUNET_new (struct GNUNET_PSYC_Modifier);
|
||||||
|
mod->oper = oper;
|
||||||
|
mod->name = name;
|
||||||
|
mod->value = value;
|
||||||
|
mod->value_size = value_size;
|
||||||
|
GNUNET_CONTAINER_DLL_insert_tail (env->mod_head, env->mod_tail, mod);
|
||||||
|
env->mod_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the first modifier of the environment.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Modifier *
|
||||||
|
GNUNET_PSYC_env_head (const struct GNUNET_PSYC_Environment *env)
|
||||||
|
{
|
||||||
|
return env->mod_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last modifier of the environment.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Modifier *
|
||||||
|
GNUNET_PSYC_env_tail (const struct GNUNET_PSYC_Environment *env)
|
||||||
|
{
|
||||||
|
return env->mod_tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a modifier from the environment.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_env_remove (struct GNUNET_PSYC_Environment *env,
|
||||||
|
struct GNUNET_PSYC_Modifier *mod)
|
||||||
|
{
|
||||||
|
GNUNET_CONTAINER_DLL_remove (env->mod_head, env->mod_tail, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the modifier at the beginning of an environment and remove it.
|
||||||
|
*
|
||||||
|
* @param env
|
||||||
|
* @param oper
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
* @param value_size
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_env_shift (struct GNUNET_PSYC_Environment *env,
|
||||||
|
enum GNUNET_PSYC_Operator *oper, const char **name,
|
||||||
|
const void **value, size_t *value_size)
|
||||||
|
{
|
||||||
|
if (NULL == env->mod_head)
|
||||||
|
return GNUNET_NO;
|
||||||
|
|
||||||
|
struct GNUNET_PSYC_Modifier *mod = env->mod_head;
|
||||||
|
*oper = mod->oper;
|
||||||
|
*name = mod->name;
|
||||||
|
*value = mod->value;
|
||||||
|
*value_size = mod->value_size;
|
||||||
|
|
||||||
|
GNUNET_CONTAINER_DLL_remove (env->mod_head, env->mod_tail, mod);
|
||||||
|
GNUNET_free (mod);
|
||||||
|
env->mod_count--;
|
||||||
|
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate through all modifiers in the environment.
|
||||||
|
*
|
||||||
|
* @param env The environment.
|
||||||
|
* @param it Iterator.
|
||||||
|
* @param it_cls Closure for iterator.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_env_iterate (const struct GNUNET_PSYC_Environment *env,
|
||||||
|
GNUNET_PSYC_Iterator it, void *it_cls)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Modifier *mod;
|
||||||
|
for (mod = env->mod_head; NULL != mod; mod = mod->next)
|
||||||
|
it (it_cls, mod->oper, mod->name, mod->value, mod->value_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of modifiers in the environment.
|
||||||
|
*
|
||||||
|
* @param env The environment.
|
||||||
|
*
|
||||||
|
* @return Number of modifiers.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
GNUNET_PSYC_env_get_count (const struct GNUNET_PSYC_Environment *env)
|
||||||
|
{
|
||||||
|
return env->mod_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy an environment.
|
||||||
|
*
|
||||||
|
* @param env The environment to destroy.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_env_destroy (struct GNUNET_PSYC_Environment *env)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Modifier *mod, *prev = NULL;
|
||||||
|
for (mod = env->mod_head; NULL != mod; mod = mod->next)
|
||||||
|
{
|
||||||
|
if (NULL != prev)
|
||||||
|
GNUNET_free (prev);
|
||||||
|
prev = mod;
|
||||||
|
}
|
||||||
|
if (NULL != prev)
|
||||||
|
GNUNET_free (prev);
|
||||||
|
|
||||||
|
GNUNET_free (env);
|
||||||
|
}
|
1355
src/psycutil/psyc_message.c
Normal file
1355
src/psycutil/psyc_message.c
Normal file
File diff suppressed because it is too large
Load Diff
711
src/psycutil/psyc_slicer.c
Normal file
711
src/psycutil/psyc_slicer.c
Normal file
@ -0,0 +1,711 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* PSYC Slicer API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_psyc_util_lib.h"
|
||||||
|
|
||||||
|
#define LOG(kind,...) GNUNET_log_from (kind, "psyc-util-slicer",__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for a try-and-slice instance.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Slicer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Method handlers: H(method_name) -> SlicerMethodCallbacks
|
||||||
|
*/
|
||||||
|
struct GNUNET_CONTAINER_MultiHashMap *method_handlers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifier handlers: H(modifier_name) -> SlicerModifierCallbacks
|
||||||
|
*/
|
||||||
|
struct GNUNET_CONTAINER_MultiHashMap *modifier_handlers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive handle for incoming messages.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_ReceiveHandle *recv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently being processed message.
|
||||||
|
*/
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently being processed message part.
|
||||||
|
*/
|
||||||
|
const struct GNUNET_MessageHeader *pmsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of currently being received message.
|
||||||
|
*/
|
||||||
|
uint64_t message_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment offset of currently being received message.
|
||||||
|
*/
|
||||||
|
uint64_t fragment_offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags of currently being received message.
|
||||||
|
*/
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method name of currently being received message.
|
||||||
|
*/
|
||||||
|
char *method_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of currently processed modifier.
|
||||||
|
*/
|
||||||
|
char *mod_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of currently processed modifier.
|
||||||
|
*/
|
||||||
|
char *mod_value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key of the nym the current message originates from.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey nym_pub_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of @a method_name (including terminating \0).
|
||||||
|
*/
|
||||||
|
uint16_t method_name_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of @a modifier_name (including terminating \0).
|
||||||
|
*/
|
||||||
|
uint16_t mod_name_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of modifier value fragment.
|
||||||
|
*/
|
||||||
|
uint16_t mod_value_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full size of modifier value.
|
||||||
|
*/
|
||||||
|
uint16_t mod_full_value_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remaining bytes from the value of the current modifier.
|
||||||
|
*/
|
||||||
|
uint16_t mod_value_remaining;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operator of currently processed modifier.
|
||||||
|
*/
|
||||||
|
uint8_t mod_oper;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callbacks for a slicer method handler.
|
||||||
|
*/
|
||||||
|
struct SlicerMethodCallbacks
|
||||||
|
{
|
||||||
|
GNUNET_PSYC_MessageCallback msg_cb;
|
||||||
|
GNUNET_PSYC_MethodCallback method_cb;
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb;
|
||||||
|
GNUNET_PSYC_DataCallback data_cb;
|
||||||
|
GNUNET_PSYC_EndOfMessageCallback eom_cb;
|
||||||
|
void *cls;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct SlicerMethodRemoveClosure
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Slicer *slicer;
|
||||||
|
struct SlicerMethodCallbacks rm_cbs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callbacks for a slicer method handler.
|
||||||
|
*/
|
||||||
|
struct SlicerModifierCallbacks
|
||||||
|
{
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb;
|
||||||
|
void *cls;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct SlicerModifierRemoveClosure
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Slicer *slicer;
|
||||||
|
struct SlicerModifierCallbacks rm_cbs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call a method handler for an incoming message part.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
slicer_method_handler_notify (void *cls, const struct GNUNET_HashCode *key,
|
||||||
|
void *value)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Slicer *slicer = cls;
|
||||||
|
const struct GNUNET_MessageHeader *pmsg = slicer->pmsg;
|
||||||
|
struct SlicerMethodCallbacks *cbs = value;
|
||||||
|
|
||||||
|
uint16_t ptype = ntohs (pmsg->type);
|
||||||
|
switch (ptype)
|
||||||
|
{
|
||||||
|
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD:
|
||||||
|
{
|
||||||
|
if (NULL != cbs->msg_cb)
|
||||||
|
cbs->msg_cb (cbs->cls, slicer->msg);
|
||||||
|
if (NULL == cbs->method_cb)
|
||||||
|
break;
|
||||||
|
struct GNUNET_PSYC_MessageMethod *
|
||||||
|
meth = (struct GNUNET_PSYC_MessageMethod *) pmsg;
|
||||||
|
cbs->method_cb (cbs->cls, slicer->msg, meth, slicer->message_id,
|
||||||
|
slicer->method_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
|
||||||
|
{
|
||||||
|
if (NULL == cbs->modifier_cb)
|
||||||
|
break;
|
||||||
|
struct GNUNET_PSYC_MessageModifier *
|
||||||
|
mod = (struct GNUNET_PSYC_MessageModifier *) pmsg;
|
||||||
|
cbs->modifier_cb (cbs->cls, slicer->msg, &mod->header, slicer->message_id,
|
||||||
|
mod->oper, (const char *) &mod[1],
|
||||||
|
(const void *) &mod[1] + ntohs (mod->name_size),
|
||||||
|
ntohs (mod->header.size) - sizeof (*mod) - ntohs (mod->name_size),
|
||||||
|
ntohs (mod->value_size));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
|
||||||
|
{
|
||||||
|
if (NULL == cbs->modifier_cb)
|
||||||
|
break;
|
||||||
|
cbs->modifier_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id,
|
||||||
|
slicer->mod_oper, slicer->mod_name, &pmsg[1],
|
||||||
|
ntohs (pmsg->size) - sizeof (*pmsg),
|
||||||
|
slicer->mod_full_value_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
|
||||||
|
{
|
||||||
|
if (NULL == cbs->data_cb)
|
||||||
|
break;
|
||||||
|
cbs->data_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id,
|
||||||
|
&pmsg[1], ntohs (pmsg->size) - sizeof (*pmsg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
|
||||||
|
if (NULL == cbs->eom_cb)
|
||||||
|
break;
|
||||||
|
cbs->eom_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id, GNUNET_NO);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
|
||||||
|
if (NULL == cbs->eom_cb)
|
||||||
|
break;
|
||||||
|
cbs->eom_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id, GNUNET_YES);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call a method handler for an incoming message part.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
slicer_modifier_handler_notify (void *cls, const struct GNUNET_HashCode *key,
|
||||||
|
void *value)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Slicer *slicer = cls;
|
||||||
|
struct SlicerModifierCallbacks *cbs = value;
|
||||||
|
|
||||||
|
cbs->modifier_cb (cbs->cls, slicer->msg, slicer->pmsg, slicer->message_id,
|
||||||
|
slicer->mod_oper, slicer->mod_name, slicer->mod_value,
|
||||||
|
slicer->mod_value_size, slicer->mod_full_value_size);
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an incoming message and call matching handlers.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The slicer to use.
|
||||||
|
* @param msg
|
||||||
|
* The message as it arrived from the network.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_message (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg)
|
||||||
|
{
|
||||||
|
GNUNET_PSYC_receive_message (slicer->recv, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an incoming message part and call matching handlers.
|
||||||
|
*
|
||||||
|
* @param cls
|
||||||
|
* Closure.
|
||||||
|
* @param message_id
|
||||||
|
* ID of the message.
|
||||||
|
* @param flags
|
||||||
|
* Flags for the message.
|
||||||
|
* @see enum GNUNET_PSYC_MessageFlags
|
||||||
|
* @param msg
|
||||||
|
* The message part. as it arrived from the network.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_message_part (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const struct GNUNET_PSYC_MessageHeader *msg,
|
||||||
|
const struct GNUNET_MessageHeader *pmsg)
|
||||||
|
{
|
||||||
|
slicer->msg = msg;
|
||||||
|
slicer->pmsg = pmsg;
|
||||||
|
|
||||||
|
uint64_t message_id = GNUNET_ntohll (msg->message_id);
|
||||||
|
|
||||||
|
uint16_t ptype = ntohs (pmsg->type);
|
||||||
|
if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_MessageMethod *
|
||||||
|
meth = (struct GNUNET_PSYC_MessageMethod *) pmsg;
|
||||||
|
slicer->method_name_size = ntohs (meth->header.size) - sizeof (*meth);
|
||||||
|
slicer->method_name = GNUNET_malloc (slicer->method_name_size);
|
||||||
|
GNUNET_memcpy (slicer->method_name, &meth[1], slicer->method_name_size);
|
||||||
|
slicer->message_id = message_id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GNUNET_assert (message_id == slicer->message_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&msg->slave_pub_key);
|
||||||
|
LOG (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"Slicer received message of type %u and size %u, "
|
||||||
|
"with ID %" PRIu64 " and method %s from %s\n",
|
||||||
|
ptype, ntohs (pmsg->size), message_id, slicer->method_name, nym_str);
|
||||||
|
GNUNET_free (nym_str);
|
||||||
|
|
||||||
|
/* try-and-slice modifier */
|
||||||
|
|
||||||
|
switch (ptype)
|
||||||
|
{
|
||||||
|
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_MessageModifier *
|
||||||
|
mod = (struct GNUNET_PSYC_MessageModifier *) pmsg;
|
||||||
|
slicer->mod_oper = mod->oper;
|
||||||
|
slicer->mod_name_size = ntohs (mod->name_size);
|
||||||
|
slicer->mod_name = GNUNET_malloc (slicer->mod_name_size);
|
||||||
|
GNUNET_memcpy (slicer->mod_name, &mod[1], slicer->mod_name_size);
|
||||||
|
slicer->mod_value = (char *) &mod[1] + slicer->mod_name_size;
|
||||||
|
slicer->mod_full_value_size = ntohs (mod->value_size);
|
||||||
|
slicer->mod_value_remaining = slicer->mod_full_value_size;
|
||||||
|
slicer->mod_value_size
|
||||||
|
= ntohs (mod->header.size) - sizeof (*mod) - slicer->mod_name_size;
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
|
||||||
|
if (ptype == GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT)
|
||||||
|
{
|
||||||
|
slicer->mod_value = (char *) &pmsg[1];
|
||||||
|
slicer->mod_value_size = ntohs (pmsg->size) - sizeof (*pmsg);
|
||||||
|
}
|
||||||
|
slicer->mod_value_remaining -= slicer->mod_value_size;
|
||||||
|
char *name = GNUNET_malloc (slicer->mod_name_size);
|
||||||
|
GNUNET_memcpy (name, slicer->mod_name, slicer->mod_name_size);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
struct GNUNET_HashCode key;
|
||||||
|
uint16_t name_len = strlen (name);
|
||||||
|
GNUNET_CRYPTO_hash (name, name_len, &key);
|
||||||
|
GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key,
|
||||||
|
slicer_modifier_handler_notify,
|
||||||
|
slicer);
|
||||||
|
char *p = strrchr (name, '_');
|
||||||
|
if (NULL == p)
|
||||||
|
break;
|
||||||
|
*p = '\0';
|
||||||
|
} while (1);
|
||||||
|
GNUNET_free (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try-and-slice method */
|
||||||
|
|
||||||
|
char *name = GNUNET_malloc (slicer->method_name_size);
|
||||||
|
GNUNET_memcpy (name, slicer->method_name, slicer->method_name_size);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
struct GNUNET_HashCode key;
|
||||||
|
uint16_t name_len = strlen (name);
|
||||||
|
GNUNET_CRYPTO_hash (name, name_len, &key);
|
||||||
|
GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key,
|
||||||
|
slicer_method_handler_notify,
|
||||||
|
slicer);
|
||||||
|
char *p = strrchr (name, '_');
|
||||||
|
if (NULL == p)
|
||||||
|
break;
|
||||||
|
*p = '\0';
|
||||||
|
} while (1);
|
||||||
|
GNUNET_free (name);
|
||||||
|
|
||||||
|
if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
|
||||||
|
GNUNET_free (slicer->method_name);
|
||||||
|
|
||||||
|
if (0 == slicer->mod_value_remaining && NULL != slicer->mod_name)
|
||||||
|
{
|
||||||
|
GNUNET_free (slicer->mod_name);
|
||||||
|
slicer->mod_name = NULL;
|
||||||
|
slicer->mod_name_size = 0;
|
||||||
|
slicer->mod_value_size = 0;
|
||||||
|
slicer->mod_full_value_size = 0;
|
||||||
|
slicer->mod_oper = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
slicer->msg = NULL;
|
||||||
|
slicer->pmsg = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a try-and-slice instance.
|
||||||
|
*
|
||||||
|
* A slicer processes incoming messages and notifies callbacks about matching
|
||||||
|
* methods or modifiers encountered.
|
||||||
|
*
|
||||||
|
* @return A new try-and-slice construct.
|
||||||
|
*/
|
||||||
|
struct GNUNET_PSYC_Slicer *
|
||||||
|
GNUNET_PSYC_slicer_create (void)
|
||||||
|
{
|
||||||
|
struct GNUNET_PSYC_Slicer *slicer = GNUNET_malloc (sizeof (*slicer));
|
||||||
|
slicer->method_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
|
||||||
|
slicer->modifier_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
|
||||||
|
slicer->recv = GNUNET_PSYC_receive_create (NULL,
|
||||||
|
(GNUNET_PSYC_MessagePartCallback)
|
||||||
|
GNUNET_PSYC_slicer_message_part,
|
||||||
|
slicer);
|
||||||
|
return slicer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a method to the try-and-slice instance.
|
||||||
|
*
|
||||||
|
* The callbacks are called for messages with a matching @a method_name prefix.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The try-and-slice instance to extend.
|
||||||
|
* @param method_name
|
||||||
|
* Name of the given method, use empty string to match all.
|
||||||
|
* @param method_cb
|
||||||
|
* Method handler invoked upon a matching message.
|
||||||
|
* @param modifier_cb
|
||||||
|
* Modifier handler, invoked after @a method_cb
|
||||||
|
* for each modifier in the message.
|
||||||
|
* @param data_cb
|
||||||
|
* Data handler, invoked after @a modifier_cb for each data fragment.
|
||||||
|
* @param eom_cb
|
||||||
|
* Invoked upon reaching the end of a matching message.
|
||||||
|
* @param cls
|
||||||
|
* Closure for the callbacks.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_method_add (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const char *method_name,
|
||||||
|
GNUNET_PSYC_MessageCallback msg_cb,
|
||||||
|
GNUNET_PSYC_MethodCallback method_cb,
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb,
|
||||||
|
GNUNET_PSYC_DataCallback data_cb,
|
||||||
|
GNUNET_PSYC_EndOfMessageCallback eom_cb,
|
||||||
|
void *cls)
|
||||||
|
{
|
||||||
|
struct GNUNET_HashCode key;
|
||||||
|
GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
|
||||||
|
|
||||||
|
struct SlicerMethodCallbacks *cbs = GNUNET_malloc (sizeof (*cbs));
|
||||||
|
cbs->msg_cb = msg_cb,
|
||||||
|
cbs->method_cb = method_cb;
|
||||||
|
cbs->modifier_cb = modifier_cb;
|
||||||
|
cbs->data_cb = data_cb;
|
||||||
|
cbs->eom_cb = eom_cb;
|
||||||
|
cbs->cls = cls;
|
||||||
|
|
||||||
|
GNUNET_CONTAINER_multihashmap_put (slicer->method_handlers, &key, cbs,
|
||||||
|
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
slicer_method_remove (void *cls, const struct GNUNET_HashCode *key, void *value)
|
||||||
|
{
|
||||||
|
struct SlicerMethodRemoveClosure *rm_cls = cls;
|
||||||
|
struct GNUNET_PSYC_Slicer *slicer = rm_cls->slicer;
|
||||||
|
struct SlicerMethodCallbacks *rm_cbs = &rm_cls->rm_cbs;
|
||||||
|
struct SlicerMethodCallbacks *cbs = value;
|
||||||
|
|
||||||
|
if ((NULL == rm_cbs->msg_cb || cbs->msg_cb == rm_cbs->msg_cb)
|
||||||
|
&& (NULL == rm_cbs->method_cb || cbs->method_cb == rm_cbs->method_cb)
|
||||||
|
&& (NULL == rm_cbs->modifier_cb || cbs->modifier_cb == rm_cbs->modifier_cb)
|
||||||
|
&& (NULL == rm_cbs->data_cb || cbs->data_cb == rm_cbs->data_cb)
|
||||||
|
&& (NULL == rm_cbs->eom_cb || cbs->eom_cb == rm_cbs->eom_cb))
|
||||||
|
{
|
||||||
|
GNUNET_CONTAINER_multihashmap_remove (slicer->method_handlers, key, cbs);
|
||||||
|
GNUNET_free (cbs);
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a registered method from the try-and-slice instance.
|
||||||
|
*
|
||||||
|
* Removes one matching handler registered with the given
|
||||||
|
* @a method_name and callbacks.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The try-and-slice instance.
|
||||||
|
* @param method_name
|
||||||
|
* Name of the method to remove.
|
||||||
|
* @param method_cb
|
||||||
|
* Method handler.
|
||||||
|
* @param modifier_cb
|
||||||
|
* Modifier handler.
|
||||||
|
* @param data_cb
|
||||||
|
* Data handler.
|
||||||
|
* @param eom_cb
|
||||||
|
* End of message handler.
|
||||||
|
*
|
||||||
|
* @return #GNUNET_OK if a method handler was removed,
|
||||||
|
* #GNUNET_NO if no handler matched the given method name and callbacks.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_slicer_method_remove (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const char *method_name,
|
||||||
|
GNUNET_PSYC_MessageCallback msg_cb,
|
||||||
|
GNUNET_PSYC_MethodCallback method_cb,
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb,
|
||||||
|
GNUNET_PSYC_DataCallback data_cb,
|
||||||
|
GNUNET_PSYC_EndOfMessageCallback eom_cb)
|
||||||
|
{
|
||||||
|
struct GNUNET_HashCode key;
|
||||||
|
GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
|
||||||
|
|
||||||
|
struct SlicerMethodRemoveClosure rm_cls;
|
||||||
|
rm_cls.slicer = slicer;
|
||||||
|
struct SlicerMethodCallbacks *rm_cbs = &rm_cls.rm_cbs;
|
||||||
|
rm_cbs->msg_cb = msg_cb;
|
||||||
|
rm_cbs->method_cb = method_cb;
|
||||||
|
rm_cbs->modifier_cb = modifier_cb;
|
||||||
|
rm_cbs->data_cb = data_cb;
|
||||||
|
rm_cbs->eom_cb = eom_cb;
|
||||||
|
|
||||||
|
return
|
||||||
|
(GNUNET_SYSERR
|
||||||
|
== GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key,
|
||||||
|
slicer_method_remove,
|
||||||
|
&rm_cls))
|
||||||
|
? GNUNET_NO
|
||||||
|
: GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch a place for changed objects.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The try-and-slice instance.
|
||||||
|
* @param object_filter
|
||||||
|
* Object prefix to match.
|
||||||
|
* @param modifier_cb
|
||||||
|
* Function to call when encountering a state modifier.
|
||||||
|
* @param cls
|
||||||
|
* Closure for callback.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_modifier_add (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const char *object_filter,
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb,
|
||||||
|
void *cls)
|
||||||
|
{
|
||||||
|
struct SlicerModifierCallbacks *cbs = GNUNET_malloc (sizeof *cbs);
|
||||||
|
cbs->modifier_cb = modifier_cb;
|
||||||
|
cbs->cls = cls;
|
||||||
|
|
||||||
|
struct GNUNET_HashCode key;
|
||||||
|
GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key);
|
||||||
|
GNUNET_CONTAINER_multihashmap_put (slicer->modifier_handlers, &key, cbs,
|
||||||
|
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
slicer_modifier_remove (void *cls, const struct GNUNET_HashCode *key, void *value)
|
||||||
|
{
|
||||||
|
struct SlicerModifierRemoveClosure *rm_cls = cls;
|
||||||
|
struct GNUNET_PSYC_Slicer *slicer = rm_cls->slicer;
|
||||||
|
struct SlicerModifierCallbacks *rm_cbs = &rm_cls->rm_cbs;
|
||||||
|
struct SlicerModifierCallbacks *cbs = value;
|
||||||
|
|
||||||
|
if (cbs->modifier_cb == rm_cbs->modifier_cb)
|
||||||
|
{
|
||||||
|
GNUNET_CONTAINER_multihashmap_remove (slicer->modifier_handlers, key, cbs);
|
||||||
|
GNUNET_free (cbs);
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a registered modifier from the try-and-slice instance.
|
||||||
|
*
|
||||||
|
* Removes one matching handler registered with the given
|
||||||
|
* @a object_filter and @a modifier_cb.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* The try-and-slice instance.
|
||||||
|
* @param object_filter
|
||||||
|
* Object prefix to match.
|
||||||
|
* @param modifier_cb
|
||||||
|
* Function to call when encountering a state modifier changes.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GNUNET_PSYC_slicer_modifier_remove (struct GNUNET_PSYC_Slicer *slicer,
|
||||||
|
const char *object_filter,
|
||||||
|
GNUNET_PSYC_ModifierCallback modifier_cb)
|
||||||
|
{
|
||||||
|
struct GNUNET_HashCode key;
|
||||||
|
GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key);
|
||||||
|
|
||||||
|
struct SlicerModifierRemoveClosure rm_cls;
|
||||||
|
rm_cls.slicer = slicer;
|
||||||
|
struct SlicerModifierCallbacks *rm_cbs = &rm_cls.rm_cbs;
|
||||||
|
rm_cbs->modifier_cb = modifier_cb;
|
||||||
|
|
||||||
|
return
|
||||||
|
(GNUNET_SYSERR
|
||||||
|
== GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key,
|
||||||
|
slicer_modifier_remove,
|
||||||
|
&rm_cls))
|
||||||
|
? GNUNET_NO
|
||||||
|
: GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
slicer_method_free (void *cls, const struct GNUNET_HashCode *key, void *value)
|
||||||
|
{
|
||||||
|
struct SlicerMethodCallbacks *cbs = value;
|
||||||
|
GNUNET_free (cbs);
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
slicer_modifier_free (void *cls, const struct GNUNET_HashCode *key, void *value)
|
||||||
|
{
|
||||||
|
struct SlicerModifierCallbacks *cbs = value;
|
||||||
|
GNUNET_free (cbs);
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all registered method handlers.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* Slicer to clear.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_method_clear (struct GNUNET_PSYC_Slicer *slicer)
|
||||||
|
{
|
||||||
|
GNUNET_CONTAINER_multihashmap_iterate (slicer->method_handlers,
|
||||||
|
slicer_method_free, NULL);
|
||||||
|
GNUNET_CONTAINER_multihashmap_clear (slicer->method_handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all registered modifier handlers.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* Slicer to clear.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_modifier_clear (struct GNUNET_PSYC_Slicer *slicer)
|
||||||
|
{
|
||||||
|
GNUNET_CONTAINER_multihashmap_iterate (slicer->modifier_handlers,
|
||||||
|
slicer_modifier_free, NULL);
|
||||||
|
GNUNET_CONTAINER_multihashmap_clear (slicer->modifier_handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all registered method & modifier handlers.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* Slicer to clear.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_clear (struct GNUNET_PSYC_Slicer *slicer)
|
||||||
|
{
|
||||||
|
GNUNET_PSYC_slicer_method_clear (slicer);
|
||||||
|
GNUNET_PSYC_slicer_modifier_clear (slicer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a given try-and-slice instance.
|
||||||
|
*
|
||||||
|
* @param slicer
|
||||||
|
* Slicer to destroy
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GNUNET_PSYC_slicer_destroy (struct GNUNET_PSYC_Slicer *slicer)
|
||||||
|
{
|
||||||
|
GNUNET_PSYC_slicer_clear (slicer);
|
||||||
|
GNUNET_CONTAINER_multihashmap_destroy (slicer->method_handlers);
|
||||||
|
GNUNET_CONTAINER_multihashmap_destroy (slicer->modifier_handlers);
|
||||||
|
GNUNET_PSYC_receive_destroy (slicer->recv);
|
||||||
|
GNUNET_free (slicer);
|
||||||
|
}
|
96
src/psycutil/test_psyc_env.c
Normal file
96
src/psycutil/test_psyc_env.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of GNUnet.
|
||||||
|
* Copyright (C) 2013 GNUnet e.V.
|
||||||
|
*
|
||||||
|
* GNUnet is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GNUnet is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gabor X Toth
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* Tests for the environment library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "gnunet_util_lib.h"
|
||||||
|
#include "gnunet_testing_lib.h"
|
||||||
|
#include "gnunet_psyc_util_lib.h"
|
||||||
|
|
||||||
|
struct GNUNET_PSYC_Modifier mods[] = {
|
||||||
|
{ .oper = GNUNET_PSYC_OP_SET,
|
||||||
|
.name = "_foo", .value = "foo", .value_size = 3 },
|
||||||
|
|
||||||
|
{ .oper = GNUNET_PSYC_OP_ASSIGN,
|
||||||
|
.name = "_foo_bar", .value = "foo bar", .value_size = 7 },
|
||||||
|
|
||||||
|
{ .oper = GNUNET_PSYC_OP_AUGMENT,
|
||||||
|
.name = "_foo_bar_baz", .value = "foo bar baz", .value_size = 11 }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ItCls
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
iterator (void *cls, enum GNUNET_PSYC_Operator oper,
|
||||||
|
const char *name, const char *value, uint32_t value_size)
|
||||||
|
{
|
||||||
|
struct ItCls *it_cls = cls;
|
||||||
|
struct GNUNET_PSYC_Modifier *m = &mods[it_cls->n++];
|
||||||
|
|
||||||
|
GNUNET_assert (oper == m->oper);
|
||||||
|
GNUNET_assert (value_size == m->value_size);
|
||||||
|
GNUNET_assert (0 == memcmp (name, m->name, strlen (m->name)));
|
||||||
|
GNUNET_assert (0 == memcmp (value, m->value, m->value_size));
|
||||||
|
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GNUNET_log_setup ("test-env", "WARNING", NULL);
|
||||||
|
|
||||||
|
struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
|
||||||
|
GNUNET_assert (NULL != env);
|
||||||
|
int i, len = 3;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
GNUNET_PSYC_env_add (env, mods[i].oper, mods[i].name,
|
||||||
|
mods[i].value, mods[i].value_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ItCls it_cls = { .n = 0 };
|
||||||
|
GNUNET_PSYC_env_iterate (env, iterator, &it_cls);
|
||||||
|
GNUNET_assert (len == it_cls.n);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
enum GNUNET_PSYC_Operator oper;
|
||||||
|
const char *name;
|
||||||
|
const void *value;
|
||||||
|
size_t value_size;
|
||||||
|
GNUNET_PSYC_env_shift (env, &oper, &name, &value, &value_size);
|
||||||
|
GNUNET_assert (len - i - 1 == GNUNET_PSYC_env_get_count (env));
|
||||||
|
}
|
||||||
|
|
||||||
|
GNUNET_PSYC_env_destroy (env);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
3
src/social/.gitignore
vendored
Normal file
3
src/social/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
gnunet-social
|
||||||
|
gnunet-service-social
|
||||||
|
test_social
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user