Merge branch 'master' of ssh://gnunet.org/gnunet
[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
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
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   uint16_t msize;
971   char *fn;
972
973   msize = ntohs (ism->header.size);
974   if (((const char *) ism)[msize - 1] != '\0')
975   {
976     GNUNET_break (0);
977     return GNUNET_SYSERR;
978   }
979   if (0 != ism->reserved)
980   {
981     GNUNET_break (0);
982     return GNUNET_SYSERR;
983   }
984   fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]);
985   if (NULL == fn)
986   {
987     GNUNET_break (0);
988     return GNUNET_SYSERR;
989   }
990   GNUNET_free (fn);
991   return GNUNET_OK;
992 }
993
994
995 /**
996  * We've validated the hash of the file we're about to index.  Signal
997  * success to the client and update our internal data structures.
998  *
999  * @param isc the data about the index info entry for the request
1000  */
1001 static void
1002 signal_index_ok (struct IndexStartContext *isc)
1003 {
1004   struct GSF_LocalClient *lc = isc->lc;
1005   struct GNUNET_MQ_Envelope *env;
1006   struct GNUNET_MessageHeader *msg;
1007
1008   GNUNET_FS_add_to_index (isc->filename,
1009                           &isc->file_id);
1010   env = GNUNET_MQ_msg (msg,
1011                        GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
1012   GNUNET_MQ_send (lc->mq,
1013                   env);
1014   GNUNET_free (isc->filename);
1015   GNUNET_free (isc);
1016   GNUNET_SERVICE_client_continue (lc->client);
1017 }
1018
1019
1020 /**
1021  * Function called once the hash computation over an
1022  * indexed file has completed.
1023  *
1024  * @param cls closure, our publishing context
1025  * @param res resulting hash, NULL on error
1026  */
1027 static void
1028 hash_for_index_val (void *cls,
1029                     const struct GNUNET_HashCode *res)
1030 {
1031   struct IndexStartContext *isc = cls;
1032   struct GSF_LocalClient *lc = isc->lc;
1033   struct GNUNET_MQ_Envelope *env;
1034   struct GNUNET_MessageHeader *msg;
1035
1036   GNUNET_CONTAINER_DLL_remove (lc->isc_head,
1037                                lc->isc_tail,
1038                                isc);
1039   isc->fhc = NULL;
1040   if ( (NULL == res) ||
1041        (0 != memcmp (res,
1042                      &isc->file_id,
1043                      sizeof (struct GNUNET_HashCode))))
1044   {
1045     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1046                 _("Hash mismatch trying to index file `%s' which does not have hash `%s'\n"),
1047                 isc->filename,
1048                 GNUNET_h2s (&isc->file_id));
1049     env = GNUNET_MQ_msg (msg,
1050                          GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED);
1051     GNUNET_MQ_send (lc->mq,
1052                     env);
1053     GNUNET_SERVICE_client_continue (lc->client);
1054     GNUNET_free (isc);
1055     return;
1056   }
1057   signal_index_ok (isc);
1058 }
1059
1060
1061 /**
1062  * Handle INDEX_START-message.
1063  *
1064  * @param cls identification of the client
1065  * @param message the actual message
1066  */
1067 static void
1068 handle_client_index_start (void *cls,
1069                            const struct IndexStartMessage *ism)
1070 {
1071   struct GSF_LocalClient *lc = cls;
1072   struct IndexStartContext *isc;
1073   char *fn;
1074   uint64_t dev;
1075   uint64_t ino;
1076   uint64_t mydev;
1077   uint64_t myino;
1078
1079   fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]);
1080   GNUNET_assert (NULL != fn);
1081   dev = GNUNET_ntohll (ism->device);
1082   ino = GNUNET_ntohll (ism->inode);
1083   isc = GNUNET_new (struct IndexStartContext);
1084   isc->filename = fn;
1085   isc->file_id = ism->file_id;
1086   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1087               "Received START_INDEX message for file `%s'\n",
1088               isc->filename);
1089   isc->lc = lc;
1090   mydev = 0;
1091   myino = 0;
1092   if ( ( (dev != 0) ||
1093          (ino != 0) ) &&
1094        (GNUNET_OK == GNUNET_DISK_file_get_identifiers (fn,
1095                                                        &mydev,
1096                                                        &myino)) &&
1097        (dev == mydev) &&
1098        (ino == myino) )
1099   {
1100     /* fast validation OK! */
1101     signal_index_ok (isc);
1102     return;
1103   }
1104   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105               "Mismatch in file identifiers (%llu != %llu or %u != %u), need to hash.\n",
1106               (unsigned long long) ino,
1107               (unsigned long long) myino,
1108               (unsigned int) dev,
1109               (unsigned int) mydev);
1110   /* slow validation, need to hash full file (again) */
1111   GNUNET_CONTAINER_DLL_insert (lc->isc_head,
1112                                lc->isc_tail,
1113                                isc);
1114   isc->fhc = GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE,
1115                                       isc->filename,
1116                                       HASHING_BLOCKSIZE,
1117                                       &hash_for_index_val,
1118                                       isc);
1119   if (NULL == isc->fhc)
1120     hash_for_index_val (isc,
1121                         NULL);
1122 }
1123
1124
1125 /**
1126  * Handle INDEX_LIST_GET-message.
1127  *
1128  * @param cls closure
1129  * @param message the actual message
1130  */
1131 static void
1132 handle_client_index_list_get (void *cls,
1133                               const struct GNUNET_MessageHeader *message)
1134 {
1135   struct GSF_LocalClient *lc = cls;
1136
1137   GNUNET_FS_indexing_send_list (lc->mq);
1138   GNUNET_SERVICE_client_continue (lc->client);
1139 }
1140
1141
1142 /**
1143  * Handle UNINDEX-message.
1144  *
1145  * @param cls identification of the client
1146  * @param message the actual message
1147  */
1148 static void
1149 handle_client_unindex (void *cls,
1150                        const struct UnindexMessage *um)
1151 {
1152   struct GSF_LocalClient *lc = cls;
1153   struct GNUNET_MQ_Envelope *env;
1154   struct GNUNET_MessageHeader *msg;
1155   int found;
1156
1157   GNUNET_break (0 == um->reserved);
1158   found = GNUNET_FS_indexing_do_unindex (&um->file_id);
1159   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1160               "Client requested unindexing of file `%s': %s\n",
1161               GNUNET_h2s (&um->file_id),
1162               found ? "found" : "not found");
1163   env = GNUNET_MQ_msg (msg,
1164                        GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK);
1165   GNUNET_MQ_send (lc->mq,
1166                   env);
1167   GNUNET_SERVICE_client_continue (lc->client);
1168 }
1169
1170
1171 /**
1172  * Task run during shutdown.
1173  *
1174  * @param cls unused
1175  */
1176 static void
1177 shutdown_task (void *cls)
1178 {
1179   GSF_cadet_stop_server ();
1180   if (NULL != GSF_core)
1181   {
1182     GNUNET_CORE_disconnect (GSF_core);
1183     GSF_core = NULL;
1184   }
1185   if (NULL != GSF_ats)
1186   {
1187     GNUNET_ATS_performance_done (GSF_ats);
1188     GSF_ats = NULL;
1189   }
1190   GSF_put_done_ ();
1191   GSF_push_done_ ();
1192   GSF_pending_request_done_ ();
1193   GSF_plan_done ();
1194   GSF_connected_peer_done_ ();
1195   GNUNET_DATASTORE_disconnect (GSF_dsh,
1196                                GNUNET_NO);
1197   GSF_dsh = NULL;
1198   GNUNET_DHT_disconnect (GSF_dht);
1199   GSF_dht = NULL;
1200   GNUNET_BLOCK_context_destroy (GSF_block_ctx);
1201   GSF_block_ctx = NULL;
1202   GNUNET_CONFIGURATION_destroy (block_cfg);
1203   block_cfg = NULL;
1204   GNUNET_STATISTICS_destroy (GSF_stats, GNUNET_NO);
1205   GSF_stats = NULL;
1206   if (NULL != cover_age_task)
1207   {
1208     GNUNET_SCHEDULER_cancel (cover_age_task);
1209     cover_age_task = NULL;
1210   }
1211   GNUNET_FS_indexing_done ();
1212   GNUNET_LOAD_value_free (datastore_get_load);
1213   datastore_get_load = NULL;
1214   GNUNET_LOAD_value_free (GSF_rt_entry_lifetime);
1215   GSF_rt_entry_lifetime = NULL;
1216 }
1217
1218
1219 /**
1220  * Function called after GNUNET_CORE_connect has succeeded
1221  * (or failed for good).  Note that the private key of the
1222  * peer is intentionally not exposed here; if you need it,
1223  * your process should try to read the private key file
1224  * directly (which should work if you are authorized...).
1225  *
1226  * @param cls closure
1227  * @param my_identity ID of this peer, NULL if we failed
1228  */
1229 static void
1230 peer_init_handler (void *cls,
1231                    const struct GNUNET_PeerIdentity *my_identity)
1232 {
1233   if (0 != GNUNET_CRYPTO_cmp_peer_identity (&GSF_my_id,
1234                                             my_identity))
1235   {
1236     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1237                 "Peer identity missmatch, refusing to start!\n");
1238     GNUNET_SCHEDULER_shutdown ();
1239   }
1240 }
1241
1242
1243 /**
1244  * Process fs requests.
1245  *
1246  * @param c configuration to use
1247  */
1248 static int
1249 main_init (const struct GNUNET_CONFIGURATION_Handle *c)
1250 {
1251   struct GNUNET_MQ_MessageHandler no_p2p_handlers[] = {
1252     GNUNET_MQ_handler_end ()
1253   };
1254   struct GNUNET_MQ_MessageHandler p2p_handlers[] = {
1255     GNUNET_MQ_hd_var_size (p2p_get,
1256                            GNUNET_MESSAGE_TYPE_FS_GET,
1257                            struct GetMessage,
1258                            NULL),
1259     GNUNET_MQ_hd_var_size (p2p_put,
1260                            GNUNET_MESSAGE_TYPE_FS_PUT,
1261                            struct PutMessage,
1262                            NULL),
1263     GNUNET_MQ_hd_fixed_size (p2p_migration_stop,
1264                              GNUNET_MESSAGE_TYPE_FS_MIGRATION_STOP,
1265                              struct MigrationStopMessage,
1266                              NULL),
1267     GNUNET_MQ_handler_end ()
1268   };
1269   int anon_p2p_off;
1270   char *keyfile;
1271
1272   /* this option is really only for testcases that need to disable
1273      _anonymous_ file-sharing for some reason */
1274   anon_p2p_off = (GNUNET_YES ==
1275                   GNUNET_CONFIGURATION_get_value_yesno (GSF_cfg,
1276                                                         "fs",
1277                                                         "DISABLE_ANON_TRANSFER"));
1278
1279   if (GNUNET_OK !=
1280       GNUNET_CONFIGURATION_get_value_filename (GSF_cfg,
1281                                                "PEER",
1282                                                "PRIVATE_KEY",
1283                                                &keyfile))
1284   {
1285     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1286                 _("FS service is lacking HOSTKEY configuration setting.  Exiting.\n"));
1287     GNUNET_SCHEDULER_shutdown ();
1288     return GNUNET_SYSERR;
1289   }
1290   pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile);
1291   GNUNET_free (keyfile);
1292   GNUNET_assert (NULL != pk);
1293   GNUNET_CRYPTO_eddsa_key_get_public (pk,
1294                                       &GSF_my_id.public_key);
1295
1296   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1297               "I am peer %s\n",
1298               GNUNET_i2s (&GSF_my_id));
1299   GSF_core
1300     = GNUNET_CORE_connect (GSF_cfg,
1301                            NULL,
1302                            &peer_init_handler,
1303                            &GSF_peer_connect_handler,
1304                            &GSF_peer_disconnect_handler,
1305                            (GNUNET_YES == anon_p2p_off)
1306                            ? no_p2p_handlers
1307                            : p2p_handlers);
1308   if (NULL == GSF_core)
1309   {
1310     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1311                 _("Failed to connect to `%s' service.\n"),
1312                 "core");
1313     return GNUNET_SYSERR;
1314   }
1315   cover_age_task =
1316       GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY,
1317                                     &age_cover_counters,
1318                                     NULL);
1319   datastore_get_load = GNUNET_LOAD_value_init (DATASTORE_LOAD_AUTODECLINE);
1320   GSF_cadet_start_server ();
1321   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1322                                  NULL);
1323   return GNUNET_OK;
1324 }
1325
1326
1327 /**
1328  * Process fs requests.
1329  *
1330  * @param cls closure
1331  * @param cfg configuration to use
1332  * @param service the initialized service
1333  */
1334 static void
1335 run (void *cls,
1336      const struct GNUNET_CONFIGURATION_Handle *cfg,
1337      struct GNUNET_SERVICE_Handle *service)
1338 {
1339   unsigned long long dqs;
1340
1341   GSF_cfg = cfg;
1342   if (GNUNET_OK !=
1343       GNUNET_CONFIGURATION_get_value_size (GSF_cfg,
1344                                            "fs",
1345                                            "DATASTORE_QUEUE_SIZE",
1346                                            &dqs))
1347   {
1348     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO,
1349                                "fs",
1350                                "DATASTORE_QUEUE_SIZE");
1351     dqs = 32;
1352   }
1353   GSF_datastore_queue_size = (unsigned int) dqs;
1354   GSF_enable_randomized_delays =
1355       GNUNET_CONFIGURATION_get_value_yesno (cfg, "fs", "DELAY");
1356   GSF_dsh = GNUNET_DATASTORE_connect (cfg);
1357   if (NULL == GSF_dsh)
1358   {
1359     GNUNET_SCHEDULER_shutdown ();
1360     return;
1361   }
1362   GSF_rt_entry_lifetime = GNUNET_LOAD_value_init (GNUNET_TIME_UNIT_FOREVER_REL);
1363   GSF_stats = GNUNET_STATISTICS_create ("fs", cfg);
1364   block_cfg = GNUNET_CONFIGURATION_create ();
1365   GSF_block_ctx = GNUNET_BLOCK_context_create (block_cfg);
1366   GNUNET_assert (NULL != GSF_block_ctx);
1367   GSF_dht = GNUNET_DHT_connect (cfg, FS_DHT_HT_SIZE);
1368   GSF_plan_init ();
1369   GSF_pending_request_init_ ();
1370   GSF_connected_peer_init_ ();
1371   GSF_ats = GNUNET_ATS_performance_init (GSF_cfg,
1372                                          &update_latencies,
1373                                          NULL);
1374   GSF_push_init_ ();
1375   GSF_put_init_ ();
1376   if ( (GNUNET_OK != GNUNET_FS_indexing_init (cfg,
1377                                               GSF_dsh)) ||
1378        (GNUNET_OK != main_init (cfg)) )
1379   {
1380     GNUNET_SCHEDULER_shutdown ();
1381     shutdown_task (NULL);
1382     return;
1383   }
1384 }
1385
1386
1387 /**
1388  * Define "main" method using service macro.
1389  */
1390 GNUNET_SERVICE_MAIN
1391 ("fs",
1392  GNUNET_SERVICE_OPTION_NONE,
1393  &run,
1394  &client_connect_cb,
1395  &client_disconnect_cb,
1396  NULL,
1397  GNUNET_MQ_hd_var_size (client_index_start,
1398                         GNUNET_MESSAGE_TYPE_FS_INDEX_START,
1399                         struct IndexStartMessage,
1400                         NULL),
1401  GNUNET_MQ_hd_fixed_size (client_index_list_get,
1402                           GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET,
1403                           struct GNUNET_MessageHeader,
1404                           NULL),
1405  GNUNET_MQ_hd_fixed_size (client_unindex,
1406                           GNUNET_MESSAGE_TYPE_FS_UNINDEX,
1407                           struct UnindexMessage,
1408                           NULL),
1409  GNUNET_MQ_hd_var_size (client_start_search,
1410                         GNUNET_MESSAGE_TYPE_FS_START_SEARCH,
1411                         struct SearchMessage,
1412                         NULL),
1413  GNUNET_MQ_hd_fixed_size (client_loc_sign,
1414                           GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGN,
1415                           struct RequestLocSignatureMessage,
1416                           NULL),
1417  GNUNET_MQ_handler_end ());
1418
1419
1420 /* end of gnunet-service-fs.c */