aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE849
-rw-r--r--README.md1
-rw-r--r--src/gnunet/config/config.go13
-rw-r--r--src/gnunet/core/peer.go36
-rw-r--r--src/gnunet/crypto/gns.go35
-rw-r--r--src/gnunet/crypto/gns_test.go150
-rw-r--r--src/gnunet/crypto/hash.go3
-rw-r--r--src/gnunet/crypto/key_derivation.go1
-rw-r--r--src/gnunet/crypto/key_exchange.go4
-rw-r--r--src/gnunet/crypto/signature.go1
-rw-r--r--src/gnunet/crypto/symmetric.go19
-rw-r--r--src/gnunet/enums/dht.go23
-rw-r--r--src/gnunet/enums/gns.go1
-rw-r--r--src/gnunet/message/message.go8
-rw-r--r--src/gnunet/message/msg_core.go33
-rw-r--r--src/gnunet/message/msg_dht.go2
-rw-r--r--src/gnunet/message/msg_gns.go16
-rw-r--r--src/gnunet/message/msg_namecache.go4
-rw-r--r--src/gnunet/message/msg_transport.go207
-rw-r--r--src/gnunet/service/client.go3
-rw-r--r--src/gnunet/service/gns/block.go185
-rw-r--r--src/gnunet/service/gns/block_handler.go398
-rw-r--r--src/gnunet/service/gns/box.go151
-rw-r--r--src/gnunet/service/gns/dns.go61
-rw-r--r--src/gnunet/service/gns/module.go257
-rw-r--r--src/gnunet/service/gns/service.go12
-rw-r--r--src/gnunet/service/service.go13
-rw-r--r--src/gnunet/transport/channel.go1
-rw-r--r--src/gnunet/transport/channel_netw.go39
-rw-r--r--src/gnunet/transport/connection.go9
-rw-r--r--src/gnunet/transport/session.go3
-rw-r--r--src/gnunet/util/address.go55
-rw-r--r--src/gnunet/util/array.go10
-rw-r--r--src/gnunet/util/format.go13
-rw-r--r--src/gnunet/util/id.go3
-rw-r--r--src/gnunet/util/peer_id.go3
-rw-r--r--src/gnunet/util/rnd.go8
37 files changed, 2030 insertions, 600 deletions
diff --git a/LICENSE b/LICENSE
index 0a4f9a1..6cfcd65 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,235 +1,616 @@
1GNU AFFERO GENERAL PUBLIC LICENSE 1GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007
2Version 3, 19 November 2007 2Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
3
4Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5 3
6Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 4Everyone is permitted to copy and distribute verbatim copies of this license
7 5document, but changing it is not allowed.
8 Preamble 6
9 7Preamble
10The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. 8
11 9The GNU Affero General Public License is a free, copyleft license for software
12The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are 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. 10and other kinds of works, specifically designed to ensure cooperation with the
13 11community in the case of network server software.
14When 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. 12
15 13The licenses for most software and other practical works are designed to take
16Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. 14away your freedom to share and change the works. By contrast, our General
17 15Public Licenses are intended to guarantee your freedom to share and change all
18A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. 16versions of a program--to make sure it remains free software for all its users.
19 17
20The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. 18When we speak of free software, we are referring to freedom, not price. Our
21 19General Public Licenses are designed to make sure that you have the freedom to
22An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. 20distribute copies of free software (and charge for them if you wish), that you
23 21receive source code or can get it if you want it, that you can change the
24The precise terms and conditions for copying, distribution and modification follow. 22software or use pieces of it in new free programs, and that you know you can
25 23do these things.
26 TERMS AND CONDITIONS 24
27 25Developers that use our General Public Licenses protect your rights with two
280. Definitions. 26steps: (1) assert copyright on the software, and (2) offer you this License
29 27which gives you legal permission to copy, distribute and/or modify the software.
30"This License" refers to version 3 of the GNU Affero General Public License. 28
31 29A secondary benefit of defending all users' freedom is that improvements made
32"Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. 30in alternate versions of the program, if they receive widespread use, become
33 31available for other developers to incorporate. Many developers of free
34"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. 32software are heartened and encouraged by the resulting cooperation. However,
35 33in the case of software used on network servers, this result may fail to come
36To "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. 34about. The GNU General Public License permits making a modified version and
37 35letting the public access it on a server without ever releasing its source code
38A "covered work" means either the unmodified Program or a work based on the Program. 36to the public.
39 37
40To "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. 38The GNU Affero General Public License is designed specifically to ensure that,
41 39in such cases, the modified source code becomes available to the community. It
42To "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. 40requires the operator of a network server to provide the source code of the
43 41modified version running there to the users of that server. Therefore, public
44An 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. 42use of a modified version, on a publicly accessible server, gives the public
45 43access to the source code of the modified version.
461. Source Code. 44
47The "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. 45An older license, called the Affero General Public License and published by
48 46Affero, was designed to accomplish similar goals. This is a different license,
49A "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. 47not a version of the Affero GPL, but Affero has released a new version of the
50 48Affero GPL which permits relicensing under this license.
51The "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. 49
52 50The precise terms and conditions for copying, distribution and modification
53The "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 51follow.
54subprograms and other parts of the work. 52
55 53TERMS AND CONDITIONS
56The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. 54
57 550. Definitions.
58The Corresponding Source for a work in source code form is that same work. 56
59 57"This License" refers to version 3 of the GNU Affero General Public License.
602. Basic Permissions. 58
61All 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. 59"Copyright" also means copyright-like laws that apply to other kinds of works,
62 60such as semiconductor masks.
63You 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. 61
64 62"The Program" refers to any copyrightable work licensed under this License.
65Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 63Each licensee is addressed as "you". "Licensees" and "recipients" may be
66 64individuals or organizations.
673. Protecting Users' Legal Rights From Anti-Circumvention Law. 65
68No 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. 66To "modify" a work means to copy from or adapt all or part of the work in a
69 67fashion requiring copyright permission, other than the making of an exact copy.
70When 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. 68 The resulting work is called a "modified version" of the earlier work or a
71 69work "based on" the earlier work.
724. Conveying Verbatim Copies. 70
73You 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. 71A "covered work" means either the unmodified Program or a work based on the
74 72Program.
75You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 73
76 74To "propagate" a work means to do anything with it that, without permission,
775. Conveying Modified Source Versions. 75would make you directly or secondarily liable for infringement under applicable
78You 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: 76copyright law, except executing it on a computer or modifying a private copy.
79 77Propagation includes copying, distribution (with or without modification),
80 a) The work must carry prominent notices stating that you modified it, and giving a relevant date. 78making available to the public, and in some countries other activities as well.
81 79
82 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". 80To "convey" a work means any kind of propagation that enables other parties to
83 81make or receive copies. Mere interaction with a user through a computer
84 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. 82network, with no transfer of a copy, is not conveying.
85 83
86 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. 84An interactive user interface displays "Appropriate Legal Notices" to the
87 85extent that it includes a convenient and prominently visible feature that
88A 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. 86(1) displays an appropriate copyright notice, and (2) tells the user that
89 87there is no warranty for the work (except to the extent that warranties are
906. Conveying Non-Source Forms. 88provided), that licensees may convey the work under this License, and how to
91You 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: 89view a copy of this License. If the interface presents a list of user commands
92 90or options, such as a menu, a prominent item in the list meets this criterion.
93 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. 91
94 921. Source Code.
95 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. 93
96 94The "source code" for a work means the preferred form of the work for making
97 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. 95modifications to it. "Object code" means any non-source form of a work.
98 96
99 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. 97A "Standard Interface" means an interface that either is an official standard
100 98defined by a recognized standards body, or, in the case of interfaces specified
101 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. 99for a particular programming language, one that is widely used among developers
102 100working in that language.
103A 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. 101
104 102The "System Libraries" of an executable work include anything, other than the
105A "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. 103work as a whole, that (a) is included in the normal form of packaging a Major
106 104Component, but which is not part of that Major Component, and (b) serves only
107"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. 105to enable use of the work with that Major Component, or to implement a Standard
108 106Interface for which an implementation is available to the public in source code
109If 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). 107form. A "Major Component", in this context, means a major essential component
110 108(kernel, window system, and so on) of the specific operating system (if any) on
111The 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. 109which the executable work runs, or a compiler used to produce the work, or an
112 110object code interpreter used to run it.
113Corresponding 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. 111
114 112The "Corresponding Source" for a work in object code form means all the source
1157. Additional Terms. 113code needed to generate, install, and (for an executable work) run the object
116"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. 114code and to modify the work, including scripts to control those activities.
117 115However, it does not include the work's System Libraries, or general-purpose
118When 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. 116tools or generally available free programs which are used unmodified in
119 117performing those activities but which are not part of the work. For example,
120Notwithstanding 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: 118Corresponding Source includes interface definition files associated with source
121 119files for the work, and the source code for shared libraries and dynamically
122 a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or 120linked subprograms that the work is specifically designed to require, such as
123 121by intimate data communication or control flow between those subprograms and
124 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 122other parts of the work.
125 123
126 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 124The Corresponding Source need not include anything that users can regenerate
127 125automatically from other parts of the Corresponding Source.
128 d) Limiting the use for publicity purposes of names of licensors or authors of the material; or 126
129 127The Corresponding Source for a work in source code form is that same work.
130 e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or 128
131 1292. Basic Permissions.
132 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. 130
133 131All rights granted under this License are granted for the term of copyright on
134All 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. 132the Program, and are irrevocable provided the stated conditions are met. This
135 133License explicitly affirms your unlimited permission to run the unmodified
136If 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. 134Program. The output from running a covered work is covered by this License
137 135only if the output, given its content, constitutes a covered work. This
138Additional 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. 136License acknowledges your rights of fair use or other equivalent, as provided
139 137by copyright law.
1408. Termination. 138
141 139You may make, run and propagate covered works that you do not convey, without
142You 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). 140conditions so long as your license otherwise remains in force. You may convey
143 141covered works to others for the sole purpose of having them make modifications
144However, 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. 142exclusively for you, or provide you with facilities for running those works,
145 143provided that you comply with the terms of this License in conveying all
146Moreover, 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. 144material for which you do not control copyright. Those thus making or running
147 145the covered works for you must do so exclusively on your behalf, under your
148Termination 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. 146direction and control, on terms that prohibit them from making any copies of
149 147your copyrighted material outside their relationship with you.
1509. Acceptance Not Required for Having Copies. 148
151 149Conveying under any other circumstances is permitted solely under the
152You 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. 150conditions stated below. Sublicensing is not allowed; section 10 makes it
153 151unnecessary.
15410. Automatic Licensing of Downstream Recipients. 152
155 1533. Protecting Users' Legal Rights From Anti-Circumvention Law.
156Each 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. 154
157 155No covered work shall be deemed part of an effective technological measure
158An "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. 156under any applicable law fulfilling obligations under article 11 of the WIPO
159 157copyright treaty adopted on 20 December 1996, or similar laws prohibiting or
160You 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. 158restricting circumvention of such measures.
161 159
16211. Patents. 160When you convey a covered work, you waive any legal power to forbid
163 161circumvention of technological measures to the extent such circumvention is
164A "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". 162effected by exercising rights under this License with respect to the covered
165 163work, and you disclaim any intention to limit operation or modification of the
166A 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. 164work as a means of enforcing, against the work's users, your or third parties'
167 165legal rights to forbid circumvention of technological measures.
168Each 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. 166
169 1674. Conveying Verbatim Copies.
170In 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 s ue 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. 168
171 169You may convey verbatim copies of the Program's source code as you receive it,
172If 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 170in any medium, provided that you conspicuously and appropriately publish on
173license 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. 171each copy an appropriate copyright notice; keep intact all notices stating
174 172that this License and any non-permissive terms added in accord with section
175If, 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. 1737 apply to the code; keep intact all notices of the absence of any warranty;
176 174and give all recipients a copy of this License along with the Program.
177A 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. 175
178 176You may charge any price or no price for each copy that you convey, and you
179Nothing 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. 177may offer support or warranty protection for a fee.
180 178
18112. No Surrender of Others' Freedom. 1795. Conveying Modified Source Versions.
182 180
183If 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 181You may convey a work based on the Program, or the modifications to produce it
184not 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. 182from the Program, in the form of source code under the terms of section 4,
185 183provided that you also meet all of these conditions:
18613. Remote Network Interaction; Use with the GNU General Public License. 184
187 185 a) The work must carry prominent notices stating that you modified it, and
188Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. 186 giving a relevant date.
189 187
190Notwithstanding 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 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 work with which it is combined will remain governed by version 3 of the GNU General Public License. 188 b) The work must carry prominent notices stating that it is released under
191 189 this License and any conditions added under section 7. This requirement
19214. Revised Versions of this License. 190 modifies the requirement in section 4 to "keep intact all notices".
193 191
194The Free Software Foundation may publish revised and/or new versions of the GNU Affero 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. 192 c) You must license the entire work, as a whole, under this License to
195 193 anyone who comes into possession of a copy. This License will
196Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero 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 Affero General Public License, you may choose any version ever published by the Free Software Foundation. 194 therefore apply, along with any applicable section 7 additional terms,
197 195 to the whole of the work, and all its parts, regardless of how they are
198If the Program specifies that a proxy can decide which future versions of the GNU Affero 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. 196 packaged. This License gives no permission to license the work in any
199 197 other way, but it does not invalidate such permission if you have
200Later 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. 198 separately received it.
201 199
20215. Disclaimer of Warranty. 200 d) If the work has interactive user interfaces, each must display
203 201 Appropriate Legal Notices; however, if the Program has interactive
204THERE 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. 202 interfaces that do not display Appropriate Legal Notices, your work
205 203 need not make them do so.
20616. Limitation of Liability. 204
207 205A compilation of a covered work with other separate and independent works,
208IN 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. 206which are not by their nature extensions of the covered work, and which are
209 207not combined with it such as to form a larger program, in or on a volume of a
21017. Interpretation of Sections 15 and 16. 208storage or distribution medium, is called an "aggregate" if the compilation
211 209and its resulting copyright are not used to limit the access or legal rights
212If 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. 210of the compilation's users beyond what the individual works permit. Inclusion
213 211of a covered work in an aggregate does not cause this License to apply to the
214END OF TERMS AND CONDITIONS 212other parts of the aggregate.
215 213
216 How to Apply These Terms to Your New Programs 2146. Conveying Non-Source Forms.
217 215
218If 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. 216You may convey a covered work in object code form under the terms of sections
219 2174 and 5, provided that you also convey the machine-readable Corresponding
220To 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. 218Source under the terms of this License, in one of these ways:
221 219
222 <one line to give the program's name and a brief idea of what it does.> 220 a) Convey the object code in, or embodied in, a physical product
223 Copyright (C) <year> <name of author> 221 (including a physical distribution medium), accompanied by the
224 222 Corresponding Source fixed on a durable physical medium customarily
225 This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 223 used for software interchange.
226 224
227 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 Affero General Public License for more details. 225 b) Convey the object code in, or embodied in, a physical product
228 226 (including a physical distribution medium), accompanied by a written
229 You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. 227 offer, valid for at least three years and valid for as long as you
230 228 offer spare parts or customer support for that product model, to give
231Also add information on how to contact you by electronic and paper mail. 229 anyone who possesses the object code either (1) a copy of the
232 230 Corresponding Source for all the software in the product that is
233If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. 231 covered by this License, on a durable physical medium customarily used
234 232 for software interchange, for a price no more than your reasonable cost
235You 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 AGPL, see <http://www.gnu.org/licenses/>. \ No newline at end of file 233 of physically performing this conveying of source, or (2) access to
234 copy the Corresponding Source from a network server at no charge.
235
236 c) Convey individual copies of the object code with a copy of the written
237 offer to provide the Corresponding Source. This alternative is allowed
238 only occasionally and noncommercially, and only if you received the
239 object code with such an offer, in accord with subsection 6b.
240
241 d) Convey the object code by offering access from a designated place
242 (gratis or for a charge), and offer equivalent access to the
243 Corresponding Source in the same way through the same place at no
244 further charge. You need not require recipients to copy the
245 Corresponding Source along with the object code. If the place to copy
246 the object code is a network server, the Corresponding Source may be on
247 a different server (operated by you or a third party) that supports
248 equivalent copying facilities, provided you maintain clear directions
249 next to the object code saying where to find the Corresponding Source.
250 Regardless of what server hosts the Corresponding Source, you remain
251 obligated to ensure that it is available for as long as needed to
252 satisfy these requirements.
253
254 e) Convey the object code using peer-to-peer transmission, provided you
255 inform other peers where the object code and Corresponding Source of
256 the work are being offered to the general public at no charge under
257 subsection 6d.
258
259A separable portion of the object code, whose source code is excluded from the
260Corresponding Source as a System Library, need not be included in conveying
261the object code work.
262
263A "User Product" is either (1) a "consumer product", which means any tangible
264personal property which is normally used for personal, family, or household
265purposes, or (2) anything designed or sold for incorporation into a dwelling.
266In determining whether a product is a consumer product, doubtful cases shall
267be resolved in favor of coverage. For a particular product received by a
268particular user, "normally used" refers to a typical or common use of that
269class of product, regardless of the status of the particular user or of the
270way in which the particular user actually uses, or expects or is expected to
271use, the product. A product is a consumer product regardless of whether the
272product has substantial commercial, industrial or non-consumer uses, unless
273such uses represent the only significant mode of use of the product.
274
275"Installation Information" for a User Product means any methods, procedures,
276authorization keys, or other information required to install and execute
277modified versions of a covered work in that User Product from a modified
278version of its Corresponding Source. The information must suffice to ensure
279that the continued functioning of the modified object code is in no case
280prevented or interfered with solely because modification has been made.
281
282If you convey an object code work under this section in, or with, or
283specifically for use in, a User Product, and the conveying occurs as part of
284a transaction in which the right of possession and use of the User Product is
285transferred to the recipient in perpetuity or for a fixed term (regardless of
286how the transaction is characterized), the Corresponding Source conveyed under
287this section must be accompanied by the Installation Information. But this
288requirement does not apply if neither you nor any third party retains the
289ability to install modified object code on the User Product (for example, the
290work has been installed in ROM).
291
292The requirement to provide Installation Information does not include a
293requirement to continue to provide support service, warranty, or updates for a
294work that has been modified or installed by the recipient, or for the User
295Product in which it has been modified or installed. Access to a network may
296be denied when the modification itself materially and adversely affects the
297operation of the network or violates the rules and protocols for communication
298across the network.
299
300Corresponding Source conveyed, and Installation Information provided, in
301accord with this section must be in a format that is publicly documented (and
302with an implementation available to the public in source code form), and must
303require no special password or key for unpacking, reading or copying.
304
3057. Additional Terms.
306
307"Additional permissions" are terms that supplement the terms of this License
308by making exceptions from one or more of its conditions. Additional permissions
309that are applicable to the entire Program shall be treated as though they were
310included in this License, to the extent that they are valid under applicable
311law. If additional permissions apply only to part of the Program, that part
312may be used separately under those permissions, but the entire Program remains
313governed by this License without regard to the additional permissions.
314
315When you convey a copy of a covered work, you may at your option remove any
316additional permissions from that copy, or from any part of it. (Additional
317permissions may be written to require their own removal in certain cases when
318you modify the work.) You may place additional permissions on material, added
319by you to a covered work, for which you have or can give appropriate copyright
320permission.
321
322Notwithstanding any other provision of this License, for material you add to a
323covered work, you may (if authorized by the copyright holders of that material)
324supplement the terms of this License with terms:
325
326 a) Disclaiming warranty or limiting liability differently from the terms of
327 sections 15 and 16 of this License; or
328
329 b) Requiring preservation of specified reasonable legal notices or author
330 attributions in that material or in the Appropriate Legal Notices
331 displayed by works containing it; or
332
333 c) Prohibiting misrepresentation of the origin of that material, or
334 requiring that modified versions of such material be marked in
335 reasonable ways as different from the original version; or
336
337 d) Limiting the use for publicity purposes of names of licensors or authors
338 of the material; or
339
340 e) Declining to grant rights under trademark law for use of some trade
341 names, trademarks, or service marks; or
342
343 f) Requiring indemnification of licensors and authors of that material by
344 anyone who conveys the material (or modified versions of it) with
345 contractual assumptions of liability to the recipient, for any liability
346 that these contractual assumptions directly impose on those licensors
347 and authors.
348
349All other non-permissive additional terms are considered "further restrictions"
350within the meaning of section 10. If the Program as you received it, or any
351part of it, contains a notice stating that it is governed by this License along
352with a term that is a further restriction, you may remove that term. If a
353license document contains a further restriction but permits relicensing or
354conveying under this License, you may add to a covered work material governed
355by the terms of that license document, provided that the further restriction
356does not survive such relicensing or conveying.
357
358If you add terms to a covered work in accord with this section, you must place,
359in the relevant source files, a statement of the additional terms that apply
360to those files, or a notice indicating where to find the applicable terms.
361
362Additional terms, permissive or non-permissive, may be stated in the form of a
363separately written license, or stated as exceptions; the above requirements
364apply either way.
365
3668. Termination.
367
368You may not propagate or modify a covered work except as expressly provided
369under this License. Any attempt otherwise to propagate or modify it is void,
370and will automatically terminate your rights under this License (including any
371patent licenses granted under the third paragraph of section 11).
372
373However, if you cease all violation of this License, then your license from a
374particular copyright holder is reinstated (a) provisionally, unless and until
375the copyright holder explicitly and finally terminates your license, and (b)
376permanently, if the copyright holder fails to notify you of the violation by
377some reasonable means prior to 60 days after the cessation.
378
379Moreover, your license from a particular copyright holder is reinstated
380permanently if the copyright holder notifies you of the violation by some
381reasonable means, this is the first time you have received notice of violation
382of this License (for any work) from that copyright holder, and you cure the
383violation prior to 30 days after your receipt of the notice.
384
385Termination of your rights under this section does not terminate the licenses
386of parties who have received copies or rights from you under this License.
387If your rights have been terminated and not permanently reinstated, you do not
388qualify to receive new licenses for the same material under section 10.
389
3909. Acceptance Not Required for Having Copies.
391
392You are not required to accept this License in order to receive or run a copy
393of the Program. Ancillary propagation of a covered work occurring solely as a
394consequence of using peer-to-peer transmission to receive a copy likewise does
395not require acceptance. However, nothing other than this License grants you
396permission to propagate or modify any covered work. These actions infringe
397copyright if you do not accept this License. Therefore, by modifying or
398propagating a covered work, you indicate your acceptance of this License to
399do so.
400
40110. Automatic Licensing of Downstream Recipients.
402
403Each time you convey a covered work, the recipient automatically receives a
404license from the original licensors, to run, modify and propagate that work,
405subject to this License. You are not responsible for enforcing compliance by
406third parties with this License.
407
408An "entity transaction" is a transaction transferring control of an
409organization, or substantially all assets of one, or subdividing an
410organization, or merging organizations. If propagation of a covered work
411results from an entity transaction, each party to that transaction who receives
412a copy of the work also receives whatever licenses to the work the party's
413predecessor in interest had or could give under the previous paragraph, plus a
414right to possession of the Corresponding Source of the work from the
415predecessor in interest, if the predecessor has it or can get it with
416reasonable efforts.
417
418You may not impose any further restrictions on the exercise of the rights
419granted or affirmed under this License. For example, you may not impose a
420license fee, royalty, or other charge for exercise of rights granted under this
421License, and you may not initiate litigation (including a cross-claim or
422counterclaim in a lawsuit) alleging that any patent claim is infringed by
423making, using, selling, offering for sale, or importing the Program or any
424portion of it.
425
42611. Patents.
427
428A "contributor" is a copyright holder who authorizes use under this License of
429the Program or a work on which the Program is based. The work thus licensed is
430called the contributor's "contributor version".
431
432A contributor's "essential patent claims" are all patent claims owned or
433controlled by the contributor, whether already acquired or hereafter acquired,
434that would be infringed by some manner, permitted by this License, of making,
435using, or selling its contributor version, but do not include claims that would
436be infringed only as a consequence of further modification of the contributor
437version. For purposes of this definition, "control" includes the right to
438grant patent sublicenses in a manner consistent with the requirements of this
439License.
440
441Each contributor grants you a non-exclusive, worldwide, royalty-free patent
442license under the contributor's essential patent claims, to make, use, sell,
443offer for sale, import and otherwise run, modify and propagate the contents of
444its contributor version.
445
446In the following three paragraphs, a "patent license" is any express agreement
447or commitment, however denominated, not to enforce a patent (such as an express
448permission to practice a patent or covenant not to s ue for patent
449infringement). To "grant" such a patent license to a party means to make such an
450agreement or commitment not to enforce a patent against the party.
451
452If you convey a covered work, knowingly relying on a patent license, and the
453Corresponding Source of the work is not available for anyone to copy, free of
454charge and under the terms of this License, through a publicly available
455network server or other readily accessible means, then you must either
456(1) cause the Corresponding Source to be so available, or (2) arrange to
457deprive yourself of the benefit of the patent license for this particular work,
458or (3) arrange, in a manner consistent with the requirements of this License,
459to extend the patent license to downstream recipients. "Knowingly relying"
460means you have actual knowledge that, but for the patent license, your
461conveying the covered work in a country, or your recipient's use of the
462covered work in a country, would infringe one or more identifiable patents in
463that country that you have reason to believe are valid.
464
465If, pursuant to or in connection with a single transaction or arrangement, you
466convey, or propagate by procuring conveyance of, a covered work, and grant a
467patent license to some of the parties receiving the covered work authorizing
468them to use, propagate, modify or convey a specific copy of the covered work,
469then the patent license you grant is automatically extended to all recipients
470of the covered work and works based on it.
471
472A patent license is "discriminatory" if it does not include within the scope of
473its coverage, prohibits the exercise of, or is conditioned on the non-exercise
474of one or more of the rights that are specifically granted under this License.
475You may not convey a covered work if you are a party to an arrangement with a
476third party that is in the business of distributing software, under which you
477make payment to the third party based on the extent of your activity of
478conveying the work, and under which the third party grants, to any of the
479parties who would receive the covered work from you, a discriminatory patent
480license (a) in connection with copies of the covered work conveyed by you (or
481copies made from those copies), or (b) primarily for and in connection with
482specific products or compilations that contain the covered work, unless you
483entered into that arrangement, or that patent license was granted, prior to
48428 March 2007.
485
486Nothing in this License shall be construed as excluding or limiting any implied
487license or other defenses to infringement that may otherwise be available to
488you under applicable patent law.
489
49012. No Surrender of Others' Freedom.
491
492If conditions are imposed on you (whether by court order, agreement or
493otherwise) that contradict the conditions of this License, they do not excuse
494you from the conditions of this License. If you cannot convey a covered work
495so as to satisfy simultaneously your obligations under this License and any
496other pertinent obligations, then as a consequence you may not convey it at
497all. For example, if you agree to terms that obligate you to collect a royalty
498for further conveying from those to whom you convey the Program, the only way
499you could satisfy both those terms and this License would be to refrain
500entirely from conveying the Program.
501
50213. Remote Network Interaction; Use with the GNU General Public License.
503
504Notwithstanding any other provision of this License, if you modify the Program,
505your modified version must prominently offer all users interacting with it
506remotely through a computer network (if your version supports such interaction)
507an opportunity to receive the Corresponding Source of your version by providing
508access to the Corresponding Source from a network server at no charge, through
509some standard or customary means of facilitating copying of software. This
510Corresponding Source shall include the Corresponding Source for any work
511covered by version 3 of the GNU General Public License that is incorporated
512pursuant to the following paragraph.
513
514Notwithstanding any other provision of this License, you have permission to
515link or combine any covered work with a work licensed under version 3 of the
516GNU General Public License into a single combined work, and to convey the
517resulting work. The terms of this License will continue to apply to the part
518which is the covered work, but the work with which it is combined will remain
519governed by version 3 of the GNU General Public License.
520
52114. Revised Versions of this License.
522
523The Free Software Foundation may publish revised and/or new versions of the GNU
524Affero General Public License from time to time. Such new versions will be
525similar in spirit to the present version, but may differ in detail to address
526new problems or concerns.
527
528Each version is given a distinguishing version number. If the Program
529specifies that a certain numbered version of the GNU Affero General Public
530License "or any later version" applies to it, you have the option of
531following the terms and conditions either of that numbered version or of any
532later version published by the Free Software Foundation. If the Program does
533not specify a version number of the GNU Affero General Public License, you may
534choose any version ever published by the Free Software Foundation.
535
536If the Program specifies that a proxy can decide which future versions of the
537GNU Affero General Public License can be used, that proxy's public statement
538of acceptance of a version permanently authorizes you to choose that version
539for the Program.
540
541Later license versions may give you additional or different permissions.
542However, no additional obligations are imposed on any author or copyright
543holder as a result of your choosing to follow a later version.
544
54515. Disclaimer of Warranty.
546
547THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
548LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
549OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND,
550EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
551WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
552ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.
553SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
554SERVICING, REPAIR OR CORRECTION.
555
55616. Limitation of Liability.
557
558IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
559COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS
560PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
561INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
562THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
563INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
564PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
565PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
566
56717. Interpretation of Sections 15 and 16.
568
569If the disclaimer of warranty and limitation of liability provided above cannot
570be given local legal effect according to their terms, reviewing courts shall
571apply local law that most closely approximates an absolute waiver of all civil
572liability in connection with the Program, unless a warranty or assumption of
573liability accompanies a copy of the Program in return for a fee.
574
575END OF TERMS AND CONDITIONS
576
577How to Apply These Terms to Your New Programs
578
579If you develop a new program, and you want it to be of the greatest possible
580use to the public, the best way to achieve this is to make it free software
581which everyone can redistribute and change under these terms.
582
583To do so, attach the following notices to the program. It is safest to attach
584them to the start of each source file to most effectively state the exclusion
585of warranty; and each file should have at least the "copyright" line and a
586pointer to where the full notice is found.
587
588 <one line to give the program's name and a brief idea of what it does.>
589 Copyright (C) <year> <name of author>
590
591 This program is free software: you can redistribute it and/or modify it
592 under the terms of the GNU Affero General Public License as published by
593 the Free Software Foundation, either version 3 of the License, or (at
594 your option) any later version.
595
596 This program is distributed in the hope that it will be useful, but
597 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
598 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
599 License for more details.
600
601 You should have received a copy of the GNU Affero General Public License
602 along with this program. If not, see <http://www.gnu.org/licenses/>.
603
604Also add information on how to contact you by electronic and paper mail.
605
606If your software can interact with users remotely through a computer network,
607you should also make sure that it provides a way for users to get its source.
608For example, if your program is a web application, its interface could display
609a "Source" link that leads users to an archive of the code. There are many
610ways you could offer source, and different solutions will be better for
611different programs; see section 13 for the specific requirements.
612
613You should also get your employer (if you work as a programmer) or school, if
614any, to sign a "copyright disclaimer" for the program, if necessary. For more
615information on this, and how to apply and follow the GNU AGPL, see
616<http://www.gnu.org/licenses/>.
diff --git a/README.md b/README.md
index 1875501..37b1cb8 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,7 @@ packages are accessible through `GOPATH`. To install the dependencies:
33```bash 33```bash
34$ go get -u golang.org/x/crypto/... 34$ go get -u golang.org/x/crypto/...
35$ go get -u golang.org/x/text/... 35$ go get -u golang.org/x/text/...
36$ go get -u github.com/miekg/dns/...
36$ go get -u github.com/bfix/gospel/... 37$ go get -u github.com/bfix/gospel/...
37``` 38```
38 39
diff --git a/src/gnunet/config/config.go b/src/gnunet/config/config.go
index 1a53941..eaadd98 100644
--- a/src/gnunet/config/config.go
+++ b/src/gnunet/config/config.go
@@ -7,9 +7,10 @@ import (
7 "regexp" 7 "regexp"
8 "strings" 8 "strings"
9 9
10 "gnunet/util"
11
10 "github.com/bfix/gospel/crypto/ed25519" 12 "github.com/bfix/gospel/crypto/ed25519"
11 "github.com/bfix/gospel/logger" 13 "github.com/bfix/gospel/logger"
12 "gnunet/util"
13) 14)
14 15
15/////////////////////////////////////////////////////////////////////// 16///////////////////////////////////////////////////////////////////////
@@ -64,6 +65,7 @@ type Config struct {
64} 65}
65 66
66var ( 67var (
68 // Cfg is the global configuration
67 Cfg *Config 69 Cfg *Config
68) 70)
69 71
@@ -88,6 +90,8 @@ var (
88 rx = regexp.MustCompile("\\$\\{([^\\}]*)\\}") 90 rx = regexp.MustCompile("\\$\\{([^\\}]*)\\}")
89) 91)
90 92
93// substString is a helper function to substitute environment variables
94// with actual values.
91func substString(s string, env map[string]string) string { 95func substString(s string, env map[string]string) string {
92 matches := rx.FindAllStringSubmatch(s, -1) 96 matches := rx.FindAllStringSubmatch(s, -1)
93 for _, m := range matches { 97 for _, m := range matches {
@@ -102,7 +106,8 @@ func substString(s string, env map[string]string) string {
102 return s 106 return s
103} 107}
104 108
105// applySubstitutions 109// applySubstitutions traverses the configuration data structure
110// and applies string substitutions to all string values.
106func applySubstitutions(x interface{}, env map[string]string) { 111func applySubstitutions(x interface{}, env map[string]string) {
107 112
108 var process func(v reflect.Value) 113 var process func(v reflect.Value)
@@ -140,10 +145,11 @@ func applySubstitutions(x interface{}, env map[string]string) {
140 } 145 }
141 } 146 }
142 } 147 }
143 148 // start processing at the top-level structure
144 v := reflect.ValueOf(x) 149 v := reflect.ValueOf(x)
145 switch v.Kind() { 150 switch v.Kind() {
146 case reflect.Ptr: 151 case reflect.Ptr:
152 // indirect top-level
147 e := v.Elem() 153 e := v.Elem()
148 if e.IsValid() { 154 if e.IsValid() {
149 process(e) 155 process(e)
@@ -151,6 +157,7 @@ func applySubstitutions(x interface{}, env map[string]string) {
151 logger.Printf(logger.ERROR, "[config] 'nil' pointer encountered") 157 logger.Printf(logger.ERROR, "[config] 'nil' pointer encountered")
152 } 158 }
153 case reflect.Struct: 159 case reflect.Struct:
160 // direct top-level
154 process(v) 161 process(v)
155 } 162 }
156} 163}
diff --git a/src/gnunet/core/peer.go b/src/gnunet/core/peer.go
index ac2d980..d0b3a4c 100644
--- a/src/gnunet/core/peer.go
+++ b/src/gnunet/core/peer.go
@@ -3,30 +3,25 @@ package core
3import ( 3import (
4 "fmt" 4 "fmt"
5 5
6 "github.com/bfix/gospel/crypto/ed25519"
7 "gnunet/message" 6 "gnunet/message"
8 "gnunet/util" 7 "gnunet/util"
9)
10 8
11/* 9 "github.com/bfix/gospel/crypto/ed25519"
12type Peer interface { 10)
13 GetID() []byte
14 GetIDString() string
15 GetAddressList() []*util.Address
16 Sign(msg []byte) ([]byte, error)
17 Verify(msg, sig []byte) bool
18}
19*/
20 11
12// Peer represents a node in the GNUnet P2P network.
21type Peer struct { 13type Peer struct {
22 pub *ed25519.PublicKey 14 prv *ed25519.PrivateKey // node private key (long-term signing key)
23 idString string 15 pub *ed25519.PublicKey // node public key (=identifier)
24 addrList []*util.Address 16 idString string // node identifier as string
25 prv *ed25519.PrivateKey // long-term signing key 17 addrList []*util.Address // list of addresses associated with node
26 ephPrv *ed25519.PrivateKey // ephemeral signing key 18 ephPrv *ed25519.PrivateKey // ephemeral signing key
27 ephMsg *message.EphemeralKeyMsg // ephemeral signing key message 19 ephMsg *message.EphemeralKeyMsg // ephemeral signing key message
28} 20}
29 21
22// NewPeer instantiates a new peer object from given data. If a local peer
23// is created, the data is the seed for generating the private key of the node;
24// for a remote peer the data is the binary representation of its public key.
30func NewPeer(data []byte, local bool) (p *Peer, err error) { 25func NewPeer(data []byte, local bool) (p *Peer, err error) {
31 p = new(Peer) 26 p = new(Peer)
32 if local { 27 if local {
@@ -45,42 +40,52 @@ func NewPeer(data []byte, local bool) (p *Peer, err error) {
45 return 40 return
46} 41}
47 42
43// EphKeyMsg returns a new initialized message to negotiate session keys.
48func (p *Peer) EphKeyMsg() *message.EphemeralKeyMsg { 44func (p *Peer) EphKeyMsg() *message.EphemeralKeyMsg {
49 return p.ephMsg 45 return p.ephMsg
50} 46}
51 47
48// SetEphKeyMsg saves a template for new key negotiation messages.
52func (p *Peer) SetEphKeyMsg(msg *message.EphemeralKeyMsg) { 49func (p *Peer) SetEphKeyMsg(msg *message.EphemeralKeyMsg) {
53 p.ephMsg = msg 50 p.ephMsg = msg
54} 51}
55 52
53// EphPrvKey returns the current ephemeral private key.
56func (p *Peer) EphPrvKey() *ed25519.PrivateKey { 54func (p *Peer) EphPrvKey() *ed25519.PrivateKey {
57 return p.ephPrv 55 return p.ephPrv
58} 56}
59 57
58// PrvKey return the private key of the node.
60func (p *Peer) PrvKey() *ed25519.PrivateKey { 59func (p *Peer) PrvKey() *ed25519.PrivateKey {
61 return p.prv 60 return p.prv
62} 61}
63 62
63// PubKey return the public key of the node.
64func (p *Peer) PubKey() *ed25519.PublicKey { 64func (p *Peer) PubKey() *ed25519.PublicKey {
65 return p.pub 65 return p.pub
66} 66}
67 67
68// GetID returns the node ID (public key) in binary format
68func (p *Peer) GetID() []byte { 69func (p *Peer) GetID() []byte {
69 return p.pub.Bytes() 70 return p.pub.Bytes()
70} 71}
71 72
73// GetIDString returns the string representation of the public key of the node.
72func (p *Peer) GetIDString() string { 74func (p *Peer) GetIDString() string {
73 return p.idString 75 return p.idString
74} 76}
75 77
78// GetAddressList returns a list of addresses associated with this peer.
76func (p *Peer) GetAddressList() []*util.Address { 79func (p *Peer) GetAddressList() []*util.Address {
77 return p.addrList 80 return p.addrList
78} 81}
79 82
83// AddAddress adds a new address for a node.
80func (p *Peer) AddAddress(a *util.Address) { 84func (p *Peer) AddAddress(a *util.Address) {
81 p.addrList = append(p.addrList, a) 85 p.addrList = append(p.addrList, a)
82} 86}
83 87
88// Sign a message with the (long-term) private key.
84func (p *Peer) Sign(msg []byte) (*ed25519.EdSignature, error) { 89func (p *Peer) Sign(msg []byte) (*ed25519.EdSignature, error) {
85 if p.prv == nil { 90 if p.prv == nil {
86 return nil, fmt.Errorf("No private key") 91 return nil, fmt.Errorf("No private key")
@@ -88,6 +93,7 @@ func (p *Peer) Sign(msg []byte) (*ed25519.EdSignature, error) {
88 return p.prv.EdSign(msg) 93 return p.prv.EdSign(msg)
89} 94}
90 95
96// Verify a message signature with the public key of a peer.
91func (p *Peer) Verify(msg []byte, sig *ed25519.EdSignature) (bool, error) { 97func (p *Peer) Verify(msg []byte, sig *ed25519.EdSignature) (bool, error) {
92 return p.pub.EdVerify(msg, sig) 98 return p.pub.EdVerify(msg, sig)
93} 99}
diff --git a/src/gnunet/crypto/gns.go b/src/gnunet/crypto/gns.go
new file mode 100644
index 0000000..c6a8cd6
--- /dev/null
+++ b/src/gnunet/crypto/gns.go
@@ -0,0 +1,35 @@
1package crypto
2
3import (
4 "crypto/sha256"
5 "crypto/sha512"
6
7 "github.com/bfix/gospel/crypto/ed25519"
8 "golang.org/x/crypto/hkdf"
9)
10
11// DeriveBlockKey returns a symmetric key and initialization vector to decipher a GNS block.
12func DeriveBlockKey(label string, pub *ed25519.PublicKey) (iv *SymmetricIV, skey *SymmetricKey) {
13 // generate symmetric key
14 prk := hkdf.Extract(sha512.New, pub.Bytes(), []byte("gns-aes-ctx-key"))
15 rdr := hkdf.Expand(sha256.New, prk, []byte(label))
16 skey = NewSymmetricKey()
17 rdr.Read(skey.AESKey)
18 rdr.Read(skey.TwofishKey)
19
20 // generate initialization vector
21 prk = hkdf.Extract(sha512.New, pub.Bytes(), []byte("gns-aes-ctx-iv"))
22 rdr = hkdf.Expand(sha256.New, prk, []byte(label))
23 iv = NewSymmetricIV()
24 rdr.Read(iv.AESIv)
25 rdr.Read(iv.TwofishIv)
26 return
27}
28
29// DecryptBlock for a given zone and label.
30func DecryptBlock(data []byte, zoneKey *ed25519.PublicKey, label string) (out []byte, err error) {
31 // derive key material for decryption
32 iv, skey := DeriveBlockKey(label, zoneKey)
33 // perform decryption
34 return SymmetricDecrypt(data, skey, iv)
35}
diff --git a/src/gnunet/crypto/gns_test.go b/src/gnunet/crypto/gns_test.go
new file mode 100644
index 0000000..7f3cdb8
--- /dev/null
+++ b/src/gnunet/crypto/gns_test.go
@@ -0,0 +1,150 @@
1package crypto
2
3import (
4 "bytes"
5 "encoding/hex"
6 "testing"
7
8 "github.com/bfix/gospel/crypto/ed25519"
9)
10
11var (
12 PUB = []byte{
13 0x93, 0x34, 0x71, 0xF6, 0x99, 0x19, 0x0C, 0x62,
14 0x85, 0xC7, 0x9B, 0x83, 0x9D, 0xCA, 0x83, 0x91,
15 0x38, 0xFA, 0x87, 0xFB, 0xB8, 0xD4, 0xF6, 0xF0,
16 0xF0, 0x4B, 0x7F, 0x0A, 0x48, 0xBF, 0x95, 0xF7,
17 }
18 LABEL = "home"
19)
20
21func TestDeriveBlockKey(t *testing.T) {
22 var (
23 SKEY = []byte{
24 0x1D, 0x86, 0x8E, 0xF7, 0x30, 0x96, 0x3B, 0x39,
25 0x66, 0xE6, 0x49, 0xD8, 0xF1, 0x13, 0x18, 0x39,
26 0x8A, 0x7A, 0xB0, 0xF3, 0xDC, 0xF6, 0xE7, 0x2A,
27 0xF6, 0x65, 0xDE, 0x86, 0x47, 0x7B, 0x20, 0x1B,
28
29 0x21, 0xA6, 0xFA, 0x55, 0x7C, 0x29, 0xF5, 0x94,
30 0x8E, 0x9A, 0x80, 0xB0, 0xB6, 0xD5, 0x4D, 0x38,
31 0x0E, 0x6A, 0x0F, 0x42, 0x4B, 0x27, 0xBB, 0x6A,
32 0x1E, 0xD1, 0x33, 0x08, 0xD6, 0x2E, 0x21, 0x8C,
33 }
34 IV = []byte{
35 0xAC, 0x18, 0x03, 0xB7, 0x8B, 0x1E, 0x09, 0xA9,
36 0xD0, 0x20, 0x47, 0x2B, 0x1B, 0x23, 0xE8, 0x24,
37
38 0xC9, 0x23, 0x9E, 0x61, 0x3A, 0x8D, 0x95, 0xA9,
39 0x3F, 0x6C, 0x1C, 0xC8, 0xCB, 0xD1, 0xBD, 0x6B,
40 }
41 )
42
43 iv, skey := DeriveBlockKey(LABEL, ed25519.NewPublicKeyFromBytes(PUB))
44
45 if bytes.Compare(IV[:16], iv.AESIv) != 0 {
46 t.Logf("AES_IV(computed) = %s\n", hex.EncodeToString(iv.AESIv))
47 t.Logf("AES_IV(expected) = %s\n", hex.EncodeToString(IV[:16]))
48 t.Fatal("AES IV mismatch")
49 }
50 if bytes.Compare(IV[16:], iv.TwofishIv) != 0 {
51 t.Logf("Twofish_IV(computed) = %s\n", hex.EncodeToString(iv.TwofishIv))
52 t.Logf("Twofish_IV(expected) = %s\n", hex.EncodeToString(IV[16:]))
53 t.Fatal("Twofish IV mismatch")
54 }
55
56 if bytes.Compare(SKEY[:32], skey.AESKey) != 0 {
57 t.Logf("AES_KEY(computed) = %s\n", hex.EncodeToString(skey.AESKey))
58 t.Logf("AES_KEY(expected) = %s\n", hex.EncodeToString(SKEY[:32]))
59 t.Fatal("AES KEY mismatch")
60 }
61 if bytes.Compare(SKEY[32:], skey.TwofishKey) != 0 {
62 t.Logf("Twofish_KEY(computed) = %s\n", hex.EncodeToString(skey.TwofishKey))
63 t.Logf("Twofish_KEY(expected) = %s\n", hex.EncodeToString(SKEY[32:]))
64 t.Fatal("Twofish KEY mismatch")
65 }
66}
67
68func TestDecryptBlock(t *testing.T) {
69 var (
70 DATA = []byte{
71 0xAC, 0xA5, 0x3C, 0x55, 0x63, 0x21, 0x31, 0x1F,
72 0x11, 0x6E, 0xEF, 0x48, 0xED, 0x53, 0x46, 0x31,
73 0x7C, 0x50, 0xFB, 0x6B, 0xA6, 0xC8, 0x6C, 0x46,
74 0x1E, 0xE3, 0xCA, 0x45, 0xCD, 0x5B, 0xD6, 0x86,
75 0x42, 0x87, 0xEF, 0x18, 0xCE, 0x8E, 0x83, 0x21,
76 0x04, 0xCB, 0xCF, 0x40, 0x7E, 0x0F, 0x51, 0x54,
77 0xE2, 0x3C, 0xDE, 0xE9, 0x22, 0x00, 0xFF, 0x40,
78 0xBB, 0x53, 0xE3, 0x69, 0x99, 0x92, 0x47, 0x97,
79 0xF0, 0x4E, 0x3B, 0x70,
80 }
81 OUT = []byte{
82 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xAD, 0x0E,
83 0x60, 0x28, 0xFE, 0x80, 0x00, 0x00, 0x00, 0x10,
84 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
85 0x0A, 0x68, 0x6F, 0x69, 0x2D, 0x70, 0x6F, 0x6C,
86 0x6C, 0x6F, 0x69, 0x03, 0x6F, 0x72, 0x67, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00,
91 }
92 )
93
94 out, err := DecryptBlock(DATA, ed25519.NewPublicKeyFromBytes(PUB), LABEL)
95 if err != nil {
96 t.Fatal(err)
97 }
98 if bytes.Compare(out, OUT) != 0 {
99 t.Logf("Decrypt(computed) = %s\n", hex.EncodeToString(out))
100 t.Logf("Decrypt(expected) = %s\n", hex.EncodeToString(OUT))
101 t.Fatal("Decryptions failed")
102 }
103}
104
105func TestVerifyBlock(t *testing.T) {
106 var (
107 SIGNED = []byte{
108 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x0f,
109 0x00, 0x05, 0xad, 0x0e, 0x60, 0x28, 0xfe, 0x80,
110 0xac, 0xa5, 0x3c, 0x55, 0x63, 0x21, 0x31, 0x1f,
111 0x11, 0x6e, 0xef, 0x48, 0xed, 0x53, 0x46, 0x31,
112 0x7c, 0x50, 0xfb, 0x6b, 0xa6, 0xc8, 0x6c, 0x46,
113 0x1e, 0xe3, 0xca, 0x45, 0xcd, 0x5b, 0xd6, 0x86,
114 0x42, 0x87, 0xef, 0x18, 0xce, 0x8e, 0x83, 0x21,
115 0x04, 0xcb, 0xcf, 0x40, 0x7e, 0x0f, 0x51, 0x54,
116 0xe2, 0x3c, 0xde, 0xe9, 0x22, 0x00, 0xff, 0x40,
117 0xbb, 0x53, 0xe3, 0x69, 0x99, 0x92, 0x47, 0x97,
118 0xf0, 0x4e, 0x3b, 0x70,
119 }
120 SIG = []byte{
121 0x09, 0xc9, 0x6a, 0xda, 0x69, 0xce, 0x7c, 0x91,
122 0xbd, 0xa4, 0x59, 0xdc, 0xc9, 0x76, 0xf4, 0x6c,
123 0x62, 0xb7, 0x79, 0x3f, 0x94, 0xb2, 0xf6, 0xf0,
124 0x90, 0x17, 0x4e, 0x2f, 0x68, 0x49, 0xf8, 0xcc,
125
126 0x0b, 0x77, 0x32, 0x32, 0x28, 0x77, 0x2d, 0x2a,
127 0x31, 0x31, 0xc1, 0x2c, 0x44, 0x18, 0xf2, 0x5f,
128 0x1a, 0xe9, 0x8b, 0x2e, 0x65, 0xca, 0x1d, 0xe8,
129 0x22, 0x82, 0x6a, 0x06, 0xe0, 0x6a, 0x5a, 0xe5,
130 }
131 PUB = []byte{
132 0x26, 0x84, 0x1b, 0x24, 0x35, 0xa4, 0x63, 0xe9,
133 0xf0, 0x48, 0xae, 0x3e, 0xf7, 0xe8, 0x1b, 0xca,
134 0x55, 0x9f, 0x4c, 0x1e, 0x16, 0x18, 0xa6, 0xd3,
135 0x5b, 0x91, 0x0d, 0x54, 0x31, 0x6e, 0xbf, 0x97,
136 }
137 )
138 sig, err := ed25519.NewEcSignatureFromBytes(SIG)
139 if err != nil {
140 t.Fatal(err)
141 }
142 dkey := ed25519.NewPublicKeyFromBytes(PUB)
143 ok, err := dkey.EcVerify(SIGNED, sig)
144 if err != nil {
145 t.Fatal(err)
146 }
147 if !ok {
148 t.Fatal("EcDSA verify failed")
149 }
150}
diff --git a/src/gnunet/crypto/hash.go b/src/gnunet/crypto/hash.go
index 87e3941..0fe7c7e 100644
--- a/src/gnunet/crypto/hash.go
+++ b/src/gnunet/crypto/hash.go
@@ -6,16 +6,19 @@ import (
6 "gnunet/util" 6 "gnunet/util"
7) 7)
8 8
9// HashCode is the result of a 512-bit hash function (SHA-512)
9type HashCode struct { 10type HashCode struct {
10 Bits []byte `size:"64"` 11 Bits []byte `size:"64"`
11} 12}
12 13
14// NewHashCode creates a new, uninitalized hash value
13func NewHashCode() *HashCode { 15func NewHashCode() *HashCode {
14 return &HashCode{ 16 return &HashCode{
15 Bits: make([]byte, 64), 17 Bits: make([]byte, 64),
16 } 18 }
17} 19}
18 20
21// Hash returns the SHA-512 hash value of a given blob
19func Hash(data []byte) *HashCode { 22func Hash(data []byte) *HashCode {
20 val := sha512.Sum512(data) 23 val := sha512.Sum512(data)
21 return &HashCode{ 24 return &HashCode{
diff --git a/src/gnunet/crypto/key_derivation.go b/src/gnunet/crypto/key_derivation.go
index 575f511..976db2a 100644
--- a/src/gnunet/crypto/key_derivation.go
+++ b/src/gnunet/crypto/key_derivation.go
@@ -9,6 +9,7 @@ import (
9 "golang.org/x/crypto/hkdf" 9 "golang.org/x/crypto/hkdf"
10) 10)
11 11
12// Curve parameters
12var ( 13var (
13 ED25519_N = ed25519.GetCurve().N 14 ED25519_N = ed25519.GetCurve().N
14) 15)
diff --git a/src/gnunet/crypto/key_exchange.go b/src/gnunet/crypto/key_exchange.go
index 0efa441..1403249 100644
--- a/src/gnunet/crypto/key_exchange.go
+++ b/src/gnunet/crypto/key_exchange.go
@@ -4,8 +4,8 @@ import (
4 "github.com/bfix/gospel/crypto/ed25519" 4 "github.com/bfix/gospel/crypto/ed25519"
5) 5)
6 6
7// SharedSecret computes a 64 byte shared secret 7// SharedSecret computes a 64 byte shared secret between (prvA,pubB)
8// between (prvA,pubB) and (prvB,pubA). 8// and (prvB,pubA) by a Diffie-Hellman-like scheme.
9func SharedSecret(prv *ed25519.PrivateKey, pub *ed25519.PublicKey) *HashCode { 9func SharedSecret(prv *ed25519.PrivateKey, pub *ed25519.PublicKey) *HashCode {
10 ss := pub.Mult(prv.D).Q.X().Bytes() 10 ss := pub.Mult(prv.D).Q.X().Bytes()
11 return Hash(ss) 11 return Hash(ss)
diff --git a/src/gnunet/crypto/signature.go b/src/gnunet/crypto/signature.go
index 9a69b56..ba8e535 100644
--- a/src/gnunet/crypto/signature.go
+++ b/src/gnunet/crypto/signature.go
@@ -1,5 +1,6 @@
1package crypto 1package crypto
2 2
3// SignaturePurpose is the GNUnet data structure used as header for signed data.
3type SignaturePurpose struct { 4type SignaturePurpose struct {
4 Size uint32 `order:"big"` // How many bytes are signed? 5 Size uint32 `order:"big"` // How many bytes are signed?
5 Purpose uint32 `order:"big"` // Signature purpose 6 Purpose uint32 `order:"big"` // Signature purpose
diff --git a/src/gnunet/crypto/symmetric.go b/src/gnunet/crypto/symmetric.go
index 82116a4..5607d3a 100644
--- a/src/gnunet/crypto/symmetric.go
+++ b/src/gnunet/crypto/symmetric.go
@@ -8,11 +8,17 @@ import (
8 "golang.org/x/crypto/twofish" 8 "golang.org/x/crypto/twofish"
9) 9)
10 10
11// Symmetric encryption in GNUnet uses a two-layer scheme:
12// * Encryption: OUT = twofish_cfb(aes_cfb(IN))
13// * Decryption: OUT = aes_cfb(twofish_cfb(IN))
14
15// SymmetricKey is a key for the GNUnet-specific two-layer encryption scheme.
11type SymmetricKey struct { 16type SymmetricKey struct {
12 AESKey []byte `size:"32"` 17 AESKey []byte `size:"32"` // key for AES-CFB
13 TwofishKey []byte `size:"32"` 18 TwofishKey []byte `size:"32"` // key for Twofish-CFB
14} 19}
15 20
21// NewSymmetricKey generates a new (random) symmetric key.
16func NewSymmetricKey() *SymmetricKey { 22func NewSymmetricKey() *SymmetricKey {
17 skey := &SymmetricKey{ 23 skey := &SymmetricKey{
18 AESKey: make([]byte, 32), 24 AESKey: make([]byte, 32),
@@ -23,11 +29,14 @@ func NewSymmetricKey() *SymmetricKey {
23 return skey 29 return skey
24} 30}
25 31
32// SymmetricIV is an initialization vector for the GNUnet-specific two-layer
33// encryption scheme.
26type SymmetricIV struct { 34type SymmetricIV struct {
27 AESIv []byte `size:"16"` 35 AESIv []byte `size:"16"` // IV for AES-CFB
28 TwofishIv []byte `size:"16"` 36 TwofishIv []byte `size:"16"` // IV for Twofish-CFB
29} 37}
30 38
39// NewSymmetricIV generates a new (random) initialization vector.
31func NewSymmetricIV() *SymmetricIV { 40func NewSymmetricIV() *SymmetricIV {
32 iv := &SymmetricIV{ 41 iv := &SymmetricIV{
33 AESIv: make([]byte, 16), 42 AESIv: make([]byte, 16),
@@ -38,6 +47,7 @@ func NewSymmetricIV() *SymmetricIV {
38 return iv 47 return iv
39} 48}
40 49
50// SymmetricDecrypt decrypts the data with given key and initialization vector.
41func SymmetricDecrypt(data []byte, skey *SymmetricKey, iv *SymmetricIV) ([]byte, error) { 51func SymmetricDecrypt(data []byte, skey *SymmetricKey, iv *SymmetricIV) ([]byte, error) {
42 // Decrypt with Twofish CFB stream cipher 52 // Decrypt with Twofish CFB stream cipher
43 tf, err := twofish.NewCipher(skey.TwofishKey) 53 tf, err := twofish.NewCipher(skey.TwofishKey)
@@ -58,6 +68,7 @@ func SymmetricDecrypt(data []byte, skey *SymmetricKey, iv *SymmetricIV) ([]byte,
58 return out, nil 68 return out, nil
59} 69}
60 70
71// SymmetricEncrypt encrypts the data with given key and initialization vector.
61func SymmetricEncrypt(data []byte, skey *SymmetricKey, iv *SymmetricIV) ([]byte, error) { 72func SymmetricEncrypt(data []byte, skey *SymmetricKey, iv *SymmetricIV) ([]byte, error) {
62 // Encrypt with AES CFB stream cipher 73 // Encrypt with AES CFB stream cipher
63 aes, err := aes.NewCipher(skey.AESKey) 74 aes, err := aes.NewCipher(skey.AESKey)
diff --git a/src/gnunet/enums/dht.go b/src/gnunet/enums/dht.go
index 87c36a3..8f004d7 100644
--- a/src/gnunet/enums/dht.go
+++ b/src/gnunet/enums/dht.go
@@ -1,5 +1,6 @@
1package enums 1package enums
2 2
3// DHT flags and settings
3var ( 4var (
4 DHT_RO_NONE = 0 // Default. Do nothing special. 5 DHT_RO_NONE = 0 // Default. Do nothing special.
5 DHT_RO_DEMULTIPLEX_EVERYWHERE = 1 // Each peer along the way should look at 'enc' 6 DHT_RO_DEMULTIPLEX_EVERYWHERE = 1 // Each peer along the way should look at 'enc'
@@ -10,3 +11,25 @@ var (
10 11
11 DHT_GNS_REPLICATION_LEVEL = 10 12 DHT_GNS_REPLICATION_LEVEL = 10
12) 13)
14
15// DHT block types
16var (
17 BLOCK_TYPE_ANY = 0 // Any type of block, used as a wildcard when searching.
18 BLOCK_TYPE_FS_DBLOCK = 1 // Data block (leaf) in the CHK tree.
19 BLOCK_TYPE_FS_IBLOCK = 2 // Inner block in the CHK tree.
20 BLOCK_TYPE_FS_KBLOCK = 3 // Legacy type, no longer in use.
21 BLOCK_TYPE_FS_SBLOCK = 4 // Legacy type, no longer in use.
22 BLOCK_TYPE_FS_NBLOCK = 5 // Legacy type, no longer in use.
23 BLOCK_TYPE_FS_ONDEMAND = 6 // Type of a block representing a block to be encoded on demand from disk.
24 BLOCK_TYPE_DHT_HELLO = 7 // Type of a block that contains a HELLO for a peer
25 BLOCK_TYPE_TEST = 8 // Block for testing.
26 BLOCK_TYPE_FS_UBLOCK = 9 // Type of a block representing any type of search result (universal).
27 BLOCK_TYPE_DNS = 10 // Block for storing DNS exit service advertisements.
28 BLOCK_TYPE_GNS_NAMERECORD = 11 // Block for storing record data
29 BLOCK_TYPE_REVOCATION = 12 // Block type for a revocation message by which a key is revoked.
30
31 BLOCK_TYPE_REGEX = 22 // Block to store a cadet regex state
32 BLOCK_TYPE_REGEX_ACCEPT = 23 // Block to store a cadet regex accepting state
33 BLOCK_TYPE_SET_TEST = 24 // Block for testing set/consensus.
34 BLOCK_TYPE_CONSENSUS_ELEMENT = 25 // Block type for consensus elements.
35)
diff --git a/src/gnunet/enums/gns.go b/src/gnunet/enums/gns.go
index 2de5048..d5b1f7a 100644
--- a/src/gnunet/enums/gns.go
+++ b/src/gnunet/enums/gns.go
@@ -1,5 +1,6 @@
1package enums 1package enums
2 2
3// GNS constants
3var ( 4var (
4 GNS_MAX_BLOCK_SIZE = (63 * 1024) // Maximum size of a value that can be stored in a GNS block. 5 GNS_MAX_BLOCK_SIZE = (63 * 1024) // Maximum size of a value that can be stored in a GNS block.
5 6
diff --git a/src/gnunet/message/message.go b/src/gnunet/message/message.go
index 6b49a55..e792ae8 100644
--- a/src/gnunet/message/message.go
+++ b/src/gnunet/message/message.go
@@ -6,27 +6,35 @@ import (
6 "github.com/bfix/gospel/data" 6 "github.com/bfix/gospel/data"
7) 7)
8 8
9// Error codes
9var ( 10var (
10 ErrMsgHeaderTooSmall = errors.New("Message header too small") 11 ErrMsgHeaderTooSmall = errors.New("Message header too small")
11) 12)
12 13
14// Message is an interface for all GNUnet-specific messages.
13type Message interface { 15type Message interface {
14 Header() *MessageHeader 16 Header() *MessageHeader
15} 17}
16 18
19// MessageHeader encapsulates the common part of all GNUnet messages (at the
20// beginning of the data).
17type MessageHeader struct { 21type MessageHeader struct {
18 MsgSize uint16 `order:"big"` 22 MsgSize uint16 `order:"big"`
19 MsgType uint16 `order:"big"` 23 MsgType uint16 `order:"big"`
20} 24}
21 25
26// Size returns the total size of the message (header + body)
22func (mh *MessageHeader) Size() uint16 { 27func (mh *MessageHeader) Size() uint16 {
23 return mh.MsgSize 28 return mh.MsgSize
24} 29}
25 30
31// Type returns the message type (defines the layout of the body data)
26func (mh *MessageHeader) Type() uint16 { 32func (mh *MessageHeader) Type() uint16 {
27 return mh.MsgType 33 return mh.MsgType
28} 34}
29 35
36// GetMsgHeader returns the header of a message from a byte array (as the
37// serialized form).
30func GetMsgHeader(b []byte) (mh *MessageHeader, err error) { 38func GetMsgHeader(b []byte) (mh *MessageHeader, err error) {
31 if b == nil || len(b) < 4 { 39 if b == nil || len(b) < 4 {
32 return nil, ErrMsgHeaderTooSmall 40 return nil, ErrMsgHeaderTooSmall
diff --git a/src/gnunet/message/msg_core.go b/src/gnunet/message/msg_core.go
index 0ddbd8b..538fcea 100644
--- a/src/gnunet/message/msg_core.go
+++ b/src/gnunet/message/msg_core.go
@@ -5,21 +5,25 @@ import (
5 "fmt" 5 "fmt"
6 "time" 6 "time"
7 7
8 "github.com/bfix/gospel/crypto/ed25519" 8 "gnunet/crypto"
9 "github.com/bfix/gospel/data"
10 "gnunet/enums" 9 "gnunet/enums"
11 "gnunet/util" 10 "gnunet/util"
11
12 "github.com/bfix/gospel/crypto/ed25519"
13 "github.com/bfix/gospel/data"
12) 14)
13 15
16// EphKeyBlock defines the layout of signed ephemeral key with attributes.
14type EphKeyBlock struct { 17type EphKeyBlock struct {
15 SignSize uint32 `order:"big"` // length of signed block 18 Purpose *crypto.SignaturePurpose // signature purpose: SIG_ECC_KEY
16 SigPurpose uint32 `order:"big"` // signature purpose: SIG_ECC_KEY 19 CreateTime util.AbsoluteTime // Time of key creation
17 CreateTime util.AbsoluteTime // Time of key creation 20 ExpireTime util.RelativeTime // Time to live for key
18 ExpireTime util.RelativeTime // Time to live for key 21 EphemeralKey []byte `size:"32"` // Ephemeral EdDSA public key
19 EphemeralKey []byte `size:"32"` // Ephemeral EdDSA public key 22 PeerID *util.PeerID // Peer identity (EdDSA public key)
20 PeerID *util.PeerID // Peer identity (EdDSA public key)
21} 23}
22 24
25// EphemeralKeyMsg announces a new transient key for a peer. The key is signed
26// by the issuing peer.
23type EphemeralKeyMsg struct { 27type EphemeralKeyMsg struct {
24 MsgSize uint16 `order:"big"` // total size of message 28 MsgSize uint16 `order:"big"` // total size of message
25 MsgType uint16 `order:"big"` // CORE_EPHEMERAL_KEY (88) 29 MsgType uint16 `order:"big"` // CORE_EPHEMERAL_KEY (88)
@@ -28,6 +32,7 @@ type EphemeralKeyMsg struct {
28 SignedBlock *EphKeyBlock 32 SignedBlock *EphKeyBlock
29} 33}
30 34
35// NewEphemeralKeyMsg creates an empty message for key announcement.
31func NewEphemeralKeyMsg() *EphemeralKeyMsg { 36func NewEphemeralKeyMsg() *EphemeralKeyMsg {
32 return &EphemeralKeyMsg{ 37 return &EphemeralKeyMsg{
33 MsgSize: 160, 38 MsgSize: 160,
@@ -35,8 +40,10 @@ func NewEphemeralKeyMsg() *EphemeralKeyMsg {
35 SenderStatus: 1, 40 SenderStatus: 1,
36 Signature: make([]byte, 64), 41 Signature: make([]byte, 64),
37 SignedBlock: &EphKeyBlock{ 42 SignedBlock: &EphKeyBlock{
38 SignSize: 88, 43 Purpose: &crypto.SignaturePurpose{
39 SigPurpose: enums.SIG_ECC_KEY, 44 Size: 88,
45 Purpose: enums.SIG_ECC_KEY,
46 },
40 CreateTime: util.AbsoluteTimeNow(), 47 CreateTime: util.AbsoluteTimeNow(),
41 ExpireTime: util.NewRelativeTime(12 * time.Hour), 48 ExpireTime: util.NewRelativeTime(12 * time.Hour),
42 EphemeralKey: make([]byte, 32), 49 EphemeralKey: make([]byte, 32),
@@ -45,6 +52,7 @@ func NewEphemeralKeyMsg() *EphemeralKeyMsg {
45 } 52 }
46} 53}
47 54
55// String returns a human-readable representation of the message.
48func (m *EphemeralKeyMsg) String() string { 56func (m *EphemeralKeyMsg) String() string {
49 return fmt.Sprintf("EphKeyMsg{peer=%s,ephkey=%s,create=%s,expire=%s,status=%d}", 57 return fmt.Sprintf("EphKeyMsg{peer=%s,ephkey=%s,create=%s,expire=%s,status=%d}",
50 util.EncodeBinaryToString(m.SignedBlock.PeerID.Key), 58 util.EncodeBinaryToString(m.SignedBlock.PeerID.Key),
@@ -58,10 +66,13 @@ func (msg *EphemeralKeyMsg) Header() *MessageHeader {
58 return &MessageHeader{msg.MsgSize, msg.MsgType} 66 return &MessageHeader{msg.MsgSize, msg.MsgType}
59} 67}
60 68
69// Public extracts the public key of an announcing peer.
61func (m *EphemeralKeyMsg) Public() *ed25519.PublicKey { 70func (m *EphemeralKeyMsg) Public() *ed25519.PublicKey {
62 return ed25519.NewPublicKeyFromBytes(m.SignedBlock.PeerID.Key) 71 return ed25519.NewPublicKeyFromBytes(m.SignedBlock.PeerID.Key)
63} 72}
64 73
74// Verify the integrity of the message data using the public key of the
75// announcing peer.
65func (m *EphemeralKeyMsg) Verify(pub *ed25519.PublicKey) (bool, error) { 76func (m *EphemeralKeyMsg) Verify(pub *ed25519.PublicKey) (bool, error) {
66 data, err := data.Marshal(m.SignedBlock) 77 data, err := data.Marshal(m.SignedBlock)
67 if err != nil { 78 if err != nil {
@@ -74,6 +85,8 @@ func (m *EphemeralKeyMsg) Verify(pub *ed25519.PublicKey) (bool, error) {
74 return pub.EdVerify(data, sig) 85 return pub.EdVerify(data, sig)
75} 86}
76 87
88// NewEphemeralKey creates a new ephemeral key signed by a long-term private
89// key and the corresponding GNUnet message to announce the new key.
77func NewEphemeralKey(peerId []byte, ltPrv *ed25519.PrivateKey) (*ed25519.PrivateKey, *EphemeralKeyMsg, error) { 90func NewEphemeralKey(peerId []byte, ltPrv *ed25519.PrivateKey) (*ed25519.PrivateKey, *EphemeralKeyMsg, error) {
78 msg := NewEphemeralKeyMsg() 91 msg := NewEphemeralKeyMsg()
79 copy(msg.SignedBlock.PeerID.Key, peerId) 92 copy(msg.SignedBlock.PeerID.Key, peerId)
diff --git a/src/gnunet/message/msg_dht.go b/src/gnunet/message/msg_dht.go
index bd3475a..b1d28ba 100644
--- a/src/gnunet/message/msg_dht.go
+++ b/src/gnunet/message/msg_dht.go
@@ -51,6 +51,7 @@ func (m *DHTClientGetMsg) SetXQuery(xq []byte) []byte {
51 return prev 51 return prev
52} 52}
53 53
54// String returns a human-readable representation of the message.
54func (m *DHTClientGetMsg) String() string { 55func (m *DHTClientGetMsg) String() string {
55 return fmt.Sprintf("DHTClientGetMsg{Id:%d,Type=%d,Options=%d,Repl=%d,Key=%s}", 56 return fmt.Sprintf("DHTClientGetMsg{Id:%d,Type=%d,Options=%d,Repl=%d,Key=%s}",
56 m.Id, m.Type, m.Options, m.ReplLevel, hex.EncodeToString(m.Key.Bits)) 57 m.Id, m.Type, m.Options, m.ReplLevel, hex.EncodeToString(m.Key.Bits))
@@ -98,6 +99,7 @@ func NewDHTClientResultMsg(key *crypto.HashCode) *DHTClientResultMsg {
98 } 99 }
99} 100}
100 101
102// String returns a human-readable representation of the message.
101func (m *DHTClientResultMsg) String() string { 103func (m *DHTClientResultMsg) String() string {
102 return fmt.Sprintf("DHTClientResultMsg{id:%d,expire=%s}", m.Id, m.Expire) 104 return fmt.Sprintf("DHTClientResultMsg{id:%d,expire=%s}", m.Id, m.Expire)
103} 105}
diff --git a/src/gnunet/message/msg_gns.go b/src/gnunet/message/msg_gns.go
index 0ff34be..b01c410 100644
--- a/src/gnunet/message/msg_gns.go
+++ b/src/gnunet/message/msg_gns.go
@@ -3,9 +3,10 @@ package message
3import ( 3import (
4 "fmt" 4 "fmt"
5 5
6 "github.com/bfix/gospel/logger"
7 "gnunet/enums" 6 "gnunet/enums"
8 "gnunet/util" 7 "gnunet/util"
8
9 "github.com/bfix/gospel/logger"
9) 10)
10 11
11//---------------------------------------------------------------------- 12//----------------------------------------------------------------------
@@ -38,13 +39,13 @@ func NewGNSLookupMsg() *GNSLookupMsg {
38 } 39 }
39} 40}
40 41
41// SetName 42// SetName appends the name to lookup to the message
42func (m *GNSLookupMsg) SetName(name string) { 43func (m *GNSLookupMsg) SetName(name string) {
43 m.Name = util.Clone(append([]byte(name), 0)) 44 m.Name = util.Clone(append([]byte(name), 0))
44 m.MsgSize = uint16(48 + len(m.Name)) 45 m.MsgSize = uint16(48 + len(m.Name))
45} 46}
46 47
47// GetName 48// GetName returns the name to lookup from the message
48func (m *GNSLookupMsg) GetName() string { 49func (m *GNSLookupMsg) GetName() string {
49 size := len(m.Name) 50 size := len(m.Name)
50 if m.Name[size-1] != 0 { 51 if m.Name[size-1] != 0 {
@@ -55,7 +56,7 @@ func (m *GNSLookupMsg) GetName() string {
55 return string(m.Name[:size]) 56 return string(m.Name[:size])
56} 57}
57 58
58// String 59// String returns a human-readable representation of the message.
59func (m *GNSLookupMsg) String() string { 60func (m *GNSLookupMsg) String() string {
60 return fmt.Sprintf( 61 return fmt.Sprintf(
61 "GNSLookupMsg{Id=%d,Zone=%s,Options=%d,Type=%d,Name=%s}", 62 "GNSLookupMsg{Id=%d,Zone=%s,Options=%d,Type=%d,Name=%s}",
@@ -72,6 +73,8 @@ func (msg *GNSLookupMsg) Header() *MessageHeader {
72// GNS_LOOKUP_RESULT 73// GNS_LOOKUP_RESULT
73//---------------------------------------------------------------------- 74//----------------------------------------------------------------------
74 75
76// GNSResourceRecord is the GNUnet-specific representation of resource
77// records (not to be confused with DNS resource records).
75type GNSResourceRecord struct { 78type GNSResourceRecord struct {
76 Expires util.AbsoluteTime // Expiration time for the record 79 Expires util.AbsoluteTime // Expiration time for the record
77 Size uint32 `order:"big"` // Number of bytes in 'Data' 80 Size uint32 `order:"big"` // Number of bytes in 'Data'
@@ -80,6 +83,7 @@ type GNSResourceRecord struct {
80 Data []byte `size:"Size"` // Record data 83 Data []byte `size:"Size"` // Record data
81} 84}
82 85
86// String returns a human-readable representation of the message.
83func (r *GNSResourceRecord) String() string { 87func (r *GNSResourceRecord) String() string {
84 return fmt.Sprintf("GNSResourceRecord{type=%s,expire=%s,flags=%d,size=%d}", 88 return fmt.Sprintf("GNSResourceRecord{type=%s,expire=%s,flags=%d,size=%d}",
85 enums.GNS_TYPE[int(r.Type)], r.Expires, r.Flags, r.Size) 89 enums.GNS_TYPE[int(r.Type)], r.Expires, r.Flags, r.Size)
@@ -105,7 +109,7 @@ func NewGNSLookupResultMsg(id uint32) *GNSLookupResultMsg {
105 } 109 }
106} 110}
107 111
108// AddRecord 112// AddRecord adds a GNS resource recordto the response message.
109func (m *GNSLookupResultMsg) AddRecord(rec *GNSResourceRecord) error { 113func (m *GNSLookupResultMsg) AddRecord(rec *GNSResourceRecord) error {
110 recSize := 20 + int(rec.Size) 114 recSize := 20 + int(rec.Size)
111 if int(m.MsgSize)+recSize > enums.GNS_MAX_BLOCK_SIZE { 115 if int(m.MsgSize)+recSize > enums.GNS_MAX_BLOCK_SIZE {
@@ -117,7 +121,7 @@ func (m *GNSLookupResultMsg) AddRecord(rec *GNSResourceRecord) error {
117 return nil 121 return nil
118} 122}
119 123
120// String 124// String returns a human-readable representation of the message.
121func (m *GNSLookupResultMsg) String() string { 125func (m *GNSLookupResultMsg) String() string {
122 return fmt.Sprintf("GNSLookupResultMsg{Id=%d,Count=%d}", m.Id, m.Count) 126 return fmt.Sprintf("GNSLookupResultMsg{Id=%d,Count=%d}", m.Id, m.Count)
123} 127}
diff --git a/src/gnunet/message/msg_namecache.go b/src/gnunet/message/msg_namecache.go
index 8f82622..9e3312d 100644
--- a/src/gnunet/message/msg_namecache.go
+++ b/src/gnunet/message/msg_namecache.go
@@ -33,7 +33,7 @@ func NewNamecacheLookupMsg(query *crypto.HashCode) *NamecacheLookupMsg {
33 } 33 }
34} 34}
35 35
36// String 36// String returns a human-readable representation of the message.
37func (m *NamecacheLookupMsg) String() string { 37func (m *NamecacheLookupMsg) String() string {
38 return fmt.Sprintf("NamecacheLookupMsg{Id=%d,Query=%s}", 38 return fmt.Sprintf("NamecacheLookupMsg{Id=%d,Query=%s}",
39 m.Id, hex.EncodeToString(m.Query.Bits)) 39 m.Id, hex.EncodeToString(m.Query.Bits))
@@ -72,7 +72,7 @@ func NewNamecacheLookupResultMsg() *NamecacheLookupResultMsg {
72 } 72 }
73} 73}
74 74
75// String 75// String returns a human-readable representation of the message.
76func (m *NamecacheLookupResultMsg) String() string { 76func (m *NamecacheLookupResultMsg) String() string {
77 return fmt.Sprintf("NamecacheLookupResultMsg{id=%d,expire=%s}", 77 return fmt.Sprintf("NamecacheLookupResultMsg{id=%d,expire=%s}",
78 m.Id, m.Expire) 78 m.Id, m.Expire)
diff --git a/src/gnunet/message/msg_transport.go b/src/gnunet/message/msg_transport.go
index 1459d6a..54e63f2 100644
--- a/src/gnunet/message/msg_transport.go
+++ b/src/gnunet/message/msg_transport.go
@@ -4,22 +4,26 @@ import (
4 "fmt" 4 "fmt"
5 "time" 5 "time"
6 6
7 "github.com/bfix/gospel/crypto/ed25519" 7 "gnunet/crypto"
8 "github.com/bfix/gospel/data"
9 "gnunet/enums" 8 "gnunet/enums"
10 "gnunet/util" 9 "gnunet/util"
10
11 "github.com/bfix/gospel/crypto/ed25519"
12 "github.com/bfix/gospel/data"
11) 13)
12 14
13//---------------------------------------------------------------------- 15//----------------------------------------------------------------------
14// TRANSPORT_TCP_WELCOME 16// TRANSPORT_TCP_WELCOME
15//---------------------------------------------------------------------- 17//----------------------------------------------------------------------
16 18
19// TransportTcpWelcomeMsg
17type TransportTcpWelcomeMsg struct { 20type TransportTcpWelcomeMsg struct {
18 MsgSize uint16 `order:"big"` // total size of message 21 MsgSize uint16 `order:"big"` // total size of message
19 MsgType uint16 `order:"big"` // TRANSPORT_TCP_WELCOME (61) 22 MsgType uint16 `order:"big"` // TRANSPORT_TCP_WELCOME (61)
20 PeerID *util.PeerID // Peer identity (EdDSA public key) 23 PeerID *util.PeerID // Peer identity (EdDSA public key)
21} 24}
22 25
26// NewTransportTcpWelcomeMsg creates a new message for a given peer.
23func NewTransportTcpWelcomeMsg(peerid *util.PeerID) *TransportTcpWelcomeMsg { 27func NewTransportTcpWelcomeMsg(peerid *util.PeerID) *TransportTcpWelcomeMsg {
24 if peerid == nil { 28 if peerid == nil {
25 peerid = util.NewPeerID(nil) 29 peerid = util.NewPeerID(nil)
@@ -31,6 +35,7 @@ func NewTransportTcpWelcomeMsg(peerid *util.PeerID) *TransportTcpWelcomeMsg {
31 } 35 }
32} 36}
33 37
38// String returns a human-readable representation of the message.
34func (m *TransportTcpWelcomeMsg) String() string { 39func (m *TransportTcpWelcomeMsg) String() string {
35 return fmt.Sprintf("TransportTcpWelcomeMsg{peer=%s}", m.PeerID) 40 return fmt.Sprintf("TransportTcpWelcomeMsg{peer=%s}", m.PeerID)
36} 41}
@@ -41,6 +46,59 @@ func (msg *TransportTcpWelcomeMsg) Header() *MessageHeader {
41} 46}
42 47
43//---------------------------------------------------------------------- 48//----------------------------------------------------------------------
49// TRANSPORT_PING
50//
51// Message used to ask a peer to validate receipt (to check an address
52// from a HELLO). Followed by the address we are trying to validate,
53// or an empty address if we are just sending a PING to confirm that a
54// connection which the receiver (of the PING) initiated is still valid.
55//----------------------------------------------------------------------
56
57// TransportPingMsg
58type TransportPingMsg struct {
59 MsgSize uint16 `order:"big"` // total size of message
60 MsgType uint16 `order:"big"` // TRANSPORT_PING (372)
61 Challenge uint32 // Challenge code (to ensure fresh reply)
62 Target *util.PeerID // EdDSA public key (long-term) of target peer
63 Address []byte `size:"*"` // encoded address
64}
65
66// TransportPingMsg creates a new message for given peer with an address to
67// be validated.
68func NewTransportPingMsg(target *util.PeerID, a *util.Address) *TransportPingMsg {
69 if target == nil {
70 target = util.NewPeerID(nil)
71 }
72 m := &TransportPingMsg{
73 MsgSize: uint16(40),
74 MsgType: TRANSPORT_PING,
75 Challenge: util.RndUInt32(),
76 Target: target,
77 Address: nil,
78 }
79 if a != nil {
80 if addrData, err := data.Marshal(a); err == nil {
81 m.Address = addrData
82 m.MsgSize += uint16(len(addrData))
83 }
84 }
85 return m
86}
87
88// String returns a human-readable representation of the message.
89func (m *TransportPingMsg) String() string {
90 a := new(util.Address)
91 data.Unmarshal(a, m.Address)
92 return fmt.Sprintf("TransportPingMsg{target=%s,addr=%s,challenge=%d}",
93 m.Target, a, m.Challenge)
94}
95
96// Header returns the message header in a separate instance.
97func (msg *TransportPingMsg) Header() *MessageHeader {
98 return &MessageHeader{msg.MsgSize, msg.MsgType}
99}
100
101//----------------------------------------------------------------------
44// TRANSPORT_PONG 102// TRANSPORT_PONG
45// 103//
46// Message used to validate a HELLO. The challenge is included in the 104// Message used to validate a HELLO. The challenge is included in the
@@ -53,29 +111,33 @@ func (msg *TransportTcpWelcomeMsg) Header() *MessageHeader {
53// a connection that we initiated). 111// a connection that we initiated).
54//---------------------------------------------------------------------- 112//----------------------------------------------------------------------
55 113
114// SignedAddress is the signed block of data representing a node address
56type SignedAddress struct { 115type SignedAddress struct {
57 SignLength uint32 `order:"big"` // Length of signed block 116 Purpose *crypto.SignaturePurpose // SIG_TRANSPORT_PONG_OWN
58 Purpose uint32 `order:"big"` // SIG_TRANSPORT_PONG_OWN 117 ExpireOn util.AbsoluteTime // usec epoch
59 ExpireOn util.AbsoluteTime // usec epoch 118 AddrSize uint32 `order:"big"` // size of address
60 AddrSize uint32 `order:"big"` // size of address 119 Address []byte `size:"AddrSize"` // address
61 Address []byte `size:"AddrSize"` // address
62} 120}
63 121
122// NewSignedAddress creates a new (signable) data block from an address.
64func NewSignedAddress(a *util.Address) *SignedAddress { 123func NewSignedAddress(a *util.Address) *SignedAddress {
65 // serialize address 124 // serialize address
66 addrData, _ := data.Marshal(a) 125 addrData, _ := data.Marshal(a)
67 alen := len(addrData) 126 alen := len(addrData)
68 addr := &SignedAddress{ 127 addr := &SignedAddress{
69 SignLength: uint32(alen + 20), 128 Purpose: &crypto.SignaturePurpose{
70 Purpose: enums.SIG_TRANSPORT_PONG_OWN, 129 Size: uint32(alen + 20),
71 ExpireOn: util.AbsoluteTimeNow().Add(12 * time.Hour), 130 Purpose: enums.SIG_TRANSPORT_PONG_OWN,
72 AddrSize: uint32(alen), 131 },
73 Address: make([]byte, alen), 132 ExpireOn: util.AbsoluteTimeNow().Add(12 * time.Hour),
133 AddrSize: uint32(alen),
134 Address: make([]byte, alen),
74 } 135 }
75 copy(addr.Address, addrData) 136 copy(addr.Address, addrData)
76 return addr 137 return addr
77} 138}
78 139
140// TransportPongMsg
79type TransportPongMsg struct { 141type TransportPongMsg struct {
80 MsgSize uint16 `order:"big"` // total size of message 142 MsgSize uint16 `order:"big"` // total size of message
81 MsgType uint16 `order:"big"` // TRANSPORT_PING (372) 143 MsgType uint16 `order:"big"` // TRANSPORT_PING (372)
@@ -84,6 +146,8 @@ type TransportPongMsg struct {
84 SignedBlock *SignedAddress // signed block of data 146 SignedBlock *SignedAddress // signed block of data
85} 147}
86 148
149// NewTransportPongMsg creates a reponse message with an address the replying
150// peer wants to be reached.
87func NewTransportPongMsg(challenge uint32, a *util.Address) *TransportPongMsg { 151func NewTransportPongMsg(challenge uint32, a *util.Address) *TransportPongMsg {
88 m := &TransportPongMsg{ 152 m := &TransportPongMsg{
89 MsgSize: 72, 153 MsgSize: 72,
@@ -94,12 +158,13 @@ func NewTransportPongMsg(challenge uint32, a *util.Address) *TransportPongMsg {
94 } 158 }
95 if a != nil { 159 if a != nil {
96 sa := NewSignedAddress(a) 160 sa := NewSignedAddress(a)
97 m.MsgSize += uint16(sa.SignLength) 161 m.MsgSize += uint16(sa.Purpose.Size)
98 m.SignedBlock = sa 162 m.SignedBlock = sa
99 } 163 }
100 return m 164 return m
101} 165}
102 166
167// String returns a human-readable representation of the message.
103func (m *TransportPongMsg) String() string { 168func (m *TransportPongMsg) String() string {
104 a := new(util.Address) 169 a := new(util.Address)
105 if err := data.Unmarshal(a, m.SignedBlock.Address); err == nil { 170 if err := data.Unmarshal(a, m.SignedBlock.Address); err == nil {
@@ -114,6 +179,7 @@ func (msg *TransportPongMsg) Header() *MessageHeader {
114 return &MessageHeader{msg.MsgSize, msg.MsgType} 179 return &MessageHeader{msg.MsgSize, msg.MsgType}
115} 180}
116 181
182// Sign the address block of a pong message.
117func (m *TransportPongMsg) Sign(prv *ed25519.PrivateKey) error { 183func (m *TransportPongMsg) Sign(prv *ed25519.PrivateKey) error {
118 data, err := data.Marshal(m.SignedBlock) 184 data, err := data.Marshal(m.SignedBlock)
119 if err != nil { 185 if err != nil {
@@ -127,6 +193,7 @@ func (m *TransportPongMsg) Sign(prv *ed25519.PrivateKey) error {
127 return nil 193 return nil
128} 194}
129 195
196// Verify the address block of a pong message
130func (m *TransportPongMsg) Verify(pub *ed25519.PublicKey) (bool, error) { 197func (m *TransportPongMsg) Verify(pub *ed25519.PublicKey) (bool, error) {
131 data, err := data.Marshal(m.SignedBlock) 198 data, err := data.Marshal(m.SignedBlock)
132 if err != nil { 199 if err != nil {
@@ -140,55 +207,6 @@ func (m *TransportPongMsg) Verify(pub *ed25519.PublicKey) (bool, error) {
140} 207}
141 208
142//---------------------------------------------------------------------- 209//----------------------------------------------------------------------
143// TRANSPORT_PING
144//
145// Message used to ask a peer to validate receipt (to check an address
146// from a HELLO). Followed by the address we are trying to validate,
147// or an empty address if we are just sending a PING to confirm that a
148// connection which the receiver (of the PING) initiated is still valid.
149//----------------------------------------------------------------------
150
151type TransportPingMsg struct {
152 MsgSize uint16 `order:"big"` // total size of message
153 MsgType uint16 `order:"big"` // TRANSPORT_PING (372)
154 Challenge uint32 // Challenge code (to ensure fresh reply)
155 Target *util.PeerID // EdDSA public key (long-term) of target peer
156 Address []byte `size:"*"` // encoded address
157}
158
159func NewTransportPingMsg(target *util.PeerID, a *util.Address) *TransportPingMsg {
160 if target == nil {
161 target = util.NewPeerID(nil)
162 }
163 m := &TransportPingMsg{
164 MsgSize: uint16(40),
165 MsgType: TRANSPORT_PING,
166 Challenge: util.RndUInt32(),
167 Target: target,
168 Address: nil,
169 }
170 if a != nil {
171 if addrData, err := data.Marshal(a); err == nil {
172 m.Address = addrData
173 m.MsgSize += uint16(len(addrData))
174 }
175 }
176 return m
177}
178
179func (m *TransportPingMsg) String() string {
180 a := new(util.Address)
181 data.Unmarshal(a, m.Address)
182 return fmt.Sprintf("TransportPingMsg{target=%s,addr=%s,challenge=%d}",
183 m.Target, a, m.Challenge)
184}
185
186// Header returns the message header in a separate instance.
187func (msg *TransportPingMsg) Header() *MessageHeader {
188 return &MessageHeader{msg.MsgSize, msg.MsgType}
189}
190
191//----------------------------------------------------------------------
192// HELLO 210// HELLO
193// 211//
194// A HELLO message is used to exchange information about 212// A HELLO message is used to exchange information about
@@ -202,6 +220,7 @@ func (msg *TransportPingMsg) Header() *MessageHeader {
202// 4) address (address-length bytes) 220// 4) address (address-length bytes)
203//---------------------------------------------------------------------- 221//----------------------------------------------------------------------
204 222
223// HelloAddress
205type HelloAddress struct { 224type HelloAddress struct {
206 Transport string // Name of transport 225 Transport string // Name of transport
207 AddrSize uint16 `order:"big"` // Size of address entry 226 AddrSize uint16 `order:"big"` // Size of address entry
@@ -209,6 +228,7 @@ type HelloAddress struct {
209 Address []byte `size:"AddrSize"` // Address specification 228 Address []byte `size:"AddrSize"` // Address specification
210} 229}
211 230
231// NewHelloAddress create a new HELLO address from the given address
212func NewAddress(a *util.Address) *HelloAddress { 232func NewAddress(a *util.Address) *HelloAddress {
213 addr := &HelloAddress{ 233 addr := &HelloAddress{
214 Transport: a.Transport, 234 Transport: a.Transport,
@@ -220,11 +240,13 @@ func NewAddress(a *util.Address) *HelloAddress {
220 return addr 240 return addr
221} 241}
222 242
243// String returns a human-readable representation of the message.
223func (a *HelloAddress) String() string { 244func (a *HelloAddress) String() string {
224 return fmt.Sprintf("Address{%s,expire=%s}", 245 return fmt.Sprintf("Address{%s,expire=%s}",
225 util.AddressString(a.Transport, a.Address), a.ExpireOn) 246 util.AddressString(a.Transport, a.Address), a.ExpireOn)
226} 247}
227 248
249// HelloMsg
228type HelloMsg struct { 250type HelloMsg struct {
229 MsgSize uint16 `order:"big"` // total size of message 251 MsgSize uint16 `order:"big"` // total size of message
230 MsgType uint16 `order:"big"` // HELLO (17) 252 MsgType uint16 `order:"big"` // HELLO (17)
@@ -233,6 +255,7 @@ type HelloMsg struct {
233 Addresses []*HelloAddress `size:"*"` // List of end-point addressess 255 Addresses []*HelloAddress `size:"*"` // List of end-point addressess
234} 256}
235 257
258// NewHelloMsg creates a new HELLO msg for a given peer.
236func NewHelloMsg(peerid *util.PeerID) *HelloMsg { 259func NewHelloMsg(peerid *util.PeerID) *HelloMsg {
237 if peerid == nil { 260 if peerid == nil {
238 peerid = util.NewPeerID(nil) 261 peerid = util.NewPeerID(nil)
@@ -246,11 +269,13 @@ func NewHelloMsg(peerid *util.PeerID) *HelloMsg {
246 } 269 }
247} 270}
248 271
272// String returns a human-readable representation of the message.
249func (m *HelloMsg) String() string { 273func (m *HelloMsg) String() string {
250 return fmt.Sprintf("HelloMsg{peer=%s,friendsonly=%d,addr=%v}", 274 return fmt.Sprintf("HelloMsg{peer=%s,friendsonly=%d,addr=%v}",
251 m.PeerID, m.FriendOnly, m.Addresses) 275 m.PeerID, m.FriendOnly, m.Addresses)
252} 276}
253 277
278// AddAddress adds a new address to the HELLO message.
254func (m *HelloMsg) AddAddress(a *HelloAddress) { 279func (m *HelloMsg) AddAddress(a *HelloAddress) {
255 m.Addresses = append(m.Addresses, a) 280 m.Addresses = append(m.Addresses, a)
256 m.MsgSize += uint16(len(a.Transport)) + a.AddrSize + 11 281 m.MsgSize += uint16(len(a.Transport)) + a.AddrSize + 11
@@ -265,11 +290,13 @@ func (msg *HelloMsg) Header() *MessageHeader {
265// TRANSPORT_SESSION_ACK 290// TRANSPORT_SESSION_ACK
266//---------------------------------------------------------------------- 291//----------------------------------------------------------------------
267 292
293// SessionAckMsg
268type SessionAckMsg struct { 294type SessionAckMsg struct {
269 MsgSize uint16 `order:"big"` // total size of message 295 MsgSize uint16 `order:"big"` // total size of message
270 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_ACK (377) 296 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_ACK (377)
271} 297}
272 298
299// NewSessionAckMsg creates an new message (no body required).
273func NewSessionAckMsg() *SessionAckMsg { 300func NewSessionAckMsg() *SessionAckMsg {
274 return &SessionAckMsg{ 301 return &SessionAckMsg{
275 MsgSize: 16, 302 MsgSize: 16,
@@ -277,6 +304,7 @@ func NewSessionAckMsg() *SessionAckMsg {
277 } 304 }
278} 305}
279 306
307// String returns a human-readable representation of the message.
280func (m *SessionAckMsg) String() string { 308func (m *SessionAckMsg) String() string {
281 return "SessionAck{}" 309 return "SessionAck{}"
282} 310}
@@ -290,6 +318,7 @@ func (msg *SessionAckMsg) Header() *MessageHeader {
290// TRANSPORT_SESSION_SYN 318// TRANSPORT_SESSION_SYN
291//---------------------------------------------------------------------- 319//----------------------------------------------------------------------
292 320
321// SessionSynMsg
293type SessionSynMsg struct { 322type SessionSynMsg struct {
294 MsgSize uint16 `order:"big"` // total size of message 323 MsgSize uint16 `order:"big"` // total size of message
295 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN (375) 324 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN (375)
@@ -297,6 +326,7 @@ type SessionSynMsg struct {
297 Timestamp util.AbsoluteTime // usec epoch 326 Timestamp util.AbsoluteTime // usec epoch
298} 327}
299 328
329// NewSessionSynMsg creates a SYN request for the a session
300func NewSessionSynMsg() *SessionSynMsg { 330func NewSessionSynMsg() *SessionSynMsg {
301 return &SessionSynMsg{ 331 return &SessionSynMsg{
302 MsgSize: 16, 332 MsgSize: 16,
@@ -306,6 +336,7 @@ func NewSessionSynMsg() *SessionSynMsg {
306 } 336 }
307} 337}
308 338
339// String returns a human-readable representation of the message.
309func (m *SessionSynMsg) String() string { 340func (m *SessionSynMsg) String() string {
310 return fmt.Sprintf("SessionSyn{timestamp=%s}", m.Timestamp) 341 return fmt.Sprintf("SessionSyn{timestamp=%s}", m.Timestamp)
311} 342}
@@ -319,6 +350,7 @@ func (msg *SessionSynMsg) Header() *MessageHeader {
319// TRANSPORT_SESSION_SYN_ACK 350// TRANSPORT_SESSION_SYN_ACK
320//---------------------------------------------------------------------- 351//----------------------------------------------------------------------
321 352
353// SessionSynAckMsg
322type SessionSynAckMsg struct { 354type SessionSynAckMsg struct {
323 MsgSize uint16 `order:"big"` // total size of message 355 MsgSize uint16 `order:"big"` // total size of message
324 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN_ACK (376) 356 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN_ACK (376)
@@ -326,6 +358,7 @@ type SessionSynAckMsg struct {
326 Timestamp util.AbsoluteTime // usec epoch 358 Timestamp util.AbsoluteTime // usec epoch
327} 359}
328 360
361// NewSessionSynAckMsg is an ACK for a SYN request
329func NewSessionSynAckMsg() *SessionSynAckMsg { 362func NewSessionSynAckMsg() *SessionSynAckMsg {
330 return &SessionSynAckMsg{ 363 return &SessionSynAckMsg{
331 MsgSize: 16, 364 MsgSize: 16,
@@ -335,6 +368,7 @@ func NewSessionSynAckMsg() *SessionSynAckMsg {
335 } 368 }
336} 369}
337 370
371// String returns a human-readable representation of the message.
338func (m *SessionSynAckMsg) String() string { 372func (m *SessionSynAckMsg) String() string {
339 return fmt.Sprintf("SessionSynAck{timestamp=%s}", m.Timestamp) 373 return fmt.Sprintf("SessionSynAck{timestamp=%s}", m.Timestamp)
340} 374}
@@ -348,12 +382,14 @@ func (msg *SessionSynAckMsg) Header() *MessageHeader {
348// TRANSPORT_SESSION_QUOTA 382// TRANSPORT_SESSION_QUOTA
349//---------------------------------------------------------------------- 383//----------------------------------------------------------------------
350 384
385// SessionQuotaMsg
351type SessionQuotaMsg struct { 386type SessionQuotaMsg struct {
352 MsgSize uint16 `order:"big"` // total size of message 387 MsgSize uint16 `order:"big"` // total size of message
353 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_QUOTA (379) 388 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_QUOTA (379)
354 Quota uint32 `order:"big"` // Quota in bytes per second 389 Quota uint32 `order:"big"` // Quota in bytes per second
355} 390}
356 391
392// NewSessionQuotaMsg announces a session quota to the other end of the session.
357func NewSessionQuotaMsg(quota uint32) *SessionQuotaMsg { 393func NewSessionQuotaMsg(quota uint32) *SessionQuotaMsg {
358 m := new(SessionQuotaMsg) 394 m := new(SessionQuotaMsg)
359 if quota > 0 { 395 if quota > 0 {
@@ -364,6 +400,7 @@ func NewSessionQuotaMsg(quota uint32) *SessionQuotaMsg {
364 return m 400 return m
365} 401}
366 402
403// String returns a human-readable representation of the message.
367func (m *SessionQuotaMsg) String() string { 404func (m *SessionQuotaMsg) String() string {
368 return fmt.Sprintf("SessionQuotaMsg{%sB/s}", util.Scale1024(uint64(m.Quota))) 405 return fmt.Sprintf("SessionQuotaMsg{%sB/s}", util.Scale1024(uint64(m.Quota)))
369} 406}
@@ -374,57 +411,63 @@ func (msg *SessionQuotaMsg) Header() *MessageHeader {
374} 411}
375 412
376//---------------------------------------------------------------------- 413//----------------------------------------------------------------------
377// TRANSPORT_SESSION_KEEPALIVE_RESPONSE 414// TRANSPORT_SESSION_KEEPALIVE
378//---------------------------------------------------------------------- 415//----------------------------------------------------------------------
379 416
380type SessionKeepAliveRespMsg struct { 417// SessionKeepAliveMsg
418type SessionKeepAliveMsg struct {
381 MsgSize uint16 `order:"big"` // total size of message 419 MsgSize uint16 `order:"big"` // total size of message
382 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE_RESPONSE (382) 420 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE (381)
383 Nonce uint32 421 Nonce uint32
384} 422}
385 423
386func NewSessionKeepAliveRespMsg(nonce uint32) *SessionKeepAliveRespMsg { 424// NewSessionKeepAliveMsg creates a new request to keep a session.
387 m := &SessionKeepAliveRespMsg{ 425func NewSessionKeepAliveMsg() *SessionKeepAliveMsg {
426 m := &SessionKeepAliveMsg{
388 MsgSize: 8, 427 MsgSize: 8,
389 MsgType: TRANSPORT_SESSION_KEEPALIVE_RESPONSE, 428 MsgType: TRANSPORT_SESSION_KEEPALIVE,
390 Nonce: nonce, 429 Nonce: util.RndUInt32(),
391 } 430 }
392 return m 431 return m
393} 432}
394 433
395func (m *SessionKeepAliveRespMsg) String() string { 434// String returns a human-readable representation of the message.
396 return fmt.Sprintf("SessionKeepAliveRespMsg{%d}", m.Nonce) 435func (m *SessionKeepAliveMsg) String() string {
436 return fmt.Sprintf("SessionKeepAliveMsg{%d}", m.Nonce)
397} 437}
398 438
399// Header returns the message header in a separate instance. 439// Header returns the message header in a separate instance.
400func (msg *SessionKeepAliveRespMsg) Header() *MessageHeader { 440func (msg *SessionKeepAliveMsg) Header() *MessageHeader {
401 return &MessageHeader{msg.MsgSize, msg.MsgType} 441 return &MessageHeader{msg.MsgSize, msg.MsgType}
402} 442}
403 443
404//---------------------------------------------------------------------- 444//----------------------------------------------------------------------
405// TRANSPORT_SESSION_KEEPALIVE 445// TRANSPORT_SESSION_KEEPALIVE_RESPONSE
406//---------------------------------------------------------------------- 446//----------------------------------------------------------------------
407 447
408type SessionKeepAliveMsg struct { 448// SessionKeepAliveRespMsg
449type SessionKeepAliveRespMsg struct {
409 MsgSize uint16 `order:"big"` // total size of message 450 MsgSize uint16 `order:"big"` // total size of message
410 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE (381) 451 MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE_RESPONSE (382)
411 Nonce uint32 452 Nonce uint32
412} 453}
413 454
414func NewSessionKeepAliveMsg() *SessionKeepAliveMsg { 455// NewSessionKeepAliveRespMsg is a response message for a "keep session" request.
415 m := &SessionKeepAliveMsg{ 456func NewSessionKeepAliveRespMsg(nonce uint32) *SessionKeepAliveRespMsg {
457 m := &SessionKeepAliveRespMsg{
416 MsgSize: 8, 458 MsgSize: 8,
417 MsgType: TRANSPORT_SESSION_KEEPALIVE, 459 MsgType: TRANSPORT_SESSION_KEEPALIVE_RESPONSE,
418 Nonce: util.RndUInt32(), 460 Nonce: nonce,
419 } 461 }
420 return m 462 return m
421} 463}
422 464
423func (m *SessionKeepAliveMsg) String() string { 465// String returns a human-readable representation of the message.
424 return fmt.Sprintf("SessionKeepAliveMsg{%d}", m.Nonce) 466func (m *SessionKeepAliveRespMsg) String() string {
467 return fmt.Sprintf("SessionKeepAliveRespMsg{%d}", m.Nonce)
425} 468}
426 469
427// Header returns the message header in a separate instance. 470// Header returns the message header in a separate instance.
428func (msg *SessionKeepAliveMsg) Header() *MessageHeader { 471func (msg *SessionKeepAliveRespMsg) Header() *MessageHeader {
429 return &MessageHeader{msg.MsgSize, msg.MsgType} 472 return &MessageHeader{msg.MsgSize, msg.MsgType}
430} 473}
diff --git a/src/gnunet/service/client.go b/src/gnunet/service/client.go
index 2d1c3dd..3bae7da 100644
--- a/src/gnunet/service/client.go
+++ b/src/gnunet/service/client.go
@@ -1,9 +1,10 @@
1package service 1package service
2 2
3import ( 3import (
4 "github.com/bfix/gospel/logger"
5 "gnunet/message" 4 "gnunet/message"
6 "gnunet/transport" 5 "gnunet/transport"
6
7 "github.com/bfix/gospel/logger"
7) 8)
8 9
9// Client 10// Client
diff --git a/src/gnunet/service/gns/block.go b/src/gnunet/service/gns/block.go
new file mode 100644
index 0000000..9d83f99
--- /dev/null
+++ b/src/gnunet/service/gns/block.go
@@ -0,0 +1,185 @@
1package gns
2
3import (
4 "fmt"
5
6 "gnunet/crypto"
7 "gnunet/enums"
8 "gnunet/message"
9 "gnunet/util"
10
11 "github.com/bfix/gospel/crypto/ed25519"
12 "github.com/bfix/gospel/data"
13)
14
15var (
16 ErrBlockNotDecrypted = fmt.Errorf("GNS block not decrypted")
17)
18
19//======================================================================
20// GNS block: An encrypted and signed container for GNS resource records
21// that represents the "atomic" data structure associated with a GNS
22// label in a given zone.
23//======================================================================
24
25// SignedBlockData: signed and encrypted list of resource records stored
26// in a GNSRecordSet
27type SignedBlockData struct {
28 Purpose *crypto.SignaturePurpose // Size and purpose of signature (8 bytes)
29 Expire util.AbsoluteTime // Expiration time of the block.
30 EncData []byte `size:"*"` // encrypted GNSRecordSet
31
32 // transient data (not serialized)
33 data []byte // unencrypted GNSRecord set
34}
35
36// GNSBlock is the result of GNS lookups for a given label in a zone.
37type GNSBlock struct {
38 Signature []byte `size:"64"` // Signature of the block.
39 DerivedKey []byte `size:"32"` // Derived key used for signing
40 Block *SignedBlockData
41
42 // transient data (not serialized)
43 checked bool // block integrity checked
44 verified bool // block signature verified (internal)
45 decrypted bool // block data decrypted (internal)
46}
47
48// String returns the human-readable representation of a GNSBlock
49func (b *GNSBlock) String() string {
50 return fmt.Sprintf("GNSBlock{Verified=%v,Decrypted=%v,data=[%d]}",
51 b.verified, b.decrypted, len(b.Block.EncData))
52}
53
54// Records returns the list of resource records in a block.
55func (b *GNSBlock) Records() ([]*message.GNSResourceRecord, error) {
56 // check if block is decrypted
57 if !b.decrypted {
58 return nil, ErrBlockNotDecrypted
59 }
60 // parse block data into record set
61 rs := NewGNSRecordSet()
62 if err := data.Unmarshal(rs, b.Block.data); err != nil {
63 return nil, err
64 }
65 return rs.Records, nil
66}
67
68// Verify the integrity of the block data from a signature.
69func (b *GNSBlock) Verify(zoneKey *ed25519.PublicKey, label string) (err error) {
70 // Integrity check performed
71 b.checked = true
72
73 // verify derived key
74 dkey := ed25519.NewPublicKeyFromBytes(b.DerivedKey)
75 dkey2 := crypto.DerivePublicKey(zoneKey, label, "gns")
76 if !dkey.Q.Equals(dkey2.Q) {
77 return fmt.Errorf("Invalid signature key for GNS Block")
78 }
79 // verify signature
80 var (
81 sig *ed25519.EcSignature
82 buf []byte
83 ok bool
84 )
85 if sig, err = ed25519.NewEcSignatureFromBytes(b.Signature); err != nil {
86 return
87 }
88 if buf, err = data.Marshal(b.Block); err != nil {
89 return
90 }
91 if ok, err = dkey.EcVerify(buf, sig); err == nil && !ok {
92 err = fmt.Errorf("Signature verification failed for GNS block")
93 }
94 b.verified = true
95 return
96}
97
98// Decrypt block data with a key/iv combination derived from (PKEY,label)
99func (b *GNSBlock) Decrypt(zoneKey *ed25519.PublicKey, label string) (err error) {
100 // decrypt payload
101 b.Block.data, err = crypto.DecryptBlock(b.Block.EncData, zoneKey, label)
102 b.decrypted = true
103 return
104}
105
106// NewGNSBlock instantiates an empty GNS block
107func NewGNSBlock() *GNSBlock {
108 return &GNSBlock{
109 Signature: make([]byte, 64),
110 DerivedKey: make([]byte, 32),
111 Block: &SignedBlockData{
112 Purpose: new(crypto.SignaturePurpose),
113 Expire: *new(util.AbsoluteTime),
114 EncData: nil,
115 data: nil,
116 },
117 checked: false,
118 verified: false,
119 decrypted: false,
120 }
121}
122
123//----------------------------------------------------------------------
124// GNSRecordSet
125//----------------------------------------------------------------------
126
127// GNSRecordSet ist the GNUnet data structure for a list of resource records
128// in a GNSBlock. As part of GNUnet messages, the record set is padded so that
129// the binary size of (records||padding) is the smallest power of two.
130type GNSRecordSet struct {
131 Count uint32 `order:"big"` // number of resource records
132 Records []*message.GNSResourceRecord `size:"Count"` // list of resource records
133 Padding []byte `size:"*"` // padding
134}
135
136// NewGNSRecordSet returns an empty resource record set.
137func NewGNSRecordSet() *GNSRecordSet {
138 return &GNSRecordSet{
139 Count: 0,
140 Records: make([]*message.GNSResourceRecord, 0),
141 Padding: make([]byte, 0),
142 }
143}
144
145// AddRecord to append a resource record to the set.
146func (rs *GNSRecordSet) AddRecord(rec *message.GNSResourceRecord) {
147 rs.Count++
148 rs.Records = append(rs.Records, rec)
149}
150
151//======================================================================
152// List of resource records types (for GNS/DNS queries)
153//======================================================================
154
155// RRTypeList is a list of integers representing RR types.
156type RRTypeList []int
157
158// Initialize a new type list with given type values
159func NewRRTypeList(args ...int) (res RRTypeList) {
160 for _, val := range args {
161 // if GNS_TYPE_ANY is encountered, it becomes the sole type
162 if val == enums.GNS_TYPE_ANY {
163 res = make(RRTypeList, 1)
164 res[0] = val
165 return
166 }
167 res = append(res, val)
168 }
169 return
170}
171
172// HasType returns true if the type is included in the list
173func (tl RRTypeList) HasType(t int) bool {
174 // return true if type is GNS_TYPE_ANY
175 if tl[0] == enums.GNS_TYPE_ANY {
176 return true
177 }
178 // check for type in list
179 for _, val := range tl {
180 if val == t {
181 return true
182 }
183 }
184 return false
185}
diff --git a/src/gnunet/service/gns/block_handler.go b/src/gnunet/service/gns/block_handler.go
new file mode 100644
index 0000000..860b4a7
--- /dev/null
+++ b/src/gnunet/service/gns/block_handler.go
@@ -0,0 +1,398 @@
1package gns
2
3import (
4 "encoding/hex"
5 "fmt"
6
7 "gnunet/enums"
8 "gnunet/message"
9
10 "github.com/bfix/gospel/crypto/ed25519"
11 "github.com/bfix/gospel/logger"
12)
13
14// HdlrInst is the type for functions that instanciate custom block handlers.
15type HdlrInst func(*message.GNSResourceRecord, []string) (BlockHandler, error)
16
17// Error codes
18var (
19 ErrInvalidRecordMix = fmt.Errorf("Invalid mix of RR types in block")
20 ErrBlockHandler = fmt.Errorf("Internal block handler failure")
21)
22
23// Mapping of RR types to BlockHandler instanciation functions
24var (
25 customHandler = map[int]HdlrInst{
26 enums.GNS_TYPE_PKEY: NewPkeyHandler,
27 enums.GNS_TYPE_GNS2DNS: NewGns2DnsHandler,
28 enums.GNS_TYPE_BOX: NewBoxHandler,
29 enums.GNS_TYPE_LEHO: NewLehoHandler,
30 }
31)
32
33//======================================================================
34// GNS blocks that contain special records (PKEY, GNS2DNS, BOX, LEHO...)
35// require special treatment with respect to other resource records with
36// different types in the same block. Usually only certain other types
37// (or none at all) are allowed.
38//======================================================================
39
40// BlockHandler interface.
41type BlockHandler interface {
42 // AddRecord inserts a RR into the BlockHandler for (later) processing.
43 // The handler can inspect the remaining labels in a path if required.
44 // It returns an error if a record is not accepted by the block handler.
45 AddRecord(rr *message.GNSResourceRecord, labels []string) error
46
47 // TypeAction returns a flag indicating how a resource record of a
48 // given type is to be treated by a custom block handler:
49 // = -1: Record is not allowed
50 // = 0: Record is allowed but will be ignored
51 // = 1: Record is allowed and will be processed
52 TypeAction(t int) int
53
54 // Records returns a list of RR of the given types associated with
55 // the custom handler
56 Records(kind RRTypeList) *GNSRecordSet
57}
58
59//----------------------------------------------------------------------
60// Manage list of block handlers
61// Under normal circumstances there is only one (or none) block handler
62// per block, but future constructs may allow multiple block handlers
63// to be present. The block handler list implements the BlockHandler
64// interface.
65// The BlockHandlerList maintains a map of actually instantiated handlers
66// (indexed by record type) and a list of record types (with occurrence
67// count) in the block.
68//----------------------------------------------------------------------
69
70// BlockHandlerList is a list of block handlers instantiated.
71type BlockHandlerList struct {
72 list map[int]BlockHandler // list of handler instances
73}
74
75// NewBlockHandlerList instantiates an a list of active block handlers
76// for a given set of records (GNS block).
77func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) (*BlockHandlerList, error) {
78 // initialize block handler list
79 hl := &BlockHandlerList{
80 list: make(map[int]BlockHandler),
81 }
82 // build a list of record types that are handled by a custom handler.
83 rrList := NewRRTypeList(
84 enums.GNS_TYPE_PKEY,
85 enums.GNS_TYPE_GNS2DNS,
86 enums.GNS_TYPE_BOX,
87 enums.GNS_TYPE_LEHO)
88
89 // Traverse record list and build list of handler instances
90 for _, rec := range records {
91 // check for custom handler type
92 rrType := int(rec.Type)
93 if rrList.HasType(rrType) {
94 // check if a handler for given type already exists
95 var (
96 hdlr BlockHandler
97 ok bool
98 err error
99 )
100 if hdlr, ok = hl.list[rrType]; ok {
101 // add record to existing handler
102 if err = hdlr.AddRecord(rec, labels); err != nil {
103 return nil, err
104 }
105 continue
106 }
107 // create a new handler instance
108 switch rrType {
109 case enums.GNS_TYPE_PKEY:
110 hdlr, err = NewPkeyHandler(rec, labels)
111 case enums.GNS_TYPE_GNS2DNS:
112 hdlr, err = NewGns2DnsHandler(rec, labels)
113 case enums.GNS_TYPE_BOX:
114 hdlr, err = NewBoxHandler(rec, labels)
115 case enums.GNS_TYPE_LEHO:
116 hdlr, err = NewLehoHandler(rec, labels)
117 }
118 if err != nil {
119 return nil, err
120 }
121 // store handler in list
122 hl.list[rrType] = hdlr
123 }
124 }
125 return hl, nil
126}
127
128// GetHandler returns a BlockHandler for the given key. If no block handler exists
129// under the given name, a new one is created and stored in the list. The type of
130// the new block handler is derived from the key value.
131func (hl *BlockHandlerList) GetHandler(t int) BlockHandler {
132 // return handler for given key if it exists
133 if hdlr, ok := hl.list[t]; ok {
134 return hdlr
135 }
136 return nil
137}
138
139//----------------------------------------------------------------------
140// PKEY handler: Only one PKEY as sole record in a block
141//----------------------------------------------------------------------
142
143// PkeyHandler implementing the BlockHandler interface
144type PkeyHandler struct {
145 pkey *ed25519.PublicKey // Zone key
146 rec *message.GNSResourceRecord // associated recource record
147}
148
149// NewPkeyHandler returns a new BlockHandler instance
150func NewPkeyHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) {
151 if int(rec.Type) != enums.GNS_TYPE_PKEY {
152 return nil, ErrInvalidRecordType
153 }
154 h := &PkeyHandler{
155 pkey: nil,
156 }
157 if err := h.AddRecord(rec, labels); err != nil {
158 return nil, err
159 }
160 return h, nil
161}
162
163// AddRecord inserts a PKEY record into the handler.
164func (h *PkeyHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error {
165 if int(rec.Type) != enums.GNS_TYPE_PKEY {
166 return ErrInvalidRecordType
167 }
168 // check for sole PKEY record in block
169 if h.pkey != nil {
170 return ErrInvalidPKEY
171 }
172 // check for sane key data
173 if len(rec.Data) != 32 {
174 return ErrInvalidPKEY
175 }
176 // set a PKEY handler
177 h.pkey = ed25519.NewPublicKeyFromBytes(rec.Data)
178 h.rec = rec
179 return nil
180}
181
182// TypeAction return a flag indicating how a resource record of a given type
183// is to be treated (see BlockHandler interface)
184func (h *PkeyHandler) TypeAction(t int) int {
185 // no other resource record type is not allowed
186 if t == enums.GNS_TYPE_PKEY {
187 return 1
188 }
189 return -1
190}
191
192// Records returns a list of RR of the given type associated with this handler
193func (h *PkeyHandler) Records(kind RRTypeList) *GNSRecordSet {
194 rs := NewGNSRecordSet()
195 if kind.HasType(enums.GNS_TYPE_PKEY) {
196 rs.AddRecord(h.rec)
197 }
198 return rs
199}
200
201//----------------------------------------------------------------------
202// GNS2DNS handler
203//----------------------------------------------------------------------
204
205// Gns2DnsHandler implementing the BlockHandler interface
206type Gns2DnsHandler struct {
207 Name string // DNS query name
208 Servers []string // DNS servers to ask
209 recs []*message.GNSResourceRecord // list of rersource records
210}
211
212// NewGns2DnsHandler returns a new BlockHandler instance
213func NewGns2DnsHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) {
214 if int(rec.Type) != enums.GNS_TYPE_GNS2DNS {
215 return nil, ErrInvalidRecordType
216 }
217 h := &Gns2DnsHandler{
218 Name: "",
219 Servers: make([]string, 0),
220 recs: make([]*message.GNSResourceRecord, 0),
221 }
222 if err := h.AddRecord(rec, labels); err != nil {
223 return nil, err
224 }
225 return h, nil
226}
227
228// AddRecord inserts a GNS2DNS record into the handler.
229func (h *Gns2DnsHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error {
230 if int(rec.Type) != enums.GNS_TYPE_GNS2DNS {
231 return ErrInvalidRecordType
232 }
233 logger.Printf(logger.DBG, "[gns] GNS2DNS data: %s\n", hex.EncodeToString(rec.Data))
234
235 // extract list of names in DATA block:
236 next, dnsQuery := DNSNameFromBytes(rec.Data, 0)
237 dnsServer := string(rec.Data[next : len(rec.Data)-1])
238 logger.Printf(logger.DBG, "[gns] GNS2DNS query '%s'@'%s'\n", dnsQuery, dnsServer)
239 if len(dnsServer) == 0 || len(dnsQuery) == 0 {
240 return ErrInvalidRecordBody
241 }
242
243 // check if all GNS2DNS records refer to the same query name
244 if len(h.Servers) == 0 {
245 h.Name = dnsQuery
246 }
247 if dnsQuery != h.Name {
248 return ErrInvalidRecordBody
249 }
250 h.Servers = append(h.Servers, dnsServer)
251 h.recs = append(h.recs, rec)
252 return nil
253}
254
255// TypeAction return a flag indicating how a resource record of a given type
256// is to be treated (see BlockHandler interface)
257func (h *Gns2DnsHandler) TypeAction(t int) int {
258 // anything goes...
259 return 1
260}
261
262// Records returns a list of RR of the given type associated with this handler
263func (h *Gns2DnsHandler) Records(kind RRTypeList) *GNSRecordSet {
264 rs := NewGNSRecordSet()
265 if kind.HasType(enums.GNS_TYPE_GNS2DNS) {
266 for _, rec := range h.recs {
267 rs.AddRecord(rec)
268 }
269 }
270 return rs
271}
272
273//----------------------------------------------------------------------
274// BOX handler
275//----------------------------------------------------------------------
276
277// BoxHandler implementing the BlockHandler interface
278type BoxHandler struct {
279 boxes map[string]*Box // map of found boxes
280}
281
282// NewBoxHandler returns a new BlockHandler instance
283func NewBoxHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) {
284 if int(rec.Type) != enums.GNS_TYPE_BOX {
285 return nil, ErrInvalidRecordType
286 }
287 h := &BoxHandler{
288 boxes: make(map[string]*Box),
289 }
290 if err := h.AddRecord(rec, labels); err != nil {
291 return nil, err
292 }
293 return h, nil
294}
295
296// AddRecord inserts a BOX record into the handler.
297func (h *BoxHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error {
298 if int(rec.Type) != enums.GNS_TYPE_BOX {
299 return ErrInvalidRecordType
300 }
301 logger.Printf(logger.DBG, "[box-rr] for labels %v\n", labels)
302 // check if we need to process the BOX record:
303 // (1) only two remaining labels
304 if len(labels) != 2 {
305 return nil
306 }
307 // (2) remaining labels must start with '_'
308 if labels[0][0] != '_' || labels[1][0] != '_' {
309 return nil
310 }
311 // (3) check of "svc" and "proto" match values in the BOX
312 box := NewBox(rec)
313 if box.Matches(labels) {
314 logger.Println(logger.DBG, "[box-rr] MATCH -- adding record")
315 h.boxes[box.key] = box
316 }
317 return nil
318}
319
320// TypeAction return a flag indicating how a resource record of a given type
321// is to be treated (see BlockHandler interface)
322func (h *BoxHandler) TypeAction(t int) int {
323 // anything goes...
324 return 1
325}
326
327// Records returns a list of RR of the given type associated with this handler
328func (h *BoxHandler) Records(kind RRTypeList) *GNSRecordSet {
329 rs := NewGNSRecordSet()
330 for _, box := range h.boxes {
331 if kind.HasType(int(box.Type)) {
332 // valid box found: assemble new resource record.
333 rr := new(message.GNSResourceRecord)
334 rr.Expires = box.rec.Expires
335 rr.Flags = box.rec.Flags
336 rr.Type = box.Type
337 rr.Size = uint32(len(box.RR))
338 rr.Data = box.RR
339 rs.AddRecord(rr)
340 }
341 }
342 return rs
343}
344
345//----------------------------------------------------------------------
346// LEHO handler
347//----------------------------------------------------------------------
348
349// LehoHandler implementing the BlockHandler interface
350type LehoHandler struct {
351 name string
352 rec *message.GNSResourceRecord
353}
354
355// NewLehoHandler returns a new BlockHandler instance
356func NewLehoHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) {
357 if int(rec.Type) != enums.GNS_TYPE_LEHO {
358 return nil, ErrInvalidRecordType
359 }
360 h := &LehoHandler{
361 name: "",
362 }
363 if err := h.AddRecord(rec, labels); err != nil {
364 return nil, err
365 }
366 return h, nil
367}
368
369// AddRecord inserts a LEHO record into the handler.
370func (h *LehoHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error {
371 if int(rec.Type) != enums.GNS_TYPE_LEHO {
372 return ErrInvalidRecordType
373 }
374 h.name = string(rec.Data)
375 h.rec = rec
376 return nil
377}
378
379// TypeAction return a flag indicating how a resource record of a given type
380// is to be treated (see BlockHandler interface)
381func (h *LehoHandler) TypeAction(t int) int {
382 // only A and AAAA records allowed beside LEHO
383 switch t {
384 case enums.GNS_TYPE_LEHO, enums.GNS_TYPE_DNS_A, enums.GNS_TYPE_DNS_AAAA:
385 return 1
386 default:
387 return -1
388 }
389}
390
391// Records returns a list of RR of the given type associated with this handler
392func (h *LehoHandler) Records(kind RRTypeList) *GNSRecordSet {
393 rs := NewGNSRecordSet()
394 if kind.HasType(enums.GNS_TYPE_LEHO) {
395 rs.AddRecord(h.rec)
396 }
397 return rs
398}
diff --git a/src/gnunet/service/gns/box.go b/src/gnunet/service/gns/box.go
new file mode 100644
index 0000000..e2d3609
--- /dev/null
+++ b/src/gnunet/service/gns/box.go
@@ -0,0 +1,151 @@
1package gns
2
3import (
4 "encoding/hex"
5 "strconv"
6 "strings"
7
8 "gnunet/message"
9
10 "github.com/bfix/gospel/data"
11 "github.com/bfix/gospel/logger"
12)
13
14// Box is an encapsulated RR for special names
15type Box struct {
16 Proto uint16 `order:"big"` // Protcol identifier
17 Svc uint16 `order:"big"` // Service identifier
18 Type uint32 `order:"big"` // Type of embedded RR
19 RR []byte `size:"*"` // embedded RR
20
21 // transient attributes (not serialized)
22 key string // map key for box instance
23 rec *message.GNSResourceRecord // originating RR
24}
25
26// NewBox creates a new box instance from a BOX resource record.
27func NewBox(rec *message.GNSResourceRecord) *Box {
28 b := new(Box)
29 if err := data.Unmarshal(b, rec.Data); err != nil {
30 logger.Printf(logger.ERROR, "[gns] Can't unmarshal BOX")
31 return nil
32 }
33 b.key = hex.EncodeToString(rec.Data[:8])
34 b.rec = rec
35 return b
36}
37
38// Matches verifies that the remaining labels comply with the values
39// in the BOX record.
40func (b *Box) Matches(labels []string) bool {
41 // resolve protocol and service names
42 proto, protoName := GetProtocol(labels[0])
43 svc, _ := GetService(labels[1], protoName)
44 // no match on invalid resolution
45 if proto == 0 || svc == 0 {
46 return false
47 }
48 // check for matching values in box
49 return proto == b.Proto && svc == b.Svc
50}
51
52//----------------------------------------------------------------------
53// helper functions
54
55// list of handled protocols in BOX records
56var protocols = map[string]int{
57 "icmp": 1,
58 "igmp": 2,
59 "tcp": 6,
60 "udp": 17,
61 "ipv6-icmp": 58,
62}
63
64// GetProtocol returns the protocol number and name for a given name. The
65// name can be an integer value (e.g. "_6" for "tcp") or a mnemonic name
66// (e.g. like "_tcp").
67func GetProtocol(name string) (uint16, string) {
68 // check for required prefix
69 if name[0] != '_' {
70 return 0, ""
71 }
72 name = strings.ToLower(name[1:])
73
74 // if label is an integer value it is the protocol number
75 if val, err := strconv.Atoi(name); err == nil {
76 // check for valid number (reverse protocol lookup)
77 for label, id := range protocols {
78 if id == val {
79 // return found entry
80 return uint16(val), label
81 }
82 }
83 // number out of range
84 return 0, ""
85 }
86 // try to resolve via protocol map
87 if id, ok := protocols[name]; ok {
88 return uint16(id), name
89 }
90 // resolution failed
91 return 0, ""
92}
93
94// list of services (per protocol) handled in BOX records
95var services = map[string]map[string]int{
96 "udp": {
97 "domain": 53,
98 },
99 "tcp": {
100 "ftp": 21,
101 "ftps": 990,
102 "gopher": 70,
103 "http": 80,
104 "https": 443,
105 "imap2": 143,
106 "imap3": 220,
107 "imaps": 993,
108 "pop3": 110,
109 "pop3s": 995,
110 "smtp": 25,
111 "ssh": 22,
112 "telnet": 23,
113 },
114}
115
116// GetService returns the port number and the name of a service (with given
117// protocol). The name can be an integer value (e.g. "_443" for "https") or
118// a mnemonic name (e.g. like "_https").
119func GetService(name, proto string) (uint16, string) {
120 // check for required prefix
121 if name[0] != '_' {
122 return 0, ""
123 }
124 name = strings.ToLower(name[1:])
125
126 // get list of services for given protocol
127 svcs, ok := services[proto]
128 if !ok {
129 // no services available for this protocol
130 return 0, ""
131 }
132
133 // if label is an integer value it is the port number
134 if val, err := strconv.Atoi(name); err == nil {
135 // check for valid number (reverse service lookup)
136 for label, id := range svcs {
137 if id == val {
138 // return found entry
139 return uint16(val), label
140 }
141 }
142 // number out of range
143 return 0, ""
144 }
145 // try to resolve via services map
146 if id, ok := svcs[name]; ok {
147 return uint16(id), name
148 }
149 // resolution failed
150 return 0, ""
151}
diff --git a/src/gnunet/service/gns/dns.go b/src/gnunet/service/gns/dns.go
index 2ebe331..fe138b0 100644
--- a/src/gnunet/service/gns/dns.go
+++ b/src/gnunet/service/gns/dns.go
@@ -47,7 +47,7 @@ func DNSNameFromBytes(b []byte, offset int) (int, string) {
47 47
48// queryDNS resolves a name on a given nameserver and delivers all matching 48// queryDNS resolves a name on a given nameserver and delivers all matching
49// resource record (of type 'kind') to the result channel. 49// resource record (of type 'kind') to the result channel.
50func queryDNS(id int, name string, server net.IP, kind int, res chan *GNSRecordSet) { 50func queryDNS(id int, name string, server net.IP, kind RRTypeList, res chan *GNSRecordSet) {
51 logger.Printf(logger.DBG, "[dns][%d] Starting query for '%s' on '%s'...\n", id, name, server.String()) 51 logger.Printf(logger.DBG, "[dns][%d] Starting query for '%s' on '%s'...\n", id, name, server.String())
52 52
53 // assemble query 53 // assemble query
@@ -91,27 +91,32 @@ func queryDNS(id int, name string, server net.IP, kind int, res chan *GNSRecordS
91 } 91 }
92 set := NewGNSRecordSet() 92 set := NewGNSRecordSet()
93 for _, record := range in.Answer { 93 for _, record := range in.Answer {
94 // create a new GNS resource record 94 // check if answer record is of requested type
95 rr := new(message.GNSResourceRecord) 95 if kind.HasType(int(record.Header().Rrtype)) {
96 rr.Expires = util.AbsoluteTimeNever() 96 // get wire-format of resource record
97 rr.Flags = 0 97 buf := make([]byte, 2048)
98 rr.Type = uint32(record.Header().Rrtype) 98 n, err := dns.PackRR(record, buf, 0, nil, false)
99 rr.Size = uint32(record.Header().Rdlength) 99 if err != nil {
100 rr.Data = make([]byte, rr.Size) 100 logger.Printf(logger.WARN, "[dns][%d] Failed to get RR data for %s\n", id, err.Error())
101 continue
102 }
101 103
102 // get wire-format of resource record 104 // create a new GNS resource record
103 buf := make([]byte, 2048) 105 rr := new(message.GNSResourceRecord)
104 n, err := dns.PackRR(record, buf, 0, nil, false) 106 expires := time.Now().Add(time.Duration(record.Header().Ttl) * time.Second)
105 if err != nil { 107 rr.Expires = util.NewAbsoluteTime(expires)
106 logger.Printf(logger.WARN, "[dns][%d] Failed to get RR data for %s\n", id, err.Error()) 108 rr.Flags = 0
107 continue 109 rr.Type = uint32(record.Header().Rrtype)
108 } 110 rr.Size = uint32(record.Header().Rdlength)
109 if n < int(rr.Size) { 111 rr.Data = make([]byte, rr.Size)
110 logger.Printf(logger.WARN, "[dns][%d] Nit enough data in RR (%d != %d)\n", id, n, rr.Size) 112
111 continue 113 if n < int(rr.Size) {
114 logger.Printf(logger.WARN, "[dns][%d] Not enough data in RR (%d != %d)\n", id, n, rr.Size)
115 continue
116 }
117 copy(rr.Data, buf[n-int(rr.Size):])
118 set.AddRecord(rr)
112 } 119 }
113 copy(rr.Data, buf[n-int(rr.Size):])
114 set.AddRecord(rr)
115 } 120 }
116 logger.Printf(logger.WARN, "[dns][%d] %d resource records extracted from response (%d/5).\n", id, set.Count, retry+1) 121 logger.Printf(logger.WARN, "[dns][%d] %d resource records extracted from response (%d/5).\n", id, set.Count, retry+1)
117 res <- set 122 res <- set
@@ -124,7 +129,7 @@ func queryDNS(id int, name string, server net.IP, kind int, res chan *GNSRecordS
124// ResolveDNS resolves a name in DNS. Multiple DNS servers are queried in 129// ResolveDNS resolves a name in DNS. Multiple DNS servers are queried in
125// parallel; the first result delivered by any of the servers is returned 130// parallel; the first result delivered by any of the servers is returned
126// as the result list of matching resource records. 131// as the result list of matching resource records.
127func (gns *GNSModule) ResolveDNS(name string, servers []string, kind int, pkey *ed25519.PublicKey) (set *GNSRecordSet, err error) { 132func (gns *GNSModule) ResolveDNS(name string, servers []string, kind RRTypeList, pkey *ed25519.PublicKey) (set *GNSRecordSet, err error) {
128 logger.Printf(logger.DBG, "[dns] Resolution of '%s' starting...\n", name) 133 logger.Printf(logger.DBG, "[dns] Resolution of '%s' starting...\n", name)
129 134
130 // start DNS queries concurrently 135 // start DNS queries concurrently
@@ -133,20 +138,22 @@ func (gns *GNSModule) ResolveDNS(name string, servers []string, kind int, pkey *
133 for idx, srv := range servers { 138 for idx, srv := range servers {
134 // check if srv is an IPv4/IPv6 address 139 // check if srv is an IPv4/IPv6 address
135 addr := net.ParseIP(srv) 140 addr := net.ParseIP(srv)
141 logger.Printf(logger.DBG, "ParseIP('%s', len=%d) --> %v\n", srv, len(srv), addr)
136 if addr == nil { 142 if addr == nil {
143 query := NewRRTypeList(enums.GNS_TYPE_DNS_A, enums.GNS_TYPE_DNS_AAAA)
137 // no; resolve server name in GNS 144 // no; resolve server name in GNS
138 if strings.HasSuffix(srv, ".+") { 145 if strings.HasSuffix(srv, ".+") {
139 // resolve server name relative to current zone 146 // resolve server name relative to current zone
140 zone := util.EncodeBinaryToString(pkey.Bytes()) 147 zone := util.EncodeBinaryToString(pkey.Bytes())
141 srv = strings.TrimSuffix(srv, ".+") 148 srv = strings.TrimSuffix(srv, ".+")
142 set, err = gns.Resolve(srv, pkey, enums.GNS_TYPE_ANY, enums.GNS_LO_DEFAULT) 149 set, err = gns.Resolve(srv, pkey, query, enums.GNS_LO_DEFAULT)
143 if err != nil { 150 if err != nil {
144 logger.Printf(logger.ERROR, "[dns] Can't resolve NS server '%s' in '%s'\n", srv, zone) 151 logger.Printf(logger.ERROR, "[dns] Can't resolve NS server '%s' in '%s'\n", srv, zone)
145 continue 152 continue
146 } 153 }
147 } else { 154 } else {
148 // resolve absolute GNS name (MUST end in a PKEY) 155 // resolve absolute GNS name (name MUST end in a PKEY)
149 set, err = gns.Resolve(srv, nil, enums.GNS_TYPE_ANY, enums.GNS_LO_DEFAULT) 156 set, err = gns.Resolve(srv, nil, query, enums.GNS_LO_DEFAULT)
150 if err != nil { 157 if err != nil {
151 logger.Printf(logger.ERROR, "[dns] Can't resolve NS server '%s'\n", srv) 158 logger.Printf(logger.ERROR, "[dns] Can't resolve NS server '%s'\n", srv)
152 continue 159 continue
@@ -158,11 +165,17 @@ func (gns *GNSModule) ResolveDNS(name string, servers []string, kind int, pkey *
158 switch int(rec.Type) { 165 switch int(rec.Type) {
159 case enums.GNS_TYPE_DNS_AAAA: 166 case enums.GNS_TYPE_DNS_AAAA:
160 addr = net.IP(rec.Data) 167 addr = net.IP(rec.Data)
168 // we prefer IPv6
161 break rec_loop 169 break rec_loop
162 case enums.GNS_TYPE_DNS_A: 170 case enums.GNS_TYPE_DNS_A:
163 addr = net.IP(rec.Data) 171 addr = net.IP(rec.Data)
164 } 172 }
165 } 173 }
174 // check if we have an IP address available
175 if addr == nil {
176 logger.Printf(logger.WARN, "[dns] No IP address for nameserver in GNS")
177 continue
178 }
166 } 179 }
167 // query DNS concurrently 180 // query DNS concurrently
168 go queryDNS(idx, name, addr, kind, res) 181 go queryDNS(idx, name, addr, kind, res)
diff --git a/src/gnunet/service/gns/module.go b/src/gnunet/service/gns/module.go
index e4dc5fb..3e7bd18 100644
--- a/src/gnunet/service/gns/module.go
+++ b/src/gnunet/service/gns/module.go
@@ -1,7 +1,6 @@
1package gns 1package gns
2 2
3import ( 3import (
4 "encoding/hex"
5 "fmt" 4 "fmt"
6 "strings" 5 "strings"
7 6
@@ -55,82 +54,39 @@ func NewQuery(pkey *ed25519.PublicKey, label string) *Query {
55} 54}
56 55
57//---------------------------------------------------------------------- 56//----------------------------------------------------------------------
58// GNS blocks with special types (PKEY, GNS2DNS) require special
59// treatment with respect to other resource records with different types
60// in the same block. Usually only certain other types (or not at all)
61// are allowed and the allowed ones are required to deliver a consistent
62// list of resulting resource records passed back to the caller.
63//----------------------------------------------------------------------
64
65// BlockHandler interface.
66type BlockHandler interface {
67 // TypeAction returns a flag indicating how a resource record of a
68 // given type is to be treated:
69 // = -1: Record is not allowed (terminates lookup with an error)
70 // = 0: Record is allowed but will be ignored
71 // = 1: Record is allowed and will be processed
72 TypeAction(int) int
73}
74
75// Gns2DnsHandler implementing the BlockHandler interface
76type Gns2DnsHandler struct {
77 Name string
78 Servers []string
79}
80
81// NewGns2DnsHandler returns a new BlockHandler instance
82func NewGns2DnsHandler() *Gns2DnsHandler {
83 return &Gns2DnsHandler{
84 Name: "",
85 Servers: make([]string, 0),
86 }
87}
88
89// TypeAction return a flag indicating how a resource record of a given type
90// is to be treated (see RecordMaster interface)
91func (m *Gns2DnsHandler) TypeAction(t int) int {
92 // only process other GNS2DNS records
93 if t == enums.GNS_TYPE_GNS2DNS {
94 return 1
95 }
96 // skip everything else
97 return 0
98}
99
100// AddRequest adds the DNS request for "name" at "server" to the list
101// of requests. All GNS2DNS records must query for the same name
102func (m *Gns2DnsHandler) AddRequest(name, server string) bool {
103 if len(m.Servers) == 0 {
104 m.Name = name
105 }
106 if name != m.Name {
107 return false
108 }
109 m.Servers = append(m.Servers, server)
110 return true
111}
112
113//----------------------------------------------------------------------
114// The GNS module (recursively) resolves GNS names: 57// The GNS module (recursively) resolves GNS names:
115// Resolves DNS-like names (e.g. "minecraft.servers.bob.games") to the 58// Resolves DNS-like names (e.g. "minecraft.servers.bob.games"; a name is
116// requested resource records (RRs). In short, the resolution process 59// a list of labels with '.' as separator) to the requested resource
117// works as follows: 60// records (RRs). In short, the resolution process works as follows:
118// 61//
119// Resolve(name): 62// Resolve(name):
120// -------------- 63// --------------
121// (1) split the full name into elements in reverse order: names[] 64// (1) split the name ('.' as separator) into labels in reverse order: labels[]
122// (2) Resolve first element (root zone, right-most name part, name[0]) to 65// (2) Resolve first label (= root zone, right-most name part, labels[0]) to
123// a zone public key PKEY: 66// a zone public key PKEY:
124// (a) the name is a string representation of a public key -> (3) 67// (a) the label is a string representation of a public key -> (3)
125// (b) the zone key for the name is stored in the config file -> (3) 68// (b) the zone key for the label is stored in the config file -> (3)
126// (c) a local zone with that given name -> (3) 69// (c) a local zone with that given label -> (3)
127// (d) ERROR: "Unknown root zone" 70// (d) ERROR: "Unknown root zone"
128// (3) names = names[1:] // remove first element 71// (3) labels = labels[1:]
129// block = Lookup (PKEY, names[0]): 72// records = Resolve (labels[0], PKEY)
130// (a) If last element of namess: -> (4) 73// If last label in name: -> (5)
131// (b) block is PKEY record: 74// (4) for all rec in records:
132// PKEY <- block, --> (3) 75// (a) if rec is a PKEY record:
133// (4) return block: it is the responsibility of the caller to assemble 76// PKEY <- record, --> (3)
77// (b) if rec is a GNS2DNS record:
78// delegate to DNS to resolve rest of name -> (5)
79// (c) if rec is BOX record:
80// if rest of name is pattern "_service._proto" and matches
81// the values in the BOX:
82// Replace records with resource record from BOX -> (5)
83// (d) if rec is CNAME record:
84// if no remaining labels:
85// if requested types include CNAME -> (5)
86// if
87// resolution failed: name not completely processed and no zone available
88//
89// (5) return records: it is the responsibility of the caller to assemble
134// the desired result from block data (e.g. filter for requested 90// the desired result from block data (e.g. filter for requested
135// resource record types). 91// resource record types).
136//---------------------------------------------------------------------- 92//----------------------------------------------------------------------
@@ -145,10 +101,10 @@ type GNSModule struct {
145 GetLocalZone func(name string) (*ed25519.PublicKey, error) 101 GetLocalZone func(name string) (*ed25519.PublicKey, error)
146} 102}
147 103
148// Resolve a GNS name with multiple elements, If pkey is not nil, the name 104// Resolve a GNS name with multiple labels. If pkey is not nil, the name
149// is interpreted as "relative to current zone". 105// is interpreted as "relative to current zone".
150func (gns *GNSModule) Resolve(path string, pkey *ed25519.PublicKey, kind int, mode int) (set *GNSRecordSet, err error) { 106func (gns *GNSModule) Resolve(path string, pkey *ed25519.PublicKey, kind RRTypeList, mode int) (set *GNSRecordSet, err error) {
151 // get the name elements in reverse order 107 // get the labels in reverse order
152 names := util.ReverseStringList(strings.Split(path, ".")) 108 names := util.ReverseStringList(strings.Split(path, "."))
153 logger.Printf(logger.DBG, "[gns] Resolver called for %v\n", names) 109 logger.Printf(logger.DBG, "[gns] Resolver called for %v\n", names)
154 110
@@ -161,8 +117,8 @@ func (gns *GNSModule) Resolve(path string, pkey *ed25519.PublicKey, kind int, mo
161 return gns.ResolveAbsolute(names, kind, mode) 117 return gns.ResolveAbsolute(names, kind, mode)
162} 118}
163 119
164// Resolve a fully qualified GNS absolute name (with multiple levels). 120// Resolve a fully qualified GNS absolute name (with multiple labels).
165func (gns *GNSModule) ResolveAbsolute(names []string, kind int, mode int) (set *GNSRecordSet, err error) { 121func (gns *GNSModule) ResolveAbsolute(labels []string, kind RRTypeList, mode int) (set *GNSRecordSet, err error) {
166 // get the root zone key for the TLD 122 // get the root zone key for the TLD
167 var ( 123 var (
168 pkey *ed25519.PublicKey 124 pkey *ed25519.PublicKey
@@ -170,40 +126,43 @@ func (gns *GNSModule) ResolveAbsolute(names []string, kind int, mode int) (set *
170 ) 126 )
171 for { 127 for {
172 // (1) check if TLD is a public key string 128 // (1) check if TLD is a public key string
173 if len(names[0]) == 52 { 129 if len(labels[0]) == 52 {
174 if data, err = util.DecodeStringToBinary(names[0], 32); err == nil { 130 if data, err = util.DecodeStringToBinary(labels[0], 32); err == nil {
175 if pkey = ed25519.NewPublicKeyFromBytes(data); pkey != nil { 131 if pkey = ed25519.NewPublicKeyFromBytes(data); pkey != nil {
176 break 132 break
177 } 133 }
178 } 134 }
179 } 135 }
180 // (2) check if TLD is in our local config 136 // (2) check if TLD is in our local config
181 if pkey = config.Cfg.GNS.GetRootZoneKey(names[0]); pkey != nil { 137 if pkey = config.Cfg.GNS.GetRootZoneKey(labels[0]); pkey != nil {
182 break 138 break
183 } 139 }
184 // (3) check if TLD is one of our identities 140 // (3) check if TLD is one of our identities
185 if pkey, err = gns.GetLocalZone(names[0]); err == nil { 141 if pkey, err = gns.GetLocalZone(labels[0]); err == nil {
186 break 142 break
187 } 143 }
188 // (4) we can't resolve this TLD 144 // (4) we can't resolve this TLD
189 return nil, ErrUnknownTLD 145 return nil, ErrUnknownTLD
190 } 146 }
191 // continue with resolution relative to a zone. 147 // continue with resolution relative to a zone.
192 return gns.ResolveRelative(names[1:], pkey, kind, mode) 148 return gns.ResolveRelative(labels[1:], pkey, kind, mode)
193} 149}
194 150
195// Resolve relative path (to a given zone) recursively by processing simple 151// Resolve relative path (to a given zone) recursively by processing simple
196// (PKEY,Label) lookups in sequence and handle intermediate GNS record types 152// (PKEY,Label) lookups in sequence and handle intermediate GNS record types
197func (gns *GNSModule) ResolveRelative(names []string, pkey *ed25519.PublicKey, kind int, mode int) (set *GNSRecordSet, err error) { 153func (gns *GNSModule) ResolveRelative(labels []string, pkey *ed25519.PublicKey, kind RRTypeList, mode int) (set *GNSRecordSet, err error) {
198 // Process all names in sequence 154 // Process all names in sequence
199 var records []*message.GNSResourceRecord 155 var (
156 records []*message.GNSResourceRecord // final resource records from resolution
157 hdlrs *BlockHandlerList // list of block handlers in final step
158 )
200name_loop: 159name_loop:
201 for ; len(names) > 0; names = names[1:] { 160 for ; len(labels) > 0; labels = labels[1:] {
202 logger.Printf(logger.DBG, "[gns] ResolveRelative '%s' in '%s'\n", names[0], util.EncodeBinaryToString(pkey.Bytes())) 161 logger.Printf(logger.DBG, "[gns] ResolveRelative '%s' in '%s'\n", labels[0], util.EncodeBinaryToString(pkey.Bytes()))
203 162
204 // resolve next level 163 // resolve next level
205 var block *GNSBlock 164 var block *GNSBlock
206 if block, err = gns.Lookup(pkey, names[0], mode == enums.GNS_LO_DEFAULT); err != nil { 165 if block, err = gns.Lookup(pkey, labels[0], mode == enums.GNS_LO_DEFAULT); err != nil {
207 // failed to resolve name 166 // failed to resolve name
208 return 167 return
209 } 168 }
@@ -213,94 +172,64 @@ name_loop:
213 } 172 }
214 // post-process block by inspecting contained resource records for 173 // post-process block by inspecting contained resource records for
215 // special GNS types 174 // special GNS types
216 var hdlr BlockHandler
217 if records, err = block.Records(); err != nil { 175 if records, err = block.Records(); err != nil {
218 return 176 return
219 } 177 }
220 for _, rec := range records { 178 // assemble a list of block handlers for this block: if multiple
221 // let a block handler decide how to handle records 179 // block handlers are present, they are consistent with all block
222 if hdlr != nil { 180 // records.
223 switch hdlr.TypeAction(int(rec.Type)) { 181 if hdlrs, err = NewBlockHandlerList(records, labels[1:]); err != nil {
224 case -1: 182 // conflicting block handler records found: terminate with error.
225 // No records of this type allowed in block 183 // (N.B.: The BlockHandlerList class executes the logic which mix
226 err = ErrInvalidRecordType 184 // of resource records in a single block is considered valid.)
227 return 185 return
228 case 0: 186 }
229 // records of this type are simply ignored
230 continue
231 case 1:
232 // process record of this type
233 }
234 }
235 switch int(rec.Type) {
236 //----------------------------------------------------------
237 case enums.GNS_TYPE_PKEY:
238 // check for single RR and sane key data
239 if len(rec.Data) != 32 || len(records) > 1 {
240 err = ErrInvalidPKEY
241 return
242 }
243 // set new PKEY and continue resolution
244 pkey = ed25519.NewPublicKeyFromBytes(rec.Data)
245 continue name_loop
246 187
247 //---------------------------------------------------------- 188 //--------------------------------------------------------------
248 case enums.GNS_TYPE_GNS2DNS: 189 // handle special block cases in priority order:
249 // get the master controlling this block; create a new 190 //--------------------------------------------------------------
250 // one if necessary 191
251 var inst *Gns2DnsHandler 192 if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_PKEY); hdlr != nil {
252 if hdlr == nil { 193 // (1) PKEY record:
253 inst = NewGns2DnsHandler() 194 inst := hdlr.(*PkeyHandler)
254 hdlr = inst 195 // if labels are pending, set new zone and continue resolution
255 } else { 196 if len(labels) > 1 {
256 inst = hdlr.(*Gns2DnsHandler) 197 pkey = inst.pkey
257 } 198 continue name_loop
258 // extract list of names in DATA block:
259 logger.Printf(logger.DBG, "[gns] GNS2DNS data: %s\n", hex.EncodeToString(rec.Data))
260 var dnsNames []string
261 for pos := 0; ; {
262 next, name := DNSNameFromBytes(rec.Data, pos)
263 if len(name) == 0 {
264 break
265 }
266 dnsNames = append(dnsNames, name)
267 pos = next
268 }
269 logger.Printf(logger.DBG, "[gns] GNS2DNS params: %v\n", dnsNames)
270 if len(dnsNames) != 2 {
271 err = ErrInvalidRecordBody
272 return
273 }
274 // Add to collection of requests
275 logger.Printf(logger.DBG, "[gns] GNS2DNS: query for '%s' on '%s'\n", dnsNames[0], dnsNames[1])
276 if !inst.AddRequest(dnsNames[0], dnsNames[1]) {
277 err = ErrInvalidRecordBody
278 return
279 }
280 } 199 }
281 } 200 } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_GNS2DNS); hdlr != nil {
282 // handle special block cases 201 // (2) GNS2DNS records: delegate resolution to DNS
283 if hdlr != nil { 202 inst := hdlr.(*Gns2DnsHandler)
284 switch inst := hdlr.(type) { 203 // we need to handle delegation to DNS: returns a list of found
285 case *Gns2DnsHandler: 204 // resource records in DNS (filter by 'kind')
286 // we need to handle delegation to DNS: returns a list of found 205 lbls := strings.Join(util.ReverseStringList(labels[1:]), ".")
287 // resource records in DNS (filter by 'kind') 206 if len(lbls) > 0 {
288 fqdn := strings.Join(util.ReverseStringList(names[1:]), ".") + "." + inst.Name 207 lbls += "."
289 if set, err = gns.ResolveDNS(fqdn, inst.Servers, kind, pkey); err != nil { 208 }
290 logger.Println(logger.ERROR, "[gns] GNS2DNS resilution failed.") 209 fqdn := lbls + inst.Name
291 return 210 if set, err = gns.ResolveDNS(fqdn, inst.Servers, kind, pkey); err != nil {
292 } 211 logger.Println(logger.ERROR, "[gns] GNS2DNS resolution failed.")
293 // we are done with resolution; pass on records to caller 212 return
294 records = set.Records 213 }
214 // we are done with resolution; pass on records to caller
215 records = set.Records
216 break name_loop
217 } else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_BOX); hdlr != nil {
218 // (3) BOX records:
219 inst := hdlr.(*BoxHandler)
220 new_records := inst.Records(kind).Records
221 if len(new_records) > 0 {
222 records = new_records
295 break name_loop 223 break name_loop
296 } 224 }
297 } 225 }
298 } 226 }
299 // Assemble resulting resource record set 227 // Assemble resulting resource record set by filtering for requested types.
228 // Records might get transformed by active block handlers.
300 set = NewGNSRecordSet() 229 set = NewGNSRecordSet()
301 for _, rec := range records { 230 for _, rec := range records {
302 // is this the record type we are looking for? 231 // is this the record type we are looking for?
303 if kind == enums.GNS_TYPE_ANY || int(rec.Type) == kind { 232 if kind.HasType(int(rec.Type)) {
304 // add it to the result 233 // add it to the result
305 set.AddRecord(rec) 234 set.AddRecord(rec)
306 } 235 }
@@ -321,7 +250,6 @@ func (gns *GNSModule) Lookup(pkey *ed25519.PublicKey, label string, remote bool)
321 return 250 return
322 } 251 }
323 if block == nil { 252 if block == nil {
324 logger.Println(logger.DBG, "[gns] local Lookup: no block found")
325 if remote { 253 if remote {
326 // get the block from a remote lookup 254 // get the block from a remote lookup
327 if block, err = gns.LookupRemote(query); err != nil || block == nil { 255 if block, err = gns.LookupRemote(query); err != nil || block == nil {
@@ -330,12 +258,15 @@ func (gns *GNSModule) Lookup(pkey *ed25519.PublicKey, label string, remote bool)
330 block = nil 258 block = nil
331 } else { 259 } else {
332 logger.Println(logger.DBG, "[gns] remote Lookup: no block found") 260 logger.Println(logger.DBG, "[gns] remote Lookup: no block found")
261 err = fmt.Errorf("No block found")
333 } 262 }
334 // lookup fails completely -- no result 263 // lookup fails completely -- no result
335 return 264 return
336 } 265 }
337 // store RRs from remote locally. 266 // store RRs from remote locally.
338 gns.StoreLocal(query, block) 267 gns.StoreLocal(query, block)
268 } else {
269 err = fmt.Errorf("No block found")
339 } 270 }
340 } 271 }
341 return 272 return
diff --git a/src/gnunet/service/gns/service.go b/src/gnunet/service/gns/service.go
index 852f513..dd516ff 100644
--- a/src/gnunet/service/gns/service.go
+++ b/src/gnunet/service/gns/service.go
@@ -4,9 +4,6 @@ import (
4 "encoding/hex" 4 "encoding/hex"
5 "io" 5 "io"
6 6
7 "github.com/bfix/gospel/crypto/ed25519"
8 "github.com/bfix/gospel/data"
9 "github.com/bfix/gospel/logger"
10 "gnunet/config" 7 "gnunet/config"
11 "gnunet/crypto" 8 "gnunet/crypto"
12 "gnunet/enums" 9 "gnunet/enums"
@@ -14,6 +11,10 @@ import (
14 "gnunet/service" 11 "gnunet/service"
15 "gnunet/transport" 12 "gnunet/transport"
16 "gnunet/util" 13 "gnunet/util"
14
15 "github.com/bfix/gospel/crypto/ed25519"
16 "github.com/bfix/gospel/data"
17 "github.com/bfix/gospel/logger"
17) 18)
18 19
19//---------------------------------------------------------------------- 20//----------------------------------------------------------------------
@@ -77,7 +78,8 @@ func (s *GNSService) ServeClient(mc *transport.MsgChannel) {
77 // access to the message channel to send responses) 78 // access to the message channel to send responses)
78 pkey := ed25519.NewPublicKeyFromBytes(m.Zone) 79 pkey := ed25519.NewPublicKeyFromBytes(m.Zone)
79 label := m.GetName() 80 label := m.GetName()
80 recset, err := s.Resolve(label, pkey, int(m.Type), int(m.Options)) 81 kind := NewRRTypeList(int(m.Type))
82 recset, err := s.Resolve(label, pkey, kind, int(m.Options))
81 if err != nil { 83 if err != nil {
82 logger.Printf(logger.ERROR, "[gns] Failed to lookup block: %s\n", err.Error()) 84 logger.Printf(logger.ERROR, "[gns] Failed to lookup block: %s\n", err.Error())
83 break 85 break
@@ -146,7 +148,7 @@ func (s *GNSService) LookupNamecache(query *Query) (block *GNSBlock, err error)
146 break 148 break
147 } 149 }
148 // check if block was found 150 // check if block was found
149 if len(m.EncData) == 0 { 151 if len(m.EncData) == 0 || util.IsNull(m.EncData) {
150 logger.Println(logger.DBG, "[gns] block not found in namecache") 152 logger.Println(logger.DBG, "[gns] block not found in namecache")
151 break 153 break
152 } 154 }
diff --git a/src/gnunet/service/service.go b/src/gnunet/service/service.go
index 5b44d47..6aab226 100644
--- a/src/gnunet/service/service.go
+++ b/src/gnunet/service/service.go
@@ -3,8 +3,9 @@ package service
3import ( 3import (
4 "fmt" 4 "fmt"
5 5
6 "github.com/bfix/gospel/logger"
7 "gnunet/transport" 6 "gnunet/transport"
7
8 "github.com/bfix/gospel/logger"
8) 9)
9 10
10// Service is an interface for GNUnet services. Every service has one channel 11// Service is an interface for GNUnet services. Every service has one channel
@@ -48,7 +49,7 @@ func (si *ServiceImpl) Start(spec string) (err error) {
48 } 49 }
49 50
50 // start channel server 51 // start channel server
51 logger.Printf(logger.DBG, "[%s] Service starting.\n", si.name) 52 logger.Printf(logger.INFO, "[%s] Service starting.\n", si.name)
52 if si.srvc, err = transport.NewChannelServer(spec, si.hdlr); err != nil { 53 if si.srvc, err = transport.NewChannelServer(spec, si.hdlr); err != nil {
53 return 54 return
54 } 55 }
@@ -61,19 +62,19 @@ func (si *ServiceImpl) Start(spec string) (err error) {
61 select { 62 select {
62 case in := <-si.hdlr: 63 case in := <-si.hdlr:
63 if in == nil { 64 if in == nil {
64 logger.Printf(logger.DBG, "[%s] Listener terminated.\n", si.name) 65 logger.Printf(logger.INFO, "[%s] Listener terminated.\n", si.name)
65 break loop 66 break loop
66 } 67 }
67 switch ch := in.(type) { 68 switch ch := in.(type) {
68 case transport.Channel: 69 case transport.Channel:
69 logger.Printf(logger.DBG, "[%s] Client connected.\n", si.name) 70 logger.Printf(logger.INFO, "[%s] Client connected.\n", si.name)
70 go si.impl.ServeClient(transport.NewMsgChannel(ch)) 71 go si.impl.ServeClient(transport.NewMsgChannel(ch))
71 } 72 }
72 case <-si.ctrl: 73 case <-si.ctrl:
73 break loop 74 break loop
74 } 75 }
75 } 76 }
76 logger.Printf(logger.DBG, "[%s] Service closing.\n", si.name) 77 logger.Printf(logger.INFO, "[%s] Service closing.\n", si.name)
77 si.srvc.Close() 78 si.srvc.Close()
78 si.running = false 79 si.running = false
79 }() 80 }()
@@ -89,7 +90,7 @@ func (si *ServiceImpl) Stop() error {
89 } 90 }
90 si.running = false 91 si.running = false
91 si.ctrl <- true 92 si.ctrl <- true
92 logger.Printf(logger.DBG, "[%s] Service terminating.\n", si.name) 93 logger.Printf(logger.INFO, "[%s] Service terminating.\n", si.name)
93 94
94 return si.impl.Stop() 95 return si.impl.Stop()
95} 96}
diff --git a/src/gnunet/transport/channel.go b/src/gnunet/transport/channel.go
index 8502d8f..4005759 100644
--- a/src/gnunet/transport/channel.go
+++ b/src/gnunet/transport/channel.go
@@ -11,6 +11,7 @@ import (
11 "gnunet/message" 11 "gnunet/message"
12) 12)
13 13
14// Error codes
14var ( 15var (
15 ErrChannelNotImplemented = fmt.Errorf("Protocol not implemented") 16 ErrChannelNotImplemented = fmt.Errorf("Protocol not implemented")
16 ErrChannelNotOpened = fmt.Errorf("Channel not opened") 17 ErrChannelNotOpened = fmt.Errorf("Channel not opened")
diff --git a/src/gnunet/transport/channel_netw.go b/src/gnunet/transport/channel_netw.go
index 69ddda5..ecfd8e2 100644
--- a/src/gnunet/transport/channel_netw.go
+++ b/src/gnunet/transport/channel_netw.go
@@ -14,11 +14,12 @@ import (
14 14
15// NetworkChannel 15// NetworkChannel
16type NetworkChannel struct { 16type NetworkChannel struct {
17 network string 17 network string // network protocol identifier ("tcp", "unix", ...)
18 conn net.Conn 18 conn net.Conn // associated connection
19} 19}
20 20
21// NewNetworkChannel 21// NewNetworkChannel creates a new channel for a given network protocol.
22// The channel is in pending state and need to be opened before use.
22func NewNetworkChannel(netw string) Channel { 23func NewNetworkChannel(netw string) Channel {
23 return &NetworkChannel{ 24 return &NetworkChannel{
24 network: netw, 25 network: netw,
@@ -26,7 +27,11 @@ func NewNetworkChannel(netw string) Channel {
26 } 27 }
27} 28}
28 29
29// Open 30// Open a network channel based on specification:
31// The specification is a string separated into parts by the '+' delimiter
32// (e.g. "unix+/tmp/gnunet-service-gns-go.sock+perm=0770"). The network
33// identifier (first part) must match the network specification of the
34// underlaying NetworkChannel instance.
30func (c *NetworkChannel) Open(spec string) (err error) { 35func (c *NetworkChannel) Open(spec string) (err error) {
31 parts := strings.Split(spec, "+") 36 parts := strings.Split(spec, "+")
32 // check for correct protocol 37 // check for correct protocol
@@ -38,7 +43,7 @@ func (c *NetworkChannel) Open(spec string) (err error) {
38 return 43 return
39} 44}
40 45
41// Close 46// Close a network channel
42func (c *NetworkChannel) Close() error { 47func (c *NetworkChannel) Close() error {
43 if c.conn != nil { 48 if c.conn != nil {
44 return c.conn.Close() 49 return c.conn.Close()
@@ -46,7 +51,8 @@ func (c *NetworkChannel) Close() error {
46 return ErrChannelNotOpened 51 return ErrChannelNotOpened
47} 52}
48 53
49// Read 54// Read bytes from a network channel into buffer: Returns the number of read
55// bytes and an error code. Only works on open channels ;)
50func (c *NetworkChannel) Read(buf []byte) (int, error) { 56func (c *NetworkChannel) Read(buf []byte) (int, error) {
51 if c.conn == nil { 57 if c.conn == nil {
52 return 0, ErrChannelNotOpened 58 return 0, ErrChannelNotOpened
@@ -54,7 +60,8 @@ func (c *NetworkChannel) Read(buf []byte) (int, error) {
54 return c.conn.Read(buf) 60 return c.conn.Read(buf)
55} 61}
56 62
57// Write 63// Write buffer to a network channel: Returns the number of written bytes and
64// an error code.
58func (c *NetworkChannel) Write(buf []byte) (int, error) { 65func (c *NetworkChannel) Write(buf []byte) (int, error) {
59 if c.conn == nil { 66 if c.conn == nil {
60 return 0, ErrChannelNotOpened 67 return 0, ErrChannelNotOpened
@@ -67,8 +74,8 @@ func (c *NetworkChannel) Write(buf []byte) (int, error) {
67 74
68// NetworkChannelServer 75// NetworkChannelServer
69type NetworkChannelServer struct { 76type NetworkChannelServer struct {
70 network string 77 network string // network protocol to listen on
71 listener net.Listener 78 listener net.Listener // reference to listener object
72} 79}
73 80
74// NewNetworkChannelServer 81// NewNetworkChannelServer
@@ -79,7 +86,9 @@ func NewNetworkChannelServer(netw string) ChannelServer {
79 } 86 }
80} 87}
81 88
82// Open 89// Open a network channel server (= start running it) based on the given
90// specification. For every client connection to the server, the associated
91// network channel for the connection is send via the hdlr channel.
83func (s *NetworkChannelServer) Open(spec string, hdlr chan<- Channel) (err error) { 92func (s *NetworkChannelServer) Open(spec string, hdlr chan<- Channel) (err error) {
84 parts := strings.Split(spec, "+") 93 parts := strings.Split(spec, "+")
85 // check for correct protocol 94 // check for correct protocol
@@ -136,7 +145,7 @@ func (s *NetworkChannelServer) Open(spec string, hdlr chan<- Channel) (err error
136 return nil 145 return nil
137} 146}
138 147
139// Close 148// Close a network channel server (= stop the server)
140func (s *NetworkChannelServer) Close() error { 149func (s *NetworkChannelServer) Close() error {
141 if s.listener != nil { 150 if s.listener != nil {
142 err := s.listener.Close() 151 err := s.listener.Close()
@@ -147,27 +156,35 @@ func (s *NetworkChannelServer) Close() error {
147} 156}
148 157
149//////////////////////////////////////////////////////////////////////// 158////////////////////////////////////////////////////////////////////////
159// helper functions to instantiate network channels and servers for
160// common network protocols
150 161
162// NewSocketChannel: Unix Domain Socket connection
151func NewSocketChannel() Channel { 163func NewSocketChannel() Channel {
152 return NewNetworkChannel("unix") 164 return NewNetworkChannel("unix")
153} 165}
154 166
167// NewTCPChannel: TCP connection
155func NewTCPChannel() Channel { 168func NewTCPChannel() Channel {
156 return NewNetworkChannel("tcp") 169 return NewNetworkChannel("tcp")
157} 170}
158 171
172// NewUDPChannel: UDP connection
159func NewUDPChannel() Channel { 173func NewUDPChannel() Channel {
160 return NewNetworkChannel("udp") 174 return NewNetworkChannel("udp")
161} 175}
162 176
177// NewSocketChannelServer: Unix Domain Socket listener
163func NewSocketChannelServer() ChannelServer { 178func NewSocketChannelServer() ChannelServer {
164 return NewNetworkChannelServer("unix") 179 return NewNetworkChannelServer("unix")
165} 180}
166 181
182// NewTCPChannelServer: TCP listener
167func NewTCPChannelServer() ChannelServer { 183func NewTCPChannelServer() ChannelServer {
168 return NewNetworkChannelServer("tcp") 184 return NewNetworkChannelServer("tcp")
169} 185}
170 186
187// NewUDPChannelServer: UDP listener
171func NewUDPChannelServer() ChannelServer { 188func NewUDPChannelServer() ChannelServer {
172 return NewNetworkChannelServer("udp") 189 return NewNetworkChannelServer("udp")
173} 190}
diff --git a/src/gnunet/transport/connection.go b/src/gnunet/transport/connection.go
index e66bec1..1cf0317 100644
--- a/src/gnunet/transport/connection.go
+++ b/src/gnunet/transport/connection.go
@@ -5,7 +5,6 @@ import (
5 "gnunet/message" 5 "gnunet/message"
6) 6)
7 7
8////////////////////////////////////////////////////////////////////////
9// Connection for communicating peers 8// Connection for communicating peers
10type Connection struct { 9type Connection struct {
11 from, to *core.Peer 10 from, to *core.Peer
@@ -17,6 +16,8 @@ type Connection struct {
17 shared []byte 16 shared []byte
18} 17}
19 18
19// NewConnection instanciates a new connection between peers communicating
20// over a message channel (Connections are authenticated and secured).
20func NewConnection(ch *MsgChannel, from, to *core.Peer) *Connection { 21func NewConnection(ch *MsgChannel, from, to *core.Peer) *Connection {
21 return &Connection{ 22 return &Connection{
22 from: from, 23 from: from,
@@ -26,27 +27,33 @@ func NewConnection(ch *MsgChannel, from, to *core.Peer) *Connection {
26 } 27 }
27} 28}
28 29
30// SharedSecret computes the shared secret the two endpoints of a connection.
29func (c *Connection) SharedSecret(secret []byte) { 31func (c *Connection) SharedSecret(secret []byte) {
30 c.shared = make([]byte, len(secret)) 32 c.shared = make([]byte, len(secret))
31 copy(c.shared, secret) 33 copy(c.shared, secret)
32} 34}
33 35
36// GetState returns the current state of the connection.
34func (c *Connection) GetState() int { 37func (c *Connection) GetState() int {
35 return c.state 38 return c.state
36} 39}
37 40
41// SetBandwidth to control transfer rates on the connection
38func (c *Connection) SetBandwidth(bw uint32) { 42func (c *Connection) SetBandwidth(bw uint32) {
39 c.bandwidth = bw 43 c.bandwidth = bw
40} 44}
41 45
46// Close connection between two peers.
42func (c *Connection) Close() error { 47func (c *Connection) Close() error {
43 return c.ch.Close() 48 return c.ch.Close()
44} 49}
45 50
51// Send a message on the connection
46func (c *Connection) Send(msg message.Message) error { 52func (c *Connection) Send(msg message.Message) error {
47 return c.ch.Send(msg) 53 return c.ch.Send(msg)
48} 54}
49 55
56// Receive a message on the connection
50func (c *Connection) Receive() (message.Message, error) { 57func (c *Connection) Receive() (message.Message, error) {
51 return c.ch.Receive() 58 return c.ch.Receive()
52} 59}
diff --git a/src/gnunet/transport/session.go b/src/gnunet/transport/session.go
index 90e4016..7d33ea2 100644
--- a/src/gnunet/transport/session.go
+++ b/src/gnunet/transport/session.go
@@ -1,7 +1,6 @@
1package transport 1package transport
2 2
3import () 3// Session states
4
5const ( 4const (
6 KX_STATE_DOWN = iota // No handshake yet. 5 KX_STATE_DOWN = iota // No handshake yet.
7 KX_STATE_KEY_SENT // We've sent our session key. 6 KX_STATE_KEY_SENT // We've sent our session key.
diff --git a/src/gnunet/util/address.go b/src/gnunet/util/address.go
index 04e2254..37fb102 100644
--- a/src/gnunet/util/address.go
+++ b/src/gnunet/util/address.go
@@ -1,29 +1,19 @@
1package util 1package util
2 2
3import ( 3import (
4 "encoding/hex"
4 "fmt" 5 "fmt"
6 "net"
5) 7)
6 8
7type IPAddress struct { 9// Address specifies how a peer is reachable on the network.
8 Host []byte `size:"*-2"`
9 Port uint16 `order:"big"`
10}
11
12func NewIPAddress(host []byte, port uint16) *IPAddress {
13 ip := &IPAddress{
14 Host: make([]byte, len(host)),
15 Port: port,
16 }
17 copy(ip.Host, host)
18 return ip
19}
20
21type Address struct { 10type Address struct {
22 Transport string 11 Transport string // transport protocol
23 Options uint32 `order:"big"` 12 Options uint32 `order:"big"` // address options
24 Address []byte `size:"*"` 13 Address []byte `size:"*"` // address data (protocol-dependent)
25} 14}
26 15
16// NewAddress returns a new Address for the given transport and specs
27func NewAddress(transport string, addr []byte) *Address { 17func NewAddress(transport string, addr []byte) *Address {
28 a := &Address{ 18 a := &Address{
29 Transport: transport, 19 Transport: transport,
@@ -34,6 +24,37 @@ func NewAddress(transport string, addr []byte) *Address {
34 return a 24 return a
35} 25}
36 26
27// String returns a human-readable representation of an address.
37func (a *Address) String() string { 28func (a *Address) String() string {
38 return fmt.Sprintf("Address{%s}", AddressString(a.Transport, a.Address)) 29 return fmt.Sprintf("Address{%s}", AddressString(a.Transport, a.Address))
39} 30}
31
32//----------------------------------------------------------------------
33
34// AddressString returns a string representaion of an address.
35func AddressString(transport string, addr []byte) string {
36 if transport == "tcp" || transport == "udp" {
37 alen := len(addr)
38 port := uint(addr[alen-2])*256 + uint(addr[alen-1])
39 return fmt.Sprintf("%s:%s:%d", transport, net.IP(addr[:alen-2]).String(), port)
40 }
41 return fmt.Sprintf("%s:%s", transport, hex.EncodeToString(addr))
42}
43
44//----------------------------------------------------------------------
45
46// IP address (can be IPv4 or IPv6 or a DNS name)
47type IPAddress struct {
48 Host []byte `size:"*-2"`
49 Port uint16 `order:"big"`
50}
51
52// NewIPAddress creates a new instance for a given host and port.
53func NewIPAddress(host []byte, port uint16) *IPAddress {
54 ip := &IPAddress{
55 Host: make([]byte, len(host)),
56 Port: port,
57 }
58 copy(ip.Host, host)
59 return ip
60}
diff --git a/src/gnunet/util/array.go b/src/gnunet/util/array.go
index 9076516..f6213bf 100644
--- a/src/gnunet/util/array.go
+++ b/src/gnunet/util/array.go
@@ -30,6 +30,16 @@ func Reverse(b []byte) []byte {
30 return r 30 return r
31} 31}
32 32
33// IsNull returns true if all bytes in an array are set to 0.
34func IsNull(b []byte) bool {
35 for _, v := range b {
36 if v != 0 {
37 return false
38 }
39 }
40 return true
41}
42
33// CopyBlock copies 'in' to 'out' so that 'out' is filled completely. 43// CopyBlock copies 'in' to 'out' so that 'out' is filled completely.
34// - If 'in' is larger than 'out', it is left-truncated before copy 44// - If 'in' is larger than 'out', it is left-truncated before copy
35// - If 'in' is smaller than 'out', it is left-padded with 0 before copy 45// - If 'in' is smaller than 'out', it is left-padded with 0 before copy
diff --git a/src/gnunet/util/format.go b/src/gnunet/util/format.go
index 722b9a7..780c814 100644
--- a/src/gnunet/util/format.go
+++ b/src/gnunet/util/format.go
@@ -1,22 +1,13 @@
1package util 1package util
2 2
3import ( 3import (
4 "encoding/hex"
5 "fmt" 4 "fmt"
6 "net"
7) 5)
8 6
9func AddressString(transport string, addr []byte) string {
10 if transport == "tcp" || transport == "udp" {
11 alen := len(addr)
12 port := uint(addr[alen-2])*256 + uint(addr[alen-1])
13 return fmt.Sprintf("%s:%s:%d", transport, net.IP(addr[:alen-2]).String(), port)
14 }
15 return fmt.Sprintf("%s:%s", transport, hex.EncodeToString(addr))
16}
17
18var scale = " kMGTPEO" 7var scale = " kMGTPEO"
19 8
9// Scale1024 returns an integer value (e.g. a size) as a human-readable
10// string with scales: a size of 183467245 would result in "174,967M"
20func Scale1024(n uint64) string { 11func Scale1024(n uint64) string {
21 v := float64(n) 12 v := float64(n)
22 var i int 13 var i int
diff --git a/src/gnunet/util/id.go b/src/gnunet/util/id.go
index 41bd30e..ab9b98c 100644
--- a/src/gnunet/util/id.go
+++ b/src/gnunet/util/id.go
@@ -4,7 +4,8 @@ var (
4 _id = 0 4 _id = 0
5) 5)
6 6
7// generate next unique identifier (unique in the running process/application)
7func NextID() int { 8func NextID() int {
8 _id += 1 9 _id++
9 return _id 10 return _id
10} 11}
diff --git a/src/gnunet/util/peer_id.go b/src/gnunet/util/peer_id.go
index 03bc73e..6549d75 100644
--- a/src/gnunet/util/peer_id.go
+++ b/src/gnunet/util/peer_id.go
@@ -1,9 +1,11 @@
1package util 1package util
2 2
3// PeerID is the 32-byte binary representation od a Ed25519 key
3type PeerID struct { 4type PeerID struct {
4 Key []byte `size:"32"` 5 Key []byte `size:"32"`
5} 6}
6 7
8// NewPeerID creates a new object from the data.
7func NewPeerID(data []byte) *PeerID { 9func NewPeerID(data []byte) *PeerID {
8 if data == nil { 10 if data == nil {
9 data = make([]byte, 32) 11 data = make([]byte, 32)
@@ -22,6 +24,7 @@ func NewPeerID(data []byte) *PeerID {
22 } 24 }
23} 25}
24 26
27// String returns a human-readable representation of a peer id.
25func (p *PeerID) String() string { 28func (p *PeerID) String() string {
26 return EncodeBinaryToString(p.Key) 29 return EncodeBinaryToString(p.Key)
27} 30}
diff --git a/src/gnunet/util/rnd.go b/src/gnunet/util/rnd.go
index d3c8b2e..a9f247f 100644
--- a/src/gnunet/util/rnd.go
+++ b/src/gnunet/util/rnd.go
@@ -6,16 +6,19 @@ import (
6 "encoding/binary" 6 "encoding/binary"
7) 7)
8 8
9// RndArray fills a buffer with random content
9func RndArray(b []byte) { 10func RndArray(b []byte) {
10 rand.Read(b) 11 rand.Read(b)
11} 12}
12 13
14// NewRndArray creates a new buffer of given size; filled with random content.
13func NewRndArray(size int) []byte { 15func NewRndArray(size int) []byte {
14 b := make([]byte, size) 16 b := make([]byte, size)
15 rand.Read(b) 17 rand.Read(b)
16 return b 18 return b
17} 19}
18 20
21// RndUInt64 returns a new 64-bit unsigned random integer.
19func RndUInt64() uint64 { 22func RndUInt64() uint64 {
20 b := make([]byte, 8) 23 b := make([]byte, 8)
21 RndArray(b) 24 RndArray(b)
@@ -25,22 +28,27 @@ func RndUInt64() uint64 {
25 return v 28 return v
26} 29}
27 30
31// RndInt64 returns a new 64-bit signed random integer.
28func RndInt64() int64 { 32func RndInt64() int64 {
29 return int64(RndUInt64()) 33 return int64(RndUInt64())
30} 34}
31 35
36// RndUInt32 returns a new 32-bit unsigned random integer.
32func RndUInt32() uint32 { 37func RndUInt32() uint32 {
33 return uint32(RndUInt64()) 38 return uint32(RndUInt64())
34} 39}
35 40
41// RndInt32 returns a new 32-bit signed random integer.
36func RndInt32() int32 { 42func RndInt32() int32 {
37 return int32(RndUInt64()) 43 return int32(RndUInt64())
38} 44}
39 45
46// RndUInt16 returns a new 16-bit unsigned random integer.
40func RndUInt16() uint16 { 47func RndUInt16() uint16 {
41 return uint16(RndUInt64()) 48 return uint16(RndUInt64())
42} 49}
43 50
51// RndInt16 returns a new 16-bit signed random integer.
44func RndInt16() int16 { 52func RndInt16() int16 {
45 return int16(RndUInt64()) 53 return int16(RndUInt64())
46} 54}