123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2001-2013, 2017 GNUnet e.V.
- 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
- 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/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @file cadet/gnunet-service-cadet.c
- * @brief GNUnet CADET service with encryption
- * @author Bartlomiej Polot
- * @author Christian Grothoff
- *
- * Dictionary:
- * - peer: other cadet instance. If there is direct connection it's a neighbor.
- * - path: series of directly connected peer from one peer to another.
- * - connection: path which is being used in a tunnel.
- * - tunnel: encrypted connection to a peer, neighbor or not.
- * - channel: logical link between two clients, on the same or different peers.
- * have properties like reliability.
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "cadet.h"
- #include "gnunet_statistics_service.h"
- #include "gnunet-service-cadet.h"
- #include "gnunet-service-cadet_channel.h"
- #include "gnunet-service-cadet_connection.h"
- #include "gnunet-service-cadet_core.h"
- #include "gnunet-service-cadet_dht.h"
- #include "gnunet-service-cadet_hello.h"
- #include "gnunet-service-cadet_tunnels.h"
- #include "gnunet-service-cadet_peer.h"
- #include "gnunet-service-cadet_paths.h"
- #define LOG(level, ...) GNUNET_log (level,__VA_ARGS__)
- /**
- * Struct containing information about a client of the service
- */
- struct CadetClient
- {
- /**
- * Linked list next
- */
- struct CadetClient *next;
- /**
- * Linked list prev
- */
- struct CadetClient *prev;
- /**
- * Tunnels that belong to this client, indexed by local id,
- * value is a `struct CadetChannel`.
- */
- struct GNUNET_CONTAINER_MultiHashMap32 *channels;
- /**
- * Handle to communicate with the client
- */
- struct GNUNET_MQ_Handle *mq;
- /**
- * Client handle.
- */
- struct GNUNET_SERVICE_Client *client;
- /**
- * Ports that this client has declared interest in.
- * Indexed by port, contains `struct OpenPort`
- */
- struct GNUNET_CONTAINER_MultiHashMap *ports;
- /**
- * Channel ID to use for the next incoming channel for this client.
- * Wraps around (in theory).
- */
- struct GNUNET_CADET_ClientChannelNumber next_ccn;
- /**
- * ID of the client, mainly for debug messages. Purely internal to this file.
- */
- unsigned int id;
- };
- /******************************************************************************/
- /*********************** GLOBAL VARIABLES ****************************/
- /******************************************************************************/
- /****************************** Global variables ******************************/
- /**
- * Handle to our configuration.
- */
- const struct GNUNET_CONFIGURATION_Handle *cfg;
- /**
- * Handle to the statistics service.
- */
- struct GNUNET_STATISTICS_Handle *stats;
- /**
- * Handle to communicate with ATS.
- */
- struct GNUNET_ATS_ConnectivityHandle *ats_ch;
- /**
- * Local peer own ID.
- */
- struct GNUNET_PeerIdentity my_full_id;
- /**
- * Own private key.
- */
- struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
- /**
- * Signal that shutdown is happening: prevent recovery measures.
- */
- int shutting_down;
- /**
- * DLL with all the clients, head.
- */
- static struct CadetClient *clients_head;
- /**
- * DLL with all the clients, tail.
- */
- static struct CadetClient *clients_tail;
- /**
- * Next ID to assign to a client.
- */
- static unsigned int next_client_id;
- /**
- * All ports clients of this peer have opened. Maps from
- * a hashed port to a `struct OpenPort`.
- */
- struct GNUNET_CONTAINER_MultiHashMap *open_ports;
- /**
- * Map from ports to channels where the ports were closed at the
- * time we got the inbound connection.
- * Indexed by h_port, contains `struct CadetChannel`.
- */
- struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
- /**
- * Map from PIDs to `struct CadetPeer` entries.
- */
- struct GNUNET_CONTAINER_MultiPeerMap *peers;
- /**
- * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
- * hash codes to `struct CadetConnection` objects.
- */
- struct GNUNET_CONTAINER_MultiShortmap *connections;
- /**
- * How many messages are needed to trigger an AXOLOTL ratchet advance.
- */
- unsigned long long ratchet_messages;
- /**
- * How long until we trigger a ratched advance due to time.
- */
- struct GNUNET_TIME_Relative ratchet_time;
- /**
- * How frequently do we send KEEPALIVE messages on idle connections?
- */
- struct GNUNET_TIME_Relative keepalive_period;
- /**
- * Set to non-zero values to create random drops to test retransmissions.
- */
- unsigned long long drop_percent;
- /**
- * Send a message to a client.
- *
- * @param c client to get the message
- * @param env envelope with the message
- */
- void
- GSC_send_to_client (struct CadetClient *c,
- struct GNUNET_MQ_Envelope *env)
- {
- GNUNET_MQ_send (c->mq,
- env);
- }
- /**
- * Return identifier for a client as a string.
- *
- * @param c client to identify
- * @return string for debugging
- */
- const char *
- GSC_2s (struct CadetClient *c)
- {
- static char buf[32];
- GNUNET_snprintf (buf,
- sizeof (buf),
- "Client(%u)",
- c->id);
- return buf;
- }
- /**
- * Lookup channel of client @a c by @a ccn.
- *
- * @param c client to look in
- * @param ccn channel ID to look up
- * @return NULL if no such channel exists
- */
- static struct CadetChannel *
- lookup_channel (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber ccn)
- {
- return GNUNET_CONTAINER_multihashmap32_get (c->channels,
- ntohl (ccn.channel_of_client));
- }
- /**
- * Obtain the next LID to use for incoming connections to
- * the given client.
- *
- * @param c client handle
- */
- static struct GNUNET_CADET_ClientChannelNumber
- client_get_next_ccn (struct CadetClient *c)
- {
- struct GNUNET_CADET_ClientChannelNumber ccn = c->next_ccn;
- /* increment until we have a free one... */
- while (NULL !=
- lookup_channel (c,
- ccn))
- {
- ccn.channel_of_client
- = htonl (1 + (ntohl (ccn.channel_of_client)));
- if (ntohl (ccn.channel_of_client) >=
- GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- ccn.channel_of_client = htonl (0);
- }
- c->next_ccn.channel_of_client
- = htonl (1 + (ntohl (ccn.channel_of_client)));
- return ccn;
- }
- /**
- * Bind incoming channel to this client, and notify client about
- * incoming connection. Caller is responsible for notifying the other
- * peer about our acceptance of the channel.
- *
- * @param c client to bind to
- * @param ch channel to be bound
- * @param dest peer that establishes the connection
- * @param port port number
- * @param options options
- * @return local channel number assigned to the new client
- */
- struct GNUNET_CADET_ClientChannelNumber
- GSC_bind (struct CadetClient *c,
- struct CadetChannel *ch,
- struct CadetPeer *dest,
- const struct GNUNET_HashCode *port,
- uint32_t options)
- {
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_CADET_LocalChannelCreateMessage *cm;
- struct GNUNET_CADET_ClientChannelNumber ccn;
- ccn = client_get_next_ccn (c);
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_put (c->channels,
- ntohl (ccn.channel_of_client),
- ch,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Accepting incoming %s from %s on open port %s (%u), assigning ccn %X\n",
- GCCH_2s (ch),
- GCP_2s (dest),
- GNUNET_h2s (port),
- (uint32_t) ntohl (options),
- (uint32_t) ntohl (ccn.channel_of_client));
- /* notify local client about incoming connection! */
- env = GNUNET_MQ_msg (cm,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
- cm->ccn = ccn;
- cm->port = *port;
- cm->opt = htonl (options);
- cm->peer = *GCP_get_id (dest);
- GSC_send_to_client (c,
- env);
- return ccn;
- }
- /**
- * Callback invoked on all peers to destroy all tunnels
- * that may still exist.
- *
- * @param cls NULL
- * @param pid identify of a peer
- * @param value a `struct CadetPeer` that may still have a tunnel
- * @return #GNUNET_OK (iterate over all entries)
- */
- static int
- destroy_tunnels_now (void *cls,
- const struct GNUNET_PeerIdentity *pid,
- void *value)
- {
- struct CadetPeer *cp = value;
- struct CadetTunnel *t = GCP_get_tunnel (cp,
- GNUNET_NO);
- if (NULL != t)
- GCT_destroy_tunnel_now (t);
- return GNUNET_OK;
- }
- /**
- * Callback invoked on all peers to destroy all tunnels
- * that may still exist.
- *
- * @param cls NULL
- * @param pid identify of a peer
- * @param value a `struct CadetPeer` that may still have a tunnel
- * @return #GNUNET_OK (iterate over all entries)
- */
- static int
- destroy_paths_now (void *cls,
- const struct GNUNET_PeerIdentity *pid,
- void *value)
- {
- struct CadetPeer *cp = value;
- GCP_drop_owned_paths (cp);
- return GNUNET_OK;
- }
- /**
- * Shutdown everything once the clients have disconnected.
- */
- static void
- shutdown_rest ()
- {
- if (NULL != stats)
- {
- GNUNET_STATISTICS_destroy (stats,
- GNUNET_NO);
- stats = NULL;
- }
- /* Destroy tunnels. Note that all channels must be destroyed first! */
- GCP_iterate_all (&destroy_tunnels_now,
- NULL);
- /* All tunnels, channels, connections and CORE must be down before this point. */
- GCP_iterate_all (&destroy_paths_now,
- NULL);
- /* All paths, tunnels, channels, connections and CORE must be down before this point. */
- GCP_destroy_all_peers ();
- if (NULL != open_ports)
- {
- GNUNET_CONTAINER_multihashmap_destroy (open_ports);
- open_ports = NULL;
- }
- if (NULL != loose_channels)
- {
- GNUNET_CONTAINER_multihashmap_destroy (loose_channels);
- loose_channels = NULL;
- }
- if (NULL != peers)
- {
- GNUNET_CONTAINER_multipeermap_destroy (peers);
- peers = NULL;
- }
- if (NULL != connections)
- {
- GNUNET_CONTAINER_multishortmap_destroy (connections);
- connections = NULL;
- }
- if (NULL != ats_ch)
- {
- GNUNET_ATS_connectivity_done (ats_ch);
- ats_ch = NULL;
- }
- GCD_shutdown ();
- GCH_shutdown ();
- GNUNET_free_non_null (my_private_key);
- my_private_key = NULL;
- }
- /**
- * Task run during shutdown.
- *
- * @param cls unused
- */
- static void
- shutdown_task (void *cls)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Shutting down\n");
- shutting_down = GNUNET_YES;
- GCO_shutdown ();
- if (NULL == clients_head)
- shutdown_rest ();
- }
- /**
- * We had a remote connection @a value to port @a h_port before
- * client @a cls opened port @a port. Bind them now.
- *
- * @param cls the `struct CadetClient`
- * @param h_port the hashed port
- * @param value the `struct CadetChannel`
- * @return #GNUNET_YES (iterate over all such channels)
- */
- static int
- bind_loose_channel (void *cls,
- const struct GNUNET_HashCode *port,
- void *value)
- {
- struct OpenPort *op = cls;
- struct CadetChannel *ch = value;
- GCCH_bind (ch,
- op->c,
- &op->port);
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (loose_channels,
- &op->h_port,
- ch));
- return GNUNET_YES;
- }
- /**
- * Handle port open request. Creates a mapping from the
- * port to the respective client and checks whether we have
- * loose channels trying to bind to the port. If so, those
- * are bound.
- *
- * @param cls Identification of the client.
- * @param pmsg The actual message.
- */
- static void
- handle_port_open (void *cls,
- const struct GNUNET_CADET_PortMessage *pmsg)
- {
- struct CadetClient *c = cls;
- struct OpenPort *op;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Open port %s requested by %s\n",
- GNUNET_h2s (&pmsg->port),
- GSC_2s (c));
- if (NULL == c->ports)
- c->ports = GNUNET_CONTAINER_multihashmap_create (4,
- GNUNET_NO);
- op = GNUNET_new (struct OpenPort);
- op->c = c;
- op->port = pmsg->port;
- GCCH_hash_port (&op->h_port,
- &pmsg->port,
- &my_full_id);
- if (GNUNET_OK !=
- GNUNET_CONTAINER_multihashmap_put (c->ports,
- &op->port,
- op,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
- {
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (c->client);
- return;
- }
- (void) GNUNET_CONTAINER_multihashmap_put (open_ports,
- &op->h_port,
- op,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels,
- &op->h_port,
- &bind_loose_channel,
- op);
- GNUNET_SERVICE_client_continue (c->client);
- }
- /**
- * Handler for port close requests. Marks this port as closed
- * (unless of course we have another client with the same port
- * open). Note that existing channels accepted on the port are
- * not affected.
- *
- * @param cls Identification of the client.
- * @param pmsg The actual message.
- */
- static void
- handle_port_close (void *cls,
- const struct GNUNET_CADET_PortMessage *pmsg)
- {
- struct CadetClient *c = cls;
- struct OpenPort *op;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Closing port %s as requested by %s\n",
- GNUNET_h2s (&pmsg->port),
- GSC_2s (c));
- if (NULL == c->ports)
- {
- /* Client closed a port despite _never_ having opened one? */
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (c->client);
- return;
- }
- op = GNUNET_CONTAINER_multihashmap_get (c->ports,
- &pmsg->port);
- if (NULL == op)
- {
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (c->client);
- return;
- }
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (c->ports,
- &op->port,
- op));
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (open_ports,
- &op->h_port,
- op));
- GNUNET_free (op);
- GNUNET_SERVICE_client_continue (c->client);
- }
- /**
- * Handler for requests for us creating a new channel to another peer and port.
- *
- * @param cls Identification of the client.
- * @param tcm The actual message.
- */
- static void
- handle_channel_create (void *cls,
- const struct GNUNET_CADET_LocalChannelCreateMessage *tcm)
- {
- struct CadetClient *c = cls;
- struct CadetChannel *ch;
- if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- {
- /* Channel ID not in allowed range. */
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (c->client);
- return;
- }
- ch = lookup_channel (c,
- tcm->ccn);
- if (NULL != ch)
- {
- /* Channel ID already in use. Not allowed. */
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (c->client);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "New channel to %s at port %s requested by %s\n",
- GNUNET_i2s (&tcm->peer),
- GNUNET_h2s (&tcm->port),
- GSC_2s (c));
- /* Create channel */
- ch = GCCH_channel_local_new (c,
- tcm->ccn,
- GCP_get (&tcm->peer,
- GNUNET_YES),
- &tcm->port,
- ntohl (tcm->opt));
- if (NULL == ch)
- {
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (c->client);
- return;
- }
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_put (c->channels,
- ntohl (tcm->ccn.channel_of_client),
- ch,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- GNUNET_SERVICE_client_continue (c->client);
- }
- /**
- * Handler for requests of destroying an existing channel.
- *
- * @param cls client identification of the client
- * @param msg the actual message
- */
- static void
- handle_channel_destroy (void *cls,
- const struct GNUNET_CADET_LocalChannelDestroyMessage *msg)
- {
- struct CadetClient *c = cls;
- struct CadetChannel *ch;
- ch = lookup_channel (c,
- msg->ccn);
- if (NULL == ch)
- {
- /* Client attempted to destroy unknown channel.
- Can happen if the other side went down at the same time.*/
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "%s tried to destroy unknown channel %X\n",
- GSC_2s(c),
- (uint32_t) ntohl (msg->ccn.channel_of_client));
- GNUNET_SERVICE_client_continue (c->client);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "%s is destroying %s\n",
- GSC_2s(c),
- GCCH_2s (ch));
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_remove (c->channels,
- ntohl (msg->ccn.channel_of_client),
- ch));
- GCCH_channel_local_destroy (ch,
- c,
- msg->ccn);
- GNUNET_SERVICE_client_continue (c->client);
- }
- /**
- * Check for client traffic data message is well-formed.
- *
- * @param cls identification of the client
- * @param msg the actual message
- * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not
- */
- static int
- check_local_data (void *cls,
- const struct GNUNET_CADET_LocalData *msg)
- {
- size_t payload_size;
- size_t payload_claimed_size;
- const char *buf;
- struct GNUNET_MessageHeader pa;
- /* FIXME: what is the format we shall allow for @a msg?
- ONE payload item or multiple? Seems current cadet_api
- at least in theory allows more than one. Next-gen
- cadet_api will likely no more, so we could then
- simplify this mess again. */
- /* Sanity check for message size */
- payload_size = ntohs (msg->header.size) - sizeof (*msg);
- buf = (const char *) &msg[1];
- while (payload_size >= sizeof (struct GNUNET_MessageHeader))
- {
- /* need to memcpy() for alignment */
- GNUNET_memcpy (&pa,
- buf,
- sizeof (pa));
- payload_claimed_size = ntohs (pa.size);
- if ( (payload_size < payload_claimed_size) ||
- (payload_claimed_size < sizeof (struct GNUNET_MessageHeader)) ||
- (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size) )
- {
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Local data of %u total size had sub-message %u at %u with %u bytes\n",
- ntohs (msg->header.size),
- ntohs (pa.type),
- (unsigned int) (buf - (const char *) &msg[1]),
- (unsigned int) payload_claimed_size);
- return GNUNET_SYSERR;
- }
- payload_size -= payload_claimed_size;
- buf += payload_claimed_size;
- }
- if (0 != payload_size)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- }
- /**
- * Handler for client payload traffic to be send on a channel to
- * another peer.
- *
- * @param cls identification of the client
- * @param msg the actual message
- */
- static void
- handle_local_data (void *cls,
- const struct GNUNET_CADET_LocalData *msg)
- {
- struct CadetClient *c = cls;
- struct CadetChannel *ch;
- size_t payload_size;
- const char *buf;
- ch = lookup_channel (c,
- msg->ccn);
- if (NULL == ch)
- {
- /* Channel does not exist (anymore) */
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "Dropping payload for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
- (unsigned int) ntohl (msg->ccn.channel_of_client));
- GNUNET_SERVICE_client_continue (c->client);
- return;
- }
- payload_size = ntohs (msg->header.size) - sizeof (*msg);
- GNUNET_STATISTICS_update (stats,
- "# payload received from clients",
- payload_size,
- GNUNET_NO);
- buf = (const char *) &msg[1];
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Received %u bytes payload from %s for %s\n",
- (unsigned int) payload_size,
- GSC_2s (c),
- GCCH_2s (ch));
- if (GNUNET_OK !=
- GCCH_handle_local_data (ch,
- msg->ccn,
- buf,
- payload_size))
- {
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (c->client);
- return;
- }
- GNUNET_SERVICE_client_continue (c->client);
- }
- /**
- * Handler for client's ACKs for payload traffic.
- *
- * @param cls identification of the client.
- * @param msg The actual message.
- */
- static void
- handle_local_ack (void *cls,
- const struct GNUNET_CADET_LocalAck *msg)
- {
- struct CadetClient *c = cls;
- struct CadetChannel *ch;
- ch = lookup_channel (c,
- msg->ccn);
- if (NULL == ch)
- {
- /* Channel does not exist (anymore) */
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "Ignoring local ACK for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
- (unsigned int) ntohl (msg->ccn.channel_of_client));
- GNUNET_SERVICE_client_continue (c->client);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Got a local ACK from %s for %s\n",
- GSC_2s(c),
- GCCH_2s (ch));
- GCCH_handle_local_ack (ch,
- msg->ccn);
- GNUNET_SERVICE_client_continue (c->client);
- }
- /**
- * Iterator over all peers to send a monitoring client info about each peer.
- *
- * @param cls Closure ().
- * @param peer Peer ID (tunnel remote peer).
- * @param value Peer info.
- * @return #GNUNET_YES, to keep iterating.
- */
- static int
- get_all_peers_iterator (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- void *value)
- {
- struct CadetClient *c = cls;
- struct CadetPeer *p = value;
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_CADET_LocalInfoPeers *msg;
- env = GNUNET_MQ_msg (msg,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
- msg->destination = *peer;
- msg->paths = htons (GCP_count_paths (p));
- msg->tunnel = htons (NULL != GCP_get_tunnel (p,
- GNUNET_NO));
- msg->best_path_length = htonl (0); // FIXME: get length of shortest known path!
- GNUNET_MQ_send (c->mq,
- env);
- return GNUNET_YES;
- }
- /**
- * Handler for client's INFO PEERS request.
- *
- * @param cls Identification of the client.
- * @param message The actual message.
- */
- static void
- handle_get_peers (void *cls,
- const struct GNUNET_MessageHeader *message)
- {
- struct CadetClient *c = cls;
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_MessageHeader *reply;
- GCP_iterate_all (&get_all_peers_iterator,
- c);
- env = GNUNET_MQ_msg (reply,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS_END);
- GNUNET_MQ_send (c->mq,
- env);
- GNUNET_SERVICE_client_continue (c->client);
- }
- /**
- * Iterator over all paths of a peer to build an InfoPeer message.
- * Message contains blocks of peers, first not included.
- *
- * @param cls message queue for transmission
- * @param path Path itself
- * @param off offset of the peer on @a path
- * @return #GNUNET_YES if should keep iterating.
- * #GNUNET_NO otherwise.
- */
- static int
- path_info_iterator (void *cls,
- struct CadetPeerPath *path,
- unsigned int off)
- {
- struct GNUNET_MQ_Handle *mq = cls;
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_CADET_LocalInfoPath *resp;
- struct GNUNET_PeerIdentity *id;
- size_t path_size;
- unsigned int path_length;
- path_length = GCPP_get_length (path);
- path_size = sizeof (struct GNUNET_PeerIdentity) * path_length;
- if (sizeof (*resp) + path_size > UINT16_MAX)
- {
- /* try just giving the relevant path */
- path_length = GNUNET_MIN ((UINT16_MAX - sizeof (*resp)) / sizeof (struct GNUNET_PeerIdentity),
- off);
- path_size = sizeof (struct GNUNET_PeerIdentity) * path_length;
- }
- if (sizeof (*resp) + path_size > UINT16_MAX)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "Path of %u entries is too long for info message\n",
- path_length);
- return GNUNET_YES;
- }
- env = GNUNET_MQ_msg_extra (resp,
- path_size,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH);
- id = (struct GNUNET_PeerIdentity *) &resp[1];
- /* Don't copy first peer. First peer is always the local one. Last
- * peer is always the destination (leave as 0, EOL).
- */
- for (unsigned int i = 0; i < path_length; i++)
- id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path,
- i));
- resp->off = htonl (off);
- GNUNET_MQ_send (mq,
- env);
- return GNUNET_YES;
- }
- /**
- * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH request.
- *
- * @param cls Identification of the client.
- * @param msg The actual message.
- */
- static void
- handle_show_path (void *cls,
- const struct GNUNET_CADET_RequestPathInfoMessage *msg)
- {
- struct CadetClient *c = cls;
- struct CadetPeer *p;
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_MessageHeader *resp;
- p = GCP_get (&msg->peer,
- GNUNET_NO);
- if (NULL != p)
- GCP_iterate_indirect_paths (p,
- &path_info_iterator,
- c->mq);
- env = GNUNET_MQ_msg (resp,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH_END);
- GNUNET_MQ_send (c->mq,
- env);
- GNUNET_SERVICE_client_continue (c->client);
- }
- /**
- * Iterator over all tunnels to send a monitoring client info about each tunnel.
- *
- * @param cls Closure ().
- * @param peer Peer ID (tunnel remote peer).
- * @param value a `struct CadetPeer`
- * @return #GNUNET_YES, to keep iterating.
- */
- static int
- get_all_tunnels_iterator (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- void *value)
- {
- struct CadetClient *c = cls;
- struct CadetPeer *p = value;
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_CADET_LocalInfoTunnel *msg;
- struct CadetTunnel *t;
- t = GCP_get_tunnel (p,
- GNUNET_NO);
- if (NULL == t)
- return GNUNET_YES;
- env = GNUNET_MQ_msg (msg,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
- msg->destination = *peer;
- msg->channels = htonl (GCT_count_channels (t));
- msg->connections = htonl (GCT_count_any_connections (t));
- msg->cstate = htons (0);
- msg->estate = htons ((uint16_t) GCT_get_estate (t));
- GNUNET_MQ_send (c->mq,
- env);
- return GNUNET_YES;
- }
- /**
- * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS request.
- *
- * @param cls client Identification of the client.
- * @param message The actual message.
- */
- static void
- handle_info_tunnels (void *cls,
- const struct GNUNET_MessageHeader *message)
- {
- struct CadetClient *c = cls;
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_MessageHeader *reply;
- GCP_iterate_all (&get_all_tunnels_iterator,
- c);
- env = GNUNET_MQ_msg (reply,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS_END);
- GNUNET_MQ_send (c->mq,
- env);
- GNUNET_SERVICE_client_continue (c->client);
- }
- /**
- * Callback called when a client connects to the service.
- *
- * @param cls closure for the service
- * @param client the new client that connected to the service
- * @param mq the message queue used to send messages to the client
- * @return @a c
- */
- static void *
- client_connect_cb (void *cls,
- struct GNUNET_SERVICE_Client *client,
- struct GNUNET_MQ_Handle *mq)
- {
- struct CadetClient *c;
- c = GNUNET_new (struct CadetClient);
- c->client = client;
- c->mq = mq;
- c->id = next_client_id++; /* overflow not important: just for debug */
- c->channels
- = GNUNET_CONTAINER_multihashmap32_create (32);
- GNUNET_CONTAINER_DLL_insert (clients_head,
- clients_tail,
- c);
- GNUNET_STATISTICS_update (stats,
- "# clients",
- +1,
- GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "%s connected\n",
- GSC_2s (c));
- return c;
- }
- /**
- * A channel was destroyed by the other peer. Tell our client.
- *
- * @param c client that lost a channel
- * @param ccn channel identification number for the client
- * @param ch the channel object
- */
- void
- GSC_handle_remote_channel_destroy (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber ccn,
- struct CadetChannel *ch)
- {
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
- env = GNUNET_MQ_msg (tdm,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
- tdm->ccn = ccn;
- GSC_send_to_client (c,
- env);
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_remove (c->channels,
- ntohl (ccn.channel_of_client),
- ch));
- }
- /**
- * A client that created a loose channel that was not bound to a port
- * disconnected, drop it from the #loose_channels list.
- *
- * @param h_port the hashed port the channel was trying to bind to
- * @param ch the channel that was lost
- */
- void
- GSC_drop_loose_channel (const struct GNUNET_HashCode *h_port,
- struct CadetChannel *ch)
- {
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (loose_channels,
- h_port,
- ch));
- }
- /**
- * Iterator for deleting each channel whose client endpoint disconnected.
- *
- * @param cls Closure (client that has disconnected).
- * @param key The local channel id in host byte order
- * @param value The value stored at the key (channel to destroy).
- * @return #GNUNET_OK, keep iterating.
- */
- static int
- channel_destroy_iterator (void *cls,
- uint32_t key,
- void *value)
- {
- struct CadetClient *c = cls;
- struct GNUNET_CADET_ClientChannelNumber ccn;
- struct CadetChannel *ch = value;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Destroying %s, due to %s disconnecting.\n",
- GCCH_2s (ch),
- GSC_2s (c));
- ccn.channel_of_client = htonl (key);
- GCCH_channel_local_destroy (ch,
- c,
- ccn);
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_remove (c->channels,
- key,
- ch));
- return GNUNET_OK;
- }
- /**
- * Remove client's ports from the global hashmap on disconnect.
- *
- * @param cls the `struct CadetClient`
- * @param port the port.
- * @param value the `struct OpenPort` to remove
- * @return #GNUNET_OK, keep iterating.
- */
- static int
- client_release_ports (void *cls,
- const struct GNUNET_HashCode *port,
- void *value)
- {
- struct CadetClient *c = cls;
- struct OpenPort *op = value;
- GNUNET_assert (c == op->c);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Closing port %s due to %s disconnect.\n",
- GNUNET_h2s (port),
- GSC_2s (c));
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (open_ports,
- &op->h_port,
- op));
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (c->ports,
- port,
- op));
- GNUNET_free (op);
- return GNUNET_OK;
- }
- /**
- * Callback called when a client disconnected from the service
- *
- * @param cls closure for the service
- * @param client the client that disconnected
- * @param internal_cls should be equal to @a c
- */
- static void
- client_disconnect_cb (void *cls,
- struct GNUNET_SERVICE_Client *client,
- void *internal_cls)
- {
- struct CadetClient *c = internal_cls;
- GNUNET_assert (c->client == client);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "%s is disconnecting.\n",
- GSC_2s (c));
- if (NULL != c->channels)
- {
- GNUNET_CONTAINER_multihashmap32_iterate (c->channels,
- &channel_destroy_iterator,
- c);
- GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels));
- GNUNET_CONTAINER_multihashmap32_destroy (c->channels);
- }
- if (NULL != c->ports)
- {
- GNUNET_CONTAINER_multihashmap_iterate (c->ports,
- &client_release_ports,
- c);
- GNUNET_CONTAINER_multihashmap_destroy (c->ports);
- }
- GNUNET_CONTAINER_DLL_remove (clients_head,
- clients_tail,
- c);
- GNUNET_STATISTICS_update (stats,
- "# clients",
- -1,
- GNUNET_NO);
- GNUNET_free (c);
- if ( (NULL == clients_head) &&
- (GNUNET_YES == shutting_down) )
- shutdown_rest ();
- }
- /**
- * Setup CADET internals.
- *
- * @param cls closure
- * @param server the initialized server
- * @param c configuration to use
- */
- static void
- run (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *c,
- struct GNUNET_SERVICE_Handle *service)
- {
- cfg = c;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (c,
- "CADET",
- "RATCHET_MESSAGES",
- &ratchet_messages))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
- "CADET",
- "RATCHET_MESSAGES",
- "needs to be a number");
- ratchet_messages = 64;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (c,
- "CADET",
- "RATCHET_TIME",
- &ratchet_time))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
- "CADET",
- "RATCHET_TIME",
- "need delay value");
- ratchet_time = GNUNET_TIME_UNIT_HOURS;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (c,
- "CADET",
- "REFRESH_CONNECTION_TIME",
- &keepalive_period))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
- "CADET",
- "REFRESH_CONNECTION_TIME",
- "need delay value");
- keepalive_period = GNUNET_TIME_UNIT_MINUTES;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (c,
- "CADET",
- "DROP_PERCENT",
- &drop_percent))
- {
- drop_percent = 0;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
- }
- my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
- if (NULL == my_private_key)
- {
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
- &my_full_id.public_key);
- stats = GNUNET_STATISTICS_create ("cadet",
- c);
- GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
- NULL);
- ats_ch = GNUNET_ATS_connectivity_init (c);
- /* FIXME: optimize code to allow GNUNET_YES here! */
- open_ports = GNUNET_CONTAINER_multihashmap_create (16,
- GNUNET_NO);
- loose_channels = GNUNET_CONTAINER_multihashmap_create (16,
- GNUNET_NO);
- peers = GNUNET_CONTAINER_multipeermap_create (16,
- GNUNET_YES);
- connections = GNUNET_CONTAINER_multishortmap_create (256,
- GNUNET_YES);
- GCH_init (c);
- GCD_init (c);
- GCO_init (c);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "CADET started for peer %s\n",
- GNUNET_i2s (&my_full_id));
- }
- /**
- * Define "main" method using service macro.
- */
- GNUNET_SERVICE_MAIN
- ("cadet",
- GNUNET_SERVICE_OPTION_NONE,
- &run,
- &client_connect_cb,
- &client_disconnect_cb,
- NULL,
- GNUNET_MQ_hd_fixed_size (port_open,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
- struct GNUNET_CADET_PortMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (port_close,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
- struct GNUNET_CADET_PortMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (channel_create,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
- struct GNUNET_CADET_LocalChannelCreateMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (channel_destroy,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
- struct GNUNET_CADET_LocalChannelDestroyMessage,
- NULL),
- GNUNET_MQ_hd_var_size (local_data,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
- struct GNUNET_CADET_LocalData,
- NULL),
- GNUNET_MQ_hd_fixed_size (local_ack,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
- struct GNUNET_CADET_LocalAck,
- NULL),
- GNUNET_MQ_hd_fixed_size (get_peers,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS,
- struct GNUNET_MessageHeader,
- NULL),
- GNUNET_MQ_hd_fixed_size (show_path,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH,
- struct GNUNET_CADET_RequestPathInfoMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (info_tunnels,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS,
- struct GNUNET_MessageHeader,
- NULL),
- GNUNET_MQ_handler_end ());
- /* end of gnunet-service-cadet-new.c */
|