aboutsummaryrefslogtreecommitdiff
path: root/src/ats/ats_api_scheduling.c
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 /src/ats/ats_api_scheduling.c
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
Diffstat (limited to 'src/ats/ats_api_scheduling.c')
-rw-r--r--src/ats/ats_api_scheduling.c588
1 files changed, 269 insertions, 319 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 */