diff options
Diffstat (limited to 'src/peerstore')
-rw-r--r-- | src/peerstore/gnunet-service-peerstore.c | 171 |
1 files changed, 136 insertions, 35 deletions
diff --git a/src/peerstore/gnunet-service-peerstore.c b/src/peerstore/gnunet-service-peerstore.c index 3635b1dfe..b7128dda5 100644 --- a/src/peerstore/gnunet-service-peerstore.c +++ b/src/peerstore/gnunet-service-peerstore.c | |||
@@ -30,6 +30,27 @@ | |||
30 | #include "peerstore_common.h" | 30 | #include "peerstore_common.h" |
31 | 31 | ||
32 | /** | 32 | /** |
33 | * Connected client entry | ||
34 | */ | ||
35 | struct ClientEntry | ||
36 | { | ||
37 | /** | ||
38 | * DLL. | ||
39 | */ | ||
40 | struct ClientEntry *next; | ||
41 | |||
42 | /** | ||
43 | * DLL. | ||
44 | */ | ||
45 | struct ClientEntry *prev; | ||
46 | |||
47 | /** | ||
48 | * Corresponding server handle. | ||
49 | */ | ||
50 | struct GNUNET_SERVER_Client *client; | ||
51 | }; | ||
52 | |||
53 | /** | ||
33 | * Interval for expired records cleanup (in seconds) | 54 | * Interval for expired records cleanup (in seconds) |
34 | */ | 55 | */ |
35 | #define EXPIRED_RECORDS_CLEANUP_INTERVAL 300 /* 5mins */ | 56 | #define EXPIRED_RECORDS_CLEANUP_INTERVAL 300 /* 5mins */ |
@@ -60,14 +81,24 @@ static struct GNUNET_CONTAINER_MultiHashMap *watchers; | |||
60 | static struct GNUNET_SERVER_NotificationContext *nc; | 81 | static struct GNUNET_SERVER_NotificationContext *nc; |
61 | 82 | ||
62 | /** | 83 | /** |
63 | * Task run during shutdown. | 84 | * Head of linked list of connected clients |
64 | * | ||
65 | * @param cls unused | ||
66 | * @param tc unused | ||
67 | */ | 85 | */ |
68 | static void | 86 | static struct ClientEntry *client_head; |
69 | shutdown_task (void *cls, | 87 | |
70 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 88 | /** |
89 | * Tail of linked list of connected clients | ||
90 | */ | ||
91 | static struct ClientEntry *client_tail; | ||
92 | |||
93 | /** | ||
94 | * Are we in the process of shutting down the service? #GNUNET_YES / #GNUNET_NO | ||
95 | */ | ||
96 | int in_shutdown; | ||
97 | |||
98 | /** | ||
99 | * Perform the actual shutdown operations | ||
100 | */ | ||
101 | void do_shutdown () | ||
71 | { | 102 | { |
72 | if(NULL != db_lib_name) | 103 | if(NULL != db_lib_name) |
73 | { | 104 | { |
@@ -89,6 +120,21 @@ shutdown_task (void *cls, | |||
89 | } | 120 | } |
90 | 121 | ||
91 | /** | 122 | /** |
123 | * Task run during shutdown. | ||
124 | * | ||
125 | * @param cls unused | ||
126 | * @param tc unused | ||
127 | */ | ||
128 | static void | ||
129 | shutdown_task (void *cls, | ||
130 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
131 | { | ||
132 | in_shutdown = GNUNET_YES; | ||
133 | if (NULL == client_head) /* Only when no connected clients. */ | ||
134 | do_shutdown (); | ||
135 | } | ||
136 | |||
137 | /** | ||
92 | * Deletes any expired records from storage | 138 | * Deletes any expired records from storage |
93 | */ | 139 | */ |
94 | static void | 140 | static void |
@@ -116,7 +162,7 @@ cleanup_expired_records(void *cls, | |||
116 | * @param value the watcher client, a 'struct GNUNET_SERVER_Client *' | 162 | * @param value the watcher client, a 'struct GNUNET_SERVER_Client *' |
117 | * @return #GNUNET_OK to continue iterating | 163 | * @return #GNUNET_OK to continue iterating |
118 | */ | 164 | */ |
119 | int client_disconnect_it(void *cls, | 165 | static int client_disconnect_it(void *cls, |
120 | const struct GNUNET_HashCode *key, | 166 | const struct GNUNET_HashCode *key, |
121 | void *value) | 167 | void *value) |
122 | { | 168 | { |
@@ -136,10 +182,25 @@ handle_client_disconnect (void *cls, | |||
136 | struct GNUNET_SERVER_Client | 182 | struct GNUNET_SERVER_Client |
137 | * client) | 183 | * client) |
138 | { | 184 | { |
139 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A client was disconnected, cleaning up.\n"); | 185 | struct ClientEntry *ce; |
186 | |||
187 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A client disconnected, cleaning up.\n"); | ||
140 | if(NULL != watchers) | 188 | if(NULL != watchers) |
141 | GNUNET_CONTAINER_multihashmap_iterate(watchers, | 189 | GNUNET_CONTAINER_multihashmap_iterate(watchers, |
142 | &client_disconnect_it, client); | 190 | &client_disconnect_it, client); |
191 | ce = client_head; | ||
192 | while (ce != NULL) | ||
193 | { | ||
194 | if (ce->client == client) | ||
195 | { | ||
196 | GNUNET_CONTAINER_DLL_remove (client_head, client_tail, ce); | ||
197 | GNUNET_free (ce); | ||
198 | break; | ||
199 | } | ||
200 | ce = ce->next; | ||
201 | } | ||
202 | if (NULL == client_head && in_shutdown) | ||
203 | do_shutdown (); | ||
143 | } | 204 | } |
144 | 205 | ||
145 | /** | 206 | /** |
@@ -151,7 +212,7 @@ handle_client_disconnect (void *cls, | |||
151 | * @param value stored value | 212 | * @param value stored value |
152 | * @param size size of stored value | 213 | * @param size size of stored value |
153 | */ | 214 | */ |
154 | int record_iterator(void *cls, | 215 | static int record_iterator(void *cls, |
155 | struct GNUNET_PEERSTORE_Record *record, | 216 | struct GNUNET_PEERSTORE_Record *record, |
156 | char *emsg) | 217 | char *emsg) |
157 | { | 218 | { |
@@ -179,7 +240,7 @@ int record_iterator(void *cls, | |||
179 | * @param value the watcher client, a 'struct GNUNET_SERVER_Client *' | 240 | * @param value the watcher client, a 'struct GNUNET_SERVER_Client *' |
180 | * @return #GNUNET_YES to continue iterating | 241 | * @return #GNUNET_YES to continue iterating |
181 | */ | 242 | */ |
182 | int watch_notifier_it(void *cls, | 243 | static int watch_notifier_it(void *cls, |
183 | const struct GNUNET_HashCode *key, | 244 | const struct GNUNET_HashCode *key, |
184 | void *value) | 245 | void *value) |
185 | { | 246 | { |
@@ -206,7 +267,7 @@ int watch_notifier_it(void *cls, | |||
206 | * | 267 | * |
207 | * @param record changed record to update watchers with | 268 | * @param record changed record to update watchers with |
208 | */ | 269 | */ |
209 | void watch_notifier (struct GNUNET_PEERSTORE_Record *record) | 270 | static void watch_notifier (struct GNUNET_PEERSTORE_Record *record) |
210 | { | 271 | { |
211 | struct GNUNET_HashCode keyhash; | 272 | struct GNUNET_HashCode keyhash; |
212 | 273 | ||
@@ -224,13 +285,13 @@ void watch_notifier (struct GNUNET_PEERSTORE_Record *record) | |||
224 | * @param client identification of the client | 285 | * @param client identification of the client |
225 | * @param message the actual message | 286 | * @param message the actual message |
226 | */ | 287 | */ |
227 | void handle_watch_cancel (void *cls, | 288 | static void handle_watch_cancel (void *cls, |
228 | struct GNUNET_SERVER_Client *client, | 289 | struct GNUNET_SERVER_Client *client, |
229 | const struct GNUNET_MessageHeader *message) | 290 | const struct GNUNET_MessageHeader *message) |
230 | { | 291 | { |
231 | struct StoreKeyHashMessage *hm; | 292 | struct StoreKeyHashMessage *hm; |
232 | 293 | ||
233 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch cancel request from client.\n"); | 294 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch cancel request.\n"); |
234 | hm = (struct StoreKeyHashMessage *) message; | 295 | hm = (struct StoreKeyHashMessage *) message; |
235 | GNUNET_CONTAINER_multihashmap_remove(watchers, &hm->keyhash, client); | 296 | GNUNET_CONTAINER_multihashmap_remove(watchers, &hm->keyhash, client); |
236 | GNUNET_SERVER_receive_done(client, GNUNET_OK); | 297 | GNUNET_SERVER_receive_done(client, GNUNET_OK); |
@@ -243,13 +304,13 @@ void handle_watch_cancel (void *cls, | |||
243 | * @param client identification of the client | 304 | * @param client identification of the client |
244 | * @param message the actual message | 305 | * @param message the actual message |
245 | */ | 306 | */ |
246 | void handle_watch (void *cls, | 307 | static void handle_watch (void *cls, |
247 | struct GNUNET_SERVER_Client *client, | 308 | struct GNUNET_SERVER_Client *client, |
248 | const struct GNUNET_MessageHeader *message) | 309 | const struct GNUNET_MessageHeader *message) |
249 | { | 310 | { |
250 | struct StoreKeyHashMessage *hm; | 311 | struct StoreKeyHashMessage *hm; |
251 | 312 | ||
252 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch request from client.\n"); | 313 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch request.\n"); |
253 | hm = (struct StoreKeyHashMessage *) message; | 314 | hm = (struct StoreKeyHashMessage *) message; |
254 | GNUNET_SERVER_client_mark_monitor(client); | 315 | GNUNET_SERVER_client_mark_monitor(client); |
255 | GNUNET_SERVER_notification_context_add(nc, client); | 316 | GNUNET_SERVER_notification_context_add(nc, client); |
@@ -265,24 +326,25 @@ void handle_watch (void *cls, | |||
265 | * @param client identification of the client | 326 | * @param client identification of the client |
266 | * @param message the actual message | 327 | * @param message the actual message |
267 | */ | 328 | */ |
268 | void handle_iterate (void *cls, | 329 | static void handle_iterate (void *cls, |
269 | struct GNUNET_SERVER_Client *client, | 330 | struct GNUNET_SERVER_Client *client, |
270 | const struct GNUNET_MessageHeader *message) | 331 | const struct GNUNET_MessageHeader *message) |
271 | { | 332 | { |
272 | struct GNUNET_PEERSTORE_Record *record; | 333 | struct GNUNET_PEERSTORE_Record *record; |
273 | struct GNUNET_MessageHeader *endmsg; | 334 | struct GNUNET_MessageHeader *endmsg; |
274 | 335 | ||
275 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received an iterate request from client.\n"); | 336 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received an iterate request.\n"); |
276 | record = PEERSTORE_parse_record_message(message); | 337 | record = PEERSTORE_parse_record_message(message); |
277 | if(NULL == record) | 338 | if(NULL == record) |
278 | { | 339 | { |
279 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Malformed iterate request from client\n")); | 340 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Malformed iterate request.\n")); |
280 | GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); | 341 | GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); |
281 | return; | 342 | return; |
282 | } | 343 | } |
283 | if(NULL == record->sub_system) | 344 | if(NULL == record->sub_system) |
284 | { | 345 | { |
285 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Sub system not supplied in client iterate request\n")); | 346 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, |
347 | _("Sub system not supplied in client iterate request.\n")); | ||
286 | GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); | 348 | GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); |
287 | return; | 349 | return; |
288 | } | 350 | } |
@@ -319,7 +381,7 @@ void handle_iterate (void *cls, | |||
319 | * @param client identification of the client | 381 | * @param client identification of the client |
320 | * @param message the actual message | 382 | * @param message the actual message |
321 | */ | 383 | */ |
322 | void handle_store (void *cls, | 384 | static void handle_store (void *cls, |
323 | struct GNUNET_SERVER_Client *client, | 385 | struct GNUNET_SERVER_Client *client, |
324 | const struct GNUNET_MessageHeader *message) | 386 | const struct GNUNET_MessageHeader *message) |
325 | { | 387 | { |
@@ -368,6 +430,48 @@ void handle_store (void *cls, | |||
368 | } | 430 | } |
369 | 431 | ||
370 | /** | 432 | /** |
433 | * Creates an entry for a new client or returns it if it already exists. | ||
434 | * | ||
435 | * @param client Client handle | ||
436 | * @return Client entry struct | ||
437 | */ | ||
438 | static struct ClientEntry * | ||
439 | make_client_entry (struct GNUNET_SERVER_Client *client) | ||
440 | { | ||
441 | struct ClientEntry *ce; | ||
442 | |||
443 | ce = client_head; | ||
444 | while (NULL != ce) | ||
445 | { | ||
446 | if (ce->client == client) | ||
447 | return ce; | ||
448 | ce = ce->next; | ||
449 | } | ||
450 | if (GNUNET_YES == in_shutdown) | ||
451 | { | ||
452 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
453 | return NULL; | ||
454 | } | ||
455 | ce = GNUNET_new (struct ClientEntry); | ||
456 | ce->client = client; | ||
457 | GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ce); | ||
458 | return ce; | ||
459 | } | ||
460 | |||
461 | /** | ||
462 | * Callback on a new client connection | ||
463 | * | ||
464 | * @param cls closure (unused) | ||
465 | * @param client identification of the client | ||
466 | */ | ||
467 | static void | ||
468 | handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client) | ||
469 | { | ||
470 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New client connection created.\n"); | ||
471 | make_client_entry (client); | ||
472 | } | ||
473 | |||
474 | /** | ||
371 | * Peerstore service runner. | 475 | * Peerstore service runner. |
372 | * | 476 | * |
373 | * @param cls closure | 477 | * @param cls closure |
@@ -388,6 +492,7 @@ run (void *cls, | |||
388 | }; | 492 | }; |
389 | char *database; | 493 | char *database; |
390 | 494 | ||
495 | in_shutdown = GNUNET_NO; | ||
391 | cfg = c; | 496 | cfg = c; |
392 | if (GNUNET_OK != | 497 | if (GNUNET_OK != |
393 | GNUNET_CONFIGURATION_get_value_string (cfg, "peerstore", "DATABASE", | 498 | GNUNET_CONFIGURATION_get_value_string (cfg, "peerstore", "DATABASE", |
@@ -406,16 +511,12 @@ run (void *cls, | |||
406 | GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | 511 | GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); |
407 | return; | 512 | return; |
408 | } | 513 | } |
409 | else | 514 | nc = GNUNET_SERVER_notification_context_create (server, 16); |
410 | { | 515 | watchers = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO); |
411 | nc = GNUNET_SERVER_notification_context_create (server, 16); | 516 | GNUNET_SCHEDULER_add_now(&cleanup_expired_records, NULL); |
412 | watchers = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO); | 517 | GNUNET_SERVER_add_handlers (server, handlers); |
413 | GNUNET_SCHEDULER_add_now(&cleanup_expired_records, NULL); | 518 | GNUNET_SERVER_connect_notify (server, &handle_client_connect, NULL); |
414 | GNUNET_SERVER_add_handlers (server, handlers); | 519 | GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); |
415 | GNUNET_SERVER_disconnect_notify (server, | ||
416 | &handle_client_disconnect, | ||
417 | NULL); | ||
418 | } | ||
419 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | 520 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, |
420 | &shutdown_task, | 521 | &shutdown_task, |
421 | NULL); | 522 | NULL); |
@@ -434,10 +535,10 @@ main (int argc, char *const *argv) | |||
434 | { | 535 | { |
435 | return (GNUNET_OK == | 536 | return (GNUNET_OK == |
436 | GNUNET_SERVICE_run (argc, | 537 | GNUNET_SERVICE_run (argc, |
437 | argv, | 538 | argv, |
438 | "peerstore", | 539 | "peerstore", |
439 | GNUNET_SERVICE_OPTION_NONE, | 540 | GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, |
440 | &run, NULL)) ? 0 : 1; | 541 | &run, NULL)) ? 0 : 1; |
441 | } | 542 | } |
442 | 543 | ||
443 | /* end of gnunet-service-peerstore.c */ | 544 | /* end of gnunet-service-peerstore.c */ |