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