diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-01-27 14:07:49 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-01-27 14:07:49 +0100 |
commit | d3b0b69e7d360b4b82c5a5580a7ea21317dfee24 (patch) | |
tree | 894eccdb39ed57e1fadc0bb12a7fabd2b1ede244 /src/cadet/gnunet-service-cadet-new_connection.c | |
parent | 052c4fcb11913cad4baa3a4fa2032b2ae2f386e3 (diff) | |
download | gnunet-d3b0b69e7d360b4b82c5a5580a7ea21317dfee24.tar.gz gnunet-d3b0b69e7d360b4b82c5a5580a7ea21317dfee24.zip |
implement tie-breaking in case both peers establish a connection to each other via the same path at the same time, so that only one connection survives
Diffstat (limited to 'src/cadet/gnunet-service-cadet-new_connection.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_connection.c | 119 |
1 files changed, 104 insertions, 15 deletions
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c index 5f1ff61e1..a098674f5 100644 --- a/src/cadet/gnunet-service-cadet-new_connection.c +++ b/src/cadet/gnunet-service-cadet-new_connection.c | |||
@@ -158,31 +158,21 @@ struct CadetConnection | |||
158 | 158 | ||
159 | 159 | ||
160 | /** | 160 | /** |
161 | * Destroy a connection. | 161 | * Destroy a connection, part of the internal implementation. Called |
162 | * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel(). | ||
162 | * | 163 | * |
163 | * @param cc connection to destroy | 164 | * @param cc connection to destroy |
164 | */ | 165 | */ |
165 | void | 166 | static void |
166 | GCC_destroy (struct CadetConnection *cc) | 167 | GCC_destroy (struct CadetConnection *cc) |
167 | { | 168 | { |
168 | struct GNUNET_MQ_Envelope *env = NULL; | ||
169 | |||
170 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 169 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
171 | "Destroying %s\n", | 170 | "Destroying %s\n", |
172 | GCC_2s (cc)); | 171 | GCC_2s (cc)); |
173 | if (CADET_CONNECTION_SENDING_CREATE != cc->state) | ||
174 | { | ||
175 | struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg; | ||
176 | |||
177 | /* Need to notify next hop that we are down. */ | ||
178 | env = GNUNET_MQ_msg (destroy_msg, | ||
179 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | ||
180 | destroy_msg->cid = cc->cid; | ||
181 | } | ||
182 | if (NULL != cc->mq_man) | 172 | if (NULL != cc->mq_man) |
183 | { | 173 | { |
184 | GCP_request_mq_cancel (cc->mq_man, | 174 | GCP_request_mq_cancel (cc->mq_man, |
185 | env); | 175 | NULL); |
186 | cc->mq_man = NULL; | 176 | cc->mq_man = NULL; |
187 | } | 177 | } |
188 | if (NULL != cc->task) | 178 | if (NULL != cc->task) |
@@ -206,6 +196,56 @@ GCC_destroy (struct CadetConnection *cc) | |||
206 | } | 196 | } |
207 | 197 | ||
208 | 198 | ||
199 | |||
200 | /** | ||
201 | * Destroy a connection, called when the CORE layer is already done | ||
202 | * (i.e. has received a BROKEN message), but if we still have to | ||
203 | * communicate the destruction of the connection to the tunnel (if one | ||
204 | * exists). | ||
205 | * | ||
206 | * @param cc connection to destroy | ||
207 | */ | ||
208 | void | ||
209 | GCC_destroy_without_core (struct CadetConnection *cc) | ||
210 | { | ||
211 | if (NULL != cc->ct) | ||
212 | { | ||
213 | GCT_connection_lost (cc->ct); | ||
214 | cc->ct = NULL; | ||
215 | } | ||
216 | GCC_destroy (cc); | ||
217 | } | ||
218 | |||
219 | |||
220 | /** | ||
221 | * Destroy a connection, called if the tunnel association with the | ||
222 | * connection was already broken, but we still need to notify the CORE | ||
223 | * layer about the breakage. | ||
224 | * | ||
225 | * @param cc connection to destroy | ||
226 | */ | ||
227 | void | ||
228 | GCC_destroy_without_tunnel (struct CadetConnection *cc) | ||
229 | { | ||
230 | cc->ct = NULL; | ||
231 | if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) && | ||
232 | (NULL != cc->mq_man) ) | ||
233 | { | ||
234 | struct GNUNET_MQ_Envelope *env; | ||
235 | struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg; | ||
236 | |||
237 | /* Need to notify next hop that we are down. */ | ||
238 | env = GNUNET_MQ_msg (destroy_msg, | ||
239 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | ||
240 | destroy_msg->cid = cc->cid; | ||
241 | GCP_request_mq_cancel (cc->mq_man, | ||
242 | env); | ||
243 | cc->mq_man = NULL; | ||
244 | } | ||
245 | GCC_destroy (cc); | ||
246 | } | ||
247 | |||
248 | |||
209 | /** | 249 | /** |
210 | * Return the tunnel associated with this connection. | 250 | * Return the tunnel associated with this connection. |
211 | * | 251 | * |
@@ -630,7 +670,8 @@ connection_create (struct CadetPeer *destination, | |||
630 | * @param ct which tunnel uses this connection | 670 | * @param ct which tunnel uses this connection |
631 | * @param ready_cb function to call when ready to transmit | 671 | * @param ready_cb function to call when ready to transmit |
632 | * @param ready_cb_cls closure for @a cb | 672 | * @param ready_cb_cls closure for @a cb |
633 | * @return handle to the connection | 673 | * @return handle to the connection, NULL if we already have |
674 | * a connection that takes precedence on @a path | ||
634 | */ | 675 | */ |
635 | struct CadetConnection * | 676 | struct CadetConnection * |
636 | GCC_create_inbound (struct CadetPeer *destination, | 677 | GCC_create_inbound (struct CadetPeer *destination, |
@@ -640,6 +681,54 @@ GCC_create_inbound (struct CadetPeer *destination, | |||
640 | GCC_ReadyCallback ready_cb, | 681 | GCC_ReadyCallback ready_cb, |
641 | void *ready_cb_cls) | 682 | void *ready_cb_cls) |
642 | { | 683 | { |
684 | struct CadetConnection *cc; | ||
685 | unsigned int off; | ||
686 | |||
687 | off = GCPP_find_peer (path, | ||
688 | destination); | ||
689 | GNUNET_assert (UINT_MAX != off); | ||
690 | cc = GCPP_get_connection (path, | ||
691 | destination, | ||
692 | off); | ||
693 | if (NULL != cc) | ||
694 | { | ||
695 | int cmp; | ||
696 | |||
697 | cmp = memcmp (cid, | ||
698 | &cc->cid, | ||
699 | sizeof (*cid)); | ||
700 | if (0 == cmp) | ||
701 | { | ||
702 | /* Two peers picked the SAME random connection identifier at the | ||
703 | same time for the same path? Must be malicious. Drop | ||
704 | connection (existing and inbound), even if it is the only | ||
705 | one. */ | ||
706 | GNUNET_break_op (0); | ||
707 | GCT_connection_lost (cc->ct); | ||
708 | GCC_destroy_without_tunnel (cc); | ||
709 | return NULL; | ||
710 | } | ||
711 | if (0 < cmp) | ||
712 | { | ||
713 | /* drop existing */ | ||
714 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
715 | "Got two connections on %s, dropping my existing %s\n", | ||
716 | GCPP_2s (path), | ||
717 | GCC_2s (cc)); | ||
718 | GCT_connection_lost (cc->ct); | ||
719 | GCC_destroy_without_tunnel (cc); | ||
720 | } | ||
721 | else | ||
722 | { | ||
723 | /* keep existing */ | ||
724 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
725 | "Got two connections on %s, keeping my existing %s\n", | ||
726 | GCPP_2s (path), | ||
727 | GCC_2s (cc)); | ||
728 | return NULL; | ||
729 | } | ||
730 | } | ||
731 | |||
643 | return connection_create (destination, | 732 | return connection_create (destination, |
644 | path, | 733 | path, |
645 | ct, | 734 | ct, |