~ubuntu-branches/ubuntu/trusty/gnunet/trusty

« back to all changes in this revision

Viewing changes to src/fs/gnunet-service-fs.c

  • Committer: Package Import Robot
  • Author(s): Bertrand Marc
  • Date: 2012-05-06 00:28:20 UTC
  • mfrom: (1.2.17)
  • Revision ID: package-import@ubuntu.com-20120506002820-n02u1ginv8pjh0ee
Tags: 0.9.2-1
* New maintainer (Closes: #660438).
* New upstream release (Closes: #621645).
* Remove debian/patches, not necessary any more.
* Update dependencies, according to README:
  + update minimal versions. 
  + depends on libunistring-dev.
  + depends on libltdl-dev instead of libltdl3-dev.
  + no need to depend on libgtk anymore.
  + gnunet-server suggests miniupnpc.
* debian/rules:
  + no need to define LOGFILE and PIDFILE.
  + create a minimal conf file.
  + cut gnunet-download-manager.scm extension.
  + remove autogenerated files in clean.
* Gnunet is now released under the GPL v3.
* Standards version 3.9.3.
* Add debian/watch.
* Adding Italian debconf translations, thanks to Beatrice Torracca
  (Closes: #663432).
* Move to dh-autoreconf and add extend-diff-ignore in debian/source/options.
* Remove gnunet-tools since gnunet-setup is not part of gnunet anymore
  (Closes:#651192).
* gnunet-server.init:
  + several services are now supervised by gnunet-service-arm.
  + define the logfile at run time.
* Use a secured group gnunetdns for SUID binaries and change permissions
  accordingly, see https://gnunet.org/gnunet-access-control-model
* gnunet-server.postinst, gnunet-server.postrm: use dpkg-statoverride to set
  and remove setuid permissions.
* Remove properly the old incompatible /etc/gnunetd.conf, use
  /etc/gnunet.conf instead.
* Add minimal (generic) man pages when information is available.
* Remove dpkg options for compression.
* gnunet-server.docs: add README.mysql and README.postgres.
* debian/rules: remove template binaries after dh_install.
* debian/copyright:
  + use copyright format 1.0.
  + mention AUTHORS and translators.
  + use GPL-3+ when possible.
  + add a paragraph for two files distributed under MIT/X11.
* Use dh_installdocs --link-doc to avoid redundancy.
* Remove unused debian/gnunet-dev.lintian-overrides.
* debian/control: add Vcs-git and Vcs-browser fields.
* gnunet-server.postrm:
  + use debconf to determine which user and group to delete.
  + remove /var/lib/gnunet on purge.
  + remove /etc/default/gnunet-server on purge (Closes: #668766).
* Make gnunet-dbg dependencies alternatives as it provides debugging
  symbol for all of them.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
     This file is part of GNUnet.
 
3
     (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
 
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., 59 Temple Place - Suite 330,
 
18
     Boston, MA 02111-1307, USA.
 
19
*/
 
20
 
 
21
/**
 
22
 * @file fs/gnunet-service-fs.c
 
23
 * @brief gnunet anonymity protocol implementation
 
24
 * @author Christian Grothoff
 
25
 *
 
26
 * To use:
 
27
 * - consider re-issue GSF_dht_lookup_ after non-DHT reply received
 
28
 */
 
29
#include "platform.h"
 
30
#include <float.h>
 
31
#include "gnunet_constants.h"
 
32
#include "gnunet_core_service.h"
 
33
#include "gnunet_dht_service.h"
 
34
#include "gnunet_datastore_service.h"
 
35
#include "gnunet_load_lib.h"
 
36
#include "gnunet_peer_lib.h"
 
37
#include "gnunet_protocols.h"
 
38
#include "gnunet_signatures.h"
 
39
#include "gnunet_statistics_service.h"
 
40
#include "gnunet_transport_service.h"
 
41
#include "gnunet_util_lib.h"
 
42
#include "gnunet-service-fs_cp.h"
 
43
#include "gnunet-service-fs_indexing.h"
 
44
#include "gnunet-service-fs_lc.h"
 
45
#include "gnunet-service-fs_pe.h"
 
46
#include "gnunet-service-fs_pr.h"
 
47
#include "gnunet-service-fs_push.h"
 
48
#include "gnunet-service-fs_put.h"
 
49
#include "fs.h"
 
50
 
 
51
/**
 
52
 * Size for the hash map for DHT requests from the FS
 
53
 * service.  Should be about the number of concurrent
 
54
 * DHT requests we plan to make.
 
55
 */
 
56
#define FS_DHT_HT_SIZE 1024
 
57
 
 
58
 
 
59
/**
 
60
 * How quickly do we age cover traffic?  At the given
 
61
 * time interval, remaining cover traffic counters are
 
62
 * decremented by 1/16th.
 
63
 */
 
64
#define COVER_AGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
 
65
 
 
66
 
 
67
/* ****************************** globals ****************************** */
 
68
 
 
69
/**
 
70
 * Our connection to the datastore.
 
71
 */
 
72
struct GNUNET_DATASTORE_Handle *GSF_dsh;
 
73
 
 
74
/**
 
75
 * Our configuration.
 
76
 */
 
77
const struct GNUNET_CONFIGURATION_Handle *GSF_cfg;
 
78
 
 
79
/**
 
80
 * Handle for reporting statistics.
 
81
 */
 
82
struct GNUNET_STATISTICS_Handle *GSF_stats;
 
83
 
 
84
/**
 
85
 * Handle for DHT operations.
 
86
 */
 
87
struct GNUNET_DHT_Handle *GSF_dht;
 
88
 
 
89
/**
 
90
 * How long do requests typically stay in the routing table?
 
91
 */
 
92
struct GNUNET_LOAD_Value *GSF_rt_entry_lifetime;
 
93
 
 
94
/**
 
95
 * Running average of the observed latency to other peers (round trip).
 
96
 * Initialized to 5s as the initial default.
 
97
 */
 
98
struct GNUNET_TIME_Relative GSF_avg_latency = { 500 };
 
99
 
 
100
/**
 
101
 * Typical priorities we're seeing from other peers right now.  Since
 
102
 * most priorities will be zero, this value is the weighted average of
 
103
 * non-zero priorities seen "recently".  In order to ensure that new
 
104
 * values do not dramatically change the ratio, values are first
 
105
 * "capped" to a reasonable range (+N of the current value) and then
 
106
 * averaged into the existing value by a ratio of 1:N.  Hence
 
107
 * receiving the largest possible priority can still only raise our
 
108
 * "current_priorities" by at most 1.
 
109
 */
 
110
double GSF_current_priorities;
 
111
 
 
112
/**
 
113
 * How many query messages have we received 'recently' that
 
114
 * have not yet been claimed as cover traffic?
 
115
 */
 
116
unsigned int GSF_cover_query_count;
 
117
 
 
118
/**
 
119
 * How many content messages have we received 'recently' that
 
120
 * have not yet been claimed as cover traffic?
 
121
 */
 
122
unsigned int GSF_cover_content_count;
 
123
 
 
124
/**
 
125
 * Our block context.
 
126
 */
 
127
struct GNUNET_BLOCK_Context *GSF_block_ctx;
 
128
 
 
129
/**
 
130
 * Pointer to handle to the core service (points to NULL until we've
 
131
 * connected to it).
 
132
 */
 
133
struct GNUNET_CORE_Handle *GSF_core;
 
134
 
 
135
/**
 
136
 * Are we introducing randomized delays for better anonymity?
 
137
 */
 
138
int GSF_enable_randomized_delays;
 
139
 
 
140
/* ***************************** locals ******************************* */
 
141
 
 
142
/**
 
143
 * Configuration for block library.
 
144
 */
 
145
static struct GNUNET_CONFIGURATION_Handle *block_cfg;
 
146
 
 
147
/**
 
148
 * ID of our task that we use to age the cover counters.
 
149
 */
 
150
static GNUNET_SCHEDULER_TaskIdentifier cover_age_task;
 
151
 
 
152
/**
 
153
 * Datastore 'GET' load tracking.
 
154
 */
 
155
static struct GNUNET_LOAD_Value *datastore_get_load;
 
156
 
 
157
/**
 
158
 * Identity of this peer.
 
159
 */
 
160
static struct GNUNET_PeerIdentity my_id;
 
161
 
 
162
/**
 
163
 * Task that periodically ages our cover traffic statistics.
 
164
 *
 
165
 * @param cls unused closure
 
166
 * @param tc task context
 
167
 */
 
168
static void
 
169
age_cover_counters (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
170
{
 
171
  GSF_cover_content_count = (GSF_cover_content_count * 15) / 16;
 
172
  GSF_cover_query_count = (GSF_cover_query_count * 15) / 16;
 
173
  cover_age_task =
 
174
      GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY, &age_cover_counters,
 
175
                                    NULL);
 
176
}
 
177
 
 
178
 
 
179
/**
 
180
 * We've just now completed a datastore request.  Update our
 
181
 * datastore load calculations.
 
182
 *
 
183
 * @param start time when the datastore request was issued
 
184
 */
 
185
void
 
186
GSF_update_datastore_delay_ (struct GNUNET_TIME_Absolute start)
 
187
{
 
188
  struct GNUNET_TIME_Relative delay;
 
189
 
 
190
  delay = GNUNET_TIME_absolute_get_duration (start);
 
191
  GNUNET_LOAD_update (datastore_get_load, delay.rel_value);
 
192
}
 
193
 
 
194
 
 
195
/**
 
196
 * Test if the DATABASE (GET) load on this peer is too high
 
197
 * to even consider processing the query at
 
198
 * all.
 
199
 *
 
200
 * @return GNUNET_YES if the load is too high to do anything (load high)
 
201
 *         GNUNET_NO to process normally (load normal)
 
202
 *         GNUNET_SYSERR to process for free (load low)
 
203
 */
 
204
int
 
205
GSF_test_get_load_too_high_ (uint32_t priority)
 
206
{
 
207
  double ld;
 
208
 
 
209
  ld = GNUNET_LOAD_get_load (datastore_get_load);
 
210
  if (ld < 1)
 
211
    return GNUNET_SYSERR;
 
212
  if (ld <= priority)
 
213
    return GNUNET_NO;
 
214
  return GNUNET_YES;
 
215
}
 
216
 
 
217
 
 
218
/**
 
219
 * We've received peer performance information. Update
 
220
 * our running average for the P2P latency.
 
221
 *
 
222
 * @param atsi performance information
 
223
 * @param atsi_count number of 'atsi' records
 
224
 */
 
225
static void
 
226
update_latencies (const struct GNUNET_ATS_Information *atsi,
 
227
                  unsigned int atsi_count)
 
228
{
 
229
  unsigned int i;
 
230
 
 
231
  for (i = 0; i < atsi_count; i++)
 
232
  {
 
233
    if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DELAY)
 
234
    {
 
235
      GSF_avg_latency.rel_value =
 
236
          (GSF_avg_latency.rel_value * 31 +
 
237
           GNUNET_MIN (5000, ntohl (atsi[i].value))) / 32;
 
238
      GNUNET_STATISTICS_set (GSF_stats,
 
239
                             gettext_noop
 
240
                             ("# running average P2P latency (ms)"),
 
241
                             GSF_avg_latency.rel_value, GNUNET_NO);
 
242
      break;
 
243
    }
 
244
  }
 
245
}
 
246
 
 
247
 
 
248
/**
 
249
 * Handle P2P "PUT" message.
 
250
 *
 
251
 * @param cls closure, always NULL
 
252
 * @param other the other peer involved (sender or receiver, NULL
 
253
 *        for loopback messages where we are both sender and receiver)
 
254
 * @param message the actual message
 
255
 * @param atsi performance information
 
256
 * @param atsi_count number of records in 'atsi'
 
257
 * @return GNUNET_OK to keep the connection open,
 
258
 *         GNUNET_SYSERR to close it (signal serious error)
 
259
 */
 
260
static int
 
261
handle_p2p_put (void *cls, const struct GNUNET_PeerIdentity *other,
 
262
                const struct GNUNET_MessageHeader *message,
 
263
                const struct GNUNET_ATS_Information *atsi,
 
264
                unsigned int atsi_count)
 
265
{
 
266
  struct GSF_ConnectedPeer *cp;
 
267
 
 
268
  cp = GSF_peer_get_ (other);
 
269
  if (NULL == cp)
 
270
  {
 
271
    GNUNET_break (0);
 
272
    return GNUNET_OK;
 
273
  }
 
274
  GSF_cover_content_count++;
 
275
  update_latencies (atsi, atsi_count);
 
276
  return GSF_handle_p2p_content_ (cp, message);
 
277
}
 
278
 
 
279
 
 
280
/**
 
281
 * We have a new request, consider forwarding it to the given
 
282
 * peer.
 
283
 *
 
284
 * @param cls the 'struct GSF_PendingRequest'
 
285
 * @param peer identity of the peer
 
286
 * @param cp handle to the connected peer record
 
287
 * @param ppd peer performance data
 
288
 */
 
289
static void
 
290
consider_request_for_forwarding (void *cls,
 
291
                                 const struct GNUNET_PeerIdentity *peer,
 
292
                                 struct GSF_ConnectedPeer *cp,
 
293
                                 const struct GSF_PeerPerformanceData *ppd)
 
294
{
 
295
  struct GSF_PendingRequest *pr = cls;
 
296
 
 
297
  if (GNUNET_YES != GSF_pending_request_test_target_ (pr, peer))
 
298
  {
 
299
    GNUNET_STATISTICS_update (GSF_stats,
 
300
                              gettext_noop ("# Loopback routes suppressed"), 1,
 
301
                              GNUNET_NO);
 
302
    return;
 
303
  }
 
304
  GSF_plan_add_ (cp, pr);
 
305
}
 
306
 
 
307
 
 
308
/**
 
309
 * Function to be called after we're done processing
 
310
 * replies from the local lookup.  If the result status
 
311
 * code indicates that there may be more replies, plan
 
312
 * forwarding the request.
 
313
 *
 
314
 * @param cls closure (NULL)
 
315
 * @param pr the pending request we were processing
 
316
 * @param result final datastore lookup result
 
317
 */
 
318
static void
 
319
consider_forwarding (void *cls, struct GSF_PendingRequest *pr,
 
320
                     enum GNUNET_BLOCK_EvaluationResult result)
 
321
{
 
322
  if (GNUNET_BLOCK_EVALUATION_OK_LAST == result)
 
323
    return;                     /* we're done... */
 
324
  GSF_iterate_connected_peers_ (&consider_request_for_forwarding, pr);
 
325
}
 
326
 
 
327
 
 
328
/**
 
329
 * Handle P2P "GET" request.
 
330
 *
 
331
 * @param cls closure, always NULL
 
332
 * @param other the other peer involved (sender or receiver, NULL
 
333
 *        for loopback messages where we are both sender and receiver)
 
334
 * @param message the actual message
 
335
 * @param atsi performance information
 
336
 * @param atsi_count number of records in 'atsi'
 
337
 * @return GNUNET_OK to keep the connection open,
 
338
 *         GNUNET_SYSERR to close it (signal serious error)
 
339
 */
 
340
static int
 
341
handle_p2p_get (void *cls, const struct GNUNET_PeerIdentity *other,
 
342
                const struct GNUNET_MessageHeader *message,
 
343
                const struct GNUNET_ATS_Information *atsi,
 
344
                unsigned int atsi_count)
 
345
{
 
346
  struct GSF_PendingRequest *pr;
 
347
 
 
348
  pr = GSF_handle_p2p_query_ (other, message);
 
349
  if (NULL == pr)
 
350
    return GNUNET_SYSERR;
 
351
  GSF_pending_request_get_data_ (pr)->has_started = GNUNET_YES;
 
352
  GSF_local_lookup_ (pr, &consider_forwarding, NULL);
 
353
  update_latencies (atsi, atsi_count);
 
354
  return GNUNET_OK;
 
355
}
 
356
 
 
357
 
 
358
/**
 
359
 * We're done with the local lookup, now consider
 
360
 * P2P processing (depending on request options and
 
361
 * result status).  Also signal that we can now
 
362
 * receive more request information from the client.
 
363
 *
 
364
 * @param cls the client doing the request ('struct GNUNET_SERVER_Client')
 
365
 * @param pr the pending request we were processing
 
366
 * @param result final datastore lookup result
 
367
 */
 
368
static void
 
369
start_p2p_processing (void *cls, struct GSF_PendingRequest *pr,
 
370
                      enum GNUNET_BLOCK_EvaluationResult result)
 
371
{
 
372
  struct GNUNET_SERVER_Client *client = cls;
 
373
  struct GSF_PendingRequestData *prd;
 
374
 
 
375
  prd = GSF_pending_request_get_data_ (pr);
 
376
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
 
377
              "Finished database lookup for local request `%s' with result %d\n",
 
378
              GNUNET_h2s (&prd->query), result);
 
379
  GNUNET_SERVER_receive_done (client, GNUNET_OK);
 
380
  if (GNUNET_BLOCK_EVALUATION_OK_LAST == result)
 
381
    return;                     /* we're done, 'pr' was already destroyed... */
 
382
  if (0 != (GSF_PRO_LOCAL_ONLY & prd->options))
 
383
  {
 
384
    GSF_pending_request_cancel_ (pr, GNUNET_YES);
 
385
    return;
 
386
  }
 
387
  GSF_dht_lookup_ (pr);
 
388
  consider_forwarding (NULL, pr, result);
 
389
}
 
390
 
 
391
 
 
392
/**
 
393
 * Handle START_SEARCH-message (search request from client).
 
394
 *
 
395
 * @param cls closure
 
396
 * @param client identification of the client
 
397
 * @param message the actual message
 
398
 */
 
399
static void
 
400
handle_start_search (void *cls, struct GNUNET_SERVER_Client *client,
 
401
                     const struct GNUNET_MessageHeader *message)
 
402
{
 
403
  struct GSF_PendingRequest *pr;
 
404
  int ret;
 
405
 
 
406
  pr = NULL;
 
407
  ret = GSF_local_client_start_search_handler_ (client, message, &pr);
 
408
  switch (ret)
 
409
  {
 
410
  case GNUNET_SYSERR:
 
411
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
 
412
    break;
 
413
  case GNUNET_NO:
 
414
    GNUNET_SERVER_receive_done (client, GNUNET_OK);
 
415
    break;
 
416
  case GNUNET_YES:
 
417
    GSF_pending_request_get_data_ (pr)->has_started = GNUNET_YES;
 
418
    GSF_local_lookup_ (pr, &start_p2p_processing, client);
 
419
    break;
 
420
  default:
 
421
    GNUNET_assert (0);
 
422
  }
 
423
}
 
424
 
 
425
 
 
426
/**
 
427
 * Task run during shutdown.
 
428
 *
 
429
 * @param cls unused
 
430
 * @param tc unused
 
431
 */
 
432
static void
 
433
shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
434
{
 
435
  if (NULL != GSF_core)
 
436
  {
 
437
    GNUNET_CORE_disconnect (GSF_core);
 
438
    GSF_core = NULL;
 
439
  }
 
440
  GSF_put_done_ ();
 
441
  GSF_push_done_ ();
 
442
  GSF_pending_request_done_ ();
 
443
  GSF_plan_done ();
 
444
  GSF_connected_peer_done_ ();
 
445
  GNUNET_DATASTORE_disconnect (GSF_dsh, GNUNET_NO);
 
446
  GSF_dsh = NULL;
 
447
  GNUNET_DHT_disconnect (GSF_dht);
 
448
  GSF_dht = NULL;
 
449
  GNUNET_BLOCK_context_destroy (GSF_block_ctx);
 
450
  GSF_block_ctx = NULL;
 
451
  GNUNET_CONFIGURATION_destroy (block_cfg);
 
452
  block_cfg = NULL;
 
453
  GNUNET_STATISTICS_destroy (GSF_stats, GNUNET_NO);
 
454
  GSF_stats = NULL;
 
455
  if (GNUNET_SCHEDULER_NO_TASK != cover_age_task)
 
456
  {
 
457
    GNUNET_SCHEDULER_cancel (cover_age_task);
 
458
    cover_age_task = GNUNET_SCHEDULER_NO_TASK;
 
459
  }
 
460
  GNUNET_FS_indexing_done ();
 
461
  GNUNET_LOAD_value_free (datastore_get_load);
 
462
  datastore_get_load = NULL;
 
463
  GNUNET_LOAD_value_free (GSF_rt_entry_lifetime);
 
464
  GSF_rt_entry_lifetime = NULL;
 
465
}
 
466
 
 
467
 
 
468
/**
 
469
 * Function called for each pending request whenever a new
 
470
 * peer connects, giving us a chance to decide about submitting
 
471
 * the existing request to the new peer.
 
472
 *
 
473
 * @param cls the 'struct GSF_ConnectedPeer' of the new peer
 
474
 * @param key query for the request
 
475
 * @param pr handle to the pending request
 
476
 * @return GNUNET_YES to continue to iterate
 
477
 */
 
478
static int
 
479
consider_peer_for_forwarding (void *cls, const GNUNET_HashCode * key,
 
480
                              struct GSF_PendingRequest *pr)
 
481
{
 
482
  struct GSF_ConnectedPeer *cp = cls;
 
483
  struct GNUNET_PeerIdentity pid;
 
484
 
 
485
  GSF_connected_peer_get_identity_ (cp, &pid);
 
486
  if (GNUNET_YES != GSF_pending_request_test_target_ (pr, &pid))
 
487
  {
 
488
    GNUNET_STATISTICS_update (GSF_stats,
 
489
                              gettext_noop ("# Loopback routes suppressed"), 1,
 
490
                              GNUNET_NO);
 
491
    return GNUNET_YES;
 
492
  }
 
493
  GSF_plan_add_ (cp, pr);
 
494
  return GNUNET_YES;
 
495
}
 
496
 
 
497
 
 
498
/**
 
499
 * Method called whenever a given peer connects.
 
500
 *
 
501
 * @param cls closure, not used
 
502
 * @param peer peer identity this notification is about
 
503
 * @param atsi performance information
 
504
 * @param atsi_count number of records in 'atsi'
 
505
 */
 
506
static void
 
507
peer_connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer,
 
508
                      const struct GNUNET_ATS_Information *atsi,
 
509
                      unsigned int atsi_count)
 
510
{
 
511
  struct GSF_ConnectedPeer *cp;
 
512
 
 
513
  if (0 == memcmp (&my_id, peer, sizeof (struct GNUNET_PeerIdentity)))
 
514
    return;
 
515
  cp = GSF_peer_connect_handler_ (peer, atsi, atsi_count);
 
516
  if (NULL == cp)
 
517
    return;
 
518
  GSF_iterate_pending_requests_ (&consider_peer_for_forwarding, cp);
 
519
}
 
520
 
 
521
 
 
522
/**
 
523
 * Function called after GNUNET_CORE_connect has succeeded
 
524
 * (or failed for good).  Note that the private key of the
 
525
 * peer is intentionally not exposed here; if you need it,
 
526
 * your process should try to read the private key file
 
527
 * directly (which should work if you are authorized...).
 
528
 *
 
529
 * @param cls closure
 
530
 * @param server handle to the server, NULL if we failed
 
531
 * @param my_identity ID of this peer, NULL if we failed
 
532
 */
 
533
static void
 
534
peer_init_handler (void *cls, struct GNUNET_CORE_Handle *server,
 
535
                   const struct GNUNET_PeerIdentity *my_identity)
 
536
{
 
537
  my_id = *my_identity;
 
538
}
 
539
 
 
540
 
 
541
/**
 
542
 * Process fs requests.
 
543
 *
 
544
 * @param server the initialized server
 
545
 * @param c configuration to use
 
546
 */
 
547
static int
 
548
main_init (struct GNUNET_SERVER_Handle *server,
 
549
           const struct GNUNET_CONFIGURATION_Handle *c)
 
550
{
 
551
  static const struct GNUNET_CORE_MessageHandler p2p_handlers[] = {
 
552
    {&handle_p2p_get,
 
553
     GNUNET_MESSAGE_TYPE_FS_GET, 0},
 
554
    {&handle_p2p_put,
 
555
     GNUNET_MESSAGE_TYPE_FS_PUT, 0},
 
556
    {&GSF_handle_p2p_migration_stop_,
 
557
     GNUNET_MESSAGE_TYPE_FS_MIGRATION_STOP,
 
558
     sizeof (struct MigrationStopMessage)},
 
559
    {NULL, 0, 0}
 
560
  };
 
561
  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
 
562
    {&GNUNET_FS_handle_index_start, NULL,
 
563
     GNUNET_MESSAGE_TYPE_FS_INDEX_START, 0},
 
564
    {&GNUNET_FS_handle_index_list_get, NULL,
 
565
     GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET,
 
566
     sizeof (struct GNUNET_MessageHeader)},
 
567
    {&GNUNET_FS_handle_unindex, NULL, GNUNET_MESSAGE_TYPE_FS_UNINDEX,
 
568
     sizeof (struct UnindexMessage)},
 
569
    {&handle_start_search, NULL, GNUNET_MESSAGE_TYPE_FS_START_SEARCH,
 
570
     0},
 
571
    {NULL, NULL, 0, 0}
 
572
  };
 
573
 
 
574
  GSF_core =
 
575
      GNUNET_CORE_connect (GSF_cfg, 1, NULL, &peer_init_handler,
 
576
                           &peer_connect_handler, &GSF_peer_disconnect_handler_,
 
577
                           NULL, GNUNET_NO, NULL, GNUNET_NO, p2p_handlers);
 
578
  if (NULL == GSF_core)
 
579
  {
 
580
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
 
581
                _("Failed to connect to `%s' service.\n"), "core");
 
582
    return GNUNET_SYSERR;
 
583
  }
 
584
  GNUNET_SERVER_disconnect_notify (server, &GSF_client_disconnect_handler_,
 
585
                                   NULL);
 
586
  GNUNET_SERVER_add_handlers (server, handlers);
 
587
  cover_age_task =
 
588
      GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY, &age_cover_counters,
 
589
                                    NULL);
 
590
  datastore_get_load = GNUNET_LOAD_value_init (DATASTORE_LOAD_AUTODECLINE);
 
591
  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
 
592
                                NULL);
 
593
  return GNUNET_OK;
 
594
}
 
595
 
 
596
 
 
597
/**
 
598
 * Process fs requests.
 
599
 *
 
600
 * @param cls closure
 
601
 * @param server the initialized server
 
602
 * @param cfg configuration to use
 
603
 */
 
604
static void
 
605
run (void *cls, struct GNUNET_SERVER_Handle *server,
 
606
     const struct GNUNET_CONFIGURATION_Handle *cfg)
 
607
{
 
608
  GSF_cfg = cfg;
 
609
  GSF_enable_randomized_delays =
 
610
      GNUNET_CONFIGURATION_get_value_yesno (cfg, "fs", "DELAY");
 
611
  GSF_dsh = GNUNET_DATASTORE_connect (cfg);
 
612
  if (NULL == GSF_dsh)
 
613
  {
 
614
    GNUNET_SCHEDULER_shutdown ();
 
615
    return;
 
616
  }
 
617
  GSF_rt_entry_lifetime = GNUNET_LOAD_value_init (GNUNET_TIME_UNIT_FOREVER_REL);
 
618
  GSF_stats = GNUNET_STATISTICS_create ("fs", cfg);
 
619
  block_cfg = GNUNET_CONFIGURATION_create ();
 
620
  GNUNET_CONFIGURATION_set_value_string (block_cfg, "block", "PLUGINS", "fs");
 
621
  GSF_block_ctx = GNUNET_BLOCK_context_create (block_cfg);
 
622
  GNUNET_assert (NULL != GSF_block_ctx);
 
623
  GSF_dht = GNUNET_DHT_connect (cfg, FS_DHT_HT_SIZE);
 
624
  GSF_plan_init ();
 
625
  GSF_pending_request_init_ ();
 
626
  GSF_connected_peer_init_ ();
 
627
  GSF_push_init_ ();
 
628
  GSF_put_init_ ();
 
629
  if ((GNUNET_OK != GNUNET_FS_indexing_init (cfg, GSF_dsh)) ||
 
630
      (GNUNET_OK != main_init (server, cfg)))
 
631
  {
 
632
    GNUNET_SCHEDULER_shutdown ();
 
633
    shutdown_task (NULL, NULL);
 
634
    return;
 
635
  }
 
636
}
 
637
 
 
638
 
 
639
/**
 
640
 * The main function for the fs service.
 
641
 *
 
642
 * @param argc number of arguments from the command line
 
643
 * @param argv command line arguments
 
644
 * @return 0 ok, 1 on error
 
645
 */
 
646
int
 
647
main (int argc, char *const *argv)
 
648
{
 
649
  return (GNUNET_OK ==
 
650
          GNUNET_SERVICE_run (argc, argv, "fs", GNUNET_SERVICE_OPTION_NONE,
 
651
                              &run, NULL)) ? 0 : 1;
 
652
}
 
653
 
 
654
/* end of gnunet-service-fs.c */