aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-12-13 19:40:46 +0100
committerSebastian Nadler <sebastian.nadler@tum.de>2023-12-14 19:13:21 +0100
commitc8257020c1aa1bd2c18cc64fee3db90d02065425 (patch)
tree1019c49d0d54078aab9acadfc19c0891411bb2fe
parentfc6ed5001f47fe0036cac78571bd24a86f2efb75 (diff)
downloadgnunet-c8257020c1aa1bd2c18cc64fee3db90d02065425.tar.gz
gnunet-c8257020c1aa1bd2c18cc64fee3db90d02065425.zip
NAMESTORE: Remove fcfsd
-rw-r--r--contrib/Makefile.am1
-rw-r--r--contrib/apparmor/gnunet-namestore-fcfsd13
-rw-r--r--contrib/apparmor/gnunet-service-arm2
-rw-r--r--data/Makefile.am3
-rw-r--r--data/fcfsd/fcfsd-forbidden.html11
-rw-r--r--data/fcfsd/fcfsd-index.html345
-rw-r--r--data/fcfsd/fcfsd-notfound.html11
-rw-r--r--data/meson.build3
-rw-r--r--doc/man/Makefile.am1
-rw-r--r--doc/man/gnunet-dns2gns.11
-rw-r--r--doc/man/gnunet-namestore-fcfsd.1103
-rw-r--r--doc/man/meson.build1
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/service/namestore/Makefile.am16
-rw-r--r--src/service/namestore/gnunet-namestore-fcfsd.c1160
-rw-r--r--src/service/namestore/meson.build15
-rw-r--r--src/service/namestore/namestore.conf.in11
17 files changed, 0 insertions, 1698 deletions
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index b3dccbbd1..b7507d224 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -143,7 +143,6 @@ EXTRA_DIST = \
143 apparmor/gnunet-namestore-gtk \ 143 apparmor/gnunet-namestore-gtk \
144 apparmor/gnunet-service-testbed-logger \ 144 apparmor/gnunet-service-testbed-logger \
145 apparmor/gnunet-peerstore \ 145 apparmor/gnunet-peerstore \
146 apparmor/gnunet-namestore-fcfsd \
147 apparmor/gnunet-core \ 146 apparmor/gnunet-core \
148 apparmor/gnunet-gns-import.sh \ 147 apparmor/gnunet-gns-import.sh \
149 apparmor/gnunet-gns-proxy \ 148 apparmor/gnunet-gns-proxy \
diff --git a/contrib/apparmor/gnunet-namestore-fcfsd b/contrib/apparmor/gnunet-namestore-fcfsd
deleted file mode 100644
index 8ac09e69b..000000000
--- a/contrib/apparmor/gnunet-namestore-fcfsd
+++ /dev/null
@@ -1,13 +0,0 @@
1# Last Modified: Tue Jul 21 17:25:12 2015
2#include <tunables/global>
3#include <tunables/gnunet>
4
5profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-namestore-fcfsd {
6 #include <abstractions/base>
7 #include <abstractions/gnunet-common>
8
9 @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-namestore-fcfsd mr,
10
11 # Site-specific additions and overrides. See local/README for details.
12 #include <local/gnunet>
13}
diff --git a/contrib/apparmor/gnunet-service-arm b/contrib/apparmor/gnunet-service-arm
index 546e6332e..2ad8d6140 100644
--- a/contrib/apparmor/gnunet-service-arm
+++ b/contrib/apparmor/gnunet-service-arm
@@ -32,8 +32,6 @@ profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-arm {
32 32
33 @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-gns-proxy Px, 33 @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-gns-proxy Px,
34 34
35 @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-namestore-fcfsd Px,
36
37 #GNUnet service 35 #GNUnet service
38 @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-* Px, 36 @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-* Px,
39 37
diff --git a/data/Makefile.am b/data/Makefile.am
index b40007e94..cebfc9e0d 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -14,9 +14,6 @@ dist_pkgdata_DATA = \
14 gns/gns-bcd-png.tex \ 14 gns/gns-bcd-png.tex \
15 gns/gns-bcd-simple.html \ 15 gns/gns-bcd-simple.html \
16 gns/gns-bcd-simple.tex \ 16 gns/gns-bcd-simple.tex \
17 fcfsd/fcfsd-index.html \
18 fcfsd/fcfsd-forbidden.html \
19 fcfsd/fcfsd-notfound.html \
20 branding/logo/gnunet-logo.png \ 17 branding/logo/gnunet-logo.png \
21 branding/logo/gnunet-logo-dark-text.svg \ 18 branding/logo/gnunet-logo-dark-text.svg \
22 branding/logo/gnunet-logo-dark-only-text.svg \ 19 branding/logo/gnunet-logo-dark-only-text.svg \
diff --git a/data/fcfsd/fcfsd-forbidden.html b/data/fcfsd/fcfsd-forbidden.html
deleted file mode 100644
index 57ebb4c61..000000000
--- a/data/fcfsd/fcfsd-forbidden.html
+++ /dev/null
@@ -1,11 +0,0 @@
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="utf-8"/>
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Forbidden - GNUnet FCFS Authority Name Registration Service</title>
7 </head>
8 <body>
9 <h1>You can not access this resource.</h1>
10 </body>
11</html>
diff --git a/data/fcfsd/fcfsd-index.html b/data/fcfsd/fcfsd-index.html
deleted file mode 100644
index 3fa71d7c8..000000000
--- a/data/fcfsd/fcfsd-index.html
+++ /dev/null
@@ -1,345 +0,0 @@
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="utf-8"/>
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>GNUnet FCFS Authority Name Registration Service</title>
7 <style>
8 html {
9 box-sizing: border-box;
10 font-family: sans-serif;
11 }
12
13 *, *:before, *:after {
14 box-sizing: inherit;
15 }
16
17 header {
18 width: 800px;
19 margin: 0 auto;
20 }
21
22 main {
23 width: 800px;
24 margin: 0 auto;
25 }
26
27 section h4 {
28 text-align: center;
29 width: 100%;
30 }
31
32 section input {
33 width: 100%;
34 padding: 8px 17px;
35 font-size: 1rem;
36 border: 1px solid #aaa;
37 border-radius: 7px;
38 background-color: white;
39 margin-bottom: 7px;
40 }
41
42 section input:focus {
43 box-shadow: 0px 0px 5px 3px lightblue;
44 }
45
46 section button {
47 font-size: 1rem;
48 font-weight: bold;
49 background-color: #8b008b;
50 color: white;
51 border: none;
52 padding: 7px;
53 }
54
55 section button:hover {
56 background-color: #bf00bf;
57 }
58
59 section button:disabled {
60 background-color: gray;
61 }
62
63 section h3 {
64 text-align: center;
65 width: 100%;
66 }
67
68 section small {
69 display: block;
70 margin-bottom: 5px;
71 }
72
73 .error-message {
74 color: red;
75 }
76
77 .success-message {
78 color: green;
79 }
80
81 @media screen and (max-width: 991px) {
82 header, main {
83 width: 100%;
84 }
85 }
86
87 footer {
88 margin-top: 30px;
89 text-align: center;
90 }
91
92 nav {
93 border-bottom: 1px solid black;
94 }
95
96 nav button {
97 font-size: 1rem;
98 font-weight: bold;
99 background-color: #ccc;
100 border: 1px solid black;
101 border-bottom: none;
102 border-top-right-radius: 7px;
103 border-top-left-radius: 7px;
104 padding: 7px;
105 }
106
107 nav button:hover {
108 background-color: #f0f0f0;
109 cursor: pointer;
110 }
111
112 nav button.selected {
113 background-color: #f0f0f0;
114 }
115 </style>
116 </head>
117 <body>
118 <header>
119 <h1>Name Registration Service</h1>
120 <p>Here you can register a name for your zone as part of this service's
121 delegated names.</p>
122 <p>The registration is based on a <em>First Come First Served</em>
123 policy, meaning a name is given to the first user requesting it.</p>
124 <p>Use the search bar below to see if your desired name is available and
125 then use the form to submit your registration request.</p>
126 </header>
127 <main>
128 <div class="form-container">
129 <nav>
130 <button id="tab-search">Search</button>
131 <button id="tab-register">Register</button>
132 </nav>
133 <section id="search-form">
134 <h4>Is your name available?</h4>
135 <h3 id="search-result-message"></h3>
136 <input id="search-name"
137 name="search-name"
138 type="text"
139 placeholder="Your name..."
140 autocomplete="name"
141 maxlength="63"
142 minlength="1">
143 <small class="error-message" id="search-name-error"></small>
144 <button>Search</button>
145 </section>
146 <section id="submit-form">
147 <h4>Submit a registration request</h4>
148 <h3 id="submit-result-message"></h3>
149 <input id="register-name"
150 name="register-name"
151 type="text"
152 placeholder="Your name..."
153 autocomplete="off"
154 maxlength="63"
155 minlength="1">
156 <input id="register-value"
157 name="register-value"
158 type="text"
159 placeholder="Your zone key..."
160 autocomplete="off"
161 minlength="1">
162 <small class="error-message" id="submit-error"></small>
163 <button>Submit</button>
164 </section>
165 </div>
166 </main>
167 <footer>
168 <a href="https://gnunet.org">GNUnet homepage</a>
169 </footer>
170 <script>
171 const buttons = document.querySelectorAll('nav button');
172 for (let i=0; i<buttons.length; ++i) {
173 buttons[i].onclick = function (e) {
174 let selected = document.querySelector('nav button.selected');
175 if (selected) {
176 selected.classList.toggle('selected');
177 }
178 e.target.classList.toggle('selected');
179
180 let show = '';
181 let hide = '';
182 if (e.target.id === 'tab-search') {
183 show = 'search-form';
184 hide = 'submit-form';
185 } else {
186 show = 'submit-form';
187 hide = 'search-form'
188 }
189
190 document.getElementById(hide).style.display = 'none';
191 document.getElementById(show).style.display = 'block';
192 };
193 }
194
195 buttons[0].click({target: buttons[0]});
196
197 const searchbutton = document.querySelector('#search-form button');
198 const submitbutton = document.querySelector('#submit-form button');
199
200 document.getElementById('search-name').onkeydown = function (e) {
201 if (e.key !== 'Enter') {
202 return;
203 }
204
205 searchbutton.click();
206 };
207
208 for (let n of ['register-name', 'register-value']) {
209 document.getElementById(n).onkeydown = function (e) {
210 if (e.key !== 'Enter') {
211 return;
212 }
213
214 submitbutton.click();
215 };
216 }
217
218 searchbutton.onclick = function (e) {
219 const searchname = document.getElementById('search-name');
220 const errormsg = document.getElementById('search-name-error');
221 const resultmsg = document.getElementById('search-result-message');
222
223 if (0 === searchname.value.length) {
224 errormsg.innerText = 'The field can not be empty';
225 searchname.setCustomValidity('The field can not be empty');
226 return;
227 }
228
229 if (-1 !== searchname.value.indexOf('.')) {
230 errormsg.innerText = 'The name can not contain dots';
231 searchname.setCustomValidity('The name can not contain dots');
232 return;
233 }
234
235 searchname.setCustomValidity('');
236 errormsg.innerText = '';
237
238 const name = searchname.value.toLowerCase();
239
240 searchbutton.disabled = true;
241 submitbutton.disabled = true;
242
243 fetch(`/search?name=${name}`)
244 .then(function (response) {
245 if (!response.ok) {
246 throw 'error';
247 }
248
249 return response.json()
250 })
251 .then(function (data) {
252 if ("true" === data.free) {
253 resultmsg.innerText = `'${name}' is available!`;
254 resultmsg.classList.add('success-message');
255 resultmsg.classList.remove('error-message');
256 } else {
257 resultmsg.innerText = `'${name}' is not available`;
258 resultmsg.classList.remove('success-message');
259 resultmsg.classList.add('error-message');
260 }
261 searchbutton.disabled = false;
262 submitbutton.disabled = false;
263 })
264 .catch(function (error) {
265 resultmsg.innerText = 'An error occurred while processing your query';
266 resultmsg.classList.remove('success-message');
267 resultmsg.classList.add('error-message');
268 console.error(error);
269 searchbutton.disabled = false;
270 submitbutton.disabled = false;
271 });
272 };
273
274 submitbutton.onclick = function (e) {
275 const registername = document.getElementById('register-name');
276 const registervalue = document.getElementById('register-value');
277 const errormsg = document.getElementById('submit-error');
278 const resultmsg = document.getElementById('submit-result-message');
279
280 let errors = 0;
281 let errs = [];
282
283 if (0 === registername.value.length) {
284 errs.push('The name field can not be empty');
285 registername.setCustomValidity('The name field can not be empty');
286 ++errors;
287 }
288 if (-1 !== registername.value.indexOf('.')) {
289 errs.push('The name can not contain dots');
290 registername.setCustomValidity('The name can not contain dots');
291 ++errors;
292 }
293 if (0 === registervalue.value.length) {
294 errs.push('The value field can not be empty');
295 registervalue.setCustomValidity('The value field can not be empty');
296 ++errors;
297 }
298
299 if (0 < errors) {
300 errormsg.innerHTML = 'The form contains invalid values:';
301 for (let e of errs) {
302 errormsg.innerHTML += '<br/>' + e;
303 }
304 return;
305 }
306
307 searchbutton.disabled = true;
308 submitbutton.disabled = true;
309
310 fetch('/register', {
311 method: 'POST',
312 cache: 'no-cache',
313 headers: {
314 'Content-Type': 'application/json',
315 },
316 body: JSON.stringify({
317 name: registername.value,
318 key: registervalue.value,
319 }),
320 }).then(function (response) {
321 return response.json();
322 }).then(function (data) {
323 if (data.error === "false") {
324 resultmsg.innerText = `'${registername.value}' was registered successfully!`;
325 resultmsg.classList.add('success-message');
326 resultmsg.classList.remove('error-message');
327 } else {
328 resultmsg.innerText = `'${registername.value}' could not be registered! (${data.message})`;
329 resultmsg.classList.remove('success-message');
330 resultmsg.classList.add('error-message');
331 }
332 searchbutton.disabled = false;
333 submitbutton.disabled = false;
334 }).catch(function (error) {
335 resultmsg.innerText = 'An error occurred while processing your query';
336 resultmsg.classList.remove('success-message');
337 resultmsg.classList.add('error-message');
338 console.error(error);
339 searchbutton.disabled = false;
340 submitbutton.disabled = false;
341 });
342 };
343 </script>
344 </body>
345</html>
diff --git a/data/fcfsd/fcfsd-notfound.html b/data/fcfsd/fcfsd-notfound.html
deleted file mode 100644
index 676bf4a9a..000000000
--- a/data/fcfsd/fcfsd-notfound.html
+++ /dev/null
@@ -1,11 +0,0 @@
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="utf-8"/>
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Not Found - GNUnet FCFS Authority Name Registration Service</title>
7 </head>
8 <body>
9 <h1>The requested resource could not be found</h1>
10 </body>
11</html>
diff --git a/data/meson.build b/data/meson.build
index 20de89900..1564780ed 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -11,9 +11,6 @@ install_data(['gns'/'def.tex',
11 'gns'/'gns-bcd-png.tex', 11 'gns'/'gns-bcd-png.tex',
12 'gns'/'gns-bcd-simple.html', 12 'gns'/'gns-bcd-simple.html',
13 'gns'/'gns-bcd-simple.tex', 13 'gns'/'gns-bcd-simple.tex',
14 'fcfsd'/'fcfsd-index.html',
15 'fcfsd'/'fcfsd-forbidden.html',
16 'fcfsd'/'fcfsd-notfound.html',
17 'branding'/'logo'/'gnunet-logo.png', 14 'branding'/'logo'/'gnunet-logo.png',
18 'branding'/'logo'/'gnunet-logo-dark-text.svg', 15 'branding'/'logo'/'gnunet-logo-dark-text.svg',
19 'branding'/'logo'/'gnunet-logo-dark-only-text.svg', 16 'branding'/'logo'/'gnunet-logo-dark-only-text.svg',
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 17a23da92..75ddc4276 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -66,7 +66,6 @@ man_MANS = \
66 gnunet-messenger.1 \ 66 gnunet-messenger.1 \
67 gnunet-namecache.1 \ 67 gnunet-namecache.1 \
68 gnunet-namestore.1 \ 68 gnunet-namestore.1 \
69 gnunet-namestore-fcfsd.1 \
70 gnunet-namestore-dbtool.1 \ 69 gnunet-namestore-dbtool.1 \
71 gnunet-namestore-zonefile.1 \ 70 gnunet-namestore-zonefile.1 \
72 gnunet-nat.1 \ 71 gnunet-nat.1 \
diff --git a/doc/man/gnunet-dns2gns.1 b/doc/man/gnunet-dns2gns.1
index 0993fb419..72a7785d7 100644
--- a/doc/man/gnunet-dns2gns.1
+++ b/doc/man/gnunet-dns2gns.1
@@ -57,7 +57,6 @@ Valid values are DEBUG, INFO, WARNING and ERROR.
57Print GNUnet version number. 57Print GNUnet version number.
58.El 58.El
59.Sh SEE ALSO 59.Sh SEE ALSO
60.Xr gnunet-gns-fcfs 1 ,
61.Xr gnunet-gns 1 , 60.Xr gnunet-gns 1 ,
62.Xr gnunet-identity 1 61.Xr gnunet-identity 1
63.Pp 62.Pp
diff --git a/doc/man/gnunet-namestore-fcfsd.1 b/doc/man/gnunet-namestore-fcfsd.1
deleted file mode 100644
index 39bb9fcbc..000000000
--- a/doc/man/gnunet-namestore-fcfsd.1
+++ /dev/null
@@ -1,103 +0,0 @@
1.\" This file is part of GNUnet.
2.\" Copyright (C) 2001-2019 GNUnet e.V.
3.\"
4.\" Permission is granted to copy, distribute and/or modify this document
5.\" under the terms of the GNU Free Documentation License, Version 1.3 or
6.\" any later version published by the Free Software Foundation; with no
7.\" Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
8.\" copy of the license is included in the file
9.\" FDL-1.3.
10.\"
11.\" A copy of the license is also available from the Free Software
12.\" Foundation Web site at http://www.gnu.org/licenses/fdl.html}.
13.\"
14.\" Alternately, this document is also available under the General
15.\" Public License, version 3 or later, as published by the Free Software
16.\" Foundation. A copy of the license is included in the file
17.\" GPL3.
18.\"
19.\" A copy of the license is also available from the Free Software
20.\" Foundation Web site at http://www.gnu.org/licenses/gpl.html
21.\"
22.\" SPDX-License-Identifier: GPL3.0-or-later OR FDL1.3-or-later
23.\"
24.Dd September 5, 2013
25.Dt GNUNET-NAMESTORE-FCFSD 1
26.Os
27.Sh NAME
28.Nm gnunet-namestore-fcfsd
29.Nd HTTP server for GNU Name System First-Come-First-Served name registration
30.Sh SYNOPSIS
31.Nm
32.Op Fl c Ar FILENAME | Fl -config= Ns Ar FILENAME
33.Op Fl h | -help
34.Op Fl L Ar LOGLEVEL | Fl -loglevel= Ns Ar LOGLEVEL
35.Op Fl v | -version
36.Op Fl z Ar EGO | -zone= Ns Ar EGO
37.Sh DESCRIPTION
38Most users will not want to run an FCFS-zone and thus will not need this program.
39.Pp
40.Nm
41runs a web server where users can register names to be mapped to their GNS zone.
42Names are made available on a First Come First Served basis (hence fcfs).
43Registered names do not expire.
44The HTTP server is run on the port that is specified in the configuration file in section "[fcfsd]" under the name "HTTPPORT".
45.Pp
46It is possible to manage gnunet-gns-fcfsd using gnunet-(service-arm) by starting the daemon using "gnunet-arm -i fcfsd" or by setting "IMMEDIATE_START=YES" in the "fcfds" section of your configuration and the "-z ZONE" in as the "OPTION".
47.Pp
48An FCFS-zone is run at
49.Lk http://gnunet.org/fcfs/ .
50GNS users are encouraged to register their zone with the gnunet.org FCFS authority.
51.Pp
52If you want to run your own FCFS registrar, you need to first create a pseudonym (using "gnunet-identity -C NAME"), and use it with the
53.Fl z
54option.
55After that, you can start the FCFSD service (possibly using
56.Xr gnunet-arm 1 Ns ).
57.Pp
58The options are as follows:
59.Bl -tag -width indent
60.It Fl c Ar FILENAME | Fl -config= Ns Ar FILENAME
61Use the configuration file FILENAME.
62.It Fl h | -help
63Print short help on options.
64.It Fl L Ar LOGLEVEL | Fl -loglevel= Ns Ar LOGLEVEL
65Use LOGLEVEL for logging.
66Valid values are DEBUG, INFO, WARNING and ERROR.
67.It Fl v | -version
68Print GNUnet version number.
69.It Fl z Ar EGO | -zone= Ns Ar EGO
70Specifies for which
71.Ar EGO
72FCFSD should manage the zone.
73.El
74.\".Sh EXAMPLES
75.\".Sh FILES
76.Sh SEE ALSO
77.Xr gnunet-identity 1 ,
78.Xr gnunet-gns 1 ,
79.Xr gnunet-gns-proxy 1
80.sp
81The full documentation for gnunet is maintained as a Texinfo manual.
82If the
83.Xr info 1
84and gnunet programs are properly installed at your site, the command
85.Pp
86.Dl info gnunet
87.Pp
88should give you access to the complete handbook,
89.Pp
90.Dl info gnunet-c-tutorial
91.Pp
92will give you access to a tutorial for developers.
93.sp
94Depending on your installation, this information is also available in
95.Xr gnunet 7 and
96.Xr gnunet-c-tutorial 7 .
97.\".Sh HISTORY
98.\".Sh AUTHORS
99.Sh BUGS
100Report bugs by using
101.Lk https://bugs.gnunet.org
102or by sending electronic mail to
103.Aq Mt gnunet-developers@gnu.org .
diff --git a/doc/man/meson.build b/doc/man/meson.build
index 6a271ff3c..74679053f 100644
--- a/doc/man/meson.build
+++ b/doc/man/meson.build
@@ -36,7 +36,6 @@ install_man(
36 'gnunet-messenger.1', 36 'gnunet-messenger.1',
37 'gnunet-namecache.1', 37 'gnunet-namecache.1',
38 'gnunet-namestore.1', 38 'gnunet-namestore.1',
39 'gnunet-namestore-fcfsd.1',
40 'gnunet-namestore-dbtool.1', 39 'gnunet-namestore-dbtool.1',
41 'gnunet-namestore-zonefile.1', 40 'gnunet-namestore-zonefile.1',
42 'gnunet-nat.1', 41 'gnunet-nat.1',
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 689864e1a..9e1826d13 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -373,7 +373,6 @@ src/service/messenger/messenger_api_room.c
373src/service/messenger/messenger_api_util.c 373src/service/messenger/messenger_api_util.c
374src/service/namecache/gnunet-service-namecache.c 374src/service/namecache/gnunet-service-namecache.c
375src/service/namecache/namecache_api.c 375src/service/namecache/namecache_api.c
376src/service/namestore/gnunet-namestore-fcfsd.c
377src/service/namestore/gnunet-service-namestore.c 376src/service/namestore/gnunet-service-namestore.c
378src/service/namestore/namestore_api.c 377src/service/namestore/namestore_api.c
379src/service/namestore/namestore_api_monitor.c 378src/service/namestore/namestore_api_monitor.c
diff --git a/src/service/namestore/Makefile.am b/src/service/namestore/Makefile.am
index 01c6e9096..514c8bec6 100644
--- a/src/service/namestore/Makefile.am
+++ b/src/service/namestore/Makefile.am
@@ -21,10 +21,6 @@ lib_LTLIBRARIES = \
21libexec_PROGRAMS = \ 21libexec_PROGRAMS = \
22 gnunet-service-namestore 22 gnunet-service-namestore
23 23
24libexec_PROGRAMS += \
25 gnunet-namestore-fcfsd
26
27
28libgnunetnamestore_la_SOURCES = \ 24libgnunetnamestore_la_SOURCES = \
29 namestore_api.c \ 25 namestore_api.c \
30 namestore_api_monitor.c \ 26 namestore_api_monitor.c \
@@ -39,18 +35,6 @@ libgnunetnamestore_la_LDFLAGS = \
39 $(GN_LIB_LDFLAGS) \ 35 $(GN_LIB_LDFLAGS) \
40 -version-info 0:1:0 36 -version-info 0:1:0
41 37
42gnunet_namestore_fcfsd_SOURCES = \
43 gnunet-namestore-fcfsd.c
44gnunet_namestore_fcfsd_LDADD = $(MHD_LIBS) \
45 $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \
46 $(top_builddir)/src/service/identity/libgnunetidentity.la \
47 libgnunetnamestore.la \
48 $(top_builddir)/src/lib/util/libgnunetutil.la \
49 $(top_builddir)/src/lib/json/libgnunetjson.la \
50 $(GN_LIBINTL) -ljansson
51gnunet_namestore_fcfsd_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
52
53
54gnunet_service_namestore_SOURCES = \ 38gnunet_service_namestore_SOURCES = \
55 gnunet-service-namestore.c 39 gnunet-service-namestore.c
56gnunet_service_namestore_LDADD = \ 40gnunet_service_namestore_LDADD = \
diff --git a/src/service/namestore/gnunet-namestore-fcfsd.c b/src/service/namestore/gnunet-namestore-fcfsd.c
deleted file mode 100644
index 03ded7fcb..000000000
--- a/src/service/namestore/gnunet-namestore-fcfsd.c
+++ /dev/null
@@ -1,1160 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file gnunet-namestore-fcfsd.c
23 * @brief HTTP daemon that offers first-come-first-serve GNS domain registration
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include <microhttpd.h>
29#include "gnunet_util_lib.h"
30#include "gnunet_identity_service.h"
31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_namestore_service.h"
33#include "gnunet_mhd_compat.h"
34#include "gnunet_json_lib.h"
35
36/**
37 * Structure representing a static page.
38 * "Static" means that the server does not process the page before sending it
39 * to the client. Clients can still process the received data, for example
40 * because there are scripting elements within.
41 */
42struct StaticPage
43{
44 /**
45 * Handle to file on disk.
46 */
47 struct GNUNET_DISK_FileHandle *handle;
48
49 /**
50 * Size in bytes of the file.
51 */
52 uint64_t size;
53
54 /**
55 * Cached response object to send to clients.
56 */
57 struct MHD_Response *response;
58};
59
60/**
61 * Structure containing some request-specific data.
62 */
63struct RequestData
64{
65 /**
66 * The connection this request was sent in.
67 */
68 struct MHD_Connection *c;
69
70 /**
71 * Body of the response object.
72 */
73 char *body;
74
75 /**
76 * Length in bytes of the body.
77 */
78 size_t body_length;
79
80 /**
81 * Response code.
82 */
83 int code;
84
85 /**
86 * Task started to search for an entry in the namestore.
87 */
88 struct GNUNET_NAMESTORE_QueueEntry *searching;
89
90 /**
91 * Task started to iterate over the namestore.
92 */
93 struct GNUNET_NAMESTORE_ZoneIterator *iterating;
94
95 /**
96 * Pointer used while processing POST data.
97 */
98 void *ptr;
99
100 /**
101 * Name requested to be registered.
102 */
103 char *register_name;
104
105 /**
106 * Key (encoded as a string) to be associated with the requested name.
107 */
108 char *register_key;
109
110 /**
111 * Key to be associated with the requested name.
112 */
113 struct GNUNET_CRYPTO_PublicKey key;
114};
115
116/**
117 * Name of the zone being managed.
118 */
119static char *zone = NULL;
120
121/**
122 * The port the daemon is listening to for HTTP requests.
123 */
124static unsigned long long port = 18080;
125
126/**
127 * Connection with the namestore service.
128 */
129static struct GNUNET_NAMESTORE_Handle *namestore = NULL;
130
131/**
132 * Connection with the identity service.
133 */
134static struct GNUNET_IDENTITY_Handle *identity = NULL;
135
136/**
137 * Private key of the zone.
138 */
139static const struct GNUNET_CRYPTO_PrivateKey *zone_key = NULL;
140
141/**
142 * The HTTP daemon.
143 */
144static struct MHD_Daemon *httpd = NULL;
145
146/**
147 * Task executing the HTTP daemon.
148 */
149static struct GNUNET_SCHEDULER_Task *httpd_task = NULL;
150
151/**
152 * The main page, a.k.a. "index.html"
153 */
154static struct StaticPage *main_page = NULL;
155
156/**
157 * Page indicating the requested resource could not be found.
158 */
159static struct StaticPage *notfound_page = NULL;
160
161/**
162 * Page indicating the requested resource could not be accessed, and other
163 * errors.
164 */
165static struct StaticPage *forbidden_page = NULL;
166
167/**
168 * The relative expiration time for added records
169 */
170static struct GNUNET_TIME_Relative record_exp;
171
172/**
173 * Task ran at shutdown to clean up everything.
174 *
175 * @param cls unused
176 */
177static void
178do_shutdown (void *cls)
179{
180 /* We cheat a bit here: the file descriptor is implicitly closed by MHD, so
181 calling `GNUNET_DISK_file_close' would generate a spurious warning message
182 in the log. Since that function does nothing but close the descriptor and
183 free the allocated memory, After destroying the response all that's left to
184 do is call `GNUNET_free'. */
185 if (NULL != main_page)
186 {
187 MHD_destroy_response (main_page->response);
188 GNUNET_free (main_page->handle);
189 GNUNET_free (main_page);
190 }
191 if (NULL != notfound_page)
192 {
193 MHD_destroy_response (notfound_page->response);
194 GNUNET_free (notfound_page->handle);
195 GNUNET_free (notfound_page);
196 }
197 if (NULL != forbidden_page)
198 {
199 MHD_destroy_response (forbidden_page->response);
200 GNUNET_free (forbidden_page->handle);
201 GNUNET_free (forbidden_page);
202 }
203
204 if (NULL != namestore)
205 {
206 GNUNET_NAMESTORE_disconnect (namestore);
207 }
208
209 if (NULL != identity)
210 {
211 GNUNET_IDENTITY_disconnect (identity);
212 }
213
214 if (NULL != httpd_task)
215 {
216 GNUNET_SCHEDULER_cancel (httpd_task);
217 }
218 if (NULL != httpd)
219 {
220 MHD_stop_daemon (httpd);
221 }
222}
223
224
225/**
226 * Called when the HTTP server has some pending operations.
227 *
228 * @param cls unused
229 */
230static void
231do_httpd (void *cls);
232
233/**
234 * Schedule a task to run MHD.
235 */
236static void
237run_httpd (void)
238{
239 fd_set rs;
240 fd_set ws;
241 fd_set es;
242
243 struct GNUNET_NETWORK_FDSet *grs = GNUNET_NETWORK_fdset_create ();
244 struct GNUNET_NETWORK_FDSet *gws = GNUNET_NETWORK_fdset_create ();
245 struct GNUNET_NETWORK_FDSet *ges = GNUNET_NETWORK_fdset_create ();
246
247 FD_ZERO (&rs);
248 FD_ZERO (&ws);
249 FD_ZERO (&es);
250
251 int max = -1;
252 GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max));
253
254 unsigned MHD_LONG_LONG timeout = 0;
255 struct GNUNET_TIME_Relative gtime = GNUNET_TIME_UNIT_FOREVER_REL;
256 if (MHD_YES == MHD_get_timeout (httpd, &timeout))
257 {
258 gtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
259 timeout);
260 }
261
262 GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
263 GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
264 GNUNET_NETWORK_fdset_copy_native (ges, &es, max + 1);
265
266 httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
267 gtime,
268 grs,
269 gws,
270 &do_httpd,
271 NULL);
272 GNUNET_NETWORK_fdset_destroy (grs);
273 GNUNET_NETWORK_fdset_destroy (gws);
274 GNUNET_NETWORK_fdset_destroy (ges);
275}
276
277
278/**
279 * Called when the HTTP server has some pending operations.
280 *
281 * @param cls unused
282 */
283static void
284do_httpd (void *cls)
285{
286 httpd_task = NULL;
287 MHD_run (httpd);
288 run_httpd ();
289}
290
291
292static void
293run_httpd_now (void)
294{
295 if (NULL != httpd_task)
296 {
297 GNUNET_SCHEDULER_cancel (httpd_task);
298 httpd_task = NULL;
299 }
300 httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL);
301}
302
303
304/**
305 * Generate a JSON object.
306 *
307 * @param key the key for the first element
308 * @param value the value for the first element
309 * @param ... key-value pairs of the object, terminated by NULL
310 * @return a JSON string (allocated)
311 */
312static char *
313make_json (const char *key, const char *value, ...)
314{
315 va_list args;
316 va_start (args, value);
317
318 json_t *obj = NULL;
319
320 obj = json_object ();
321 if ((NULL == key) || (NULL == value))
322 {
323 va_end (args);
324 return json_dumps (obj, JSON_COMPACT);
325 }
326
327 json_object_set (obj, key, json_string (value));
328
329 char *k = va_arg (args, char *);
330 if (NULL == k)
331 {
332 va_end (args);
333 return json_dumps (obj, JSON_COMPACT);
334 }
335 char *v = va_arg (args, char *);
336 if (NULL == v)
337 {
338 va_end (args);
339 return json_dumps (obj, JSON_COMPACT);
340 }
341
342 while (NULL != k && NULL != v)
343 {
344 json_object_set (obj, k, json_string (v));
345 k = va_arg (args, char *);
346 if (NULL != k)
347 {
348 v = va_arg (args, char *);
349 }
350 }
351
352 va_end (args);
353
354 char *json = json_dumps (obj, JSON_COMPACT);
355 json_decref (obj);
356
357 return json;
358}
359
360
361/**
362 * The namestore search task failed.
363 *
364 * @param cls the request data
365 */
366static void
367search_error_cb (void *cls)
368{
369 struct RequestData *rd = cls;
370 MHD_resume_connection (rd->c);
371 rd->searching = NULL;
372 rd->body = make_json ("error", "true",
373 "message", _ ("can not search the namestore"),
374 NULL);
375 rd->body_length = strlen (rd->body);
376 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
377 run_httpd_now ();
378}
379
380
381/**
382 * The lookup terminated with some results.
383 *
384 * @param cls closure
385 * @param zone the private key of the zone
386 * @param label the result label
387 * @param count number of records found
388 * @param d records found
389 */
390static void
391search_done_cb (void *cls,
392 const struct GNUNET_CRYPTO_PrivateKey *zone,
393 const char *label,
394 unsigned int count,
395 const struct GNUNET_GNSRECORD_Data *d)
396{
397 (void) zone;
398 (void) d;
399
400 struct RequestData *rd = cls;
401 MHD_resume_connection (rd->c);
402
403 rd->searching = NULL;
404 rd->body = make_json ("error", "false",
405 "free", (0 == count) ? "true" : "false",
406 NULL);
407 rd->body_length = strlen (rd->body);
408 rd->code = MHD_HTTP_OK;
409
410 run_httpd_now ();
411}
412
413
414/**
415 * An error occurred while registering a name.
416 *
417 * @param cls the connection
418 */
419static void
420register_error_cb (void *cls)
421{
422 struct RequestData *rd = cls;
423
424 MHD_resume_connection (rd->c);
425 rd->searching = NULL;
426 rd->body = make_json ("error", "true",
427 "message", _ ("unable to scan namestore"),
428 NULL);
429 rd->body_length = strlen (rd->body);
430 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
431 run_httpd_now ();
432}
433
434
435static void
436register_done_cb (void *cls,
437 enum GNUNET_ErrorCode ec)
438{
439 struct RequestData *rd = cls;
440
441 MHD_resume_connection (rd->c);
442 rd->searching = NULL;
443
444 if (GNUNET_EC_NONE != ec)
445 {
446 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
447 _ ("Failed to create record for `%s': %s\n"),
448 rd->register_name,
449 GNUNET_ErrorCode_get_hint (ec));
450 rd->body = make_json ("error", "true",
451 "message",
452 GNUNET_ErrorCode_get_hint (ec),
453 NULL);
454 rd->body_length = strlen (rd->body);
455 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
456 }
457 else
458 {
459 rd->body = make_json ("error", "false",
460 "message", _ ("no errors"),
461 NULL);
462 rd->body_length = strlen (rd->body);
463 rd->code = MHD_HTTP_OK;
464 }
465
466 run_httpd_now ();
467}
468
469
470/**
471 * Attempt to register the requested name.
472 *
473 * @param cls the connection
474 * @param key the zone key
475 * @param label name of the record
476 * @param count number of records found
477 * @param d records
478 */
479static void
480register_do_cb (void *cls,
481 const struct GNUNET_CRYPTO_PrivateKey *key,
482 const char *label,
483 unsigned int count,
484 const struct GNUNET_GNSRECORD_Data *d)
485{
486 (void) key;
487 (void) d;
488
489 struct RequestData *rd = cls;
490
491 rd->searching = NULL;
492
493 if (0 != count)
494 {
495 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
496 _ ("The requested key `%s' exists as `%s'\n"),
497 rd->register_key,
498 label);
499
500 MHD_resume_connection (rd->c);
501 rd->searching = NULL;
502 rd->body = make_json ("error", "true",
503 "message", _ ("key exists"),
504 NULL);
505 rd->body_length = strlen (rd->body);
506 rd->code = MHD_HTTP_FORBIDDEN;
507 run_httpd_now ();
508 return;
509 }
510
511 struct GNUNET_GNSRECORD_Data gd;
512 char *gdraw = NULL;
513
514 if (GNUNET_OK != GNUNET_GNSRECORD_data_from_identity (&(rd->key),
515 &gdraw,
516 &(gd.data_size),
517 &(gd.record_type)))
518 {
519 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
520 _ ("Error creating record data\n"));
521 MHD_resume_connection (rd->c);
522 rd->searching = NULL;
523 rd->body = make_json ("error", "true",
524 "message", _ ("unable to store record"),
525 NULL);
526 rd->body_length = strlen (rd->body);
527 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
528 run_httpd_now ();
529 return;
530 }
531
532 gd.data = gdraw;
533 gd.expiration_time = record_exp.rel_value_us;
534 gd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
535
536 rd->searching = GNUNET_NAMESTORE_record_set_store (namestore,
537 zone_key,
538 rd->register_name,
539 1,
540 &gd,
541 &register_done_cb,
542 rd);
543
544 GNUNET_free (gdraw);
545}
546
547
548/**
549 * An error occurred while iterating the namestore.
550 *
551 * @param cls the connection
552 */
553static void
554iterate_error_cb (void *cls)
555{
556 struct RequestData *rd = cls;
557
558 MHD_resume_connection (rd->c);
559 rd->iterating = NULL;
560 rd->body = make_json ("error", "true",
561 "message", _ ("unable to scan namestore"),
562 NULL);
563 rd->body_length = strlen (rd->body);
564 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
565 run_httpd_now ();
566}
567
568
569/**
570 * A block was received from the namestore.
571 *
572 * @param cls the connection
573 * @param key the zone key
574 * @param label the records' label
575 * @param count number of records found
576 * @param d the found records
577 */
578static void
579iterate_do_cb (void *cls,
580 const struct GNUNET_CRYPTO_PrivateKey *key,
581 const char *label,
582 unsigned int count,
583 const struct GNUNET_GNSRECORD_Data *d)
584{
585 (void) key;
586 (void) label;
587 (void) d;
588
589 struct RequestData *rd = cls;
590
591 if (0 == strcmp (label, rd->register_name))
592 {
593 GNUNET_break (0 != count);
594 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
595 _ ("Requested name `%s' exists with `%u' records\n"),
596 rd->register_name,
597 count);
598
599 MHD_resume_connection (rd->c);
600 rd->body = make_json ("error", "true",
601 "message", _ ("name exists\n"),
602 NULL);
603 rd->body_length = strlen (rd->body);
604 rd->code = MHD_HTTP_FORBIDDEN;
605 GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating);
606 run_httpd_now ();
607 return;
608 }
609
610 GNUNET_NAMESTORE_zone_iterator_next (rd->iterating, 1);
611}
612
613
614/**
615 * All entries in the namestore have been iterated over.
616 *
617 * @param cls the connection
618 */
619static void
620iterate_done_cb (void *cls)
621{
622 struct RequestData *rd = cls;
623
624 rd->iterating = NULL;
625
626 /* See if the key was not registered already */
627 rd->searching = GNUNET_NAMESTORE_zone_to_name (namestore,
628 zone_key,
629 &(rd->key),
630 &register_error_cb,
631 rd,
632 &register_do_cb,
633 rd);
634}
635
636
637/**
638 * Generate a response containing JSON and send it to the client.
639 *
640 * @param c the connection
641 * @param body the response body
642 * @param length the body length in bytes
643 * @param code the response code
644 * @return MHD_NO on error
645 */
646static MHD_RESULT
647serve_json (struct MHD_Connection *c,
648 char *body,
649 size_t length,
650 int code)
651{
652 struct MHD_Response *response =
653 MHD_create_response_from_buffer (length,
654 body,
655 MHD_RESPMEM_PERSISTENT);
656 MHD_RESULT r = MHD_queue_response (c, code, response);
657 MHD_destroy_response (response);
658 return r;
659}
660
661
662/**
663 * Send a response back to a connected client.
664 *
665 * @param cls unused
666 * @param connection the connection with the client
667 * @param url the requested address
668 * @param method the HTTP method used
669 * @param version the protocol version (including the "HTTP/" part)
670 * @param upload_data data sent with a POST request
671 * @param upload_data_size length in bytes of the POST data
672 * @param ptr used to pass data between request handling phases
673 * @return MHD_NO on error
674 */
675static MHD_RESULT
676create_response (void *cls,
677 struct MHD_Connection *connection,
678 const char *url,
679 const char *method,
680 const char *version,
681 const char *upload_data,
682 size_t *upload_data_size,
683 void **ptr)
684{
685 (void) cls;
686 (void) version;
687
688 struct RequestData *rd = *ptr;
689
690 if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
691 {
692 /* Handle a previously suspended request */
693 if (NULL != rd)
694 {
695 return serve_json (rd->c, rd->body, rd->body_length, rd->code);
696 }
697
698 if (0 == strcmp ("/", url))
699 {
700 return MHD_queue_response (connection,
701 MHD_HTTP_OK,
702 main_page->response);
703 }
704
705 if (0 == strcmp ("/search", url))
706 {
707 const char *name = MHD_lookup_connection_value (connection,
708 MHD_GET_ARGUMENT_KIND,
709 "name");
710 if (NULL == name)
711 {
712 return MHD_queue_response (connection,
713 MHD_HTTP_BAD_REQUEST,
714 forbidden_page->response);
715 }
716
717 MHD_suspend_connection (connection);
718 rd = GNUNET_new (struct RequestData);
719 rd->c = connection;
720 rd->searching = GNUNET_NAMESTORE_records_lookup (namestore,
721 zone_key,
722 name,
723 &search_error_cb,
724 rd,
725 &search_done_cb,
726 rd);
727 *ptr = rd;
728 return MHD_YES;
729 }
730
731 return MHD_queue_response (connection,
732 MHD_HTTP_NOT_FOUND,
733 notfound_page->response);
734 }
735
736 if (0 == strcmp (method, MHD_HTTP_METHOD_HEAD))
737 {
738 /* We take a shortcut here by always serving the main page: starting a
739 namestore lookup, allocating the necessary resources, waiting for the
740 lookup to complete and then discard everything just because it was a HEAD
741 and thus only the headers are significative, is an unnecessary waste of
742 resources. The handling of this method could be smarter, for example by
743 sending a proper content type header based on the endpoint, but this is
744 not a service in which HEAD requests are significant, so there's no need
745 to spend too much time here. */
746 return MHD_queue_response (connection,
747 MHD_HTTP_OK,
748 main_page->response);
749 }
750
751 if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
752 {
753 if (0 == strcmp ("/register", url))
754 {
755 /* Handle a previously suspended request */
756 if ((NULL != rd) && (NULL != rd->body))
757 {
758 return serve_json (rd->c, rd->body, rd->body_length, rd->code);
759 }
760
761 if (NULL == rd)
762 {
763 rd = GNUNET_new (struct RequestData);
764 rd->c = connection;
765 rd->body = NULL;
766 rd->ptr = NULL;
767 *ptr = rd;
768 }
769
770 json_t *json = NULL;
771 enum GNUNET_JSON_PostResult result =
772 GNUNET_JSON_post_parser (32 * 1024,
773 connection,
774 &(rd->ptr),
775 upload_data,
776 upload_data_size,
777 &json);
778
779 switch (result)
780 {
781 case GNUNET_JSON_PR_CONTINUE:
782 /* Keep processing POST data */
783 return MHD_YES;
784 case GNUNET_JSON_PR_OUT_OF_MEMORY:
785 case GNUNET_JSON_PR_REQUEST_TOO_LARGE:
786 rd->body = make_json ("error", "true",
787 "message", _ ("unable to process submitted data"),
788 NULL);
789 rd->body_length = strlen (rd->body);
790#ifdef MHD_HTTP_CONTENT_TOO_LARGE
791 rd->code = MHD_HTTP_CONTENT_TOO_LARGE;
792#else
793 rd->code = MHD_HTTP_PAYLOAD_TOO_LARGE;
794#endif
795 return MHD_YES;
796 case GNUNET_JSON_PR_JSON_INVALID:
797 rd->body = make_json ("error", "true",
798 "message", _ ("the submitted data is invalid"),
799 NULL);
800 rd->body_length = strlen (rd->body);
801 rd->code = MHD_HTTP_BAD_REQUEST;
802 return MHD_YES;
803 default:
804 break;
805 }
806
807 /* POST data has been read in its entirety */
808
809 const char *name = json_string_value (json_object_get (json, "name"));
810 const char *key = json_string_value (json_object_get (json, "key"));
811 if ((NULL == name) || (NULL == key) || (0 == strlen (name)) || (0 ==
812 strlen (
813 key)))
814 {
815 json_decref (json);
816 rd->body = make_json ("error", "true",
817 "message", _ ("invalid parameters"),
818 NULL);
819 rd->body_length = strlen (rd->body);
820 rd->code = MHD_HTTP_BAD_REQUEST;
821 return MHD_YES;
822 }
823
824 rd->register_name = strdup (name);
825 rd->register_key = strdup (key);
826
827 json_decref (json);
828 GNUNET_JSON_post_parser_cleanup (rd->ptr);
829
830 if ((NULL != strchr (rd->register_name, '.')) ||
831 (NULL != strchr (rd->register_name, '+')))
832 {
833 rd->body = make_json ("error", "true",
834 "message", _ ("invalid name"),
835 NULL);
836 rd->body_length = strlen (rd->body);
837 rd->code = MHD_HTTP_BAD_REQUEST;
838 return MHD_YES;
839 }
840
841 if (GNUNET_OK != GNUNET_CRYPTO_public_key_from_string (rd->register_key,
842 &(rd->key)))
843 {
844 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
845 _ ("Unable to parse key %s\n"),
846 rd->register_key);
847
848 rd->body = make_json ("error", "true",
849 "message", _ ("unable to parse key"),
850 NULL);
851 rd->body_length = strlen (rd->body);
852 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
853 return MHD_YES;
854 }
855
856 MHD_suspend_connection (connection);
857 /* See if the requested name is free */
858 rd->iterating =
859 GNUNET_NAMESTORE_zone_iteration_start (namestore,
860 zone_key,
861 &iterate_error_cb,
862 rd,
863 &iterate_do_cb,
864 rd,
865 &iterate_done_cb,
866 rd);
867 return MHD_YES;
868 }
869
870 return MHD_queue_response (connection,
871 MHD_HTTP_FORBIDDEN,
872 forbidden_page->response);
873 }
874
875 return MHD_queue_response (connection,
876 MHD_HTTP_NOT_IMPLEMENTED,
877 forbidden_page->response);
878}
879
880
881/**
882 * Called when a request is completed.
883 *
884 * @param cls unused
885 * @param connection the connection
886 * @param ptr connection-specific data
887 * @param status status code
888 */
889static void
890completed_cb (void *cls,
891 struct MHD_Connection *connection,
892 void **ptr,
893 enum MHD_RequestTerminationCode status)
894{
895 (void) cls;
896 (void) connection;
897 (void) status;
898
899 struct RequestData *rd = *ptr;
900
901 if (NULL == rd)
902 {
903 return;
904 }
905
906 if (NULL == rd->body)
907 {
908 GNUNET_free (rd->body);
909 }
910
911 if (NULL != rd->searching)
912 {
913 GNUNET_NAMESTORE_cancel (rd->searching);
914 }
915
916 if (NULL != rd->register_name)
917 {
918 GNUNET_free (rd->register_name);
919 }
920
921 if (NULL != rd->register_key)
922 {
923 GNUNET_free (rd->register_key);
924 }
925
926 if (NULL != rd->iterating)
927 {
928 GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating);
929 }
930
931 GNUNET_free (rd);
932}
933
934
935/**
936 * Called for each ego provided by the identity service.
937 *
938 * @param cls closure
939 * @param ego the ego
940 * @param ctx application-provided data for the ego
941 * @param name the ego name
942 */
943static void
944identity_cb (void *cls,
945 struct GNUNET_IDENTITY_Ego *ego,
946 void **ctx,
947 const char *name)
948{
949 (void) cls;
950 (void) ctx;
951
952 if ((NULL == name) || (0 != strcmp (name, zone)))
953 {
954 return;
955 }
956
957 if (NULL == ego)
958 {
959 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
960 _ ("No ego configured for `fcfsd` subsystem\n"));
961 GNUNET_SCHEDULER_shutdown ();
962 return;
963 }
964
965 zone_key = GNUNET_IDENTITY_ego_get_private_key (ego);
966
967 int flags = MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_ALLOW_SUSPEND_RESUME;
968 do
969 {
970 httpd = MHD_start_daemon (flags,
971 (uint16_t) port,
972 NULL, NULL,
973 &create_response, NULL,
974 MHD_OPTION_CONNECTION_LIMIT, 128,
975 MHD_OPTION_PER_IP_CONNECTION_LIMIT, 1,
976 MHD_OPTION_CONNECTION_TIMEOUT, 4 * 1024,
977 MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
978 MHD_OPTION_END);
979 flags = MHD_USE_DEBUG;
980 } while (NULL == httpd && flags != MHD_USE_DEBUG);
981
982 if (NULL == httpd)
983 {
984 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
985 _ ("Failed to start HTTP server\n"));
986 GNUNET_SCHEDULER_shutdown ();
987 return;
988 }
989
990 run_httpd ();
991}
992
993
994/**
995 * Open a file on disk and generate a response object for it.
996 *
997 * @param name name of the file to open
998 * @param basedir directory where the file is located
999 * @return NULL on error
1000 */
1001static struct StaticPage *
1002open_static_page (const char *name, const char *basedir)
1003{
1004 char *fullname = NULL;
1005 GNUNET_asprintf (&fullname, "%s/fcfsd-%s", basedir, name);
1006
1007 struct GNUNET_DISK_FileHandle *f =
1008 GNUNET_DISK_file_open (fullname,
1009 GNUNET_DISK_OPEN_READ,
1010 GNUNET_DISK_PERM_NONE);
1011 GNUNET_free (fullname);
1012
1013 if (NULL == f)
1014 {
1015 return NULL;
1016 }
1017
1018 off_t size = 0;
1019 if (GNUNET_SYSERR == GNUNET_DISK_file_handle_size (f, &size))
1020 {
1021 GNUNET_DISK_file_close (f);
1022 return NULL;
1023 }
1024
1025 struct MHD_Response *response =
1026 MHD_create_response_from_fd64 (size,
1027 f->fd);
1028
1029 if (NULL == response)
1030 {
1031 GNUNET_DISK_file_close (f);
1032 return NULL;
1033 }
1034
1035 struct StaticPage *page = GNUNET_new (struct StaticPage);
1036 page->handle = f;
1037 page->size = (uint64_t) size;
1038 page->response = response;
1039 return page;
1040}
1041
1042
1043/**
1044 * Called after the service is up.
1045 *
1046 * @param cls closure
1047 * @param args remaining command line arguments
1048 * @param cfgfile name of the configuration file
1049 * @param cfg the service configuration
1050 */
1051static void
1052run_service (void *cls,
1053 char *const *args,
1054 const char *cfgfile,
1055 const struct GNUNET_CONFIGURATION_Handle *cfg)
1056{
1057 (void) cls;
1058 (void) args;
1059 (void) cfgfile;
1060
1061 GNUNET_log_setup ("fcfsd", "WARNING", NULL);
1062
1063 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
1064 "fcfsd",
1065 "RELATIVE_RECORD_EXPIRATION",
1066 &record_exp))
1067 {
1068 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1069 _ ("No expiration specified for records.\n"));
1070 GNUNET_SCHEDULER_shutdown ();
1071 return;
1072 }
1073
1074 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
1075 "fcfsd",
1076 "HTTPPORT",
1077 &port))
1078 {
1079 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1080 _ ("No port specified, using default value\n"));
1081 }
1082
1083 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1084
1085 namestore = GNUNET_NAMESTORE_connect (cfg);
1086 if (NULL == namestore)
1087 {
1088 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1089 _ ("Failed to connect to namestore\n"));
1090 GNUNET_SCHEDULER_shutdown ();
1091 return;
1092 }
1093
1094 identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
1095 if (NULL == identity)
1096 {
1097 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1098 _ ("Failed to connect to identity\n"));
1099 GNUNET_SCHEDULER_shutdown ();
1100 return;
1101 }
1102
1103 char *basedir = NULL;
1104 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
1105 "fcfsd",
1106 "HTMLDIR",
1107 &basedir))
1108 {
1109 basedir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
1110 }
1111
1112 main_page = open_static_page ("index.html", basedir);
1113 notfound_page = open_static_page ("notfound.html", basedir);
1114 forbidden_page = open_static_page ("forbidden.html", basedir);
1115
1116 GNUNET_free (basedir);
1117
1118 if ((NULL == main_page) || (NULL == notfound_page) || (NULL ==
1119 forbidden_page) )
1120 {
1121 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1122 _ ("Unable to set up the daemon\n"));
1123 GNUNET_SCHEDULER_shutdown ();
1124 return;
1125 }
1126}
1127
1128
1129/**
1130 * The main function of the fcfs daemon.
1131 *
1132 * @param argc number of arguments from the command line
1133 * @param argv the command line arguments
1134 * @return 0 successful exit, a different value otherwise
1135 */
1136int
1137main (int argc, char *const *argv)
1138{
1139 struct GNUNET_GETOPT_CommandLineOption options[] = {
1140 GNUNET_GETOPT_option_mandatory
1141 (GNUNET_GETOPT_option_string ('z',
1142 "zone",
1143 "EGO",
1144 gettext_noop (
1145 "name of the zone managed by FCFSD"),
1146 &zone)),
1147 GNUNET_GETOPT_OPTION_END
1148 };
1149
1150 return ((GNUNET_OK == GNUNET_PROGRAM_run (argc,
1151 argv,
1152 "gnunet-namestore-fcfsd",
1153 _ (
1154 "GNU Name System First-Come-First-Served name registration service"),
1155 options,
1156 &run_service,
1157 NULL)) ?
1158 0 :
1159 1);
1160}
diff --git a/src/service/namestore/meson.build b/src/service/namestore/meson.build
index 62512c405..a2183d630 100644
--- a/src/service/namestore/meson.build
+++ b/src/service/namestore/meson.build
@@ -40,21 +40,6 @@ executable ('gnunet-service-namestore',
40 include_directories: [incdir, configuration_inc], 40 include_directories: [incdir, configuration_inc],
41 install: true, 41 install: true,
42 install_dir: get_option('libdir')/'gnunet'/'libexec') 42 install_dir: get_option('libdir')/'gnunet'/'libexec')
43executable ('gnunet-namestore-fcfsd',
44 ['gnunet-namestore-fcfsd.c'],
45 dependencies: [libgnunetnamestore_dep,
46 libgnunetutil_dep,
47 libgnunetnamecache_dep,
48 libgnunetgnsrecord_dep,
49 libgnunetidentity_dep,
50 mhd_dep,
51 json_dep,
52 libgnunetjson_dep,
53 libgnunetstatistics_dep],
54 include_directories: [incdir, configuration_inc],
55 install: true,
56 install_dir: get_option('libdir')/'gnunet'/'libexec')
57
58 43
59configure_file(copy: true, 44configure_file(copy: true,
60 input: 'test_namestore_api.conf', 45 input: 'test_namestore_api.conf',
diff --git a/src/service/namestore/namestore.conf.in b/src/service/namestore/namestore.conf.in
index d817f3f95..8c467c5ac 100644
--- a/src/service/namestore/namestore.conf.in
+++ b/src/service/namestore/namestore.conf.in
@@ -34,14 +34,3 @@ SQL_DIR = ${DATADIR}/sql/
34 34
35[uri] 35[uri]
36gns = gnunet-namestore -e 1a -u 36gns = gnunet-namestore -e 1a -u
37
38
39[fcfsd]
40# Name of the fcfs registration service binary (for ARM)
41BINARY = gnunet-namestore-fcfsd
42START_ON_DEMAND = NO
43UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-fcfsd.sock
44RELATIVE_RECORD_EXPIRATION = 7 d
45
46# On what port does the FCFS daemon listen for HTTP clients?
47HTTPPORT = 18080