diff options
Diffstat (limited to 'src/dht/gnunet-service-dht_routing.c')
-rw-r--r-- | src/dht/gnunet-service-dht_routing.c | 389 |
1 files changed, 198 insertions, 191 deletions
diff --git a/src/dht/gnunet-service-dht_routing.c b/src/dht/gnunet-service-dht_routing.c index 99c6b5e4f..3454c1acb 100644 --- a/src/dht/gnunet-service-dht_routing.c +++ b/src/dht/gnunet-service-dht_routing.c | |||
@@ -39,7 +39,8 @@ | |||
39 | * Information we keep about all recent GET requests | 39 | * Information we keep about all recent GET requests |
40 | * so that we can route replies. | 40 | * so that we can route replies. |
41 | */ | 41 | */ |
42 | struct RecentRequest { | 42 | struct RecentRequest |
43 | { | ||
43 | /** | 44 | /** |
44 | * The peer this request was received from. | 45 | * The peer this request was received from. |
45 | */ | 46 | */ |
@@ -97,7 +98,8 @@ static struct GNUNET_CONTAINER_MultiHashMap *recent_map; | |||
97 | /** | 98 | /** |
98 | * Closure for the 'process' function. | 99 | * Closure for the 'process' function. |
99 | */ | 100 | */ |
100 | struct ProcessContext { | 101 | struct ProcessContext |
102 | { | ||
101 | /** | 103 | /** |
102 | * Path of the original PUT | 104 | * Path of the original PUT |
103 | */ | 105 | */ |
@@ -150,9 +152,9 @@ struct ProcessContext { | |||
150 | * #GNUNET_SYSERR if the result is malformed or type unsupported | 152 | * #GNUNET_SYSERR if the result is malformed or type unsupported |
151 | */ | 153 | */ |
152 | static int | 154 | static int |
153 | process(void *cls, | 155 | process (void *cls, |
154 | const struct GNUNET_HashCode *key, | 156 | const struct GNUNET_HashCode *key, |
155 | void *value) | 157 | void *value) |
156 | { | 158 | { |
157 | struct ProcessContext *pc = cls; | 159 | struct ProcessContext *pc = cls; |
158 | struct RecentRequest *rr = value; | 160 | struct RecentRequest *rr = value; |
@@ -167,106 +169,110 @@ process(void *cls, | |||
167 | return GNUNET_OK; /* type missmatch */ | 169 | return GNUNET_OK; /* type missmatch */ |
168 | 170 | ||
169 | if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE)) | 171 | if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE)) |
170 | { | 172 | { |
171 | gpl = pc->get_path_length; | 173 | gpl = pc->get_path_length; |
172 | ppl = pc->put_path_length; | 174 | ppl = pc->put_path_length; |
173 | } | 175 | } |
174 | else | 176 | else |
175 | { | 177 | { |
176 | gpl = 0; | 178 | gpl = 0; |
177 | ppl = 0; | 179 | ppl = 0; |
178 | } | 180 | } |
179 | if ((0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) && | 181 | if ((0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) && |
180 | (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO)) | 182 | (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO)) |
181 | { | 183 | { |
182 | /* key may not match HELLO, which is OK since | 184 | /* key may not match HELLO, which is OK since |
183 | * the search is approximate. Still, the evaluation | 185 | * the search is approximate. Still, the evaluation |
184 | * would fail since the match is not exact. So | 186 | * would fail since the match is not exact. So |
185 | * we fake it by changing the key to the actual PID ... */ | 187 | * we fake it by changing the key to the actual PID ... */ |
186 | GNUNET_BLOCK_get_key(GDS_block_context, | 188 | GNUNET_BLOCK_get_key (GDS_block_context, |
187 | GNUNET_BLOCK_TYPE_DHT_HELLO, | 189 | GNUNET_BLOCK_TYPE_DHT_HELLO, |
188 | pc->data, | 190 | pc->data, |
189 | pc->data_size, | 191 | pc->data_size, |
190 | &hc); | 192 | &hc); |
191 | eval_key = &hc; | 193 | eval_key = &hc; |
192 | } | 194 | } |
193 | else | 195 | else |
194 | { | 196 | { |
195 | eval_key = key; | 197 | eval_key = key; |
196 | } | 198 | } |
197 | eval | 199 | eval |
198 | = GNUNET_BLOCK_evaluate(GDS_block_context, | 200 | = GNUNET_BLOCK_evaluate (GDS_block_context, |
199 | pc->type, | 201 | pc->type, |
200 | rr->bg, | 202 | rr->bg, |
201 | GNUNET_BLOCK_EO_NONE, | 203 | GNUNET_BLOCK_EO_NONE, |
202 | eval_key, | 204 | eval_key, |
203 | rr->xquery, | 205 | rr->xquery, |
204 | rr->xquery_size, | 206 | rr->xquery_size, |
205 | pc->data, | 207 | pc->data, |
206 | pc->data_size); | 208 | pc->data_size); |
207 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 209 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
208 | "Result for %s of type %d was evaluated as %d\n", | 210 | "Result for %s of type %d was evaluated as %d\n", |
209 | GNUNET_h2s(key), | 211 | GNUNET_h2s (key), |
210 | pc->type, | 212 | pc->type, |
211 | eval); | 213 | eval); |
212 | switch (eval) | 214 | switch (eval) |
213 | { | 215 | { |
214 | case GNUNET_BLOCK_EVALUATION_OK_MORE: | 216 | case GNUNET_BLOCK_EVALUATION_OK_MORE: |
215 | case GNUNET_BLOCK_EVALUATION_OK_LAST: | 217 | case GNUNET_BLOCK_EVALUATION_OK_LAST: |
216 | GNUNET_STATISTICS_update(GDS_stats, | 218 | GNUNET_STATISTICS_update (GDS_stats, |
217 | gettext_noop | 219 | gettext_noop |
218 | ("# Good REPLIES matched against routing table"), | 220 | ("# Good REPLIES matched against routing table"), |
219 | 1, GNUNET_NO); | 221 | 1, GNUNET_NO); |
220 | GDS_NEIGHBOURS_handle_reply(&rr->peer, | 222 | GDS_NEIGHBOURS_handle_reply (&rr->peer, |
221 | pc->type, | 223 | pc->type, |
222 | pc->expiration_time, | 224 | pc->expiration_time, |
223 | key, | 225 | key, |
224 | ppl, pc->put_path, | 226 | ppl, pc->put_path, |
225 | gpl, pc->get_path, | 227 | gpl, pc->get_path, |
226 | pc->data, | 228 | pc->data, |
227 | pc->data_size); | 229 | pc->data_size); |
228 | break; | 230 | break; |
229 | 231 | ||
230 | case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: | 232 | case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: |
231 | GNUNET_STATISTICS_update(GDS_stats, | 233 | GNUNET_STATISTICS_update (GDS_stats, |
232 | gettext_noop | 234 | gettext_noop |
233 | ("# Duplicate REPLIES matched against routing table"), | 235 | ( |
234 | 1, GNUNET_NO); | 236 | "# Duplicate REPLIES matched against routing table"), |
235 | return GNUNET_OK; | 237 | 1, GNUNET_NO); |
236 | 238 | return GNUNET_OK; | |
237 | case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: | 239 | |
238 | GNUNET_STATISTICS_update(GDS_stats, | 240 | case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: |
239 | gettext_noop | 241 | GNUNET_STATISTICS_update (GDS_stats, |
240 | ("# Invalid REPLIES matched against routing table"), | 242 | gettext_noop |
241 | 1, GNUNET_NO); | 243 | ( |
242 | return GNUNET_SYSERR; | 244 | "# Invalid REPLIES matched against routing table"), |
243 | 245 | 1, GNUNET_NO); | |
244 | case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: | 246 | return GNUNET_SYSERR; |
245 | GNUNET_STATISTICS_update(GDS_stats, | 247 | |
246 | gettext_noop | 248 | case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: |
247 | ("# Irrelevant REPLIES matched against routing table"), | 249 | GNUNET_STATISTICS_update (GDS_stats, |
248 | 1, GNUNET_NO); | 250 | gettext_noop |
249 | return GNUNET_OK; | 251 | ( |
250 | 252 | "# Irrelevant REPLIES matched against routing table"), | |
251 | case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: | 253 | 1, GNUNET_NO); |
252 | GNUNET_break(0); | 254 | return GNUNET_OK; |
253 | return GNUNET_OK; | 255 | |
254 | 256 | case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: | |
255 | case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: | 257 | GNUNET_break (0); |
256 | GNUNET_break(0); | 258 | return GNUNET_OK; |
257 | return GNUNET_OK; | 259 | |
258 | 260 | case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: | |
259 | case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: | 261 | GNUNET_break (0); |
260 | GNUNET_STATISTICS_update(GDS_stats, | 262 | return GNUNET_OK; |
261 | gettext_noop | 263 | |
262 | ("# Unsupported REPLIES matched against routing table"), | 264 | case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: |
263 | 1, GNUNET_NO); | 265 | GNUNET_STATISTICS_update (GDS_stats, |
264 | return GNUNET_SYSERR; | 266 | gettext_noop |
265 | 267 | ( | |
266 | default: | 268 | "# Unsupported REPLIES matched against routing table"), |
267 | GNUNET_break(0); | 269 | 1, GNUNET_NO); |
268 | return GNUNET_SYSERR; | 270 | return GNUNET_SYSERR; |
269 | } | 271 | |
272 | default: | ||
273 | GNUNET_break (0); | ||
274 | return GNUNET_SYSERR; | ||
275 | } | ||
270 | return GNUNET_OK; | 276 | return GNUNET_OK; |
271 | } | 277 | } |
272 | 278 | ||
@@ -289,15 +295,15 @@ process(void *cls, | |||
289 | * @param data_size number of bytes in data | 295 | * @param data_size number of bytes in data |
290 | */ | 296 | */ |
291 | void | 297 | void |
292 | GDS_ROUTING_process(enum GNUNET_BLOCK_Type type, | 298 | GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, |
293 | struct GNUNET_TIME_Absolute expiration_time, | 299 | struct GNUNET_TIME_Absolute expiration_time, |
294 | const struct GNUNET_HashCode *key, | 300 | const struct GNUNET_HashCode *key, |
295 | unsigned int put_path_length, | 301 | unsigned int put_path_length, |
296 | const struct GNUNET_PeerIdentity *put_path, | 302 | const struct GNUNET_PeerIdentity *put_path, |
297 | unsigned int get_path_length, | 303 | unsigned int get_path_length, |
298 | const struct GNUNET_PeerIdentity *get_path, | 304 | const struct GNUNET_PeerIdentity *get_path, |
299 | const void *data, | 305 | const void *data, |
300 | size_t data_size) | 306 | size_t data_size) |
301 | { | 307 | { |
302 | struct ProcessContext pc; | 308 | struct ProcessContext pc; |
303 | 309 | ||
@@ -310,19 +316,19 @@ GDS_ROUTING_process(enum GNUNET_BLOCK_Type type, | |||
310 | pc.data = data; | 316 | pc.data = data; |
311 | pc.data_size = data_size; | 317 | pc.data_size = data_size; |
312 | if (NULL == data) | 318 | if (NULL == data) |
313 | { | 319 | { |
314 | /* Some apps might have an 'empty' reply as a valid reply; however, | 320 | /* Some apps might have an 'empty' reply as a valid reply; however, |
315 | 'process' will call GNUNET_BLOCK_evaluate' which treats a 'NULL' | 321 | 'process' will call GNUNET_BLOCK_evaluate' which treats a 'NULL' |
316 | reply as request-validation (but we need response-validation). | 322 | reply as request-validation (but we need response-validation). |
317 | So we set 'data' to a 0-byte non-NULL value just to be sure */ | 323 | So we set 'data' to a 0-byte non-NULL value just to be sure */ |
318 | GNUNET_break(0 == data_size); | 324 | GNUNET_break (0 == data_size); |
319 | pc.data_size = 0; | 325 | pc.data_size = 0; |
320 | pc.data = ""; /* something not null */ | 326 | pc.data = ""; /* something not null */ |
321 | } | 327 | } |
322 | GNUNET_CONTAINER_multihashmap_get_multiple(recent_map, | 328 | GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, |
323 | key, | 329 | key, |
324 | &process, | 330 | &process, |
325 | &pc); | 331 | &pc); |
326 | } | 332 | } |
327 | 333 | ||
328 | 334 | ||
@@ -332,23 +338,23 @@ GDS_ROUTING_process(enum GNUNET_BLOCK_Type type, | |||
332 | * in the heap and hashmap. | 338 | * in the heap and hashmap. |
333 | */ | 339 | */ |
334 | static void | 340 | static void |
335 | expire_oldest_entry() | 341 | expire_oldest_entry () |
336 | { | 342 | { |
337 | struct RecentRequest *recent_req; | 343 | struct RecentRequest *recent_req; |
338 | 344 | ||
339 | GNUNET_STATISTICS_update(GDS_stats, | 345 | GNUNET_STATISTICS_update (GDS_stats, |
340 | gettext_noop | 346 | gettext_noop |
341 | ("# Entries removed from routing table"), 1, | 347 | ("# Entries removed from routing table"), 1, |
342 | GNUNET_NO); | 348 | GNUNET_NO); |
343 | recent_req = GNUNET_CONTAINER_heap_peek(recent_heap); | 349 | recent_req = GNUNET_CONTAINER_heap_peek (recent_heap); |
344 | GNUNET_assert(recent_req != NULL); | 350 | GNUNET_assert (recent_req != NULL); |
345 | GNUNET_CONTAINER_heap_remove_node(recent_req->heap_node); | 351 | GNUNET_CONTAINER_heap_remove_node (recent_req->heap_node); |
346 | GNUNET_BLOCK_group_destroy(recent_req->bg); | 352 | GNUNET_BLOCK_group_destroy (recent_req->bg); |
347 | GNUNET_assert(GNUNET_YES == | 353 | GNUNET_assert (GNUNET_YES == |
348 | GNUNET_CONTAINER_multihashmap_remove(recent_map, | 354 | GNUNET_CONTAINER_multihashmap_remove (recent_map, |
349 | &recent_req->key, | 355 | &recent_req->key, |
350 | recent_req)); | 356 | recent_req)); |
351 | GNUNET_free(recent_req); | 357 | GNUNET_free (recent_req); |
352 | } | 358 | } |
353 | 359 | ||
354 | 360 | ||
@@ -363,26 +369,26 @@ expire_oldest_entry() | |||
363 | * #GNUNET_SYSERR if the request was successfully combined | 369 | * #GNUNET_SYSERR if the request was successfully combined |
364 | */ | 370 | */ |
365 | static int | 371 | static int |
366 | try_combine_recent(void *cls, | 372 | try_combine_recent (void *cls, |
367 | const struct GNUNET_HashCode *key, | 373 | const struct GNUNET_HashCode *key, |
368 | void *value) | 374 | void *value) |
369 | { | 375 | { |
370 | struct RecentRequest *in = cls; | 376 | struct RecentRequest *in = cls; |
371 | struct RecentRequest *rr = value; | 377 | struct RecentRequest *rr = value; |
372 | 378 | ||
373 | if ((0 != GNUNET_memcmp(&in->peer, | 379 | if ((0 != GNUNET_memcmp (&in->peer, |
374 | &rr->peer)) || | 380 | &rr->peer)) || |
375 | (in->type != rr->type) || | 381 | (in->type != rr->type) || |
376 | (in->xquery_size != rr->xquery_size) || | 382 | (in->xquery_size != rr->xquery_size) || |
377 | (0 != memcmp(in->xquery, | 383 | (0 != memcmp (in->xquery, |
378 | rr->xquery, | 384 | rr->xquery, |
379 | in->xquery_size))) | 385 | in->xquery_size))) |
380 | return GNUNET_OK; | 386 | return GNUNET_OK; |
381 | GNUNET_break(GNUNET_SYSERR != | 387 | GNUNET_break (GNUNET_SYSERR != |
382 | GNUNET_BLOCK_group_merge(in->bg, | 388 | GNUNET_BLOCK_group_merge (in->bg, |
383 | rr->bg)); | 389 | rr->bg)); |
384 | rr->bg = in->bg; | 390 | rr->bg = in->bg; |
385 | GNUNET_free(in); | 391 | GNUNET_free (in); |
386 | return GNUNET_SYSERR; | 392 | return GNUNET_SYSERR; |
387 | } | 393 | } |
388 | 394 | ||
@@ -400,53 +406,53 @@ try_combine_recent(void *cls, | |||
400 | * @param reply_bf_mutator mutator for @a reply_bf | 406 | * @param reply_bf_mutator mutator for @a reply_bf |
401 | */ | 407 | */ |
402 | void | 408 | void |
403 | GDS_ROUTING_add(const struct GNUNET_PeerIdentity *sender, | 409 | GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender, |
404 | enum GNUNET_BLOCK_Type type, | 410 | enum GNUNET_BLOCK_Type type, |
405 | struct GNUNET_BLOCK_Group *bg, | 411 | struct GNUNET_BLOCK_Group *bg, |
406 | enum GNUNET_DHT_RouteOption options, | 412 | enum GNUNET_DHT_RouteOption options, |
407 | const struct GNUNET_HashCode *key, | 413 | const struct GNUNET_HashCode *key, |
408 | const void *xquery, | 414 | const void *xquery, |
409 | size_t xquery_size) | 415 | size_t xquery_size) |
410 | { | 416 | { |
411 | struct RecentRequest *recent_req; | 417 | struct RecentRequest *recent_req; |
412 | 418 | ||
413 | while (GNUNET_CONTAINER_heap_get_size(recent_heap) >= DHT_MAX_RECENT) | 419 | while (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT) |
414 | expire_oldest_entry(); | 420 | expire_oldest_entry (); |
415 | GNUNET_STATISTICS_update(GDS_stats, | 421 | GNUNET_STATISTICS_update (GDS_stats, |
416 | gettext_noop("# Entries added to routing table"), | 422 | gettext_noop ("# Entries added to routing table"), |
417 | 1, | 423 | 1, |
418 | GNUNET_NO); | 424 | GNUNET_NO); |
419 | recent_req = GNUNET_malloc(sizeof(struct RecentRequest) + xquery_size); | 425 | recent_req = GNUNET_malloc (sizeof(struct RecentRequest) + xquery_size); |
420 | recent_req->peer = *sender; | 426 | recent_req->peer = *sender; |
421 | recent_req->key = *key; | 427 | recent_req->key = *key; |
422 | recent_req->bg = bg; | 428 | recent_req->bg = bg; |
423 | recent_req->type = type; | 429 | recent_req->type = type; |
424 | recent_req->options = options; | 430 | recent_req->options = options; |
425 | recent_req->xquery = &recent_req[1]; | 431 | recent_req->xquery = &recent_req[1]; |
426 | GNUNET_memcpy(&recent_req[1], | 432 | GNUNET_memcpy (&recent_req[1], |
427 | xquery, | 433 | xquery, |
428 | xquery_size); | 434 | xquery_size); |
429 | recent_req->xquery_size = xquery_size; | 435 | recent_req->xquery_size = xquery_size; |
430 | if (GNUNET_SYSERR == | 436 | if (GNUNET_SYSERR == |
431 | GNUNET_CONTAINER_multihashmap_get_multiple(recent_map, | 437 | GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, |
432 | key, | 438 | key, |
433 | &try_combine_recent, | 439 | &try_combine_recent, |
434 | recent_req)) | 440 | recent_req)) |
435 | { | 441 | { |
436 | GNUNET_STATISTICS_update(GDS_stats, | 442 | GNUNET_STATISTICS_update (GDS_stats, |
437 | gettext_noop | 443 | gettext_noop |
438 | ("# DHT requests combined"), | 444 | ("# DHT requests combined"), |
439 | 1, GNUNET_NO); | 445 | 1, GNUNET_NO); |
440 | return; | 446 | return; |
441 | } | 447 | } |
442 | recent_req->heap_node | 448 | recent_req->heap_node |
443 | = GNUNET_CONTAINER_heap_insert(recent_heap, | 449 | = GNUNET_CONTAINER_heap_insert (recent_heap, |
444 | recent_req, | ||
445 | GNUNET_TIME_absolute_get().abs_value_us); | ||
446 | GNUNET_CONTAINER_multihashmap_put(recent_map, | ||
447 | key, | ||
448 | recent_req, | 450 | recent_req, |
449 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | 451 | GNUNET_TIME_absolute_get ().abs_value_us); |
452 | GNUNET_CONTAINER_multihashmap_put (recent_map, | ||
453 | key, | ||
454 | recent_req, | ||
455 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
450 | } | 456 | } |
451 | 457 | ||
452 | 458 | ||
@@ -454,10 +460,11 @@ GDS_ROUTING_add(const struct GNUNET_PeerIdentity *sender, | |||
454 | * Initialize routing subsystem. | 460 | * Initialize routing subsystem. |
455 | */ | 461 | */ |
456 | void | 462 | void |
457 | GDS_ROUTING_init() | 463 | GDS_ROUTING_init () |
458 | { | 464 | { |
459 | recent_heap = GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN); | 465 | recent_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); |
460 | recent_map = GNUNET_CONTAINER_multihashmap_create(DHT_MAX_RECENT * 4 / 3, GNUNET_NO); | 466 | recent_map = GNUNET_CONTAINER_multihashmap_create (DHT_MAX_RECENT * 4 / 3, |
467 | GNUNET_NO); | ||
461 | } | 468 | } |
462 | 469 | ||
463 | 470 | ||
@@ -465,15 +472,15 @@ GDS_ROUTING_init() | |||
465 | * Shutdown routing subsystem. | 472 | * Shutdown routing subsystem. |
466 | */ | 473 | */ |
467 | void | 474 | void |
468 | GDS_ROUTING_done() | 475 | GDS_ROUTING_done () |
469 | { | 476 | { |
470 | while (GNUNET_CONTAINER_heap_get_size(recent_heap) > 0) | 477 | while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0) |
471 | expire_oldest_entry(); | 478 | expire_oldest_entry (); |
472 | GNUNET_assert(0 == GNUNET_CONTAINER_heap_get_size(recent_heap)); | 479 | GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (recent_heap)); |
473 | GNUNET_CONTAINER_heap_destroy(recent_heap); | 480 | GNUNET_CONTAINER_heap_destroy (recent_heap); |
474 | recent_heap = NULL; | 481 | recent_heap = NULL; |
475 | GNUNET_assert(0 == GNUNET_CONTAINER_multihashmap_size(recent_map)); | 482 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (recent_map)); |
476 | GNUNET_CONTAINER_multihashmap_destroy(recent_map); | 483 | GNUNET_CONTAINER_multihashmap_destroy (recent_map); |
477 | recent_map = NULL; | 484 | recent_map = NULL; |
478 | } | 485 | } |
479 | 486 | ||