tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / fs / gnunet-service-fs.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2014, 2016 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 fs/gnunet-service-fs.c
23  * @brief gnunet anonymity protocol implementation
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include <float.h>
28 #include "gnunet_constants.h"
29 #include "gnunet_core_service.h"
30 #include "gnunet_dht_service.h"
31 #include "gnunet_datastore_service.h"
32 #include "gnunet_load_lib.h"
33 #include "gnunet_peer_lib.h"
34 #include "gnunet_protocols.h"
35 #include "gnunet_signatures.h"
36 #include "gnunet_statistics_service.h"
37 #include "gnunet_transport_service.h"
38 #include "gnunet_util_lib.h"
39 #include "gnunet-service-fs_cp.h"
40 #include "gnunet-service-fs_indexing.h"
41 #include "gnunet-service-fs_pe.h"
42 #include "gnunet-service-fs_pr.h"
43 #include "gnunet-service-fs_push.h"
44 #include "gnunet-service-fs_put.h"
45 #include "gnunet-service-fs_cadet.h"
46 #include "fs.h"
47 #include "fs_api.h"
48
49 /**
50  * Size for the hash map for DHT requests from the FS
51  * service.  Should be about the number of concurrent
52  * DHT requests we plan to make.
53  */
54 #define FS_DHT_HT_SIZE 1024
55
56
57 /**
58  * How quickly do we age cover traffic?  At the given
59  * time interval, remaining cover traffic counters are
60  * decremented by 1/16th.
61  */
62 #define COVER_AGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
63
64 /**
65  * Collect an instane number of statistics?  May cause excessive IPC.
66  */
67 #define INSANE_STATISTICS GNUNET_NO
68
69
70
71 /**
72  * Doubly-linked list of requests we are performing
73  * on behalf of the same client.
74  */
75 struct ClientRequest
76 {
77
78   /**
79    * This is a doubly-linked list.
80    */
81   struct ClientRequest *next;
82
83   /**
84    * This is a doubly-linked list.
85    */
86   struct ClientRequest *prev;
87
88   /**
89    * Request this entry represents.
90    */
91   struct GSF_PendingRequest *pr;
92
93   /**
94    * Client list this request belongs to.
95    */
96   struct GSF_LocalClient *lc;
97
98   /**
99    * Task scheduled to destroy the request.
100    */
101   struct GNUNET_SCHEDULER_Task * kill_task;
102
103 };
104
105
106 /**
107  * Replies to be transmitted to the client.  The actual
108  * response message is allocated after this struct.
109  */
110 struct ClientResponse
111 {
112   /**
113    * This is a doubly-linked list.
114    */
115   struct ClientResponse *next;
116
117   /**
118    * This is a doubly-linked list.
119    */
120   struct ClientResponse *prev;
121
122   /**
123    * Client list entry this response belongs to.
124    */
125   struct GSF_LocalClient *lc;
126
127   /**
128    * Number of bytes in the response.
129    */
130   size_t msize;
131 };
132
133
134 /**
135  * Information we track while handling an index
136  * start request from a client.
137  */
138 struct IndexStartContext
139 {
140
141   /**
142    * This is a doubly linked list.
143    */
144   struct IndexStartContext *next;
145
146   /**
147    * This is a doubly linked list.
148    */
149   struct IndexStartContext *prev;
150
151   /**
152    * Name of the indexed file.
153    */
154   char *filename;
155
156   /**
157    * Context for transmitting confirmation to client.
158    */
159   struct GSF_LocalClient *lc;
160
161   /**
162    * Context for hashing of the file.
163    */
164   struct GNUNET_CRYPTO_FileHashContext *fhc;
165
166   /**
167    * Hash of the contents of the file.
168    */
169   struct GNUNET_HashCode file_id;
170
171 };
172
173
174 /**
175  * A local client.
176  */
177 struct GSF_LocalClient
178 {
179
180   /**
181    * ID of the client.
182    */
183   struct GNUNET_SERVICE_Client *client;
184
185   /**
186    * Queue for sending replies.
187    */
188   struct GNUNET_MQ_Handle *mq;
189
190   /**
191    * Head of list of requests performed on behalf
192    * of this client right now.
193    */
194   struct ClientRequest *cr_head;
195
196   /**
197    * Tail of list of requests performed on behalf
198    * of this client right now.
199    */
200   struct ClientRequest *cr_tail;
201
202   /**
203    * This is a doubly linked list.
204    */
205   struct IndexStartContext *isc_head;
206
207   /**
208    * This is a doubly linked list.
209    */
210   struct IndexStartContext *isc_tail;
211
212   /**
213    * Head of linked list of responses.
214    */
215   struct ClientResponse *res_head;
216
217   /**
218    * Tail of linked list of responses.
219    */
220   struct ClientResponse *res_tail;
221
222 };
223
224
225 /* ****************************** globals ****************************** */
226
227 /**
228  * Our connection to the datastore.
229  */
230 struct GNUNET_DATASTORE_Handle *GSF_dsh;
231
232 /**
233  * Our configuration.
234  */
235 const struct GNUNET_CONFIGURATION_Handle *GSF_cfg;
236
237 /**
238  * Handle for reporting statistics.
239  */
240 struct GNUNET_STATISTICS_Handle *GSF_stats;
241
242 /**
243  * Handle for DHT operations.
244  */
245 struct GNUNET_DHT_Handle *GSF_dht;
246
247 /**
248  * How long do requests typically stay in the routing table?
249  */
250 struct GNUNET_LOAD_Value *GSF_rt_entry_lifetime;
251
252 /**
253  * Running average of the observed latency to other peers (round trip).
254  * Initialized to 5s as the initial default.
255  */
256 struct GNUNET_TIME_Relative GSF_avg_latency = { 500 };
257
258 /**
259  * Handle to ATS service.
260  */
261 struct GNUNET_ATS_PerformanceHandle *GSF_ats;
262
263
264 /**
265  * Typical priorities we're seeing from other peers right now.  Since
266  * most priorities will be zero, this value is the weighted average of
267  * non-zero priorities seen "recently".  In order to ensure that new
268  * values do not dramatically change the ratio, values are first
269  * "capped" to a reasonable range (+N of the current value) and then
270  * averaged into the existing value by a ratio of 1:N.  Hence
271  * receiving the largest possible priority can still only raise our
272  * "current_priorities" by at most 1.
273  */
274 double GSF_current_priorities;
275
276 /**
277  * Size of the datastore queue we assume for common requests.
278  */
279 unsigned int GSF_datastore_queue_size;
280
281 /**
282  * How many query messages have we received 'recently' that
283  * have not yet been claimed as cover traffic?
284  */
285 unsigned int GSF_cover_query_count;
286
287 /**
288  * How many content messages have we received 'recently' that
289  * have not yet been claimed as cover traffic?
290  */
291 unsigned int GSF_cover_content_count;
292
293 /**
294  * Our block context.
295  */
296 struct GNUNET_BLOCK_Context *GSF_block_ctx;
297
298 /**
299  * Pointer to handle to the core service (points to NULL until we've
300  * connected to it).
301  */
302 struct GNUNET_CORE_Handle *GSF_core;
303
304 /**
305  * Are we introducing randomized delays for better anonymity?
306  */
307 int GSF_enable_randomized_delays;
308
309 /**
310  * Identity of this peer.
311  */
312 struct GNUNET_PeerIdentity GSF_my_id;
313
314 /* ***************************** locals ******************************* */
315
316 /**
317  * Configuration for block library.
318  */
319 static struct GNUNET_CONFIGURATION_Handle *block_cfg;
320
321 /**
322  * Private key of this peer.  Used to sign LOC URI requests.
323  */
324 static struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
325
326 /**
327  * ID of our task that we use to age the cover counters.
328  */
329 static struct GNUNET_SCHEDULER_Task * cover_age_task;
330
331 /**
332  * Datastore 'GET' load tracking.
333  */
334 static struct GNUNET_LOAD_Value *datastore_get_load;
335
336
337 /**
338  * Creates a fresh local client handle.
339  *
340  * @param cls NULL
341  * @param client handle of the client
342  * @param mq message queue for @a client
343  * @return handle to local client entry
344  */
345 static void *
346 client_connect_cb (void *cls,
347                    struct GNUNET_SERVICE_Client *client,
348                    struct GNUNET_MQ_Handle *mq)
349 {
350   struct GSF_LocalClient *pos;
351
352   pos = GNUNET_new (struct GSF_LocalClient);
353   pos->client = client;
354   pos->mq = mq;
355   return pos;
356 }
357
358
359 /**
360  * Free the given client request.
361  *
362  * @param cls the client request to free
363  */
364 static void
365 client_request_destroy (void *cls)
366 {
367   struct ClientRequest *cr = cls;
368   struct GSF_LocalClient *lc = cr->lc;
369
370   cr->kill_task = NULL;
371   GNUNET_CONTAINER_DLL_remove (lc->cr_head,
372                                lc->cr_tail,
373                                cr);
374   GSF_pending_request_cancel_ (cr->pr,
375                                GNUNET_YES);
376   GNUNET_STATISTICS_update (GSF_stats,
377                             gettext_noop ("# client searches active"),
378                             -1,
379                             GNUNET_NO);
380   GNUNET_free (cr);
381 }
382
383
384 /**
385  * Handle a reply to a pending request.  Also called if a request
386  * expires (then with data == NULL).  The handler may be called
387  * many times (depending on the request type), but will not be
388  * called during or after a call to #GSF_pending_request_cancel()
389  * and will also not be called anymore after a call signalling
390  * expiration.
391  *
392  * @param cls user-specified closure
393  * @param eval evaluation of the result
394  * @param pr handle to the original pending request
395  * @param reply_anonymity_level anonymity level for the reply, UINT32_MAX for "unknown"
396  * @param expiration when does @a data expire?
397  * @param last_transmission when was the last time we've tried to download this block? (FOREVER if unknown)
398  * @param type type of the block
399  * @param data response data, NULL on request expiration
400  * @param data_len number of bytes in @a data
401  */
402 static void
403 client_response_handler (void *cls,
404                          enum GNUNET_BLOCK_EvaluationResult eval,
405                          struct GSF_PendingRequest *pr,
406                          uint32_t reply_anonymity_level,
407                          struct GNUNET_TIME_Absolute expiration,
408                          struct GNUNET_TIME_Absolute last_transmission,
409                          enum GNUNET_BLOCK_Type type,
410                          const void *data,
411                          size_t data_len)
412 {
413   struct ClientRequest *cr = cls;
414   struct GSF_LocalClient *lc;
415   struct GNUNET_MQ_Envelope *env;
416   struct ClientPutMessage *pm;
417   const struct GSF_PendingRequestData *prd;
418
419   if (NULL == data)
420   {
421     /* local-only request, with no result, clean up. */
422     if (NULL == cr->kill_task)
423       cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy,
424                                                 cr);
425     return;
426   }
427   prd = GSF_pending_request_get_data_ (pr);
428   GNUNET_break (type != GNUNET_BLOCK_TYPE_ANY);
429   if ((prd->type != type) && (prd->type != GNUNET_BLOCK_TYPE_ANY))
430   {
431     GNUNET_break (0);
432     return;
433   }
434   GNUNET_STATISTICS_update (GSF_stats,
435                             gettext_noop
436                             ("# replies received for local clients"), 1,
437                             GNUNET_NO);
438   GNUNET_assert (pr == cr->pr);
439   lc = cr->lc;
440   env = GNUNET_MQ_msg_extra (pm,
441                              data_len,
442                              GNUNET_MESSAGE_TYPE_FS_PUT);
443   pm->type = htonl (type);
444   pm->expiration = GNUNET_TIME_absolute_hton (expiration);
445   pm->last_transmission = GNUNET_TIME_absolute_hton (last_transmission);
446   pm->num_transmissions = htonl (prd->num_transmissions);
447   pm->respect_offered = htonl (prd->respect_offered);
448   GNUNET_memcpy (&pm[1],
449                  data,
450                  data_len);
451   GNUNET_MQ_send (lc->mq,
452                   env);
453   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
454               "Queued reply to query `%s' for local client\n",
455               GNUNET_h2s (&prd->query));
456   if (GNUNET_BLOCK_EVALUATION_OK_LAST != eval)
457   {
458     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
459                 "Evaluation %d - keeping query alive\n",
460                 (int) eval);
461     return;
462   }
463   if (NULL == cr->kill_task)
464     cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy,
465                                               cr);
466 }
467
468
469 /**
470  * A client disconnected from us.  Tear down the local client
471  * record.
472  *
473  * @param cls unused
474  * @param client handle of the client
475  * @param app_ctx the `struct GSF_LocalClient`
476  */
477 static void
478 client_disconnect_cb (void *cls,
479                       struct GNUNET_SERVICE_Client *client,
480                       void *app_ctx)
481 {
482   struct GSF_LocalClient *lc = app_ctx;
483   struct IndexStartContext *isc;
484   struct ClientRequest *cr;
485   struct ClientResponse *res;
486
487   while (NULL != (cr = lc->cr_head))
488   {
489     if (NULL != cr->kill_task)
490       GNUNET_SCHEDULER_cancel (cr->kill_task);
491     client_request_destroy (cr);
492   }
493   while (NULL != (res = lc->res_head))
494   {
495     GNUNET_CONTAINER_DLL_remove (lc->res_head,
496                                  lc->res_tail,
497                                  res);
498     GNUNET_free (res);
499   }
500   while (NULL != (isc = lc->isc_head))
501   {
502     GNUNET_CONTAINER_DLL_remove (lc->isc_head,
503                                  lc->isc_tail,
504                                  isc);
505     GNUNET_CRYPTO_hash_file_cancel (isc->fhc);
506     GNUNET_free (isc);
507   }
508   GNUNET_free (lc);
509 }
510
511
512
513
514
515 /**
516  * Task that periodically ages our cover traffic statistics.
517  *
518  * @param cls unused closure
519  */
520 static void
521 age_cover_counters (void *cls)
522 {
523   GSF_cover_content_count = (GSF_cover_content_count * 15) / 16;
524   GSF_cover_query_count = (GSF_cover_query_count * 15) / 16;
525   cover_age_task =
526       GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY,
527                                     &age_cover_counters,
528                                     NULL);
529 }
530
531
532 /**
533  * We've just now completed a datastore request.  Update our
534  * datastore load calculations.
535  *
536  * @param start time when the datastore request was issued
537  */
538 void
539 GSF_update_datastore_delay_ (struct GNUNET_TIME_Absolute start)
540 {
541   struct GNUNET_TIME_Relative delay;
542
543   delay = GNUNET_TIME_absolute_get_duration (start);
544   GNUNET_LOAD_update (datastore_get_load, delay.rel_value_us);
545 }
546
547
548 /**
549  * Test if the DATABASE (GET) load on this peer is too high
550  * to even consider processing the query at
551  * all.
552  *
553  * @param priority priority of the request (used as a reference point to compare with the load)
554  * @return #GNUNET_YES if the load is too high to do anything (load high)
555  *         #GNUNET_NO to process normally (load normal)
556  *         #GNUNET_SYSERR to process for free (load low)
557  */
558 int
559 GSF_test_get_load_too_high_ (uint32_t priority)
560 {
561   double ld;
562
563   ld = GNUNET_LOAD_get_load (datastore_get_load);
564   if (ld < 1)
565     return GNUNET_SYSERR;
566   if (ld <= priority)
567     return GNUNET_NO;
568   return GNUNET_YES;
569 }
570
571
572 /**
573  * We've received peer performance information. Update
574  * our running average for the P2P latency.
575  *
576  * @param cls closure
577  * @param address the address
578  * @param active is this address in active use
579  * @param bandwidth_out assigned outbound bandwidth for the connection
580  * @param bandwidth_in assigned inbound bandwidth for the connection
581  * @param prop performance data for the address (as far as known)
582  */
583 static void
584 update_latencies (void *cls,
585                   const struct GNUNET_HELLO_Address *address,
586                   int active,
587                   struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
588                   struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
589                   const struct GNUNET_ATS_Properties *prop)
590 {
591   if (NULL == address)
592   {
593     /* ATS service temporarily disconnected */
594     return;
595   }
596
597   if (GNUNET_YES != active)
598     return;
599   GSF_update_peer_latency_ (&address->peer,
600                             prop->delay);
601   GSF_avg_latency.rel_value_us =
602     (GSF_avg_latency.rel_value_us * 31 +
603      GNUNET_MIN (5000, prop->delay.rel_value_us)) / 32;
604   GNUNET_STATISTICS_set (GSF_stats,
605                          gettext_noop ("# running average P2P latency (ms)"),
606                          GSF_avg_latency.rel_value_us / 1000LL,
607                          GNUNET_NO);
608 }
609
610
611 /**
612  * Check P2P "PUT" message.
613  *
614  * @param cls closure with the `struct GSF_ConnectedPeer`
615  * @param message the actual message
616  * @return #GNUNET_OK to keep the connection open,
617  *         #GNUNET_SYSERR to close it (signal serious error)
618  */
619 static int
620 check_p2p_put (void *cls,
621                const struct PutMessage *put)
622 {
623   enum GNUNET_BLOCK_Type type;
624
625   type = ntohl (put->type);
626   if (GNUNET_BLOCK_TYPE_FS_ONDEMAND == type)
627   {
628     GNUNET_break_op (0);
629     return GNUNET_SYSERR;
630   }
631   return GNUNET_OK;
632 }
633
634
635 /**
636  * We have a new request, consider forwarding it to the given
637  * peer.
638  *
639  * @param cls the `struct GSF_PendingRequest`
640  * @param peer identity of the peer
641  * @param cp handle to the connected peer record
642  * @param ppd peer performance data
643  */
644 static void
645 consider_request_for_forwarding (void *cls,
646                                  const struct GNUNET_PeerIdentity *peer,
647                                  struct GSF_ConnectedPeer *cp,
648                                  const struct GSF_PeerPerformanceData *ppd)
649 {
650   struct GSF_PendingRequest *pr = cls;
651
652   if (GNUNET_YES !=
653       GSF_pending_request_test_target_ (pr, peer))
654   {
655 #if INSANE_STATISTICS
656     GNUNET_STATISTICS_update (GSF_stats,
657                               gettext_noop ("# Loopback routes suppressed"), 1,
658                               GNUNET_NO);
659 #endif
660     return;
661   }
662   GSF_plan_add_ (cp,
663                  pr);
664 }
665
666
667 /**
668  * Function to be called after we're done processing
669  * replies from the local lookup.  If the result status
670  * code indicates that there may be more replies, plan
671  * forwarding the request.
672  *
673  * @param cls closure (NULL)
674  * @param pr the pending request we were processing
675  * @param result final datastore lookup result
676  */
677 void
678 GSF_consider_forwarding (void *cls,
679                          struct GSF_PendingRequest *pr,
680                          enum GNUNET_BLOCK_EvaluationResult result)
681 {
682   if (GNUNET_BLOCK_EVALUATION_OK_LAST == result)
683     return;                     /* we're done... */
684   if (GNUNET_YES !=
685       GSF_pending_request_test_active_ (pr))
686     return; /* request is not actually active, skip! */
687   GSF_iterate_connected_peers_ (&consider_request_for_forwarding,
688                                 pr);
689 }
690
691
692 /**
693  * Check P2P "GET" request.
694  *
695  * @param cls closure
696  * @param gm the actual message
697  * @return #GNUNET_OK to keep the connection open,
698  *         #GNUNET_SYSERR to close it (signal serious error)
699  */
700 static int
701 check_p2p_get (void *cls,
702                const struct GetMessage *gm)
703 {
704   size_t msize;
705   unsigned int bm;
706   unsigned int bits;
707   size_t bfsize;
708
709   msize = ntohs (gm->header.size);
710   bm = ntohl (gm->hash_bitmap);
711   bits = 0;
712   while (bm > 0)
713   {
714     if (1 == (bm & 1))
715       bits++;
716     bm >>= 1;
717   }
718   if (msize < sizeof (struct GetMessage) + bits * sizeof (struct GNUNET_PeerIdentity))
719   {
720     GNUNET_break_op (0);
721     return GNUNET_SYSERR;
722   }
723   bfsize = msize - sizeof (struct GetMessage) - bits * sizeof (struct GNUNET_PeerIdentity);
724   /* bfsize must be power of 2, check! */
725   if (0 != ((bfsize - 1) & bfsize))
726   {
727     GNUNET_break_op (0);
728     return GNUNET_SYSERR;
729   }
730   return GNUNET_OK;
731 }
732
733
734 /**
735  * We're done with the local lookup, now consider
736  * P2P processing (depending on request options and
737  * result status).  Also signal that we can now
738  * receive more request information from the client.
739  *
740  * @param cls the client doing the request (`struct GSF_LocalClient`)
741  * @param pr the pending request we were processing
742  * @param result final datastore lookup result
743  */
744 static void
745 start_p2p_processing (void *cls,
746                       struct GSF_PendingRequest *pr,
747                       enum GNUNET_BLOCK_EvaluationResult result)
748 {
749   struct GSF_LocalClient *lc = cls;
750   struct GSF_PendingRequestData *prd;
751
752   GNUNET_SERVICE_client_continue (lc->client);
753   if (GNUNET_BLOCK_EVALUATION_OK_LAST == result)
754     return;                     /* we're done, 'pr' was already destroyed... */
755   prd = GSF_pending_request_get_data_ (pr);
756   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
757               "Finished database lookup for local request `%s' with result %d\n",
758               GNUNET_h2s (&prd->query),
759               result);
760   if (0 == prd->anonymity_level)
761   {
762     switch (prd->type)
763     {
764     case GNUNET_BLOCK_TYPE_FS_DBLOCK:
765     case GNUNET_BLOCK_TYPE_FS_IBLOCK:
766       /* the above block types MAY be available via 'cadet' */
767       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
768                   "Considering cadet-based download for block\n");
769       GSF_cadet_lookup_ (pr);
770       break;
771     case GNUNET_BLOCK_TYPE_FS_UBLOCK:
772       /* the above block types are in the DHT */
773       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
774                   "Considering DHT-based search for block\n");
775       GSF_dht_lookup_ (pr);
776       break;
777     default:
778       GNUNET_break (0);
779       break;
780     }
781   }
782   GSF_consider_forwarding (NULL,
783                            pr,
784                            result);
785 }
786
787
788 /**
789  * Check #GNUNET_MESSAGE_TYPE_FS_START_SEARCH-message (search request
790  * from client).
791  *
792  * @param cls identification of the client
793  * @param sm the actual message
794  * @return #GNUNET_OK if @a sm is well-formed
795  */
796 static int
797 check_client_start_search (void *cls,
798                            const struct SearchMessage *sm)
799 {
800   uint16_t msize;
801
802   msize = ntohs (sm->header.size) - sizeof (struct SearchMessage);
803   if (0 != msize % sizeof (struct GNUNET_HashCode))
804   {
805     GNUNET_break (0);
806     return GNUNET_SYSERR;
807   }
808   return GNUNET_OK;
809 }
810
811
812 /**
813  * Handle #GNUNET_MESSAGE_TYPE_FS_START_SEARCH-message (search request
814  * from client).
815  *
816  * Responsible for creating the request entry itself and setting
817  * up reply callback and cancellation on client disconnect.
818  *
819  * @param cls identification of the client
820  * @param sm the actual message
821  */
822 static void
823 handle_client_start_search (void *cls,
824                             const struct SearchMessage *sm)
825 {
826   static struct GNUNET_PeerIdentity all_zeros;
827   struct GSF_LocalClient *lc = cls;
828   struct ClientRequest *cr;
829   struct GSF_PendingRequestData *prd;
830   uint16_t msize;
831   unsigned int sc;
832   enum GNUNET_BLOCK_Type type;
833   enum GSF_PendingRequestOptions options;
834
835   GNUNET_STATISTICS_update (GSF_stats,
836                             gettext_noop ("# client searches received"),
837                             1,
838                             GNUNET_NO);
839   msize = ntohs (sm->header.size) - sizeof (struct SearchMessage);
840   sc = msize / sizeof (struct GNUNET_HashCode);
841   type = ntohl (sm->type);
842   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
843               "Received request for `%s' of type %u from local client\n",
844               GNUNET_h2s (&sm->query),
845               (unsigned int) type);
846   cr = NULL;
847   /* detect duplicate UBLOCK requests */
848   if ((type == GNUNET_BLOCK_TYPE_FS_UBLOCK) ||
849       (type == GNUNET_BLOCK_TYPE_ANY))
850   {
851     cr = lc->cr_head;
852     while (NULL != cr)
853     {
854       prd = GSF_pending_request_get_data_ (cr->pr);
855       /* only unify with queries that hae not yet started local processing
856          (SEARCH_MESSAGE_OPTION_CONTINUED was always set) and that have a
857          matching query and type */
858       if ((GNUNET_YES != prd->has_started) &&
859           (0 != memcmp (&prd->query,
860                         &sm->query,
861                         sizeof (struct GNUNET_HashCode))) &&
862           (prd->type == type))
863         break;
864       cr = cr->next;
865     }
866   }
867   if (NULL != cr)
868   {
869     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
870                 "Have existing request, merging content-seen lists.\n");
871     GSF_pending_request_update_ (cr->pr,
872                                  (const struct GNUNET_HashCode *) &sm[1],
873                                  sc);
874     GNUNET_STATISTICS_update (GSF_stats,
875                               gettext_noop ("# client searches updated (merged content seen list)"),
876                               1,
877                               GNUNET_NO);
878   }
879   else
880   {
881     GNUNET_STATISTICS_update (GSF_stats,
882                               gettext_noop ("# client searches active"),
883                               1,
884                               GNUNET_NO);
885     cr = GNUNET_new (struct ClientRequest);
886     cr->lc = lc;
887     GNUNET_CONTAINER_DLL_insert (lc->cr_head,
888                                  lc->cr_tail,
889                                  cr);
890     options = GSF_PRO_LOCAL_REQUEST;
891     if (0 != (SEARCH_MESSAGE_OPTION_LOOPBACK_ONLY & ntohl (sm->options)))
892       options |= GSF_PRO_LOCAL_ONLY;
893     cr->pr = GSF_pending_request_create_ (options, type,
894                                           &sm->query,
895                                           (0 !=
896                                            memcmp (&sm->target,
897                                                    &all_zeros,
898                                                    sizeof (struct GNUNET_PeerIdentity)))
899                                           ? &sm->target : NULL, NULL, 0,
900                                           0 /* bf */ ,
901                                           ntohl (sm->anonymity_level),
902                                           0 /* priority */ ,
903                                           0 /* ttl */ ,
904                                           0 /* sender PID */ ,
905                                           0 /* origin PID */ ,
906                                           (const struct GNUNET_HashCode *) &sm[1], sc,
907                                           &client_response_handler,
908                                           cr);
909   }
910   if (0 != (SEARCH_MESSAGE_OPTION_CONTINUED & ntohl (sm->options)))
911   {
912     GNUNET_SERVICE_client_continue (lc->client);
913     return;
914   }
915   GSF_pending_request_get_data_ (cr->pr)->has_started = GNUNET_YES;
916   GSF_local_lookup_ (cr->pr,
917                      &start_p2p_processing,
918                      lc);
919 }
920
921
922 /**
923  * Handle request to sign a LOC URI (from client).
924  *
925  * @param cls identification of the client
926  * @param msg the actual message
927  */
928 static void
929 handle_client_loc_sign (void *cls,
930                         const struct RequestLocSignatureMessage *msg)
931 {
932   struct GSF_LocalClient *lc = cls;
933   struct GNUNET_FS_Uri base;
934   struct GNUNET_FS_Uri *loc;
935   struct GNUNET_MQ_Envelope *env;
936   struct ResponseLocSignatureMessage *resp;
937
938   GNUNET_break (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT ==
939                 ntohl (msg->purpose));
940   base.type = GNUNET_FS_URI_CHK;
941   base.data.chk.chk = msg->chk;
942   base.data.chk.file_length = GNUNET_ntohll (msg->file_length);
943   loc = GNUNET_FS_uri_loc_create (&base,
944                                   pk,
945                                   GNUNET_TIME_absolute_ntoh (msg->expiration_time));
946   env = GNUNET_MQ_msg (resp,
947                        GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGNATURE);
948   resp->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT);
949   resp->expiration_time = GNUNET_TIME_absolute_hton (loc->data.loc.expirationTime);
950   resp->signature = loc->data.loc.contentSignature;
951   resp->peer = loc->data.loc.peer;
952   GNUNET_FS_uri_destroy (loc);
953   GNUNET_MQ_send (lc->mq,
954                   env);
955   GNUNET_SERVICE_client_continue (lc->client);
956 }
957
958
959 /**
960  * Check INDEX_START-message.
961  *
962  * @param cls identification of the client
963  * @param ism the actual message
964  * @return #GNUNET_OK if @a ism is well-formed
965  */
966 static int
967 check_client_index_start (void *cls,
968                           const struct IndexStartMessage *ism)
969 {
970   char *fn;
971
972   GNUNET_MQ_check_zero_termination (ism);
973   if (0 != ism->reserved)
974   {
975     GNUNET_break (0);
976     return GNUNET_SYSERR;
977   }
978   fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]);
979   if (NULL == fn)
980   {
981     GNUNET_break (0);
982     return GNUNET_SYSERR;
983   }
984   GNUNET_free (fn);
985   return GNUNET_OK;
986 }
987
988
989 /**
990  * We've validated the hash of the file we're about to index.  Signal
991  * success to the client and update our internal data structures.
992  *
993  * @param isc the data about the index info entry for the request
994  */
995 static void
996 signal_index_ok (struct IndexStartContext *isc)
997 {
998   struct GSF_LocalClient *lc = isc->lc;
999   struct GNUNET_MQ_Envelope *env;
1000   struct GNUNET_MessageHeader *msg;
1001
1002   GNUNET_FS_add_to_index (isc->filename,
1003                           &isc->file_id);
1004   env = GNUNET_MQ_msg (msg,
1005                        GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
1006   GNUNET_MQ_send (lc->mq,
1007                   env);
1008   GNUNET_free (isc->filename);
1009   GNUNET_free (isc);
1010   GNUNET_SERVICE_client_continue (lc->client);
1011 }
1012
1013
1014 /**
1015  * Function called once the hash computation over an
1016  * indexed file has completed.
1017  *
1018  * @param cls closure, our publishing context
1019  * @param res resulting hash, NULL on error
1020  */
1021 static void
1022 hash_for_index_val (void *cls,
1023                     const struct GNUNET_HashCode *res)
1024 {
1025   struct IndexStartContext *isc = cls;
1026   struct GSF_LocalClient *lc = isc->lc;
1027   struct GNUNET_MQ_Envelope *env;
1028   struct GNUNET_MessageHeader *msg;
1029
1030   GNUNET_CONTAINER_DLL_remove (lc->isc_head,
1031                                lc->isc_tail,
1032                                isc);
1033   isc->fhc = NULL;
1034   if ( (NULL == res) ||
1035        (0 != memcmp (res,
1036                      &isc->file_id,
1037                      sizeof (struct GNUNET_HashCode))))
1038   {
1039     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1040                 _("Hash mismatch trying to index file `%s' which does not have hash `%s'\n"),
1041                 isc->filename,
1042                 GNUNET_h2s (&isc->file_id));
1043     env = GNUNET_MQ_msg (msg,
1044                          GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED);
1045     GNUNET_MQ_send (lc->mq,
1046                     env);
1047     GNUNET_SERVICE_client_continue (lc->client);
1048     GNUNET_free (isc);
1049     return;
1050   }
1051   signal_index_ok (isc);
1052 }
1053
1054
1055 /**
1056  * Handle INDEX_START-message.
1057  *
1058  * @param cls identification of the client
1059  * @param message the actual message
1060  */
1061 static void
1062 handle_client_index_start (void *cls,
1063                            const struct IndexStartMessage *ism)
1064 {
1065   struct GSF_LocalClient *lc = cls;
1066   struct IndexStartContext *isc;
1067   char *fn;
1068   uint64_t dev;
1069   uint64_t ino;
1070   uint64_t mydev;
1071   uint64_t myino;
1072
1073   fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]);
1074   GNUNET_assert (NULL != fn);
1075   dev = GNUNET_ntohll (ism->device);
1076   ino = GNUNET_ntohll (ism->inode);
1077   isc = GNUNET_new (struct IndexStartContext);
1078   isc->filename = fn;
1079   isc->file_id = ism->file_id;
1080   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1081               "Received START_INDEX message for file `%s'\n",
1082               isc->filename);
1083   isc->lc = lc;
1084   mydev = 0;
1085   myino = 0;
1086   if ( ( (dev != 0) ||
1087          (ino != 0) ) &&
1088        (GNUNET_OK == GNUNET_DISK_file_get_identifiers (fn,
1089                                                        &mydev,
1090                                                        &myino)) &&
1091        (dev == mydev) &&
1092        (ino == myino) )
1093   {
1094     /* fast validation OK! */
1095     signal_index_ok (isc);
1096     return;
1097   }
1098   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1099               "Mismatch in file identifiers (%llu != %llu or %u != %u), need to hash.\n",
1100               (unsigned long long) ino,
1101               (unsigned long long) myino,
1102               (unsigned int) dev,
1103               (unsigned int) mydev);
1104   /* slow validation, need to hash full file (again) */
1105   GNUNET_CONTAINER_DLL_insert (lc->isc_head,
1106                                lc->isc_tail,
1107                                isc);
1108   isc->fhc = GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE,
1109                                       isc->filename,
1110                                       HASHING_BLOCKSIZE,
1111                                       &hash_for_index_val,
1112                                       isc);
1113   if (NULL == isc->fhc)
1114     hash_for_index_val (isc,
1115                         NULL);
1116 }
1117
1118
1119 /**
1120  * Handle INDEX_LIST_GET-message.
1121  *
1122  * @param cls closure
1123  * @param message the actual message
1124  */
1125 static void
1126 handle_client_index_list_get (void *cls,
1127                               const struct GNUNET_MessageHeader *message)
1128 {
1129   struct GSF_LocalClient *lc = cls;
1130
1131   GNUNET_FS_indexing_send_list (lc->mq);
1132   GNUNET_SERVICE_client_continue (lc->client);
1133 }
1134
1135
1136 /**
1137  * Handle UNINDEX-message.
1138  *
1139  * @param cls identification of the client
1140  * @param message the actual message
1141  */
1142 static void
1143 handle_client_unindex (void *cls,
1144                        const struct UnindexMessage *um)
1145 {
1146   struct GSF_LocalClient *lc = cls;
1147   struct GNUNET_MQ_Envelope *env;
1148   struct GNUNET_MessageHeader *msg;
1149   int found;
1150
1151   GNUNET_break (0 == um->reserved);
1152   found = GNUNET_FS_indexing_do_unindex (&um->file_id);
1153   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1154               "Client requested unindexing of file `%s': %s\n",
1155               GNUNET_h2s (&um->file_id),
1156               found ? "found" : "not found");
1157   env = GNUNET_MQ_msg (msg,
1158                        GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK);
1159   GNUNET_MQ_send (lc->mq,
1160                   env);
1161   GNUNET_SERVICE_client_continue (lc->client);
1162 }
1163
1164
1165 /**
1166  * Task run during shutdown.
1167  *
1168  * @param cls unused
1169  */
1170 static void
1171 shutdown_task (void *cls)
1172 {
1173   GSF_cadet_stop_server ();
1174   if (NULL != GSF_core)
1175   {
1176     GNUNET_CORE_disconnect (GSF_core);
1177     GSF_core = NULL;
1178   }
1179   if (NULL != GSF_ats)
1180   {
1181     GNUNET_ATS_performance_done (GSF_ats);
1182     GSF_ats = NULL;
1183   }
1184   GSF_put_done_ ();
1185   GSF_push_done_ ();
1186   GSF_pending_request_done_ ();
1187   GSF_plan_done ();
1188   GSF_connected_peer_done_ ();
1189   GNUNET_DATASTORE_disconnect (GSF_dsh,
1190                                GNUNET_NO);
1191   GSF_dsh = NULL;
1192   GNUNET_DHT_disconnect (GSF_dht);
1193   GSF_dht = NULL;
1194   GNUNET_BLOCK_context_destroy (GSF_block_ctx);
1195   GSF_block_ctx = NULL;
1196   GNUNET_CONFIGURATION_destroy (block_cfg);
1197   block_cfg = NULL;
1198   GNUNET_STATISTICS_destroy (GSF_stats, GNUNET_NO);
1199   GSF_stats = NULL;
1200   if (NULL != cover_age_task)
1201   {
1202     GNUNET_SCHEDULER_cancel (cover_age_task);
1203     cover_age_task = NULL;
1204   }
1205   GNUNET_FS_indexing_done ();
1206   GNUNET_LOAD_value_free (datastore_get_load);
1207   datastore_get_load = NULL;
1208   GNUNET_LOAD_value_free (GSF_rt_entry_lifetime);
1209   GSF_rt_entry_lifetime = NULL;
1210 }
1211
1212
1213 /**
1214  * Function called after GNUNET_CORE_connect has succeeded
1215  * (or failed for good).  Note that the private key of the
1216  * peer is intentionally not exposed here; if you need it,
1217  * your process should try to read the private key file
1218  * directly (which should work if you are authorized...).
1219  *
1220  * @param cls closure
1221  * @param my_identity ID of this peer, NULL if we failed
1222  */
1223 static void
1224 peer_init_handler (void *cls,
1225                    const struct GNUNET_PeerIdentity *my_identity)
1226 {
1227   if (0 != GNUNET_memcmp (&GSF_my_id,
1228                                             my_identity))
1229   {
1230     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1231                 "Peer identity mismatch, refusing to start!\n");
1232     GNUNET_SCHEDULER_shutdown ();
1233   }
1234 }
1235
1236
1237 /**
1238  * Process fs requests.
1239  *
1240  * @param c configuration to use
1241  */
1242 static int
1243 main_init (const struct GNUNET_CONFIGURATION_Handle *c)
1244 {
1245   struct GNUNET_MQ_MessageHandler no_p2p_handlers[] = {
1246     GNUNET_MQ_handler_end ()
1247   };
1248   struct GNUNET_MQ_MessageHandler p2p_handlers[] = {
1249     GNUNET_MQ_hd_var_size (p2p_get,
1250                            GNUNET_MESSAGE_TYPE_FS_GET,
1251                            struct GetMessage,
1252                            NULL),
1253     GNUNET_MQ_hd_var_size (p2p_put,
1254                            GNUNET_MESSAGE_TYPE_FS_PUT,
1255                            struct PutMessage,
1256                            NULL),
1257     GNUNET_MQ_hd_fixed_size (p2p_migration_stop,
1258                              GNUNET_MESSAGE_TYPE_FS_MIGRATION_STOP,
1259                              struct MigrationStopMessage,
1260                              NULL),
1261     GNUNET_MQ_handler_end ()
1262   };
1263   int anon_p2p_off;
1264   char *keyfile;
1265
1266   /* this option is really only for testcases that need to disable
1267      _anonymous_ file-sharing for some reason */
1268   anon_p2p_off = (GNUNET_YES ==
1269                   GNUNET_CONFIGURATION_get_value_yesno (GSF_cfg,
1270                                                         "fs",
1271                                                         "DISABLE_ANON_TRANSFER"));
1272
1273   if (GNUNET_OK !=
1274       GNUNET_CONFIGURATION_get_value_filename (GSF_cfg,
1275                                                "PEER",
1276                                                "PRIVATE_KEY",
1277                                                &keyfile))
1278   {
1279     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1280                 _("FS service is lacking HOSTKEY configuration setting.  Exiting.\n"));
1281     GNUNET_SCHEDULER_shutdown ();
1282     return GNUNET_SYSERR;
1283   }
1284   pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile);
1285   GNUNET_free (keyfile);
1286   GNUNET_assert (NULL != pk);
1287   GNUNET_CRYPTO_eddsa_key_get_public (pk,
1288                                       &GSF_my_id.public_key);
1289
1290   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1291               "I am peer %s\n",
1292               GNUNET_i2s (&GSF_my_id));
1293   GSF_core
1294     = GNUNET_CORE_connect (GSF_cfg,
1295                            NULL,
1296                            &peer_init_handler,
1297                            &GSF_peer_connect_handler,
1298                            &GSF_peer_disconnect_handler,
1299                            (GNUNET_YES == anon_p2p_off)
1300                            ? no_p2p_handlers
1301                            : p2p_handlers);
1302   if (NULL == GSF_core)
1303   {
1304     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1305                 _("Failed to connect to `%s' service.\n"),
1306                 "core");
1307     return GNUNET_SYSERR;
1308   }
1309   cover_age_task =
1310       GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY,
1311                                     &age_cover_counters,
1312                                     NULL);
1313   datastore_get_load = GNUNET_LOAD_value_init (DATASTORE_LOAD_AUTODECLINE);
1314   GSF_cadet_start_server ();
1315   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1316                                  NULL);
1317   return GNUNET_OK;
1318 }
1319
1320
1321 /**
1322  * Process fs requests.
1323  *
1324  * @param cls closure
1325  * @param cfg configuration to use
1326  * @param service the initialized service
1327  */
1328 static void
1329 run (void *cls,
1330      const struct GNUNET_CONFIGURATION_Handle *cfg,
1331      struct GNUNET_SERVICE_Handle *service)
1332 {
1333   unsigned long long dqs;
1334
1335   GSF_cfg = cfg;
1336   if (GNUNET_OK !=
1337       GNUNET_CONFIGURATION_get_value_size (GSF_cfg,
1338                                            "fs",
1339                                            "DATASTORE_QUEUE_SIZE",
1340                                            &dqs))
1341   {
1342     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO,
1343                                "fs",
1344                                "DATASTORE_QUEUE_SIZE");
1345     dqs = 32;
1346   }
1347   GSF_datastore_queue_size = (unsigned int) dqs;
1348   GSF_enable_randomized_delays =
1349       GNUNET_CONFIGURATION_get_value_yesno (cfg, "fs", "DELAY");
1350   GSF_dsh = GNUNET_DATASTORE_connect (cfg);
1351   if (NULL == GSF_dsh)
1352   {
1353     GNUNET_SCHEDULER_shutdown ();
1354     return;
1355   }
1356   GSF_rt_entry_lifetime = GNUNET_LOAD_value_init (GNUNET_TIME_UNIT_FOREVER_REL);
1357   GSF_stats = GNUNET_STATISTICS_create ("fs", cfg);
1358   block_cfg = GNUNET_CONFIGURATION_create ();
1359   GSF_block_ctx = GNUNET_BLOCK_context_create (block_cfg);
1360   GNUNET_assert (NULL != GSF_block_ctx);
1361   GSF_dht = GNUNET_DHT_connect (cfg, FS_DHT_HT_SIZE);
1362   GSF_plan_init ();
1363   GSF_pending_request_init_ ();
1364   GSF_connected_peer_init_ ();
1365   GSF_ats = GNUNET_ATS_performance_init (GSF_cfg,
1366                                          &update_latencies,
1367                                          NULL);
1368   GSF_push_init_ ();
1369   GSF_put_init_ ();
1370   if ( (GNUNET_OK != GNUNET_FS_indexing_init (cfg,
1371                                               GSF_dsh)) ||
1372        (GNUNET_OK != main_init (cfg)) )
1373   {
1374     GNUNET_SCHEDULER_shutdown ();
1375     shutdown_task (NULL);
1376     return;
1377   }
1378 }
1379
1380
1381 /**
1382  * Define "main" method using service macro.
1383  */
1384 GNUNET_SERVICE_MAIN
1385 ("fs",
1386  GNUNET_SERVICE_OPTION_NONE,
1387  &run,
1388  &client_connect_cb,
1389  &client_disconnect_cb,
1390  NULL,
1391  GNUNET_MQ_hd_var_size (client_index_start,
1392                         GNUNET_MESSAGE_TYPE_FS_INDEX_START,
1393                         struct IndexStartMessage,
1394                         NULL),
1395  GNUNET_MQ_hd_fixed_size (client_index_list_get,
1396                           GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET,
1397                           struct GNUNET_MessageHeader,
1398                           NULL),
1399  GNUNET_MQ_hd_fixed_size (client_unindex,
1400                           GNUNET_MESSAGE_TYPE_FS_UNINDEX,
1401                           struct UnindexMessage,
1402                           NULL),
1403  GNUNET_MQ_hd_var_size (client_start_search,
1404                         GNUNET_MESSAGE_TYPE_FS_START_SEARCH,
1405                         struct SearchMessage,
1406                         NULL),
1407  GNUNET_MQ_hd_fixed_size (client_loc_sign,
1408                           GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGN,
1409                           struct RequestLocSignatureMessage,
1410                           NULL),
1411  GNUNET_MQ_handler_end ());
1412
1413
1414 /* end of gnunet-service-fs.c */