aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-service-fs.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-10-01 12:53:07 +0000
committerChristian Grothoff <christian@grothoff.org>2016-10-01 12:53:07 +0000
commitf7fac7f6736df4e350a8b5ed7d9f51782d7e039e (patch)
tree6eee38f2dbc4de932c22d213dde60cf06992b127 /src/fs/gnunet-service-fs.c
parent760f75d2d87f01ca93ebfb349eedbb4224c03c7c (diff)
downloadgnunet-f7fac7f6736df4e350a8b5ed7d9f51782d7e039e.tar.gz
gnunet-f7fac7f6736df4e350a8b5ed7d9f51782d7e039e.zip
migrating fs to new service API
Diffstat (limited to 'src/fs/gnunet-service-fs.c')
-rw-r--r--src/fs/gnunet-service-fs.c850
1 files changed, 744 insertions, 106 deletions
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index 4131b1670..c83d73555 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -68,6 +68,161 @@
68#define INSANE_STATISTICS GNUNET_NO 68#define INSANE_STATISTICS GNUNET_NO
69 69
70 70
71
72/**
73 * Doubly-linked list of requests we are performing
74 * on behalf of the same client.
75 */
76struct ClientRequest
77{
78
79 /**
80 * This is a doubly-linked list.
81 */
82 struct ClientRequest *next;
83
84 /**
85 * This is a doubly-linked list.
86 */
87 struct ClientRequest *prev;
88
89 /**
90 * Request this entry represents.
91 */
92 struct GSF_PendingRequest *pr;
93
94 /**
95 * Client list this request belongs to.
96 */
97 struct GSF_LocalClient *lc;
98
99 /**
100 * Task scheduled to destroy the request.
101 */
102 struct GNUNET_SCHEDULER_Task * kill_task;
103
104};
105
106
107/**
108 * Replies to be transmitted to the client. The actual
109 * response message is allocated after this struct.
110 */
111struct ClientResponse
112{
113 /**
114 * This is a doubly-linked list.
115 */
116 struct ClientResponse *next;
117
118 /**
119 * This is a doubly-linked list.
120 */
121 struct ClientResponse *prev;
122
123 /**
124 * Client list entry this response belongs to.
125 */
126 struct GSF_LocalClient *lc;
127
128 /**
129 * Number of bytes in the response.
130 */
131 size_t msize;
132};
133
134
135/**
136 * Information we track while handling an index
137 * start request from a client.
138 */
139struct IndexStartContext
140{
141
142 /**
143 * This is a doubly linked list.
144 */
145 struct IndexStartContext *next;
146
147 /**
148 * This is a doubly linked list.
149 */
150 struct IndexStartContext *prev;
151
152 /**
153 * Name of the indexed file.
154 */
155 char *filename;
156
157 /**
158 * Context for transmitting confirmation to client.
159 */
160 struct GSF_LocalClient *lc;
161
162 /**
163 * Context for hashing of the file.
164 */
165 struct GNUNET_CRYPTO_FileHashContext *fhc;
166
167 /**
168 * Hash of the contents of the file.
169 */
170 struct GNUNET_HashCode file_id;
171
172};
173
174
175/**
176 * A local client.
177 */
178struct GSF_LocalClient
179{
180
181 /**
182 * ID of the client.
183 */
184 struct GNUNET_SERVICE_Client *client;
185
186 /**
187 * Queue for sending replies.
188 */
189 struct GNUNET_MQ_Handle *mq;
190
191 /**
192 * Head of list of requests performed on behalf
193 * of this client right now.
194 */
195 struct ClientRequest *cr_head;
196
197 /**
198 * Tail of list of requests performed on behalf
199 * of this client right now.
200 */
201 struct ClientRequest *cr_tail;
202
203 /**
204 * This is a doubly linked list.
205 */
206 struct IndexStartContext *isc_head;
207
208 /**
209 * This is a doubly linked list.
210 */
211 struct IndexStartContext *isc_tail;
212
213 /**
214 * Head of linked list of responses.
215 */
216 struct ClientResponse *res_head;
217
218 /**
219 * Tail of linked list of responses.
220 */
221 struct ClientResponse *res_tail;
222
223};
224
225
71/* ****************************** globals ****************************** */ 226/* ****************************** globals ****************************** */
72 227
73/** 228/**
@@ -152,6 +307,11 @@ struct GNUNET_CORE_Handle *GSF_core;
152 */ 307 */
153int GSF_enable_randomized_delays; 308int GSF_enable_randomized_delays;
154 309
310/**
311 * Identity of this peer.
312 */
313struct GNUNET_PeerIdentity GSF_my_id;
314
155/* ***************************** locals ******************************* */ 315/* ***************************** locals ******************************* */
156 316
157/** 317/**
@@ -174,10 +334,183 @@ static struct GNUNET_SCHEDULER_Task * cover_age_task;
174 */ 334 */
175static struct GNUNET_LOAD_Value *datastore_get_load; 335static struct GNUNET_LOAD_Value *datastore_get_load;
176 336
337
177/** 338/**
178 * Identity of this peer. 339 * Creates a fresh local client handle.
340 *
341 * @param cls NULL
342 * @param client handle of the client
343 * @param mq message queue for @a client
344 * @return handle to local client entry
179 */ 345 */
180struct GNUNET_PeerIdentity GSF_my_id; 346static void *
347client_connect_cb (void *cls,
348 struct GNUNET_SERVICE_Client *client,
349 struct GNUNET_MQ_Handle *mq)
350{
351 struct GSF_LocalClient *pos;
352
353 pos = GNUNET_new (struct GSF_LocalClient);
354 pos->client = client;
355 pos->mq = mq;
356 return pos;
357}
358
359
360/**
361 * Free the given client request.
362 *
363 * @param cls the client request to free
364 */
365static void
366client_request_destroy (void *cls)
367{
368 struct ClientRequest *cr = cls;
369 struct GSF_LocalClient *lc = cr->lc;
370
371 cr->kill_task = NULL;
372 GNUNET_CONTAINER_DLL_remove (lc->cr_head,
373 lc->cr_tail,
374 cr);
375 GSF_pending_request_cancel_ (cr->pr,
376 GNUNET_YES);
377 GNUNET_STATISTICS_update (GSF_stats,
378 gettext_noop ("# client searches active"),
379 -1,
380 GNUNET_NO);
381 GNUNET_free (cr);
382}
383
384
385/**
386 * Handle a reply to a pending request. Also called if a request
387 * expires (then with data == NULL). The handler may be called
388 * many times (depending on the request type), but will not be
389 * called during or after a call to #GSF_pending_request_cancel()
390 * and will also not be called anymore after a call signalling
391 * expiration.
392 *
393 * @param cls user-specified closure
394 * @param eval evaluation of the result
395 * @param pr handle to the original pending request
396 * @param reply_anonymity_level anonymity level for the reply, UINT32_MAX for "unknown"
397 * @param expiration when does @a data expire?
398 * @param last_transmission when was the last time we've tried to download this block? (FOREVER if unknown)
399 * @param type type of the block
400 * @param data response data, NULL on request expiration
401 * @param data_len number of bytes in @a data
402 */
403static void
404client_response_handler (void *cls,
405 enum GNUNET_BLOCK_EvaluationResult eval,
406 struct GSF_PendingRequest *pr,
407 uint32_t reply_anonymity_level,
408 struct GNUNET_TIME_Absolute expiration,
409 struct GNUNET_TIME_Absolute last_transmission,
410 enum GNUNET_BLOCK_Type type,
411 const void *data,
412 size_t data_len)
413{
414 struct ClientRequest *cr = cls;
415 struct GSF_LocalClient *lc;
416 struct GNUNET_MQ_Envelope *env;
417 struct ClientPutMessage *pm;
418 const struct GSF_PendingRequestData *prd;
419
420 if (NULL == data)
421 {
422 /* local-only request, with no result, clean up. */
423 if (NULL == cr->kill_task)
424 cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy,
425 cr);
426 return;
427 }
428 prd = GSF_pending_request_get_data_ (pr);
429 GNUNET_break (type != GNUNET_BLOCK_TYPE_ANY);
430 if ((prd->type != type) && (prd->type != GNUNET_BLOCK_TYPE_ANY))
431 {
432 GNUNET_break (0);
433 return;
434 }
435 GNUNET_STATISTICS_update (GSF_stats,
436 gettext_noop
437 ("# replies received for local clients"), 1,
438 GNUNET_NO);
439 GNUNET_assert (pr == cr->pr);
440 lc = cr->lc;
441 env = GNUNET_MQ_msg_extra (pm,
442 data_len,
443 GNUNET_MESSAGE_TYPE_FS_PUT);
444 pm->type = htonl (type);
445 pm->expiration = GNUNET_TIME_absolute_hton (expiration);
446 pm->last_transmission = GNUNET_TIME_absolute_hton (last_transmission);
447 pm->num_transmissions = htonl (prd->num_transmissions);
448 pm->respect_offered = htonl (prd->respect_offered);
449 GNUNET_memcpy (&pm[1],
450 data,
451 data_len);
452 GNUNET_MQ_send (lc->mq,
453 env);
454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
455 "Queued reply to query `%s' for local client\n",
456 GNUNET_h2s (&prd->query));
457 if (GNUNET_BLOCK_EVALUATION_OK_LAST != eval)
458 {
459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
460 "Evaluation %d - keeping query alive\n",
461 (int) eval);
462 return;
463 }
464 if (NULL == cr->kill_task)
465 cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy,
466 cr);
467}
468
469
470/**
471 * A client disconnected from us. Tear down the local client
472 * record.
473 *
474 * @param cls unused
475 * @param client handle of the client
476 * @param app_ctx the `struct GSF_LocalClient`
477 */
478static void
479client_disconnect_cb (void *cls,
480 struct GNUNET_SERVICE_Client *client,
481 void *app_ctx)
482{
483 struct GSF_LocalClient *lc = app_ctx;
484 struct IndexStartContext *isc;
485 struct ClientRequest *cr;
486 struct ClientResponse *res;
487
488 while (NULL != (cr = lc->cr_head))
489 {
490 if (NULL != cr->kill_task)
491 GNUNET_SCHEDULER_cancel (cr->kill_task);
492 client_request_destroy (cr);
493 }
494 while (NULL != (res = lc->res_head))
495 {
496 GNUNET_CONTAINER_DLL_remove (lc->res_head,
497 lc->res_tail,
498 res);
499 GNUNET_free (res);
500 }
501 while (NULL != (isc = lc->isc_head))
502 {
503 GNUNET_CONTAINER_DLL_remove (lc->isc_head,
504 lc->isc_tail,
505 isc);
506 GNUNET_CRYPTO_hash_file_cancel (isc->fhc);
507 GNUNET_free (isc);
508 }
509 GNUNET_free (lc);
510}
511
512
513
181 514
182 515
183/** 516/**
@@ -289,7 +622,7 @@ check_p2p_put (void *cls,
289 const struct PutMessage *put) 622 const struct PutMessage *put)
290{ 623{
291 enum GNUNET_BLOCK_Type type; 624 enum GNUNET_BLOCK_Type type;
292 625
293 type = ntohl (put->type); 626 type = ntohl (put->type);
294 if (GNUNET_BLOCK_TYPE_FS_ONDEMAND == type) 627 if (GNUNET_BLOCK_TYPE_FS_ONDEMAND == type)
295 { 628 {
@@ -373,7 +706,7 @@ check_p2p_get (void *cls,
373 unsigned int bm; 706 unsigned int bm;
374 unsigned int bits; 707 unsigned int bits;
375 size_t bfsize; 708 size_t bfsize;
376 709
377 msize = ntohs (gm->header.size); 710 msize = ntohs (gm->header.size);
378 bm = ntohl (gm->hash_bitmap); 711 bm = ntohl (gm->hash_bitmap);
379 bits = 0; 712 bits = 0;
@@ -394,8 +727,8 @@ check_p2p_get (void *cls,
394 { 727 {
395 GNUNET_break_op (0); 728 GNUNET_break_op (0);
396 return GNUNET_SYSERR; 729 return GNUNET_SYSERR;
397 } 730 }
398 return GNUNET_OK; 731 return GNUNET_OK;
399} 732}
400 733
401 734
@@ -405,7 +738,7 @@ check_p2p_get (void *cls,
405 * result status). Also signal that we can now 738 * result status). Also signal that we can now
406 * receive more request information from the client. 739 * receive more request information from the client.
407 * 740 *
408 * @param cls the client doing the request (`struct GNUNET_SERVER_Client`) 741 * @param cls the client doing the request (`struct GSF_LocalClient`)
409 * @param pr the pending request we were processing 742 * @param pr the pending request we were processing
410 * @param result final datastore lookup result 743 * @param result final datastore lookup result
411 */ 744 */
@@ -414,11 +747,10 @@ start_p2p_processing (void *cls,
414 struct GSF_PendingRequest *pr, 747 struct GSF_PendingRequest *pr,
415 enum GNUNET_BLOCK_EvaluationResult result) 748 enum GNUNET_BLOCK_EvaluationResult result)
416{ 749{
417 struct GNUNET_SERVER_Client *client = cls; 750 struct GSF_LocalClient *lc = cls;
418 struct GSF_PendingRequestData *prd; 751 struct GSF_PendingRequestData *prd;
419 752
420 GNUNET_SERVER_receive_done (client, 753 GNUNET_SERVICE_client_continue (lc->client);
421 GNUNET_OK);
422 if (GNUNET_BLOCK_EVALUATION_OK_LAST == result) 754 if (GNUNET_BLOCK_EVALUATION_OK_LAST == result)
423 return; /* we're done, 'pr' was already destroyed... */ 755 return; /* we're done, 'pr' was already destroyed... */
424 prd = GSF_pending_request_get_data_ (pr); 756 prd = GSF_pending_request_get_data_ (pr);
@@ -448,7 +780,33 @@ start_p2p_processing (void *cls,
448 break; 780 break;
449 } 781 }
450 } 782 }
451 GSF_consider_forwarding (NULL, pr, result); 783 GSF_consider_forwarding (NULL,
784 pr,
785 result);
786}
787
788
789/**
790 * Check #GNUNET_MESSAGE_TYPE_FS_START_SEARCH-message (search request
791 * from client).
792 *
793 * @param cls identification of the client
794 * @param sm the actual message
795 * @return #GNUNET_OK if @a sm is well-formed
796 */
797static int
798check_client_start_search (void *cls,
799 const struct SearchMessage *sm)
800{
801 uint16_t msize;
802
803 msize = ntohs (sm->header.size) - sizeof (struct SearchMessage);
804 if (0 != msize % sizeof (struct GNUNET_HashCode))
805 {
806 GNUNET_break (0);
807 return GNUNET_SYSERR;
808 }
809 return GNUNET_OK;
452} 810}
453 811
454 812
@@ -456,63 +814,128 @@ start_p2p_processing (void *cls,
456 * Handle #GNUNET_MESSAGE_TYPE_FS_START_SEARCH-message (search request 814 * Handle #GNUNET_MESSAGE_TYPE_FS_START_SEARCH-message (search request
457 * from client). 815 * from client).
458 * 816 *
459 * @param cls closure 817 * Responsible for creating the request entry itself and setting
460 * @param client identification of the client 818 * up reply callback and cancellation on client disconnect.
461 * @param message the actual message 819 *
820 * @param cls identification of the client
821 * @param sm the actual message
462 */ 822 */
463static void 823static void
464handle_start_search (void *cls, 824handle_client_start_search (void *cls,
465 struct GNUNET_SERVER_Client *client, 825 const struct SearchMessage *sm)
466 const struct GNUNET_MessageHeader *message)
467{ 826{
468 struct GSF_PendingRequest *pr; 827 static struct GNUNET_PeerIdentity all_zeros;
469 int ret; 828 struct GSF_LocalClient *lc = cls;
470 829 struct ClientRequest *cr;
471 pr = NULL; 830 struct GSF_PendingRequestData *prd;
472 ret = GSF_local_client_start_search_handler_ (client, 831 uint16_t msize;
473 message, 832 unsigned int sc;
474 &pr); 833 enum GNUNET_BLOCK_Type type;
475 switch (ret) 834 enum GSF_PendingRequestOptions options;
476 { 835
477 case GNUNET_SYSERR: 836 GNUNET_STATISTICS_update (GSF_stats,
478 GNUNET_SERVER_receive_done (client, 837 gettext_noop ("# client searches received"),
479 GNUNET_SYSERR); 838 1,
480 break; 839 GNUNET_NO);
481 case GNUNET_NO: 840 msize = ntohs (sm->header.size) - sizeof (struct SearchMessage);
482 GNUNET_SERVER_receive_done (client, 841 sc = msize / sizeof (struct GNUNET_HashCode);
483 GNUNET_OK); 842 type = ntohl (sm->type);
484 break; 843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
485 case GNUNET_YES: 844 "Received request for `%s' of type %u from local client\n",
486 GSF_pending_request_get_data_ (pr)->has_started = GNUNET_YES; 845 GNUNET_h2s (&sm->query),
487 GSF_local_lookup_ (pr, 846 (unsigned int) type);
488 &start_p2p_processing, 847 cr = NULL;
489 client); 848 /* detect duplicate UBLOCK requests */
490 break; 849 if ((type == GNUNET_BLOCK_TYPE_FS_UBLOCK) ||
491 default: 850 (type == GNUNET_BLOCK_TYPE_ANY))
492 GNUNET_assert (0); 851 {
852 cr = lc->cr_head;
853 while (NULL != cr)
854 {
855 prd = GSF_pending_request_get_data_ (cr->pr);
856 /* only unify with queries that hae not yet started local processing
857 (SEARCH_MESSAGE_OPTION_CONTINUED was always set) and that have a
858 matching query and type */
859 if ((GNUNET_YES != prd->has_started) &&
860 (0 != memcmp (&prd->query,
861 &sm->query,
862 sizeof (struct GNUNET_HashCode))) &&
863 (prd->type == type))
864 break;
865 cr = cr->next;
866 }
867 }
868 if (NULL != cr)
869 {
870 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
871 "Have existing request, merging content-seen lists.\n");
872 GSF_pending_request_update_ (cr->pr,
873 (const struct GNUNET_HashCode *) &sm[1],
874 sc);
875 GNUNET_STATISTICS_update (GSF_stats,
876 gettext_noop ("# client searches updated (merged content seen list)"),
877 1,
878 GNUNET_NO);
879 }
880 else
881 {
882 GNUNET_STATISTICS_update (GSF_stats,
883 gettext_noop ("# client searches active"),
884 1,
885 GNUNET_NO);
886 cr = GNUNET_new (struct ClientRequest);
887 cr->lc = lc;
888 GNUNET_CONTAINER_DLL_insert (lc->cr_head,
889 lc->cr_tail,
890 cr);
891 options = GSF_PRO_LOCAL_REQUEST;
892 if (0 != (SEARCH_MESSAGE_OPTION_LOOPBACK_ONLY & ntohl (sm->options)))
893 options |= GSF_PRO_LOCAL_ONLY;
894 cr->pr = GSF_pending_request_create_ (options, type,
895 &sm->query,
896 (0 !=
897 memcmp (&sm->target,
898 &all_zeros,
899 sizeof (struct GNUNET_PeerIdentity)))
900 ? &sm->target : NULL, NULL, 0,
901 0 /* bf */ ,
902 ntohl (sm->anonymity_level),
903 0 /* priority */ ,
904 0 /* ttl */ ,
905 0 /* sender PID */ ,
906 0 /* origin PID */ ,
907 (const struct GNUNET_HashCode *) &sm[1], sc,
908 &client_response_handler,
909 cr);
493 } 910 }
911 if (0 != (SEARCH_MESSAGE_OPTION_CONTINUED & ntohl (sm->options)))
912 {
913 GNUNET_SERVICE_client_continue (lc->client);
914 return;
915 }
916 GSF_pending_request_get_data_ (cr->pr)->has_started = GNUNET_YES;
917 GSF_local_lookup_ (cr->pr,
918 &start_p2p_processing,
919 lc);
494} 920}
495 921
496 922
497/** 923/**
498 * Handle request to sign a LOC URI (from client). 924 * Handle request to sign a LOC URI (from client).
499 * 925 *
500 * @param cls closure (NULL) 926 * @param cls identification of the client
501 * @param client identification of the client 927 * @param msg the actual message
502 * @param message the actual message
503 */ 928 */
504static void 929static void
505handle_loc_sign (void *cls, 930handle_client_loc_sign (void *cls,
506 struct GNUNET_SERVER_Client *client, 931 const struct RequestLocSignatureMessage *msg)
507 const struct GNUNET_MessageHeader *message)
508{ 932{
509 const struct RequestLocSignatureMessage *msg; 933 struct GSF_LocalClient *lc = cls;
510 struct GNUNET_FS_Uri base; 934 struct GNUNET_FS_Uri base;
511 struct GNUNET_FS_Uri *loc; 935 struct GNUNET_FS_Uri *loc;
512 struct ResponseLocSignatureMessage resp; 936 struct GNUNET_MQ_Envelope *env;
513 struct GSF_LocalClient *lc; 937 struct ResponseLocSignatureMessage *resp;
514 938
515 msg = (const struct RequestLocSignatureMessage *) message;
516 GNUNET_break (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT == 939 GNUNET_break (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT ==
517 ntohl (msg->purpose)); 940 ntohl (msg->purpose));
518 base.type = GNUNET_FS_URI_CHK; 941 base.type = GNUNET_FS_URI_CHK;
@@ -521,17 +944,228 @@ handle_loc_sign (void *cls,
521 loc = GNUNET_FS_uri_loc_create (&base, 944 loc = GNUNET_FS_uri_loc_create (&base,
522 pk, 945 pk,
523 GNUNET_TIME_absolute_ntoh (msg->expiration_time)); 946 GNUNET_TIME_absolute_ntoh (msg->expiration_time));
524 resp.header.size = htons (sizeof (struct ResponseLocSignatureMessage)); 947 env = GNUNET_MQ_msg (resp,
525 resp.header.type = htons (GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGNATURE); 948 GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGNATURE);
526 resp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT); 949 resp->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT);
527 resp.expiration_time = GNUNET_TIME_absolute_hton (loc->data.loc.expirationTime); 950 resp->expiration_time = GNUNET_TIME_absolute_hton (loc->data.loc.expirationTime);
528 resp.signature = loc->data.loc.contentSignature; 951 resp->signature = loc->data.loc.contentSignature;
529 resp.peer = loc->data.loc.peer; 952 resp->peer = loc->data.loc.peer;
530 GNUNET_FS_uri_destroy (loc); 953 GNUNET_FS_uri_destroy (loc);
531 lc = GSF_local_client_lookup_ (client); 954 GNUNET_MQ_send (lc->mq,
532 GSF_local_client_transmit_ (lc, 955 env);
533 &resp.header); 956 GNUNET_SERVICE_client_continue (lc->client);
534 GNUNET_SERVER_receive_done (client, GNUNET_OK); 957}
958
959
960/**
961 * Check INDEX_START-message.
962 *
963 * @param cls identification of the client
964 * @param ism the actual message
965 * @return #GNUNET_OK if @a ism is well-formed
966 */
967static int
968check_client_index_start (void *cls,
969 const struct IndexStartMessage *ism)
970{
971 uint16_t msize;
972 char *fn;
973
974 msize = ntohs (ism->header.size);
975 if (((const char *) ism)[msize - 1] != '\0')
976 {
977 GNUNET_break (0);
978 return GNUNET_SYSERR;
979 }
980 if (0 != ism->reserved)
981 {
982 GNUNET_break (0);
983 return GNUNET_SYSERR;
984 }
985 fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]);
986 if (NULL == fn)
987 {
988 GNUNET_break (0);
989 return GNUNET_SYSERR;
990 }
991 GNUNET_free (fn);
992 return GNUNET_OK;
993}
994
995
996/**
997 * We've validated the hash of the file we're about to index. Signal
998 * success to the client and update our internal data structures.
999 *
1000 * @param isc the data about the index info entry for the request
1001 */
1002static void
1003signal_index_ok (struct IndexStartContext *isc)
1004{
1005 struct GSF_LocalClient *lc = isc->lc;
1006 struct GNUNET_MQ_Envelope *env;
1007 struct GNUNET_MessageHeader *msg;
1008
1009 GNUNET_FS_add_to_index (isc->filename,
1010 &isc->file_id);
1011 env = GNUNET_MQ_msg (msg,
1012 GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
1013 GNUNET_MQ_send (lc->mq,
1014 env);
1015 GNUNET_free (isc->filename);
1016 GNUNET_free (isc);
1017 GNUNET_SERVICE_client_continue (lc->client);
1018}
1019
1020
1021/**
1022 * Function called once the hash computation over an
1023 * indexed file has completed.
1024 *
1025 * @param cls closure, our publishing context
1026 * @param res resulting hash, NULL on error
1027 */
1028static void
1029hash_for_index_val (void *cls,
1030 const struct GNUNET_HashCode *res)
1031{
1032 struct IndexStartContext *isc = cls;
1033 struct GSF_LocalClient *lc = isc->lc;
1034 struct GNUNET_MQ_Envelope *env;
1035 struct GNUNET_MessageHeader *msg;
1036
1037 GNUNET_CONTAINER_DLL_remove (lc->isc_head,
1038 lc->isc_tail,
1039 isc);
1040 isc->fhc = NULL;
1041 if ( (NULL == res) ||
1042 (0 != memcmp (res,
1043 &isc->file_id,
1044 sizeof (struct GNUNET_HashCode))))
1045 {
1046 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1047 _("Hash mismatch trying to index file `%s' which does not have hash `%s'\n"),
1048 isc->filename,
1049 GNUNET_h2s (&isc->file_id));
1050 env = GNUNET_MQ_msg (msg,
1051 GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED);
1052 GNUNET_MQ_send (lc->mq,
1053 env);
1054 GNUNET_SERVICE_client_continue (lc->client);
1055 GNUNET_free (isc);
1056 return;
1057 }
1058 signal_index_ok (isc);
1059}
1060
1061
1062/**
1063 * Handle INDEX_START-message.
1064 *
1065 * @param cls identification of the client
1066 * @param message the actual message
1067 */
1068static void
1069handle_client_index_start (void *cls,
1070 const struct IndexStartMessage *ism)
1071{
1072 struct GSF_LocalClient *lc = cls;
1073 struct IndexStartContext *isc;
1074 char *fn;
1075 uint64_t dev;
1076 uint64_t ino;
1077 uint64_t mydev;
1078 uint64_t myino;
1079
1080 fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]);
1081 GNUNET_assert (NULL != fn);
1082 dev = GNUNET_ntohll (ism->device);
1083 ino = GNUNET_ntohll (ism->inode);
1084 isc = GNUNET_new (struct IndexStartContext);
1085 isc->filename = fn;
1086 isc->file_id = ism->file_id;
1087 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1088 "Received START_INDEX message for file `%s'\n",
1089 isc->filename);
1090 isc->lc = lc;
1091 mydev = 0;
1092 myino = 0;
1093 if ( ( (dev != 0) ||
1094 (ino != 0) ) &&
1095 (GNUNET_OK == GNUNET_DISK_file_get_identifiers (fn,
1096 &mydev,
1097 &myino)) &&
1098 (dev == mydev) &&
1099 (ino == myino) )
1100 {
1101 /* fast validation OK! */
1102 signal_index_ok (isc);
1103 return;
1104 }
1105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1106 "Mismatch in file identifiers (%llu != %llu or %u != %u), need to hash.\n",
1107 (unsigned long long) ino,
1108 (unsigned long long) myino,
1109 (unsigned int) dev,
1110 (unsigned int) mydev);
1111 /* slow validation, need to hash full file (again) */
1112 GNUNET_CONTAINER_DLL_insert (lc->isc_head,
1113 lc->isc_tail,
1114 isc);
1115 isc->fhc = GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE,
1116 isc->filename,
1117 HASHING_BLOCKSIZE,
1118 &hash_for_index_val,
1119 isc);
1120 if (NULL == isc->fhc)
1121 hash_for_index_val (isc,
1122 NULL);
1123}
1124
1125
1126/**
1127 * Handle INDEX_LIST_GET-message.
1128 *
1129 * @param cls closure
1130 * @param message the actual message
1131 */
1132static void
1133handle_client_index_list_get (void *cls,
1134 const struct GNUNET_MessageHeader *message)
1135{
1136 struct GSF_LocalClient *lc = cls;
1137
1138 GNUNET_FS_indexing_send_list (lc->mq);
1139 GNUNET_SERVICE_client_continue (lc->client);
1140}
1141
1142
1143/**
1144 * Handle UNINDEX-message.
1145 *
1146 * @param cls identification of the client
1147 * @param message the actual message
1148 */
1149static void
1150handle_client_unindex (void *cls,
1151 const struct UnindexMessage *um)
1152{
1153 struct GSF_LocalClient *lc = cls;
1154 struct GNUNET_MQ_Envelope *env;
1155 struct GNUNET_MessageHeader *msg;
1156 int found;
1157
1158 GNUNET_break (0 == um->reserved);
1159 found = GNUNET_FS_indexing_do_unindex (&um->file_id);
1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1161 "Client requested unindexing of file `%s': %s\n",
1162 GNUNET_h2s (&um->file_id),
1163 found ? "found" : "not found");
1164 env = GNUNET_MQ_msg (msg,
1165 GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK);
1166 GNUNET_MQ_send (lc->mq,
1167 env);
1168 GNUNET_SERVICE_client_continue (lc->client);
535} 1169}
536 1170
537 1171
@@ -560,7 +1194,8 @@ shutdown_task (void *cls)
560 GSF_pending_request_done_ (); 1194 GSF_pending_request_done_ ();
561 GSF_plan_done (); 1195 GSF_plan_done ();
562 GSF_connected_peer_done_ (); 1196 GSF_connected_peer_done_ ();
563 GNUNET_DATASTORE_disconnect (GSF_dsh, GNUNET_NO); 1197 GNUNET_DATASTORE_disconnect (GSF_dsh,
1198 GNUNET_NO);
564 GSF_dsh = NULL; 1199 GSF_dsh = NULL;
565 GNUNET_DHT_disconnect (GSF_dht); 1200 GNUNET_DHT_disconnect (GSF_dht);
566 GSF_dht = NULL; 1201 GSF_dht = NULL;
@@ -610,12 +1245,10 @@ peer_init_handler (void *cls,
610/** 1245/**
611 * Process fs requests. 1246 * Process fs requests.
612 * 1247 *
613 * @param server the initialized server
614 * @param c configuration to use 1248 * @param c configuration to use
615 */ 1249 */
616static int 1250static int
617main_init (struct GNUNET_SERVER_Handle *server, 1251main_init (const struct GNUNET_CONFIGURATION_Handle *c)
618 const struct GNUNET_CONFIGURATION_Handle *c)
619{ 1252{
620 struct GNUNET_MQ_MessageHandler no_p2p_handlers[] = { 1253 struct GNUNET_MQ_MessageHandler no_p2p_handlers[] = {
621 GNUNET_MQ_handler_end () 1254 GNUNET_MQ_handler_end ()
@@ -635,22 +1268,6 @@ main_init (struct GNUNET_SERVER_Handle *server,
635 NULL), 1268 NULL),
636 GNUNET_MQ_handler_end () 1269 GNUNET_MQ_handler_end ()
637 }; 1270 };
638 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
639 { &GNUNET_FS_handle_index_start, NULL,
640 GNUNET_MESSAGE_TYPE_FS_INDEX_START, 0 },
641 { &GNUNET_FS_handle_index_list_get, NULL,
642 GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET,
643 sizeof (struct GNUNET_MessageHeader) },
644 { &GNUNET_FS_handle_unindex, NULL,
645 GNUNET_MESSAGE_TYPE_FS_UNINDEX,
646 sizeof (struct UnindexMessage) },
647 { &handle_start_search, NULL,
648 GNUNET_MESSAGE_TYPE_FS_START_SEARCH, 0 },
649 { &handle_loc_sign, NULL,
650 GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGN,
651 sizeof (struct RequestLocSignatureMessage) },
652 {NULL, NULL, 0, 0}
653 };
654 int anon_p2p_off; 1271 int anon_p2p_off;
655 char *keyfile; 1272 char *keyfile;
656 1273
@@ -697,10 +1314,6 @@ main_init (struct GNUNET_SERVER_Handle *server,
697 "core"); 1314 "core");
698 return GNUNET_SYSERR; 1315 return GNUNET_SYSERR;
699 } 1316 }
700 GNUNET_SERVER_disconnect_notify (server,
701 &GSF_client_disconnect_handler_,
702 NULL);
703 GNUNET_SERVER_add_handlers (server, handlers);
704 cover_age_task = 1317 cover_age_task =
705 GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY, 1318 GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY,
706 &age_cover_counters, 1319 &age_cover_counters,
@@ -718,22 +1331,26 @@ main_init (struct GNUNET_SERVER_Handle *server,
718 * Process fs requests. 1331 * Process fs requests.
719 * 1332 *
720 * @param cls closure 1333 * @param cls closure
721 * @param server the initialized server
722 * @param cfg configuration to use 1334 * @param cfg configuration to use
1335 * @param service the initialized service
723 */ 1336 */
724static void 1337static void
725run (void *cls, struct GNUNET_SERVER_Handle *server, 1338run (void *cls,
726 const struct GNUNET_CONFIGURATION_Handle *cfg) 1339 const struct GNUNET_CONFIGURATION_Handle *cfg,
1340 struct GNUNET_SERVICE_Handle *service)
727{ 1341{
728 unsigned long long dqs; 1342 unsigned long long dqs;
729 1343
730 GSF_cfg = cfg; 1344 GSF_cfg = cfg;
731 if (GNUNET_OK != 1345 if (GNUNET_OK !=
732 GNUNET_CONFIGURATION_get_value_size (GSF_cfg, "fs", "DATASTORE_QUEUE_SIZE", 1346 GNUNET_CONFIGURATION_get_value_size (GSF_cfg,
1347 "fs",
1348 "DATASTORE_QUEUE_SIZE",
733 &dqs)) 1349 &dqs))
734 { 1350 {
735 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, 1351 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO,
736 "fs", "DATASTORE_QUEUE_SIZE"); 1352 "fs",
1353 "DATASTORE_QUEUE_SIZE");
737 dqs = 1024; 1354 dqs = 1024;
738 } 1355 }
739 GSF_datastore_queue_size = (unsigned int) dqs; 1356 GSF_datastore_queue_size = (unsigned int) dqs;
@@ -754,11 +1371,14 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
754 GSF_plan_init (); 1371 GSF_plan_init ();
755 GSF_pending_request_init_ (); 1372 GSF_pending_request_init_ ();
756 GSF_connected_peer_init_ (); 1373 GSF_connected_peer_init_ ();
757 GSF_ats = GNUNET_ATS_performance_init (GSF_cfg, &update_latencies, NULL); 1374 GSF_ats = GNUNET_ATS_performance_init (GSF_cfg,
1375 &update_latencies,
1376 NULL);
758 GSF_push_init_ (); 1377 GSF_push_init_ ();
759 GSF_put_init_ (); 1378 GSF_put_init_ ();
760 if ((GNUNET_OK != GNUNET_FS_indexing_init (cfg, GSF_dsh)) || 1379 if ( (GNUNET_OK != GNUNET_FS_indexing_init (cfg,
761 (GNUNET_OK != main_init (server, cfg))) 1380 GSF_dsh)) ||
1381 (GNUNET_OK != main_init (cfg)) )
762 { 1382 {
763 GNUNET_SCHEDULER_shutdown (); 1383 GNUNET_SCHEDULER_shutdown ();
764 shutdown_task (NULL); 1384 shutdown_task (NULL);
@@ -768,18 +1388,36 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
768 1388
769 1389
770/** 1390/**
771 * The main function for the fs service. 1391 * Define "main" method using service macro.
772 *
773 * @param argc number of arguments from the command line
774 * @param argv command line arguments
775 * @return 0 ok, 1 on error
776 */ 1392 */
777int 1393GNUNET_SERVICE_MAIN
778main (int argc, char *const *argv) 1394("fs",
779{ 1395 GNUNET_SERVICE_OPTION_NONE,
780 return (GNUNET_OK == 1396 &run,
781 GNUNET_SERVICE_run (argc, argv, "fs", GNUNET_SERVICE_OPTION_NONE, 1397 &client_connect_cb,
782 &run, NULL)) ? 0 : 1; 1398 &client_disconnect_cb,
783} 1399 NULL,
1400 GNUNET_MQ_hd_var_size (client_index_start,
1401 GNUNET_MESSAGE_TYPE_FS_INDEX_START,
1402 struct IndexStartMessage,
1403 NULL),
1404 GNUNET_MQ_hd_fixed_size (client_index_list_get,
1405 GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET,
1406 struct GNUNET_MessageHeader,
1407 NULL),
1408 GNUNET_MQ_hd_fixed_size (client_unindex,
1409 GNUNET_MESSAGE_TYPE_FS_UNINDEX,
1410 struct UnindexMessage,
1411 NULL),
1412 GNUNET_MQ_hd_var_size (client_start_search,
1413 GNUNET_MESSAGE_TYPE_FS_START_SEARCH,
1414 struct SearchMessage,
1415 NULL),
1416 GNUNET_MQ_hd_fixed_size (client_loc_sign,
1417 GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGN,
1418 struct RequestLocSignatureMessage,
1419 NULL),
1420 GNUNET_MQ_handler_end ());
1421
784 1422
785/* end of gnunet-service-fs.c */ 1423/* end of gnunet-service-fs.c */