aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO56
-rw-r--r--contrib/defaults.conf12
-rw-r--r--src/core/core_api.c4
-rw-r--r--src/fs/fs.h177
-rw-r--r--src/fs/gnunet-service-fs.c1617
-rw-r--r--src/include/gnunet_bio_lib.h2
-rw-r--r--src/include/gnunet_constants.h11
-rw-r--r--src/include/gnunet_core_service.h3
-rw-r--r--src/include/gnunet_protocols.h12
9 files changed, 1648 insertions, 246 deletions
diff --git a/TODO b/TODO
index e37e66739..5cacc1603 100644
--- a/TODO
+++ b/TODO
@@ -12,36 +12,14 @@ away), in order in which they will likely be done:
12* MySQL / Postgres plugins (datastore, datacache) 12* MySQL / Postgres plugins (datastore, datacache)
13* UPNP 13* UPNP
14 14
15
16Urgent items (before announcing ng.gnunet.org): 15Urgent items (before announcing ng.gnunet.org):
17* TESTING (needed for DV, DHT, Topology)
18 - implement library for local testing
19 + modify configuration to allow controlling
20 connections for non-local starts
21 + CORE service does not start with valid peer ID (all zeros)
22 -- testcase fails!
23 + consider changing API for peer-group termination
24 to call continuation when done
25 + testbed creation with topology (needs working F2F topology) [Nate]
26 + testbed with churn [Nate]
27 - implement testcases for library
28 + get test for basic peer start to work!
29 + test basic peer connect
30 + test group start
31 + test basic peer re-configure [Nate]
32 + test topology creation [Nate]
33 + test churn generation [Nate]
34* TOPOLOGY:
35 - implement testcases (needs TESTING)
36* HOSTLIST:
37 - implement testcases
38* FS (basic anonymous FS only) 16* FS (basic anonymous FS only)
39 - design network structs (P2P) 17 - need way to determine network load (up/down)
40 + query 18 - need *fast* way to check/update trust in peers
41 + response 19 (async peerinfo would not be right)
42 - implement FS service 20 - implement FS service
43 + CS-functions (query BF, on-demand encoding, indexed-list serialization/deserialization) 21 + P2P-functions (query, response, peer-disconnect)
44 + P2P-functions (query, response) 22 + CS/P2P-functions (initiate P2P, handle P2P->CS)
45 - implement testcases 23 - implement testcases
46 + URI API 24 + URI API
47 + getopt API 25 + getopt API
@@ -52,6 +30,18 @@ Urgent items (before announcing ng.gnunet.org):
52 ~ search 30 ~ search
53 ~ unindex 31 ~ unindex
54 + directory API 32 + directory API
33* TESTING (needed for DV, DHT, Topology)
34 - implement library for local testing
35 + modify configuration to allow controlling connections for non-local starts
36 + CORE service does not start with valid peer ID (all zeros) -- testcase fails!
37 + consider changing API for peer-group termination to call continuation when done
38 - implement testcases for library
39 + get test for basic peer start to work!
40 + test basic peer connect
41 + test group start
42* TEST:
43 - topology (needs TESTING)
44 - hostlist (maybe easier with TESTING?)
55* new webpage 45* new webpage
56 - prevent? 46 - prevent?
57 - migrate Mantis!? 47 - migrate Mantis!?
@@ -64,9 +54,8 @@ Urgent items (before announcing ng.gnunet.org):
640.9.0pre0: 540.9.0pre0:
65* Module features to implement: 55* Module features to implement:
66 - advanced FS API parts 56 - advanced FS API parts
67 + namespaces 57 + namespaces: fundamental namespace API
68 ~ fundamental namespace API 58 + search: SBlocks, KSBlocks, probes, notify FS-service of known results
69 + search: SBlocks, KSBlocks, probes
70 + collection 59 + collection
71 + location URIs (publish, search, download) 60 + location URIs (publish, search, download)
72 + persistence support (publish, unindex, search, download) 61 + persistence support (publish, unindex, search, download)
@@ -79,6 +68,8 @@ Urgent items (before announcing ng.gnunet.org):
79 + gnunet-download (many options) 68 + gnunet-download (many options)
80 + gnunet-directory (man page, options) 69 + gnunet-directory (man page, options)
81 + gnunet-pseudonym (all of it) 70 + gnunet-pseudonym (all of it)
71 + gnunet-service-fs (remove failing on-demand blocks)
72 + datastore: do active migration support here?
82 - implement adv. FS testcases 73 - implement adv. FS testcases
83 + insert: sblocks, loc uris 74 + insert: sblocks, loc uris
84 + download: loc uris 75 + download: loc uris
@@ -98,8 +89,13 @@ Urgent items (before announcing ng.gnunet.org):
98 + default generation 89 + default generation
99 + need to settle basic design; do we want to keep guile? 90 + need to settle basic design; do we want to keep guile?
100 - testing (RC-pre0) 91 - testing (RC-pre0)
92 + testbed creation with topology (needs working F2F topology) [Nate]
93 + testbed with churn [Nate]
101 + implement library for distributed testing [Nate] 94 + implement library for distributed testing [Nate]
102 + implement testcases for distributed testing [Nate] 95 + implement testcases for distributed testing [Nate]
96 + test basic peer re-configure [Nate]
97 + test topology creation [Nate]
98 + test churn generation [Nate]
103 99
1040.9.0pre1: 1000.9.0pre1:
105* Module features to implement: 101* Module features to implement:
diff --git a/contrib/defaults.conf b/contrib/defaults.conf
index 0af2752fb..1f3f5c5a4 100644
--- a/contrib/defaults.conf
+++ b/contrib/defaults.conf
@@ -177,3 +177,15 @@ DATABASE = sqlite
177 177
178[datastore-sqlite] 178[datastore-sqlite]
179FILENAME = $SERVICEHOME/datastore/sqlite.db 179FILENAME = $SERVICEHOME/datastore/sqlite.db
180
181[fs]
182INDEXDB = $SERVICEHOME/idxinfo.lst
183PORT = 2094
184HOSTNAME = localhost
185HOME = $SERVICEHOME
186CONFIG = $DEFAULTCONFIG
187BINARY = gnunet-service-fs
188ACCEPT_FROM = 127.0.0.1;
189ACCEPT_FROM6 = ::1;
190ALLOW_SHUTDOWN = YES
191
diff --git a/src/core/core_api.c b/src/core/core_api.c
index 6aca88640..05f34ec27 100644
--- a/src/core/core_api.c
+++ b/src/core/core_api.c
@@ -550,8 +550,8 @@ main_handler (void *cls, const struct GNUNET_MessageHeader *msg)
550 GNUNET_TIME_relative_ntoh (cim->latency), 550 GNUNET_TIME_relative_ntoh (cim->latency),
551 (int) ntohl (cim->reserved_amount), 551 (int) ntohl (cim->reserved_amount),
552 cim->preference); 552 cim->preference);
553 /* done, clean up! */ 553 /* done, clean up! */
554 GNUNET_CORE_notify_transmit_ready_cancel (h->submitted); 554 GNUNET_CORE_notify_transmit_ready_cancel (h->submitted); // HUH?
555 trigger_next_request (h); 555 trigger_next_request (h);
556 break; 556 break;
557 case GNUNET_MESSAGE_TYPE_CORE_SOLICIT_TRAFFIC: 557 case GNUNET_MESSAGE_TYPE_CORE_SOLICIT_TRAFFIC:
diff --git a/src/fs/fs.h b/src/fs/fs.h
index c2a2e7d03..002ffb6b3 100644
--- a/src/fs/fs.h
+++ b/src/fs/fs.h
@@ -26,6 +26,7 @@
26#ifndef FS_H 26#ifndef FS_H
27#define FS_H 27#define FS_H
28 28
29#include "gnunet_constants.h"
29#include "gnunet_datastore_service.h" 30#include "gnunet_datastore_service.h"
30#include "gnunet_fs_service.h" 31#include "gnunet_fs_service.h"
31 32
@@ -61,6 +62,63 @@
61 */ 62 */
62#define HASHING_BLOCKSIZE (1024 * 1024) 63#define HASHING_BLOCKSIZE (1024 * 1024)
63 64
65/**
66 * Number of bits we set per entry in the bloomfilter.
67 * Do not change!
68 */
69#define BLOOMFILTER_K 16
70
71/**
72 * By how much (in ms) do we decrement the TTL
73 * at each hop?
74 */
75#define TTL_DECREMENT 5000
76
77/**
78 * How long are we willing to wait for the datastore to be ready to
79 * process a request for a query without priority?
80 */
81#define BASIC_DATASTORE_REQUEST_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
82
83
84/**
85 * How long are we willing to wait for the core to be ready to
86 * transmit a reply to the target peer (if we can not transmit
87 * until then, we will discard the reply).
88 */
89#define ACCEPTABLE_REPLY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
90
91
92/**
93 * Bandwidth value of an (effectively) 0-priority query.
94 */
95#define QUERY_BANDWIDTH_VALUE 0.001
96
97/**
98 * Bandwidth value of a 0-priority content (must be
99 * fairly high compared to query since content is
100 * typically significantly larger -- and more valueable
101 * since it can take many queries to get one piece of
102 * content).
103 */
104#define CONTENT_BANDWIDTH_VALUE 0.8
105
106/**
107 * By which amount do we decrement the TTL for simple forwarding /
108 * indirection of the query; in milli-seconds. Set somewhat in
109 * accordance to your network latency (above the time it'll take you
110 * to send a packet and get a reply).
111 */
112#define TTL_DECREMENT 5000
113
114/**
115 * Until which load do we consider the peer idle and do not
116 * charge at all? (should be larger than GNUNET_IDLE_LOAD_THRESHOLD used
117 * by the rest of the code)!
118 */
119#define IDLE_LOAD_THRESHOLD ((100 + GNUNET_CONSTANTS_IDLE_LOAD_THRESHOLD) / 2)
120
121
64 122
65/** 123/**
66 * @brief content hash key 124 * @brief content hash key
@@ -1209,7 +1267,12 @@ struct SearchMessage
1209 * SBLOCKS (aka query). 1267 * SBLOCKS (aka query).
1210 */ 1268 */
1211 GNUNET_HashCode query; 1269 GNUNET_HashCode query;
1212 1270
1271 /* this is followed by the hash codes of already-known
1272 results (which should hence be excluded from what
1273 the service returns); naturally, this only applies
1274 to queries that can have multiple results, such as
1275 those for KBLOCKS (KSK) and SBLOCKS (SKS) */
1213}; 1276};
1214 1277
1215 1278
@@ -1243,6 +1306,118 @@ struct ContentMessage
1243 1306
1244}; 1307};
1245 1308
1309/**
1310 * Only the (mandatory) query is included.
1311 */
1312#define GET_MESSAGE_BIT_QUERY_ONLY 0
1313
1314/**
1315 * The peer identity of a peer waiting for the
1316 * reply is included (used if the response
1317 * should be transmitted to someone other than
1318 * the sender of the GET).
1319 */
1320#define GET_MESSAGE_BIT_RETURN_TO 1
1321
1322/**
1323 * The hash of the public key of the target
1324 * namespace is included (for SKS queries).
1325 */
1326#define GET_MESSAGE_BIT_SKS_NAMESPACE 2
1327
1328/**
1329 * The peer identity of a peer that had claimed to have the content
1330 * previously is included (can be used if responder-anonymity is not
1331 * desired; note that the precursor presumably lacked a direct
1332 * connection to the specified peer; still, the receiver is in no way
1333 * required to limit forwarding only to the specified peer, it should
1334 * only prefer it somewhat if possible).
1335 */
1336#define GET_MESSAGE_BIT_TRANSMIT_TO 4
1337
1338
1339/**
1340 * Message sent between peers asking for FS-content.
1341 */
1342struct GetMessage
1343{
1344
1345 /**
1346 * Message type will be GNUNET_MESSAGE_TYPE_FS_GET.
1347 */
1348 struct GNUNET_MessageHeader header;
1349
1350 /**
1351 * Type of the query (block type).
1352 */
1353 uint32_t type GNUNET_PACKED;
1354
1355 /**
1356 * How important is this request (network byte order)
1357 */
1358 uint32_t priority GNUNET_PACKED;
1359
1360 /**
1361 * Relative time to live in GNUNET_CRON_MILLISECONDS (network byte order)
1362 */
1363 int32_t ttl GNUNET_PACKED;
1364
1365 /**
1366 * The content hash should be mutated using this value
1367 * before checking against the bloomfilter (used to
1368 * get many different filters for the same hash codes).
1369 * The number should be in big-endian format when used
1370 * for mingling.
1371 */
1372 int32_t filter_mutator GNUNET_PACKED;
1373
1374 /**
1375 * Which of the optional hash codes are present at the end of the
1376 * message? See GET_MESSAGE_BIT_xx constants. For each bit that is
1377 * set, an additional GNUNET_HashCode with the respective content
1378 * (in order of the bits) will be appended to the end of the GET
1379 * message.
1380 */
1381 uint32_t hash_bitmap GNUNET_PACKED;
1382
1383 /**
1384 * Hashcodes of the file(s) we're looking for.
1385 * Details depend on the query type.
1386 */
1387 GNUNET_HashCode query GNUNET_PACKED;
1388
1389 /* this is followed by hash codes
1390 as specified in the "hash_bitmap";
1391 after that, an optional bloomfilter
1392 (with bits set for replies that should
1393 be suppressed) can be present */
1394};
1395
1396
1397/**
1398 * Message sent between peers providing FS-content.
1399 */
1400struct PutMessage
1401{
1402
1403 /**
1404 * Message type will be GNUNET_MESSAGE_TYPE_FS_PUT.
1405 */
1406 struct GNUNET_MessageHeader header;
1407
1408 /**
1409 * Type of the block (in big endian).
1410 */
1411 uint32_t type GNUNET_PACKED;
1412
1413 /**
1414 * When does this result expire?
1415 */
1416 struct GNUNET_TIME_RelativeNBO expiration;
1417
1418 /* this is followed by the actual encrypted content */
1419
1420};
1246 1421
1247 1422
1248#endif 1423#endif
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index 8d36e74c5..1f248c059 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -24,34 +24,29 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * 25 *
26 * TODO: 26 * TODO:
27 * - read_index_list 27 * - tracking of PendingRequests (and defining that struct...)
28 * - write_index_list 28 * - setup P2P search on CS request
29 * - bloomfilter support (GET, CS-request with BF, etc.) 29 * - setup P2P search on P2P GET
30 * - handling of on-demand blocks from datastore (need to use indexed-list!) 30 * - forward replies based on tracked requests
31 * - all P2P messages 31 * - validation of KBLOCKS (almost done)
32 * - validation of SBLOCKS
33 * - validation of KSBLOCKS
34 * - content migration (put in local DS)
35 * - possible major issue: we may
36 * queue "gazillions" of (K|S)Blocks for the
37 * core to transmit to another peer; need
38 * to make sure this is bounded overall...
39 * - various load-based actions (can wait)
40 * - remove on-demand blocks if they keep failing (can wait)
32 */ 41 */
33#include "platform.h" 42#include "platform.h"
34#include "gnunet_protocols.h"
35#include "gnunet_core_service.h" 43#include "gnunet_core_service.h"
36#include "gnunet_datastore_service.h" 44#include "gnunet_datastore_service.h"
45#include "gnunet_protocols.h"
46#include "gnunet_signatures.h"
37#include "gnunet_util_lib.h" 47#include "gnunet_util_lib.h"
38#include "fs.h" 48#include "fs.h"
39 49
40/**
41 * Our connection to the datastore.
42 */
43static struct GNUNET_DATASTORE_Handle *dsh;
44
45/**
46 * Our scheduler.
47 */
48static struct GNUNET_SCHEDULER_Handle *sched;
49
50/**
51 * Our configuration.
52 */
53const struct GNUNET_CONFIGURATION_Handle *cfg;
54
55 50
56/** 51/**
57 * In-memory information about indexed files (also available 52 * In-memory information about indexed files (also available
@@ -72,7 +67,7 @@ struct IndexInfo
72 const char *filename; 67 const char *filename;
73 68
74 /** 69 /**
75 * Context for tranmitting confirmation to client, 70 * Context for transmitting confirmation to client,
76 * NULL if we've done this already. 71 * NULL if we've done this already.
77 */ 72 */
78 struct GNUNET_SERVER_TransmitContext *tc; 73 struct GNUNET_SERVER_TransmitContext *tc;
@@ -86,10 +81,367 @@ struct IndexInfo
86 81
87 82
88/** 83/**
84 * Signature of a function that is called whenever a datastore
85 * request can be processed (or an entry put on the queue times out).
86 *
87 * @param cls closure
88 * @param ok GNUNET_OK if DS is ready, GNUNET_SYSERR on timeout
89 */
90typedef void (*RequestFunction)(void *cls,
91 int ok);
92
93
94/**
95 * Doubly-linked list of our requests for the datastore.
96 */
97struct DatastoreRequestQueue
98{
99
100 /**
101 * This is a doubly-linked list.
102 */
103 struct DatastoreRequestQueue *next;
104
105 /**
106 * This is a doubly-linked list.
107 */
108 struct DatastoreRequestQueue *prev;
109
110 /**
111 * Function to call (will issue the request).
112 */
113 RequestFunction req;
114
115 /**
116 * Closure for req.
117 */
118 void *req_cls;
119
120 /**
121 * When should this request time-out because we don't care anymore?
122 */
123 struct GNUNET_TIME_Absolute timeout;
124
125 /**
126 * ID of task used for signaling timeout.
127 */
128 GNUNET_SCHEDULER_TaskIdentifier task;
129
130};
131
132
133/**
134 * Closure for processing START_SEARCH messages from a client.
135 */
136struct LocalGetContext
137{
138
139 /**
140 * This is a doubly-linked list.
141 */
142 struct LocalGetContext *next;
143
144 /**
145 * This is a doubly-linked list.
146 */
147 struct LocalGetContext *prev;
148
149 /**
150 * Client that initiated the search.
151 */
152 struct GNUNET_SERVER_Client *client;
153
154 /**
155 * Array of results that we've already received
156 * (can be NULL).
157 */
158 GNUNET_HashCode *results;
159
160 /**
161 * Bloomfilter over all results (for fast query construction);
162 * NULL if we don't have any results.
163 */
164 struct GNUNET_CONTAINER_BloomFilter *results_bf;
165
166 /**
167 * DS request associated with this operation.
168 */
169 struct DatastoreRequestQueue *req;
170
171 /**
172 * Current result message to transmit to client (or NULL).
173 */
174 struct ContentMessage *result;
175
176 /**
177 * Type of the content that we're looking for.
178 * 0 for any.
179 */
180 uint32_t type;
181
182 /**
183 * Desired anonymity level.
184 */
185 uint32_t anonymity_level;
186
187 /**
188 * Number of results actually stored in the results array.
189 */
190 unsigned int results_used;
191
192 /**
193 * Size of the results array in memory.
194 */
195 unsigned int results_size;
196
197 /**
198 * If the request is for a DBLOCK or IBLOCK, this is the identity of
199 * the peer that is known to have a response. Set to all-zeros if
200 * such a target is not known (note that even if OUR anonymity
201 * level is >0 we may happen to know the responder's identity;
202 * nevertheless, we should probably not use it for a DHT-lookup
203 * or similar blunt actions in order to avoid exposing ourselves).
204 * <p>
205 * If the request is for an SBLOCK, this is the identity of the
206 * pseudonym to which the SBLOCK belongs.
207 * <p>
208 * If the request is for a KBLOCK, "target" must be all zeros.
209 */
210 GNUNET_HashCode target;
211
212 /**
213 * Hash of the keyword (aka query) for KBLOCKs; Hash of
214 * the CHK-encoded block for DBLOCKS and IBLOCKS (aka query)
215 * and hash of the identifier XORed with the target for
216 * SBLOCKS (aka query).
217 */
218 GNUNET_HashCode query;
219
220};
221
222
223/**
224 * Possible routing policies for an FS-GET request.
225 */
226enum RoutingPolicy
227 {
228 /**
229 * Simply drop the request.
230 */
231 ROUTING_POLICY_NONE = 0,
232
233 /**
234 * Answer it if we can from local datastore.
235 */
236 ROUTING_POLICY_ANSWER = 1,
237
238 /**
239 * Forward the request to other peers (if possible).
240 */
241 ROUTING_POLICY_FORWARD = 2,
242
243 /**
244 * Forward to other peers, and ask them to route
245 * the response via ourselves.
246 */
247 ROUTING_POLICY_INDIRECT = 6,
248
249 /**
250 * Do everything we could possibly do (that would
251 * make sense).
252 */
253 ROUTING_POLICY_ALL = 7
254 };
255
256
257/**
258 * Internal context we use for our initial processing
259 * of a GET request.
260 */
261struct ProcessGetContext
262{
263 /**
264 * The search query (used for datastore lookup).
265 */
266 GNUNET_HashCode query;
267
268 /**
269 * Which peer we should forward the response to.
270 */
271 struct GNUNET_PeerIdentity reply_to;
272
273 /**
274 * Namespace for the result (only set for SKS requests)
275 */
276 GNUNET_HashCode namespace;
277
278 /**
279 * Peer that we should forward the query to if possible
280 * (since that peer likely has the content).
281 */
282 struct GNUNET_PeerIdentity prime_target;
283
284 /**
285 * When did we receive this request?
286 */
287 struct GNUNET_TIME_Absolute start_time;
288
289 /**
290 * Our entry in the DRQ (non-NULL while we wait for our
291 * turn to interact with the local database).
292 */
293 struct DatastoreRequestQueue *drq;
294
295 /**
296 * Filter used to eliminate duplicate
297 * results. Can be NULL if we are
298 * not yet filtering any results.
299 */
300 struct GNUNET_CONTAINER_BloomFilter *bf;
301
302 /**
303 * Bitmap describing which of the optional
304 * hash codes / peer identities were given to us.
305 */
306 uint32_t bm;
307
308 /**
309 * Desired block type.
310 */
311 uint32_t type;
312
313 /**
314 * Priority of the request.
315 */
316 uint32_t priority;
317
318 /**
319 * In what ways are we going to process
320 * the request?
321 */
322 enum RoutingPolicy policy;
323
324 /**
325 * Time-to-live for the request (value
326 * we use).
327 */
328 int32_t ttl;
329
330 /**
331 * Number to mingle hashes for bloom-filter
332 * tests with.
333 */
334 int32_t mingle;
335
336 /**
337 * Number of results that were found so far.
338 */
339 unsigned int results_found;
340};
341
342
343/**
344 * Information we keep for each pending
345 * request.
346 */
347struct PendingRequest
348{
349 // FIXME
350};
351
352
353/**
354 * Closure for "process_reply" function.
355 */
356struct ProcessReplyClosure
357{
358 /**
359 * The data for the reply.
360 */
361 const void *data;
362
363 /**
364 * When the reply expires.
365 */
366 struct GNUNET_TIME_Absolute expiration;
367
368 /**
369 * Size of data.
370 */
371 size_t size;
372
373 /**
374 * Type of the block.
375 */
376 uint32_t type;
377
378 /**
379 * How much was this reply worth to us?
380 */
381 uint32_t priority;
382};
383
384
385/**
386 * Map from queries to pending requests ("struct PendingRequest") for
387 * this query.
388 */
389static struct GNUNET_CONTAINER_MultiHashMap *request_map;
390
391/**
392 * Our connection to the datastore.
393 */
394static struct GNUNET_DATASTORE_Handle *dsh;
395
396/**
397 * Our scheduler.
398 */
399static struct GNUNET_SCHEDULER_Handle *sched;
400
401/**
402 * Our configuration.
403 */
404const struct GNUNET_CONFIGURATION_Handle *cfg;
405
406/**
407 * Handle to the core service (NULL until we've
408 * connected to it).
409 */
410struct GNUNET_CORE_Handle *core;
411
412/**
413 * Head of doubly-linked LGC list.
414 */
415static struct LocalGetContext *lgc_head;
416
417/**
418 * Tail of doubly-linked LGC list.
419 */
420static struct LocalGetContext *lgc_tail;
421
422/**
423 * Head of request queue for the datastore, sorted by timeout.
424 */
425static struct DatastoreRequestQueue *drq_head;
426
427/**
428 * Tail of request queue for the datastore.
429 */
430static struct DatastoreRequestQueue *drq_tail;
431
432/**
89 * Linked list of indexed files. 433 * Linked list of indexed files.
90 */ 434 */
91static struct IndexInfo *indexed_files; 435static struct IndexInfo *indexed_files;
92 436
437/**
438 * Maps hash over content of indexed files
439 * to the respective filename. The filenames
440 * are pointers into the indexed_files linked
441 * list and do not need to be freed.
442 */
443static struct GNUNET_CONTAINER_MultiHashMap *ifm;
444
93 445
94/** 446/**
95 * Write the current index information list to disk. 447 * Write the current index information list to disk.
@@ -97,7 +449,54 @@ static struct IndexInfo *indexed_files;
97static void 449static void
98write_index_list () 450write_index_list ()
99{ 451{
100 // FIXME 452 struct GNUNET_BIO_WriteHandle *wh;
453 char *fn;
454 struct IndexInfo *pos;
455
456 if (GNUNET_OK !=
457 GNUNET_CONFIGURATION_get_value_filename (cfg,
458 "FS",
459 "INDEXDB",
460 &fn))
461 {
462 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
463 _("Configuration option `%s' in section `%s' missing.\n"),
464 "INDEXDB",
465 "FS");
466 return;
467 }
468 wh = GNUNET_BIO_write_open (fn);
469 if (NULL == wh)
470 {
471 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
472 _("Could not open `%s'.\n"),
473 fn);
474 GNUNET_free (fn);
475 return;
476 }
477 pos = indexed_files;
478 while (pos != NULL)
479 {
480 if ( (GNUNET_OK !=
481 GNUNET_BIO_write (wh,
482 &pos->file_id,
483 sizeof (GNUNET_HashCode))) ||
484 (GNUNET_OK !=
485 GNUNET_BIO_write_string (wh,
486 pos->filename)) )
487 break;
488 pos = pos->next;
489 }
490 if (GNUNET_OK !=
491 GNUNET_BIO_write_close (wh))
492 {
493 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
494 _("Error writing `%s'.\n"),
495 fn);
496 GNUNET_free (fn);
497 return;
498 }
499 GNUNET_free (fn);
101} 500}
102 501
103 502
@@ -107,7 +506,70 @@ write_index_list ()
107static void 506static void
108read_index_list () 507read_index_list ()
109{ 508{
110 // FIXME 509 struct GNUNET_BIO_ReadHandle *rh;
510 char *fn;
511 struct IndexInfo *pos;
512 char *fname;
513 GNUNET_HashCode hc;
514 size_t slen;
515 char *emsg;
516
517 if (GNUNET_OK !=
518 GNUNET_CONFIGURATION_get_value_filename (cfg,
519 "FS",
520 "INDEXDB",
521 &fn))
522 {
523 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
524 _("Configuration option `%s' in section `%s' missing.\n"),
525 "INDEXDB",
526 "FS");
527 return;
528 }
529 rh = GNUNET_BIO_read_open (fn);
530 if (NULL == rh)
531 {
532 GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
533 _("Could not open `%s'.\n"),
534 fn);
535 GNUNET_free (fn);
536 return;
537 }
538
539 while ( (GNUNET_OK ==
540 GNUNET_BIO_read (rh,
541 "Hash of indexed file",
542 &hc,
543 sizeof (GNUNET_HashCode))) &&
544 (GNUNET_OK ==
545 GNUNET_BIO_read_string (rh,
546 "Name of indexed file",
547 &fname,
548 1024 * 16)) )
549 {
550 slen = strlen (fname) + 1;
551 pos = GNUNET_malloc (sizeof (struct IndexInfo) + slen);
552 pos->file_id = hc;
553 pos->filename = (const char *) &pos[1];
554 memcpy (&pos[1], fname, slen);
555 if (GNUNET_SYSERR ==
556 GNUNET_CONTAINER_multihashmap_put (ifm,
557 &hc,
558 (void*) pos->filename,
559 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
560 {
561 GNUNET_free (pos);
562 }
563 else
564 {
565 pos->next = indexed_files;
566 indexed_files = pos;
567 }
568 }
569 if (GNUNET_OK !=
570 GNUNET_BIO_read_close (rh, &emsg))
571 GNUNET_free (emsg);
572 GNUNET_free (fn);
111} 573}
112 574
113 575
@@ -121,6 +583,25 @@ read_index_list ()
121static void 583static void
122signal_index_ok (struct IndexInfo *ii) 584signal_index_ok (struct IndexInfo *ii)
123{ 585{
586 if (GNUNET_SYSERR ==
587 GNUNET_CONTAINER_multihashmap_put (ifm,
588 &ii->file_id,
589 (void*) ii->filename,
590 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
591 {
592 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
593 _("Index request received for file `%s' is indexed as `%s'. Permitting anyway.\n"),
594 ii->filename,
595 (const char*) GNUNET_CONTAINER_multihashmap_get (ifm,
596 &ii->file_id));
597 GNUNET_SERVER_transmit_context_append (ii->tc,
598 NULL, 0,
599 GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
600 GNUNET_SERVER_transmit_context_run (ii->tc,
601 GNUNET_TIME_UNIT_MINUTES);
602 GNUNET_free (ii);
603 return;
604 }
124 ii->next = indexed_files; 605 ii->next = indexed_files;
125 indexed_files = ii; 606 indexed_files = ii;
126 write_index_list (); 607 write_index_list ();
@@ -133,7 +614,6 @@ signal_index_ok (struct IndexInfo *ii)
133} 614}
134 615
135 616
136
137/** 617/**
138 * Function called once the hash computation over an 618 * Function called once the hash computation over an
139 * indexed file has completed. 619 * indexed file has completed.
@@ -146,7 +626,7 @@ hash_for_index_val (void *cls,
146 const GNUNET_HashCode * 626 const GNUNET_HashCode *
147 res) 627 res)
148{ 628{
149 struct IndexInfo *ii; 629 struct IndexInfo *ii = cls;
150 630
151 if ( (res == NULL) || 631 if ( (res == NULL) ||
152 (0 != memcmp (res, 632 (0 != memcmp (res,
@@ -199,7 +679,7 @@ handle_index_start (void *cls,
199 GNUNET_SYSERR); 679 GNUNET_SYSERR);
200 return; 680 return;
201 } 681 }
202 682 ism = (const struct IndexStartMessage*) message;
203 fn = (const char*) &ism[1]; 683 fn = (const char*) &ism[1];
204 dev = ntohl (ism->device); 684 dev = ntohl (ism->device);
205 ino = GNUNET_ntohll (ism->inode); 685 ino = GNUNET_ntohll (ism->inode);
@@ -341,67 +821,6 @@ handle_unindex (void *cls,
341 821
342 822
343/** 823/**
344 * Signature of a function that is called whenever a datastore
345 * request can be processed (or an entry put on the queue times out).
346 *
347 * @param cls closure
348 * @param ok GNUNET_OK if DS is ready, GNUNET_SYSERR on timeout
349 */
350typedef void (*RequestFunction)(void *cls,
351 int ok);
352
353
354/**
355 * Doubly-linked list of our requests for the datastore.
356 */
357struct DatastoreRequestQueue
358{
359
360 /**
361 * This is a doubly-linked list.
362 */
363 struct DatastoreRequestQueue *next;
364
365 /**
366 * This is a doubly-linked list.
367 */
368 struct DatastoreRequestQueue *prev;
369
370 /**
371 * Function to call (will issue the request).
372 */
373 RequestFunction req;
374
375 /**
376 * Closure for req.
377 */
378 void *req_cls;
379
380 /**
381 * When should this request time-out because we don't care anymore?
382 */
383 struct GNUNET_TIME_Absolute timeout;
384
385 /**
386 * ID of task used for signaling timeout.
387 */
388 GNUNET_SCHEDULER_TaskIdentifier task;
389
390};
391
392
393/**
394 * Head of request queue for the datastore, sorted by timeout.
395 */
396static struct DatastoreRequestQueue *drq_head;
397
398/**
399 * Tail of request queue for the datastore.
400 */
401static struct DatastoreRequestQueue *drq_tail;
402
403
404/**
405 * Run the next DS request in our 824 * Run the next DS request in our
406 * queue, we're done with the current one. 825 * queue, we're done with the current one.
407 */ 826 */
@@ -503,107 +922,6 @@ queue_ds_request (struct GNUNET_TIME_Relative deadline,
503 922
504 923
505/** 924/**
506 * Closure for processing START_SEARCH messages from a client.
507 */
508struct LocalGetContext
509{
510
511 /**
512 * This is a doubly-linked list.
513 */
514 struct LocalGetContext *next;
515
516 /**
517 * This is a doubly-linked list.
518 */
519 struct LocalGetContext *prev;
520
521 /**
522 * Client that initiated the search.
523 */
524 struct GNUNET_SERVER_Client *client;
525
526 /**
527 * Array of results that we've already received
528 * (can be NULL).
529 */
530 GNUNET_HashCode *results;
531
532 /**
533 * Bloomfilter over all results (for fast query construction);
534 * NULL if we don't have any results.
535 */
536 struct GNUNET_CONTAINER_BloomFilter *results_bf;
537
538 /**
539 * DS request associated with this operation.
540 */
541 struct DatastoreRequestQueue *req;
542
543 /**
544 * Current result message to transmit to client (or NULL).
545 */
546 struct ContentMessage *result;
547
548 /**
549 * Type of the content that we're looking for.
550 * 0 for any.
551 */
552 uint32_t type;
553
554 /**
555 * Desired anonymity level.
556 */
557 uint32_t anonymity_level;
558
559 /**
560 * Number of results actually stored in the results array.
561 */
562 unsigned int results_used;
563
564 /**
565 * Size of the results array in memory.
566 */
567 unsigned int results_size;
568
569 /**
570 * If the request is for a DBLOCK or IBLOCK, this is the identity of
571 * the peer that is known to have a response. Set to all-zeros if
572 * such a target is not known (note that even if OUR anonymity
573 * level is >0 we may happen to know the responder's identity;
574 * nevertheless, we should probably not use it for a DHT-lookup
575 * or similar blunt actions in order to avoid exposing ourselves).
576 * <p>
577 * If the request is for an SBLOCK, this is the identity of the
578 * pseudonym to which the SBLOCK belongs.
579 * <p>
580 * If the request is for a KBLOCK, "target" must be all zeros.
581 */
582 GNUNET_HashCode target;
583
584 /**
585 * Hash of the keyword (aka query) for KBLOCKs; Hash of
586 * the CHK-encoded block for DBLOCKS and IBLOCKS (aka query)
587 * and hash of the identifier XORed with the target for
588 * SBLOCKS (aka query).
589 */
590 GNUNET_HashCode query;
591
592};
593
594
595/**
596 * Head of doubly-linked LGC list.
597 */
598static struct LocalGetContext *lgc_head;
599
600/**
601 * Tail of doubly-linked LGC list.
602 */
603static struct LocalGetContext *lgc_tail;
604
605
606/**
607 * Free the state associated with a local get context. 925 * Free the state associated with a local get context.
608 * 926 *
609 * @param lgc the lgc to free 927 * @param lgc the lgc to free
@@ -664,6 +982,167 @@ transmit_local_result (void *cls,
664 982
665 983
666/** 984/**
985 * Continuation called from datastore's remove
986 * function.
987 *
988 * @param cls unused
989 * @param success did the deletion work?
990 * @param msg error message
991 */
992static void
993remove_cont (void *cls,
994 int success,
995 const char *msg)
996{
997 if (GNUNET_OK != success)
998 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
999 _("Failed to delete bogus block: %s\n"),
1000 msg);
1001 GNUNET_DATASTORE_get_next (dsh, GNUNET_YES);
1002}
1003
1004
1005/**
1006 * Mingle hash with the mingle_number to
1007 * produce different bits.
1008 */
1009static void
1010mingle_hash (const GNUNET_HashCode * in,
1011 int32_t mingle_number,
1012 GNUNET_HashCode * hc)
1013{
1014 GNUNET_HashCode m;
1015
1016 GNUNET_CRYPTO_hash (&mingle_number,
1017 sizeof (int32_t),
1018 &m);
1019 GNUNET_CRYPTO_hash_xor (&m, in, hc);
1020}
1021
1022
1023/**
1024 * We've received an on-demand encoded block
1025 * from the datastore. Attempt to do on-demand
1026 * encoding and (if successful), call the
1027 * continuation with the resulting block. On
1028 * error, clean up and ask the datastore for
1029 * more results.
1030 *
1031 * @param key key for the content
1032 * @param size number of bytes in data
1033 * @param data content stored
1034 * @param type type of the content
1035 * @param priority priority of the content
1036 * @param anonymity anonymity-level for the content
1037 * @param expiration expiration time for the content
1038 * @param uid unique identifier for the datum;
1039 * maybe 0 if no unique identifier is available
1040 * @param cont function to call with the actual block
1041 * @param cont_cls closure for cont
1042 */
1043static void
1044handle_on_demand_block (const GNUNET_HashCode * key,
1045 uint32_t size,
1046 const void *data,
1047 uint32_t type,
1048 uint32_t priority,
1049 uint32_t anonymity,
1050 struct GNUNET_TIME_Absolute
1051 expiration, uint64_t uid,
1052 GNUNET_DATASTORE_Iterator cont,
1053 void *cont_cls)
1054{
1055 const struct OnDemandBlock *odb;
1056 GNUNET_HashCode nkey;
1057 struct GNUNET_CRYPTO_AesSessionKey skey;
1058 struct GNUNET_CRYPTO_AesInitializationVector iv;
1059 GNUNET_HashCode query;
1060 ssize_t nsize;
1061 char ndata[DBLOCK_SIZE];
1062 char edata[DBLOCK_SIZE];
1063 const char *fn;
1064 struct GNUNET_DISK_FileHandle *fh;
1065 uint64_t off;
1066
1067 if (size != sizeof (struct OnDemandBlock))
1068 {
1069 GNUNET_break (0);
1070 GNUNET_DATASTORE_remove (dsh,
1071 key,
1072 size,
1073 data,
1074 &remove_cont,
1075 NULL,
1076 GNUNET_TIME_UNIT_FOREVER_REL);
1077 return;
1078 }
1079 odb = (const struct OnDemandBlock*) data;
1080 off = GNUNET_ntohll (odb->offset);
1081 fn = (const char*) GNUNET_CONTAINER_multihashmap_get (ifm,
1082 &odb->file_id);
1083 if ( (NULL == fn) ||
1084 (NULL == (fh = GNUNET_DISK_file_open (fn,
1085 GNUNET_DISK_OPEN_READ))) ||
1086 (off !=
1087 GNUNET_DISK_file_seek (fh,
1088 off,
1089 GNUNET_DISK_SEEK_SET)) ||
1090 (-1 ==
1091 (nsize = GNUNET_DISK_file_read (fh,
1092 ndata,
1093 sizeof (ndata)))) )
1094 {
1095 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1096 _("Could not access indexed file `%s' at offset %llu: %s\n"),
1097 GNUNET_h2s (&odb->file_id),
1098 (unsigned long long) off,
1099 STRERROR (errno));
1100 if (fh != NULL)
1101 GNUNET_DISK_file_close (fh);
1102 /* FIXME: if this happens often, we need
1103 to remove the OnDemand block from the DS! */
1104 GNUNET_DATASTORE_get_next (dsh, GNUNET_YES);
1105 return;
1106 }
1107 GNUNET_DISK_file_close (fh);
1108 GNUNET_CRYPTO_hash (ndata,
1109 nsize,
1110 &nkey);
1111 GNUNET_CRYPTO_hash_to_aes_key (&nkey, &skey, &iv);
1112 GNUNET_CRYPTO_aes_encrypt (ndata,
1113 nsize,
1114 &skey,
1115 &iv,
1116 edata);
1117 GNUNET_CRYPTO_hash (edata,
1118 nsize,
1119 &query);
1120 if (0 != memcmp (&query,
1121 key,
1122 sizeof (GNUNET_HashCode)))
1123 {
1124 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1125 _("Indexed file `%s' changed at offset %llu\n"),
1126 fn,
1127 (unsigned long long) off);
1128 /* FIXME: if this happens often, we need
1129 to remove the OnDemand block from the DS! */
1130 GNUNET_DATASTORE_get_next (dsh, GNUNET_YES);
1131 return;
1132 }
1133 cont (cont_cls,
1134 key,
1135 nsize,
1136 edata,
1137 GNUNET_DATASTORE_BLOCKTYPE_DBLOCK,
1138 priority,
1139 anonymity,
1140 expiration,
1141 uid);
1142}
1143
1144
1145/**
667 * We're processing (local) results for a search request 1146 * We're processing (local) results for a search request
668 * from a (local) client. Pass applicable results to the 1147 * from a (local) client. Pass applicable results to the
669 * client and if we are done either clean up (operation 1148 * client and if we are done either clean up (operation
@@ -694,8 +1173,8 @@ process_local_get_result (void *cls,
694{ 1173{
695 struct LocalGetContext *lgc = cls; 1174 struct LocalGetContext *lgc = cls;
696 size_t msize; 1175 size_t msize;
1176 unsigned int i;
697 1177
698 // FIXME: handle ONDEMAND blocks!
699 if (key == NULL) 1178 if (key == NULL)
700 { 1179 {
701 /* no further results from datastore; continue 1180 /* no further results from datastore; continue
@@ -717,25 +1196,40 @@ process_local_get_result (void *cls,
717 local_get_context_free (lgc); 1196 local_get_context_free (lgc);
718 return; 1197 return;
719 } 1198 }
720 if (lgc->results_used == lgc->results_size) 1199 if (type == GNUNET_DATASTORE_BLOCKTYPE_ONDEMAND)
721 { 1200 {
722 GNUNET_array_grow (lgc->results, 1201 handle_on_demand_block (key, size, data, type, priority,
723 lgc->results_size, 1202 anonymity, expiration, uid,
724 lgc->results_size * 2 + 2); 1203 &process_local_get_result,
725 if ( (lgc->type != GNUNET_DATASTORE_BLOCKTYPE_DBLOCK) || 1204 lgc);
726 (lgc->type != GNUNET_DATASTORE_BLOCKTYPE_IBLOCK) ) 1205 return;
727 { 1206 }
728 // FIXME: possibly grow/create BF! 1207 if (type != lgc->type)
729 } 1208 {
1209 /* this should be virtually impossible to reach (DBLOCK
1210 query hash being identical to KBLOCK/SBLOCK query hash);
1211 nevertheless, if it happens, the correct thing is to
1212 simply skip the result. */
1213 GNUNET_DATASTORE_get_next (dsh, GNUNET_YES);
1214 return;
730 } 1215 }
1216 /* check if this is a result we've alredy
1217 received */
1218 for (i=0;i<lgc->results_used;i++)
1219 if (0 == memcmp (key,
1220 &lgc->results[i],
1221 sizeof (GNUNET_HashCode)))
1222 {
1223 GNUNET_DATASTORE_get_next (dsh, GNUNET_YES);
1224 return;
1225 }
1226 if (lgc->results_used == lgc->results_size)
1227 GNUNET_array_grow (lgc->results,
1228 lgc->results_size,
1229 lgc->results_size * 2 + 2);
731 GNUNET_CRYPTO_hash (data, 1230 GNUNET_CRYPTO_hash (data,
732 size, 1231 size,
733 &lgc->results[lgc->results_used++]); 1232 &lgc->results[lgc->results_used++]);
734 if ( (lgc->type != GNUNET_DATASTORE_BLOCKTYPE_DBLOCK) ||
735 (lgc->type != GNUNET_DATASTORE_BLOCKTYPE_IBLOCK) )
736 {
737 // FIXME: add result to BF!
738 }
739 msize = size + sizeof (struct ContentMessage); 1233 msize = size + sizeof (struct ContentMessage);
740 GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); 1234 GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE);
741 lgc->result = GNUNET_malloc (msize); 1235 lgc->result = GNUNET_malloc (msize);
@@ -766,11 +1260,14 @@ transmit_local_get (void *cls,
766 const struct GNUNET_SCHEDULER_TaskContext *tc) 1260 const struct GNUNET_SCHEDULER_TaskContext *tc)
767{ 1261{
768 struct LocalGetContext *lgc = cls; 1262 struct LocalGetContext *lgc = cls;
769 1263 uint32_t type;
770 // FIXME: handle ONDEMAND blocks (change type to ANY for DBLOCK/IBLOCK) 1264
1265 type = lgc->type;
1266 if (type == GNUNET_DATASTORE_BLOCKTYPE_DBLOCK)
1267 type = GNUNET_DATASTORE_BLOCKTYPE_ANY; /* to get on-demand as well */
771 GNUNET_DATASTORE_get (dsh, 1268 GNUNET_DATASTORE_get (dsh,
772 &lgc->query, 1269 &lgc->query,
773 lgc->type, 1270 type,
774 &process_local_get_result, 1271 &process_local_get_result,
775 lgc, 1272 lgc,
776 GNUNET_TIME_UNIT_FOREVER_REL); 1273 GNUNET_TIME_UNIT_FOREVER_REL);
@@ -813,10 +1310,32 @@ handle_start_search (void *cls,
813{ 1310{
814 const struct SearchMessage *sm; 1311 const struct SearchMessage *sm;
815 struct LocalGetContext *lgc; 1312 struct LocalGetContext *lgc;
816 1313 uint16_t msize;
1314 unsigned int sc;
1315
1316 msize = ntohs (message->size);
1317 if ( (msize < sizeof (struct SearchMessage)) ||
1318 (0 != (msize - sizeof (struct SearchMessage)) % sizeof (GNUNET_HashCode)) )
1319 {
1320 GNUNET_break (0);
1321 GNUNET_SERVER_receive_done (client,
1322 GNUNET_SYSERR);
1323 return;
1324 }
1325 sc = (msize - sizeof (struct SearchMessage)) / sizeof (GNUNET_HashCode);
817 sm = (const struct SearchMessage*) message; 1326 sm = (const struct SearchMessage*) message;
818 GNUNET_SERVER_client_keep (client); 1327 GNUNET_SERVER_client_keep (client);
819 lgc = GNUNET_malloc (sizeof (struct LocalGetContext)); 1328 lgc = GNUNET_malloc (sizeof (struct LocalGetContext));
1329 if (sc > 0)
1330 {
1331 lgc->results_used = sc;
1332 GNUNET_array_grow (lgc->results,
1333 lgc->results_size,
1334 sc * 2);
1335 memcpy (lgc->results,
1336 &sm[1],
1337 sc * sizeof (GNUNET_HashCode));
1338 }
820 lgc->client = client; 1339 lgc->client = client;
821 lgc->type = ntohl (sm->type); 1340 lgc->type = ntohl (sm->type);
822 lgc->anonymity_level = ntohl (sm->anonymity_level); 1341 lgc->anonymity_level = ntohl (sm->anonymity_level);
@@ -841,7 +1360,7 @@ static struct GNUNET_SERVER_MessageHandler handlers[] = {
841 {&handle_unindex, NULL, GNUNET_MESSAGE_TYPE_FS_UNINDEX, 1360 {&handle_unindex, NULL, GNUNET_MESSAGE_TYPE_FS_UNINDEX,
842 sizeof (struct UnindexMessage) }, 1361 sizeof (struct UnindexMessage) },
843 {&handle_start_search, NULL, GNUNET_MESSAGE_TYPE_FS_START_SEARCH, 1362 {&handle_start_search, NULL, GNUNET_MESSAGE_TYPE_FS_START_SEARCH,
844 sizeof (struct SearchMessage) }, 1363 0 },
845 {NULL, NULL, 0, 0} 1364 {NULL, NULL, 0, 0}
846}; 1365};
847 1366
@@ -879,9 +1398,682 @@ static void
879shutdown_task (void *cls, 1398shutdown_task (void *cls,
880 const struct GNUNET_SCHEDULER_TaskContext *tc) 1399 const struct GNUNET_SCHEDULER_TaskContext *tc)
881{ 1400{
1401 struct IndexInfo *pos;
1402
1403 if (NULL != core)
1404 GNUNET_CORE_disconnect (core);
882 GNUNET_DATASTORE_disconnect (dsh, 1405 GNUNET_DATASTORE_disconnect (dsh,
883 GNUNET_NO); 1406 GNUNET_NO);
884 dsh = NULL; 1407 dsh = NULL;
1408 // FIXME: iterate over 'request_map' to free entries!
1409 GNUNET_CONTAINER_multihashmap_destroy (request_map);
1410 request_map = NULL;
1411 GNUNET_CONTAINER_multihashmap_destroy (ifm);
1412 ifm = NULL;
1413 while (NULL != (pos = indexed_files))
1414 {
1415 indexed_files = pos->next;
1416 GNUNET_free (pos);
1417 }
1418}
1419
1420
1421/**
1422 * Method called whenever a peer disconnects.
1423 *
1424 * @param cls closure, not used
1425 * @param peer peer identity this notification is about
1426 */
1427static void
1428peer_disconnect_handler (void *cls,
1429 const struct
1430 GNUNET_PeerIdentity * peer)
1431{
1432 // FIXME: remove all pending requests from this
1433 // peer from our memory
1434 // (iterate over request_map)
1435}
1436
1437
1438/**
1439 * We're processing a GET request from
1440 * another peer and have decided to forward
1441 * it to other peers.
1442 *
1443 * @param cls our "struct ProcessGetContext *"
1444 * @param tc unused
1445 */
1446static void
1447forward_get_request (void *cls,
1448 const struct GNUNET_SCHEDULER_TaskContext *tc)
1449{
1450 struct ProcessGetContext *pgc = cls;
1451
1452 // FIXME: install entry in
1453 // 'request_map' and do actual
1454 // forwarding...
1455 if (pgc->bf != NULL)
1456 GNUNET_CONTAINER_bloomfilter_free (pgc->bf);
1457 GNUNET_free (pgc);
1458}
1459
1460
1461/**
1462 * Transmit the given message by copying it to
1463 * the target buffer "buf". "buf" will be
1464 * NULL and "size" zero if the socket was closed for
1465 * writing in the meantime. In that case, only
1466 * free the message
1467 *
1468 * @param cls closure, pointer to the message
1469 * @param size number of bytes available in buf
1470 * @param buf where the callee should write the message
1471 * @return number of bytes written to buf
1472 */
1473static size_t
1474transmit_message (void *cls,
1475 size_t size, void *buf)
1476{
1477 struct GNUNET_MessageHeader *msg = cls;
1478 uint16_t msize;
1479
1480 if (NULL == buf)
1481 {
1482#if DEBUG_FS
1483 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1484 "Dropping reply, core too busy.\n");
1485#endif
1486 GNUNET_free (msg);
1487 return 0;
1488 }
1489 msize = ntohs (msg->size);
1490 GNUNET_assert (size >= msize);
1491 memcpy (buf, msg, msize);
1492 GNUNET_free (msg);
1493 return msize;
1494}
1495
1496
1497/**
1498 * Test if the load on this peer is too high
1499 * to even consider processing the query at
1500 * all.
1501 *
1502 * @return GNUNET_YES if the load is too high, GNUNET_NO otherwise
1503 */
1504static int
1505test_load_too_high ()
1506{
1507 return GNUNET_NO; // FIXME
1508}
1509
1510
1511/**
1512 * We're processing (local) results for a search request
1513 * from another peer. Pass applicable results to the
1514 * peer and if we are done either clean up (operation
1515 * complete) or forward to other peers (more results possible).
1516 *
1517 * @param cls our closure (struct LocalGetContext)
1518 * @param key key for the content
1519 * @param size number of bytes in data
1520 * @param data content stored
1521 * @param type type of the content
1522 * @param priority priority of the content
1523 * @param anonymity anonymity-level for the content
1524 * @param expiration expiration time for the content
1525 * @param uid unique identifier for the datum;
1526 * maybe 0 if no unique identifier is available
1527 */
1528static void
1529process_p2p_get_result (void *cls,
1530 const GNUNET_HashCode * key,
1531 uint32_t size,
1532 const void *data,
1533 uint32_t type,
1534 uint32_t priority,
1535 uint32_t anonymity,
1536 struct GNUNET_TIME_Absolute
1537 expiration,
1538 uint64_t uid)
1539{
1540 struct ProcessGetContext *pgc = cls;
1541 GNUNET_HashCode dhash;
1542 GNUNET_HashCode mhash;
1543 struct PutMessage *reply;
1544
1545 if (NULL == key)
1546 {
1547 /* no more results */
1548 if ( ( (pgc->policy & ROUTING_POLICY_FORWARD) == ROUTING_POLICY_FORWARD) &&
1549 ( (0 == pgc->results_found) ||
1550 (pgc->type == GNUNET_DATASTORE_BLOCKTYPE_KBLOCK) ||
1551 (pgc->type == GNUNET_DATASTORE_BLOCKTYPE_SBLOCK) ||
1552 (pgc->type == GNUNET_DATASTORE_BLOCKTYPE_SKBLOCK) ) )
1553 {
1554 GNUNET_SCHEDULER_add_continuation (sched,
1555 GNUNET_NO,
1556 &forward_get_request,
1557 pgc,
1558 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1559 }
1560 else
1561 {
1562 if (pgc->bf != NULL)
1563 GNUNET_CONTAINER_bloomfilter_free (pgc->bf);
1564 GNUNET_free (pgc);
1565 }
1566 next_ds_request ();
1567 return;
1568 }
1569 if (type == GNUNET_DATASTORE_BLOCKTYPE_ONDEMAND)
1570 {
1571 handle_on_demand_block (key, size, data, type, priority,
1572 anonymity, expiration, uid,
1573 &process_p2p_get_result,
1574 pgc);
1575 return;
1576 }
1577 /* check for duplicates */
1578 GNUNET_CRYPTO_hash (data, size, &dhash);
1579 mingle_hash (&dhash,
1580 pgc->mingle,
1581 &mhash);
1582 if ( (pgc->bf != NULL) &&
1583 (GNUNET_YES ==
1584 GNUNET_CONTAINER_bloomfilter_test (pgc->bf,
1585 &mhash)) )
1586 {
1587#if DEBUG_FS
1588 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1589 "Result from datastore filtered by bloomfilter.\n");
1590#endif
1591 GNUNET_DATASTORE_get_next (dsh, GNUNET_YES);
1592 return;
1593 }
1594 pgc->results_found++;
1595 if ( (pgc->type == GNUNET_DATASTORE_BLOCKTYPE_KBLOCK) ||
1596 (pgc->type == GNUNET_DATASTORE_BLOCKTYPE_SBLOCK) ||
1597 (pgc->type == GNUNET_DATASTORE_BLOCKTYPE_SKBLOCK) )
1598 {
1599 if (pgc->bf == NULL)
1600 pgc->bf = GNUNET_CONTAINER_bloomfilter_init (NULL,
1601 32,
1602 BLOOMFILTER_K);
1603 GNUNET_CONTAINER_bloomfilter_add (pgc->bf,
1604 &mhash);
1605 }
1606
1607 reply = GNUNET_malloc (sizeof (struct PutMessage) + size);
1608 reply->header.size = htons (sizeof (struct PutMessage) + size);
1609 reply->header.type = htons (GNUNET_MESSAGE_TYPE_FS_PUT);
1610 reply->type = htonl (type);
1611 reply->expiration = GNUNET_TIME_relative_hton (GNUNET_TIME_absolute_get_remaining (expiration));
1612 memcpy (&reply[1], data, size);
1613 GNUNET_CORE_notify_transmit_ready (core,
1614 pgc->priority,
1615 ACCEPTABLE_REPLY_DELAY,
1616 &pgc->reply_to,
1617 sizeof (struct PutMessage) + size,
1618 &transmit_message,
1619 reply);
1620 if ( (GNUNET_YES == test_load_too_high()) ||
1621 (pgc->results_found > 5 + 2 * pgc->priority) )
1622 {
1623 GNUNET_DATASTORE_get_next (dsh, GNUNET_NO);
1624 pgc->policy &= ~ ROUTING_POLICY_FORWARD;
1625 return;
1626 }
1627 GNUNET_DATASTORE_get_next (dsh, GNUNET_YES);
1628}
1629
1630
1631/**
1632 * We're processing a GET request from
1633 * another peer. Give it to our local
1634 * datastore.
1635 *
1636 * @param cls our "struct ProcessGetContext"
1637 * @param ok did we get a datastore slice or not?
1638 */
1639static void
1640ds_get_request (void *cls,
1641 int ok)
1642{
1643 struct ProcessGetContext *pgc = cls;
1644 uint32_t type;
1645 struct GNUNET_TIME_Relative timeout;
1646
1647 if (GNUNET_OK != ok)
1648 {
1649 /* no point in doing P2P stuff if we can't even do local */
1650 GNUNET_free (dsh);
1651 return;
1652 }
1653 type = pgc->type;
1654 if (type == GNUNET_DATASTORE_BLOCKTYPE_DBLOCK)
1655 type = GNUNET_DATASTORE_BLOCKTYPE_ANY; /* to get on-demand as well */
1656 timeout = GNUNET_TIME_relative_multiply (BASIC_DATASTORE_REQUEST_DELAY,
1657 (pgc->priority + 1));
1658 GNUNET_DATASTORE_get (dsh,
1659 &pgc->query,
1660 type,
1661 &process_p2p_get_result,
1662 pgc,
1663 timeout);
1664}
1665
1666
1667/**
1668 * The priority level imposes a bound on the maximum
1669 * value for the ttl that can be requested.
1670 *
1671 * @param ttl_in requested ttl
1672 * @param priority given priority
1673 * @return ttl_in if ttl_in is below the limit,
1674 * otherwise the ttl-limit for the given priority
1675 */
1676static int32_t
1677bound_ttl (int32_t ttl_in, uint32_t prio)
1678{
1679 unsigned long long allowed;
1680
1681 if (ttl_in <= 0)
1682 return ttl_in;
1683 allowed = ((unsigned long long) prio) * TTL_DECREMENT / 1000;
1684 if (ttl_in > allowed)
1685 {
1686 if (allowed >= (1 << 30))
1687 return 1 << 30;
1688 return allowed;
1689 }
1690 return ttl_in;
1691}
1692
1693
1694/**
1695 * We've received a request with the specified
1696 * priority. Bound it according to how much
1697 * we trust the given peer.
1698 *
1699 * @param prio_in requested priority
1700 * @param peer the peer making the request
1701 * @return effective priority
1702 */
1703static uint32_t
1704bound_priority (uint32_t prio_in,
1705 const struct GNUNET_PeerIdentity *peer)
1706{
1707 return 0; // FIXME!
1708}
1709
1710
1711/**
1712 * Handle P2P "GET" request.
1713 *
1714 * @param cls closure, always NULL
1715 * @param peer the other peer involved (sender or receiver, NULL
1716 * for loopback messages where we are both sender and receiver)
1717 * @param message the actual message
1718 * @return GNUNET_OK to keep the connection open,
1719 * GNUNET_SYSERR to close it (signal serious error)
1720 */
1721static int
1722handle_p2p_get (void *cls,
1723 const struct GNUNET_PeerIdentity *other,
1724 const struct GNUNET_MessageHeader *message)
1725{
1726 uint16_t msize;
1727 const struct GetMessage *gm;
1728 unsigned int bits;
1729 const GNUNET_HashCode *opt;
1730 struct ProcessGetContext *pgc;
1731 uint32_t bm;
1732 size_t bfsize;
1733 uint32_t ttl_decrement;
1734 double preference;
1735 int net_load_up;
1736 int net_load_down;
1737
1738 msize = ntohs(message->size);
1739 if (msize < sizeof (struct GetMessage))
1740 {
1741 GNUNET_break_op (0);
1742 return GNUNET_SYSERR;
1743 }
1744 gm = (const struct GetMessage*) message;
1745 bm = ntohl (gm->hash_bitmap);
1746 bits = 0;
1747 while (bm > 0)
1748 {
1749 if (1 == (bm & 1))
1750 bits++;
1751 bm >>= 1;
1752 }
1753 if (msize < sizeof (struct GetMessage) + bits * sizeof (GNUNET_HashCode))
1754 {
1755 GNUNET_break_op (0);
1756 return GNUNET_SYSERR;
1757 }
1758 opt = (const GNUNET_HashCode*) &gm[1];
1759 bfsize = msize - sizeof (struct GetMessage) + bits * sizeof (GNUNET_HashCode);
1760 pgc = GNUNET_malloc (sizeof (struct ProcessGetContext));
1761 if (bfsize > 0)
1762 pgc->bf = GNUNET_CONTAINER_bloomfilter_init ((const char*) &pgc[1],
1763 bfsize,
1764 BLOOMFILTER_K);
1765 pgc->type = ntohl (gm->type);
1766 pgc->bm = ntohl (gm->hash_bitmap);
1767 pgc->mingle = gm->filter_mutator;
1768 bits = 0;
1769 if (0 != (pgc->bm & GET_MESSAGE_BIT_RETURN_TO))
1770 pgc->reply_to.hashPubKey = opt[bits++];
1771 else
1772 pgc->reply_to = *other;
1773 if (0 != (pgc->bm & GET_MESSAGE_BIT_SKS_NAMESPACE))
1774 pgc->namespace = opt[bits++];
1775 else if (pgc->type == GNUNET_DATASTORE_BLOCKTYPE_SBLOCK)
1776 {
1777 GNUNET_break_op (0);
1778 GNUNET_free (pgc);
1779 return GNUNET_SYSERR;
1780 }
1781 if (0 != (pgc->bm & GET_MESSAGE_BIT_TRANSMIT_TO))
1782 pgc->prime_target.hashPubKey = opt[bits++];
1783 /* note that we can really only check load here since otherwise
1784 peers could find out that we are overloaded by being disconnected
1785 after sending us a malformed query... */
1786 if (GNUNET_YES == test_load_too_high ())
1787 {
1788 if (NULL != pgc->bf)
1789 GNUNET_CONTAINER_bloomfilter_free (pgc->bf);
1790 GNUNET_free (pgc);
1791#if DEBUG_FS
1792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1793 "Dropping query from `%s', this peer is too busy.\n",
1794 GNUNET_h2s (other));
1795#endif
1796 return GNUNET_OK;
1797 }
1798 net_load_up = 50; // FIXME
1799 net_load_down = 50; // FIXME
1800 pgc->policy = ROUTING_POLICY_NONE;
1801 if ( (net_load_up < IDLE_LOAD_THRESHOLD) &&
1802 (net_load_down < IDLE_LOAD_THRESHOLD) )
1803 {
1804 pgc->policy |= ROUTING_POLICY_ALL;
1805 pgc->priority = 0; /* no charge */
1806 }
1807 else
1808 {
1809 pgc->priority = bound_priority (ntohl (gm->priority), other);
1810 if ( (net_load_up <
1811 IDLE_LOAD_THRESHOLD + pgc->priority * pgc->priority) &&
1812 (net_load_down <
1813 IDLE_LOAD_THRESHOLD + pgc->priority * pgc->priority) )
1814 {
1815 pgc->policy |= ROUTING_POLICY_ALL;
1816 }
1817 else
1818 {
1819 // FIXME: is this sound?
1820 if (net_load_up < 90 + 10 * pgc->priority)
1821 pgc->policy |= ROUTING_POLICY_FORWARD;
1822 if (net_load_down < 90 + 10 * pgc->priority)
1823 pgc->policy |= ROUTING_POLICY_ANSWER;
1824 }
1825 }
1826 if (pgc->policy == ROUTING_POLICY_NONE)
1827 {
1828#if DEBUG_FS
1829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1830 "Dropping query from `%s', network saturated.\n",
1831 GNUNET_h2s (other));
1832#endif
1833 if (NULL != pgc->bf)
1834 GNUNET_CONTAINER_bloomfilter_free (pgc->bf);
1835 GNUNET_free (pgc);
1836 return GNUNET_OK; /* drop */
1837 }
1838 if ((pgc->policy & ROUTING_POLICY_INDIRECT) != ROUTING_POLICY_INDIRECT)
1839 pgc->priority = 0; /* kill the priority (we cannot benefit) */
1840 pgc->ttl = bound_ttl (ntohl (gm->ttl), pgc->priority);
1841 /* decrement ttl (always) */
1842 ttl_decrement = 2 * TTL_DECREMENT +
1843 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1844 TTL_DECREMENT);
1845 if ( (pgc->ttl < 0) &&
1846 (pgc->ttl - ttl_decrement > 0) )
1847 {
1848#if DEBUG_FS
1849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1850 "Dropping query from `%s' due to TTL underflow.\n",
1851 GNUNET_h2s (other));
1852#endif
1853 /* integer underflow => drop (should be very rare)! */
1854 if (NULL != pgc->bf)
1855 GNUNET_CONTAINER_bloomfilter_free (pgc->bf);
1856 GNUNET_free (pgc);
1857 return GNUNET_OK;
1858 }
1859 pgc->ttl -= ttl_decrement;
1860 pgc->start_time = GNUNET_TIME_absolute_get ();
1861 preference = (double) pgc->priority;
1862 if (preference < QUERY_BANDWIDTH_VALUE)
1863 preference = QUERY_BANDWIDTH_VALUE;
1864 // FIXME: also reserve bandwidth for reply?
1865 GNUNET_CORE_peer_configure (core,
1866 other,
1867 GNUNET_TIME_UNIT_FOREVER_REL,
1868 0, 0, preference, NULL, NULL);
1869 if (0 != (pgc->policy & ROUTING_POLICY_ANSWER))
1870 pgc->drq = queue_ds_request (BASIC_DATASTORE_REQUEST_DELAY,
1871 &ds_get_request,
1872 pgc);
1873 else
1874 GNUNET_SCHEDULER_add_continuation (sched,
1875 GNUNET_NO,
1876 &forward_get_request,
1877 pgc,
1878 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1879 return GNUNET_OK;
1880}
1881
1882
1883/**
1884 * Iterator over pending requests.
1885 *
1886 * @param cls response (struct ProcessReplyClosure)
1887 * @param key our query
1888 * @param value value in the hash map (meta-info about the query)
1889 * @return GNUNET_YES (we should continue to iterate)
1890 */
1891static int
1892process_reply (void *cls,
1893 const GNUNET_HashCode * key,
1894 void *value)
1895{
1896 struct ProcessReplyClosure *prq = cls;
1897 struct PendingRequest *pr = value;
1898
1899 fprintf (stderr, "FIXME %p %p\n", prq, pr);
1900 // FIXME: forward reply to client
1901 // or other peers (depending on pr...)
1902 return GNUNET_YES;
1903}
1904
1905
1906/**
1907 * Handle P2P "PUT" request.
1908 *
1909 * @param cls closure, always NULL
1910 * @param peer the other peer involved (sender or receiver, NULL
1911 * for loopback messages where we are both sender and receiver)
1912 * @param message the actual message
1913 * @return GNUNET_OK to keep the connection open,
1914 * GNUNET_SYSERR to close it (signal serious error)
1915 */
1916static int
1917handle_p2p_put (void *cls,
1918 const struct GNUNET_PeerIdentity *other,
1919 const struct GNUNET_MessageHeader *message)
1920{
1921 const struct PutMessage *put;
1922 uint16_t msize;
1923 size_t dsize;
1924 uint32_t type;
1925 struct GNUNET_TIME_Absolute expiration;
1926 GNUNET_HashCode query;
1927 const struct KBlock *kb;
1928 struct ProcessReplyClosure prq;
1929
1930 msize = ntohs (message->size);
1931 if (msize < sizeof (struct PutMessage))
1932 {
1933 GNUNET_break_op(0);
1934 return GNUNET_SYSERR;
1935 }
1936 put = (const struct PutMessage*) message;
1937 dsize = msize - sizeof (struct PutMessage);
1938 type = ntohl (put->type);
1939 expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh (put->expiration));
1940
1941 /* first, validate! */
1942 switch (type)
1943 {
1944 case GNUNET_DATASTORE_BLOCKTYPE_DBLOCK:
1945 case GNUNET_DATASTORE_BLOCKTYPE_IBLOCK:
1946 GNUNET_CRYPTO_hash (&put[1], dsize, &query);
1947 break;
1948 case GNUNET_DATASTORE_BLOCKTYPE_KBLOCK:
1949 if (dsize < sizeof (struct KBlock))
1950 {
1951 GNUNET_break_op (0);
1952 return GNUNET_SYSERR;
1953 }
1954 kb = (const struct KBlock*) &put[1];
1955 // FIXME -- validation code below broken...
1956 if ( (dsize != ntohs (kb->purpose.size) + 42) ||
1957 (GNUNET_OK !=
1958 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK,
1959 &kb->purpose,
1960 &kb->signature,
1961 &kb->keyspace)) )
1962 {
1963 GNUNET_break_op (0);
1964 return GNUNET_SYSERR;
1965 }
1966 GNUNET_CRYPTO_hash (&kb->keyspace,
1967 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1968 &query);
1969 break;
1970 case GNUNET_DATASTORE_BLOCKTYPE_SBLOCK:
1971 // FIXME -- validate SBLOCK!
1972 GNUNET_break (0);
1973 return GNUNET_OK;
1974 case GNUNET_DATASTORE_BLOCKTYPE_SKBLOCK:
1975 // FIXME -- validate SKBLOCK!
1976 GNUNET_break (0);
1977 return GNUNET_OK;
1978 default:
1979 /* unknown block type */
1980 GNUNET_break_op (0);
1981 return GNUNET_SYSERR;
1982 }
1983
1984 /* now, lookup 'query' */
1985 prq.data = (const void*) &put[1];
1986 prq.size = dsize;
1987 prq.type = type;
1988 prq.expiration = expiration;
1989 prq.priority = 0;
1990 GNUNET_CONTAINER_multihashmap_get_multiple (request_map,
1991 &query,
1992 &process_reply,
1993 &prq);
1994 // FIXME: if migration is on and load is low,
1995 // queue to store data in datastore;
1996 // use "prq.priority" for that!
1997 return GNUNET_OK;
1998}
1999
2000
2001/**
2002 * List of handlers for P2P messages
2003 * that we care about.
2004 */
2005static struct GNUNET_CORE_MessageHandler p2p_handlers[] =
2006 {
2007 { &handle_p2p_get,
2008 GNUNET_MESSAGE_TYPE_FS_GET, 0 },
2009 { &handle_p2p_put,
2010 GNUNET_MESSAGE_TYPE_FS_PUT, 0 },
2011 { NULL, 0, 0 }
2012 };
2013
2014
2015/**
2016 * Task that will try to initiate a connection with the
2017 * core service.
2018 *
2019 * @param cls unused
2020 * @param tc unused
2021 */
2022static void
2023core_connect_task (void *cls,
2024 const struct GNUNET_SCHEDULER_TaskContext *tc);
2025
2026
2027/**
2028 * Function called by the core after we've
2029 * connected.
2030 */
2031static void
2032core_start_cb (void *cls,
2033 struct GNUNET_CORE_Handle * server,
2034 const struct GNUNET_PeerIdentity *
2035 my_identity,
2036 const struct
2037 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *
2038 publicKey)
2039{
2040 if (server == NULL)
2041 {
2042 GNUNET_SCHEDULER_add_delayed (sched,
2043 GNUNET_NO,
2044 GNUNET_SCHEDULER_PRIORITY_HIGH,
2045 GNUNET_SCHEDULER_NO_TASK,
2046 GNUNET_TIME_UNIT_SECONDS,
2047 &core_connect_task,
2048 NULL);
2049 return;
2050 }
2051 core = server;
2052}
2053
2054
2055/**
2056 * Task that will try to initiate a connection with the
2057 * core service.
2058 *
2059 * @param cls unused
2060 * @param tc unused
2061 */
2062static void
2063core_connect_task (void *cls,
2064 const struct GNUNET_SCHEDULER_TaskContext *tc)
2065{
2066 GNUNET_CORE_connect (sched,
2067 cfg,
2068 GNUNET_TIME_UNIT_FOREVER_REL,
2069 NULL,
2070 &core_start_cb,
2071 NULL,
2072 &peer_disconnect_handler,
2073 NULL,
2074 NULL, GNUNET_NO,
2075 NULL, GNUNET_NO,
2076 p2p_handlers);
885} 2077}
886 2078
887 2079
@@ -899,9 +2091,12 @@ run (void *cls,
899 struct GNUNET_SERVER_Handle *server, 2091 struct GNUNET_SERVER_Handle *server,
900 const struct GNUNET_CONFIGURATION_Handle *c) 2092 const struct GNUNET_CONFIGURATION_Handle *c)
901{ 2093{
902 read_index_list ();
903 sched = s; 2094 sched = s;
904 cfg = c; 2095 cfg = c;
2096
2097 ifm = GNUNET_CONTAINER_multihashmap_create (128);
2098 request_map = GNUNET_CONTAINER_multihashmap_create (128); // FIXME: get size from config
2099 read_index_list ();
905 dsh = GNUNET_DATASTORE_connect (cfg, 2100 dsh = GNUNET_DATASTORE_connect (cfg,
906 sched); 2101 sched);
907 if (NULL == dsh) 2102 if (NULL == dsh)
@@ -914,7 +2109,7 @@ run (void *cls,
914 &handle_client_disconnect, 2109 &handle_client_disconnect,
915 NULL); 2110 NULL);
916 GNUNET_SERVER_add_handlers (server, handlers); 2111 GNUNET_SERVER_add_handlers (server, handlers);
917 // FIXME: also register with core to handle P2P messages! 2112 core_connect_task (NULL, NULL);
918 GNUNET_SCHEDULER_add_delayed (sched, 2113 GNUNET_SCHEDULER_add_delayed (sched,
919 GNUNET_YES, 2114 GNUNET_YES,
920 GNUNET_SCHEDULER_PRIORITY_IDLE, 2115 GNUNET_SCHEDULER_PRIORITY_IDLE,
diff --git a/src/include/gnunet_bio_lib.h b/src/include/gnunet_bio_lib.h
index 2765b4695..2a2639f05 100644
--- a/src/include/gnunet_bio_lib.h
+++ b/src/include/gnunet_bio_lib.h
@@ -88,7 +88,7 @@ int GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
88 * @param maxLen maximum allowed length for the string 88 * @param maxLen maximum allowed length for the string
89 * @return GNUNET_OK on success, GNUNET_SYSERR on failure 89 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
90 */ 90 */
91int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, 91int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h,
92 const char *what, 92 const char *what,
93 char **result, 93 char **result,
94 size_t maxLen); 94 size_t maxLen);
diff --git a/src/include/gnunet_constants.h b/src/include/gnunet_constants.h
index bb122eb64..eb8addf5f 100644
--- a/src/include/gnunet_constants.h
+++ b/src/include/gnunet_constants.h
@@ -63,6 +63,17 @@ extern "C"
63#define GNUNET_CONSTANTS_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10) 63#define GNUNET_CONSTANTS_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10)
64 64
65 65
66/**
67 * Until which load do we consider the peer overly idle
68 * (which means that we would like to use more resources).<p>
69 *
70 * Note that we use 70 to leave some room for applications
71 * to consume resources "idly" (i.e. up to 85%) and then
72 * still have some room for "paid for" resource consumption.
73 */
74#define GNUNET_CONSTANTS_IDLE_LOAD_THRESHOLD 70
75
76
66#if 0 /* keep Emacsens' auto-indent happy */ 77#if 0 /* keep Emacsens' auto-indent happy */
67{ 78{
68#endif 79#endif
diff --git a/src/include/gnunet_core_service.h b/src/include/gnunet_core_service.h
index 5d08552f4..b5dceca3a 100644
--- a/src/include/gnunet_core_service.h
+++ b/src/include/gnunet_core_service.h
@@ -77,7 +77,8 @@ typedef unsigned int
77 (*GNUNET_CORE_BufferFillCallback) (void *cls, 77 (*GNUNET_CORE_BufferFillCallback) (void *cls,
78 const struct GNUNET_PeerIdentity * 78 const struct GNUNET_PeerIdentity *
79 receiver, 79 receiver,
80 void *position, unsigned int padding); 80 void *position,
81 size_t padding);
81 82
82 83
83/** 84/**
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 664b10636..ff35c6b97 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -420,6 +420,18 @@ extern "C"
420 */ 420 */
421#define GNUNET_MESSAGE_TYPE_FS_CONTENT 137 421#define GNUNET_MESSAGE_TYPE_FS_CONTENT 137
422 422
423/**
424 * P2P request for content (one FS to another).
425 */
426#define GNUNET_MESSAGE_TYPE_FS_GET 138
427
428
429/**
430 * P2P response with content or active
431 * migration of content.
432 */
433#define GNUNET_MESSAGE_TYPE_FS_PUT 139
434
423/* 435/*
424 TODO: 436 TODO:
425 - DV 437 - DV