diff options
-rw-r--r-- | src/transport/Makefile.am | 94 | ||||
-rw-r--r-- | src/transport/transport_api.c | 2163 | ||||
-rw-r--r-- | src/transport/transport_api_new.c | 1471 |
3 files changed, 799 insertions, 2929 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 4121206c7..60bd9c6e2 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am | |||
@@ -65,22 +65,7 @@ endif | |||
65 | #noinst_PROGRAMS = ${check_PROGRAMS} | 65 | #noinst_PROGRAMS = ${check_PROGRAMS} |
66 | 66 | ||
67 | lib_LTLIBRARIES = \ | 67 | lib_LTLIBRARIES = \ |
68 | libgnunettransport.la \ | 68 | libgnunettransport.la |
69 | libgnunettransportnew.la | ||
70 | |||
71 | libgnunettransportnew_la_SOURCES = \ | ||
72 | transport_api_new.c transport.h \ | ||
73 | transport_api_blacklist.c \ | ||
74 | transport_api_address_lookup.c \ | ||
75 | transport_api_peer_address_lookup.c \ | ||
76 | transport_api_address_iterate.c | ||
77 | libgnunettransportnew_la_LIBADD = \ | ||
78 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
79 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
80 | $(GN_LIBINTL) | ||
81 | libgnunettransportnew_la_LDFLAGS = \ | ||
82 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
83 | -version-info 0:0:0 | ||
84 | 69 | ||
85 | libgnunettransport_la_SOURCES = \ | 70 | libgnunettransport_la_SOURCES = \ |
86 | transport_api.c transport.h \ | 71 | transport_api.c transport.h \ |
@@ -96,7 +81,6 @@ libgnunettransport_la_LDFLAGS = \ | |||
96 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | 81 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ |
97 | -version-info 0:0:0 | 82 | -version-info 0:0:0 |
98 | 83 | ||
99 | |||
100 | bin_PROGRAMS = \ | 84 | bin_PROGRAMS = \ |
101 | gnunet-transport \ | 85 | gnunet-transport \ |
102 | $(WLAN_BIN) \ | 86 | $(WLAN_BIN) \ |
@@ -132,20 +116,20 @@ gnunet_transport_wlan_helper_dummy_LDADD = \ | |||
132 | gnunet_transport_list_connections_SOURCES = \ | 116 | gnunet_transport_list_connections_SOURCES = \ |
133 | gnunet-transport-list-connections.c | 117 | gnunet-transport-list-connections.c |
134 | gnunet_transport_list_connections_LDADD = \ | 118 | gnunet_transport_list_connections_LDADD = \ |
135 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 119 | $(top_builddir)/src/transport/libgnunettransport.la \ |
136 | $(top_builddir)/src/util/libgnunetutil.la \ | 120 | $(top_builddir)/src/util/libgnunetutil.la \ |
137 | $(GN_LIBINTL) | 121 | $(GN_LIBINTL) |
138 | gnunet_transport_list_connections_DEPENDENCIES = \ | 122 | gnunet_transport_list_connections_DEPENDENCIES = \ |
139 | libgnunettransportnew.la | 123 | libgnunettransport.la |
140 | 124 | ||
141 | gnunet_transport_SOURCES = \ | 125 | gnunet_transport_SOURCES = \ |
142 | gnunet-transport.c | 126 | gnunet-transport.c |
143 | gnunet_transport_LDADD = \ | 127 | gnunet_transport_LDADD = \ |
144 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 128 | $(top_builddir)/src/transport/libgnunettransport.la \ |
145 | $(top_builddir)/src/util/libgnunetutil.la \ | 129 | $(top_builddir)/src/util/libgnunetutil.la \ |
146 | $(GN_LIBINTL) | 130 | $(GN_LIBINTL) |
147 | gnunet_transport_DEPENDENCIES = \ | 131 | gnunet_transport_DEPENDENCIES = \ |
148 | libgnunettransportnew.la | 132 | libgnunettransport.la |
149 | 133 | ||
150 | gnunet_service_transport_SOURCES = \ | 134 | gnunet_service_transport_SOURCES = \ |
151 | gnunet-service-transport.c $(TRANSPORT_ATS_SRC) | 135 | gnunet-service-transport.c $(TRANSPORT_ATS_SRC) |
@@ -318,7 +302,7 @@ endif | |||
318 | test_transport_ats_SOURCES = \ | 302 | test_transport_ats_SOURCES = \ |
319 | test_transport_ats.c $(TRANSPORT_ATS_SRC) | 303 | test_transport_ats.c $(TRANSPORT_ATS_SRC) |
320 | test_transport_ats_LDADD = -lm \ | 304 | test_transport_ats_LDADD = -lm \ |
321 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 305 | $(top_builddir)/src/transport/libgnunettransport.la \ |
322 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 306 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
323 | $(top_builddir)/src/testing/libgnunettesting.la \ | 307 | $(top_builddir)/src/testing/libgnunettesting.la \ |
324 | $(top_builddir)/src/util/libgnunetutil.la \ | 308 | $(top_builddir)/src/util/libgnunetutil.la \ |
@@ -327,7 +311,7 @@ test_transport_ats_LDADD = -lm \ | |||
327 | test_transport_ats_multiple_peers_SOURCES = \ | 311 | test_transport_ats_multiple_peers_SOURCES = \ |
328 | test_transport_ats_multiple_peers.c $(TRANSPORT_ATS_SRC) | 312 | test_transport_ats_multiple_peers.c $(TRANSPORT_ATS_SRC) |
329 | test_transport_ats_multiple_peers_LDADD = -lm \ | 313 | test_transport_ats_multiple_peers_LDADD = -lm \ |
330 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 314 | $(top_builddir)/src/transport/libgnunettransport.la \ |
331 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 315 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
332 | $(top_builddir)/src/testing/libgnunettesting.la \ | 316 | $(top_builddir)/src/testing/libgnunettesting.la \ |
333 | $(top_builddir)/src/util/libgnunetutil.la | 317 | $(top_builddir)/src/util/libgnunetutil.la |
@@ -341,70 +325,70 @@ perf_transport_ats_LDADD = \ | |||
341 | test_transport_api_tcp_SOURCES = \ | 325 | test_transport_api_tcp_SOURCES = \ |
342 | test_transport_api.c | 326 | test_transport_api.c |
343 | test_transport_api_tcp_LDADD = \ | 327 | test_transport_api_tcp_LDADD = \ |
344 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 328 | $(top_builddir)/src/transport/libgnunettransport.la \ |
345 | $(top_builddir)/src/hello/libgnunethello.la \ | 329 | $(top_builddir)/src/hello/libgnunethello.la \ |
346 | $(top_builddir)/src/util/libgnunetutil.la | 330 | $(top_builddir)/src/util/libgnunetutil.la |
347 | 331 | ||
348 | test_transport_api_tcp_nat_SOURCES = \ | 332 | test_transport_api_tcp_nat_SOURCES = \ |
349 | test_transport_api.c | 333 | test_transport_api.c |
350 | test_transport_api_tcp_nat_LDADD = \ | 334 | test_transport_api_tcp_nat_LDADD = \ |
351 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 335 | $(top_builddir)/src/transport/libgnunettransport.la \ |
352 | $(top_builddir)/src/hello/libgnunethello.la \ | 336 | $(top_builddir)/src/hello/libgnunethello.la \ |
353 | $(top_builddir)/src/util/libgnunetutil.la | 337 | $(top_builddir)/src/util/libgnunetutil.la |
354 | 338 | ||
355 | test_transport_api_reliability_tcp_SOURCES = \ | 339 | test_transport_api_reliability_tcp_SOURCES = \ |
356 | test_transport_api_reliability.c | 340 | test_transport_api_reliability.c |
357 | test_transport_api_reliability_tcp_LDADD = \ | 341 | test_transport_api_reliability_tcp_LDADD = \ |
358 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 342 | $(top_builddir)/src/transport/libgnunettransport.la \ |
359 | $(top_builddir)/src/hello/libgnunethello.la \ | 343 | $(top_builddir)/src/hello/libgnunethello.la \ |
360 | $(top_builddir)/src/util/libgnunetutil.la | 344 | $(top_builddir)/src/util/libgnunetutil.la |
361 | 345 | ||
362 | test_transport_api_multiaddress_tcp_SOURCES = \ | 346 | test_transport_api_multiaddress_tcp_SOURCES = \ |
363 | test_transport_api_multiaddress.c | 347 | test_transport_api_multiaddress.c |
364 | test_transport_api_multiaddress_tcp_LDADD = \ | 348 | test_transport_api_multiaddress_tcp_LDADD = \ |
365 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 349 | $(top_builddir)/src/transport/libgnunettransport.la \ |
366 | $(top_builddir)/src/hello/libgnunethello.la \ | 350 | $(top_builddir)/src/hello/libgnunethello.la \ |
367 | $(top_builddir)/src/util/libgnunetutil.la | 351 | $(top_builddir)/src/util/libgnunetutil.la |
368 | 352 | ||
369 | test_transport_api_reliability_tcp_nat_SOURCES = \ | 353 | test_transport_api_reliability_tcp_nat_SOURCES = \ |
370 | test_transport_api_reliability.c | 354 | test_transport_api_reliability.c |
371 | test_transport_api_reliability_tcp_nat_LDADD = \ | 355 | test_transport_api_reliability_tcp_nat_LDADD = \ |
372 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 356 | $(top_builddir)/src/transport/libgnunettransport.la \ |
373 | $(top_builddir)/src/hello/libgnunethello.la \ | 357 | $(top_builddir)/src/hello/libgnunethello.la \ |
374 | $(top_builddir)/src/util/libgnunetutil.la | 358 | $(top_builddir)/src/util/libgnunetutil.la |
375 | 359 | ||
376 | test_transport_api_reliability_wlan_SOURCES = \ | 360 | test_transport_api_reliability_wlan_SOURCES = \ |
377 | test_transport_api_reliability.c | 361 | test_transport_api_reliability.c |
378 | test_transport_api_reliability_wlan_LDADD = \ | 362 | test_transport_api_reliability_wlan_LDADD = \ |
379 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 363 | $(top_builddir)/src/transport/libgnunettransport.la \ |
380 | $(top_builddir)/src/hello/libgnunethello.la \ | 364 | $(top_builddir)/src/hello/libgnunethello.la \ |
381 | $(top_builddir)/src/util/libgnunetutil.la | 365 | $(top_builddir)/src/util/libgnunetutil.la |
382 | 366 | ||
383 | test_transport_api_unreliability_wlan_SOURCES = \ | 367 | test_transport_api_unreliability_wlan_SOURCES = \ |
384 | test_transport_api_unreliability.c | 368 | test_transport_api_unreliability.c |
385 | test_transport_api_unreliability_wlan_LDADD = \ | 369 | test_transport_api_unreliability_wlan_LDADD = \ |
386 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 370 | $(top_builddir)/src/transport/libgnunettransport.la \ |
387 | $(top_builddir)/src/hello/libgnunethello.la \ | 371 | $(top_builddir)/src/hello/libgnunethello.la \ |
388 | $(top_builddir)/src/util/libgnunetutil.la | 372 | $(top_builddir)/src/util/libgnunetutil.la |
389 | 373 | ||
390 | test_transport_api_udp_SOURCES = \ | 374 | test_transport_api_udp_SOURCES = \ |
391 | test_transport_api.c | 375 | test_transport_api.c |
392 | test_transport_api_udp_LDADD = \ | 376 | test_transport_api_udp_LDADD = \ |
393 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 377 | $(top_builddir)/src/transport/libgnunettransport.la \ |
394 | $(top_builddir)/src/hello/libgnunethello.la \ | 378 | $(top_builddir)/src/hello/libgnunethello.la \ |
395 | $(top_builddir)/src/util/libgnunetutil.la | 379 | $(top_builddir)/src/util/libgnunetutil.la |
396 | 380 | ||
397 | test_transport_api_udp_nat_SOURCES = \ | 381 | test_transport_api_udp_nat_SOURCES = \ |
398 | test_transport_api.c | 382 | test_transport_api.c |
399 | test_transport_api_udp_nat_LDADD = \ | 383 | test_transport_api_udp_nat_LDADD = \ |
400 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 384 | $(top_builddir)/src/transport/libgnunettransport.la \ |
401 | $(top_builddir)/src/hello/libgnunethello.la \ | 385 | $(top_builddir)/src/hello/libgnunethello.la \ |
402 | $(top_builddir)/src/util/libgnunetutil.la | 386 | $(top_builddir)/src/util/libgnunetutil.la |
403 | 387 | ||
404 | test_transport_api_unix_SOURCES = \ | 388 | test_transport_api_unix_SOURCES = \ |
405 | test_transport_api.c | 389 | test_transport_api.c |
406 | test_transport_api_unix_LDADD = \ | 390 | test_transport_api_unix_LDADD = \ |
407 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 391 | $(top_builddir)/src/transport/libgnunettransport.la \ |
408 | $(top_builddir)/src/hello/libgnunethello.la \ | 392 | $(top_builddir)/src/hello/libgnunethello.la \ |
409 | $(top_builddir)/src/util/libgnunetutil.la | 393 | $(top_builddir)/src/util/libgnunetutil.la |
410 | 394 | ||
@@ -419,14 +403,14 @@ test_transport_api_unix_LDADD = \ | |||
419 | test_transport_api_http_SOURCES = \ | 403 | test_transport_api_http_SOURCES = \ |
420 | test_transport_api.c | 404 | test_transport_api.c |
421 | test_transport_api_http_LDADD = \ | 405 | test_transport_api_http_LDADD = \ |
422 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 406 | $(top_builddir)/src/transport/libgnunettransport.la \ |
423 | $(top_builddir)/src/hello/libgnunethello.la \ | 407 | $(top_builddir)/src/hello/libgnunethello.la \ |
424 | $(top_builddir)/src/util/libgnunetutil.la | 408 | $(top_builddir)/src/util/libgnunetutil.la |
425 | 409 | ||
426 | test_transport_api_reliability_http_SOURCES = \ | 410 | test_transport_api_reliability_http_SOURCES = \ |
427 | test_transport_api_reliability.c | 411 | test_transport_api_reliability.c |
428 | test_transport_api_reliability_http_LDADD = \ | 412 | test_transport_api_reliability_http_LDADD = \ |
429 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 413 | $(top_builddir)/src/transport/libgnunettransport.la \ |
430 | $(top_builddir)/src/hello/libgnunethello.la \ | 414 | $(top_builddir)/src/hello/libgnunethello.la \ |
431 | $(top_builddir)/src/util/libgnunetutil.la | 415 | $(top_builddir)/src/util/libgnunetutil.la |
432 | 416 | ||
@@ -441,28 +425,28 @@ test_transport_api_reliability_http_LDADD = \ | |||
441 | test_transport_api_https_SOURCES = \ | 425 | test_transport_api_https_SOURCES = \ |
442 | test_transport_api.c | 426 | test_transport_api.c |
443 | test_transport_api_https_LDADD = \ | 427 | test_transport_api_https_LDADD = \ |
444 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 428 | $(top_builddir)/src/transport/libgnunettransport.la \ |
445 | $(top_builddir)/src/hello/libgnunethello.la \ | 429 | $(top_builddir)/src/hello/libgnunethello.la \ |
446 | $(top_builddir)/src/util/libgnunetutil.la | 430 | $(top_builddir)/src/util/libgnunetutil.la |
447 | 431 | ||
448 | test_transport_api_reliability_https_SOURCES = \ | 432 | test_transport_api_reliability_https_SOURCES = \ |
449 | test_transport_api_reliability.c | 433 | test_transport_api_reliability.c |
450 | test_transport_api_reliability_https_LDADD = \ | 434 | test_transport_api_reliability_https_LDADD = \ |
451 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 435 | $(top_builddir)/src/transport/libgnunettransport.la \ |
452 | $(top_builddir)/src/hello/libgnunethello.la \ | 436 | $(top_builddir)/src/hello/libgnunethello.la \ |
453 | $(top_builddir)/src/util/libgnunetutil.la | 437 | $(top_builddir)/src/util/libgnunetutil.la |
454 | 438 | ||
455 | test_transport_api_unreliability_unix_SOURCES = \ | 439 | test_transport_api_unreliability_unix_SOURCES = \ |
456 | test_transport_api_unreliability.c | 440 | test_transport_api_unreliability.c |
457 | test_transport_api_unreliability_unix_LDADD = \ | 441 | test_transport_api_unreliability_unix_LDADD = \ |
458 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 442 | $(top_builddir)/src/transport/libgnunettransport.la \ |
459 | $(top_builddir)/src/hello/libgnunethello.la \ | 443 | $(top_builddir)/src/hello/libgnunethello.la \ |
460 | $(top_builddir)/src/util/libgnunetutil.la | 444 | $(top_builddir)/src/util/libgnunetutil.la |
461 | 445 | ||
462 | test_transport_api_unreliability_udp_SOURCES = \ | 446 | test_transport_api_unreliability_udp_SOURCES = \ |
463 | test_transport_api_unreliability.c | 447 | test_transport_api_unreliability.c |
464 | test_transport_api_unreliability_udp_LDADD = \ | 448 | test_transport_api_unreliability_udp_LDADD = \ |
465 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 449 | $(top_builddir)/src/transport/libgnunettransport.la \ |
466 | $(top_builddir)/src/hello/libgnunethello.la \ | 450 | $(top_builddir)/src/hello/libgnunethello.la \ |
467 | $(top_builddir)/src/util/libgnunetutil.la | 451 | $(top_builddir)/src/util/libgnunetutil.la |
468 | 452 | ||
@@ -470,7 +454,7 @@ if LINUX | |||
470 | test_transport_api_wlan_SOURCES = \ | 454 | test_transport_api_wlan_SOURCES = \ |
471 | test_transport_api.c | 455 | test_transport_api.c |
472 | test_transport_api_wlan_LDADD = \ | 456 | test_transport_api_wlan_LDADD = \ |
473 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 457 | $(top_builddir)/src/transport/libgnunettransport.la \ |
474 | $(top_builddir)/src/hello/libgnunethello.la \ | 458 | $(top_builddir)/src/hello/libgnunethello.la \ |
475 | $(top_builddir)/src/util/libgnunetutil.la | 459 | $(top_builddir)/src/util/libgnunetutil.la |
476 | endif | 460 | endif |
@@ -478,94 +462,94 @@ endif | |||
478 | test_quota_compliance_tcp_SOURCES = \ | 462 | test_quota_compliance_tcp_SOURCES = \ |
479 | test_quota_compliance.c | 463 | test_quota_compliance.c |
480 | test_quota_compliance_tcp_LDADD = \ | 464 | test_quota_compliance_tcp_LDADD = \ |
481 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 465 | $(top_builddir)/src/transport/libgnunettransport.la \ |
482 | $(top_builddir)/src/hello/libgnunethello.la \ | 466 | $(top_builddir)/src/hello/libgnunethello.la \ |
483 | $(top_builddir)/src/util/libgnunetutil.la | 467 | $(top_builddir)/src/util/libgnunetutil.la |
484 | 468 | ||
485 | test_quota_compliance_tcp_asymmetric_recv_constant_SOURCES = \ | 469 | test_quota_compliance_tcp_asymmetric_recv_constant_SOURCES = \ |
486 | test_quota_compliance.c | 470 | test_quota_compliance.c |
487 | test_quota_compliance_tcp_asymmetric_recv_constant_LDADD = \ | 471 | test_quota_compliance_tcp_asymmetric_recv_constant_LDADD = \ |
488 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 472 | $(top_builddir)/src/transport/libgnunettransport.la \ |
489 | $(top_builddir)/src/hello/libgnunethello.la \ | 473 | $(top_builddir)/src/hello/libgnunethello.la \ |
490 | $(top_builddir)/src/util/libgnunetutil.la | 474 | $(top_builddir)/src/util/libgnunetutil.la |
491 | 475 | ||
492 | #test_quota_compliance_tcp_asymmetric_send_constant_SOURCES = \ | 476 | #test_quota_compliance_tcp_asymmetric_send_constant_SOURCES = \ |
493 | # test_quota_compliance.c | 477 | # test_quota_compliance.c |
494 | #test_quota_compliance_tcp_asymmetric_send_constant_LDADD = \ | 478 | #test_quota_compliance_tcp_asymmetric_send_constant_LDADD = \ |
495 | # $(top_builddir)/src/transport/libgnunettransportnew.la \ | 479 | # $(top_builddir)/src/transport/libgnunettransport.la \ |
496 | # $(top_builddir)/src/util/libgnunetutil.la | 480 | # $(top_builddir)/src/util/libgnunetutil.la |
497 | 481 | ||
498 | test_quota_compliance_http_SOURCES = \ | 482 | test_quota_compliance_http_SOURCES = \ |
499 | test_quota_compliance.c | 483 | test_quota_compliance.c |
500 | test_quota_compliance_http_LDADD = \ | 484 | test_quota_compliance_http_LDADD = \ |
501 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 485 | $(top_builddir)/src/transport/libgnunettransport.la \ |
502 | $(top_builddir)/src/hello/libgnunethello.la \ | 486 | $(top_builddir)/src/hello/libgnunethello.la \ |
503 | $(top_builddir)/src/util/libgnunetutil.la | 487 | $(top_builddir)/src/util/libgnunetutil.la |
504 | 488 | ||
505 | test_quota_compliance_http_asymmetric_recv_constant_SOURCES = \ | 489 | test_quota_compliance_http_asymmetric_recv_constant_SOURCES = \ |
506 | test_quota_compliance.c | 490 | test_quota_compliance.c |
507 | test_quota_compliance_http_asymmetric_recv_constant_LDADD = \ | 491 | test_quota_compliance_http_asymmetric_recv_constant_LDADD = \ |
508 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 492 | $(top_builddir)/src/transport/libgnunettransport.la \ |
509 | $(top_builddir)/src/hello/libgnunethello.la \ | 493 | $(top_builddir)/src/hello/libgnunethello.la \ |
510 | $(top_builddir)/src/util/libgnunetutil.la | 494 | $(top_builddir)/src/util/libgnunetutil.la |
511 | 495 | ||
512 | #test_quota_compliance_http_asymmetric_send_constant_SOURCES = \ | 496 | #test_quota_compliance_http_asymmetric_send_constant_SOURCES = \ |
513 | # test_quota_compliance.c | 497 | # test_quota_compliance.c |
514 | #test_quota_compliance_http_asymmetric_send_constant_LDADD = \ | 498 | #test_quota_compliance_http_asymmetric_send_constant_LDADD = \ |
515 | # $(top_builddir)/src/transport/libgnunettransportnew.la \ | 499 | # $(top_builddir)/src/transport/libgnunettransport.la \ |
516 | # $(top_builddir)/src/util/libgnunetutil.la | 500 | # $(top_builddir)/src/util/libgnunetutil.la |
517 | 501 | ||
518 | test_quota_compliance_https_SOURCES = \ | 502 | test_quota_compliance_https_SOURCES = \ |
519 | test_quota_compliance.c | 503 | test_quota_compliance.c |
520 | test_quota_compliance_https_LDADD = \ | 504 | test_quota_compliance_https_LDADD = \ |
521 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 505 | $(top_builddir)/src/transport/libgnunettransport.la \ |
522 | $(top_builddir)/src/hello/libgnunethello.la \ | 506 | $(top_builddir)/src/hello/libgnunethello.la \ |
523 | $(top_builddir)/src/util/libgnunetutil.la | 507 | $(top_builddir)/src/util/libgnunetutil.la |
524 | 508 | ||
525 | test_quota_compliance_https_asymmetric_recv_constant_SOURCES = \ | 509 | test_quota_compliance_https_asymmetric_recv_constant_SOURCES = \ |
526 | test_quota_compliance.c | 510 | test_quota_compliance.c |
527 | test_quota_compliance_https_asymmetric_recv_constant_LDADD = \ | 511 | test_quota_compliance_https_asymmetric_recv_constant_LDADD = \ |
528 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 512 | $(top_builddir)/src/transport/libgnunettransport.la \ |
529 | $(top_builddir)/src/hello/libgnunethello.la \ | 513 | $(top_builddir)/src/hello/libgnunethello.la \ |
530 | $(top_builddir)/src/util/libgnunetutil.la | 514 | $(top_builddir)/src/util/libgnunetutil.la |
531 | 515 | ||
532 | #test_quota_compliance_https_asymmetric_send_constant_SOURCES = \ | 516 | #test_quota_compliance_https_asymmetric_send_constant_SOURCES = \ |
533 | # test_quota_compliance.c | 517 | # test_quota_compliance.c |
534 | #test_quota_compliance_https_asymmetric_send_constant_LDADD = \ | 518 | #test_quota_compliance_https_asymmetric_send_constant_LDADD = \ |
535 | # $(top_builddir)/src/transport/libgnunettransportnew.la \ | 519 | # $(top_builddir)/src/transport/libgnunettransport.la \ |
536 | # $(top_builddir)/src/util/libgnunetutil.la | 520 | # $(top_builddir)/src/util/libgnunetutil.la |
537 | 521 | ||
538 | test_quota_compliance_udp_SOURCES = \ | 522 | test_quota_compliance_udp_SOURCES = \ |
539 | test_quota_compliance.c | 523 | test_quota_compliance.c |
540 | test_quota_compliance_udp_LDADD = \ | 524 | test_quota_compliance_udp_LDADD = \ |
541 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 525 | $(top_builddir)/src/transport/libgnunettransport.la \ |
542 | $(top_builddir)/src/hello/libgnunethello.la \ | 526 | $(top_builddir)/src/hello/libgnunethello.la \ |
543 | $(top_builddir)/src/util/libgnunetutil.la | 527 | $(top_builddir)/src/util/libgnunetutil.la |
544 | 528 | ||
545 | test_quota_compliance_udp_asymmetric_recv_constant_SOURCES = \ | 529 | test_quota_compliance_udp_asymmetric_recv_constant_SOURCES = \ |
546 | test_quota_compliance.c | 530 | test_quota_compliance.c |
547 | test_quota_compliance_udp_asymmetric_recv_constant_LDADD = \ | 531 | test_quota_compliance_udp_asymmetric_recv_constant_LDADD = \ |
548 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 532 | $(top_builddir)/src/transport/libgnunettransport.la \ |
549 | $(top_builddir)/src/hello/libgnunethello.la \ | 533 | $(top_builddir)/src/hello/libgnunethello.la \ |
550 | $(top_builddir)/src/util/libgnunetutil.la | 534 | $(top_builddir)/src/util/libgnunetutil.la |
551 | 535 | ||
552 | #test_quota_compliance_udp_asymmetric_send_constant_SOURCES = \ | 536 | #test_quota_compliance_udp_asymmetric_send_constant_SOURCES = \ |
553 | # test_quota_compliance.c | 537 | # test_quota_compliance.c |
554 | #test_quota_compliance_udp_asymmetric_send_constant_LDADD = \ | 538 | #test_quota_compliance_udp_asymmetric_send_constant_LDADD = \ |
555 | # $(top_builddir)/src/transport/libgnunettransportnew.la \ | 539 | # $(top_builddir)/src/transport/libgnunettransport.la \ |
556 | # $(top_builddir)/src/util/libgnunetutil.la | 540 | # $(top_builddir)/src/util/libgnunetutil.la |
557 | 541 | ||
558 | test_quota_compliance_unix_SOURCES = \ | 542 | test_quota_compliance_unix_SOURCES = \ |
559 | test_quota_compliance.c | 543 | test_quota_compliance.c |
560 | test_quota_compliance_unix_LDADD = \ | 544 | test_quota_compliance_unix_LDADD = \ |
561 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 545 | $(top_builddir)/src/transport/libgnunettransport.la \ |
562 | $(top_builddir)/src/hello/libgnunethello.la \ | 546 | $(top_builddir)/src/hello/libgnunethello.la \ |
563 | $(top_builddir)/src/util/libgnunetutil.la | 547 | $(top_builddir)/src/util/libgnunetutil.la |
564 | 548 | ||
565 | test_quota_compliance_unix_asymmetric_recv_constant_SOURCES = \ | 549 | test_quota_compliance_unix_asymmetric_recv_constant_SOURCES = \ |
566 | test_quota_compliance.c | 550 | test_quota_compliance.c |
567 | test_quota_compliance_unix_asymmetric_recv_constant_LDADD = \ | 551 | test_quota_compliance_unix_asymmetric_recv_constant_LDADD = \ |
568 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 552 | $(top_builddir)/src/transport/libgnunettransport.la \ |
569 | $(top_builddir)/src/hello/libgnunethello.la \ | 553 | $(top_builddir)/src/hello/libgnunethello.la \ |
570 | $(top_builddir)/src/util/libgnunetutil.la | 554 | $(top_builddir)/src/util/libgnunetutil.la |
571 | 555 | ||
@@ -573,7 +557,7 @@ test_quota_compliance_unix_asymmetric_recv_constant_LDADD = \ | |||
573 | test_transport_api_multi_SOURCES = \ | 557 | test_transport_api_multi_SOURCES = \ |
574 | test_transport_api.c | 558 | test_transport_api.c |
575 | test_transport_api_multi_LDADD = \ | 559 | test_transport_api_multi_LDADD = \ |
576 | $(top_builddir)/src/transport/libgnunettransportnew.la \ | 560 | $(top_builddir)/src/transport/libgnunettransport.la \ |
577 | $(top_builddir)/src/hello/libgnunethello.la \ | 561 | $(top_builddir)/src/hello/libgnunethello.la \ |
578 | $(top_builddir)/src/util/libgnunetutil.la | 562 | $(top_builddir)/src/util/libgnunetutil.la |
579 | EXTRA_DIST = \ | 563 | EXTRA_DIST = \ |
diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c index 7b5798ce0..4583cf876 100644 --- a/src/transport/transport_api.c +++ b/src/transport/transport_api.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2009, 2010 Christian Grothoff (and other contributing authors) | 3 | (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -22,6 +22,11 @@ | |||
22 | * @file transport/transport_api.c | 22 | * @file transport/transport_api.c |
23 | * @brief library to access the low-level P2P IO service | 23 | * @brief library to access the low-level P2P IO service |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * | ||
26 | * TODO: | ||
27 | * - adjust testcases to use new 'try connect' style (should be easy, breaks API compatibility!) | ||
28 | * - adjust core service to use new 'try connect' style (should be MUCH nicer there as well!) | ||
29 | * - test test test | ||
25 | */ | 30 | */ |
26 | #include "platform.h" | 31 | #include "platform.h" |
27 | #include "gnunet_bandwidth_lib.h" | 32 | #include "gnunet_bandwidth_lib.h" |
@@ -37,133 +42,32 @@ | |||
37 | #include "transport.h" | 42 | #include "transport.h" |
38 | 43 | ||
39 | /** | 44 | /** |
40 | * After how long do we give up on transmitting a HELLO | ||
41 | * to the service? | ||
42 | */ | ||
43 | #define OFFER_HELLO_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
44 | |||
45 | /** | ||
46 | * After how long do we automatically retry an unsuccessful | ||
47 | * CONNECT request? | ||
48 | */ | ||
49 | #define CONNECT_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 750) | ||
50 | |||
51 | /** | ||
52 | * How long should ARM wait when starting up the | ||
53 | * transport service before reporting back? | ||
54 | */ | ||
55 | #define START_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
56 | |||
57 | /** | ||
58 | * How long should ARM wait when stopping the | ||
59 | * transport service before reporting back? | ||
60 | */ | ||
61 | #define STOP_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
62 | |||
63 | /** | ||
64 | * How large to start with for the hashmap of neighbours. | 45 | * How large to start with for the hashmap of neighbours. |
65 | */ | 46 | */ |
66 | #define STARTING_NEIGHBOURS_SIZE 10 | 47 | #define STARTING_NEIGHBOURS_SIZE 16 |
67 | 48 | ||
68 | 49 | ||
69 | /** | 50 | /** |
70 | * What stage are we in for transmission processing? | 51 | * Handle for a message that should be transmitted to the service. |
71 | */ | 52 | * Used for both control messages and normal messages. |
72 | enum TransmitStage | ||
73 | { | ||
74 | /** | ||
75 | * No active message. | ||
76 | */ | ||
77 | TS_NEW = 0, | ||
78 | |||
79 | /** | ||
80 | * Message in local queue, not given to service. | ||
81 | */ | ||
82 | TS_QUEUED = 1, | ||
83 | |||
84 | /** | ||
85 | * Message given to service, not confirmed (no SEND_OK). | ||
86 | */ | ||
87 | TS_TRANSMITTED = 2, | ||
88 | |||
89 | /** | ||
90 | * One message was given to service and before it was confirmed, | ||
91 | * another one was already queued (waiting for SEND_OK to pass on | ||
92 | * to service). | ||
93 | */ | ||
94 | TS_TRANSMITTED_QUEUED = 3 | ||
95 | }; | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Handle for a transmission-ready request. | ||
100 | */ | 53 | */ |
101 | struct GNUNET_TRANSPORT_TransmitHandle | 54 | struct GNUNET_TRANSPORT_TransmitHandle |
102 | { | 55 | { |
103 | 56 | ||
104 | /** | 57 | /** |
105 | * Neighbour for this handle, NULL for control-traffic. | 58 | * We keep all requests in a DLL. |
106 | */ | ||
107 | struct NeighbourList *neighbour; | ||
108 | |||
109 | /** | ||
110 | * Function to call when notify_size bytes are available | ||
111 | * for transmission. | ||
112 | */ | ||
113 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
114 | |||
115 | /** | ||
116 | * Closure for notify. | ||
117 | */ | ||
118 | void *notify_cls; | ||
119 | |||
120 | /** | ||
121 | * transmit_ready task Id. The task is used to introduce the | ||
122 | * artificial delay that may be required to maintain the bandwidth | ||
123 | * limits. Later, this will be the ID of the "transmit_timeout" | ||
124 | * task which is used to signal a timeout if the transmission could | ||
125 | * not be done in a timely fashion. | ||
126 | */ | ||
127 | GNUNET_SCHEDULER_TaskIdentifier notify_delay_task; | ||
128 | |||
129 | /** | ||
130 | * Timeout for this request. | ||
131 | */ | ||
132 | struct GNUNET_TIME_Absolute timeout; | ||
133 | |||
134 | /** | ||
135 | * How many bytes is our notify callback waiting for? | ||
136 | */ | ||
137 | size_t notify_size; | ||
138 | |||
139 | /** | ||
140 | * How important is this message? | ||
141 | */ | ||
142 | uint32_t priority; | ||
143 | |||
144 | }; | ||
145 | |||
146 | |||
147 | /** | ||
148 | * Handle for a control message queue entry. | ||
149 | */ | ||
150 | struct ControlMessage | ||
151 | { | ||
152 | |||
153 | /** | ||
154 | * This is a doubly-linked list. | ||
155 | */ | 59 | */ |
156 | struct ControlMessage *next; | 60 | struct GNUNET_TRANSPORT_TransmitHandle *next; |
157 | 61 | ||
158 | /** | 62 | /** |
159 | * This is a doubly-linked list. | 63 | * We keep all requests in a DLL. |
160 | */ | 64 | */ |
161 | struct ControlMessage *prev; | 65 | struct GNUNET_TRANSPORT_TransmitHandle *prev; |
162 | 66 | ||
163 | /** | 67 | /** |
164 | * Overall transport handle. | 68 | * Neighbour for this handle, NULL for control messages. |
165 | */ | 69 | */ |
166 | struct GNUNET_TRANSPORT_Handle *h; | 70 | struct Neighbour *neighbour; |
167 | 71 | ||
168 | /** | 72 | /** |
169 | * Function to call when notify_size bytes are available | 73 | * Function to call when notify_size bytes are available |
@@ -177,47 +81,33 @@ struct ControlMessage | |||
177 | void *notify_cls; | 81 | void *notify_cls; |
178 | 82 | ||
179 | /** | 83 | /** |
180 | * transmit_ready task Id. The task is used to introduce the | 84 | * Timeout for this request, 0 for control messages. |
181 | * artificial delay that may be required to maintain the bandwidth | ||
182 | * limits. Later, this will be the ID of the "transmit_timeout" | ||
183 | * task which is used to signal a timeout if the transmission could | ||
184 | * not be done in a timely fashion. | ||
185 | */ | 85 | */ |
186 | GNUNET_SCHEDULER_TaskIdentifier notify_delay_task; | 86 | struct GNUNET_TIME_Absolute timeout; |
187 | 87 | ||
188 | /** | 88 | /** |
189 | * How many bytes is our notify callback waiting for? | 89 | * Task to trigger request timeout if the request is stalled due to |
90 | * congestion. | ||
190 | */ | 91 | */ |
191 | size_t notify_size; | 92 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; |
192 | |||
193 | }; | ||
194 | |||
195 | /** | ||
196 | * Context for storing information about attempted next transmission. | ||
197 | */ | ||
198 | struct TryTransmitContext | ||
199 | { | ||
200 | 93 | ||
201 | /** | 94 | /** |
202 | * Main transport handle. | 95 | * How many bytes is our notify callback waiting for? |
203 | */ | 96 | */ |
204 | struct GNUNET_TRANSPORT_Handle *h; | 97 | size_t notify_size; |
205 | 98 | ||
206 | /** | 99 | /** |
207 | * Returned transmission handle. | 100 | * How important is this message? Not used for control messages. |
208 | */ | 101 | */ |
209 | struct GNUNET_TRANSPORT_TransmitHandle *ret; | 102 | uint32_t priority; |
210 | 103 | ||
211 | /** | ||
212 | * Time to retry the send task. | ||
213 | */ | ||
214 | struct GNUNET_TIME_Relative retry_time; | ||
215 | }; | 104 | }; |
216 | 105 | ||
106 | |||
217 | /** | 107 | /** |
218 | * Entry in hash table of all of our current neighbours. | 108 | * Entry in hash table of all of our current neighbours. |
219 | */ | 109 | */ |
220 | struct NeighbourList | 110 | struct Neighbour |
221 | { | 111 | { |
222 | /** | 112 | /** |
223 | * Overall transport handle. | 113 | * Overall transport handle. |
@@ -225,10 +115,9 @@ struct NeighbourList | |||
225 | struct GNUNET_TRANSPORT_Handle *h; | 115 | struct GNUNET_TRANSPORT_Handle *h; |
226 | 116 | ||
227 | /** | 117 | /** |
228 | * Active transmit handle; available if 'transmit_forbidden' | 118 | * Active transmit handle or NULL. |
229 | * is GNUNET_NO. | ||
230 | */ | 119 | */ |
231 | struct GNUNET_TRANSPORT_TransmitHandle transmit_handle; | 120 | struct GNUNET_TRANSPORT_TransmitHandle *th; |
232 | 121 | ||
233 | /** | 122 | /** |
234 | * Identity of this neighbour. | 123 | * Identity of this neighbour. |
@@ -241,44 +130,38 @@ struct NeighbourList | |||
241 | struct GNUNET_BANDWIDTH_Tracker out_tracker; | 130 | struct GNUNET_BANDWIDTH_Tracker out_tracker; |
242 | 131 | ||
243 | /** | 132 | /** |
244 | * Set to GNUNET_NO if we are currently allowed to accept a | 133 | * Entry in our readyness heap (which is sorted by 'next_ready' |
245 | * message to the transport service for this peer, GNUNET_YES | 134 | * value). NULL if there is no pending transmission request for |
246 | * if we have one and are waiting for transmission, GNUNET_SYSERR | 135 | * this neighbour or if we're waiting for 'is_ready' to become |
247 | * if we are waiting for confirmation AND have already accepted | 136 | * true AFTER the 'out_tracker' suggested that this peer's quota |
248 | * yet another message. | 137 | * has been satisfied (so once 'is_ready' goes to GNUNET_YES, |
138 | * we should immediately go back into the heap). | ||
249 | */ | 139 | */ |
250 | enum TransmitStage transmit_stage; | 140 | struct GNUNET_CONTAINER_HeapNode *hn; |
251 | 141 | ||
252 | /** | 142 | /** |
253 | * Have we received a notification that this peer is connected | 143 | * Is this peer currently ready to receive a message? |
254 | * to us right now? | ||
255 | */ | 144 | */ |
256 | int is_connected; | 145 | int is_ready; |
257 | |||
258 | /** | ||
259 | * Are we in the middle of disconnecting the peer already? | ||
260 | */ | ||
261 | unsigned int in_disconnect; | ||
262 | 146 | ||
263 | }; | 147 | }; |
264 | 148 | ||
265 | 149 | ||
266 | /** | 150 | /** |
267 | * Linked list of requests from clients for our HELLO that were | 151 | * Linked list of functions to call whenever our HELLO is updated. |
268 | * deferred. | ||
269 | */ | 152 | */ |
270 | struct HelloWaitList | 153 | struct HelloWaitList |
271 | { | 154 | { |
272 | 155 | ||
273 | /** | 156 | /** |
274 | * This is a linked list. | 157 | * This is a doubly linked list. |
275 | */ | 158 | */ |
276 | struct HelloWaitList *next; | 159 | struct HelloWaitList *next; |
277 | 160 | ||
278 | /** | 161 | /** |
279 | * Reference back to our transport handle. | 162 | * This is a doubly linked list. |
280 | */ | 163 | */ |
281 | struct GNUNET_TRANSPORT_Handle *handle; | 164 | struct HelloWaitList *prev; |
282 | 165 | ||
283 | /** | 166 | /** |
284 | * Callback to call once we got our HELLO. | 167 | * Callback to call once we got our HELLO. |
@@ -323,12 +206,12 @@ struct GNUNET_TRANSPORT_Handle | |||
323 | /** | 206 | /** |
324 | * Head of DLL of control messages. | 207 | * Head of DLL of control messages. |
325 | */ | 208 | */ |
326 | struct ControlMessage *control_head; | 209 | struct GNUNET_TRANSPORT_TransmitHandle *control_head; |
327 | 210 | ||
328 | /** | 211 | /** |
329 | * Tail of DLL of control messages. | 212 | * Tail of DLL of control messages. |
330 | */ | 213 | */ |
331 | struct ControlMessage *control_tail; | 214 | struct GNUNET_TRANSPORT_TransmitHandle *control_tail; |
332 | 215 | ||
333 | /** | 216 | /** |
334 | * The current HELLO message for this peer. Updated | 217 | * The current HELLO message for this peer. Updated |
@@ -344,7 +227,7 @@ struct GNUNET_TRANSPORT_Handle | |||
344 | /** | 227 | /** |
345 | * Handle to our registration with the client for notification. | 228 | * Handle to our registration with the client for notification. |
346 | */ | 229 | */ |
347 | struct GNUNET_CLIENT_TransmitHandle *network_handle; | 230 | struct GNUNET_CLIENT_TransmitHandle *cth; |
348 | 231 | ||
349 | /** | 232 | /** |
350 | * Linked list of pending requests for our HELLO. | 233 | * Linked list of pending requests for our HELLO. |
@@ -352,16 +235,30 @@ struct GNUNET_TRANSPORT_Handle | |||
352 | struct HelloWaitList *hwl_head; | 235 | struct HelloWaitList *hwl_head; |
353 | 236 | ||
354 | /** | 237 | /** |
238 | * Linked list of pending requests for our HELLO. | ||
239 | */ | ||
240 | struct HelloWaitList *hwl_tail; | ||
241 | |||
242 | /** | ||
355 | * My configuration. | 243 | * My configuration. |
356 | */ | 244 | */ |
357 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 245 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
358 | 246 | ||
359 | /** | 247 | /** |
360 | * Linked list of the current neighbours of this peer. | 248 | * Hash map of the current connected neighbours of this peer. |
249 | * Maps peer identities to 'struct Neighbour' entries. | ||
361 | */ | 250 | */ |
362 | struct GNUNET_CONTAINER_MultiHashMap *neighbours; | 251 | struct GNUNET_CONTAINER_MultiHashMap *neighbours; |
363 | 252 | ||
364 | /** | 253 | /** |
254 | * Heap sorting peers with pending messages by the timestamps that | ||
255 | * specify when we could next send a message to the respective peer. | ||
256 | * Excludes control messages (which can always go out immediately). | ||
257 | * Maps time stamps to 'struct Neighbour' entries. | ||
258 | */ | ||
259 | struct GNUNET_CONTAINER_Heap *ready_heap; | ||
260 | |||
261 | /** | ||
365 | * Peer identity as assumed by this process, or all zeros. | 262 | * Peer identity as assumed by this process, or all zeros. |
366 | */ | 263 | */ |
367 | struct GNUNET_PeerIdentity self; | 264 | struct GNUNET_PeerIdentity self; |
@@ -372,8 +269,10 @@ struct GNUNET_TRANSPORT_Handle | |||
372 | GNUNET_SCHEDULER_TaskIdentifier reconnect_task; | 269 | GNUNET_SCHEDULER_TaskIdentifier reconnect_task; |
373 | 270 | ||
374 | /** | 271 | /** |
375 | * ID of the task trying to trigger transmission for a peer | 272 | * ID of the task trying to trigger transmission for a peer while |
376 | * while maintaining bandwidth quotas. | 273 | * maintaining bandwidth quotas. In use if there are no control |
274 | * messages and the smallest entry in the 'ready_heap' has a time | ||
275 | * stamp in the future. | ||
377 | */ | 276 | */ |
378 | GNUNET_SCHEDULER_TaskIdentifier quota_task; | 277 | GNUNET_SCHEDULER_TaskIdentifier quota_task; |
379 | 278 | ||
@@ -383,38 +282,31 @@ struct GNUNET_TRANSPORT_Handle | |||
383 | struct GNUNET_TIME_Relative reconnect_delay; | 282 | struct GNUNET_TIME_Relative reconnect_delay; |
384 | 283 | ||
385 | /** | 284 | /** |
386 | * Set once we are in the process of disconnecting from the | ||
387 | * service. | ||
388 | */ | ||
389 | int in_disconnect; | ||
390 | |||
391 | /** | ||
392 | * Should we check that 'self' matches what the service thinks? | 285 | * Should we check that 'self' matches what the service thinks? |
393 | * (if GNUNET_NO, then 'self' is all zeros!). | 286 | * (if GNUNET_NO, then 'self' is all zeros!). |
394 | */ | 287 | */ |
395 | int check_self; | 288 | int check_self; |
396 | }; | 289 | }; |
397 | 290 | ||
398 | struct HelloContext | ||
399 | { | ||
400 | 291 | ||
401 | /** | 292 | /** |
402 | * Size of the HELLO copied to end of struct. | 293 | * Schedule the task to send one message, either from the control |
403 | */ | 294 | * list or the peer message queues to the service. |
404 | uint16_t size; | 295 | * |
405 | 296 | * @param h transport service to schedule a transmission for | |
406 | /** | 297 | */ |
407 | * Continuation to call once HELLO sent. | 298 | static void |
408 | */ | 299 | schedule_transmission (struct GNUNET_TRANSPORT_Handle *h); |
409 | GNUNET_SCHEDULER_Task cont; | ||
410 | 300 | ||
411 | /** | ||
412 | * Closure to call with the continuation. | ||
413 | */ | ||
414 | void *cont_cls; | ||
415 | 301 | ||
416 | /* HELLO */ | 302 | /** |
417 | }; | 303 | * Function that will schedule the job that will try |
304 | * to connect us again to the client. | ||
305 | * | ||
306 | * @param h transport service to reconnect | ||
307 | */ | ||
308 | static void | ||
309 | disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_Handle *h); | ||
418 | 310 | ||
419 | 311 | ||
420 | /** | 312 | /** |
@@ -424,7 +316,7 @@ struct HelloContext | |||
424 | * @param peer peer to look up | 316 | * @param peer peer to look up |
425 | * @return NULL if no such peer entry exists | 317 | * @return NULL if no such peer entry exists |
426 | */ | 318 | */ |
427 | static struct NeighbourList * | 319 | static struct Neighbour * |
428 | neighbour_find (struct GNUNET_TRANSPORT_Handle *h, | 320 | neighbour_find (struct GNUNET_TRANSPORT_Handle *h, |
429 | const struct GNUNET_PeerIdentity *peer) | 321 | const struct GNUNET_PeerIdentity *peer) |
430 | { | 322 | { |
@@ -433,144 +325,288 @@ neighbour_find (struct GNUNET_TRANSPORT_Handle *h, | |||
433 | 325 | ||
434 | 326 | ||
435 | /** | 327 | /** |
436 | * Schedule the task to send one message, either from the control | 328 | * Add neighbour to our list |
437 | * list or the peer message queues to the service. | ||
438 | */ | ||
439 | static void schedule_transmission (struct GNUNET_TRANSPORT_Handle *h); | ||
440 | |||
441 | |||
442 | /** | ||
443 | * Function called by the scheduler when the timeout for bandwidth | ||
444 | * availablility for the target neighbour is reached. | ||
445 | * | 329 | * |
446 | * @param cls the 'struct GNUNET_TRANSPORT_Handle*' | 330 | * @return NULL if this API is currently disconnecting from the service |
447 | * @param tc scheduler context | ||
448 | */ | 331 | */ |
449 | static void | 332 | static struct Neighbour * |
450 | quota_transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 333 | neighbour_add (struct GNUNET_TRANSPORT_Handle *h, |
334 | const struct GNUNET_PeerIdentity *pid) | ||
451 | { | 335 | { |
452 | struct GNUNET_TRANSPORT_Handle *h = cls; | 336 | struct Neighbour *n; |
453 | 337 | ||
454 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; | 338 | #if DEBUG_TRANSPORT |
455 | schedule_transmission (h); | 339 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
340 | "Creating entry for neighbour `%4s'.\n", | ||
341 | GNUNET_i2s (pid)); | ||
342 | #endif | ||
343 | n = GNUNET_malloc (sizeof (struct Neighbour)); | ||
344 | n->id = *pid; | ||
345 | n->h = h; | ||
346 | n->is_ready = GNUNET_YES; | ||
347 | GNUNET_BANDWIDTH_tracker_init (&n->out_tracker, | ||
348 | GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, | ||
349 | MAX_BANDWIDTH_CARRY_S); | ||
350 | GNUNET_assert (GNUNET_OK == | ||
351 | GNUNET_CONTAINER_multihashmap_put (h->neighbours, | ||
352 | &pid->hashPubKey, | ||
353 | n, | ||
354 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
355 | return n; | ||
456 | } | 356 | } |
457 | 357 | ||
458 | 358 | ||
459 | /** | 359 | /** |
460 | * Iterator over hash map entries, attempt to schedule | 360 | * Iterator over hash map entries, for deleting state of a neighbour. |
461 | * a transmission to entries in the neighbour hashmap. | ||
462 | * | 361 | * |
463 | * @param cls closure a TryTransmitContext | 362 | * @param cls the 'struct GNUNET_TRANSPORT_Handle*' |
464 | * @param key current key code | 363 | * @param key peer identity |
465 | * @param value value in the hash map, the neighbour entry to consider | 364 | * @param value value in the hash map, the neighbour entry to delete |
466 | * @return GNUNET_YES if we should continue to | 365 | * @return GNUNET_YES if we should continue to |
467 | * iterate, | 366 | * iterate, |
468 | * GNUNET_NO if not. | 367 | * GNUNET_NO if not. |
469 | */ | 368 | */ |
470 | static int | 369 | static int |
471 | try_schedule_transmission (void *cls, | 370 | neighbour_delete (void *cls, |
472 | const GNUNET_HashCode * key, | 371 | const GNUNET_HashCode * key, |
473 | void *value) | 372 | void *value) |
474 | { | 373 | { |
475 | struct NeighbourList *n = value; | 374 | struct GNUNET_TRANSPORT_Handle *handle = cls; |
476 | struct TryTransmitContext *try_transmit_ctx = cls; | 375 | struct Neighbour *n = value; |
477 | struct GNUNET_TIME_Relative duration; | 376 | |
478 | GNUNET_CONNECTION_TransmitReadyNotify notify; | 377 | if (NULL != handle->nd_cb) |
479 | struct GNUNET_TRANSPORT_TransmitHandle *th; | 378 | handle->nd_cb (handle->cls, |
480 | struct GNUNET_TIME_Absolute duration_abs; | 379 | &n->id); |
481 | 380 | GNUNET_assert (NULL == n->th); | |
482 | if (n->transmit_stage != TS_QUEUED) | 381 | GNUNET_assert (NULL == n->hn); |
483 | return GNUNET_YES; /* not eligible, keep iterating */ | 382 | GNUNET_assert (GNUNET_YES == |
484 | if (n->is_connected != GNUNET_YES) | 383 | GNUNET_CONTAINER_multihashmap_remove (handle->neighbours, |
485 | return GNUNET_YES; /* keep iterating */ | 384 | key, |
486 | 385 | n)); | |
487 | th = &n->transmit_handle; | 386 | GNUNET_free (n); |
488 | GNUNET_break (n == th->neighbour); | 387 | return GNUNET_YES; |
489 | /* check outgoing quota */ | 388 | } |
490 | duration = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, | 389 | |
491 | th->notify_size - sizeof (struct OutboundMessage)); | 390 | |
492 | duration_abs = GNUNET_TIME_relative_to_absolute (duration); | 391 | /** |
493 | if (th->timeout.abs_value < duration_abs.abs_value) | 392 | * Function we use for handling incoming messages. |
393 | * | ||
394 | * @param cls closure (struct GNUNET_TRANSPORT_Handle *) | ||
395 | * @param msg message received, NULL on timeout or fatal error | ||
396 | */ | ||
397 | static void | ||
398 | demultiplexer (void *cls, | ||
399 | const struct GNUNET_MessageHeader *msg) | ||
400 | { | ||
401 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
402 | const struct DisconnectInfoMessage *dim; | ||
403 | const struct ConnectInfoMessage *cim; | ||
404 | const struct InboundMessage *im; | ||
405 | const struct GNUNET_MessageHeader *imm; | ||
406 | const struct SendOkMessage *okm; | ||
407 | struct HelloWaitList *hwl; | ||
408 | struct HelloWaitList *next_hwl; | ||
409 | struct Neighbour *n; | ||
410 | struct GNUNET_PeerIdentity me; | ||
411 | uint16_t size; | ||
412 | uint32_t ats_count; | ||
413 | |||
414 | GNUNET_assert (h->client != NULL); | ||
415 | if (msg == NULL) | ||
494 | { | 416 | { |
495 | /* signal timeout! */ | 417 | #if DEBUG_TRANSPORT |
418 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
419 | "Error receiving from transport service, disconnecting temporarily.\n"); | ||
420 | #endif | ||
421 | disconnect_and_schedule_reconnect (h); | ||
422 | return; | ||
423 | } | ||
424 | GNUNET_CLIENT_receive (h->client, | ||
425 | &demultiplexer, h, | ||
426 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
427 | size = ntohs (msg->size); | ||
428 | switch (ntohs (msg->type)) | ||
429 | { | ||
430 | case GNUNET_MESSAGE_TYPE_HELLO: | ||
431 | if (GNUNET_OK != | ||
432 | GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) msg, | ||
433 | &me)) | ||
434 | { | ||
435 | GNUNET_break (0); | ||
436 | break; | ||
437 | } | ||
496 | #if DEBUG_TRANSPORT | 438 | #if DEBUG_TRANSPORT |
497 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 439 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
498 | "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n", | 440 | "Receiving (my own) `%s' message, I am `%4s'.\n", |
499 | duration.rel_value, | 441 | "HELLO", GNUNET_i2s (&me)); |
500 | GNUNET_i2s (&n->id)); | ||
501 | #endif | 442 | #endif |
502 | if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | 443 | GNUNET_free_non_null (h->my_hello); |
444 | h->my_hello = NULL; | ||
445 | if (size < sizeof (struct GNUNET_MessageHeader)) | ||
503 | { | 446 | { |
504 | GNUNET_SCHEDULER_cancel (th->notify_delay_task); | 447 | GNUNET_break (0); |
505 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | 448 | break; |
506 | } | 449 | } |
507 | n->transmit_stage = TS_NEW; | 450 | h->my_hello = GNUNET_malloc (size); |
508 | if (NULL != (notify = th->notify)) | 451 | memcpy (h->my_hello, msg, size); |
452 | hwl = h->hwl_head; | ||
453 | while (NULL != hwl) | ||
509 | { | 454 | { |
510 | th->notify = NULL; | 455 | next_hwl = hwl->next; |
511 | GNUNET_assert (0 == notify (th->notify_cls, 0, NULL)); | 456 | hwl->rec (hwl->rec_cls, |
457 | (const struct GNUNET_MessageHeader *) h->my_hello); | ||
458 | hwl = next_hwl; | ||
459 | } | ||
460 | break; | ||
461 | case GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT: | ||
462 | if (size < sizeof (struct ConnectInfoMessage)) | ||
463 | { | ||
464 | GNUNET_break (0); | ||
465 | break; | ||
466 | } | ||
467 | cim = (const struct ConnectInfoMessage *) msg; | ||
468 | ats_count = ntohl (cim->ats_count); | ||
469 | if (size != sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)) | ||
470 | { | ||
471 | GNUNET_break (0); | ||
472 | break; | ||
512 | } | 473 | } |
513 | return GNUNET_YES; /* keep iterating */ | ||
514 | } | ||
515 | if (duration.rel_value > 0) | ||
516 | { | ||
517 | #if DEBUG_TRANSPORT | 474 | #if DEBUG_TRANSPORT |
518 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 475 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
519 | "Need more bandwidth (%u b/s allowed, %u b needed), delaying delivery to `%4s' by %llu ms\n", | 476 | "Receiving `%s' message for `%4s'.\n", |
520 | (unsigned int) n->out_tracker.available_bytes_per_s__, | 477 | "CONNECT", GNUNET_i2s (&cim->id)); |
521 | (unsigned int) th->notify_size - sizeof (struct OutboundMessage), | ||
522 | GNUNET_i2s (&n->id), | ||
523 | (unsigned long long) duration.rel_value); | ||
524 | #endif | 478 | #endif |
525 | try_transmit_ctx->retry_time = GNUNET_TIME_relative_min (try_transmit_ctx->retry_time, | 479 | n = neighbour_find (h, &cim->id); |
526 | duration); | 480 | if (n != NULL) |
527 | return GNUNET_YES; /* keep iterating */ | 481 | { |
528 | } | 482 | GNUNET_break (0); |
483 | break; | ||
484 | } | ||
485 | n = neighbour_add (h, &cim->id); | ||
486 | if (h->nc_cb != NULL) | ||
487 | h->nc_cb (h->cls, &n->id, | ||
488 | &cim->ats, ats_count); | ||
489 | break; | ||
490 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT: | ||
491 | if (size != sizeof (struct DisconnectInfoMessage)) | ||
492 | { | ||
493 | GNUNET_break (0); | ||
494 | break; | ||
495 | } | ||
496 | dim = (const struct DisconnectInfoMessage *) msg; | ||
497 | GNUNET_break (ntohl (dim->reserved) == 0); | ||
498 | #if DEBUG_TRANSPORT_DISCONNECT | ||
499 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
500 | "Receiving `%s' message for `%4s'.\n", | ||
501 | "DISCONNECT", | ||
502 | GNUNET_i2s (&dim->peer)); | ||
503 | #endif | ||
504 | n = neighbour_find (h, &dim->peer); | ||
505 | if (n == NULL) | ||
506 | { | ||
507 | GNUNET_break (0); | ||
508 | break; | ||
509 | } | ||
510 | neighbour_delete (h, &dim->peer.hashPubKey, n); | ||
511 | break; | ||
512 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK: | ||
513 | if (size != sizeof (struct SendOkMessage)) | ||
514 | { | ||
515 | GNUNET_break (0); | ||
516 | break; | ||
517 | } | ||
518 | okm = (const struct SendOkMessage *) msg; | ||
529 | #if DEBUG_TRANSPORT | 519 | #if DEBUG_TRANSPORT |
530 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 520 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
531 | "Have %u bytes of bandwidth available for transmission to `%4s' right now\n", | 521 | "Receiving `%s' message, transmission %s.\n", "SEND_OK", |
532 | th->notify_size - sizeof (struct OutboundMessage), | 522 | ntohl (okm->success) == GNUNET_OK ? "succeeded" : "failed"); |
533 | GNUNET_i2s (&n->id)); | 523 | #endif |
524 | n = neighbour_find (h, &okm->peer); | ||
525 | if (n == NULL) | ||
526 | break; | ||
527 | GNUNET_break (GNUNET_NO == n->is_ready); | ||
528 | n->is_ready = GNUNET_YES; | ||
529 | if ( (n->th != NULL) && | ||
530 | (n->hn == NULL) ) | ||
531 | { | ||
532 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->th->timeout_task); | ||
533 | GNUNET_SCHEDULER_cancel (n->th->timeout_task); | ||
534 | n->th->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
535 | /* we've been waiting for this (congestion, not quota, | ||
536 | caused delayed transmission) */ | ||
537 | n->hn = GNUNET_CONTAINER_heap_insert (h->ready_heap, | ||
538 | n, 0); | ||
539 | schedule_transmission (h); | ||
540 | } | ||
541 | break; | ||
542 | case GNUNET_MESSAGE_TYPE_TRANSPORT_RECV: | ||
543 | #if DEBUG_TRANSPORT | ||
544 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
545 | "Receiving `%s' message.\n", "RECV"); | ||
534 | #endif | 546 | #endif |
547 | if (size < | ||
548 | sizeof (struct InboundMessage) + | ||
549 | sizeof (struct GNUNET_MessageHeader)) | ||
550 | { | ||
551 | GNUNET_break (0); | ||
552 | break; | ||
553 | } | ||
554 | im = (const struct InboundMessage *) msg; | ||
555 | GNUNET_break (0 == ntohl (im->reserved)); | ||
556 | ats_count = ntohl(im->ats_count); | ||
557 | imm = (const struct GNUNET_MessageHeader *) &((&(im->ats))[ats_count+1]); | ||
535 | 558 | ||
536 | if ( (try_transmit_ctx->ret == NULL) || | 559 | if (ntohs (imm->size) + sizeof (struct InboundMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) != size) |
537 | (try_transmit_ctx->ret->priority < th->priority) ) | 560 | { |
538 | try_transmit_ctx->ret = th; | 561 | GNUNET_break (0); |
539 | return GNUNET_YES; | 562 | break; |
563 | } | ||
564 | #if DEBUG_TRANSPORT | ||
565 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
566 | "Received message of type %u from `%4s'.\n", | ||
567 | ntohs (imm->type), GNUNET_i2s (&im->peer)); | ||
568 | #endif | ||
569 | n = neighbour_find (h, &im->peer); | ||
570 | if (n == NULL) | ||
571 | { | ||
572 | GNUNET_break (0); | ||
573 | break; | ||
574 | } | ||
575 | if (h->rec != NULL) | ||
576 | h->rec (h->cls, &im->peer, imm, | ||
577 | &im->ats, ats_count); | ||
578 | break; | ||
579 | default: | ||
580 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
581 | _ | ||
582 | ("Received unexpected message of type %u in %s:%u\n"), | ||
583 | ntohs (msg->type), __FILE__, __LINE__); | ||
584 | GNUNET_break (0); | ||
585 | break; | ||
586 | } | ||
540 | } | 587 | } |
541 | 588 | ||
542 | 589 | ||
543 | /** | 590 | /** |
544 | * Figure out which transmission to a peer can be done right now. | 591 | * A transmission request could not be satisfied because of |
545 | * If none can, schedule a task to call 'schedule_transmission' | 592 | * network congestion. Notify the initiator and clean up. |
546 | * whenever a peer transmission can be done in the future and | ||
547 | * return NULL. Otherwise return the next transmission to be | ||
548 | * performed. | ||
549 | * | 593 | * |
550 | * @param h handle to transport | 594 | * @param cls the 'struct GNUNET_TRANSPORT_TransmitHandle' |
551 | * @return NULL to wait longer before doing any peer transmissions | 595 | * @param tc scheduler context |
552 | */ | 596 | */ |
553 | static struct GNUNET_TRANSPORT_TransmitHandle * | 597 | static void |
554 | schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h) | 598 | timeout_request_due_to_congestion (void *cls, |
599 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
555 | { | 600 | { |
556 | struct TryTransmitContext try_transmit_ctx; | 601 | struct GNUNET_TRANSPORT_TransmitHandle *th = cls; |
602 | struct Neighbour *n = th->neighbour; | ||
557 | 603 | ||
558 | if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) | 604 | n->th->timeout_task = GNUNET_SCHEDULER_NO_TASK; |
559 | { | 605 | GNUNET_assert (th == n->th); |
560 | GNUNET_SCHEDULER_cancel (h->quota_task); | 606 | GNUNET_assert (NULL == n->hn); |
561 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; | 607 | n->th = NULL; |
562 | } | 608 | th->notify (th->notify_cls, 0, NULL); |
563 | try_transmit_ctx.h = h; | 609 | GNUNET_free (th); |
564 | try_transmit_ctx.ret = NULL; | ||
565 | try_transmit_ctx.retry_time = GNUNET_TIME_UNIT_FOREVER_REL; | ||
566 | GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, | ||
567 | &try_schedule_transmission, | ||
568 | &try_transmit_ctx); | ||
569 | if (try_transmit_ctx.ret == NULL) | ||
570 | h->quota_task = GNUNET_SCHEDULER_add_delayed (try_transmit_ctx.retry_time, | ||
571 | "a_transmit_ready, | ||
572 | h); | ||
573 | return try_transmit_ctx.ret; | ||
574 | } | 610 | } |
575 | 611 | ||
576 | 612 | ||
@@ -586,90 +622,73 @@ static size_t | |||
586 | transport_notify_ready (void *cls, size_t size, void *buf) | 622 | transport_notify_ready (void *cls, size_t size, void *buf) |
587 | { | 623 | { |
588 | struct GNUNET_TRANSPORT_Handle *h = cls; | 624 | struct GNUNET_TRANSPORT_Handle *h = cls; |
589 | struct ControlMessage *cm; | ||
590 | struct GNUNET_TRANSPORT_TransmitHandle *th; | 625 | struct GNUNET_TRANSPORT_TransmitHandle *th; |
591 | struct NeighbourList *n; | 626 | struct Neighbour *n; |
627 | char *cbuf; | ||
592 | struct OutboundMessage obm; | 628 | struct OutboundMessage obm; |
593 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
594 | size_t ret; | 629 | size_t ret; |
595 | size_t mret; | ||
596 | size_t nret; | 630 | size_t nret; |
597 | char *cbuf; | 631 | size_t mret; |
598 | 632 | ||
599 | h->network_handle = NULL; | 633 | GNUNET_assert (NULL != h->client); |
600 | if (buf == NULL) | 634 | h->cth = NULL; |
635 | if (NULL == buf) | ||
601 | { | 636 | { |
602 | schedule_transmission (h); | 637 | /* transmission failed */ |
638 | disconnect_and_schedule_reconnect (h); | ||
603 | return 0; | 639 | return 0; |
604 | } | 640 | } |
605 | #if DEBUG_TRANSPORT | 641 | |
606 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
607 | "Ready to transmit %u bytes to transport service\n", size); | ||
608 | #endif | ||
609 | cbuf = buf; | 642 | cbuf = buf; |
610 | ret = 0; | 643 | ret = 0; |
611 | while ( (NULL != (cm = h->control_head)) && | 644 | /* first send control messages */ |
612 | (cm->notify_size <= size) ) | 645 | while ( (NULL != (th = h->control_head)) && |
646 | (th->notify_size <= size) ) | ||
613 | { | 647 | { |
614 | if (cm->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
615 | { | ||
616 | GNUNET_SCHEDULER_cancel (cm->notify_delay_task); | ||
617 | cm->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
618 | } | ||
619 | GNUNET_CONTAINER_DLL_remove (h->control_head, | 648 | GNUNET_CONTAINER_DLL_remove (h->control_head, |
620 | h->control_tail, | 649 | h->control_tail, |
621 | cm); | 650 | th); |
622 | nret = cm->notify (cm->notify_cls, size, &cbuf[ret]); | 651 | nret = th->notify (th->notify_cls, size, &cbuf[ret]); |
623 | #if DEBUG_TRANSPORT | 652 | #if DEBUG_TRANSPORT |
624 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 653 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
625 | "Added %u bytes of control message at %u\n", | 654 | "Added %u bytes of control message at %u\n", |
626 | nret, | 655 | nret, |
627 | ret); | 656 | ret); |
628 | #endif | 657 | #endif |
629 | GNUNET_free (cm); | 658 | GNUNET_free (th); |
630 | ret += nret; | 659 | ret += nret; |
631 | size -= nret; | 660 | size -= nret; |
632 | } | 661 | } |
633 | while ( (NULL != (th = schedule_peer_transmission (h))) && | 662 | |
634 | (th->notify_size <= size) ) | 663 | /* then, if possible and no control messages pending, send data messages */ |
664 | while ( (NULL == h->control_head) && | ||
665 | (NULL != (n = GNUNET_CONTAINER_heap_peek (h->ready_heap))) ) | ||
635 | { | 666 | { |
636 | if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | 667 | if (GNUNET_YES != n->is_ready) |
637 | { | ||
638 | GNUNET_SCHEDULER_cancel (th->notify_delay_task); | ||
639 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
640 | } | ||
641 | n = th->neighbour; | ||
642 | switch (n->transmit_stage) | ||
643 | { | 668 | { |
644 | case TS_NEW: | 669 | /* peer not ready, wait for notification! */ |
645 | GNUNET_break (0); | 670 | GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap)); |
646 | break; | 671 | n->hn = NULL; |
647 | case TS_QUEUED: | 672 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == n->th->timeout_task); |
648 | n->transmit_stage = TS_TRANSMITTED; | 673 | n->th->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (n->th->timeout), |
649 | break; | 674 | &timeout_request_due_to_congestion, |
650 | case TS_TRANSMITTED: | 675 | n->th); |
651 | GNUNET_break (0); | 676 | continue; |
652 | break; | ||
653 | case TS_TRANSMITTED_QUEUED: | ||
654 | GNUNET_break (0); | ||
655 | break; | ||
656 | default: | ||
657 | GNUNET_break (0); | ||
658 | } | 677 | } |
678 | th = n->th; | ||
679 | if (th->notify_size + sizeof (struct OutboundMessage) > size) | ||
680 | break; /* does not fit */ | ||
681 | if (GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, th->notify_size).rel_value > 0) | ||
682 | break; /* too early */ | ||
683 | GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap)); | ||
684 | n->hn = NULL; | ||
685 | n->th = NULL; | ||
686 | n->is_ready = GNUNET_NO; | ||
659 | GNUNET_assert (size >= sizeof (struct OutboundMessage)); | 687 | GNUNET_assert (size >= sizeof (struct OutboundMessage)); |
660 | notify = th->notify; | 688 | mret = th->notify (th->notify_cls, |
661 | th->notify = NULL; | 689 | size - sizeof (struct OutboundMessage), |
662 | mret = notify (th->notify_cls, | 690 | &cbuf[ret + sizeof (struct OutboundMessage)]); |
663 | size - sizeof (struct OutboundMessage), | ||
664 | &cbuf[ret + sizeof (struct OutboundMessage)]); | ||
665 | GNUNET_assert (mret <= size - sizeof (struct OutboundMessage)); | 691 | GNUNET_assert (mret <= size - sizeof (struct OutboundMessage)); |
666 | #if DEBUG_TRANSPORT | ||
667 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
668 | "Message of %u bytes with timeout %llums constructed for `%4s'\n", | ||
669 | (unsigned int) mret, | ||
670 | (unsigned long long) GNUNET_TIME_absolute_get_remaining (th->timeout).rel_value, | ||
671 | GNUNET_i2s (&n->id)); | ||
672 | #endif | ||
673 | if (mret != 0) | 692 | if (mret != 0) |
674 | { | 693 | { |
675 | GNUNET_assert (mret + sizeof (struct OutboundMessage) < GNUNET_SERVER_MAX_MESSAGE_SIZE); | 694 | GNUNET_assert (mret + sizeof (struct OutboundMessage) < GNUNET_SERVER_MAX_MESSAGE_SIZE); |
@@ -683,27 +702,9 @@ transport_notify_ready (void *cls, size_t size, void *buf) | |||
683 | size -= (mret + sizeof (struct OutboundMessage)); | 702 | size -= (mret + sizeof (struct OutboundMessage)); |
684 | GNUNET_BANDWIDTH_tracker_consume (&n->out_tracker, mret); | 703 | GNUNET_BANDWIDTH_tracker_consume (&n->out_tracker, mret); |
685 | } | 704 | } |
686 | else | 705 | GNUNET_free (th); |
687 | { | ||
688 | switch (n->transmit_stage) | ||
689 | { | ||
690 | case TS_NEW: | ||
691 | GNUNET_break (0); | ||
692 | break; | ||
693 | case TS_QUEUED: | ||
694 | GNUNET_break (0); | ||
695 | break; | ||
696 | case TS_TRANSMITTED: | ||
697 | n->transmit_stage = TS_NEW; | ||
698 | break; | ||
699 | case TS_TRANSMITTED_QUEUED: | ||
700 | n->transmit_stage = TS_QUEUED; | ||
701 | continue; | ||
702 | default: | ||
703 | GNUNET_break (0); | ||
704 | } | ||
705 | } | ||
706 | } | 706 | } |
707 | /* if there are more pending messages, try to schedule those */ | ||
707 | schedule_transmission (h); | 708 | schedule_transmission (h); |
708 | #if DEBUG_TRANSPORT | 709 | #if DEBUG_TRANSPORT |
709 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 710 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -716,76 +717,98 @@ transport_notify_ready (void *cls, size_t size, void *buf) | |||
716 | /** | 717 | /** |
717 | * Schedule the task to send one message, either from the control | 718 | * Schedule the task to send one message, either from the control |
718 | * list or the peer message queues to the service. | 719 | * list or the peer message queues to the service. |
720 | * | ||
721 | * @param cls transport service to schedule a transmission for | ||
722 | * @param tc scheduler context | ||
719 | */ | 723 | */ |
720 | static void | 724 | static void |
721 | schedule_transmission (struct GNUNET_TRANSPORT_Handle *h) | 725 | schedule_transmission_task (void *cls, |
726 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
722 | { | 727 | { |
728 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
723 | size_t size; | 729 | size_t size; |
724 | struct GNUNET_TIME_Relative timeout; | ||
725 | struct GNUNET_TRANSPORT_TransmitHandle *th; | 730 | struct GNUNET_TRANSPORT_TransmitHandle *th; |
731 | struct Neighbour *n; | ||
726 | 732 | ||
727 | if (NULL != h->network_handle) | 733 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; |
728 | return; | 734 | GNUNET_assert (NULL != h->client); |
729 | if (h->client == NULL) | 735 | /* destroy all requests that have timed out */ |
736 | while ( (NULL != (n = GNUNET_CONTAINER_heap_peek (h->ready_heap))) && | ||
737 | (GNUNET_TIME_absolute_get_remaining (n->th->timeout).rel_value == 0) ) | ||
730 | { | 738 | { |
739 | /* notify client that the request could not be satisfied within | ||
740 | the given time constraints */ | ||
741 | th = n->th; | ||
742 | n->th = NULL; | ||
743 | GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap)); | ||
744 | n->hn = NULL; | ||
745 | #if DEBUG_TRANSPORT | ||
731 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 746 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
732 | _("Could not yet schedule transmission: we are not yet connected to the transport service!\n")); | 747 | "Signalling timeout for transmission to peer %s due to congestion\n", |
733 | return; /* not yet connected */ | 748 | GNUNET_i2s (&n->id)); |
749 | #endif | ||
750 | GNUNET_assert (0 == | ||
751 | th->notify (th->notify_cls, 0, NULL)); | ||
752 | GNUNET_free (th); | ||
734 | } | 753 | } |
754 | if (NULL != h->cth) | ||
755 | return; | ||
735 | if (NULL != h->control_head) | 756 | if (NULL != h->control_head) |
736 | { | 757 | { |
737 | size = h->control_head->notify_size; | 758 | size = h->control_head->notify_size; |
738 | timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
739 | } | 759 | } |
740 | else | 760 | else |
741 | { | 761 | { |
742 | th = schedule_peer_transmission (h); | 762 | n = GNUNET_CONTAINER_heap_peek (h->ready_heap); |
743 | if (th == NULL) | 763 | if (NULL == n) |
744 | { | 764 | return; /* no pending messages */ |
745 | /* no transmission ready right now */ | 765 | size = n->th->notify_size + sizeof (struct OutboundMessage); |
766 | } | ||
746 | #if DEBUG_TRANSPORT | 767 | #if DEBUG_TRANSPORT |
747 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 768 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
748 | "Could not yet schedule transmission: none ready\n"); | 769 | "Calling notify_transmit_ready\n"); |
749 | #endif | ||
750 | return; | ||
751 | } | ||
752 | size = th->notify_size; | ||
753 | timeout = GNUNET_TIME_absolute_get_remaining (th->timeout); | ||
754 | } | ||
755 | #if DEBUG_TRANSPORT | ||
756 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
757 | "Calling notify_transmit_ready\n"); | ||
758 | #endif | 770 | #endif |
759 | h->network_handle = | 771 | h->cth = |
760 | GNUNET_CLIENT_notify_transmit_ready (h->client, | 772 | GNUNET_CLIENT_notify_transmit_ready (h->client, |
761 | size, | 773 | size, |
762 | timeout, | 774 | GNUNET_TIME_UNIT_FOREVER_REL, |
763 | GNUNET_NO, | 775 | GNUNET_NO, |
764 | &transport_notify_ready, | 776 | &transport_notify_ready, |
765 | h); | 777 | h); |
766 | GNUNET_assert (NULL != h->network_handle); | 778 | GNUNET_assert (NULL != h->cth); |
767 | } | 779 | } |
768 | 780 | ||
769 | 781 | ||
770 | /** | 782 | /** |
771 | * Called when our transmit request timed out before any transport | 783 | * Schedule the task to send one message, either from the control |
772 | * reported success connecting to the desired peer or before the | 784 | * list or the peer message queues to the service. |
773 | * transport was ready to receive. Signal error and free | 785 | * |
774 | * TransmitHandle. | 786 | * @param h transport service to schedule a transmission for |
775 | */ | 787 | */ |
776 | static void | 788 | static void |
777 | control_transmit_timeout (void *cls, | 789 | schedule_transmission (struct GNUNET_TRANSPORT_Handle *h) |
778 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
779 | { | 790 | { |
780 | struct ControlMessage *th = cls; | 791 | struct GNUNET_TIME_Relative delay; |
781 | 792 | struct Neighbour *n; | |
782 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | 793 | |
783 | if (NULL != th->notify) | 794 | GNUNET_assert (NULL != h->client); |
784 | th->notify (th->notify_cls, 0, NULL); | 795 | if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) |
785 | GNUNET_CONTAINER_DLL_remove (th->h->control_head, | 796 | { |
786 | th->h->control_tail, | 797 | GNUNET_SCHEDULER_cancel (h->quota_task); |
787 | th); | 798 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; |
788 | GNUNET_free (th); | 799 | } |
800 | if (NULL != h->control_head) | ||
801 | delay = GNUNET_TIME_UNIT_ZERO; | ||
802 | else if (NULL != (n = GNUNET_CONTAINER_heap_peek (h->ready_heap))) | ||
803 | delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, n->th->notify_size); | ||
804 | else | ||
805 | return; /* no work to be done */ | ||
806 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
807 | "Scheduling next transmission to service in %llu ms\n", | ||
808 | (unsigned long long) delay.rel_value); | ||
809 | h->quota_task = GNUNET_SCHEDULER_add_delayed (delay, | ||
810 | &schedule_transmission_task, | ||
811 | h); | ||
789 | } | 812 | } |
790 | 813 | ||
791 | 814 | ||
@@ -795,79 +818,179 @@ control_transmit_timeout (void *cls, | |||
795 | * | 818 | * |
796 | * @param h handle to the transport service | 819 | * @param h handle to the transport service |
797 | * @param size number of bytes to be transmitted | 820 | * @param size number of bytes to be transmitted |
798 | * @param at_head request must be added to the head of the queue | ||
799 | * (otherwise request will be appended) | ||
800 | * @param timeout how long this transmission can wait (at most) | ||
801 | * @param notify function to call to get the content | 821 | * @param notify function to call to get the content |
802 | * @param notify_cls closure for notify | 822 | * @param notify_cls closure for notify |
803 | */ | 823 | */ |
804 | static void | 824 | static void |
805 | schedule_control_transmit (struct GNUNET_TRANSPORT_Handle *h, | 825 | schedule_control_transmit (struct GNUNET_TRANSPORT_Handle *h, |
806 | size_t size, | 826 | size_t size, |
807 | int at_head, | ||
808 | struct GNUNET_TIME_Relative timeout, | ||
809 | GNUNET_CONNECTION_TransmitReadyNotify notify, | 827 | GNUNET_CONNECTION_TransmitReadyNotify notify, |
810 | void *notify_cls) | 828 | void *notify_cls) |
811 | { | 829 | { |
812 | struct ControlMessage *cm; | 830 | struct GNUNET_TRANSPORT_TransmitHandle *th; |
813 | 831 | ||
814 | #if DEBUG_TRANSPORT | 832 | #if DEBUG_TRANSPORT |
815 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 833 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
816 | "Control transmit of %u bytes within %llums requested\n", | 834 | "Control transmit of %u bytes requested\n", |
817 | size, (unsigned long long) timeout.rel_value); | 835 | size); |
818 | #endif | 836 | #endif |
819 | cm = GNUNET_malloc (sizeof (struct ControlMessage)); | 837 | th = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_TransmitHandle)); |
820 | cm->h = h; | 838 | th->notify = notify; |
821 | cm->notify = notify; | 839 | th->notify_cls = notify_cls; |
822 | cm->notify_cls = notify_cls; | 840 | th->notify_size = size; |
823 | cm->notify_size = size; | 841 | GNUNET_CONTAINER_DLL_insert_tail (h->control_head, |
824 | cm->notify_delay_task | 842 | h->control_tail, |
825 | = GNUNET_SCHEDULER_add_delayed (timeout, &control_transmit_timeout, cm); | 843 | th); |
826 | if (at_head) | ||
827 | GNUNET_CONTAINER_DLL_insert (h->control_head, | ||
828 | h->control_tail, | ||
829 | cm); | ||
830 | else | ||
831 | GNUNET_CONTAINER_DLL_insert_after (h->control_head, | ||
832 | h->control_tail, | ||
833 | h->control_tail, | ||
834 | cm); | ||
835 | schedule_transmission (h); | 844 | schedule_transmission (h); |
836 | } | 845 | } |
837 | 846 | ||
838 | 847 | ||
839 | /** | 848 | /** |
840 | * FIXME: document | 849 | * Transmit START message to service. |
850 | * | ||
851 | * @param cls unused | ||
852 | * @param size number of bytes available in buf | ||
853 | * @param buf where to copy the message | ||
854 | * @return number of bytes copied to buf | ||
841 | */ | 855 | */ |
842 | struct SetQuotaContext | 856 | static size_t |
857 | send_start (void *cls, size_t size, void *buf) | ||
843 | { | 858 | { |
844 | /** | 859 | struct GNUNET_TRANSPORT_Handle *h = cls; |
845 | * FIXME: document | 860 | struct StartMessage s; |
846 | */ | ||
847 | struct GNUNET_TRANSPORT_Handle *handle; | ||
848 | 861 | ||
849 | /** | 862 | if (buf == NULL) |
850 | * FIXME: document | 863 | { |
851 | */ | 864 | /* Can only be shutdown, just give up */ |
852 | struct GNUNET_PeerIdentity target; | 865 | #if DEBUG_TRANSPORT |
866 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
867 | "Shutdown while trying to transmit `%s' request.\n", | ||
868 | "START"); | ||
869 | #endif | ||
870 | return 0; | ||
871 | } | ||
872 | #if DEBUG_TRANSPORT | ||
873 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
874 | "Transmitting `%s' request.\n", "START"); | ||
875 | #endif | ||
876 | GNUNET_assert (size >= sizeof (struct StartMessage)); | ||
877 | s.header.size = htons (sizeof (struct StartMessage)); | ||
878 | s.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_START); | ||
879 | s.do_check = htonl (h->check_self); | ||
880 | s.self = h->self; | ||
881 | memcpy (buf, &s, sizeof (struct StartMessage)); | ||
882 | GNUNET_CLIENT_receive (h->client, | ||
883 | &demultiplexer, h, GNUNET_TIME_UNIT_FOREVER_REL); | ||
884 | return sizeof (struct StartMessage); | ||
885 | } | ||
853 | 886 | ||
854 | /** | ||
855 | * FIXME: document | ||
856 | */ | ||
857 | GNUNET_SCHEDULER_Task cont; | ||
858 | 887 | ||
859 | /** | 888 | /** |
860 | * Closure for 'cont'. | 889 | * Try again to connect to transport service. |
861 | */ | 890 | * |
862 | void *cont_cls; | 891 | * @param cls the handle to the transport service |
892 | * @param tc scheduler context | ||
893 | */ | ||
894 | static void | ||
895 | reconnect (void *cls, | ||
896 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
897 | { | ||
898 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
899 | |||
900 | h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
901 | if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
902 | { | ||
903 | /* shutdown, just give up */ | ||
904 | return; | ||
905 | } | ||
906 | #if DEBUG_TRANSPORT | ||
907 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
908 | "Connecting to transport service.\n"); | ||
909 | #endif | ||
910 | GNUNET_assert (h->client == NULL); | ||
911 | GNUNET_assert (h->control_head == NULL); | ||
912 | GNUNET_assert (h->control_tail == NULL); | ||
913 | h->client = GNUNET_CLIENT_connect ("transport", h->cfg); | ||
914 | GNUNET_assert (h->client != NULL); | ||
915 | schedule_control_transmit (h, | ||
916 | sizeof (struct StartMessage), | ||
917 | &send_start, h); | ||
918 | } | ||
919 | |||
920 | |||
921 | /** | ||
922 | * Function that will schedule the job that will try | ||
923 | * to connect us again to the client. | ||
924 | * | ||
925 | * @param h transport service to reconnect | ||
926 | */ | ||
927 | static void | ||
928 | disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_Handle *h) | ||
929 | { | ||
930 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
931 | |||
932 | GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); | ||
933 | /* Forget about all neighbours that we used to be connected to */ | ||
934 | GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, | ||
935 | &neighbour_delete, | ||
936 | h); | ||
937 | if (NULL != h->cth) | ||
938 | { | ||
939 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); | ||
940 | h->cth = NULL; | ||
941 | } | ||
942 | if (NULL != h->client) | ||
943 | { | ||
944 | GNUNET_CLIENT_disconnect (h->client, GNUNET_YES); | ||
945 | h->client = NULL; | ||
946 | } | ||
947 | if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) | ||
948 | { | ||
949 | GNUNET_SCHEDULER_cancel (h->quota_task); | ||
950 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; | ||
951 | } | ||
952 | while ( (NULL != (th = h->control_head))) | ||
953 | { | ||
954 | GNUNET_CONTAINER_DLL_remove (h->control_head, | ||
955 | h->control_tail, | ||
956 | th); | ||
957 | th->notify (th->notify_cls, 0, NULL); | ||
958 | GNUNET_free (th); | ||
959 | } | ||
960 | #if DEBUG_TRANSPORT | ||
961 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
962 | "Scheduling task to reconnect to transport service in %llu ms.\n", | ||
963 | h->reconnect_delay.rel_value); | ||
964 | #endif | ||
965 | h->reconnect_task | ||
966 | = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, | ||
967 | &reconnect, h); | ||
968 | if (h->reconnect_delay.rel_value == 0) | ||
969 | { | ||
970 | h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
971 | } | ||
972 | else | ||
973 | { | ||
974 | h->reconnect_delay = GNUNET_TIME_relative_multiply (h->reconnect_delay, 2); | ||
975 | h->reconnect_delay = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, | ||
976 | h->reconnect_delay); | ||
977 | } | ||
978 | } | ||
979 | |||
980 | |||
981 | /** | ||
982 | * Closure for 'send_set_quota'. | ||
983 | */ | ||
984 | struct SetQuotaContext | ||
985 | { | ||
863 | 986 | ||
864 | /** | 987 | /** |
865 | * FIXME: document | 988 | * Identity of the peer impacted by the quota change. |
866 | */ | 989 | */ |
867 | struct GNUNET_TIME_Absolute timeout; | 990 | struct GNUNET_PeerIdentity target; |
868 | 991 | ||
869 | /** | 992 | /** |
870 | * FIXME: document | 993 | * Quota to transmit. |
871 | */ | 994 | */ |
872 | struct GNUNET_BANDWIDTH_Value32NBO quota_in; | 995 | struct GNUNET_BANDWIDTH_Value32NBO quota_in; |
873 | }; | 996 | }; |
@@ -885,14 +1008,10 @@ static size_t | |||
885 | send_set_quota (void *cls, size_t size, void *buf) | 1008 | send_set_quota (void *cls, size_t size, void *buf) |
886 | { | 1009 | { |
887 | struct SetQuotaContext *sqc = cls; | 1010 | struct SetQuotaContext *sqc = cls; |
888 | struct QuotaSetMessage *msg; | 1011 | struct QuotaSetMessage msg; |
889 | 1012 | ||
890 | if (buf == NULL) | 1013 | if (buf == NULL) |
891 | { | 1014 | { |
892 | if (sqc->cont != NULL) | ||
893 | GNUNET_SCHEDULER_add_continuation (sqc->cont, | ||
894 | sqc->cont_cls, | ||
895 | GNUNET_SCHEDULER_REASON_TIMEOUT); | ||
896 | GNUNET_free (sqc); | 1015 | GNUNET_free (sqc); |
897 | return 0; | 1016 | return 0; |
898 | } | 1017 | } |
@@ -903,15 +1022,11 @@ send_set_quota (void *cls, size_t size, void *buf) | |||
903 | GNUNET_i2s (&sqc->target)); | 1022 | GNUNET_i2s (&sqc->target)); |
904 | #endif | 1023 | #endif |
905 | GNUNET_assert (size >= sizeof (struct QuotaSetMessage)); | 1024 | GNUNET_assert (size >= sizeof (struct QuotaSetMessage)); |
906 | msg = buf; | 1025 | msg.header.size = htons (sizeof (struct QuotaSetMessage)); |
907 | msg->header.size = htons (sizeof (struct QuotaSetMessage)); | 1026 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA); |
908 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA); | 1027 | msg.quota = sqc->quota_in; |
909 | msg->quota = sqc->quota_in; | 1028 | msg.peer = sqc->target; |
910 | memcpy (&msg->peer, &sqc->target, sizeof (struct GNUNET_PeerIdentity)); | 1029 | memcpy (buf, &msg, sizeof (msg)); |
911 | if (sqc->cont != NULL) | ||
912 | GNUNET_SCHEDULER_add_continuation (sqc->cont, | ||
913 | sqc->cont_cls, | ||
914 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
915 | GNUNET_free (sqc); | 1030 | GNUNET_free (sqc); |
916 | return sizeof (struct QuotaSetMessage); | 1031 | return sizeof (struct QuotaSetMessage); |
917 | } | 1032 | } |
@@ -932,137 +1047,99 @@ GNUNET_TRANSPORT_set_quota (struct GNUNET_TRANSPORT_Handle *handle, | |||
932 | struct GNUNET_BANDWIDTH_Value32NBO quota_in, | 1047 | struct GNUNET_BANDWIDTH_Value32NBO quota_in, |
933 | struct GNUNET_BANDWIDTH_Value32NBO quota_out) | 1048 | struct GNUNET_BANDWIDTH_Value32NBO quota_out) |
934 | { | 1049 | { |
935 | struct NeighbourList *n; | 1050 | struct Neighbour *n; |
936 | struct SetQuotaContext *sqc; | 1051 | struct SetQuotaContext *sqc; |
937 | 1052 | ||
938 | n = neighbour_find (handle, target); | 1053 | n = neighbour_find (handle, target); |
939 | if (n != NULL) | 1054 | if (NULL == n) |
940 | { | ||
941 | #if DEBUG_TRANSPORT | ||
942 | if (ntohl (quota_out.value__) != n->out_tracker.available_bytes_per_s__) | ||
943 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
944 | "Quota changed from %u to %u for peer `%s'\n", | ||
945 | (unsigned int) n->out_tracker.available_bytes_per_s__, | ||
946 | (unsigned int) ntohl (quota_out.value__), | ||
947 | GNUNET_i2s (target)); | ||
948 | else | ||
949 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
950 | "Quota remains at %u for peer `%s'\n", | ||
951 | (unsigned int) n->out_tracker.available_bytes_per_s__, | ||
952 | GNUNET_i2s (target)); | ||
953 | #endif | ||
954 | GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker, | ||
955 | quota_out); | ||
956 | } | ||
957 | else | ||
958 | { | 1055 | { |
959 | #if DEBUG_TRANSPORT | 1056 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
960 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
961 | "Quota changed to %u for peer `%s', but I have no such neighbour!\n", | 1057 | "Quota changed to %u for peer `%s', but I have no such neighbour!\n", |
962 | (unsigned int) ntohl (quota_out.value__), | 1058 | (unsigned int) ntohl (quota_out.value__), |
963 | GNUNET_i2s (target)); | 1059 | GNUNET_i2s (target)); |
964 | #endif | 1060 | return; |
965 | } | 1061 | } |
1062 | GNUNET_assert (NULL != handle->client); | ||
1063 | #if DEBUG_TRANSPORT | ||
1064 | if (ntohl (quota_out.value__) != n->out_tracker.available_bytes_per_s__) | ||
1065 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1066 | "Quota changed from %u to %u for peer `%s'\n", | ||
1067 | (unsigned int) n->out_tracker.available_bytes_per_s__, | ||
1068 | (unsigned int) ntohl (quota_out.value__), | ||
1069 | GNUNET_i2s (target)); | ||
1070 | else | ||
1071 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1072 | "Quota remains at %u for peer `%s'\n", | ||
1073 | (unsigned int) n->out_tracker.available_bytes_per_s__, | ||
1074 | GNUNET_i2s (target)); | ||
1075 | #endif | ||
1076 | GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker, | ||
1077 | quota_out); | ||
966 | sqc = GNUNET_malloc (sizeof (struct SetQuotaContext)); | 1078 | sqc = GNUNET_malloc (sizeof (struct SetQuotaContext)); |
967 | sqc->handle = handle; | ||
968 | sqc->target = *target; | 1079 | sqc->target = *target; |
969 | sqc->cont = NULL; | ||
970 | sqc->cont_cls = NULL; | ||
971 | sqc->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_FOREVER_REL); | ||
972 | sqc->quota_in = quota_in; | 1080 | sqc->quota_in = quota_in; |
973 | schedule_control_transmit (handle, | 1081 | schedule_control_transmit (handle, |
974 | sizeof (struct QuotaSetMessage), | 1082 | sizeof (struct QuotaSetMessage), |
975 | GNUNET_NO, | 1083 | &send_set_quota, sqc); |
976 | GNUNET_TIME_UNIT_FOREVER_REL, &send_set_quota, sqc); | ||
977 | } | 1084 | } |
978 | 1085 | ||
979 | 1086 | ||
980 | /** | 1087 | /** |
981 | * Ask the transport service to establish a connection to | 1088 | * Send REQUEST_CONNECT message to the service. |
982 | * the given peer. | ||
983 | * | 1089 | * |
984 | * @param handle connection to transport service | 1090 | * @param cls the 'struct GNUNET_PeerIdentity' |
985 | * @param target who we should try to connect to | 1091 | * @param size number of bytes available in buf |
986 | */ | 1092 | * @param buf where to copy the message |
987 | void | 1093 | * @return number of bytes copied to buf |
988 | GNUNET_TRANSPORT_try_connect (struct GNUNET_TRANSPORT_Handle *handle, | ||
989 | const struct GNUNET_PeerIdentity *target) | ||
990 | { | ||
991 | /* old API does nothing */ | ||
992 | } | ||
993 | |||
994 | |||
995 | |||
996 | |||
997 | /** | ||
998 | * Obtain the HELLO message for this peer. | ||
999 | * | ||
1000 | * @param handle connection to transport service | ||
1001 | * @param rec function to call with the HELLO, sender will be our peer | ||
1002 | * identity; message and sender will be NULL on timeout | ||
1003 | * (handshake with transport service pending/failed). | ||
1004 | * cost estimate will be 0. | ||
1005 | * @param rec_cls closure for rec | ||
1006 | */ | 1094 | */ |
1007 | void | 1095 | static size_t |
1008 | GNUNET_TRANSPORT_get_hello (struct GNUNET_TRANSPORT_Handle *handle, | 1096 | send_try_connect (void *cls, size_t size, void *buf) |
1009 | GNUNET_TRANSPORT_HelloUpdateCallback rec, | ||
1010 | void *rec_cls) | ||
1011 | { | 1097 | { |
1012 | struct HelloWaitList *hwl; | 1098 | struct GNUNET_PeerIdentity *pid = cls; |
1099 | struct TransportRequestConnectMessage msg; | ||
1013 | 1100 | ||
1014 | hwl = GNUNET_malloc (sizeof (struct HelloWaitList)); | 1101 | if (buf == NULL) |
1015 | hwl->next = handle->hwl_head; | ||
1016 | handle->hwl_head = hwl; | ||
1017 | hwl->handle = handle; | ||
1018 | hwl->rec = rec; | ||
1019 | hwl->rec_cls = rec_cls; | ||
1020 | if (handle->my_hello == NULL) | ||
1021 | { | 1102 | { |
1022 | #if DEBUG_TRANSPORT_HELLO | 1103 | GNUNET_free (pid); |
1023 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1104 | return 0; |
1024 | "No HELLO yet, waiting to receive it from transport service\n"); | ||
1025 | #endif | ||
1026 | return; | ||
1027 | } | 1105 | } |
1028 | rec (rec_cls, (const struct GNUNET_MessageHeader *) handle->my_hello); | 1106 | #if DEBUG_TRANSPORT |
1107 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1108 | "Transmitting `%s' request with respect to `%4s'.\n", | ||
1109 | "REQUEST_CONNECT", | ||
1110 | GNUNET_i2s (pid)); | ||
1111 | #endif | ||
1112 | GNUNET_assert (size >= sizeof (struct TransportRequestConnectMessage)); | ||
1113 | msg.header.size = htons (sizeof (struct TransportRequestConnectMessage)); | ||
1114 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT); | ||
1115 | msg.reserved = htonl (0); | ||
1116 | msg.peer = *pid; | ||
1117 | memcpy (buf, &msg, sizeof (msg)); | ||
1118 | GNUNET_free (pid); | ||
1119 | return sizeof (struct TransportRequestConnectMessage); | ||
1029 | } | 1120 | } |
1030 | 1121 | ||
1031 | 1122 | ||
1032 | |||
1033 | /** | 1123 | /** |
1034 | * Stop receiving updates about changes to our HELLO message. | 1124 | * Ask the transport service to establish a connection to |
1125 | * the given peer. | ||
1035 | * | 1126 | * |
1036 | * @param handle connection to transport service | 1127 | * @param handle connection to transport service |
1037 | * @param rec function previously registered to be called with the HELLOs | 1128 | * @param target who we should try to connect to |
1038 | * @param rec_cls closure for rec | ||
1039 | */ | 1129 | */ |
1040 | void | 1130 | void |
1041 | GNUNET_TRANSPORT_get_hello_cancel (struct GNUNET_TRANSPORT_Handle *handle, | 1131 | GNUNET_TRANSPORT_try_connect (struct GNUNET_TRANSPORT_Handle *handle, |
1042 | GNUNET_TRANSPORT_HelloUpdateCallback rec, | 1132 | const struct GNUNET_PeerIdentity *target) |
1043 | void *rec_cls) | ||
1044 | { | 1133 | { |
1045 | struct HelloWaitList *pos; | 1134 | struct GNUNET_PeerIdentity *pid; |
1046 | struct HelloWaitList *prev; | ||
1047 | 1135 | ||
1048 | prev = NULL; | 1136 | if (NULL == handle->client) |
1049 | pos = handle->hwl_head; | ||
1050 | while (pos != NULL) | ||
1051 | { | ||
1052 | if ( (pos->rec == rec) && | ||
1053 | (pos->rec_cls == rec_cls) ) | ||
1054 | break; | ||
1055 | prev = pos; | ||
1056 | pos = pos->next; | ||
1057 | } | ||
1058 | GNUNET_break (pos != NULL); | ||
1059 | if (pos == NULL) | ||
1060 | return; | 1137 | return; |
1061 | if (prev == NULL) | 1138 | pid = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
1062 | handle->hwl_head = pos->next; | 1139 | *pid = *target; |
1063 | else | 1140 | schedule_control_transmit (handle, |
1064 | prev->next = pos->next; | 1141 | sizeof (struct TransportRequestConnectMessage), |
1065 | GNUNET_free (pos); | 1142 | &send_try_connect, pid); |
1066 | } | 1143 | } |
1067 | 1144 | ||
1068 | 1145 | ||
@@ -1077,8 +1154,9 @@ GNUNET_TRANSPORT_get_hello_cancel (struct GNUNET_TRANSPORT_Handle *handle, | |||
1077 | static size_t | 1154 | static size_t |
1078 | send_hello (void *cls, size_t size, void *buf) | 1155 | send_hello (void *cls, size_t size, void *buf) |
1079 | { | 1156 | { |
1080 | struct HelloContext *hc = cls; | 1157 | struct GNUNET_MessageHeader *msg = cls; |
1081 | uint16_t ssize; | 1158 | uint16_t ssize; |
1159 | |||
1082 | if (buf == NULL) | 1160 | if (buf == NULL) |
1083 | { | 1161 | { |
1084 | #if DEBUG_TRANSPORT_TIMEOUT | 1162 | #if DEBUG_TRANSPORT_TIMEOUT |
@@ -1086,24 +1164,17 @@ send_hello (void *cls, size_t size, void *buf) | |||
1086 | "Timeout while trying to transmit `%s' request.\n", | 1164 | "Timeout while trying to transmit `%s' request.\n", |
1087 | "HELLO"); | 1165 | "HELLO"); |
1088 | #endif | 1166 | #endif |
1089 | if (NULL != hc->cont) | 1167 | GNUNET_free (msg); |
1090 | GNUNET_SCHEDULER_add_now(hc->cont, hc->cont_cls); | ||
1091 | GNUNET_free (hc); | ||
1092 | return 0; | 1168 | return 0; |
1093 | } | 1169 | } |
1094 | #if DEBUG_TRANSPORT | 1170 | #if DEBUG_TRANSPORT |
1095 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1171 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1096 | "Transmitting `%s' request.\n", "HELLO"); | 1172 | "Transmitting `%s' request.\n", "HELLO"); |
1097 | #endif | 1173 | #endif |
1098 | GNUNET_assert (size >= hc->size); | 1174 | ssize = ntohs (msg->size); |
1099 | memcpy (buf, &hc[1], hc->size); | 1175 | GNUNET_assert (size >= ssize); |
1100 | 1176 | memcpy (buf, msg, ssize); | |
1101 | if (hc->cont != NULL) | 1177 | GNUNET_free (msg); |
1102 | { | ||
1103 | GNUNET_SCHEDULER_add_continuation(hc->cont, hc->cont_cls, GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
1104 | } | ||
1105 | ssize = hc->size; | ||
1106 | GNUNET_free (hc); | ||
1107 | return ssize; | 1178 | return ssize; |
1108 | } | 1179 | } |
1109 | 1180 | ||
@@ -1127,8 +1198,10 @@ GNUNET_TRANSPORT_offer_hello (struct GNUNET_TRANSPORT_Handle *handle, | |||
1127 | { | 1198 | { |
1128 | uint16_t size; | 1199 | uint16_t size; |
1129 | struct GNUNET_PeerIdentity peer; | 1200 | struct GNUNET_PeerIdentity peer; |
1130 | struct HelloContext *hc; | 1201 | struct GNUNET_MessageHeader *msg; |
1131 | 1202 | ||
1203 | if (NULL == handle->client) | ||
1204 | return; | ||
1132 | GNUNET_break (ntohs (hello->type) == GNUNET_MESSAGE_TYPE_HELLO); | 1205 | GNUNET_break (ntohs (hello->type) == GNUNET_MESSAGE_TYPE_HELLO); |
1133 | size = ntohs (hello->size); | 1206 | size = ntohs (hello->size); |
1134 | GNUNET_break (size >= sizeof (struct GNUNET_MessageHeader)); | 1207 | GNUNET_break (size >= sizeof (struct GNUNET_MessageHeader)); |
@@ -1138,403 +1211,78 @@ GNUNET_TRANSPORT_offer_hello (struct GNUNET_TRANSPORT_Handle *handle, | |||
1138 | GNUNET_break (0); | 1211 | GNUNET_break (0); |
1139 | return; | 1212 | return; |
1140 | } | 1213 | } |
1141 | hc = GNUNET_malloc(sizeof(struct HelloContext) + size); | 1214 | msg = GNUNET_malloc(size); |
1142 | hc->size = size; | 1215 | memcpy (msg, hello, size); |
1143 | hc->cont = cont; | ||
1144 | hc->cont_cls = cls; | ||
1145 | memcpy (&hc[1], hello, size); | ||
1146 | |||
1147 | #if DEBUG_TRANSPORT | 1216 | #if DEBUG_TRANSPORT |
1148 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1217 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1149 | "Offering `%s' message of `%4s' to transport for validation.\n", | 1218 | "Offering `%s' message of `%4s' to transport for validation.\n", |
1150 | "HELLO", | 1219 | "HELLO", |
1151 | GNUNET_i2s (&peer)); | 1220 | GNUNET_i2s (&peer)); |
1152 | #endif | 1221 | #endif |
1153 | |||
1154 | schedule_control_transmit (handle, | 1222 | schedule_control_transmit (handle, |
1155 | size, | 1223 | size, |
1156 | GNUNET_NO, OFFER_HELLO_TIMEOUT, &send_hello, hc); | 1224 | &send_hello, msg); |
1157 | } | ||
1158 | |||
1159 | |||
1160 | /** | ||
1161 | * Transmit START message to service. | ||
1162 | * | ||
1163 | * @param cls unused | ||
1164 | * @param size number of bytes available in buf | ||
1165 | * @param buf where to copy the message | ||
1166 | * @return number of bytes copied to buf | ||
1167 | */ | ||
1168 | static size_t | ||
1169 | send_start (void *cls, size_t size, void *buf) | ||
1170 | { | ||
1171 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
1172 | struct StartMessage s; | ||
1173 | |||
1174 | if (buf == NULL) | ||
1175 | { | ||
1176 | /* Can only be shutdown, just give up */ | ||
1177 | #if DEBUG_TRANSPORT | ||
1178 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1179 | "Shutdown while trying to transmit `%s' request.\n", | ||
1180 | "START"); | ||
1181 | #endif | ||
1182 | return 0; | ||
1183 | } | ||
1184 | #if DEBUG_TRANSPORT | ||
1185 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1186 | "Transmitting `%s' request.\n", "START"); | ||
1187 | #endif | ||
1188 | GNUNET_assert (size >= sizeof (struct StartMessage)); | ||
1189 | s.header.size = htons (sizeof (struct StartMessage)); | ||
1190 | s.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_START); | ||
1191 | s.do_check = htonl (h->check_self); | ||
1192 | s.self = h->self; | ||
1193 | memcpy (buf, &s, sizeof (struct StartMessage)); | ||
1194 | return sizeof (struct StartMessage); | ||
1195 | } | 1225 | } |
1196 | 1226 | ||
1197 | 1227 | ||
1198 | /** | 1228 | /** |
1199 | * Free neighbour. | 1229 | * Obtain the HELLO message for this peer. |
1200 | * | ||
1201 | * @param n the entry to free | ||
1202 | */ | ||
1203 | static void | ||
1204 | neighbour_free (struct NeighbourList *n) | ||
1205 | { | ||
1206 | struct GNUNET_TRANSPORT_Handle *h; | ||
1207 | |||
1208 | /* Added so task gets canceled when a disconnect is received! */ | ||
1209 | /* Method 1 | ||
1210 | if (n->transmit_handle.notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
1211 | { | ||
1212 | GNUNET_SCHEDULER_cancel(n->transmit_handle.notify_delay_task); | ||
1213 | n->transmit_handle.notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
1214 | n->transmit_handle.notify = NULL; | ||
1215 | } | ||
1216 | */ | ||
1217 | /* NATE: if the above is not needed, then clearly this assertion | ||
1218 | should hold (I've checked the code and I'm pretty sure this is | ||
1219 | true. -CG | ||
1220 | FIXME: remove above comments once we've seen tests pass with the assert... */ | ||
1221 | GNUNET_assert (n->transmit_handle.notify_delay_task == GNUNET_SCHEDULER_NO_TASK); | ||
1222 | GNUNET_assert (n->transmit_handle.notify == NULL); | ||
1223 | h = n->h; | ||
1224 | #if DEBUG_TRANSPORT | ||
1225 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1226 | "Removing neighbour `%s' from list of connected peers.\n", | ||
1227 | GNUNET_i2s (&n->id)); | ||
1228 | #endif | ||
1229 | GNUNET_break (n->is_connected == GNUNET_NO); | ||
1230 | GNUNET_break (n->transmit_stage == TS_NEW); | ||
1231 | |||
1232 | GNUNET_assert(GNUNET_YES == | ||
1233 | GNUNET_CONTAINER_multihashmap_remove(h->neighbours, | ||
1234 | &n->id.hashPubKey, | ||
1235 | n)); | ||
1236 | GNUNET_free (n); | ||
1237 | } | ||
1238 | |||
1239 | |||
1240 | /** | ||
1241 | * Mark neighbour as disconnected. | ||
1242 | * | ||
1243 | * @param n the entry to mark as disconnected | ||
1244 | */ | ||
1245 | static void | ||
1246 | neighbour_disconnect (struct NeighbourList *n) | ||
1247 | { | ||
1248 | struct GNUNET_TRANSPORT_Handle *h = n->h; | ||
1249 | #if DEBUG_TRANSPORT | ||
1250 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1251 | "Removing neighbour `%s' from list of connected peers.\n", | ||
1252 | GNUNET_i2s (&n->id)); | ||
1253 | #endif | ||
1254 | GNUNET_break (n->is_connected == GNUNET_YES); | ||
1255 | n->is_connected = GNUNET_NO; | ||
1256 | /* FIXME: this 'in_disconnect' flag is dubious; we should define | ||
1257 | clearly what disconnect means for pending 'notify_transmit_ready' | ||
1258 | requests; maybe a good approach is to REQUIRE clients to | ||
1259 | call 'notify_transmit_ready_cancel' on pending requests on disconnect | ||
1260 | and otherwise FAIL HARD with an assertion failure before | ||
1261 | 'neighbour_free' right here (transmit_stage would be forced | ||
1262 | to 'TS_NEW') */ | ||
1263 | n->in_disconnect = GNUNET_YES; | ||
1264 | if (h->nd_cb != NULL) | ||
1265 | h->nd_cb (h->cls, &n->id); | ||
1266 | if (n->transmit_stage == TS_NEW) | ||
1267 | neighbour_free (n); | ||
1268 | } | ||
1269 | |||
1270 | |||
1271 | /** | ||
1272 | * Function we use for handling incoming messages. | ||
1273 | * | ||
1274 | * @param cls closure (struct GNUNET_TRANSPORT_Handle *) | ||
1275 | * @param msg message received, NULL on timeout or fatal error | ||
1276 | */ | ||
1277 | static void demultiplexer (void *cls, | ||
1278 | const struct GNUNET_MessageHeader *msg); | ||
1279 | |||
1280 | |||
1281 | /** | ||
1282 | * Iterator over hash map entries, for getting rid of a neighbor | ||
1283 | * upon a reconnect call. | ||
1284 | * | 1230 | * |
1285 | * @param cls closure (NULL) | 1231 | * @param handle connection to transport service |
1286 | * @param key current key code | 1232 | * @param rec function to call with the HELLO, sender will be our peer |
1287 | * @param value value in the hash map, the neighbour entry to forget | 1233 | * identity; message and sender will be NULL on timeout |
1288 | * @return GNUNET_YES if we should continue to | 1234 | * (handshake with transport service pending/failed). |
1289 | * iterate, | 1235 | * cost estimate will be 0. |
1290 | * GNUNET_NO if not. | 1236 | * @param rec_cls closure for rec |
1291 | */ | 1237 | */ |
1292 | static int | 1238 | void |
1293 | forget_neighbours (void *cls, | 1239 | GNUNET_TRANSPORT_get_hello (struct GNUNET_TRANSPORT_Handle *handle, |
1294 | const GNUNET_HashCode * key, | 1240 | GNUNET_TRANSPORT_HelloUpdateCallback rec, |
1295 | void *value) | 1241 | void *rec_cls) |
1296 | { | 1242 | { |
1297 | struct NeighbourList *n = value; | 1243 | struct HelloWaitList *hwl; |
1298 | |||
1299 | #if DEBUG_TRANSPORT_DISCONNECT | ||
1300 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1301 | "Disconnecting due to reconnect being called\n"); | ||
1302 | #endif | ||
1303 | if (n->is_connected) | ||
1304 | neighbour_disconnect (n); | ||
1305 | 1244 | ||
1306 | return GNUNET_YES; | 1245 | hwl = GNUNET_malloc (sizeof (struct HelloWaitList)); |
1246 | hwl->rec = rec; | ||
1247 | hwl->rec_cls = rec_cls; | ||
1248 | GNUNET_CONTAINER_DLL_insert (handle->hwl_head, | ||
1249 | handle->hwl_tail, | ||
1250 | hwl); | ||
1251 | if (handle->my_hello == NULL) | ||
1252 | return; | ||
1253 | rec (rec_cls, (const struct GNUNET_MessageHeader *) handle->my_hello); | ||
1307 | } | 1254 | } |
1308 | 1255 | ||
1309 | 1256 | ||
1310 | /** | 1257 | /** |
1311 | * Try again to connect to transport service. | 1258 | * Stop receiving updates about changes to our HELLO message. |
1312 | * | 1259 | * |
1313 | * @param cls the handle to the transport service | 1260 | * @param handle connection to transport service |
1314 | * @param tc scheduler context | 1261 | * @param rec function previously registered to be called with the HELLOs |
1262 | * @param rec_cls closure for rec | ||
1315 | */ | 1263 | */ |
1316 | static void | 1264 | void |
1317 | reconnect (void *cls, | 1265 | GNUNET_TRANSPORT_get_hello_cancel (struct GNUNET_TRANSPORT_Handle *handle, |
1318 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 1266 | GNUNET_TRANSPORT_HelloUpdateCallback rec, |
1267 | void *rec_cls) | ||
1319 | { | 1268 | { |
1320 | struct GNUNET_TRANSPORT_Handle *h = cls; | 1269 | struct HelloWaitList *pos; |
1321 | struct ControlMessage *pos; | ||
1322 | |||
1323 | h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
1324 | if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
1325 | { | ||
1326 | /* shutdown, just give up */ | ||
1327 | return; | ||
1328 | } | ||
1329 | /* Forget about all neighbours that we used to be connected to */ | ||
1330 | GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, | ||
1331 | &forget_neighbours, | ||
1332 | NULL); | ||
1333 | 1270 | ||
1334 | #if DEBUG_TRANSPORT | 1271 | pos = handle->hwl_head; |
1335 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1336 | "Connecting to transport service.\n"); | ||
1337 | #endif | ||
1338 | GNUNET_assert (h->client == NULL); | ||
1339 | h->client = GNUNET_CLIENT_connect ("transport", h->cfg); | ||
1340 | GNUNET_assert (h->client != NULL); | ||
1341 | /* make sure we don't send "START" twice, remove existing entry from | ||
1342 | queue (if present) */ | ||
1343 | pos = h->control_head; | ||
1344 | while (pos != NULL) | 1272 | while (pos != NULL) |
1345 | { | 1273 | { |
1346 | if (pos->notify == &send_start) | 1274 | if ( (pos->rec == rec) && |
1347 | { | 1275 | (pos->rec_cls == rec_cls) ) |
1348 | GNUNET_CONTAINER_DLL_remove (h->control_head, | 1276 | break; |
1349 | h->control_tail, | ||
1350 | pos); | ||
1351 | if (GNUNET_SCHEDULER_NO_TASK != pos->notify_delay_task) | ||
1352 | { | ||
1353 | GNUNET_SCHEDULER_cancel (pos->notify_delay_task); | ||
1354 | pos->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
1355 | } | ||
1356 | GNUNET_free (pos); | ||
1357 | break; | ||
1358 | } | ||
1359 | pos = pos->next; | 1277 | pos = pos->next; |
1360 | } | 1278 | } |
1361 | schedule_control_transmit (h, | 1279 | GNUNET_break (pos != NULL); |
1362 | sizeof (struct StartMessage), | 1280 | if (pos == NULL) |
1363 | GNUNET_YES, | 1281 | return; |
1364 | GNUNET_TIME_UNIT_FOREVER_REL, &send_start, h); | 1282 | GNUNET_CONTAINER_DLL_remove (handle->hwl_head, |
1365 | GNUNET_CLIENT_receive (h->client, | 1283 | handle->hwl_tail, |
1366 | &demultiplexer, h, GNUNET_TIME_UNIT_FOREVER_REL); | 1284 | pos); |
1367 | } | 1285 | GNUNET_free (pos); |
1368 | |||
1369 | |||
1370 | /** | ||
1371 | * Function that will schedule the job that will try | ||
1372 | * to connect us again to the client. | ||
1373 | * | ||
1374 | * @param h transport service to reconnect | ||
1375 | */ | ||
1376 | static void | ||
1377 | schedule_reconnect (struct GNUNET_TRANSPORT_Handle *h) | ||
1378 | { | ||
1379 | #if DEBUG_TRANSPORT | ||
1380 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1381 | "Scheduling task to reconnect to transport service in %llu ms.\n", | ||
1382 | h->reconnect_delay.rel_value); | ||
1383 | #endif | ||
1384 | GNUNET_assert (h->client == NULL); | ||
1385 | GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); | ||
1386 | h->reconnect_task | ||
1387 | = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h); | ||
1388 | if (h->reconnect_delay.rel_value == 0) | ||
1389 | { | ||
1390 | h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1391 | } | ||
1392 | else | ||
1393 | { | ||
1394 | h->reconnect_delay = GNUNET_TIME_relative_multiply (h->reconnect_delay, 2); | ||
1395 | h->reconnect_delay = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, | ||
1396 | h->reconnect_delay); | ||
1397 | } | ||
1398 | } | ||
1399 | |||
1400 | |||
1401 | /** | ||
1402 | * Send request connect message to the service. | ||
1403 | * | ||
1404 | * @param cls the TransportRequestConnectMessage | ||
1405 | * @param size number of bytes available in buf | ||
1406 | * @param buf where to copy the message | ||
1407 | * @return number of bytes copied to buf | ||
1408 | */ | ||
1409 | static size_t | ||
1410 | send_transport_request_connect (void *cls, size_t size, void *buf) | ||
1411 | { | ||
1412 | struct TransportRequestConnectMessage *trcm = cls; | ||
1413 | |||
1414 | if (buf == NULL) | ||
1415 | { | ||
1416 | #if DEBUG_TRANSPORT | ||
1417 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1418 | "Buffer null for %s\n", | ||
1419 | "REQUEST_CONNECT"); | ||
1420 | #endif | ||
1421 | GNUNET_free (trcm); | ||
1422 | return 0; | ||
1423 | } | ||
1424 | #if DEBUG_TRANSPORT | ||
1425 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1426 | "Transmitting `%s' request for `%4s'.\n", | ||
1427 | "REQUEST_CONNECT", | ||
1428 | GNUNET_i2s (&trcm->peer)); | ||
1429 | #endif | ||
1430 | GNUNET_assert (size >= sizeof (struct TransportRequestConnectMessage)); | ||
1431 | memcpy(buf, trcm, sizeof(struct TransportRequestConnectMessage)); | ||
1432 | GNUNET_free (trcm); | ||
1433 | return sizeof(struct TransportRequestConnectMessage); | ||
1434 | } | ||
1435 | |||
1436 | /** | ||
1437 | * Create and send a request connect message to | ||
1438 | * the transport service for a particular peer. | ||
1439 | * | ||
1440 | * @param h handle to the transport service | ||
1441 | * @param n the neighbor to send the request connect message about | ||
1442 | * | ||
1443 | */ | ||
1444 | static void | ||
1445 | send_request_connect_message(struct GNUNET_TRANSPORT_Handle *h, struct NeighbourList *n) | ||
1446 | { | ||
1447 | struct TransportRequestConnectMessage *trcm; | ||
1448 | |||
1449 | trcm = GNUNET_malloc(sizeof(struct TransportRequestConnectMessage)); | ||
1450 | trcm->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT); | ||
1451 | trcm->header.size = htons(sizeof(struct TransportRequestConnectMessage)); | ||
1452 | memcpy(&trcm->peer, &n->id, sizeof(struct GNUNET_PeerIdentity)); | ||
1453 | schedule_control_transmit (h, | ||
1454 | sizeof (struct TransportRequestConnectMessage), | ||
1455 | GNUNET_NO, | ||
1456 | GNUNET_TIME_UNIT_FOREVER_REL, &send_transport_request_connect, trcm); | ||
1457 | } | ||
1458 | |||
1459 | |||
1460 | /** | ||
1461 | * Add neighbour to our list | ||
1462 | * | ||
1463 | * @return NULL if this API is currently disconnecting from the service | ||
1464 | */ | ||
1465 | static struct NeighbourList * | ||
1466 | neighbour_add (struct GNUNET_TRANSPORT_Handle *h, | ||
1467 | const struct GNUNET_PeerIdentity *pid) | ||
1468 | { | ||
1469 | struct NeighbourList *n; | ||
1470 | |||
1471 | if (GNUNET_YES == h->in_disconnect) | ||
1472 | return NULL; | ||
1473 | /* check for duplicates */ | ||
1474 | if (NULL != (n = neighbour_find (h, pid))) | ||
1475 | { | ||
1476 | GNUNET_break (0); | ||
1477 | return n; | ||
1478 | } | ||
1479 | #if DEBUG_TRANSPORT | ||
1480 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1481 | "Creating entry for neighbour `%4s'.\n", | ||
1482 | GNUNET_i2s (pid)); | ||
1483 | #endif | ||
1484 | n = GNUNET_malloc (sizeof (struct NeighbourList)); | ||
1485 | n->id = *pid; | ||
1486 | n->h = h; | ||
1487 | GNUNET_BANDWIDTH_tracker_init (&n->out_tracker, | ||
1488 | GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, | ||
1489 | MAX_BANDWIDTH_CARRY_S); | ||
1490 | GNUNET_CONTAINER_multihashmap_put (h->neighbours, | ||
1491 | &pid->hashPubKey, | ||
1492 | n, | ||
1493 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
1494 | |||
1495 | return n; | ||
1496 | } | ||
1497 | |||
1498 | |||
1499 | /** | ||
1500 | * Iterator over hash map entries, for deleting state of a neighbor. | ||
1501 | * | ||
1502 | * @param cls closure (NULL) | ||
1503 | * @param key current key code | ||
1504 | * @param value value in the hash map, the neighbour entry to delete | ||
1505 | * @return GNUNET_YES if we should continue to | ||
1506 | * iterate, | ||
1507 | * GNUNET_NO if not. | ||
1508 | */ | ||
1509 | static int | ||
1510 | delete_neighbours (void *cls, | ||
1511 | const GNUNET_HashCode * key, | ||
1512 | void *value) | ||
1513 | { | ||
1514 | struct NeighbourList *n = value; | ||
1515 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
1516 | |||
1517 | switch (n->transmit_stage) | ||
1518 | { | ||
1519 | case TS_NEW: | ||
1520 | case TS_TRANSMITTED: | ||
1521 | /* nothing to do */ | ||
1522 | break; | ||
1523 | case TS_QUEUED: | ||
1524 | case TS_TRANSMITTED_QUEUED: | ||
1525 | th = &n->transmit_handle; | ||
1526 | if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
1527 | { | ||
1528 | GNUNET_SCHEDULER_cancel (th->notify_delay_task); | ||
1529 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
1530 | } | ||
1531 | GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); | ||
1532 | break; | ||
1533 | default: | ||
1534 | GNUNET_break (0); | ||
1535 | } | ||
1536 | GNUNET_free (n); | ||
1537 | return GNUNET_YES; | ||
1538 | } | 1286 | } |
1539 | 1287 | ||
1540 | 1288 | ||
@@ -1573,75 +1321,35 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
1573 | ret->nd_cb = nd; | 1321 | ret->nd_cb = nd; |
1574 | ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; | 1322 | ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; |
1575 | ret->neighbours = GNUNET_CONTAINER_multihashmap_create(STARTING_NEIGHBOURS_SIZE); | 1323 | ret->neighbours = GNUNET_CONTAINER_multihashmap_create(STARTING_NEIGHBOURS_SIZE); |
1576 | schedule_reconnect (ret); | 1324 | ret->ready_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); |
1325 | ret->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, ret); | ||
1577 | return ret; | 1326 | return ret; |
1578 | } | 1327 | } |
1579 | 1328 | ||
1580 | 1329 | ||
1581 | /** | 1330 | /** |
1582 | * Disconnect from the transport service. | 1331 | * Disconnect from the transport service. |
1332 | * | ||
1333 | * @param handle handle to the service as returned from GNUNET_TRANSPORT_connect | ||
1583 | */ | 1334 | */ |
1584 | void | 1335 | void |
1585 | GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) | 1336 | GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) |
1586 | { | 1337 | { |
1587 | struct HelloWaitList *hwl; | ||
1588 | struct GNUNET_CLIENT_Connection *client; | ||
1589 | struct ControlMessage *cm; | ||
1590 | |||
1591 | #if DEBUG_TRANSPORT | 1338 | #if DEBUG_TRANSPORT |
1592 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n"); | 1339 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1340 | "Transport disconnect called!\n"); | ||
1593 | #endif | 1341 | #endif |
1594 | /* FIXME: this flag is dubious, we should be able to do this | 1342 | /* this disconnects all neighbours... */ |
1595 | more cleanly; also, we should probably do 'disconnect' | 1343 | if (handle->reconnect_task == GNUNET_SCHEDULER_NO_TASK) |
1596 | callbacks for every connected peer here, i.e. by calling | 1344 | disconnect_and_schedule_reconnect (handle); |
1597 | the iterator with 'forget_neighbours' instead of 'delete_neighbours'. | 1345 | /* and now we stop trying to connect again... */ |
1598 | */ | ||
1599 | |||
1600 | handle->in_disconnect = GNUNET_YES; | ||
1601 | |||
1602 | GNUNET_assert (GNUNET_SYSERR != | ||
1603 | GNUNET_CONTAINER_multihashmap_iterate(handle->neighbours, | ||
1604 | &delete_neighbours, | ||
1605 | handle)); | ||
1606 | GNUNET_CONTAINER_multihashmap_destroy (handle->neighbours); | ||
1607 | |||
1608 | while (NULL != (hwl = handle->hwl_head)) | ||
1609 | { | ||
1610 | handle->hwl_head = hwl->next; | ||
1611 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1612 | _ | ||
1613 | ("Disconnect while notification for `%s' still registered.\n"), | ||
1614 | "HELLO"); | ||
1615 | if (hwl->rec != NULL) | ||
1616 | hwl->rec (hwl->rec_cls, NULL); | ||
1617 | GNUNET_free (hwl); | ||
1618 | } | ||
1619 | |||
1620 | /* Check for still scheduled control messages, cancel delay tasks if so */ | ||
1621 | /* Added because somehow a notify_delay_task is remaining scheduled and is ever so annoying */ | ||
1622 | while ( (NULL != (cm = handle->control_head))) | ||
1623 | { | ||
1624 | #if DEBUG_TRANSPORT | ||
1625 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1626 | "Disconnect before control message sent!\n"); | ||
1627 | #endif | ||
1628 | if (cm->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
1629 | { | ||
1630 | GNUNET_SCHEDULER_cancel (cm->notify_delay_task); | ||
1631 | cm->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
1632 | } | ||
1633 | GNUNET_CONTAINER_DLL_remove (handle->control_head, | ||
1634 | handle->control_tail, | ||
1635 | cm); | ||
1636 | GNUNET_free (cm); | ||
1637 | } | ||
1638 | /* end check */ | ||
1639 | |||
1640 | if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) | 1346 | if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) |
1641 | { | 1347 | { |
1642 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); | 1348 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); |
1643 | handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | 1349 | handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; |
1644 | } | 1350 | } |
1351 | GNUNET_CONTAINER_multihashmap_destroy (handle->neighbours); | ||
1352 | handle->neighbours = NULL; | ||
1645 | if (handle->quota_task != GNUNET_SCHEDULER_NO_TASK) | 1353 | if (handle->quota_task != GNUNET_SCHEDULER_NO_TASK) |
1646 | { | 1354 | { |
1647 | GNUNET_SCHEDULER_cancel (handle->quota_task); | 1355 | GNUNET_SCHEDULER_cancel (handle->quota_task); |
@@ -1649,315 +1357,15 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) | |||
1649 | } | 1357 | } |
1650 | GNUNET_free_non_null (handle->my_hello); | 1358 | GNUNET_free_non_null (handle->my_hello); |
1651 | handle->my_hello = NULL; | 1359 | handle->my_hello = NULL; |
1652 | 1360 | GNUNET_assert (handle->hwl_head == NULL); | |
1653 | if (NULL != handle->network_handle) | 1361 | GNUNET_assert (handle->hwl_tail == NULL); |
1654 | { | 1362 | GNUNET_CONTAINER_heap_destroy (handle->ready_heap); |
1655 | GNUNET_CLIENT_notify_transmit_ready_cancel (handle->network_handle); | 1363 | handle->ready_heap = NULL; |
1656 | handle->network_handle = NULL; | ||
1657 | } | ||
1658 | if (NULL != (client = handle->client)) | ||
1659 | { | ||
1660 | #if DEBUG_TRANSPORT | ||
1661 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1662 | "Disconnecting from transport service for good.\n"); | ||
1663 | #endif | ||
1664 | handle->client = NULL; | ||
1665 | GNUNET_CLIENT_disconnect (client, GNUNET_YES); | ||
1666 | } | ||
1667 | GNUNET_free (handle); | 1364 | GNUNET_free (handle); |
1668 | } | 1365 | } |
1669 | 1366 | ||
1670 | 1367 | ||
1671 | /** | 1368 | /** |
1672 | * Function we use for handling incoming messages. | ||
1673 | * | ||
1674 | * @param cls closure (struct GNUNET_TRANSPORT_Handle *) | ||
1675 | * @param msg message received, NULL on timeout or fatal error | ||
1676 | */ | ||
1677 | static void | ||
1678 | demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) | ||
1679 | { | ||
1680 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
1681 | const struct DisconnectInfoMessage *dim; | ||
1682 | const struct ConnectInfoMessage *cim; | ||
1683 | const struct InboundMessage *im; | ||
1684 | const struct GNUNET_MessageHeader *imm; | ||
1685 | const struct SendOkMessage *okm; | ||
1686 | struct HelloWaitList *hwl; | ||
1687 | struct HelloWaitList *next_hwl; | ||
1688 | struct NeighbourList *n; | ||
1689 | struct GNUNET_PeerIdentity me; | ||
1690 | uint16_t size; | ||
1691 | uint32_t ats_count; | ||
1692 | |||
1693 | if (h->client == NULL) | ||
1694 | { | ||
1695 | /* shutdown initiated from 'GNUNET_TRANSPORT_disconnect', | ||
1696 | finish clean up work! */ | ||
1697 | GNUNET_free (h); | ||
1698 | return; | ||
1699 | } | ||
1700 | if (msg == NULL) | ||
1701 | { | ||
1702 | #if DEBUG_TRANSPORT | ||
1703 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1704 | "Error receiving from transport service, disconnecting temporarily.\n"); | ||
1705 | #endif | ||
1706 | if (h->network_handle != NULL) | ||
1707 | { | ||
1708 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->network_handle); | ||
1709 | h->network_handle = NULL; | ||
1710 | } | ||
1711 | GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); | ||
1712 | h->client = NULL; | ||
1713 | schedule_reconnect (h); | ||
1714 | return; | ||
1715 | } | ||
1716 | GNUNET_CLIENT_receive (h->client, | ||
1717 | &demultiplexer, h, GNUNET_TIME_UNIT_FOREVER_REL); | ||
1718 | size = ntohs (msg->size); | ||
1719 | switch (ntohs (msg->type)) | ||
1720 | { | ||
1721 | case GNUNET_MESSAGE_TYPE_HELLO: | ||
1722 | if (GNUNET_OK != | ||
1723 | GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) msg, | ||
1724 | &me)) | ||
1725 | { | ||
1726 | GNUNET_break (0); | ||
1727 | break; | ||
1728 | } | ||
1729 | #if DEBUG_TRANSPORT | ||
1730 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1731 | "Receiving (my own) `%s' message, I am `%4s'.\n", | ||
1732 | "HELLO", GNUNET_i2s (&me)); | ||
1733 | #endif | ||
1734 | GNUNET_free_non_null (h->my_hello); | ||
1735 | h->my_hello = NULL; | ||
1736 | if (size < sizeof (struct GNUNET_MessageHeader)) | ||
1737 | { | ||
1738 | GNUNET_break (0); | ||
1739 | break; | ||
1740 | } | ||
1741 | h->my_hello = GNUNET_malloc (size); | ||
1742 | memcpy (h->my_hello, msg, size); | ||
1743 | hwl = h->hwl_head; | ||
1744 | while (NULL != hwl) | ||
1745 | { | ||
1746 | next_hwl = hwl->next; | ||
1747 | hwl->rec (hwl->rec_cls, | ||
1748 | (const struct GNUNET_MessageHeader *) h->my_hello); | ||
1749 | hwl = next_hwl; | ||
1750 | } | ||
1751 | break; | ||
1752 | case GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT: | ||
1753 | if (size < sizeof (struct ConnectInfoMessage)) | ||
1754 | { | ||
1755 | GNUNET_break (0); | ||
1756 | break; | ||
1757 | } | ||
1758 | cim = (const struct ConnectInfoMessage *) msg; | ||
1759 | ats_count = ntohl (cim->ats_count); | ||
1760 | if (size != sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)) | ||
1761 | { | ||
1762 | GNUNET_break (0); | ||
1763 | break; | ||
1764 | } | ||
1765 | if (0 == memcmp (&cim->id, | ||
1766 | &h->self, | ||
1767 | sizeof (struct GNUNET_PeerIdentity))) | ||
1768 | { | ||
1769 | /* connect to self!? */ | ||
1770 | GNUNET_break (0); | ||
1771 | break; | ||
1772 | } | ||
1773 | #if DEBUG_TRANSPORT | ||
1774 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1775 | "Receiving `%s' message for `%4s'.\n", | ||
1776 | "CONNECT", GNUNET_i2s (&cim->id)); | ||
1777 | #endif | ||
1778 | n = neighbour_find (h, &cim->id); | ||
1779 | if (n == NULL) | ||
1780 | n = neighbour_add (h, &cim->id); | ||
1781 | if (n == NULL) | ||
1782 | return; | ||
1783 | GNUNET_break (n->is_connected == GNUNET_NO); | ||
1784 | n->is_connected = GNUNET_YES; | ||
1785 | /* FIXME */ | ||
1786 | if (h->nc_cb != NULL) | ||
1787 | h->nc_cb (h->cls, &n->id, | ||
1788 | &cim->ats,ats_count); | ||
1789 | /* FIXEND */ | ||
1790 | break; | ||
1791 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT: | ||
1792 | if (size != sizeof (struct DisconnectInfoMessage)) | ||
1793 | { | ||
1794 | GNUNET_break (0); | ||
1795 | break; | ||
1796 | } | ||
1797 | dim = (const struct DisconnectInfoMessage *) msg; | ||
1798 | GNUNET_break (ntohl (dim->reserved) == 0); | ||
1799 | if (0 == memcmp (&dim->peer, | ||
1800 | &h->self, | ||
1801 | sizeof (struct GNUNET_PeerIdentity))) | ||
1802 | { | ||
1803 | /* discconnect from self!? */ | ||
1804 | GNUNET_break (0); | ||
1805 | break; | ||
1806 | } | ||
1807 | #if DEBUG_TRANSPORT_DISCONNECT | ||
1808 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1809 | "Receiving `%s' message for `%4s'.\n", | ||
1810 | "DISCONNECT", | ||
1811 | GNUNET_i2s (&dim->peer)); | ||
1812 | #endif | ||
1813 | n = neighbour_find (h, &dim->peer); | ||
1814 | GNUNET_break (n != NULL); | ||
1815 | if (n != NULL) | ||
1816 | neighbour_disconnect (n); | ||
1817 | break; | ||
1818 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK: | ||
1819 | if (size != sizeof (struct SendOkMessage)) | ||
1820 | { | ||
1821 | GNUNET_break (0); | ||
1822 | break; | ||
1823 | } | ||
1824 | okm = (const struct SendOkMessage *) msg; | ||
1825 | #if DEBUG_TRANSPORT | ||
1826 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1827 | "Receiving `%s' message, transmission %s.\n", "SEND_OK", | ||
1828 | ntohl (okm->success) == GNUNET_OK ? "succeeded" : "failed"); | ||
1829 | #endif | ||
1830 | n = neighbour_find (h, &okm->peer); | ||
1831 | GNUNET_assert (n != NULL); | ||
1832 | switch (n->transmit_stage) | ||
1833 | { | ||
1834 | case TS_NEW: | ||
1835 | GNUNET_break (0); | ||
1836 | break; | ||
1837 | case TS_QUEUED: | ||
1838 | GNUNET_break (0); | ||
1839 | break; | ||
1840 | case TS_TRANSMITTED: | ||
1841 | n->transmit_stage = TS_NEW; | ||
1842 | break; | ||
1843 | case TS_TRANSMITTED_QUEUED: | ||
1844 | n->transmit_stage = TS_QUEUED; | ||
1845 | schedule_transmission (h); | ||
1846 | break; | ||
1847 | default: | ||
1848 | GNUNET_break (0); | ||
1849 | } | ||
1850 | break; | ||
1851 | case GNUNET_MESSAGE_TYPE_TRANSPORT_RECV: | ||
1852 | #if DEBUG_TRANSPORT | ||
1853 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1854 | "Receiving `%s' message.\n", "RECV"); | ||
1855 | #endif | ||
1856 | if (size < | ||
1857 | sizeof (struct InboundMessage) + | ||
1858 | sizeof (struct GNUNET_MessageHeader)) | ||
1859 | { | ||
1860 | GNUNET_break (0); | ||
1861 | break; | ||
1862 | } | ||
1863 | im = (const struct InboundMessage *) msg; | ||
1864 | GNUNET_break (0 == ntohl (im->reserved)); | ||
1865 | ats_count = ntohl(im->ats_count); | ||
1866 | //imm = (const struct GNUNET_MessageHeader *) &im[1]; | ||
1867 | imm = (const struct GNUNET_MessageHeader *) &((&(im->ats))[ats_count+1]); | ||
1868 | |||
1869 | if (ntohs (imm->size) + sizeof (struct InboundMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) != size) | ||
1870 | { | ||
1871 | GNUNET_break (0); | ||
1872 | break; | ||
1873 | } | ||
1874 | #if DEBUG_TRANSPORT | ||
1875 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1876 | "Received message of type %u from `%4s'.\n", | ||
1877 | ntohs (imm->type), GNUNET_i2s (&im->peer)); | ||
1878 | #endif | ||
1879 | n = neighbour_find (h, &im->peer); | ||
1880 | if (n == NULL) | ||
1881 | { | ||
1882 | GNUNET_break (0); | ||
1883 | break; | ||
1884 | } | ||
1885 | if (n->is_connected != GNUNET_YES) | ||
1886 | { | ||
1887 | GNUNET_break (0); | ||
1888 | break; | ||
1889 | } | ||
1890 | /* FIXME: */ | ||
1891 | if (h->rec != NULL) | ||
1892 | h->rec (h->cls, &im->peer, imm, | ||
1893 | &im->ats, ats_count); | ||
1894 | /* ENDFIX */ | ||
1895 | break; | ||
1896 | default: | ||
1897 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1898 | _ | ||
1899 | ("Received unexpected message of type %u in %s:%u\n"), | ||
1900 | ntohs (msg->type), __FILE__, __LINE__); | ||
1901 | GNUNET_break (0); | ||
1902 | break; | ||
1903 | } | ||
1904 | } | ||
1905 | |||
1906 | |||
1907 | /** | ||
1908 | * Called when our transmit request timed out before any transport | ||
1909 | * reported success connecting to the desired peer or before the | ||
1910 | * transport was ready to receive. Signal error and free | ||
1911 | * TransmitHandle. | ||
1912 | * | ||
1913 | * @param cls the 'struct GNUNET_TRANSPORT_TransmitHandle*' that is timing out | ||
1914 | * @param tc scheduler context | ||
1915 | */ | ||
1916 | static void | ||
1917 | peer_transmit_timeout (void *cls, | ||
1918 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1919 | { | ||
1920 | struct GNUNET_TRANSPORT_TransmitHandle *th = cls; | ||
1921 | struct NeighbourList *n; | ||
1922 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
1923 | void *notify_cls; | ||
1924 | |||
1925 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
1926 | n = th->neighbour; | ||
1927 | #if DEBUG_TRANSPORT | ||
1928 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1929 | "Triggering timeout for request to transmit to `%4s' (%d)\n", | ||
1930 | GNUNET_i2s (&n->id), | ||
1931 | n->transmit_stage); | ||
1932 | #endif | ||
1933 | notify = th->notify; | ||
1934 | th->notify = NULL; | ||
1935 | notify_cls = th->notify_cls; | ||
1936 | switch (n->transmit_stage) | ||
1937 | { | ||
1938 | case TS_NEW: | ||
1939 | GNUNET_break (0); | ||
1940 | break; | ||
1941 | case TS_QUEUED: | ||
1942 | n->transmit_stage = TS_NEW; | ||
1943 | if (n->is_connected == GNUNET_NO) | ||
1944 | neighbour_free (n); | ||
1945 | break; | ||
1946 | case TS_TRANSMITTED: | ||
1947 | GNUNET_break (0); | ||
1948 | break; | ||
1949 | case TS_TRANSMITTED_QUEUED: | ||
1950 | n->transmit_stage = TS_TRANSMITTED; | ||
1951 | break; | ||
1952 | default: | ||
1953 | GNUNET_break (0); | ||
1954 | } | ||
1955 | if (NULL != notify) | ||
1956 | notify (notify_cls, 0, NULL); | ||
1957 | } | ||
1958 | |||
1959 | |||
1960 | /** | ||
1961 | * Check if we could queue a message of the given size for | 1369 | * Check if we could queue a message of the given size for |
1962 | * transmission. The transport service will take both its | 1370 | * transmission. The transport service will take both its |
1963 | * internal buffers and bandwidth limits imposed by the | 1371 | * internal buffers and bandwidth limits imposed by the |
@@ -1977,89 +1385,54 @@ peer_transmit_timeout (void *cls, | |||
1977 | * using GNUNET_TRANSPORT_notify_transmit_ready_cancel) | 1385 | * using GNUNET_TRANSPORT_notify_transmit_ready_cancel) |
1978 | */ | 1386 | */ |
1979 | struct GNUNET_TRANSPORT_TransmitHandle * | 1387 | struct GNUNET_TRANSPORT_TransmitHandle * |
1980 | GNUNET_TRANSPORT_notify_transmit_ready (struct GNUNET_TRANSPORT_Handle | 1388 | GNUNET_TRANSPORT_notify_transmit_ready (struct GNUNET_TRANSPORT_Handle *handle, |
1981 | *handle, | 1389 | const struct GNUNET_PeerIdentity *target, |
1982 | const struct GNUNET_PeerIdentity | 1390 | size_t size, |
1983 | *target, size_t size, | ||
1984 | uint32_t priority, | 1391 | uint32_t priority, |
1985 | struct GNUNET_TIME_Relative timeout, | 1392 | struct GNUNET_TIME_Relative timeout, |
1986 | GNUNET_CONNECTION_TransmitReadyNotify | 1393 | GNUNET_CONNECTION_TransmitReadyNotify notify, |
1987 | notify, void *notify_cls) | 1394 | void *notify_cls) |
1988 | { | 1395 | { |
1396 | struct Neighbour *n; | ||
1989 | struct GNUNET_TRANSPORT_TransmitHandle *th; | 1397 | struct GNUNET_TRANSPORT_TransmitHandle *th; |
1990 | struct NeighbourList *n; | 1398 | struct GNUNET_TIME_Relative delay; |
1991 | 1399 | ||
1992 | if (size + sizeof (struct OutboundMessage) >= | ||
1993 | GNUNET_SERVER_MAX_MESSAGE_SIZE) | ||
1994 | { | ||
1995 | #if DEBUG_TRANSPORT | ||
1996 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1997 | "Message size is %d, max allowed is %d.\n", | ||
1998 | size + sizeof (struct OutboundMessage), GNUNET_SERVER_MAX_MESSAGE_SIZE - 1); | ||
1999 | #endif | ||
2000 | GNUNET_break (0); | ||
2001 | return NULL; | ||
2002 | } | ||
2003 | #if DEBUG_TRANSPORT | ||
2004 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2005 | "Asking transport service for transmission of %u bytes to peer `%4s' within %llu ms.\n", | ||
2006 | size, GNUNET_i2s (target), | ||
2007 | (unsigned long long) timeout.rel_value); | ||
2008 | #endif | ||
2009 | n = neighbour_find (handle, target); | 1400 | n = neighbour_find (handle, target); |
2010 | if (n == NULL) | 1401 | if (NULL == n) |
2011 | { | 1402 | { |
2012 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1403 | /* use GNUNET_TRANSPORT_try_connect first, only use this function |
2013 | "Created neighbour entry for peer `%s'\n", | 1404 | once a connection has been established */ |
2014 | GNUNET_i2s (target)); | 1405 | GNUNET_assert (0); |
2015 | n = neighbour_add (handle, target); | ||
2016 | } | ||
2017 | if (n == NULL) | ||
2018 | { | ||
2019 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2020 | "Could not create neighbour entry for peer `%s'\n", | ||
2021 | GNUNET_i2s (target)); | ||
2022 | return NULL; | 1406 | return NULL; |
2023 | } | 1407 | } |
2024 | 1408 | if (NULL != n->th) | |
2025 | /** | ||
2026 | * Send a request connect message if not connected, | ||
2027 | * otherwise we will never send anything to | ||
2028 | * transport service | ||
2029 | */ | ||
2030 | if (n->is_connected == GNUNET_NO) | ||
2031 | { | ||
2032 | send_request_connect_message(handle, n); | ||
2033 | } | ||
2034 | |||
2035 | switch (n->transmit_stage) | ||
2036 | { | 1409 | { |
2037 | case TS_NEW: | 1410 | /* attempt to send two messages at the same time to the same peer */ |
2038 | n->transmit_stage = TS_QUEUED; | 1411 | GNUNET_assert (0); |
2039 | break; | ||
2040 | case TS_QUEUED: | ||
2041 | GNUNET_break (0); | ||
2042 | return NULL; | ||
2043 | case TS_TRANSMITTED: | ||
2044 | n->transmit_stage = TS_TRANSMITTED_QUEUED; | ||
2045 | break; | ||
2046 | case TS_TRANSMITTED_QUEUED: | ||
2047 | GNUNET_break (0); | ||
2048 | return NULL; | ||
2049 | default: | ||
2050 | GNUNET_break (0); | ||
2051 | return NULL; | 1412 | return NULL; |
2052 | } | 1413 | } |
2053 | th = &n->transmit_handle; | 1414 | GNUNET_assert (NULL == n->hn); |
1415 | th = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_TransmitHandle)); | ||
2054 | th->neighbour = n; | 1416 | th->neighbour = n; |
2055 | th->notify = notify; | 1417 | th->notify = notify; |
2056 | th->notify_cls = notify_cls; | 1418 | th->notify_cls = notify_cls; |
2057 | th->timeout = GNUNET_TIME_relative_to_absolute (timeout); | 1419 | th->timeout = GNUNET_TIME_relative_to_absolute (timeout); |
2058 | th->notify_size = size + sizeof (struct OutboundMessage); | 1420 | th->notify_size = size; |
2059 | th->priority = priority; | 1421 | th->priority = priority; |
2060 | th->notify_delay_task | 1422 | n->th = th; |
2061 | = GNUNET_SCHEDULER_add_delayed (timeout, | 1423 | /* calculate when our transmission should be ready */ |
2062 | &peer_transmit_timeout, th); | 1424 | delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, size); |
1425 | if (delay.rel_value > timeout.rel_value) | ||
1426 | delay.rel_value = 0; /* notify immediately (with failure) */ | ||
1427 | #if DEBUG_TRANSPORT | ||
1428 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1429 | "Bandwidth tracker allows next transmission to peer %s in %llu ms\n", | ||
1430 | GNUNET_i2s (target), | ||
1431 | (unsigned long long) delay.rel_value); | ||
1432 | #endif | ||
1433 | n->hn = GNUNET_CONTAINER_heap_insert (handle->ready_heap, | ||
1434 | n, | ||
1435 | delay.rel_value); | ||
2063 | schedule_transmission (handle); | 1436 | schedule_transmission (handle); |
2064 | return th; | 1437 | return th; |
2065 | } | 1438 | } |
@@ -2067,47 +1440,31 @@ GNUNET_TRANSPORT_notify_transmit_ready (struct GNUNET_TRANSPORT_Handle | |||
2067 | 1440 | ||
2068 | /** | 1441 | /** |
2069 | * Cancel the specified transmission-ready notification. | 1442 | * Cancel the specified transmission-ready notification. |
1443 | * | ||
1444 | * @param th handle returned from GNUNET_TRANSPORT_notify_transmit_ready | ||
2070 | */ | 1445 | */ |
2071 | void | 1446 | void |
2072 | GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct | 1447 | GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct GNUNET_TRANSPORT_TransmitHandle *th) |
2073 | GNUNET_TRANSPORT_TransmitHandle | ||
2074 | *th) | ||
2075 | { | 1448 | { |
2076 | struct NeighbourList *n; | 1449 | struct Neighbour *n; |
2077 | 1450 | ||
2078 | th->notify = NULL; | 1451 | GNUNET_assert (NULL == th->next); |
1452 | GNUNET_assert (NULL == th->prev); | ||
2079 | n = th->neighbour; | 1453 | n = th->neighbour; |
2080 | #if DEBUG_TRANSPORT | 1454 | GNUNET_assert (th == n->th); |
2081 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1455 | n->th = NULL; |
2082 | "Transmission request of %u bytes to `%4s' was canceled.\n", | 1456 | if (n->hn != NULL) |
2083 | th->notify_size - sizeof (struct OutboundMessage), | ||
2084 | GNUNET_i2s (&n->id)); | ||
2085 | #endif | ||
2086 | if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) | ||
2087 | { | 1457 | { |
2088 | GNUNET_SCHEDULER_cancel (th->notify_delay_task); | 1458 | GNUNET_CONTAINER_heap_remove_node (n->hn); |
2089 | th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; | 1459 | n->hn = NULL; |
2090 | } | 1460 | } |
2091 | switch (n->transmit_stage) | 1461 | else |
2092 | { | 1462 | { |
2093 | case TS_NEW: | 1463 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != th->timeout_task); |
2094 | GNUNET_assert (0); | 1464 | GNUNET_SCHEDULER_cancel (th->timeout_task); |
2095 | break; | 1465 | th->timeout_task = GNUNET_SCHEDULER_NO_TASK; |
2096 | case TS_QUEUED: | ||
2097 | n->transmit_stage = TS_NEW; | ||
2098 | if ( (n->in_disconnect == GNUNET_NO) && | ||
2099 | (n->is_connected == GNUNET_NO) ) | ||
2100 | neighbour_free (n); | ||
2101 | break; | ||
2102 | case TS_TRANSMITTED: | ||
2103 | GNUNET_break (0); | ||
2104 | break; | ||
2105 | case TS_TRANSMITTED_QUEUED: | ||
2106 | n->transmit_stage = TS_TRANSMITTED; | ||
2107 | break; | ||
2108 | default: | ||
2109 | GNUNET_break (0); | ||
2110 | } | 1466 | } |
1467 | GNUNET_free (th); | ||
2111 | } | 1468 | } |
2112 | 1469 | ||
2113 | 1470 | ||
diff --git a/src/transport/transport_api_new.c b/src/transport/transport_api_new.c deleted file mode 100644 index 4583cf876..000000000 --- a/src/transport/transport_api_new.c +++ /dev/null | |||
@@ -1,1471 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file transport/transport_api.c | ||
23 | * @brief library to access the low-level P2P IO service | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * TODO: | ||
27 | * - adjust testcases to use new 'try connect' style (should be easy, breaks API compatibility!) | ||
28 | * - adjust core service to use new 'try connect' style (should be MUCH nicer there as well!) | ||
29 | * - test test test | ||
30 | */ | ||
31 | #include "platform.h" | ||
32 | #include "gnunet_bandwidth_lib.h" | ||
33 | #include "gnunet_client_lib.h" | ||
34 | #include "gnunet_constants.h" | ||
35 | #include "gnunet_container_lib.h" | ||
36 | #include "gnunet_arm_service.h" | ||
37 | #include "gnunet_hello_lib.h" | ||
38 | #include "gnunet_protocols.h" | ||
39 | #include "gnunet_server_lib.h" | ||
40 | #include "gnunet_time_lib.h" | ||
41 | #include "gnunet_transport_service.h" | ||
42 | #include "transport.h" | ||
43 | |||
44 | /** | ||
45 | * How large to start with for the hashmap of neighbours. | ||
46 | */ | ||
47 | #define STARTING_NEIGHBOURS_SIZE 16 | ||
48 | |||
49 | |||
50 | /** | ||
51 | * Handle for a message that should be transmitted to the service. | ||
52 | * Used for both control messages and normal messages. | ||
53 | */ | ||
54 | struct GNUNET_TRANSPORT_TransmitHandle | ||
55 | { | ||
56 | |||
57 | /** | ||
58 | * We keep all requests in a DLL. | ||
59 | */ | ||
60 | struct GNUNET_TRANSPORT_TransmitHandle *next; | ||
61 | |||
62 | /** | ||
63 | * We keep all requests in a DLL. | ||
64 | */ | ||
65 | struct GNUNET_TRANSPORT_TransmitHandle *prev; | ||
66 | |||
67 | /** | ||
68 | * Neighbour for this handle, NULL for control messages. | ||
69 | */ | ||
70 | struct Neighbour *neighbour; | ||
71 | |||
72 | /** | ||
73 | * Function to call when notify_size bytes are available | ||
74 | * for transmission. | ||
75 | */ | ||
76 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
77 | |||
78 | /** | ||
79 | * Closure for notify. | ||
80 | */ | ||
81 | void *notify_cls; | ||
82 | |||
83 | /** | ||
84 | * Timeout for this request, 0 for control messages. | ||
85 | */ | ||
86 | struct GNUNET_TIME_Absolute timeout; | ||
87 | |||
88 | /** | ||
89 | * Task to trigger request timeout if the request is stalled due to | ||
90 | * congestion. | ||
91 | */ | ||
92 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
93 | |||
94 | /** | ||
95 | * How many bytes is our notify callback waiting for? | ||
96 | */ | ||
97 | size_t notify_size; | ||
98 | |||
99 | /** | ||
100 | * How important is this message? Not used for control messages. | ||
101 | */ | ||
102 | uint32_t priority; | ||
103 | |||
104 | }; | ||
105 | |||
106 | |||
107 | /** | ||
108 | * Entry in hash table of all of our current neighbours. | ||
109 | */ | ||
110 | struct Neighbour | ||
111 | { | ||
112 | /** | ||
113 | * Overall transport handle. | ||
114 | */ | ||
115 | struct GNUNET_TRANSPORT_Handle *h; | ||
116 | |||
117 | /** | ||
118 | * Active transmit handle or NULL. | ||
119 | */ | ||
120 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
121 | |||
122 | /** | ||
123 | * Identity of this neighbour. | ||
124 | */ | ||
125 | struct GNUNET_PeerIdentity id; | ||
126 | |||
127 | /** | ||
128 | * Outbound bandwidh tracker. | ||
129 | */ | ||
130 | struct GNUNET_BANDWIDTH_Tracker out_tracker; | ||
131 | |||
132 | /** | ||
133 | * Entry in our readyness heap (which is sorted by 'next_ready' | ||
134 | * value). NULL if there is no pending transmission request for | ||
135 | * this neighbour or if we're waiting for 'is_ready' to become | ||
136 | * true AFTER the 'out_tracker' suggested that this peer's quota | ||
137 | * has been satisfied (so once 'is_ready' goes to GNUNET_YES, | ||
138 | * we should immediately go back into the heap). | ||
139 | */ | ||
140 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
141 | |||
142 | /** | ||
143 | * Is this peer currently ready to receive a message? | ||
144 | */ | ||
145 | int is_ready; | ||
146 | |||
147 | }; | ||
148 | |||
149 | |||
150 | /** | ||
151 | * Linked list of functions to call whenever our HELLO is updated. | ||
152 | */ | ||
153 | struct HelloWaitList | ||
154 | { | ||
155 | |||
156 | /** | ||
157 | * This is a doubly linked list. | ||
158 | */ | ||
159 | struct HelloWaitList *next; | ||
160 | |||
161 | /** | ||
162 | * This is a doubly linked list. | ||
163 | */ | ||
164 | struct HelloWaitList *prev; | ||
165 | |||
166 | /** | ||
167 | * Callback to call once we got our HELLO. | ||
168 | */ | ||
169 | GNUNET_TRANSPORT_HelloUpdateCallback rec; | ||
170 | |||
171 | /** | ||
172 | * Closure for rec. | ||
173 | */ | ||
174 | void *rec_cls; | ||
175 | |||
176 | }; | ||
177 | |||
178 | |||
179 | /** | ||
180 | * Handle for the transport service (includes all of the | ||
181 | * state for the transport service). | ||
182 | */ | ||
183 | struct GNUNET_TRANSPORT_Handle | ||
184 | { | ||
185 | |||
186 | /** | ||
187 | * Closure for the callbacks. | ||
188 | */ | ||
189 | void *cls; | ||
190 | |||
191 | /** | ||
192 | * Function to call for received data. | ||
193 | */ | ||
194 | GNUNET_TRANSPORT_ReceiveCallback rec; | ||
195 | |||
196 | /** | ||
197 | * function to call on connect events | ||
198 | */ | ||
199 | GNUNET_TRANSPORT_NotifyConnect nc_cb; | ||
200 | |||
201 | /** | ||
202 | * function to call on disconnect events | ||
203 | */ | ||
204 | GNUNET_TRANSPORT_NotifyDisconnect nd_cb; | ||
205 | |||
206 | /** | ||
207 | * Head of DLL of control messages. | ||
208 | */ | ||
209 | struct GNUNET_TRANSPORT_TransmitHandle *control_head; | ||
210 | |||
211 | /** | ||
212 | * Tail of DLL of control messages. | ||
213 | */ | ||
214 | struct GNUNET_TRANSPORT_TransmitHandle *control_tail; | ||
215 | |||
216 | /** | ||
217 | * The current HELLO message for this peer. Updated | ||
218 | * whenever transports change their addresses. | ||
219 | */ | ||
220 | struct GNUNET_HELLO_Message *my_hello; | ||
221 | |||
222 | /** | ||
223 | * My client connection to the transport service. | ||
224 | */ | ||
225 | struct GNUNET_CLIENT_Connection *client; | ||
226 | |||
227 | /** | ||
228 | * Handle to our registration with the client for notification. | ||
229 | */ | ||
230 | struct GNUNET_CLIENT_TransmitHandle *cth; | ||
231 | |||
232 | /** | ||
233 | * Linked list of pending requests for our HELLO. | ||
234 | */ | ||
235 | struct HelloWaitList *hwl_head; | ||
236 | |||
237 | /** | ||
238 | * Linked list of pending requests for our HELLO. | ||
239 | */ | ||
240 | struct HelloWaitList *hwl_tail; | ||
241 | |||
242 | /** | ||
243 | * My configuration. | ||
244 | */ | ||
245 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
246 | |||
247 | /** | ||
248 | * Hash map of the current connected neighbours of this peer. | ||
249 | * Maps peer identities to 'struct Neighbour' entries. | ||
250 | */ | ||
251 | struct GNUNET_CONTAINER_MultiHashMap *neighbours; | ||
252 | |||
253 | /** | ||
254 | * Heap sorting peers with pending messages by the timestamps that | ||
255 | * specify when we could next send a message to the respective peer. | ||
256 | * Excludes control messages (which can always go out immediately). | ||
257 | * Maps time stamps to 'struct Neighbour' entries. | ||
258 | */ | ||
259 | struct GNUNET_CONTAINER_Heap *ready_heap; | ||
260 | |||
261 | /** | ||
262 | * Peer identity as assumed by this process, or all zeros. | ||
263 | */ | ||
264 | struct GNUNET_PeerIdentity self; | ||
265 | |||
266 | /** | ||
267 | * ID of the task trying to reconnect to the service. | ||
268 | */ | ||
269 | GNUNET_SCHEDULER_TaskIdentifier reconnect_task; | ||
270 | |||
271 | /** | ||
272 | * ID of the task trying to trigger transmission for a peer while | ||
273 | * maintaining bandwidth quotas. In use if there are no control | ||
274 | * messages and the smallest entry in the 'ready_heap' has a time | ||
275 | * stamp in the future. | ||
276 | */ | ||
277 | GNUNET_SCHEDULER_TaskIdentifier quota_task; | ||
278 | |||
279 | /** | ||
280 | * Delay until we try to reconnect. | ||
281 | */ | ||
282 | struct GNUNET_TIME_Relative reconnect_delay; | ||
283 | |||
284 | /** | ||
285 | * Should we check that 'self' matches what the service thinks? | ||
286 | * (if GNUNET_NO, then 'self' is all zeros!). | ||
287 | */ | ||
288 | int check_self; | ||
289 | }; | ||
290 | |||
291 | |||
292 | /** | ||
293 | * Schedule the task to send one message, either from the control | ||
294 | * list or the peer message queues to the service. | ||
295 | * | ||
296 | * @param h transport service to schedule a transmission for | ||
297 | */ | ||
298 | static void | ||
299 | schedule_transmission (struct GNUNET_TRANSPORT_Handle *h); | ||
300 | |||
301 | |||
302 | /** | ||
303 | * Function that will schedule the job that will try | ||
304 | * to connect us again to the client. | ||
305 | * | ||
306 | * @param h transport service to reconnect | ||
307 | */ | ||
308 | static void | ||
309 | disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_Handle *h); | ||
310 | |||
311 | |||
312 | /** | ||
313 | * Get the neighbour list entry for the given peer | ||
314 | * | ||
315 | * @param h our context | ||
316 | * @param peer peer to look up | ||
317 | * @return NULL if no such peer entry exists | ||
318 | */ | ||
319 | static struct Neighbour * | ||
320 | neighbour_find (struct GNUNET_TRANSPORT_Handle *h, | ||
321 | const struct GNUNET_PeerIdentity *peer) | ||
322 | { | ||
323 | return GNUNET_CONTAINER_multihashmap_get(h->neighbours, &peer->hashPubKey); | ||
324 | } | ||
325 | |||
326 | |||
327 | /** | ||
328 | * Add neighbour to our list | ||
329 | * | ||
330 | * @return NULL if this API is currently disconnecting from the service | ||
331 | */ | ||
332 | static struct Neighbour * | ||
333 | neighbour_add (struct GNUNET_TRANSPORT_Handle *h, | ||
334 | const struct GNUNET_PeerIdentity *pid) | ||
335 | { | ||
336 | struct Neighbour *n; | ||
337 | |||
338 | #if DEBUG_TRANSPORT | ||
339 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
340 | "Creating entry for neighbour `%4s'.\n", | ||
341 | GNUNET_i2s (pid)); | ||
342 | #endif | ||
343 | n = GNUNET_malloc (sizeof (struct Neighbour)); | ||
344 | n->id = *pid; | ||
345 | n->h = h; | ||
346 | n->is_ready = GNUNET_YES; | ||
347 | GNUNET_BANDWIDTH_tracker_init (&n->out_tracker, | ||
348 | GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, | ||
349 | MAX_BANDWIDTH_CARRY_S); | ||
350 | GNUNET_assert (GNUNET_OK == | ||
351 | GNUNET_CONTAINER_multihashmap_put (h->neighbours, | ||
352 | &pid->hashPubKey, | ||
353 | n, | ||
354 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
355 | return n; | ||
356 | } | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Iterator over hash map entries, for deleting state of a neighbour. | ||
361 | * | ||
362 | * @param cls the 'struct GNUNET_TRANSPORT_Handle*' | ||
363 | * @param key peer identity | ||
364 | * @param value value in the hash map, the neighbour entry to delete | ||
365 | * @return GNUNET_YES if we should continue to | ||
366 | * iterate, | ||
367 | * GNUNET_NO if not. | ||
368 | */ | ||
369 | static int | ||
370 | neighbour_delete (void *cls, | ||
371 | const GNUNET_HashCode * key, | ||
372 | void *value) | ||
373 | { | ||
374 | struct GNUNET_TRANSPORT_Handle *handle = cls; | ||
375 | struct Neighbour *n = value; | ||
376 | |||
377 | if (NULL != handle->nd_cb) | ||
378 | handle->nd_cb (handle->cls, | ||
379 | &n->id); | ||
380 | GNUNET_assert (NULL == n->th); | ||
381 | GNUNET_assert (NULL == n->hn); | ||
382 | GNUNET_assert (GNUNET_YES == | ||
383 | GNUNET_CONTAINER_multihashmap_remove (handle->neighbours, | ||
384 | key, | ||
385 | n)); | ||
386 | GNUNET_free (n); | ||
387 | return GNUNET_YES; | ||
388 | } | ||
389 | |||
390 | |||
391 | /** | ||
392 | * Function we use for handling incoming messages. | ||
393 | * | ||
394 | * @param cls closure (struct GNUNET_TRANSPORT_Handle *) | ||
395 | * @param msg message received, NULL on timeout or fatal error | ||
396 | */ | ||
397 | static void | ||
398 | demultiplexer (void *cls, | ||
399 | const struct GNUNET_MessageHeader *msg) | ||
400 | { | ||
401 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
402 | const struct DisconnectInfoMessage *dim; | ||
403 | const struct ConnectInfoMessage *cim; | ||
404 | const struct InboundMessage *im; | ||
405 | const struct GNUNET_MessageHeader *imm; | ||
406 | const struct SendOkMessage *okm; | ||
407 | struct HelloWaitList *hwl; | ||
408 | struct HelloWaitList *next_hwl; | ||
409 | struct Neighbour *n; | ||
410 | struct GNUNET_PeerIdentity me; | ||
411 | uint16_t size; | ||
412 | uint32_t ats_count; | ||
413 | |||
414 | GNUNET_assert (h->client != NULL); | ||
415 | if (msg == NULL) | ||
416 | { | ||
417 | #if DEBUG_TRANSPORT | ||
418 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
419 | "Error receiving from transport service, disconnecting temporarily.\n"); | ||
420 | #endif | ||
421 | disconnect_and_schedule_reconnect (h); | ||
422 | return; | ||
423 | } | ||
424 | GNUNET_CLIENT_receive (h->client, | ||
425 | &demultiplexer, h, | ||
426 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
427 | size = ntohs (msg->size); | ||
428 | switch (ntohs (msg->type)) | ||
429 | { | ||
430 | case GNUNET_MESSAGE_TYPE_HELLO: | ||
431 | if (GNUNET_OK != | ||
432 | GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) msg, | ||
433 | &me)) | ||
434 | { | ||
435 | GNUNET_break (0); | ||
436 | break; | ||
437 | } | ||
438 | #if DEBUG_TRANSPORT | ||
439 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
440 | "Receiving (my own) `%s' message, I am `%4s'.\n", | ||
441 | "HELLO", GNUNET_i2s (&me)); | ||
442 | #endif | ||
443 | GNUNET_free_non_null (h->my_hello); | ||
444 | h->my_hello = NULL; | ||
445 | if (size < sizeof (struct GNUNET_MessageHeader)) | ||
446 | { | ||
447 | GNUNET_break (0); | ||
448 | break; | ||
449 | } | ||
450 | h->my_hello = GNUNET_malloc (size); | ||
451 | memcpy (h->my_hello, msg, size); | ||
452 | hwl = h->hwl_head; | ||
453 | while (NULL != hwl) | ||
454 | { | ||
455 | next_hwl = hwl->next; | ||
456 | hwl->rec (hwl->rec_cls, | ||
457 | (const struct GNUNET_MessageHeader *) h->my_hello); | ||
458 | hwl = next_hwl; | ||
459 | } | ||
460 | break; | ||
461 | case GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT: | ||
462 | if (size < sizeof (struct ConnectInfoMessage)) | ||
463 | { | ||
464 | GNUNET_break (0); | ||
465 | break; | ||
466 | } | ||
467 | cim = (const struct ConnectInfoMessage *) msg; | ||
468 | ats_count = ntohl (cim->ats_count); | ||
469 | if (size != sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)) | ||
470 | { | ||
471 | GNUNET_break (0); | ||
472 | break; | ||
473 | } | ||
474 | #if DEBUG_TRANSPORT | ||
475 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
476 | "Receiving `%s' message for `%4s'.\n", | ||
477 | "CONNECT", GNUNET_i2s (&cim->id)); | ||
478 | #endif | ||
479 | n = neighbour_find (h, &cim->id); | ||
480 | if (n != NULL) | ||
481 | { | ||
482 | GNUNET_break (0); | ||
483 | break; | ||
484 | } | ||
485 | n = neighbour_add (h, &cim->id); | ||
486 | if (h->nc_cb != NULL) | ||
487 | h->nc_cb (h->cls, &n->id, | ||
488 | &cim->ats, ats_count); | ||
489 | break; | ||
490 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT: | ||
491 | if (size != sizeof (struct DisconnectInfoMessage)) | ||
492 | { | ||
493 | GNUNET_break (0); | ||
494 | break; | ||
495 | } | ||
496 | dim = (const struct DisconnectInfoMessage *) msg; | ||
497 | GNUNET_break (ntohl (dim->reserved) == 0); | ||
498 | #if DEBUG_TRANSPORT_DISCONNECT | ||
499 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
500 | "Receiving `%s' message for `%4s'.\n", | ||
501 | "DISCONNECT", | ||
502 | GNUNET_i2s (&dim->peer)); | ||
503 | #endif | ||
504 | n = neighbour_find (h, &dim->peer); | ||
505 | if (n == NULL) | ||
506 | { | ||
507 | GNUNET_break (0); | ||
508 | break; | ||
509 | } | ||
510 | neighbour_delete (h, &dim->peer.hashPubKey, n); | ||
511 | break; | ||
512 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK: | ||
513 | if (size != sizeof (struct SendOkMessage)) | ||
514 | { | ||
515 | GNUNET_break (0); | ||
516 | break; | ||
517 | } | ||
518 | okm = (const struct SendOkMessage *) msg; | ||
519 | #if DEBUG_TRANSPORT | ||
520 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
521 | "Receiving `%s' message, transmission %s.\n", "SEND_OK", | ||
522 | ntohl (okm->success) == GNUNET_OK ? "succeeded" : "failed"); | ||
523 | #endif | ||
524 | n = neighbour_find (h, &okm->peer); | ||
525 | if (n == NULL) | ||
526 | break; | ||
527 | GNUNET_break (GNUNET_NO == n->is_ready); | ||
528 | n->is_ready = GNUNET_YES; | ||
529 | if ( (n->th != NULL) && | ||
530 | (n->hn == NULL) ) | ||
531 | { | ||
532 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->th->timeout_task); | ||
533 | GNUNET_SCHEDULER_cancel (n->th->timeout_task); | ||
534 | n->th->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
535 | /* we've been waiting for this (congestion, not quota, | ||
536 | caused delayed transmission) */ | ||
537 | n->hn = GNUNET_CONTAINER_heap_insert (h->ready_heap, | ||
538 | n, 0); | ||
539 | schedule_transmission (h); | ||
540 | } | ||
541 | break; | ||
542 | case GNUNET_MESSAGE_TYPE_TRANSPORT_RECV: | ||
543 | #if DEBUG_TRANSPORT | ||
544 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
545 | "Receiving `%s' message.\n", "RECV"); | ||
546 | #endif | ||
547 | if (size < | ||
548 | sizeof (struct InboundMessage) + | ||
549 | sizeof (struct GNUNET_MessageHeader)) | ||
550 | { | ||
551 | GNUNET_break (0); | ||
552 | break; | ||
553 | } | ||
554 | im = (const struct InboundMessage *) msg; | ||
555 | GNUNET_break (0 == ntohl (im->reserved)); | ||
556 | ats_count = ntohl(im->ats_count); | ||
557 | imm = (const struct GNUNET_MessageHeader *) &((&(im->ats))[ats_count+1]); | ||
558 | |||
559 | if (ntohs (imm->size) + sizeof (struct InboundMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) != size) | ||
560 | { | ||
561 | GNUNET_break (0); | ||
562 | break; | ||
563 | } | ||
564 | #if DEBUG_TRANSPORT | ||
565 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
566 | "Received message of type %u from `%4s'.\n", | ||
567 | ntohs (imm->type), GNUNET_i2s (&im->peer)); | ||
568 | #endif | ||
569 | n = neighbour_find (h, &im->peer); | ||
570 | if (n == NULL) | ||
571 | { | ||
572 | GNUNET_break (0); | ||
573 | break; | ||
574 | } | ||
575 | if (h->rec != NULL) | ||
576 | h->rec (h->cls, &im->peer, imm, | ||
577 | &im->ats, ats_count); | ||
578 | break; | ||
579 | default: | ||
580 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
581 | _ | ||
582 | ("Received unexpected message of type %u in %s:%u\n"), | ||
583 | ntohs (msg->type), __FILE__, __LINE__); | ||
584 | GNUNET_break (0); | ||
585 | break; | ||
586 | } | ||
587 | } | ||
588 | |||
589 | |||
590 | /** | ||
591 | * A transmission request could not be satisfied because of | ||
592 | * network congestion. Notify the initiator and clean up. | ||
593 | * | ||
594 | * @param cls the 'struct GNUNET_TRANSPORT_TransmitHandle' | ||
595 | * @param tc scheduler context | ||
596 | */ | ||
597 | static void | ||
598 | timeout_request_due_to_congestion (void *cls, | ||
599 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
600 | { | ||
601 | struct GNUNET_TRANSPORT_TransmitHandle *th = cls; | ||
602 | struct Neighbour *n = th->neighbour; | ||
603 | |||
604 | n->th->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
605 | GNUNET_assert (th == n->th); | ||
606 | GNUNET_assert (NULL == n->hn); | ||
607 | n->th = NULL; | ||
608 | th->notify (th->notify_cls, 0, NULL); | ||
609 | GNUNET_free (th); | ||
610 | } | ||
611 | |||
612 | |||
613 | /** | ||
614 | * Transmit message(s) to service. | ||
615 | * | ||
616 | * @param cls handle to transport | ||
617 | * @param size number of bytes available in buf | ||
618 | * @param buf where to copy the message | ||
619 | * @return number of bytes copied to buf | ||
620 | */ | ||
621 | static size_t | ||
622 | transport_notify_ready (void *cls, size_t size, void *buf) | ||
623 | { | ||
624 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
625 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
626 | struct Neighbour *n; | ||
627 | char *cbuf; | ||
628 | struct OutboundMessage obm; | ||
629 | size_t ret; | ||
630 | size_t nret; | ||
631 | size_t mret; | ||
632 | |||
633 | GNUNET_assert (NULL != h->client); | ||
634 | h->cth = NULL; | ||
635 | if (NULL == buf) | ||
636 | { | ||
637 | /* transmission failed */ | ||
638 | disconnect_and_schedule_reconnect (h); | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | cbuf = buf; | ||
643 | ret = 0; | ||
644 | /* first send control messages */ | ||
645 | while ( (NULL != (th = h->control_head)) && | ||
646 | (th->notify_size <= size) ) | ||
647 | { | ||
648 | GNUNET_CONTAINER_DLL_remove (h->control_head, | ||
649 | h->control_tail, | ||
650 | th); | ||
651 | nret = th->notify (th->notify_cls, size, &cbuf[ret]); | ||
652 | #if DEBUG_TRANSPORT | ||
653 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
654 | "Added %u bytes of control message at %u\n", | ||
655 | nret, | ||
656 | ret); | ||
657 | #endif | ||
658 | GNUNET_free (th); | ||
659 | ret += nret; | ||
660 | size -= nret; | ||
661 | } | ||
662 | |||
663 | /* then, if possible and no control messages pending, send data messages */ | ||
664 | while ( (NULL == h->control_head) && | ||
665 | (NULL != (n = GNUNET_CONTAINER_heap_peek (h->ready_heap))) ) | ||
666 | { | ||
667 | if (GNUNET_YES != n->is_ready) | ||
668 | { | ||
669 | /* peer not ready, wait for notification! */ | ||
670 | GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap)); | ||
671 | n->hn = NULL; | ||
672 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == n->th->timeout_task); | ||
673 | n->th->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (n->th->timeout), | ||
674 | &timeout_request_due_to_congestion, | ||
675 | n->th); | ||
676 | continue; | ||
677 | } | ||
678 | th = n->th; | ||
679 | if (th->notify_size + sizeof (struct OutboundMessage) > size) | ||
680 | break; /* does not fit */ | ||
681 | if (GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, th->notify_size).rel_value > 0) | ||
682 | break; /* too early */ | ||
683 | GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap)); | ||
684 | n->hn = NULL; | ||
685 | n->th = NULL; | ||
686 | n->is_ready = GNUNET_NO; | ||
687 | GNUNET_assert (size >= sizeof (struct OutboundMessage)); | ||
688 | mret = th->notify (th->notify_cls, | ||
689 | size - sizeof (struct OutboundMessage), | ||
690 | &cbuf[ret + sizeof (struct OutboundMessage)]); | ||
691 | GNUNET_assert (mret <= size - sizeof (struct OutboundMessage)); | ||
692 | if (mret != 0) | ||
693 | { | ||
694 | GNUNET_assert (mret + sizeof (struct OutboundMessage) < GNUNET_SERVER_MAX_MESSAGE_SIZE); | ||
695 | obm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND); | ||
696 | obm.header.size = htons (mret + sizeof (struct OutboundMessage)); | ||
697 | obm.priority = htonl (th->priority); | ||
698 | obm.timeout = GNUNET_TIME_relative_hton (GNUNET_TIME_absolute_get_remaining (th->timeout)); | ||
699 | obm.peer = n->id; | ||
700 | memcpy (&cbuf[ret], &obm, sizeof (struct OutboundMessage)); | ||
701 | ret += (mret + sizeof (struct OutboundMessage)); | ||
702 | size -= (mret + sizeof (struct OutboundMessage)); | ||
703 | GNUNET_BANDWIDTH_tracker_consume (&n->out_tracker, mret); | ||
704 | } | ||
705 | GNUNET_free (th); | ||
706 | } | ||
707 | /* if there are more pending messages, try to schedule those */ | ||
708 | schedule_transmission (h); | ||
709 | #if DEBUG_TRANSPORT | ||
710 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
711 | "Transmitting %u bytes to transport service\n", ret); | ||
712 | #endif | ||
713 | return ret; | ||
714 | } | ||
715 | |||
716 | |||
717 | /** | ||
718 | * Schedule the task to send one message, either from the control | ||
719 | * list or the peer message queues to the service. | ||
720 | * | ||
721 | * @param cls transport service to schedule a transmission for | ||
722 | * @param tc scheduler context | ||
723 | */ | ||
724 | static void | ||
725 | schedule_transmission_task (void *cls, | ||
726 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
727 | { | ||
728 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
729 | size_t size; | ||
730 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
731 | struct Neighbour *n; | ||
732 | |||
733 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; | ||
734 | GNUNET_assert (NULL != h->client); | ||
735 | /* destroy all requests that have timed out */ | ||
736 | while ( (NULL != (n = GNUNET_CONTAINER_heap_peek (h->ready_heap))) && | ||
737 | (GNUNET_TIME_absolute_get_remaining (n->th->timeout).rel_value == 0) ) | ||
738 | { | ||
739 | /* notify client that the request could not be satisfied within | ||
740 | the given time constraints */ | ||
741 | th = n->th; | ||
742 | n->th = NULL; | ||
743 | GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap)); | ||
744 | n->hn = NULL; | ||
745 | #if DEBUG_TRANSPORT | ||
746 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
747 | "Signalling timeout for transmission to peer %s due to congestion\n", | ||
748 | GNUNET_i2s (&n->id)); | ||
749 | #endif | ||
750 | GNUNET_assert (0 == | ||
751 | th->notify (th->notify_cls, 0, NULL)); | ||
752 | GNUNET_free (th); | ||
753 | } | ||
754 | if (NULL != h->cth) | ||
755 | return; | ||
756 | if (NULL != h->control_head) | ||
757 | { | ||
758 | size = h->control_head->notify_size; | ||
759 | } | ||
760 | else | ||
761 | { | ||
762 | n = GNUNET_CONTAINER_heap_peek (h->ready_heap); | ||
763 | if (NULL == n) | ||
764 | return; /* no pending messages */ | ||
765 | size = n->th->notify_size + sizeof (struct OutboundMessage); | ||
766 | } | ||
767 | #if DEBUG_TRANSPORT | ||
768 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
769 | "Calling notify_transmit_ready\n"); | ||
770 | #endif | ||
771 | h->cth = | ||
772 | GNUNET_CLIENT_notify_transmit_ready (h->client, | ||
773 | size, | ||
774 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
775 | GNUNET_NO, | ||
776 | &transport_notify_ready, | ||
777 | h); | ||
778 | GNUNET_assert (NULL != h->cth); | ||
779 | } | ||
780 | |||
781 | |||
782 | /** | ||
783 | * Schedule the task to send one message, either from the control | ||
784 | * list or the peer message queues to the service. | ||
785 | * | ||
786 | * @param h transport service to schedule a transmission for | ||
787 | */ | ||
788 | static void | ||
789 | schedule_transmission (struct GNUNET_TRANSPORT_Handle *h) | ||
790 | { | ||
791 | struct GNUNET_TIME_Relative delay; | ||
792 | struct Neighbour *n; | ||
793 | |||
794 | GNUNET_assert (NULL != h->client); | ||
795 | if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) | ||
796 | { | ||
797 | GNUNET_SCHEDULER_cancel (h->quota_task); | ||
798 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; | ||
799 | } | ||
800 | if (NULL != h->control_head) | ||
801 | delay = GNUNET_TIME_UNIT_ZERO; | ||
802 | else if (NULL != (n = GNUNET_CONTAINER_heap_peek (h->ready_heap))) | ||
803 | delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, n->th->notify_size); | ||
804 | else | ||
805 | return; /* no work to be done */ | ||
806 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
807 | "Scheduling next transmission to service in %llu ms\n", | ||
808 | (unsigned long long) delay.rel_value); | ||
809 | h->quota_task = GNUNET_SCHEDULER_add_delayed (delay, | ||
810 | &schedule_transmission_task, | ||
811 | h); | ||
812 | } | ||
813 | |||
814 | |||
815 | /** | ||
816 | * Queue control request for transmission to the transport | ||
817 | * service. | ||
818 | * | ||
819 | * @param h handle to the transport service | ||
820 | * @param size number of bytes to be transmitted | ||
821 | * @param notify function to call to get the content | ||
822 | * @param notify_cls closure for notify | ||
823 | */ | ||
824 | static void | ||
825 | schedule_control_transmit (struct GNUNET_TRANSPORT_Handle *h, | ||
826 | size_t size, | ||
827 | GNUNET_CONNECTION_TransmitReadyNotify notify, | ||
828 | void *notify_cls) | ||
829 | { | ||
830 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
831 | |||
832 | #if DEBUG_TRANSPORT | ||
833 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
834 | "Control transmit of %u bytes requested\n", | ||
835 | size); | ||
836 | #endif | ||
837 | th = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_TransmitHandle)); | ||
838 | th->notify = notify; | ||
839 | th->notify_cls = notify_cls; | ||
840 | th->notify_size = size; | ||
841 | GNUNET_CONTAINER_DLL_insert_tail (h->control_head, | ||
842 | h->control_tail, | ||
843 | th); | ||
844 | schedule_transmission (h); | ||
845 | } | ||
846 | |||
847 | |||
848 | /** | ||
849 | * Transmit START message to service. | ||
850 | * | ||
851 | * @param cls unused | ||
852 | * @param size number of bytes available in buf | ||
853 | * @param buf where to copy the message | ||
854 | * @return number of bytes copied to buf | ||
855 | */ | ||
856 | static size_t | ||
857 | send_start (void *cls, size_t size, void *buf) | ||
858 | { | ||
859 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
860 | struct StartMessage s; | ||
861 | |||
862 | if (buf == NULL) | ||
863 | { | ||
864 | /* Can only be shutdown, just give up */ | ||
865 | #if DEBUG_TRANSPORT | ||
866 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
867 | "Shutdown while trying to transmit `%s' request.\n", | ||
868 | "START"); | ||
869 | #endif | ||
870 | return 0; | ||
871 | } | ||
872 | #if DEBUG_TRANSPORT | ||
873 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
874 | "Transmitting `%s' request.\n", "START"); | ||
875 | #endif | ||
876 | GNUNET_assert (size >= sizeof (struct StartMessage)); | ||
877 | s.header.size = htons (sizeof (struct StartMessage)); | ||
878 | s.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_START); | ||
879 | s.do_check = htonl (h->check_self); | ||
880 | s.self = h->self; | ||
881 | memcpy (buf, &s, sizeof (struct StartMessage)); | ||
882 | GNUNET_CLIENT_receive (h->client, | ||
883 | &demultiplexer, h, GNUNET_TIME_UNIT_FOREVER_REL); | ||
884 | return sizeof (struct StartMessage); | ||
885 | } | ||
886 | |||
887 | |||
888 | /** | ||
889 | * Try again to connect to transport service. | ||
890 | * | ||
891 | * @param cls the handle to the transport service | ||
892 | * @param tc scheduler context | ||
893 | */ | ||
894 | static void | ||
895 | reconnect (void *cls, | ||
896 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
897 | { | ||
898 | struct GNUNET_TRANSPORT_Handle *h = cls; | ||
899 | |||
900 | h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
901 | if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
902 | { | ||
903 | /* shutdown, just give up */ | ||
904 | return; | ||
905 | } | ||
906 | #if DEBUG_TRANSPORT | ||
907 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
908 | "Connecting to transport service.\n"); | ||
909 | #endif | ||
910 | GNUNET_assert (h->client == NULL); | ||
911 | GNUNET_assert (h->control_head == NULL); | ||
912 | GNUNET_assert (h->control_tail == NULL); | ||
913 | h->client = GNUNET_CLIENT_connect ("transport", h->cfg); | ||
914 | GNUNET_assert (h->client != NULL); | ||
915 | schedule_control_transmit (h, | ||
916 | sizeof (struct StartMessage), | ||
917 | &send_start, h); | ||
918 | } | ||
919 | |||
920 | |||
921 | /** | ||
922 | * Function that will schedule the job that will try | ||
923 | * to connect us again to the client. | ||
924 | * | ||
925 | * @param h transport service to reconnect | ||
926 | */ | ||
927 | static void | ||
928 | disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_Handle *h) | ||
929 | { | ||
930 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
931 | |||
932 | GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); | ||
933 | /* Forget about all neighbours that we used to be connected to */ | ||
934 | GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, | ||
935 | &neighbour_delete, | ||
936 | h); | ||
937 | if (NULL != h->cth) | ||
938 | { | ||
939 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); | ||
940 | h->cth = NULL; | ||
941 | } | ||
942 | if (NULL != h->client) | ||
943 | { | ||
944 | GNUNET_CLIENT_disconnect (h->client, GNUNET_YES); | ||
945 | h->client = NULL; | ||
946 | } | ||
947 | if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) | ||
948 | { | ||
949 | GNUNET_SCHEDULER_cancel (h->quota_task); | ||
950 | h->quota_task = GNUNET_SCHEDULER_NO_TASK; | ||
951 | } | ||
952 | while ( (NULL != (th = h->control_head))) | ||
953 | { | ||
954 | GNUNET_CONTAINER_DLL_remove (h->control_head, | ||
955 | h->control_tail, | ||
956 | th); | ||
957 | th->notify (th->notify_cls, 0, NULL); | ||
958 | GNUNET_free (th); | ||
959 | } | ||
960 | #if DEBUG_TRANSPORT | ||
961 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
962 | "Scheduling task to reconnect to transport service in %llu ms.\n", | ||
963 | h->reconnect_delay.rel_value); | ||
964 | #endif | ||
965 | h->reconnect_task | ||
966 | = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, | ||
967 | &reconnect, h); | ||
968 | if (h->reconnect_delay.rel_value == 0) | ||
969 | { | ||
970 | h->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS; | ||
971 | } | ||
972 | else | ||
973 | { | ||
974 | h->reconnect_delay = GNUNET_TIME_relative_multiply (h->reconnect_delay, 2); | ||
975 | h->reconnect_delay = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, | ||
976 | h->reconnect_delay); | ||
977 | } | ||
978 | } | ||
979 | |||
980 | |||
981 | /** | ||
982 | * Closure for 'send_set_quota'. | ||
983 | */ | ||
984 | struct SetQuotaContext | ||
985 | { | ||
986 | |||
987 | /** | ||
988 | * Identity of the peer impacted by the quota change. | ||
989 | */ | ||
990 | struct GNUNET_PeerIdentity target; | ||
991 | |||
992 | /** | ||
993 | * Quota to transmit. | ||
994 | */ | ||
995 | struct GNUNET_BANDWIDTH_Value32NBO quota_in; | ||
996 | }; | ||
997 | |||
998 | |||
999 | /** | ||
1000 | * Send SET_QUOTA message to the service. | ||
1001 | * | ||
1002 | * @param cls the 'struct SetQuotaContext' | ||
1003 | * @param size number of bytes available in buf | ||
1004 | * @param buf where to copy the message | ||
1005 | * @return number of bytes copied to buf | ||
1006 | */ | ||
1007 | static size_t | ||
1008 | send_set_quota (void *cls, size_t size, void *buf) | ||
1009 | { | ||
1010 | struct SetQuotaContext *sqc = cls; | ||
1011 | struct QuotaSetMessage msg; | ||
1012 | |||
1013 | if (buf == NULL) | ||
1014 | { | ||
1015 | GNUNET_free (sqc); | ||
1016 | return 0; | ||
1017 | } | ||
1018 | #if DEBUG_TRANSPORT | ||
1019 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1020 | "Transmitting `%s' request with respect to `%4s'.\n", | ||
1021 | "SET_QUOTA", | ||
1022 | GNUNET_i2s (&sqc->target)); | ||
1023 | #endif | ||
1024 | GNUNET_assert (size >= sizeof (struct QuotaSetMessage)); | ||
1025 | msg.header.size = htons (sizeof (struct QuotaSetMessage)); | ||
1026 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA); | ||
1027 | msg.quota = sqc->quota_in; | ||
1028 | msg.peer = sqc->target; | ||
1029 | memcpy (buf, &msg, sizeof (msg)); | ||
1030 | GNUNET_free (sqc); | ||
1031 | return sizeof (struct QuotaSetMessage); | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | /** | ||
1036 | * Set the share of incoming bandwidth for the given | ||
1037 | * peer to the specified amount. | ||
1038 | * | ||
1039 | * @param handle connection to transport service | ||
1040 | * @param target who's bandwidth quota is being changed | ||
1041 | * @param quota_in incoming bandwidth quota in bytes per ms | ||
1042 | * @param quota_out outgoing bandwidth quota in bytes per ms | ||
1043 | */ | ||
1044 | void | ||
1045 | GNUNET_TRANSPORT_set_quota (struct GNUNET_TRANSPORT_Handle *handle, | ||
1046 | const struct GNUNET_PeerIdentity *target, | ||
1047 | struct GNUNET_BANDWIDTH_Value32NBO quota_in, | ||
1048 | struct GNUNET_BANDWIDTH_Value32NBO quota_out) | ||
1049 | { | ||
1050 | struct Neighbour *n; | ||
1051 | struct SetQuotaContext *sqc; | ||
1052 | |||
1053 | n = neighbour_find (handle, target); | ||
1054 | if (NULL == n) | ||
1055 | { | ||
1056 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1057 | "Quota changed to %u for peer `%s', but I have no such neighbour!\n", | ||
1058 | (unsigned int) ntohl (quota_out.value__), | ||
1059 | GNUNET_i2s (target)); | ||
1060 | return; | ||
1061 | } | ||
1062 | GNUNET_assert (NULL != handle->client); | ||
1063 | #if DEBUG_TRANSPORT | ||
1064 | if (ntohl (quota_out.value__) != n->out_tracker.available_bytes_per_s__) | ||
1065 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1066 | "Quota changed from %u to %u for peer `%s'\n", | ||
1067 | (unsigned int) n->out_tracker.available_bytes_per_s__, | ||
1068 | (unsigned int) ntohl (quota_out.value__), | ||
1069 | GNUNET_i2s (target)); | ||
1070 | else | ||
1071 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1072 | "Quota remains at %u for peer `%s'\n", | ||
1073 | (unsigned int) n->out_tracker.available_bytes_per_s__, | ||
1074 | GNUNET_i2s (target)); | ||
1075 | #endif | ||
1076 | GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker, | ||
1077 | quota_out); | ||
1078 | sqc = GNUNET_malloc (sizeof (struct SetQuotaContext)); | ||
1079 | sqc->target = *target; | ||
1080 | sqc->quota_in = quota_in; | ||
1081 | schedule_control_transmit (handle, | ||
1082 | sizeof (struct QuotaSetMessage), | ||
1083 | &send_set_quota, sqc); | ||
1084 | } | ||
1085 | |||
1086 | |||
1087 | /** | ||
1088 | * Send REQUEST_CONNECT message to the service. | ||
1089 | * | ||
1090 | * @param cls the 'struct GNUNET_PeerIdentity' | ||
1091 | * @param size number of bytes available in buf | ||
1092 | * @param buf where to copy the message | ||
1093 | * @return number of bytes copied to buf | ||
1094 | */ | ||
1095 | static size_t | ||
1096 | send_try_connect (void *cls, size_t size, void *buf) | ||
1097 | { | ||
1098 | struct GNUNET_PeerIdentity *pid = cls; | ||
1099 | struct TransportRequestConnectMessage msg; | ||
1100 | |||
1101 | if (buf == NULL) | ||
1102 | { | ||
1103 | GNUNET_free (pid); | ||
1104 | return 0; | ||
1105 | } | ||
1106 | #if DEBUG_TRANSPORT | ||
1107 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1108 | "Transmitting `%s' request with respect to `%4s'.\n", | ||
1109 | "REQUEST_CONNECT", | ||
1110 | GNUNET_i2s (pid)); | ||
1111 | #endif | ||
1112 | GNUNET_assert (size >= sizeof (struct TransportRequestConnectMessage)); | ||
1113 | msg.header.size = htons (sizeof (struct TransportRequestConnectMessage)); | ||
1114 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT); | ||
1115 | msg.reserved = htonl (0); | ||
1116 | msg.peer = *pid; | ||
1117 | memcpy (buf, &msg, sizeof (msg)); | ||
1118 | GNUNET_free (pid); | ||
1119 | return sizeof (struct TransportRequestConnectMessage); | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | /** | ||
1124 | * Ask the transport service to establish a connection to | ||
1125 | * the given peer. | ||
1126 | * | ||
1127 | * @param handle connection to transport service | ||
1128 | * @param target who we should try to connect to | ||
1129 | */ | ||
1130 | void | ||
1131 | GNUNET_TRANSPORT_try_connect (struct GNUNET_TRANSPORT_Handle *handle, | ||
1132 | const struct GNUNET_PeerIdentity *target) | ||
1133 | { | ||
1134 | struct GNUNET_PeerIdentity *pid; | ||
1135 | |||
1136 | if (NULL == handle->client) | ||
1137 | return; | ||
1138 | pid = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
1139 | *pid = *target; | ||
1140 | schedule_control_transmit (handle, | ||
1141 | sizeof (struct TransportRequestConnectMessage), | ||
1142 | &send_try_connect, pid); | ||
1143 | } | ||
1144 | |||
1145 | |||
1146 | /** | ||
1147 | * Send HELLO message to the service. | ||
1148 | * | ||
1149 | * @param cls the HELLO message to send | ||
1150 | * @param size number of bytes available in buf | ||
1151 | * @param buf where to copy the message | ||
1152 | * @return number of bytes copied to buf | ||
1153 | */ | ||
1154 | static size_t | ||
1155 | send_hello (void *cls, size_t size, void *buf) | ||
1156 | { | ||
1157 | struct GNUNET_MessageHeader *msg = cls; | ||
1158 | uint16_t ssize; | ||
1159 | |||
1160 | if (buf == NULL) | ||
1161 | { | ||
1162 | #if DEBUG_TRANSPORT_TIMEOUT | ||
1163 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1164 | "Timeout while trying to transmit `%s' request.\n", | ||
1165 | "HELLO"); | ||
1166 | #endif | ||
1167 | GNUNET_free (msg); | ||
1168 | return 0; | ||
1169 | } | ||
1170 | #if DEBUG_TRANSPORT | ||
1171 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1172 | "Transmitting `%s' request.\n", "HELLO"); | ||
1173 | #endif | ||
1174 | ssize = ntohs (msg->size); | ||
1175 | GNUNET_assert (size >= ssize); | ||
1176 | memcpy (buf, msg, ssize); | ||
1177 | GNUNET_free (msg); | ||
1178 | return ssize; | ||
1179 | } | ||
1180 | |||
1181 | |||
1182 | /** | ||
1183 | * Offer the transport service the HELLO of another peer. Note that | ||
1184 | * the transport service may just ignore this message if the HELLO is | ||
1185 | * malformed or useless due to our local configuration. | ||
1186 | * | ||
1187 | * @param handle connection to transport service | ||
1188 | * @param hello the hello message | ||
1189 | * @param cont continuation to call when HELLO has been sent | ||
1190 | * @param cls closure for continuation | ||
1191 | * | ||
1192 | */ | ||
1193 | void | ||
1194 | GNUNET_TRANSPORT_offer_hello (struct GNUNET_TRANSPORT_Handle *handle, | ||
1195 | const struct GNUNET_MessageHeader *hello, | ||
1196 | GNUNET_SCHEDULER_Task cont, | ||
1197 | void *cls) | ||
1198 | { | ||
1199 | uint16_t size; | ||
1200 | struct GNUNET_PeerIdentity peer; | ||
1201 | struct GNUNET_MessageHeader *msg; | ||
1202 | |||
1203 | if (NULL == handle->client) | ||
1204 | return; | ||
1205 | GNUNET_break (ntohs (hello->type) == GNUNET_MESSAGE_TYPE_HELLO); | ||
1206 | size = ntohs (hello->size); | ||
1207 | GNUNET_break (size >= sizeof (struct GNUNET_MessageHeader)); | ||
1208 | if (GNUNET_OK != GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message*) hello, | ||
1209 | &peer)) | ||
1210 | { | ||
1211 | GNUNET_break (0); | ||
1212 | return; | ||
1213 | } | ||
1214 | msg = GNUNET_malloc(size); | ||
1215 | memcpy (msg, hello, size); | ||
1216 | #if DEBUG_TRANSPORT | ||
1217 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1218 | "Offering `%s' message of `%4s' to transport for validation.\n", | ||
1219 | "HELLO", | ||
1220 | GNUNET_i2s (&peer)); | ||
1221 | #endif | ||
1222 | schedule_control_transmit (handle, | ||
1223 | size, | ||
1224 | &send_hello, msg); | ||
1225 | } | ||
1226 | |||
1227 | |||
1228 | /** | ||
1229 | * Obtain the HELLO message for this peer. | ||
1230 | * | ||
1231 | * @param handle connection to transport service | ||
1232 | * @param rec function to call with the HELLO, sender will be our peer | ||
1233 | * identity; message and sender will be NULL on timeout | ||
1234 | * (handshake with transport service pending/failed). | ||
1235 | * cost estimate will be 0. | ||
1236 | * @param rec_cls closure for rec | ||
1237 | */ | ||
1238 | void | ||
1239 | GNUNET_TRANSPORT_get_hello (struct GNUNET_TRANSPORT_Handle *handle, | ||
1240 | GNUNET_TRANSPORT_HelloUpdateCallback rec, | ||
1241 | void *rec_cls) | ||
1242 | { | ||
1243 | struct HelloWaitList *hwl; | ||
1244 | |||
1245 | hwl = GNUNET_malloc (sizeof (struct HelloWaitList)); | ||
1246 | hwl->rec = rec; | ||
1247 | hwl->rec_cls = rec_cls; | ||
1248 | GNUNET_CONTAINER_DLL_insert (handle->hwl_head, | ||
1249 | handle->hwl_tail, | ||
1250 | hwl); | ||
1251 | if (handle->my_hello == NULL) | ||
1252 | return; | ||
1253 | rec (rec_cls, (const struct GNUNET_MessageHeader *) handle->my_hello); | ||
1254 | } | ||
1255 | |||
1256 | |||
1257 | /** | ||
1258 | * Stop receiving updates about changes to our HELLO message. | ||
1259 | * | ||
1260 | * @param handle connection to transport service | ||
1261 | * @param rec function previously registered to be called with the HELLOs | ||
1262 | * @param rec_cls closure for rec | ||
1263 | */ | ||
1264 | void | ||
1265 | GNUNET_TRANSPORT_get_hello_cancel (struct GNUNET_TRANSPORT_Handle *handle, | ||
1266 | GNUNET_TRANSPORT_HelloUpdateCallback rec, | ||
1267 | void *rec_cls) | ||
1268 | { | ||
1269 | struct HelloWaitList *pos; | ||
1270 | |||
1271 | pos = handle->hwl_head; | ||
1272 | while (pos != NULL) | ||
1273 | { | ||
1274 | if ( (pos->rec == rec) && | ||
1275 | (pos->rec_cls == rec_cls) ) | ||
1276 | break; | ||
1277 | pos = pos->next; | ||
1278 | } | ||
1279 | GNUNET_break (pos != NULL); | ||
1280 | if (pos == NULL) | ||
1281 | return; | ||
1282 | GNUNET_CONTAINER_DLL_remove (handle->hwl_head, | ||
1283 | handle->hwl_tail, | ||
1284 | pos); | ||
1285 | GNUNET_free (pos); | ||
1286 | } | ||
1287 | |||
1288 | |||
1289 | /** | ||
1290 | * Connect to the transport service. Note that the connection may | ||
1291 | * complete (or fail) asynchronously. | ||
1292 | * | ||
1293 | * @param cfg configuration to use | ||
1294 | * @param self our own identity (API should check that it matches | ||
1295 | * the identity found by transport), or NULL (no check) | ||
1296 | * @param cls closure for the callbacks | ||
1297 | * @param rec receive function to call | ||
1298 | * @param nc function to call on connect events | ||
1299 | * @param nd function to call on disconnect events | ||
1300 | */ | ||
1301 | struct GNUNET_TRANSPORT_Handle * | ||
1302 | GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1303 | const struct GNUNET_PeerIdentity *self, | ||
1304 | void *cls, | ||
1305 | GNUNET_TRANSPORT_ReceiveCallback rec, | ||
1306 | GNUNET_TRANSPORT_NotifyConnect nc, | ||
1307 | GNUNET_TRANSPORT_NotifyDisconnect nd) | ||
1308 | { | ||
1309 | struct GNUNET_TRANSPORT_Handle *ret; | ||
1310 | |||
1311 | ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_Handle)); | ||
1312 | if (self != NULL) | ||
1313 | { | ||
1314 | ret->self = *self; | ||
1315 | ret->check_self = GNUNET_YES; | ||
1316 | } | ||
1317 | ret->cfg = cfg; | ||
1318 | ret->cls = cls; | ||
1319 | ret->rec = rec; | ||
1320 | ret->nc_cb = nc; | ||
1321 | ret->nd_cb = nd; | ||
1322 | ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; | ||
1323 | ret->neighbours = GNUNET_CONTAINER_multihashmap_create(STARTING_NEIGHBOURS_SIZE); | ||
1324 | ret->ready_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1325 | ret->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, ret); | ||
1326 | return ret; | ||
1327 | } | ||
1328 | |||
1329 | |||
1330 | /** | ||
1331 | * Disconnect from the transport service. | ||
1332 | * | ||
1333 | * @param handle handle to the service as returned from GNUNET_TRANSPORT_connect | ||
1334 | */ | ||
1335 | void | ||
1336 | GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) | ||
1337 | { | ||
1338 | #if DEBUG_TRANSPORT | ||
1339 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1340 | "Transport disconnect called!\n"); | ||
1341 | #endif | ||
1342 | /* this disconnects all neighbours... */ | ||
1343 | if (handle->reconnect_task == GNUNET_SCHEDULER_NO_TASK) | ||
1344 | disconnect_and_schedule_reconnect (handle); | ||
1345 | /* and now we stop trying to connect again... */ | ||
1346 | if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
1347 | { | ||
1348 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); | ||
1349 | handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
1350 | } | ||
1351 | GNUNET_CONTAINER_multihashmap_destroy (handle->neighbours); | ||
1352 | handle->neighbours = NULL; | ||
1353 | if (handle->quota_task != GNUNET_SCHEDULER_NO_TASK) | ||
1354 | { | ||
1355 | GNUNET_SCHEDULER_cancel (handle->quota_task); | ||
1356 | handle->quota_task = GNUNET_SCHEDULER_NO_TASK; | ||
1357 | } | ||
1358 | GNUNET_free_non_null (handle->my_hello); | ||
1359 | handle->my_hello = NULL; | ||
1360 | GNUNET_assert (handle->hwl_head == NULL); | ||
1361 | GNUNET_assert (handle->hwl_tail == NULL); | ||
1362 | GNUNET_CONTAINER_heap_destroy (handle->ready_heap); | ||
1363 | handle->ready_heap = NULL; | ||
1364 | GNUNET_free (handle); | ||
1365 | } | ||
1366 | |||
1367 | |||
1368 | /** | ||
1369 | * Check if we could queue a message of the given size for | ||
1370 | * transmission. The transport service will take both its | ||
1371 | * internal buffers and bandwidth limits imposed by the | ||
1372 | * other peer into consideration when answering this query. | ||
1373 | * | ||
1374 | * @param handle connection to transport service | ||
1375 | * @param target who should receive the message | ||
1376 | * @param size how big is the message we want to transmit? | ||
1377 | * @param priority how important is the message? | ||
1378 | * @param timeout after how long should we give up (and call | ||
1379 | * notify with buf NULL and size 0)? | ||
1380 | * @param notify function to call when we are ready to | ||
1381 | * send such a message | ||
1382 | * @param notify_cls closure for notify | ||
1383 | * @return NULL if someone else is already waiting to be notified | ||
1384 | * non-NULL if the notify callback was queued (can be used to cancel | ||
1385 | * using GNUNET_TRANSPORT_notify_transmit_ready_cancel) | ||
1386 | */ | ||
1387 | struct GNUNET_TRANSPORT_TransmitHandle * | ||
1388 | GNUNET_TRANSPORT_notify_transmit_ready (struct GNUNET_TRANSPORT_Handle *handle, | ||
1389 | const struct GNUNET_PeerIdentity *target, | ||
1390 | size_t size, | ||
1391 | uint32_t priority, | ||
1392 | struct GNUNET_TIME_Relative timeout, | ||
1393 | GNUNET_CONNECTION_TransmitReadyNotify notify, | ||
1394 | void *notify_cls) | ||
1395 | { | ||
1396 | struct Neighbour *n; | ||
1397 | struct GNUNET_TRANSPORT_TransmitHandle *th; | ||
1398 | struct GNUNET_TIME_Relative delay; | ||
1399 | |||
1400 | n = neighbour_find (handle, target); | ||
1401 | if (NULL == n) | ||
1402 | { | ||
1403 | /* use GNUNET_TRANSPORT_try_connect first, only use this function | ||
1404 | once a connection has been established */ | ||
1405 | GNUNET_assert (0); | ||
1406 | return NULL; | ||
1407 | } | ||
1408 | if (NULL != n->th) | ||
1409 | { | ||
1410 | /* attempt to send two messages at the same time to the same peer */ | ||
1411 | GNUNET_assert (0); | ||
1412 | return NULL; | ||
1413 | } | ||
1414 | GNUNET_assert (NULL == n->hn); | ||
1415 | th = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_TransmitHandle)); | ||
1416 | th->neighbour = n; | ||
1417 | th->notify = notify; | ||
1418 | th->notify_cls = notify_cls; | ||
1419 | th->timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1420 | th->notify_size = size; | ||
1421 | th->priority = priority; | ||
1422 | n->th = th; | ||
1423 | /* calculate when our transmission should be ready */ | ||
1424 | delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, size); | ||
1425 | if (delay.rel_value > timeout.rel_value) | ||
1426 | delay.rel_value = 0; /* notify immediately (with failure) */ | ||
1427 | #if DEBUG_TRANSPORT | ||
1428 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1429 | "Bandwidth tracker allows next transmission to peer %s in %llu ms\n", | ||
1430 | GNUNET_i2s (target), | ||
1431 | (unsigned long long) delay.rel_value); | ||
1432 | #endif | ||
1433 | n->hn = GNUNET_CONTAINER_heap_insert (handle->ready_heap, | ||
1434 | n, | ||
1435 | delay.rel_value); | ||
1436 | schedule_transmission (handle); | ||
1437 | return th; | ||
1438 | } | ||
1439 | |||
1440 | |||
1441 | /** | ||
1442 | * Cancel the specified transmission-ready notification. | ||
1443 | * | ||
1444 | * @param th handle returned from GNUNET_TRANSPORT_notify_transmit_ready | ||
1445 | */ | ||
1446 | void | ||
1447 | GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct GNUNET_TRANSPORT_TransmitHandle *th) | ||
1448 | { | ||
1449 | struct Neighbour *n; | ||
1450 | |||
1451 | GNUNET_assert (NULL == th->next); | ||
1452 | GNUNET_assert (NULL == th->prev); | ||
1453 | n = th->neighbour; | ||
1454 | GNUNET_assert (th == n->th); | ||
1455 | n->th = NULL; | ||
1456 | if (n->hn != NULL) | ||
1457 | { | ||
1458 | GNUNET_CONTAINER_heap_remove_node (n->hn); | ||
1459 | n->hn = NULL; | ||
1460 | } | ||
1461 | else | ||
1462 | { | ||
1463 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != th->timeout_task); | ||
1464 | GNUNET_SCHEDULER_cancel (th->timeout_task); | ||
1465 | th->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
1466 | } | ||
1467 | GNUNET_free (th); | ||
1468 | } | ||
1469 | |||
1470 | |||
1471 | /* end of transport_api.c */ | ||