aboutsummaryrefslogtreecommitdiff
path: root/src/cadet/gnunet-service-cadet-new_connection.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-01-27 14:07:49 +0100
committerChristian Grothoff <christian@grothoff.org>2017-01-27 14:07:49 +0100
commitd3b0b69e7d360b4b82c5a5580a7ea21317dfee24 (patch)
tree894eccdb39ed57e1fadc0bb12a7fabd2b1ede244 /src/cadet/gnunet-service-cadet-new_connection.c
parent052c4fcb11913cad4baa3a4fa2032b2ae2f386e3 (diff)
downloadgnunet-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.c119
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 */
165void 166static void
166GCC_destroy (struct CadetConnection *cc) 167GCC_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 */
208void
209GCC_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 */
227void
228GCC_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 */
635struct CadetConnection * 676struct CadetConnection *
636GCC_create_inbound (struct CadetPeer *destination, 677GCC_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,