2 This file is part of GNUnet.
3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file core/gnunet-service-core.c
23 * @brief high-level P2P messaging
24 * @author Christian Grothoff
26 * Considerations for later:
27 * - check that hostkey used by transport (for HELLOs) is the
28 * same as the hostkey that we are using!
29 * - add code to send PINGs if we are about to time-out otherwise
30 * - optimize lookup (many O(n) list traversals
31 * could ideally be changed to O(1) hash map lookups)
34 #include "gnunet_constants.h"
35 #include "gnunet_util_lib.h"
36 #include "gnunet_hello_lib.h"
37 #include "gnunet_peerinfo_service.h"
38 #include "gnunet_protocols.h"
39 #include "gnunet_signatures.h"
40 #include "gnunet_statistics_service.h"
41 #include "gnunet_transport_service.h"
45 #define DEBUG_HANDSHAKE GNUNET_NO
47 #define DEBUG_CORE_QUOTA GNUNET_NO
50 * Receive and send buffer windows grow over time. For
51 * how long can 'unused' bandwidth accumulate before we
52 * need to cap it? (specified in seconds).
54 #define MAX_WINDOW_TIME_S (5 * 60)
57 * How many messages do we queue up at most for optional
58 * notifications to a client? (this can cause notifications
59 * about outgoing messages to be dropped).
61 #define MAX_NOTIFY_QUEUE 1024
64 * Minimum bandwidth (out) to assign to any connected peer.
65 * Should be rather low; values larger than DEFAULT_BW_IN_OUT make no
68 #define MIN_BANDWIDTH_PER_PEER GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT
71 * After how much time past the "official" expiration time do
72 * we discard messages? Should not be zero since we may
73 * intentionally defer transmission until close to the deadline
74 * and then may be slightly past the deadline due to inaccuracy
75 * in sleep and our own CPU consumption.
77 #define PAST_EXPIRATION_DISCARD_TIME GNUNET_TIME_UNIT_SECONDS
80 * What is the maximum delay for a SET_KEY message?
82 #define MAX_SET_KEY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
85 * How long do we wait for SET_KEY confirmation initially?
87 #define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (MAX_SET_KEY_DELAY, 1)
90 * What is the maximum delay for a PING message?
92 #define MAX_PING_DELAY GNUNET_TIME_relative_multiply (MAX_SET_KEY_DELAY, 2)
95 * What is the maximum delay for a PONG message?
97 #define MAX_PONG_DELAY GNUNET_TIME_relative_multiply (MAX_PING_DELAY, 2)
100 * What is the minimum frequency for a PING message?
102 #define MIN_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
105 * How often do we recalculate bandwidth quotas?
107 #define QUOTA_UPDATE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
110 * What is the priority for a SET_KEY message?
112 #define SET_KEY_PRIORITY 0xFFFFFF
115 * What is the priority for a PING message?
117 #define PING_PRIORITY 0xFFFFFF
120 * What is the priority for a PONG message?
122 #define PONG_PRIORITY 0xFFFFFF
125 * How many messages do we queue per peer at most? Must be at
128 #define MAX_PEER_QUEUE_SIZE 16
131 * How many non-mandatory messages do we queue per client at most?
133 #define MAX_CLIENT_QUEUE_SIZE 32
136 * What is the maximum age of a message for us to consider
137 * processing it? Note that this looks at the timestamp used
138 * by the other peer, so clock skew between machines does
139 * come into play here. So this should be picked high enough
140 * so that a little bit of clock skew does not prevent peers
141 * from connecting to us.
143 #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
147 * State machine for our P2P encryption handshake. Everyone starts in
148 * "DOWN", if we receive the other peer's key (other peer initiated)
149 * we start in state RECEIVED (since we will immediately send our
150 * own); otherwise we start in SENT. If we get back a PONG from
151 * within either state, we move up to CONFIRMED (the PONG will always
152 * be sent back encrypted with the key we sent to the other peer).
154 enum PeerStateMachine
158 PEER_STATE_KEY_RECEIVED,
159 PEER_STATE_KEY_CONFIRMED
164 * Encapsulation for encrypted messages exchanged between
165 * peers. Followed by the actual encrypted data.
167 struct EncryptedMessage
170 * Message type is either CORE_ENCRYPTED_MESSAGE.
172 struct GNUNET_MessageHeader header;
175 * Random value used for IV generation.
177 uint32_t iv_seed GNUNET_PACKED;
180 * MAC of the encrypted message (starting at 'sequence_number'),
181 * used to verify message integrity. Everything after this value
182 * (excluding this value itself) will be encrypted and authenticated.
183 * ENCRYPTED_HEADER_SIZE must be set to the offset of the *next* field.
185 GNUNET_HashCode hmac;
188 * Sequence number, in network byte order. This field
189 * must be the first encrypted/decrypted field
191 uint32_t sequence_number GNUNET_PACKED;
194 * Desired bandwidth (how much we should send to this peer / how
195 * much is the sender willing to receive)?
197 struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
200 * Timestamp. Used to prevent reply of ancient messages
201 * (recent messages are caught with the sequence number).
203 struct GNUNET_TIME_AbsoluteNBO timestamp;
209 * Number of bytes (at the beginning) of "struct EncryptedMessage"
210 * that are NOT encrypted.
212 #define ENCRYPTED_HEADER_SIZE (offsetof(struct EncryptedMessage, sequence_number))
216 * We're sending an (encrypted) PING to the other peer to check if he
217 * can decrypt. The other peer should respond with a PONG with the
218 * same content, except this time encrypted with the receiver's key.
223 * Message type is CORE_PING.
225 struct GNUNET_MessageHeader header;
230 uint32_t iv_seed GNUNET_PACKED;
233 * Intended target of the PING, used primarily to check
234 * that decryption actually worked.
236 struct GNUNET_PeerIdentity target;
239 * Random number chosen to make reply harder.
241 uint32_t challenge GNUNET_PACKED;
247 * Response to a PING. Includes data from the original PING
248 * plus initial bandwidth quota information.
253 * Message type is CORE_PONG.
255 struct GNUNET_MessageHeader header;
260 uint32_t iv_seed GNUNET_PACKED;
263 * Random number to make faking the reply harder. Must be
264 * first field after header (this is where we start to encrypt!).
266 uint32_t challenge GNUNET_PACKED;
269 * Desired bandwidth (how much we should send to this
270 * peer / how much is the sender willing to receive).
272 struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
275 * Intended target of the PING, used primarily to check
276 * that decryption actually worked.
278 struct GNUNET_PeerIdentity target;
283 * Message transmitted to set (or update) a session key.
289 * Message type is either CORE_SET_KEY.
291 struct GNUNET_MessageHeader header;
294 * Status of the sender (should be in "enum PeerStateMachine"), nbo.
296 int32_t sender_status GNUNET_PACKED;
299 * Purpose of the signature, will be
300 * GNUNET_SIGNATURE_PURPOSE_SET_KEY.
302 struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
305 * At what time was this key created?
307 struct GNUNET_TIME_AbsoluteNBO creation_time;
310 * The encrypted session key.
312 struct GNUNET_CRYPTO_RsaEncryptedData encrypted_key;
315 * Who is the intended recipient?
317 struct GNUNET_PeerIdentity target;
320 * Signature of the stuff above (starting at purpose).
322 struct GNUNET_CRYPTO_RsaSignature signature;
328 * Message waiting for transmission. This struct
329 * is followed by the actual content of the message.
335 * We keep messages in a doubly linked list.
337 struct MessageEntry *next;
340 * We keep messages in a doubly linked list.
342 struct MessageEntry *prev;
345 * By when are we supposed to transmit this message?
347 struct GNUNET_TIME_Absolute deadline;
350 * By when are we supposed to transmit this message (after
353 struct GNUNET_TIME_Absolute slack_deadline;
356 * How important is this message to us?
358 unsigned int priority;
361 * If this is a SET_KEY message, what was our connection status when this
362 * message was queued?
364 enum PeerStateMachine sender_status;
367 * Is this a SET_KEY message?
372 * How long is the message? (number of bytes following
373 * the "struct MessageEntry", but not including the
374 * size of "struct MessageEntry" itself!)
379 * Was this message selected for transmission in the
380 * current round? GNUNET_YES or GNUNET_NO.
385 * Did we give this message some slack (delayed sending) previously
386 * (and hence should not give it any more slack)? GNUNET_YES or
395 * Record kept for each request for transmission issued by a
396 * client that is still pending.
398 struct ClientActiveRequest;
401 * Data kept per neighbouring peer.
406 * We keep neighbours in a linked list (for now).
408 struct Neighbour *next;
411 * Unencrypted messages destined for this peer.
413 struct MessageEntry *messages;
416 * Head of the batched, encrypted message queue (already ordered,
417 * transmit starting with the head).
419 struct MessageEntry *encrypted_head;
422 * Tail of the batched, encrypted message queue (already ordered,
423 * append new messages to tail)
425 struct MessageEntry *encrypted_tail;
428 * Head of list of requests from clients for transmission to
431 struct ClientActiveRequest *active_client_request_head;
434 * Tail of list of requests from clients for transmission to
437 struct ClientActiveRequest *active_client_request_tail;
440 * Handle for pending requests for transmission to this peer
441 * with the transport service. NULL if no request is pending.
443 struct GNUNET_TRANSPORT_TransmitHandle *th;
446 * Public key of the neighbour, NULL if we don't have it yet.
448 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
451 * We received a PING message before we got the "public_key"
452 * (or the SET_KEY). We keep it here until we have a key
453 * to decrypt it. NULL if no PING is pending.
455 struct PingMessage *pending_ping;
458 * We received a PONG message before we got the "public_key"
459 * (or the SET_KEY). We keep it here until we have a key
460 * to decrypt it. NULL if no PONG is pending.
462 struct PongMessage *pending_pong;
465 * Non-NULL if we are currently looking up HELLOs for this peer.
468 struct GNUNET_PEERINFO_IteratorContext *pitr;
471 * SetKeyMessage to transmit, NULL if we are not currently trying
474 struct SetKeyMessage *skm;
477 * Identity of the neighbour.
479 struct GNUNET_PeerIdentity peer;
482 * Key we use to encrypt our messages for the other peer
483 * (initialized by us when we do the handshake).
485 struct GNUNET_CRYPTO_AesSessionKey encrypt_key;
488 * Key we use to decrypt messages from the other peer
489 * (given to us by the other peer during the handshake).
491 struct GNUNET_CRYPTO_AesSessionKey decrypt_key;
494 * ID of task used for re-trying plaintext scheduling.
496 GNUNET_SCHEDULER_TaskIdentifier retry_plaintext_task;
499 * ID of task used for re-trying SET_KEY and PING message.
501 GNUNET_SCHEDULER_TaskIdentifier retry_set_key_task;
504 * ID of task used for updating bandwidth quota for this neighbour.
506 GNUNET_SCHEDULER_TaskIdentifier quota_update_task;
509 * ID of task used for sending keep-alive pings.
511 GNUNET_SCHEDULER_TaskIdentifier keep_alive_task;
514 * ID of task used for cleaning up dead neighbour entries.
516 GNUNET_SCHEDULER_TaskIdentifier dead_clean_task;
519 * At what time did we generate our encryption key?
521 struct GNUNET_TIME_Absolute encrypt_key_created;
524 * At what time did the other peer generate the decryption key?
526 struct GNUNET_TIME_Absolute decrypt_key_created;
529 * At what time did we initially establish (as in, complete session
530 * key handshake) this connection? Should be zero if status != KEY_CONFIRMED.
532 struct GNUNET_TIME_Absolute time_established;
535 * At what time did we last receive an encrypted message from the
536 * other peer? Should be zero if status != KEY_CONFIRMED.
538 struct GNUNET_TIME_Absolute last_activity;
541 * At what frequency are we currently re-trying SET_KEY messages?
543 struct GNUNET_TIME_Relative set_key_retry_frequency;
546 * Tracking bandwidth for sending to this peer.
548 struct GNUNET_BANDWIDTH_Tracker available_send_window;
551 * Tracking bandwidth for receiving from this peer.
553 struct GNUNET_BANDWIDTH_Tracker available_recv_window;
556 * How valueable were the messages of this peer recently?
558 unsigned long long current_preference;
561 * Bit map indicating which of the 32 sequence numbers before the last
562 * were received (good for accepting out-of-order packets and
563 * estimating reliability of the connection)
565 unsigned int last_packets_bitmap;
568 * last sequence number received on this connection (highest)
570 uint32_t last_sequence_number_received;
573 * last sequence number transmitted
575 uint32_t last_sequence_number_sent;
578 * Available bandwidth in for this peer (current target).
580 struct GNUNET_BANDWIDTH_Value32NBO bw_in;
583 * Available bandwidth out for this peer (current target).
585 struct GNUNET_BANDWIDTH_Value32NBO bw_out;
588 * Internal bandwidth limit set for this peer (initially typically
589 * set to "-1"). Actual "bw_out" is MIN of
590 * "bpm_out_internal_limit" and "bw_out_external_limit".
592 struct GNUNET_BANDWIDTH_Value32NBO bw_out_internal_limit;
595 * External bandwidth limit set for this peer by the
596 * peer that we are communicating with. "bw_out" is MIN of
597 * "bw_out_internal_limit" and "bw_out_external_limit".
599 struct GNUNET_BANDWIDTH_Value32NBO bw_out_external_limit;
602 * What was our PING challenge number (for this peer)?
604 uint32_t ping_challenge;
607 * What is our connection status?
609 enum PeerStateMachine status;
612 * Are we currently connected to this neighbour?
620 * Data structure for each client connected to the core service.
625 * Clients are kept in a linked list.
630 * Handle for the client with the server API.
632 struct GNUNET_SERVER_Client *client_handle;
635 * Array of the types of messages this peer cares
636 * about (with "tcnt" entries). Allocated as part
637 * of this client struct, do not free!
639 const uint16_t *types;
642 * Map of peer identities to active transmission requests of this
643 * client to the peer (of type 'struct ClientActiveRequest').
645 struct GNUNET_CONTAINER_MultiHashMap *requests;
648 * Options for messages this client cares about,
649 * see GNUNET_CORE_OPTION_ values.
654 * Number of types of incoming messages this client
655 * specifically cares about. Size of the "types" array.
663 * Record kept for each request for transmission issued by a
664 * client that is still pending.
666 struct ClientActiveRequest
670 * Active requests are kept in a doubly-linked list of
671 * the respective target peer.
673 struct ClientActiveRequest *next;
676 * Active requests are kept in a doubly-linked list of
677 * the respective target peer.
679 struct ClientActiveRequest *prev;
682 * Handle to the client.
684 struct Client *client;
687 * By what time would the client want to see this message out?
689 struct GNUNET_TIME_Absolute deadline;
692 * How important is this request.
697 * How many more requests does this client have?
702 * How many bytes does the client intend to send?
707 * Unique request ID (in big endian).
718 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
723 static struct GNUNET_PeerIdentity my_identity;
728 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
732 * Handle to peerinfo service.
734 static struct GNUNET_PEERINFO_Handle *peerinfo;
737 * Our message stream tokenizer (for encrypted payload).
739 static struct GNUNET_SERVER_MessageStreamTokenizer *mst;
744 const struct GNUNET_CONFIGURATION_Handle *cfg;
749 static struct GNUNET_TRANSPORT_Handle *transport;
752 * Linked list of our clients.
754 static struct Client *clients;
757 * Context for notifications we need to send to our clients.
759 static struct GNUNET_SERVER_NotificationContext *notifier;
762 * We keep neighbours in a linked list (for now).
764 static struct Neighbour *neighbours;
767 * For creating statistics.
769 static struct GNUNET_STATISTICS_Handle *stats;
772 * Sum of all preferences among all neighbours.
774 static unsigned long long preference_sum;
777 * Total number of neighbours we have.
779 static unsigned int neighbour_count;
782 * How much inbound bandwidth are we supposed to be using per second?
783 * FIXME: this value is not used!
785 static unsigned long long bandwidth_target_in_bps;
788 * How much outbound bandwidth are we supposed to be using per second?
790 static unsigned long long bandwidth_target_out_bps;
793 * Derive an authentication key from "set key" information
796 derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
797 const struct GNUNET_CRYPTO_AesSessionKey *skey,
799 struct GNUNET_TIME_Absolute creation_time)
801 static const char ctx[] = "authentication key";
802 struct GNUNET_TIME_AbsoluteNBO ctbe;
805 ctbe = GNUNET_TIME_absolute_hton (creation_time);
806 GNUNET_CRYPTO_hmac_derive_key (akey,
820 * Derive an IV from packet information
823 derive_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
824 const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed,
825 const struct GNUNET_PeerIdentity *identity)
827 static const char ctx[] = "initialization vector";
829 GNUNET_CRYPTO_aes_derive_iv (iv,
833 &identity->hashPubKey.bits,
834 sizeof(identity->hashPubKey.bits),
840 * Derive an IV from pong packet information
843 derive_pong_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
844 const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed,
845 uint32_t challenge, const struct GNUNET_PeerIdentity *identity)
847 static const char ctx[] = "pong initialization vector";
849 GNUNET_CRYPTO_aes_derive_iv (iv,
853 &identity->hashPubKey.bits,
854 sizeof(identity->hashPubKey.bits),
863 * At what time should the connection to the given neighbour
864 * time out (given no further activity?)
866 * @param n neighbour in question
867 * @return absolute timeout
869 static struct GNUNET_TIME_Absolute
870 get_neighbour_timeout (struct Neighbour *n)
872 return GNUNET_TIME_absolute_add (n->last_activity,
873 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
878 * A preference value for a neighbour was update. Update
879 * the preference sum accordingly.
881 * @param inc how much was a preference value increased?
884 update_preference_sum (unsigned long long inc)
887 unsigned long long os;
890 preference_sum += inc;
891 if (preference_sum >= os)
893 /* overflow! compensate by cutting all values in half! */
898 n->current_preference /= 2;
899 preference_sum += n->current_preference;
902 GNUNET_STATISTICS_set (stats, gettext_noop ("# total peer preference"), preference_sum, GNUNET_NO);
907 * Find the entry for the given neighbour.
909 * @param peer identity of the neighbour
910 * @return NULL if we are not connected, otherwise the
913 static struct Neighbour *
914 find_neighbour (const struct GNUNET_PeerIdentity *peer)
916 struct Neighbour *ret;
919 while ((ret != NULL) &&
920 (0 != memcmp (&ret->peer,
921 peer, sizeof (struct GNUNET_PeerIdentity))))
928 * Send a message to one of our clients.
930 * @param client target for the message
931 * @param msg message to transmit
932 * @param can_drop could this message be dropped if the
933 * client's queue is getting too large?
936 send_to_client (struct Client *client,
937 const struct GNUNET_MessageHeader *msg,
940 #if DEBUG_CORE_CLIENT
941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
942 "Preparing to send %u bytes of message of type %u to client.\n",
943 (unsigned int) ntohs (msg->size),
944 (unsigned int) ntohs (msg->type));
946 GNUNET_SERVER_notification_context_unicast (notifier,
947 client->client_handle,
954 * Send a message to all of our current clients that have
955 * the right options set.
957 * @param msg message to multicast
958 * @param can_drop can this message be discarded if the queue is too long
959 * @param options mask to use
962 send_to_all_clients (const struct GNUNET_MessageHeader *msg,
971 if (0 != (c->options & options))
973 #if DEBUG_CORE_CLIENT
974 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
975 "Sending message of type %u to client.\n",
976 (unsigned int) ntohs (msg->type));
978 send_to_client (c, msg, can_drop);
986 * Function called by transport telling us that a peer
989 * @param n the peer that changed status
992 handle_peer_status_change (struct Neighbour *n)
994 struct PeerStatusNotifyMessage psnm;
996 if ( (! n->is_connected) ||
997 (n->status != PEER_STATE_KEY_CONFIRMED) )
1000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1001 "Peer `%4s' changed status\n",
1002 GNUNET_i2s (&n->peer));
1004 psnm.header.size = htons (sizeof (struct PeerStatusNotifyMessage));
1005 psnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE);
1006 psnm.ats_count = htonl (0);
1007 psnm.ats.type = htonl (0);
1008 psnm.ats.value = htonl (0);
1009 psnm.timeout = GNUNET_TIME_absolute_hton (get_neighbour_timeout (n));
1010 psnm.bandwidth_in = n->bw_in;
1011 psnm.bandwidth_out = n->bw_out;
1012 psnm.peer = n->peer;
1013 send_to_all_clients (&psnm.header,
1015 GNUNET_CORE_OPTION_SEND_STATUS_CHANGE);
1016 GNUNET_STATISTICS_update (stats,
1017 gettext_noop ("# peer status changes"),
1024 * Go over our message queue and if it is not too long, go
1025 * over the pending requests from clients for this
1026 * neighbour and send some clients a 'READY' notification.
1028 * @param n which peer to process
1031 schedule_peer_messages (struct Neighbour *n)
1033 struct SendMessageReady smr;
1034 struct ClientActiveRequest *car;
1035 struct ClientActiveRequest *pos;
1037 struct MessageEntry *mqe;
1038 unsigned int queue_size;
1040 /* check if neighbour queue is empty enough! */
1048 if (queue_size >= MAX_PEER_QUEUE_SIZE)
1050 #if DEBUG_CORE_CLIENT
1051 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1052 "Not considering client transmission requests: queue full\n");
1054 return; /* queue still full */
1056 /* find highest priority request */
1057 pos = n->active_client_request_head;
1061 if ( (car == NULL) ||
1062 (pos->priority > car->priority) )
1067 return; /* no pending requests */
1068 #if DEBUG_CORE_CLIENT
1069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1070 "Permitting client transmission request to `%s'\n",
1071 GNUNET_i2s (&n->peer));
1074 GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1075 n->active_client_request_tail,
1077 GNUNET_CONTAINER_multihashmap_remove (c->requests,
1078 &n->peer.hashPubKey,
1080 smr.header.size = htons (sizeof (struct SendMessageReady));
1081 smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
1082 smr.size = htons (car->msize);
1083 smr.smr_id = car->smr_id;
1085 send_to_client (c, &smr.header, GNUNET_NO);
1091 * Handle CORE_SEND_REQUEST message.
1094 handle_client_send_request (void *cls,
1095 struct GNUNET_SERVER_Client *client,
1096 const struct GNUNET_MessageHeader *message)
1098 const struct SendMessageRequest *req;
1099 struct Neighbour *n;
1101 struct ClientActiveRequest *car;
1103 req = (const struct SendMessageRequest*) message;
1104 n = find_neighbour (&req->peer);
1106 (GNUNET_YES != n->is_connected) ||
1107 (n->status != PEER_STATE_KEY_CONFIRMED) )
1109 /* neighbour must have disconnected since request was issued,
1110 ignore (client will realize it once it processes the
1111 disconnect notification) */
1112 #if DEBUG_CORE_CLIENT
1113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1114 "Dropped client request for transmission (am disconnected)\n");
1116 GNUNET_STATISTICS_update (stats,
1117 gettext_noop ("# send requests dropped (disconnected)"),
1120 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1124 while ( (c != NULL) &&
1125 (c->client_handle != client) )
1129 /* client did not send INIT first! */
1131 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1134 if (c->requests == NULL)
1135 c->requests = GNUNET_CONTAINER_multihashmap_create (16);
1136 #if DEBUG_CORE_CLIENT
1137 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1138 "Received client transmission request. queueing\n");
1140 car = GNUNET_CONTAINER_multihashmap_get (c->requests,
1141 &req->peer.hashPubKey);
1144 /* create new entry */
1145 car = GNUNET_malloc (sizeof (struct ClientActiveRequest));
1146 GNUNET_assert (GNUNET_OK ==
1147 GNUNET_CONTAINER_multihashmap_put (c->requests,
1148 &req->peer.hashPubKey,
1150 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1151 GNUNET_CONTAINER_DLL_insert (n->active_client_request_head,
1152 n->active_client_request_tail,
1156 car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline);
1157 car->priority = ntohl (req->priority);
1158 car->queue_size = ntohl (req->queue_size);
1159 car->msize = ntohs (req->size);
1160 car->smr_id = req->smr_id;
1161 schedule_peer_messages (n);
1162 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1167 * Handle CORE_INIT request.
1170 handle_client_init (void *cls,
1171 struct GNUNET_SERVER_Client *client,
1172 const struct GNUNET_MessageHeader *message)
1174 const struct InitMessage *im;
1175 struct InitReplyMessage irm;
1178 const uint16_t *types;
1180 struct Neighbour *n;
1181 struct ConnectNotifyMessage cnm;
1184 #if DEBUG_CORE_CLIENT
1185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1186 "Client connecting to core service with `%s' message\n",
1189 /* check that we don't have an entry already */
1193 if (client == c->client_handle)
1196 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1201 msize = ntohs (message->size);
1202 if (msize < sizeof (struct InitMessage))
1205 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1208 GNUNET_SERVER_notification_context_add (notifier, client);
1209 im = (const struct InitMessage *) message;
1210 types = (const uint16_t *) &im[1];
1211 msize -= sizeof (struct InitMessage);
1212 c = GNUNET_malloc (sizeof (struct Client) + msize);
1213 c->client_handle = client;
1216 c->tcnt = msize / sizeof (uint16_t);
1217 c->types = (const uint16_t *) &c[1];
1218 wtypes = (uint16_t *) &c[1];
1219 for (i=0;i<c->tcnt;i++)
1220 wtypes[i] = ntohs (types[i]);
1221 c->options = ntohl (im->options);
1222 #if DEBUG_CORE_CLIENT
1223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1224 "Client %p is interested in %u message types\n",
1226 (unsigned int) c->tcnt);
1228 /* send init reply message */
1229 irm.header.size = htons (sizeof (struct InitReplyMessage));
1230 irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
1231 irm.reserved = htonl (0);
1232 memcpy (&irm.publicKey,
1234 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1235 #if DEBUG_CORE_CLIENT
1236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1237 "Sending `%s' message to client.\n", "INIT_REPLY");
1239 send_to_client (c, &irm.header, GNUNET_NO);
1240 if (0 != (c->options & GNUNET_CORE_OPTION_SEND_CONNECT))
1242 /* notify new client about existing neighbours */
1243 cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
1244 cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1245 cnm.ats_count = htonl (0);
1246 cnm.ats.type = htonl (0);
1247 cnm.ats.value = htonl (0);
1251 if (n->status == PEER_STATE_KEY_CONFIRMED)
1253 #if DEBUG_CORE_CLIENT
1254 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1255 "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
1258 send_to_client (c, &cnm.header, GNUNET_NO);
1263 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1268 * Free client request records.
1271 * @param key identity of peer for which this is an active request
1272 * @param value the 'struct ClientActiveRequest' to free
1273 * @return GNUNET_YES (continue iteration)
1276 destroy_active_client_request (void *cls,
1277 const GNUNET_HashCode *key,
1280 struct ClientActiveRequest *car = value;
1281 struct Neighbour *n;
1282 struct GNUNET_PeerIdentity peer;
1284 peer.hashPubKey = *key;
1285 n = find_neighbour (&peer);
1286 GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1287 n->active_client_request_tail,
1295 * A client disconnected, clean up.
1297 * @param cls closure
1298 * @param client identification of the client
1301 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1304 struct Client *prev;
1308 #if DEBUG_CORE_CLIENT
1309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1310 "Client %p has disconnected from core service.\n",
1317 if (client == pos->client_handle)
1324 /* client never sent INIT */
1328 clients = pos->next;
1330 prev->next = pos->next;
1331 if (pos->requests != NULL)
1333 GNUNET_CONTAINER_multihashmap_iterate (pos->requests,
1334 &destroy_active_client_request,
1336 GNUNET_CONTAINER_multihashmap_destroy (pos->requests);
1343 * Handle CORE_ITERATE_PEERS request.
1346 handle_client_iterate_peers (void *cls,
1347 struct GNUNET_SERVER_Client *client,
1348 const struct GNUNET_MessageHeader *message)
1351 struct Neighbour *n;
1352 struct ConnectNotifyMessage cnm;
1353 struct GNUNET_MessageHeader done_msg;
1354 struct GNUNET_SERVER_TransmitContext *tc;
1356 /* notify new client about existing neighbours */
1357 cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
1358 cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1359 done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1360 done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1361 tc = GNUNET_SERVER_transmit_context_create (client);
1363 cnm.ats_count = htonl (0);
1364 cnm.ats.type = htonl (0);
1365 cnm.ats.value = htonl (0);
1368 if (n->status == PEER_STATE_KEY_CONFIRMED)
1370 #if DEBUG_CORE_CLIENT
1371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1372 "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
1375 GNUNET_SERVER_transmit_context_append_message (tc, &cnm.header);
1379 GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
1380 GNUNET_SERVER_transmit_context_run (tc,
1381 GNUNET_TIME_UNIT_FOREVER_REL);
1386 * Handle REQUEST_INFO request.
1389 handle_client_request_info (void *cls,
1390 struct GNUNET_SERVER_Client *client,
1391 const struct GNUNET_MessageHeader *message)
1393 const struct RequestInfoMessage *rcm;
1395 struct Neighbour *n;
1396 struct ConfigurationInfoMessage cim;
1397 int32_t want_reserv;
1399 unsigned long long old_preference;
1401 #if DEBUG_CORE_CLIENT
1402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1403 "Core service receives `%s' request.\n", "REQUEST_INFO");
1408 if (client == pos->client_handle)
1415 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1419 rcm = (const struct RequestInfoMessage *) message;
1420 n = find_neighbour (&rcm->peer);
1421 memset (&cim, 0, sizeof (cim));
1424 want_reserv = ntohl (rcm->reserve_inbound);
1425 if (n->bw_out_internal_limit.value__ != rcm->limit_outbound.value__)
1427 n->bw_out_internal_limit = rcm->limit_outbound;
1428 if (n->bw_out.value__ != GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
1429 n->bw_out_external_limit).value__)
1431 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
1432 n->bw_out_external_limit);
1433 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_recv_window,
1435 GNUNET_TRANSPORT_set_quota (transport,
1439 GNUNET_TIME_UNIT_FOREVER_REL,
1441 handle_peer_status_change (n);
1444 if (want_reserv < 0)
1446 got_reserv = want_reserv;
1448 else if (want_reserv > 0)
1450 if (GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window,
1451 want_reserv).rel_value == 0)
1452 got_reserv = want_reserv;
1454 got_reserv = 0; /* all or nothing */
1458 GNUNET_BANDWIDTH_tracker_consume (&n->available_recv_window,
1460 old_preference = n->current_preference;
1461 n->current_preference += GNUNET_ntohll(rcm->preference_change);
1462 if (old_preference > n->current_preference)
1464 /* overflow; cap at maximum value */
1465 n->current_preference = ULLONG_MAX;
1467 update_preference_sum (n->current_preference - old_preference);
1468 #if DEBUG_CORE_QUOTA
1469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1470 "Received reservation request for %d bytes for peer `%4s', reserved %d bytes\n",
1472 GNUNET_i2s (&rcm->peer),
1475 cim.reserved_amount = htonl (got_reserv);
1476 cim.rim_id = rcm->rim_id;
1477 cim.bw_out = n->bw_out;
1478 cim.preference = n->current_preference;
1480 cim.header.size = htons (sizeof (struct ConfigurationInfoMessage));
1481 cim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO);
1482 cim.peer = rcm->peer;
1483 #if DEBUG_CORE_CLIENT
1484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1485 "Sending `%s' message to client.\n", "CONFIGURATION_INFO");
1487 send_to_client (pos, &cim.header, GNUNET_NO);
1488 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1493 * Free the given entry for the neighbour (it has
1494 * already been removed from the list at this point).
1496 * @param n neighbour to free
1499 free_neighbour (struct Neighbour *n)
1501 struct MessageEntry *m;
1502 struct ClientActiveRequest *car;
1505 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1506 "Destroying neighbour entry for peer `%4s'\n",
1507 GNUNET_i2s (&n->peer));
1509 if (n->pitr != NULL)
1511 GNUNET_PEERINFO_iterate_cancel (n->pitr);
1516 GNUNET_free (n->skm);
1519 while (NULL != (m = n->messages))
1521 n->messages = m->next;
1524 while (NULL != (m = n->encrypted_head))
1526 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1531 while (NULL != (car = n->active_client_request_head))
1533 GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1534 n->active_client_request_tail,
1536 GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
1537 &n->peer.hashPubKey,
1543 GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
1546 if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
1547 GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
1548 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
1549 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
1550 if (n->quota_update_task != GNUNET_SCHEDULER_NO_TASK)
1551 GNUNET_SCHEDULER_cancel (n->quota_update_task);
1552 if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
1553 GNUNET_SCHEDULER_cancel (n->dead_clean_task);
1554 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
1555 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
1556 if (n->status == PEER_STATE_KEY_CONFIRMED)
1557 GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"), -1, GNUNET_NO);
1558 GNUNET_free_non_null (n->public_key);
1559 GNUNET_free_non_null (n->pending_ping);
1560 GNUNET_free_non_null (n->pending_pong);
1566 * Check if we have encrypted messages for the specified neighbour
1567 * pending, and if so, check with the transport about sending them
1570 * @param n neighbour to check.
1572 static void process_encrypted_neighbour_queue (struct Neighbour *n);
1576 * Encrypt size bytes from in and write the result to out. Use the
1577 * key for outbound traffic of the given neighbour.
1579 * @param n neighbour we are sending to
1580 * @param iv initialization vector to use
1581 * @param in ciphertext
1582 * @param out plaintext
1583 * @param size size of in/out
1584 * @return GNUNET_OK on success
1587 do_encrypt (struct Neighbour *n,
1588 const struct GNUNET_CRYPTO_AesInitializationVector * iv,
1589 const void *in, void *out, size_t size)
1591 if (size != (uint16_t) size)
1596 GNUNET_assert (size ==
1597 GNUNET_CRYPTO_aes_encrypt (in,
1601 GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes encrypted"), size, GNUNET_NO);
1603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1604 "Encrypted %u bytes for `%4s' using key %u, IV %u\n",
1605 (unsigned int) size,
1606 GNUNET_i2s (&n->peer),
1607 (unsigned int) n->encrypt_key.crc32,
1608 GNUNET_CRYPTO_crc32_n (iv, sizeof(iv)));
1615 * Consider freeing the given neighbour since we may not need
1616 * to keep it around anymore.
1618 * @param n neighbour to consider discarding
1621 consider_free_neighbour (struct Neighbour *n);
1625 * Task triggered when a neighbour entry is about to time out
1626 * (and we should prevent this by sending a PING).
1628 * @param cls the 'struct Neighbour'
1629 * @param tc scheduler context (not used)
1632 send_keep_alive (void *cls,
1633 const struct GNUNET_SCHEDULER_TaskContext *tc)
1635 struct Neighbour *n = cls;
1636 struct GNUNET_TIME_Relative retry;
1637 struct GNUNET_TIME_Relative left;
1638 struct MessageEntry *me;
1639 struct PingMessage pp;
1640 struct PingMessage *pm;
1641 struct GNUNET_CRYPTO_AesInitializationVector iv;
1643 n->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
1645 me = GNUNET_malloc (sizeof (struct MessageEntry) +
1646 sizeof (struct PingMessage));
1647 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PING_DELAY);
1648 me->priority = PING_PRIORITY;
1649 me->size = sizeof (struct PingMessage);
1650 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
1654 pm = (struct PingMessage *) &me[1];
1655 pm->header.size = htons (sizeof (struct PingMessage));
1656 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
1657 pm->iv_seed = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
1659 derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
1660 pp.challenge = n->ping_challenge;
1661 pp.target = n->peer;
1663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1664 "Encrypting `%s' message with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
1666 (unsigned int) n->ping_challenge,
1667 GNUNET_i2s (&n->peer),
1668 (unsigned int) n->encrypt_key.crc32,
1669 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
1676 sizeof (struct PingMessage) -
1677 ((void *) &pm->target - (void *) pm));
1678 process_encrypted_neighbour_queue (n);
1679 /* reschedule PING job */
1680 left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
1681 retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1682 MIN_PING_FREQUENCY);
1684 = GNUNET_SCHEDULER_add_delayed (retry,
1692 * Task triggered when a neighbour entry might have gotten stale.
1694 * @param cls the 'struct Neighbour'
1695 * @param tc scheduler context (not used)
1698 consider_free_task (void *cls,
1699 const struct GNUNET_SCHEDULER_TaskContext *tc)
1701 struct Neighbour *n = cls;
1703 n->dead_clean_task = GNUNET_SCHEDULER_NO_TASK;
1704 consider_free_neighbour (n);
1709 * Consider freeing the given neighbour since we may not need
1710 * to keep it around anymore.
1712 * @param n neighbour to consider discarding
1715 consider_free_neighbour (struct Neighbour *n)
1717 struct Neighbour *pos;
1718 struct Neighbour *prev;
1719 struct GNUNET_TIME_Relative left;
1721 if ( (n->th != NULL) ||
1722 (n->pitr != NULL) ||
1723 (GNUNET_YES == n->is_connected) )
1724 return; /* no chance */
1726 left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
1727 if (left.rel_value > 0)
1729 if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
1730 GNUNET_SCHEDULER_cancel (n->dead_clean_task);
1731 n->dead_clean_task = GNUNET_SCHEDULER_add_delayed (left,
1732 &consider_free_task,
1736 /* actually free the neighbour... */
1745 neighbours = n->next;
1747 prev->next = n->next;
1748 GNUNET_assert (neighbour_count > 0);
1750 GNUNET_STATISTICS_set (stats,
1751 gettext_noop ("# neighbour entries allocated"),
1759 * Function called when the transport service is ready to
1760 * receive an encrypted message for the respective peer
1762 * @param cls neighbour to use message from
1763 * @param size number of bytes we can transmit
1764 * @param buf where to copy the message
1765 * @return number of bytes transmitted
1768 notify_encrypted_transmit_ready (void *cls, size_t size, void *buf)
1770 struct Neighbour *n = cls;
1771 struct MessageEntry *m;
1776 m = n->encrypted_head;
1780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1781 "Encrypted message queue empty, no messages added to buffer for `%4s'\n",
1782 GNUNET_i2s (&n->peer));
1786 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1793 GNUNET_assert (size >= m->size);
1794 memcpy (cbuf, &m[1], m->size);
1796 GNUNET_BANDWIDTH_tracker_consume (&n->available_send_window,
1799 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1800 "Copied message of type %u and size %u into transport buffer for `%4s'\n",
1801 (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
1803 GNUNET_i2s (&n->peer));
1805 process_encrypted_neighbour_queue (n);
1810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1811 "Transmission of message of type %u and size %u failed\n",
1812 (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
1813 (unsigned int) m->size);
1817 consider_free_neighbour (n);
1823 * Check if we have plaintext messages for the specified neighbour
1824 * pending, and if so, consider batching and encrypting them (and
1825 * then trigger processing of the encrypted queue if needed).
1827 * @param n neighbour to check.
1829 static void process_plaintext_neighbour_queue (struct Neighbour *n);
1833 * Check if we have encrypted messages for the specified neighbour
1834 * pending, and if so, check with the transport about sending them
1837 * @param n neighbour to check.
1840 process_encrypted_neighbour_queue (struct Neighbour *n)
1842 struct MessageEntry *m;
1845 return; /* request already pending */
1846 m = n->encrypted_head;
1849 /* encrypted queue empty, try plaintext instead */
1850 process_plaintext_neighbour_queue (n);
1854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1855 "Asking transport for transmission of %u bytes to `%4s' in next %llu ms\n",
1856 (unsigned int) m->size,
1857 GNUNET_i2s (&n->peer),
1858 (unsigned long long) GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value);
1861 GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer,
1864 GNUNET_TIME_absolute_get_remaining
1866 ¬ify_encrypted_transmit_ready,
1870 /* message request too large or duplicate request */
1872 /* discard encrypted message */
1873 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1877 process_encrypted_neighbour_queue (n);
1883 * Decrypt size bytes from in and write the result to out. Use the
1884 * key for inbound traffic of the given neighbour. This function does
1885 * NOT do any integrity-checks on the result.
1887 * @param n neighbour we are receiving from
1888 * @param iv initialization vector to use
1889 * @param in ciphertext
1890 * @param out plaintext
1891 * @param size size of in/out
1892 * @return GNUNET_OK on success
1895 do_decrypt (struct Neighbour *n,
1896 const struct GNUNET_CRYPTO_AesInitializationVector * iv,
1897 const void *in, void *out, size_t size)
1899 if (size != (uint16_t) size)
1904 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
1905 (n->status != PEER_STATE_KEY_CONFIRMED))
1907 GNUNET_break_op (0);
1908 return GNUNET_SYSERR;
1911 GNUNET_CRYPTO_aes_decrypt (in,
1918 return GNUNET_SYSERR;
1920 GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes decrypted"), size, GNUNET_NO);
1922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1923 "Decrypted %u bytes from `%4s' using key %u, IV %u\n",
1924 (unsigned int) size,
1925 GNUNET_i2s (&n->peer),
1926 (unsigned int) n->decrypt_key.crc32,
1927 GNUNET_CRYPTO_crc32_n (iv, sizeof(*iv)));
1934 * Select messages for transmission. This heuristic uses a combination
1935 * of earliest deadline first (EDF) scheduling (with bounded horizon)
1936 * and priority-based discard (in case no feasible schedule exist) and
1937 * speculative optimization (defer any kind of transmission until
1938 * we either create a batch of significant size, 25% of max, or until
1939 * we are close to a deadline). Furthermore, when scheduling the
1940 * heuristic also packs as many messages into the batch as possible,
1941 * starting with those with the earliest deadline. Yes, this is fun.
1943 * @param n neighbour to select messages from
1944 * @param size number of bytes to select for transmission
1945 * @param retry_time set to the time when we should try again
1946 * (only valid if this function returns zero)
1947 * @return number of bytes selected, or 0 if we decided to
1948 * defer scheduling overall; in that case, retry_time is set.
1951 select_messages (struct Neighbour *n,
1952 size_t size, struct GNUNET_TIME_Relative *retry_time)
1954 struct MessageEntry *pos;
1955 struct MessageEntry *min;
1956 struct MessageEntry *last;
1957 unsigned int min_prio;
1958 struct GNUNET_TIME_Absolute t;
1959 struct GNUNET_TIME_Absolute now;
1960 struct GNUNET_TIME_Relative delta;
1962 struct GNUNET_TIME_Relative slack; /* how long could we wait before missing deadlines? */
1965 unsigned int queue_size;
1966 int discard_low_prio;
1968 GNUNET_assert (NULL != n->messages);
1969 now = GNUNET_TIME_absolute_get ();
1970 /* last entry in linked list of messages processed */
1972 /* should we remove the entry with the lowest
1973 priority from consideration for scheduling at the
1984 discard_low_prio = GNUNET_YES;
1985 while (GNUNET_YES == discard_low_prio)
1988 min_prio = UINT_MAX;
1989 discard_low_prio = GNUNET_NO;
1990 /* calculate number of bytes available for transmission at time "t" */
1991 avail = GNUNET_BANDWIDTH_tracker_get_available (&n->available_send_window);
1993 /* how many bytes have we (hypothetically) scheduled so far */
1995 /* maximum time we can wait before transmitting anything
1996 and still make all of our deadlines */
1997 slack = GNUNET_TIME_UNIT_FOREVER_REL;
1999 /* note that we use "*2" here because we want to look
2000 a bit further into the future; much more makes no
2001 sense since new message might be scheduled in the
2003 while ((pos != NULL) && (off < size * 2))
2005 if (pos->do_transmit == GNUNET_YES)
2007 /* already removed from consideration */
2011 if (discard_low_prio == GNUNET_NO)
2013 delta = GNUNET_TIME_absolute_get_difference (t, pos->deadline);
2014 if (delta.rel_value > 0)
2016 // FIXME: HUH? Check!
2018 avail += GNUNET_BANDWIDTH_value_get_available_until (n->bw_out,
2021 if (avail < pos->size)
2023 // FIXME: HUH? Check!
2024 discard_low_prio = GNUNET_YES; /* we could not schedule this one! */
2029 /* update slack, considering both its absolute deadline
2030 and relative deadlines caused by other messages
2031 with their respective load */
2032 slack = GNUNET_TIME_relative_min (slack,
2033 GNUNET_BANDWIDTH_value_get_delay_for (n->bw_out,
2035 if (pos->deadline.abs_value <= now.abs_value)
2038 slack = GNUNET_TIME_UNIT_ZERO;
2040 else if (GNUNET_YES == pos->got_slack)
2042 /* should be soon now! */
2043 slack = GNUNET_TIME_relative_min (slack,
2044 GNUNET_TIME_absolute_get_remaining (pos->slack_deadline));
2049 GNUNET_TIME_relative_min (slack,
2050 GNUNET_TIME_absolute_get_difference (now, pos->deadline));
2051 pos->got_slack = GNUNET_YES;
2052 pos->slack_deadline = GNUNET_TIME_absolute_min (pos->deadline,
2053 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_MAX_CORK_DELAY));
2058 t = GNUNET_TIME_absolute_max (pos->deadline, t); // HUH? Check!
2059 if (pos->priority <= min_prio)
2061 /* update min for discard */
2062 min_prio = pos->priority;
2067 if (discard_low_prio)
2069 GNUNET_assert (min != NULL);
2070 /* remove lowest-priority entry from consideration */
2071 min->do_transmit = GNUNET_YES; /* means: discard (for now) */
2075 /* guard against sending "tiny" messages with large headers without
2077 if ( (slack.rel_value > GNUNET_CONSTANTS_MAX_CORK_DELAY.rel_value) &&
2079 (queue_size <= MAX_PEER_QUEUE_SIZE - 2) )
2081 /* less than 25% of message would be filled with deadlines still
2082 being met if we delay by one second or more; so just wait for
2083 more data; but do not wait longer than 1s (since we don't want
2084 to delay messages for a really long time either). */
2085 *retry_time = GNUNET_CONSTANTS_MAX_CORK_DELAY;
2086 /* reset do_transmit values for next time */
2089 pos->do_transmit = GNUNET_NO;
2092 GNUNET_STATISTICS_update (stats,
2093 gettext_noop ("# transmissions delayed due to corking"),
2096 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2097 "Deferring transmission for %llums due to underfull message buffer size (%u/%u)\n",
2098 (unsigned long long) retry_time->rel_value,
2100 (unsigned int) size);
2104 /* select marked messages (up to size) for transmission */
2109 if ((pos->size <= size) && (pos->do_transmit == GNUNET_NO))
2111 pos->do_transmit = GNUNET_YES; /* mark for transmission */
2115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2116 "Selecting message of size %u for transmission\n",
2117 (unsigned int) pos->size);
2123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2124 "Not selecting message of size %u for transmission at this time (maximum is %u)\n",
2125 (unsigned int) pos->size,
2128 pos->do_transmit = GNUNET_NO; /* mark for not transmitting! */
2133 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2134 "Selected %llu/%llu bytes of %u/%u plaintext messages for transmission to `%4s'.\n",
2135 (unsigned long long) off, (unsigned long long) tsize,
2136 queue_size, (unsigned int) MAX_PEER_QUEUE_SIZE,
2137 GNUNET_i2s (&n->peer));
2144 * Batch multiple messages into a larger buffer.
2146 * @param n neighbour to take messages from
2147 * @param buf target buffer
2148 * @param size size of buf
2149 * @param deadline set to transmission deadline for the result
2150 * @param retry_time set to the time when we should try again
2151 * (only valid if this function returns zero)
2152 * @param priority set to the priority of the batch
2153 * @return number of bytes written to buf (can be zero)
2156 batch_message (struct Neighbour *n,
2159 struct GNUNET_TIME_Absolute *deadline,
2160 struct GNUNET_TIME_Relative *retry_time,
2161 unsigned int *priority)
2163 char ntmb[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
2164 struct NotifyTrafficMessage *ntm = (struct NotifyTrafficMessage*) ntmb;
2165 struct MessageEntry *pos;
2166 struct MessageEntry *prev;
2167 struct MessageEntry *next;
2172 *deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2173 *retry_time = GNUNET_TIME_UNIT_FOREVER_REL;
2174 if (0 == select_messages (n, size, retry_time))
2177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2178 "No messages selected, will try again in %llu ms\n",
2179 retry_time->rel_value);
2183 ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND);
2184 ntm->ats_count = htonl (0);
2185 ntm->ats.type = htonl (0);
2186 ntm->ats.value = htonl (0);
2187 ntm->peer = n->peer;
2190 while ((pos != NULL) && (size >= sizeof (struct GNUNET_MessageHeader)))
2193 if (GNUNET_YES == pos->do_transmit)
2195 GNUNET_assert (pos->size <= size);
2196 /* do notifications */
2197 /* FIXME: track if we have *any* client that wants
2198 full notifications and only do this if that is
2200 if (pos->size < GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct NotifyTrafficMessage))
2202 memcpy (&ntm[1], &pos[1], pos->size);
2203 ntm->header.size = htons (sizeof (struct NotifyTrafficMessage) +
2204 sizeof (struct GNUNET_MessageHeader));
2205 send_to_all_clients (&ntm->header,
2207 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
2211 /* message too large for 'full' notifications, we do at
2212 least the 'hdr' type */
2215 sizeof (struct GNUNET_MessageHeader));
2217 ntm->header.size = htons (sizeof (struct NotifyTrafficMessage) +
2219 send_to_all_clients (&ntm->header,
2221 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
2223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2224 "Encrypting %u bytes with message of type %u and size %u\n",
2226 (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->type),
2227 (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->size));
2229 /* copy for encrypted transmission */
2230 memcpy (&buf[ret], &pos[1], pos->size);
2233 *priority += pos->priority;
2235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2236 "Adding plaintext message of size %u with deadline %llu ms to batch\n",
2237 (unsigned int) pos->size,
2238 (unsigned long long) GNUNET_TIME_absolute_get_remaining (pos->deadline).rel_value);
2240 deadline->abs_value = GNUNET_MIN (deadline->abs_value, pos->deadline.abs_value);
2254 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2255 "Deadline for message batch is %llu ms\n",
2256 GNUNET_TIME_absolute_get_remaining (*deadline).rel_value);
2263 * Remove messages with deadlines that have long expired from
2266 * @param n neighbour to inspect
2269 discard_expired_messages (struct Neighbour *n)
2271 struct MessageEntry *prev;
2272 struct MessageEntry *next;
2273 struct MessageEntry *pos;
2274 struct GNUNET_TIME_Absolute now;
2275 struct GNUNET_TIME_Relative delta;
2279 now = GNUNET_TIME_absolute_get ();
2285 delta = GNUNET_TIME_absolute_get_difference (pos->deadline, now);
2286 if (delta.rel_value > PAST_EXPIRATION_DISCARD_TIME.rel_value)
2289 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2290 "Message is %llu ms past due, discarding.\n",
2297 GNUNET_STATISTICS_update (stats,
2298 gettext_noop ("# messages discarded (expired prior to transmission)"),
2308 if (GNUNET_YES == disc)
2309 schedule_peer_messages (n);
2314 * Signature of the main function of a task.
2316 * @param cls closure
2317 * @param tc context information (why was this task triggered now)
2320 retry_plaintext_processing (void *cls,
2321 const struct GNUNET_SCHEDULER_TaskContext *tc)
2323 struct Neighbour *n = cls;
2325 n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2326 process_plaintext_neighbour_queue (n);
2331 * Send our key (and encrypted PING) to the other peer.
2333 * @param n the other peer
2335 static void send_key (struct Neighbour *n);
2338 * Task that will retry "send_key" if our previous attempt failed
2342 set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2344 struct Neighbour *n = cls;
2347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2348 "Retrying key transmission to `%4s'\n",
2349 GNUNET_i2s (&n->peer));
2351 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
2352 n->set_key_retry_frequency =
2353 GNUNET_TIME_relative_multiply (n->set_key_retry_frequency, 2);
2359 * Check if we have plaintext messages for the specified neighbour
2360 * pending, and if so, consider batching and encrypting them (and
2361 * then trigger processing of the encrypted queue if needed).
2363 * @param n neighbour to check.
2366 process_plaintext_neighbour_queue (struct Neighbour *n)
2368 char pbuf[GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE + sizeof (struct EncryptedMessage)]; /* plaintext */
2370 struct EncryptedMessage *em; /* encrypted message */
2371 struct EncryptedMessage *ph; /* plaintext header */
2372 struct MessageEntry *me;
2373 unsigned int priority;
2374 struct GNUNET_TIME_Absolute deadline;
2375 struct GNUNET_TIME_Relative retry_time;
2376 struct GNUNET_CRYPTO_AesInitializationVector iv;
2377 struct GNUNET_CRYPTO_AuthKey auth_key;
2379 if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
2381 GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
2382 n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2386 case PEER_STATE_DOWN:
2389 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2390 "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2391 GNUNET_i2s(&n->peer));
2394 case PEER_STATE_KEY_SENT:
2395 if (n->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK)
2396 n->retry_set_key_task
2397 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2398 &set_key_retry_task, n);
2400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2401 "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2402 GNUNET_i2s(&n->peer));
2405 case PEER_STATE_KEY_RECEIVED:
2406 if (n->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK)
2407 n->retry_set_key_task
2408 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2409 &set_key_retry_task, n);
2411 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2412 "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2413 GNUNET_i2s(&n->peer));
2416 case PEER_STATE_KEY_CONFIRMED:
2417 /* ready to continue */
2420 discard_expired_messages (n);
2421 if (n->messages == NULL)
2424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2425 "Plaintext message queue for `%4s' is empty.\n",
2426 GNUNET_i2s(&n->peer));
2428 return; /* no pending messages */
2430 if (n->encrypted_head != NULL)
2433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2434 "Encrypted message queue for `%4s' is still full, delaying plaintext processing.\n",
2435 GNUNET_i2s(&n->peer));
2437 return; /* wait for messages already encrypted to be
2440 ph = (struct EncryptedMessage *) pbuf;
2441 deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2443 used = sizeof (struct EncryptedMessage);
2444 used += batch_message (n,
2446 GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE,
2447 &deadline, &retry_time, &priority);
2448 if (used == sizeof (struct EncryptedMessage))
2451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2452 "No messages selected for transmission to `%4s' at this time, will try again later.\n",
2453 GNUNET_i2s(&n->peer));
2455 /* no messages selected for sending, try again later... */
2456 n->retry_plaintext_task =
2457 GNUNET_SCHEDULER_add_delayed (retry_time,
2458 &retry_plaintext_processing, n);
2461 #if DEBUG_CORE_QUOTA
2462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2463 "Sending %u b/s as new limit to peer `%4s'\n",
2464 (unsigned int) ntohl (n->bw_in.value__),
2465 GNUNET_i2s (&n->peer));
2467 ph->iv_seed = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
2468 ph->sequence_number = htonl (++n->last_sequence_number_sent);
2469 ph->inbound_bw_limit = n->bw_in;
2470 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
2472 /* setup encryption message header */
2473 me = GNUNET_malloc (sizeof (struct MessageEntry) + used);
2474 me->deadline = deadline;
2475 me->priority = priority;
2477 em = (struct EncryptedMessage *) &me[1];
2478 em->header.size = htons (used);
2479 em->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
2480 em->iv_seed = ph->iv_seed;
2481 derive_iv (&iv, &n->encrypt_key, ph->iv_seed, &n->peer);
2484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2485 "Encrypting %u bytes of plaintext messages for `%4s' for transmission in %llums.\n",
2486 (unsigned int) used - ENCRYPTED_HEADER_SIZE,
2487 GNUNET_i2s(&n->peer),
2488 (unsigned long long) GNUNET_TIME_absolute_get_remaining (deadline).rel_value);
2490 GNUNET_assert (GNUNET_OK ==
2493 &ph->sequence_number,
2494 &em->sequence_number, used - ENCRYPTED_HEADER_SIZE));
2495 derive_auth_key (&auth_key,
2498 n->encrypt_key_created);
2499 GNUNET_CRYPTO_hmac (&auth_key,
2500 &em->sequence_number,
2501 used - ENCRYPTED_HEADER_SIZE,
2504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2505 "Authenticated %u bytes of ciphertext %u: `%s'\n",
2506 used - ENCRYPTED_HEADER_SIZE,
2507 GNUNET_CRYPTO_crc32_n (&em->sequence_number,
2508 used - ENCRYPTED_HEADER_SIZE),
2509 GNUNET_h2s (&em->hmac));
2511 /* append to transmission list */
2512 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
2516 process_encrypted_neighbour_queue (n);
2517 schedule_peer_messages (n);
2522 * Function that recalculates the bandwidth quota for the
2523 * given neighbour and transmits it to the transport service.
2525 * @param cls neighbour for the quota update
2529 neighbour_quota_update (void *cls,
2530 const struct GNUNET_SCHEDULER_TaskContext *tc);
2534 * Schedule the task that will recalculate the bandwidth
2535 * quota for this peer (and possibly force a disconnect of
2536 * idle peers by calculating a bandwidth of zero).
2539 schedule_quota_update (struct Neighbour *n)
2541 GNUNET_assert (n->quota_update_task ==
2542 GNUNET_SCHEDULER_NO_TASK);
2543 n->quota_update_task
2544 = GNUNET_SCHEDULER_add_delayed (QUOTA_UPDATE_FREQUENCY,
2545 &neighbour_quota_update,
2551 * Initialize a new 'struct Neighbour'.
2553 * @param pid ID of the new neighbour
2554 * @return handle for the new neighbour
2556 static struct Neighbour *
2557 create_neighbour (const struct GNUNET_PeerIdentity *pid)
2559 struct Neighbour *n;
2560 struct GNUNET_TIME_Absolute now;
2563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2564 "Creating neighbour entry for peer `%4s'\n",
2567 n = GNUNET_malloc (sizeof (struct Neighbour));
2568 n->next = neighbours;
2571 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), neighbour_count, GNUNET_NO);
2573 GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
2574 now = GNUNET_TIME_absolute_get ();
2575 n->encrypt_key_created = now;
2576 n->last_activity = now;
2577 n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
2578 n->bw_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2579 n->bw_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2580 n->bw_out_internal_limit = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
2581 n->bw_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2582 n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
2584 neighbour_quota_update (n, NULL);
2585 consider_free_neighbour (n);
2591 * Handle CORE_SEND request.
2594 * @param client the client issuing the request
2595 * @param message the "struct SendMessage"
2598 handle_client_send (void *cls,
2599 struct GNUNET_SERVER_Client *client,
2600 const struct GNUNET_MessageHeader *message)
2602 const struct SendMessage *sm;
2603 struct Neighbour *n;
2604 struct MessageEntry *prev;
2605 struct MessageEntry *pos;
2606 struct MessageEntry *e;
2607 struct MessageEntry *min_prio_entry;
2608 struct MessageEntry *min_prio_prev;
2609 unsigned int min_prio;
2610 unsigned int queue_size;
2613 msize = ntohs (message->size);
2615 sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader))
2617 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "about to assert fail, msize is %d, should be at least %d\n", msize, sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader));
2620 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2623 sm = (const struct SendMessage *) message;
2624 msize -= sizeof (struct SendMessage);
2625 if (0 == memcmp (&sm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2627 /* FIXME: should we not allow loopback-injection here? */
2630 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2633 n = find_neighbour (&sm->peer);
2635 n = create_neighbour (&sm->peer);
2637 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2638 "Core received `%s' request, queueing %u bytes of plaintext data for transmission to `%4s'.\n",
2640 (unsigned int) msize,
2641 GNUNET_i2s (&sm->peer));
2643 discard_expired_messages (n);
2644 /* bound queue size */
2645 /* NOTE: this entire block to bound the queue size should be
2646 obsolete with the new client-request code and the
2647 'schedule_peer_messages' mechanism; we still have this code in
2648 here for now as a sanity check for the new mechanmism;
2649 ultimately, we should probably simply reject SEND messages that
2650 are not 'approved' (or provide a new core API for very unreliable
2651 delivery that always sends with priority 0). Food for thought. */
2652 min_prio = UINT32_MAX;
2653 min_prio_entry = NULL;
2654 min_prio_prev = NULL;
2660 if (pos->priority <= min_prio)
2662 min_prio_entry = pos;
2663 min_prio_prev = prev;
2664 min_prio = pos->priority;
2670 if (queue_size >= MAX_PEER_QUEUE_SIZE)
2673 if (ntohl(sm->priority) <= min_prio)
2675 /* discard new entry; this should no longer happen! */
2678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2679 "Queue full (%u/%u), discarding new request (%u bytes of type %u)\n",
2681 (unsigned int) MAX_PEER_QUEUE_SIZE,
2682 (unsigned int) msize,
2683 (unsigned int) ntohs (message->type));
2685 GNUNET_STATISTICS_update (stats,
2686 gettext_noop ("# discarded CORE_SEND requests"),
2690 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2693 GNUNET_assert (min_prio_entry != NULL);
2694 /* discard "min_prio_entry" */
2696 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2697 "Queue full, discarding existing older request\n");
2699 GNUNET_STATISTICS_update (stats, gettext_noop ("# discarded lower priority CORE_SEND requests"), 1, GNUNET_NO);
2700 if (min_prio_prev == NULL)
2701 n->messages = min_prio_entry->next;
2703 min_prio_prev->next = min_prio_entry->next;
2704 GNUNET_free (min_prio_entry);
2708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2709 "Adding transmission request for `%4s' of size %u to queue\n",
2710 GNUNET_i2s (&sm->peer),
2711 (unsigned int) msize);
2713 e = GNUNET_malloc (sizeof (struct MessageEntry) + msize);
2714 e->deadline = GNUNET_TIME_absolute_ntoh (sm->deadline);
2715 e->priority = ntohl (sm->priority);
2717 memcpy (&e[1], &sm[1], msize);
2719 /* insert, keep list sorted by deadline */
2722 while ((pos != NULL) && (pos->deadline.abs_value < e->deadline.abs_value))
2733 /* consider scheduling now */
2734 process_plaintext_neighbour_queue (n);
2736 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2741 * Function called when the transport service is ready to
2742 * receive a message. Only resets 'n->th' to NULL.
2744 * @param cls neighbour to use message from
2745 * @param size number of bytes we can transmit
2746 * @param buf where to copy the message
2747 * @return number of bytes transmitted
2750 notify_transport_connect_done (void *cls, size_t size, void *buf)
2752 struct Neighbour *n = cls;
2755 if (GNUNET_YES != n->is_connected)
2757 /* transport should only call us to transmit a message after
2758 * telling us about a successful connection to the respective peer */
2760 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout on notify connect!\n");
2766 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2767 _("Failed to connect to `%4s': transport failed to connect\n"),
2768 GNUNET_i2s (&n->peer));
2771 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2772 _("TRANSPORT connection to peer `%4s' is up, trying to establish CORE connection\n"),
2773 GNUNET_i2s (&n->peer));
2774 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
2775 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
2776 n->retry_set_key_task = GNUNET_SCHEDULER_add_now (&set_key_retry_task,
2783 * Handle CORE_REQUEST_CONNECT request.
2786 * @param client the client issuing the request
2787 * @param message the "struct ConnectMessage"
2790 handle_client_request_connect (void *cls,
2791 struct GNUNET_SERVER_Client *client,
2792 const struct GNUNET_MessageHeader *message)
2794 const struct ConnectMessage *cm = (const struct ConnectMessage*) message;
2795 struct Neighbour *n;
2796 struct GNUNET_TIME_Relative timeout;
2798 if (0 == memcmp (&cm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2801 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2804 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2805 n = find_neighbour (&cm->peer);
2807 n = create_neighbour (&cm->peer);
2808 if ( (GNUNET_YES == n->is_connected) ||
2811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2812 "Core received `%s' request for `%4s', already connected!\n",
2814 GNUNET_i2s (&cm->peer));
2815 return; /* already connected, or at least trying */
2817 GNUNET_STATISTICS_update (stats, gettext_noop ("# connection requests received"), 1, GNUNET_NO);
2819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2820 "Core received `%s' request for `%4s', will try to establish connection\n",
2822 GNUNET_i2s (&cm->peer));
2824 timeout = GNUNET_TIME_relative_ntoh (cm->timeout);
2825 /* ask transport to connect to the peer */
2826 n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
2828 sizeof (struct GNUNET_MessageHeader), 0,
2830 ¬ify_transport_connect_done,
2832 GNUNET_break (NULL != n->th);
2837 * PEERINFO is giving us a HELLO for a peer. Add the public key to
2838 * the neighbour's struct and retry send_key. Or, if we did not get a
2839 * HELLO, just do nothing.
2841 * @param cls the 'struct Neighbour' to retry sending the key for
2842 * @param peer the peer for which this is the HELLO
2843 * @param hello HELLO message of that peer
2846 process_hello_retry_send_key (void *cls,
2847 const struct GNUNET_PeerIdentity *peer,
2848 const struct GNUNET_HELLO_Message *hello)
2850 struct Neighbour *n = cls;
2855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2856 "Entered `%s' and `%s' is NULL!\n",
2857 "process_hello_retry_send_key",
2861 if (n->public_key != NULL)
2863 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
2865 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
2866 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
2868 GNUNET_STATISTICS_update (stats,
2869 gettext_noop ("# SET_KEY messages deferred (need public key)"),
2877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2878 "Failed to obtain public key for peer `%4s', delaying processing of SET_KEY\n",
2879 GNUNET_i2s (&n->peer));
2881 GNUNET_STATISTICS_update (stats,
2882 gettext_noop ("# Delayed connecting due to lack of public key"),
2885 if (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task)
2886 n->retry_set_key_task
2887 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2888 &set_key_retry_task, n);
2894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2895 "Entered `%s' for peer `%4s'\n",
2896 "process_hello_retry_send_key",
2899 if (n->public_key != NULL)
2901 /* already have public key, why are we here? */
2907 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2908 "Received new `%s' message for `%4s', initiating key exchange.\n",
2913 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2914 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
2916 GNUNET_STATISTICS_update (stats,
2917 gettext_noop ("# Error extracting public key from HELLO"),
2920 GNUNET_free (n->public_key);
2921 n->public_key = NULL;
2923 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2924 "GNUNET_HELLO_get_key returned awfully\n");
2932 * Send our key (and encrypted PING) to the other peer.
2934 * @param n the other peer
2937 send_key (struct Neighbour *n)
2939 struct MessageEntry *pos;
2940 struct SetKeyMessage *sm;
2941 struct MessageEntry *me;
2942 struct PingMessage pp;
2943 struct PingMessage *pm;
2944 struct GNUNET_CRYPTO_AesInitializationVector iv;
2946 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
2948 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
2949 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
2951 if (n->pitr != NULL)
2954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2955 "Key exchange in progress with `%4s'.\n",
2956 GNUNET_i2s (&n->peer));
2958 return; /* already in progress */
2960 if (GNUNET_YES != n->is_connected)
2963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2964 "Not yet connected to peer `%4s'!\n",
2965 GNUNET_i2s (&n->peer));
2969 GNUNET_STATISTICS_update (stats,
2970 gettext_noop ("# Asking transport to connect (for SET_KEY)"),
2973 n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
2975 sizeof (struct SetKeyMessage) + sizeof (struct PingMessage),
2977 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2978 ¬ify_encrypted_transmit_ready,
2984 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2985 "Asked to perform key exchange with `%4s'.\n",
2986 GNUNET_i2s (&n->peer));
2988 if (n->public_key == NULL)
2990 /* lookup n's public key, then try again */
2992 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2993 "Lacking public key for `%4s', trying to obtain one (send_key).\n",
2994 GNUNET_i2s (&n->peer));
2996 GNUNET_assert (n->pitr == NULL);
2997 n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
2999 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20),
3000 &process_hello_retry_send_key, n);
3003 pos = n->encrypted_head;
3006 if (GNUNET_YES == pos->is_setkey)
3008 if (pos->sender_status == n->status)
3011 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3012 "`%s' message for `%4s' queued already\n",
3014 GNUNET_i2s (&n->peer));
3016 goto trigger_processing;
3018 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
3023 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3024 "Removing queued `%s' message for `%4s', will create a new one\n",
3026 GNUNET_i2s (&n->peer));
3036 case PEER_STATE_DOWN:
3037 n->status = PEER_STATE_KEY_SENT;
3039 case PEER_STATE_KEY_SENT:
3041 case PEER_STATE_KEY_RECEIVED:
3043 case PEER_STATE_KEY_CONFIRMED:
3051 /* first, set key message */
3052 me = GNUNET_malloc (sizeof (struct MessageEntry) +
3053 sizeof (struct SetKeyMessage) +
3054 sizeof (struct PingMessage));
3055 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_SET_KEY_DELAY);
3056 me->priority = SET_KEY_PRIORITY;
3057 me->size = sizeof (struct SetKeyMessage) + sizeof (struct PingMessage);
3058 me->is_setkey = GNUNET_YES;
3059 me->got_slack = GNUNET_YES; /* do not defer this one! */
3060 me->sender_status = n->status;
3061 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
3065 sm = (struct SetKeyMessage *) &me[1];
3066 sm->header.size = htons (sizeof (struct SetKeyMessage));
3067 sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SET_KEY);
3068 sm->sender_status = htonl ((int32_t) ((n->status == PEER_STATE_DOWN) ?
3069 PEER_STATE_KEY_SENT : n->status));
3071 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3072 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3073 sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
3074 sizeof (struct GNUNET_PeerIdentity));
3075 sm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_KEY);
3076 sm->creation_time = GNUNET_TIME_absolute_hton (n->encrypt_key_created);
3077 sm->target = n->peer;
3078 GNUNET_assert (GNUNET_OK ==
3079 GNUNET_CRYPTO_rsa_encrypt (&n->encrypt_key,
3081 GNUNET_CRYPTO_AesSessionKey),
3083 &sm->encrypted_key));
3084 GNUNET_assert (GNUNET_OK ==
3085 GNUNET_CRYPTO_rsa_sign (my_private_key, &sm->purpose,
3087 pm = (struct PingMessage *) &sm[1];
3088 pm->header.size = htons (sizeof (struct PingMessage));
3089 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
3090 pm->iv_seed = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
3091 derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
3092 pp.challenge = n->ping_challenge;
3093 pp.target = n->peer;
3095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3096 "Encrypting `%s' and `%s' messages with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
3098 (unsigned int) n->ping_challenge,
3099 GNUNET_i2s (&n->peer),
3100 (unsigned int) n->encrypt_key.crc32,
3101 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3108 sizeof (struct PingMessage) -
3109 ((void *) &pm->target - (void *) pm));
3110 GNUNET_STATISTICS_update (stats,
3111 gettext_noop ("# SET_KEY and PING messages created"),
3115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3116 "Have %llu ms left for `%s' transmission.\n",
3117 (unsigned long long) GNUNET_TIME_absolute_get_remaining (me->deadline).rel_value,
3121 /* trigger queue processing */
3122 process_encrypted_neighbour_queue (n);
3123 if ( (n->status != PEER_STATE_KEY_CONFIRMED) &&
3124 (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task) )
3125 n->retry_set_key_task
3126 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
3127 &set_key_retry_task, n);
3132 * We received a SET_KEY message. Validate and update
3133 * our key material and status.
3135 * @param n the neighbour from which we received message m
3136 * @param m the set key message we received
3139 handle_set_key (struct Neighbour *n,
3140 const struct SetKeyMessage *m);
3144 * PEERINFO is giving us a HELLO for a peer. Add the public key to
3145 * the neighbour's struct and retry handling the set_key message. Or,
3146 * if we did not get a HELLO, just free the set key message.
3148 * @param cls pointer to the set key message
3149 * @param peer the peer for which this is the HELLO
3150 * @param hello HELLO message of that peer
3153 process_hello_retry_handle_set_key (void *cls,
3154 const struct GNUNET_PeerIdentity *peer,
3155 const struct GNUNET_HELLO_Message *hello)
3157 struct Neighbour *n = cls;
3158 struct SetKeyMessage *sm = n->skm;
3164 if (n->public_key != NULL)
3167 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3168 "Received `%s' for `%4s', continuing processing of `%s' message.\n",
3170 GNUNET_i2s (&n->peer),
3173 handle_set_key (n, sm);
3177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3178 _("Ignoring `%s' message due to lack of public key for peer `%4s' (failed to obtain one).\n"),
3180 GNUNET_i2s (&n->peer));
3185 if (n->public_key != NULL)
3186 return; /* multiple HELLOs match!? */
3188 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3189 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
3191 GNUNET_break_op (0);
3192 GNUNET_free (n->public_key);
3193 n->public_key = NULL;
3199 * We received a PING message. Validate and transmit
3202 * @param n sender of the PING
3203 * @param m the encrypted PING message itself
3206 handle_ping (struct Neighbour *n, const struct PingMessage *m)
3208 struct PingMessage t;
3209 struct PongMessage tx;
3210 struct PongMessage *tp;
3211 struct MessageEntry *me;
3212 struct GNUNET_CRYPTO_AesInitializationVector iv;
3215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3216 "Core service receives `%s' request from `%4s'.\n",
3217 "PING", GNUNET_i2s (&n->peer));
3219 derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
3225 sizeof (struct PingMessage) -
3226 ((void *) &m->target - (void *) m)))
3229 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3230 "Decrypted `%s' to `%4s' with challenge %u decrypted using key %u, IV %u (salt %u)\n",
3232 GNUNET_i2s (&t.target),
3233 (unsigned int) t.challenge,
3234 (unsigned int) n->decrypt_key.crc32,
3235 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3238 GNUNET_STATISTICS_update (stats,
3239 gettext_noop ("# PING messages decrypted"),
3242 if (0 != memcmp (&t.target,
3243 &my_identity, sizeof (struct GNUNET_PeerIdentity)))
3245 GNUNET_break_op (0);
3248 me = GNUNET_malloc (sizeof (struct MessageEntry) +
3249 sizeof (struct PongMessage));
3250 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
3254 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PONG_DELAY);
3255 me->priority = PONG_PRIORITY;
3256 me->size = sizeof (struct PongMessage);
3257 tx.inbound_bw_limit = n->bw_in;
3258 tx.challenge = t.challenge;
3259 tx.target = t.target;
3260 tp = (struct PongMessage *) &me[1];
3261 tp->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG);
3262 tp->header.size = htons (sizeof (struct PongMessage));
3263 tp->iv_seed = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
3264 derive_pong_iv (&iv, &n->encrypt_key, tp->iv_seed, t.challenge, &n->peer);
3269 sizeof (struct PongMessage) -
3270 ((void *) &tp->challenge - (void *) tp));
3271 GNUNET_STATISTICS_update (stats,
3272 gettext_noop ("# PONG messages created"),
3276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3277 "Encrypting `%s' with challenge %u using key %u, IV %u (salt %u)\n",
3279 (unsigned int) t.challenge,
3280 (unsigned int) n->encrypt_key.crc32,
3281 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3284 /* trigger queue processing */
3285 process_encrypted_neighbour_queue (n);
3290 * We received a PONG message. Validate and update our status.
3292 * @param n sender of the PONG
3293 * @param m the encrypted PONG message itself
3296 handle_pong (struct Neighbour *n,
3297 const struct PongMessage *m)
3299 struct PongMessage t;
3300 struct ConnectNotifyMessage cnm;
3301 struct GNUNET_CRYPTO_AesInitializationVector iv;
3304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3305 "Core service receives `%s' response from `%4s'.\n",
3306 "PONG", GNUNET_i2s (&n->peer));
3308 /* mark as garbage, just to be sure */
3309 memset (&t, 255, sizeof (t));
3310 derive_pong_iv (&iv, &n->decrypt_key, m->iv_seed, n->ping_challenge,
3317 sizeof (struct PongMessage) -
3318 ((void *) &m->challenge - (void *) m)))
3320 GNUNET_break_op (0);
3323 GNUNET_STATISTICS_update (stats,
3324 gettext_noop ("# PONG messages decrypted"),
3328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3329 "Decrypted `%s' from `%4s' with challenge %u using key %u, IV %u (salt %u)\n",
3331 GNUNET_i2s (&t.target),
3332 (unsigned int) t.challenge,
3333 (unsigned int) n->decrypt_key.crc32,
3334 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3337 if ((0 != memcmp (&t.target,
3339 sizeof (struct GNUNET_PeerIdentity))) ||
3340 (n->ping_challenge != t.challenge))
3342 /* PONG malformed */
3344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3345 "Received malformed `%s' wanted sender `%4s' with challenge %u\n",
3347 GNUNET_i2s (&n->peer),
3348 (unsigned int) n->ping_challenge);
3349 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3350 "Received malformed `%s' received from `%4s' with challenge %u\n",
3351 "PONG", GNUNET_i2s (&t.target),
3352 (unsigned int) t.challenge);
3354 GNUNET_break_op (n->ping_challenge != t.challenge);
3359 case PEER_STATE_DOWN:
3360 GNUNET_break (0); /* should be impossible */
3362 case PEER_STATE_KEY_SENT:
3363 GNUNET_break (0); /* should be impossible, how did we decrypt? */
3365 case PEER_STATE_KEY_RECEIVED:
3366 GNUNET_STATISTICS_update (stats,
3367 gettext_noop ("# Session keys confirmed via PONG"),
3370 n->status = PEER_STATE_KEY_CONFIRMED;
3371 if (n->bw_out_external_limit.value__ != t.inbound_bw_limit.value__)
3373 n->bw_out_external_limit = t.inbound_bw_limit;
3374 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
3375 n->bw_out_internal_limit);
3376 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
3378 GNUNET_TRANSPORT_set_quota (transport,
3382 GNUNET_TIME_UNIT_FOREVER_REL,
3386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3387 "Confirmed key via `%s' message for peer `%4s'\n",
3388 "PONG", GNUNET_i2s (&n->peer));
3390 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3392 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3393 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3395 cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
3396 cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
3397 cnm.ats_count = htonl (0);
3399 cnm.ats.type = htonl (0);
3400 cnm.ats.value = htonl (0);
3401 send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_CONNECT);
3402 process_encrypted_neighbour_queue (n);
3404 case PEER_STATE_KEY_CONFIRMED:
3405 n->last_activity = GNUNET_TIME_absolute_get ();
3406 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
3407 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
3409 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
3412 handle_peer_status_change (n);
3422 * We received a SET_KEY message. Validate and update
3423 * our key material and status.
3425 * @param n the neighbour from which we received message m
3426 * @param m the set key message we received
3429 handle_set_key (struct Neighbour *n, const struct SetKeyMessage *m)
3431 struct SetKeyMessage *m_cpy;
3432 struct GNUNET_TIME_Absolute t;
3433 struct GNUNET_CRYPTO_AesSessionKey k;
3434 struct PingMessage *ping;
3435 struct PongMessage *pong;
3436 enum PeerStateMachine sender_status;
3439 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3440 "Core service receives `%s' request from `%4s'.\n",
3441 "SET_KEY", GNUNET_i2s (&n->peer));
3443 if (n->public_key == NULL)
3445 if (n->pitr != NULL)
3448 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3449 "Ignoring `%s' message due to lack of public key for peer (still trying to obtain one).\n",
3455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3456 "Lacking public key for peer, trying to obtain one (handle_set_key).\n");
3458 m_cpy = GNUNET_malloc (sizeof (struct SetKeyMessage));
3459 memcpy (m_cpy, m, sizeof (struct SetKeyMessage));
3460 /* lookup n's public key, then try again */
3461 GNUNET_assert (n->skm == NULL);
3463 n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
3465 GNUNET_TIME_UNIT_MINUTES,
3466 &process_hello_retry_handle_set_key, n);
3467 GNUNET_STATISTICS_update (stats,
3468 gettext_noop ("# SET_KEY messages deferred (need public key)"),
3473 if (0 != memcmp (&m->target,
3475 sizeof (struct GNUNET_PeerIdentity)))
3477 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3478 _("Received `%s' message that was for `%s', not for me. Ignoring.\n"),
3480 GNUNET_i2s (&m->target));
3483 if ((ntohl (m->purpose.size) !=
3484 sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3485 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3486 sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
3487 sizeof (struct GNUNET_PeerIdentity)) ||
3489 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_KEY,
3490 &m->purpose, &m->signature, n->public_key)))
3492 /* invalid signature */
3493 GNUNET_break_op (0);
3496 t = GNUNET_TIME_absolute_ntoh (m->creation_time);
3497 if (((n->status == PEER_STATE_KEY_RECEIVED) ||
3498 (n->status == PEER_STATE_KEY_CONFIRMED)) &&
3499 (t.abs_value < n->decrypt_key_created.abs_value))
3501 /* this could rarely happen due to massive re-ordering of
3502 messages on the network level, but is most likely either
3503 a bug or some adversary messing with us. Report. */
3504 GNUNET_break_op (0);
3508 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3509 "Decrypting key material.\n");
3511 if ((GNUNET_CRYPTO_rsa_decrypt (my_private_key,
3514 sizeof (struct GNUNET_CRYPTO_AesSessionKey))
3515 != sizeof (struct GNUNET_CRYPTO_AesSessionKey)) ||
3516 (GNUNET_OK != GNUNET_CRYPTO_aes_check_session_key (&k)))
3518 /* failed to decrypt !? */
3519 GNUNET_break_op (0);
3522 GNUNET_STATISTICS_update (stats,
3523 gettext_noop ("# SET_KEY messages decrypted"),
3527 if (n->decrypt_key_created.abs_value != t.abs_value)
3529 /* fresh key, reset sequence numbers */
3530 n->last_sequence_number_received = 0;
3531 n->last_packets_bitmap = 0;
3532 n->decrypt_key_created = t;
3534 sender_status = (enum PeerStateMachine) ntohl (m->sender_status);
3537 case PEER_STATE_DOWN:
3538 n->status = PEER_STATE_KEY_RECEIVED;
3540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3541 "Responding to `%s' with my own key.\n", "SET_KEY");
3545 case PEER_STATE_KEY_SENT:
3546 case PEER_STATE_KEY_RECEIVED:
3547 n->status = PEER_STATE_KEY_RECEIVED;
3548 if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
3549 (sender_status != PEER_STATE_KEY_CONFIRMED))
3552 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3553 "Responding to `%s' with my own key (other peer has status %u).\n",
3555 (unsigned int) sender_status);
3560 case PEER_STATE_KEY_CONFIRMED:
3561 if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
3562 (sender_status != PEER_STATE_KEY_CONFIRMED))
3565 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3566 "Responding to `%s' with my own key (other peer has status %u), I was already fully up.\n",
3568 (unsigned int) sender_status);
3577 if (n->pending_ping != NULL)
3579 ping = n->pending_ping;
3580 n->pending_ping = NULL;
3581 handle_ping (n, ping);
3584 if (n->pending_pong != NULL)
3586 pong = n->pending_pong;
3587 n->pending_pong = NULL;
3588 handle_pong (n, pong);
3595 * Send a P2P message to a client.
3597 * @param sender who sent us the message?
3598 * @param client who should we give the message to?
3599 * @param m contains the message to transmit
3600 * @param msize number of bytes in buf to transmit
3603 send_p2p_message_to_client (struct Neighbour *sender,
3604 struct Client *client,
3605 const void *m, size_t msize)
3607 char buf[msize + sizeof (struct NotifyTrafficMessage)];
3608 struct NotifyTrafficMessage *ntm;
3611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3612 "Core service passes message from `%4s' of type %u to client.\n",
3613 GNUNET_i2s(&sender->peer),
3614 (unsigned int) ntohs (((const struct GNUNET_MessageHeader *) m)->type));
3616 ntm = (struct NotifyTrafficMessage *) buf;
3617 ntm->header.size = htons (msize + sizeof (struct NotifyTrafficMessage));
3618 ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
3619 ntm->ats_count = htonl (0);
3620 ntm->ats.type = htonl (0);
3621 ntm->ats.value = htonl (0);
3622 ntm->peer = sender->peer;
3623 memcpy (&ntm[1], m, msize);
3624 send_to_client (client, &ntm->header, GNUNET_YES);
3629 * Deliver P2P message to interested clients.
3631 * @param cls always NULL
3632 * @param client who sent us the message (struct Neighbour)
3633 * @param m the message
3636 deliver_message (void *cls,
3638 const struct GNUNET_MessageHeader *m)
3640 struct Neighbour *sender = client;
3641 size_t msize = ntohs (m->size);
3643 struct Client *cpos;
3649 type = ntohs (m->type);
3651 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3652 "Received encapsulated message of type %u and size %u from `%4s'\n",
3653 (unsigned int) type,
3655 GNUNET_i2s (&sender->peer));
3657 GNUNET_snprintf (buf,
3659 gettext_noop ("# bytes of messages of type %u received"),
3660 (unsigned int) type);
3661 GNUNET_STATISTICS_set (stats,
3665 dropped = GNUNET_YES;
3667 while (cpos != NULL)
3669 deliver_full = GNUNET_NO;
3670 if (0 != (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))
3671 deliver_full = GNUNET_YES;
3674 for (tpos = 0; tpos < cpos->tcnt; tpos++)
3676 if (type != cpos->types[tpos])
3678 deliver_full = GNUNET_YES;
3682 if (GNUNET_YES == deliver_full)
3684 send_p2p_message_to_client (sender, cpos, m, msize);
3685 dropped = GNUNET_NO;
3687 else if (cpos->options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)
3689 send_p2p_message_to_client (sender, cpos, m,
3690 sizeof (struct GNUNET_MessageHeader));
3694 if (dropped == GNUNET_YES)
3697 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3698 "Message of type %u from `%4s' not delivered to any client.\n",
3699 (unsigned int) type,
3700 GNUNET_i2s (&sender->peer));
3702 GNUNET_STATISTICS_update (stats,
3703 gettext_noop ("# messages not delivered to any client"),
3710 * We received an encrypted message. Decrypt, validate and
3711 * pass on to the appropriate clients.
3714 handle_encrypted_message (struct Neighbour *n,
3715 const struct EncryptedMessage *m)
3717 size_t size = ntohs (m->header.size);
3719 struct EncryptedMessage *pt; /* plaintext */
3722 struct GNUNET_TIME_Absolute t;
3723 struct GNUNET_CRYPTO_AesInitializationVector iv;
3724 struct GNUNET_CRYPTO_AuthKey auth_key;
3727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3728 "Core service receives `%s' request from `%4s'.\n",
3729 "ENCRYPTED_MESSAGE", GNUNET_i2s (&n->peer));
3732 derive_auth_key (&auth_key,
3735 n->decrypt_key_created);
3736 GNUNET_CRYPTO_hmac (&auth_key,
3737 &m->sequence_number,
3738 size - ENCRYPTED_HEADER_SIZE, &ph);
3740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3741 "Re-Authenticated %u bytes of ciphertext (`%u'): `%s'\n",
3742 (unsigned int) size - ENCRYPTED_HEADER_SIZE,
3743 GNUNET_CRYPTO_crc32_n (&m->sequence_number,
3744 size - ENCRYPTED_HEADER_SIZE),
3748 if (0 != memcmp (&ph,
3750 sizeof (GNUNET_HashCode)))
3752 /* checksum failed */
3753 GNUNET_break_op (0);
3756 derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
3761 &m->sequence_number,
3762 &buf[ENCRYPTED_HEADER_SIZE],
3763 size - ENCRYPTED_HEADER_SIZE))
3765 pt = (struct EncryptedMessage *) buf;
3767 /* validate sequence number */
3768 snum = ntohl (pt->sequence_number);
3769 if (n->last_sequence_number_received == snum)
3771 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3772 "Received duplicate message, ignoring.\n");
3773 /* duplicate, ignore */
3774 GNUNET_STATISTICS_set (stats,
3775 gettext_noop ("# bytes dropped (duplicates)"),
3780 if ((n->last_sequence_number_received > snum) &&
3781 (n->last_sequence_number_received - snum > 32))
3783 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3784 "Received ancient out of sequence message, ignoring.\n");
3785 /* ancient out of sequence, ignore */
3786 GNUNET_STATISTICS_set (stats,
3787 gettext_noop ("# bytes dropped (out of sequence)"),
3792 if (n->last_sequence_number_received > snum)
3794 unsigned int rotbit =
3795 1 << (n->last_sequence_number_received - snum - 1);
3796 if ((n->last_packets_bitmap & rotbit) != 0)
3798 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3799 "Received duplicate message, ignoring.\n");
3800 GNUNET_STATISTICS_set (stats,
3801 gettext_noop ("# bytes dropped (duplicates)"),
3804 /* duplicate, ignore */
3807 n->last_packets_bitmap |= rotbit;
3809 if (n->last_sequence_number_received < snum)
3811 int shift = (snum - n->last_sequence_number_received);
3812 if (shift >= 8 * sizeof(n->last_packets_bitmap))
3813 n->last_packets_bitmap = 0;
3815 n->last_packets_bitmap <<= shift;
3816 n->last_sequence_number_received = snum;
3819 /* check timestamp */
3820 t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
3821 if (GNUNET_TIME_absolute_get_duration (t).rel_value > MAX_MESSAGE_AGE.rel_value)
3823 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3825 ("Message received far too old (%llu ms). Content ignored.\n"),
3826 GNUNET_TIME_absolute_get_duration (t).rel_value);
3827 GNUNET_STATISTICS_set (stats,
3828 gettext_noop ("# bytes dropped (ancient message)"),
3834 /* process decrypted message(s) */
3835 if (n->bw_out_external_limit.value__ != pt->inbound_bw_limit.value__)
3837 #if DEBUG_CORE_SET_QUOTA
3838 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3839 "Received %u b/s as new inbound limit for peer `%4s'\n",
3840 (unsigned int) ntohl (pt->inbound_bw_limit.value__),
3841 GNUNET_i2s (&n->peer));
3843 n->bw_out_external_limit = pt->inbound_bw_limit;
3844 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
3845 n->bw_out_internal_limit);
3846 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
3848 GNUNET_TRANSPORT_set_quota (transport,
3852 GNUNET_TIME_UNIT_FOREVER_REL,
3855 n->last_activity = GNUNET_TIME_absolute_get ();
3856 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
3857 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
3859 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
3862 GNUNET_STATISTICS_set (stats,
3863 gettext_noop ("# bytes of payload decrypted"),
3864 size - sizeof (struct EncryptedMessage),
3866 handle_peer_status_change (n);
3867 if (GNUNET_OK != GNUNET_SERVER_mst_receive (mst,
3869 &buf[sizeof (struct EncryptedMessage)],
3870 size - sizeof (struct EncryptedMessage),
3871 GNUNET_YES, GNUNET_NO))
3872 GNUNET_break_op (0);
3877 * Function called by the transport for each received message.
3879 * @param cls closure
3880 * @param peer (claimed) identity of the other peer
3881 * @param message the message
3882 * @param latency estimated latency for communicating with the
3883 * given peer (round-trip)
3884 * @param distance in overlay hops, as given by transport plugin
3887 handle_transport_receive (void *cls,
3888 const struct GNUNET_PeerIdentity *peer,
3889 const struct GNUNET_MessageHeader *message,
3890 struct GNUNET_TIME_Relative latency,
3891 unsigned int distance)
3893 struct Neighbour *n;
3894 struct GNUNET_TIME_Absolute now;
3901 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3902 "Received message of type %u from `%4s', demultiplexing.\n",
3903 (unsigned int) ntohs (message->type),
3906 if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
3911 n = find_neighbour (peer);
3913 n = create_neighbour (peer);
3914 changed = GNUNET_YES; /* FIXME... */
3915 up = (n->status == PEER_STATE_KEY_CONFIRMED);
3916 type = ntohs (message->type);
3917 size = ntohs (message->size);
3920 case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
3921 if (size != sizeof (struct SetKeyMessage))
3923 GNUNET_break_op (0);
3926 GNUNET_STATISTICS_update (stats, gettext_noop ("# session keys received"), 1, GNUNET_NO);
3927 handle_set_key (n, (const struct SetKeyMessage *) message);
3929 case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
3930 if (size < sizeof (struct EncryptedMessage) +
3931 sizeof (struct GNUNET_MessageHeader))
3933 GNUNET_break_op (0);
3936 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
3937 (n->status != PEER_STATE_KEY_CONFIRMED))
3939 GNUNET_break_op (0);
3942 handle_encrypted_message (n, (const struct EncryptedMessage *) message);
3944 case GNUNET_MESSAGE_TYPE_CORE_PING:
3945 if (size != sizeof (struct PingMessage))
3947 GNUNET_break_op (0);
3950 GNUNET_STATISTICS_update (stats, gettext_noop ("# PING messages received"), 1, GNUNET_NO);
3951 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
3952 (n->status != PEER_STATE_KEY_CONFIRMED))
3955 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3956 "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
3957 "PING", GNUNET_i2s (&n->peer));
3959 GNUNET_free_non_null (n->pending_ping);
3960 n->pending_ping = GNUNET_malloc (sizeof (struct PingMessage));
3961 memcpy (n->pending_ping, message, sizeof (struct PingMessage));
3964 handle_ping (n, (const struct PingMessage *) message);
3966 case GNUNET_MESSAGE_TYPE_CORE_PONG:
3967 if (size != sizeof (struct PongMessage))
3969 GNUNET_break_op (0);
3972 GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages received"), 1, GNUNET_NO);
3973 if ( (n->status != PEER_STATE_KEY_RECEIVED) &&
3974 (n->status != PEER_STATE_KEY_CONFIRMED) )
3977 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3978 "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
3979 "PONG", GNUNET_i2s (&n->peer));
3981 GNUNET_free_non_null (n->pending_pong);
3982 n->pending_pong = GNUNET_malloc (sizeof (struct PongMessage));
3983 memcpy (n->pending_pong, message, sizeof (struct PongMessage));
3986 handle_pong (n, (const struct PongMessage *) message);
3989 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3990 _("Unsupported message of type %u received.\n"),
3991 (unsigned int) type);
3994 if (n->status == PEER_STATE_KEY_CONFIRMED)
3996 now = GNUNET_TIME_absolute_get ();
3997 n->last_activity = now;
3998 changed = GNUNET_YES;
4001 GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"), 1, GNUNET_NO);
4002 n->time_established = now;
4004 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
4005 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
4007 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
4012 handle_peer_status_change (n);
4017 * Function that recalculates the bandwidth quota for the
4018 * given neighbour and transmits it to the transport service.
4020 * @param cls neighbour for the quota update
4024 neighbour_quota_update (void *cls,
4025 const struct GNUNET_SCHEDULER_TaskContext *tc)
4027 struct Neighbour *n = cls;
4028 struct GNUNET_BANDWIDTH_Value32NBO q_in;
4029 struct GNUNET_BANDWIDTH_Value32NBO q_out;
4030 struct GNUNET_BANDWIDTH_Value32NBO q_out_min;
4033 unsigned long long distributable;
4034 uint64_t need_per_peer;
4035 uint64_t need_per_second;
4038 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4039 "Neighbour quota update calculation running for peer `%4s'\n",
4040 GNUNET_i2s (&n->peer));
4042 n->quota_update_task = GNUNET_SCHEDULER_NO_TASK;
4043 /* calculate relative preference among all neighbours;
4044 divides by a bit more to avoid division by zero AND to
4045 account for possibility of new neighbours joining any time
4046 AND to convert to double... */
4047 if (preference_sum == 0)
4049 pref_rel = 1.0 / (double) neighbour_count;
4053 pref_rel = n->current_preference / preference_sum;
4055 need_per_peer = GNUNET_BANDWIDTH_value_get_available_until (MIN_BANDWIDTH_PER_PEER,
4056 GNUNET_TIME_UNIT_SECONDS);
4057 need_per_second = need_per_peer * neighbour_count;
4059 /* calculate inbound bandwidth per peer */
4061 if (bandwidth_target_in_bps > need_per_second)
4062 distributable = bandwidth_target_in_bps - need_per_second;
4063 share = distributable * pref_rel;
4064 if (share + need_per_peer > UINT32_MAX)
4065 q_in = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
4067 q_in = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4069 /* calculate outbound bandwidth per peer */
4071 if (bandwidth_target_out_bps > need_per_second)
4072 distributable = bandwidth_target_out_bps - need_per_second;
4073 share = distributable * pref_rel;
4074 if (share + need_per_peer > UINT32_MAX)
4075 q_out = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
4077 q_out = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4078 n->bw_out_internal_limit = q_out;
4080 q_out_min = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit, n->bw_out_internal_limit);
4081 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window, n->bw_out);
4083 /* check if we want to disconnect for good due to inactivity */
4084 if ( (GNUNET_TIME_absolute_get_duration (get_neighbour_timeout (n)).rel_value > 0) &&
4085 (GNUNET_TIME_absolute_get_duration (n->time_established).rel_value > GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value) )
4088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4089 "Forcing disconnect of `%4s' due to inactivity\n",
4090 GNUNET_i2s (&n->peer));
4092 q_in = GNUNET_BANDWIDTH_value_init (0); /* force disconnect */
4094 #if DEBUG_CORE_QUOTA
4095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4096 "Current quota for `%4s' is %u/%llu b/s in (old: %u b/s) / %u out (%u internal)\n",
4097 GNUNET_i2s (&n->peer),
4098 (unsigned int) ntohl (q_in.value__),
4099 bandwidth_target_out_bps,
4100 (unsigned int) ntohl (n->bw_in.value__),
4101 (unsigned int) ntohl (n->bw_out.value__),
4102 (unsigned int) ntohl (n->bw_out_internal_limit.value__));
4104 if ((n->bw_in.value__ != q_in.value__) || (n->bw_out.value__ != q_out_min.value__))
4106 if (n->bw_in.value__ != q_in.value__)
4108 if (n->bw_out.value__ != q_out_min.value__)
4109 n->bw_out = q_out_min;
4110 if (GNUNET_YES == n->is_connected)
4111 GNUNET_TRANSPORT_set_quota (transport,
4115 GNUNET_TIME_UNIT_FOREVER_REL,
4117 handle_peer_status_change (n);
4119 schedule_quota_update (n);
4124 * Function called by transport to notify us that
4125 * a peer connected to us (on the network level).
4127 * @param cls closure
4128 * @param peer the peer that connected
4129 * @param latency current latency of the connection
4130 * @param distance in overlay hops, as given by transport plugin
4133 handle_transport_notify_connect (void *cls,
4134 const struct GNUNET_PeerIdentity *peer,
4135 struct GNUNET_TIME_Relative latency,
4136 unsigned int distance)
4138 struct Neighbour *n;
4140 if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
4145 n = find_neighbour (peer);
4148 if (GNUNET_YES == n->is_connected)
4150 /* duplicate connect notification!? */
4157 n = create_neighbour (peer);
4159 GNUNET_STATISTICS_update (stats,
4160 gettext_noop ("# peers connected (transport)"),
4163 n->is_connected = GNUNET_YES;
4164 GNUNET_BANDWIDTH_tracker_init (&n->available_send_window,
4167 GNUNET_BANDWIDTH_tracker_init (&n->available_recv_window,
4171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4172 "Received connection from `%4s'.\n",
4173 GNUNET_i2s (&n->peer));
4175 GNUNET_TRANSPORT_set_quota (transport,
4179 GNUNET_TIME_UNIT_FOREVER_REL,
4186 * Function called by transport telling us that a peer
4189 * @param cls closure
4190 * @param peer the peer that disconnected
4193 handle_transport_notify_disconnect (void *cls,
4194 const struct GNUNET_PeerIdentity *peer)
4196 struct DisconnectNotifyMessage cnm;
4197 struct Neighbour *n;
4198 struct ClientActiveRequest *car;
4199 struct GNUNET_TIME_Relative left;
4202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4203 "Peer `%4s' disconnected from us; received notification from transport.\n", GNUNET_i2s (peer));
4206 n = find_neighbour (peer);
4212 GNUNET_break (n->is_connected);
4213 if (n->status == PEER_STATE_KEY_CONFIRMED)
4215 cnm.header.size = htons (sizeof (struct DisconnectNotifyMessage));
4216 cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
4218 send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_DISCONNECT);
4222 GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
4225 n->is_connected = GNUNET_NO;
4226 n->status = PEER_STATE_DOWN;
4227 while (NULL != (car = n->active_client_request_head))
4229 GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
4230 n->active_client_request_tail,
4232 GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
4233 &n->peer.hashPubKey,
4238 GNUNET_STATISTICS_update (stats,
4239 gettext_noop ("# peers connected (transport)"),
4242 if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
4243 GNUNET_SCHEDULER_cancel (n->dead_clean_task);
4244 left = GNUNET_TIME_relative_subtract (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
4245 GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT);
4246 n->last_activity = GNUNET_TIME_absolute_subtract (GNUNET_TIME_absolute_get (),
4248 n->dead_clean_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT,
4249 &consider_free_task,
4255 * Last task run during shutdown. Disconnects us from
4259 cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4261 struct Neighbour *n;
4265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4266 "Core service shutting down.\n");
4268 while (NULL != (n = neighbours))
4270 neighbours = n->next;
4271 GNUNET_assert (neighbour_count > 0);
4275 GNUNET_assert (transport != NULL);
4276 GNUNET_TRANSPORT_disconnect (transport);
4278 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), neighbour_count, GNUNET_NO);
4279 GNUNET_SERVER_notification_context_destroy (notifier);
4281 while (NULL != (c = clients))
4282 handle_client_disconnect (NULL, c->client_handle);
4283 if (my_private_key != NULL)
4284 GNUNET_CRYPTO_rsa_key_free (my_private_key);
4286 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
4287 if (peerinfo != NULL)
4288 GNUNET_PEERINFO_disconnect (peerinfo);
4290 GNUNET_SERVER_mst_destroy (mst);
4295 * Initiate core service.
4297 * @param cls closure
4298 * @param server the initialized server
4299 * @param c configuration to use
4303 struct GNUNET_SERVER_Handle *server,
4304 const struct GNUNET_CONFIGURATION_Handle *c)
4306 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
4307 {&handle_client_init, NULL,
4308 GNUNET_MESSAGE_TYPE_CORE_INIT, 0},
4309 {&handle_client_iterate_peers, NULL,
4310 GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
4311 sizeof (struct GNUNET_MessageHeader)},
4312 {&handle_client_request_info, NULL,
4313 GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
4314 sizeof (struct RequestInfoMessage)},
4315 {&handle_client_send_request, NULL,
4316 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
4317 sizeof (struct SendMessageRequest)},
4318 {&handle_client_send, NULL,
4319 GNUNET_MESSAGE_TYPE_CORE_SEND, 0},
4320 {&handle_client_request_connect, NULL,
4321 GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT,
4322 sizeof (struct ConnectMessage)},
4328 /* parse configuration */
4331 GNUNET_CONFIGURATION_get_value_number (c,
4334 &bandwidth_target_in_bps)) ||
4336 GNUNET_CONFIGURATION_get_value_number (c,
4339 &bandwidth_target_out_bps)) ||
4341 GNUNET_CONFIGURATION_get_value_filename (c,
4343 "HOSTKEY", &keyfile)))
4345 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4347 ("Core service is lacking key configuration settings. Exiting.\n"));
4348 GNUNET_SCHEDULER_shutdown ();
4351 peerinfo = GNUNET_PEERINFO_connect (cfg);
4352 if (NULL == peerinfo)
4354 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4355 _("Could not access PEERINFO service. Exiting.\n"));
4356 GNUNET_SCHEDULER_shutdown ();
4357 GNUNET_free (keyfile);
4360 my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
4361 GNUNET_free (keyfile);
4362 if (my_private_key == NULL)
4364 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4365 _("Core service could not access hostkey. Exiting.\n"));
4366 GNUNET_PEERINFO_disconnect (peerinfo);
4367 GNUNET_SCHEDULER_shutdown ();
4370 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
4371 GNUNET_CRYPTO_hash (&my_public_key,
4372 sizeof (my_public_key), &my_identity.hashPubKey);
4373 /* setup notification */
4374 notifier = GNUNET_SERVER_notification_context_create (server,
4376 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
4377 /* setup transport connection */
4378 transport = GNUNET_TRANSPORT_connect (cfg,
4381 &handle_transport_receive,
4382 &handle_transport_notify_connect,
4383 &handle_transport_notify_disconnect);
4384 GNUNET_assert (NULL != transport);
4385 stats = GNUNET_STATISTICS_create ("core", cfg);
4387 GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded CORE_SEND requests"), 0, GNUNET_NO);
4388 GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded lower priority CORE_SEND requests"), 0, GNUNET_NO);
4390 mst = GNUNET_SERVER_mst_create (&deliver_message,
4392 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
4393 &cleaning_task, NULL);
4394 /* process client requests */
4395 GNUNET_SERVER_add_handlers (server, handlers);
4396 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4397 _("Core service of `%4s' ready.\n"), GNUNET_i2s (&my_identity));
4403 * The main function for the transport service.
4405 * @param argc number of arguments from the command line
4406 * @param argv command line arguments
4407 * @return 0 ok, 1 on error
4410 main (int argc, char *const *argv)
4412 return (GNUNET_OK ==
4413 GNUNET_SERVICE_run (argc,
4416 GNUNET_SERVICE_OPTION_NONE,
4417 &run, NULL)) ? 0 : 1;
4420 /* end of gnunet-service-core.c */