aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-service-fs_lc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/gnunet-service-fs_lc.c')
-rw-r--r--src/fs/gnunet-service-fs_lc.c306
1 files changed, 132 insertions, 174 deletions
diff --git a/src/fs/gnunet-service-fs_lc.c b/src/fs/gnunet-service-fs_lc.c
index 18f5c10dc..aa6569387 100644
--- a/src/fs/gnunet-service-fs_lc.c
+++ b/src/fs/gnunet-service-fs_lc.c
@@ -170,16 +170,13 @@ GSF_local_client_lookup_ (struct GNUNET_SERVER_Client *client)
170 struct GSF_LocalClient *pos; 170 struct GSF_LocalClient *pos;
171 171
172 pos = client_head; 172 pos = client_head;
173 while ( (pos != NULL) && 173 while ((pos != NULL) && (pos->client != client))
174 (pos->client != client) )
175 pos = pos->next; 174 pos = pos->next;
176 if (pos != NULL) 175 if (pos != NULL)
177 return pos; 176 return pos;
178 pos = GNUNET_malloc (sizeof (struct GSF_LocalClient)); 177 pos = GNUNET_malloc (sizeof (struct GSF_LocalClient));
179 pos->client = client; 178 pos->client = client;
180 GNUNET_CONTAINER_DLL_insert (client_head, 179 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, pos);
181 client_tail,
182 pos);
183 return pos; 180 return pos;
184} 181}
185 182
@@ -189,24 +186,21 @@ GSF_local_client_lookup_ (struct GNUNET_SERVER_Client *client)
189 * 186 *
190 * @param cls the client request to free 187 * @param cls the client request to free
191 * @param tc task context 188 * @param tc task context
192 */ 189 */
193static void 190static void
194client_request_destroy (void *cls, 191client_request_destroy (void *cls,
195 const struct GNUNET_SCHEDULER_TaskContext *tc) 192 const struct GNUNET_SCHEDULER_TaskContext *tc)
196{ 193{
197 struct ClientRequest *cr = cls; 194 struct ClientRequest *cr = cls;
198 struct GSF_LocalClient *lc; 195 struct GSF_LocalClient *lc;
199 196
200 cr->kill_task = GNUNET_SCHEDULER_NO_TASK; 197 cr->kill_task = GNUNET_SCHEDULER_NO_TASK;
201 lc = cr->lc; 198 lc = cr->lc;
202 GNUNET_CONTAINER_DLL_remove (lc->cr_head, 199 GNUNET_CONTAINER_DLL_remove (lc->cr_head, lc->cr_tail, cr);
203 lc->cr_tail,
204 cr);
205 GSF_pending_request_cancel_ (cr->pr, GNUNET_NO); 200 GSF_pending_request_cancel_ (cr->pr, GNUNET_NO);
206 GNUNET_STATISTICS_update (GSF_stats, 201 GNUNET_STATISTICS_update (GSF_stats,
207 gettext_noop ("# client searches active"), 202 gettext_noop ("# client searches active"),
208 - 1, 203 -1, GNUNET_NO);
209 GNUNET_NO);
210 GNUNET_free (cr); 204 GNUNET_free (cr);
211} 205}
212 206
@@ -230,13 +224,12 @@ client_request_destroy (void *cls,
230 */ 224 */
231static void 225static void
232client_response_handler (void *cls, 226client_response_handler (void *cls,
233 enum GNUNET_BLOCK_EvaluationResult eval, 227 enum GNUNET_BLOCK_EvaluationResult eval,
234 struct GSF_PendingRequest *pr, 228 struct GSF_PendingRequest *pr,
235 uint32_t reply_anonymity_level, 229 uint32_t reply_anonymity_level,
236 struct GNUNET_TIME_Absolute expiration, 230 struct GNUNET_TIME_Absolute expiration,
237 enum GNUNET_BLOCK_Type type, 231 enum GNUNET_BLOCK_Type type,
238 const void *data, 232 const void *data, size_t data_len)
239 size_t data_len)
240{ 233{
241 struct ClientRequest *cr = cls; 234 struct ClientRequest *cr = cls;
242 struct GSF_LocalClient *lc; 235 struct GSF_LocalClient *lc;
@@ -245,47 +238,44 @@ client_response_handler (void *cls,
245 size_t msize; 238 size_t msize;
246 239
247 if (NULL == data) 240 if (NULL == data)
248 { 241 {
249 /* ugh, request 'timed out' -- how can this be? */ 242 /* ugh, request 'timed out' -- how can this be? */
250 GNUNET_break (0); 243 GNUNET_break (0);
251 return; 244 return;
252 } 245 }
253 prd = GSF_pending_request_get_data_ (pr); 246 prd = GSF_pending_request_get_data_ (pr);
254 GNUNET_break (type != GNUNET_BLOCK_TYPE_ANY); 247 GNUNET_break (type != GNUNET_BLOCK_TYPE_ANY);
255 if ( (prd->type != type) && 248 if ((prd->type != type) && (prd->type != GNUNET_BLOCK_TYPE_ANY))
256 (prd->type != GNUNET_BLOCK_TYPE_ANY) ) 249 {
257 { 250 GNUNET_break (0);
258 GNUNET_break (0); 251 return;
259 return; 252 }
260 }
261 GNUNET_STATISTICS_update (GSF_stats, 253 GNUNET_STATISTICS_update (GSF_stats,
262 gettext_noop ("# replies received for local clients"), 254 gettext_noop
263 1, 255 ("# replies received for local clients"), 1,
264 GNUNET_NO); 256 GNUNET_NO);
265 GNUNET_assert (pr == cr->pr); 257 GNUNET_assert (pr == cr->pr);
266 lc = cr->lc; 258 lc = cr->lc;
267 msize = sizeof (struct PutMessage) + data_len; 259 msize = sizeof (struct PutMessage) + data_len;
268 { 260 {
269 char buf[msize]; 261 char buf[msize];
270 262
271 pm = (struct PutMessage*) buf; 263 pm = (struct PutMessage *) buf;
272 pm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_PUT); 264 pm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_PUT);
273 pm->header.size = htons (msize); 265 pm->header.size = htons (msize);
274 pm->type = htonl (type); 266 pm->type = htonl (type);
275 pm->expiration = GNUNET_TIME_absolute_hton (expiration); 267 pm->expiration = GNUNET_TIME_absolute_hton (expiration);
276 memcpy (&pm[1], data, data_len); 268 memcpy (&pm[1], data, data_len);
277 GSF_local_client_transmit_ (lc, &pm->header); 269 GSF_local_client_transmit_ (lc, &pm->header);
278 } 270 }
279#if DEBUG_FS_CLIENT 271#if DEBUG_FS_CLIENT
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
281 "Queued reply to query `%s' for local client\n", 273 "Queued reply to query `%s' for local client\n",
282 GNUNET_h2s (&prd->query), 274 GNUNET_h2s (&prd->query), (unsigned int) prd->type);
283 (unsigned int) prd->type);
284#endif 275#endif
285 if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST) 276 if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST)
286 return; 277 return;
287 cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy, 278 cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy, cr);
288 cr);
289} 279}
290 280
291 281
@@ -298,7 +288,8 @@ client_response_handler (void *cls,
298 */ 288 */
299struct GSF_PendingRequest * 289struct GSF_PendingRequest *
300GSF_local_client_start_search_handler_ (struct GNUNET_SERVER_Client *client, 290GSF_local_client_start_search_handler_ (struct GNUNET_SERVER_Client *client,
301 const struct GNUNET_MessageHeader *message) 291 const struct GNUNET_MessageHeader
292 *message)
302{ 293{
303 static GNUNET_HashCode all_zeros; 294 static GNUNET_HashCode all_zeros;
304 const struct SearchMessage *sm; 295 const struct SearchMessage *sm;
@@ -311,99 +302,84 @@ GSF_local_client_start_search_handler_ (struct GNUNET_SERVER_Client *client,
311 enum GSF_PendingRequestOptions options; 302 enum GSF_PendingRequestOptions options;
312 303
313 msize = ntohs (message->size); 304 msize = ntohs (message->size);
314 if ( (msize < sizeof (struct SearchMessage)) || 305 if ((msize < sizeof (struct SearchMessage)) ||
315 (0 != (msize - sizeof (struct SearchMessage)) % sizeof (GNUNET_HashCode)) ) 306 (0 != (msize - sizeof (struct SearchMessage)) % sizeof (GNUNET_HashCode)))
316 { 307 {
317 GNUNET_break (0); 308 GNUNET_break (0);
318 GNUNET_SERVER_receive_done (client, 309 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
319 GNUNET_SYSERR); 310 return NULL;
320 return NULL; 311 }
321 }
322 GNUNET_STATISTICS_update (GSF_stats, 312 GNUNET_STATISTICS_update (GSF_stats,
323 gettext_noop ("# client searches received"), 313 gettext_noop ("# client searches received"),
324 1, 314 1, GNUNET_NO);
325 GNUNET_NO);
326 sc = (msize - sizeof (struct SearchMessage)) / sizeof (GNUNET_HashCode); 315 sc = (msize - sizeof (struct SearchMessage)) / sizeof (GNUNET_HashCode);
327 sm = (const struct SearchMessage*) message; 316 sm = (const struct SearchMessage *) message;
328 type = ntohl (sm->type); 317 type = ntohl (sm->type);
329#if DEBUG_FS_CLIENT 318#if DEBUG_FS_CLIENT
330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
331 "Received request for `%s' of type %u from local client\n", 320 "Received request for `%s' of type %u from local client\n",
332 GNUNET_h2s (&sm->query), 321 GNUNET_h2s (&sm->query), (unsigned int) type);
333 (unsigned int) type);
334#endif 322#endif
335 lc = GSF_local_client_lookup_ (client); 323 lc = GSF_local_client_lookup_ (client);
336 324
337 /* detect duplicate KBLOCK requests */ 325 /* detect duplicate KBLOCK requests */
338 if ( (type == GNUNET_BLOCK_TYPE_FS_KBLOCK) || 326 if ((type == GNUNET_BLOCK_TYPE_FS_KBLOCK) ||
339 (type == GNUNET_BLOCK_TYPE_FS_NBLOCK) || 327 (type == GNUNET_BLOCK_TYPE_FS_NBLOCK) || (type == GNUNET_BLOCK_TYPE_ANY))
340 (type == GNUNET_BLOCK_TYPE_ANY) ) 328 {
329 /* FIXME: this does currently not work to filter duplicate
330 * results from *local* datastore since the local store is
331 * queried before we continue to process additional
332 * messages from the client! -- fix protocol? */
333 cr = lc->cr_head;
334 while (cr != NULL)
335 {
336 prd = GSF_pending_request_get_data_ (cr->pr);
337 if ((0 != memcmp (&prd->query,
338 &sm->query,
339 sizeof (GNUNET_HashCode))) && (prd->type == type))
340 break;
341 cr = cr->next;
342 }
343 if (cr != NULL)
341 { 344 {
342 /* FIXME: this does currently not work to filter duplicate
343 results from *local* datastore since the local store is
344 queried before we continue to process additional
345 messages from the client! -- fix protocol? */
346 cr = lc->cr_head;
347 while (cr != NULL)
348 {
349 prd = GSF_pending_request_get_data_ (cr->pr);
350 if ( (0 != memcmp (&prd->query,
351 &sm->query,
352 sizeof (GNUNET_HashCode))) &&
353 (prd->type == type) )
354 break;
355 cr = cr->next;
356 }
357 if (cr != NULL)
358 {
359#if DEBUG_FS_CLIENT 345#if DEBUG_FS_CLIENT
360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 346 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
361 "Have existing request, merging content-seen lists.\n"); 347 "Have existing request, merging content-seen lists.\n");
362#endif 348#endif
363 GSF_pending_request_update_ (cr->pr, 349 GSF_pending_request_update_ (cr->pr,
364 (const GNUNET_HashCode*) &sm[1], 350 (const GNUNET_HashCode *) &sm[1], sc);
365 sc); 351 GNUNET_STATISTICS_update (GSF_stats,
366 GNUNET_STATISTICS_update (GSF_stats, 352 gettext_noop
367 gettext_noop ("# client searches updated (merged content seen list)"), 353 ("# client searches updated (merged content seen list)"),
368 1, 354 1, GNUNET_NO);
369 GNUNET_NO); 355 GNUNET_SERVER_receive_done (client, GNUNET_OK);
370 GNUNET_SERVER_receive_done (client, 356 return NULL;
371 GNUNET_OK);
372 return NULL;
373 }
374 } 357 }
358 }
375 359
376 GNUNET_STATISTICS_update (GSF_stats, 360 GNUNET_STATISTICS_update (GSF_stats,
377 gettext_noop ("# client searches active"), 361 gettext_noop ("# client searches active"),
378 1, 362 1, GNUNET_NO);
379 GNUNET_NO);
380 cr = GNUNET_malloc (sizeof (struct ClientRequest)); 363 cr = GNUNET_malloc (sizeof (struct ClientRequest));
381 cr->lc = lc; 364 cr->lc = lc;
382 GNUNET_CONTAINER_DLL_insert (lc->cr_head, 365 GNUNET_CONTAINER_DLL_insert (lc->cr_head, lc->cr_tail, cr);
383 lc->cr_tail, 366 options = GSF_PRO_LOCAL_REQUEST;
384 cr);
385 options = GSF_PRO_LOCAL_REQUEST;
386 if (0 != (1 & ntohl (sm->options))) 367 if (0 != (1 & ntohl (sm->options)))
387 options |= GSF_PRO_LOCAL_ONLY; 368 options |= GSF_PRO_LOCAL_ONLY;
388 cr->pr = GSF_pending_request_create_ (options, 369 cr->pr = GSF_pending_request_create_ (options, type, &sm->query, (type == GNUNET_BLOCK_TYPE_FS_SBLOCK) ? &sm->target /* namespace */
389 type, 370 : NULL,
390 &sm->query, 371 (0 != memcmp (&sm->target,
391 (type == GNUNET_BLOCK_TYPE_FS_SBLOCK) 372 &all_zeros,
392 ? &sm->target /* namespace */ 373 sizeof (GNUNET_HashCode)))
393 : NULL, 374 ? (const struct GNUNET_PeerIdentity *)
394 (0 != memcmp (&sm->target, 375 &sm->target : NULL, NULL, 0,
395 &all_zeros, 376 0 /* bf */ ,
396 sizeof (GNUNET_HashCode))) 377 ntohl (sm->anonymity_level),
397 ? (const struct GNUNET_PeerIdentity*) &sm->target 378 0 /* priority */ ,
398 : NULL, 379 0 /* ttl */ ,
399 NULL, 0, 0 /* bf */, 380 0 /* sender PID */ ,
400 ntohl (sm->anonymity_level), 381 (const GNUNET_HashCode *) &sm[1], sc,
401 0 /* priority */, 382 &client_response_handler, cr);
402 0 /* ttl */,
403 0 /* sender PID */,
404 (const GNUNET_HashCode*) &sm[1], sc,
405 &client_response_handler,
406 cr);
407 return cr->pr; 383 return cr->pr;
408} 384}
409 385
@@ -422,36 +398,30 @@ GSF_local_client_start_search_handler_ (struct GNUNET_SERVER_Client *client,
422 * @return number of bytes written to buf 398 * @return number of bytes written to buf
423 */ 399 */
424static size_t 400static size_t
425transmit_to_client (void *cls, 401transmit_to_client (void *cls, size_t size, void *buf)
426 size_t size,
427 void *buf)
428{ 402{
429 struct GSF_LocalClient *lc = cls; 403 struct GSF_LocalClient *lc = cls;
430 char *cbuf = buf; 404 char *cbuf = buf;
431 struct ClientResponse *res; 405 struct ClientResponse *res;
432 size_t msize; 406 size_t msize;
433 407
434 lc->th = NULL; 408 lc->th = NULL;
435 if (NULL == buf) 409 if (NULL == buf)
436 return 0; 410 return 0;
437 msize = 0; 411 msize = 0;
438 while ( (NULL != (res = lc->res_head) ) && 412 while ((NULL != (res = lc->res_head)) && (res->msize <= size))
439 (res->msize <= size) ) 413 {
440 { 414 memcpy (&cbuf[msize], &res[1], res->msize);
441 memcpy (&cbuf[msize], &res[1], res->msize); 415 msize += res->msize;
442 msize += res->msize; 416 size -= res->msize;
443 size -= res->msize; 417 GNUNET_CONTAINER_DLL_remove (lc->res_head, lc->res_tail, res);
444 GNUNET_CONTAINER_DLL_remove (lc->res_head, 418 GNUNET_free (res);
445 lc->res_tail, 419 }
446 res);
447 GNUNET_free (res);
448 }
449 if (NULL != res) 420 if (NULL != res)
450 lc->th = GNUNET_SERVER_notify_transmit_ready (lc->client, 421 lc->th = GNUNET_SERVER_notify_transmit_ready (lc->client,
451 res->msize, 422 res->msize,
452 GNUNET_TIME_UNIT_FOREVER_REL, 423 GNUNET_TIME_UNIT_FOREVER_REL,
453 &transmit_to_client, 424 &transmit_to_client, lc);
454 lc);
455 return msize; 425 return msize;
456} 426}
457 427
@@ -466,7 +436,7 @@ transmit_to_client (void *cls,
466 */ 436 */
467void 437void
468GSF_local_client_transmit_ (struct GSF_LocalClient *lc, 438GSF_local_client_transmit_ (struct GSF_LocalClient *lc,
469 const struct GNUNET_MessageHeader *msg) 439 const struct GNUNET_MessageHeader *msg)
470{ 440{
471 struct ClientResponse *res; 441 struct ClientResponse *res;
472 size_t msize; 442 size_t msize;
@@ -476,15 +446,12 @@ GSF_local_client_transmit_ (struct GSF_LocalClient *lc,
476 res->lc = lc; 446 res->lc = lc;
477 res->msize = msize; 447 res->msize = msize;
478 memcpy (&res[1], msg, msize); 448 memcpy (&res[1], msg, msize);
479 GNUNET_CONTAINER_DLL_insert_tail (lc->res_head, 449 GNUNET_CONTAINER_DLL_insert_tail (lc->res_head, lc->res_tail, res);
480 lc->res_tail,
481 res);
482 if (NULL == lc->th) 450 if (NULL == lc->th)
483 lc->th = GNUNET_SERVER_notify_transmit_ready (lc->client, 451 lc->th = GNUNET_SERVER_notify_transmit_ready (lc->client,
484 msize, 452 msize,
485 GNUNET_TIME_UNIT_FOREVER_REL, 453 GNUNET_TIME_UNIT_FOREVER_REL,
486 &transmit_to_client, 454 &transmit_to_client, lc);
487 lc);
488} 455}
489 456
490 457
@@ -496,49 +463,40 @@ GSF_local_client_transmit_ (struct GSF_LocalClient *lc,
496 * @param client handle of the client 463 * @param client handle of the client
497 */ 464 */
498void 465void
499GSF_client_disconnect_handler_ (void *cls, 466GSF_client_disconnect_handler_ (void *cls, struct GNUNET_SERVER_Client *client)
500 struct GNUNET_SERVER_Client *client)
501{ 467{
502 struct GSF_LocalClient *pos; 468 struct GSF_LocalClient *pos;
503 struct ClientRequest *cr; 469 struct ClientRequest *cr;
504 struct ClientResponse *res; 470 struct ClientResponse *res;
505 471
506 pos = client_head; 472 pos = client_head;
507 while ( (pos != NULL) && 473 while ((pos != NULL) && (pos->client != client))
508 (pos->client != client) )
509 pos = pos->next; 474 pos = pos->next;
510 if (pos == NULL) 475 if (pos == NULL)
511 return; 476 return;
512 while (NULL != (cr = pos->cr_head)) 477 while (NULL != (cr = pos->cr_head))
513 { 478 {
514 GNUNET_CONTAINER_DLL_remove (pos->cr_head, 479 GNUNET_CONTAINER_DLL_remove (pos->cr_head, pos->cr_tail, cr);
515 pos->cr_tail, 480 GSF_pending_request_cancel_ (cr->pr, GNUNET_NO);
516 cr); 481 GNUNET_STATISTICS_update (GSF_stats,
517 GSF_pending_request_cancel_ (cr->pr, GNUNET_NO); 482 gettext_noop ("# client searches active"),
518 GNUNET_STATISTICS_update (GSF_stats, 483 -1, GNUNET_NO);
519 gettext_noop ("# client searches active"), 484 if (GNUNET_SCHEDULER_NO_TASK != cr->kill_task)
520 - 1, 485 GNUNET_SCHEDULER_cancel (cr->kill_task);
521 GNUNET_NO); 486 GNUNET_free (cr);
522 if (GNUNET_SCHEDULER_NO_TASK != cr->kill_task) 487 }
523 GNUNET_SCHEDULER_cancel (cr->kill_task);
524 GNUNET_free (cr);
525 }
526 while (NULL != (res = pos->res_head)) 488 while (NULL != (res = pos->res_head))
527 { 489 {
528 GNUNET_CONTAINER_DLL_remove (pos->res_head, 490 GNUNET_CONTAINER_DLL_remove (pos->res_head, pos->res_tail, res);
529 pos->res_tail, 491 GNUNET_free (res);
530 res); 492 }
531 GNUNET_free (res);
532 }
533 if (pos->th != NULL) 493 if (pos->th != NULL)
534 { 494 {
535 GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th); 495 GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
536 pos->th = NULL; 496 pos->th = NULL;
537 } 497 }
538 GSF_handle_local_client_disconnect_ (pos); 498 GSF_handle_local_client_disconnect_ (pos);
539 GNUNET_CONTAINER_DLL_remove (client_head, 499 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, pos);
540 client_tail,
541 pos);
542 GNUNET_free (pos); 500 GNUNET_free (pos);
543} 501}
544 502