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