GNUnet 0.21.1
gnunet-service-fs_cadet_server.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2017 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
30#include "platform.h"
31#include "gnunet_constants.h"
32#include "gnunet_util_lib.h"
34#include "gnunet_protocols.h"
35#include "gnunet_applications.h"
36#include "gnunet-service-fs.h"
39
43#define IDLE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
44
45
50{
55
60
64 size_t msize;
65};
66
67
71struct CadetClient
72{
76 struct CadetClient *next;
77
81 struct CadetClient *prev;
82
87
92
97
102
107
112
117};
118
119
124
128static struct CadetClient *sc_head;
129
133static struct CadetClient *sc_tail;
134
138static unsigned int sc_count;
139
143static unsigned long long sc_count_max;
144
145
151static void
153{
154 struct CadetClient *sc = cls;
155 struct GNUNET_CADET_Channel *tun;
156
157 sc->timeout_task = NULL;
158 tun = sc->channel;
159 sc->channel = NULL;
161 "Timeout for inactive cadet client %p\n",
162 sc);
164}
165
166
172static void
174{
175 if (NULL != sc->timeout_task)
176 GNUNET_SCHEDULER_cancel (sc->timeout_task);
179 sc);
180}
181
182
189static void
191{
192 struct CadetClient *sc = cls;
193 struct GNUNET_MQ_Handle *mq;
194
195 mq = GNUNET_CADET_get_mq (sc->channel);
196 if (0 != GNUNET_MQ_get_length (mq))
197 {
199 "Write pending, waiting for it to complete\n");
200 return;
201 }
204 "Finished processing cadet request from client %p, ready to receive the next one\n",
205 sc);
206 GNUNET_CADET_receive_done (sc->channel);
207}
208
209
225static void
227 const struct GNUNET_HashCode *key,
228 size_t size,
229 const void *data,
231 uint32_t priority,
232 uint32_t anonymity,
233 uint32_t replication,
235 uint64_t uid)
236{
237 struct CadetClient *sc = cls;
238 size_t msize = size + sizeof(struct CadetReplyMessage);
239 struct GNUNET_MQ_Envelope *env;
240 struct CadetReplyMessage *srm;
241
242 sc->qe = NULL;
243 if (NULL == data)
244 {
245 /* no result, this should not really happen, as for
246 non-anonymous routing only peers that HAVE the
247 answers should be queried; OTOH, this is not a
248 hard error as we might have had the answer in the
249 past and the user might have unindexed it. Hence
250 we log at level "INFO" for now. */if (NULL == key)
251 {
253 "Have no answer and the query was NULL\n");
254 }
255 else
256 {
258 "Have no answer for query `%s'\n",
259 GNUNET_h2s (key));
260 }
263 "# queries received via CADET not answered"),
264 1,
265 GNUNET_NO);
267 return;
268 }
270 {
272 "Performing on-demand encoding for query %s\n",
273 GNUNET_h2s (key));
274 if (GNUNET_OK !=
276 size,
277 data,
278 type,
279 priority,
280 anonymity,
283 uid,
285 sc))
286 {
288 "On-demand encoding request failed\n");
290 }
291 return;
292 }
293 if (msize > GNUNET_MAX_MESSAGE_SIZE)
294 {
295 GNUNET_break (0);
297 return;
298 }
301 "Starting transmission of %u byte reply of type %d for query `%s' via cadet to %p\n",
302 (unsigned int) size,
303 (unsigned int) type,
304 GNUNET_h2s (key),
305 sc);
307 size,
309 srm->type = htonl (type);
311 GNUNET_memcpy (&srm[1],
312 data,
313 size);
316 sc);
318 gettext_noop ("# Blocks transferred via cadet"),
319 1,
320 GNUNET_NO);
322 env);
323}
324
325
333static void
334handle_request (void *cls,
335 const struct CadetQueryMessage *sqm)
336{
337 struct CadetClient *sc = cls;
338
340 "Received query for `%s' via cadet from client %p\n",
341 GNUNET_h2s (&sqm->query),
342 sc);
344 gettext_noop ("# queries received via cadet"),
345 1,
346 GNUNET_NO);
349 0 /* next_uid */,
350 false /* random */,
351 &sqm->query,
352 ntohl (sqm->type),
353 0 /* priority */,
356 sc);
357 if (NULL == sc->qe)
358 {
360 "Queueing request with datastore failed (queue full?)\n");
362 }
363}
364
365
375static void *
376connect_cb (void *cls,
378 const struct GNUNET_PeerIdentity *initiator)
379{
380 struct CadetClient *sc;
381
382 GNUNET_assert (NULL != channel);
383 if (sc_count >= sc_count_max)
384 {
387 "# cadet client connections rejected"),
388 1,
389 GNUNET_NO);
391 return NULL;
392 }
394 gettext_noop ("# cadet connections active"),
395 1,
396 GNUNET_NO);
397 sc = GNUNET_new (struct CadetClient);
398 sc->channel = channel;
400 sc_tail,
401 sc);
402 sc_count++;
405 "Accepting inbound cadet connection from `%s' as client %p\n",
406 GNUNET_i2s (initiator),
407 sc);
408 return sc;
409}
410
411
419static void
420disconnect_cb (void *cls,
421 const struct GNUNET_CADET_Channel *channel)
422{
423 struct CadetClient *sc = cls;
424 struct WriteQueueItem *wqi;
425
426 if (NULL == sc)
427 return;
428 sc->channel = NULL;
430 "Terminating cadet connection with client %p\n",
431 sc);
433 gettext_noop ("# cadet connections active"), -1,
434 GNUNET_NO);
435 if (NULL != sc->terminate_task)
436 GNUNET_SCHEDULER_cancel (sc->terminate_task);
437 if (NULL != sc->timeout_task)
438 GNUNET_SCHEDULER_cancel (sc->timeout_task);
439 if (NULL != sc->qe)
441 while (NULL != (wqi = sc->wqi_head))
442 {
444 sc->wqi_tail,
445 wqi);
446 GNUNET_free (wqi);
447 }
449 sc_tail,
450 sc);
451 sc_count--;
452 GNUNET_free (sc);
453}
454
455
470static void
472 const struct GNUNET_CADET_Channel *channel,
473 int window_size)
474{
475 /* FIXME: could do flow control here... */
476}
477
478
482void
484{
488 struct CadetQueryMessage,
489 NULL),
491 };
492 struct GNUNET_HashCode port;
493
494 if (GNUNET_YES !=
496 "fs",
497 "MAX_CADET_CLIENTS",
498 &sc_count_max))
499 return;
501 "Initializing cadet FS server with a limit of %llu connections\n",
505 GNUNET_assert (NULL != cadet_handle);
508 &port);
510 &port,
511 &connect_cb,
512 NULL,
515 handlers);
516}
517
518
522void
524{
527 NULL);
529 cadet_map = NULL;
530 if (NULL != cadet_port)
531 {
533 cadet_port = NULL;
534 }
535 if (NULL != cadet_handle)
536 {
538 cadet_handle = NULL;
539 }
540 GNUNET_assert (NULL == sc_head);
541 GNUNET_assert (0 == sc_count);
542}
543
544
545/* end of gnunet-service-fs_cadet.c */
struct GNUNET_MQ_MessageHandlers handlers[]
Definition: 003.c:1
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define gettext_noop(String)
Definition: gettext.h:70
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static unsigned int replication
Desired replication level.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static unsigned int anonymity
static uint32_t type
Type string converted to DNS type value.
static struct GNUNET_FS_SearchContext * sc
Definition: gnunet-search.c:87
struct GNUNET_STATISTICS_Handle * GSF_stats
Handle for reporting statistics.
const struct GNUNET_CONFIGURATION_Handle * GSF_cfg
Our configuration.
struct GNUNET_DATASTORE_Handle * GSF_dsh
Our connection to the datastore.
unsigned int GSF_datastore_queue_size
Size of the datastore queue we assume for common requests.
shared data structures of gnunet-service-fs.c
non-anonymous file-transfer
struct GNUNET_CONTAINER_MultiPeerMap * cadet_map
Map from peer identities to 'struct CadetHandles' with cadet channels to those peers.
int GSF_cadet_release_clients(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Function called on each active cadets to shut them down.
static void disconnect_cb(void *cls, const struct GNUNET_CADET_Channel *channel)
Function called by cadet when a client disconnects.
static void window_change_cb(void *cls, const struct GNUNET_CADET_Channel *channel, int window_size)
Function called whenever an MQ-channel's transmission window size changes.
static unsigned int sc_count
Number of active cadet clients in the 'sc_*'-DLL.
static void refresh_timeout_task(struct CadetClient *sc)
Reset the timeout for the cadet client (due to activity).
static void handle_datastore_reply(void *cls, const struct GNUNET_HashCode *key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid)
Process a datum that was stored in the datastore.
static struct CadetClient * sc_tail
Tail of DLL of cadet clients.
void GSF_cadet_start_server()
Initialize subsystem for non-anonymous file-sharing.
static unsigned long long sc_count_max
Maximum allowed number of cadet clients.
void GSF_cadet_stop_server()
Shutdown subsystem for non-anonymous file-sharing.
static void handle_request(void *cls, const struct CadetQueryMessage *sqm)
Functions with this signature are called whenever a complete query message is received.
static void timeout_cadet_task(void *cls)
Task run to asynchronously terminate the cadet due to timeout.
#define IDLE_TIMEOUT
After how long do we termiante idle connections?
static void * connect_cb(void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator)
Functions of this type are called upon new cadet connection from other peers.
static void continue_writing(void *cls)
Check if we are done with the write queue, and if so tell CADET that we are ready to read more.
static struct GNUNET_CADET_Port * cadet_port
Listen port for incoming requests.
static struct CadetClient * sc_head
Head of DLL of cadet clients.
int GNUNET_FS_handle_on_demand_block(const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid, GNUNET_DATASTORE_DatumProcessor cont, void *cont_cls)
We've received an on-demand encoded block from the datastore.
indexing for the file-sharing service
struct GNUNET_CADET_Handle * cadet_handle
Handler to CADET.
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
Constants for network applications operating on top of the CADET service.
CADET service; establish channels to distant peers.
Constants for network protocols.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
#define GNUNET_APPLICATION_PORT_FS_BLOCK_TRANSFER
Transfer of blocks for non-anonymmous file-sharing.
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition: cadet_api.c:894
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Indicate readiness to receive the next message on a channel.
Definition: cadet_api.c:872
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:830
struct GNUNET_MQ_Handle * GNUNET_CADET_get_mq(const struct GNUNET_CADET_Channel *channel)
Obtain the message queue for a connected channel.
Definition: cadet_api.c:1066
struct GNUNET_CADET_Port * GNUNET_CADET_open_port(struct GNUNET_CADET_Handle *h, const struct GNUNET_HashCode *port, GNUNET_CADET_ConnectEventHandler connects, void *connects_cls, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Open a port to receive incoming MQ-based channels.
Definition: cadet_api.c:954
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:774
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port.
Definition: cadet_api.c:801
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void GNUNET_DATASTORE_cancel(struct GNUNET_DATASTORE_QueueEntry *qe)
Cancel a datastore operation.
struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_get_key(struct GNUNET_DATASTORE_Handle *h, uint64_t next_uid, bool random, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, unsigned int queue_priority, unsigned int max_queue_size, GNUNET_DATASTORE_DatumProcessor proc, void *proc_cls)
Get a result for a particular key from the datastore.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:293
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:304
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition: mq.c:638
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_FS_CADET_QUERY
P2P request for content (one FS to another via a cadet).
#define GNUNET_MESSAGE_TYPE_FS_CADET_REPLY
P2P answer for content (one FS to another via a cadet).
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1278
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
static unsigned int size
Size of the "table".
Definition: peer.c:68
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
@ GNUNET_BLOCK_TYPE_FS_ONDEMAND
Type of a block representing a block to be encoded on demand from disk.
@ GNUNET_BLOCK_TYPE_ANY
Identifier for any block.
Struct containing information about a client of the service.
struct GNUNET_SCHEDULER_Task * terminate_task
Task that is scheduled to asynchronously terminate the connection.
struct GNUNET_DATASTORE_QueueEntry * qe
Current active request to the datastore, if we have one pending.
size_t reply_size
Size of the last write that was initiated.
struct WriteQueueItem * wqi_tail
Tail of write queue.
struct CadetClient * prev
Linked list prev.
struct GNUNET_CADET_Channel * channel
Channel for communication.
struct WriteQueueItem * wqi_head
Head of write queue.
struct GNUNET_SCHEDULER_Task * timeout_task
Task that is scheduled to terminate idle connections.
struct CadetClient * next
Linked list next.
Query from one peer, asking the other for CHK-data.
struct GNUNET_HashCode query
Query hash from CHK (hash of encrypted block).
uint32_t type
Block type must be DBLOCK or IBLOCK.
Reply to a CadetQueryMessage.
struct GNUNET_TIME_AbsoluteNBO expiration
Expiration time for the block.
uint32_t type
Block type must be DBLOCK or IBLOCK.
Opaque handle to a channel.
Definition: cadet.h:116
Opaque handle to a port.
Definition: cadet_api.c:80
Entry in our priority queue.
A 512-bit hashcode.
Handle to a message queue.
Definition: mq.c:87
enum GNUNET_MQ_PriorityPreferences priority
Flags that were set for this queue by GNUNET_MQ_set_options().
Definition: mq.c:165
Message handler for a specific message type.
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
A message in the queue to be written to the cadet.
struct WriteQueueItem * next
Kept in a DLL.
size_t msize
Number of bytes of payload, allocated at the end of this struct.
struct WriteQueueItem * prev
Kept in a DLL.