diff options
author | Bart Polot <bart@net.in.tum.de> | 2014-07-22 16:00:36 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2014-07-22 16:00:36 +0000 |
commit | b6e0aac51cd54c83eaefaff1f4c7145732127393 (patch) | |
tree | c235d8dfcdd223a628ad5ca70b1534b3356ec54d /src | |
parent | 09335b5d3364817416be8f0657c98f2c4d290fc3 (diff) | |
download | gnunet-b6e0aac51cd54c83eaefaff1f4c7145732127393.tar.gz gnunet-b6e0aac51cd54c83eaefaff1f4c7145732127393.zip |
- make sure connection is destroyed and no use-after-free happens
Diffstat (limited to 'src')
-rw-r--r-- | src/cadet/gnunet-service-cadet_connection.c | 34 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet_peer.c | 63 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet_peer.h | 19 |
3 files changed, 68 insertions, 48 deletions
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c index d310501bb..5c28f9e4c 100644 --- a/src/cadet/gnunet-service-cadet_connection.c +++ b/src/cadet/gnunet-service-cadet_connection.c | |||
@@ -564,8 +564,10 @@ send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force) | |||
564 | * @param fwd Was this a FWD going message? | 564 | * @param fwd Was this a FWD going message? |
565 | * @param size Size of the message. | 565 | * @param size Size of the message. |
566 | * @param wait Time spent waiting for core (only the time for THIS message) | 566 | * @param wait Time spent waiting for core (only the time for THIS message) |
567 | * | ||
568 | * @return #GNUNET_YES if connection was destroyed, #GNUNET_NO otherwise. | ||
567 | */ | 569 | */ |
568 | static void | 570 | static int |
569 | conn_message_sent (void *cls, | 571 | conn_message_sent (void *cls, |
570 | struct CadetConnection *c, int sent, | 572 | struct CadetConnection *c, int sent, |
571 | uint16_t type, uint32_t pid, int fwd, size_t size, | 573 | uint16_t type, uint32_t pid, int fwd, size_t size, |
@@ -609,7 +611,7 @@ conn_message_sent (void *cls, | |||
609 | LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n", | 611 | LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n", |
610 | GC_m2s (type)); | 612 | GC_m2s (type)); |
611 | } | 613 | } |
612 | return; | 614 | return GNUNET_NO; |
613 | } | 615 | } |
614 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages); | 616 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages); |
615 | c->pending_messages--; | 617 | c->pending_messages--; |
@@ -617,7 +619,7 @@ conn_message_sent (void *cls, | |||
617 | { | 619 | { |
618 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! destroying connection!\n"); | 620 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! destroying connection!\n"); |
619 | GCC_destroy (c); | 621 | GCC_destroy (c); |
620 | return; | 622 | return GNUNET_YES; |
621 | } | 623 | } |
622 | /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ | 624 | /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ |
623 | switch (type) | 625 | switch (type) |
@@ -674,7 +676,7 @@ conn_message_sent (void *cls, | |||
674 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n"); | 676 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n"); |
675 | 677 | ||
676 | if (NULL == c->perf) | 678 | if (NULL == c->perf) |
677 | return; /* Only endpoints are interested in timing. */ | 679 | return GNUNET_NO; /* Only endpoints are interested in timing. */ |
678 | 680 | ||
679 | p = c->perf; | 681 | p = c->perf; |
680 | usecsperbyte = ((double) wait.rel_value_us) / size; | 682 | usecsperbyte = ((double) wait.rel_value_us) / size; |
@@ -695,6 +697,7 @@ conn_message_sent (void *cls, | |||
695 | p->avg /= p->size; | 697 | p->avg /= p->size; |
696 | } | 698 | } |
697 | p->idx = (p->idx + 1) % AVG_MSGS; | 699 | p->idx = (p->idx + 1) % AVG_MSGS; |
700 | return GNUNET_NO; | ||
698 | } | 701 | } |
699 | 702 | ||
700 | 703 | ||
@@ -1209,8 +1212,7 @@ poll_sent (void *cls, | |||
1209 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n"); | 1212 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n"); |
1210 | return; | 1213 | return; |
1211 | } | 1214 | } |
1212 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1215 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL sent for , scheduling new one!\n"); |
1213 | " *** POLL sent for , scheduling new one!\n"); | ||
1214 | fc->poll_msg = NULL; | 1216 | fc->poll_msg = NULL; |
1215 | fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); | 1217 | fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); |
1216 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, | 1218 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, |
@@ -1806,8 +1808,7 @@ GCC_handle_broken (void* cls, | |||
1806 | struct GNUNET_CADET_ConnectionBroken *msg; | 1808 | struct GNUNET_CADET_ConnectionBroken *msg; |
1807 | struct CadetConnection *c; | 1809 | struct CadetConnection *c; |
1808 | struct CadetTunnel *t; | 1810 | struct CadetTunnel *t; |
1809 | unsigned int del; | 1811 | int destroyed; |
1810 | int pending; | ||
1811 | int fwd; | 1812 | int fwd; |
1812 | 1813 | ||
1813 | msg = (struct GNUNET_CADET_ConnectionBroken *) message; | 1814 | msg = (struct GNUNET_CADET_ConnectionBroken *) message; |
@@ -1845,28 +1846,21 @@ GCC_handle_broken (void* cls, | |||
1845 | c->state = CADET_CONNECTION_BROKEN; | 1846 | c->state = CADET_CONNECTION_BROKEN; |
1846 | GCT_remove_connection (t, c); | 1847 | GCT_remove_connection (t, c); |
1847 | c->t = NULL; | 1848 | c->t = NULL; |
1848 | pending = c->pending_messages; | 1849 | destroyed = GNUNET_NO; |
1849 | 1850 | ||
1850 | /* GCP_connection_pop will destroy the connection when the last message | 1851 | /* GCP_connection_pop could destroy the connection! */ |
1851 | * is popped! Do not use 'c' after the call. */ | 1852 | while (NULL != (out_msg = GCP_connection_pop (neighbor, c, &destroyed))) |
1852 | while (NULL != (out_msg = GCP_connection_pop (neighbor, c, &del))) | ||
1853 | { | 1853 | { |
1854 | pending -= del + 1; /* Substract the deleted messages + the popped one */ | ||
1855 | GCT_resend_message (out_msg, t); | 1854 | GCT_resend_message (out_msg, t); |
1856 | } | 1855 | } |
1857 | /* All pending messages should have been popped, | 1856 | /* All pending messages should have been popped, |
1858 | * and the connection destroyed by the continuation. | 1857 | * and the connection destroyed by the continuation. |
1859 | * If last message was just deleted, then continuation wasn't called. | ||
1860 | */ | 1858 | */ |
1861 | if (0 < pending || 0 < del) | 1859 | if (GNUNET_YES != destroyed) |
1862 | { | 1860 | { |
1863 | GNUNET_break (0 == pending); | 1861 | GNUNET_break (0); |
1864 | GCC_destroy (c); | 1862 | GCC_destroy (c); |
1865 | } | 1863 | } |
1866 | else | ||
1867 | { | ||
1868 | GNUNET_break (0 == pending); /* If negative: counter error! */ | ||
1869 | } | ||
1870 | } | 1864 | } |
1871 | else | 1865 | else |
1872 | { | 1866 | { |
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c index 90b70aa8e..ce22c20da 100644 --- a/src/cadet/gnunet-service-cadet_peer.c +++ b/src/cadet/gnunet-service-cadet_peer.c | |||
@@ -1074,8 +1074,8 @@ queue_send (void *cls, size_t size, void *buf) | |||
1074 | queue->payload_id, GCC_2s (c), c, GC_f2s (queue->fwd), data_size); | 1074 | queue->payload_id, GCC_2s (c), c, GC_f2s (queue->fwd), data_size); |
1075 | } | 1075 | } |
1076 | 1076 | ||
1077 | /* Free queue, but cls was freed by send_core_* */ | 1077 | /* Free queue, but cls was freed by send_core_*. */ |
1078 | GCP_queue_destroy (queue, GNUNET_NO, GNUNET_YES, pid); | 1078 | (void) GCP_queue_destroy (queue, GNUNET_NO, GNUNET_YES, pid); |
1079 | 1079 | ||
1080 | /* If more data in queue, send next */ | 1080 | /* If more data in queue, send next */ |
1081 | queue = peer_get_first_message (peer); | 1081 | queue = peer_get_first_message (peer); |
@@ -1121,16 +1121,23 @@ queue_send (void *cls, size_t size, void *buf) | |||
1121 | * Free a transmission that was already queued with all resources | 1121 | * Free a transmission that was already queued with all resources |
1122 | * associated to the request. | 1122 | * associated to the request. |
1123 | * | 1123 | * |
1124 | * If connection was marked to be destroyed, and this was the last queued | ||
1125 | * message on it, the connection will be free'd as a result. | ||
1126 | * | ||
1124 | * @param queue Queue handler to cancel. | 1127 | * @param queue Queue handler to cancel. |
1125 | * @param clear_cls Is it necessary to free associated cls? | 1128 | * @param clear_cls Is it necessary to free associated cls? |
1126 | * @param sent Was it really sent? (Could have been canceled) | 1129 | * @param sent Was it really sent? (Could have been canceled) |
1127 | * @param pid PID, if relevant (was sent and was a payload message). | 1130 | * @param pid PID, if relevant (was sent and was a payload message). |
1131 | * | ||
1132 | * @return #GNUNET_YES if connection was destroyed as a result, | ||
1133 | * #GNUNET_NO otherwise. | ||
1128 | */ | 1134 | */ |
1129 | void | 1135 | int |
1130 | GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, | 1136 | GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, |
1131 | int sent, uint32_t pid) | 1137 | int sent, uint32_t pid) |
1132 | { | 1138 | { |
1133 | struct CadetPeer *peer; | 1139 | struct CadetPeer *peer; |
1140 | int connection_destroyed; | ||
1134 | 1141 | ||
1135 | peer = queue->peer; | 1142 | peer = queue->peer; |
1136 | LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy %s\n", GC_m2s (queue->type)); | 1143 | LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy %s\n", GC_m2s (queue->type)); |
@@ -1168,11 +1175,18 @@ GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, | |||
1168 | 1175 | ||
1169 | if (NULL != queue->callback) | 1176 | if (NULL != queue->callback) |
1170 | { | 1177 | { |
1178 | struct GNUNET_TIME_Relative core_wait_time; | ||
1179 | |||
1171 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback\n"); | 1180 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback\n"); |
1172 | queue->callback (queue->callback_cls, | 1181 | core_wait_time = GNUNET_TIME_absolute_get_duration (queue->start_waiting); |
1173 | queue->c, sent, queue->type, pid, | 1182 | connection_destroyed = queue->callback (queue->callback_cls, |
1174 | queue->fwd, queue->size, | 1183 | queue->c, sent, queue->type, pid, |
1175 | GNUNET_TIME_absolute_get_duration (queue->start_waiting)); | 1184 | queue->fwd, queue->size, |
1185 | core_wait_time); | ||
1186 | } | ||
1187 | else | ||
1188 | { | ||
1189 | connection_destroyed = GNUNET_NO; | ||
1176 | } | 1190 | } |
1177 | 1191 | ||
1178 | if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit) | 1192 | if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit) |
@@ -1182,6 +1196,7 @@ GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, | |||
1182 | } | 1196 | } |
1183 | 1197 | ||
1184 | GNUNET_free (queue); | 1198 | GNUNET_free (queue); |
1199 | return connection_destroyed; | ||
1185 | } | 1200 | } |
1186 | 1201 | ||
1187 | 1202 | ||
@@ -1309,20 +1324,23 @@ GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c) | |||
1309 | struct CadetPeerQueue *q; | 1324 | struct CadetPeerQueue *q; |
1310 | struct CadetPeerQueue *next; | 1325 | struct CadetPeerQueue *next; |
1311 | struct CadetPeerQueue *prev; | 1326 | struct CadetPeerQueue *prev; |
1327 | int connection_destroyed; | ||
1312 | 1328 | ||
1329 | connection_destroyed = GNUNET_NO; | ||
1313 | for (q = peer->queue_head; NULL != q; q = next) | 1330 | for (q = peer->queue_head; NULL != q; q = next) |
1314 | { | 1331 | { |
1315 | prev = q->prev; | 1332 | prev = q->prev; |
1316 | if (q->c == c) | 1333 | if (q->c == c) |
1317 | { | 1334 | { |
1318 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GC_m2s (q->type)); | 1335 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GC_m2s (q->type)); |
1336 | GNUNET_break (GNUNET_NO == connection_destroyed); | ||
1319 | if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY == q->type) | 1337 | if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY == q->type) |
1320 | { | 1338 | { |
1321 | q->c = NULL; | 1339 | q->c = NULL; |
1322 | } | 1340 | } |
1323 | else | 1341 | else |
1324 | { | 1342 | { |
1325 | GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); | 1343 | connection_destroyed = GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); |
1326 | } | 1344 | } |
1327 | 1345 | ||
1328 | /* Get next from prev, q->next might be already freed: | 1346 | /* Get next from prev, q->next might be already freed: |
@@ -1338,13 +1356,11 @@ GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c) | |||
1338 | next = q->next; | 1356 | next = q->next; |
1339 | } | 1357 | } |
1340 | } | 1358 | } |
1341 | if (NULL == peer->queue_head) | 1359 | |
1360 | if (NULL == peer->queue_head && NULL != peer->core_transmit) | ||
1342 | { | 1361 | { |
1343 | if (NULL != peer->core_transmit) | 1362 | GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit); |
1344 | { | 1363 | peer->core_transmit = NULL; |
1345 | GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit); | ||
1346 | peer->core_transmit = NULL; | ||
1347 | } | ||
1348 | } | 1364 | } |
1349 | } | 1365 | } |
1350 | 1366 | ||
@@ -1382,28 +1398,28 @@ connection_get_first_message (struct CadetPeer *peer, struct CadetConnection *c) | |||
1382 | * Get the first message for a connection and unqueue it. | 1398 | * Get the first message for a connection and unqueue it. |
1383 | * | 1399 | * |
1384 | * Only tunnel (or higher) level messages are unqueued. Connection specific | 1400 | * Only tunnel (or higher) level messages are unqueued. Connection specific |
1385 | * messages are destroyed and the count given to the caller. | 1401 | * messages are silently destroyed upon encounter. |
1386 | * | 1402 | * |
1387 | * @param peer Neighboring peer. | 1403 | * @param peer Neighboring peer. |
1388 | * @param c Connection. | 1404 | * @param c Connection. |
1389 | * @param del[out] How many messages have been deleted without returning. | 1405 | * @param destroyed[in/out] Was the connection destroyed (prev/as a result)?. |
1390 | * Can be NULL. | ||
1391 | * | 1406 | * |
1392 | * @return First message for this connection. | 1407 | * @return First message for this connection. |
1393 | */ | 1408 | */ |
1394 | struct GNUNET_MessageHeader * | 1409 | struct GNUNET_MessageHeader * |
1395 | GCP_connection_pop (struct CadetPeer *peer, | 1410 | GCP_connection_pop (struct CadetPeer *peer, |
1396 | struct CadetConnection *c, | 1411 | struct CadetConnection *c, |
1397 | unsigned int *del) | 1412 | int *destroyed) |
1398 | { | 1413 | { |
1399 | struct CadetPeerQueue *q; | 1414 | struct CadetPeerQueue *q; |
1400 | struct CadetPeerQueue *next; | 1415 | struct CadetPeerQueue *next; |
1401 | struct GNUNET_MessageHeader *msg; | 1416 | struct GNUNET_MessageHeader *msg; |
1417 | int dest; | ||
1402 | 1418 | ||
1403 | if (NULL != del) *del = 0; | ||
1404 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection pop on connection %p\n", c); | 1419 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection pop on connection %p\n", c); |
1405 | for (q = peer->queue_head; NULL != q; q = next) | 1420 | for (q = peer->queue_head; NULL != q; q = next) |
1406 | { | 1421 | { |
1422 | GNUNET_break (NULL == destroyed || GNUNET_NO == *destroyed); | ||
1407 | next = q->next; | 1423 | next = q->next; |
1408 | if (q->c != c) | 1424 | if (q->c != c) |
1409 | continue; | 1425 | continue; |
@@ -1415,14 +1431,17 @@ GCP_connection_pop (struct CadetPeer *peer, | |||
1415 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | 1431 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: |
1416 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | 1432 | case GNUNET_MESSAGE_TYPE_CADET_ACK: |
1417 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | 1433 | case GNUNET_MESSAGE_TYPE_CADET_POLL: |
1418 | GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); | 1434 | dest = GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); |
1419 | if (NULL != del) *del = *del + 1; | 1435 | if (NULL != destroyed && GNUNET_YES == dest) |
1436 | *destroyed = GNUNET_YES; | ||
1420 | continue; | 1437 | continue; |
1421 | 1438 | ||
1422 | case GNUNET_MESSAGE_TYPE_CADET_KX: | 1439 | case GNUNET_MESSAGE_TYPE_CADET_KX: |
1423 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | 1440 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: |
1424 | msg = (struct GNUNET_MessageHeader *) q->cls; | 1441 | msg = (struct GNUNET_MessageHeader *) q->cls; |
1425 | GCP_queue_destroy (q, GNUNET_NO, GNUNET_NO, 0); | 1442 | dest = GCP_queue_destroy (q, GNUNET_NO, GNUNET_NO, 0); |
1443 | if (NULL != destroyed && GNUNET_YES == dest) | ||
1444 | *destroyed = GNUNET_YES; | ||
1426 | return msg; | 1445 | return msg; |
1427 | 1446 | ||
1428 | default: | 1447 | default: |
diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h index e581685fa..ea64665d4 100644 --- a/src/cadet/gnunet-service-cadet_peer.h +++ b/src/cadet/gnunet-service-cadet_peer.h | |||
@@ -63,8 +63,10 @@ struct CadetPeerQueue; | |||
63 | * @param fwd Was this a FWD going message? | 63 | * @param fwd Was this a FWD going message? |
64 | * @param size Size of the message. | 64 | * @param size Size of the message. |
65 | * @param wait Time spent waiting for core (only the time for THIS message) | 65 | * @param wait Time spent waiting for core (only the time for THIS message) |
66 | * | ||
67 | * @return #GNUNET_YES if connection was destroyed, #GNUNET_NO otherwise. | ||
66 | */ | 68 | */ |
67 | typedef void (*GCP_sent) (void *cls, | 69 | typedef int (*GCP_sent) (void *cls, |
68 | struct CadetConnection *c, int sent, | 70 | struct CadetConnection *c, int sent, |
69 | uint16_t type, uint32_t pid, int fwd, size_t size, | 71 | uint16_t type, uint32_t pid, int fwd, size_t size, |
70 | struct GNUNET_TIME_Relative wait); | 72 | struct GNUNET_TIME_Relative wait); |
@@ -125,12 +127,18 @@ GCP_connect (struct CadetPeer *peer); | |||
125 | * Free a transmission that was already queued with all resources | 127 | * Free a transmission that was already queued with all resources |
126 | * associated to the request. | 128 | * associated to the request. |
127 | * | 129 | * |
130 | * If connection was marked to be destroyed, and this was the last queued | ||
131 | * message on it, the connection will be free'd as a result. | ||
132 | * | ||
128 | * @param queue Queue handler to cancel. | 133 | * @param queue Queue handler to cancel. |
129 | * @param clear_cls Is it necessary to free associated cls? | 134 | * @param clear_cls Is it necessary to free associated cls? |
130 | * @param sent Was it really sent? (Could have been canceled) | 135 | * @param sent Was it really sent? (Could have been canceled) |
131 | * @param pid PID, if relevant (was sent and was a payload message). | 136 | * @param pid PID, if relevant (was sent and was a payload message). |
137 | * | ||
138 | * @return #GNUNET_YES if connection was destroyed as a result, | ||
139 | * #GNUNET_NO otherwise. | ||
132 | */ | 140 | */ |
133 | void | 141 | int |
134 | GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, | 142 | GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, |
135 | int sent, uint32_t pid); | 143 | int sent, uint32_t pid); |
136 | 144 | ||
@@ -170,19 +178,18 @@ GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c); | |||
170 | * Get the first message for a connection and unqueue it. | 178 | * Get the first message for a connection and unqueue it. |
171 | * | 179 | * |
172 | * Only tunnel (or higher) level messages are unqueued. Connection specific | 180 | * Only tunnel (or higher) level messages are unqueued. Connection specific |
173 | * messages are destroyed and the count given to the caller. | 181 | * messages are silently destroyed upon encounter. |
174 | * | 182 | * |
175 | * @param peer Neighboring peer. | 183 | * @param peer Neighboring peer. |
176 | * @param c Connection. | 184 | * @param c Connection. |
177 | * @param del[out] How many messages have been deleted without returning. | 185 | * @param destroyed[out] Was the connection destroyed as a result?. |
178 | * Can be NULL. | ||
179 | * | 186 | * |
180 | * @return First message for this connection. | 187 | * @return First message for this connection. |
181 | */ | 188 | */ |
182 | struct GNUNET_MessageHeader * | 189 | struct GNUNET_MessageHeader * |
183 | GCP_connection_pop (struct CadetPeer *peer, | 190 | GCP_connection_pop (struct CadetPeer *peer, |
184 | struct CadetConnection *c, | 191 | struct CadetConnection *c, |
185 | unsigned int *del); | 192 | int *destroyed); |
186 | 193 | ||
187 | /** | 194 | /** |
188 | * Unlock a possibly locked queue for a connection. | 195 | * Unlock a possibly locked queue for a connection. |