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));
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 m = n->encrypted_head;
2036 /* encrypted queue empty, try plaintext instead */
2037 process_plaintext_neighbour_queue (n);
2041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2042 "Asking transport for transmission of %u bytes to `%4s' in next %llu ms\n",
2043 (unsigned int) m->size,
2044 GNUNET_i2s (&n->peer),
2045 (unsigned long long) GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value);
2048 GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer,
2051 GNUNET_TIME_absolute_get_remaining
2053 ¬ify_encrypted_transmit_ready,
2057 /* message request too large or duplicate request */
2059 /* discard encrypted message */
2060 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
2064 process_encrypted_neighbour_queue (n);
2070 * Decrypt size bytes from in and write the result to out. Use the
2071 * key for inbound traffic of the given neighbour. This function does
2072 * NOT do any integrity-checks on the result.
2074 * @param n neighbour we are receiving from
2075 * @param iv initialization vector to use
2076 * @param in ciphertext
2077 * @param out plaintext
2078 * @param size size of in/out
2079 * @return GNUNET_OK on success
2082 do_decrypt (struct Neighbour *n,
2083 const struct GNUNET_CRYPTO_AesInitializationVector * iv,
2084 const void *in, void *out, size_t size)
2086 if (size != (uint16_t) size)
2091 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
2092 (n->status != PEER_STATE_KEY_CONFIRMED))
2094 GNUNET_break_op (0);
2095 return GNUNET_SYSERR;
2098 GNUNET_CRYPTO_aes_decrypt (in,
2105 return GNUNET_SYSERR;
2107 GNUNET_STATISTICS_update (stats,
2108 gettext_noop ("# bytes decrypted"),
2112 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2113 "Decrypted %u bytes from `%4s' using key %u, IV %u\n",
2114 (unsigned int) size,
2115 GNUNET_i2s (&n->peer),
2116 (unsigned int) n->decrypt_key.crc32,
2117 GNUNET_CRYPTO_crc32_n (iv, sizeof(*iv)));
2124 * Select messages for transmission. This heuristic uses a combination
2125 * of earliest deadline first (EDF) scheduling (with bounded horizon)
2126 * and priority-based discard (in case no feasible schedule exist) and
2127 * speculative optimization (defer any kind of transmission until
2128 * we either create a batch of significant size, 25% of max, or until
2129 * we are close to a deadline). Furthermore, when scheduling the
2130 * heuristic also packs as many messages into the batch as possible,
2131 * starting with those with the earliest deadline. Yes, this is fun.
2133 * @param n neighbour to select messages from
2134 * @param size number of bytes to select for transmission
2135 * @param retry_time set to the time when we should try again
2136 * (only valid if this function returns zero)
2137 * @return number of bytes selected, or 0 if we decided to
2138 * defer scheduling overall; in that case, retry_time is set.
2141 select_messages (struct Neighbour *n,
2142 size_t size, struct GNUNET_TIME_Relative *retry_time)
2144 struct MessageEntry *pos;
2145 struct MessageEntry *min;
2146 struct MessageEntry *last;
2147 unsigned int min_prio;
2148 struct GNUNET_TIME_Absolute t;
2149 struct GNUNET_TIME_Absolute now;
2150 struct GNUNET_TIME_Relative delta;
2152 struct GNUNET_TIME_Relative slack; /* how long could we wait before missing deadlines? */
2155 unsigned int queue_size;
2156 int discard_low_prio;
2158 GNUNET_assert (NULL != n->messages);
2159 now = GNUNET_TIME_absolute_get ();
2160 /* last entry in linked list of messages processed */
2162 /* should we remove the entry with the lowest
2163 priority from consideration for scheduling at the
2174 discard_low_prio = GNUNET_YES;
2175 while (GNUNET_YES == discard_low_prio)
2178 min_prio = UINT_MAX;
2179 discard_low_prio = GNUNET_NO;
2180 /* calculate number of bytes available for transmission at time "t" */
2181 avail = GNUNET_BANDWIDTH_tracker_get_available (&n->available_send_window);
2183 /* how many bytes have we (hypothetically) scheduled so far */
2185 /* maximum time we can wait before transmitting anything
2186 and still make all of our deadlines */
2187 slack = GNUNET_TIME_UNIT_FOREVER_REL;
2189 /* note that we use "*2" here because we want to look
2190 a bit further into the future; much more makes no
2191 sense since new message might be scheduled in the
2193 while ((pos != NULL) && (off < size * 2))
2195 if (pos->do_transmit == GNUNET_YES)
2197 /* already removed from consideration */
2201 if (discard_low_prio == GNUNET_NO)
2203 delta = GNUNET_TIME_absolute_get_difference (t, pos->deadline);
2204 if (delta.rel_value > 0)
2206 // FIXME: HUH? Check!
2208 avail += GNUNET_BANDWIDTH_value_get_available_until (n->bw_out,
2211 if (avail < pos->size)
2213 // FIXME: HUH? Check!
2214 discard_low_prio = GNUNET_YES; /* we could not schedule this one! */
2219 /* update slack, considering both its absolute deadline
2220 and relative deadlines caused by other messages
2221 with their respective load */
2222 slack = GNUNET_TIME_relative_min (slack,
2223 GNUNET_BANDWIDTH_value_get_delay_for (n->bw_out,
2225 if (pos->deadline.abs_value <= now.abs_value)
2228 slack = GNUNET_TIME_UNIT_ZERO;
2230 else if (GNUNET_YES == pos->got_slack)
2232 /* should be soon now! */
2233 slack = GNUNET_TIME_relative_min (slack,
2234 GNUNET_TIME_absolute_get_remaining (pos->slack_deadline));
2239 GNUNET_TIME_relative_min (slack,
2240 GNUNET_TIME_absolute_get_difference (now, pos->deadline));
2241 pos->got_slack = GNUNET_YES;
2242 pos->slack_deadline = GNUNET_TIME_absolute_min (pos->deadline,
2243 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_MAX_CORK_DELAY));
2248 t = GNUNET_TIME_absolute_max (pos->deadline, t); // HUH? Check!
2249 if (pos->priority <= min_prio)
2251 /* update min for discard */
2252 min_prio = pos->priority;
2257 if (discard_low_prio)
2259 GNUNET_assert (min != NULL);
2260 /* remove lowest-priority entry from consideration */
2261 min->do_transmit = GNUNET_YES; /* means: discard (for now) */
2265 /* guard against sending "tiny" messages with large headers without
2267 if ( (slack.rel_value > GNUNET_CONSTANTS_MAX_CORK_DELAY.rel_value) &&
2269 (queue_size <= MAX_PEER_QUEUE_SIZE - 2) )
2271 /* less than 25% of message would be filled with deadlines still
2272 being met if we delay by one second or more; so just wait for
2273 more data; but do not wait longer than 1s (since we don't want
2274 to delay messages for a really long time either). */
2275 *retry_time = GNUNET_CONSTANTS_MAX_CORK_DELAY;
2276 /* reset do_transmit values for next time */
2279 pos->do_transmit = GNUNET_NO;
2282 GNUNET_STATISTICS_update (stats,
2283 gettext_noop ("# transmissions delayed due to corking"),
2286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2287 "Deferring transmission for %llums due to underfull message buffer size (%u/%u)\n",
2288 (unsigned long long) retry_time->rel_value,
2290 (unsigned int) size);
2294 /* select marked messages (up to size) for transmission */
2299 if ((pos->size <= size) && (pos->do_transmit == GNUNET_NO))
2301 pos->do_transmit = GNUNET_YES; /* mark for transmission */
2305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2306 "Selecting message of size %u for transmission\n",
2307 (unsigned int) pos->size);
2313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2314 "Not selecting message of size %u for transmission at this time (maximum is %u)\n",
2315 (unsigned int) pos->size,
2318 pos->do_transmit = GNUNET_NO; /* mark for not transmitting! */
2323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2324 "Selected %llu/%llu bytes of %u/%u plaintext messages for transmission to `%4s'.\n",
2325 (unsigned long long) off, (unsigned long long) tsize,
2326 queue_size, (unsigned int) MAX_PEER_QUEUE_SIZE,
2327 GNUNET_i2s (&n->peer));
2334 * Batch multiple messages into a larger buffer.
2336 * @param n neighbour to take messages from
2337 * @param buf target buffer
2338 * @param size size of buf
2339 * @param deadline set to transmission deadline for the result
2340 * @param retry_time set to the time when we should try again
2341 * (only valid if this function returns zero)
2342 * @param priority set to the priority of the batch
2343 * @return number of bytes written to buf (can be zero)
2346 batch_message (struct Neighbour *n,
2349 struct GNUNET_TIME_Absolute *deadline,
2350 struct GNUNET_TIME_Relative *retry_time,
2351 unsigned int *priority)
2353 char ntmb[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
2354 struct NotifyTrafficMessage *ntm = (struct NotifyTrafficMessage*) ntmb;
2355 struct MessageEntry *pos;
2356 struct MessageEntry *prev;
2357 struct MessageEntry *next;
2362 *deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2363 *retry_time = GNUNET_TIME_UNIT_FOREVER_REL;
2364 if (0 == select_messages (n, size, retry_time))
2367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2368 "No messages selected, will try again in %llu ms\n",
2369 retry_time->rel_value);
2373 ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND);
2374 ntm->ats_count = htonl (0);
2375 ntm->ats.type = htonl (0);
2376 ntm->ats.value = htonl (0);
2377 ntm->peer = n->peer;
2380 while ((pos != NULL) && (size >= sizeof (struct GNUNET_MessageHeader)))
2383 if (GNUNET_YES == pos->do_transmit)
2385 GNUNET_assert (pos->size <= size);
2386 /* do notifications */
2387 /* FIXME: track if we have *any* client that wants
2388 full notifications and only do this if that is
2390 if (pos->size < GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct NotifyTrafficMessage))
2392 memcpy (&ntm[1], &pos[1], pos->size);
2393 ntm->header.size = htons (sizeof (struct NotifyTrafficMessage) +
2394 sizeof (struct GNUNET_MessageHeader));
2395 send_to_all_clients (&ntm->header,
2397 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
2401 /* message too large for 'full' notifications, we do at
2402 least the 'hdr' type */
2405 sizeof (struct GNUNET_MessageHeader));
2407 ntm->header.size = htons (sizeof (struct NotifyTrafficMessage) +
2409 send_to_all_clients (&ntm->header,
2411 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
2413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2414 "Encrypting %u bytes with message of type %u and size %u\n",
2416 (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->type),
2417 (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->size));
2419 /* copy for encrypted transmission */
2420 memcpy (&buf[ret], &pos[1], pos->size);
2423 *priority += pos->priority;
2425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2426 "Adding plaintext message of size %u with deadline %llu ms to batch\n",
2427 (unsigned int) pos->size,
2428 (unsigned long long) GNUNET_TIME_absolute_get_remaining (pos->deadline).rel_value);
2430 deadline->abs_value = GNUNET_MIN (deadline->abs_value, pos->deadline.abs_value);
2444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2445 "Deadline for message batch is %llu ms\n",
2446 GNUNET_TIME_absolute_get_remaining (*deadline).rel_value);
2453 * Remove messages with deadlines that have long expired from
2456 * @param n neighbour to inspect
2459 discard_expired_messages (struct Neighbour *n)
2461 struct MessageEntry *prev;
2462 struct MessageEntry *next;
2463 struct MessageEntry *pos;
2464 struct GNUNET_TIME_Absolute now;
2465 struct GNUNET_TIME_Relative delta;
2469 now = GNUNET_TIME_absolute_get ();
2475 delta = GNUNET_TIME_absolute_get_difference (pos->deadline, now);
2476 if (delta.rel_value > PAST_EXPIRATION_DISCARD_TIME.rel_value)
2479 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2480 "Message is %llu ms past due, discarding.\n",
2487 GNUNET_STATISTICS_update (stats,
2488 gettext_noop ("# messages discarded (expired prior to transmission)"),
2498 if (GNUNET_YES == disc)
2499 schedule_peer_messages (n);
2504 * Signature of the main function of a task.
2506 * @param cls closure
2507 * @param tc context information (why was this task triggered now)
2510 retry_plaintext_processing (void *cls,
2511 const struct GNUNET_SCHEDULER_TaskContext *tc)
2513 struct Neighbour *n = cls;
2515 n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2516 process_plaintext_neighbour_queue (n);
2521 * Send our key (and encrypted PING) to the other peer.
2523 * @param n the other peer
2525 static void send_key (struct Neighbour *n);
2528 * Task that will retry "send_key" if our previous attempt failed
2532 set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2534 struct Neighbour *n = cls;
2537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2538 "Retrying key transmission to `%4s'\n",
2539 GNUNET_i2s (&n->peer));
2541 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
2542 n->set_key_retry_frequency =
2543 GNUNET_TIME_relative_multiply (n->set_key_retry_frequency, 2);
2549 * Check if we have plaintext messages for the specified neighbour
2550 * pending, and if so, consider batching and encrypting them (and
2551 * then trigger processing of the encrypted queue if needed).
2553 * @param n neighbour to check.
2556 process_plaintext_neighbour_queue (struct Neighbour *n)
2558 char pbuf[GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE + sizeof (struct EncryptedMessage)]; /* plaintext */
2560 struct EncryptedMessage *em; /* encrypted message */
2561 struct EncryptedMessage *ph; /* plaintext header */
2562 struct MessageEntry *me;
2563 unsigned int priority;
2564 struct GNUNET_TIME_Absolute deadline;
2565 struct GNUNET_TIME_Relative retry_time;
2566 struct GNUNET_CRYPTO_AesInitializationVector iv;
2567 struct GNUNET_CRYPTO_AuthKey auth_key;
2569 if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
2571 GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
2572 n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2576 case PEER_STATE_DOWN:
2579 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2580 "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2581 GNUNET_i2s(&n->peer));
2584 case PEER_STATE_KEY_SENT:
2585 if (n->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK)
2586 n->retry_set_key_task
2587 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2588 &set_key_retry_task, n);
2590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2591 "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2592 GNUNET_i2s(&n->peer));
2595 case PEER_STATE_KEY_RECEIVED:
2596 if (n->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK)
2597 n->retry_set_key_task
2598 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2599 &set_key_retry_task, n);
2601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2602 "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2603 GNUNET_i2s(&n->peer));
2606 case PEER_STATE_KEY_CONFIRMED:
2607 /* ready to continue */
2610 discard_expired_messages (n);
2611 if (n->messages == NULL)
2614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2615 "Plaintext message queue for `%4s' is empty.\n",
2616 GNUNET_i2s(&n->peer));
2618 return; /* no pending messages */
2620 if (n->encrypted_head != NULL)
2623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2624 "Encrypted message queue for `%4s' is still full, delaying plaintext processing.\n",
2625 GNUNET_i2s(&n->peer));
2627 return; /* wait for messages already encrypted to be
2630 ph = (struct EncryptedMessage *) pbuf;
2631 deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2633 used = sizeof (struct EncryptedMessage);
2634 used += batch_message (n,
2636 GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE,
2637 &deadline, &retry_time, &priority);
2638 if (used == sizeof (struct EncryptedMessage))
2641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2642 "No messages selected for transmission to `%4s' at this time, will try again later.\n",
2643 GNUNET_i2s(&n->peer));
2645 /* no messages selected for sending, try again later... */
2646 n->retry_plaintext_task =
2647 GNUNET_SCHEDULER_add_delayed (retry_time,
2648 &retry_plaintext_processing, n);
2651 #if DEBUG_CORE_QUOTA
2652 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2653 "Sending %u b/s as new limit to peer `%4s'\n",
2654 (unsigned int) ntohl (n->bw_in.value__),
2655 GNUNET_i2s (&n->peer));
2657 ph->iv_seed = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
2658 ph->sequence_number = htonl (++n->last_sequence_number_sent);
2659 ph->inbound_bw_limit = n->bw_in;
2660 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
2662 /* setup encryption message header */
2663 me = GNUNET_malloc (sizeof (struct MessageEntry) + used);
2664 me->deadline = deadline;
2665 me->priority = priority;
2667 em = (struct EncryptedMessage *) &me[1];
2668 em->header.size = htons (used);
2669 em->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
2670 em->iv_seed = ph->iv_seed;
2671 derive_iv (&iv, &n->encrypt_key, ph->iv_seed, &n->peer);
2674 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2675 "Encrypting %u bytes of plaintext messages for `%4s' for transmission in %llums.\n",
2676 (unsigned int) used - ENCRYPTED_HEADER_SIZE,
2677 GNUNET_i2s(&n->peer),
2678 (unsigned long long) GNUNET_TIME_absolute_get_remaining (deadline).rel_value);
2680 GNUNET_assert (GNUNET_OK ==
2683 &ph->sequence_number,
2684 &em->sequence_number, used - ENCRYPTED_HEADER_SIZE));
2685 derive_auth_key (&auth_key,
2688 n->encrypt_key_created);
2689 GNUNET_CRYPTO_hmac (&auth_key,
2690 &em->sequence_number,
2691 used - ENCRYPTED_HEADER_SIZE,
2694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2695 "Authenticated %u bytes of ciphertext %u: `%s'\n",
2696 used - ENCRYPTED_HEADER_SIZE,
2697 GNUNET_CRYPTO_crc32_n (&em->sequence_number,
2698 used - ENCRYPTED_HEADER_SIZE),
2699 GNUNET_h2s (&em->hmac));
2701 /* append to transmission list */
2702 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
2706 process_encrypted_neighbour_queue (n);
2707 schedule_peer_messages (n);
2712 * Function that recalculates the bandwidth quota for the
2713 * given neighbour and transmits it to the transport service.
2715 * @param cls neighbour for the quota update
2719 neighbour_quota_update (void *cls,
2720 const struct GNUNET_SCHEDULER_TaskContext *tc);
2724 * Schedule the task that will recalculate the bandwidth
2725 * quota for this peer (and possibly force a disconnect of
2726 * idle peers by calculating a bandwidth of zero).
2729 schedule_quota_update (struct Neighbour *n)
2731 GNUNET_assert (n->quota_update_task ==
2732 GNUNET_SCHEDULER_NO_TASK);
2733 n->quota_update_task
2734 = GNUNET_SCHEDULER_add_delayed (QUOTA_UPDATE_FREQUENCY,
2735 &neighbour_quota_update,
2741 * Initialize a new 'struct Neighbour'.
2743 * @param pid ID of the new neighbour
2744 * @return handle for the new neighbour
2746 static struct Neighbour *
2747 create_neighbour (const struct GNUNET_PeerIdentity *pid)
2749 struct Neighbour *n;
2750 struct GNUNET_TIME_Absolute now;
2753 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2754 "Creating neighbour entry for peer `%4s'\n",
2757 n = GNUNET_malloc (sizeof (struct Neighbour));
2759 GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
2760 now = GNUNET_TIME_absolute_get ();
2761 n->encrypt_key_created = now;
2762 n->last_activity = now;
2763 n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
2764 n->bw_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2765 n->bw_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2766 n->bw_out_internal_limit = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
2767 n->bw_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2768 n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
2770 GNUNET_assert (GNUNET_OK ==
2771 GNUNET_CONTAINER_multihashmap_put (neighbours,
2772 &n->peer.hashPubKey,
2774 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2775 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
2776 GNUNET_CONTAINER_multihashmap_size (neighbours), GNUNET_NO);
2777 neighbour_quota_update (n, NULL);
2778 consider_free_neighbour (n);
2784 * Handle CORE_SEND request.
2787 * @param client the client issuing the request
2788 * @param message the "struct SendMessage"
2791 handle_client_send (void *cls,
2792 struct GNUNET_SERVER_Client *client,
2793 const struct GNUNET_MessageHeader *message)
2795 const struct SendMessage *sm;
2796 struct Neighbour *n;
2797 struct MessageEntry *prev;
2798 struct MessageEntry *pos;
2799 struct MessageEntry *e;
2800 struct MessageEntry *min_prio_entry;
2801 struct MessageEntry *min_prio_prev;
2802 unsigned int min_prio;
2803 unsigned int queue_size;
2806 msize = ntohs (message->size);
2808 sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader))
2810 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "about to assert fail, msize is %d, should be at least %d\n", msize, sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader));
2813 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2816 sm = (const struct SendMessage *) message;
2817 msize -= sizeof (struct SendMessage);
2818 if (0 == memcmp (&sm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2821 GNUNET_SERVER_mst_receive (mst,
2823 (const char*) &sm[1],
2828 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2831 n = find_neighbour (&sm->peer);
2833 n = create_neighbour (&sm->peer);
2835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2836 "Core received `%s' request, queueing %u bytes of plaintext data for transmission to `%4s'.\n",
2838 (unsigned int) msize,
2839 GNUNET_i2s (&sm->peer));
2841 discard_expired_messages (n);
2842 /* bound queue size */
2843 /* NOTE: this entire block to bound the queue size should be
2844 obsolete with the new client-request code and the
2845 'schedule_peer_messages' mechanism; we still have this code in
2846 here for now as a sanity check for the new mechanmism;
2847 ultimately, we should probably simply reject SEND messages that
2848 are not 'approved' (or provide a new core API for very unreliable
2849 delivery that always sends with priority 0). Food for thought. */
2850 min_prio = UINT32_MAX;
2851 min_prio_entry = NULL;
2852 min_prio_prev = NULL;
2858 if (pos->priority <= min_prio)
2860 min_prio_entry = pos;
2861 min_prio_prev = prev;
2862 min_prio = pos->priority;
2868 if (queue_size >= MAX_PEER_QUEUE_SIZE)
2871 if (ntohl(sm->priority) <= min_prio)
2873 /* discard new entry; this should no longer happen! */
2876 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2877 "Queue full (%u/%u), discarding new request (%u bytes of type %u)\n",
2879 (unsigned int) MAX_PEER_QUEUE_SIZE,
2880 (unsigned int) msize,
2881 (unsigned int) ntohs (message->type));
2883 GNUNET_STATISTICS_update (stats,
2884 gettext_noop ("# discarded CORE_SEND requests"),
2888 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2891 GNUNET_assert (min_prio_entry != NULL);
2892 /* discard "min_prio_entry" */
2894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2895 "Queue full, discarding existing older request\n");
2897 GNUNET_STATISTICS_update (stats, gettext_noop ("# discarded lower priority CORE_SEND requests"), 1, GNUNET_NO);
2898 if (min_prio_prev == NULL)
2899 n->messages = min_prio_entry->next;
2901 min_prio_prev->next = min_prio_entry->next;
2902 GNUNET_free (min_prio_entry);
2906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2907 "Adding transmission request for `%4s' of size %u to queue\n",
2908 GNUNET_i2s (&sm->peer),
2909 (unsigned int) msize);
2911 GNUNET_break (0 == ntohl (sm->reserved));
2912 e = GNUNET_malloc (sizeof (struct MessageEntry) + msize);
2913 e->deadline = GNUNET_TIME_absolute_ntoh (sm->deadline);
2914 e->priority = ntohl (sm->priority);
2916 if (GNUNET_YES != (int) ntohl (sm->cork))
2917 e->got_slack = GNUNET_YES;
2918 memcpy (&e[1], &sm[1], msize);
2920 /* insert, keep list sorted by deadline */
2923 while ((pos != NULL) && (pos->deadline.abs_value < e->deadline.abs_value))
2934 /* consider scheduling now */
2935 process_plaintext_neighbour_queue (n);
2937 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2942 * Handle CORE_REQUEST_CONNECT request.
2945 * @param client the client issuing the request
2946 * @param message the "struct ConnectMessage"
2949 handle_client_request_connect (void *cls,
2950 struct GNUNET_SERVER_Client *client,
2951 const struct GNUNET_MessageHeader *message)
2953 const struct ConnectMessage *cm = (const struct ConnectMessage*) message;
2954 struct Neighbour *n;
2956 if (0 == memcmp (&cm->peer,
2958 sizeof (struct GNUNET_PeerIdentity)))
2960 /* In this case a client has asked us to connect to ourselves, not really an error! */
2961 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2964 GNUNET_break (ntohl (cm->reserved) == 0);
2966 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2967 "Core received `%s' request for `%4s', will try to establish connection\n",
2969 GNUNET_i2s (&cm->peer));
2971 GNUNET_STATISTICS_update (stats,
2972 gettext_noop ("# connection requests received"),
2975 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2976 n = find_neighbour (&cm->peer);
2978 (GNUNET_YES != n->is_connected) )
2980 GNUNET_TRANSPORT_try_connect (transport,
2985 GNUNET_STATISTICS_update (stats,
2986 gettext_noop ("# connection requests ignored (already connected)"),
2994 * PEERINFO is giving us a HELLO for a peer. Add the public key to
2995 * the neighbour's struct and retry send_key. Or, if we did not get a
2996 * HELLO, just do nothing.
2998 * @param cls the 'struct Neighbour' to retry sending the key for
2999 * @param peer the peer for which this is the HELLO
3000 * @param hello HELLO message of that peer
3001 * @param err_msg NULL if successful, otherwise contains error message
3004 process_hello_retry_send_key (void *cls,
3005 const struct GNUNET_PeerIdentity *peer,
3006 const struct GNUNET_HELLO_Message *hello,
3007 const char *err_msg)
3009 struct Neighbour *n = cls;
3011 if (err_msg != NULL)
3013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3014 _("Error in communication with PEERINFO service\n"));
3021 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3022 "Entered `%s' and `%s' is NULL!\n",
3023 "process_hello_retry_send_key",
3027 if (n->public_key != NULL)
3029 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3031 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3032 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3034 GNUNET_STATISTICS_update (stats,
3035 gettext_noop ("# SET_KEY messages deferred (need public key)"),
3043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3044 "Failed to obtain public key for peer `%4s', delaying processing of SET_KEY\n",
3045 GNUNET_i2s (&n->peer));
3047 GNUNET_STATISTICS_update (stats,
3048 gettext_noop ("# Delayed connecting due to lack of public key"),
3051 if (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task)
3052 n->retry_set_key_task
3053 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
3054 &set_key_retry_task, n);
3060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3061 "Entered `%s' for peer `%4s'\n",
3062 "process_hello_retry_send_key",
3065 if (n->public_key != NULL)
3067 /* already have public key, why are we here? */
3073 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3074 "Received new `%s' message for `%4s', initiating key exchange.\n",
3079 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3080 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
3082 GNUNET_STATISTICS_update (stats,
3083 gettext_noop ("# Error extracting public key from HELLO"),
3086 GNUNET_free (n->public_key);
3087 n->public_key = NULL;
3089 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3090 "GNUNET_HELLO_get_key returned awfully\n");
3098 * Send our key (and encrypted PING) to the other peer.
3100 * @param n the other peer
3103 send_key (struct Neighbour *n)
3105 struct MessageEntry *pos;
3106 struct SetKeyMessage *sm;
3107 struct MessageEntry *me;
3108 struct PingMessage pp;
3109 struct PingMessage *pm;
3110 struct GNUNET_CRYPTO_AesInitializationVector iv;
3112 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3114 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3115 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3117 if (n->pitr != NULL)
3120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3121 "Key exchange in progress with `%4s'.\n",
3122 GNUNET_i2s (&n->peer));
3124 return; /* already in progress */
3126 if (GNUNET_YES != n->is_connected)
3128 GNUNET_STATISTICS_update (stats,
3129 gettext_noop ("# Asking transport to connect (for SET_KEY)"),
3132 GNUNET_TRANSPORT_try_connect (transport,
3137 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3138 "Asked to perform key exchange with `%4s'.\n",
3139 GNUNET_i2s (&n->peer));
3141 if (n->public_key == NULL)
3143 /* lookup n's public key, then try again */
3145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3146 "Lacking public key for `%4s', trying to obtain one (send_key).\n",
3147 GNUNET_i2s (&n->peer));
3149 GNUNET_assert (n->pitr == NULL);
3150 n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
3152 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20),
3153 &process_hello_retry_send_key, n);
3156 pos = n->encrypted_head;
3159 if (GNUNET_YES == pos->is_setkey)
3161 if (pos->sender_status == n->status)
3164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3165 "`%s' message for `%4s' queued already\n",
3167 GNUNET_i2s (&n->peer));
3169 goto trigger_processing;
3171 GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
3176 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3177 "Removing queued `%s' message for `%4s', will create a new one\n",
3179 GNUNET_i2s (&n->peer));
3189 case PEER_STATE_DOWN:
3190 n->status = PEER_STATE_KEY_SENT;
3192 case PEER_STATE_KEY_SENT:
3194 case PEER_STATE_KEY_RECEIVED:
3196 case PEER_STATE_KEY_CONFIRMED:
3204 /* first, set key message */
3205 me = GNUNET_malloc (sizeof (struct MessageEntry) +
3206 sizeof (struct SetKeyMessage) +
3207 sizeof (struct PingMessage));
3208 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_SET_KEY_DELAY);
3209 me->priority = SET_KEY_PRIORITY;
3210 me->size = sizeof (struct SetKeyMessage) + sizeof (struct PingMessage);
3211 me->is_setkey = GNUNET_YES;
3212 me->got_slack = GNUNET_YES; /* do not defer this one! */
3213 me->sender_status = n->status;
3214 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
3218 sm = (struct SetKeyMessage *) &me[1];
3219 sm->header.size = htons (sizeof (struct SetKeyMessage));
3220 sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SET_KEY);
3221 sm->sender_status = htonl ((int32_t) ((n->status == PEER_STATE_DOWN) ?
3222 PEER_STATE_KEY_SENT : n->status));
3224 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3225 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3226 sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
3227 sizeof (struct GNUNET_PeerIdentity));
3228 sm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_KEY);
3229 sm->creation_time = GNUNET_TIME_absolute_hton (n->encrypt_key_created);
3230 sm->target = n->peer;
3231 GNUNET_assert (GNUNET_OK ==
3232 GNUNET_CRYPTO_rsa_encrypt (&n->encrypt_key,
3234 GNUNET_CRYPTO_AesSessionKey),
3236 &sm->encrypted_key));
3237 GNUNET_assert (GNUNET_OK ==
3238 GNUNET_CRYPTO_rsa_sign (my_private_key, &sm->purpose,
3240 pm = (struct PingMessage *) &sm[1];
3241 pm->header.size = htons (sizeof (struct PingMessage));
3242 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
3243 pm->iv_seed = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
3244 derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
3245 pp.challenge = n->ping_challenge;
3246 pp.target = n->peer;
3248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3249 "Encrypting `%s' and `%s' messages with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
3251 (unsigned int) n->ping_challenge,
3252 GNUNET_i2s (&n->peer),
3253 (unsigned int) n->encrypt_key.crc32,
3254 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3261 sizeof (struct PingMessage) -
3262 ((void *) &pm->target - (void *) pm));
3263 GNUNET_STATISTICS_update (stats,
3264 gettext_noop ("# SET_KEY and PING messages created"),
3268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3269 "Have %llu ms left for `%s' transmission.\n",
3270 (unsigned long long) GNUNET_TIME_absolute_get_remaining (me->deadline).rel_value,
3274 /* trigger queue processing */
3275 process_encrypted_neighbour_queue (n);
3276 if ( (n->status != PEER_STATE_KEY_CONFIRMED) &&
3277 (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task) )
3278 n->retry_set_key_task
3279 = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
3280 &set_key_retry_task, n);
3285 * We received a SET_KEY message. Validate and update
3286 * our key material and status.
3288 * @param n the neighbour from which we received message m
3289 * @param m the set key message we received
3290 * @param ats performance data
3291 * @param ats_count number of entries in ats (excluding 0-termination)
3294 handle_set_key (struct Neighbour *n,
3295 const struct SetKeyMessage *m,
3296 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3297 uint32_t ats_count);
3302 * PEERINFO is giving us a HELLO for a peer. Add the public key to
3303 * the neighbour's struct and retry handling the set_key message. Or,
3304 * if we did not get a HELLO, just free the set key message.
3306 * @param cls pointer to the set key message
3307 * @param peer the peer for which this is the HELLO
3308 * @param hello HELLO message of that peer
3309 * @param err_msg NULL if successful, otherwise contains error message
3312 process_hello_retry_handle_set_key (void *cls,
3313 const struct GNUNET_PeerIdentity *peer,
3314 const struct GNUNET_HELLO_Message *hello,
3315 const char *err_msg)
3317 struct Neighbour *n = cls;
3318 struct SetKeyMessage *sm = n->skm;
3320 if (err_msg != NULL)
3322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3323 _("Error in communication with PEERINFO service\n"));
3331 if (n->public_key != NULL)
3334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3335 "Received `%s' for `%4s', continuing processing of `%s' message.\n",
3337 GNUNET_i2s (&n->peer),
3340 handle_set_key (n, sm, NULL, 0);
3344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3345 _("Ignoring `%s' message due to lack of public key for peer `%4s' (failed to obtain one).\n"),
3347 GNUNET_i2s (&n->peer));
3352 if (n->public_key != NULL)
3353 return; /* multiple HELLOs match!? */
3355 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3356 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
3358 GNUNET_break_op (0);
3359 GNUNET_free (n->public_key);
3360 n->public_key = NULL;
3366 * Merge the given performance data with the data we currently
3367 * track for the given neighbour.
3369 * @param n neighbour
3370 * @param ats new performance data
3371 * @param ats_count number of records in ats
3374 update_neighbour_performance (struct Neighbour *n,
3375 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3383 for (i = 0; i < ats_count; i++)
3385 for (j=0;j < n->ats_count; j++)
3387 if (n->ats[j].type == ats[i].type)
3389 n->ats[j].value = ats[i].value;
3393 if (j == n->ats_count)
3395 GNUNET_array_append (n->ats,
3404 * We received a PING message. Validate and transmit
3407 * @param n sender of the PING
3408 * @param m the encrypted PING message itself
3409 * @param ats performance data
3410 * @param ats_count number of entries in ats (excluding 0-termination)
3413 handle_ping (struct Neighbour *n,
3414 const struct PingMessage *m,
3415 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3418 struct PingMessage t;
3419 struct PongMessage tx;
3420 struct PongMessage *tp;
3421 struct MessageEntry *me;
3422 struct GNUNET_CRYPTO_AesInitializationVector iv;
3425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3426 "Core service receives `%s' request from `%4s'.\n",
3427 "PING", GNUNET_i2s (&n->peer));
3429 derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
3435 sizeof (struct PingMessage) -
3436 ((void *) &m->target - (void *) m)))
3439 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3440 "Decrypted `%s' to `%4s' with challenge %u decrypted using key %u, IV %u (salt %u)\n",
3442 GNUNET_i2s (&t.target),
3443 (unsigned int) t.challenge,
3444 (unsigned int) n->decrypt_key.crc32,
3445 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3448 GNUNET_STATISTICS_update (stats,
3449 gettext_noop ("# PING messages decrypted"),
3452 if (0 != memcmp (&t.target,
3453 &my_identity, sizeof (struct GNUNET_PeerIdentity)))
3458 GNUNET_snprintf(sender, sizeof (sender), "%8s", GNUNET_i2s (&n->peer));
3459 GNUNET_snprintf(peer, sizeof (peer), "%8s", GNUNET_i2s (&t.target));
3460 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3461 _("Received PING from `%s' for different identity: I am `%s', PONG identity: `%s'\n"),
3463 GNUNET_i2s (&my_identity),
3465 GNUNET_break_op (0);
3468 update_neighbour_performance (n, ats, ats_count);
3469 me = GNUNET_malloc (sizeof (struct MessageEntry) +
3470 sizeof (struct PongMessage));
3471 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
3475 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PONG_DELAY);
3476 me->priority = PONG_PRIORITY;
3477 me->size = sizeof (struct PongMessage);
3478 tx.inbound_bw_limit = n->bw_in;
3479 tx.challenge = t.challenge;
3480 tx.target = t.target;
3481 tp = (struct PongMessage *) &me[1];
3482 tp->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG);
3483 tp->header.size = htons (sizeof (struct PongMessage));
3484 tp->iv_seed = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
3485 derive_pong_iv (&iv, &n->encrypt_key, tp->iv_seed, t.challenge, &n->peer);
3490 sizeof (struct PongMessage) -
3491 ((void *) &tp->challenge - (void *) tp));
3492 GNUNET_STATISTICS_update (stats,
3493 gettext_noop ("# PONG messages created"),
3497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3498 "Encrypting `%s' with challenge %u using key %u, IV %u (salt %u)\n",
3500 (unsigned int) t.challenge,
3501 (unsigned int) n->encrypt_key.crc32,
3502 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3505 /* trigger queue processing */
3506 process_encrypted_neighbour_queue (n);
3511 * We received a PONG message. Validate and update our status.
3513 * @param n sender of the PONG
3514 * @param m the encrypted PONG message itself
3515 * @param ats performance data
3516 * @param ats_count number of entries in ats (excluding 0-termination)
3519 handle_pong (struct Neighbour *n,
3520 const struct PongMessage *m,
3521 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3524 struct PongMessage t;
3525 struct ConnectNotifyMessage *cnm;
3526 struct GNUNET_CRYPTO_AesInitializationVector iv;
3527 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
3528 struct GNUNET_TRANSPORT_ATS_Information *mats;
3532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3533 "Core service receives `%s' response from `%4s'.\n",
3534 "PONG", GNUNET_i2s (&n->peer));
3536 /* mark as garbage, just to be sure */
3537 memset (&t, 255, sizeof (t));
3538 derive_pong_iv (&iv, &n->decrypt_key, m->iv_seed, n->ping_challenge,
3545 sizeof (struct PongMessage) -
3546 ((void *) &m->challenge - (void *) m)))
3548 GNUNET_break_op (0);
3551 GNUNET_STATISTICS_update (stats,
3552 gettext_noop ("# PONG messages decrypted"),
3556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3557 "Decrypted `%s' from `%4s' with challenge %u using key %u, IV %u (salt %u)\n",
3559 GNUNET_i2s (&t.target),
3560 (unsigned int) t.challenge,
3561 (unsigned int) n->decrypt_key.crc32,
3562 GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3565 if ((0 != memcmp (&t.target,
3567 sizeof (struct GNUNET_PeerIdentity))) ||
3568 (n->ping_challenge != t.challenge))
3570 /* PONG malformed */
3572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3573 "Received malformed `%s' wanted sender `%4s' with challenge %u\n",
3575 GNUNET_i2s (&n->peer),
3576 (unsigned int) n->ping_challenge);
3577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3578 "Received malformed `%s' received from `%4s' with challenge %u\n",
3579 "PONG", GNUNET_i2s (&t.target),
3580 (unsigned int) t.challenge);
3582 GNUNET_break_op (n->ping_challenge != t.challenge);
3587 case PEER_STATE_DOWN:
3588 GNUNET_break (0); /* should be impossible */
3590 case PEER_STATE_KEY_SENT:
3591 GNUNET_break (0); /* should be impossible, how did we decrypt? */
3593 case PEER_STATE_KEY_RECEIVED:
3594 GNUNET_STATISTICS_update (stats,
3595 gettext_noop ("# Session keys confirmed via PONG"),
3598 n->status = PEER_STATE_KEY_CONFIRMED;
3599 if (n->bw_out_external_limit.value__ != t.inbound_bw_limit.value__)
3601 n->bw_out_external_limit = t.inbound_bw_limit;
3602 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
3603 n->bw_out_internal_limit);
3604 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
3606 GNUNET_TRANSPORT_set_quota (transport,
3612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3613 "Confirmed key via `%s' message for peer `%4s'\n",
3614 "PONG", GNUNET_i2s (&n->peer));
3616 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3618 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3619 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3621 update_neighbour_performance (n, ats, ats_count);
3622 size = sizeof (struct ConnectNotifyMessage) +
3623 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3624 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
3627 /* recovery strategy: throw away performance data */
3628 GNUNET_array_grow (n->ats,
3631 size = sizeof (struct PeerStatusNotifyMessage) +
3632 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3634 cnm = (struct ConnectNotifyMessage*) buf;
3635 cnm->header.size = htons (size);
3636 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
3637 cnm->ats_count = htonl (n->ats_count);
3638 cnm->peer = n->peer;
3642 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
3643 mats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
3644 mats[n->ats_count].value = htonl (0);
3645 send_to_all_clients (&cnm->header,
3647 GNUNET_CORE_OPTION_SEND_CONNECT);
3648 process_encrypted_neighbour_queue (n);
3650 case PEER_STATE_KEY_CONFIRMED:
3651 n->last_activity = GNUNET_TIME_absolute_get ();
3652 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
3653 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
3655 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
3658 handle_peer_status_change (n);
3668 * We received a SET_KEY message. Validate and update
3669 * our key material and status.
3671 * @param n the neighbour from which we received message m
3672 * @param m the set key message we received
3673 * @param ats performance data
3674 * @param ats_count number of entries in ats (excluding 0-termination)
3677 handle_set_key (struct Neighbour *n,
3678 const struct SetKeyMessage *m,
3679 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3682 struct SetKeyMessage *m_cpy;
3683 struct GNUNET_TIME_Absolute t;
3684 struct GNUNET_CRYPTO_AesSessionKey k;
3685 struct PingMessage *ping;
3686 struct PongMessage *pong;
3687 enum PeerStateMachine sender_status;
3690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3691 "Core service receives `%s' request from `%4s'.\n",
3692 "SET_KEY", GNUNET_i2s (&n->peer));
3694 if (n->public_key == NULL)
3696 if (n->pitr != NULL)
3699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3700 "Ignoring `%s' message due to lack of public key for peer (still trying to obtain one).\n",
3706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3707 "Lacking public key for peer, trying to obtain one (handle_set_key).\n");
3709 m_cpy = GNUNET_malloc (sizeof (struct SetKeyMessage));
3710 memcpy (m_cpy, m, sizeof (struct SetKeyMessage));
3711 /* lookup n's public key, then try again */
3712 GNUNET_assert (n->skm == NULL);
3714 n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
3716 GNUNET_TIME_UNIT_MINUTES,
3717 &process_hello_retry_handle_set_key, n);
3718 GNUNET_STATISTICS_update (stats,
3719 gettext_noop ("# SET_KEY messages deferred (need public key)"),
3724 if (0 != memcmp (&m->target,
3726 sizeof (struct GNUNET_PeerIdentity)))
3728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3729 _("Received `%s' message that was for `%s', not for me. Ignoring.\n"),
3731 GNUNET_i2s (&m->target));
3734 if ((ntohl (m->purpose.size) !=
3735 sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3736 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3737 sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
3738 sizeof (struct GNUNET_PeerIdentity)) ||
3740 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_KEY,
3741 &m->purpose, &m->signature, n->public_key)))
3743 /* invalid signature */
3744 GNUNET_break_op (0);
3747 t = GNUNET_TIME_absolute_ntoh (m->creation_time);
3748 if (((n->status == PEER_STATE_KEY_RECEIVED) ||
3749 (n->status == PEER_STATE_KEY_CONFIRMED)) &&
3750 (t.abs_value < n->decrypt_key_created.abs_value))
3752 /* this could rarely happen due to massive re-ordering of
3753 messages on the network level, but is most likely either
3754 a bug or some adversary messing with us. Report. */
3755 GNUNET_break_op (0);
3759 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3760 "Decrypting key material.\n");
3762 if ((GNUNET_CRYPTO_rsa_decrypt (my_private_key,
3765 sizeof (struct GNUNET_CRYPTO_AesSessionKey))
3766 != sizeof (struct GNUNET_CRYPTO_AesSessionKey)) ||
3767 (GNUNET_OK != GNUNET_CRYPTO_aes_check_session_key (&k)))
3769 /* failed to decrypt !? */
3770 GNUNET_break_op (0);
3773 GNUNET_STATISTICS_update (stats,
3774 gettext_noop ("# SET_KEY messages decrypted"),
3778 if (n->decrypt_key_created.abs_value != t.abs_value)
3780 /* fresh key, reset sequence numbers */
3781 n->last_sequence_number_received = 0;
3782 n->last_packets_bitmap = 0;
3783 n->decrypt_key_created = t;
3785 update_neighbour_performance (n, ats, ats_count);
3786 sender_status = (enum PeerStateMachine) ntohl (m->sender_status);
3789 case PEER_STATE_DOWN:
3790 n->status = PEER_STATE_KEY_RECEIVED;
3792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3793 "Responding to `%s' with my own key.\n", "SET_KEY");
3797 case PEER_STATE_KEY_SENT:
3798 case PEER_STATE_KEY_RECEIVED:
3799 n->status = PEER_STATE_KEY_RECEIVED;
3800 if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
3801 (sender_status != PEER_STATE_KEY_CONFIRMED))
3804 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3805 "Responding to `%s' with my own key (other peer has status %u).\n",
3807 (unsigned int) sender_status);
3812 case PEER_STATE_KEY_CONFIRMED:
3813 if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
3814 (sender_status != PEER_STATE_KEY_CONFIRMED))
3817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3818 "Responding to `%s' with my own key (other peer has status %u), I was already fully up.\n",
3820 (unsigned int) sender_status);
3829 if (n->pending_ping != NULL)
3831 ping = n->pending_ping;
3832 n->pending_ping = NULL;
3833 handle_ping (n, ping, NULL, 0);
3836 if (n->pending_pong != NULL)
3838 pong = n->pending_pong;
3839 n->pending_pong = NULL;
3840 handle_pong (n, pong, NULL, 0);
3847 * Send a P2P message to a client.
3849 * @param sender who sent us the message?
3850 * @param client who should we give the message to?
3851 * @param m contains the message to transmit
3852 * @param msize number of bytes in buf to transmit
3855 send_p2p_message_to_client (struct Neighbour *sender,
3856 struct Client *client,
3857 const void *m, size_t msize)
3859 size_t size = msize + sizeof (struct NotifyTrafficMessage) +
3860 (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3862 struct NotifyTrafficMessage *ntm;
3863 struct GNUNET_TRANSPORT_ATS_Information *ats;
3865 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
3868 /* recovery strategy: throw performance data away... */
3869 GNUNET_array_grow (sender->ats,
3872 size = msize + sizeof (struct NotifyTrafficMessage) +
3873 (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3876 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3877 "Core service passes message from `%4s' of type %u to client.\n",
3878 GNUNET_i2s(&sender->peer),
3879 (unsigned int) ntohs (((const struct GNUNET_MessageHeader *) m)->type));
3881 ntm = (struct NotifyTrafficMessage *) buf;
3882 ntm->header.size = htons (size);
3883 ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
3884 ntm->ats_count = htonl (sender->ats_count);
3885 ntm->peer = sender->peer;
3889 sizeof (struct GNUNET_TRANSPORT_ATS_Information) * sender->ats_count);
3890 ats[sender->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
3891 ats[sender->ats_count].value = htonl (0);
3892 memcpy (&ats[sender->ats_count+1],
3895 send_to_client (client, &ntm->header, GNUNET_YES);
3900 * Deliver P2P message to interested clients.
3902 * @param cls always NULL
3903 * @param client who sent us the message (struct Neighbour)
3904 * @param m the message
3907 deliver_message (void *cls,
3909 const struct GNUNET_MessageHeader *m)
3911 struct Neighbour *sender = client;
3912 size_t msize = ntohs (m->size);
3914 struct Client *cpos;
3920 type = ntohs (m->type);
3922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3923 "Received encapsulated message of type %u and size %u from `%4s'\n",
3924 (unsigned int) type,
3926 GNUNET_i2s (&sender->peer));
3928 GNUNET_snprintf (buf,
3930 gettext_noop ("# bytes of messages of type %u received"),
3931 (unsigned int) type);
3932 GNUNET_STATISTICS_update (stats,
3936 dropped = GNUNET_YES;
3938 while (cpos != NULL)
3940 deliver_full = GNUNET_NO;
3941 if (0 != (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))
3942 deliver_full = GNUNET_YES;
3945 for (tpos = 0; tpos < cpos->tcnt; tpos++)
3947 if (type != cpos->types[tpos])
3949 deliver_full = GNUNET_YES;
3953 if (GNUNET_YES == deliver_full)
3955 send_p2p_message_to_client (sender, cpos, m, msize);
3956 dropped = GNUNET_NO;
3958 else if (cpos->options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)
3960 send_p2p_message_to_client (sender, cpos, m,
3961 sizeof (struct GNUNET_MessageHeader));
3965 if (dropped == GNUNET_YES)
3968 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3969 "Message of type %u from `%4s' not delivered to any client.\n",
3970 (unsigned int) type,
3971 GNUNET_i2s (&sender->peer));
3973 GNUNET_STATISTICS_update (stats,
3974 gettext_noop ("# messages not delivered to any client"),
3981 * We received an encrypted message. Decrypt, validate and
3982 * pass on to the appropriate clients.
3984 * @param n target of the message
3985 * @param m encrypted message
3986 * @param ats performance data
3987 * @param ats_count number of entries in ats (excluding 0-termination)
3990 handle_encrypted_message (struct Neighbour *n,
3991 const struct EncryptedMessage *m,
3992 const struct GNUNET_TRANSPORT_ATS_Information *ats,
3995 size_t size = ntohs (m->header.size);
3997 struct EncryptedMessage *pt; /* plaintext */
4000 struct GNUNET_TIME_Absolute t;
4001 struct GNUNET_CRYPTO_AesInitializationVector iv;
4002 struct GNUNET_CRYPTO_AuthKey auth_key;
4005 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4006 "Core service receives `%s' request from `%4s'.\n",
4007 "ENCRYPTED_MESSAGE", GNUNET_i2s (&n->peer));
4010 derive_auth_key (&auth_key,
4013 n->decrypt_key_created);
4014 GNUNET_CRYPTO_hmac (&auth_key,
4015 &m->sequence_number,
4016 size - ENCRYPTED_HEADER_SIZE, &ph);
4018 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4019 "Re-Authenticated %u bytes of ciphertext (`%u'): `%s'\n",
4020 (unsigned int) size - ENCRYPTED_HEADER_SIZE,
4021 GNUNET_CRYPTO_crc32_n (&m->sequence_number,
4022 size - ENCRYPTED_HEADER_SIZE),
4026 if (0 != memcmp (&ph,
4028 sizeof (GNUNET_HashCode)))
4030 /* checksum failed */
4031 GNUNET_break_op (0);
4034 derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
4039 &m->sequence_number,
4040 &buf[ENCRYPTED_HEADER_SIZE],
4041 size - ENCRYPTED_HEADER_SIZE))
4043 pt = (struct EncryptedMessage *) buf;
4045 /* validate sequence number */
4046 snum = ntohl (pt->sequence_number);
4047 if (n->last_sequence_number_received == snum)
4049 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4050 "Received duplicate message, ignoring.\n");
4051 /* duplicate, ignore */
4052 GNUNET_STATISTICS_set (stats,
4053 gettext_noop ("# bytes dropped (duplicates)"),
4058 if ((n->last_sequence_number_received > snum) &&
4059 (n->last_sequence_number_received - snum > 32))
4061 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4062 "Received ancient out of sequence message, ignoring.\n");
4063 /* ancient out of sequence, ignore */
4064 GNUNET_STATISTICS_set (stats,
4065 gettext_noop ("# bytes dropped (out of sequence)"),
4070 if (n->last_sequence_number_received > snum)
4072 unsigned int rotbit =
4073 1 << (n->last_sequence_number_received - snum - 1);
4074 if ((n->last_packets_bitmap & rotbit) != 0)
4076 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4077 "Received duplicate message, ignoring.\n");
4078 GNUNET_STATISTICS_set (stats,
4079 gettext_noop ("# bytes dropped (duplicates)"),
4082 /* duplicate, ignore */
4085 n->last_packets_bitmap |= rotbit;
4087 if (n->last_sequence_number_received < snum)
4089 int shift = (snum - n->last_sequence_number_received);
4090 if (shift >= 8 * sizeof(n->last_packets_bitmap))
4091 n->last_packets_bitmap = 0;
4093 n->last_packets_bitmap <<= shift;
4094 n->last_sequence_number_received = snum;
4097 /* check timestamp */
4098 t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
4099 if (GNUNET_TIME_absolute_get_duration (t).rel_value > MAX_MESSAGE_AGE.rel_value)
4101 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4103 ("Message received far too old (%llu ms). Content ignored.\n"),
4104 GNUNET_TIME_absolute_get_duration (t).rel_value);
4105 GNUNET_STATISTICS_set (stats,
4106 gettext_noop ("# bytes dropped (ancient message)"),
4112 /* process decrypted message(s) */
4113 if (n->bw_out_external_limit.value__ != pt->inbound_bw_limit.value__)
4115 #if DEBUG_CORE_SET_QUOTA
4116 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4117 "Received %u b/s as new inbound limit for peer `%4s'\n",
4118 (unsigned int) ntohl (pt->inbound_bw_limit.value__),
4119 GNUNET_i2s (&n->peer));
4121 n->bw_out_external_limit = pt->inbound_bw_limit;
4122 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
4123 n->bw_out_internal_limit);
4124 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
4126 GNUNET_TRANSPORT_set_quota (transport,
4131 n->last_activity = GNUNET_TIME_absolute_get ();
4132 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
4133 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
4135 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
4138 GNUNET_STATISTICS_update (stats,
4139 gettext_noop ("# bytes of payload decrypted"),
4140 size - sizeof (struct EncryptedMessage),
4142 handle_peer_status_change (n);
4143 update_neighbour_performance (n, ats, ats_count);
4144 if (GNUNET_OK != GNUNET_SERVER_mst_receive (mst,
4146 &buf[sizeof (struct EncryptedMessage)],
4147 size - sizeof (struct EncryptedMessage),
4148 GNUNET_YES, GNUNET_NO))
4149 GNUNET_break_op (0);
4154 * Function called by the transport for each received message.
4156 * @param cls closure
4157 * @param peer (claimed) identity of the other peer
4158 * @param message the message
4159 * @param ats performance data
4160 * @param ats_count number of entries in ats (excluding 0-termination)
4163 handle_transport_receive (void *cls,
4164 const struct GNUNET_PeerIdentity *peer,
4165 const struct GNUNET_MessageHeader *message,
4166 const struct GNUNET_TRANSPORT_ATS_Information *ats,
4169 struct Neighbour *n;
4170 struct GNUNET_TIME_Absolute now;
4177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4178 "Received message of type %u from `%4s', demultiplexing.\n",
4179 (unsigned int) ntohs (message->type),
4182 if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
4187 n = find_neighbour (peer);
4189 n = create_neighbour (peer);
4190 changed = GNUNET_NO;
4191 up = (n->status == PEER_STATE_KEY_CONFIRMED);
4192 type = ntohs (message->type);
4193 size = ntohs (message->size);
4196 case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
4197 if (size != sizeof (struct SetKeyMessage))
4199 GNUNET_break_op (0);
4202 GNUNET_STATISTICS_update (stats,
4203 gettext_noop ("# session keys received"),
4207 (const struct SetKeyMessage *) message,
4210 case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
4211 if (size < sizeof (struct EncryptedMessage) +
4212 sizeof (struct GNUNET_MessageHeader))
4214 GNUNET_break_op (0);
4217 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
4218 (n->status != PEER_STATE_KEY_CONFIRMED))
4220 GNUNET_STATISTICS_update (stats,
4221 gettext_noop ("# failed to decrypt message (no session key)"),
4227 handle_encrypted_message (n,
4228 (const struct EncryptedMessage *) message,
4231 case GNUNET_MESSAGE_TYPE_CORE_PING:
4232 if (size != sizeof (struct PingMessage))
4234 GNUNET_break_op (0);
4237 GNUNET_STATISTICS_update (stats, gettext_noop ("# PING messages received"), 1, GNUNET_NO);
4238 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
4239 (n->status != PEER_STATE_KEY_CONFIRMED))
4242 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4243 "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
4244 "PING", GNUNET_i2s (&n->peer));
4246 GNUNET_free_non_null (n->pending_ping);
4247 n->pending_ping = GNUNET_malloc (sizeof (struct PingMessage));
4248 memcpy (n->pending_ping, message, sizeof (struct PingMessage));
4251 handle_ping (n, (const struct PingMessage *) message,
4254 case GNUNET_MESSAGE_TYPE_CORE_PONG:
4255 if (size != sizeof (struct PongMessage))
4257 GNUNET_break_op (0);
4260 GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages received"), 1, GNUNET_NO);
4261 if ( (n->status != PEER_STATE_KEY_RECEIVED) &&
4262 (n->status != PEER_STATE_KEY_CONFIRMED) )
4265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4266 "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
4267 "PONG", GNUNET_i2s (&n->peer));
4269 GNUNET_free_non_null (n->pending_pong);
4270 n->pending_pong = GNUNET_malloc (sizeof (struct PongMessage));
4271 memcpy (n->pending_pong, message, sizeof (struct PongMessage));
4274 handle_pong (n, (const struct PongMessage *) message,
4278 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4279 _("Unsupported message of type %u received.\n"),
4280 (unsigned int) type);
4283 if (n->status == PEER_STATE_KEY_CONFIRMED)
4285 now = GNUNET_TIME_absolute_get ();
4286 n->last_activity = now;
4287 changed = GNUNET_YES;
4290 GNUNET_STATISTICS_update (stats,
4291 gettext_noop ("# established sessions"),
4294 n->time_established = now;
4296 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
4297 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
4299 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
4304 handle_peer_status_change (n);
4309 * Function that recalculates the bandwidth quota for the
4310 * given neighbour and transmits it to the transport service.
4312 * @param cls neighbour for the quota update
4316 neighbour_quota_update (void *cls,
4317 const struct GNUNET_SCHEDULER_TaskContext *tc)
4319 struct Neighbour *n = cls;
4320 struct GNUNET_BANDWIDTH_Value32NBO q_in;
4321 struct GNUNET_BANDWIDTH_Value32NBO q_out;
4322 struct GNUNET_BANDWIDTH_Value32NBO q_out_min;
4325 unsigned long long distributable;
4326 uint64_t need_per_peer;
4327 uint64_t need_per_second;
4328 unsigned int neighbour_count;
4331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4332 "Neighbour quota update calculation running for peer `%4s'\n",
4333 GNUNET_i2s (&n->peer));
4335 n->quota_update_task = GNUNET_SCHEDULER_NO_TASK;
4336 /* calculate relative preference among all neighbours;
4337 divides by a bit more to avoid division by zero AND to
4338 account for possibility of new neighbours joining any time
4339 AND to convert to double... */
4340 neighbour_count = GNUNET_CONTAINER_multihashmap_size (neighbours);
4341 if (neighbour_count == 0)
4343 if (preference_sum == 0)
4345 pref_rel = 1.0 / (double) neighbour_count;
4349 pref_rel = (double) n->current_preference / preference_sum;
4351 need_per_peer = GNUNET_BANDWIDTH_value_get_available_until (MIN_BANDWIDTH_PER_PEER,
4352 GNUNET_TIME_UNIT_SECONDS);
4353 need_per_second = need_per_peer * neighbour_count;
4355 /* calculate inbound bandwidth per peer */
4357 if (bandwidth_target_in_bps > need_per_second)
4358 distributable = bandwidth_target_in_bps - need_per_second;
4359 share = distributable * pref_rel;
4360 if (share + need_per_peer > UINT32_MAX)
4361 q_in = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
4363 q_in = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4365 /* calculate outbound bandwidth per peer */
4367 if (bandwidth_target_out_bps > need_per_second)
4368 distributable = bandwidth_target_out_bps - need_per_second;
4369 share = distributable * pref_rel;
4370 if (share + need_per_peer > UINT32_MAX)
4371 q_out = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
4373 q_out = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4374 n->bw_out_internal_limit = q_out;
4376 q_out_min = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit, n->bw_out_internal_limit);
4377 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window, n->bw_out);
4379 /* check if we want to disconnect for good due to inactivity */
4380 if ( (GNUNET_TIME_absolute_get_duration (get_neighbour_timeout (n)).rel_value > 0) &&
4381 (GNUNET_TIME_absolute_get_duration (n->time_established).rel_value > GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value) )
4384 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4385 "Forcing disconnect of `%4s' due to inactivity\n",
4386 GNUNET_i2s (&n->peer));
4388 q_in = GNUNET_BANDWIDTH_value_init (0); /* force disconnect */
4390 #if DEBUG_CORE_QUOTA
4391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4392 "Current quota for `%4s' is %u/%llu b/s in (old: %u b/s) / %u out (%u internal)\n",
4393 GNUNET_i2s (&n->peer),
4394 (unsigned int) ntohl (q_in.value__),
4395 bandwidth_target_out_bps,
4396 (unsigned int) ntohl (n->bw_in.value__),
4397 (unsigned int) ntohl (n->bw_out.value__),
4398 (unsigned int) ntohl (n->bw_out_internal_limit.value__));
4400 if ((n->bw_in.value__ != q_in.value__) || (n->bw_out.value__ != q_out_min.value__))
4402 if (n->bw_in.value__ != q_in.value__)
4404 if (n->bw_out.value__ != q_out_min.value__)
4405 n->bw_out = q_out_min;
4406 if (GNUNET_YES == n->is_connected)
4407 GNUNET_TRANSPORT_set_quota (transport,
4411 handle_peer_status_change (n);
4413 schedule_quota_update (n);
4418 * Function called by transport to notify us that
4419 * a peer connected to us (on the network level).
4421 * @param cls closure
4422 * @param peer the peer that connected
4423 * @param ats performance data
4424 * @param ats_count number of entries in ats (excluding 0-termination)
4427 handle_transport_notify_connect (void *cls,
4428 const struct GNUNET_PeerIdentity *peer,
4429 const struct GNUNET_TRANSPORT_ATS_Information *ats,
4432 struct Neighbour *n;
4434 if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
4439 n = find_neighbour (peer);
4442 if (GNUNET_YES == n->is_connected)
4444 /* duplicate connect notification!? */
4451 n = create_neighbour (peer);
4453 GNUNET_STATISTICS_update (stats,
4454 gettext_noop ("# peers connected (transport)"),
4457 n->is_connected = GNUNET_YES;
4458 update_neighbour_performance (n, ats, ats_count);
4459 GNUNET_BANDWIDTH_tracker_init (&n->available_send_window,
4462 GNUNET_BANDWIDTH_tracker_init (&n->available_recv_window,
4466 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4467 "Received connection from `%4s'.\n",
4468 GNUNET_i2s (&n->peer));
4470 GNUNET_TRANSPORT_set_quota (transport,
4479 * Function called by transport telling us that a peer
4482 * @param cls closure
4483 * @param peer the peer that disconnected
4486 handle_transport_notify_disconnect (void *cls,
4487 const struct GNUNET_PeerIdentity *peer)
4489 struct DisconnectNotifyMessage cnm;
4490 struct Neighbour *n;
4491 struct ClientActiveRequest *car;
4492 struct GNUNET_TIME_Relative left;
4495 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4496 "Peer `%4s' disconnected from us; received notification from transport.\n",
4499 n = find_neighbour (peer);
4505 GNUNET_break (n->is_connected == GNUNET_YES);
4506 if (n->status == PEER_STATE_KEY_CONFIRMED)
4508 cnm.header.size = htons (sizeof (struct DisconnectNotifyMessage));
4509 cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
4510 cnm.reserved = htonl (0);
4512 send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_DISCONNECT);
4513 GNUNET_STATISTICS_update (stats,
4514 gettext_noop ("# established sessions"),
4519 /* On transport disconnect transport doesn't cancel requests, so must do so here. */
4522 GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
4525 n->is_connected = GNUNET_NO;
4526 n->status = PEER_STATE_DOWN;
4527 while (NULL != (car = n->active_client_request_head))
4529 GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
4530 n->active_client_request_tail,
4532 GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
4533 &n->peer.hashPubKey,
4538 GNUNET_STATISTICS_update (stats,
4539 gettext_noop ("# peers connected (transport)"),
4542 if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
4543 GNUNET_SCHEDULER_cancel (n->dead_clean_task);
4544 left = GNUNET_TIME_relative_subtract (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
4545 GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT);
4546 n->last_activity = GNUNET_TIME_absolute_subtract (GNUNET_TIME_absolute_get (),
4548 n->dead_clean_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT,
4549 &consider_free_task,
4555 * Wrapper around 'free_neighbour'; helper for 'cleaning_task'.
4558 free_neighbour_helper (void *cls,
4559 const GNUNET_HashCode *key,
4562 struct Neighbour *n = value;
4570 * Last task run during shutdown. Disconnects us from
4574 cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4579 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4580 "Core service shutting down.\n");
4582 GNUNET_assert (transport != NULL);
4583 GNUNET_TRANSPORT_disconnect (transport);
4585 GNUNET_CONTAINER_multihashmap_iterate (neighbours,
4586 &free_neighbour_helper,
4588 GNUNET_CONTAINER_multihashmap_destroy (neighbours);
4590 GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), 0, GNUNET_NO);
4591 GNUNET_SERVER_notification_context_destroy (notifier);
4593 while (NULL != (c = clients))
4594 handle_client_disconnect (NULL, c->client_handle);
4595 if (my_private_key != NULL)
4596 GNUNET_CRYPTO_rsa_key_free (my_private_key);
4598 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
4599 if (peerinfo != NULL)
4600 GNUNET_PEERINFO_disconnect (peerinfo);
4602 GNUNET_SERVER_mst_destroy (mst);
4607 * Initiate core service.
4609 * @param cls closure
4610 * @param server the initialized server
4611 * @param c configuration to use
4615 struct GNUNET_SERVER_Handle *server,
4616 const struct GNUNET_CONFIGURATION_Handle *c)
4618 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
4619 {&handle_client_init, NULL,
4620 GNUNET_MESSAGE_TYPE_CORE_INIT, 0},
4621 {&handle_client_iterate_peers, NULL,
4622 GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
4623 sizeof (struct GNUNET_MessageHeader)},
4624 {&handle_client_have_peer, NULL,
4625 GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED,
4626 sizeof (struct GNUNET_MessageHeader) + sizeof(struct GNUNET_PeerIdentity)},
4627 {&handle_client_request_info, NULL,
4628 GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
4629 sizeof (struct RequestInfoMessage)},
4630 {&handle_client_send_request, NULL,
4631 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
4632 sizeof (struct SendMessageRequest)},
4633 {&handle_client_send, NULL,
4634 GNUNET_MESSAGE_TYPE_CORE_SEND, 0},
4635 {&handle_client_request_connect, NULL,
4636 GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT,
4637 sizeof (struct ConnectMessage)},
4643 /* parse configuration */
4646 GNUNET_CONFIGURATION_get_value_number (c,
4649 &bandwidth_target_in_bps)) ||
4651 GNUNET_CONFIGURATION_get_value_number (c,
4654 &bandwidth_target_out_bps)) ||
4656 GNUNET_CONFIGURATION_get_value_filename (c,
4658 "HOSTKEY", &keyfile)))
4660 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4662 ("Core service is lacking key configuration settings. Exiting.\n"));
4663 GNUNET_SCHEDULER_shutdown ();
4666 peerinfo = GNUNET_PEERINFO_connect (cfg);
4667 if (NULL == peerinfo)
4669 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4670 _("Could not access PEERINFO service. Exiting.\n"));
4671 GNUNET_SCHEDULER_shutdown ();
4672 GNUNET_free (keyfile);
4675 my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
4676 GNUNET_free (keyfile);
4677 if (my_private_key == NULL)
4679 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4680 _("Core service could not access hostkey. Exiting.\n"));
4681 GNUNET_PEERINFO_disconnect (peerinfo);
4682 GNUNET_SCHEDULER_shutdown ();
4685 neighbours = GNUNET_CONTAINER_multihashmap_create (128);
4686 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
4687 GNUNET_CRYPTO_hash (&my_public_key,
4688 sizeof (my_public_key), &my_identity.hashPubKey);
4689 self.public_key = &my_public_key;
4690 self.peer = my_identity;
4691 self.last_activity = GNUNET_TIME_UNIT_FOREVER_ABS;
4692 self.status = PEER_STATE_KEY_CONFIRMED;
4693 self.is_connected = GNUNET_YES;
4694 /* setup notification */
4695 notifier = GNUNET_SERVER_notification_context_create (server,
4697 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
4698 /* setup transport connection */
4699 transport = GNUNET_TRANSPORT_connect (cfg,
4702 &handle_transport_receive,
4703 &handle_transport_notify_connect,
4704 &handle_transport_notify_disconnect);
4705 GNUNET_assert (NULL != transport);
4706 stats = GNUNET_STATISTICS_create ("core", cfg);
4708 GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded CORE_SEND requests"), 0, GNUNET_NO);
4709 GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded lower priority CORE_SEND requests"), 0, GNUNET_NO);
4711 mst = GNUNET_SERVER_mst_create (&deliver_message,
4713 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
4714 &cleaning_task, NULL);
4715 /* process client requests */
4716 GNUNET_SERVER_add_handlers (server, handlers);
4717 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4718 _("Core service of `%4s' ready.\n"), GNUNET_i2s (&my_identity));
4724 * The main function for the transport service.
4726 * @param argc number of arguments from the command line
4727 * @param argv command line arguments
4728 * @return 0 ok, 1 on error
4731 main (int argc, char *const *argv)
4733 return (GNUNET_OK ==
4734 GNUNET_SERVICE_run (argc,
4737 GNUNET_SERVICE_OPTION_NONE,
4738 &run, NULL)) ? 0 : 1;
4741 /* end of gnunet-service-core.c */