mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-24 13:12:03 +00:00
Merge pull request #1169 in FS/freeswitch from feature/FS-9775-rewrite-dht to master
* commit '57f793a07696739b9f3db15e40f6039a3ec5aad0': (92 commits) FS-9775: Remove nodeid from bucket container FS-9775: Update testbuckets to latest api FS-9775: Update testbuckets to new api FS-9775: Committing start of very basic datastore concept, will start tieing in the physical transport layer for replication under new ticket/branch fix unqlite build, don't do warn all ansi on it FS-9775: Committing to get assistance with building unqlite FS-9775: Remove moved h file references FS-9775: First round of integration of DHT into libblade, requires ongoing changes to DHT for proper exposure to blade level FS-9775: Fixed building libblade with address sanitizing support FS-9775: Tweaks, bug fixes, etc. Committing in preparation for introducing into libblade. FS-9775: Implement serialization, deserialization & repopulation for dht table FS-9775: A bunch of stuff related to chaining multiple jobs, bug fixes, few other changes FS-9775: DHT Repopulate empty buckets FS-9775: DHT Process table timing changes & test cleanup FS-9775: Some cleanup and bug fixes in DHT, switched to using hash destructors, and added sending of errors to most failed query scenarios FS-9775: First tested pass on search functionality, not tested with deep searching at multiple levels FS-9775: Add flags to dhtrt_create_node (merge) FS-9775: Bug fixes and exposed interface changes while implementing tests for get/put which are functional and pass initial tests now. Deep searching needs to be revamped now to complete the full announcing process. FS-9775: Exclude newly created nodes from find FS-9775: Fix memory reuse. Remove redundant fields ...
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
build/*.m4
|
||||
configure
|
||||
|
||||
@@ -1,674 +1 @@
|
||||
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>.
|
||||
|
||||
@@ -5,14 +5,20 @@ AUTOMAKE_OPTIONS = subdir-objects
|
||||
|
||||
AM_CFLAGS += -I$(top_srcdir)/src -I$(top_srcdir)/src/include
|
||||
|
||||
lib_LTLIBRARIES = libblade.la
|
||||
libblade_la_SOURCES = src/blade.c src/blade_stack.c src/blade_peer.c src/bpcp.c
|
||||
libblade_la_CFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
|
||||
libblade_la_LDFLAGS = -version-info 0:1:0 -lncurses -lpthread -lm $(AM_LDFLAGS)
|
||||
noinst_LTLIBRARIES = libunqlite.la
|
||||
libunqlite_la_SOURCES = src/unqlite.c
|
||||
libunqlite_la_CFLAGS = -DUNQLITE_ENABLE_THREADS
|
||||
libunqlite_la_LIBADD = -lpthread
|
||||
|
||||
lib_LTLIBRARIES = libblade.la
|
||||
libblade_la_SOURCES = src/blade.c src/blade_stack.c src/blade_peer.c src/bpcp.c src/blade_datastore.c
|
||||
libblade_la_CFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
|
||||
libblade_la_LDFLAGS = -version-info 0:1:0 -lncurses -lpthread -lm $(AM_LDFLAGS)
|
||||
libblade_la_LIBADD = libunqlite.la
|
||||
library_includedir = $(prefix)/include
|
||||
library_include_HEADERS = src/include/blade.h src/include/blade_types.h src/include/blade_stack.h src/include/blade_peer.h src/include/bpcp.h
|
||||
library_include_HEADERS += test/tap.h
|
||||
library_include_HEADERS += src/include/blade_datastore.h
|
||||
library_include_HEADERS += src/include/unqlite.h test/tap.h
|
||||
|
||||
tests: libblade.la
|
||||
$(MAKE) -C test tests
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
AC_DEFUN([AX_CFLAGS_WARN_ALL_ANSI],[dnl
|
||||
AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
|
||||
AS_VAR_PUSHDEF([FLAGS],[AM_CFLAGS])dnl
|
||||
AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_warn_all_ansi])dnl
|
||||
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum ansi warnings],
|
||||
VAR,[VAR="no, unknown"
|
||||
@@ -47,7 +47,7 @@ AS_VAR_POPDEF([FLAGS])dnl
|
||||
dnl the only difference - the LANG selection... and the default FLAGS
|
||||
|
||||
AC_DEFUN([AX_CXXFLAGS_WARN_ALL_ANSI],[dnl
|
||||
AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
|
||||
AS_VAR_PUSHDEF([FLAGS],[AM_CXXFLAGS])dnl
|
||||
AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_warn_all_ansi])dnl
|
||||
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum ansi warnings],
|
||||
VAR,[VAR="no, unknown"
|
||||
|
||||
@@ -241,11 +241,9 @@ AC_ARG_ENABLE(address_sanitizer,
|
||||
[enable_address_sanitizer="no"])
|
||||
|
||||
if test "${enable_address_sanitizer}" = "yes"; then
|
||||
if test "x${ax_cv_c_compiler_vendor}" = "xclang" ; then
|
||||
AM_CFLAGS="${AM_CFLAGS} -fsanitize=address -fno-omit-frame-pointer"
|
||||
AM_CXXFLAGS="${AM_CXXFLAGS} -fsanitize=address -fno-omit-frame-pointer"
|
||||
AM_LDFLAGS="${AM_LDFLAGS} -fsanitize=address"
|
||||
fi
|
||||
AM_CFLAGS="${AM_CFLAGS} -fsanitize=address -fno-omit-frame-pointer"
|
||||
AM_CXXFLAGS="${AM_CXXFLAGS} -fsanitize=address -fno-omit-frame-pointer"
|
||||
AM_LDFLAGS="${AM_LDFLAGS} -fsanitize=address"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([libks],
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2014, Anthony Minessale II
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blade.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
BDS_NONE = 0,
|
||||
BDS_MYPOOL = (1 << 0),
|
||||
} bdspvt_flag_t;
|
||||
|
||||
struct blade_datastore_s {
|
||||
bdspvt_flag_t flags;
|
||||
ks_pool_t *pool;
|
||||
unqlite *db;
|
||||
};
|
||||
|
||||
struct blade_datastore_fetch_userdata_s
|
||||
{
|
||||
blade_datastore_t *bds;
|
||||
blade_datastore_fetch_callback_t callback;
|
||||
void *userdata;
|
||||
};
|
||||
typedef struct blade_datastore_fetch_userdata_s blade_datastore_fetch_userdata_t;
|
||||
|
||||
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_datastore_destroy(blade_datastore_t **bdsP)
|
||||
{
|
||||
blade_datastore_t *bds = NULL;
|
||||
bdspvt_flag_t flags;
|
||||
ks_pool_t *pool;
|
||||
|
||||
ks_assert(bdsP);
|
||||
|
||||
bds = *bdsP;
|
||||
*bdsP = NULL;
|
||||
|
||||
ks_assert(bds);
|
||||
|
||||
flags = bds->flags;
|
||||
pool = bds->pool;
|
||||
|
||||
if (bds->db) {
|
||||
unqlite_close(bds->db);
|
||||
bds->db = NULL;
|
||||
}
|
||||
|
||||
ks_pool_free(bds->pool, &bds);
|
||||
|
||||
if (pool && (flags & BDS_MYPOOL)) ks_pool_close(&pool);
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_datastore_create(blade_datastore_t **bdsP, ks_pool_t *pool)
|
||||
{
|
||||
bdspvt_flag_t newflags = BDS_NONE;
|
||||
blade_datastore_t *bds = NULL;
|
||||
|
||||
if (!pool) {
|
||||
newflags |= BDS_MYPOOL;
|
||||
ks_pool_open(&pool);
|
||||
ks_assert(pool);
|
||||
}
|
||||
|
||||
bds = ks_pool_alloc(pool, sizeof(*bds));
|
||||
bds->flags = newflags;
|
||||
bds->pool = pool;
|
||||
*bdsP = bds;
|
||||
|
||||
if (unqlite_open(&bds->db, NULL, UNQLITE_OPEN_IN_MEMORY) != UNQLITE_OK) {
|
||||
const char *errbuf = NULL;
|
||||
blade_datastore_error(bds, &errbuf, NULL);
|
||||
ks_log(KS_LOG_ERROR, "BDS Error: %s\n", errbuf);
|
||||
return KS_STATUS_FAIL;
|
||||
}
|
||||
|
||||
// @todo unqlite_lib_config(UNQLITE_LIB_CONFIG_MEM_ERR_CALLBACK)
|
||||
|
||||
// @todo VM init if document store is used (and output consumer callback)
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) blade_datastore_pulse(blade_datastore_t *bds, int32_t timeout)
|
||||
{
|
||||
ks_assert(bds);
|
||||
ks_assert(timeout >= 0);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) blade_datastore_error(blade_datastore_t *bds, const char **buffer, int32_t *buffer_length)
|
||||
{
|
||||
ks_assert(bds);
|
||||
ks_assert(bds->db);
|
||||
ks_assert(buffer);
|
||||
|
||||
unqlite_config(bds->db, UNQLITE_CONFIG_ERR_LOG, buffer, buffer_length);
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_datastore_store(blade_datastore_t *bds, const void *key, int32_t key_length, const void *data, int64_t data_length)
|
||||
{
|
||||
int32_t rc;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(bds);
|
||||
ks_assert(bds->db);
|
||||
ks_assert(key);
|
||||
ks_assert(key_length > 0);
|
||||
ks_assert(data);
|
||||
ks_assert(data_length > 0);
|
||||
|
||||
rc = unqlite_begin(bds->db);
|
||||
|
||||
if (rc != UNQLITE_OK) {
|
||||
if (rc == UNQLITE_BUSY) ret = KS_STATUS_TIMEOUT;
|
||||
else {
|
||||
const char *errbuf;
|
||||
blade_datastore_error(bds, &errbuf, NULL);
|
||||
ks_log(KS_LOG_ERROR, "BDS Error: %s\n", errbuf);
|
||||
|
||||
ret = KS_STATUS_FAIL;
|
||||
}
|
||||
} else if (unqlite_kv_store(bds->db, key, key_length, data, data_length) == UNQLITE_OK) unqlite_commit(bds->db);
|
||||
else unqlite_rollback(bds->db);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int blade_datastore_fetch_callback(const void *data, unsigned int data_length, void *userdata)
|
||||
{
|
||||
int rc = UNQLITE_OK;
|
||||
blade_datastore_fetch_userdata_t *ud = NULL;
|
||||
|
||||
ks_assert(data);
|
||||
ks_assert(data_length > 0);
|
||||
ks_assert(userdata);
|
||||
|
||||
ud = (blade_datastore_fetch_userdata_t *)userdata;
|
||||
if (!ud->callback(ud->bds, data, data_length, ud->userdata)) rc = UNQLITE_ABORT;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_datastore_fetch(blade_datastore_t *bds,
|
||||
blade_datastore_fetch_callback_t callback,
|
||||
const void *key,
|
||||
int32_t key_length,
|
||||
void *userdata)
|
||||
{
|
||||
int32_t rc;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
blade_datastore_fetch_userdata_t ud;
|
||||
|
||||
ks_assert(bds);
|
||||
ks_assert(bds->db);
|
||||
ks_assert(callback);
|
||||
ks_assert(key);
|
||||
ks_assert(key_length > 0);
|
||||
|
||||
ud.bds = bds;
|
||||
ud.callback = callback;
|
||||
ud.userdata = userdata;
|
||||
|
||||
rc = unqlite_kv_fetch_callback(bds->db, key, key_length, blade_datastore_fetch_callback, &ud);
|
||||
|
||||
if (rc != UNQLITE_OK) {
|
||||
if (rc == UNQLITE_BUSY) ret = KS_STATUS_TIMEOUT;
|
||||
else {
|
||||
const char *errbuf;
|
||||
blade_datastore_error(bds, &errbuf, NULL);
|
||||
ks_log(KS_LOG_ERROR, "BDS Error: %s\n", errbuf);
|
||||
|
||||
ret = KS_STATUS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -33,14 +33,22 @@
|
||||
|
||||
#include "blade.h"
|
||||
|
||||
#define KS_DHT_TPOOL_MIN 2
|
||||
#define KS_DHT_TPOOL_MAX 8
|
||||
#define KS_DHT_TPOOL_STACK (1024 * 256)
|
||||
#define KS_DHT_TPOOL_IDLE 10
|
||||
|
||||
typedef enum {
|
||||
BP_NONE = 0,
|
||||
BP_MYPOOL = (1 << 0)
|
||||
BP_MYPOOL = (1 << 0),
|
||||
BP_MYTPOOL = (1 << 1)
|
||||
} bppvt_flag_t;
|
||||
|
||||
struct blade_peer_s {
|
||||
bppvt_flag_t flags;
|
||||
ks_pool_t *pool;
|
||||
ks_thread_pool_t *tpool;
|
||||
ks_dht_t *dht;
|
||||
};
|
||||
|
||||
|
||||
@@ -60,33 +68,75 @@ KS_DECLARE(ks_status_t) blade_peer_destroy(blade_peer_t **bpP)
|
||||
flags = bp->flags;
|
||||
pool = bp->pool;
|
||||
|
||||
ks_pool_free(bp->pool, bp);
|
||||
if (bp->dht) ks_dht_destroy(&bp->dht);
|
||||
if (bp->tpool && (flags & BP_MYTPOOL)) ks_thread_pool_destroy(&bp->tpool);
|
||||
|
||||
ks_pool_free(bp->pool, &bp);
|
||||
|
||||
if (pool && (flags & BP_MYPOOL)) {
|
||||
ks_pool_close(&pool);
|
||||
}
|
||||
if (pool && (flags & BP_MYPOOL)) ks_pool_close(&pool);
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_peer_create(blade_peer_t **bpP, ks_pool_t *pool)
|
||||
KS_DECLARE(ks_status_t) blade_peer_create(blade_peer_t **bpP, ks_pool_t *pool, ks_thread_pool_t *tpool, ks_dht_nodeid_t *nodeid)
|
||||
{
|
||||
bppvt_flag_t newflags = BP_NONE;
|
||||
blade_peer_t *bp = NULL;
|
||||
ks_dht_t *dht = NULL;
|
||||
|
||||
if (!pool) {
|
||||
newflags |= BP_MYPOOL;
|
||||
ks_pool_open(&pool);
|
||||
ks_assert(pool);
|
||||
}
|
||||
if (!tpool) {
|
||||
newflags |= BP_MYTPOOL;
|
||||
ks_thread_pool_create(&tpool, BLADE_PEER_TPOOL_MIN, BLADE_PEER_TPOOL_MAX, BLADE_PEER_TPOOL_STACK, KS_PRI_NORMAL, BLADE_PEER_TPOOL_IDLE);
|
||||
ks_assert(tpool);
|
||||
}
|
||||
ks_dht_create(&dht, pool, tpool, nodeid);
|
||||
ks_assert(dht);
|
||||
|
||||
bp = ks_pool_alloc(pool, sizeof(*bp));
|
||||
bp->pool = pool;
|
||||
bp->flags = newflags;
|
||||
bp->pool = pool;
|
||||
bp->tpool = tpool;
|
||||
bp->dht = dht;
|
||||
*bpP = bp;
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_dht_nodeid_t *) blade_peer_myid(blade_peer_t *bp)
|
||||
{
|
||||
ks_assert(bp);
|
||||
ks_assert(bp->dht);
|
||||
|
||||
return &bp->dht->nodeid;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) blade_peer_autoroute(blade_peer_t *bp, ks_bool_t autoroute, ks_port_t port)
|
||||
{
|
||||
ks_assert(bp);
|
||||
|
||||
ks_dht_autoroute(bp->dht, autoroute, port);
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_peer_bind(blade_peer_t *bp, const ks_sockaddr_t *addr, ks_dht_endpoint_t **endpoint)
|
||||
{
|
||||
ks_assert(bp);
|
||||
ks_assert(addr);
|
||||
|
||||
return ks_dht_bind(bp->dht, addr, endpoint);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) blade_peer_pulse(blade_peer_t *bp, int32_t timeout)
|
||||
{
|
||||
ks_assert(bp);
|
||||
ks_assert(timeout >= 0);
|
||||
|
||||
ks_dht_pulse(bp->dht, timeout);
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
|
||||
@@ -35,13 +35,16 @@
|
||||
|
||||
typedef enum {
|
||||
BH_NONE = 0,
|
||||
BH_MYPOOL = (1 << 0)
|
||||
BH_MYPOOL = (1 << 0),
|
||||
BH_MYTPOOL = (1 << 1)
|
||||
} bhpvt_flag_t;
|
||||
|
||||
struct blade_handle_s {
|
||||
ks_pool_t *pool;
|
||||
bhpvt_flag_t flags;
|
||||
ks_pool_t *pool;
|
||||
ks_thread_pool_t *tpool;
|
||||
blade_peer_t *peer;
|
||||
blade_datastore_t *datastore;
|
||||
};
|
||||
|
||||
|
||||
@@ -61,9 +64,12 @@ KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP)
|
||||
flags = bh->flags;
|
||||
pool = bh->pool;
|
||||
|
||||
blade_peer_destroy(&bh->peer);
|
||||
if (bh->datastore) blade_datastore_destroy(&bh->datastore);
|
||||
|
||||
ks_pool_free(bh->pool, bh);
|
||||
blade_peer_destroy(&bh->peer);
|
||||
if (bh->tpool && (flags & BH_MYTPOOL)) ks_thread_pool_destroy(&bh->tpool);
|
||||
|
||||
ks_pool_free(bh->pool, &bh);
|
||||
|
||||
if (pool && (flags & BH_MYPOOL)) {
|
||||
ks_pool_close(&pool);
|
||||
@@ -72,26 +78,116 @@ KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP)
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *pool)
|
||||
KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *pool, ks_thread_pool_t *tpool, const char *nodeid)
|
||||
{
|
||||
bhpvt_flag_t newflags = BH_NONE;
|
||||
blade_handle_t *bh = NULL;
|
||||
ks_dht_nodeid_t nid;
|
||||
|
||||
ks_assert(nodeid);
|
||||
ks_assert(strlen(nodeid) == (KS_DHT_NODEID_SIZE * 2));
|
||||
|
||||
if (!pool) {
|
||||
newflags |= BH_MYPOOL;
|
||||
ks_pool_open(&pool);
|
||||
}
|
||||
|
||||
if (!tpool) {
|
||||
newflags |= BH_MYTPOOL;
|
||||
ks_thread_pool_create(&tpool, BLADE_HANDLE_TPOOL_MIN, BLADE_HANDLE_TPOOL_MAX, BLADE_HANDLE_TPOOL_STACK, KS_PRI_NORMAL, BLADE_HANDLE_TPOOL_IDLE);
|
||||
ks_assert(tpool);
|
||||
}
|
||||
|
||||
bh = ks_pool_alloc(pool, sizeof(*bh));
|
||||
bh->pool = pool;
|
||||
bh->flags = newflags;
|
||||
blade_peer_create(&bh->peer, bh->pool);
|
||||
bh->pool = pool;
|
||||
bh->tpool = tpool;
|
||||
ks_dht_dehex(nid.id, nodeid, KS_DHT_NODEID_SIZE);
|
||||
blade_peer_create(&bh->peer, bh->pool, bh->tpool, &nid);
|
||||
|
||||
*bhP = bh;
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) blade_handle_myid(blade_handle_t *bh, char *buffer)
|
||||
{
|
||||
ks_dht_nodeid_t *nodeid = NULL;
|
||||
|
||||
ks_assert(bh);
|
||||
ks_assert(bh->peer);
|
||||
|
||||
nodeid = blade_peer_myid(bh->peer);
|
||||
ks_dht_hex(nodeid->id, buffer, KS_DHT_NODEID_SIZE);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) blade_handle_autoroute(blade_handle_t *bh, ks_bool_t autoroute, ks_port_t port)
|
||||
{
|
||||
ks_assert(bh);
|
||||
ks_assert(bh->peer);
|
||||
|
||||
blade_peer_autoroute(bh->peer, autoroute, port);
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_handle_bind(blade_handle_t *bh, const char *ip, ks_port_t port, ks_dht_endpoint_t **endpoint)
|
||||
{
|
||||
ks_sockaddr_t addr;
|
||||
int family = AF_INET;
|
||||
|
||||
ks_assert(bh);
|
||||
ks_assert(ip);
|
||||
ks_assert(port);
|
||||
|
||||
if (ip[1] != '.' && ip[2] != '.' && ip[3] != '.') family = AF_INET6;
|
||||
|
||||
ks_addr_set(&addr, ip, port, family);
|
||||
return blade_peer_bind(bh->peer, &addr, endpoint);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) blade_handle_pulse(blade_handle_t *bh, int32_t timeout)
|
||||
{
|
||||
ks_assert(bh);
|
||||
ks_assert(timeout >= 0);
|
||||
|
||||
blade_peer_pulse(bh->peer, timeout);
|
||||
if (bh->datastore) blade_datastore_pulse(bh->datastore, timeout);
|
||||
}
|
||||
|
||||
|
||||
KS_DECLARE(void) blade_handle_datastore_start(blade_handle_t *bh)
|
||||
{
|
||||
ks_assert(bh);
|
||||
|
||||
if (bh->datastore) return;
|
||||
|
||||
blade_datastore_create(&bh->datastore, bh->pool);
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_handle_datastore_store(blade_handle_t *bh, const void *key, int32_t key_length, const void *data, int64_t data_length)
|
||||
{
|
||||
ks_assert(bh);
|
||||
ks_assert(bh->datastore);
|
||||
ks_assert(key);
|
||||
ks_assert(key_length > 0);
|
||||
ks_assert(data);
|
||||
ks_assert(data_length > 0);
|
||||
|
||||
return blade_datastore_store(bh->datastore, key, key_length, data, data_length);
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) blade_handle_datastore_fetch(blade_handle_t *bh,
|
||||
blade_datastore_fetch_callback_t callback,
|
||||
const void *key,
|
||||
int32_t key_length,
|
||||
void *userdata)
|
||||
{
|
||||
ks_assert(bh);
|
||||
ks_assert(bh->datastore);
|
||||
ks_assert(callback);
|
||||
ks_assert(key);
|
||||
ks_assert(key_length > 0);
|
||||
|
||||
return blade_datastore_fetch(bh->datastore, callback, key, key_length, userdata);
|
||||
}
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
|
||||
@@ -34,10 +34,13 @@
|
||||
#ifndef _BLADE_H_
|
||||
#define _BLADE_H_
|
||||
#include <ks.h>
|
||||
#include <ks_dht.h>
|
||||
#include <sodium.h>
|
||||
#include "unqlite.h"
|
||||
#include "blade_types.h"
|
||||
#include "blade_stack.h"
|
||||
#include "blade_peer.h"
|
||||
#include "blade_datastore.h"
|
||||
#include "bpcp.h"
|
||||
|
||||
KS_BEGIN_EXTERN_C
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2014, Anthony Minessale II
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BLADE_DATASTORE_H_
|
||||
#define _BLADE_DATASTORE_H_
|
||||
#include <blade.h>
|
||||
|
||||
KS_BEGIN_EXTERN_C
|
||||
KS_DECLARE(ks_status_t) blade_datastore_create(blade_datastore_t **bdsP, ks_pool_t *pool);
|
||||
KS_DECLARE(ks_status_t) blade_datastore_destroy(blade_datastore_t **bdsP);
|
||||
KS_DECLARE(void) blade_datastore_pulse(blade_datastore_t *bds, int32_t timeout);
|
||||
KS_DECLARE(void) blade_datastore_error(blade_datastore_t *bds, const char **buffer, int32_t *buffer_length);
|
||||
KS_DECLARE(ks_status_t) blade_datastore_store(blade_datastore_t *bds, const void *key, int32_t key_length, const void *data, int64_t data_length);
|
||||
KS_DECLARE(ks_status_t) blade_datastore_fetch(blade_datastore_t *bds,
|
||||
blade_datastore_fetch_callback_t callback,
|
||||
const void *key,
|
||||
int32_t key_length,
|
||||
void *userdata);
|
||||
KS_END_EXTERN_C
|
||||
|
||||
#endif
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -35,9 +35,18 @@
|
||||
#define _BPCP_H_
|
||||
#include <blade.h>
|
||||
|
||||
#define BLADE_PEER_TPOOL_MIN 2
|
||||
#define BLADE_PEER_TPOOL_MAX 8
|
||||
#define BLADE_PEER_TPOOL_STACK (1024 * 256)
|
||||
#define BLADE_PEER_TPOOL_IDLE 10
|
||||
|
||||
KS_BEGIN_EXTERN_C
|
||||
KS_DECLARE(ks_status_t) blade_peer_create(blade_peer_t **bpP, ks_pool_t *pool);
|
||||
KS_DECLARE(ks_status_t) blade_peer_create(blade_peer_t **bpP, ks_pool_t *pool, ks_thread_pool_t *tpool, ks_dht_nodeid_t *nodeid);
|
||||
KS_DECLARE(ks_status_t) blade_peer_destroy(blade_peer_t **bpP);
|
||||
KS_DECLARE(ks_dht_nodeid_t *) blade_peer_myid(blade_peer_t *bp);
|
||||
KS_DECLARE(void) blade_peer_autoroute(blade_peer_t *bp, ks_bool_t autoroute, ks_port_t port);
|
||||
KS_DECLARE(ks_status_t) blade_peer_bind(blade_peer_t *bp, const ks_sockaddr_t *addr, ks_dht_endpoint_t **endpoint);
|
||||
KS_DECLARE(void) blade_peer_pulse(blade_peer_t *bp, int32_t timeout);
|
||||
KS_END_EXTERN_C
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,9 +35,25 @@
|
||||
#define _BLADE_STACK_H_
|
||||
#include <blade.h>
|
||||
|
||||
#define BLADE_HANDLE_TPOOL_MIN 2
|
||||
#define BLADE_HANDLE_TPOOL_MAX 8
|
||||
#define BLADE_HANDLE_TPOOL_STACK (1024 * 256)
|
||||
#define BLADE_HANDLE_TPOOL_IDLE 10
|
||||
|
||||
KS_BEGIN_EXTERN_C
|
||||
KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP);
|
||||
KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *pool);
|
||||
KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *pool, ks_thread_pool_t *tpool, const char *nodeid);
|
||||
KS_DECLARE(void) blade_handle_myid(blade_handle_t *bh, char *buffer);
|
||||
KS_DECLARE(void) blade_handle_autoroute(blade_handle_t *bh, ks_bool_t autoroute, ks_port_t port);
|
||||
KS_DECLARE(ks_status_t) blade_handle_bind(blade_handle_t *bh, const char *ip, ks_port_t port, ks_dht_endpoint_t **endpoint);
|
||||
KS_DECLARE(void) blade_handle_pulse(blade_handle_t *bh, int32_t timeout);
|
||||
KS_DECLARE(void) blade_handle_datastore_start(blade_handle_t *bh);
|
||||
KS_DECLARE(ks_status_t) blade_handle_datastore_store(blade_handle_t *bh, const void *key, int32_t key_length, const void *data, int64_t data_length);
|
||||
KS_DECLARE(ks_status_t) blade_handle_datastore_fetch(blade_handle_t *bh,
|
||||
blade_datastore_fetch_callback_t callback,
|
||||
const void *key,
|
||||
int32_t key_length,
|
||||
void *userdata);
|
||||
KS_END_EXTERN_C
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,9 @@ KS_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct blade_handle_s blade_handle_t;
|
||||
typedef struct blade_peer_s blade_peer_t;
|
||||
typedef struct blade_datastore_s blade_datastore_t;
|
||||
|
||||
typedef ks_bool_t (*blade_datastore_fetch_callback_t)(blade_datastore_t *bds, const void *data, uint32_t data_length, void *userdata);
|
||||
|
||||
KS_END_EXTERN_C
|
||||
|
||||
|
||||
@@ -0,0 +1,950 @@
|
||||
/* This file was automatically generated. Do not edit (Except for compile time directives)! */
|
||||
#ifndef _UNQLITE_H_
|
||||
#define _UNQLITE_H_
|
||||
/*
|
||||
* Symisc UnQLite: An Embeddable NoSQL (Post Modern) Database Engine.
|
||||
* Copyright (C) 2012-2016, Symisc Systems http://unqlite.org/
|
||||
* Version 1.1.7
|
||||
* For information on licensing, redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES
|
||||
* please contact Symisc Systems via:
|
||||
* legal@symisc.net
|
||||
* licensing@symisc.net
|
||||
* contact@symisc.net
|
||||
* or visit:
|
||||
* http://unqlite.org/licensing.html
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2012, 2016 Symisc Systems, S.U.A.R.L [M.I.A.G Mrad Chems Eddine <chm@symisc.net>].
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SYMISC SYSTEMS ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SYMISC SYSTEMS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* $SymiscID: unqlite.h v1.2 Win10 2106-12-02 00:04:12 stable <chm@symisc.net> $ */
|
||||
#include <stdarg.h> /* needed for the definition of va_list */
|
||||
/*
|
||||
* Compile time engine version, signature, identification in the symisc source tree
|
||||
* and copyright notice.
|
||||
* Each macro have an equivalent C interface associated with it that provide the same
|
||||
* information but are associated with the library instead of the header file.
|
||||
* Refer to [unqlite_lib_version()], [unqlite_lib_signature()], [unqlite_lib_ident()] and
|
||||
* [unqlite_lib_copyright()] for more information.
|
||||
*/
|
||||
/*
|
||||
* The UNQLITE_VERSION C preprocessor macroevaluates to a string literal
|
||||
* that is the unqlite version in the format "X.Y.Z" where X is the major
|
||||
* version number and Y is the minor version number and Z is the release
|
||||
* number.
|
||||
*/
|
||||
#define UNQLITE_VERSION "1.1.7"
|
||||
/*
|
||||
* The UNQLITE_VERSION_NUMBER C preprocessor macro resolves to an integer
|
||||
* with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
|
||||
* numbers used in [UNQLITE_VERSION].
|
||||
*/
|
||||
#define UNQLITE_VERSION_NUMBER 1001007
|
||||
/*
|
||||
* The UNQLITE_SIG C preprocessor macro evaluates to a string
|
||||
* literal which is the public signature of the unqlite engine.
|
||||
* This signature could be included for example in a host-application
|
||||
* generated Server MIME header as follows:
|
||||
* Server: YourWebServer/x.x unqlite/x.x.x \r\n
|
||||
*/
|
||||
#define UNQLITE_SIG "unqlite/1.1.7"
|
||||
/*
|
||||
* UnQLite identification in the Symisc source tree:
|
||||
* Each particular check-in of a particular software released
|
||||
* by symisc systems have an unique identifier associated with it.
|
||||
* This macro hold the one associated with unqlite.
|
||||
*/
|
||||
#define UNQLITE_IDENT "unqlite:b172a1e2c3f62fb35c8e1fb2795121f82356cad6"
|
||||
/*
|
||||
* Copyright notice.
|
||||
* If you have any questions about the licensing situation, please
|
||||
* visit http://unqlite.org/licensing.html
|
||||
* or contact Symisc Systems via:
|
||||
* legal@symisc.net
|
||||
* licensing@symisc.net
|
||||
* contact@symisc.net
|
||||
*/
|
||||
#define UNQLITE_COPYRIGHT "Copyright (C) Symisc Systems, S.U.A.R.L [Mrad Chems Eddine <chm@symisc.net>] 2012-2016, http://unqlite.org/"
|
||||
|
||||
/* Forward declaration to public objects */
|
||||
typedef struct unqlite_io_methods unqlite_io_methods;
|
||||
typedef struct unqlite_kv_methods unqlite_kv_methods;
|
||||
typedef struct unqlite_kv_engine unqlite_kv_engine;
|
||||
typedef struct jx9_io_stream unqlite_io_stream;
|
||||
typedef struct jx9_context unqlite_context;
|
||||
typedef struct jx9_value unqlite_value;
|
||||
typedef struct unqlite_vfs unqlite_vfs;
|
||||
typedef struct unqlite_vm unqlite_vm;
|
||||
typedef struct unqlite unqlite;
|
||||
/*
|
||||
* ------------------------------
|
||||
* Compile time directives
|
||||
* ------------------------------
|
||||
* For most purposes, UnQLite can be built just fine using the default compilation options.
|
||||
* However, if required, the compile-time options documented below can be used to omit UnQLite
|
||||
* features (resulting in a smaller compiled library size) or to change the default values
|
||||
* of some parameters.
|
||||
* Every effort has been made to ensure that the various combinations of compilation options
|
||||
* work harmoniously and produce a working library.
|
||||
*
|
||||
* UNQLITE_ENABLE_THREADS
|
||||
* This option controls whether or not code is included in UnQLite to enable it to operate
|
||||
* safely in a multithreaded environment. The default is not. All mutexing code is omitted
|
||||
* and it is unsafe to use UnQLite in a multithreaded program. When compiled with the
|
||||
* UNQLITE_ENABLE_THREADS directive enabled, UnQLite can be used in a multithreaded program
|
||||
* and it is safe to share the same virtual machine and engine handle between two or more threads.
|
||||
* The value of UNQLITE_ENABLE_THREADS can be determined at run-time using the unqlite_lib_is_threadsafe()
|
||||
* interface.
|
||||
* When UnQLite has been compiled with threading support then the threading mode can be altered
|
||||
* at run-time using the unqlite_lib_config() interface together with one of these verbs:
|
||||
* UNQLITE_LIB_CONFIG_THREAD_LEVEL_SINGLE
|
||||
* UNQLITE_LIB_CONFIG_THREAD_LEVEL_MULTI
|
||||
* Platforms others than Windows and UNIX systems must install their own mutex subsystem via
|
||||
* unqlite_lib_config() with a configuration verb set to UNQLITE_LIB_CONFIG_USER_MUTEX.
|
||||
* Otherwise the library is not threadsafe.
|
||||
* Note that you must link UnQLite with the POSIX threads library under UNIX systems (i.e: -lpthread).
|
||||
*
|
||||
* Options To Omit/Enable Features
|
||||
*
|
||||
* The following options can be used to reduce the size of the compiled library by omitting optional
|
||||
* features. This is probably only useful in embedded systems where space is especially tight, as even
|
||||
* with all features included the UnQLite library is relatively small. Don't forget to tell your
|
||||
* compiler to optimize for binary size! (the -Os option if using GCC). Telling your compiler
|
||||
* to optimize for size usually has a much larger impact on library footprint than employing
|
||||
* any of these compile-time options.
|
||||
*
|
||||
* JX9_DISABLE_BUILTIN_FUNC
|
||||
* Jx9 is shipped with more than 312 built-in functions suitable for most purposes like
|
||||
* string and INI processing, ZIP extracting, Base64 encoding/decoding, JSON encoding/decoding
|
||||
* and so forth.
|
||||
* If this directive is enabled, then all built-in Jx9 functions are omitted from the build.
|
||||
* Note that special functions such as db_create(), db_store(), db_fetch(), etc. are not omitted
|
||||
* from the build and are not affected by this directive.
|
||||
*
|
||||
* JX9_ENABLE_MATH_FUNC
|
||||
* If this directive is enabled, built-in math functions such as sqrt(), abs(), log(), ceil(), etc.
|
||||
* are included in the build. Note that you may need to link UnQLite with the math library in same
|
||||
* Linux/BSD flavor (i.e: -lm).
|
||||
*
|
||||
* JX9_DISABLE_DISK_IO
|
||||
* If this directive is enabled, built-in VFS functions such as chdir(), mkdir(), chroot(), unlink(),
|
||||
* sleep(), etc. are omitted from the build.
|
||||
*
|
||||
* UNQLITE_ENABLE_JX9_HASH_IO
|
||||
* If this directive is enabled, built-in hash functions such as md5(), sha1(), md5_file(), crc32(), etc.
|
||||
* are included in the build.
|
||||
*/
|
||||
/* Symisc public definitions */
|
||||
#if !defined(SYMISC_STANDARD_DEFS)
|
||||
#define SYMISC_STANDARD_DEFS
|
||||
#if defined (_WIN32) || defined (WIN32) || defined(__MINGW32__) || defined (_MSC_VER) || defined (_WIN32_WCE)
|
||||
/* Windows Systems */
|
||||
#if !defined(__WINNT__)
|
||||
#define __WINNT__
|
||||
#endif
|
||||
/*
|
||||
* Determine if we are dealing with WindowsCE - which has a much
|
||||
* reduced API.
|
||||
*/
|
||||
#if defined(_WIN32_WCE)
|
||||
#ifndef __WIN_CE__
|
||||
#define __WIN_CE__
|
||||
#endif /* __WIN_CE__ */
|
||||
#endif /* _WIN32_WCE */
|
||||
#else
|
||||
/*
|
||||
* By default we will assume that we are compiling on a UNIX systems.
|
||||
* Otherwise the OS_OTHER directive must be defined.
|
||||
*/
|
||||
#if !defined(OS_OTHER)
|
||||
#if !defined(__UNIXES__)
|
||||
#define __UNIXES__
|
||||
#endif /* __UNIXES__ */
|
||||
#else
|
||||
#endif /* OS_OTHER */
|
||||
#endif /* __WINNT__/__UNIXES__ */
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef signed __int64 sxi64; /* 64 bits(8 bytes) signed int64 */
|
||||
typedef unsigned __int64 sxu64; /* 64 bits(8 bytes) unsigned int64 */
|
||||
#else
|
||||
typedef signed long long int sxi64; /* 64 bits(8 bytes) signed int64 */
|
||||
typedef unsigned long long int sxu64; /* 64 bits(8 bytes) unsigned int64 */
|
||||
#endif /* _MSC_VER */
|
||||
/* Signature of the consumer routine */
|
||||
typedef int (*ProcConsumer)(const void *, unsigned int, void *);
|
||||
/* Forward reference */
|
||||
typedef struct SyMutexMethods SyMutexMethods;
|
||||
typedef struct SyMemMethods SyMemMethods;
|
||||
typedef struct SyString SyString;
|
||||
typedef struct syiovec syiovec;
|
||||
typedef struct SyMutex SyMutex;
|
||||
typedef struct Sytm Sytm;
|
||||
/* Scatter and gather array. */
|
||||
struct syiovec
|
||||
{
|
||||
#if defined (__WINNT__)
|
||||
/* Same fields type and offset as WSABUF structure defined one winsock2 header */
|
||||
unsigned long nLen;
|
||||
char *pBase;
|
||||
#else
|
||||
void *pBase;
|
||||
unsigned long nLen;
|
||||
#endif
|
||||
};
|
||||
struct SyString
|
||||
{
|
||||
const char *zString; /* Raw string (may not be null terminated) */
|
||||
unsigned int nByte; /* Raw string length */
|
||||
};
|
||||
/* Time structure. */
|
||||
struct Sytm
|
||||
{
|
||||
int tm_sec; /* seconds (0 - 60) */
|
||||
int tm_min; /* minutes (0 - 59) */
|
||||
int tm_hour; /* hours (0 - 23) */
|
||||
int tm_mday; /* day of month (1 - 31) */
|
||||
int tm_mon; /* month of year (0 - 11) */
|
||||
int tm_year; /* year + 1900 */
|
||||
int tm_wday; /* day of week (Sunday = 0) */
|
||||
int tm_yday; /* day of year (0 - 365) */
|
||||
int tm_isdst; /* is summer time in effect? */
|
||||
char *tm_zone; /* abbreviation of timezone name */
|
||||
long tm_gmtoff; /* offset from UTC in seconds */
|
||||
};
|
||||
/* Convert a tm structure (struct tm *) found in <time.h> to a Sytm structure */
|
||||
#define STRUCT_TM_TO_SYTM(pTM, pSYTM) \
|
||||
(pSYTM)->tm_hour = (pTM)->tm_hour;\
|
||||
(pSYTM)->tm_min = (pTM)->tm_min;\
|
||||
(pSYTM)->tm_sec = (pTM)->tm_sec;\
|
||||
(pSYTM)->tm_mon = (pTM)->tm_mon;\
|
||||
(pSYTM)->tm_mday = (pTM)->tm_mday;\
|
||||
(pSYTM)->tm_year = (pTM)->tm_year + 1900;\
|
||||
(pSYTM)->tm_yday = (pTM)->tm_yday;\
|
||||
(pSYTM)->tm_wday = (pTM)->tm_wday;\
|
||||
(pSYTM)->tm_isdst = (pTM)->tm_isdst;\
|
||||
(pSYTM)->tm_gmtoff = 0;\
|
||||
(pSYTM)->tm_zone = 0;
|
||||
|
||||
/* Convert a SYSTEMTIME structure (LPSYSTEMTIME: Windows Systems only ) to a Sytm structure */
|
||||
#define SYSTEMTIME_TO_SYTM(pSYSTIME, pSYTM) \
|
||||
(pSYTM)->tm_hour = (pSYSTIME)->wHour;\
|
||||
(pSYTM)->tm_min = (pSYSTIME)->wMinute;\
|
||||
(pSYTM)->tm_sec = (pSYSTIME)->wSecond;\
|
||||
(pSYTM)->tm_mon = (pSYSTIME)->wMonth - 1;\
|
||||
(pSYTM)->tm_mday = (pSYSTIME)->wDay;\
|
||||
(pSYTM)->tm_year = (pSYSTIME)->wYear;\
|
||||
(pSYTM)->tm_yday = 0;\
|
||||
(pSYTM)->tm_wday = (pSYSTIME)->wDayOfWeek;\
|
||||
(pSYTM)->tm_gmtoff = 0;\
|
||||
(pSYTM)->tm_isdst = -1;\
|
||||
(pSYTM)->tm_zone = 0;
|
||||
|
||||
/* Dynamic memory allocation methods. */
|
||||
struct SyMemMethods
|
||||
{
|
||||
void * (*xAlloc)(unsigned int); /* [Required:] Allocate a memory chunk */
|
||||
void * (*xRealloc)(void *, unsigned int); /* [Required:] Re-allocate a memory chunk */
|
||||
void (*xFree)(void *); /* [Required:] Release a memory chunk */
|
||||
unsigned int (*xChunkSize)(void *); /* [Optional:] Return chunk size */
|
||||
int (*xInit)(void *); /* [Optional:] Initialization callback */
|
||||
void (*xRelease)(void *); /* [Optional:] Release callback */
|
||||
void *pUserData; /* [Optional:] First argument to xInit() and xRelease() */
|
||||
};
|
||||
/* Out of memory callback signature. */
|
||||
typedef int (*ProcMemError)(void *);
|
||||
/* Mutex methods. */
|
||||
struct SyMutexMethods
|
||||
{
|
||||
int (*xGlobalInit)(void); /* [Optional:] Global mutex initialization */
|
||||
void (*xGlobalRelease)(void); /* [Optional:] Global Release callback () */
|
||||
SyMutex * (*xNew)(int); /* [Required:] Request a new mutex */
|
||||
void (*xRelease)(SyMutex *); /* [Optional:] Release a mutex */
|
||||
void (*xEnter)(SyMutex *); /* [Required:] Enter mutex */
|
||||
int (*xTryEnter)(SyMutex *); /* [Optional:] Try to enter a mutex */
|
||||
void (*xLeave)(SyMutex *); /* [Required:] Leave a locked mutex */
|
||||
};
|
||||
#if defined (_MSC_VER) || defined (__MINGW32__) || defined (__GNUC__) && defined (__declspec)
|
||||
#define SX_APIIMPORT __declspec(dllimport)
|
||||
#define SX_APIEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define SX_APIIMPORT
|
||||
#define SX_APIEXPORT
|
||||
#endif
|
||||
/* Standard return values from Symisc public interfaces */
|
||||
#define SXRET_OK 0 /* Not an error */
|
||||
#define SXERR_MEM (-1) /* Out of memory */
|
||||
#define SXERR_IO (-2) /* IO error */
|
||||
#define SXERR_EMPTY (-3) /* Empty field */
|
||||
#define SXERR_LOCKED (-4) /* Locked operation */
|
||||
#define SXERR_ORANGE (-5) /* Out of range value */
|
||||
#define SXERR_NOTFOUND (-6) /* Item not found */
|
||||
#define SXERR_LIMIT (-7) /* Limit reached */
|
||||
#define SXERR_MORE (-8) /* Need more input */
|
||||
#define SXERR_INVALID (-9) /* Invalid parameter */
|
||||
#define SXERR_ABORT (-10) /* User callback request an operation abort */
|
||||
#define SXERR_EXISTS (-11) /* Item exists */
|
||||
#define SXERR_SYNTAX (-12) /* Syntax error */
|
||||
#define SXERR_UNKNOWN (-13) /* Unknown error */
|
||||
#define SXERR_BUSY (-14) /* Busy operation */
|
||||
#define SXERR_OVERFLOW (-15) /* Stack or buffer overflow */
|
||||
#define SXERR_WILLBLOCK (-16) /* Operation will block */
|
||||
#define SXERR_NOTIMPLEMENTED (-17) /* Operation not implemented */
|
||||
#define SXERR_EOF (-18) /* End of input */
|
||||
#define SXERR_PERM (-19) /* Permission error */
|
||||
#define SXERR_NOOP (-20) /* No-op */
|
||||
#define SXERR_FORMAT (-21) /* Invalid format */
|
||||
#define SXERR_NEXT (-22) /* Not an error */
|
||||
#define SXERR_OS (-23) /* System call return an error */
|
||||
#define SXERR_CORRUPT (-24) /* Corrupted pointer */
|
||||
#define SXERR_CONTINUE (-25) /* Not an error: Operation in progress */
|
||||
#define SXERR_NOMATCH (-26) /* No match */
|
||||
#define SXERR_RESET (-27) /* Operation reset */
|
||||
#define SXERR_DONE (-28) /* Not an error */
|
||||
#define SXERR_SHORT (-29) /* Buffer too short */
|
||||
#define SXERR_PATH (-30) /* Path error */
|
||||
#define SXERR_TIMEOUT (-31) /* Timeout */
|
||||
#define SXERR_BIG (-32) /* Too big for processing */
|
||||
#define SXERR_RETRY (-33) /* Retry your call */
|
||||
#define SXERR_IGNORE (-63) /* Ignore */
|
||||
#endif /* SYMISC_PUBLIC_DEFS */
|
||||
/*
|
||||
* Marker for exported interfaces.
|
||||
*/
|
||||
#define UNQLITE_APIEXPORT SX_APIEXPORT
|
||||
/*
|
||||
* If compiling for a processor that lacks floating point
|
||||
* support, substitute integer for floating-point.
|
||||
*/
|
||||
#ifdef UNQLITE_OMIT_FLOATING_POINT
|
||||
typedef sxi64 uqlite_real;
|
||||
#else
|
||||
typedef double unqlite_real;
|
||||
#endif
|
||||
typedef sxi64 unqlite_int64;
|
||||
/* Standard UnQLite return values */
|
||||
#define UNQLITE_OK SXRET_OK /* Successful result */
|
||||
/* Beginning of error codes */
|
||||
#define UNQLITE_NOMEM SXERR_MEM /* Out of memory */
|
||||
#define UNQLITE_ABORT SXERR_ABORT /* Another thread have released this instance */
|
||||
#define UNQLITE_IOERR SXERR_IO /* IO error */
|
||||
#define UNQLITE_CORRUPT SXERR_CORRUPT /* Corrupt pointer */
|
||||
#define UNQLITE_LOCKED SXERR_LOCKED /* Forbidden Operation */
|
||||
#define UNQLITE_BUSY SXERR_BUSY /* The database file is locked */
|
||||
#define UNQLITE_DONE SXERR_DONE /* Operation done */
|
||||
#define UNQLITE_PERM SXERR_PERM /* Permission error */
|
||||
#define UNQLITE_NOTIMPLEMENTED SXERR_NOTIMPLEMENTED /* Method not implemented by the underlying Key/Value storage engine */
|
||||
#define UNQLITE_NOTFOUND SXERR_NOTFOUND /* No such record */
|
||||
#define UNQLITE_NOOP SXERR_NOOP /* No such method */
|
||||
#define UNQLITE_INVALID SXERR_INVALID /* Invalid parameter */
|
||||
#define UNQLITE_EOF SXERR_EOF /* End Of Input */
|
||||
#define UNQLITE_UNKNOWN SXERR_UNKNOWN /* Unknown configuration option */
|
||||
#define UNQLITE_LIMIT SXERR_LIMIT /* Database limit reached */
|
||||
#define UNQLITE_EXISTS SXERR_EXISTS /* Record exists */
|
||||
#define UNQLITE_EMPTY SXERR_EMPTY /* Empty record */
|
||||
#define UNQLITE_COMPILE_ERR (-70) /* Compilation error */
|
||||
#define UNQLITE_VM_ERR (-71) /* Virtual machine error */
|
||||
#define UNQLITE_FULL (-73) /* Full database (unlikely) */
|
||||
#define UNQLITE_CANTOPEN (-74) /* Unable to open the database file */
|
||||
#define UNQLITE_READ_ONLY (-75) /* Read only Key/Value storage engine */
|
||||
#define UNQLITE_LOCKERR (-76) /* Locking protocol error */
|
||||
/* end-of-error-codes */
|
||||
/*
|
||||
* Database Handle Configuration Commands.
|
||||
*
|
||||
* The following set of constants are the available configuration verbs that can
|
||||
* be used by the host-application to configure an UnQLite database handle.
|
||||
* These constants must be passed as the second argument to [unqlite_config()].
|
||||
*
|
||||
* Each options require a variable number of arguments.
|
||||
* The [unqlite_config()] interface will return UNQLITE_OK on success, any other
|
||||
* return value indicates failure.
|
||||
* For a full discussion on the configuration verbs and their expected
|
||||
* parameters, please refer to this page:
|
||||
* http://unqlite.org/c_api/unqlite_config.html
|
||||
*/
|
||||
#define UNQLITE_CONFIG_JX9_ERR_LOG 1 /* TWO ARGUMENTS: const char **pzBuf, int *pLen */
|
||||
#define UNQLITE_CONFIG_MAX_PAGE_CACHE 2 /* ONE ARGUMENT: int nMaxPage */
|
||||
#define UNQLITE_CONFIG_ERR_LOG 3 /* TWO ARGUMENTS: const char **pzBuf, int *pLen */
|
||||
#define UNQLITE_CONFIG_KV_ENGINE 4 /* ONE ARGUMENT: const char *zKvName */
|
||||
#define UNQLITE_CONFIG_DISABLE_AUTO_COMMIT 5 /* NO ARGUMENTS */
|
||||
#define UNQLITE_CONFIG_GET_KV_NAME 6 /* ONE ARGUMENT: const char **pzPtr */
|
||||
/*
|
||||
* UnQLite/Jx9 Virtual Machine Configuration Commands.
|
||||
*
|
||||
* The following set of constants are the available configuration verbs that can
|
||||
* be used by the host-application to configure the Jx9 (Via UnQLite) Virtual machine.
|
||||
* These constants must be passed as the second argument to the [unqlite_vm_config()]
|
||||
* interface.
|
||||
* Each options require a variable number of arguments.
|
||||
* The [unqlite_vm_config()] interface will return UNQLITE_OK on success, any other return
|
||||
* value indicates failure.
|
||||
* There are many options but the most importants are: UNQLITE_VM_CONFIG_OUTPUT which install
|
||||
* a VM output consumer callback, UNQLITE_VM_CONFIG_HTTP_REQUEST which parse and register
|
||||
* a HTTP request and UNQLITE_VM_CONFIG_ARGV_ENTRY which populate the $argv array.
|
||||
* For a full discussion on the configuration verbs and their expected parameters, please
|
||||
* refer to this page:
|
||||
* http://unqlite.org/c_api/unqlite_vm_config.html
|
||||
*/
|
||||
#define UNQLITE_VM_CONFIG_OUTPUT 1 /* TWO ARGUMENTS: int (*xConsumer)(const void *pOut, unsigned int nLen, void *pUserData), void *pUserData */
|
||||
#define UNQLITE_VM_CONFIG_IMPORT_PATH 2 /* ONE ARGUMENT: const char *zIncludePath */
|
||||
#define UNQLITE_VM_CONFIG_ERR_REPORT 3 /* NO ARGUMENTS: Report all run-time errors in the VM output */
|
||||
#define UNQLITE_VM_CONFIG_RECURSION_DEPTH 4 /* ONE ARGUMENT: int nMaxDepth */
|
||||
#define UNQLITE_VM_OUTPUT_LENGTH 5 /* ONE ARGUMENT: unsigned int *pLength */
|
||||
#define UNQLITE_VM_CONFIG_CREATE_VAR 6 /* TWO ARGUMENTS: const char *zName, unqlite_value *pValue */
|
||||
#define UNQLITE_VM_CONFIG_HTTP_REQUEST 7 /* TWO ARGUMENTS: const char *zRawRequest, int nRequestLength */
|
||||
#define UNQLITE_VM_CONFIG_SERVER_ATTR 8 /* THREE ARGUMENTS: const char *zKey, const char *zValue, int nLen */
|
||||
#define UNQLITE_VM_CONFIG_ENV_ATTR 9 /* THREE ARGUMENTS: const char *zKey, const char *zValue, int nLen */
|
||||
#define UNQLITE_VM_CONFIG_EXEC_VALUE 10 /* ONE ARGUMENT: unqlite_value **ppValue */
|
||||
#define UNQLITE_VM_CONFIG_IO_STREAM 11 /* ONE ARGUMENT: const unqlite_io_stream *pStream */
|
||||
#define UNQLITE_VM_CONFIG_ARGV_ENTRY 12 /* ONE ARGUMENT: const char *zValue */
|
||||
#define UNQLITE_VM_CONFIG_EXTRACT_OUTPUT 13 /* TWO ARGUMENTS: const void **ppOut, unsigned int *pOutputLen */
|
||||
/*
|
||||
* Storage engine configuration commands.
|
||||
*
|
||||
* The following set of constants are the available configuration verbs that can
|
||||
* be used by the host-application to configure the underlying storage engine (i.e Hash, B+tree, R+tree).
|
||||
* These constants must be passed as the first argument to [unqlite_kv_config()].
|
||||
* Each options require a variable number of arguments.
|
||||
* The [unqlite_kv_config()] interface will return UNQLITE_OK on success, any other return
|
||||
* value indicates failure.
|
||||
* For a full discussion on the configuration verbs and their expected parameters, please
|
||||
* refer to this page:
|
||||
* http://unqlite.org/c_api/unqlite_kv_config.html
|
||||
*/
|
||||
#define UNQLITE_KV_CONFIG_HASH_FUNC 1 /* ONE ARGUMENT: unsigned int (*xHash)(const void *,unsigned int) */
|
||||
#define UNQLITE_KV_CONFIG_CMP_FUNC 2 /* ONE ARGUMENT: int (*xCmp)(const void *,const void *,unsigned int) */
|
||||
/*
|
||||
* Global Library Configuration Commands.
|
||||
*
|
||||
* The following set of constants are the available configuration verbs that can
|
||||
* be used by the host-application to configure the whole library.
|
||||
* These constants must be passed as the first argument to [unqlite_lib_config()].
|
||||
*
|
||||
* Each options require a variable number of arguments.
|
||||
* The [unqlite_lib_config()] interface will return UNQLITE_OK on success, any other return
|
||||
* value indicates failure.
|
||||
* Notes:
|
||||
* The default configuration is recommended for most applications and so the call to
|
||||
* [unqlite_lib_config()] is usually not necessary. It is provided to support rare
|
||||
* applications with unusual needs.
|
||||
* The [unqlite_lib_config()] interface is not threadsafe. The application must insure that
|
||||
* no other [unqlite_*()] interfaces are invoked by other threads while [unqlite_lib_config()]
|
||||
* is running. Furthermore, [unqlite_lib_config()] may only be invoked prior to library
|
||||
* initialization using [unqlite_lib_init()] or [unqlite_init()] or after shutdown
|
||||
* by [unqlite_lib_shutdown()]. If [unqlite_lib_config()] is called after [unqlite_lib_init()]
|
||||
* or [unqlite_init()] and before [unqlite_lib_shutdown()] then it will return UNQLITE_LOCKED.
|
||||
* For a full discussion on the configuration verbs and their expected parameters, please
|
||||
* refer to this page:
|
||||
* http://unqlite.org/c_api/unqlite_lib.html
|
||||
*/
|
||||
#define UNQLITE_LIB_CONFIG_USER_MALLOC 1 /* ONE ARGUMENT: const SyMemMethods *pMemMethods */
|
||||
#define UNQLITE_LIB_CONFIG_MEM_ERR_CALLBACK 2 /* TWO ARGUMENTS: int (*xMemError)(void *), void *pUserData */
|
||||
#define UNQLITE_LIB_CONFIG_USER_MUTEX 3 /* ONE ARGUMENT: const SyMutexMethods *pMutexMethods */
|
||||
#define UNQLITE_LIB_CONFIG_THREAD_LEVEL_SINGLE 4 /* NO ARGUMENTS */
|
||||
#define UNQLITE_LIB_CONFIG_THREAD_LEVEL_MULTI 5 /* NO ARGUMENTS */
|
||||
#define UNQLITE_LIB_CONFIG_VFS 6 /* ONE ARGUMENT: const unqlite_vfs *pVfs */
|
||||
#define UNQLITE_LIB_CONFIG_STORAGE_ENGINE 7 /* ONE ARGUMENT: unqlite_kv_methods *pStorage */
|
||||
#define UNQLITE_LIB_CONFIG_PAGE_SIZE 8 /* ONE ARGUMENT: int iPageSize */
|
||||
/*
|
||||
* These bit values are intended for use in the 3rd parameter to the [unqlite_open()] interface
|
||||
* and in the 4th parameter to the xOpen method of the [unqlite_vfs] object.
|
||||
*/
|
||||
#define UNQLITE_OPEN_READONLY 0x00000001 /* Read only mode. Ok for [unqlite_open] */
|
||||
#define UNQLITE_OPEN_READWRITE 0x00000002 /* Ok for [unqlite_open] */
|
||||
#define UNQLITE_OPEN_CREATE 0x00000004 /* Ok for [unqlite_open] */
|
||||
#define UNQLITE_OPEN_EXCLUSIVE 0x00000008 /* VFS only */
|
||||
#define UNQLITE_OPEN_TEMP_DB 0x00000010 /* VFS only */
|
||||
#define UNQLITE_OPEN_NOMUTEX 0x00000020 /* Ok for [unqlite_open] */
|
||||
#define UNQLITE_OPEN_OMIT_JOURNALING 0x00000040 /* Omit journaling for this database. Ok for [unqlite_open] */
|
||||
#define UNQLITE_OPEN_IN_MEMORY 0x00000080 /* An in memory database. Ok for [unqlite_open]*/
|
||||
#define UNQLITE_OPEN_MMAP 0x00000100 /* Obtain a memory view of the whole file. Ok for [unqlite_open] */
|
||||
/*
|
||||
* Synchronization Type Flags
|
||||
*
|
||||
* When UnQLite invokes the xSync() method of an [unqlite_io_methods] object it uses
|
||||
* a combination of these integer values as the second argument.
|
||||
*
|
||||
* When the UNQLITE_SYNC_DATAONLY flag is used, it means that the sync operation only
|
||||
* needs to flush data to mass storage. Inode information need not be flushed.
|
||||
* If the lower four bits of the flag equal UNQLITE_SYNC_NORMAL, that means to use normal
|
||||
* fsync() semantics. If the lower four bits equal UNQLITE_SYNC_FULL, that means to use
|
||||
* Mac OS X style fullsync instead of fsync().
|
||||
*/
|
||||
#define UNQLITE_SYNC_NORMAL 0x00002
|
||||
#define UNQLITE_SYNC_FULL 0x00003
|
||||
#define UNQLITE_SYNC_DATAONLY 0x00010
|
||||
/*
|
||||
* File Locking Levels
|
||||
*
|
||||
* UnQLite uses one of these integer values as the second
|
||||
* argument to calls it makes to the xLock() and xUnlock() methods
|
||||
* of an [unqlite_io_methods] object.
|
||||
*/
|
||||
#define UNQLITE_LOCK_NONE 0
|
||||
#define UNQLITE_LOCK_SHARED 1
|
||||
#define UNQLITE_LOCK_RESERVED 2
|
||||
#define UNQLITE_LOCK_PENDING 3
|
||||
#define UNQLITE_LOCK_EXCLUSIVE 4
|
||||
/*
|
||||
* CAPIREF: OS Interface: Open File Handle
|
||||
*
|
||||
* An [unqlite_file] object represents an open file in the [unqlite_vfs] OS interface
|
||||
* layer.
|
||||
* Individual OS interface implementations will want to subclass this object by appending
|
||||
* additional fields for their own use. The pMethods entry is a pointer to an
|
||||
* [unqlite_io_methods] object that defines methods for performing
|
||||
* I/O operations on the open file.
|
||||
*/
|
||||
typedef struct unqlite_file unqlite_file;
|
||||
struct unqlite_file {
|
||||
const unqlite_io_methods *pMethods; /* Methods for an open file. MUST BE FIRST */
|
||||
};
|
||||
/*
|
||||
* CAPIREF: OS Interface: File Methods Object
|
||||
*
|
||||
* Every file opened by the [unqlite_vfs] xOpen method populates an
|
||||
* [unqlite_file] object (or, more commonly, a subclass of the
|
||||
* [unqlite_file] object) with a pointer to an instance of this object.
|
||||
* This object defines the methods used to perform various operations
|
||||
* against the open file represented by the [unqlite_file] object.
|
||||
*
|
||||
* If the xOpen method sets the unqlite_file.pMethods element
|
||||
* to a non-NULL pointer, then the unqlite_io_methods.xClose method
|
||||
* may be invoked even if the xOpen reported that it failed. The
|
||||
* only way to prevent a call to xClose following a failed xOpen
|
||||
* is for the xOpen to set the unqlite_file.pMethods element to NULL.
|
||||
*
|
||||
* The flags argument to xSync may be one of [UNQLITE_SYNC_NORMAL] or
|
||||
* [UNQLITE_SYNC_FULL]. The first choice is the normal fsync().
|
||||
* The second choice is a Mac OS X style fullsync. The [UNQLITE_SYNC_DATAONLY]
|
||||
* flag may be ORed in to indicate that only the data of the file
|
||||
* and not its inode needs to be synced.
|
||||
*
|
||||
* The integer values to xLock() and xUnlock() are one of
|
||||
*
|
||||
* UNQLITE_LOCK_NONE
|
||||
* UNQLITE_LOCK_SHARED
|
||||
* UNQLITE_LOCK_RESERVED
|
||||
* UNQLITE_LOCK_PENDING
|
||||
* UNQLITE_LOCK_EXCLUSIVE
|
||||
*
|
||||
* xLock() increases the lock. xUnlock() decreases the lock.
|
||||
* The xCheckReservedLock() method checks whether any database connection,
|
||||
* either in this process or in some other process, is holding a RESERVED,
|
||||
* PENDING, or EXCLUSIVE lock on the file. It returns true if such a lock exists
|
||||
* and false otherwise.
|
||||
*
|
||||
* The xSectorSize() method returns the sector size of the device that underlies
|
||||
* the file. The sector size is the minimum write that can be performed without
|
||||
* disturbing other bytes in the file.
|
||||
*
|
||||
*/
|
||||
struct unqlite_io_methods {
|
||||
int iVersion; /* Structure version number (currently 1) */
|
||||
int (*xClose)(unqlite_file*);
|
||||
int (*xRead)(unqlite_file*, void*, unqlite_int64 iAmt, unqlite_int64 iOfst);
|
||||
int (*xWrite)(unqlite_file*, const void*, unqlite_int64 iAmt, unqlite_int64 iOfst);
|
||||
int (*xTruncate)(unqlite_file*, unqlite_int64 size);
|
||||
int (*xSync)(unqlite_file*, int flags);
|
||||
int (*xFileSize)(unqlite_file*, unqlite_int64 *pSize);
|
||||
int (*xLock)(unqlite_file*, int);
|
||||
int (*xUnlock)(unqlite_file*, int);
|
||||
int (*xCheckReservedLock)(unqlite_file*, int *pResOut);
|
||||
int (*xSectorSize)(unqlite_file*);
|
||||
};
|
||||
/*
|
||||
* CAPIREF: OS Interface Object
|
||||
*
|
||||
* An instance of the unqlite_vfs object defines the interface between
|
||||
* the UnQLite core and the underlying operating system. The "vfs"
|
||||
* in the name of the object stands for "Virtual File System".
|
||||
*
|
||||
* Only a single vfs can be registered within the UnQLite core.
|
||||
* Vfs registration is done using the [unqlite_lib_config()] interface
|
||||
* with a configuration verb set to UNQLITE_LIB_CONFIG_VFS.
|
||||
* Note that Windows and UNIX (Linux, FreeBSD, Solaris, Mac OS X, etc.) users
|
||||
* does not have to worry about registering and installing a vfs since UnQLite
|
||||
* come with a built-in vfs for these platforms that implements most the methods
|
||||
* defined below.
|
||||
*
|
||||
* Clients running on exotic systems (ie: Other than Windows and UNIX systems)
|
||||
* must register their own vfs in order to be able to use the UnQLite library.
|
||||
*
|
||||
* The value of the iVersion field is initially 1 but may be larger in
|
||||
* future versions of UnQLite.
|
||||
*
|
||||
* The szOsFile field is the size of the subclassed [unqlite_file] structure
|
||||
* used by this VFS. mxPathname is the maximum length of a pathname in this VFS.
|
||||
*
|
||||
* At least szOsFile bytes of memory are allocated by UnQLite to hold the [unqlite_file]
|
||||
* structure passed as the third argument to xOpen. The xOpen method does not have to
|
||||
* allocate the structure; it should just fill it in. Note that the xOpen method must
|
||||
* set the unqlite_file.pMethods to either a valid [unqlite_io_methods] object or to NULL.
|
||||
* xOpen must do this even if the open fails. UnQLite expects that the unqlite_file.pMethods
|
||||
* element will be valid after xOpen returns regardless of the success or failure of the
|
||||
* xOpen call.
|
||||
*
|
||||
*/
|
||||
struct unqlite_vfs {
|
||||
const char *zName; /* Name of this virtual file system [i.e: Windows, UNIX, etc.] */
|
||||
int iVersion; /* Structure version number (currently 1) */
|
||||
int szOsFile; /* Size of subclassed unqlite_file */
|
||||
int mxPathname; /* Maximum file pathname length */
|
||||
int (*xOpen)(unqlite_vfs*, const char *zName, unqlite_file*,unsigned int flags);
|
||||
int (*xDelete)(unqlite_vfs*, const char *zName, int syncDir);
|
||||
int (*xAccess)(unqlite_vfs*, const char *zName, int flags, int *pResOut);
|
||||
int (*xFullPathname)(unqlite_vfs*, const char *zName,int buf_len,char *zBuf);
|
||||
int (*xTmpDir)(unqlite_vfs*,char *zBuf,int buf_len);
|
||||
int (*xSleep)(unqlite_vfs*, int microseconds);
|
||||
int (*xCurrentTime)(unqlite_vfs*,Sytm *pOut);
|
||||
int (*xGetLastError)(unqlite_vfs*, int, char *);
|
||||
};
|
||||
/*
|
||||
* Flags for the xAccess VFS method
|
||||
*
|
||||
* These integer constants can be used as the third parameter to
|
||||
* the xAccess method of an [unqlite_vfs] object. They determine
|
||||
* what kind of permissions the xAccess method is looking for.
|
||||
* With UNQLITE_ACCESS_EXISTS, the xAccess method
|
||||
* simply checks whether the file exists.
|
||||
* With UNQLITE_ACCESS_READWRITE, the xAccess method
|
||||
* checks whether the named directory is both readable and writable
|
||||
* (in other words, if files can be added, removed, and renamed within
|
||||
* the directory).
|
||||
* The UNQLITE_ACCESS_READWRITE constant is currently used only by the
|
||||
* [temp_store_directory pragma], though this could change in a future
|
||||
* release of UnQLite.
|
||||
* With UNQLITE_ACCESS_READ, the xAccess method
|
||||
* checks whether the file is readable. The UNQLITE_ACCESS_READ constant is
|
||||
* currently unused, though it might be used in a future release of
|
||||
* UnQLite.
|
||||
*/
|
||||
#define UNQLITE_ACCESS_EXISTS 0
|
||||
#define UNQLITE_ACCESS_READWRITE 1
|
||||
#define UNQLITE_ACCESS_READ 2
|
||||
/*
|
||||
* The type used to represent a page number. The first page in a file
|
||||
* is called page 1. 0 is used to represent "not a page".
|
||||
* A page number is an unsigned 64-bit integer.
|
||||
*/
|
||||
typedef sxu64 pgno;
|
||||
/*
|
||||
* A database disk page is represented by an instance
|
||||
* of the follwoing structure.
|
||||
*/
|
||||
typedef struct unqlite_page unqlite_page;
|
||||
struct unqlite_page
|
||||
{
|
||||
unsigned char *zData; /* Content of this page */
|
||||
void *pUserData; /* Extra content */
|
||||
pgno pgno; /* Page number for this page */
|
||||
};
|
||||
/*
|
||||
* UnQLite handle to the underlying Key/Value Storage Engine (See below).
|
||||
*/
|
||||
typedef void * unqlite_kv_handle;
|
||||
/*
|
||||
* UnQLite pager IO methods.
|
||||
*
|
||||
* An instance of the following structure define the exported methods of the UnQLite pager
|
||||
* to the underlying Key/Value storage engine.
|
||||
*/
|
||||
typedef struct unqlite_kv_io unqlite_kv_io;
|
||||
struct unqlite_kv_io
|
||||
{
|
||||
unqlite_kv_handle pHandle; /* UnQLite handle passed as the first parameter to the
|
||||
* method defined below.
|
||||
*/
|
||||
unqlite_kv_methods *pMethods; /* Underlying storage engine */
|
||||
/* Pager methods */
|
||||
int (*xGet)(unqlite_kv_handle,pgno,unqlite_page **);
|
||||
int (*xLookup)(unqlite_kv_handle,pgno,unqlite_page **);
|
||||
int (*xNew)(unqlite_kv_handle,unqlite_page **);
|
||||
int (*xWrite)(unqlite_page *);
|
||||
int (*xDontWrite)(unqlite_page *);
|
||||
int (*xDontJournal)(unqlite_page *);
|
||||
int (*xDontMkHot)(unqlite_page *);
|
||||
int (*xPageRef)(unqlite_page *);
|
||||
int (*xPageUnref)(unqlite_page *);
|
||||
int (*xPageSize)(unqlite_kv_handle);
|
||||
int (*xReadOnly)(unqlite_kv_handle);
|
||||
unsigned char * (*xTmpPage)(unqlite_kv_handle);
|
||||
void (*xSetUnpin)(unqlite_kv_handle,void (*xPageUnpin)(void *));
|
||||
void (*xSetReload)(unqlite_kv_handle,void (*xPageReload)(void *));
|
||||
void (*xErr)(unqlite_kv_handle,const char *);
|
||||
};
|
||||
/*
|
||||
* Key/Value Storage Engine Cursor Object
|
||||
*
|
||||
* An instance of a subclass of the following object defines a cursor
|
||||
* used to scan through a key-value storage engine.
|
||||
*/
|
||||
typedef struct unqlite_kv_cursor unqlite_kv_cursor;
|
||||
struct unqlite_kv_cursor
|
||||
{
|
||||
unqlite_kv_engine *pStore; /* Must be first */
|
||||
/* Subclasses will typically add additional fields */
|
||||
};
|
||||
/*
|
||||
* Possible seek positions.
|
||||
*/
|
||||
#define UNQLITE_CURSOR_MATCH_EXACT 1
|
||||
#define UNQLITE_CURSOR_MATCH_LE 2
|
||||
#define UNQLITE_CURSOR_MATCH_GE 3
|
||||
/*
|
||||
* Key/Value Storage Engine.
|
||||
*
|
||||
* A Key-Value storage engine is defined by an instance of the following
|
||||
* object.
|
||||
* UnQLite works with run-time interchangeable storage engines (i.e. Hash, B+Tree, R+Tree, LSM, etc.).
|
||||
* The storage engine works with key/value pairs where both the key
|
||||
* and the value are byte arrays of arbitrary length and with no restrictions on content.
|
||||
* UnQLite come with two built-in KV storage engine: A Virtual Linear Hash (VLH) storage
|
||||
* engine is used for persistent on-disk databases with O(1) lookup time and an in-memory
|
||||
* hash-table or Red-black tree storage engine is used for in-memory databases.
|
||||
* Future versions of UnQLite might add other built-in storage engines (i.e. LSM).
|
||||
* Registration of a Key/Value storage engine at run-time is done via [unqlite_lib_config()]
|
||||
* with a configuration verb set to UNQLITE_LIB_CONFIG_STORAGE_ENGINE.
|
||||
*/
|
||||
struct unqlite_kv_engine
|
||||
{
|
||||
const unqlite_kv_io *pIo; /* IO methods: MUST be first */
|
||||
/* Subclasses will typically add additional fields */
|
||||
};
|
||||
/*
|
||||
* Key/Value Storage Engine Virtual Method Table.
|
||||
*
|
||||
* Key/Value storage engine methods is defined by an instance of the following
|
||||
* object.
|
||||
* Registration of a Key/Value storage engine at run-time is done via [unqlite_lib_config()]
|
||||
* with a configuration verb set to UNQLITE_LIB_CONFIG_STORAGE_ENGINE.
|
||||
*/
|
||||
struct unqlite_kv_methods
|
||||
{
|
||||
const char *zName; /* Storage engine name [i.e. Hash, B+tree, LSM, R-tree, Mem, etc.]*/
|
||||
int szKv; /* 'unqlite_kv_engine' subclass size */
|
||||
int szCursor; /* 'unqlite_kv_cursor' subclass size */
|
||||
int iVersion; /* Structure version, currently 1 */
|
||||
/* Storage engine methods */
|
||||
int (*xInit)(unqlite_kv_engine *,int iPageSize);
|
||||
void (*xRelease)(unqlite_kv_engine *);
|
||||
int (*xConfig)(unqlite_kv_engine *,int op,va_list ap);
|
||||
int (*xOpen)(unqlite_kv_engine *,pgno);
|
||||
int (*xReplace)(
|
||||
unqlite_kv_engine *,
|
||||
const void *pKey,int nKeyLen,
|
||||
const void *pData,unqlite_int64 nDataLen
|
||||
);
|
||||
int (*xAppend)(
|
||||
unqlite_kv_engine *,
|
||||
const void *pKey,int nKeyLen,
|
||||
const void *pData,unqlite_int64 nDataLen
|
||||
);
|
||||
void (*xCursorInit)(unqlite_kv_cursor *);
|
||||
int (*xSeek)(unqlite_kv_cursor *,const void *pKey,int nByte,int iPos); /* Mandatory */
|
||||
int (*xFirst)(unqlite_kv_cursor *);
|
||||
int (*xLast)(unqlite_kv_cursor *);
|
||||
int (*xValid)(unqlite_kv_cursor *);
|
||||
int (*xNext)(unqlite_kv_cursor *);
|
||||
int (*xPrev)(unqlite_kv_cursor *);
|
||||
int (*xDelete)(unqlite_kv_cursor *);
|
||||
int (*xKeyLength)(unqlite_kv_cursor *,int *);
|
||||
int (*xKey)(unqlite_kv_cursor *,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
|
||||
int (*xDataLength)(unqlite_kv_cursor *,unqlite_int64 *);
|
||||
int (*xData)(unqlite_kv_cursor *,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
|
||||
void (*xReset)(unqlite_kv_cursor *);
|
||||
void (*xCursorRelease)(unqlite_kv_cursor *);
|
||||
};
|
||||
/*
|
||||
* UnQLite journal file suffix.
|
||||
*/
|
||||
#ifndef UNQLITE_JOURNAL_FILE_SUFFIX
|
||||
#define UNQLITE_JOURNAL_FILE_SUFFIX "_unqlite_journal"
|
||||
#endif
|
||||
/*
|
||||
* Call Context - Error Message Serverity Level.
|
||||
*
|
||||
* The following constans are the allowed severity level that can
|
||||
* passed as the second argument to the [unqlite_context_throw_error()] or
|
||||
* [unqlite_context_throw_error_format()] interfaces.
|
||||
* Refer to the official documentation for additional information.
|
||||
*/
|
||||
#define UNQLITE_CTX_ERR 1 /* Call context error such as unexpected number of arguments, invalid types and so on. */
|
||||
#define UNQLITE_CTX_WARNING 2 /* Call context Warning */
|
||||
#define UNQLITE_CTX_NOTICE 3 /* Call context Notice */
|
||||
/*
|
||||
* C-API-REF: Please refer to the official documentation for interfaces
|
||||
* purpose and expected parameters.
|
||||
*/
|
||||
|
||||
/* Database Engine Handle */
|
||||
UNQLITE_APIEXPORT int unqlite_open(unqlite **ppDB,const char *zFilename,unsigned int iMode);
|
||||
UNQLITE_APIEXPORT int unqlite_config(unqlite *pDb,int nOp,...);
|
||||
UNQLITE_APIEXPORT int unqlite_close(unqlite *pDb);
|
||||
|
||||
|
||||
/* Key/Value (KV) Store Interfaces */
|
||||
UNQLITE_APIEXPORT int unqlite_kv_store(unqlite *pDb,const void *pKey,int nKeyLen,const void *pData,unqlite_int64 nDataLen);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_append(unqlite *pDb,const void *pKey,int nKeyLen,const void *pData,unqlite_int64 nDataLen);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_store_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_append_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_fetch(unqlite *pDb,const void *pKey,int nKeyLen,void *pBuf,unqlite_int64 /* in|out */*pBufLen);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_fetch_callback(unqlite *pDb,const void *pKey,
|
||||
int nKeyLen,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_delete(unqlite *pDb,const void *pKey,int nKeyLen);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_config(unqlite *pDb,int iOp,...);
|
||||
|
||||
/* Document (JSON) Store Interfaces powered by the Jx9 Scripting Language */
|
||||
UNQLITE_APIEXPORT int unqlite_compile(unqlite *pDb,const char *zJx9,int nByte,unqlite_vm **ppOut);
|
||||
UNQLITE_APIEXPORT int unqlite_compile_file(unqlite *pDb,const char *zPath,unqlite_vm **ppOut);
|
||||
UNQLITE_APIEXPORT int unqlite_vm_config(unqlite_vm *pVm,int iOp,...);
|
||||
UNQLITE_APIEXPORT int unqlite_vm_exec(unqlite_vm *pVm);
|
||||
UNQLITE_APIEXPORT int unqlite_vm_reset(unqlite_vm *pVm);
|
||||
UNQLITE_APIEXPORT int unqlite_vm_release(unqlite_vm *pVm);
|
||||
UNQLITE_APIEXPORT int unqlite_vm_dump(unqlite_vm *pVm, int (*xConsumer)(const void *, unsigned int, void *), void *pUserData);
|
||||
UNQLITE_APIEXPORT unqlite_value * unqlite_vm_extract_variable(unqlite_vm *pVm,const char *zVarname);
|
||||
|
||||
/* Cursor Iterator Interfaces */
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_init(unqlite *pDb,unqlite_kv_cursor **ppOut);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_release(unqlite *pDb,unqlite_kv_cursor *pCur);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_seek(unqlite_kv_cursor *pCursor,const void *pKey,int nKeyLen,int iPos);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_first_entry(unqlite_kv_cursor *pCursor);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_last_entry(unqlite_kv_cursor *pCursor);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_valid_entry(unqlite_kv_cursor *pCursor);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_next_entry(unqlite_kv_cursor *pCursor);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_prev_entry(unqlite_kv_cursor *pCursor);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_key(unqlite_kv_cursor *pCursor,void *pBuf,int *pnByte);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_key_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_data(unqlite_kv_cursor *pCursor,void *pBuf,unqlite_int64 *pnData);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_data_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_delete_entry(unqlite_kv_cursor *pCursor);
|
||||
UNQLITE_APIEXPORT int unqlite_kv_cursor_reset(unqlite_kv_cursor *pCursor);
|
||||
|
||||
/* Manual Transaction Manager */
|
||||
UNQLITE_APIEXPORT int unqlite_begin(unqlite *pDb);
|
||||
UNQLITE_APIEXPORT int unqlite_commit(unqlite *pDb);
|
||||
UNQLITE_APIEXPORT int unqlite_rollback(unqlite *pDb);
|
||||
|
||||
/* Utility interfaces */
|
||||
UNQLITE_APIEXPORT int unqlite_util_load_mmaped_file(const char *zFile,void **ppMap,unqlite_int64 *pFileSize);
|
||||
UNQLITE_APIEXPORT int unqlite_util_release_mmaped_file(void *pMap,unqlite_int64 iFileSize);
|
||||
UNQLITE_APIEXPORT int unqlite_util_random_string(unqlite *pDb,char *zBuf,unsigned int buf_size);
|
||||
UNQLITE_APIEXPORT unsigned int unqlite_util_random_num(unqlite *pDb);
|
||||
|
||||
/* In-process extending interfaces */
|
||||
UNQLITE_APIEXPORT int unqlite_create_function(unqlite_vm *pVm,const char *zName,int (*xFunc)(unqlite_context *,int,unqlite_value **),void *pUserData);
|
||||
UNQLITE_APIEXPORT int unqlite_delete_function(unqlite_vm *pVm, const char *zName);
|
||||
UNQLITE_APIEXPORT int unqlite_create_constant(unqlite_vm *pVm,const char *zName,void (*xExpand)(unqlite_value *, void *),void *pUserData);
|
||||
UNQLITE_APIEXPORT int unqlite_delete_constant(unqlite_vm *pVm, const char *zName);
|
||||
|
||||
/* On Demand Object allocation interfaces */
|
||||
UNQLITE_APIEXPORT unqlite_value * unqlite_vm_new_scalar(unqlite_vm *pVm);
|
||||
UNQLITE_APIEXPORT unqlite_value * unqlite_vm_new_array(unqlite_vm *pVm);
|
||||
UNQLITE_APIEXPORT int unqlite_vm_release_value(unqlite_vm *pVm,unqlite_value *pValue);
|
||||
UNQLITE_APIEXPORT unqlite_value * unqlite_context_new_scalar(unqlite_context *pCtx);
|
||||
UNQLITE_APIEXPORT unqlite_value * unqlite_context_new_array(unqlite_context *pCtx);
|
||||
UNQLITE_APIEXPORT void unqlite_context_release_value(unqlite_context *pCtx,unqlite_value *pValue);
|
||||
|
||||
/* Dynamically Typed Value Object Management Interfaces */
|
||||
UNQLITE_APIEXPORT int unqlite_value_int(unqlite_value *pVal, int iValue);
|
||||
UNQLITE_APIEXPORT int unqlite_value_int64(unqlite_value *pVal, unqlite_int64 iValue);
|
||||
UNQLITE_APIEXPORT int unqlite_value_bool(unqlite_value *pVal, int iBool);
|
||||
UNQLITE_APIEXPORT int unqlite_value_null(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_double(unqlite_value *pVal, double Value);
|
||||
UNQLITE_APIEXPORT int unqlite_value_string(unqlite_value *pVal, const char *zString, int nLen);
|
||||
UNQLITE_APIEXPORT int unqlite_value_string_format(unqlite_value *pVal, const char *zFormat,...);
|
||||
UNQLITE_APIEXPORT int unqlite_value_reset_string_cursor(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_resource(unqlite_value *pVal, void *pUserData);
|
||||
UNQLITE_APIEXPORT int unqlite_value_release(unqlite_value *pVal);
|
||||
|
||||
/* Foreign Function Parameter Values */
|
||||
UNQLITE_APIEXPORT int unqlite_value_to_int(unqlite_value *pValue);
|
||||
UNQLITE_APIEXPORT int unqlite_value_to_bool(unqlite_value *pValue);
|
||||
UNQLITE_APIEXPORT unqlite_int64 unqlite_value_to_int64(unqlite_value *pValue);
|
||||
UNQLITE_APIEXPORT double unqlite_value_to_double(unqlite_value *pValue);
|
||||
UNQLITE_APIEXPORT const char * unqlite_value_to_string(unqlite_value *pValue, int *pLen);
|
||||
UNQLITE_APIEXPORT void * unqlite_value_to_resource(unqlite_value *pValue);
|
||||
UNQLITE_APIEXPORT int unqlite_value_compare(unqlite_value *pLeft, unqlite_value *pRight, int bStrict);
|
||||
|
||||
/* Setting The Result Of A Foreign Function */
|
||||
UNQLITE_APIEXPORT int unqlite_result_int(unqlite_context *pCtx, int iValue);
|
||||
UNQLITE_APIEXPORT int unqlite_result_int64(unqlite_context *pCtx, unqlite_int64 iValue);
|
||||
UNQLITE_APIEXPORT int unqlite_result_bool(unqlite_context *pCtx, int iBool);
|
||||
UNQLITE_APIEXPORT int unqlite_result_double(unqlite_context *pCtx, double Value);
|
||||
UNQLITE_APIEXPORT int unqlite_result_null(unqlite_context *pCtx);
|
||||
UNQLITE_APIEXPORT int unqlite_result_string(unqlite_context *pCtx, const char *zString, int nLen);
|
||||
UNQLITE_APIEXPORT int unqlite_result_string_format(unqlite_context *pCtx, const char *zFormat, ...);
|
||||
UNQLITE_APIEXPORT int unqlite_result_value(unqlite_context *pCtx, unqlite_value *pValue);
|
||||
UNQLITE_APIEXPORT int unqlite_result_resource(unqlite_context *pCtx, void *pUserData);
|
||||
|
||||
/* Dynamically Typed Value Object Query Interfaces */
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_int(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_float(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_bool(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_string(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_null(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_numeric(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_callable(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_scalar(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_json_array(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_json_object(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_resource(unqlite_value *pVal);
|
||||
UNQLITE_APIEXPORT int unqlite_value_is_empty(unqlite_value *pVal);
|
||||
|
||||
/* JSON Array/Object Management Interfaces */
|
||||
UNQLITE_APIEXPORT unqlite_value * unqlite_array_fetch(unqlite_value *pArray, const char *zKey, int nByte);
|
||||
UNQLITE_APIEXPORT int unqlite_array_walk(unqlite_value *pArray, int (*xWalk)(unqlite_value *, unqlite_value *, void *), void *pUserData);
|
||||
UNQLITE_APIEXPORT int unqlite_array_add_elem(unqlite_value *pArray, unqlite_value *pKey, unqlite_value *pValue);
|
||||
UNQLITE_APIEXPORT int unqlite_array_add_strkey_elem(unqlite_value *pArray, const char *zKey, unqlite_value *pValue);
|
||||
UNQLITE_APIEXPORT int unqlite_array_count(unqlite_value *pArray);
|
||||
|
||||
/* Call Context Handling Interfaces */
|
||||
UNQLITE_APIEXPORT int unqlite_context_output(unqlite_context *pCtx, const char *zString, int nLen);
|
||||
UNQLITE_APIEXPORT int unqlite_context_output_format(unqlite_context *pCtx,const char *zFormat, ...);
|
||||
UNQLITE_APIEXPORT int unqlite_context_throw_error(unqlite_context *pCtx, int iErr, const char *zErr);
|
||||
UNQLITE_APIEXPORT int unqlite_context_throw_error_format(unqlite_context *pCtx, int iErr, const char *zFormat, ...);
|
||||
UNQLITE_APIEXPORT unsigned int unqlite_context_random_num(unqlite_context *pCtx);
|
||||
UNQLITE_APIEXPORT int unqlite_context_random_string(unqlite_context *pCtx, char *zBuf, int nBuflen);
|
||||
UNQLITE_APIEXPORT void * unqlite_context_user_data(unqlite_context *pCtx);
|
||||
UNQLITE_APIEXPORT int unqlite_context_push_aux_data(unqlite_context *pCtx, void *pUserData);
|
||||
UNQLITE_APIEXPORT void * unqlite_context_peek_aux_data(unqlite_context *pCtx);
|
||||
UNQLITE_APIEXPORT unsigned int unqlite_context_result_buf_length(unqlite_context *pCtx);
|
||||
UNQLITE_APIEXPORT const char * unqlite_function_name(unqlite_context *pCtx);
|
||||
|
||||
/* Call Context Memory Management Interfaces */
|
||||
UNQLITE_APIEXPORT void * unqlite_context_alloc_chunk(unqlite_context *pCtx,unsigned int nByte,int ZeroChunk,int AutoRelease);
|
||||
UNQLITE_APIEXPORT void * unqlite_context_realloc_chunk(unqlite_context *pCtx,void *pChunk,unsigned int nByte);
|
||||
UNQLITE_APIEXPORT void unqlite_context_free_chunk(unqlite_context *pCtx,void *pChunk);
|
||||
|
||||
/* Global Library Management Interfaces */
|
||||
UNQLITE_APIEXPORT int unqlite_lib_config(int nConfigOp,...);
|
||||
UNQLITE_APIEXPORT int unqlite_lib_init(void);
|
||||
UNQLITE_APIEXPORT int unqlite_lib_shutdown(void);
|
||||
UNQLITE_APIEXPORT int unqlite_lib_is_threadsafe(void);
|
||||
UNQLITE_APIEXPORT const char * unqlite_lib_version(void);
|
||||
UNQLITE_APIEXPORT const char * unqlite_lib_signature(void);
|
||||
UNQLITE_APIEXPORT const char * unqlite_lib_ident(void);
|
||||
UNQLITE_APIEXPORT const char * unqlite_lib_copyright(void);
|
||||
|
||||
#endif /* _UNQLITE_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,11 @@ testbuild_SOURCES = testbuild.c tap.c
|
||||
testbuild_CFLAGS = $(AM_CFLAGS)
|
||||
testbuild_LDADD = $(TEST_LDADD)
|
||||
|
||||
check_PROGRAMS += bladec
|
||||
bladec_SOURCES = bladec.c tap.c
|
||||
bladec_CFLAGS = $(AM_CFLAGS)
|
||||
bladec_LDADD = $(TEST_LDADD)
|
||||
|
||||
|
||||
TESTS=$(check_PROGRAMS)
|
||||
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
#include "blade.h"
|
||||
#include "tap.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define STDIO_FD(_fs) _fileno(_fs)
|
||||
#define READ(_fd, _buffer, _count) _read(_fd, _buffer, _count)
|
||||
#else
|
||||
#define STDIO_FD(_fs) fileno(_fs)
|
||||
#define READ(_fd, _buffer, _count) read(_fd, _buffer, _count)
|
||||
#endif
|
||||
|
||||
#define CONSOLE_INPUT_MAX 512
|
||||
|
||||
ks_bool_t g_shutdown = KS_FALSE;
|
||||
char g_console_input[CONSOLE_INPUT_MAX];
|
||||
size_t g_console_input_length = 0;
|
||||
size_t g_console_input_eol = 0;
|
||||
|
||||
void loop(blade_handle_t *bh);
|
||||
void process_console_input(blade_handle_t *bh, char *line);
|
||||
|
||||
typedef void (*command_callback)(blade_handle_t *bh, char *args);
|
||||
|
||||
struct command_def_s {
|
||||
const char *cmd;
|
||||
command_callback callback;
|
||||
};
|
||||
|
||||
void command_test(blade_handle_t *bh, char *args);
|
||||
void command_quit(blade_handle_t *bh, char *args);
|
||||
void command_myid(blade_handle_t *bh, char *args);
|
||||
void command_bind(blade_handle_t *bh, char *args);
|
||||
void command_store(blade_handle_t *bh, char *args);
|
||||
void command_fetch(blade_handle_t *bh, char *args);
|
||||
|
||||
static const struct command_def_s command_defs[] = {
|
||||
{ "test", command_test },
|
||||
{ "quit", command_quit },
|
||||
{ "myid", command_myid },
|
||||
{ "bind", command_bind },
|
||||
{ "store", command_store },
|
||||
{ "fetch", command_fetch },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
blade_handle_t *bh = NULL;
|
||||
const char *nodeid;
|
||||
|
||||
ks_assert(argc >= 2);
|
||||
|
||||
nodeid = argv[1];
|
||||
|
||||
ks_global_set_default_logger(KS_LOG_LEVEL_DEBUG);
|
||||
|
||||
blade_init();
|
||||
|
||||
blade_handle_create(&bh, NULL, NULL, nodeid);
|
||||
|
||||
blade_handle_autoroute(bh, KS_TRUE, KS_DHT_DEFAULT_PORT);
|
||||
|
||||
loop(bh);
|
||||
|
||||
blade_handle_destroy(&bh);
|
||||
|
||||
blade_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void buffer_console_input(void)
|
||||
{
|
||||
ssize_t bytes = 0;
|
||||
struct pollfd poll[1];
|
||||
poll[0].fd = STDIO_FD(stdin);
|
||||
poll[0].events = POLLIN | POLLERR;
|
||||
|
||||
if (ks_poll(poll, 1, 1) > 0) {
|
||||
if (poll[0].revents & POLLIN) {
|
||||
if ((bytes = READ(poll[0].fd, g_console_input + g_console_input_length, CONSOLE_INPUT_MAX - g_console_input_length)) <= 0) {
|
||||
// @todo error
|
||||
return;
|
||||
}
|
||||
g_console_input_length += bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop(blade_handle_t *bh)
|
||||
{
|
||||
while (!g_shutdown) {
|
||||
ks_bool_t eol = KS_FALSE;
|
||||
buffer_console_input();
|
||||
|
||||
for (; g_console_input_eol < g_console_input_length; ++g_console_input_eol) {
|
||||
char c = g_console_input[g_console_input_eol];
|
||||
if (c == '\r' || c == '\n') {
|
||||
eol = KS_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (eol) {
|
||||
g_console_input[g_console_input_eol] = '\0';
|
||||
process_console_input(bh, g_console_input);
|
||||
g_console_input_eol++;
|
||||
for (; g_console_input_eol < g_console_input_length; ++g_console_input_eol) {
|
||||
char c = g_console_input[g_console_input_eol];
|
||||
if (c != '\r' && c != '\n') break;
|
||||
}
|
||||
if (g_console_input_eol == g_console_input_length) g_console_input_eol = g_console_input_length = 0;
|
||||
else {
|
||||
memcpy(g_console_input, g_console_input + g_console_input_eol, g_console_input_length - g_console_input_eol);
|
||||
g_console_input_length -= g_console_input_eol;
|
||||
g_console_input_eol = 0;
|
||||
}
|
||||
}
|
||||
if (g_console_input_length == CONSOLE_INPUT_MAX) {
|
||||
// @todo lines must not exceed 512 bytes, treat as error and ignore buffer until next new line?
|
||||
ks_assert(0);
|
||||
}
|
||||
blade_handle_pulse(bh, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void parse_argument(char **input, char **arg, char terminator)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
ks_assert(input);
|
||||
ks_assert(*input);
|
||||
ks_assert(arg);
|
||||
|
||||
tmp = *input;
|
||||
*arg = tmp;
|
||||
|
||||
while (*tmp && *tmp != terminator) ++tmp;
|
||||
if (*tmp == terminator) {
|
||||
*tmp = '\0';
|
||||
++tmp;
|
||||
}
|
||||
*input = tmp;
|
||||
}
|
||||
|
||||
void process_console_input(blade_handle_t *bh, char *line)
|
||||
{
|
||||
char *args = line;
|
||||
char *cmd = NULL;
|
||||
ks_bool_t found = KS_FALSE;
|
||||
|
||||
ks_log(KS_LOG_DEBUG, "Output: %s\n", line);
|
||||
|
||||
parse_argument(&args, &cmd, ' ');
|
||||
|
||||
ks_log(KS_LOG_DEBUG, "Command: %s, Args: %s\n", cmd, args);
|
||||
|
||||
for (int32_t index = 0; command_defs[index].cmd; ++index) {
|
||||
if (!strcmp(command_defs[index].cmd, cmd)) {
|
||||
found = KS_TRUE;
|
||||
command_defs[index].callback(bh, args);
|
||||
}
|
||||
}
|
||||
if (!found) ks_log(KS_LOG_INFO, "Command '%s' unknown.\n", cmd);
|
||||
}
|
||||
|
||||
void command_test(blade_handle_t *bh, char *args)
|
||||
{
|
||||
ks_log(KS_LOG_DEBUG, "Hello World!\n");
|
||||
}
|
||||
|
||||
void command_quit(blade_handle_t *bh, char *args)
|
||||
{
|
||||
ks_assert(bh);
|
||||
ks_assert(args);
|
||||
|
||||
ks_log(KS_LOG_DEBUG, "Shutting down\n");
|
||||
g_shutdown = KS_TRUE;
|
||||
}
|
||||
|
||||
void command_myid(blade_handle_t *bh, char *args)
|
||||
{
|
||||
char buf[KS_DHT_NODEID_SIZE * 2 + 1];
|
||||
|
||||
ks_assert(bh);
|
||||
ks_assert(args);
|
||||
|
||||
blade_handle_myid(bh, buf);
|
||||
|
||||
ks_log(KS_LOG_INFO, "%s\n", buf);
|
||||
}
|
||||
|
||||
void command_bind(blade_handle_t *bh, char *args)
|
||||
{
|
||||
char *ip = NULL;
|
||||
char *port = NULL;
|
||||
ks_port_t p;
|
||||
|
||||
ks_assert(args);
|
||||
|
||||
parse_argument(&args, &ip, ' ');
|
||||
parse_argument(&args, &port, ' ');
|
||||
|
||||
p = atoi(port); // @todo use strtol for error handling
|
||||
|
||||
blade_handle_bind(bh, ip, p, NULL);
|
||||
}
|
||||
|
||||
void command_store(blade_handle_t *bh, char *args)
|
||||
{
|
||||
char *key;
|
||||
char *data;
|
||||
|
||||
ks_assert(args);
|
||||
|
||||
blade_handle_datastore_start(bh);
|
||||
|
||||
parse_argument(&args, &key, ' ');
|
||||
parse_argument(&args, &data, ' ');
|
||||
|
||||
blade_handle_datastore_store(bh, key, strlen(key), data, strlen(data) + 1);
|
||||
}
|
||||
|
||||
ks_bool_t blade_datastore_fetch_callback(blade_datastore_t *bds, const void *data, uint32_t data_length, void *userdata)
|
||||
{
|
||||
ks_log(KS_LOG_INFO, "%s\n", data);
|
||||
return KS_TRUE;
|
||||
}
|
||||
|
||||
void command_fetch(blade_handle_t *bh, char *args)
|
||||
{
|
||||
char *key;
|
||||
|
||||
ks_assert(args);
|
||||
|
||||
blade_handle_datastore_start(bh);
|
||||
|
||||
parse_argument(&args, &key, ' ');
|
||||
|
||||
blade_handle_datastore_fetch(bh, blade_datastore_fetch_callback, key, strlen(key), bh);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ int main(void)
|
||||
|
||||
plan(1);
|
||||
|
||||
status = blade_handle_create(&bh, NULL);
|
||||
status = blade_handle_create(&bh, NULL, NULL);
|
||||
status = blade_handle_destroy(&bh);
|
||||
|
||||
ok(status == KS_STATUS_SUCCESS);
|
||||
|
||||
@@ -45,8 +45,22 @@ Only use // style-comments on tempory comments that will probably be removed eve
|
||||
Add the emacs/vi comment to the bottom of every file.
|
||||
Use Doxygen for function args.
|
||||
Tabs not spaces.
|
||||
Use flags as bitwise when possible, use arrays if going beyond 32
|
||||
Typedef all enums using UPPER_CASE notation for the values
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
SOME_FLAG_X = (1 << 0),
|
||||
SOME_FLAG_Y = (1 << 1)
|
||||
} some_flag_type_t;
|
||||
|
||||
typedef enum {
|
||||
SOME_TYPE_X = 1,
|
||||
SOME_TYPE_Y,
|
||||
SOME_TYPE_Z
|
||||
} some_type_t;
|
||||
|
||||
|
||||
KS_DECLARE(ks_status_t) function_example(somedata_t **data, ks_pool_t *pool)
|
||||
{
|
||||
int var = 3, x = 0;
|
||||
@@ -54,7 +68,7 @@ KS_DECLARE(ks_status_t) function_example(somedata_t **data, ks_pool_t *pool)
|
||||
if (!pool) return KS_STATUS_FAIL;
|
||||
|
||||
for (x = 0; x < 100; x++) {
|
||||
var = += x;
|
||||
var += x;
|
||||
}
|
||||
|
||||
if (var > 20) {
|
||||
|
||||
@@ -3,16 +3,19 @@ EXTRA_DIST =
|
||||
SUBDIRS = . test
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
|
||||
AM_CFLAGS += -I$(top_srcdir)/src -I$(top_srcdir)/src/include -I$(top_srcdir)/crypt
|
||||
AM_CFLAGS += -I$(top_srcdir)/src -I$(top_srcdir)/src/include -I$(top_srcdir)/crypt -O0
|
||||
AM_CPPFLAGS = $(AM_CFLAGS)
|
||||
|
||||
lib_LTLIBRARIES = libks.la
|
||||
libks_la_SOURCES = src/ks.c src/ks_string.c src/ks_json.c src/ks_thread.c src/ks_thread_pool.c src/ks_mutex.c src/ks_config.c
|
||||
libks_la_SOURCES += src/ks_log.c src/ks_socket.c src/ks_buffer.c src/ks_pool.c src/simclist.c
|
||||
libks_la_SOURCES += src/ks_time.c src/ks_printf.c src/ks_hash.c src/ks_q.c src/ks_dso.c src/ks_dht.c
|
||||
libks_la_SOURCES += src/ks_time.c src/ks_printf.c src/ks_hash.c src/ks_q.c src/ks_dso.c # src/ks_dht.c
|
||||
libks_la_SOURCES += src/ks_ssl.c src/kws.c src/ks_rng.c
|
||||
libks_la_SOURCES += src/utp/utp_api.cpp src/utp/utp_callbacks.cpp src/utp/utp_hash.cpp src/utp/utp_internal.cpp
|
||||
libks_la_SOURCES += src/utp/utp_packedsockaddr.cpp src/utp/utp_utils.cpp src/ks_bencode.c
|
||||
libks_la_SOURCES += src/dht/ks_dht.c src/dht/ks_dht_datagram.c src/dht/ks_dht_endpoint.c src/dht/ks_dht_message.c src/dht/ks_dht_transaction.c
|
||||
libks_la_SOURCES += src/dht/ks_dht_job.c src/dht/ks_dht_search.c src/dht/ks_dht_publish.c src/dht/ks_dht_distribute.c src/dht/ks_dht_storageitem.c
|
||||
libks_la_SOURCES += src/dht/ks_dht_bucket.c
|
||||
libks_la_SOURCES += crypt/aeskey.c crypt/aestab.c crypt/sha2.c crypt/twofish.c crypt/aes_modes.c crypt/aescrypt.c crypt/twofish_cfb.c
|
||||
#aes.h aescpp.h brg_endian.h aesopt.h aestab.h brg_types.h sha2.h twofish.h
|
||||
|
||||
@@ -24,7 +27,7 @@ library_includedir = $(prefix)/include
|
||||
library_include_HEADERS = src/include/ks_config.h src/include/ks.h src/include/ks_threadmutex.h src/include/ks_json.h src/include/ks_buffer.h
|
||||
library_include_HEADERS += src/include/ks_thread_pool.h
|
||||
library_include_HEADERS += src/include/ks_pool.h src/include/simclist.h src/include/ks_time.h src/include/ks_q.h src/include/ks_socket.h
|
||||
library_include_HEADERS += src/include/ks_dso.h src/include/ks_dht.h src/include/ks_platform.h src/include/ks_types.h # src/include/ks_rng.h
|
||||
library_include_HEADERS += src/include/ks_dso.h src/include/ks_platform.h src/include/ks_types.h # src/include/ks_rng.h src/include/ks_dht.h
|
||||
library_include_HEADERS += src/include/ks_printf.h src/include/ks_hash.h src/include/ks_ssl.h src/include/kws.h
|
||||
library_include_HEADERS += src/utp/utp_internal.h src/utp/utp.h src/utp/utp_types.h src/utp/utp_callbacks.h src/utp/utp_templates.h
|
||||
library_include_HEADERS += src/utp/utp_hash.h src/utp/utp_packedsockaddr.h src/utp/utp_utils.h src/include/ks_utp.h
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,60 @@
|
||||
#include "ks_dht.h"
|
||||
#include "ks_dht-int.h"
|
||||
#include "sodium.h"
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_datagram_create(ks_dht_datagram_t **datagram,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_t *dht,
|
||||
ks_dht_endpoint_t *endpoint,
|
||||
const ks_sockaddr_t *raddr)
|
||||
{
|
||||
ks_dht_datagram_t *dg;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(datagram);
|
||||
ks_assert(pool);
|
||||
ks_assert(dht);
|
||||
ks_assert(endpoint);
|
||||
ks_assert(raddr);
|
||||
ks_assert(raddr->family == AF_INET || raddr->family == AF_INET6);
|
||||
|
||||
*datagram = dg = ks_pool_alloc(pool, sizeof(ks_dht_datagram_t));
|
||||
ks_assert(dg);
|
||||
|
||||
dg->pool = pool;
|
||||
dg->dht = dht;
|
||||
dg->endpoint = endpoint;
|
||||
dg->raddr = *raddr;
|
||||
|
||||
memcpy(dg->buffer, dht->recv_buffer, dht->recv_buffer_length);
|
||||
dg->buffer_length = dht->recv_buffer_length;
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
ks_dht_datagram_destroy(datagram);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_datagram_destroy(ks_dht_datagram_t **datagram)
|
||||
{
|
||||
ks_dht_datagram_t *dg;
|
||||
|
||||
ks_assert(datagram);
|
||||
ks_assert(*datagram);
|
||||
|
||||
dg = *datagram;
|
||||
|
||||
ks_pool_free(dg->pool, datagram);
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "ks_dht.h"
|
||||
#include "ks_dht-int.h"
|
||||
#include "sodium.h"
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_distribute_create(ks_dht_distribute_t **distribute,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_storageitem_callback_t callback,
|
||||
void *data,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item)
|
||||
{
|
||||
ks_dht_distribute_t *d;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(distribute);
|
||||
ks_assert(pool);
|
||||
ks_assert(cas >= 0);
|
||||
ks_assert(item);
|
||||
|
||||
*distribute = d = ks_pool_alloc(pool, sizeof(ks_dht_distribute_t));
|
||||
ks_assert(d);
|
||||
|
||||
d->pool = pool;
|
||||
|
||||
d->callback = callback;
|
||||
d->data = data;
|
||||
ks_mutex_create(&d->mutex, KS_MUTEX_FLAG_DEFAULT, d->pool);
|
||||
ks_assert(d->mutex);
|
||||
d->cas = cas;
|
||||
d->item = item;
|
||||
|
||||
ks_dht_storageitem_reference(d->item);
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
if (d) ks_dht_distribute_destroy(distribute);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_distribute_destroy(ks_dht_distribute_t **distribute)
|
||||
{
|
||||
ks_dht_distribute_t *d;
|
||||
|
||||
ks_assert(distribute);
|
||||
ks_assert(*distribute);
|
||||
|
||||
d = *distribute;
|
||||
|
||||
if (d->mutex) ks_mutex_destroy(&d->mutex);
|
||||
ks_dht_storageitem_dereference(d->item);
|
||||
|
||||
ks_pool_free(d->pool, distribute);
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "ks_dht.h"
|
||||
#include "ks_dht-int.h"
|
||||
#include "sodium.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_endpoint_create(ks_dht_endpoint_t **endpoint,
|
||||
ks_pool_t *pool,
|
||||
const ks_sockaddr_t *addr,
|
||||
ks_socket_t sock)
|
||||
{
|
||||
ks_dht_endpoint_t *ep;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(endpoint);
|
||||
ks_assert(pool);
|
||||
ks_assert(addr);
|
||||
ks_assert(addr->family == AF_INET || addr->family == AF_INET6);
|
||||
|
||||
*endpoint = ep = ks_pool_alloc(pool, sizeof(ks_dht_endpoint_t));
|
||||
ks_assert(ep);
|
||||
|
||||
ep->pool = pool;
|
||||
ep->addr = *addr;
|
||||
ep->sock = sock;
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
if (ep) ks_dht_endpoint_destroy(endpoint);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_endpoint_destroy(ks_dht_endpoint_t **endpoint)
|
||||
{
|
||||
ks_dht_endpoint_t *ep;
|
||||
|
||||
ks_assert(endpoint);
|
||||
ks_assert(*endpoint);
|
||||
|
||||
ep = *endpoint;
|
||||
|
||||
if (ep->sock != KS_SOCK_INVALID) ks_socket_close(&ep->sock);
|
||||
|
||||
ks_pool_free(ep->pool, endpoint);
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -0,0 +1,136 @@
|
||||
#include "ks_dht.h"
|
||||
#include "ks_dht-int.h"
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_job_create(ks_dht_job_t **job,
|
||||
ks_pool_t *pool,
|
||||
const ks_sockaddr_t *raddr,
|
||||
int32_t attempts,
|
||||
void *data)
|
||||
{
|
||||
ks_dht_job_t *j;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(job);
|
||||
ks_assert(pool);
|
||||
//ks_assert(dht);
|
||||
ks_assert(attempts > 0 && attempts <= 10);
|
||||
|
||||
*job = j = ks_pool_alloc(pool, sizeof(ks_dht_job_t));
|
||||
ks_assert(j);
|
||||
|
||||
j->pool = pool;
|
||||
j->state = KS_DHT_JOB_STATE_QUERYING;
|
||||
if (raddr) j->raddr = *raddr;
|
||||
j->attempts = attempts;
|
||||
j->data = data;
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
if (j) ks_dht_job_destroy(job);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_job_build_ping(ks_dht_job_t *job, ks_dht_job_callback_t query_callback, ks_dht_job_callback_t finish_callback)
|
||||
{
|
||||
ks_assert(job);
|
||||
ks_assert(query_callback);
|
||||
|
||||
job->query_callback = query_callback;
|
||||
job->finish_callback = finish_callback;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_job_build_findnode(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback,
|
||||
ks_dht_nodeid_t *target)
|
||||
{
|
||||
ks_assert(job);
|
||||
ks_assert(query_callback);
|
||||
ks_assert(target);
|
||||
|
||||
job->query_callback = query_callback;
|
||||
job->finish_callback = finish_callback;
|
||||
job->query_target = *target;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_job_build_get(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length)
|
||||
{
|
||||
ks_assert(job);
|
||||
ks_assert(query_callback);
|
||||
ks_assert(target);
|
||||
|
||||
job->query_callback = query_callback;
|
||||
job->finish_callback = finish_callback;
|
||||
job->query_target = *target;
|
||||
if (salt && salt_length > 0) job->query_salt = ben_blob(salt, salt_length);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_job_build_put(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback,
|
||||
ks_dht_token_t *token,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item)
|
||||
{
|
||||
ks_assert(job);
|
||||
ks_assert(query_callback);
|
||||
ks_assert(token);
|
||||
ks_assert(item);
|
||||
|
||||
job->query_callback = query_callback;
|
||||
job->finish_callback = finish_callback;
|
||||
job->query_token = *token;
|
||||
job->query_cas = cas;
|
||||
job->query_storageitem = item;
|
||||
ks_dht_storageitem_reference(job->query_storageitem);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_job_build_search(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback)
|
||||
{
|
||||
ks_assert(job);
|
||||
ks_assert(query_callback);
|
||||
|
||||
job->query_callback = query_callback;
|
||||
job->finish_callback = finish_callback;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_job_destroy(ks_dht_job_t **job)
|
||||
{
|
||||
ks_dht_job_t *j;
|
||||
|
||||
ks_assert(job);
|
||||
ks_assert(*job);
|
||||
|
||||
j = *job;
|
||||
|
||||
if (j->query_salt) ben_free(j->query_salt);
|
||||
if (j->response_id) ks_dhtrt_release_node(j->response_id);
|
||||
for (int32_t i = 0; i < j->response_nodes_count; ++i) ks_dhtrt_release_node(j->response_nodes[i]);
|
||||
for (int32_t i = 0; i < j->response_nodes6_count; ++i) ks_dhtrt_release_node(j->response_nodes6[i]);
|
||||
|
||||
if (j->query_storageitem) ks_dht_storageitem_dereference(j->query_storageitem);
|
||||
if (j->response_storageitem) ks_dht_storageitem_dereference(j->response_storageitem);
|
||||
|
||||
if (j->error_description) ben_free(j->error_description);
|
||||
|
||||
ks_pool_free(j->pool, job);
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -0,0 +1,122 @@
|
||||
#include "ks_dht.h"
|
||||
#include "ks_dht-int.h"
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_message_create(ks_dht_message_t **message,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_endpoint_t *endpoint,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_bool_t alloc_data)
|
||||
{
|
||||
ks_dht_message_t *m;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(message);
|
||||
ks_assert(pool);
|
||||
|
||||
*message = m = ks_pool_alloc(pool, sizeof(ks_dht_message_t));
|
||||
ks_assert(m);
|
||||
|
||||
m->pool = pool;
|
||||
m->endpoint = endpoint;
|
||||
m->raddr = *raddr;
|
||||
if (alloc_data) {
|
||||
m->data = ben_dict();
|
||||
ks_assert(m->data);
|
||||
}
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
ks_dht_message_destroy(message);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_message_destroy(ks_dht_message_t **message)
|
||||
{
|
||||
ks_dht_message_t *m;
|
||||
|
||||
ks_assert(message);
|
||||
ks_assert(*message);
|
||||
|
||||
m = *message;
|
||||
|
||||
if (m->data) {
|
||||
ben_free(m->data);
|
||||
m->data = NULL;
|
||||
}
|
||||
|
||||
ks_pool_free(m->pool, message);
|
||||
}
|
||||
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_message_parse(ks_dht_message_t *message, const uint8_t *buffer, ks_size_t buffer_length)
|
||||
{
|
||||
struct bencode *t;
|
||||
struct bencode *y;
|
||||
const char *tv;
|
||||
const char *yv;
|
||||
ks_size_t tv_len;
|
||||
ks_size_t yv_len;
|
||||
|
||||
ks_assert(message);
|
||||
ks_assert(message->pool);
|
||||
ks_assert(buffer);
|
||||
ks_assert(!message->data);
|
||||
|
||||
message->data = ben_decode((const void *)buffer, buffer_length);
|
||||
if (!message->data) {
|
||||
ks_log(KS_LOG_DEBUG, "Message cannot be decoded\n");
|
||||
return KS_STATUS_FAIL;
|
||||
}
|
||||
|
||||
ks_log(KS_LOG_DEBUG, "Message decoded\n");
|
||||
ks_log(KS_LOG_DEBUG, "%s\n", ben_print(message->data));
|
||||
|
||||
t = ben_dict_get_by_str(message->data, "t");
|
||||
if (!t) {
|
||||
ks_log(KS_LOG_DEBUG, "Message missing required key 't'\n");
|
||||
return KS_STATUS_FAIL;
|
||||
}
|
||||
|
||||
tv = ben_str_val(t);
|
||||
tv_len = ben_str_len(t);
|
||||
if (tv_len > KS_DHT_MESSAGE_TRANSACTIONID_MAX_SIZE) {
|
||||
ks_log(KS_LOG_DEBUG, "Message 't' value has an unexpectedly large size of %d\n", tv_len);
|
||||
return KS_STATUS_FAIL;
|
||||
}
|
||||
|
||||
memcpy(message->transactionid, tv, tv_len);
|
||||
message->transactionid_length = tv_len;
|
||||
// @todo hex output of transactionid
|
||||
//ks_log(KS_LOG_DEBUG, "Message transaction id is %d\n", message->transactionid);
|
||||
|
||||
y = ben_dict_get_by_str(message->data, "y");
|
||||
if (!y) {
|
||||
ks_log(KS_LOG_DEBUG, "Message missing required key 'y'\n");
|
||||
return KS_STATUS_FAIL;
|
||||
}
|
||||
|
||||
yv = ben_str_val(y);
|
||||
yv_len = ben_str_len(y);
|
||||
if (yv_len >= KS_DHT_MESSAGE_TYPE_MAX_SIZE) {
|
||||
ks_log(KS_LOG_DEBUG, "Message 'y' value has an unexpectedly large size of %d\n", yv_len);
|
||||
return KS_STATUS_FAIL;
|
||||
}
|
||||
|
||||
memcpy(message->type, yv, yv_len);
|
||||
message->type[yv_len] = '\0';
|
||||
//ks_log(KS_LOG_DEBUG, "Message type is '%s'\n", message->type);
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "ks_dht.h"
|
||||
#include "ks_dht-int.h"
|
||||
#include "sodium.h"
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_publish_create(ks_dht_publish_t **publish,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item)
|
||||
{
|
||||
ks_dht_publish_t *p;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(publish);
|
||||
ks_assert(pool);
|
||||
ks_assert(cas >= 0);
|
||||
ks_assert(item);
|
||||
|
||||
*publish = p = ks_pool_alloc(pool, sizeof(ks_dht_publish_t));
|
||||
ks_assert(p);
|
||||
|
||||
p->pool = pool;
|
||||
|
||||
p->callback = callback;
|
||||
p->data = data;
|
||||
p->cas = cas;
|
||||
p->item = item;
|
||||
|
||||
ks_dht_storageitem_reference(p->item);
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
if (p) ks_dht_publish_destroy(publish);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_publish_destroy(ks_dht_publish_t **publish)
|
||||
{
|
||||
ks_dht_publish_t *p;
|
||||
|
||||
ks_assert(publish);
|
||||
ks_assert(*publish);
|
||||
|
||||
p = *publish;
|
||||
|
||||
ks_dht_storageitem_dereference(p->item);
|
||||
|
||||
ks_pool_free(p->pool, publish);
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "ks_dht.h"
|
||||
#include "ks_dht-int.h"
|
||||
#include "sodium.h"
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_search_create(ks_dht_search_t **search,
|
||||
ks_pool_t *pool,
|
||||
ks_dhtrt_routetable_t *table,
|
||||
const ks_dht_nodeid_t *target,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data)
|
||||
{
|
||||
ks_dht_search_t *s;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(search);
|
||||
ks_assert(pool);
|
||||
ks_assert(table);
|
||||
ks_assert(target);
|
||||
|
||||
*search = s = ks_pool_alloc(pool, sizeof(ks_dht_search_t));
|
||||
ks_assert(s);
|
||||
|
||||
s->pool = pool;
|
||||
|
||||
ks_mutex_create(&s->mutex, KS_MUTEX_FLAG_DEFAULT, s->pool);
|
||||
ks_assert(s->mutex);
|
||||
|
||||
s->table = table;
|
||||
memcpy(s->target.id, target->id, KS_DHT_NODEID_SIZE);
|
||||
|
||||
s->callback = callback;
|
||||
s->data = data;
|
||||
|
||||
ks_hash_create(&s->searched, KS_HASH_MODE_ARBITRARY, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, s->pool);
|
||||
ks_assert(s->searched);
|
||||
ks_hash_set_keysize(s->searched, KS_DHT_NODEID_SIZE);
|
||||
|
||||
s->searching = 0;
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
if (s) ks_dht_search_destroy(search);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_search_destroy(ks_dht_search_t **search)
|
||||
{
|
||||
ks_dht_search_t *s;
|
||||
|
||||
ks_assert(search);
|
||||
ks_assert(*search);
|
||||
|
||||
s = *search;
|
||||
|
||||
if (s->searched) ks_hash_destroy(&s->searched);
|
||||
if (s->mutex) ks_mutex_destroy(&s->mutex);
|
||||
|
||||
ks_pool_free(s->pool, search);
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -0,0 +1,214 @@
|
||||
#include "ks_dht.h"
|
||||
#include "ks_dht-int.h"
|
||||
#include "sodium.h"
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_immutable_internal(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
struct bencode *v,
|
||||
ks_bool_t clone_v)
|
||||
{
|
||||
ks_dht_storageitem_t *si;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(item);
|
||||
ks_assert(pool);
|
||||
ks_assert(v);
|
||||
ks_assert(SHA_DIGEST_LENGTH == KS_DHT_NODEID_SIZE);
|
||||
|
||||
*item = si = ks_pool_alloc(pool, sizeof(ks_dht_storageitem_t));
|
||||
ks_assert(si);
|
||||
|
||||
si->pool = pool;
|
||||
si->id = *target;
|
||||
si->mutable = KS_FALSE;
|
||||
si->expiration = ks_time_now() + ((ks_time_t)KS_DHT_STORAGEITEM_EXPIRATION * KS_USEC_PER_SEC);
|
||||
si->keepalive = ks_time_now() + ((ks_time_t)KS_DHT_STORAGEITEM_KEEPALIVE * KS_USEC_PER_SEC);
|
||||
si->v = clone_v ? ben_clone(v) : v;
|
||||
ks_assert(si->v);
|
||||
|
||||
si->refc = 1;
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
if (si) ks_dht_storageitem_destroy(item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_immutable(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *value,
|
||||
ks_size_t value_length)
|
||||
{
|
||||
struct bencode *v = NULL;
|
||||
|
||||
ks_assert(item);
|
||||
ks_assert(pool);
|
||||
ks_assert(value);
|
||||
ks_assert(value_length > 0);
|
||||
ks_assert(SHA_DIGEST_LENGTH == KS_DHT_NODEID_SIZE);
|
||||
|
||||
v = ben_blob(value, value_length);
|
||||
ks_assert(v);
|
||||
|
||||
return ks_dht_storageitem_create_immutable_internal(item, pool, target, v, KS_FALSE);
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_mutable_internal(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
struct bencode *v,
|
||||
ks_bool_t clone_v,
|
||||
ks_dht_storageitem_pkey_t *pk,
|
||||
struct bencode *salt,
|
||||
ks_bool_t clone_salt,
|
||||
int64_t sequence,
|
||||
ks_dht_storageitem_signature_t *signature)
|
||||
{
|
||||
ks_dht_storageitem_t *si;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(item);
|
||||
ks_assert(pool);
|
||||
ks_assert(v);
|
||||
ks_assert(SHA_DIGEST_LENGTH == KS_DHT_NODEID_SIZE);
|
||||
ks_assert(pk);
|
||||
ks_assert(signature);
|
||||
|
||||
*item = si = ks_pool_alloc(pool, sizeof(ks_dht_storageitem_t));
|
||||
ks_assert(si);
|
||||
|
||||
si->pool = pool;
|
||||
si->id = *target;
|
||||
si->mutable = KS_TRUE;
|
||||
si->expiration = ks_time_now() + ((ks_time_t)KS_DHT_STORAGEITEM_EXPIRATION * KS_USEC_PER_SEC);
|
||||
si->keepalive = ks_time_now() + ((ks_time_t)KS_DHT_STORAGEITEM_KEEPALIVE * KS_USEC_PER_SEC);
|
||||
si->v = clone_v ? ben_clone(v) : v;
|
||||
ks_assert(si->v);
|
||||
|
||||
si->refc = 1;
|
||||
|
||||
ks_mutex_create(&si->mutex, KS_MUTEX_FLAG_DEFAULT, si->pool);
|
||||
ks_assert(si->mutex);
|
||||
|
||||
si->pk = *pk;
|
||||
if (salt) {
|
||||
si->salt = clone_salt ? ben_clone(salt) : salt;
|
||||
ks_assert(si->salt);
|
||||
}
|
||||
si->seq = sequence;
|
||||
si->sig = *signature;
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
if (si) ks_dht_storageitem_destroy(item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_mutable(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *value,
|
||||
ks_size_t value_length,
|
||||
ks_dht_storageitem_pkey_t *pk,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length,
|
||||
int64_t sequence,
|
||||
ks_dht_storageitem_signature_t *signature)
|
||||
{
|
||||
struct bencode *v = NULL;
|
||||
struct bencode *s = NULL;
|
||||
|
||||
ks_assert(item);
|
||||
ks_assert(pool);
|
||||
ks_assert(value);
|
||||
ks_assert(value_length > 0);
|
||||
ks_assert(SHA_DIGEST_LENGTH == KS_DHT_NODEID_SIZE);
|
||||
ks_assert(pk);
|
||||
ks_assert(signature);
|
||||
|
||||
v = ben_blob(value, value_length);
|
||||
if (salt && salt_length > 0) s = ben_blob(salt, salt_length);
|
||||
return ks_dht_storageitem_create_mutable_internal(item, pool, target, v, KS_FALSE, pk, s, KS_FALSE, sequence, signature);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_storageitem_update_mutable(ks_dht_storageitem_t *item, struct bencode *v, int64_t sequence, ks_dht_storageitem_signature_t *signature)
|
||||
{
|
||||
ks_assert(item);
|
||||
ks_assert(v);
|
||||
ks_assert(sequence);
|
||||
ks_assert(signature);
|
||||
|
||||
ks_mutex_lock(item->mutex);
|
||||
ben_free(item->v);
|
||||
item->v = ben_clone(v);
|
||||
item->seq = sequence;
|
||||
item->sig = *signature;
|
||||
ks_mutex_unlock(item->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitem_destroy(ks_dht_storageitem_t **item)
|
||||
{
|
||||
ks_dht_storageitem_t *si;
|
||||
|
||||
ks_assert(item);
|
||||
ks_assert(*item);
|
||||
|
||||
si = *item;
|
||||
|
||||
if (si->v) {
|
||||
ben_free(si->v);
|
||||
si->v = NULL;
|
||||
}
|
||||
if (si->mutex) ks_mutex_destroy(&si->mutex);
|
||||
if (si->salt) {
|
||||
ben_free(si->salt);
|
||||
si->salt = NULL;
|
||||
}
|
||||
|
||||
ks_pool_free(si->pool, item);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_storageitem_reference(ks_dht_storageitem_t *item)
|
||||
{
|
||||
ks_assert(item);
|
||||
|
||||
ks_mutex_lock(item->mutex);
|
||||
item->refc++;
|
||||
ks_mutex_unlock(item->mutex);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_storageitem_dereference(ks_dht_storageitem_t *item)
|
||||
{
|
||||
ks_assert(item);
|
||||
|
||||
ks_mutex_lock(item->mutex);
|
||||
item->refc--;
|
||||
ks_mutex_unlock(item->mutex);
|
||||
|
||||
ks_assert(item->refc >= 0);
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_storageitem_callback(ks_dht_storageitem_t *item, ks_dht_storageitem_callback_t callback)
|
||||
{
|
||||
ks_assert(item);
|
||||
|
||||
item->callback = callback;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "ks_dht.h"
|
||||
#include "ks_dht-int.h"
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_transaction_create(ks_dht_transaction_t **transaction,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_job_t *job,
|
||||
uint32_t transactionid,
|
||||
ks_dht_job_callback_t callback)
|
||||
{
|
||||
ks_dht_transaction_t *t;
|
||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||
|
||||
ks_assert(transaction);
|
||||
ks_assert(pool);
|
||||
ks_assert(job);
|
||||
|
||||
*transaction = t = ks_pool_alloc(pool, sizeof(ks_dht_transaction_t));
|
||||
ks_assert(t);
|
||||
|
||||
t->pool = pool;
|
||||
t->job = job;
|
||||
t->transactionid = transactionid;
|
||||
t->callback = callback;
|
||||
t->expiration = ks_time_now() + ((ks_time_t)KS_DHT_TRANSACTION_EXPIRATION * KS_USEC_PER_SEC);
|
||||
|
||||
// done:
|
||||
if (ret != KS_STATUS_SUCCESS) {
|
||||
if (t) ks_dht_transaction_destroy(transaction);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
KS_DECLARE(void) ks_dht_transaction_destroy(ks_dht_transaction_t **transaction)
|
||||
{
|
||||
ks_dht_transaction_t *t;
|
||||
|
||||
ks_assert(transaction);
|
||||
ks_assert(*transaction);
|
||||
|
||||
t = *transaction;
|
||||
|
||||
ks_pool_free(t->pool, transaction);
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
@@ -123,7 +123,7 @@ KS_DECLARE(void) ks_random_string(char *buf, uint16_t len, char *set);
|
||||
#include "ks_time.h"
|
||||
#include "ks_socket.h"
|
||||
#include "ks_dso.h"
|
||||
#include "ks_dht.h"
|
||||
//#include "ks_dht.h"
|
||||
#include "ks_utp.h"
|
||||
#include "simclist.h"
|
||||
#include "ks_ssl.h"
|
||||
|
||||
@@ -0,0 +1,447 @@
|
||||
#ifndef KS_DHT_INT_H
|
||||
#define KS_DHT_INT_H
|
||||
|
||||
#include "ks.h"
|
||||
|
||||
KS_BEGIN_EXTERN_C
|
||||
|
||||
/**
|
||||
* Determines the appropriate endpoint to reach a remote address.
|
||||
* If an endpoint is provided, nothing more needs to be done.
|
||||
* If no endpoint is provided, first it will check for an active endpoint it can route though.
|
||||
* If no active endpoint is available and autorouting is enabled it will attempt to bind a usable endpoint.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param raddr pointer to the remote address
|
||||
* @param endpoint dereferenced in/out pointer to the endpoint, if populated then returns immediately
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, ...
|
||||
* @see ks_ip_route
|
||||
* @see ks_hash_read_unlock
|
||||
* @see ks_addr_set
|
||||
* @see ks_dht_bind
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_autoroute_check(ks_dht_t *dht, const ks_sockaddr_t *raddr, ks_dht_endpoint_t **endpoint);
|
||||
|
||||
/**
|
||||
* Called internally to receive datagrams from endpoints.
|
||||
* Handles datagrams by dispatching each through a threadpool.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param timeout time in ms to wait for an incoming datagram on any endpoint
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_endpoints(ks_dht_t *dht, int32_t timeout);
|
||||
|
||||
/**
|
||||
* Called internally to expire or reannounce storage item data.
|
||||
* Handles reannouncing and purging of expiring storage items.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_storageitems(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Called internally to process job state machine.
|
||||
* Handles completing and purging of finished jobs.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_jobs(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Called internally to send queued messages.
|
||||
* Handles throttling of message sending to ensure system buffers are not overloaded and messages are not dropped.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_send(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Called internally to expire transactions.
|
||||
* Handles purging of expired and finished transactions.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_transactions(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Called internally to expire and cycle tokens.
|
||||
* Handles cycling new secret entropy for token generation.
|
||||
* @param dht pointer to the dht instance
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse_tokens(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
* Converts a ks_dht_nodeid_t into it's hex string representation.
|
||||
* @param id pointer to the nodeid
|
||||
* @param buffer pointer to the buffer able to contain at least (KS_DHT_NODEID_SIZE * 2) + 1 characters
|
||||
* @return The pointer to the front of the populated string buffer
|
||||
*/
|
||||
KS_DECLARE(char *) ks_dht_hex(const uint8_t *data, char *buffer, ks_size_t len);
|
||||
|
||||
/**
|
||||
* Compacts address information as per the DHT specifications.
|
||||
* @param address pointer to the address being compacted from
|
||||
* @param buffer pointer to the buffer containing compacted data
|
||||
* @param buffer_length pointer to the buffer length consumed
|
||||
* @param buffer_size max size of the buffer
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_compact_addressinfo(const ks_sockaddr_t *address,
|
||||
uint8_t *buffer,
|
||||
ks_size_t *buffer_length,
|
||||
ks_size_t buffer_size);
|
||||
|
||||
/**
|
||||
* Expands address information as per the DHT specifications.
|
||||
* @param buffer pointer to the buffer containing compacted data
|
||||
* @param buffer_length pointer to the buffer length consumed
|
||||
* @param buffer_size max size of the buffer
|
||||
* @param address pointer to the address being expanded into
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM, ...
|
||||
* @see ks_addr_set_raw
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_expand_addressinfo(const uint8_t *buffer,
|
||||
ks_size_t *buffer_length,
|
||||
ks_size_t buffer_size,
|
||||
ks_sockaddr_t *address);
|
||||
|
||||
/**
|
||||
* Compacts node information as per the DHT specifications.
|
||||
* Compacts address information after the nodeid.
|
||||
* @param nodeid pointer to the nodeid being compacted from
|
||||
* @param address pointer to the address being compacted from
|
||||
* @param buffer pointer to the buffer containing compacted data
|
||||
* @param buffer_length pointer to the buffer length consumed
|
||||
* @param buffer_size max size of the buffer
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM, ...
|
||||
* @see ks_dht_utility_compact_addressinfo
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_compact_nodeinfo(const ks_dht_nodeid_t *nodeid,
|
||||
const ks_sockaddr_t *address,
|
||||
uint8_t *buffer,
|
||||
ks_size_t *buffer_length,
|
||||
ks_size_t buffer_size);
|
||||
|
||||
/**
|
||||
* Expands address information as per the DHT specifications.
|
||||
* Expands compacted address information after the nodeid.
|
||||
* @param buffer pointer to the buffer containing compacted data
|
||||
* @param buffer_length pointer to the buffer length consumed
|
||||
* @param buffer_size max size of the buffer
|
||||
* @param address pointer to the address being expanded into
|
||||
* @param nodeid pointer to the nodeid being expanded into
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM, ...
|
||||
* @see ks_dht_utility_expand_addressinfo
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_expand_nodeinfo(const uint8_t *buffer,
|
||||
ks_size_t *buffer_length,
|
||||
ks_size_t buffer_size,
|
||||
ks_dht_nodeid_t *nodeid,
|
||||
ks_sockaddr_t *address);
|
||||
|
||||
/**
|
||||
* Extracts a ks_dht_nodeid_t from a bencode dictionary given a string key.
|
||||
* @param args pointer to the bencode dictionary
|
||||
* @param key string key in the bencode dictionary to extract the value from
|
||||
* @param nodeid dereferenced out pointer to the nodeid
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_ARG_INVALID
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_extract_nodeid(struct bencode *args, const char *key, ks_dht_nodeid_t **nodeid);
|
||||
|
||||
/**
|
||||
* Extracts a ks_dht_token_t from a bencode dictionary given a string key.
|
||||
* @param args pointer to the bencode dictionary
|
||||
* @param key string key in the bencode dictionary to extract the value from
|
||||
* @param nodeid dereferenced out pointer to the token
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_ARG_INVALID
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_utility_extract_token(struct bencode *args, const char *key, ks_dht_token_t **token);
|
||||
|
||||
/**
|
||||
* Generates an opaque write token based on a shifting secret value, the remote address and target nodeid of interest.
|
||||
* This token ensures that future operations can be verified to the remote peer and target id requested.
|
||||
* @param secret rotating secret portion of the token hash
|
||||
* @param raddr pointer to the remote address used for the ip and port in the token hash
|
||||
* @param target pointer to the nodeid of the target used for the token hash
|
||||
* @param token pointer to the output token being generated
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_FAIL
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_token_generate(uint32_t secret, const ks_sockaddr_t *raddr, ks_dht_nodeid_t *target, ks_dht_token_t *token);
|
||||
|
||||
/**
|
||||
* Verify an opaque write token matches the provided remote address and target nodeid.
|
||||
* Handles checking against the last two secret values for the token hash.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param raddr pointer to the remote address used for the ip and port in the token hash
|
||||
* @param target pointer to the nodeid of the target used for the token hash
|
||||
* @param token pointer to the input token being compared
|
||||
* @return Either KS_TRUE if verification passes, otherwise KS_FALSE
|
||||
*/
|
||||
KS_DECLARE(ks_bool_t) ks_dht_token_verify(ks_dht_t *dht, const ks_sockaddr_t *raddr, ks_dht_nodeid_t *target, ks_dht_token_t *token);
|
||||
|
||||
/**
|
||||
* Encodes a message for transmission as a UDP datagram and sends it.
|
||||
* Uses the internally tracked local endpoint and remote address to route the UDP datagram.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param message pointer to the message being sent
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, ...
|
||||
* @see ks_socket_sendto
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_send(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
|
||||
/**
|
||||
* Sets up the common parts of a query message.
|
||||
* Determines the local endpoint aware of autorouting, assigns the remote address, generates a transaction, and queues a callback.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param job pointer to the job
|
||||
* @param query string value of the query type, for example "ping"
|
||||
* @param callback callback to be called when response to transaction is received
|
||||
* @param transaction dereferenced out pointer to the allocated transaction, may be NULL to ignore output
|
||||
* @param message dereferenced out pointer to the allocated message
|
||||
* @param args dereferenced out pointer to the allocated bencode args, may be NULL to ignore output
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_FAIL, ...
|
||||
* @see ks_dht_autoroute_check
|
||||
* @see ks_dht_transaction_alloc
|
||||
* @see ks_dht_transaction_init
|
||||
* @see ks_dht_message_alloc
|
||||
* @see ks_dht_message_init
|
||||
* @see ks_dht_message_query
|
||||
* @see ks_hash_insert
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_setup(ks_dht_t *dht,
|
||||
ks_dht_job_t *job,
|
||||
const char *query,
|
||||
ks_dht_job_callback_t callback,
|
||||
ks_dht_transaction_t **transaction,
|
||||
ks_dht_message_t **message,
|
||||
struct bencode **args);
|
||||
|
||||
/**
|
||||
* Sets up the common parts of a response message.
|
||||
* Determines the local endpoint aware of autorouting, assigns the remote address, and assigns the transaction.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param ep pointer to the endpoint, may be NULL to find an endpoint or autoroute one
|
||||
* @param raddr pointer to the remote address
|
||||
* @param transactionid pointer to the buffer containing the transactionid, may be of variable size depending on the querying node
|
||||
* @param transactionid_length length of the transactionid buffer
|
||||
* @param message dereferenced out pointer to the allocated message
|
||||
* @param args dereferenced out pointer to the allocated bencode args, may be NULL to ignore output
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, ...
|
||||
* @see ks_dht_autoroute_check
|
||||
* @see ks_dht_message_alloc
|
||||
* @see ks_dht_message_init
|
||||
* @see ks_dht_message_response
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_response_setup(ks_dht_t *dht,
|
||||
ks_dht_endpoint_t *ep,
|
||||
const ks_sockaddr_t *raddr,
|
||||
uint8_t *transactionid,
|
||||
ks_size_t transactionid_length,
|
||||
ks_dht_message_t **message,
|
||||
struct bencode **args);
|
||||
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_error(ks_dht_t *dht,
|
||||
ks_dht_endpoint_t *ep,
|
||||
const ks_sockaddr_t *raddr,
|
||||
uint8_t *transactionid,
|
||||
ks_size_t transactionid_length,
|
||||
long long errorcode,
|
||||
const char *errorstr);
|
||||
|
||||
KS_DECLARE(void) ks_dht_pulse_jobs(ks_dht_t *dht);
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_ping(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_findnode(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_get(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
KS_DECLARE(ks_status_t) ks_dht_query_put(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
KS_DECLARE(void *)ks_dht_process(ks_thread_t *thread, void *data);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_error(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query_ping(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response_ping(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query_findnode(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response_findnode(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query_get(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response_get(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_query_put(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
KS_DECLARE(ks_status_t) ks_dht_process_response_put(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_datagram_create(ks_dht_datagram_t **datagram,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_t *dht,
|
||||
ks_dht_endpoint_t *endpoint,
|
||||
const ks_sockaddr_t *raddr);
|
||||
KS_DECLARE(void) ks_dht_datagram_destroy(ks_dht_datagram_t **datagram);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_job_create(ks_dht_job_t **job,
|
||||
ks_pool_t *pool,
|
||||
const ks_sockaddr_t *raddr,
|
||||
int32_t attempts,
|
||||
void *data);
|
||||
KS_DECLARE(void) ks_dht_job_build_ping(ks_dht_job_t *job, ks_dht_job_callback_t query_callback, ks_dht_job_callback_t finish_callback);
|
||||
KS_DECLARE(void) ks_dht_job_build_findnode(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback,
|
||||
ks_dht_nodeid_t *target);
|
||||
KS_DECLARE(void) ks_dht_job_build_get(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length);
|
||||
KS_DECLARE(void) ks_dht_job_build_put(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback,
|
||||
ks_dht_token_t *token,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
KS_DECLARE(void) ks_dht_job_build_search(ks_dht_job_t *job,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback);
|
||||
KS_DECLARE(void) ks_dht_job_build_search_findnode(ks_dht_job_t *job,
|
||||
ks_dht_nodeid_t *target,
|
||||
uint32_t family,
|
||||
ks_dht_job_callback_t query_callback,
|
||||
ks_dht_job_callback_t finish_callback);
|
||||
KS_DECLARE(void) ks_dht_job_destroy(ks_dht_job_t **job);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_endpoint_create(ks_dht_endpoint_t **endpoint,
|
||||
ks_pool_t *pool,
|
||||
const ks_sockaddr_t *addr,
|
||||
ks_socket_t sock);
|
||||
KS_DECLARE(void) ks_dht_endpoint_destroy(ks_dht_endpoint_t **endpoint);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_message_create(ks_dht_message_t **message,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_endpoint_t *endpoint,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_bool_t alloc_data);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_message_destroy(ks_dht_message_t **message);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_message_parse(ks_dht_message_t *message, const uint8_t *buffer, ks_size_t buffer_length);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_search_create(ks_dht_search_t **search,
|
||||
ks_pool_t *pool,
|
||||
ks_dhtrt_routetable_t *table,
|
||||
const ks_dht_nodeid_t *target,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data);
|
||||
KS_DECLARE(void) ks_dht_search_destroy(ks_dht_search_t **search);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_publish_create(ks_dht_publish_t **publish,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
KS_DECLARE(void) ks_dht_publish_destroy(ks_dht_publish_t **publish);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_distribute_create(ks_dht_distribute_t **distribute,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_storageitem_callback_t callback,
|
||||
void *data,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
KS_DECLARE(void) ks_dht_distribute_destroy(ks_dht_distribute_t **distribute);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_target_immutable_internal(struct bencode *value, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_target_mutable_internal(ks_dht_storageitem_pkey_t *pk, struct bencode *salt, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_immutable_internal(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
struct bencode *v,
|
||||
ks_bool_t clone_v);
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_immutable(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *value,
|
||||
ks_size_t value_length);
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_mutable_internal(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
struct bencode *v,
|
||||
ks_bool_t clone_v,
|
||||
ks_dht_storageitem_pkey_t *pk,
|
||||
struct bencode *salt,
|
||||
ks_bool_t clone_salt,
|
||||
int64_t sequence,
|
||||
ks_dht_storageitem_signature_t *signature);
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_create_mutable(ks_dht_storageitem_t **item,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *value,
|
||||
ks_size_t value_length,
|
||||
ks_dht_storageitem_pkey_t *pk,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length,
|
||||
int64_t sequence,
|
||||
ks_dht_storageitem_signature_t *signature);
|
||||
KS_DECLARE(void) ks_dht_storageitem_update_mutable(ks_dht_storageitem_t *item, struct bencode *v, int64_t sequence, ks_dht_storageitem_signature_t *signature);
|
||||
KS_DECLARE(void) ks_dht_storageitem_destroy(ks_dht_storageitem_t **item);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_transaction_create(ks_dht_transaction_t **transaction,
|
||||
ks_pool_t *pool,
|
||||
ks_dht_job_t *job,
|
||||
uint32_t transactionid,
|
||||
ks_dht_job_callback_t callback);
|
||||
KS_DECLARE(void) ks_dht_transaction_destroy(ks_dht_transaction_t **transaction);
|
||||
|
||||
KS_END_EXTERN_C
|
||||
|
||||
#endif /* KS_DHT_INT_H */
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
+565
-78
@@ -1,101 +1,588 @@
|
||||
/*
|
||||
Copyright (c) 2009-2011 by Juliusz Chroboczek
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _KS_DHT_H
|
||||
#define _KS_DHT_H
|
||||
#ifndef KS_DHT_H
|
||||
#define KS_DHT_H
|
||||
|
||||
#include "ks.h"
|
||||
#include "ks_bencode.h"
|
||||
#include "sodium.h"
|
||||
|
||||
KS_BEGIN_EXTERN_C
|
||||
|
||||
typedef enum {
|
||||
KS_DHT_EVENT_NONE = 0,
|
||||
KS_DHT_EVENT_VALUES = 1,
|
||||
KS_DHT_EVENT_VALUES6 = 2,
|
||||
KS_DHT_EVENT_SEARCH_DONE = 3,
|
||||
KS_DHT_EVENT_SEARCH_DONE6 = 4
|
||||
} ks_dht_event_t;
|
||||
|
||||
#define KS_DHT_DEFAULT_PORT 5309
|
||||
|
||||
#define KS_DHT_TPOOL_MIN 2
|
||||
#define KS_DHT_TPOOL_MAX 8
|
||||
#define KS_DHT_TPOOL_STACK (1024 * 256)
|
||||
#define KS_DHT_TPOOL_IDLE 10
|
||||
|
||||
#define KS_DHT_DATAGRAM_BUFFER_SIZE 1000
|
||||
|
||||
//#define KS_DHT_RECV_BUFFER_SIZE 0xFFFF
|
||||
|
||||
#define KS_DHT_NODEID_SIZE 20
|
||||
|
||||
#define KS_DHT_RESPONSE_NODES_MAX_SIZE 8
|
||||
|
||||
#define KS_DHT_MESSAGE_TRANSACTIONID_MAX_SIZE 20
|
||||
#define KS_DHT_MESSAGE_TYPE_MAX_SIZE 20
|
||||
#define KS_DHT_MESSAGE_QUERY_MAX_SIZE 20
|
||||
#define KS_DHT_MESSAGE_ERROR_MAX_SIZE 256
|
||||
|
||||
#define KS_DHT_TRANSACTION_EXPIRATION 10
|
||||
#define KS_DHT_TRANSACTIONS_PULSE 1
|
||||
|
||||
#define KS_DHT_SEARCH_RESULTS_MAX_SIZE 8 // @todo replace with KS_DHTRT_BUCKET_SIZE
|
||||
|
||||
#define KS_DHT_STORAGEITEM_PKEY_SIZE crypto_sign_PUBLICKEYBYTES
|
||||
#define KS_DHT_STORAGEITEM_SKEY_SIZE crypto_sign_SECRETKEYBYTES
|
||||
#define KS_DHT_STORAGEITEM_SALT_MAX_SIZE 64
|
||||
#define KS_DHT_STORAGEITEM_SIGNATURE_SIZE crypto_sign_BYTES
|
||||
#define KS_DHT_STORAGEITEM_EXPIRATION 7200
|
||||
#define KS_DHT_STORAGEITEM_KEEPALIVE 300
|
||||
#define KS_DHT_STORAGEITEMS_PULSE 10
|
||||
|
||||
#define KS_DHT_TOKEN_SIZE SHA_DIGEST_LENGTH
|
||||
#define KS_DHT_TOKEN_EXPIRATION 300
|
||||
#define KS_DHT_TOKENS_PULSE 1
|
||||
|
||||
#define KS_DHTRT_MAXQUERYSIZE 20
|
||||
|
||||
typedef struct ks_dht_s ks_dht_t;
|
||||
typedef struct ks_dht_datagram_s ks_dht_datagram_t;
|
||||
typedef struct ks_dht_job_s ks_dht_job_t;
|
||||
typedef struct ks_dht_nodeid_s ks_dht_nodeid_t;
|
||||
typedef struct ks_dht_token_s ks_dht_token_t;
|
||||
typedef struct ks_dht_storageitem_pkey_s ks_dht_storageitem_pkey_t;
|
||||
typedef struct ks_dht_storageitem_skey_s ks_dht_storageitem_skey_t;
|
||||
typedef struct ks_dht_storageitem_signature_s ks_dht_storageitem_signature_t;
|
||||
typedef struct ks_dht_message_s ks_dht_message_t;
|
||||
typedef struct ks_dht_endpoint_s ks_dht_endpoint_t;
|
||||
typedef struct ks_dht_transaction_s ks_dht_transaction_t;
|
||||
typedef struct ks_dht_search_s ks_dht_search_t;
|
||||
typedef struct ks_dht_publish_s ks_dht_publish_t;
|
||||
typedef struct ks_dht_distribute_s ks_dht_distribute_t;
|
||||
typedef struct ks_dht_node_s ks_dht_node_t;
|
||||
typedef struct ks_dhtrt_routetable_s ks_dhtrt_routetable_t;
|
||||
typedef struct ks_dhtrt_querynodes_s ks_dhtrt_querynodes_t;
|
||||
typedef struct ks_dht_storageitem_s ks_dht_storageitem_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
DHT_PARAM_AUTOROUTE = 1
|
||||
} ks_dht_param_t;
|
||||
|
||||
typedef enum {
|
||||
KS_DHT_AF_INET4 = (1 << 0),
|
||||
KS_DHT_AF_INET6 = (1 << 1)
|
||||
} ks_dht_af_flag_t;
|
||||
typedef ks_status_t (*ks_dht_job_callback_t)(ks_dht_t *dht, ks_dht_job_t *job);
|
||||
typedef ks_status_t (*ks_dht_message_callback_t)(ks_dht_t *dht, ks_dht_message_t *message);
|
||||
//typedef ks_status_t (*ks_dht_search_callback_t)(ks_dht_t *dht, ks_dht_search_t *search);
|
||||
typedef ks_status_t (*ks_dht_storageitem_callback_t)(ks_dht_t *dht, ks_dht_storageitem_t *item);
|
||||
|
||||
|
||||
typedef void (*dht_callback_t)(void *closure, ks_dht_event_t event, const unsigned char *info_hash, const void *data, size_t data_len);
|
||||
struct ks_dht_datagram_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_t *dht;
|
||||
ks_dht_endpoint_t *endpoint;
|
||||
ks_sockaddr_t raddr;
|
||||
uint8_t buffer[KS_DHT_DATAGRAM_BUFFER_SIZE];
|
||||
ks_size_t buffer_length;
|
||||
};
|
||||
|
||||
typedef struct dht_handle_s dht_handle_t;
|
||||
/**
|
||||
* Note: This must remain a structure for casting from raw data
|
||||
*/
|
||||
struct ks_dht_nodeid_s {
|
||||
uint8_t id[KS_DHT_NODEID_SIZE];
|
||||
};
|
||||
|
||||
KS_DECLARE(int) dht_periodic(dht_handle_t *h, const void *buf, size_t buflen, ks_sockaddr_t *from);
|
||||
KS_DECLARE(ks_status_t) ks_dht_init(dht_handle_t **handle, ks_dht_af_flag_t af_flags, const unsigned char *id, unsigned int port);
|
||||
KS_DECLARE(void) ks_dht_set_param(dht_handle_t *h, ks_dht_param_t param, ks_bool_t val);
|
||||
KS_DECLARE(ks_status_t) ks_dht_add_ip(dht_handle_t *h, char *ip, int port);
|
||||
KS_DECLARE(void) ks_dht_start(dht_handle_t *h);
|
||||
KS_DECLARE(int) dht_insert_node(dht_handle_t *h, const unsigned char *id, ks_sockaddr_t *sa);
|
||||
KS_DECLARE(int) dht_ping_node(dht_handle_t *h, ks_sockaddr_t *sa);
|
||||
KS_DECLARE(int) dht_search(dht_handle_t *h, const unsigned char *id, int port, int af, dht_callback_t callback, void *closure);
|
||||
KS_DECLARE(int) dht_nodes(dht_handle_t *h, int af, int *good_return, int *dubious_return, int *cached_return, int *incoming_return);
|
||||
KS_DECLARE(ks_status_t) ks_dht_one_loop(dht_handle_t *h, int timeout);
|
||||
KS_DECLARE(ks_status_t) ks_dht_get_bind_addrs(dht_handle_t *h, const ks_sockaddr_t ***addrs, ks_size_t *addrlen);
|
||||
KS_DECLARE(void) ks_dht_set_callback(dht_handle_t *h, dht_callback_t callback, void *closure);
|
||||
KS_DECLARE(void) ks_dht_set_port(dht_handle_t *h, unsigned int port);
|
||||
KS_DECLARE(void) dht_dump_tables(dht_handle_t *h, FILE *f);
|
||||
KS_DECLARE(int) dht_get_nodes(dht_handle_t *h, struct sockaddr_in *sin, int *num, struct sockaddr_in6 *sin6, int *num6);
|
||||
KS_DECLARE(int) dht_uninit(dht_handle_t **h);
|
||||
KS_DECLARE(void) ks_dht_set_v(dht_handle_t *h, const unsigned char *v);
|
||||
KS_DECLARE(int) ks_dht_calculate_mutable_storage_target(unsigned char *pk, unsigned char *salt, int salt_length, unsigned char *target, int target_length);
|
||||
KS_DECLARE(int) ks_dht_generate_mutable_storage_args(struct bencode *data, int64_t sequence, int cas,
|
||||
unsigned char *id, int id_len, /* querying nodes id */
|
||||
const unsigned char *sk, const unsigned char *pk,
|
||||
unsigned char *salt, unsigned long long salt_length,
|
||||
unsigned char *token, unsigned long long token_length,
|
||||
unsigned char *signature, unsigned long long *signature_length,
|
||||
struct bencode **arguments);
|
||||
enum ks_afflags_t { ifv4=AF_INET, ifv6=AF_INET6, ifboth=AF_INET+AF_INET6};
|
||||
enum ks_dht_nodetype_t { KS_DHT_REMOTE=0x01,
|
||||
KS_DHT_LOCAL=0x02,
|
||||
KS_DHT_BOTH=KS_DHT_REMOTE+KS_DHT_LOCAL };
|
||||
|
||||
/* This must be provided by the user. */
|
||||
KS_DECLARE(int) dht_blacklisted(const ks_sockaddr_t *sa);
|
||||
KS_DECLARE(void) dht_hash(void *hash_return, int hash_size, const void *v1, int len1, const void *v2, int len2, const void *v3, int len3);
|
||||
KS_DECLARE(int) dht_random_bytes(void *buf, size_t size);
|
||||
enum ks_create_node_flags_t {
|
||||
KS_DHTRT_CREATE_DEFAULT=0,
|
||||
KS_DHTRT_CREATE_PING,
|
||||
KS_DHTRT_CREATE_TOUCH
|
||||
};
|
||||
|
||||
struct ks_dht_node_s {
|
||||
ks_dht_nodeid_t nodeid;
|
||||
ks_sockaddr_t addr;
|
||||
enum ks_dht_nodetype_t type; /* local or remote */
|
||||
ks_dhtrt_routetable_t* table;
|
||||
ks_rwl_t *reflock;
|
||||
};
|
||||
|
||||
KS_DECLARE(int) ks_dht_send_message_mutable(dht_handle_t *h, unsigned char *sk, unsigned char *pk, char **node_id,
|
||||
char *message_id, int sequence, char *message, ks_time_t life);
|
||||
struct ks_dht_token_s {
|
||||
uint8_t token[KS_DHT_TOKEN_SIZE];
|
||||
};
|
||||
|
||||
KS_DECLARE(int) ks_dht_send_message_mutable_cjson(dht_handle_t *h, unsigned char *sk, unsigned char *pk, char **node_id,
|
||||
char *message_id, int sequence, cJSON *message, ks_time_t life);
|
||||
enum ks_dht_job_state_t {
|
||||
KS_DHT_JOB_STATE_QUERYING,
|
||||
KS_DHT_JOB_STATE_RESPONDING,
|
||||
KS_DHT_JOB_STATE_EXPIRING,
|
||||
KS_DHT_JOB_STATE_COMPLETING,
|
||||
};
|
||||
|
||||
typedef void (ks_dht_store_entry_json_cb)(struct dht_handle_s *h, const cJSON *msg, void *obj);
|
||||
KS_DECLARE(void) ks_dht_store_entry_json_cb_set(struct dht_handle_s *h, ks_dht_store_entry_json_cb *store_json_cb, void *arg);
|
||||
enum ks_dht_job_result_t {
|
||||
KS_DHT_JOB_RESULT_SUCCESS = 0,
|
||||
KS_DHT_JOB_RESULT_EXPIRED,
|
||||
KS_DHT_JOB_RESULT_ERROR,
|
||||
KS_DHT_JOB_RESULT_FAILURE,
|
||||
};
|
||||
|
||||
KS_DECLARE(int) ks_dht_api_find_node(dht_handle_t *h, char *node_id_hex, char *target_hex, ks_bool_t ipv6);
|
||||
struct ks_dht_job_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_t *dht;
|
||||
ks_dht_job_t *next;
|
||||
|
||||
enum ks_dht_job_state_t state;
|
||||
enum ks_dht_job_result_t result;
|
||||
|
||||
ks_sockaddr_t raddr; // will obtain local endpoint node id when creating message using raddr
|
||||
int32_t attempts;
|
||||
|
||||
//enum ks_dht_job_type_t type;
|
||||
ks_dht_job_callback_t query_callback;
|
||||
ks_dht_job_callback_t finish_callback;
|
||||
|
||||
void *data;
|
||||
ks_dht_message_t *response;
|
||||
|
||||
// job specific query parameters
|
||||
ks_dht_nodeid_t query_target;
|
||||
struct bencode *query_salt;
|
||||
int64_t query_cas;
|
||||
ks_dht_token_t query_token;
|
||||
ks_dht_storageitem_t *query_storageitem;
|
||||
|
||||
// error response parameters
|
||||
int64_t error_code;
|
||||
struct bencode *error_description;
|
||||
|
||||
// job specific response parameters
|
||||
ks_dht_node_t *response_id;
|
||||
ks_dht_node_t *response_nodes[KS_DHT_RESPONSE_NODES_MAX_SIZE];
|
||||
ks_size_t response_nodes_count;
|
||||
ks_dht_node_t *response_nodes6[KS_DHT_RESPONSE_NODES_MAX_SIZE];
|
||||
ks_size_t response_nodes6_count;
|
||||
|
||||
ks_dht_token_t response_token;
|
||||
int64_t response_seq;
|
||||
ks_bool_t response_hasitem;
|
||||
ks_dht_storageitem_t *response_storageitem;
|
||||
};
|
||||
|
||||
struct ks_dhtrt_routetable_s {
|
||||
void* internal;
|
||||
ks_pool_t* pool;
|
||||
ks_logger_t logger;
|
||||
};
|
||||
|
||||
struct ks_dhtrt_querynodes_s {
|
||||
ks_dht_nodeid_t nodeid; /* in: id to query */
|
||||
enum ks_afflags_t family; /* in: AF_INET or AF_INET6 or both */
|
||||
enum ks_dht_nodetype_t type; /* remote, local, or both */
|
||||
uint8_t max; /* in: maximum to return */
|
||||
uint8_t count; /* out: number returned */
|
||||
ks_dht_node_t* nodes[ KS_DHTRT_MAXQUERYSIZE ]; /* out: array of peers (ks_dht_node_t* nodes[incount]) */
|
||||
};
|
||||
|
||||
struct ks_dht_storageitem_pkey_s {
|
||||
uint8_t key[KS_DHT_STORAGEITEM_PKEY_SIZE];
|
||||
};
|
||||
|
||||
struct ks_dht_storageitem_skey_s {
|
||||
uint8_t key[KS_DHT_STORAGEITEM_SKEY_SIZE];
|
||||
};
|
||||
|
||||
struct ks_dht_storageitem_signature_s {
|
||||
uint8_t sig[KS_DHT_STORAGEITEM_SIGNATURE_SIZE];
|
||||
};
|
||||
|
||||
struct ks_dht_message_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_endpoint_t *endpoint;
|
||||
ks_sockaddr_t raddr;
|
||||
struct bencode *data;
|
||||
uint8_t transactionid[KS_DHT_MESSAGE_TRANSACTIONID_MAX_SIZE];
|
||||
ks_size_t transactionid_length;
|
||||
ks_dht_transaction_t *transaction;
|
||||
char type[KS_DHT_MESSAGE_TYPE_MAX_SIZE];
|
||||
struct bencode *args;
|
||||
ks_dht_nodeid_t args_id;
|
||||
};
|
||||
|
||||
struct ks_dht_endpoint_s {
|
||||
ks_pool_t *pool;
|
||||
ks_sockaddr_t addr;
|
||||
ks_socket_t sock;
|
||||
};
|
||||
|
||||
struct ks_dht_transaction_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_job_t *job;
|
||||
uint32_t transactionid;
|
||||
//ks_dht_nodeid_t target; // @todo look at moving this into job now
|
||||
ks_dht_job_callback_t callback;
|
||||
ks_time_t expiration;
|
||||
ks_bool_t finished;
|
||||
};
|
||||
|
||||
struct ks_dht_search_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dhtrt_routetable_t *table;
|
||||
ks_dht_nodeid_t target;
|
||||
ks_dht_job_callback_t callback;
|
||||
void *data;
|
||||
ks_mutex_t *mutex;
|
||||
ks_hash_t *searched;
|
||||
int32_t searching;
|
||||
ks_dht_node_t *results[KS_DHT_SEARCH_RESULTS_MAX_SIZE];
|
||||
ks_dht_nodeid_t distances[KS_DHT_SEARCH_RESULTS_MAX_SIZE];
|
||||
ks_size_t results_length;
|
||||
};
|
||||
|
||||
struct ks_dht_publish_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_job_callback_t callback;
|
||||
void *data;
|
||||
int64_t cas;
|
||||
ks_dht_storageitem_t *item;
|
||||
};
|
||||
|
||||
struct ks_dht_distribute_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_storageitem_callback_t callback;
|
||||
void *data;
|
||||
ks_mutex_t *mutex;
|
||||
int32_t publishing;
|
||||
int64_t cas;
|
||||
ks_dht_storageitem_t *item;
|
||||
};
|
||||
|
||||
struct ks_dht_storageitem_s {
|
||||
ks_pool_t *pool;
|
||||
ks_dht_nodeid_t id;
|
||||
ks_time_t expiration;
|
||||
ks_time_t keepalive;
|
||||
struct bencode *v;
|
||||
|
||||
ks_mutex_t *mutex;
|
||||
volatile int32_t refc;
|
||||
ks_dht_storageitem_callback_t callback;
|
||||
|
||||
ks_bool_t mutable;
|
||||
ks_dht_storageitem_pkey_t pk;
|
||||
ks_dht_storageitem_skey_t sk;
|
||||
struct bencode *salt;
|
||||
int64_t seq;
|
||||
ks_dht_storageitem_signature_t sig;
|
||||
};
|
||||
|
||||
struct ks_dht_s {
|
||||
ks_pool_t *pool;
|
||||
ks_bool_t pool_alloc;
|
||||
|
||||
ks_thread_pool_t *tpool;
|
||||
ks_bool_t tpool_alloc;
|
||||
|
||||
ks_dht_nodeid_t nodeid;
|
||||
// @todo make sure this node is unlocked, and never gets destroyed, should also never use local nodes in search results as they can be internal
|
||||
// network addresses, not what others have contacted through
|
||||
ks_dht_node_t *node;
|
||||
|
||||
ks_bool_t autoroute;
|
||||
ks_port_t autoroute_port;
|
||||
|
||||
ks_hash_t *registry_type;
|
||||
ks_hash_t *registry_query;
|
||||
ks_hash_t *registry_error;
|
||||
|
||||
ks_dht_endpoint_t **endpoints;
|
||||
int32_t endpoints_length;
|
||||
int32_t endpoints_size;
|
||||
ks_hash_t *endpoints_hash;
|
||||
struct pollfd *endpoints_poll;
|
||||
|
||||
ks_q_t *send_q;
|
||||
ks_dht_message_t *send_q_unsent;
|
||||
uint8_t recv_buffer[KS_DHT_DATAGRAM_BUFFER_SIZE + 1]; // Add 1, if we receive it then overflow error
|
||||
ks_size_t recv_buffer_length;
|
||||
|
||||
ks_mutex_t *jobs_mutex;
|
||||
ks_dht_job_t *jobs_first;
|
||||
ks_dht_job_t *jobs_last;
|
||||
|
||||
ks_time_t transactions_pulse;
|
||||
ks_mutex_t *transactionid_mutex;
|
||||
volatile uint32_t transactionid_next;
|
||||
ks_hash_t *transactions_hash;
|
||||
|
||||
ks_dhtrt_routetable_t *rt_ipv4;
|
||||
ks_dhtrt_routetable_t *rt_ipv6;
|
||||
|
||||
ks_time_t tokens_pulse;
|
||||
volatile uint32_t token_secret_current;
|
||||
volatile uint32_t token_secret_previous;
|
||||
ks_time_t token_secret_expiration;
|
||||
|
||||
ks_time_t storageitems_pulse;
|
||||
ks_hash_t *storageitems_hash;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor function for ks_dht_t.
|
||||
* Will allocate and initialize internal state including registration of message handlers.
|
||||
* @param dht dereferenced out pointer to the allocated dht instance
|
||||
* @param pool pointer to the memory pool used by the dht instance, may be NULL to create a new memory pool internally
|
||||
* @param tpool pointer to a thread pool used by the dht instance, may be NULL to create a new thread pool internally
|
||||
* @param nodeid pointer to the nodeid for this dht instance
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_NO_MEM
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_create(ks_dht_t **dht, ks_pool_t *pool, ks_thread_pool_t *tpool, ks_dht_nodeid_t *nodeid);
|
||||
|
||||
/**
|
||||
* Destructor function for ks_dht_t.
|
||||
* Will deinitialize and deallocate internal state.
|
||||
* @param dht dereferenced in/out pointer to the dht instance, NULL upon return
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_destroy(ks_dht_t **dht);
|
||||
|
||||
/**
|
||||
* Enable or disable (default) autorouting support.
|
||||
* When enabled, autorouting will allow sending to remote addresses on interfaces which are not yet bound.
|
||||
* The address will be bound with the provided autoroute port when this occurs.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param autoroute enable or disable autorouting
|
||||
* @param port when enabling autorouting this port will be used to bind new addresses, may be 0 to use the default DHT port
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_autoroute(ks_dht_t *dht, ks_bool_t autoroute, ks_port_t port);
|
||||
|
||||
/**
|
||||
* Register a callback for a specific message type.
|
||||
* Will overwrite any duplicate handlers.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param value string of the type text under the 'y' key of a message
|
||||
* @param callback the callback to be called when a message matches
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_register_type(ks_dht_t *dht, const char *value, ks_dht_message_callback_t callback);
|
||||
|
||||
/**
|
||||
* Register a callback for a specific message query.
|
||||
* Will overwrite any duplicate handlers.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param value string of the type text under the 'q' key of a message
|
||||
* @param callback the callback to be called when a message matches
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_register_query(ks_dht_t *dht, const char *value, ks_dht_message_callback_t callback);
|
||||
|
||||
/**
|
||||
* Register a callback for a specific message error.
|
||||
* Will overwrite any duplicate handlers.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param value string of the errorcode under the first item of the 'e' key of a message
|
||||
* @param callback the callback to be called when a message matches
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_register_error(ks_dht_t *dht, const char *value, ks_dht_message_callback_t callback);
|
||||
|
||||
/**
|
||||
* Bind a local address and port for receiving UDP datagrams.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param addr pointer to the local address information
|
||||
* @param endpoint dereferenced out pointer to the allocated endpoint, may be NULL to ignore endpoint output
|
||||
* @return The ks_status_t result: KS_STATUS_SUCCESS, KS_STATUS_FAIL, ...
|
||||
* @see ks_socket_option
|
||||
* @see ks_addr_bind
|
||||
* @see ks_dht_endpoint_alloc
|
||||
* @see ks_dht_endpoint_init
|
||||
* @see ks_hash_insert
|
||||
* @see ks_dhtrt_initroute
|
||||
* @see ks_dhtrt_create_node
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_bind(ks_dht_t *dht, const ks_sockaddr_t *addr, ks_dht_endpoint_t **endpoint);
|
||||
|
||||
/**
|
||||
* Pulse the internals of dht.
|
||||
* Handles receiving UDP datagrams, dispatching processing, handles expirations, throttled message sending, route table pulsing, etc.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param timeout timeout value used when polling sockets for new UDP datagrams
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_pulse(ks_dht_t *dht, int32_t timeout);
|
||||
|
||||
|
||||
KS_DECLARE(char *) ks_dht_hex(const uint8_t *data, char *buffer, ks_size_t len);
|
||||
KS_DECLARE(uint8_t *) ks_dht_dehex(uint8_t *data, const char *buffer, ks_size_t len);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_target_immutable(const uint8_t *value, ks_size_t value_length, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_target_mutable(ks_dht_storageitem_pkey_t *pk, const uint8_t *salt, ks_size_t salt_length, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitem_signature_generate(ks_dht_storageitem_signature_t *sig,
|
||||
ks_dht_storageitem_skey_t *sk,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length,
|
||||
int64_t sequence,
|
||||
const uint8_t *value,
|
||||
ks_size_t value_length);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitem_reference(ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitem_dereference(ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitem_callback(ks_dht_storageitem_t *item, ks_dht_storageitem_callback_t callback);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitems_read_lock(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitems_read_unlock(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitems_write_lock(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_storageitems_write_unlock(ks_dht_t *dht);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_dht_storageitem_t *) ks_dht_storageitems_find(ks_dht_t *dht, ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dht_storageitems_insert(ks_dht_t *dht, ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_ping(ks_dht_t *dht, const ks_sockaddr_t *raddr, ks_dht_job_callback_t callback, void *data);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_findnode(ks_dht_t *dht,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
ks_dht_nodeid_t *target);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_get(ks_dht_t *dht,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
ks_dht_nodeid_t *target,
|
||||
const uint8_t *salt,
|
||||
ks_size_t salt_length);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_put(ks_dht_t *dht,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
ks_dht_token_t *token,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
* Create a network search of the closest nodes to a target.
|
||||
* @param dht pointer to the dht instance
|
||||
* @param family either AF_INET or AF_INET6 for the appropriate network to search
|
||||
* @param target pointer to the nodeid for the target to be searched
|
||||
* @param callback an optional callback to add to the search when it is finished
|
||||
* @param search dereferenced out pointer to the allocated search, may be NULL to ignore search output
|
||||
* @see ks_dht_search_create
|
||||
* @see ks_hash_insert
|
||||
* @see ks_dht_findnode
|
||||
*/
|
||||
KS_DECLARE(void) ks_dht_search(ks_dht_t *dht,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
ks_dhtrt_routetable_t *table,
|
||||
ks_dht_nodeid_t *target);
|
||||
|
||||
KS_DECLARE(void) ks_dht_publish(ks_dht_t *dht,
|
||||
const ks_sockaddr_t *raddr,
|
||||
ks_dht_job_callback_t callback,
|
||||
void *data,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
|
||||
KS_DECLARE(void) ks_dht_distribute(ks_dht_t *dht,
|
||||
ks_dht_storageitem_callback_t callback,
|
||||
void *data,
|
||||
ks_dhtrt_routetable_t *table,
|
||||
int64_t cas,
|
||||
ks_dht_storageitem_t *item);
|
||||
|
||||
/**
|
||||
* route table methods
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_initroute(ks_dhtrt_routetable_t **tableP,
|
||||
ks_dht_t *dht,
|
||||
ks_pool_t *pool);
|
||||
KS_DECLARE(void) ks_dhtrt_deinitroute(ks_dhtrt_routetable_t **table);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_create_node(ks_dhtrt_routetable_t* table,
|
||||
ks_dht_nodeid_t nodeid,
|
||||
enum ks_dht_nodetype_t type,
|
||||
char* ip, unsigned short port,
|
||||
enum ks_create_node_flags_t flags,
|
||||
ks_dht_node_t** node);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_delete_node(ks_dhtrt_routetable_t* table, ks_dht_node_t* node);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_touch_node(ks_dhtrt_routetable_t* table, ks_dht_nodeid_t nodeid);
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_expire_node(ks_dhtrt_routetable_t* table, ks_dht_nodeid_t nodeid);
|
||||
|
||||
KS_DECLARE(uint8_t) ks_dhtrt_findclosest_nodes(ks_dhtrt_routetable_t* table, ks_dhtrt_querynodes_t* query);
|
||||
KS_DECLARE(ks_dht_node_t*) ks_dhtrt_find_node(ks_dhtrt_routetable_t* table, ks_dht_nodeid_t id);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_sharelock_node(ks_dht_node_t* node);
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_release_node(ks_dht_node_t* node);
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_release_querynodes(ks_dhtrt_querynodes_t* query);
|
||||
|
||||
KS_DECLARE(void) ks_dhtrt_process_table(ks_dhtrt_routetable_t* table);
|
||||
|
||||
KS_DECLARE(uint32_t) ks_dhtrt_serialize(ks_dhtrt_routetable_t* table, void** ptr);
|
||||
KS_DECLARE(ks_status_t) ks_dhtrt_deserialize(ks_dhtrt_routetable_t* table, void* ptr);
|
||||
|
||||
/* debugging aids */
|
||||
KS_DECLARE(void) ks_dhtrt_dump(ks_dhtrt_routetable_t* table, int level);
|
||||
|
||||
|
||||
KS_END_EXTERN_C
|
||||
|
||||
#endif /* _KS_DHT_H */
|
||||
#endif /* KS_DHT_H */
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
|
||||
@@ -90,15 +90,17 @@ typedef enum {
|
||||
|
||||
|
||||
typedef enum {
|
||||
KS_HASH_FLAG_NONE = 0,
|
||||
KS_HASH_FLAG_DEFAULT = (1 << 0),
|
||||
KS_HASH_FLAG_FREE_KEY = (1 << 1),
|
||||
KS_HASH_FLAG_FREE_VALUE = (1 << 2),
|
||||
KS_HASH_FLAG_RWLOCK = (1 << 3),
|
||||
KS_HASH_FLAG_DUP_CHECK = (1 << 4)
|
||||
KS_HASH_FLAG_MUTEX = 0,
|
||||
KS_HASH_FLAG_FREE_KEY = (1 << 0),
|
||||
KS_HASH_FLAG_FREE_VALUE = (1 << 1),
|
||||
KS_HASH_FLAG_RWLOCK = (1 << 2),
|
||||
KS_HASH_FLAG_DUP_CHECK = (1 << 3),
|
||||
KS_HASH_FLAG_NOLOCK = (1 << 4)
|
||||
} ks_hash_flag_t;
|
||||
|
||||
#define KS_HASH_FREE_BOTH KS_HASH_FLAG_FREE_KEY | KS_HASH_FLAG_FREE_VALUE
|
||||
#define KS_HASH_FLAG_NONE KS_HASH_FLAG_MUTEX
|
||||
|
||||
|
||||
typedef enum {
|
||||
KS_HASH_MODE_DEFAULT = 0,
|
||||
@@ -134,7 +136,7 @@ ks_hash_create_ex(ks_hash_t **hp, unsigned int minsize,
|
||||
* @param h the ks_hash to insert into
|
||||
* @param k the key - ks_hash claims ownership and will free on removal
|
||||
* @param v the value - does not claim ownership
|
||||
* @return non-zero for successful insertion
|
||||
* @return KS_STATUS_SUCCESS for successful insertion
|
||||
*
|
||||
* This function will cause the table to expand if the insertion would take
|
||||
* the ratio of entries to table size over the maximum load factor.
|
||||
@@ -147,7 +149,7 @@ ks_hash_create_ex(ks_hash_t **hp, unsigned int minsize,
|
||||
*/
|
||||
|
||||
|
||||
KS_DECLARE(int) ks_hash_insert_ex(ks_hash_t *h, void *k, void *v, ks_hash_flag_t flags, ks_hash_destructor_t destructor);
|
||||
KS_DECLARE(ks_status_t) ks_hash_insert_ex(ks_hash_t *h, void *k, void *v, ks_hash_flag_t flags, ks_hash_destructor_t destructor);
|
||||
#define ks_hash_insert(_h, _k, _v) ks_hash_insert_ex(_h, _k, _v, 0, NULL)
|
||||
|
||||
#define DEFINE_KS_HASH_INSERT(fnname, keytype, valuetype) \
|
||||
|
||||
@@ -34,8 +34,9 @@ KS_BEGIN_EXTERN_C
|
||||
|
||||
typedef enum {
|
||||
KS_POOL_FLAG_DEFAULT = 0,
|
||||
|
||||
KS_POOL_FLAG_BEST_FIT = (1 << 0),
|
||||
KS_POOL_FLAG_NO_ASSERT = (1 << 1),
|
||||
KS_POOL_FLAG_NO_ZERO = (1 << 2),
|
||||
/*
|
||||
* Choose a best fit algorithm not first fit. This takes more CPU
|
||||
* time but will result in a tighter heap.
|
||||
@@ -290,7 +291,7 @@ KS_DECLARE(void *) ks_pool_calloc_ex(ks_pool_t *mp_p, const unsigned long ele_n,
|
||||
*
|
||||
*/
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_pool_free(ks_pool_t *mp_p, void *addr);
|
||||
KS_DECLARE(ks_status_t) ks_pool_free_ex(ks_pool_t *mp_p, void **addrP);
|
||||
|
||||
/*
|
||||
* void *ks_pool_resize
|
||||
@@ -452,7 +453,7 @@ KS_DECLARE(const char *) ks_pool_strerror(const ks_status_t error);
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_pool_set_cleanup(ks_pool_t *mp_p, void *ptr, void *arg, int type, ks_pool_cleanup_fn_t fn);
|
||||
|
||||
#define ks_pool_safe_free(_p, _a) ks_pool_free(_p, _a); (_a) = NULL
|
||||
#define ks_pool_free(_p, _x) ks_pool_free_ex(_p, (void **)_x)
|
||||
|
||||
/*<<<<<<<<<< This is end of the auto-generated output from fillproto. */
|
||||
|
||||
|
||||
@@ -99,13 +99,13 @@ KS_DECLARE(ks_status_t) ks_socket_rcvbuf(ks_socket_t socket, int bufsize);
|
||||
KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags);
|
||||
|
||||
KS_DECLARE(ks_socket_t) ks_socket_connect(int type, int protocol, ks_sockaddr_t *addr);
|
||||
KS_DECLARE(ks_status_t) ks_addr_bind(ks_socket_t server_sock, ks_sockaddr_t *addr);
|
||||
KS_DECLARE(ks_status_t) ks_addr_bind(ks_socket_t server_sock, const ks_sockaddr_t *addr);
|
||||
KS_DECLARE(const char *) ks_addr_get_host(ks_sockaddr_t *addr);
|
||||
KS_DECLARE(ks_port_t) ks_addr_get_port(ks_sockaddr_t *addr);
|
||||
KS_DECLARE(int) ks_addr_cmp(const ks_sockaddr_t *sa1, const ks_sockaddr_t *sa2);
|
||||
KS_DECLARE(ks_status_t) ks_addr_copy(ks_sockaddr_t *addr, const ks_sockaddr_t *src_addr);
|
||||
KS_DECLARE(ks_status_t) ks_addr_set(ks_sockaddr_t *addr, const char *host, ks_port_t port, int family);
|
||||
KS_DECLARE(ks_status_t) ks_addr_set_raw(ks_sockaddr_t *addr, void *data, ks_port_t port, int family);
|
||||
KS_DECLARE(ks_status_t) ks_addr_set_raw(ks_sockaddr_t *addr, const void *data, ks_port_t port, int family);
|
||||
KS_DECLARE(ks_status_t) ks_addr_raw_data(const ks_sockaddr_t *addr, void **data, ks_size_t *datalen);
|
||||
KS_DECLARE(ks_status_t) ks_listen(const char *host, ks_port_t port, int family, int backlog, ks_listen_callback_t callback, void *user_data);
|
||||
KS_DECLARE(ks_status_t) ks_socket_shutdown(ks_socket_t sock, int how);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+27
-22
@@ -210,8 +210,8 @@ ks_hash_create_ex(ks_hash_t **hp, unsigned int minsize,
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags == KS_HASH_FLAG_DEFAULT) {
|
||||
flags = KS_HASH_FLAG_FREE_KEY | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_RWLOCK;
|
||||
if ((flags & KS_HASH_FLAG_NOLOCK)) {
|
||||
flags &= ~KS_HASH_FLAG_RWLOCK;
|
||||
}
|
||||
|
||||
ks_assert(pool);
|
||||
@@ -240,7 +240,9 @@ ks_hash_create_ex(ks_hash_t **hp, unsigned int minsize,
|
||||
ks_rwl_create(&h->rwl, h->pool);
|
||||
}
|
||||
|
||||
ks_mutex_create(&h->mutex, KS_MUTEX_FLAG_DEFAULT, h->pool);
|
||||
if (!(flags & KS_HASH_FLAG_NOLOCK)) {
|
||||
ks_mutex_create(&h->mutex, KS_MUTEX_FLAG_DEFAULT, h->pool);
|
||||
}
|
||||
|
||||
|
||||
if (NULL == h) abort(); /*oom*/
|
||||
@@ -291,7 +293,7 @@ ks_hash_expand(ks_hash_t *h)
|
||||
newtable[index] = e;
|
||||
}
|
||||
}
|
||||
ks_pool_safe_free(h->pool, h->table);
|
||||
ks_pool_free(h->pool, &h->table);
|
||||
h->table = newtable;
|
||||
}
|
||||
/* Plan B: realloc instead */
|
||||
@@ -355,10 +357,10 @@ static void * _ks_hash_remove(ks_hash_t *h, void *k, unsigned int hashvalue, uns
|
||||
h->entrycount--;
|
||||
v = e->v;
|
||||
if (e->flags & KS_HASH_FLAG_FREE_KEY) {
|
||||
ks_pool_free(h->pool, e->k);
|
||||
ks_pool_free(h->pool, &e->k);
|
||||
}
|
||||
if (e->flags & KS_HASH_FLAG_FREE_VALUE) {
|
||||
ks_pool_safe_free(h->pool, e->v);
|
||||
ks_pool_free(h->pool, &e->v);
|
||||
v = NULL;
|
||||
} else if (e->destructor) {
|
||||
e->destructor(e->v);
|
||||
@@ -367,7 +369,7 @@ static void * _ks_hash_remove(ks_hash_t *h, void *k, unsigned int hashvalue, uns
|
||||
h->destructor(e->v);
|
||||
v = e->v = NULL;
|
||||
}
|
||||
ks_pool_safe_free(h->pool, e);
|
||||
ks_pool_free(h->pool, &e);
|
||||
return v;
|
||||
}
|
||||
pE = &(e->next);
|
||||
@@ -377,7 +379,7 @@ static void * _ks_hash_remove(ks_hash_t *h, void *k, unsigned int hashvalue, uns
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
KS_DECLARE(int)
|
||||
KS_DECLARE(ks_status_t)
|
||||
ks_hash_insert_ex(ks_hash_t *h, void *k, void *v, ks_hash_flag_t flags, ks_hash_destructor_t destructor)
|
||||
{
|
||||
struct entry *e;
|
||||
@@ -404,7 +406,6 @@ ks_hash_insert_ex(ks_hash_t *h, void *k, void *v, ks_hash_flag_t flags, ks_hash_
|
||||
index = indexFor(h->tablelength, hashvalue);
|
||||
}
|
||||
e = (struct entry *)ks_pool_alloc(h->pool, sizeof(struct entry));
|
||||
if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
|
||||
e->h = hashvalue;
|
||||
e->k = k;
|
||||
e->v = v;
|
||||
@@ -415,13 +416,15 @@ ks_hash_insert_ex(ks_hash_t *h, void *k, void *v, ks_hash_flag_t flags, ks_hash_
|
||||
|
||||
ks_hash_write_unlock(h);
|
||||
|
||||
return -1;
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
KS_DECLARE(void) ks_hash_write_lock(ks_hash_t *h)
|
||||
{
|
||||
if ((h->flags & KS_HASH_FLAG_RWLOCK)) {
|
||||
if ((h->flags & KS_HASH_FLAG_NOLOCK)) {
|
||||
return;
|
||||
} else if ((h->flags & KS_HASH_FLAG_RWLOCK)) {
|
||||
ks_rwl_write_lock(h->rwl);
|
||||
} else {
|
||||
ks_mutex_lock(h->mutex);
|
||||
@@ -430,7 +433,9 @@ KS_DECLARE(void) ks_hash_write_lock(ks_hash_t *h)
|
||||
|
||||
KS_DECLARE(void) ks_hash_write_unlock(ks_hash_t *h)
|
||||
{
|
||||
if ((h->flags & KS_HASH_FLAG_RWLOCK)) {
|
||||
if ((h->flags & KS_HASH_FLAG_NOLOCK)) {
|
||||
return;
|
||||
} else if ((h->flags & KS_HASH_FLAG_RWLOCK)) {
|
||||
ks_rwl_write_unlock(h->rwl);
|
||||
} else {
|
||||
ks_mutex_unlock(h->mutex);
|
||||
@@ -533,11 +538,11 @@ ks_hash_destroy(ks_hash_t **h)
|
||||
f = e; e = e->next;
|
||||
|
||||
if (f->flags & KS_HASH_FLAG_FREE_KEY) {
|
||||
ks_pool_free((*h)->pool, f->k);
|
||||
ks_pool_free((*h)->pool, &f->k);
|
||||
}
|
||||
|
||||
if (f->flags & KS_HASH_FLAG_FREE_VALUE) {
|
||||
ks_pool_safe_free((*h)->pool, f->v);
|
||||
ks_pool_free((*h)->pool, &f->v);
|
||||
} else if (f->destructor) {
|
||||
f->destructor(f->v);
|
||||
f->v = NULL;
|
||||
@@ -545,16 +550,18 @@ ks_hash_destroy(ks_hash_t **h)
|
||||
(*h)->destructor(f->v);
|
||||
f->v = NULL;
|
||||
}
|
||||
ks_pool_safe_free((*h)->pool, f);
|
||||
ks_pool_free((*h)->pool, &f);
|
||||
}
|
||||
}
|
||||
|
||||
pool = (*h)->pool;
|
||||
ks_pool_safe_free(pool, (*h)->table);
|
||||
ks_pool_free(pool, &(*h)->table);
|
||||
ks_hash_write_unlock(*h);
|
||||
if ((*h)->rwl) ks_pool_free(pool, (*h)->rwl);
|
||||
ks_pool_free(pool, (*h)->mutex);
|
||||
ks_pool_free(pool, *h);
|
||||
if ((*h)->rwl) ks_pool_free(pool, &(*h)->rwl);
|
||||
if ((*h)->mutex) {
|
||||
ks_pool_free(pool, &(*h)->mutex);
|
||||
}
|
||||
ks_pool_free(pool, &(*h));
|
||||
pool = NULL;
|
||||
*h = NULL;
|
||||
|
||||
@@ -565,8 +572,6 @@ KS_DECLARE(void) ks_hash_last(ks_hash_iterator_t **iP)
|
||||
{
|
||||
ks_hash_iterator_t *i = *iP;
|
||||
|
||||
//ks_assert(i->locked != KS_READLOCKED || (i->h->flags & KS_HASH_FLAG_RWLOCK));
|
||||
|
||||
if (i->locked == KS_READLOCKED) {
|
||||
ks_mutex_lock(i->h->mutex);
|
||||
i->h->readers--;
|
||||
@@ -575,7 +580,7 @@ KS_DECLARE(void) ks_hash_last(ks_hash_iterator_t **iP)
|
||||
ks_rwl_read_unlock(i->h->rwl);
|
||||
}
|
||||
|
||||
ks_pool_free(i->h->pool, i);
|
||||
ks_pool_free(i->h->pool, &i);
|
||||
|
||||
*iP = NULL;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ KS_DECLARE(ks_status_t) ks_mutex_destroy(ks_mutex_t **mutexP)
|
||||
#endif
|
||||
free(mutex);
|
||||
} else {
|
||||
ks_pool_free(mutex->pool, (void *)mutex);
|
||||
ks_pool_free(mutex->pool, &mutex);
|
||||
}
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
@@ -422,7 +422,7 @@ KS_DECLARE(ks_status_t) ks_cond_destroy(ks_cond_t **cond)
|
||||
|
||||
*cond = NULL;
|
||||
|
||||
return ks_pool_free(condp->pool, condp);
|
||||
return ks_pool_free(condp->pool, &condp);
|
||||
}
|
||||
|
||||
|
||||
@@ -430,6 +430,7 @@ struct ks_rwl {
|
||||
#ifdef WIN32
|
||||
SRWLOCK rwlock;
|
||||
ks_hash_t *read_lock_list;
|
||||
ks_mutex_t *read_lock_mutex;
|
||||
#else
|
||||
pthread_rwlock_t rwlock;
|
||||
#endif
|
||||
@@ -479,6 +480,10 @@ KS_DECLARE(ks_status_t) ks_rwl_create(ks_rwl_t **rwlock, ks_pool_t *pool)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ks_mutex_create(&check->read_lock_mutex, KS_MUTEX_FLAG_DEFAULT, pool) != KS_STATUS_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
InitializeSRWLock(&check->rwlock);
|
||||
#else
|
||||
if ((pthread_rwlock_init(&check->rwlock, NULL))) {
|
||||
@@ -496,13 +501,18 @@ KS_DECLARE(ks_status_t) ks_rwl_create(ks_rwl_t **rwlock, ks_pool_t *pool)
|
||||
KS_DECLARE(ks_status_t) ks_rwl_read_lock(ks_rwl_t *rwlock)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
||||
ks_mutex_lock(rwlock->read_lock_mutex);
|
||||
|
||||
int count = (int)(intptr_t)ks_hash_remove(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self());
|
||||
|
||||
if (count) {
|
||||
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)++count);
|
||||
ks_mutex_unlock(rwlock->read_lock_mutex);
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ks_mutex_unlock(rwlock->read_lock_mutex);
|
||||
|
||||
AcquireSRWLockShared(&rwlock->rwlock);
|
||||
#else
|
||||
@@ -511,6 +521,7 @@ KS_DECLARE(ks_status_t) ks_rwl_read_lock(ks_rwl_t *rwlock)
|
||||
|
||||
#ifdef WIN32
|
||||
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)(int)1);
|
||||
ks_mutex_unlock(rwlock->read_lock_mutex);
|
||||
#endif
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
@@ -539,14 +550,18 @@ KS_DECLARE(ks_status_t) ks_rwl_write_lock(ks_rwl_t *rwlock)
|
||||
KS_DECLARE(ks_status_t) ks_rwl_try_read_lock(ks_rwl_t *rwlock)
|
||||
{
|
||||
#ifdef WIN32
|
||||
ks_mutex_lock(rwlock->read_lock_mutex);
|
||||
|
||||
int count = (int)(intptr_t)ks_hash_remove(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self());
|
||||
|
||||
if (count) {
|
||||
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)++count);
|
||||
ks_mutex_unlock(rwlock->read_lock_mutex);
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!TryAcquireSRWLockShared(&rwlock->rwlock)) {
|
||||
ks_mutex_unlock(rwlock->read_lock_mutex);
|
||||
return KS_STATUS_FAIL;
|
||||
}
|
||||
#else
|
||||
@@ -557,6 +572,7 @@ KS_DECLARE(ks_status_t) ks_rwl_try_read_lock(ks_rwl_t *rwlock)
|
||||
|
||||
#ifdef WIN32
|
||||
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)(int)1);
|
||||
ks_mutex_unlock(rwlock->read_lock_mutex);
|
||||
#endif
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
@@ -589,14 +605,18 @@ KS_DECLARE(ks_status_t) ks_rwl_try_write_lock(ks_rwl_t *rwlock)
|
||||
KS_DECLARE(ks_status_t) ks_rwl_read_unlock(ks_rwl_t *rwlock)
|
||||
{
|
||||
#ifdef WIN32
|
||||
ks_mutex_lock(rwlock->read_lock_mutex);
|
||||
|
||||
int count = (int)(intptr_t)ks_hash_remove(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self());
|
||||
|
||||
if (count > 1) {
|
||||
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)--count);
|
||||
ks_mutex_unlock(rwlock->read_lock_mutex);
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ReleaseSRWLockShared(&rwlock->rwlock);
|
||||
ks_mutex_unlock(rwlock->read_lock_mutex);
|
||||
#else
|
||||
pthread_rwlock_unlock(&rwlock->rwlock);
|
||||
#endif
|
||||
@@ -635,7 +655,7 @@ KS_DECLARE(ks_status_t) ks_rwl_destroy(ks_rwl_t **rwlock)
|
||||
|
||||
*rwlock = NULL;
|
||||
|
||||
return ks_pool_free(rwlockp->pool, rwlockp);
|
||||
return ks_pool_free(rwlockp->pool, &rwlockp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright 1996 by Gray Watson.
|
||||
*
|
||||
* This file is part of the ks_mpool package.
|
||||
* This file is part of the ks_pool package.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for
|
||||
* any purpose and without fee is hereby granted, provided that the
|
||||
@@ -1465,6 +1465,12 @@ KS_DECLARE(void *) ks_pool_alloc_ex(ks_pool_t *mp_p, const unsigned long byte_si
|
||||
mp_p->mp_log_func(mp_p, KS_POOL_FUNC_ALLOC, byte_size, 0, addr, NULL, 0);
|
||||
}
|
||||
|
||||
ks_assert(addr || (mp_p->mp_flags & KS_POOL_FLAG_NO_ASSERT));
|
||||
|
||||
if (!(mp_p->mp_flags & KS_POOL_FLAG_NO_ZERO)) {
|
||||
memset(addr, 0, byte_size);
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -1554,6 +1560,12 @@ KS_DECLARE(void *) ks_pool_calloc_ex(ks_pool_t *mp_p, const unsigned long ele_n,
|
||||
mp_p->mp_log_func(mp_p, KS_POOL_FUNC_CALLOC, ele_size, ele_n, addr, NULL, 0);
|
||||
}
|
||||
|
||||
ks_assert(addr || (mp_p->mp_flags & KS_POOL_FLAG_NO_ASSERT));
|
||||
|
||||
if (!(mp_p->mp_flags & KS_POOL_FLAG_NO_ZERO)) {
|
||||
memset(addr, 0, ele_n * ele_size);
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -1604,13 +1616,18 @@ KS_DECLARE(void *) ks_pool_calloc(ks_pool_t *mp_p, const unsigned long ele_n, co
|
||||
* mp_p <-> Pointer to the memory pool.
|
||||
*
|
||||
*
|
||||
* addr <-> Address to free.
|
||||
* addr <-> pointer to pointer of Address to free.
|
||||
*
|
||||
*/
|
||||
KS_DECLARE(ks_status_t) ks_pool_free(ks_pool_t *mp_p, void *addr)
|
||||
KS_DECLARE(ks_status_t) ks_pool_free_ex(ks_pool_t *mp_p, void **addrP)
|
||||
{
|
||||
ks_status_t r;
|
||||
void *addr;
|
||||
|
||||
ks_assert(addrP);
|
||||
|
||||
addr = *addrP;
|
||||
|
||||
ks_assert(mp_p);
|
||||
ks_assert(addr);
|
||||
|
||||
@@ -1637,6 +1654,10 @@ KS_DECLARE(ks_status_t) ks_pool_free(ks_pool_t *mp_p, void *addr)
|
||||
|
||||
ks_mutex_unlock(mp_p->mutex);
|
||||
|
||||
if (r == KS_STATUS_SUCCESS) {
|
||||
*addrP = NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
@@ -1785,6 +1806,8 @@ KS_DECLARE(void *) ks_pool_resize_ex(ks_pool_t *mp_p, void *old_addr, const unsi
|
||||
|
||||
ks_mutex_unlock(mp_p->mutex);
|
||||
|
||||
ks_assert(new_addr || (mp_p->mp_flags & KS_POOL_FLAG_NO_ASSERT));
|
||||
|
||||
return new_addr;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,14 +73,14 @@ static void ks_q_cleanup(ks_pool_t *mpool, void *ptr, void *arg, int type, ks_po
|
||||
while(np) {
|
||||
fp = np;
|
||||
np = np->next;
|
||||
ks_pool_free(q->pool, fp);
|
||||
ks_pool_free(q->pool, &fp);
|
||||
}
|
||||
|
||||
np = q->empty;
|
||||
while(np) {
|
||||
fp = np;
|
||||
np = np->next;
|
||||
ks_pool_free(q->pool, fp);
|
||||
ks_pool_free(q->pool, &fp);
|
||||
}
|
||||
break;
|
||||
case KS_MPCL_DESTROY:
|
||||
@@ -167,7 +167,7 @@ KS_DECLARE(ks_status_t) ks_q_destroy(ks_q_t **qP)
|
||||
ks_q_term(q);
|
||||
|
||||
pool = q->pool;
|
||||
ks_pool_free(pool, q);
|
||||
ks_pool_free(pool, &q);
|
||||
pool = NULL;
|
||||
|
||||
return KS_STATUS_SUCCESS;
|
||||
|
||||
@@ -213,7 +213,7 @@ KS_DECLARE(ks_socket_t) ks_socket_connect(int type, int protocol, ks_sockaddr_t
|
||||
return sock;
|
||||
}
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_addr_bind(ks_socket_t server_sock, ks_sockaddr_t *addr)
|
||||
KS_DECLARE(ks_status_t) ks_addr_bind(ks_socket_t server_sock, const ks_sockaddr_t *addr)
|
||||
{
|
||||
ks_status_t status = KS_STATUS_SUCCESS;
|
||||
|
||||
@@ -353,7 +353,7 @@ KS_DECLARE(ks_status_t) ks_addr_set(ks_sockaddr_t *addr, const char *host, ks_po
|
||||
}
|
||||
|
||||
|
||||
KS_DECLARE(ks_status_t) ks_addr_set_raw(ks_sockaddr_t *addr, void *data, ks_port_t port, int family)
|
||||
KS_DECLARE(ks_status_t) ks_addr_set_raw(ks_sockaddr_t *addr, const void *data, ks_port_t port, int family)
|
||||
{
|
||||
ks_status_t status = KS_STATUS_SUCCESS;
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ KS_DECLARE(ks_status_t) ks_thread_create_ex(ks_thread_t **rthread, ks_thread_fun
|
||||
if (thread) {
|
||||
thread->running = 0;
|
||||
if (pool) {
|
||||
ks_pool_safe_free(pool, thread);
|
||||
ks_pool_free(pool, &thread);
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
@@ -102,10 +102,10 @@ static int check_queue(ks_thread_pool_t *tp, ks_bool_t adding)
|
||||
|
||||
need--;
|
||||
}
|
||||
|
||||
/*
|
||||
ks_log(KS_LOG_DEBUG, "WORKER check: adding %d need %d running %d dying %d total %d max %d\n",
|
||||
adding, need, tp->running_thread_count, tp->dying_thread_count, tp->thread_count, tp->max);
|
||||
|
||||
*/
|
||||
return need;
|
||||
}
|
||||
|
||||
@@ -129,10 +129,10 @@ static void *worker_thread(ks_thread_t *thread, void *data)
|
||||
ks_status_t status;
|
||||
|
||||
status = ks_q_pop_timeout(tp->q, &pop, 1000);
|
||||
|
||||
/*
|
||||
ks_log(KS_LOG_DEBUG, "WORKER %d idle_sec %d running %d dying %d total %d max %d\n",
|
||||
my_id, idle_sec, tp->running_thread_count, tp->dying_thread_count, tp->thread_count, tp->max);
|
||||
|
||||
*/
|
||||
check_queue(tp, KS_FALSE);
|
||||
|
||||
if (status == KS_STATUS_TIMEOUT) {
|
||||
@@ -170,7 +170,7 @@ static void *worker_thread(ks_thread_t *thread, void *data)
|
||||
idle_sec = 0;
|
||||
job->func(thread, job->data);
|
||||
|
||||
ks_pool_free(tp->pool, job);
|
||||
ks_pool_free(tp->pool, &job);
|
||||
|
||||
ks_mutex_lock(tp->mutex);
|
||||
tp->busy_thread_count--;
|
||||
|
||||
@@ -752,7 +752,7 @@ KS_DECLARE(void) kws_destroy(kws_t **kwsP)
|
||||
kws->down = 2;
|
||||
|
||||
if (kws->write_buffer) {
|
||||
ks_pool_free(kws->pool, kws->write_buffer);
|
||||
ks_pool_free(kws->pool, &kws->write_buffer);
|
||||
kws->write_buffer = NULL;
|
||||
kws->write_buffer_len = 0;
|
||||
}
|
||||
@@ -767,12 +767,12 @@ KS_DECLARE(void) kws_destroy(kws_t **kwsP)
|
||||
kws->ssl = NULL;
|
||||
}
|
||||
|
||||
if (kws->buffer) ks_pool_free(kws->pool, kws->buffer);
|
||||
if (kws->bbuffer) ks_pool_free(kws->pool, kws->bbuffer);
|
||||
if (kws->buffer) ks_pool_free(kws->pool, &kws->buffer);
|
||||
if (kws->bbuffer) ks_pool_free(kws->pool, &kws->bbuffer);
|
||||
|
||||
kws->buffer = kws->bbuffer = NULL;
|
||||
|
||||
ks_pool_free(kws->pool, kws);
|
||||
ks_pool_free(kws->pool, &kws);
|
||||
kws = NULL;
|
||||
}
|
||||
|
||||
@@ -786,7 +786,7 @@ KS_DECLARE(ks_ssize_t) kws_close(kws_t *kws, int16_t reason)
|
||||
kws->down = 1;
|
||||
|
||||
if (kws->uri) {
|
||||
ks_pool_free(kws->pool, kws->uri);
|
||||
ks_pool_free(kws->pool, &kws->uri);
|
||||
kws->uri = NULL;
|
||||
}
|
||||
|
||||
|
||||
+31
-16
@@ -4,6 +4,11 @@ check_PROGRAMS =
|
||||
|
||||
EXTRA_DIST = tap.h
|
||||
|
||||
check_PROGRAMS += testbuckets
|
||||
testbuckets_SOURCES = testbuckets.c tap.c
|
||||
testbuckets_CFLAGS = $(AM_CFLAGS)
|
||||
testbuckets_LDADD = $(TEST_LDADD)
|
||||
|
||||
check_PROGRAMS += testpools
|
||||
testpools_SOURCES = testpools.c tap.c
|
||||
testpools_CFLAGS = $(AM_CFLAGS)
|
||||
@@ -49,25 +54,35 @@ testwebsock_SOURCES = testwebsock.c tap.c
|
||||
testwebsock_CFLAGS = $(AM_CFLAGS)
|
||||
testwebsock_LDADD = $(TEST_LDADD)
|
||||
|
||||
check_PROGRAMS += testdht
|
||||
testdht_SOURCES = testdht.c tap.c
|
||||
testdht_CFLAGS = $(AM_CFLAGS)
|
||||
testdht_LDADD = $(TEST_LDADD)
|
||||
#check_PROGRAMS += testdht
|
||||
#testdht_SOURCES = testdht.c tap.c
|
||||
#testdht_CFLAGS = $(AM_CFLAGS)
|
||||
#testdht_LDADD = $(TEST_LDADD)
|
||||
|
||||
check_PROGRAMS += testdht_net
|
||||
testdht_net_SOURCES = testdht-net.c tap.c
|
||||
testdht_net_CFLAGS = $(AM_CFLAGS)
|
||||
testdht_net_LDADD = $(TEST_LDADD)
|
||||
check_PROGRAMS += testdht2
|
||||
testdht2_SOURCES = testdht2.c tap.c
|
||||
testdht2_CFLAGS = $(AM_CFLAGS)
|
||||
testdht2_LDADD = $(TEST_LDADD)
|
||||
|
||||
check_PROGRAMS += testdht_msg
|
||||
testdht_msg_SOURCES = testdht-msg.c tap.c
|
||||
testdht_msg_CFLAGS = $(AM_CFLAGS)
|
||||
testdht_msg_LDADD = $(TEST_LDADD)
|
||||
check_PROGRAMS += nodeidgen
|
||||
nodeidgen_SOURCES = nodeidgen.c tap.c
|
||||
nodeidgen_CFLAGS = $(AM_CFLAGS)
|
||||
nodeidgen_LDADD = $(TEST_LDADD)
|
||||
|
||||
check_PROGRAMS += dht_example
|
||||
dht_example_SOURCES = dht-example.c
|
||||
dht_example_CFLAGS = $(AM_CFLAGS)
|
||||
dht_example_LDADD = $(abs_top_builddir)/libks.la $(openssl_LIBS) -ledit -lpthread
|
||||
#check_PROGRAMS += testdht_net
|
||||
#testdht_net_SOURCES = testdht-net.c tap.c
|
||||
#testdht_net_CFLAGS = $(AM_CFLAGS)
|
||||
#testdht_net_LDADD = $(TEST_LDADD)
|
||||
|
||||
#check_PROGRAMS += testdht_msg
|
||||
#testdht_msg_SOURCES = testdht-msg.c tap.c
|
||||
#testdht_msg_CFLAGS = $(AM_CFLAGS)
|
||||
#testdht_msg_LDADD = $(TEST_LDADD)
|
||||
|
||||
#check_PROGRAMS += dht_example
|
||||
#dht_example_SOURCES = dht-example.c
|
||||
#dht_example_CFLAGS = $(AM_CFLAGS)
|
||||
#dht_example_LDADD = $(abs_top_builddir)/libks.la $(openssl_LIBS) -ledit -lpthread
|
||||
|
||||
#check_PROGRAMS += libtorrent_example
|
||||
#libtorrent_example_SOURCES = libtorrent-example.c
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <ks.h>
|
||||
#include <ks_dht.h>
|
||||
#include <ks_dht-int.h>
|
||||
#include <tap.h>
|
||||
|
||||
int main() {
|
||||
uint8_t nodeid[KS_DHT_NODEID_SIZE];
|
||||
char buf[KS_DHT_NODEID_SIZE * 2 + 1];
|
||||
|
||||
randombytes_buf(nodeid, KS_DHT_NODEID_SIZE);
|
||||
|
||||
ks_dht_hex(nodeid, buf, KS_DHT_NODEID_SIZE);
|
||||
|
||||
printf(buf);
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,385 @@
|
||||
#include <ks.h>
|
||||
#include <ks_dht.h>
|
||||
#include <ks_dht-int.h>
|
||||
#include <tap.h>
|
||||
|
||||
ks_dht_storageitem_skey_t sk;
|
||||
ks_dht_storageitem_pkey_t pk;
|
||||
|
||||
ks_status_t dht2_updated_callback(ks_dht_t *dht, ks_dht_storageitem_t *item)
|
||||
{
|
||||
diag("dht2_updated_callback\n");
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ks_status_t dht2_distribute_callback(ks_dht_t *dht, ks_dht_storageitem_t *item)
|
||||
{
|
||||
diag("dht2_distribute_callback\n");
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ks_status_t dht2_put_callback(ks_dht_t *dht, ks_dht_job_t *job)
|
||||
{
|
||||
diag("dht2_put_callback\n");
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ks_status_t dht2_get_token_callback(ks_dht_t *dht, ks_dht_job_t *job)
|
||||
{
|
||||
char buf[KS_DHT_TOKEN_SIZE * 2 + 1];
|
||||
const char *v = "Hello World!";
|
||||
size_t v_len = strlen(v);
|
||||
ks_dht_storageitem_signature_t sig;
|
||||
ks_dht_storageitem_t *mutable = NULL;
|
||||
|
||||
diag("dht2_get_token_callback %s\n", ks_dht_hex(job->response_token.token, buf, KS_DHT_TOKEN_SIZE));
|
||||
|
||||
ks_dht_storageitem_signature_generate(&sig, &sk, NULL, 0, 1, (uint8_t *)v, v_len);
|
||||
// @todo check if exists
|
||||
ks_dht_storageitem_create_mutable(&mutable, dht->pool, &job->query_target, (uint8_t *)v, v_len, &pk, NULL, 0, 1, &sig);
|
||||
mutable->sk = sk;
|
||||
ks_dht_storageitems_insert(dht, mutable);
|
||||
|
||||
ks_dht_put(dht, &job->raddr, dht2_put_callback, NULL, &job->response_token, 0, mutable);
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ks_status_t dht2_search_callback(ks_dht_t *dht, ks_dht_job_t *job)
|
||||
{
|
||||
ks_dht_search_t *search = (ks_dht_search_t *)job->data;
|
||||
diag("dht2_search_callback %d\n", search->results_length);
|
||||
return KS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int main() {
|
||||
//ks_size_t buflen;
|
||||
ks_status_t err;
|
||||
int mask = 0;
|
||||
ks_dht_nodeid_t nodeid;
|
||||
ks_dht_t *dht1 = NULL;
|
||||
ks_dht_t *dht2 = NULL;
|
||||
ks_dht_t *dht3 = NULL;
|
||||
ks_dht_endpoint_t *ep1;
|
||||
ks_dht_endpoint_t *ep2;
|
||||
ks_dht_endpoint_t *ep3;
|
||||
ks_bool_t have_v4, have_v6;
|
||||
char v4[48] = {0}, v6[48] = {0};
|
||||
ks_sockaddr_t addr;
|
||||
ks_sockaddr_t raddr1;
|
||||
//ks_sockaddr_t raddr2;
|
||||
//ks_sockaddr_t raddr3;
|
||||
ks_dht_nodeid_t target;
|
||||
//ks_dht_storageitem_t *immutable = NULL;
|
||||
ks_dht_storageitem_t *mutable1 = NULL;
|
||||
ks_dht_storageitem_t *mutable2 = NULL;
|
||||
const char *v = "Hello World!";
|
||||
size_t v_len = strlen(v);
|
||||
//ks_dht_storageitem_skey_t sk; //= { { 0xe0, 0x6d, 0x31, 0x83, 0xd1, 0x41, 0x59, 0x22, 0x84, 0x33, 0xed, 0x59, 0x92, 0x21, 0xb8, 0x0b,
|
||||
//0xd0, 0xa5, 0xce, 0x83, 0x52, 0xe4, 0xbd, 0xf0, 0x26, 0x2f, 0x76, 0x78, 0x6e, 0xf1, 0xc7, 0x4d,
|
||||
//0xb7, 0xe7, 0xa9, 0xfe, 0xa2, 0xc0, 0xeb, 0x26, 0x9d, 0x61, 0xe3, 0xb3, 0x8e, 0x45, 0x0a, 0x22,
|
||||
//0xe7, 0x54, 0x94, 0x1a, 0xc7, 0x84, 0x79, 0xd6, 0xc5, 0x4e, 0x1f, 0xaf, 0x60, 0x37, 0x88, 0x1d } };
|
||||
//ks_dht_storageitem_pkey_t pk; //= { { 0x77, 0xff, 0x84, 0x90, 0x5a, 0x91, 0x93, 0x63, 0x67, 0xc0, 0x13, 0x60, 0x80, 0x31, 0x04, 0xf9,
|
||||
//0x24, 0x32, 0xfc, 0xd9, 0x04, 0xa4, 0x35, 0x11, 0x87, 0x6d, 0xf5, 0xcd, 0xf3, 0xe7, 0xe5, 0x48 } };
|
||||
//uint8_t sk1[KS_DHT_STORAGEITEM_SKEY_SIZE];
|
||||
//uint8_t pk1[KS_DHT_STORAGEITEM_PKEY_SIZE];
|
||||
ks_dht_storageitem_signature_t sig;
|
||||
//char sk_buf[KS_DHT_STORAGEITEM_SKEY_SIZE * 2 + 1];
|
||||
//char pk_buf[KS_DHT_STORAGEITEM_PKEY_SIZE * 2 + 1];
|
||||
//const char *test1vector = "3:seqi1e1:v12:Hello World!";
|
||||
//const char *test1vector = "4:salt6:foobar3:seqi1e1:v12:Hello World!";
|
||||
//size_t test1vector_len = strlen(test1vector);
|
||||
//uint8_t test1vector_sig[KS_DHT_STORAGEITEM_SIGNATURE_SIZE];
|
||||
//char test1vector_buf[KS_DHT_STORAGEITEM_SIGNATURE_SIZE * 2 + 1];
|
||||
|
||||
err = ks_init();
|
||||
ok(!err);
|
||||
|
||||
ks_global_set_default_logger(KS_LOG_LEVEL_INFO);
|
||||
|
||||
err = ks_find_local_ip(v4, sizeof(v4), &mask, AF_INET, NULL);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
have_v4 = !zstr_buf(v4);
|
||||
|
||||
//err = ks_find_local_ip(v6, sizeof(v6), NULL, AF_INET6, NULL);
|
||||
//ok(err == KS_STATUS_SUCCESS);
|
||||
have_v6 = KS_FALSE;//!zstr_buf(v6);
|
||||
|
||||
ok(have_v4 || have_v6);
|
||||
|
||||
if (have_v4) {
|
||||
diag("Binding to %s on ipv4\n", v4);
|
||||
}
|
||||
if (have_v6) {
|
||||
diag("Binding to %s on ipv6\n", v6);
|
||||
}
|
||||
|
||||
ks_dht_dehex(nodeid.id, "0000000000000000000000000000000000000001", KS_DHT_NODEID_SIZE);
|
||||
err = ks_dht_create(&dht1, NULL, NULL, &nodeid);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
ks_dht_dehex(nodeid.id, "0000000000000000000000000000000000000002", KS_DHT_NODEID_SIZE);
|
||||
err = ks_dht_create(&dht2, NULL, NULL, &nodeid);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
ks_dht_dehex(nodeid.id, "0000000000000000000000000000000000000003", KS_DHT_NODEID_SIZE);
|
||||
err = ks_dht_create(&dht3, NULL, NULL, &nodeid);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
if (have_v4) {
|
||||
err = ks_addr_set(&addr, v4, KS_DHT_DEFAULT_PORT, AF_INET);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
err = ks_dht_bind(dht1, &addr, &ep1);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
raddr1 = addr;
|
||||
|
||||
err = ks_addr_set(&addr, v4, KS_DHT_DEFAULT_PORT + 1, AF_INET);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
err = ks_dht_bind(dht2, &addr, &ep2);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
//raddr2 = addr;
|
||||
|
||||
err = ks_addr_set(&addr, v4, KS_DHT_DEFAULT_PORT + 2, AF_INET);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
err = ks_dht_bind(dht3, &addr, &ep3);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
//raddr3 = addr;
|
||||
}
|
||||
|
||||
if (have_v6) {
|
||||
err = ks_addr_set(&addr, v6, KS_DHT_DEFAULT_PORT, AF_INET6);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
err = ks_dht_bind(dht1, &addr, NULL);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
err = ks_addr_set(&addr, v6, KS_DHT_DEFAULT_PORT + 1, AF_INET6);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
err = ks_dht_bind(dht2, &addr, NULL);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
err = ks_addr_set(&addr, v6, KS_DHT_DEFAULT_PORT + 2, AF_INET6);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
|
||||
err = ks_dht_bind(dht3, &addr, NULL);
|
||||
ok(err == KS_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
diag("Ping test\n");
|
||||
|
||||
ks_dht_ping(dht2, &raddr1, NULL, NULL); // (QUERYING)
|
||||
|
||||
ks_dht_pulse(dht2, 100); // Send queued ping from dht2 to dht1 (RESPONDING)
|
||||
|
||||
ks_dht_pulse(dht1, 100); // Receive and process ping query from dht2, queue and send ping response
|
||||
|
||||
ok(ks_dhtrt_find_node(dht1->rt_ipv4, dht2->nodeid) == NULL); // The node should be dubious, and thus not be returned as good yet
|
||||
|
||||
ks_dht_pulse(dht2, 100); // Receive and process ping response from dht1 (PROCESSING then COMPLETING)
|
||||
|
||||
ok(ks_dhtrt_find_node(dht2->rt_ipv4, dht1->nodeid) != NULL); // The node should be good, and thus be returned as good
|
||||
|
||||
ks_dht_pulse(dht2, 100); // Call finish callback and purge the job (COMPLETING)
|
||||
|
||||
diag("Pulsing for route table pings\n"); // Wait for route table pinging to catch up
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ks_dht_pulse(dht1, 100);
|
||||
ks_dht_pulse(dht2, 100);
|
||||
ks_dht_pulse(dht3, 100);
|
||||
}
|
||||
ok(ks_dhtrt_find_node(dht1->rt_ipv4, dht2->nodeid) != NULL); // The node should be good by now, and thus be returned as good
|
||||
|
||||
|
||||
ks_dht_ping(dht3, &raddr1, NULL, NULL); // (QUERYING)
|
||||
|
||||
ks_dht_pulse(dht3, 100); // Send queued ping from dht3 to dht1 (RESPONDING)
|
||||
|
||||
ks_dht_pulse(dht1, 100); // Receive and process ping query from dht3, queue and send ping response
|
||||
|
||||
ok(ks_dhtrt_find_node(dht1->rt_ipv4, dht3->nodeid) == NULL); // The node should be dubious, and thus not be returned as good yet
|
||||
|
||||
ks_dht_pulse(dht3, 100); // Receive and process ping response from dht1 (PROCESSING then COMPLETING)
|
||||
|
||||
ok(ks_dhtrt_find_node(dht3->rt_ipv4, dht1->nodeid) != NULL); // The node should be good, and thus be returned as good
|
||||
|
||||
ks_dht_pulse(dht3, 100); // Call finish callback and purge the job (COMPLETING)
|
||||
|
||||
diag("Pulsing for route table pings\n"); // Wait for route table pinging to catch up
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ks_dht_pulse(dht1, 100);
|
||||
ks_dht_pulse(dht2, 100);
|
||||
ks_dht_pulse(dht3, 100);
|
||||
}
|
||||
ok(ks_dhtrt_find_node(dht1->rt_ipv4, dht2->nodeid) != NULL); // The node should be good by now, and thus be returned as good
|
||||
|
||||
// Test bootstrap find_node from dht3 to dht1 to find dht2 nodeid
|
||||
|
||||
/*
|
||||
diag("Find_Node test\n");
|
||||
|
||||
ks_dht_findnode(dht3, NULL, &raddr1, NULL, NULL, &dht2->nodeid);
|
||||
|
||||
ks_dht_pulse(dht3, 100); // Send queued findnode from dht3 to dht1
|
||||
|
||||
ks_dht_pulse(dht1, 100); // Receive and process findnode query from dht3, queue and send findnode response
|
||||
|
||||
ok(ks_dhtrt_find_node(dht1->rt_ipv4, dht3->nodeid) == NULL); // The node should be dubious, and thus not be returned as good yet
|
||||
|
||||
ks_dht_pulse(dht3, 100); // Receive and process findnode response from dht1
|
||||
|
||||
ks_dht_pulse(dht3, 100); // Call finish callback and purge the job (COMPLETING)
|
||||
|
||||
ok(ks_dhtrt_find_node(dht3->rt_ipv4, dht2->nodeid) == NULL); // The node should be dubious, and thus not be returned as good yet
|
||||
|
||||
diag("Pulsing for route table pings\n"); // Wait for route table pinging to catch up
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ks_dht_pulse(dht1, 100);
|
||||
ks_dht_pulse(dht2, 100);
|
||||
ks_dht_pulse(dht3, 100);
|
||||
}
|
||||
ok(ks_dhtrt_find_node(dht3->rt_ipv4, dht2->nodeid) != NULL); // The node should be good by now, and thus be returned as good
|
||||
*/
|
||||
|
||||
diag("Search test\n");
|
||||
|
||||
ks_dht_search(dht3, dht2_search_callback, NULL, dht3->rt_ipv4, &dht2->nodeid);
|
||||
diag("Pulsing for route table pings\n"); // Wait for route table pinging to catch up
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
ks_dht_pulse(dht1, 100);
|
||||
ks_dht_pulse(dht2, 100);
|
||||
ks_dht_pulse(dht3, 100);
|
||||
}
|
||||
|
||||
//diag("Get test\n");
|
||||
|
||||
|
||||
/*
|
||||
ks_dht_storageitem_target_immutable((uint8_t *)v, v_len, &target);
|
||||
ks_dht_storageitem_create_immutable(&immutable, dht1->pool, &target, (uint8_t *)v, v_len);
|
||||
ks_dht_storageitems_insert(dht1, immutable);
|
||||
*/
|
||||
|
||||
/*
|
||||
crypto_sign_keypair(pk.key, sk.key);
|
||||
|
||||
ks_dht_storageitem_signature_generate(&sig, &sk, NULL, 0, 1, (uint8_t *)v, v_len);
|
||||
ks_dht_storageitem_target_mutable(&pk, NULL, 0, &target);
|
||||
ks_dht_storageitem_create_mutable(&mutable, dht1->pool, &target, (uint8_t *)v, v_len, &pk, NULL, 0, 1, &sig);
|
||||
mutable->sk = sk;
|
||||
ks_dht_storageitems_insert(dht1, mutable);
|
||||
|
||||
ks_dht_get(dht2, &raddr1, dht2_get_callback, NULL, &target, NULL, 0);
|
||||
|
||||
ks_dht_pulse(dht2, 100); // send get query
|
||||
|
||||
ks_dht_pulse(dht1, 100); // receive get query and send get response
|
||||
|
||||
ks_dht_pulse(dht2, 100); // receive get response
|
||||
|
||||
ok(ks_dht_storageitems_find(dht2, &target) != NULL); // item should be verified and stored
|
||||
|
||||
ks_dht_pulse(dht2, 100); // Call finish callback and purge the job (COMPLETING)
|
||||
*/
|
||||
|
||||
/*
|
||||
diag("Put test\n");
|
||||
|
||||
crypto_sign_keypair(pk.key, sk.key);
|
||||
|
||||
ks_dht_storageitem_target_mutable(&pk, NULL, 0, &target);
|
||||
|
||||
ks_dht_get(dht2, &raddr1, dht2_get_token_callback, NULL, &target, NULL, 0); // create job
|
||||
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
ks_dht_pulse(dht1, 100);
|
||||
ks_dht_pulse(dht2, 100);
|
||||
ks_dht_pulse(dht3, 100);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
diag("Publish test\n");
|
||||
|
||||
crypto_sign_keypair(pk.key, sk.key);
|
||||
|
||||
ks_dht_storageitem_target_mutable(&pk, NULL, 0, &target);
|
||||
|
||||
ks_dht_storageitem_signature_generate(&sig, &sk, NULL, 0, 1, (uint8_t *)v, v_len);
|
||||
|
||||
ks_dht_storageitem_create_mutable(&mutable, dht2->pool, &target, (uint8_t *)v, v_len, &pk, NULL, 0, 1, &sig);
|
||||
mutable->sk = sk;
|
||||
ks_dht_storageitems_insert(dht2, mutable);
|
||||
|
||||
ks_dht_publish(dht2, &raddr1, dht2_put_callback, NULL, 0, mutable); // create job
|
||||
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
ks_dht_pulse(dht1, 100);
|
||||
ks_dht_pulse(dht2, 100);
|
||||
ks_dht_pulse(dht3, 100);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
diag("Distribute test\n");
|
||||
|
||||
crypto_sign_keypair(pk.key, sk.key);
|
||||
|
||||
ks_dht_storageitem_target_mutable(&pk, NULL, 0, &target);
|
||||
|
||||
ks_dht_storageitem_signature_generate(&sig, &sk, NULL, 0, 1, (uint8_t *)v, v_len);
|
||||
|
||||
ks_dht_storageitem_create_mutable(&mutable2, dht2->pool, &target, (uint8_t *)v, v_len, &pk, NULL, 0, 1, &sig);
|
||||
mutable2->sk = sk;
|
||||
ks_dht_storageitems_insert(dht2, mutable2);
|
||||
|
||||
ks_dht_distribute(dht2, dht2_distribute_callback, NULL, dht2->rt_ipv4, 0, mutable2); // create job
|
||||
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
ks_dht_pulse(dht1, 100);
|
||||
ks_dht_pulse(dht2, 100);
|
||||
ks_dht_pulse(dht3, 100);
|
||||
}
|
||||
ks_dht_storageitem_dereference(mutable2);
|
||||
ok(mutable2->refc == 0);
|
||||
|
||||
mutable1 = ks_dht_storageitems_find(dht1, &target);
|
||||
ok(mutable1 != NULL);
|
||||
|
||||
ks_dht_storageitem_callback(mutable1, dht2_updated_callback);
|
||||
ks_dht_storageitem_callback(mutable2, dht2_updated_callback);
|
||||
|
||||
ks_dht_storageitem_signature_generate(&sig, &sk, NULL, 0, 2, (uint8_t *)v, v_len);
|
||||
mutable1->seq = 2;
|
||||
mutable1->sig = sig;
|
||||
|
||||
//ks_dht_storageitem_signature_generate(&sig, &sk, NULL, 0, 2, (uint8_t *)v, v_len);
|
||||
//mutable2->seq = 2;
|
||||
//mutable2->sig = sig;
|
||||
|
||||
ks_dht_distribute(dht2, dht2_distribute_callback, NULL, dht2->rt_ipv4, 0, mutable2);
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
ks_dht_pulse(dht1, 100);
|
||||
ks_dht_pulse(dht2, 100);
|
||||
ks_dht_pulse(dht3, 100);
|
||||
}
|
||||
ks_dht_storageitem_dereference(mutable1);
|
||||
|
||||
/* Cleanup and shutdown */
|
||||
diag("Cleanup\n");
|
||||
|
||||
ks_dht_destroy(&dht3);
|
||||
|
||||
ks_dht_destroy(&dht2);
|
||||
|
||||
ks_dht_destroy(&dht1);
|
||||
|
||||
ks_shutdown();
|
||||
|
||||
done_testing();
|
||||
}
|
||||
@@ -132,7 +132,7 @@ int test3(void)
|
||||
char *A, *B, *C;
|
||||
|
||||
ks_pool_open(&pool);
|
||||
ks_hash_create(&hash, KS_HASH_MODE_ARBITRARY, KS_HASH_FLAG_NONE, pool);
|
||||
ks_hash_create(&hash, KS_HASH_MODE_ARBITRARY, KS_HASH_FLAG_NOLOCK, pool);
|
||||
ks_hash_set_keysize(hash, TEST3_SIZE);
|
||||
|
||||
randombytes_buf(data, sizeof(data));
|
||||
|
||||
@@ -84,7 +84,7 @@ int main(int argc, char **argv)
|
||||
|
||||
printf("FREE:\n");
|
||||
|
||||
status = ks_pool_safe_free(pool, str);
|
||||
status = ks_pool_free(pool, &str);
|
||||
if (status != KS_STATUS_SUCCESS) {
|
||||
fprintf(stderr, "FREE ERR: [%s]\n", ks_pool_strerror(err));
|
||||
exit(255);
|
||||
@@ -122,7 +122,7 @@ int main(int argc, char **argv)
|
||||
|
||||
printf("FREE OBJ:\n");
|
||||
|
||||
status = ks_pool_safe_free(pool, foo);
|
||||
status = ks_pool_free(pool, &foo);
|
||||
ok(status == KS_STATUS_SUCCESS);
|
||||
if (status != KS_STATUS_SUCCESS) {
|
||||
fprintf(stderr, "FREE OBJ ERR: [%s]\n", ks_pool_strerror(status));
|
||||
@@ -181,7 +181,7 @@ int main(int argc, char **argv)
|
||||
|
||||
printf("FREE 2:\n");
|
||||
|
||||
status = ks_pool_free(pool, str);
|
||||
status = ks_pool_free(pool, &str);
|
||||
ok(status == KS_STATUS_SUCCESS);
|
||||
if (status != KS_STATUS_SUCCESS) {
|
||||
fprintf(stderr, "FREE2 ERR: [%s]\n", ks_pool_strerror(status));
|
||||
|
||||
@@ -10,7 +10,7 @@ static void *test1_thread(ks_thread_t *thread, void *data)
|
||||
while(ks_q_pop(q, &pop) == KS_STATUS_SUCCESS) {
|
||||
//int *i = (int *)pop;
|
||||
//printf("POP %d\n", *i);
|
||||
ks_pool_free(thread->pool, pop);
|
||||
ks_pool_free(thread->pool, &pop);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -19,7 +19,7 @@ static void *test1_thread(ks_thread_t *thread, void *data)
|
||||
static void do_flush(ks_q_t *q, void *ptr, void *flush_data)
|
||||
{
|
||||
ks_pool_t *pool = (ks_pool_t *)flush_data;
|
||||
ks_pool_free(pool, ptr);
|
||||
ks_pool_free(pool, &ptr);
|
||||
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ static void *test2_thread(ks_thread_t *thread, void *data)
|
||||
//int *i = (int *)pop;
|
||||
//printf("%p POP %d\n", (void *)pthread_self(), *i);
|
||||
popped++;
|
||||
ks_pool_free(thread->pool, pop);
|
||||
ks_pool_free(thread->pool, &pop);
|
||||
} else if (status == KS_STATUS_INACTIVE) {
|
||||
break;
|
||||
} else if (t2->try && ks_q_size(t2->q)) {
|
||||
|
||||
@@ -185,7 +185,7 @@ static void *thread_test_function_atatched(ks_thread_t *thread, void *data)
|
||||
|
||||
for (i = 0; i < LOOP_COUNT; i++) {
|
||||
if (last_mem) {
|
||||
ks_pool_safe_free(thread->pool, last_mem);
|
||||
ks_pool_free(thread->pool, &last_mem);
|
||||
}
|
||||
mem = ks_pool_alloc(thread->pool, 1024);
|
||||
last_mem = mem;
|
||||
@@ -246,7 +246,7 @@ static void check_thread_priority(void)
|
||||
ok( ks_thread_priority(thread_p) == KS_PRI_IMPORTANT );
|
||||
end_todo;
|
||||
|
||||
ks_pool_free(pool, thread_p);
|
||||
ks_pool_free(pool, &thread_p);
|
||||
}
|
||||
|
||||
static void join_threads(void)
|
||||
|
||||
Reference in New Issue
Block a user