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
162 * We've sent our session key.
167 * We've received the other peers session key.
169 PEER_STATE_KEY_RECEIVED,
172 * The other peer has confirmed our session key with a message
173 * encrypted with his session key (which we got). Session is now fully up.
175 PEER_STATE_KEY_CONFIRMED
180 * Encapsulation for encrypted messages exchanged between
181 * peers. Followed by the actual encrypted data.
183 struct EncryptedMessage
186 * Message type is either CORE_ENCRYPTED_MESSAGE.
188 struct GNUNET_MessageHeader header;
191 * Random value used for IV generation.
193 uint32_t iv_seed GNUNET_PACKED;
196 * MAC of the encrypted message (starting at 'sequence_number'),
197 * used to verify message integrity. Everything after this value
198 * (excluding this value itself) will be encrypted and authenticated.
199 * ENCRYPTED_HEADER_SIZE must be set to the offset of the *next* field.
201 GNUNET_HashCode hmac;
204 * Sequence number, in network byte order. This field
205 * must be the first encrypted/decrypted field
207 uint32_t sequence_number GNUNET_PACKED;
210 * Desired bandwidth (how much we should send to this peer / how
211 * much is the sender willing to receive)?
213 struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
216 * Timestamp. Used to prevent reply of ancient messages
217 * (recent messages are caught with the sequence number).
219 struct GNUNET_TIME_AbsoluteNBO timestamp;
225 * Number of bytes (at the beginning) of "struct EncryptedMessage"
226 * that are NOT encrypted.
228 #define ENCRYPTED_HEADER_SIZE (offsetof(struct EncryptedMessage, sequence_number))
232 * We're sending an (encrypted) PING to the other peer to check if he
233 * can decrypt. The other peer should respond with a PONG with the
234 * same content, except this time encrypted with the receiver's key.
239 * Message type is CORE_PING.
241 struct GNUNET_MessageHeader header;
246 uint32_t iv_seed GNUNET_PACKED;
249 * Intended target of the PING, used primarily to check
250 * that decryption actually worked.
252 struct GNUNET_PeerIdentity target;
255 * Random number chosen to make reply harder.
257 uint32_t challenge GNUNET_PACKED;
263 * Response to a PING. Includes data from the original PING
264 * plus initial bandwidth quota information.
269 * Message type is CORE_PONG.
271 struct GNUNET_MessageHeader header;
276 uint32_t iv_seed GNUNET_PACKED;
279 * Random number to make faking the reply harder. Must be
280 * first field after header (this is where we start to encrypt!).
282 uint32_t challenge GNUNET_PACKED;
285 * Desired bandwidth (how much we should send to this
286 * peer / how much is the sender willing to receive).
288 struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
291 * Intended target of the PING, used primarily to check
292 * that decryption actually worked.
294 struct GNUNET_PeerIdentity target;
299 * Message transmitted to set (or update) a session key.
305 * Message type is either CORE_SET_KEY.
307 struct GNUNET_MessageHeader header;
310 * Status of the sender (should be in "enum PeerStateMachine"), nbo.
312 int32_t sender_status GNUNET_PACKED;
315 * Purpose of the signature, will be
316 * GNUNET_SIGNATURE_PURPOSE_SET_KEY.
318 struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
321 * At what time was this key created?
323 struct GNUNET_TIME_AbsoluteNBO creation_time;
326 * The encrypted session key.
328 struct GNUNET_CRYPTO_RsaEncryptedData encrypted_key;
331 * Who is the intended recipient?
333 struct GNUNET_PeerIdentity target;
336 * Signature of the stuff above (starting at purpose).
338 struct GNUNET_CRYPTO_RsaSignature signature;
344 * Message waiting for transmission. This struct
345 * is followed by the actual content of the message.
351 * We keep messages in a doubly linked list.
353 struct MessageEntry *next;
356 * We keep messages in a doubly linked list.
358 struct MessageEntry *prev;
361 * By when are we supposed to transmit this message?
363 struct GNUNET_TIME_Absolute deadline;
366 * By when are we supposed to transmit this message (after
369 struct GNUNET_TIME_Absolute slack_deadline;
372 * How important is this message to us?
374 unsigned int priority;
377 * If this is a SET_KEY message, what was our connection status when this
378 * message was queued?
380 enum PeerStateMachine sender_status;
383 * Is this a SET_KEY message?
388 * How long is the message? (number of bytes following
389 * the "struct MessageEntry", but not including the
390 * size of "struct MessageEntry" itself!)
395 * Was this message selected for transmission in the
396 * current round? GNUNET_YES or GNUNET_NO.
401 * Did we give this message some slack (delayed sending) previously
402 * (and hence should not give it any more slack)? GNUNET_YES or
411 * Record kept for each request for transmission issued by a
412 * client that is still pending.
414 struct ClientActiveRequest;
417 * Data kept per neighbouring peer.
423 * Unencrypted messages destined for this peer.
425 struct MessageEntry *messages;
428 * Head of the batched, encrypted message queue (already ordered,
429 * transmit starting with the head).
431 struct MessageEntry *encrypted_head;
434 * Tail of the batched, encrypted message queue (already ordered,
435 * append new messages to tail)
437 struct MessageEntry *encrypted_tail;
440 * Head of list of requests from clients for transmission to
443 struct ClientActiveRequest *active_client_request_head;
446 * Tail of list of requests from clients for transmission to
449 struct ClientActiveRequest *active_client_request_tail;
452 * Handle for pending requests for transmission to this peer
453 * with the transport service. NULL if no request is pending.
455 struct GNUNET_TRANSPORT_TransmitHandle *th;
458 * Public key of the neighbour, NULL if we don't have it yet.
460 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
463 * We received a PING message before we got the "public_key"
464 * (or the SET_KEY). We keep it here until we have a key
465 * to decrypt it. NULL if no PING is pending.
467 struct PingMessage *pending_ping;
470 * We received a PONG message before we got the "public_key"
471 * (or the SET_KEY). We keep it here until we have a key
472 * to decrypt it. NULL if no PONG is pending.
474 struct PongMessage *pending_pong;
477 * Non-NULL if we are currently looking up HELLOs for this peer.
480 struct GNUNET_PEERINFO_IteratorContext *pitr;
483 * SetKeyMessage to transmit, NULL if we are not currently trying
486 struct SetKeyMessage *skm;
489 * Performance data for the peer.
491 struct GNUNET_TRANSPORT_ATS_Information *ats;
494 * Identity of the neighbour.
496 struct GNUNET_PeerIdentity peer;
499 * Key we use to encrypt our messages for the other peer
500 * (initialized by us when we do the handshake).
502 struct GNUNET_CRYPTO_AesSessionKey encrypt_key;
505 * Key we use to decrypt messages from the other peer
506 * (given to us by the other peer during the handshake).
508 struct GNUNET_CRYPTO_AesSessionKey decrypt_key;
511 * ID of task used for re-trying plaintext scheduling.
513 GNUNET_SCHEDULER_TaskIdentifier retry_plaintext_task;
516 * ID of task used for re-trying SET_KEY and PING message.
518 GNUNET_SCHEDULER_TaskIdentifier retry_set_key_task;
521 * ID of task used for updating bandwidth quota for this neighbour.
523 GNUNET_SCHEDULER_TaskIdentifier quota_update_task;
526 * ID of task used for sending keep-alive pings.
528 GNUNET_SCHEDULER_TaskIdentifier keep_alive_task;
531 * ID of task used for cleaning up dead neighbour entries.
533 GNUNET_SCHEDULER_TaskIdentifier dead_clean_task;
536 * At what time did we generate our encryption key?
538 struct GNUNET_TIME_Absolute encrypt_key_created;
541 * At what time did the other peer generate the decryption key?
543 struct GNUNET_TIME_Absolute decrypt_key_created;
546 * At what time did we initially establish (as in, complete session
547 * key handshake) this connection? Should be zero if status != KEY_CONFIRMED.
549 struct GNUNET_TIME_Absolute time_established;
552 * At what time did we last receive an encrypted message from the
553 * other peer? Should be zero if status != KEY_CONFIRMED.
555 struct GNUNET_TIME_Absolute last_activity;
558 * At what frequency are we currently re-trying SET_KEY messages?
560 struct GNUNET_TIME_Relative set_key_retry_frequency;
563 * Tracking bandwidth for sending to this peer.
565 struct GNUNET_BANDWIDTH_Tracker available_send_window;
568 * Tracking bandwidth for receiving from this peer.
570 struct GNUNET_BANDWIDTH_Tracker available_recv_window;
573 * How valueable were the messages of this peer recently?
575 unsigned long long current_preference;
578 * Number of entries in 'ats'.
580 unsigned int ats_count;
583 * Bit map indicating which of the 32 sequence numbers before the last
584 * were received (good for accepting out-of-order packets and
585 * estimating reliability of the connection)
587 unsigned int last_packets_bitmap;
590 * last sequence number received on this connection (highest)
592 uint32_t last_sequence_number_received;
595 * last sequence number transmitted
597 uint32_t last_sequence_number_sent;
600 * Available bandwidth in for this peer (current target).
602 struct GNUNET_BANDWIDTH_Value32NBO bw_in;
605 * Available bandwidth out for this peer (current target).
607 struct GNUNET_BANDWIDTH_Value32NBO bw_out;
610 * Internal bandwidth limit set for this peer (initially typically
611 * set to "-1"). Actual "bw_out" is MIN of
612 * "bpm_out_internal_limit" and "bw_out_external_limit".
614 struct GNUNET_BANDWIDTH_Value32NBO bw_out_internal_limit;
617 * External bandwidth limit set for this peer by the
618 * peer that we are communicating with. "bw_out" is MIN of
619 * "bw_out_internal_limit" and "bw_out_external_limit".
621 struct GNUNET_BANDWIDTH_Value32NBO bw_out_external_limit;
624 * What was our PING challenge number (for this peer)?
626 uint32_t ping_challenge;
629 * What is our connection status?
631 enum PeerStateMachine status;
634 * Are we currently connected to this neighbour?
642 * Data structure for each client connected to the core service.
647 * Clients are kept in a linked list.
652 * Handle for the client with the server API.
654 struct GNUNET_SERVER_Client *client_handle;
657 * Array of the types of messages this peer cares
658 * about (with "tcnt" entries). Allocated as part
659 * of this client struct, do not free!
661 const uint16_t *types;
664 * Map of peer identities to active transmission requests of this
665 * client to the peer (of type 'struct ClientActiveRequest').
667 struct GNUNET_CONTAINER_MultiHashMap *requests;
670 * Options for messages this client cares about,
671 * see GNUNET_CORE_OPTION_ values.
676 * Number of types of incoming messages this client
677 * specifically cares about. Size of the "types" array.
685 * Record kept for each request for transmission issued by a
686 * client that is still pending.
688 struct ClientActiveRequest
692 * Active requests are kept in a doubly-linked list of
693 * the respective target peer.
695 struct ClientActiveRequest *next;
698 * Active requests are kept in a doubly-linked list of
699 * the respective target peer.
701 struct ClientActiveRequest *prev;
704 * Handle to the client.
706 struct Client *client;
709 * By what time would the client want to see this message out?
711 struct GNUNET_TIME_Absolute deadline;
714 * How important is this request.
719 * How many more requests does this client have?
724 * How many bytes does the client intend to send?
729 * Unique request ID (in big endian).
740 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
745 static struct GNUNET_PeerIdentity my_identity;
750 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
754 * Handle to peerinfo service.
756 static struct GNUNET_PEERINFO_Handle *peerinfo;
759 * Our message stream tokenizer (for encrypted payload).
761 static struct GNUNET_SERVER_MessageStreamTokenizer *mst;
766 const struct GNUNET_CONFIGURATION_Handle *cfg;
771 static struct GNUNET_TRANSPORT_Handle *transport;
774 * Linked list of our clients.
776 static struct Client *clients;
779 * Context for notifications we need to send to our clients.
781 static struct GNUNET_SERVER_NotificationContext *notifier;
784 * Map of peer identities to 'struct Neighbour'.
786 static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
789 * Neighbour entry for "this" peer.
791 static struct Neighbour self;
794 * For creating statistics.
796 static struct GNUNET_STATISTICS_Handle *stats;
799 * Sum of all preferences among all neighbours.
801 static unsigned long long preference_sum;
804 * How much inbound bandwidth are we supposed to be using per second?
806 static unsigned long long bandwidth_target_in_bps;
809 * How much outbound bandwidth are we supposed to be using per second?
811 static unsigned long long bandwidth_target_out_bps;
814 * Derive an authentication key from "set key" information
817 derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
818 const struct GNUNET_CRYPTO_AesSessionKey *skey,
820 struct GNUNET_TIME_Absolute creation_time)
822 static const char ctx[] = "authentication key";
823 struct GNUNET_TIME_AbsoluteNBO ctbe;
826 ctbe = GNUNET_TIME_absolute_hton (creation_time);
827 GNUNET_CRYPTO_hmac_derive_key (akey,
841 * Derive an IV from packet information
844 derive_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
845 const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed,
846 const struct GNUNET_PeerIdentity *identity)
848 static const char ctx[] = "initialization vector";
850 GNUNET_CRYPTO_aes_derive_iv (iv,
854 &identity->hashPubKey.bits,
855 sizeof(identity->hashPubKey.bits),
861 * Derive an IV from pong packet information
864 derive_pong_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
865 const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed,
866 uint32_t challenge, const struct GNUNET_PeerIdentity *identity)
868 static const char ctx[] = "pong initialization vector";
870 GNUNET_CRYPTO_aes_derive_iv (iv,
874 &identity->hashPubKey.bits,
875 sizeof(identity->hashPubKey.bits),
884 * At what time should the connection to the given neighbour
885 * time out (given no further activity?)
887 * @param n neighbour in question
888 * @return absolute timeout
890 static struct GNUNET_TIME_Absolute
891 get_neighbour_timeout (struct Neighbour *n)
893 return GNUNET_TIME_absolute_add (n->last_activity,
894 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
899 * Helper function for update_preference_sum.
902 update_preference (void *cls,
903 const GNUNET_HashCode *key,
906 unsigned long long *ps = cls;
907 struct Neighbour *n = value;
909 n->current_preference /= 2;
910 *ps += n->current_preference;
916 * A preference value for a neighbour was update. Update
917 * the preference sum accordingly.
919 * @param inc how much was a preference value increased?
922 update_preference_sum (unsigned long long inc)
924 unsigned long long os;
927 preference_sum += inc;
928 if (preference_sum >= os)
930 /* overflow! compensate by cutting all values in half! */
932 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
935 GNUNET_STATISTICS_set (stats, gettext_noop ("# total peer preference"), preference_sum, GNUNET_NO);
940 * Find the entry for the given neighbour.
942 * @param peer identity of the neighbour
943 * @return NULL if we are not connected, otherwise the
946 static struct Neighbour *
947 find_neighbour (const struct GNUNET_PeerIdentity *peer)
949 return GNUNET_CONTAINER_multihashmap_get (neighbours, &peer->hashPubKey);
954 * Send a message to one of our clients.
956 * @param client target for the message
957 * @param msg message to transmit
958 * @param can_drop could this message be dropped if the
959 * client's queue is getting too large?
962 send_to_client (struct Client *client,
963 const struct GNUNET_MessageHeader *msg,
966 #if DEBUG_CORE_CLIENT
967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
968 "Preparing to send %u bytes of message of type %u to client.\n",
969 (unsigned int) ntohs (msg->size),
970 (unsigned int) ntohs (msg->type));
972 GNUNET_SERVER_notification_context_unicast (notifier,
973 client->client_handle,
980 * Send a message to all of our current clients that have
981 * the right options set.
983 * @param msg message to multicast
984 * @param can_drop can this message be discarded if the queue is too long
985 * @param options mask to use
988 send_to_all_clients (const struct GNUNET_MessageHeader *msg,
997 if (0 != (c->options & options))
999 #if DEBUG_CORE_CLIENT > 1
1000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1001 "Sending message of type %u to client.\n",
1002 (unsigned int) ntohs (msg->type));
1004 send_to_client (c, msg, can_drop);
1012 * Function called by transport telling us that a peer
1015 * @param n the peer that changed status
1018 handle_peer_status_change (struct Neighbour *n)
1020 struct PeerStatusNotifyMessage *psnm;
1021 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1022 struct GNUNET_TRANSPORT_ATS_Information *ats;
1025 if ( (! n->is_connected) ||
1026 (n->status != PEER_STATE_KEY_CONFIRMED) )
1029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1030 "Peer `%4s' changed status\n",
1031 GNUNET_i2s (&n->peer));
1033 size = sizeof (struct PeerStatusNotifyMessage) +
1034 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1035 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1038 /* recovery strategy: throw away performance data */
1039 GNUNET_array_grow (n->ats,
1042 size = sizeof (struct PeerStatusNotifyMessage) +
1043 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1045 psnm = (struct PeerStatusNotifyMessage*) buf;
1046 psnm->header.size = htons (size);
1047 psnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE);
1048 psnm->timeout = GNUNET_TIME_absolute_hton (get_neighbour_timeout (n));
1049 psnm->bandwidth_in = n->bw_in;
1050 psnm->bandwidth_out = n->bw_out;
1051 psnm->peer = n->peer;
1052 psnm->ats_count = htonl (n->ats_count);
1056 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
1057 ats[n->ats_count].type = htonl (0);
1058 ats[n->ats_count].value = htonl (0);
1059 send_to_all_clients (&psnm->header,
1061 GNUNET_CORE_OPTION_SEND_STATUS_CHANGE);
1062 GNUNET_STATISTICS_update (stats,
1063 gettext_noop ("# peer status changes"),
1070 * Go over our message queue and if it is not too long, go
1071 * over the pending requests from clients for this
1072 * neighbour and send some clients a 'READY' notification.
1074 * @param n which peer to process
1077 schedule_peer_messages (struct Neighbour *n)
1079 struct SendMessageReady smr;
1080 struct ClientActiveRequest *car;
1081 struct ClientActiveRequest *pos;
1083 struct MessageEntry *mqe;
1084 unsigned int queue_size;
1086 /* check if neighbour queue is empty enough! */
1096 if (queue_size >= MAX_PEER_QUEUE_SIZE)
1098 #if DEBUG_CORE_CLIENT
1099 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1100 "Not considering client transmission requests: queue full\n");
1102 return; /* queue still full */
1104 /* find highest priority request */
1105 pos = n->active_client_request_head;
1109 if ( (car == NULL) ||
1110 (pos->priority > car->priority) )
1117 car = n->active_client_request_head;
1120 return; /* no pending requests */
1121 #if DEBUG_CORE_CLIENT
1122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1123 "Permitting client transmission request to `%s'\n",
1124 GNUNET_i2s (&n->peer));
1127 GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1128 n->active_client_request_tail,
1130 GNUNET_assert (GNUNET_YES ==
1131 GNUNET_CONTAINER_multihashmap_remove (c->requests,
1132 &n->peer.hashPubKey,
1134 smr.header.size = htons (sizeof (struct SendMessageReady));
1135 smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
1136 smr.size = htons (car->msize);
1137 smr.smr_id = car->smr_id;
1139 send_to_client (c, &smr.header, GNUNET_NO);
1145 * Handle CORE_SEND_REQUEST message.
1148 handle_client_send_request (void *cls,
1149 struct GNUNET_SERVER_Client *client,
1150 const struct GNUNET_MessageHeader *message)
1152 const struct SendMessageRequest *req;
1153 struct Neighbour *n;
1155 struct ClientActiveRequest *car;
1157 req = (const struct SendMessageRequest*) message;
1158 if (0 == memcmp (&req->peer,
1160 sizeof (struct GNUNET_PeerIdentity)))
1163 n = find_neighbour (&req->peer);
1165 (GNUNET_YES != n->is_connected) ||
1166 (n->status != PEER_STATE_KEY_CONFIRMED) )
1168 /* neighbour must have disconnected since request was issued,
1169 ignore (client will realize it once it processes the
1170 disconnect notification) */
1171 #if DEBUG_CORE_CLIENT
1172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1173 "Dropped client request for transmission (am disconnected)\n");
1175 GNUNET_STATISTICS_update (stats,
1176 gettext_noop ("# send requests dropped (disconnected)"),
1179 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1183 while ( (c != NULL) &&
1184 (c->client_handle != client) )
1188 /* client did not send INIT first! */
1190 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1193 if (c->requests == NULL)
1194 c->requests = GNUNET_CONTAINER_multihashmap_create (16);
1195 #if DEBUG_CORE_CLIENT
1196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1197 "Received client transmission request. queueing\n");
1199 car = GNUNET_CONTAINER_multihashmap_get (c->requests,
1200 &req->peer.hashPubKey);
1203 /* create new entry */
1204 car = GNUNET_malloc (sizeof (struct ClientActiveRequest));
1205 GNUNET_assert (GNUNET_OK ==
1206 GNUNET_CONTAINER_multihashmap_put (c->requests,
1207 &req->peer.hashPubKey,
1209 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1210 GNUNET_CONTAINER_DLL_insert (n->active_client_request_head,
1211 n->active_client_request_tail,
1215 car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline);
1216 car->priority = ntohl (req->priority);
1217 car->queue_size = ntohl (req->queue_size);
1218 car->msize = ntohs (req->size);
1219 car->smr_id = req->smr_id;
1220 schedule_peer_messages (n);
1221 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1226 * Notify client about an existing connection to one of our neighbours.
1229 notify_client_about_neighbour (void *cls,
1230 const GNUNET_HashCode *key,
1233 struct Client *c = cls;
1234 struct Neighbour *n = value;
1236 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1237 struct GNUNET_TRANSPORT_ATS_Information *ats;
1238 struct ConnectNotifyMessage *cnm;
1240 size = sizeof (struct ConnectNotifyMessage) +
1241 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1242 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1245 /* recovery strategy: throw away performance data */
1246 GNUNET_array_grow (n->ats,
1249 size = sizeof (struct ConnectNotifyMessage) +
1250 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1252 cnm = (struct ConnectNotifyMessage*) buf;
1253 cnm->header.size = htons (size);
1254 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1255 cnm->ats_count = htonl (n->ats_count);
1259 sizeof (struct GNUNET_TRANSPORT_ATS_Information) * n->ats_count);
1260 ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1261 ats[n->ats_count].value = htonl (0);
1262 if (n->status == PEER_STATE_KEY_CONFIRMED)
1264 #if DEBUG_CORE_CLIENT
1265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1266 "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
1268 cnm->peer = n->peer;
1269 send_to_client (c, &cnm->header, GNUNET_NO);
1277 * Handle CORE_INIT request.
1280 handle_client_init (void *cls,
1281 struct GNUNET_SERVER_Client *client,
1282 const struct GNUNET_MessageHeader *message)
1284 const struct InitMessage *im;
1285 struct InitReplyMessage irm;
1288 const uint16_t *types;
1292 #if DEBUG_CORE_CLIENT
1293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1294 "Client connecting to core service with `%s' message\n",
1297 /* check that we don't have an entry already */
1301 if (client == c->client_handle)
1304 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1309 msize = ntohs (message->size);
1310 if (msize < sizeof (struct InitMessage))
1313 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1316 GNUNET_SERVER_notification_context_add (notifier, client);
1317 im = (const struct InitMessage *) message;
1318 types = (const uint16_t *) &im[1];
1319 msize -= sizeof (struct InitMessage);
1320 c = GNUNET_malloc (sizeof (struct Client) + msize);
1321 c->client_handle = client;
1324 c->tcnt = msize / sizeof (uint16_t);
1325 c->types = (const uint16_t *) &c[1];
1326 wtypes = (uint16_t *) &c[1];
1327 for (i=0;i<c->tcnt;i++)
1328 wtypes[i] = ntohs (types[i]);
1329 c->options = ntohl (im->options);
1330 #if DEBUG_CORE_CLIENT
1331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1332 "Client %p is interested in %u message types\n",
1334 (unsigned int) c->tcnt);
1336 /* send init reply message */
1337 irm.header.size = htons (sizeof (struct InitReplyMessage));
1338 irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
1339 irm.reserved = htonl (0);
1340 memcpy (&irm.publicKey,
1342 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1343 #if DEBUG_CORE_CLIENT
1344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1345 "Sending `%s' message to client.\n", "INIT_REPLY");
1347 send_to_client (c, &irm.header, GNUNET_NO);
1348 if (0 != (c->options & GNUNET_CORE_OPTION_SEND_CONNECT))
1350 /* notify new client about existing neighbours */
1351 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
1352 ¬ify_client_about_neighbour,
1355 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1360 * Free client request records.
1363 * @param key identity of peer for which this is an active request
1364 * @param value the 'struct ClientActiveRequest' to free
1365 * @return GNUNET_YES (continue iteration)
1368 destroy_active_client_request (void *cls,
1369 const GNUNET_HashCode *key,
1372 struct ClientActiveRequest *car = value;
1373 struct Neighbour *n;
1374 struct GNUNET_PeerIdentity peer;
1376 peer.hashPubKey = *key;
1377 n = find_neighbour (&peer);
1378 GNUNET_assert (NULL != n);
1379 GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1380 n->active_client_request_tail,
1388 * A client disconnected, clean up.
1390 * @param cls closure
1391 * @param client identification of the client
1394 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1397 struct Client *prev;
1401 #if DEBUG_CORE_CLIENT
1402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1403 "Client %p has disconnected from core service.\n",
1410 if (client == pos->client_handle)
1417 /* client never sent INIT */
1421 clients = pos->next;
1423 prev->next = pos->next;
1424 if (pos->requests != NULL)
1426 GNUNET_CONTAINER_multihashmap_iterate (pos->requests,
1427 &destroy_active_client_request,
1429 GNUNET_CONTAINER_multihashmap_destroy (pos->requests);
1436 * Helper function for handle_client_iterate_peers.
1438 * @param cls the 'struct GNUNET_SERVER_TransmitContext' to queue replies
1439 * @param key identity of the connected peer
1440 * @param value the 'struct Neighbour' for the peer
1441 * @return GNUNET_OK (continue to iterate)
1444 queue_connect_message (void *cls,
1445 const GNUNET_HashCode *key,
1448 struct GNUNET_SERVER_TransmitContext *tc = cls;
1449 struct Neighbour *n = value;
1450 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1451 struct GNUNET_TRANSPORT_ATS_Information *ats;
1453 struct ConnectNotifyMessage *cnm;
1455 cnm = (struct ConnectNotifyMessage*) buf;
1456 if (n->status != PEER_STATE_KEY_CONFIRMED)
1458 size = sizeof (struct ConnectNotifyMessage) +
1459 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1460 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1463 /* recovery strategy: throw away performance data */
1464 GNUNET_array_grow (n->ats,
1467 size = sizeof (struct PeerStatusNotifyMessage) +
1468 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1470 cnm = (struct ConnectNotifyMessage*) buf;
1471 cnm->header.size = htons (size);
1472 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1473 cnm->ats_count = htonl (n->ats_count);
1477 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
1478 ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1479 ats[n->ats_count].value = htonl (0);
1480 #if DEBUG_CORE_CLIENT
1481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1482 "Sending `%s' message to client.\n",
1485 cnm->peer = n->peer;
1486 GNUNET_SERVER_transmit_context_append_message (tc,
1493 * Handle CORE_ITERATE_PEERS request.
1496 * @param client client sending the iteration request
1497 * @param message iteration request message
1500 handle_client_iterate_peers (void *cls,
1501 struct GNUNET_SERVER_Client *client,
1502 const struct GNUNET_MessageHeader *message)
1505 struct GNUNET_MessageHeader done_msg;
1506 struct GNUNET_SERVER_TransmitContext *tc;
1508 /* notify new client about existing neighbours */
1510 msize = ntohs(message->size);
1511 tc = GNUNET_SERVER_transmit_context_create (client);
1512 if (msize == sizeof(struct GNUNET_MessageHeader))
1513 GNUNET_CONTAINER_multihashmap_iterate (neighbours, &queue_connect_message, tc);
1517 done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1518 done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
1519 GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
1520 GNUNET_SERVER_transmit_context_run (tc,
1521 GNUNET_TIME_UNIT_FOREVER_REL);
1525 * Handle CORE_ITERATE_PEERS request. Notify client about existing neighbours.
1528 * @param client client sending the iteration request
1529 * @param message iteration request message
1532 handle_client_have_peer (void *cls,
1533 struct GNUNET_SERVER_Client *client,
1534 const struct GNUNET_MessageHeader *message)
1537 struct GNUNET_MessageHeader done_msg;
1538 struct GNUNET_SERVER_TransmitContext *tc;
1539 struct GNUNET_PeerIdentity *peer;
1541 tc = GNUNET_SERVER_transmit_context_create (client);
1542 peer = (struct GNUNET_PeerIdentity *) &message[1];
1543 GNUNET_CONTAINER_multihashmap_get_multiple(neighbours,
1545 &queue_connect_message,
1547 done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1548 done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
1549 GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
1550 GNUNET_SERVER_transmit_context_run (tc,
1551 GNUNET_TIME_UNIT_FOREVER_REL);
1556 * Handle REQUEST_INFO request.
1559 * @param client client sending the request
1560 * @param message iteration request message
1563 handle_client_request_info (void *cls,
1564 struct GNUNET_SERVER_Client *client,
1565 const struct GNUNET_MessageHeader *message)
1567 const struct RequestInfoMessage *rcm;
1569 struct Neighbour *n;
1570 struct ConfigurationInfoMessage cim;
1571 int32_t want_reserv;
1573 unsigned long long old_preference;
1574 struct GNUNET_TIME_Relative rdelay;
1576 rdelay = GNUNET_TIME_relative_get_zero();
1577 #if DEBUG_CORE_CLIENT
1578 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1579 "Core service receives `%s' request.\n", "REQUEST_INFO");
1584 if (client == pos->client_handle)
1591 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1595 rcm = (const struct RequestInfoMessage *) message;
1596 n = find_neighbour (&rcm->peer);
1597 memset (&cim, 0, sizeof (cim));
1598 if ( (n != NULL) && (GNUNET_YES == n->is_connected) )
1600 want_reserv = ntohl (rcm->reserve_inbound);
1601 if (n->bw_out_internal_limit.value__ != rcm->limit_outbound.value__)
1603 n->bw_out_internal_limit = rcm->limit_outbound;
1604 if (n->bw_out.value__ != GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
1605 n->bw_out_external_limit).value__)
1607 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
1608 n->bw_out_external_limit);
1609 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_recv_window,
1611 GNUNET_TRANSPORT_set_quota (transport,
1615 handle_peer_status_change (n);
1618 if (want_reserv < 0)
1620 got_reserv = want_reserv;
1622 else if (want_reserv > 0)
1624 rdelay = GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window,
1626 if (rdelay.rel_value == 0)
1627 got_reserv = want_reserv;
1629 got_reserv = 0; /* all or nothing */
1633 GNUNET_BANDWIDTH_tracker_consume (&n->available_recv_window,
1635 old_preference = n->current_preference;
1636 n->current_preference += GNUNET_ntohll(rcm->preference_change);
1637 if (old_preference > n->current_preference)
1639 /* overflow; cap at maximum value */
1640 n->current_preference = ULLONG_MAX;
1642 update_preference_sum (n->current_preference - old_preference);
1643 #if DEBUG_CORE_QUOTA
1644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1645 "Received reservation request for %d bytes for peer `%4s', reserved %d bytes, suggesting delay of %llu ms\n",
1647 GNUNET_i2s (&rcm->peer),
1649 (unsigned long long) rdelay.rel_value);
1651 cim.reserved_amount = htonl (got_reserv);
1652 cim.reserve_delay = GNUNET_TIME_relative_hton (rdelay);
1653 cim.bw_out = n->bw_out;
1654 cim.preference = n->current_preference;
1658 /* Technically, this COULD happen (due to asynchronous behavior),
1659 but it should be rare, so we should generate an info event
1660 to help diagnosis of serious errors that might be masked by this */
1661 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1662 _("Client asked for preference change with peer `%s', which is not connected!\n"),
1663 GNUNET_i2s (&rcm->peer));
1664 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1667 cim.header.size = htons (sizeof (struct ConfigurationInfoMessage));
1668 cim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO);
1669 cim.peer = rcm->peer;
1670 cim.rim_id = rcm->rim_id;
1671 #if DEBUG_CORE_CLIENT
1672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1673 "Sending `%s' message to client.\n", "CONFIGURATION_INFO");
1675 send_to_client (pos, &cim.header, GNUNET_NO);
1676 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1681 * Free the given entry for the neighbour (it has
1682 * already been removed from the list at this point).
1684 * @param n neighbour to free
1687 free_neighbour (struct Neighbour *n)
1689 struct MessageEntry *m;
1690 struct ClientActiveRequest *car;
1693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1694 "Destroying neighbour entry for peer `%4s'\n",
1695 GNUNET_i2s (&n->peer));
1697 if (n->pitr != NULL)
1699 GNUNET_PEERINFO_iterate_cancel (n->pitr);
1704 GNUNET_free (n->skm);
1707 while (NULL != (m = n->messages))
1709 n->messages = m->next;
1712 while (NULL != (m = n->encrypted_head))
1714 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1719 while (NULL != (car = n->active_client_request_head))
1721 GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1722 n->active_client_request_tail,
1724 GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
1725 &n->peer.hashPubKey,
1731 GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
1734 if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
1735 GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
1736 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
1737 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
1738 if (n->quota_update_task != GNUNET_SCHEDULER_NO_TASK)
1739 GNUNET_SCHEDULER_cancel (n->quota_update_task);
1740 if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
1741 GNUNET_SCHEDULER_cancel (n->dead_clean_task);
1742 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
1743 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
1744 if (n->status == PEER_STATE_KEY_CONFIRMED)
1745 GNUNET_STATISTICS_update (stats,
1746 gettext_noop ("# established sessions"),
1749 GNUNET_array_grow (n->ats, n->ats_count, 0);
1750 GNUNET_free_non_null (n->public_key);
1751 GNUNET_free_non_null (n->pending_ping);
1752 GNUNET_free_non_null (n->pending_pong);
1758 * Check if we have encrypted messages for the specified neighbour
1759 * pending, and if so, check with the transport about sending them
1762 * @param n neighbour to check.
1764 static void process_encrypted_neighbour_queue (struct Neighbour *n);
1768 * Encrypt size bytes from in and write the result to out. Use the
1769 * key for outbound traffic of the given neighbour.
1771 * @param n neighbour we are sending to
1772 * @param iv initialization vector to use
1773 * @param in ciphertext
1774 * @param out plaintext
1775 * @param size size of in/out
1776 * @return GNUNET_OK on success
1779 do_encrypt (struct Neighbour *n,
1780 const struct GNUNET_CRYPTO_AesInitializationVector * iv,
1781 const void *in, void *out, size_t size)
1783 if (size != (uint16_t) size)
1788 GNUNET_assert (size ==
1789 GNUNET_CRYPTO_aes_encrypt (in,
1793 GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes encrypted"), size, GNUNET_NO);
1795 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1796 "Encrypted %u bytes for `%4s' using key %u, IV %u\n",
1797 (unsigned int) size,
1798 GNUNET_i2s (&n->peer),
1799 (unsigned int) n->encrypt_key.crc32,
1800 GNUNET_CRYPTO_crc32_n (iv, sizeof(iv)));
1807 * Consider freeing the given neighbour since we may not need
1808 * to keep it around anymore.
1810 * @param n neighbour to consider discarding
1813 consider_free_neighbour (struct Neighbour *n);
1817 * Task triggered when a neighbour entry is about to time out
1818 * (and we should prevent this by sending a PING).
1820 * @param cls the 'struct Neighbour'
1821 * @param tc scheduler context (not used)
1824 send_keep_alive (void *cls,
1825 const struct GNUNET_SCHEDULER_TaskContext *tc)
1827 struct Neighbour *n = cls;
1828 struct GNUNET_TIME_Relative retry;
1829 struct GNUNET_TIME_Relative left;
1830 struct MessageEntry *me;
1831 struct PingMessage pp;
1832 struct PingMessage *pm;
1833 struct GNUNET_CRYPTO_AesInitializationVector iv;
1835 n->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
1837 me = GNUNET_malloc (sizeof (struct MessageEntry) +
1838 sizeof (struct PingMessage));
1839 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PING_DELAY);
1840 me->priority = PING_PRIORITY;
1841 me->size = sizeof (struct PingMessage);
1842 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
1846 pm = (struct PingMessage *) &me[1];
1847 pm->header.size = htons (sizeof (struct PingMessage));
1848 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
1849 pm->iv_seed = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
1851 derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
1852 pp.challenge = n->ping_challenge;
1853 pp.target = n->peer;
1855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1856 "Encrypting `%s' message with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
1858 (unsigned int) n->ping_challenge,
1859 GNUNET_i2s (&n->peer),
1860 (unsigned int) n->encrypt_key.crc32,
1861 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
1868 sizeof (struct PingMessage) -
1869 ((void *) &pm->target - (void *) pm));
1870 process_encrypted_neighbour_queue (n);
1871 /* reschedule PING job */
1872 left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
1873 retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1874 MIN_PING_FREQUENCY);
1876 = GNUNET_SCHEDULER_add_delayed (retry,
1884 * Task triggered when a neighbour entry might have gotten stale.
1886 * @param cls the 'struct Neighbour'
1887 * @param tc scheduler context (not used)
1890 consider_free_task (void *cls,
1891 const struct GNUNET_SCHEDULER_TaskContext *tc)
1893 struct Neighbour *n = cls;
1895 n->dead_clean_task = GNUNET_SCHEDULER_NO_TASK;
1896 consider_free_neighbour (n);
1901 * Consider freeing the given neighbour since we may not need
1902 * to keep it around anymore.
1904 * @param n neighbour to consider discarding
1907 consider_free_neighbour (struct Neighbour *n)
1909 struct GNUNET_TIME_Relative left;
1911 if ( (n->th != NULL) ||
1912 (n->pitr != NULL) ||
1913 (GNUNET_YES == n->is_connected) )
1914 return; /* no chance */
1916 left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
1917 if (left.rel_value > 0)
1919 if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
1920 GNUNET_SCHEDULER_cancel (n->dead_clean_task);
1921 n->dead_clean_task = GNUNET_SCHEDULER_add_delayed (left,
1922 &consider_free_task,
1926 /* actually free the neighbour... */
1927 GNUNET_assert (GNUNET_OK ==
1928 GNUNET_CONTAINER_multihashmap_remove (neighbours,
1929 &n->peer.hashPubKey,
1931 GNUNET_STATISTICS_set (stats,
1932 gettext_noop ("# neighbour entries allocated"),
1933 GNUNET_CONTAINER_multihashmap_size (neighbours),
1940 * Function called when the transport service is ready to
1941 * receive an encrypted message for the respective peer
1943 * @param cls neighbour to use message from
1944 * @param size number of bytes we can transmit
1945 * @param buf where to copy the message
1946 * @return number of bytes transmitted
1949 notify_encrypted_transmit_ready (void *cls,
1953 struct Neighbour *n = cls;
1954 struct MessageEntry *m;
1959 m = n->encrypted_head;
1963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1964 "Encrypted message queue empty, no messages added to buffer for `%4s'\n",
1965 GNUNET_i2s (&n->peer));
1969 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1976 GNUNET_assert (size >= m->size);
1977 memcpy (cbuf, &m[1], m->size);
1979 GNUNET_BANDWIDTH_tracker_consume (&n->available_send_window,
1982 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1983 "Copied message of type %u and size %u into transport buffer for `%4s'\n",
1984 (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
1986 GNUNET_i2s (&n->peer));
1988 process_encrypted_neighbour_queue (n);
1993 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1994 "Transmission of message of type %u and size %u failed\n",
1995 (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
1996 (unsigned int) m->size);
2000 consider_free_neighbour (n);
2001 GNUNET_STATISTICS_update (stats,
2002 gettext_noop ("# encrypted bytes given to transport"),
2010 * Check if we have plaintext messages for the specified neighbour
2011 * pending, and if so, consider batching and encrypting them (and
2012 * then trigger processing of the encrypted queue if needed).
2014 * @param n neighbour to check.
2016 static void process_plaintext_neighbour_queue (struct Neighbour *n);
2020 * Check if we have encrypted messages for the specified neighbour
2021 * pending, and if so, check with the transport about sending them
2024 * @param n neighbour to check.
2027 process_encrypted_neighbour_queue (struct Neighbour *n)
2029 struct MessageEntry *m;
2032 return; /* request already pending */
2033 if (GNUNET_YES != n->is_connected)
2038 m = n->encrypted_head;
2041 /* encrypted queue empty, try plaintext instead */
2042 process_plaintext_neighbour_queue (n);
2046 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2047 "Asking transport for transmission of %u bytes to `%4s' in next %llu ms\n",
2048 (unsigned int) m->size,
2049 GNUNET_i2s (&n->peer),
2050 (unsigned long long) GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value);
2053 GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer,
2056 GNUNET_TIME_absolute_get_remaining
2058 ¬ify_encrypted_transmit_ready,
2062 /* message request too large or duplicate request */
2064 /* discard encrypted message */
2065 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
2069 process_encrypted_neighbour_queue (n);
2075 * Decrypt size bytes from in and write the result to out. Use the
2076 * key for inbound traffic of the given neighbour. This function does
2077 * NOT do any integrity-checks on the result.
2079 * @param n neighbour we are receiving from
2080 * @param iv initialization vector to use
2081 * @param in ciphertext
2082 * @param out plaintext
2083 * @param size size of in/out
2084 * @return GNUNET_OK on success
2087 do_decrypt (struct Neighbour *n,
2088 const struct GNUNET_CRYPTO_AesInitializationVector * iv,
2089 const void *in, void *out, size_t size)
2091 if (size != (uint16_t) size)
2096 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
2097 (n->status != PEER_STATE_KEY_CONFIRMED))
2099 GNUNET_break_op (0);
2100 return GNUNET_SYSERR;
2103 GNUNET_CRYPTO_aes_decrypt (in,
2110 return GNUNET_SYSERR;
2112 GNUNET_STATISTICS_update (stats,
2113 gettext_noop ("# bytes decrypted"),
2117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2118 "Decrypted %u bytes from `%4s' using key %u, IV %u\n",
2119 (unsigned int) size,
2120 GNUNET_i2s (&n->peer),
2121 (unsigned int) n->decrypt_key.crc32,
2122 GNUNET_CRYPTO_crc32_n (iv, sizeof(*iv)));
2129 * Select messages for transmission. This heuristic uses a combination
2130 * of earliest deadline first (EDF) scheduling (with bounded horizon)
2131 * and priority-based discard (in case no feasible schedule exist) and
2132 * speculative optimization (defer any kind of transmission until
2133 * we either create a batch of significant size, 25% of max, or until
2134 * we are close to a deadline). Furthermore, when scheduling the
2135 * heuristic also packs as many messages into the batch as possible,
2136 * starting with those with the earliest deadline. Yes, this is fun.
2138 * @param n neighbour to select messages from
2139 * @param size number of bytes to select for transmission
2140 * @param retry_time set to the time when we should try again
2141 * (only valid if this function returns zero)
2142 * @return number of bytes selected, or 0 if we decided to
2143 * defer scheduling overall; in that case, retry_time is set.
2146 select_messages (struct Neighbour *n,
2147 size_t size, struct GNUNET_TIME_Relative *retry_time)
2149 struct MessageEntry *pos;
2150 struct MessageEntry *min;
2151 struct MessageEntry *last;
2152 unsigned int min_prio;
2153 struct GNUNET_TIME_Absolute t;
2154 struct GNUNET_TIME_Absolute now;
2155 struct GNUNET_TIME_Relative delta;
2157 struct GNUNET_TIME_Relative slack; /* how long could we wait before missing deadlines? */
2160 unsigned int queue_size;
2161 int discard_low_prio;
2163 GNUNET_assert (NULL != n->messages);
2164 now = GNUNET_TIME_absolute_get ();
2165 /* last entry in linked list of messages processed */
2167 /* should we remove the entry with the lowest
2168 priority from consideration for scheduling at the
2179 discard_low_prio = GNUNET_YES;
2180 while (GNUNET_YES == discard_low_prio)
2183 min_prio = UINT_MAX;
2184 discard_low_prio = GNUNET_NO;
2185 /* calculate number of bytes available for transmission at time "t" */
2186 avail = GNUNET_BANDWIDTH_tracker_get_available (&n->available_send_window);
2188 /* how many bytes have we (hypothetically) scheduled so far */
2190 /* maximum time we can wait before transmitting anything
2191 and still make all of our deadlines */
2192 slack = GNUNET_TIME_UNIT_FOREVER_REL;
2194 /* note that we use "*2" here because we want to look
2195 a bit further into the future; much more makes no
2196 sense since new message might be scheduled in the
2198 while ((pos != NULL) && (off < size * 2))
2200 if (pos->do_transmit == GNUNET_YES)
2202 /* already removed from consideration */
2206 if (discard_low_prio == GNUNET_NO)
2208 delta = GNUNET_TIME_absolute_get_difference (t, pos->deadline);
2209 if (delta.rel_value > 0)
2211 // FIXME: HUH? Check!
2213 avail += GNUNET_BANDWIDTH_value_get_available_until (n->bw_out,
2216 if (avail < pos->size)
2218 // FIXME: HUH? Check!
2219 discard_low_prio = GNUNET_YES; /* we could not schedule this one! */
2224 /* update slack, considering both its absolute deadline
2225 and relative deadlines caused by other messages
2226 with their respective load */
2227 slack = GNUNET_TIME_relative_min (slack,
2228 GNUNET_BANDWIDTH_value_get_delay_for (n->bw_out,
2230 if (pos->deadline.abs_value <= now.abs_value)
2233 slack = GNUNET_TIME_UNIT_ZERO;
2235 else if (GNUNET_YES == pos->got_slack)
2237 /* should be soon now! */
2238 slack = GNUNET_TIME_relative_min (slack,
2239 GNUNET_TIME_absolute_get_remaining (pos->slack_deadline));
2244 GNUNET_TIME_relative_min (slack,
2245 GNUNET_TIME_absolute_get_difference (now, pos->deadline));
2246 pos->got_slack = GNUNET_YES;
2247 pos->slack_deadline = GNUNET_TIME_absolute_min (pos->deadline,
2248 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_MAX_CORK_DELAY));
2253 t = GNUNET_TIME_absolute_max (pos->deadline, t); // HUH? Check!
2254 if (pos->priority <= min_prio)
2256 /* update min for discard */
2257 min_prio = pos->priority;
2262 if (discard_low_prio)
2264 GNUNET_assert (min != NULL);
2265 /* remove lowest-priority entry from consideration */
2266 min->do_transmit = GNUNET_YES; /* means: discard (for now) */
2270 /* guard against sending "tiny" messages with large headers without
2272 if ( (slack.rel_value > GNUNET_CONSTANTS_MAX_CORK_DELAY.rel_value) &&
2274 (queue_size <= MAX_PEER_QUEUE_SIZE - 2) )
2276 /* less than 25% of message would be filled with deadlines still
2277 being met if we delay by one second or more; so just wait for
2278 more data; but do not wait longer than 1s (since we don't want
2279 to delay messages for a really long time either). */
2280 *retry_time = GNUNET_CONSTANTS_MAX_CORK_DELAY;
2281 /* reset do_transmit values for next time */
2284 pos->do_transmit = GNUNET_NO;
2287 GNUNET_STATISTICS_update (stats,
2288 gettext_noop ("# transmissions delayed due to corking"),
2291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2292 "Deferring transmission for %llums due to underfull message buffer size (%u/%u)\n",
2293 (unsigned long long) retry_time->rel_value,
2295 (unsigned int) size);
2299 /* select marked messages (up to size) for transmission */
2304 if ((pos->size <= size) && (pos->do_transmit == GNUNET_NO))
2306 pos->do_transmit = GNUNET_YES; /* mark for transmission */
2310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2311 "Selecting message of size %u for transmission\n",
2312 (unsigned int) pos->size);
2318 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2319 "Not selecting message of size %u for transmission at this time (maximum is %u)\n",
2320 (unsigned int) pos->size,
2323 pos->do_transmit = GNUNET_NO; /* mark for not transmitting! */
2328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2329 "Selected %llu/%llu bytes of %u/%u plaintext messages for transmission to `%4s'.\n",
2330 (unsigned long long) off, (unsigned long long) tsize,
2331 queue_size, (unsigned int) MAX_PEER_QUEUE_SIZE,
2332 GNUNET_i2s (&n->peer));
2339 * Batch multiple messages into a larger buffer.
2341 * @param n neighbour to take messages from
2342 * @param buf target buffer
2343 * @param size size of buf
2344 * @param deadline set to transmission deadline for the result
2345 * @param retry_time set to the time when we should try again
2346 * (only valid if this function returns zero)
2347 * @param priority set to the priority of the batch
2348 * @return number of bytes written to buf (can be zero)
2351 batch_message (struct Neighbour *n,
2354 struct GNUNET_TIME_Absolute *deadline,
2355 struct GNUNET_TIME_Relative *retry_time,
2356 unsigned int *priority)
2358 char ntmb[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
2359 struct NotifyTrafficMessage *ntm = (struct NotifyTrafficMessage*) ntmb;
2360 struct MessageEntry *pos;
2361 struct MessageEntry *prev;
2362 struct MessageEntry *next;
2367 *deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2368 *retry_time = GNUNET_TIME_UNIT_FOREVER_REL;
2369 if (0 == select_messages (n, size, retry_time))
2372 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2373 "No messages selected, will try again in %llu ms\n",
2374 retry_time->rel_value);
2378 ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND);
2379 ntm->ats_count = htonl (0);
2380 ntm->ats.type = htonl (0);
2381 ntm->ats.value = htonl (0);
2382 ntm->peer = n->peer;
2385 while ((pos != NULL) && (size >= sizeof (struct GNUNET_MessageHeader)))
2388 if (GNUNET_YES == pos->do_transmit)
2390 GNUNET_assert (pos->size <= size);
2391 /* do notifications */
2392 /* FIXME: track if we have *any* client that wants
2393 full notifications and only do this if that is
2395 if (pos->size < GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct NotifyTrafficMessage))
2397 memcpy (&ntm[1], &pos[1], pos->size);
2398 ntm->header.size = htons (sizeof (struct NotifyTrafficMessage) +
2399 sizeof (struct GNUNET_MessageHeader));
2400 send_to_all_clients (&ntm->header,
2402 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
2406 /* message too large for 'full' notifications, we do at
2407 least the 'hdr' type */
2410 sizeof (struct GNUNET_MessageHeader));
2412 ntm->header.size = htons (sizeof (struct NotifyTrafficMessage) +
2414 send_to_all_clients (&ntm->header,
2416 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
2418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2419 "Encrypting %u bytes with message of type %u and size %u\n",
2421 (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->type),
2422 (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->size));
2424 /* copy for encrypted transmission */
2425 memcpy (&buf[ret], &pos[1], pos->size);
2428 *priority += pos->priority;
2430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2431 "Adding plaintext message of size %u with deadline %llu ms to batch\n",
2432 (unsigned int) pos->size,
2433 (unsigned long long) GNUNET_TIME_absolute_get_remaining (pos->deadline).rel_value);
2435 deadline->abs_value = GNUNET_MIN (deadline->abs_value, pos->deadline.abs_value);
2449 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2450 "Deadline for message batch is %llu ms\n",
2451 GNUNET_TIME_absolute_get_remaining (*deadline).rel_value);
2458 * Remove messages with deadlines that have long expired from
2461 * @param n neighbour to inspect
2464 discard_expired_messages (struct Neighbour *n)
2466 struct MessageEntry *prev;
2467 struct MessageEntry *next;
2468 struct MessageEntry *pos;
2469 struct GNUNET_TIME_Absolute now;
2470 struct GNUNET_TIME_Relative delta;
2474 now = GNUNET_TIME_absolute_get ();
2480 delta = GNUNET_TIME_absolute_get_difference (pos->deadline, now);
2481 if (delta.rel_value > PAST_EXPIRATION_DISCARD_TIME.rel_value)
2484 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2485 "Message is %llu ms past due, discarding.\n",
2492 GNUNET_STATISTICS_update (stats,
2493 gettext_noop ("# messages discarded (expired prior to transmission)"),
2503 if (GNUNET_YES == disc)
2504 schedule_peer_messages (n);
2509 * Signature of the main function of a task.
2511 * @param cls closure
2512 * @param tc context information (why was this task triggered now)
2515 retry_plaintext_processing (void *cls,
2516 const struct GNUNET_SCHEDULER_TaskContext *tc)
2518 struct Neighbour *n = cls;
2520 n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2521 process_plaintext_neighbour_queue (n);
2526 * Send our key (and encrypted PING) to the other peer.
2528 * @param n the other peer
2530 static void send_key (struct Neighbour *n);
2533 * Task that will retry "send_key" if our previous attempt failed
2537 set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2539 struct Neighbour *n = cls;
2542 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2543 "Retrying key transmission to `%4s'\n",
2544 GNUNET_i2s (&n->peer));
2546 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
2547 n->set_key_retry_frequency =
2548 GNUNET_TIME_relative_multiply (n->set_key_retry_frequency, 2);
2554 * Check if we have plaintext messages for the specified neighbour
2555 * pending, and if so, consider batching and encrypting them (and
2556 * then trigger processing of the encrypted queue if needed).
2558 * @param n neighbour to check.
2561 process_plaintext_neighbour_queue (struct Neighbour *n)
2563 char pbuf[GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE + sizeof (struct EncryptedMessage)]; /* plaintext */
2565 struct EncryptedMessage *em; /* encrypted message */
2566 struct EncryptedMessage *ph; /* plaintext header */
2567 struct MessageEntry *me;
2568 unsigned int priority;
2569 struct GNUNET_TIME_Absolute deadline;
2570 struct GNUNET_TIME_Relative retry_time;
2571 struct GNUNET_CRYPTO_AesInitializationVector iv;
2572 struct GNUNET_CRYPTO_AuthKey auth_key;
2574 if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
2576 GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
2577 n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2581 case PEER_STATE_DOWN:
2584 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2585 "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2586 GNUNET_i2s(&n->peer));
2589 case PEER_STATE_KEY_SENT:
2590 if (n->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK)
2591 n->retry_set_key_task
2592 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2593 &set_key_retry_task, n);
2595 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2596 "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2597 GNUNET_i2s(&n->peer));
2600 case PEER_STATE_KEY_RECEIVED:
2601 if (n->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK)
2602 n->retry_set_key_task
2603 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2604 &set_key_retry_task, n);
2606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2607 "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2608 GNUNET_i2s(&n->peer));
2611 case PEER_STATE_KEY_CONFIRMED:
2612 /* ready to continue */
2615 discard_expired_messages (n);
2616 if (n->messages == NULL)
2619 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2620 "Plaintext message queue for `%4s' is empty.\n",
2621 GNUNET_i2s(&n->peer));
2623 return; /* no pending messages */
2625 if (n->encrypted_head != NULL)
2628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2629 "Encrypted message queue for `%4s' is still full, delaying plaintext processing.\n",
2630 GNUNET_i2s(&n->peer));
2632 return; /* wait for messages already encrypted to be
2635 ph = (struct EncryptedMessage *) pbuf;
2636 deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2638 used = sizeof (struct EncryptedMessage);
2639 used += batch_message (n,
2641 GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE,
2642 &deadline, &retry_time, &priority);
2643 if (used == sizeof (struct EncryptedMessage))
2646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2647 "No messages selected for transmission to `%4s' at this time, will try again later.\n",
2648 GNUNET_i2s(&n->peer));
2650 /* no messages selected for sending, try again later... */
2651 n->retry_plaintext_task =
2652 GNUNET_SCHEDULER_add_delayed (retry_time,
2653 &retry_plaintext_processing, n);
2656 #if DEBUG_CORE_QUOTA
2657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2658 "Sending %u b/s as new limit to peer `%4s'\n",
2659 (unsigned int) ntohl (n->bw_in.value__),
2660 GNUNET_i2s (&n->peer));
2662 ph->iv_seed = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
2663 ph->sequence_number = htonl (++n->last_sequence_number_sent);
2664 ph->inbound_bw_limit = n->bw_in;
2665 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
2667 /* setup encryption message header */
2668 me = GNUNET_malloc (sizeof (struct MessageEntry) + used);
2669 me->deadline = deadline;
2670 me->priority = priority;
2672 em = (struct EncryptedMessage *) &me[1];
2673 em->header.size = htons (used);
2674 em->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
2675 em->iv_seed = ph->iv_seed;
2676 derive_iv (&iv, &n->encrypt_key, ph->iv_seed, &n->peer);
2679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2680 "Encrypting %u bytes of plaintext messages for `%4s' for transmission in %llums.\n",
2681 (unsigned int) used - ENCRYPTED_HEADER_SIZE,
2682 GNUNET_i2s(&n->peer),
2683 (unsigned long long) GNUNET_TIME_absolute_get_remaining (deadline).rel_value);
2685 GNUNET_assert (GNUNET_OK ==
2688 &ph->sequence_number,
2689 &em->sequence_number, used - ENCRYPTED_HEADER_SIZE));
2690 derive_auth_key (&auth_key,
2693 n->encrypt_key_created);
2694 GNUNET_CRYPTO_hmac (&auth_key,
2695 &em->sequence_number,
2696 used - ENCRYPTED_HEADER_SIZE,
2699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2700 "Authenticated %u bytes of ciphertext %u: `%s'\n",
2701 used - ENCRYPTED_HEADER_SIZE,
2702 GNUNET_CRYPTO_crc32_n (&em->sequence_number,
2703 used - ENCRYPTED_HEADER_SIZE),
2704 GNUNET_h2s (&em->hmac));
2706 /* append to transmission list */
2707 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
2711 process_encrypted_neighbour_queue (n);
2712 schedule_peer_messages (n);
2717 * Function that recalculates the bandwidth quota for the
2718 * given neighbour and transmits it to the transport service.
2720 * @param cls neighbour for the quota update
2724 neighbour_quota_update (void *cls,
2725 const struct GNUNET_SCHEDULER_TaskContext *tc);
2729 * Schedule the task that will recalculate the bandwidth
2730 * quota for this peer (and possibly force a disconnect of
2731 * idle peers by calculating a bandwidth of zero).
2734 schedule_quota_update (struct Neighbour *n)
2736 GNUNET_assert (n->quota_update_task ==
2737 GNUNET_SCHEDULER_NO_TASK);
2738 n->quota_update_task
2739 = GNUNET_SCHEDULER_add_delayed (QUOTA_UPDATE_FREQUENCY,
2740 &neighbour_quota_update,
2746 * Initialize a new 'struct Neighbour'.
2748 * @param pid ID of the new neighbour
2749 * @return handle for the new neighbour
2751 static struct Neighbour *
2752 create_neighbour (const struct GNUNET_PeerIdentity *pid)
2754 struct Neighbour *n;
2755 struct GNUNET_TIME_Absolute now;
2758 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2759 "Creating neighbour entry for peer `%4s'\n",
2762 n = GNUNET_malloc (sizeof (struct Neighbour));
2764 GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
2765 now = GNUNET_TIME_absolute_get ();
2766 n->encrypt_key_created = now;
2767 n->last_activity = now;
2768 n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
2769 n->bw_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2770 n->bw_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2771 n->bw_out_internal_limit = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
2772 n->bw_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2773 n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
2775 GNUNET_assert (GNUNET_OK ==
2776 GNUNET_CONTAINER_multihashmap_put (neighbours,
2777 &n->peer.hashPubKey,
2779 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2780 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
2781 GNUNET_CONTAINER_multihashmap_size (neighbours), GNUNET_NO);
2782 neighbour_quota_update (n, NULL);
2783 consider_free_neighbour (n);
2789 * Handle CORE_SEND request.
2792 * @param client the client issuing the request
2793 * @param message the "struct SendMessage"
2796 handle_client_send (void *cls,
2797 struct GNUNET_SERVER_Client *client,
2798 const struct GNUNET_MessageHeader *message)
2800 const struct SendMessage *sm;
2801 struct Neighbour *n;
2802 struct MessageEntry *prev;
2803 struct MessageEntry *pos;
2804 struct MessageEntry *e;
2805 struct MessageEntry *min_prio_entry;
2806 struct MessageEntry *min_prio_prev;
2807 unsigned int min_prio;
2808 unsigned int queue_size;
2811 msize = ntohs (message->size);
2813 sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader))
2815 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2816 "msize is %u, should be at least %u (in %s:%d)\n",
2818 sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader),
2819 __FILE__, __LINE__);
2822 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2825 sm = (const struct SendMessage *) message;
2826 msize -= sizeof (struct SendMessage);
2827 if (0 == memcmp (&sm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2830 GNUNET_SERVER_mst_receive (mst,
2832 (const char*) &sm[1],
2837 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2840 n = find_neighbour (&sm->peer);
2842 (GNUNET_YES != n->is_connected) ||
2843 (n->status != PEER_STATE_KEY_CONFIRMED) )
2845 /* attempt to send message to peer that is not connected anymore
2846 (can happen due to asynchrony) */
2847 GNUNET_STATISTICS_update (stats,
2848 gettext_noop ("# messages discarded (disconnected)"),
2852 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2856 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2857 "Core received `%s' request, queueing %u bytes of plaintext data for transmission to `%4s'.\n",
2859 (unsigned int) msize,
2860 GNUNET_i2s (&sm->peer));
2862 discard_expired_messages (n);
2863 /* bound queue size */
2864 /* NOTE: this entire block to bound the queue size should be
2865 obsolete with the new client-request code and the
2866 'schedule_peer_messages' mechanism; we still have this code in
2867 here for now as a sanity check for the new mechanmism;
2868 ultimately, we should probably simply reject SEND messages that
2869 are not 'approved' (or provide a new core API for very unreliable
2870 delivery that always sends with priority 0). Food for thought. */
2871 min_prio = UINT32_MAX;
2872 min_prio_entry = NULL;
2873 min_prio_prev = NULL;
2879 if (pos->priority <= min_prio)
2881 min_prio_entry = pos;
2882 min_prio_prev = prev;
2883 min_prio = pos->priority;
2889 if (queue_size >= MAX_PEER_QUEUE_SIZE)
2892 if (ntohl(sm->priority) <= min_prio)
2894 /* discard new entry; this should no longer happen! */
2897 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2898 "Queue full (%u/%u), discarding new request (%u bytes of type %u)\n",
2900 (unsigned int) MAX_PEER_QUEUE_SIZE,
2901 (unsigned int) msize,
2902 (unsigned int) ntohs (message->type));
2904 GNUNET_STATISTICS_update (stats,
2905 gettext_noop ("# discarded CORE_SEND requests"),
2909 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2912 GNUNET_assert (min_prio_entry != NULL);
2913 /* discard "min_prio_entry" */
2915 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2916 "Queue full, discarding existing older request\n");
2918 GNUNET_STATISTICS_update (stats, gettext_noop ("# discarded lower priority CORE_SEND requests"), 1, GNUNET_NO);
2919 if (min_prio_prev == NULL)
2920 n->messages = min_prio_entry->next;
2922 min_prio_prev->next = min_prio_entry->next;
2923 GNUNET_free (min_prio_entry);
2927 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2928 "Adding transmission request for `%4s' of size %u to queue\n",
2929 GNUNET_i2s (&sm->peer),
2930 (unsigned int) msize);
2932 GNUNET_break (0 == ntohl (sm->reserved));
2933 e = GNUNET_malloc (sizeof (struct MessageEntry) + msize);
2934 e->deadline = GNUNET_TIME_absolute_ntoh (sm->deadline);
2935 e->priority = ntohl (sm->priority);
2937 if (GNUNET_YES != (int) ntohl (sm->cork))
2938 e->got_slack = GNUNET_YES;
2939 memcpy (&e[1], &sm[1], msize);
2941 /* insert, keep list sorted by deadline */
2944 while ((pos != NULL) && (pos->deadline.abs_value < e->deadline.abs_value))
2955 /* consider scheduling now */
2956 process_plaintext_neighbour_queue (n);
2958 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2963 * Handle CORE_REQUEST_CONNECT request.
2966 * @param client the client issuing the request
2967 * @param message the "struct ConnectMessage"
2970 handle_client_request_connect (void *cls,
2971 struct GNUNET_SERVER_Client *client,
2972 const struct GNUNET_MessageHeader *message)
2974 const struct ConnectMessage *cm = (const struct ConnectMessage*) message;
2975 struct Neighbour *n;
2977 if (0 == memcmp (&cm->peer,
2979 sizeof (struct GNUNET_PeerIdentity)))
2981 /* In this case a client has asked us to connect to ourselves, not really an error! */
2982 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2985 GNUNET_break (ntohl (cm->reserved) == 0);
2987 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2988 "Core received `%s' request for `%4s', will try to establish connection\n",
2990 GNUNET_i2s (&cm->peer));
2992 GNUNET_STATISTICS_update (stats,
2993 gettext_noop ("# connection requests received"),
2996 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2997 n = find_neighbour (&cm->peer);
2999 (GNUNET_YES != n->is_connected) )
3001 GNUNET_TRANSPORT_try_connect (transport,
3006 GNUNET_STATISTICS_update (stats,
3007 gettext_noop ("# connection requests ignored (already connected)"),
3015 * PEERINFO is giving us a HELLO for a peer. Add the public key to
3016 * the neighbour's struct and retry send_key. Or, if we did not get a
3017 * HELLO, just do nothing.
3019 * @param cls the 'struct Neighbour' to retry sending the key for
3020 * @param peer the peer for which this is the HELLO
3021 * @param hello HELLO message of that peer
3022 * @param err_msg NULL if successful, otherwise contains error message
3025 process_hello_retry_send_key (void *cls,
3026 const struct GNUNET_PeerIdentity *peer,
3027 const struct GNUNET_HELLO_Message *hello,
3028 const char *err_msg)
3030 struct Neighbour *n = cls;
3032 if (err_msg != NULL)
3034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3035 _("Error in communication with PEERINFO service\n"));
3042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3043 "Entered `%s' and `%s' is NULL!\n",
3044 "process_hello_retry_send_key",
3048 if (n->public_key != NULL)
3050 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3052 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3053 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3055 GNUNET_STATISTICS_update (stats,
3056 gettext_noop ("# SET_KEY messages deferred (need public key)"),
3064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3065 "Failed to obtain public key for peer `%4s', delaying processing of SET_KEY\n",
3066 GNUNET_i2s (&n->peer));
3068 GNUNET_STATISTICS_update (stats,
3069 gettext_noop ("# Delayed connecting due to lack of public key"),
3072 if (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task)
3073 n->retry_set_key_task
3074 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
3075 &set_key_retry_task, n);
3081 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3082 "Entered `%s' for peer `%4s'\n",
3083 "process_hello_retry_send_key",
3086 if (n->public_key != NULL)
3088 /* already have public key, why are we here? */
3094 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3095 "Received new `%s' message for `%4s', initiating key exchange.\n",
3100 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3101 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
3103 GNUNET_STATISTICS_update (stats,
3104 gettext_noop ("# Error extracting public key from HELLO"),
3107 GNUNET_free (n->public_key);
3108 n->public_key = NULL;
3110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3111 "GNUNET_HELLO_get_key returned awfully\n");
3119 * Send our key (and encrypted PING) to the other peer.
3121 * @param n the other peer
3124 send_key (struct Neighbour *n)
3126 struct MessageEntry *pos;
3127 struct SetKeyMessage *sm;
3128 struct MessageEntry *me;
3129 struct PingMessage pp;
3130 struct PingMessage *pm;
3131 struct GNUNET_CRYPTO_AesInitializationVector iv;
3133 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3135 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3136 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3138 if (n->pitr != NULL)
3141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3142 "Key exchange in progress with `%4s'.\n",
3143 GNUNET_i2s (&n->peer));
3145 return; /* already in progress */
3147 if (GNUNET_YES != n->is_connected)
3149 GNUNET_STATISTICS_update (stats,
3150 gettext_noop ("# Asking transport to connect (for SET_KEY)"),
3153 GNUNET_TRANSPORT_try_connect (transport,
3158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3159 "Asked to perform key exchange with `%4s'.\n",
3160 GNUNET_i2s (&n->peer));
3162 if (n->public_key == NULL)
3164 /* lookup n's public key, then try again */
3166 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3167 "Lacking public key for `%4s', trying to obtain one (send_key).\n",
3168 GNUNET_i2s (&n->peer));
3170 GNUNET_assert (n->pitr == NULL);
3171 n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
3173 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20),
3174 &process_hello_retry_send_key, n);
3177 pos = n->encrypted_head;
3180 if (GNUNET_YES == pos->is_setkey)
3182 if (pos->sender_status == n->status)
3185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3186 "`%s' message for `%4s' queued already\n",
3188 GNUNET_i2s (&n->peer));
3190 goto trigger_processing;
3192 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
3197 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3198 "Removing queued `%s' message for `%4s', will create a new one\n",
3200 GNUNET_i2s (&n->peer));
3210 case PEER_STATE_DOWN:
3211 n->status = PEER_STATE_KEY_SENT;
3213 case PEER_STATE_KEY_SENT:
3215 case PEER_STATE_KEY_RECEIVED:
3217 case PEER_STATE_KEY_CONFIRMED:
3225 /* first, set key message */
3226 me = GNUNET_malloc (sizeof (struct MessageEntry) +
3227 sizeof (struct SetKeyMessage) +
3228 sizeof (struct PingMessage));
3229 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_SET_KEY_DELAY);
3230 me->priority = SET_KEY_PRIORITY;
3231 me->size = sizeof (struct SetKeyMessage) + sizeof (struct PingMessage);
3232 me->is_setkey = GNUNET_YES;
3233 me->got_slack = GNUNET_YES; /* do not defer this one! */
3234 me->sender_status = n->status;
3235 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
3239 sm = (struct SetKeyMessage *) &me[1];
3240 sm->header.size = htons (sizeof (struct SetKeyMessage));
3241 sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SET_KEY);
3242 sm->sender_status = htonl ((int32_t) ((n->status == PEER_STATE_DOWN) ?
3243 PEER_STATE_KEY_SENT : n->status));
3245 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3246 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3247 sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
3248 sizeof (struct GNUNET_PeerIdentity));
3249 sm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_KEY);
3250 sm->creation_time = GNUNET_TIME_absolute_hton (n->encrypt_key_created);
3251 sm->target = n->peer;
3252 GNUNET_assert (GNUNET_OK ==
3253 GNUNET_CRYPTO_rsa_encrypt (&n->encrypt_key,
3255 GNUNET_CRYPTO_AesSessionKey),
3257 &sm->encrypted_key));
3258 GNUNET_assert (GNUNET_OK ==
3259 GNUNET_CRYPTO_rsa_sign (my_private_key, &sm->purpose,
3261 pm = (struct PingMessage *) &sm[1];
3262 pm->header.size = htons (sizeof (struct PingMessage));
3263 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
3264 pm->iv_seed = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
3265 derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
3266 pp.challenge = n->ping_challenge;
3267 pp.target = n->peer;
3269 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3270 "Encrypting `%s' and `%s' messages with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
3272 (unsigned int) n->ping_challenge,
3273 GNUNET_i2s (&n->peer),
3274 (unsigned int) n->encrypt_key.crc32,
3275 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3282 sizeof (struct PingMessage) -
3283 ((void *) &pm->target - (void *) pm));
3284 GNUNET_STATISTICS_update (stats,
3285 gettext_noop ("# SET_KEY and PING messages created"),
3289 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3290 "Have %llu ms left for `%s' transmission.\n",
3291 (unsigned long long) GNUNET_TIME_absolute_get_remaining (me->deadline).rel_value,
3295 /* trigger queue processing */
3296 process_encrypted_neighbour_queue (n);
3297 if ( (n->status != PEER_STATE_KEY_CONFIRMED) &&
3298 (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task) )
3299 n->retry_set_key_task
3300 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
3301 &set_key_retry_task, n);
3306 * We received a SET_KEY message. Validate and update
3307 * our key material and status.
3309 * @param n the neighbour from which we received message m
3310 * @param m the set key message we received
3311 * @param ats performance data
3312 * @param ats_count number of entries in ats (excluding 0-termination)
3315 handle_set_key (struct Neighbour *n,
3316 const struct SetKeyMessage *m,
3317 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3318 uint32_t ats_count);
3323 * PEERINFO is giving us a HELLO for a peer. Add the public key to
3324 * the neighbour's struct and retry handling the set_key message. Or,
3325 * if we did not get a HELLO, just free the set key message.
3327 * @param cls pointer to the set key message
3328 * @param peer the peer for which this is the HELLO
3329 * @param hello HELLO message of that peer
3330 * @param err_msg NULL if successful, otherwise contains error message
3333 process_hello_retry_handle_set_key (void *cls,
3334 const struct GNUNET_PeerIdentity *peer,
3335 const struct GNUNET_HELLO_Message *hello,
3336 const char *err_msg)
3338 struct Neighbour *n = cls;
3339 struct SetKeyMessage *sm = n->skm;
3341 if (err_msg != NULL)
3343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3344 _("Error in communication with PEERINFO service\n"));
3352 if (n->public_key != NULL)
3355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3356 "Received `%s' for `%4s', continuing processing of `%s' message.\n",
3358 GNUNET_i2s (&n->peer),
3361 handle_set_key (n, sm, NULL, 0);
3365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3366 _("Ignoring `%s' message due to lack of public key for peer `%4s' (failed to obtain one).\n"),
3368 GNUNET_i2s (&n->peer));
3373 if (n->public_key != NULL)
3374 return; /* multiple HELLOs match!? */
3376 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3377 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
3379 GNUNET_break_op (0);
3380 GNUNET_free (n->public_key);
3381 n->public_key = NULL;
3387 * Merge the given performance data with the data we currently
3388 * track for the given neighbour.
3390 * @param n neighbour
3391 * @param ats new performance data
3392 * @param ats_count number of records in ats
3395 update_neighbour_performance (struct Neighbour *n,
3396 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3404 for (i = 0; i < ats_count; i++)
3406 for (j=0;j < n->ats_count; j++)
3408 if (n->ats[j].type == ats[i].type)
3410 n->ats[j].value = ats[i].value;
3414 if (j == n->ats_count)
3416 GNUNET_array_append (n->ats,
3425 * We received a PING message. Validate and transmit
3428 * @param n sender of the PING
3429 * @param m the encrypted PING message itself
3430 * @param ats performance data
3431 * @param ats_count number of entries in ats (excluding 0-termination)
3434 handle_ping (struct Neighbour *n,
3435 const struct PingMessage *m,
3436 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3439 struct PingMessage t;
3440 struct PongMessage tx;
3441 struct PongMessage *tp;
3442 struct MessageEntry *me;
3443 struct GNUNET_CRYPTO_AesInitializationVector iv;
3446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3447 "Core service receives `%s' request from `%4s'.\n",
3448 "PING", GNUNET_i2s (&n->peer));
3450 derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
3456 sizeof (struct PingMessage) -
3457 ((void *) &m->target - (void *) m)))
3460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3461 "Decrypted `%s' to `%4s' with challenge %u decrypted using key %u, IV %u (salt %u)\n",
3463 GNUNET_i2s (&t.target),
3464 (unsigned int) t.challenge,
3465 (unsigned int) n->decrypt_key.crc32,
3466 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3469 GNUNET_STATISTICS_update (stats,
3470 gettext_noop ("# PING messages decrypted"),
3473 if (0 != memcmp (&t.target,
3474 &my_identity, sizeof (struct GNUNET_PeerIdentity)))
3479 GNUNET_snprintf(sender, sizeof (sender), "%8s", GNUNET_i2s (&n->peer));
3480 GNUNET_snprintf(peer, sizeof (peer), "%8s", GNUNET_i2s (&t.target));
3481 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3482 _("Received PING from `%s' for different identity: I am `%s', PONG identity: `%s'\n"),
3484 GNUNET_i2s (&my_identity),
3486 GNUNET_break_op (0);
3489 update_neighbour_performance (n, ats, ats_count);
3490 me = GNUNET_malloc (sizeof (struct MessageEntry) +
3491 sizeof (struct PongMessage));
3492 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
3496 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PONG_DELAY);
3497 me->priority = PONG_PRIORITY;
3498 me->size = sizeof (struct PongMessage);
3499 tx.inbound_bw_limit = n->bw_in;
3500 tx.challenge = t.challenge;
3501 tx.target = t.target;
3502 tp = (struct PongMessage *) &me[1];
3503 tp->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG);
3504 tp->header.size = htons (sizeof (struct PongMessage));
3505 tp->iv_seed = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
3506 derive_pong_iv (&iv, &n->encrypt_key, tp->iv_seed, t.challenge, &n->peer);
3511 sizeof (struct PongMessage) -
3512 ((void *) &tp->challenge - (void *) tp));
3513 GNUNET_STATISTICS_update (stats,
3514 gettext_noop ("# PONG messages created"),
3518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3519 "Encrypting `%s' with challenge %u using key %u, IV %u (salt %u)\n",
3521 (unsigned int) t.challenge,
3522 (unsigned int) n->encrypt_key.crc32,
3523 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3526 /* trigger queue processing */
3527 process_encrypted_neighbour_queue (n);
3532 * We received a PONG message. Validate and update our status.
3534 * @param n sender of the PONG
3535 * @param m the encrypted PONG message itself
3536 * @param ats performance data
3537 * @param ats_count number of entries in ats (excluding 0-termination)
3540 handle_pong (struct Neighbour *n,
3541 const struct PongMessage *m,
3542 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3545 struct PongMessage t;
3546 struct ConnectNotifyMessage *cnm;
3547 struct GNUNET_CRYPTO_AesInitializationVector iv;
3548 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
3549 struct GNUNET_TRANSPORT_ATS_Information *mats;
3553 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3554 "Core service receives `%s' response from `%4s'.\n",
3555 "PONG", GNUNET_i2s (&n->peer));
3557 /* mark as garbage, just to be sure */
3558 memset (&t, 255, sizeof (t));
3559 derive_pong_iv (&iv, &n->decrypt_key, m->iv_seed, n->ping_challenge,
3566 sizeof (struct PongMessage) -
3567 ((void *) &m->challenge - (void *) m)))
3569 GNUNET_break_op (0);
3572 GNUNET_STATISTICS_update (stats,
3573 gettext_noop ("# PONG messages decrypted"),
3577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3578 "Decrypted `%s' from `%4s' with challenge %u using key %u, IV %u (salt %u)\n",
3580 GNUNET_i2s (&t.target),
3581 (unsigned int) t.challenge,
3582 (unsigned int) n->decrypt_key.crc32,
3583 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3586 if ((0 != memcmp (&t.target,
3588 sizeof (struct GNUNET_PeerIdentity))) ||
3589 (n->ping_challenge != t.challenge))
3591 /* PONG malformed */
3593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3594 "Received malformed `%s' wanted sender `%4s' with challenge %u\n",
3596 GNUNET_i2s (&n->peer),
3597 (unsigned int) n->ping_challenge);
3598 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3599 "Received malformed `%s' received from `%4s' with challenge %u\n",
3600 "PONG", GNUNET_i2s (&t.target),
3601 (unsigned int) t.challenge);
3603 GNUNET_break_op (n->ping_challenge != t.challenge);
3608 case PEER_STATE_DOWN:
3609 GNUNET_break (0); /* should be impossible */
3611 case PEER_STATE_KEY_SENT:
3612 GNUNET_break (0); /* should be impossible, how did we decrypt? */
3614 case PEER_STATE_KEY_RECEIVED:
3615 GNUNET_STATISTICS_update (stats,
3616 gettext_noop ("# Session keys confirmed via PONG"),
3619 n->status = PEER_STATE_KEY_CONFIRMED;
3620 if (n->bw_out_external_limit.value__ != t.inbound_bw_limit.value__)
3622 n->bw_out_external_limit = t.inbound_bw_limit;
3623 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
3624 n->bw_out_internal_limit);
3625 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
3627 GNUNET_TRANSPORT_set_quota (transport,
3633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3634 "Confirmed key via `%s' message for peer `%4s'\n",
3635 "PONG", GNUNET_i2s (&n->peer));
3637 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3639 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3640 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3642 update_neighbour_performance (n, ats, ats_count);
3643 size = sizeof (struct ConnectNotifyMessage) +
3644 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3645 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
3648 /* recovery strategy: throw away performance data */
3649 GNUNET_array_grow (n->ats,
3652 size = sizeof (struct PeerStatusNotifyMessage) +
3653 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3655 cnm = (struct ConnectNotifyMessage*) buf;
3656 cnm->header.size = htons (size);
3657 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
3658 cnm->ats_count = htonl (n->ats_count);
3659 cnm->peer = n->peer;
3663 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
3664 mats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
3665 mats[n->ats_count].value = htonl (0);
3666 send_to_all_clients (&cnm->header,
3668 GNUNET_CORE_OPTION_SEND_CONNECT);
3669 process_encrypted_neighbour_queue (n);
3671 case PEER_STATE_KEY_CONFIRMED:
3672 n->last_activity = GNUNET_TIME_absolute_get ();
3673 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
3674 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
3676 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
3679 handle_peer_status_change (n);
3689 * We received a SET_KEY message. Validate and update
3690 * our key material and status.
3692 * @param n the neighbour from which we received message m
3693 * @param m the set key message we received
3694 * @param ats performance data
3695 * @param ats_count number of entries in ats (excluding 0-termination)
3698 handle_set_key (struct Neighbour *n,
3699 const struct SetKeyMessage *m,
3700 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3703 struct SetKeyMessage *m_cpy;
3704 struct GNUNET_TIME_Absolute t;
3705 struct GNUNET_CRYPTO_AesSessionKey k;
3706 struct PingMessage *ping;
3707 struct PongMessage *pong;
3708 enum PeerStateMachine sender_status;
3711 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3712 "Core service receives `%s' request from `%4s'.\n",
3713 "SET_KEY", GNUNET_i2s (&n->peer));
3715 if (n->public_key == NULL)
3717 if (n->pitr != NULL)
3720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3721 "Ignoring `%s' message due to lack of public key for peer (still trying to obtain one).\n",
3727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3728 "Lacking public key for peer, trying to obtain one (handle_set_key).\n");
3730 m_cpy = GNUNET_malloc (sizeof (struct SetKeyMessage));
3731 memcpy (m_cpy, m, sizeof (struct SetKeyMessage));
3732 /* lookup n's public key, then try again */
3733 GNUNET_assert (n->skm == NULL);
3735 n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
3737 GNUNET_TIME_UNIT_MINUTES,
3738 &process_hello_retry_handle_set_key, n);
3739 GNUNET_STATISTICS_update (stats,
3740 gettext_noop ("# SET_KEY messages deferred (need public key)"),
3745 if (0 != memcmp (&m->target,
3747 sizeof (struct GNUNET_PeerIdentity)))
3749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3750 _("Received `%s' message that was for `%s', not for me. Ignoring.\n"),
3752 GNUNET_i2s (&m->target));
3755 if ((ntohl (m->purpose.size) !=
3756 sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3757 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3758 sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
3759 sizeof (struct GNUNET_PeerIdentity)) ||
3761 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_KEY,
3762 &m->purpose, &m->signature, n->public_key)))
3764 /* invalid signature */
3765 GNUNET_break_op (0);
3768 t = GNUNET_TIME_absolute_ntoh (m->creation_time);
3769 if (((n->status == PEER_STATE_KEY_RECEIVED) ||
3770 (n->status == PEER_STATE_KEY_CONFIRMED)) &&
3771 (t.abs_value < n->decrypt_key_created.abs_value))
3773 /* this could rarely happen due to massive re-ordering of
3774 messages on the network level, but is most likely either
3775 a bug or some adversary messing with us. Report. */
3776 GNUNET_break_op (0);
3780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3781 "Decrypting key material.\n");
3783 if ((GNUNET_CRYPTO_rsa_decrypt (my_private_key,
3786 sizeof (struct GNUNET_CRYPTO_AesSessionKey))
3787 != sizeof (struct GNUNET_CRYPTO_AesSessionKey)) ||
3788 (GNUNET_OK != GNUNET_CRYPTO_aes_check_session_key (&k)))
3790 /* failed to decrypt !? */
3791 GNUNET_break_op (0);
3794 GNUNET_STATISTICS_update (stats,
3795 gettext_noop ("# SET_KEY messages decrypted"),
3799 if (n->decrypt_key_created.abs_value != t.abs_value)
3801 /* fresh key, reset sequence numbers */
3802 n->last_sequence_number_received = 0;
3803 n->last_packets_bitmap = 0;
3804 n->decrypt_key_created = t;
3806 update_neighbour_performance (n, ats, ats_count);
3807 sender_status = (enum PeerStateMachine) ntohl (m->sender_status);
3810 case PEER_STATE_DOWN:
3811 n->status = PEER_STATE_KEY_RECEIVED;
3813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3814 "Responding to `%s' with my own key.\n", "SET_KEY");
3818 case PEER_STATE_KEY_SENT:
3819 case PEER_STATE_KEY_RECEIVED:
3820 n->status = PEER_STATE_KEY_RECEIVED;
3821 if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
3822 (sender_status != PEER_STATE_KEY_CONFIRMED))
3825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3826 "Responding to `%s' with my own key (other peer has status %u).\n",
3828 (unsigned int) sender_status);
3833 case PEER_STATE_KEY_CONFIRMED:
3834 if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
3835 (sender_status != PEER_STATE_KEY_CONFIRMED))
3838 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3839 "Responding to `%s' with my own key (other peer has status %u), I was already fully up.\n",
3841 (unsigned int) sender_status);
3850 if (n->pending_ping != NULL)
3852 ping = n->pending_ping;
3853 n->pending_ping = NULL;
3854 handle_ping (n, ping, NULL, 0);
3857 if (n->pending_pong != NULL)
3859 pong = n->pending_pong;
3860 n->pending_pong = NULL;
3861 handle_pong (n, pong, NULL, 0);
3868 * Send a P2P message to a client.
3870 * @param sender who sent us the message?
3871 * @param client who should we give the message to?
3872 * @param m contains the message to transmit
3873 * @param msize number of bytes in buf to transmit
3876 send_p2p_message_to_client (struct Neighbour *sender,
3877 struct Client *client,
3878 const void *m, size_t msize)
3880 size_t size = msize + sizeof (struct NotifyTrafficMessage) +
3881 (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3883 struct NotifyTrafficMessage *ntm;
3884 struct GNUNET_TRANSPORT_ATS_Information *ats;
3886 GNUNET_assert (GNUNET_YES == sender->is_connected);
3887 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
3890 /* recovery strategy: throw performance data away... */
3891 GNUNET_array_grow (sender->ats,
3894 size = msize + sizeof (struct NotifyTrafficMessage) +
3895 (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3898 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3899 "Core service passes message from `%4s' of type %u to client.\n",
3900 GNUNET_i2s(&sender->peer),
3901 (unsigned int) ntohs (((const struct GNUNET_MessageHeader *) m)->type));
3903 ntm = (struct NotifyTrafficMessage *) buf;
3904 ntm->header.size = htons (size);
3905 ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
3906 ntm->ats_count = htonl (sender->ats_count);
3907 ntm->peer = sender->peer;
3911 sizeof (struct GNUNET_TRANSPORT_ATS_Information) * sender->ats_count);
3912 ats[sender->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
3913 ats[sender->ats_count].value = htonl (0);
3914 memcpy (&ats[sender->ats_count+1],
3917 send_to_client (client, &ntm->header, GNUNET_YES);
3922 * Deliver P2P message to interested clients.
3924 * @param cls always NULL
3925 * @param client who sent us the message (struct Neighbour)
3926 * @param m the message
3929 deliver_message (void *cls,
3931 const struct GNUNET_MessageHeader *m)
3933 struct Neighbour *sender = client;
3934 size_t msize = ntohs (m->size);
3936 struct Client *cpos;
3942 type = ntohs (m->type);
3944 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3945 "Received encapsulated message of type %u and size %u from `%4s'\n",
3946 (unsigned int) type,
3948 GNUNET_i2s (&sender->peer));
3950 GNUNET_snprintf (buf,
3952 gettext_noop ("# bytes of messages of type %u received"),
3953 (unsigned int) type);
3954 GNUNET_STATISTICS_update (stats,
3958 dropped = GNUNET_YES;
3960 while (cpos != NULL)
3962 deliver_full = GNUNET_NO;
3963 if (0 != (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))
3964 deliver_full = GNUNET_YES;
3967 for (tpos = 0; tpos < cpos->tcnt; tpos++)
3969 if (type != cpos->types[tpos])
3971 deliver_full = GNUNET_YES;
3975 if (GNUNET_YES == deliver_full)
3977 send_p2p_message_to_client (sender, cpos, m, msize);
3978 dropped = GNUNET_NO;
3980 else if (cpos->options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)
3982 send_p2p_message_to_client (sender, cpos, m,
3983 sizeof (struct GNUNET_MessageHeader));
3987 if (dropped == GNUNET_YES)
3990 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3991 "Message of type %u from `%4s' not delivered to any client.\n",
3992 (unsigned int) type,
3993 GNUNET_i2s (&sender->peer));
3995 GNUNET_STATISTICS_update (stats,
3996 gettext_noop ("# messages not delivered to any client"),
4003 * We received an encrypted message. Decrypt, validate and
4004 * pass on to the appropriate clients.
4006 * @param n target of the message
4007 * @param m encrypted message
4008 * @param ats performance data
4009 * @param ats_count number of entries in ats (excluding 0-termination)
4012 handle_encrypted_message (struct Neighbour *n,
4013 const struct EncryptedMessage *m,
4014 const struct GNUNET_TRANSPORT_ATS_Information *ats,
4017 size_t size = ntohs (m->header.size);
4019 struct EncryptedMessage *pt; /* plaintext */
4022 struct GNUNET_TIME_Absolute t;
4023 struct GNUNET_CRYPTO_AesInitializationVector iv;
4024 struct GNUNET_CRYPTO_AuthKey auth_key;
4027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4028 "Core service receives `%s' request from `%4s'.\n",
4029 "ENCRYPTED_MESSAGE", GNUNET_i2s (&n->peer));
4032 derive_auth_key (&auth_key,
4035 n->decrypt_key_created);
4036 GNUNET_CRYPTO_hmac (&auth_key,
4037 &m->sequence_number,
4038 size - ENCRYPTED_HEADER_SIZE, &ph);
4040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4041 "Re-Authenticated %u bytes of ciphertext (`%u'): `%s'\n",
4042 (unsigned int) size - ENCRYPTED_HEADER_SIZE,
4043 GNUNET_CRYPTO_crc32_n (&m->sequence_number,
4044 size - ENCRYPTED_HEADER_SIZE),
4048 if (0 != memcmp (&ph,
4050 sizeof (GNUNET_HashCode)))
4052 /* checksum failed */
4053 GNUNET_break_op (0);
4056 derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
4061 &m->sequence_number,
4062 &buf[ENCRYPTED_HEADER_SIZE],
4063 size - ENCRYPTED_HEADER_SIZE))
4065 pt = (struct EncryptedMessage *) buf;
4067 /* validate sequence number */
4068 snum = ntohl (pt->sequence_number);
4069 if (n->last_sequence_number_received == snum)
4071 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4072 "Received duplicate message, ignoring.\n");
4073 /* duplicate, ignore */
4074 GNUNET_STATISTICS_update (stats,
4075 gettext_noop ("# bytes dropped (duplicates)"),
4080 if ((n->last_sequence_number_received > snum) &&
4081 (n->last_sequence_number_received - snum > 32))
4083 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4084 "Received ancient out of sequence message, ignoring.\n");
4085 /* ancient out of sequence, ignore */
4086 GNUNET_STATISTICS_update (stats,
4087 gettext_noop ("# bytes dropped (out of sequence)"),
4092 if (n->last_sequence_number_received > snum)
4094 unsigned int rotbit =
4095 1 << (n->last_sequence_number_received - snum - 1);
4096 if ((n->last_packets_bitmap & rotbit) != 0)
4098 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4099 "Received duplicate message, ignoring.\n");
4100 GNUNET_STATISTICS_update (stats,
4101 gettext_noop ("# bytes dropped (duplicates)"),
4104 /* duplicate, ignore */
4107 n->last_packets_bitmap |= rotbit;
4109 if (n->last_sequence_number_received < snum)
4111 int shift = (snum - n->last_sequence_number_received);
4112 if (shift >= 8 * sizeof(n->last_packets_bitmap))
4113 n->last_packets_bitmap = 0;
4115 n->last_packets_bitmap <<= shift;
4116 n->last_sequence_number_received = snum;
4119 /* check timestamp */
4120 t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
4121 if (GNUNET_TIME_absolute_get_duration (t).rel_value > MAX_MESSAGE_AGE.rel_value)
4123 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4125 ("Message received far too old (%llu ms). Content ignored.\n"),
4126 GNUNET_TIME_absolute_get_duration (t).rel_value);
4127 GNUNET_STATISTICS_update (stats,
4128 gettext_noop ("# bytes dropped (ancient message)"),
4134 /* process decrypted message(s) */
4135 if (n->bw_out_external_limit.value__ != pt->inbound_bw_limit.value__)
4137 #if DEBUG_CORE_SET_QUOTA
4138 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4139 "Received %u b/s as new inbound limit for peer `%4s'\n",
4140 (unsigned int) ntohl (pt->inbound_bw_limit.value__),
4141 GNUNET_i2s (&n->peer));
4143 n->bw_out_external_limit = pt->inbound_bw_limit;
4144 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
4145 n->bw_out_internal_limit);
4146 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
4148 GNUNET_TRANSPORT_set_quota (transport,
4153 n->last_activity = GNUNET_TIME_absolute_get ();
4154 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
4155 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
4157 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
4160 GNUNET_STATISTICS_update (stats,
4161 gettext_noop ("# bytes of payload decrypted"),
4162 size - sizeof (struct EncryptedMessage),
4164 handle_peer_status_change (n);
4165 update_neighbour_performance (n, ats, ats_count);
4166 if (GNUNET_OK != GNUNET_SERVER_mst_receive (mst,
4168 &buf[sizeof (struct EncryptedMessage)],
4169 size - sizeof (struct EncryptedMessage),
4170 GNUNET_YES, GNUNET_NO))
4171 GNUNET_break_op (0);
4176 * Function called by the transport for each received message.
4178 * @param cls closure
4179 * @param peer (claimed) identity of the other peer
4180 * @param message the message
4181 * @param ats performance data
4182 * @param ats_count number of entries in ats (excluding 0-termination)
4185 handle_transport_receive (void *cls,
4186 const struct GNUNET_PeerIdentity *peer,
4187 const struct GNUNET_MessageHeader *message,
4188 const struct GNUNET_TRANSPORT_ATS_Information *ats,
4191 struct Neighbour *n;
4192 struct GNUNET_TIME_Absolute now;
4199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4200 "Received message of type %u from `%4s', demultiplexing.\n",
4201 (unsigned int) ntohs (message->type),
4204 if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
4209 n = find_neighbour (peer);
4210 if ( (n == NULL) || (GNUNET_NO == n->is_connected) )
4212 /* received message from peer that is not connected!? */
4216 changed = GNUNET_NO;
4217 up = (n->status == PEER_STATE_KEY_CONFIRMED);
4218 type = ntohs (message->type);
4219 size = ntohs (message->size);
4222 case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
4223 if (size != sizeof (struct SetKeyMessage))
4225 GNUNET_break_op (0);
4228 GNUNET_STATISTICS_update (stats,
4229 gettext_noop ("# session keys received"),
4233 (const struct SetKeyMessage *) message,
4236 case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
4237 if (size < sizeof (struct EncryptedMessage) +
4238 sizeof (struct GNUNET_MessageHeader))
4240 GNUNET_break_op (0);
4243 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
4244 (n->status != PEER_STATE_KEY_CONFIRMED))
4246 GNUNET_STATISTICS_update (stats,
4247 gettext_noop ("# failed to decrypt message (no session key)"),
4253 handle_encrypted_message (n,
4254 (const struct EncryptedMessage *) message,
4257 case GNUNET_MESSAGE_TYPE_CORE_PING:
4258 if (size != sizeof (struct PingMessage))
4260 GNUNET_break_op (0);
4263 GNUNET_STATISTICS_update (stats, gettext_noop ("# PING messages received"), 1, GNUNET_NO);
4264 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
4265 (n->status != PEER_STATE_KEY_CONFIRMED))
4268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4269 "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
4270 "PING", GNUNET_i2s (&n->peer));
4272 GNUNET_free_non_null (n->pending_ping);
4273 n->pending_ping = GNUNET_malloc (sizeof (struct PingMessage));
4274 memcpy (n->pending_ping, message, sizeof (struct PingMessage));
4277 handle_ping (n, (const struct PingMessage *) message,
4280 case GNUNET_MESSAGE_TYPE_CORE_PONG:
4281 if (size != sizeof (struct PongMessage))
4283 GNUNET_break_op (0);
4286 GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages received"), 1, GNUNET_NO);
4287 if ( (n->status != PEER_STATE_KEY_RECEIVED) &&
4288 (n->status != PEER_STATE_KEY_CONFIRMED) )
4291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4292 "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
4293 "PONG", GNUNET_i2s (&n->peer));
4295 GNUNET_free_non_null (n->pending_pong);
4296 n->pending_pong = GNUNET_malloc (sizeof (struct PongMessage));
4297 memcpy (n->pending_pong, message, sizeof (struct PongMessage));
4300 handle_pong (n, (const struct PongMessage *) message,
4304 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4305 _("Unsupported message of type %u received.\n"),
4306 (unsigned int) type);
4309 if (n->status == PEER_STATE_KEY_CONFIRMED)
4311 now = GNUNET_TIME_absolute_get ();
4312 n->last_activity = now;
4313 changed = GNUNET_YES;
4316 GNUNET_STATISTICS_update (stats,
4317 gettext_noop ("# established sessions"),
4320 n->time_established = now;
4322 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
4323 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
4325 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
4330 handle_peer_status_change (n);
4335 * Function that recalculates the bandwidth quota for the
4336 * given neighbour and transmits it to the transport service.
4338 * @param cls neighbour for the quota update
4342 neighbour_quota_update (void *cls,
4343 const struct GNUNET_SCHEDULER_TaskContext *tc)
4345 struct Neighbour *n = cls;
4346 struct GNUNET_BANDWIDTH_Value32NBO q_in;
4347 struct GNUNET_BANDWIDTH_Value32NBO q_out;
4348 struct GNUNET_BANDWIDTH_Value32NBO q_out_min;
4351 unsigned long long distributable;
4352 uint64_t need_per_peer;
4353 uint64_t need_per_second;
4354 unsigned int neighbour_count;
4357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4358 "Neighbour quota update calculation running for peer `%4s'\n",
4359 GNUNET_i2s (&n->peer));
4361 n->quota_update_task = GNUNET_SCHEDULER_NO_TASK;
4362 /* calculate relative preference among all neighbours;
4363 divides by a bit more to avoid division by zero AND to
4364 account for possibility of new neighbours joining any time
4365 AND to convert to double... */
4366 neighbour_count = GNUNET_CONTAINER_multihashmap_size (neighbours);
4367 if (neighbour_count == 0)
4369 if (preference_sum == 0)
4371 pref_rel = 1.0 / (double) neighbour_count;
4375 pref_rel = (double) n->current_preference / preference_sum;
4377 need_per_peer = GNUNET_BANDWIDTH_value_get_available_until (MIN_BANDWIDTH_PER_PEER,
4378 GNUNET_TIME_UNIT_SECONDS);
4379 need_per_second = need_per_peer * neighbour_count;
4381 /* calculate inbound bandwidth per peer */
4383 if (bandwidth_target_in_bps > need_per_second)
4384 distributable = bandwidth_target_in_bps - need_per_second;
4385 share = distributable * pref_rel;
4386 if (share + need_per_peer > UINT32_MAX)
4387 q_in = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
4389 q_in = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4391 /* calculate outbound bandwidth per peer */
4393 if (bandwidth_target_out_bps > need_per_second)
4394 distributable = bandwidth_target_out_bps - need_per_second;
4395 share = distributable * pref_rel;
4396 if (share + need_per_peer > UINT32_MAX)
4397 q_out = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
4399 q_out = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4400 n->bw_out_internal_limit = q_out;
4402 q_out_min = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit, n->bw_out_internal_limit);
4403 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window, n->bw_out);
4405 /* check if we want to disconnect for good due to inactivity */
4406 if ( (GNUNET_TIME_absolute_get_duration (get_neighbour_timeout (n)).rel_value > 0) &&
4407 (GNUNET_TIME_absolute_get_duration (n->time_established).rel_value > GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value) )
4410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4411 "Forcing disconnect of `%4s' due to inactivity\n",
4412 GNUNET_i2s (&n->peer));
4414 q_in = GNUNET_BANDWIDTH_value_init (0); /* force disconnect */
4416 #if DEBUG_CORE_QUOTA
4417 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4418 "Current quota for `%4s' is %u/%llu b/s in (old: %u b/s) / %u out (%u internal)\n",
4419 GNUNET_i2s (&n->peer),
4420 (unsigned int) ntohl (q_in.value__),
4421 bandwidth_target_out_bps,
4422 (unsigned int) ntohl (n->bw_in.value__),
4423 (unsigned int) ntohl (n->bw_out.value__),
4424 (unsigned int) ntohl (n->bw_out_internal_limit.value__));
4426 if ((n->bw_in.value__ != q_in.value__) || (n->bw_out.value__ != q_out_min.value__))
4428 if (n->bw_in.value__ != q_in.value__)
4430 if (n->bw_out.value__ != q_out_min.value__)
4431 n->bw_out = q_out_min;
4432 if (GNUNET_YES == n->is_connected)
4433 GNUNET_TRANSPORT_set_quota (transport,
4437 handle_peer_status_change (n);
4439 schedule_quota_update (n);
4444 * Function called by transport to notify us that
4445 * a peer connected to us (on the network level).
4447 * @param cls closure
4448 * @param peer the peer that connected
4449 * @param ats performance data
4450 * @param ats_count number of entries in ats (excluding 0-termination)
4453 handle_transport_notify_connect (void *cls,
4454 const struct GNUNET_PeerIdentity *peer,
4455 const struct GNUNET_TRANSPORT_ATS_Information *ats,
4458 struct Neighbour *n;
4460 if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
4465 n = find_neighbour (peer);
4468 if (GNUNET_YES == n->is_connected)
4470 /* duplicate connect notification!? */
4477 n = create_neighbour (peer);
4479 GNUNET_STATISTICS_update (stats,
4480 gettext_noop ("# peers connected (transport)"),
4483 n->is_connected = GNUNET_YES;
4484 update_neighbour_performance (n, ats, ats_count);
4485 GNUNET_BANDWIDTH_tracker_init (&n->available_send_window,
4488 GNUNET_BANDWIDTH_tracker_init (&n->available_recv_window,
4492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4493 "Received connection from `%4s'.\n",
4494 GNUNET_i2s (&n->peer));
4496 GNUNET_TRANSPORT_set_quota (transport,
4505 * Function called by transport telling us that a peer
4508 * @param cls closure
4509 * @param peer the peer that disconnected
4512 handle_transport_notify_disconnect (void *cls,
4513 const struct GNUNET_PeerIdentity *peer)
4515 struct DisconnectNotifyMessage cnm;
4516 struct Neighbour *n;
4517 struct ClientActiveRequest *car;
4518 struct GNUNET_TIME_Relative left;
4521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4522 "Peer `%4s' disconnected from us; received notification from transport.\n",
4525 n = find_neighbour (peer);
4531 GNUNET_break (n->is_connected == GNUNET_YES);
4532 if (n->status == PEER_STATE_KEY_CONFIRMED)
4534 cnm.header.size = htons (sizeof (struct DisconnectNotifyMessage));
4535 cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
4536 cnm.reserved = htonl (0);
4538 send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_DISCONNECT);
4539 GNUNET_STATISTICS_update (stats,
4540 gettext_noop ("# established sessions"),
4545 /* On transport disconnect transport doesn't cancel requests, so must do so here. */
4548 GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
4551 if (GNUNET_SCHEDULER_NO_TASK != n->keep_alive_task)
4553 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
4554 n->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
4556 n->is_connected = GNUNET_NO;
4557 n->status = PEER_STATE_DOWN;
4558 while (NULL != (car = n->active_client_request_head))
4560 GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
4561 n->active_client_request_tail,
4563 GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
4564 &n->peer.hashPubKey,
4569 GNUNET_STATISTICS_update (stats,
4570 gettext_noop ("# peers connected (transport)"),
4573 if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
4574 GNUNET_SCHEDULER_cancel (n->dead_clean_task);
4575 left = GNUNET_TIME_relative_subtract (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
4576 GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT);
4577 n->last_activity = GNUNET_TIME_absolute_subtract (GNUNET_TIME_absolute_get (),
4579 n->dead_clean_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT,
4580 &consider_free_task,
4586 * Wrapper around 'free_neighbour'; helper for 'cleaning_task'.
4589 free_neighbour_helper (void *cls,
4590 const GNUNET_HashCode *key,
4593 struct Neighbour *n = value;
4601 * Last task run during shutdown. Disconnects us from
4605 cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4611 "Core service shutting down.\n");
4613 GNUNET_assert (transport != NULL);
4614 GNUNET_TRANSPORT_disconnect (transport);
4616 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
4617 &free_neighbour_helper,
4619 GNUNET_CONTAINER_multihashmap_destroy (neighbours);
4621 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), 0, GNUNET_NO);
4622 GNUNET_SERVER_notification_context_destroy (notifier);
4624 while (NULL != (c = clients))
4625 handle_client_disconnect (NULL, c->client_handle);
4626 if (my_private_key != NULL)
4627 GNUNET_CRYPTO_rsa_key_free (my_private_key);
4629 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
4630 if (peerinfo != NULL)
4631 GNUNET_PEERINFO_disconnect (peerinfo);
4633 GNUNET_SERVER_mst_destroy (mst);
4638 * Initiate core service.
4640 * @param cls closure
4641 * @param server the initialized server
4642 * @param c configuration to use
4646 struct GNUNET_SERVER_Handle *server,
4647 const struct GNUNET_CONFIGURATION_Handle *c)
4649 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
4650 {&handle_client_init, NULL,
4651 GNUNET_MESSAGE_TYPE_CORE_INIT, 0},
4652 {&handle_client_iterate_peers, NULL,
4653 GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
4654 sizeof (struct GNUNET_MessageHeader)},
4655 {&handle_client_have_peer, NULL,
4656 GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED,
4657 sizeof (struct GNUNET_MessageHeader) + sizeof(struct GNUNET_PeerIdentity)},
4658 {&handle_client_request_info, NULL,
4659 GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
4660 sizeof (struct RequestInfoMessage)},
4661 {&handle_client_send_request, NULL,
4662 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
4663 sizeof (struct SendMessageRequest)},
4664 {&handle_client_send, NULL,
4665 GNUNET_MESSAGE_TYPE_CORE_SEND, 0},
4666 {&handle_client_request_connect, NULL,
4667 GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT,
4668 sizeof (struct ConnectMessage)},
4674 /* parse configuration */
4677 GNUNET_CONFIGURATION_get_value_number (c,
4680 &bandwidth_target_in_bps)) ||
4682 GNUNET_CONFIGURATION_get_value_number (c,
4685 &bandwidth_target_out_bps)) ||
4687 GNUNET_CONFIGURATION_get_value_filename (c,
4689 "HOSTKEY", &keyfile)))
4691 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4693 ("Core service is lacking key configuration settings. Exiting.\n"));
4694 GNUNET_SCHEDULER_shutdown ();
4697 peerinfo = GNUNET_PEERINFO_connect (cfg);
4698 if (NULL == peerinfo)
4700 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4701 _("Could not access PEERINFO service. Exiting.\n"));
4702 GNUNET_SCHEDULER_shutdown ();
4703 GNUNET_free (keyfile);
4706 my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
4707 GNUNET_free (keyfile);
4708 if (my_private_key == NULL)
4710 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4711 _("Core service could not access hostkey. Exiting.\n"));
4712 GNUNET_PEERINFO_disconnect (peerinfo);
4713 GNUNET_SCHEDULER_shutdown ();
4716 neighbours = GNUNET_CONTAINER_multihashmap_create (128);
4717 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
4718 GNUNET_CRYPTO_hash (&my_public_key,
4719 sizeof (my_public_key), &my_identity.hashPubKey);
4720 self.public_key = &my_public_key;
4721 self.peer = my_identity;
4722 self.last_activity = GNUNET_TIME_UNIT_FOREVER_ABS;
4723 self.status = PEER_STATE_KEY_CONFIRMED;
4724 self.is_connected = GNUNET_YES;
4725 /* setup notification */
4726 notifier = GNUNET_SERVER_notification_context_create (server,
4728 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
4729 /* setup transport connection */
4730 transport = GNUNET_TRANSPORT_connect (cfg,
4733 &handle_transport_receive,
4734 &handle_transport_notify_connect,
4735 &handle_transport_notify_disconnect);
4736 GNUNET_assert (NULL != transport);
4737 stats = GNUNET_STATISTICS_create ("core", cfg);
4739 GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded CORE_SEND requests"), 0, GNUNET_NO);
4740 GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded lower priority CORE_SEND requests"), 0, GNUNET_NO);
4742 mst = GNUNET_SERVER_mst_create (&deliver_message,
4744 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
4745 &cleaning_task, NULL);
4746 /* process client requests */
4747 GNUNET_SERVER_add_handlers (server, handlers);
4748 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4749 _("Core service of `%4s' ready.\n"), GNUNET_i2s (&my_identity));
4755 * The main function for the transport service.
4757 * @param argc number of arguments from the command line
4758 * @param argv command line arguments
4759 * @return 0 ok, 1 on error
4762 main (int argc, char *const *argv)
4764 return (GNUNET_OK ==
4765 GNUNET_SERVICE_run (argc,
4768 GNUNET_SERVICE_OPTION_NONE,
4769 &run, NULL)) ? 0 : 1;
4772 /* end of gnunet-service-core.c */