aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport_api.c
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2010-12-02 11:59:56 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2010-12-02 11:59:56 +0000
commit614afe91d2c80b6fec4e6a090319c1a585944d75 (patch)
treeecd31dde4d596ec9c63fb5efde6243866c24bdc4 /src/transport/transport_api.c
parent318e4c9274fefbb546363633ea465f9f339cb828 (diff)
downloadgnunet-614afe91d2c80b6fec4e6a090319c1a585944d75.tar.gz
gnunet-614afe91d2c80b6fec4e6a090319c1a585944d75.zip
Working version of transport service with ATS integration
all tests passing on my machine
Diffstat (limited to 'src/transport/transport_api.c')
-rw-r--r--src/transport/transport_api.c488
1 files changed, 174 insertions, 314 deletions
diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c
index 4d7825701..643f8b0f4 100644
--- a/src/transport/transport_api.c
+++ b/src/transport/transport_api.c
@@ -60,11 +60,6 @@
60 */ 60 */
61#define STOP_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 61#define STOP_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
62 62
63/**
64 * How large to start with for the hashmap of neighbours.
65 */
66#define STARTING_NEIGHBOURS_SIZE 10
67
68 63
69/** 64/**
70 * What stage are we in for transmission processing? 65 * What stage are we in for transmission processing?
@@ -192,33 +187,18 @@ struct ControlMessage
192 187
193}; 188};
194 189
190
195/** 191/**
196 * Context for storing information about attempted next transmission. 192 * Entry in linked list of all of our current neighbours.
197 */ 193 */
198struct TryTransmitContext 194struct NeighbourList
199{ 195{
200 196
201 /** 197 /**
202 * Main transport handle. 198 * This is a linked list.
203 */
204 struct GNUNET_TRANSPORT_Handle *h;
205
206 /**
207 * Returned transmission handle.
208 */
209 struct GNUNET_TRANSPORT_TransmitHandle *ret;
210
211 /**
212 * Time to retry the send task.
213 */ 199 */
214 struct GNUNET_TIME_Relative retry_time; 200 struct NeighbourList *next;
215};
216 201
217/**
218 * Entry in hash table of all of our current neighbours.
219 */
220struct NeighbourList
221{
222 /** 202 /**
223 * Overall transport handle. 203 * Overall transport handle.
224 */ 204 */
@@ -255,11 +235,6 @@ struct NeighbourList
255 */ 235 */
256 int is_connected; 236 int is_connected;
257 237
258 /**
259 * Are we in the middle of disconnecting the peer already?
260 */
261 unsigned int in_disconnect;
262
263}; 238};
264 239
265 240
@@ -359,7 +334,7 @@ struct GNUNET_TRANSPORT_Handle
359 /** 334 /**
360 * Linked list of the current neighbours of this peer. 335 * Linked list of the current neighbours of this peer.
361 */ 336 */
362 struct GNUNET_CONTAINER_MultiHashMap *neighbours; 337 struct NeighbourList *neighbours;
363 338
364 /** 339 /**
365 * Peer identity as assumed by this process, or all zeros. 340 * Peer identity as assumed by this process, or all zeros.
@@ -396,6 +371,7 @@ struct GNUNET_TRANSPORT_Handle
396}; 371};
397 372
398 373
374// FIXME: replace with hash map!
399/** 375/**
400 * Get the neighbour list entry for the given peer 376 * Get the neighbour list entry for the given peer
401 * 377 *
@@ -407,7 +383,13 @@ static struct NeighbourList *
407neighbour_find (struct GNUNET_TRANSPORT_Handle *h, 383neighbour_find (struct GNUNET_TRANSPORT_Handle *h,
408 const struct GNUNET_PeerIdentity *peer) 384 const struct GNUNET_PeerIdentity *peer)
409{ 385{
410 return GNUNET_CONTAINER_multihashmap_get(h->neighbours, &peer->hashPubKey); 386 struct NeighbourList *pos;
387
388 pos = h->neighbours;
389 while ((pos != NULL) &&
390 (0 != memcmp (peer, &pos->id, sizeof (struct GNUNET_PeerIdentity))))
391 pos = pos->next;
392 return pos;
411} 393}
412 394
413 395
@@ -436,90 +418,6 @@ quota_transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
436 418
437 419
438/** 420/**
439 * Iterator over hash map entries, attempt to schedule
440 * a transmission to entries in the neighbour hashmap.
441 *
442 * @param cls closure a TryTransmitContext
443 * @param key current key code
444 * @param value value in the hash map, the neighbour entry to consider
445 * @return GNUNET_YES if we should continue to
446 * iterate,
447 * GNUNET_NO if not.
448 */
449static int
450try_schedule_transmission (void *cls,
451 const GNUNET_HashCode * key,
452 void *value)
453{
454 struct NeighbourList *n = value;
455 struct TryTransmitContext *try_transmit_ctx = cls;
456 struct GNUNET_TIME_Relative duration;
457 GNUNET_CONNECTION_TransmitReadyNotify notify;
458 struct GNUNET_TRANSPORT_TransmitHandle *th;
459 struct GNUNET_TIME_Absolute duration_abs;
460
461 if (n->transmit_stage != TS_QUEUED)
462 return GNUNET_YES; /* not eligible, keep iterating */
463 if (n->is_connected != GNUNET_YES)
464 return GNUNET_YES; /* keep iterating */
465
466 th = &n->transmit_handle;
467 GNUNET_break (n == th->neighbour);
468 /* check outgoing quota */
469 duration = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker,
470 th->notify_size - sizeof (struct OutboundMessage));
471 duration_abs = GNUNET_TIME_relative_to_absolute (duration);
472 if (th->timeout.abs_value < duration_abs.abs_value)
473 {
474 /* signal timeout! */
475#if DEBUG_TRANSPORT
476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
477 "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n",
478 duration.rel_value,
479 GNUNET_i2s (&n->id));
480#endif
481 if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK)
482 {
483 GNUNET_SCHEDULER_cancel (th->notify_delay_task);
484 th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
485 }
486 n->transmit_stage = TS_NEW;
487 if (NULL != (notify = th->notify))
488 {
489 th->notify = NULL;
490 GNUNET_assert (0 == notify (th->notify_cls, 0, NULL));
491 }
492 return GNUNET_YES; /* keep iterating */
493 }
494 if (duration.rel_value > 0)
495 {
496#if DEBUG_TRANSPORT
497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
498 "Need more bandwidth (%u b/s allowed, %u b needed), delaying delivery to `%4s' by %llu ms\n",
499 (unsigned int) n->out_tracker.available_bytes_per_s__,
500 (unsigned int) th->notify_size - sizeof (struct OutboundMessage),
501 GNUNET_i2s (&n->id),
502 (unsigned long long) duration.rel_value);
503#endif
504 try_transmit_ctx->retry_time = GNUNET_TIME_relative_min (try_transmit_ctx->retry_time,
505 duration);
506 return GNUNET_YES; /* keep iterating */
507 }
508#if DEBUG_TRANSPORT
509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
510 "Have %u bytes of bandwidth available for transmission to `%4s' right now\n",
511 th->notify_size - sizeof (struct OutboundMessage),
512 GNUNET_i2s (&n->id));
513#endif
514
515 if ( (try_transmit_ctx->ret == NULL) ||
516 (try_transmit_ctx->ret->priority < th->priority) )
517 try_transmit_ctx->ret = th;
518 return GNUNET_YES;
519}
520
521
522/**
523 * Figure out which transmission to a peer can be done right now. 421 * Figure out which transmission to a peer can be done right now.
524 * If none can, schedule a task to call 'schedule_transmission' 422 * If none can, schedule a task to call 'schedule_transmission'
525 * whenever a peer transmission can be done in the future and 423 * whenever a peer transmission can be done in the future and
@@ -532,24 +430,88 @@ try_schedule_transmission (void *cls,
532static struct GNUNET_TRANSPORT_TransmitHandle * 430static struct GNUNET_TRANSPORT_TransmitHandle *
533schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h) 431schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h)
534{ 432{
535 struct TryTransmitContext try_transmit_ctx; 433 struct GNUNET_TRANSPORT_TransmitHandle *ret;
434 struct GNUNET_TRANSPORT_TransmitHandle *th;
435 struct NeighbourList *n;
436 struct NeighbourList *next;
437 struct GNUNET_TIME_Relative retry_time;
438 struct GNUNET_TIME_Relative duration;
439 GNUNET_CONNECTION_TransmitReadyNotify notify;
536 440
537 if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) 441 if (h->quota_task != GNUNET_SCHEDULER_NO_TASK)
538 { 442 {
539 GNUNET_SCHEDULER_cancel (h->quota_task); 443 GNUNET_SCHEDULER_cancel (h->quota_task);
540 h->quota_task = GNUNET_SCHEDULER_NO_TASK; 444 h->quota_task = GNUNET_SCHEDULER_NO_TASK;
541 } 445 }
542 try_transmit_ctx.h = h; 446 retry_time = GNUNET_TIME_UNIT_FOREVER_REL;
543 try_transmit_ctx.ret = NULL; 447 ret = NULL;
544 try_transmit_ctx.retry_time = GNUNET_TIME_UNIT_FOREVER_REL; 448 next = h->neighbours;
545 GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, 449 while (NULL != (n = next))
546 &try_schedule_transmission, 450 {
547 &try_transmit_ctx); 451 next = n->next;
548 if (try_transmit_ctx.ret == NULL) 452 if (n->transmit_stage != TS_QUEUED)
549 h->quota_task = GNUNET_SCHEDULER_add_delayed (try_transmit_ctx.retry_time, 453 continue; /* not eligible */
454 if (n->is_connected != GNUNET_YES)
455 continue;
456
457 th = &n->transmit_handle;
458 GNUNET_break (n == th->neighbour);
459 /* check outgoing quota */
460 duration = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker,
461 th->notify_size - sizeof (struct OutboundMessage));
462 struct GNUNET_TIME_Absolute duration_abs = GNUNET_TIME_relative_to_absolute (duration);
463 if (th->timeout.abs_value < duration_abs.abs_value)
464 {
465 /* signal timeout! */
466#if DEBUG_TRANSPORT
467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
468 "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n",
469 duration.rel_value,
470 GNUNET_i2s (&n->id));
471#endif
472 if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK)
473 {
474 GNUNET_SCHEDULER_cancel (th->notify_delay_task);
475 th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
476 }
477 n->transmit_stage = TS_NEW;
478 if (NULL != (notify = th->notify))
479 {
480 th->notify = NULL;
481 GNUNET_assert (0 == notify (th->notify_cls, 0, NULL));
482 }
483 continue;
484 }
485 if (duration.rel_value > 0)
486 {
487#if DEBUG_TRANSPORT
488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
489 "Need more bandwidth (%u b/s allowed, %u b needed), delaying delivery to `%4s' by %llu ms\n",
490 (unsigned int) n->out_tracker.available_bytes_per_s__,
491 (unsigned int) th->notify_size - sizeof (struct OutboundMessage),
492 GNUNET_i2s (&n->id),
493 duration.rel_value);
494#endif
495 retry_time = GNUNET_TIME_relative_min (retry_time,
496 duration);
497 continue;
498 }
499#if DEBUG_TRANSPORT
500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
501 "Have %u bytes of bandwidth available for transmission to `%4s' right now\n",
502 th->notify_size - sizeof (struct OutboundMessage),
503 GNUNET_i2s (&n->id));
504#endif
505
506 if ( (ret == NULL) ||
507 (ret->priority < th->priority) )
508 ret = th;
509 }
510 if (ret == NULL)
511 h->quota_task = GNUNET_SCHEDULER_add_delayed (retry_time,
550 &quota_transmit_ready, 512 &quota_transmit_ready,
551 h); 513 h);
552 return try_transmit_ctx.ret; 514 return ret;
553} 515}
554 516
555 517
@@ -815,39 +777,18 @@ schedule_control_transmit (struct GNUNET_TRANSPORT_Handle *h,
815} 777}
816 778
817 779
818/**
819 * FIXME: document
820 */
821struct SetQuotaContext 780struct SetQuotaContext
822{ 781{
823 /**
824 * FIXME: document
825 */
826 struct GNUNET_TRANSPORT_Handle *handle; 782 struct GNUNET_TRANSPORT_Handle *handle;
827 783
828 /**
829 * FIXME: document
830 */
831 struct GNUNET_PeerIdentity target; 784 struct GNUNET_PeerIdentity target;
832 785
833 /**
834 * FIXME: document
835 */
836 GNUNET_SCHEDULER_Task cont; 786 GNUNET_SCHEDULER_Task cont;
837 787
838 /**
839 * Closure for 'cont'.
840 */
841 void *cont_cls; 788 void *cont_cls;
842 789
843 /**
844 * FIXME: document
845 */
846 struct GNUNET_TIME_Absolute timeout; 790 struct GNUNET_TIME_Absolute timeout;
847 791
848 /**
849 * FIXME: document
850 */
851 struct GNUNET_BANDWIDTH_Value32NBO quota_in; 792 struct GNUNET_BANDWIDTH_Value32NBO quota_in;
852}; 793};
853 794
@@ -868,10 +809,9 @@ send_set_quota (void *cls, size_t size, void *buf)
868 809
869 if (buf == NULL) 810 if (buf == NULL)
870 { 811 {
871 if (sqc->cont != NULL) 812 GNUNET_SCHEDULER_add_continuation (sqc->cont,
872 GNUNET_SCHEDULER_add_continuation (sqc->cont, 813 sqc->cont_cls,
873 sqc->cont_cls, 814 GNUNET_SCHEDULER_REASON_TIMEOUT);
874 GNUNET_SCHEDULER_REASON_TIMEOUT);
875 GNUNET_free (sqc); 815 GNUNET_free (sqc);
876 return 0; 816 return 0;
877 } 817 }
@@ -1150,21 +1090,9 @@ static void
1150neighbour_free (struct NeighbourList *n) 1090neighbour_free (struct NeighbourList *n)
1151{ 1091{
1152 struct GNUNET_TRANSPORT_Handle *h; 1092 struct GNUNET_TRANSPORT_Handle *h;
1093 struct NeighbourList *prev;
1094 struct NeighbourList *pos;
1153 1095
1154 /* Added so task gets canceled when a disconnect is received! */
1155 /* Method 1
1156 if (n->transmit_handle.notify_delay_task != GNUNET_SCHEDULER_NO_TASK)
1157 {
1158 GNUNET_SCHEDULER_cancel(n->transmit_handle.notify_delay_task);
1159 n->transmit_handle.notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
1160 n->transmit_handle.notify = NULL;
1161 }
1162 */
1163 /* NATE: if the above is not needed, then clearly this assertion
1164 should hold (I've checked the code and I'm pretty sure this is
1165 true. -CG
1166 FIXME: remove above comments once we've seen tests pass with the assert... */
1167 GNUNET_assert (n->transmit_handle.notify_delay_task == GNUNET_SCHEDULER_NO_TASK);
1168 GNUNET_assert (n->transmit_handle.notify == NULL); 1096 GNUNET_assert (n->transmit_handle.notify == NULL);
1169 h = n->h; 1097 h = n->h;
1170#if DEBUG_TRANSPORT 1098#if DEBUG_TRANSPORT
@@ -1175,10 +1103,17 @@ neighbour_free (struct NeighbourList *n)
1175 GNUNET_break (n->is_connected == GNUNET_NO); 1103 GNUNET_break (n->is_connected == GNUNET_NO);
1176 GNUNET_break (n->transmit_stage == TS_NEW); 1104 GNUNET_break (n->transmit_stage == TS_NEW);
1177 1105
1178 GNUNET_assert(GNUNET_YES == 1106 prev = NULL;
1179 GNUNET_CONTAINER_multihashmap_remove(h->neighbours, 1107 pos = h->neighbours;
1180 &n->id.hashPubKey, 1108 while (pos != n)
1181 n)); 1109 {
1110 prev = pos;
1111 pos = pos->next;
1112 }
1113 if (prev == NULL)
1114 h->neighbours = n->next;
1115 else
1116 prev->next = n->next;
1182 GNUNET_free (n); 1117 GNUNET_free (n);
1183} 1118}
1184 1119
@@ -1199,14 +1134,6 @@ neighbour_disconnect (struct NeighbourList *n)
1199#endif 1134#endif
1200 GNUNET_break (n->is_connected == GNUNET_YES); 1135 GNUNET_break (n->is_connected == GNUNET_YES);
1201 n->is_connected = GNUNET_NO; 1136 n->is_connected = GNUNET_NO;
1202 /* FIXME: this 'in_disconnect' flag is dubious; we should define
1203 clearly what disconnect means for pending 'notify_transmit_ready'
1204 requests; maybe a good approach is to REQUIRE clients to
1205 call 'notify_transmit_ready_cancel' on pending requests on disconnect
1206 and otherwise FAIL HARD with an assertion failure before
1207 'neighbour_free' right here (transmit_stage would be forced
1208 to 'TS_NEW') */
1209 n->in_disconnect = GNUNET_YES;
1210 if (h->nd_cb != NULL) 1137 if (h->nd_cb != NULL)
1211 h->nd_cb (h->cls, &n->id); 1138 h->nd_cb (h->cls, &n->id);
1212 if (n->transmit_stage == TS_NEW) 1139 if (n->transmit_stage == TS_NEW)
@@ -1226,35 +1153,6 @@ static void demultiplexer (void *cls,
1226 1153
1227 1154
1228/** 1155/**
1229 * Iterator over hash map entries, for getting rid of a neighbor
1230 * upon a reconnect call.
1231 *
1232 * @param cls closure (NULL)
1233 * @param key current key code
1234 * @param value value in the hash map, the neighbour entry to forget
1235 * @return GNUNET_YES if we should continue to
1236 * iterate,
1237 * GNUNET_NO if not.
1238 */
1239static int
1240forget_neighbours (void *cls,
1241 const GNUNET_HashCode * key,
1242 void *value)
1243{
1244 struct NeighbourList *n = value;
1245
1246#if DEBUG_TRANSPORT_DISCONNECT
1247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1248 "Disconnecting due to reconnect being called\n");
1249#endif
1250 if (n->is_connected)
1251 neighbour_disconnect (n);
1252
1253 return GNUNET_YES;
1254}
1255
1256
1257/**
1258 * Try again to connect to transport service. 1156 * Try again to connect to transport service.
1259 * 1157 *
1260 * @param cls the handle to the transport service 1158 * @param cls the handle to the transport service
@@ -1266,6 +1164,8 @@ reconnect (void *cls,
1266{ 1164{
1267 struct GNUNET_TRANSPORT_Handle *h = cls; 1165 struct GNUNET_TRANSPORT_Handle *h = cls;
1268 struct ControlMessage *pos; 1166 struct ControlMessage *pos;
1167 struct NeighbourList *n;
1168 struct NeighbourList *next;
1269 1169
1270 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; 1170 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1271 if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) 1171 if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
@@ -1274,10 +1174,18 @@ reconnect (void *cls,
1274 return; 1174 return;
1275 } 1175 }
1276 /* Forget about all neighbours that we used to be connected to */ 1176 /* Forget about all neighbours that we used to be connected to */
1277 GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, 1177 n = h->neighbours;
1278 &forget_neighbours, 1178 while (NULL != n)
1279 NULL); 1179 {
1280 1180#if DEBUG_TRANSPORT_DISCONNECT
1181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1182 "Disconnecting due to reconnect being called\n");
1183#endif
1184 next = n->next;
1185 if (n->is_connected)
1186 neighbour_disconnect (n);
1187 n = next;
1188 }
1281#if DEBUG_TRANSPORT 1189#if DEBUG_TRANSPORT
1282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1283 "Connecting to transport service.\n"); 1191 "Connecting to transport service.\n");
@@ -1402,7 +1310,6 @@ send_request_connect_message(struct GNUNET_TRANSPORT_Handle *h, struct Neighbour
1402 GNUNET_TIME_UNIT_FOREVER_REL, &send_transport_request_connect, trcm); 1310 GNUNET_TIME_UNIT_FOREVER_REL, &send_transport_request_connect, trcm);
1403} 1311}
1404 1312
1405
1406/** 1313/**
1407 * Add neighbour to our list 1314 * Add neighbour to our list
1408 * 1315 *
@@ -1429,58 +1336,15 @@ neighbour_add (struct GNUNET_TRANSPORT_Handle *h,
1429#endif 1336#endif
1430 n = GNUNET_malloc (sizeof (struct NeighbourList)); 1337 n = GNUNET_malloc (sizeof (struct NeighbourList));
1431 n->id = *pid; 1338 n->id = *pid;
1432 n->h = h;
1433 GNUNET_BANDWIDTH_tracker_init (&n->out_tracker, 1339 GNUNET_BANDWIDTH_tracker_init (&n->out_tracker,
1434 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, 1340 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
1435 MAX_BANDWIDTH_CARRY_S); 1341 MAX_BANDWIDTH_CARRY_S);
1436 GNUNET_CONTAINER_multihashmap_put (h->neighbours, 1342 n->next = h->neighbours;
1437 &pid->hashPubKey, 1343 n->h = h;
1438 n, 1344 h->neighbours = n;
1439 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1440
1441 return n;
1442}
1443
1444 1345
1445/**
1446 * Iterator over hash map entries, for deleting state of a neighbor.
1447 *
1448 * @param cls closure (NULL)
1449 * @param key current key code
1450 * @param value value in the hash map, the neighbour entry to delete
1451 * @return GNUNET_YES if we should continue to
1452 * iterate,
1453 * GNUNET_NO if not.
1454 */
1455static int
1456delete_neighbours (void *cls,
1457 const GNUNET_HashCode * key,
1458 void *value)
1459{
1460 struct NeighbourList *n = value;
1461 struct GNUNET_TRANSPORT_TransmitHandle *th;
1462 1346
1463 switch (n->transmit_stage) 1347 return n;
1464 {
1465 case TS_NEW:
1466 case TS_TRANSMITTED:
1467 /* nothing to do */
1468 break;
1469 case TS_QUEUED:
1470 case TS_TRANSMITTED_QUEUED:
1471 th = &n->transmit_handle;
1472 if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK)
1473 {
1474 GNUNET_SCHEDULER_cancel (th->notify_delay_task);
1475 th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
1476 }
1477 GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
1478 break;
1479 default:
1480 GNUNET_break (0);
1481 }
1482 GNUNET_free (n);
1483 return GNUNET_YES;
1484} 1348}
1485 1349
1486 1350
@@ -1518,7 +1382,6 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
1518 ret->nc_cb = nc; 1382 ret->nc_cb = nc;
1519 ret->nd_cb = nd; 1383 ret->nd_cb = nd;
1520 ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; 1384 ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
1521 ret->neighbours = GNUNET_CONTAINER_multihashmap_create(STARTING_NEIGHBOURS_SIZE);
1522 schedule_reconnect (ret); 1385 schedule_reconnect (ret);
1523 return ret; 1386 return ret;
1524} 1387}
@@ -1530,6 +1393,8 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
1530void 1393void
1531GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) 1394GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle)
1532{ 1395{
1396 struct GNUNET_TRANSPORT_TransmitHandle *th;
1397 struct NeighbourList *n;
1533 struct HelloWaitList *hwl; 1398 struct HelloWaitList *hwl;
1534 struct GNUNET_CLIENT_Connection *client; 1399 struct GNUNET_CLIENT_Connection *client;
1535 struct ControlMessage *cm; 1400 struct ControlMessage *cm;
@@ -1537,20 +1402,31 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle)
1537#if DEBUG_TRANSPORT 1402#if DEBUG_TRANSPORT
1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n"); 1403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n");
1539#endif 1404#endif
1540 /* FIXME: this flag is dubious, we should be able to do this
1541 more cleanly; also, we should probably do 'disconnect'
1542 callbacks for every connected peer here, i.e. by calling
1543 the iterator with 'forget_neighbours' instead of 'delete_neighbours'.
1544 */
1545
1546 handle->in_disconnect = GNUNET_YES; 1405 handle->in_disconnect = GNUNET_YES;
1547 1406 while (NULL != (n = handle->neighbours))
1548 GNUNET_assert (GNUNET_SYSERR != 1407 {
1549 GNUNET_CONTAINER_multihashmap_iterate(handle->neighbours, 1408 handle->neighbours = n->next;
1550 &delete_neighbours, 1409 switch (n->transmit_stage)
1551 handle)); 1410 {
1552 GNUNET_CONTAINER_multihashmap_destroy (handle->neighbours); 1411 case TS_NEW:
1553 1412 case TS_TRANSMITTED:
1413 /* nothing to do */
1414 break;
1415 case TS_QUEUED:
1416 case TS_TRANSMITTED_QUEUED:
1417 th = &n->transmit_handle;
1418 if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK)
1419 {
1420 GNUNET_SCHEDULER_cancel (th->notify_delay_task);
1421 th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
1422 }
1423 GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
1424 break;
1425 default:
1426 GNUNET_break (0);
1427 }
1428 GNUNET_free (n);
1429 }
1554 while (NULL != (hwl = handle->hwl_head)) 1430 while (NULL != (hwl = handle->hwl_head))
1555 { 1431 {
1556 handle->hwl_head = hwl->next; 1432 handle->hwl_head = hwl->next;
@@ -1634,6 +1510,7 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
1634 struct NeighbourList *n; 1510 struct NeighbourList *n;
1635 struct GNUNET_PeerIdentity me; 1511 struct GNUNET_PeerIdentity me;
1636 uint16_t size; 1512 uint16_t size;
1513 uint32_t ats_count;
1637 1514
1638 if (h->client == NULL) 1515 if (h->client == NULL)
1639 { 1516 {
@@ -1695,12 +1572,19 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
1695 } 1572 }
1696 break; 1573 break;
1697 case GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT: 1574 case GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT:
1698 if (size != sizeof (struct ConnectInfoMessage)) 1575
1576 if (size < sizeof (struct ConnectInfoMessage))
1699 { 1577 {
1700 GNUNET_break (0); 1578 GNUNET_break (0);
1701 break; 1579 break;
1702 } 1580 }
1703 cim = (const struct ConnectInfoMessage *) msg; 1581 cim = (const struct ConnectInfoMessage *) msg;
1582 ats_count = ntohl (cim->ats_count);
1583 if (size != sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information))
1584 {
1585 GNUNET_break (0);
1586 break;
1587 }
1704#if DEBUG_TRANSPORT 1588#if DEBUG_TRANSPORT
1705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1706 "Receiving `%s' message for `%4s'.\n", 1590 "Receiving `%s' message for `%4s'.\n",
@@ -1708,29 +1592,16 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
1708#endif 1592#endif
1709 n = neighbour_find (h, &cim->id); 1593 n = neighbour_find (h, &cim->id);
1710 if (n == NULL) 1594 if (n == NULL)
1711 n = neighbour_add (h, 1595 n = neighbour_add (h, &cim->id);
1712 &cim->id);
1713 if (n == NULL) 1596 if (n == NULL)
1714 { 1597 return;
1715 GNUNET_break (0);
1716 return;
1717 }
1718 GNUNET_break (n->is_connected == GNUNET_NO); 1598 GNUNET_break (n->is_connected == GNUNET_NO);
1719 if (ntohl ((&cim->ats)[ntohl (cim->ats_count)].type) != GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR) 1599 n->is_connected = GNUNET_YES;
1720 { 1600 /* FIXME */
1721 GNUNET_break (0);
1722 return;
1723 }
1724 fprintf(stderr,"transport_api GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT ats_count %u\n",ntohl (cim->ats_count));
1725 n->is_connected = GNUNET_YES;
1726 if (h->nc_cb != NULL) 1601 if (h->nc_cb != NULL)
1727 h->nc_cb (h->cls, &n->id,
1728 NULL,
1729 0);
1730 /* if (h->nc_cb != NULL)
1731 h->nc_cb (h->cls, &n->id, 1602 h->nc_cb (h->cls, &n->id,
1732 &(cim->ats), 1603 NULL,0);
1733 ntohl (cim->ats_count));*/ 1604 /* FIXEND */
1734 break; 1605 break;
1735 case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT: 1606 case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT:
1736 if (size != sizeof (struct DisconnectInfoMessage)) 1607 if (size != sizeof (struct DisconnectInfoMessage))
@@ -1798,9 +1669,10 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
1798 } 1669 }
1799 im = (const struct InboundMessage *) msg; 1670 im = (const struct InboundMessage *) msg;
1800 GNUNET_break (0 == ntohl (im->reserved)); 1671 GNUNET_break (0 == ntohl (im->reserved));
1801 GNUNET_assert(sizeof (struct InboundMessage) + ntohl(im->ats_count) * sizeof(struct GNUNET_TRANSPORT_ATS_Information) + sizeof (struct GNUNET_MessageHeader) <= size); 1672 ats_count = ntohl(im->ats_count);
1802 imm = (const struct GNUNET_MessageHeader *) &((&im->ats)[ntohl(im->ats_count)+1]); 1673 //imm = (const struct GNUNET_MessageHeader *) &im[1];
1803 if (ntohs (imm->size) + sizeof (struct InboundMessage) + ntohl(im->ats_count) * sizeof(struct GNUNET_TRANSPORT_ATS_Information) != size) 1674 imm = (const struct GNUNET_MessageHeader *) &((&(im->ats))[ats_count+1]);
1675 if (ntohs (imm->size) + sizeof (struct InboundMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) != size)
1804 { 1676 {
1805 GNUNET_break (0); 1677 GNUNET_break (0);
1806 break; 1678 break;
@@ -1821,22 +1693,11 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
1821 GNUNET_break (0); 1693 GNUNET_break (0);
1822 break; 1694 break;
1823 } 1695 }
1824 if (ntohl ((&im->ats)[ntohl(im->ats_count)].type) != GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR) 1696 /* FIXME: */
1825 { 1697 if (h->rec != NULL)
1826 GNUNET_break (0); 1698 h->rec (h->cls, &im->peer, imm,
1827 return; 1699 NULL, 0);
1828 } 1700 /* ENDFIX */
1829 fprintf(stderr,"transport_api GNUNET_MESSAGE_TYPE_TRANSPORT_RECV ats_count %u\n",ntohl (im->ats_count));
1830 if (h->rec != NULL)
1831 h->rec (h->cls, &im->peer,
1832 imm,
1833 NULL,
1834 0);
1835
1836 /*h->rec (h->cls, &im->peer,
1837 imm,
1838 &im->ats,
1839 ntohl (im->ats_count));*/
1840 break; 1701 break;
1841 default: 1702 default:
1842 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1703 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -2025,7 +1886,7 @@ GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct
2025 n = th->neighbour; 1886 n = th->neighbour;
2026#if DEBUG_TRANSPORT 1887#if DEBUG_TRANSPORT
2027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2028 "Transmission request of %u bytes to `%4s' was canceled.\n", 1889 "Transmission request of %u bytes to `%4s' was cancelled.\n",
2029 th->notify_size - sizeof (struct OutboundMessage), 1890 th->notify_size - sizeof (struct OutboundMessage),
2030 GNUNET_i2s (&n->id)); 1891 GNUNET_i2s (&n->id));
2031#endif 1892#endif
@@ -2041,8 +1902,7 @@ GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct
2041 break; 1902 break;
2042 case TS_QUEUED: 1903 case TS_QUEUED:
2043 n->transmit_stage = TS_NEW; 1904 n->transmit_stage = TS_NEW;
2044 if ( (n->in_disconnect == GNUNET_NO) && 1905 if (n->is_connected == GNUNET_NO)
2045 (n->is_connected == GNUNET_NO) )
2046 neighbour_free (n); 1906 neighbour_free (n);
2047 break; 1907 break;
2048 case TS_TRANSMITTED: 1908 case TS_TRANSMITTED: