This file is part of GNUnet.
Copyright (C) 2017 GNUnet e.V.
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
+ SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
(NULL != dir->env_head) )
discard_buffer (dir,
dir->env_head);
+ /* Check for duplicates */
+ for (const struct GNUNET_MQ_Envelope *env = dir->env_head;
+ NULL != env;
+ env = GNUNET_MQ_env_next (env))
+ {
+ const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env);
+
+ if ( (hdr->size == msg->size) &&
+ (0 == memcmp (hdr,
+ msg,
+ ntohs (msg->size))) )
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received duplicate of message already in buffer, dropping\n");
+ GNUNET_STATISTICS_update (stats,
+ "# messages dropped due to duplicate in buffer",
+ 1,
+ GNUNET_NO);
+ return;
+ }
+ }
+
rung = dir->rung;
if (cur_buffers == max_buffers)
{
GNUNET_CONTAINER_DLL_remove (rung->rd_head,
rung->rd_tail,
dir);
- /* make 'nxt' point to the next higher rung, creat if necessary */
+ /* make 'nxt' point to the next higher rung, create if necessary */
nxt = rung->next;
if ( (NULL == nxt) ||
(rung->rung_off + 1 != nxt->rung_off) )
{
exp = GNUNET_TIME_absolute_add (r->last_use,
linger);
- if (0 != GNUNET_TIME_absolute_get_duration (exp).rel_value_us)
+ if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
{
/* Route not yet timed out, wait until it does. */
timeout_task = GNUNET_SCHEDULER_add_at (exp,
NULL);
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Sending BROKEN due to timeout (%s was last use, %s linger)\n",
+ GNUNET_STRINGS_absolute_time_to_string (r->last_use),
+ GNUNET_STRINGS_relative_time_to_string (linger,
+ GNUNET_YES));
send_broken (&r->prev,
&r->cid,
NULL,
return;
}
odir = (dir == &route->next) ? &route->prev : &route->next;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending BROKEN due to MQ going down\n");
send_broken (&route->next,
&route->cid,
GCP_get_id (odir->hop),
path_length = size / sizeof (struct GNUNET_PeerIdentity);
if (0 == path_length)
{
- /* bogus request */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Dropping CADET_CONNECTION_CREATE with empty path\n");
GNUNET_break_op (0);
return;
}
- /* Initiator is at offset 0. */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n",
+ GCP_2s (sender),
+ GNUNET_sh2s (&msg->cid.connection_of_tunnel),
+ path_length);
+ /* Check for loops */
+ {
+ struct GNUNET_CONTAINER_MultiPeerMap *map;
+
+ map = GNUNET_CONTAINER_multipeermap_create (path_length * 2,
+ GNUNET_YES);
+ GNUNET_assert (NULL != map);
+ for (unsigned int i=0;i<path_length;i++)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "CADET_CONNECTION_CREATE has peer %s at offset %u\n",
+ GNUNET_i2s (&pids[i]),
+ i);
+ if (GNUNET_SYSERR ==
+ GNUNET_CONTAINER_multipeermap_put (map,
+ &pids[i],
+ NULL,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+ {
+ /* bogus request */
+ GNUNET_CONTAINER_multipeermap_destroy (map);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
+ GNUNET_break_op (0);
+ return;
+ }
+ }
+ GNUNET_CONTAINER_multipeermap_destroy (map);
+ }
+ /* Initiator is at offset 0, find us */
for (off=1;off<path_length;off++)
- if (0 == memcmp (&my_full_id,
- &pids[off],
- sizeof (struct GNUNET_PeerIdentity)))
+ if (0 == GNUNET_memcmp (&my_full_id,
+ &pids[off]))
break;
if (off == path_length)
{
- /* We are not on the path, bogus request */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Dropping CADET_CONNECTION_CREATE without us in the path\n");
GNUNET_break_op (0);
return;
}
if (sender != GCP_get (&pids[off - 1],
GNUNET_NO))
{
- /* sender is not on the path, not allowed */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n");
GNUNET_break_op (0);
return;
}
if (NULL !=
- get_route (&msg->cid))
+ (route = get_route (&msg->cid)))
{
/* Duplicate CREATE, pass it on, previous one might have been lost! */
+
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
GNUNET_sh2s (&msg->cid.connection_of_tunnel));
origin = GCP_get (&pids[0],
GNUNET_YES);
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Received CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
+ "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
GCP_2s (origin),
GNUNET_sh2s (&msg->cid.connection_of_tunnel));
path = GCPP_get_path_from_route (path_length - 1,
3),
&timeout_cb,
NULL);
+ /* also pass CREATE message along to next hop */
+ route_message (sender,
+ &msg->cid,
+ &msg->header);
}
if (NULL != cc)
{
/* verify ACK came from the right direction */
- struct CadetPeerPath *path = GCC_get_path (cc);
+ unsigned int len;
+ struct CadetPeerPath *path = GCC_get_path (cc,
+ &len);
if (peer !=
GCPP_get_peer_at_offset (path,
if (NULL != cc)
{
/* verify message came from the right direction */
- struct CadetPeerPath *path = GCC_get_path (cc);
+ unsigned int len;
+ struct CadetPeerPath *path = GCC_get_path (cc,
+ &len);
if (peer !=
GCPP_get_peer_at_offset (path,
if (NULL != cc)
{
/* verify message came from the right direction */
- struct CadetPeerPath *path = GCC_get_path (cc);
+ unsigned int len;
+ struct CadetPeerPath *path = GCC_get_path (cc,
+ &len);
if (peer !=
GCPP_get_peer_at_offset (path,
struct CadetConnection *cc;
/* First, check if message belongs to a connection that ends here. */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Routing KX with ephemeral %s on CID %s\n",
+ GNUNET_e2s (&msg->ephemeral_key),
+ GNUNET_sh2s (&msg->cid.connection_of_tunnel));
+
+
cc = GCC_lookup (&msg->cid);
if (NULL != cc)
{
/* verify message came from the right direction */
- struct CadetPeerPath *path = GCC_get_path (cc);
+ unsigned int len;
+ struct CadetPeerPath *path = GCC_get_path (cc,
+ &len);
if (peer !=
GCPP_get_peer_at_offset (path,
if (NULL != cc)
{
/* verify message came from the right direction */
- struct CadetPeerPath *path = GCC_get_path (cc);
+ unsigned int len;
+ struct CadetPeerPath *path = GCC_get_path (cc,
+ &len);
if (peer !=
GCPP_get_peer_at_offset (path,
if (NULL != cc)
{
/* verify message came from the right direction */
- struct CadetPeerPath *path = GCC_get_path (cc);
+ unsigned int len;
+ struct CadetPeerPath *path = GCC_get_path (cc,
+ &len);
if (peer !=
GCPP_get_peer_at_offset (path,
return;
}
GNUNET_break (0 ==
- memcmp (my_identity,
- &my_full_id,
- sizeof (struct GNUNET_PeerIdentity)));
+ GNUNET_memcmp (my_identity,
+ &my_full_id));
}