aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport_api.c
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-11-30 17:05:17 +0000
committerNathan S. Evans <evans@in.tum.de>2010-11-30 17:05:17 +0000
commit7f806de4dcf1c2d71bfad522a2c7f8cf1d82566e (patch)
tree478e6490ec647b563ca695d899f7d655cb580cac /src/transport/transport_api.c
parent6075973b278f72f81de967c978706e80d6b79978 (diff)
downloadgnunet-7f806de4dcf1c2d71bfad522a2c7f8cf1d82566e.tar.gz
gnunet-7f806de4dcf1c2d71bfad522a2c7f8cf1d82566e.zip
use hashmap instead of linked list of neighbors, fix for double free
Diffstat (limited to 'src/transport/transport_api.c')
-rw-r--r--src/transport/transport_api.c377
1 files changed, 230 insertions, 147 deletions
diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c
index 3d35f8d0b..23f8c71a7 100644
--- a/src/transport/transport_api.c
+++ b/src/transport/transport_api.c
@@ -60,6 +60,11 @@
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
63 68
64/** 69/**
65 * What stage are we in for transmission processing? 70 * What stage are we in for transmission processing?
@@ -187,19 +192,39 @@ struct ControlMessage
187 192
188}; 193};
189 194
190
191/** 195/**
192 * Entry in linked list of all of our current neighbours. 196 * Context for storing information about attempted next transmission.
193 */ 197 */
194struct NeighbourList 198struct TryTransmitContext
195{ 199{
196 200
197 /** 201 /**
198 * This is a linked list. 202 * Main transport handle.
199 */ 203 */
200 struct NeighbourList *next; 204 struct GNUNET_TRANSPORT_Handle *h;
205
206 /**
207 * Returned transmission handle.
208 */
209 struct GNUNET_TRANSPORT_TransmitHandle *ret;
201 210
202 /** 211 /**
212 * Temporary transmit handle.
213 */
214 struct GNUNET_TRANSPORT_TransmitHandle *th;
215
216 /**
217 * Time to retry the send task.
218 */
219 struct GNUNET_TIME_Relative retry_time;
220};
221
222/**
223 * Entry in hash table of all of our current neighbours.
224 */
225struct NeighbourList
226{
227 /**
203 * Overall transport handle. 228 * Overall transport handle.
204 */ 229 */
205 struct GNUNET_TRANSPORT_Handle *h; 230 struct GNUNET_TRANSPORT_Handle *h;
@@ -235,6 +260,11 @@ struct NeighbourList
235 */ 260 */
236 int is_connected; 261 int is_connected;
237 262
263 /**
264 * Are we in the middle of disconnecting the peer already?
265 */
266 unsigned int in_disconnect;
267
238}; 268};
239 269
240 270
@@ -334,7 +364,7 @@ struct GNUNET_TRANSPORT_Handle
334 /** 364 /**
335 * Linked list of the current neighbours of this peer. 365 * Linked list of the current neighbours of this peer.
336 */ 366 */
337 struct NeighbourList *neighbours; 367 struct GNUNET_CONTAINER_MultiHashMap *neighbours;
338 368
339 /** 369 /**
340 * Peer identity as assumed by this process, or all zeros. 370 * Peer identity as assumed by this process, or all zeros.
@@ -383,13 +413,10 @@ static struct NeighbourList *
383neighbour_find (struct GNUNET_TRANSPORT_Handle *h, 413neighbour_find (struct GNUNET_TRANSPORT_Handle *h,
384 const struct GNUNET_PeerIdentity *peer) 414 const struct GNUNET_PeerIdentity *peer)
385{ 415{
386 struct NeighbourList *pos; 416 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains(h->neighbours, &peer->hashPubKey))
417 return NULL;
387 418
388 pos = h->neighbours; 419 return GNUNET_CONTAINER_multihashmap_get(h->neighbours, &peer->hashPubKey);
389 while ((pos != NULL) &&
390 (0 != memcmp (peer, &pos->id, sizeof (struct GNUNET_PeerIdentity))))
391 pos = pos->next;
392 return pos;
393} 420}
394 421
395 422
@@ -416,6 +443,87 @@ quota_transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
416 schedule_transmission (h); 443 schedule_transmission (h);
417} 444}
418 445
446/**
447 * Iterator over hash map entries, attempt to schedule
448 * a transmission to entries in the neighbour hashmap.
449 *
450 * @param cls closure a TryTransmitContext
451 * @param key current key code
452 * @param value value in the hash map, the neighbour entry to consider
453 * @return GNUNET_YES if we should continue to
454 * iterate,
455 * GNUNET_NO if not.
456 */
457static int
458try_schedule_transmission (void *cls,
459 const GNUNET_HashCode * key,
460 void *value)
461{
462 struct NeighbourList *n = value;
463 struct TryTransmitContext *try_transmit_ctx = cls;
464 struct GNUNET_TIME_Relative duration;
465 GNUNET_CONNECTION_TransmitReadyNotify notify;
466
467 if (n->transmit_stage != TS_QUEUED)
468 return GNUNET_YES; /* not eligible, keep iterating */
469 if (n->is_connected != GNUNET_YES)
470 return GNUNET_YES; /* keep iterating */
471
472 try_transmit_ctx->th = &n->transmit_handle;
473 GNUNET_break (n == try_transmit_ctx->th->neighbour);
474 /* check outgoing quota */
475 duration = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker,
476 try_transmit_ctx->th->notify_size - sizeof (struct OutboundMessage));
477 struct GNUNET_TIME_Absolute duration_abs = GNUNET_TIME_relative_to_absolute (duration);
478 if (try_transmit_ctx->th->timeout.abs_value < duration_abs.abs_value)
479 {
480 /* signal timeout! */
481#if DEBUG_TRANSPORT
482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
483 "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n",
484 duration.rel_value,
485 GNUNET_i2s (&n->id));
486#endif
487 if (try_transmit_ctx->th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK)
488 {
489 GNUNET_SCHEDULER_cancel (try_transmit_ctx->th->notify_delay_task);
490 try_transmit_ctx->th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
491 }
492 n->transmit_stage = TS_NEW;
493 if (NULL != (notify = try_transmit_ctx->th->notify))
494 {
495 try_transmit_ctx->th->notify = NULL;
496 GNUNET_assert (0 == notify (try_transmit_ctx->th->notify_cls, 0, NULL));
497 }
498 return GNUNET_YES; /* keep iterating */
499 }
500 if (duration.rel_value > 0)
501 {
502#if DEBUG_TRANSPORT
503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
504 "Need more bandwidth (%u b/s allowed, %u b needed), delaying delivery to `%4s' by %llu ms\n",
505 (unsigned int) n->out_tracker.available_bytes_per_s__,
506 (unsigned int) try_transmit_ctx->th->notify_size - sizeof (struct OutboundMessage),
507 GNUNET_i2s (&n->id),
508 duration.rel_value);
509#endif
510 try_transmit_ctx->retry_time = GNUNET_TIME_relative_min (try_transmit_ctx->retry_time,
511 duration);
512 return GNUNET_YES; /* keep iterating */
513 }
514#if DEBUG_TRANSPORT
515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
516 "Have %u bytes of bandwidth available for transmission to `%4s' right now\n",
517 try_transmit_ctx->th->notify_size - sizeof (struct OutboundMessage),
518 GNUNET_i2s (&n->id));
519#endif
520
521 if ( (try_transmit_ctx->ret == NULL) ||
522 (try_transmit_ctx->ret->priority < try_transmit_ctx->th->priority) )
523 try_transmit_ctx->ret = try_transmit_ctx->th;
524
525 return GNUNET_YES;
526}
419 527
420/** 528/**
421 * Figure out which transmission to a peer can be done right now. 529 * Figure out which transmission to a peer can be done right now.
@@ -430,88 +538,23 @@ quota_transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
430static struct GNUNET_TRANSPORT_TransmitHandle * 538static struct GNUNET_TRANSPORT_TransmitHandle *
431schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h) 539schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h)
432{ 540{
433 struct GNUNET_TRANSPORT_TransmitHandle *ret; 541
434 struct GNUNET_TRANSPORT_TransmitHandle *th; 542 struct TryTransmitContext try_transmit_ctx;
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;
440 543
441 if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) 544 if (h->quota_task != GNUNET_SCHEDULER_NO_TASK)
442 { 545 {
443 GNUNET_SCHEDULER_cancel (h->quota_task); 546 GNUNET_SCHEDULER_cancel (h->quota_task);
444 h->quota_task = GNUNET_SCHEDULER_NO_TASK; 547 h->quota_task = GNUNET_SCHEDULER_NO_TASK;
445 } 548 }
446 retry_time = GNUNET_TIME_UNIT_FOREVER_REL; 549 memset(&try_transmit_ctx, 0, sizeof(struct TryTransmitContext));
447 ret = NULL; 550 try_transmit_ctx.retry_time = GNUNET_TIME_UNIT_FOREVER_REL;
448 next = h->neighbours; 551 GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, &try_schedule_transmission, &try_transmit_ctx);
449 while (NULL != (n = next))
450 {
451 next = n->next;
452 if (n->transmit_stage != TS_QUEUED)
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 552
506 if ( (ret == NULL) || 553 if (try_transmit_ctx.ret == NULL)
507 (ret->priority < th->priority) ) 554 h->quota_task = GNUNET_SCHEDULER_add_delayed (try_transmit_ctx.retry_time,
508 ret = th;
509 }
510 if (ret == NULL)
511 h->quota_task = GNUNET_SCHEDULER_add_delayed (retry_time,
512 &quota_transmit_ready, 555 &quota_transmit_ready,
513 h); 556 h);
514 return ret; 557 return try_transmit_ctx.ret;
515} 558}
516 559
517 560
@@ -809,9 +852,10 @@ send_set_quota (void *cls, size_t size, void *buf)
809 852
810 if (buf == NULL) 853 if (buf == NULL)
811 { 854 {
812 GNUNET_SCHEDULER_add_continuation (sqc->cont, 855 if (sqc->cont != NULL)
813 sqc->cont_cls, 856 GNUNET_SCHEDULER_add_continuation (sqc->cont,
814 GNUNET_SCHEDULER_REASON_TIMEOUT); 857 sqc->cont_cls,
858 GNUNET_SCHEDULER_REASON_TIMEOUT);
815 GNUNET_free (sqc); 859 GNUNET_free (sqc);
816 return 0; 860 return 0;
817 } 861 }
@@ -1090,8 +1134,16 @@ static void
1090neighbour_free (struct NeighbourList *n) 1134neighbour_free (struct NeighbourList *n)
1091{ 1135{
1092 struct GNUNET_TRANSPORT_Handle *h; 1136 struct GNUNET_TRANSPORT_Handle *h;
1093 struct NeighbourList *prev; 1137
1094 struct NeighbourList *pos; 1138 /* Added so task gets canceled when a disconnect is received! */
1139 /* Method 1
1140 if (n->transmit_handle.notify_delay_task != GNUNET_SCHEDULER_NO_TASK)
1141 {
1142 GNUNET_SCHEDULER_cancel(n->transmit_handle.notify_delay_task);
1143 n->transmit_handle.notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
1144 n->transmit_handle.notify = NULL;
1145 }
1146 */
1095 1147
1096 GNUNET_assert (n->transmit_handle.notify == NULL); 1148 GNUNET_assert (n->transmit_handle.notify == NULL);
1097 h = n->h; 1149 h = n->h;
@@ -1103,17 +1155,8 @@ neighbour_free (struct NeighbourList *n)
1103 GNUNET_break (n->is_connected == GNUNET_NO); 1155 GNUNET_break (n->is_connected == GNUNET_NO);
1104 GNUNET_break (n->transmit_stage == TS_NEW); 1156 GNUNET_break (n->transmit_stage == TS_NEW);
1105 1157
1106 prev = NULL; 1158 GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(h->neighbours, &n->id.hashPubKey, n));
1107 pos = h->neighbours; 1159
1108 while (pos != 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;
1117 GNUNET_free (n); 1160 GNUNET_free (n);
1118} 1161}
1119 1162
@@ -1134,6 +1177,7 @@ neighbour_disconnect (struct NeighbourList *n)
1134#endif 1177#endif
1135 GNUNET_break (n->is_connected == GNUNET_YES); 1178 GNUNET_break (n->is_connected == GNUNET_YES);
1136 n->is_connected = GNUNET_NO; 1179 n->is_connected = GNUNET_NO;
1180 n->in_disconnect = GNUNET_YES;
1137 if (h->nd_cb != NULL) 1181 if (h->nd_cb != NULL)
1138 h->nd_cb (h->cls, &n->id); 1182 h->nd_cb (h->cls, &n->id);
1139 if (n->transmit_stage == TS_NEW) 1183 if (n->transmit_stage == TS_NEW)
@@ -1153,6 +1197,33 @@ static void demultiplexer (void *cls,
1153 1197
1154 1198
1155/** 1199/**
1200 * Iterator over hash map entries, for getting rid of a neighbor
1201 * upon a reconnect call.
1202 *
1203 * @param cls closure (NULL)
1204 * @param key current key code
1205 * @param value value in the hash map, the neighbour entry to forget
1206 * @return GNUNET_YES if we should continue to
1207 * iterate,
1208 * GNUNET_NO if not.
1209 */
1210static int
1211forget_neighbours (void *cls,
1212 const GNUNET_HashCode * key,
1213 void *value)
1214{
1215 struct NeighbourList *n = value;
1216#if DEBUG_TRANSPORT_DISCONNECT
1217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1218 "Disconnecting due to reconnect being called\n");
1219#endif
1220 if (n->is_connected)
1221 neighbour_disconnect (n);
1222
1223 return GNUNET_YES;
1224}
1225
1226/**
1156 * Try again to connect to transport service. 1227 * Try again to connect to transport service.
1157 * 1228 *
1158 * @param cls the handle to the transport service 1229 * @param cls the handle to the transport service
@@ -1164,8 +1235,6 @@ reconnect (void *cls,
1164{ 1235{
1165 struct GNUNET_TRANSPORT_Handle *h = cls; 1236 struct GNUNET_TRANSPORT_Handle *h = cls;
1166 struct ControlMessage *pos; 1237 struct ControlMessage *pos;
1167 struct NeighbourList *n;
1168 struct NeighbourList *next;
1169 1238
1170 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; 1239 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1171 if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) 1240 if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
@@ -1174,18 +1243,8 @@ reconnect (void *cls,
1174 return; 1243 return;
1175 } 1244 }
1176 /* Forget about all neighbours that we used to be connected to */ 1245 /* Forget about all neighbours that we used to be connected to */
1177 n = h->neighbours; 1246 GNUNET_CONTAINER_multihashmap_iterate(h->neighbours, &forget_neighbours, NULL);
1178 while (NULL != n) 1247
1179 {
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 }
1189#if DEBUG_TRANSPORT 1248#if DEBUG_TRANSPORT
1190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1191 "Connecting to transport service.\n"); 1250 "Connecting to transport service.\n");
@@ -1336,17 +1395,59 @@ neighbour_add (struct GNUNET_TRANSPORT_Handle *h,
1336#endif 1395#endif
1337 n = GNUNET_malloc (sizeof (struct NeighbourList)); 1396 n = GNUNET_malloc (sizeof (struct NeighbourList));
1338 n->id = *pid; 1397 n->id = *pid;
1398 n->h = h;
1339 GNUNET_BANDWIDTH_tracker_init (&n->out_tracker, 1399 GNUNET_BANDWIDTH_tracker_init (&n->out_tracker,
1340 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, 1400 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
1341 MAX_BANDWIDTH_CARRY_S); 1401 MAX_BANDWIDTH_CARRY_S);
1342 n->next = h->neighbours; 1402 GNUNET_CONTAINER_multihashmap_put (h->neighbours,
1343 n->h = h; 1403 &pid->hashPubKey,
1344 h->neighbours = n; 1404 n,
1345 1405 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1346 1406
1347 return n; 1407 return n;
1348} 1408}
1349 1409
1410/**
1411 * Iterator over hash map entries, for deleting state of a neighbor.
1412 *
1413 * @param cls closure (NULL)
1414 * @param key current key code
1415 * @param value value in the hash map, the neighbour entry to delete
1416 * @return GNUNET_YES if we should continue to
1417 * iterate,
1418 * GNUNET_NO if not.
1419 */
1420static int
1421delete_neighbours (void *cls,
1422 const GNUNET_HashCode * key,
1423 void *value)
1424{
1425 struct NeighbourList *n = value;
1426 struct GNUNET_TRANSPORT_TransmitHandle *th;
1427
1428 switch (n->transmit_stage)
1429 {
1430 case TS_NEW:
1431 case TS_TRANSMITTED:
1432 /* nothing to do */
1433 break;
1434 case TS_QUEUED:
1435 case TS_TRANSMITTED_QUEUED:
1436 th = &n->transmit_handle;
1437 if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK)
1438 {
1439 GNUNET_SCHEDULER_cancel (th->notify_delay_task);
1440 th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
1441 }
1442 GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
1443 break;
1444 default:
1445 GNUNET_break (0);
1446 }
1447 GNUNET_free (n);
1448 return GNUNET_YES;
1449}
1450
1350 1451
1351/** 1452/**
1352 * Connect to the transport service. Note that the connection may 1453 * Connect to the transport service. Note that the connection may
@@ -1382,6 +1483,7 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
1382 ret->nc_cb = nc; 1483 ret->nc_cb = nc;
1383 ret->nd_cb = nd; 1484 ret->nd_cb = nd;
1384 ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; 1485 ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
1486 ret->neighbours = GNUNET_CONTAINER_multihashmap_create(STARTING_NEIGHBOURS_SIZE);
1385 schedule_reconnect (ret); 1487 schedule_reconnect (ret);
1386 return ret; 1488 return ret;
1387} 1489}
@@ -1393,8 +1495,6 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
1393void 1495void
1394GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) 1496GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle)
1395{ 1497{
1396 struct GNUNET_TRANSPORT_TransmitHandle *th;
1397 struct NeighbourList *n;
1398 struct HelloWaitList *hwl; 1498 struct HelloWaitList *hwl;
1399 struct GNUNET_CLIENT_Connection *client; 1499 struct GNUNET_CLIENT_Connection *client;
1400 struct ControlMessage *cm; 1500 struct ControlMessage *cm;
@@ -1403,30 +1503,13 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle)
1403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n"); 1503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n");
1404#endif 1504#endif
1405 handle->in_disconnect = GNUNET_YES; 1505 handle->in_disconnect = GNUNET_YES;
1406 while (NULL != (n = handle->neighbours)) 1506
1407 { 1507 GNUNET_assert(GNUNET_SYSERR !=
1408 handle->neighbours = n->next; 1508 GNUNET_CONTAINER_multihashmap_iterate(handle->neighbours,
1409 switch (n->transmit_stage) 1509 &delete_neighbours,
1410 { 1510 handle));
1411 case TS_NEW: 1511 GNUNET_CONTAINER_multihashmap_destroy(handle->neighbours);
1412 case TS_TRANSMITTED: 1512
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 }
1430 while (NULL != (hwl = handle->hwl_head)) 1513 while (NULL != (hwl = handle->hwl_head))
1431 { 1514 {
1432 handle->hwl_head = hwl->next; 1515 handle->hwl_head = hwl->next;
@@ -1902,7 +1985,7 @@ GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct
1902 n = th->neighbour; 1985 n = th->neighbour;
1903#if DEBUG_TRANSPORT 1986#if DEBUG_TRANSPORT
1904 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1987 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1905 "Transmission request of %u bytes to `%4s' was cancelled.\n", 1988 "Transmission request of %u bytes to `%4s' was canceled.\n",
1906 th->notify_size - sizeof (struct OutboundMessage), 1989 th->notify_size - sizeof (struct OutboundMessage),
1907 GNUNET_i2s (&n->id)); 1990 GNUNET_i2s (&n->id));
1908#endif 1991#endif
@@ -1918,7 +2001,7 @@ GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct
1918 break; 2001 break;
1919 case TS_QUEUED: 2002 case TS_QUEUED:
1920 n->transmit_stage = TS_NEW; 2003 n->transmit_stage = TS_NEW;
1921 if (n->is_connected == GNUNET_NO) 2004 if (n->in_disconnect == GNUNET_NO)
1922 neighbour_free (n); 2005 neighbour_free (n);
1923 break; 2006 break;
1924 case TS_TRANSMITTED: 2007 case TS_TRANSMITTED: