diff options
-rw-r--r-- | TODO | 56 | ||||
-rw-r--r-- | contrib/defaults.conf | 12 | ||||
-rw-r--r-- | src/core/core_api.c | 4 | ||||
-rw-r--r-- | src/fs/fs.h | 177 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs.c | 1617 | ||||
-rw-r--r-- | src/include/gnunet_bio_lib.h | 2 | ||||
-rw-r--r-- | src/include/gnunet_constants.h | 11 | ||||
-rw-r--r-- | src/include/gnunet_core_service.h | 3 | ||||
-rw-r--r-- | src/include/gnunet_protocols.h | 12 |
9 files changed, 1648 insertions, 246 deletions
@@ -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 | |||
16 | Urgent items (before announcing ng.gnunet.org): | 15 | Urgent 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): | |||
64 | 0.9.0pre0: | 54 | 0.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 | ||
104 | 0.9.0pre1: | 100 | 0.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] |
179 | FILENAME = $SERVICEHOME/datastore/sqlite.db | 179 | FILENAME = $SERVICEHOME/datastore/sqlite.db |
180 | |||
181 | [fs] | ||
182 | INDEXDB = $SERVICEHOME/idxinfo.lst | ||
183 | PORT = 2094 | ||
184 | HOSTNAME = localhost | ||
185 | HOME = $SERVICEHOME | ||
186 | CONFIG = $DEFAULTCONFIG | ||
187 | BINARY = gnunet-service-fs | ||
188 | ACCEPT_FROM = 127.0.0.1; | ||
189 | ACCEPT_FROM6 = ::1; | ||
190 | ALLOW_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 | */ | ||
1342 | struct 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 | */ | ||
1400 | struct 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 | */ | ||
43 | static struct GNUNET_DATASTORE_Handle *dsh; | ||
44 | |||
45 | /** | ||
46 | * Our scheduler. | ||
47 | */ | ||
48 | static struct GNUNET_SCHEDULER_Handle *sched; | ||
49 | |||
50 | /** | ||
51 | * Our configuration. | ||
52 | */ | ||
53 | const 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 | */ | ||
90 | typedef void (*RequestFunction)(void *cls, | ||
91 | int ok); | ||
92 | |||
93 | |||
94 | /** | ||
95 | * Doubly-linked list of our requests for the datastore. | ||
96 | */ | ||
97 | struct 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 | */ | ||
136 | struct 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 | */ | ||
226 | enum 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 | */ | ||
261 | struct 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 | */ | ||
347 | struct PendingRequest | ||
348 | { | ||
349 | // FIXME | ||
350 | }; | ||
351 | |||
352 | |||
353 | /** | ||
354 | * Closure for "process_reply" function. | ||
355 | */ | ||
356 | struct 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 | */ | ||
389 | static struct GNUNET_CONTAINER_MultiHashMap *request_map; | ||
390 | |||
391 | /** | ||
392 | * Our connection to the datastore. | ||
393 | */ | ||
394 | static struct GNUNET_DATASTORE_Handle *dsh; | ||
395 | |||
396 | /** | ||
397 | * Our scheduler. | ||
398 | */ | ||
399 | static struct GNUNET_SCHEDULER_Handle *sched; | ||
400 | |||
401 | /** | ||
402 | * Our configuration. | ||
403 | */ | ||
404 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
405 | |||
406 | /** | ||
407 | * Handle to the core service (NULL until we've | ||
408 | * connected to it). | ||
409 | */ | ||
410 | struct GNUNET_CORE_Handle *core; | ||
411 | |||
412 | /** | ||
413 | * Head of doubly-linked LGC list. | ||
414 | */ | ||
415 | static struct LocalGetContext *lgc_head; | ||
416 | |||
417 | /** | ||
418 | * Tail of doubly-linked LGC list. | ||
419 | */ | ||
420 | static struct LocalGetContext *lgc_tail; | ||
421 | |||
422 | /** | ||
423 | * Head of request queue for the datastore, sorted by timeout. | ||
424 | */ | ||
425 | static struct DatastoreRequestQueue *drq_head; | ||
426 | |||
427 | /** | ||
428 | * Tail of request queue for the datastore. | ||
429 | */ | ||
430 | static struct DatastoreRequestQueue *drq_tail; | ||
431 | |||
432 | /** | ||
89 | * Linked list of indexed files. | 433 | * Linked list of indexed files. |
90 | */ | 434 | */ |
91 | static struct IndexInfo *indexed_files; | 435 | static 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 | */ | ||
443 | static 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; | |||
97 | static void | 449 | static void |
98 | write_index_list () | 450 | write_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 () | |||
107 | static void | 506 | static void |
108 | read_index_list () | 507 | read_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 () | |||
121 | static void | 583 | static void |
122 | signal_index_ok (struct IndexInfo *ii) | 584 | signal_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 | */ | ||
350 | typedef void (*RequestFunction)(void *cls, | ||
351 | int ok); | ||
352 | |||
353 | |||
354 | /** | ||
355 | * Doubly-linked list of our requests for the datastore. | ||
356 | */ | ||
357 | struct 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 | */ | ||
396 | static struct DatastoreRequestQueue *drq_head; | ||
397 | |||
398 | /** | ||
399 | * Tail of request queue for the datastore. | ||
400 | */ | ||
401 | static 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 | */ | ||
508 | struct 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 | */ | ||
598 | static struct LocalGetContext *lgc_head; | ||
599 | |||
600 | /** | ||
601 | * Tail of doubly-linked LGC list. | ||
602 | */ | ||
603 | static 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 | */ | ||
992 | static void | ||
993 | remove_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 | */ | ||
1009 | static void | ||
1010 | mingle_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 | */ | ||
1043 | static void | ||
1044 | handle_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 | |||
879 | shutdown_task (void *cls, | 1398 | shutdown_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 | */ | ||
1427 | static void | ||
1428 | peer_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 | */ | ||
1446 | static void | ||
1447 | forward_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 | */ | ||
1473 | static size_t | ||
1474 | transmit_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 | */ | ||
1504 | static int | ||
1505 | test_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 | */ | ||
1528 | static void | ||
1529 | process_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 | */ | ||
1639 | static void | ||
1640 | ds_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 | */ | ||
1676 | static int32_t | ||
1677 | bound_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 | */ | ||
1703 | static uint32_t | ||
1704 | bound_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 | */ | ||
1721 | static int | ||
1722 | handle_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 | */ | ||
1891 | static int | ||
1892 | process_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 | */ | ||
1916 | static int | ||
1917 | handle_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 | */ | ||
2005 | static 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 | */ | ||
2022 | static void | ||
2023 | core_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 | */ | ||
2031 | static void | ||
2032 | core_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 | */ | ||
2062 | static void | ||
2063 | core_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 | */ |
91 | int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, | 91 | int 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 |