aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-01-18 12:58:16 +0000
committerChristian Grothoff <christian@grothoff.org>2015-01-18 12:58:16 +0000
commit41fb4bc77ef852602063c1723366314ccbefc0a6 (patch)
tree0d06aaa0076c543c9a073828c04c6c699f8778c4
parent9fae47e9f9555b5d7a10b86b7f2de5cd9e6c0c1c (diff)
downloadgnunet-41fb4bc77ef852602063c1723366314ccbefc0a6.tar.gz
gnunet-41fb4bc77ef852602063c1723366314ccbefc0a6.zip
always use a slot, even if the session is NULL, simplify logic and document what still needs to be fixed
-rw-r--r--src/ats/ats_api_scheduling.c588
-rw-r--r--src/ats/gnunet-service-ats_addresses.c182
-rw-r--r--src/ats/gnunet-service-ats_addresses.h10
-rw-r--r--src/ats/gnunet-service-ats_scheduling.c19
-rw-r--r--src/include/gnunet_ats_service.h2
5 files changed, 340 insertions, 461 deletions
diff --git a/src/ats/ats_api_scheduling.c b/src/ats/ats_api_scheduling.c
index 08155eaef..7e44a8660 100644
--- a/src/ats/ats_api_scheduling.c
+++ b/src/ats/ats_api_scheduling.c
@@ -40,24 +40,57 @@
40 40
41 41
42/** 42/**
43 * Information we track per session. 43 * Information we track per address.
44 * FIXME: but what about *incoming* connections?
45 * "address" tells us about those, those
46 * are only valid while we have a session.
47 * Need to clarify all this!!!
44 */ 48 */
45struct SessionRecord 49struct GNUNET_ATS_AddressRecord
46{ 50{
47 /** 51 /**
48 * Identity of the peer (just needed for error checking). 52 * Address data.
49 */ 53 */
50 struct GNUNET_PeerIdentity peer; 54 struct GNUNET_HELLO_Address *address;
51 55
52 /** 56 /**
53 * Session handle. 57 * Session handle. NULL if we have an address but no
58 * active session for this address.
54 */ 59 */
55 struct Session *session; 60 struct Session *session;
56 61
57 /** 62 /**
58 * Set to #GNUNET_YES if the slot is used. 63 * Array with performance data about the address.
59 */ 64 */
60 int slot_used; 65 struct GNUNET_ATS_Information *ats;
66
67 /**
68 * Number of entries in @e ats.
69 */
70 uint32_t ats_count;
71
72 /**
73 * Which slot (index) in the session array does
74 * this record correspond to? FIXME:
75 * FIXME: a linear search on this is really crappy!
76 * Maybe switch to a 64-bit global counter and be
77 * done with it? Or does that then cause too much
78 * trouble on the ATS-service side?
79 */
80 uint32_t slot;
81
82 /**
83 * Is this address currently in use?
84 * FIXME: document what "in use" means, and why it
85 * is important!
86 */
87 int in_use;
88
89 /**
90 * We're about to destroy this address record, just ATS does
91 * not know this yet.
92 */
93 int in_destroy;
61}; 94};
62 95
63 96
@@ -162,7 +195,7 @@ struct GNUNET_ATS_SchedulingHandle
162 * network). Index 0 is always NULL and reserved to represent the NULL pointer. 195 * network). Index 0 is always NULL and reserved to represent the NULL pointer.
163 * Unused entries are also NULL. 196 * Unused entries are also NULL.
164 */ 197 */
165 struct SessionRecord *session_array; 198 struct GNUNET_ATS_AddressRecord **session_array;
166 199
167 /** 200 /**
168 * Task to trigger reconnect. 201 * Task to trigger reconnect.
@@ -240,14 +273,12 @@ force_reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
240 * @param peer peer the session belongs to 273 * @param peer peer the session belongs to
241 * @return the session object (or NULL) 274 * @return the session object (or NULL)
242 */ 275 */
243static struct Session * 276static struct GNUNET_ATS_AddressRecord *
244find_session (struct GNUNET_ATS_SchedulingHandle *sh, 277find_session (struct GNUNET_ATS_SchedulingHandle *sh,
245 uint32_t session_id, 278 uint32_t session_id,
246 const struct GNUNET_PeerIdentity *peer) 279 const struct GNUNET_PeerIdentity *peer)
247{ 280{
248 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", 281 struct GNUNET_ATS_AddressRecord *ar;
249 "Find session %u from peer %s in %p\n",
250 (unsigned int) session_id, GNUNET_i2s (peer), sh);
251 282
252 if (session_id >= sh->session_array_size) 283 if (session_id >= sh->session_array_size)
253 { 284 {
@@ -256,90 +287,58 @@ find_session (struct GNUNET_ATS_SchedulingHandle *sh,
256 } 287 }
257 if (0 == session_id) 288 if (0 == session_id)
258 return NULL; 289 return NULL;
259 if (sh->session_array[session_id].session == NULL) 290 ar = sh->session_array[session_id];
291 if (NULL == ar)
260 { 292 {
261 GNUNET_break (0 == 293 GNUNET_break (0);
262 memcmp (peer, &sh->session_array[session_id].peer,
263 sizeof (struct GNUNET_PeerIdentity)));
264 return NULL; 294 return NULL;
265 } 295 }
266 296 if (NULL == ar->address)
267 if (0 !=
268 memcmp (peer, &sh->session_array[session_id].peer,
269 sizeof (struct GNUNET_PeerIdentity)))
270 { 297 {
271 GNUNET_break (0); 298 /* address was destroyed in the meantime, this can happen
272 force_reconnect (sh); 299 as we communicate asynchronously with the ATS service. */
273 return NULL; 300 return NULL;
274 } 301 }
275 /* This check exploits the fact that first field of a session object 302 if (0 != memcmp (peer,
276 * is peer identity. 303 &ar->address->peer,
277 */ 304 sizeof (struct GNUNET_PeerIdentity)))
278 if (0 !=
279 memcmp (peer, sh->session_array[session_id].session,
280 sizeof (struct GNUNET_PeerIdentity)))
281 { 305 {
282 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
283 "ats-scheduling-api",
284 "Session %p belongs to peer `%s'\n",
285 sh->session_array[session_id].session,
286 GNUNET_i2s_full ((struct GNUNET_PeerIdentity *) &sh->session_array[session_id].peer));
287/*
288 GNUNET_break (0); 306 GNUNET_break (0);
289 sh->reconnect = GNUNET_YES; 307 force_reconnect (sh);
290 return NULL; 308 return NULL;
291*/
292 } 309 }
293 return sh->session_array[session_id].session; 310 return ar;
294} 311}
295 312
296 313
297/** 314/**
298 * Get an available session ID for the given session object. 315 * Get an available session ID.
299 * 316 *
300 * @param sh our handle 317 * @param sh our handle
301 * @param session session object 318 * @return an unused slot, but never NOT_FOUND (0)
302 * @param peer peer the session belongs to
303 * @return the session id
304 */ 319 */
305static uint32_t 320static uint32_t
306find_empty_session_slot (struct GNUNET_ATS_SchedulingHandle *sh, 321find_empty_session_slot (struct GNUNET_ATS_SchedulingHandle *sh)
307 struct Session *session,
308 const struct GNUNET_PeerIdentity *peer)
309{ 322{
310 unsigned int i; 323 static uint32_t off;
311 unsigned int f; 324 uint32_t i;
312 325
313 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 326 i = 0;
314 "ats-scheduling-api", 327 while ( ( (NOT_FOUND == off) ||
315 "Get session ID for session %p from peer %s in %p\n", 328 (NULL != sh->session_array[off % sh->session_array_size]) ) &&
316 session, 329 (i < sh->session_array_size) )
317 GNUNET_i2s (peer),
318 sh);
319 if (NULL == session)
320 return NOT_FOUND;
321 f = 0;
322 for (i = 1; i < sh->session_array_size; i++)
323 {
324 if ((f == 0) && (sh->session_array[i].slot_used == GNUNET_NO))
325 f = i;
326 }
327 if (f == 0)
328 { 330 {
329 f = sh->session_array_size; 331 off++;
330 GNUNET_array_grow (sh->session_array, sh->session_array_size, 332 i++;
331 sh->session_array_size * 2);
332 } 333 }
333 GNUNET_assert (f > 0); 334 if ( (NOT_FOUND != off) &&
334 sh->session_array[f].session = session; 335 (NULL == sh->session_array[off % sh->session_array_size]) )
335 sh->session_array[f].peer = *peer; 336 return off;
336 sh->session_array[f].slot_used = GNUNET_YES; 337 i = sh->session_array_size;
337 338 GNUNET_array_grow (sh->session_array,
338 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", 339 sh->session_array_size,
339 "Assigning session ID %u for session %p of peer %s in %p\n", f, 340 sh->session_array_size * 2);
340 session, GNUNET_i2s (peer), sh); 341 return i;
341
342 return f;
343} 342}
344 343
345 344
@@ -348,100 +347,47 @@ find_empty_session_slot (struct GNUNET_ATS_SchedulingHandle *sh,
348 * 347 *
349 * @param sh our handle 348 * @param sh our handle
350 * @param session session object 349 * @param session session object
351 * @param peer peer the session belongs to 350 * @param address the address we are looking for
352 * @return the session id or NOT_FOUND for error 351 * @return the session id or NOT_FOUND for error
353 */ 352 */
354static uint32_t 353static uint32_t
355find_session_id (struct GNUNET_ATS_SchedulingHandle *sh, 354find_session_id (struct GNUNET_ATS_SchedulingHandle *sh,
356 struct Session *session, 355 struct Session *session,
357 const struct GNUNET_PeerIdentity *peer) 356 const struct GNUNET_HELLO_Address *address)
358{ 357{
359 unsigned int i; 358 uint32_t i;
360 char * p2;
361 359
362 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", 360 if (NULL == address)
363 "Get session ID for session %p from peer %s in %p\n", session, 361 {
364 GNUNET_i2s (peer), sh); 362 GNUNET_break (0);
365
366 if (NULL == session)
367 return NOT_FOUND; 363 return NOT_FOUND;
364 }
368 for (i = 1; i < sh->session_array_size; i++) 365 for (i = 1; i < sh->session_array_size; i++)
369 { 366 if ( (NULL != sh->session_array[i]) &&
370 if (session == sh->session_array[i].session) 367 ( (session == sh->session_array[i]->session) ||
371 { 368 (NULL == sh->session_array[i]->session) ) &&
372 if (0 != memcmp (peer, &sh->session_array[i].peer, 369 (0 == GNUNET_HELLO_address_cmp (address,
373 sizeof (struct GNUNET_PeerIdentity))) 370 sh->session_array[i]->address)) )
374 {
375 p2 = strdup (GNUNET_i2s (&sh->session_array[i].peer));
376 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "ats-scheduling-api",
377 "Session %p did not match: old session was for peer `%s' new session is for `%s'\n",
378 session, GNUNET_i2s (peer), p2);
379 GNUNET_free (p2);
380 return NOT_FOUND;
381 }
382 return i; 371 return i;
383 }
384 }
385 return NOT_FOUND; 372 return NOT_FOUND;
386} 373}
387 374
388 375
389/** 376/**
390 * Remove the session of the given session ID from the session
391 * table (it is no longer valid).
392 *
393 * @param sh our handle
394 * @param session_id identifies session that is no longer valid
395 * @param peer peer the session belongs to
396 */
397static void
398remove_session (struct GNUNET_ATS_SchedulingHandle *sh,
399 uint32_t session_id,
400 const struct GNUNET_PeerIdentity *peer)
401{
402 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
403 "ats-scheduling-api",
404 "Release sessionID %u from peer %s in %p\n",
405 (unsigned int) session_id,
406 GNUNET_i2s (peer),
407 sh);
408
409 if (0 == session_id)
410 return;
411
412 GNUNET_assert (session_id < sh->session_array_size);
413 GNUNET_assert (GNUNET_YES == sh->session_array[session_id].slot_used);
414 GNUNET_assert (0 == memcmp (peer,
415 &sh->session_array[session_id].peer,
416 sizeof (struct GNUNET_PeerIdentity)));
417 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api",
418 "Session %p for peer `%s' removed from slot %u \n",
419 sh->session_array[session_id].session,
420 GNUNET_i2s (peer),
421 session_id);
422 sh->session_array[session_id].session = NULL;
423}
424
425
426/**
427 * Release the session slot from the session table (ATS service is 377 * Release the session slot from the session table (ATS service is
428 * also done using it). 378 * also done using it).
429 * 379 *
430 * @param sh our handle 380 * @param sh our handle
431 * @param session_id identifies session that is no longer valid 381 * @param session_id identifies session that is no longer valid
432 * @param peer peer the session belongs to
433 */ 382 */
434static void 383static void
435release_session (struct GNUNET_ATS_SchedulingHandle *sh, 384release_session (struct GNUNET_ATS_SchedulingHandle *sh,
436 uint32_t session_id, 385 uint32_t session_id)
437 const struct GNUNET_PeerIdentity *peer)
438{ 386{
439 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 387 struct GNUNET_ATS_AddressRecord *ar;
440 "ats-scheduling-api", 388
441 "Release sessionID %u from peer %s in %p\n", 389 if (NOT_FOUND == session_id)
442 (unsigned int) session_id, 390 return;
443 GNUNET_i2s (peer),
444 sh);
445 if (session_id >= sh->session_array_size) 391 if (session_id >= sh->session_array_size)
446 { 392 {
447 GNUNET_break (0); 393 GNUNET_break (0);
@@ -449,20 +395,16 @@ release_session (struct GNUNET_ATS_SchedulingHandle *sh,
449 return; 395 return;
450 } 396 }
451 /* this slot should have been removed from remove_session before */ 397 /* this slot should have been removed from remove_session before */
452 GNUNET_assert (sh->session_array[session_id].session == NULL); 398 ar = sh->session_array[session_id];
453 399 if (NULL != ar->session)
454 if (0 !=
455 memcmp (peer, &sh->session_array[session_id].peer,
456 sizeof (struct GNUNET_PeerIdentity)))
457 { 400 {
458 GNUNET_break (0); 401 GNUNET_break (0);
459 force_reconnect (sh); 402 force_reconnect (sh);
460 return; 403 return;
461 } 404 }
462 sh->session_array[session_id].slot_used = GNUNET_NO; 405 GNUNET_HELLO_address_free (ar->address);
463 memset (&sh->session_array[session_id].peer, 406 GNUNET_free (ar);
464 0, 407 sh->session_array[session_id] = NULL;
465 sizeof (struct GNUNET_PeerIdentity));
466} 408}
467 409
468 410
@@ -481,10 +423,9 @@ process_ats_session_release_message (void *cls,
481 const struct SessionReleaseMessage *srm; 423 const struct SessionReleaseMessage *srm;
482 424
483 srm = (const struct SessionReleaseMessage *) msg; 425 srm = (const struct SessionReleaseMessage *) msg;
484 426 /* FIXME: peer field in srm not necessary anymore */
485 release_session (sh, 427 release_session (sh,
486 ntohl (srm->session_id), 428 ntohl (srm->session_id));
487 &srm->peer);
488} 429}
489 430
490 431
@@ -509,6 +450,7 @@ process_ats_address_suggestion_message (void *cls,
509 uint32_t ats_count; 450 uint32_t ats_count;
510 struct GNUNET_HELLO_Address address; 451 struct GNUNET_HELLO_Address address;
511 struct Session *s; 452 struct Session *s;
453 struct GNUNET_ATS_AddressRecord *ar;
512 454
513 if (ntohs (msg->size) <= sizeof (struct AddressSuggestionMessage)) 455 if (ntohs (msg->size) <= sizeof (struct AddressSuggestionMessage))
514 { 456 {
@@ -516,6 +458,8 @@ process_ats_address_suggestion_message (void *cls,
516 force_reconnect (sh); 458 force_reconnect (sh);
517 return; 459 return;
518 } 460 }
461 /* FIXME: we have all the address details, no need for ATS
462 to send those back to us any longer! */
519 m = (const struct AddressSuggestionMessage *) msg; 463 m = (const struct AddressSuggestionMessage *) msg;
520 ats_count = ntohl (m->ats_count); 464 ats_count = ntohl (m->ats_count);
521 plugin_address_length = ntohs (m->address_length); 465 plugin_address_length = ntohs (m->address_length);
@@ -536,22 +480,29 @@ process_ats_address_suggestion_message (void *cls,
536 } 480 }
537 uint32_t session_id = ntohl (m->session_id); 481 uint32_t session_id = ntohl (m->session_id);
538 482
539 if (session_id == 0) 483 if (0 == session_id)
540 s = NULL;
541 else
542 { 484 {
543 s = find_session (sh, session_id, &m->peer); 485 GNUNET_break (0);
544 if (NULL == s) 486 force_reconnect (sh);
545 { 487 return;
546 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 488 }
547 "ats-scheduling-api", 489 ar = find_session (sh, session_id, &m->peer);
548 "ATS tries to use outdated session `%s'\n", 490 if (NULL == ar)
549 GNUNET_i2s (&m->peer)); 491 {
550 return; 492 GNUNET_break (0);
551 } 493 force_reconnect (sh);
494 return;
552 } 495 }
496 s = ar->session;
553 if (NULL == sh->suggest_cb) 497 if (NULL == sh->suggest_cb)
554 return; 498 return;
499 if ( (GNUNET_YES == ar->in_destroy) &&
500 ( (0 != ntohl (m->bandwidth_out.value__)) ||
501 (0 != ntohl (m->bandwidth_in.value__)) ) )
502 {
503 /* ignore suggestion, as this address is dying */
504 return;
505 }
555 address.peer = m->peer; 506 address.peer = m->peer;
556 address.address = plugin_address; 507 address.address = plugin_address;
557 address.address_length = plugin_address_length; 508 address.address_length = plugin_address_length;
@@ -600,6 +551,66 @@ error_handler (void *cls,
600 551
601 552
602/** 553/**
554 * Generate the "AddressUpdateMessage" for the given
555 * session record.
556 *
557 * @param sh the scheduling handle to use for transmission
558 * @param ar the address to inform the ATS service about
559 * @param msg_type the message type to use when sending the message
560 *
561 * FIXME: maybe overloading with msg_type was not the best idea here...
562 */
563static void
564send_add_address_message (struct GNUNET_ATS_SchedulingHandle *sh,
565 const struct GNUNET_ATS_AddressRecord *ar,
566 uint16_t msg_type)
567{
568 struct GNUNET_MQ_Envelope *ev;
569 struct AddressUpdateMessage *m;
570 struct GNUNET_ATS_Information *am;
571 char *pm;
572 size_t namelen;
573 size_t msize;
574
575 if (NULL == sh->mq)
576 return; /* disconnected, skip for now */
577 namelen = (NULL == ar->address->transport_name)
578 ? 0
579 : strlen (ar->address->transport_name) + 1;
580 msize = ar->address->address_length +
581 ar->ats_count * sizeof (struct GNUNET_ATS_Information) + namelen;
582
583 ev = GNUNET_MQ_msg_extra (m, msize, msg_type);
584 m->ats_count = htonl (ar->ats_count);
585 m->peer = ar->address->peer;
586 m->address_length = htons (ar->address->address_length);
587 m->address_local_info = htonl ((uint32_t) ar->address->local_info);
588 m->plugin_name_length = htons (namelen);
589 m->session_id = htonl (ar->slot);
590
591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
592 "Adding address for peer `%s', plugin `%s', session %p id %u\n",
593 GNUNET_i2s (&ar->address->peer),
594 ar->address->transport_name,
595 ar->session,
596 ar->slot);
597 am = (struct GNUNET_ATS_Information *) &m[1];
598 memcpy (am,
599 ar->ats,
600 ar->ats_count * sizeof (struct GNUNET_ATS_Information));
601 pm = (char *) &am[ar->ats_count];
602 memcpy (pm,
603 ar->address->address,
604 ar->address->address_length);
605 if (NULL != ar->address->transport_name)
606 memcpy (&pm[ar->address->address_length],
607 ar->address->transport_name,
608 namelen);
609 GNUNET_MQ_send (sh->mq, ev);
610}
611
612
613/**
603 * Re-establish the connection to the ATS service. 614 * Re-establish the connection to the ATS service.
604 * 615 *
605 * @param sh handle to use to re-connect. 616 * @param sh handle to use to re-connect.
@@ -1082,7 +1093,7 @@ GNUNET_ATS_reset_backoff (struct GNUNET_ATS_SchedulingHandle *sh,
1082 * 1093 *
1083 * @param sh handle 1094 * @param sh handle
1084 * @param peer identity of the peer we need an address for 1095 * @param peer identity of the peer we need an address for
1085 * @return suggest handle 1096 * @return suggest handle, NULL if a request is already pending
1086 */ 1097 */
1087struct GNUNET_ATS_SuggestHandle * 1098struct GNUNET_ATS_SuggestHandle *
1088GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh, 1099GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh,
@@ -1094,11 +1105,15 @@ GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh,
1094 1105
1095 s = GNUNET_new (struct GNUNET_ATS_SuggestHandle); 1106 s = GNUNET_new (struct GNUNET_ATS_SuggestHandle);
1096 s->id = *peer; 1107 s->id = *peer;
1097 GNUNET_break (GNUNET_OK == 1108 if (GNUNET_OK !=
1098 GNUNET_CONTAINER_multipeermap_put (sh->sug_requests, 1109 GNUNET_CONTAINER_multipeermap_put (sh->sug_requests,
1099 &s->id, 1110 &s->id,
1100 s, 1111 s,
1101 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 1112 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1113 {
1114 GNUNET_break (0);
1115 return NULL;
1116 }
1102 if (NULL == sh->mq) 1117 if (NULL == sh->mq)
1103 return s; 1118 return s;
1104 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS); 1119 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS);
@@ -1161,7 +1176,7 @@ GNUNET_ATS_session_known (struct GNUNET_ATS_SchedulingHandle *sh,
1161 return GNUNET_NO; 1176 return GNUNET_NO;
1162 if (NOT_FOUND != find_session_id (sh, 1177 if (NOT_FOUND != find_session_id (sh,
1163 session, 1178 session,
1164 &address->peer)) 1179 address))
1165 return GNUNET_YES; /* Exists */ 1180 return GNUNET_YES; /* Exists */
1166 return GNUNET_NO; 1181 return GNUNET_NO;
1167} 1182}
@@ -1186,24 +1201,20 @@ GNUNET_ATS_address_add (struct GNUNET_ATS_SchedulingHandle *sh,
1186 const struct GNUNET_ATS_Information *ats, 1201 const struct GNUNET_ATS_Information *ats,
1187 uint32_t ats_count) 1202 uint32_t ats_count)
1188{ 1203{
1189 struct GNUNET_MQ_Envelope *ev; 1204 struct GNUNET_ATS_AddressRecord *ar;
1190 struct AddressUpdateMessage *m;
1191 struct GNUNET_ATS_Information *am;
1192 char *pm;
1193 size_t namelen; 1205 size_t namelen;
1194 size_t msize; 1206 size_t msize;
1195 uint32_t s = 0; 1207 uint32_t s;
1196 1208
1197 if (NULL == address) 1209 if (NULL == address)
1198 { 1210 {
1211 /* we need a valid address */
1199 GNUNET_break (0); 1212 GNUNET_break (0);
1200 return GNUNET_SYSERR; 1213 return GNUNET_SYSERR;
1201 } 1214 }
1202
1203 namelen = (NULL == address->transport_name) 1215 namelen = (NULL == address->transport_name)
1204 ? 0 1216 ? 0
1205 : strlen (address->transport_name) + 1; 1217 : strlen (address->transport_name) + 1;
1206
1207 msize = address->address_length + 1218 msize = address->address_length +
1208 ats_count * sizeof (struct GNUNET_ATS_Information) + namelen; 1219 ats_count * sizeof (struct GNUNET_ATS_Information) + namelen;
1209 if ((msize + sizeof (struct AddressUpdateMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || 1220 if ((msize + sizeof (struct AddressUpdateMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
@@ -1212,48 +1223,28 @@ GNUNET_ATS_address_add (struct GNUNET_ATS_SchedulingHandle *sh,
1212 (ats_count >= 1223 (ats_count >=
1213 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information))) 1224 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)))
1214 { 1225 {
1226 /* address too large for us, this should not happen */
1215 GNUNET_break (0); 1227 GNUNET_break (0);
1216 return GNUNET_SYSERR; 1228 return GNUNET_SYSERR;
1217 } 1229 }
1218 1230
1219 if (NULL != session) 1231 if (NOT_FOUND != find_session_id (sh, session, address))
1220 { 1232 {
1221 if (NOT_FOUND != (s = find_session_id (sh, session, &address->peer))) 1233 /* Already existing, nothing todo, but this should not happen */
1222 { 1234 GNUNET_break (0);
1223 /* Already existing, nothing todo */ 1235 return GNUNET_SYSERR;
1224 return GNUNET_SYSERR;
1225 }
1226 s = find_empty_session_slot (sh,
1227 session,
1228 &address->peer);
1229 GNUNET_break (NOT_FOUND != s);
1230 } 1236 }
1231 1237 s = find_empty_session_slot (sh);
1232 ev = GNUNET_MQ_msg_extra (m, msize, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD); 1238 ar = GNUNET_new (struct GNUNET_ATS_AddressRecord);
1233 m->ats_count = htonl (ats_count); 1239 ar->slot = s;
1234 m->peer = address->peer; 1240 ar->session = session;
1235 m->address_length = htons (address->address_length); 1241 ar->address = GNUNET_HELLO_address_copy (address);
1236 m->address_local_info = htonl ((uint32_t) address->local_info); 1242 GNUNET_array_grow (ar->ats,
1237 m->plugin_name_length = htons (namelen); 1243 ar->ats_count,
1238 m->session_id = htonl (s); 1244 ats_count);
1239 1245 memcpy (ar->ats, ats, ats_count * sizeof (struct GNUNET_ATS_Information));
1240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1246 sh->session_array[s] = ar;
1241 "Adding address for peer `%s', plugin `%s', session %p id %u\n", 1247 send_add_address_message (sh, ar, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD);
1242 GNUNET_i2s (&address->peer),
1243 address->transport_name,
1244 session,
1245 s);
1246 am = (struct GNUNET_ATS_Information *) &m[1];
1247 memcpy (am,
1248 ats,
1249 ats_count * sizeof (struct GNUNET_ATS_Information));
1250 pm = (char *) &am[ats_count];
1251 memcpy (pm, address->address, address->address_length);
1252 if (NULL != address->transport_name)
1253 memcpy (&pm[address->address_length],
1254 address->transport_name,
1255 namelen);
1256 GNUNET_MQ_send (sh->mq, ev);
1257 return GNUNET_OK; 1248 return GNUNET_OK;
1258} 1249}
1259 1250
@@ -1266,6 +1257,8 @@ GNUNET_ATS_address_add (struct GNUNET_ATS_SchedulingHandle *sh,
1266 * which case the call may be ignored or the information may be stored 1257 * which case the call may be ignored or the information may be stored
1267 * for later use). Update bandwidth assignments. 1258 * for later use). Update bandwidth assignments.
1268 * 1259 *
1260 * FIXME: change API so we do not have to do the linear search!
1261 *
1269 * @param sh handle 1262 * @param sh handle
1270 * @param address the address 1263 * @param address the address
1271 * @param session session handle, can be NULL 1264 * @param session session handle, can be NULL
@@ -1281,69 +1274,24 @@ GNUNET_ATS_address_update (struct GNUNET_ATS_SchedulingHandle *sh,
1281 const struct GNUNET_ATS_Information *ats, 1274 const struct GNUNET_ATS_Information *ats,
1282 uint32_t ats_count) 1275 uint32_t ats_count)
1283{ 1276{
1284 struct GNUNET_MQ_Envelope *ev; 1277 uint32_t s;
1285 struct AddressUpdateMessage *m; 1278 struct GNUNET_ATS_AddressRecord *ar;
1286 struct GNUNET_ATS_Information *am;
1287 char *pm;
1288 size_t namelen;
1289 size_t msize;
1290 uint32_t s = 0;
1291
1292 if (NULL == address)
1293 {
1294 GNUNET_break (0);
1295 return GNUNET_SYSERR;
1296 }
1297 if (NULL == sh)
1298 {
1299 GNUNET_break (0);
1300 return GNUNET_SYSERR;
1301 }
1302 1279
1303 namelen = (address->transport_name == 1280 s = find_session_id (sh, session, address);
1304 NULL) ? 0 : strlen (address->transport_name) + 1; 1281 if (NOT_FOUND == s)
1305 msize = address->address_length +
1306 ats_count * sizeof (struct GNUNET_ATS_Information) + namelen;
1307 if ((msize + sizeof (struct AddressUpdateMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
1308 (address->address_length >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
1309 (namelen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
1310 (ats_count >=
1311 GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)))
1312 { 1282 {
1313 GNUNET_break (0); 1283 GNUNET_break (0);
1314 return GNUNET_SYSERR; 1284 return GNUNET_NO;
1315 }
1316
1317 if (NULL != session)
1318 {
1319 s = find_session_id (sh, session, &address->peer);
1320 if (NOT_FOUND == s)
1321 return GNUNET_NO;
1322 } 1285 }
1323 1286 ar = sh->session_array[s];
1324 ev = GNUNET_MQ_msg_extra (m, msize, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE); 1287 GNUNET_array_grow (ar->ats,
1325 m->ats_count = htonl (ats_count); 1288 ar->ats_count,
1326 m->peer = address->peer; 1289 ats_count);
1327 m->address_length = htons (address->address_length); 1290 memcpy (ar->ats,
1328 m->address_local_info = htonl ((uint32_t) address->local_info);
1329 m->plugin_name_length = htons (namelen);
1330 m->session_id = htonl (s);
1331
1332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1333 "Updating address for peer `%s', plugin `%s', session %p id %u\n",
1334 GNUNET_i2s (&address->peer),
1335 address->transport_name,
1336 session,
1337 s);
1338
1339 am = (struct GNUNET_ATS_Information *) &m[1];
1340 memcpy (am,
1341 ats, 1291 ats,
1342 ats_count * sizeof (struct GNUNET_ATS_Information)); 1292 ats_count * sizeof (struct GNUNET_ATS_Information));
1343 pm = (char *) &am[ats_count]; 1293 ar->session = session;
1344 memcpy (pm, address->address, address->address_length); 1294 send_add_address_message (sh, ar, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE);
1345 memcpy (&pm[address->address_length], address->transport_name, namelen);
1346 GNUNET_MQ_send (sh->mq, ev);
1347 return GNUNET_YES; 1295 return GNUNET_YES;
1348} 1296}
1349 1297
@@ -1365,42 +1313,25 @@ GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh,
1365{ 1313{
1366 struct GNUNET_MQ_Envelope *ev; 1314 struct GNUNET_MQ_Envelope *ev;
1367 struct AddressUseMessage *m; 1315 struct AddressUseMessage *m;
1316 struct GNUNET_ATS_AddressRecord *ar;
1368 char *pm; 1317 char *pm;
1369 size_t namelen; 1318 size_t namelen;
1370 size_t msize; 1319 size_t msize;
1371 uint32_t s = 0; 1320 uint32_t s = 0;
1372 1321
1373 namelen = 1322 s = find_session_id (sh, session, address);
1374 (address->transport_name == 1323 if (s == NOT_FOUND)
1375 NULL) ? 0 : strlen (address->transport_name) + 1;
1376 msize = address->address_length + namelen;
1377 if ((msize + sizeof (struct AddressUseMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
1378 (address->address_length >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
1379 (namelen >= GNUNET_SERVER_MAX_MESSAGE_SIZE))
1380 { 1324 {
1325 /* trying to set unknown address to NO */
1381 GNUNET_break (0); 1326 GNUNET_break (0);
1382 return; 1327 return;
1383 } 1328 }
1384 1329 ar = sh->session_array[s];
1385 if (NULL != session) 1330 ar->in_use = in_use;
1386 { 1331 namelen = (NULL == address->transport_name)
1387 s = find_session_id (sh, session, &address->peer); 1332 ? 0
1388 if ((s == NOT_FOUND) && (GNUNET_NO == in_use)) 1333 : strlen (address->transport_name) + 1;
1389 { 1334 msize = address->address_length + namelen;
1390 /* trying to set unknown address to NO */
1391 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1392 "Trying to set unknown address to unused for peer `%s', plugin `%s', session %p\n",
1393 GNUNET_i2s (&address->peer), address->transport_name, session);
1394 GNUNET_break (0);
1395 return;
1396 }
1397 if ((s == NOT_FOUND) && (GNUNET_YES == in_use))
1398 {
1399 /* trying to set new address to YES */
1400 s = find_empty_session_slot (sh, session, &address->peer);
1401 GNUNET_assert (NOT_FOUND != s);
1402 }
1403 }
1404 1335
1405 ev = GNUNET_MQ_msg_extra (m, msize, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_IN_USE); 1336 ev = GNUNET_MQ_msg_extra (m, msize, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_IN_USE);
1406 m->peer = address->peer; 1337 m->peer = address->peer;
@@ -1412,10 +1343,13 @@ GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh,
1412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1413 "Setting address used to %s for peer `%s', plugin `%s', session %p\n", 1344 "Setting address used to %s for peer `%s', plugin `%s', session %p\n",
1414 (GNUNET_YES == in_use) ? "YES" : "NO", 1345 (GNUNET_YES == in_use) ? "YES" : "NO",
1415 GNUNET_i2s (&address->peer), address->transport_name, session); 1346 GNUNET_i2s (&address->peer),
1347 address->transport_name,
1348 session);
1416 1349
1417 m->session_id = htonl (s); 1350 m->session_id = htonl (s);
1418 pm = (char *) &m[1]; 1351 pm = (char *) &m[1];
1352 /* FIXME: no need to send the address data */
1419 memcpy (pm, address->address, address->address_length); 1353 memcpy (pm, address->address, address->address_length);
1420 memcpy (&pm[address->address_length], address->transport_name, namelen); 1354 memcpy (&pm[address->address_length], address->transport_name, namelen);
1421 GNUNET_MQ_send (sh->mq, ev); 1355 GNUNET_MQ_send (sh->mq, ev);
@@ -1428,6 +1362,9 @@ GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh,
1428 * If a session is given, only the session will be removed, if no session is 1362 * If a session is given, only the session will be removed, if no session is
1429 * given the full address will be deleted. 1363 * given the full address will be deleted.
1430 * 1364 *
1365 * FIXME: the above sentence already indicates that this API is a
1366 * mess and troublesome. FIX IT!
1367 *
1431 * @param sh handle 1368 * @param sh handle
1432 * @param address the address 1369 * @param address the address
1433 * @param session session handle that is no longer valid, can be NULL 1370 * @param session session handle that is no longer valid, can be NULL
@@ -1437,18 +1374,30 @@ GNUNET_ATS_address_destroyed (struct GNUNET_ATS_SchedulingHandle *sh,
1437 const struct GNUNET_HELLO_Address *address, 1374 const struct GNUNET_HELLO_Address *address,
1438 struct Session *session) 1375 struct Session *session)
1439{ 1376{
1377 uint32_t s;
1440 struct GNUNET_MQ_Envelope *ev; 1378 struct GNUNET_MQ_Envelope *ev;
1441 struct AddressDestroyedMessage *m; 1379 struct AddressDestroyedMessage *m;
1380 struct GNUNET_ATS_AddressRecord *ar;
1442 char *pm; 1381 char *pm;
1443 size_t namelen; 1382 size_t namelen;
1444 size_t msize; 1383 size_t msize;
1445 uint32_t s;
1446 1384
1447 if (NULL == address) 1385 s = find_session_id (sh, session, address);
1386 if (NOT_FOUND == s)
1448 { 1387 {
1449 GNUNET_break (0); 1388 GNUNET_break (0);
1450 return; 1389 return;
1451 } 1390 }
1391 ar = sh->session_array[s];
1392 if (NULL != session)
1393 {
1394 /* FIXME: this is yucky, fix API! */
1395 GNUNET_break (ar->session == session);
1396 ar->session = NULL;
1397 return;
1398 }
1399
1400
1452 GNUNET_assert (NULL != address->transport_name); 1401 GNUNET_assert (NULL != address->transport_name);
1453 namelen = strlen (address->transport_name) + 1; 1402 namelen = strlen (address->transport_name) + 1;
1454 GNUNET_assert (namelen > 1); 1403 GNUNET_assert (namelen > 1);
@@ -1461,16 +1410,6 @@ GNUNET_ATS_address_destroyed (struct GNUNET_ATS_SchedulingHandle *sh,
1461 return; 1410 return;
1462 } 1411 }
1463 1412
1464 s = find_session_id (sh, session, &address->peer);
1465 if ((NULL != session) && (NOT_FOUND == s))
1466 {
1467 /* trying to delete unknown address */
1468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1469 "Trying to delete unknown address for peer `%s', plugin `%s', session %p\n",
1470 GNUNET_i2s (&address->peer), address->transport_name, session);
1471 return;
1472 }
1473
1474 ev = GNUNET_MQ_msg_extra (m, msize, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED); 1413 ev = GNUNET_MQ_msg_extra (m, msize, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED);
1475 m->peer = address->peer; 1414 m->peer = address->peer;
1476 m->address_length = htons (address->address_length); 1415 m->address_length = htons (address->address_length);
@@ -1479,14 +1418,25 @@ GNUNET_ATS_address_destroyed (struct GNUNET_ATS_SchedulingHandle *sh,
1479 1418
1480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1419 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1481 "Deleting address for peer `%s', plugin `%s', session %p\n", 1420 "Deleting address for peer `%s', plugin `%s', session %p\n",
1482 GNUNET_i2s (&address->peer), address->transport_name, session); 1421 GNUNET_i2s (&address->peer),
1422 address->transport_name,
1423 session);
1483 1424
1484 m->session_id = htonl (s); 1425 m->session_id = htonl (s);
1485 pm = (char *) &m[1]; 1426 pm = (char *) &m[1];
1486 memcpy (pm, address->address, address->address_length); 1427 memcpy (pm,
1487 memcpy (&pm[address->address_length], address->transport_name, namelen); 1428 address->address,
1429 address->address_length);
1430 memcpy (&pm[address->address_length],
1431 address->transport_name,
1432 namelen);
1488 GNUNET_MQ_send (sh->mq, ev); 1433 GNUNET_MQ_send (sh->mq, ev);
1489 remove_session (sh, s, &address->peer); 1434 ar->session = NULL;
1435 ar->in_destroy = GNUNET_YES;
1436 GNUNET_array_grow (ar->ats,
1437 ar->ats_count,
1438 0);
1490} 1439}
1491 1440
1441
1492/* end of ats_api_scheduling.c */ 1442/* end of ats_api_scheduling.c */
diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c
index 7c9c921cc..abdc40c59 100644
--- a/src/ats/gnunet-service-ats_addresses.c
+++ b/src/ats/gnunet-service-ats_addresses.c
@@ -482,7 +482,7 @@ free_address (struct ATS_Address *addr)
482 * @param plugin_addr address 482 * @param plugin_addr address
483 * @param plugin_addr_len address length 483 * @param plugin_addr_len address length
484 * @param local_address_info additional local info for the address 484 * @param local_address_info additional local info for the address
485 * @param session_id session identifier, can be 0 485 * @param session_id session identifier, can never be 0
486 * @return the ATS_Address 486 * @return the ATS_Address
487 */ 487 */
488static struct ATS_Address * 488static struct ATS_Address *
@@ -493,9 +493,9 @@ create_address (const struct GNUNET_PeerIdentity *peer,
493 uint32_t local_address_info, 493 uint32_t local_address_info,
494 uint32_t session_id) 494 uint32_t session_id)
495{ 495{
496 struct ATS_Address *aa = NULL; 496 struct ATS_Address *aa;
497 int c1; 497 unsigned int c1;
498 int c2; 498 unsigned int c2;
499 499
500 aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len); 500 aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len);
501 aa->peer = *peer; 501 aa->peer = *peer;
@@ -505,10 +505,6 @@ create_address (const struct GNUNET_PeerIdentity *peer,
505 aa->plugin = GNUNET_strdup (plugin_name); 505 aa->plugin = GNUNET_strdup (plugin_name);
506 aa->session_id = session_id; 506 aa->session_id = session_id;
507 aa->local_address_info = local_address_info; 507 aa->local_address_info = local_address_info;
508 aa->assigned_bw_out = 0;
509 aa->assigned_bw_in = 0;
510 aa->last_notified_bw_out = 0;
511 aa->last_notified_bw_in = 0;
512 508
513 for (c1 = 0; c1 < GNUNET_ATS_QualityPropertiesCount; c1++) 509 for (c1 = 0; c1 < GNUNET_ATS_QualityPropertiesCount; c1++)
514 { 510 {
@@ -535,7 +531,7 @@ struct CompareAddressContext
535 531
536 532
537/** 533/**
538 * Comapre addresses 534 * Comapre addresses.
539 * 535 *
540 * @param cls a CompareAddressContext containin the source address 536 * @param cls a CompareAddressContext containin the source address
541 * @param key peer id 537 * @param key peer id
@@ -654,10 +650,9 @@ find_equivalent_address (struct GAS_Addresses_Handle *handle,
654 * @param plugin_addr plugin address 650 * @param plugin_addr plugin address
655 * @param plugin_addr_len length of the plugin address 651 * @param plugin_addr_len length of the plugin address
656 * @param local_address_info the local address for the address 652 * @param local_address_info the local address for the address
657 * @param session_id session id, can be 0 653 * @param session_id session id, can never be 0
658 * @return an ATS_address or NULL 654 * @return an ATS_address or NULL
659 */ 655 */
660
661static struct ATS_Address * 656static struct ATS_Address *
662find_exact_address (struct GAS_Addresses_Handle *handle, 657find_exact_address (struct GAS_Addresses_Handle *handle,
663 const struct GNUNET_PeerIdentity *peer, 658 const struct GNUNET_PeerIdentity *peer,
@@ -724,7 +719,7 @@ get_property_cb (void *cls, const struct ATS_Address *address)
724 * 719 *
725 * @param address the address 720 * @param address the address
726 * @param type the type to extract in HBO 721 * @param type the type to extract in HBO
727 * @return the value in HBO or GNUNET_ATS_VALUE_UNDEFINED in HBO if value does not exist 722 * @return the value in HBO or #GNUNET_ATS_VALUE_UNDEFINED in HBO if value does not exist
728 */ 723 */
729static int 724static int
730get_performance_info (struct ATS_Address *address, uint32_t type) 725get_performance_info (struct ATS_Address *address, uint32_t type)
@@ -791,15 +786,15 @@ GAS_addresses_add (struct GAS_Addresses_Handle *handle,
791 local_address_info, session_id); 786 local_address_info, session_id);
792 atsi_delta = NULL; 787 atsi_delta = NULL;
793 disassemble_ats_information (new_address, atsi, atsi_count, &atsi_delta, 788 disassemble_ats_information (new_address, atsi, atsi_count, &atsi_delta,
794 &atsi_delta_count); 789 &atsi_delta_count);
795 GNUNET_free_non_null(atsi_delta); 790 GNUNET_free_non_null (atsi_delta);
796 addr_net = get_performance_info (new_address, GNUNET_ATS_NETWORK_TYPE); 791 addr_net = get_performance_info (new_address, GNUNET_ATS_NETWORK_TYPE);
797 if (GNUNET_ATS_VALUE_UNDEFINED == addr_net) 792 if (GNUNET_ATS_VALUE_UNDEFINED == addr_net)
798 addr_net = GNUNET_ATS_NET_UNSPECIFIED; 793 addr_net = GNUNET_ATS_NET_UNSPECIFIED;
799 794
800 /* Get existing address or address with session == 0 */ 795 /* Get existing address or address with session == 0 */
801 existing_address = find_equivalent_address (handle, peer, new_address); 796 existing_address = find_equivalent_address (handle, peer, new_address);
802 if (existing_address == NULL ) 797 if (existing_address == NULL)
803 { 798 {
804 /* Add a new address */ 799 /* Add a new address */
805 new_address->t_added = GNUNET_TIME_absolute_get(); 800 new_address->t_added = GNUNET_TIME_absolute_get();
@@ -957,21 +952,29 @@ GAS_addresses_update (struct GAS_Addresses_Handle *handle,
957 952
958 if (GNUNET_NO == handle->running) 953 if (GNUNET_NO == handle->running)
959 return; 954 return;
960 955 GNUNET_assert (NULL != handle->addresses);
961 GNUNET_assert(NULL != handle->addresses);
962 956
963 /* Get existing address */ 957 /* Get existing address */
964 aa = find_exact_address (handle, peer, plugin_name, plugin_addr, 958 aa = find_exact_address (handle, peer, plugin_name, plugin_addr,
965 plugin_addr_len, local_address_info, session_id); 959 plugin_addr_len,
966 if (aa == NULL ) 960 local_address_info,
961 session_id);
962 if (aa == NULL)
963 {
964 GNUNET_break (0);
967 return; 965 return;
966 }
968 if (NULL == aa->solver_information) 967 if (NULL == aa->solver_information)
968 {
969 GNUNET_break (0);
969 return; 970 return;
971 }
970 972
971 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 973 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
972 "Received `%s' for peer `%s' address \n", 974 "Received `%s' for peer `%s' address \n",
973 "ADDRESS UPDATE", 975 "ADDRESS UPDATE",
974 GNUNET_i2s (peer), aa); 976 GNUNET_i2s (peer),
977 aa);
975 978
976 /* Update address */ 979 /* Update address */
977 aa->t_last_activity = GNUNET_TIME_absolute_get(); 980 aa->t_last_activity = GNUNET_TIME_absolute_get();
@@ -1047,11 +1050,7 @@ struct DestroyContext
1047 1050
1048 1051
1049/** 1052/**
1050 * Delete an address 1053 * Delete an address.
1051 *
1052 * If session != 0, just the session is deleted, the address itself still exists
1053 * If session == 0, remove full address
1054 * If session == 0 and addrlen == 0, destroy inbound address
1055 * 1054 *
1056 * @param cls unused 1055 * @param cls unused
1057 * @param key unused 1056 * @param key unused
@@ -1072,102 +1071,32 @@ destroy_by_session_id (void *cls,
1072 memcmp (&aa->peer, 1071 memcmp (&aa->peer,
1073 &des->peer, 1072 &des->peer,
1074 sizeof (struct GNUNET_PeerIdentity))); 1073 sizeof (struct GNUNET_PeerIdentity)));
1075 if (0 == des->session_id) 1074 if ( (0 != strcmp (des->plugin, aa->plugin)) ||
1076 { 1075 (aa->addr_len != des->addr_len) ||
1077 /* Session == 0, remove full address */ 1076 (0 != memcmp (des->addr, aa->addr, aa->addr_len)))
1078 if ((0 == strcmp (des->plugin, aa->plugin)) 1077 return GNUNET_OK; /* wrong entry */
1079 && (aa->addr_len == des->addr_len) 1078 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1080 && (0 == memcmp (des->addr, aa->addr, aa->addr_len))) 1079 "Deleting full address for peer `%s' session %u %p\n",
1081 { 1080 GNUNET_i2s (&aa->peer),
1082 1081 aa->session_id,
1083 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1082 aa);
1084 "Deleting full address for peer `%s' session %u %p\n", 1083 /* Notify solver about deletion */
1085 GNUNET_i2s (&aa->peer), 1084 GNUNET_assert (GNUNET_YES ==
1086 aa->session_id, 1085 GNUNET_CONTAINER_multipeermap_remove (handle->addresses,
1087 aa); 1086 &aa->peer,
1088 /* Notify solver about deletion */ 1087 aa));
1089 GNUNET_assert (GNUNET_YES == 1088 handle->env.sf.s_del (handle->solver, aa, GNUNET_NO);
1090 GNUNET_CONTAINER_multipeermap_remove (handle->addresses, 1089 GAS_performance_notify_all_clients (&aa->peer,
1091 &aa->peer, 1090 aa->plugin,
1092 aa)); 1091 aa->addr,
1093 handle->env.sf.s_del (handle->solver, aa, GNUNET_NO); 1092 aa->addr_len,
1094 GAS_performance_notify_all_clients (&aa->peer, 1093 GNUNET_SYSERR,
1095 aa->plugin, 1094 NULL, 0,
1096 aa->addr, 1095 zero_bw,
1097 aa->addr_len, 1096 zero_bw);
1098 GNUNET_SYSERR, 1097 free_address (aa);
1099 NULL, 0, 1098 dc->result = GNUNET_NO;
1100 zero_bw, 1099 return GNUNET_OK; /* Continue iteration */
1101 zero_bw);
1102 free_address (aa);
1103 dc->result = GNUNET_NO;
1104 return GNUNET_OK; /* Continue iteration */
1105 }
1106 }
1107 else
1108 {
1109 /* Session != 0, just remove session */
1110 if (aa->session_id != des->session_id)
1111 return GNUNET_OK; /* irrelevant */
1112
1113 if ((aa->session_id != 0) && (0 != strcmp (des->plugin, aa->plugin)))
1114 {
1115 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1116 "Different plugins during removal: `%s' vs `%s' \n",
1117 des->plugin,
1118 aa->plugin);
1119 GNUNET_break (0);
1120 return GNUNET_OK;
1121 }
1122 if (GNUNET_HELLO_ADDRESS_INFO_INBOUND ==
1123 (aa->local_address_info && GNUNET_HELLO_ADDRESS_INFO_INBOUND))
1124 {
1125 /* Inbound connection died, delete full address */
1126 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1127 "Deleting inbound address for peer `%s': `%s' session %u\n",
1128 GNUNET_i2s (&aa->peer),
1129 aa->plugin,
1130 aa->session_id);
1131
1132 /* Notify solver about deletion */
1133 GNUNET_assert(GNUNET_YES ==
1134 GNUNET_CONTAINER_multipeermap_remove (handle->addresses,
1135 &aa->peer, aa));
1136 handle->env.sf.s_del (handle->solver, aa, GNUNET_NO);
1137 GAS_performance_notify_all_clients (&aa->peer,
1138 aa->plugin,
1139 aa->addr,
1140 aa->addr_len,
1141 GNUNET_SYSERR,
1142 NULL, 0,
1143 zero_bw,
1144 zero_bw);
1145 free_address (aa);
1146 dc->result = GNUNET_NO;
1147 return GNUNET_OK; /* Continue iteration */
1148 }
1149 else
1150 {
1151 /* Session died */
1152 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1153 "Deleting session for peer `%s': `%s' %u\n",
1154 GNUNET_i2s (&aa->peer),
1155 aa->plugin, aa->session_id);
1156 /* Notify solver to delete session */
1157 handle->env.sf.s_del (handle->solver, aa, GNUNET_YES);
1158 aa->session_id = 0;
1159 GAS_performance_notify_all_clients (&aa->peer,
1160 aa->plugin,
1161 aa->addr,
1162 aa->addr_len,
1163 GNUNET_NO,
1164 NULL, 0,
1165 zero_bw,
1166 zero_bw);
1167 return GNUNET_OK;
1168 }
1169 }
1170 return GNUNET_OK;
1171} 1100}
1172 1101
1173 1102
@@ -1180,7 +1109,7 @@ destroy_by_session_id (void *cls,
1180 * @param plugin_addr plugin address 1109 * @param plugin_addr plugin address
1181 * @param plugin_addr_len length of the plugin address in @a plugin_addr 1110 * @param plugin_addr_len length of the plugin address in @a plugin_addr
1182 * @param local_address_info the local address for the address 1111 * @param local_address_info the local address for the address
1183 * @param session_id session id, can be 0 1112 * @param session_id session id, can never be 0
1184 */ 1113 */
1185void 1114void
1186GAS_addresses_destroy (struct GAS_Addresses_Handle *handle, 1115GAS_addresses_destroy (struct GAS_Addresses_Handle *handle,
@@ -1207,6 +1136,7 @@ GAS_addresses_destroy (struct GAS_Addresses_Handle *handle,
1207 session_id); 1136 session_id);
1208 if (NULL == ea) 1137 if (NULL == ea)
1209 { 1138 {
1139 GNUNET_break (0);
1210 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1140 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1211 "Tried to destroy unknown address for peer `%s' `%s' session id %u\n", 1141 "Tried to destroy unknown address for peer `%s' `%s' session id %u\n",
1212 GNUNET_i2s (peer), 1142 GNUNET_i2s (peer),
@@ -1323,7 +1253,7 @@ GAS_addresses_in_use (struct GAS_Addresses_Handle *handle,
1323 */ 1253 */
1324void 1254void
1325GAS_addresses_request_address_cancel (struct GAS_Addresses_Handle *handle, 1255GAS_addresses_request_address_cancel (struct GAS_Addresses_Handle *handle,
1326 const struct GNUNET_PeerIdentity *peer) 1256 const struct GNUNET_PeerIdentity *peer)
1327{ 1257{
1328 struct GAS_Addresses_Suggestion_Requests *cur = handle->pending_requests_head; 1258 struct GAS_Addresses_Suggestion_Requests *cur = handle->pending_requests_head;
1329 1259
diff --git a/src/ats/gnunet-service-ats_addresses.h b/src/ats/gnunet-service-ats_addresses.h
index fa1aa81d9..5dea30d77 100644
--- a/src/ats/gnunet-service-ats_addresses.h
+++ b/src/ats/gnunet-service-ats_addresses.h
@@ -319,7 +319,7 @@ struct ATS_Address
319 size_t addr_len; 319 size_t addr_len;
320 320
321 /** 321 /**
322 * Session ID, can be 0 322 * Session ID, can never be 0.
323 */ 323 */
324 uint32_t session_id; 324 uint32_t session_id;
325 325
@@ -445,7 +445,7 @@ GAS_addresses_done (struct GAS_Addresses_Handle *handle);
445 * @param plugin_addr plugin address 445 * @param plugin_addr plugin address
446 * @param plugin_addr_len length of the plugin address 446 * @param plugin_addr_len length of the plugin address
447 * @param local_address_info the local address for the address 447 * @param local_address_info the local address for the address
448 * @param session_id session id, can be 0. 448 * @param session_id session id, can never be 0.
449 * @param atsi performance information for this address 449 * @param atsi performance information for this address
450 * @param atsi_count number of performance information contained in @a atsi 450 * @param atsi_count number of performance information contained in @a atsi
451 */ 451 */
@@ -477,7 +477,7 @@ GAS_addresses_add (struct GAS_Addresses_Handle *handle,
477 * @param plugin_addr plugin address 477 * @param plugin_addr plugin address
478 * @param plugin_addr_len length of the plugin address in @a plugin_addr 478 * @param plugin_addr_len length of the plugin address in @a plugin_addr
479 * @param local_address_info the local address for the address 479 * @param local_address_info the local address for the address
480 * @param session_id session id, can be 0 480 * @param session_id session id, can never be 0
481 * @param in_use #GNUNET_YES if #GNUNET_NO FIXME 481 * @param in_use #GNUNET_YES if #GNUNET_NO FIXME
482 * @return #GNUNET_SYSERR on failure (address unknown ...) 482 * @return #GNUNET_SYSERR on failure (address unknown ...)
483 */ 483 */
@@ -504,7 +504,7 @@ GAS_addresses_in_use (struct GAS_Addresses_Handle *handle,
504 * @param plugin_addr plugin address 504 * @param plugin_addr plugin address
505 * @param plugin_addr_len length of the plugin address 505 * @param plugin_addr_len length of the plugin address
506 * @param local_address_info the local address for the address 506 * @param local_address_info the local address for the address
507 * @param session_id session id, can be 0 507 * @param session_id session id, can never be 0
508 * @param atsi performance information for this address 508 * @param atsi performance information for this address
509 * @param atsi_count number of performance information contained in @a atsi 509 * @param atsi_count number of performance information contained in @a atsi
510 */ 510 */
@@ -528,7 +528,7 @@ GAS_addresses_update (struct GAS_Addresses_Handle *handle,
528 * @param plugin_name transport plugin name 528 * @param plugin_name transport plugin name
529 * @param plugin_addr plugin address 529 * @param plugin_addr plugin address
530 * @param plugin_addr_len length of the plugin address in @a plugin_addr 530 * @param plugin_addr_len length of the plugin address in @a plugin_addr
531 * @param session_id session id, can be 0 531 * @param session_id session id, can never be 0
532 * @param local_address_info the local address for the address 532 * @param local_address_info the local address for the address
533 */ 533 */
534void 534void
diff --git a/src/ats/gnunet-service-ats_scheduling.c b/src/ats/gnunet-service-ats_scheduling.c
index 4b346d992..0d8b0fa25 100644
--- a/src/ats/gnunet-service-ats_scheduling.c
+++ b/src/ats/gnunet-service-ats_scheduling.c
@@ -93,7 +93,7 @@ GAS_scheduling_remove_client (struct GNUNET_SERVER_Client *client)
93 * @param plugin_addr binary address for the plugin to use 93 * @param plugin_addr binary address for the plugin to use
94 * @param plugin_addr_len number of bytes in @a plugin_addr 94 * @param plugin_addr_len number of bytes in @a plugin_addr
95 * @param local_address_info the local address for the address 95 * @param local_address_info the local address for the address
96 * @param session_id session ID to use for the given client (other clients will see 0) 96 * @param session_id session ID to use for the given client
97 * @param atsi performance data for the address 97 * @param atsi performance data for the address
98 * @param atsi_count number of performance records in @a atsi 98 * @param atsi_count number of performance records in @a atsi
99 * @param bandwidth_out assigned outbound bandwidth 99 * @param bandwidth_out assigned outbound bandwidth
@@ -499,15 +499,14 @@ GAS_handle_address_destroyed (void *cls,
499 address, address_length, 499 address, address_length,
500 ntohl (m->address_local_info), 500 ntohl (m->address_local_info),
501 ntohl (m->session_id)); 501 ntohl (m->session_id));
502 if (0 != ntohl (m->session_id)) 502 srm.header.type = ntohs (GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE);
503 { 503 srm.header.size = ntohs (sizeof (struct SessionReleaseMessage));
504 srm.header.type = ntohs (GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE); 504 srm.session_id = m->session_id;
505 srm.header.size = ntohs (sizeof (struct SessionReleaseMessage)); 505 srm.peer = m->peer;
506 srm.session_id = m->session_id; 506 GNUNET_SERVER_notification_context_unicast (nc,
507 srm.peer = m->peer; 507 client,
508 GNUNET_SERVER_notification_context_unicast (nc, client, &srm.header, 508 &srm.header,
509 GNUNET_NO); 509 GNUNET_NO);
510 }
511 GNUNET_SERVER_receive_done (client, GNUNET_OK); 510 GNUNET_SERVER_receive_done (client, GNUNET_OK);
512} 511}
513 512
diff --git a/src/include/gnunet_ats_service.h b/src/include/gnunet_ats_service.h
index e09dc5d75..ea70614cf 100644
--- a/src/include/gnunet_ats_service.h
+++ b/src/include/gnunet_ats_service.h
@@ -388,7 +388,7 @@ GNUNET_ATS_reset_backoff (struct GNUNET_ATS_SchedulingHandle *sh,
388 * 388 *
389 * @param sh handle 389 * @param sh handle
390 * @param peer identity of the peer we need an address for 390 * @param peer identity of the peer we need an address for
391 * @return suggestion handle 391 * @return suggestion handle, NULL if a request is already pending
392 */ 392 */
393struct GNUNET_ATS_SuggestHandle * 393struct GNUNET_ATS_SuggestHandle *
394GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh, 394GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh,