1773aea7e9028a3d92194783a1802f278285352e
[oweals/gnunet.git] / src / core / gnunet-service-core.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file core/gnunet-service-core.c
23  * @brief high-level P2P messaging
24  * @author Christian Grothoff
25  *
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)
32  */
33 #include "platform.h"
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"
42 #include "core.h"
43
44
45 #define DEBUG_HANDSHAKE GNUNET_NO
46
47 #define DEBUG_CORE_QUOTA GNUNET_NO
48
49 /**
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).
53  */
54 #define MAX_WINDOW_TIME_S (5 * 60)
55
56 /**
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).
60  */
61 #define MAX_NOTIFY_QUEUE 1024
62
63 /**
64  * Minimum bandwidth (out) to assign to any connected peer.
65  * Should be rather low; values larger than DEFAULT_BW_IN_OUT make no
66  * sense.
67  */
68 #define MIN_BANDWIDTH_PER_PEER GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT
69
70 /**
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.
76  */
77 #define PAST_EXPIRATION_DISCARD_TIME GNUNET_TIME_UNIT_SECONDS
78
79 /**
80  * What is the maximum delay for a SET_KEY message?
81  */
82 #define MAX_SET_KEY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
83
84 /**
85  * How long do we wait for SET_KEY confirmation initially?
86  */
87 #define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (MAX_SET_KEY_DELAY, 1)
88
89 /**
90  * What is the maximum delay for a PING message?
91  */
92 #define MAX_PING_DELAY GNUNET_TIME_relative_multiply (MAX_SET_KEY_DELAY, 2)
93
94 /**
95  * What is the maximum delay for a PONG message?
96  */
97 #define MAX_PONG_DELAY GNUNET_TIME_relative_multiply (MAX_PING_DELAY, 2)
98
99 /**
100  * What is the minimum frequency for a PING message?
101  */
102 #define MIN_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
103
104 /**
105  * How often do we recalculate bandwidth quotas?
106  */
107 #define QUOTA_UPDATE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
108
109 /**
110  * What is the priority for a SET_KEY message?
111  */
112 #define SET_KEY_PRIORITY 0xFFFFFF
113
114 /**
115  * What is the priority for a PING message?
116  */
117 #define PING_PRIORITY 0xFFFFFF
118
119 /**
120  * What is the priority for a PONG message?
121  */
122 #define PONG_PRIORITY 0xFFFFFF
123
124 /**
125  * How many messages do we queue per peer at most?  Must be at
126  * least two.
127  */
128 #define MAX_PEER_QUEUE_SIZE 16
129
130 /**
131  * How many non-mandatory messages do we queue per client at most?
132  */
133 #define MAX_CLIENT_QUEUE_SIZE 32
134
135 /**
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.
142  */
143 #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
144
145
146 /**
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).
153  */
154 enum PeerStateMachine
155 {
156   /**
157    * No handshake yet.
158    */
159   PEER_STATE_DOWN,
160
161   /**
162    * We've sent our session key.
163    */
164   PEER_STATE_KEY_SENT,
165   
166   /**
167    * We've received the other peers session key.
168    */
169   PEER_STATE_KEY_RECEIVED,
170
171   /**
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.
174    */
175   PEER_STATE_KEY_CONFIRMED
176 };
177
178
179 /**
180  * Encapsulation for encrypted messages exchanged between
181  * peers.  Followed by the actual encrypted data.
182  */
183 struct EncryptedMessage
184 {
185   /**
186    * Message type is either CORE_ENCRYPTED_MESSAGE.
187    */
188   struct GNUNET_MessageHeader header;
189
190   /**
191    * Random value used for IV generation.
192    */
193   uint32_t iv_seed GNUNET_PACKED;
194
195   /**
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.
200    */
201   GNUNET_HashCode hmac;
202
203   /**
204    * Sequence number, in network byte order.  This field
205    * must be the first encrypted/decrypted field
206    */
207   uint32_t sequence_number GNUNET_PACKED;
208
209   /**
210    * Desired bandwidth (how much we should send to this peer / how
211    * much is the sender willing to receive)?
212    */
213   struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
214
215   /**
216    * Timestamp.  Used to prevent reply of ancient messages
217    * (recent messages are caught with the sequence number).
218    */
219   struct GNUNET_TIME_AbsoluteNBO timestamp;
220
221 };
222
223
224 /**
225  * Number of bytes (at the beginning) of "struct EncryptedMessage"
226  * that are NOT encrypted.
227  */
228 #define ENCRYPTED_HEADER_SIZE (offsetof(struct EncryptedMessage, sequence_number))
229
230
231 /**
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.
235  */
236 struct PingMessage
237 {
238   /**
239    * Message type is CORE_PING.
240    */
241   struct GNUNET_MessageHeader header;
242   
243   /**
244    * Seed for the IV
245    */
246   uint32_t iv_seed GNUNET_PACKED;
247
248   /**
249    * Intended target of the PING, used primarily to check
250    * that decryption actually worked.
251    */
252   struct GNUNET_PeerIdentity target;
253
254   /**
255    * Random number chosen to make reply harder.
256    */
257   uint32_t challenge GNUNET_PACKED;
258 };
259
260
261
262 /**
263  * Response to a PING.  Includes data from the original PING
264  * plus initial bandwidth quota information.
265  */
266 struct PongMessage
267 {
268   /**
269    * Message type is CORE_PONG.
270    */
271   struct GNUNET_MessageHeader header;
272     
273   /**
274    * Seed for the IV
275    */
276   uint32_t iv_seed GNUNET_PACKED;
277
278   /**
279    * Random number to make faking the reply harder.  Must be
280    * first field after header (this is where we start to encrypt!).
281    */
282   uint32_t challenge GNUNET_PACKED;
283
284   /**
285    * Desired bandwidth (how much we should send to this
286    * peer / how much is the sender willing to receive).
287    */
288   struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
289
290   /**
291    * Intended target of the PING, used primarily to check
292    * that decryption actually worked.
293    */
294   struct GNUNET_PeerIdentity target;
295 };
296
297
298 /**
299  * Message transmitted to set (or update) a session key.
300  */
301 struct SetKeyMessage
302 {
303
304   /**
305    * Message type is either CORE_SET_KEY.
306    */
307   struct GNUNET_MessageHeader header;
308
309   /**
310    * Status of the sender (should be in "enum PeerStateMachine"), nbo.
311    */
312   int32_t sender_status GNUNET_PACKED;
313
314   /**
315    * Purpose of the signature, will be
316    * GNUNET_SIGNATURE_PURPOSE_SET_KEY.
317    */
318   struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
319
320   /**
321    * At what time was this key created?
322    */
323   struct GNUNET_TIME_AbsoluteNBO creation_time;
324
325   /**
326    * The encrypted session key.
327    */
328   struct GNUNET_CRYPTO_RsaEncryptedData encrypted_key;
329
330   /**
331    * Who is the intended recipient?
332    */
333   struct GNUNET_PeerIdentity target;
334
335   /**
336    * Signature of the stuff above (starting at purpose).
337    */
338   struct GNUNET_CRYPTO_RsaSignature signature;
339
340 };
341
342
343 /**
344  * Message waiting for transmission. This struct
345  * is followed by the actual content of the message.
346  */
347 struct MessageEntry
348 {
349
350   /**
351    * We keep messages in a doubly linked list.
352    */
353   struct MessageEntry *next;
354
355   /**
356    * We keep messages in a doubly linked list.
357    */
358   struct MessageEntry *prev;
359
360   /**
361    * By when are we supposed to transmit this message?
362    */
363   struct GNUNET_TIME_Absolute deadline;
364
365   /**
366    * By when are we supposed to transmit this message (after
367    * giving slack)?
368    */
369   struct GNUNET_TIME_Absolute slack_deadline;
370
371   /**
372    * How important is this message to us?
373    */
374   unsigned int priority;
375
376   /**
377    * If this is a SET_KEY message, what was our connection status when this
378    * message was queued?
379    */
380   enum PeerStateMachine sender_status;
381
382   /**
383    * Is this a SET_KEY message?
384    */
385   int is_setkey;
386
387   /**
388    * How long is the message? (number of bytes following
389    * the "struct MessageEntry", but not including the
390    * size of "struct MessageEntry" itself!)
391    */
392   uint16_t size;
393
394   /**
395    * Was this message selected for transmission in the
396    * current round? GNUNET_YES or GNUNET_NO.
397    */
398   int8_t do_transmit;
399
400   /**
401    * Did we give this message some slack (delayed sending) previously
402    * (and hence should not give it any more slack)? GNUNET_YES or
403    * GNUNET_NO.
404    */
405   int8_t got_slack;
406
407 };
408
409
410 /**
411  * Record kept for each request for transmission issued by a 
412  * client that is still pending.
413  */
414 struct ClientActiveRequest;
415
416 /**
417  * Data kept per neighbouring peer.
418  */
419 struct Neighbour
420 {
421
422   /**
423    * Unencrypted messages destined for this peer.
424    */
425   struct MessageEntry *messages;
426
427   /**
428    * Head of the batched, encrypted message queue (already ordered,
429    * transmit starting with the head).
430    */
431   struct MessageEntry *encrypted_head;
432
433   /**
434    * Tail of the batched, encrypted message queue (already ordered,
435    * append new messages to tail)
436    */
437   struct MessageEntry *encrypted_tail;
438
439   /**
440    * Head of list of requests from clients for transmission to 
441    * this peer.
442    */
443   struct ClientActiveRequest *active_client_request_head;
444
445   /**
446    * Tail of list of requests from clients for transmission to 
447    * this peer.
448    */
449   struct ClientActiveRequest *active_client_request_tail;
450
451   /**
452    * Handle for pending requests for transmission to this peer
453    * with the transport service.  NULL if no request is pending.
454    */
455   struct GNUNET_TRANSPORT_TransmitHandle *th;
456
457   /**
458    * Public key of the neighbour, NULL if we don't have it yet.
459    */
460   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
461
462   /**
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.
466    */
467   struct PingMessage *pending_ping;
468
469   /**
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.
473    */
474   struct PongMessage *pending_pong;
475
476   /**
477    * Non-NULL if we are currently looking up HELLOs for this peer.
478    * for this peer.
479    */
480   struct GNUNET_PEERINFO_IteratorContext *pitr;
481
482   /**
483    * SetKeyMessage to transmit, NULL if we are not currently trying
484    * to send one.
485    */
486   struct SetKeyMessage *skm;
487
488   /**
489    * Performance data for the peer.
490    */ 
491   struct GNUNET_TRANSPORT_ATS_Information *ats;
492
493   /**
494    * Identity of the neighbour.
495    */
496   struct GNUNET_PeerIdentity peer;
497
498   /**
499    * Key we use to encrypt our messages for the other peer
500    * (initialized by us when we do the handshake).
501    */
502   struct GNUNET_CRYPTO_AesSessionKey encrypt_key;
503
504   /**
505    * Key we use to decrypt messages from the other peer
506    * (given to us by the other peer during the handshake).
507    */
508   struct GNUNET_CRYPTO_AesSessionKey decrypt_key;
509
510   /**
511    * ID of task used for re-trying plaintext scheduling.
512    */
513   GNUNET_SCHEDULER_TaskIdentifier retry_plaintext_task;
514
515   /**
516    * ID of task used for re-trying SET_KEY and PING message.
517    */
518   GNUNET_SCHEDULER_TaskIdentifier retry_set_key_task;
519
520   /**
521    * ID of task used for updating bandwidth quota for this neighbour.
522    */
523   GNUNET_SCHEDULER_TaskIdentifier quota_update_task;
524
525   /**
526    * ID of task used for sending keep-alive pings.
527    */
528   GNUNET_SCHEDULER_TaskIdentifier keep_alive_task;
529
530   /**
531    * ID of task used for cleaning up dead neighbour entries.
532    */
533   GNUNET_SCHEDULER_TaskIdentifier dead_clean_task;
534
535   /**
536    * At what time did we generate our encryption key?
537    */
538   struct GNUNET_TIME_Absolute encrypt_key_created;
539
540   /**
541    * At what time did the other peer generate the decryption key?
542    */
543   struct GNUNET_TIME_Absolute decrypt_key_created;
544
545   /**
546    * At what time did we initially establish (as in, complete session
547    * key handshake) this connection?  Should be zero if status != KEY_CONFIRMED.
548    */
549   struct GNUNET_TIME_Absolute time_established;
550
551   /**
552    * At what time did we last receive an encrypted message from the
553    * other peer?  Should be zero if status != KEY_CONFIRMED.
554    */
555   struct GNUNET_TIME_Absolute last_activity;
556
557   /**
558    * At what frequency are we currently re-trying SET_KEY messages?
559    */
560   struct GNUNET_TIME_Relative set_key_retry_frequency;
561
562   /**
563    * Tracking bandwidth for sending to this peer.
564    */
565   struct GNUNET_BANDWIDTH_Tracker available_send_window;
566
567   /**
568    * Tracking bandwidth for receiving from this peer.
569    */
570   struct GNUNET_BANDWIDTH_Tracker available_recv_window;
571
572   /**
573    * How valueable were the messages of this peer recently?
574    */
575   unsigned long long current_preference;
576
577   /**
578    * Number of entries in 'ats'.
579    */ 
580   unsigned int ats_count;
581
582   /**
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)
586    */
587   unsigned int last_packets_bitmap;
588
589   /**
590    * last sequence number received on this connection (highest)
591    */
592   uint32_t last_sequence_number_received;
593
594   /**
595    * last sequence number transmitted
596    */
597   uint32_t last_sequence_number_sent;
598
599   /**
600    * Available bandwidth in for this peer (current target).
601    */
602   struct GNUNET_BANDWIDTH_Value32NBO bw_in;    
603
604   /**
605    * Available bandwidth out for this peer (current target).
606    */
607   struct GNUNET_BANDWIDTH_Value32NBO bw_out;  
608
609   /**
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".
613    */
614   struct GNUNET_BANDWIDTH_Value32NBO bw_out_internal_limit;
615
616   /**
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".
620    */
621   struct GNUNET_BANDWIDTH_Value32NBO bw_out_external_limit;
622
623   /**
624    * What was our PING challenge number (for this peer)?
625    */
626   uint32_t ping_challenge;
627
628   /**
629    * What is our connection status?
630    */
631   enum PeerStateMachine status;
632
633   /**
634    * Are we currently connected to this neighbour?
635    */ 
636   int is_connected;
637
638 };
639
640
641 /**
642  * Data structure for each client connected to the core service.
643  */
644 struct Client
645 {
646   /**
647    * Clients are kept in a linked list.
648    */
649   struct Client *next;
650
651   /**
652    * Handle for the client with the server API.
653    */
654   struct GNUNET_SERVER_Client *client_handle;
655
656   /**
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!
660    */
661   const uint16_t *types;
662
663   /**
664    * Map of peer identities to active transmission requests of this
665    * client to the peer (of type 'struct ClientActiveRequest').
666    */
667   struct GNUNET_CONTAINER_MultiHashMap *requests;
668
669   /**
670    * Options for messages this client cares about,
671    * see GNUNET_CORE_OPTION_ values.
672    */
673   uint32_t options;
674
675   /**
676    * Number of types of incoming messages this client
677    * specifically cares about.  Size of the "types" array.
678    */
679   unsigned int tcnt;
680
681 };
682
683
684 /**
685  * Record kept for each request for transmission issued by a 
686  * client that is still pending.
687  */
688 struct ClientActiveRequest
689 {
690
691   /**
692    * Active requests are kept in a doubly-linked list of
693    * the respective target peer.
694    */
695   struct ClientActiveRequest *next;
696
697   /**
698    * Active requests are kept in a doubly-linked list of
699    * the respective target peer.
700    */
701   struct ClientActiveRequest *prev;
702
703   /**
704    * Handle to the client.
705    */
706   struct Client *client;
707
708   /**
709    * By what time would the client want to see this message out?
710    */
711   struct GNUNET_TIME_Absolute deadline;
712
713   /**
714    * How important is this request.
715    */
716   uint32_t priority;
717
718   /**
719    * How many more requests does this client have?
720    */
721   uint32_t queue_size;
722
723   /**
724    * How many bytes does the client intend to send?
725    */
726   uint16_t msize;
727
728   /**
729    * Unique request ID (in big endian).
730    */
731   uint16_t smr_id;
732   
733 };
734
735
736
737 /**
738  * Our public key.
739  */
740 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
741
742 /**
743  * Our identity.
744  */
745 static struct GNUNET_PeerIdentity my_identity;
746
747 /**
748  * Our private key.
749  */
750 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
751
752
753 /**
754  * Handle to peerinfo service.
755  */
756 static struct GNUNET_PEERINFO_Handle *peerinfo;
757
758 /**
759  * Our message stream tokenizer (for encrypted payload).
760  */
761 static struct GNUNET_SERVER_MessageStreamTokenizer *mst;
762
763 /**
764  * Our configuration.
765  */
766 const struct GNUNET_CONFIGURATION_Handle *cfg;
767
768 /**
769  * Transport service.
770  */
771 static struct GNUNET_TRANSPORT_Handle *transport;
772
773 /**
774  * Linked list of our clients.
775  */
776 static struct Client *clients;
777
778 /**
779  * Context for notifications we need to send to our clients.
780  */
781 static struct GNUNET_SERVER_NotificationContext *notifier;
782
783 /**
784  * Map of peer identities to 'struct Neighbour'.
785  */
786 static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
787
788 /**
789  * Neighbour entry for "this" peer.
790  */
791 static struct Neighbour self;
792
793 /**
794  * For creating statistics.
795  */
796 static struct GNUNET_STATISTICS_Handle *stats;
797
798 /**
799  * Sum of all preferences among all neighbours.
800  */
801 static unsigned long long preference_sum;
802
803 /**
804  * How much inbound bandwidth are we supposed to be using per second?
805  */
806 static unsigned long long bandwidth_target_in_bps;
807
808 /**
809  * How much outbound bandwidth are we supposed to be using per second?
810  */
811 static unsigned long long bandwidth_target_out_bps;
812
813 /**
814  * Derive an authentication key from "set key" information
815  */
816 static void
817 derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
818     const struct GNUNET_CRYPTO_AesSessionKey *skey,
819     uint32_t seed,
820     struct GNUNET_TIME_Absolute creation_time)
821 {
822   static const char ctx[] = "authentication key";
823   struct GNUNET_TIME_AbsoluteNBO ctbe;
824
825
826   ctbe = GNUNET_TIME_absolute_hton (creation_time);
827   GNUNET_CRYPTO_hmac_derive_key (akey,
828                                  skey,
829                                  &seed,
830                                  sizeof(seed),
831                                  &skey->key,
832                                  sizeof(skey->key),
833                                  &ctbe,
834                                  sizeof(ctbe),
835                                  ctx,
836                                  sizeof(ctx), NULL);
837 }
838
839
840 /**
841  * Derive an IV from packet information
842  */
843 static void
844 derive_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
845     const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed,
846     const struct GNUNET_PeerIdentity *identity)
847 {
848   static const char ctx[] = "initialization vector";
849
850   GNUNET_CRYPTO_aes_derive_iv (iv,
851                                skey,
852                                &seed,
853                                sizeof(seed),
854                                &identity->hashPubKey.bits,
855                                sizeof(identity->hashPubKey.bits),
856                                ctx,
857                                sizeof(ctx), NULL);
858 }
859
860 /**
861  * Derive an IV from pong packet information
862  */
863 static void
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)
867 {
868   static const char ctx[] = "pong initialization vector";
869
870   GNUNET_CRYPTO_aes_derive_iv (iv,
871                                skey,
872                                &seed,
873                                sizeof(seed),
874                                &identity->hashPubKey.bits,
875                                sizeof(identity->hashPubKey.bits),
876                                &challenge,
877                                sizeof(challenge),
878                                ctx,
879                                sizeof(ctx), NULL);
880 }
881
882
883 /**
884  * At what time should the connection to the given neighbour
885  * time out (given no further activity?)
886  *
887  * @param n neighbour in question
888  * @return absolute timeout
889  */
890 static struct GNUNET_TIME_Absolute 
891 get_neighbour_timeout (struct Neighbour *n)
892 {
893   return GNUNET_TIME_absolute_add (n->last_activity,
894                                    GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
895 }
896
897
898 /**
899  * Helper function for update_preference_sum.
900  */
901 static int
902 update_preference (void *cls,
903                    const GNUNET_HashCode *key,
904                    void *value)
905 {
906   unsigned long long *ps = cls;
907   struct Neighbour *n = value;
908
909   n->current_preference /= 2;
910   *ps += n->current_preference;
911   return GNUNET_OK;
912 }    
913
914
915 /**
916  * A preference value for a neighbour was update.  Update
917  * the preference sum accordingly.
918  *
919  * @param inc how much was a preference value increased?
920  */
921 static void
922 update_preference_sum (unsigned long long inc)
923 {
924   unsigned long long os;
925
926   os = preference_sum;
927   preference_sum += inc;
928   if (preference_sum >= os)
929     return; /* done! */
930   /* overflow! compensate by cutting all values in half! */
931   preference_sum = 0;
932   GNUNET_CONTAINER_multihashmap_iterate (neighbours,
933                                          &update_preference,
934                                          &preference_sum);
935   GNUNET_STATISTICS_set (stats, gettext_noop ("# total peer preference"), preference_sum, GNUNET_NO);
936 }
937
938
939 /**
940  * Find the entry for the given neighbour.
941  *
942  * @param peer identity of the neighbour
943  * @return NULL if we are not connected, otherwise the
944  *         neighbour's entry.
945  */
946 static struct Neighbour *
947 find_neighbour (const struct GNUNET_PeerIdentity *peer)
948 {
949   return GNUNET_CONTAINER_multihashmap_get (neighbours, &peer->hashPubKey);
950 }
951
952
953 /**
954  * Send a message to one of our clients.
955  *
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?
960  */
961 static void
962 send_to_client (struct Client *client,
963                 const struct GNUNET_MessageHeader *msg, 
964                 int can_drop)
965 {
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));
971 #endif  
972   GNUNET_SERVER_notification_context_unicast (notifier,
973                                               client->client_handle,
974                                               msg,
975                                               can_drop);
976 }
977
978
979 /**
980  * Send a message to all of our current clients that have
981  * the right options set.
982  * 
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 
986  */
987 static void
988 send_to_all_clients (const struct GNUNET_MessageHeader *msg, 
989                      int can_drop,
990                      int options)
991 {
992   struct Client *c;
993
994   c = clients;
995   while (c != NULL)
996     {
997       if (0 != (c->options & options))
998         {
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));
1003 #endif
1004           send_to_client (c, msg, can_drop);
1005         }
1006       c = c->next;
1007     }
1008 }
1009
1010
1011 /**
1012  * Function called by transport telling us that a peer
1013  * changed status.
1014  *
1015  * @param n the peer that changed status
1016  */
1017 static void
1018 handle_peer_status_change (struct Neighbour *n)
1019 {
1020   struct PeerStatusNotifyMessage *psnm;
1021   char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1022   struct GNUNET_TRANSPORT_ATS_Information *ats;
1023   size_t size;
1024
1025   if ( (! n->is_connected) ||
1026        (n->status != PEER_STATE_KEY_CONFIRMED) )
1027     return;
1028 #if DEBUG_CORE > 1
1029   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1030               "Peer `%4s' changed status\n",
1031               GNUNET_i2s (&n->peer));
1032 #endif
1033   size = sizeof (struct PeerStatusNotifyMessage) +
1034     n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1035   if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1036     {
1037       GNUNET_break (0);
1038       /* recovery strategy: throw away performance data */
1039       GNUNET_array_grow (n->ats,
1040                          n->ats_count,
1041                          0);
1042       size = sizeof (struct PeerStatusNotifyMessage) +
1043         n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1044     }
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);
1053   ats = &psnm->ats;
1054   memcpy (ats,
1055           n->ats,
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, 
1060                        GNUNET_YES, 
1061                        GNUNET_CORE_OPTION_SEND_STATUS_CHANGE);
1062   GNUNET_STATISTICS_update (stats, 
1063                             gettext_noop ("# peer status changes"), 
1064                             1, 
1065                             GNUNET_NO);
1066 }
1067
1068
1069 /**
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.
1073  *
1074  * @param n which peer to process
1075  */
1076 static void
1077 schedule_peer_messages (struct Neighbour *n)
1078 {
1079   struct SendMessageReady smr;
1080   struct ClientActiveRequest *car;
1081   struct ClientActiveRequest *pos;
1082   struct Client *c;
1083   struct MessageEntry *mqe;
1084   unsigned int queue_size;
1085   
1086   /* check if neighbour queue is empty enough! */
1087   if (n != &self)
1088     {
1089       queue_size = 0;
1090       mqe = n->messages;
1091       while (mqe != NULL) 
1092         {
1093           queue_size++;
1094           mqe = mqe->next;
1095         }
1096       if (queue_size >= MAX_PEER_QUEUE_SIZE)
1097         {
1098 #if DEBUG_CORE_CLIENT
1099           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1100                       "Not considering client transmission requests: queue full\n");
1101 #endif
1102           return; /* queue still full */
1103         }
1104       /* find highest priority request */
1105       pos = n->active_client_request_head;
1106       car = NULL;
1107       while (pos != NULL)
1108         {
1109           if ( (car == NULL) ||
1110                (pos->priority > car->priority) )
1111             car = pos;
1112           pos = pos->next;
1113         }
1114     }
1115   else
1116     {
1117       car = n->active_client_request_head;
1118     }
1119   if (car == NULL)
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));
1125 #endif
1126   c = car->client;
1127   GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1128                                n->active_client_request_tail,
1129                                car);
1130   GNUNET_assert (GNUNET_YES ==
1131                  GNUNET_CONTAINER_multihashmap_remove (c->requests,
1132                                                        &n->peer.hashPubKey,
1133                                                        car));  
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;
1138   smr.peer = n->peer;
1139   send_to_client (c, &smr.header, GNUNET_NO);
1140   GNUNET_free (car);
1141 }
1142
1143
1144 /**
1145  * Handle CORE_SEND_REQUEST message.
1146  */
1147 static void
1148 handle_client_send_request (void *cls,
1149                             struct GNUNET_SERVER_Client *client,
1150                             const struct GNUNET_MessageHeader *message)
1151 {
1152   const struct SendMessageRequest *req;
1153   struct Neighbour *n;
1154   struct Client *c;
1155   struct ClientActiveRequest *car;
1156
1157   req = (const struct SendMessageRequest*) message;
1158   if (0 == memcmp (&req->peer,
1159                    &my_identity,
1160                    sizeof (struct GNUNET_PeerIdentity)))
1161     n = &self;
1162   else
1163     n = find_neighbour (&req->peer);
1164   if ( (n == NULL) ||
1165        (GNUNET_YES != n->is_connected) ||
1166        (n->status != PEER_STATE_KEY_CONFIRMED) )
1167     { 
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");
1174 #endif
1175       GNUNET_STATISTICS_update (stats, 
1176                                 gettext_noop ("# send requests dropped (disconnected)"), 
1177                                 1, 
1178                                 GNUNET_NO);
1179       GNUNET_SERVER_receive_done (client, GNUNET_OK);
1180       return;
1181     }
1182   c = clients;
1183   while ( (c != NULL) &&
1184           (c->client_handle != client) )
1185     c = c->next;
1186   if (c == NULL)
1187     {
1188       /* client did not send INIT first! */
1189       GNUNET_break (0);
1190       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1191       return;
1192     }
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");
1198 #endif
1199   car = GNUNET_CONTAINER_multihashmap_get (c->requests,
1200                                            &req->peer.hashPubKey);
1201   if (car == NULL)
1202     {
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,
1208                                                         car,
1209                                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1210       GNUNET_CONTAINER_DLL_insert (n->active_client_request_head,
1211                                    n->active_client_request_tail,
1212                                    car);
1213       car->client = c;
1214     }
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);
1222 }
1223
1224
1225 /**
1226  * Notify client about an existing connection to one of our neighbours.
1227  */
1228 static int
1229 notify_client_about_neighbour (void *cls,
1230                                const GNUNET_HashCode *key,
1231                                void *value)
1232 {
1233   struct Client *c = cls;
1234   struct Neighbour *n = value;
1235   size_t size;
1236   char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1237   struct GNUNET_TRANSPORT_ATS_Information *ats;
1238   struct ConnectNotifyMessage *cnm;
1239
1240   size = sizeof (struct ConnectNotifyMessage) +
1241     (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1242   if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1243     {
1244       GNUNET_break (0);
1245       /* recovery strategy: throw away performance data */
1246       GNUNET_array_grow (n->ats,
1247                          n->ats_count,
1248                          0);
1249       size = sizeof (struct ConnectNotifyMessage) +
1250         (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1251     }
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);
1256   ats = &cnm->ats;
1257   memcpy (ats,
1258           n->ats,
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)
1263     {
1264 #if DEBUG_CORE_CLIENT
1265       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1266                   "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
1267 #endif
1268       cnm->peer = n->peer;
1269       send_to_client (c, &cnm->header, GNUNET_NO);
1270     }
1271   return GNUNET_OK;
1272 }
1273
1274
1275
1276 /**
1277  * Handle CORE_INIT request.
1278  */
1279 static void
1280 handle_client_init (void *cls,
1281                     struct GNUNET_SERVER_Client *client,
1282                     const struct GNUNET_MessageHeader *message)
1283 {
1284   const struct InitMessage *im;
1285   struct InitReplyMessage irm;
1286   struct Client *c;
1287   uint16_t msize;
1288   const uint16_t *types;
1289   uint16_t *wtypes;
1290   unsigned int i;
1291
1292 #if DEBUG_CORE_CLIENT
1293   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1294               "Client connecting to core service with `%s' message\n",
1295               "INIT");
1296 #endif
1297   /* check that we don't have an entry already */
1298   c = clients;
1299   while (c != NULL)
1300     {
1301       if (client == c->client_handle)
1302         {
1303           GNUNET_break (0);
1304           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1305           return;
1306         }
1307       c = c->next;
1308     }
1309   msize = ntohs (message->size);
1310   if (msize < sizeof (struct InitMessage))
1311     {
1312       GNUNET_break (0);
1313       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1314       return;
1315     }
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;
1322   c->next = clients;
1323   clients = c;
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",
1333               c,
1334               (unsigned int) c->tcnt);
1335 #endif
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,
1341           &my_public_key,
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");
1346 #endif
1347   send_to_client (c, &irm.header, GNUNET_NO);
1348   if (0 != (c->options & GNUNET_CORE_OPTION_SEND_CONNECT))
1349     {
1350       /* notify new client about existing neighbours */
1351       GNUNET_CONTAINER_multihashmap_iterate (neighbours,
1352                                              &notify_client_about_neighbour,
1353                                              c);
1354     }
1355   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1356 }
1357
1358
1359 /**
1360  * Free client request records.
1361  *
1362  * @param cls NULL
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)
1366  */
1367 static int
1368 destroy_active_client_request (void *cls,
1369                                const GNUNET_HashCode *key,
1370                                void *value)
1371 {
1372   struct ClientActiveRequest *car = value;
1373   struct Neighbour *n;
1374   struct GNUNET_PeerIdentity peer;
1375
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,
1381                                car);
1382   GNUNET_free (car);
1383   return GNUNET_YES;
1384 }
1385
1386
1387 /**
1388  * A client disconnected, clean up.
1389  *
1390  * @param cls closure
1391  * @param client identification of the client
1392  */
1393 static void
1394 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1395 {
1396   struct Client *pos;
1397   struct Client *prev;
1398
1399   if (client == NULL)
1400     return;
1401 #if DEBUG_CORE_CLIENT
1402   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1403               "Client %p has disconnected from core service.\n",
1404               client);
1405 #endif
1406   prev = NULL;
1407   pos = clients;
1408   while (pos != NULL)
1409     {
1410       if (client == pos->client_handle)
1411         break;
1412       prev = pos;
1413       pos = pos->next;
1414     }
1415   if (pos == NULL)
1416     {
1417       /* client never sent INIT */
1418       return;
1419     }
1420   if (prev == NULL)
1421     clients = pos->next;
1422   else
1423     prev->next = pos->next;
1424   if (pos->requests != NULL)
1425     {
1426       GNUNET_CONTAINER_multihashmap_iterate (pos->requests,
1427                                              &destroy_active_client_request,
1428                                              NULL);
1429       GNUNET_CONTAINER_multihashmap_destroy (pos->requests);
1430     }
1431   GNUNET_free (pos);
1432 }
1433
1434
1435 /**
1436  * Helper function for handle_client_iterate_peers.
1437  *
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)
1442  */
1443 static int
1444 queue_connect_message (void *cls,
1445                        const GNUNET_HashCode *key,
1446                        void *value)
1447 {
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;
1452   size_t size;
1453   struct ConnectNotifyMessage *cnm;
1454
1455   cnm = (struct ConnectNotifyMessage*) buf;
1456   if (n->status != PEER_STATE_KEY_CONFIRMED)
1457     return GNUNET_OK;
1458   size = sizeof (struct ConnectNotifyMessage) +
1459     (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1460   if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1461     {
1462       GNUNET_break (0);
1463       /* recovery strategy: throw away performance data */
1464       GNUNET_array_grow (n->ats,
1465                          n->ats_count,
1466                          0);
1467       size = sizeof (struct PeerStatusNotifyMessage) +
1468         n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1469     }
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);
1474   ats = &cnm->ats;
1475   memcpy (ats,
1476           n->ats,
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",
1483               "NOTIFY_CONNECT");
1484 #endif
1485   cnm->peer = n->peer;
1486   GNUNET_SERVER_transmit_context_append_message (tc, 
1487                                                  &cnm->header);
1488   return GNUNET_OK;
1489 }
1490
1491
1492 /**
1493  * Handle CORE_ITERATE_PEERS request.
1494  *
1495  * @param cls unused
1496  * @param client client sending the iteration request
1497  * @param message iteration request message
1498  */
1499 static void
1500 handle_client_iterate_peers (void *cls,
1501                              struct GNUNET_SERVER_Client *client,
1502                              const struct GNUNET_MessageHeader *message)
1503
1504 {
1505   struct GNUNET_MessageHeader done_msg;
1506   struct GNUNET_SERVER_TransmitContext *tc;
1507   int msize;
1508   /* notify new client about existing neighbours */
1509
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);
1514   else
1515     GNUNET_break(0);
1516
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);
1522 }
1523
1524 /**
1525  * Handle CORE_ITERATE_PEERS request.  Notify client about existing neighbours.
1526  *
1527  * @param cls unused
1528  * @param client client sending the iteration request
1529  * @param message iteration request message
1530  */
1531 static void
1532 handle_client_have_peer (void *cls,
1533                              struct GNUNET_SERVER_Client *client,
1534                              const struct GNUNET_MessageHeader *message)
1535
1536 {
1537   struct GNUNET_MessageHeader done_msg;
1538   struct GNUNET_SERVER_TransmitContext *tc;
1539   struct GNUNET_PeerIdentity *peer;
1540
1541   tc = GNUNET_SERVER_transmit_context_create (client);
1542   peer = (struct GNUNET_PeerIdentity *) &message[1];
1543   GNUNET_CONTAINER_multihashmap_get_multiple(neighbours,
1544                                              &peer->hashPubKey, 
1545                                              &queue_connect_message, 
1546                                              tc);
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);
1552 }
1553
1554
1555 /**
1556  * Handle REQUEST_INFO request.
1557  *
1558  * @param cls unused
1559  * @param client client sending the request
1560  * @param message iteration request message
1561  */
1562 static void
1563 handle_client_request_info (void *cls,
1564                             struct GNUNET_SERVER_Client *client,
1565                             const struct GNUNET_MessageHeader *message)
1566 {
1567   const struct RequestInfoMessage *rcm;
1568   struct Client *pos;
1569   struct Neighbour *n;
1570   struct ConfigurationInfoMessage cim;
1571   int32_t want_reserv;
1572   int32_t got_reserv;
1573   unsigned long long old_preference;
1574   struct GNUNET_TIME_Relative rdelay;
1575
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");
1580 #endif
1581   pos = clients;
1582   while (pos != NULL)
1583     {
1584       if (client == pos->client_handle)
1585         break;
1586       pos = pos->next;
1587     }
1588   if (pos == NULL)
1589     {
1590       GNUNET_break (0);
1591       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1592       return;
1593     }
1594
1595   rcm = (const struct RequestInfoMessage *) message;
1596   n = find_neighbour (&rcm->peer);
1597   memset (&cim, 0, sizeof (cim));
1598   if (n != NULL) 
1599     {
1600       want_reserv = ntohl (rcm->reserve_inbound);
1601       if (n->bw_out_internal_limit.value__ != rcm->limit_outbound.value__)
1602         {
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__)
1606             {
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,
1610                                                      n->bw_out);
1611               GNUNET_TRANSPORT_set_quota (transport,
1612                                           &n->peer,
1613                                           n->bw_in,
1614                                           n->bw_out);
1615               handle_peer_status_change (n);
1616             }
1617         }
1618       if (want_reserv < 0)
1619         {
1620           got_reserv = want_reserv;
1621         }
1622       else if (want_reserv > 0)
1623         {
1624           rdelay = GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window,
1625                                                        want_reserv);
1626           if (rdelay.rel_value == 0)
1627             got_reserv = want_reserv;
1628           else
1629             got_reserv = 0; /* all or nothing */
1630         }
1631       else
1632         got_reserv = 0;
1633       GNUNET_BANDWIDTH_tracker_consume (&n->available_recv_window,
1634                                         got_reserv);
1635       old_preference = n->current_preference;
1636       n->current_preference += GNUNET_ntohll(rcm->preference_change);
1637       if (old_preference > n->current_preference) 
1638         {
1639           /* overflow; cap at maximum value */
1640           n->current_preference = ULLONG_MAX;
1641         }
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",
1646                   (int) want_reserv,
1647                   GNUNET_i2s (&rcm->peer),
1648                   (int) got_reserv,
1649                   (unsigned long long) rdelay.rel_value);
1650 #endif
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;
1655     }
1656   else
1657     {
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);
1665       return;
1666     }
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");
1674 #endif
1675   send_to_client (pos, &cim.header, GNUNET_NO);
1676   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1677 }
1678
1679
1680 /**
1681  * Free the given entry for the neighbour (it has
1682  * already been removed from the list at this point).
1683  *
1684  * @param n neighbour to free
1685  */
1686 static void
1687 free_neighbour (struct Neighbour *n)
1688 {
1689   struct MessageEntry *m;
1690   struct ClientActiveRequest *car;
1691
1692 #if DEBUG_CORE
1693   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1694               "Destroying neighbour entry for peer `%4s'\n",
1695               GNUNET_i2s (&n->peer));
1696 #endif
1697   if (n->pitr != NULL)
1698     {
1699       GNUNET_PEERINFO_iterate_cancel (n->pitr);
1700       n->pitr = NULL;
1701     }
1702   if (n->skm != NULL)
1703     {
1704       GNUNET_free (n->skm);
1705       n->skm = NULL;
1706     }
1707   while (NULL != (m = n->messages))
1708     {
1709       n->messages = m->next;
1710       GNUNET_free (m);
1711     }
1712   while (NULL != (m = n->encrypted_head))
1713     {
1714       GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1715                                    n->encrypted_tail,
1716                                    m);
1717       GNUNET_free (m);
1718     }
1719   while (NULL != (car = n->active_client_request_head))
1720     {
1721       GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1722                                    n->active_client_request_tail,
1723                                    car);
1724       GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
1725                                             &n->peer.hashPubKey,
1726                                             car);
1727       GNUNET_free (car);
1728     }
1729   if (NULL != n->th)
1730     {
1731       GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
1732       n->th = NULL;
1733     }
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"), 
1747                               -1, 
1748                               GNUNET_NO);
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);
1753   GNUNET_free (n);
1754 }
1755
1756
1757 /**
1758  * Check if we have encrypted messages for the specified neighbour
1759  * pending, and if so, check with the transport about sending them
1760  * out.
1761  *
1762  * @param n neighbour to check.
1763  */
1764 static void process_encrypted_neighbour_queue (struct Neighbour *n);
1765
1766
1767 /**
1768  * Encrypt size bytes from in and write the result to out.  Use the
1769  * key for outbound traffic of the given neighbour.
1770  *
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
1777  */
1778 static int
1779 do_encrypt (struct Neighbour *n,
1780             const struct GNUNET_CRYPTO_AesInitializationVector * iv,
1781             const void *in, void *out, size_t size)
1782 {
1783   if (size != (uint16_t) size)
1784     {
1785       GNUNET_break (0);
1786       return GNUNET_NO;
1787     }
1788   GNUNET_assert (size ==
1789                  GNUNET_CRYPTO_aes_encrypt (in,
1790                                             (uint16_t) size,
1791                                             &n->encrypt_key,
1792                                             iv, out));
1793   GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes encrypted"), size, GNUNET_NO);
1794 #if DEBUG_CORE > 2
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)));
1801 #endif
1802   return GNUNET_OK;
1803 }
1804
1805
1806 /**
1807  * Consider freeing the given neighbour since we may not need
1808  * to keep it around anymore.
1809  *
1810  * @param n neighbour to consider discarding
1811  */
1812 static void
1813 consider_free_neighbour (struct Neighbour *n);
1814
1815
1816 /**
1817  * Task triggered when a neighbour entry is about to time out 
1818  * (and we should prevent this by sending a PING).
1819  *
1820  * @param cls the 'struct Neighbour'
1821  * @param tc scheduler context (not used)
1822  */
1823 static void
1824 send_keep_alive (void *cls,
1825                  const struct GNUNET_SCHEDULER_TaskContext *tc)
1826 {
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;
1834
1835   n->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
1836   /* send PING */
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,
1843                                      n->encrypted_tail,
1844                                      n->encrypted_tail,
1845                                      me);
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,
1850       UINT32_MAX);
1851   derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
1852   pp.challenge = n->ping_challenge;
1853   pp.target = n->peer;
1854 #if DEBUG_HANDSHAKE
1855   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1856               "Encrypting `%s' message with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
1857               "PING", 
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)),
1862               pm->iv_seed);
1863 #endif
1864   do_encrypt (n,
1865               &iv,
1866               &pp.target,
1867               &pm->target,
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);
1875   n->keep_alive_task 
1876     = GNUNET_SCHEDULER_add_delayed (retry,
1877                                     &send_keep_alive,
1878                                     n);
1879
1880 }
1881
1882
1883 /**
1884  * Task triggered when a neighbour entry might have gotten stale.
1885  *
1886  * @param cls the 'struct Neighbour'
1887  * @param tc scheduler context (not used)
1888  */
1889 static void
1890 consider_free_task (void *cls,
1891                     const struct GNUNET_SCHEDULER_TaskContext *tc)
1892 {
1893   struct Neighbour *n = cls;
1894
1895   n->dead_clean_task = GNUNET_SCHEDULER_NO_TASK;
1896   consider_free_neighbour (n);
1897 }
1898
1899
1900 /**
1901  * Consider freeing the given neighbour since we may not need
1902  * to keep it around anymore.
1903  *
1904  * @param n neighbour to consider discarding
1905  */
1906 static void
1907 consider_free_neighbour (struct Neighbour *n)
1908
1909   struct GNUNET_TIME_Relative left;
1910
1911   if ( (n->th != NULL) ||
1912        (n->pitr != NULL) ||
1913        (GNUNET_YES == n->is_connected) )
1914     return; /* no chance */
1915     
1916   left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
1917   if (left.rel_value > 0)
1918     {
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,
1923                                                          n);
1924       return;
1925     }
1926   /* actually free the neighbour... */
1927   GNUNET_assert (GNUNET_OK ==
1928                  GNUNET_CONTAINER_multihashmap_remove (neighbours,
1929                                                        &n->peer.hashPubKey,
1930                                                        n));
1931   GNUNET_STATISTICS_set (stats,
1932                          gettext_noop ("# neighbour entries allocated"), 
1933                          GNUNET_CONTAINER_multihashmap_size (neighbours),
1934                          GNUNET_NO);
1935   free_neighbour (n);
1936 }
1937
1938
1939 /**
1940  * Function called when the transport service is ready to
1941  * receive an encrypted message for the respective peer
1942  *
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
1947  */
1948 static size_t
1949 notify_encrypted_transmit_ready (void *cls, 
1950                                  size_t size, 
1951                                  void *buf)
1952 {
1953   struct Neighbour *n = cls;
1954   struct MessageEntry *m;
1955   size_t ret;
1956   char *cbuf;
1957
1958   n->th = NULL;
1959   m = n->encrypted_head;
1960   if (m == NULL)
1961     {
1962 #if DEBUG_CORE
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));
1966 #endif
1967       return 0;
1968     }
1969   GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1970                                n->encrypted_tail,
1971                                m);
1972   ret = 0;
1973   cbuf = buf;
1974   if (buf != NULL)
1975     {
1976       GNUNET_assert (size >= m->size);
1977       memcpy (cbuf, &m[1], m->size);
1978       ret = m->size;
1979       GNUNET_BANDWIDTH_tracker_consume (&n->available_send_window,
1980                                         m->size);
1981 #if DEBUG_CORE
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),
1985                   (unsigned int) ret, 
1986                   GNUNET_i2s (&n->peer));
1987 #endif
1988       process_encrypted_neighbour_queue (n);
1989     }
1990   else
1991     {
1992 #if DEBUG_CORE
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);
1997 #endif
1998     }
1999   GNUNET_free (m);
2000   consider_free_neighbour (n);
2001   GNUNET_STATISTICS_update (stats, 
2002                             gettext_noop ("# encrypted bytes given to transport"), 
2003                             ret, 
2004                             GNUNET_NO);
2005   return ret;
2006 }
2007
2008
2009 /**
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).
2013  *
2014  * @param n neighbour to check.
2015  */
2016 static void process_plaintext_neighbour_queue (struct Neighbour *n);
2017
2018
2019 /**
2020  * Check if we have encrypted messages for the specified neighbour
2021  * pending, and if so, check with the transport about sending them
2022  * out.
2023  *
2024  * @param n neighbour to check.
2025  */
2026 static void
2027 process_encrypted_neighbour_queue (struct Neighbour *n)
2028 {
2029   struct MessageEntry *m;
2030  
2031   if (n->th != NULL)
2032     return;  /* request already pending */
2033   m = n->encrypted_head;
2034   if (m == NULL)
2035     {
2036       /* encrypted queue empty, try plaintext instead */
2037       process_plaintext_neighbour_queue (n);
2038       return;
2039     }
2040 #if DEBUG_CORE > 1
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);
2046 #endif
2047   n->th =
2048     GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer,
2049                                             m->size,
2050                                             m->priority,
2051                                             GNUNET_TIME_absolute_get_remaining
2052                                             (m->deadline),
2053                                             &notify_encrypted_transmit_ready,
2054                                             n);
2055   if (n->th == NULL)
2056     {
2057       /* message request too large or duplicate request */
2058       GNUNET_break (0);
2059       /* discard encrypted message */
2060       GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
2061                                    n->encrypted_tail,
2062                                    m);
2063       GNUNET_free (m);
2064       process_encrypted_neighbour_queue (n);
2065     }
2066 }
2067
2068
2069 /**
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.
2073  *
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
2080  */
2081 static int
2082 do_decrypt (struct Neighbour *n,
2083             const struct GNUNET_CRYPTO_AesInitializationVector * iv,
2084             const void *in, void *out, size_t size)
2085 {
2086   if (size != (uint16_t) size)
2087     {
2088       GNUNET_break (0);
2089       return GNUNET_NO;
2090     }
2091   if ((n->status != PEER_STATE_KEY_RECEIVED) &&
2092       (n->status != PEER_STATE_KEY_CONFIRMED))
2093     {
2094       GNUNET_break_op (0);
2095       return GNUNET_SYSERR;
2096     }
2097   if (size !=
2098       GNUNET_CRYPTO_aes_decrypt (in,
2099                                  (uint16_t) size,
2100                                  &n->decrypt_key,
2101                                  iv,
2102                                  out))
2103     {
2104       GNUNET_break (0);
2105       return GNUNET_SYSERR;
2106     }
2107   GNUNET_STATISTICS_update (stats, 
2108                             gettext_noop ("# bytes decrypted"), 
2109                             size, 
2110                             GNUNET_NO);
2111 #if DEBUG_CORE > 1
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)));
2118 #endif
2119   return GNUNET_OK;
2120 }
2121
2122
2123 /**
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.
2132  *
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.
2139  */
2140 static size_t
2141 select_messages (struct Neighbour *n,
2142                  size_t size, struct GNUNET_TIME_Relative *retry_time)
2143 {
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;
2151   uint64_t avail;
2152   struct GNUNET_TIME_Relative slack;     /* how long could we wait before missing deadlines? */
2153   size_t off;
2154   uint64_t tsize;
2155   unsigned int queue_size;
2156   int discard_low_prio;
2157
2158   GNUNET_assert (NULL != n->messages);
2159   now = GNUNET_TIME_absolute_get ();
2160   /* last entry in linked list of messages processed */
2161   last = NULL;
2162   /* should we remove the entry with the lowest
2163      priority from consideration for scheduling at the
2164      end of the loop? */
2165   queue_size = 0;
2166   tsize = 0;
2167   pos = n->messages;
2168   while (pos != NULL)
2169     {
2170       queue_size++;
2171       tsize += pos->size;
2172       pos = pos->next;
2173     }
2174   discard_low_prio = GNUNET_YES;
2175   while (GNUNET_YES == discard_low_prio)
2176     {
2177       min = NULL;
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);
2182       t = now;
2183       /* how many bytes have we (hypothetically) scheduled so far */
2184       off = 0;
2185       /* maximum time we can wait before transmitting anything
2186          and still make all of our deadlines */
2187       slack = GNUNET_TIME_UNIT_FOREVER_REL;
2188       pos = n->messages;
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
2192          meantime... */
2193       while ((pos != NULL) && (off < size * 2))
2194         {         
2195           if (pos->do_transmit == GNUNET_YES)
2196             {
2197               /* already removed from consideration */
2198               pos = pos->next;
2199               continue;
2200             }
2201           if (discard_low_prio == GNUNET_NO)
2202             {
2203               delta = GNUNET_TIME_absolute_get_difference (t, pos->deadline);
2204               if (delta.rel_value > 0)
2205                 {
2206                   // FIXME: HUH? Check!
2207                   t = pos->deadline;
2208                   avail += GNUNET_BANDWIDTH_value_get_available_until (n->bw_out,
2209                                                                        delta);
2210                 }
2211               if (avail < pos->size)
2212                 {
2213                   // FIXME: HUH? Check!
2214                   discard_low_prio = GNUNET_YES;        /* we could not schedule this one! */
2215                 }
2216               else
2217                 {
2218                   avail -= pos->size;
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,
2224                                                                                           avail));
2225                   if (pos->deadline.abs_value <= now.abs_value) 
2226                     {
2227                       /* now or never */
2228                       slack = GNUNET_TIME_UNIT_ZERO;
2229                     }
2230                   else if (GNUNET_YES == pos->got_slack)
2231                     {
2232                       /* should be soon now! */
2233                       slack = GNUNET_TIME_relative_min (slack,
2234                                                         GNUNET_TIME_absolute_get_remaining (pos->slack_deadline));
2235                     }
2236                   else
2237                     {
2238                       slack =
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));
2244                     }
2245                 }
2246             }
2247           off += pos->size;
2248           t = GNUNET_TIME_absolute_max (pos->deadline, t); // HUH? Check!
2249           if (pos->priority <= min_prio)
2250             {
2251               /* update min for discard */
2252               min_prio = pos->priority;
2253               min = pos;
2254             }
2255           pos = pos->next;
2256         }
2257       if (discard_low_prio)
2258         {
2259           GNUNET_assert (min != NULL);
2260           /* remove lowest-priority entry from consideration */
2261           min->do_transmit = GNUNET_YES;        /* means: discard (for now) */
2262         }
2263       last = pos;
2264     }
2265   /* guard against sending "tiny" messages with large headers without
2266      urgent deadlines */
2267   if ( (slack.rel_value > GNUNET_CONSTANTS_MAX_CORK_DELAY.rel_value) && 
2268        (size > 4 * off) &&
2269        (queue_size <= MAX_PEER_QUEUE_SIZE - 2) )
2270     {
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 */
2277       while (pos != last)
2278         {
2279           pos->do_transmit = GNUNET_NO;   
2280           pos = pos->next;
2281         }
2282       GNUNET_STATISTICS_update (stats, 
2283                                 gettext_noop ("# transmissions delayed due to corking"), 
2284                                 1, GNUNET_NO);
2285 #if DEBUG_CORE
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,
2289                   (unsigned int) off,
2290                   (unsigned int) size);
2291 #endif
2292       return 0;
2293     }
2294   /* select marked messages (up to size) for transmission */
2295   off = 0;
2296   pos = n->messages;
2297   while (pos != last)
2298     {
2299       if ((pos->size <= size) && (pos->do_transmit == GNUNET_NO))
2300         {
2301           pos->do_transmit = GNUNET_YES;        /* mark for transmission */
2302           off += pos->size;
2303           size -= pos->size;
2304 #if DEBUG_CORE > 1
2305           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2306                       "Selecting message of size %u for transmission\n",
2307                       (unsigned int) pos->size);
2308 #endif
2309         }
2310       else
2311         {
2312 #if DEBUG_CORE > 1
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,
2316                       size);
2317 #endif
2318           pos->do_transmit = GNUNET_NO;   /* mark for not transmitting! */
2319         }
2320       pos = pos->next;
2321     }
2322 #if DEBUG_CORE
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));
2328 #endif
2329   return off;
2330 }
2331
2332
2333 /**
2334  * Batch multiple messages into a larger buffer.
2335  *
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)
2344  */
2345 static size_t
2346 batch_message (struct Neighbour *n,
2347                char *buf,
2348                size_t size,
2349                struct GNUNET_TIME_Absolute *deadline,
2350                struct GNUNET_TIME_Relative *retry_time,
2351                unsigned int *priority)
2352 {
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;
2358   size_t ret;
2359   
2360   ret = 0;
2361   *priority = 0;
2362   *deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2363   *retry_time = GNUNET_TIME_UNIT_FOREVER_REL;
2364   if (0 == select_messages (n, size, retry_time))
2365     {
2366 #if DEBUG_CORE
2367       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2368                   "No messages selected, will try again in %llu ms\n",
2369                   retry_time->rel_value);
2370 #endif
2371       return 0;
2372     }
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;
2378   pos = n->messages;
2379   prev = NULL;
2380   while ((pos != NULL) && (size >= sizeof (struct GNUNET_MessageHeader)))
2381     {
2382       next = pos->next;
2383       if (GNUNET_YES == pos->do_transmit)
2384         {
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
2389              actually true */
2390           if (pos->size < GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct NotifyTrafficMessage))
2391             {
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,
2396                                    GNUNET_YES,
2397                                    GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
2398             }
2399           else
2400             {
2401               /* message too large for 'full' notifications, we do at
2402                  least the 'hdr' type */
2403               memcpy (&ntm[1],
2404                       &pos[1],
2405                       sizeof (struct GNUNET_MessageHeader));
2406             }
2407           ntm->header.size = htons (sizeof (struct NotifyTrafficMessage) + 
2408                                     pos->size);
2409           send_to_all_clients (&ntm->header,
2410                                GNUNET_YES,
2411                                GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);   
2412 #if DEBUG_HANDSHAKE
2413           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2414                       "Encrypting %u bytes with message of type %u and size %u\n",
2415                       pos->size,
2416                       (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->type),
2417                       (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->size));
2418 #endif
2419           /* copy for encrypted transmission */
2420           memcpy (&buf[ret], &pos[1], pos->size);
2421           ret += pos->size;
2422           size -= pos->size;
2423           *priority += pos->priority;
2424 #if DEBUG_CORE > 1
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);
2429 #endif
2430           deadline->abs_value = GNUNET_MIN (deadline->abs_value, pos->deadline.abs_value);
2431           GNUNET_free (pos);
2432           if (prev == NULL)
2433             n->messages = next;
2434           else
2435             prev->next = next;
2436         }
2437       else
2438         {
2439           prev = pos;
2440         }
2441       pos = next;
2442     }
2443 #if DEBUG_CORE > 1
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);
2447 #endif
2448   return ret;
2449 }
2450
2451
2452 /**
2453  * Remove messages with deadlines that have long expired from
2454  * the queue.
2455  *
2456  * @param n neighbour to inspect
2457  */
2458 static void
2459 discard_expired_messages (struct Neighbour *n)
2460 {
2461   struct MessageEntry *prev;
2462   struct MessageEntry *next;
2463   struct MessageEntry *pos;
2464   struct GNUNET_TIME_Absolute now;
2465   struct GNUNET_TIME_Relative delta;
2466   int disc;
2467
2468   disc = GNUNET_NO;
2469   now = GNUNET_TIME_absolute_get ();
2470   prev = NULL;
2471   pos = n->messages;
2472   while (pos != NULL) 
2473     {
2474       next = pos->next;
2475       delta = GNUNET_TIME_absolute_get_difference (pos->deadline, now);
2476       if (delta.rel_value > PAST_EXPIRATION_DISCARD_TIME.rel_value)
2477         {
2478 #if DEBUG_CORE
2479           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2480                       "Message is %llu ms past due, discarding.\n",
2481                       delta.rel_value);
2482 #endif
2483           if (prev == NULL)
2484             n->messages = next;
2485           else
2486             prev->next = next;
2487           GNUNET_STATISTICS_update (stats, 
2488                                     gettext_noop ("# messages discarded (expired prior to transmission)"), 
2489                                     1, 
2490                                     GNUNET_NO);
2491           disc = GNUNET_YES;
2492           GNUNET_free (pos);
2493         }
2494       else
2495         prev = pos;
2496       pos = next;
2497     }
2498   if (GNUNET_YES == disc)
2499     schedule_peer_messages (n);
2500 }
2501
2502
2503 /**
2504  * Signature of the main function of a task.
2505  *
2506  * @param cls closure
2507  * @param tc context information (why was this task triggered now)
2508  */
2509 static void
2510 retry_plaintext_processing (void *cls,
2511                             const struct GNUNET_SCHEDULER_TaskContext *tc)
2512 {
2513   struct Neighbour *n = cls;
2514
2515   n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2516   process_plaintext_neighbour_queue (n);
2517 }
2518
2519
2520 /**
2521  * Send our key (and encrypted PING) to the other peer.
2522  *
2523  * @param n the other peer
2524  */
2525 static void send_key (struct Neighbour *n);
2526
2527 /**
2528  * Task that will retry "send_key" if our previous attempt failed
2529  * to yield a PONG.
2530  */
2531 static void
2532 set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2533 {
2534   struct Neighbour *n = cls;
2535
2536 #if DEBUG_CORE
2537   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2538               "Retrying key transmission to `%4s'\n",
2539               GNUNET_i2s (&n->peer));
2540 #endif
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);
2544   send_key (n);
2545 }
2546
2547
2548 /**
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).
2552  *
2553  * @param n neighbour to check.
2554  */
2555 static void
2556 process_plaintext_neighbour_queue (struct Neighbour *n)
2557 {
2558   char pbuf[GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE + sizeof (struct EncryptedMessage)];        /* plaintext */
2559   size_t used;
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;
2568
2569   if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
2570     {
2571       GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
2572       n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2573     }
2574   switch (n->status)
2575     {
2576     case PEER_STATE_DOWN:
2577       send_key (n);
2578 #if DEBUG_CORE
2579       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2580                   "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2581                   GNUNET_i2s(&n->peer));
2582 #endif
2583       return;
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);    
2589 #if DEBUG_CORE
2590       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2591                   "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2592                   GNUNET_i2s(&n->peer));
2593 #endif
2594       return;
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);        
2600 #if DEBUG_CORE
2601       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2602                   "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2603                   GNUNET_i2s(&n->peer));
2604 #endif
2605       return;
2606     case PEER_STATE_KEY_CONFIRMED:
2607       /* ready to continue */
2608       break;
2609     }
2610   discard_expired_messages (n);
2611   if (n->messages == NULL)
2612     {
2613 #if DEBUG_CORE
2614       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2615                   "Plaintext message queue for `%4s' is empty.\n",
2616                   GNUNET_i2s(&n->peer));
2617 #endif
2618       return;                   /* no pending messages */
2619     }
2620   if (n->encrypted_head != NULL)
2621     {
2622 #if DEBUG_CORE > 2
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));
2626 #endif
2627       return;                   /* wait for messages already encrypted to be
2628                                    processed first! */
2629     }
2630   ph = (struct EncryptedMessage *) pbuf;
2631   deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2632   priority = 0;
2633   used = sizeof (struct EncryptedMessage);
2634   used += batch_message (n,
2635                          &pbuf[used],
2636                          GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE,
2637                          &deadline, &retry_time, &priority);
2638   if (used == sizeof (struct EncryptedMessage))
2639     {
2640 #if DEBUG_CORE > 1
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));
2644 #endif
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);
2649       return;
2650     }
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));
2656 #endif
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 ());
2661
2662   /* setup encryption message header */
2663   me = GNUNET_malloc (sizeof (struct MessageEntry) + used);
2664   me->deadline = deadline;
2665   me->priority = priority;
2666   me->size = used;
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);
2672   /* encrypt */
2673 #if DEBUG_HANDSHAKE 
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);
2679 #endif
2680   GNUNET_assert (GNUNET_OK ==
2681                  do_encrypt (n,
2682                              &iv,
2683                              &ph->sequence_number,
2684                              &em->sequence_number, used - ENCRYPTED_HEADER_SIZE));
2685   derive_auth_key (&auth_key,
2686                    &n->encrypt_key,
2687                    ph->iv_seed,
2688                    n->encrypt_key_created);
2689   GNUNET_CRYPTO_hmac (&auth_key,
2690                       &em->sequence_number,
2691                       used - ENCRYPTED_HEADER_SIZE,
2692                       &em->hmac);
2693 #if DEBUG_HANDSHAKE
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));
2700 #endif
2701   /* append to transmission list */
2702   GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
2703                                      n->encrypted_tail,
2704                                      n->encrypted_tail,
2705                                      me);
2706   process_encrypted_neighbour_queue (n);
2707   schedule_peer_messages (n);
2708 }
2709
2710
2711 /**
2712  * Function that recalculates the bandwidth quota for the
2713  * given neighbour and transmits it to the transport service.
2714  * 
2715  * @param cls neighbour for the quota update
2716  * @param tc context
2717  */
2718 static void
2719 neighbour_quota_update (void *cls,
2720                         const struct GNUNET_SCHEDULER_TaskContext *tc);
2721
2722
2723 /**
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).
2727  */
2728 static void
2729 schedule_quota_update (struct Neighbour *n)
2730 {
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,
2736                                     n);
2737 }
2738
2739
2740 /**
2741  * Initialize a new 'struct Neighbour'.
2742  *
2743  * @param pid ID of the new neighbour
2744  * @return handle for the new neighbour
2745  */
2746 static struct Neighbour *
2747 create_neighbour (const struct GNUNET_PeerIdentity *pid)
2748 {
2749   struct Neighbour *n;
2750   struct GNUNET_TIME_Absolute now;
2751
2752 #if DEBUG_CORE
2753   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2754               "Creating neighbour entry for peer `%4s'\n",
2755               GNUNET_i2s (pid));
2756 #endif
2757   n = GNUNET_malloc (sizeof (struct Neighbour));
2758   n->peer = *pid;
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,
2769                                                 UINT32_MAX);
2770   GNUNET_assert (GNUNET_OK == 
2771                  GNUNET_CONTAINER_multihashmap_put (neighbours,
2772                                                     &n->peer.hashPubKey,
2773                                                     n,
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);
2779   return n;
2780 }
2781
2782
2783 /**
2784  * Handle CORE_SEND request.
2785  *
2786  * @param cls unused
2787  * @param client the client issuing the request
2788  * @param message the "struct SendMessage"
2789  */
2790 static void
2791 handle_client_send (void *cls,
2792                     struct GNUNET_SERVER_Client *client,
2793                     const struct GNUNET_MessageHeader *message)
2794 {
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;
2804   uint16_t msize;
2805
2806   msize = ntohs (message->size);
2807   if (msize <
2808       sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader))
2809     {
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));
2811       GNUNET_break (0);
2812       if (client != NULL)
2813         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2814       return;
2815     }
2816   sm = (const struct SendMessage *) message;
2817   msize -= sizeof (struct SendMessage);
2818   if (0 == memcmp (&sm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2819     {
2820       /* loopback */
2821       GNUNET_SERVER_mst_receive (mst,
2822                                  &self,
2823                                  (const char*) &sm[1],
2824                                  msize,
2825                                  GNUNET_YES,
2826                                  GNUNET_NO);
2827       if (client != NULL)
2828         GNUNET_SERVER_receive_done (client, GNUNET_OK);
2829       return;
2830     }
2831   n = find_neighbour (&sm->peer);
2832   if (n == NULL)
2833     n = create_neighbour (&sm->peer);
2834 #if DEBUG_CORE
2835   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2836               "Core received `%s' request, queueing %u bytes of plaintext data for transmission to `%4s'.\n",
2837               "SEND",
2838               (unsigned int) msize, 
2839               GNUNET_i2s (&sm->peer));
2840 #endif
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;
2853   queue_size = 0;
2854   prev = NULL;
2855   pos = n->messages;
2856   while (pos != NULL) 
2857     {
2858       if (pos->priority <= min_prio)
2859         {
2860           min_prio_entry = pos;
2861           min_prio_prev = prev;
2862           min_prio = pos->priority;
2863         }
2864       queue_size++;
2865       prev = pos;
2866       pos = pos->next;
2867     }
2868   if (queue_size >= MAX_PEER_QUEUE_SIZE)
2869     {
2870       /* queue full */
2871       if (ntohl(sm->priority) <= min_prio)
2872         {
2873           /* discard new entry; this should no longer happen! */
2874           GNUNET_break (0);
2875 #if DEBUG_CORE
2876           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2877                       "Queue full (%u/%u), discarding new request (%u bytes of type %u)\n",
2878                       queue_size,
2879                       (unsigned int) MAX_PEER_QUEUE_SIZE,
2880                       (unsigned int) msize,
2881                       (unsigned int) ntohs (message->type));
2882 #endif
2883           GNUNET_STATISTICS_update (stats, 
2884                                     gettext_noop ("# discarded CORE_SEND requests"), 
2885                                     1, GNUNET_NO);
2886
2887           if (client != NULL)
2888             GNUNET_SERVER_receive_done (client, GNUNET_OK);
2889           return;
2890         }
2891       GNUNET_assert (min_prio_entry != NULL);
2892       /* discard "min_prio_entry" */
2893 #if DEBUG_CORE
2894       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2895                   "Queue full, discarding existing older request\n");
2896 #endif
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;
2900       else
2901         min_prio_prev->next = min_prio_entry->next;      
2902       GNUNET_free (min_prio_entry);     
2903     }
2904
2905 #if DEBUG_CORE
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);
2910 #endif  
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);
2915   e->size = msize;
2916   if (GNUNET_YES != (int) ntohl (sm->cork))
2917     e->got_slack = GNUNET_YES;
2918   memcpy (&e[1], &sm[1], msize);
2919
2920   /* insert, keep list sorted by deadline */
2921   prev = NULL;
2922   pos = n->messages;
2923   while ((pos != NULL) && (pos->deadline.abs_value < e->deadline.abs_value))
2924     {
2925       prev = pos;
2926       pos = pos->next;
2927     }
2928   if (prev == NULL)
2929     n->messages = e;
2930   else
2931     prev->next = e;
2932   e->next = pos;
2933
2934   /* consider scheduling now */
2935   process_plaintext_neighbour_queue (n);
2936   if (client != NULL)
2937     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2938 }
2939
2940
2941 /**
2942  * Handle CORE_REQUEST_CONNECT request.
2943  *
2944  * @param cls unused
2945  * @param client the client issuing the request
2946  * @param message the "struct ConnectMessage"
2947  */
2948 static void
2949 handle_client_request_connect (void *cls,
2950                                struct GNUNET_SERVER_Client *client,
2951                                const struct GNUNET_MessageHeader *message)
2952 {
2953   const struct ConnectMessage *cm = (const struct ConnectMessage*) message;
2954   struct Neighbour *n;
2955
2956   if (0 == memcmp (&cm->peer, 
2957                    &my_identity, 
2958                    sizeof (struct GNUNET_PeerIdentity)))
2959     {
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);
2962       return;
2963     }  
2964   GNUNET_break (ntohl (cm->reserved) == 0);
2965 #if DEBUG_CORE
2966   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2967               "Core received `%s' request for `%4s', will try to establish connection\n",
2968               "REQUEST_CONNECT",
2969               GNUNET_i2s (&cm->peer));
2970 #endif
2971   GNUNET_STATISTICS_update (stats, 
2972                             gettext_noop ("# connection requests received"), 
2973                             1,
2974                             GNUNET_NO);
2975   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2976   n = find_neighbour (&cm->peer);
2977   if ( (n == NULL) || 
2978        (GNUNET_YES != n->is_connected) )
2979     {
2980       GNUNET_TRANSPORT_try_connect (transport,
2981                                     &cm->peer);
2982     }
2983   else
2984     {
2985       GNUNET_STATISTICS_update (stats, 
2986                                 gettext_noop ("# connection requests ignored (already connected)"), 
2987                                 1,
2988                                 GNUNET_NO);
2989     }
2990 }
2991
2992
2993 /**
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.
2997  *
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
3002  */
3003 static void
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)
3008 {
3009   struct Neighbour *n = cls;
3010
3011   if (err_msg != NULL)
3012   {
3013     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3014                 _("Error in communication with PEERINFO service\n"));
3015     /* return; */
3016   }
3017
3018   if (peer == NULL)
3019     {
3020 #if DEBUG_CORE
3021       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3022                   "Entered `%s' and `%s' is NULL!\n",
3023                   "process_hello_retry_send_key",
3024                   "peer");
3025 #endif
3026       n->pitr = NULL;
3027       if (n->public_key != NULL)
3028         {
3029           if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3030             {
3031               GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3032               n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3033             }      
3034           GNUNET_STATISTICS_update (stats,
3035                                     gettext_noop ("# SET_KEY messages deferred (need public key)"), 
3036                                     -1, 
3037                                     GNUNET_NO);
3038           send_key (n);
3039         }
3040       else
3041         {
3042 #if DEBUG_CORE
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));
3046 #endif
3047           GNUNET_STATISTICS_update (stats,
3048                                     gettext_noop ("# Delayed connecting due to lack of public key"),
3049                                     1,
3050                                     GNUNET_NO);      
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);
3055         }
3056       return;
3057     }
3058
3059 #if DEBUG_CORE
3060   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3061               "Entered `%s' for peer `%4s'\n",
3062               "process_hello_retry_send_key",
3063               GNUNET_i2s (peer));
3064 #endif
3065   if (n->public_key != NULL)
3066     {
3067       /* already have public key, why are we here? */
3068       GNUNET_break (0);
3069       return;
3070     }
3071
3072 #if DEBUG_CORE
3073   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3074               "Received new `%s' message for `%4s', initiating key exchange.\n",
3075               "HELLO",
3076               GNUNET_i2s (peer));
3077 #endif
3078   n->public_key =
3079     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3080   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
3081     {
3082       GNUNET_STATISTICS_update (stats,
3083                                 gettext_noop ("# Error extracting public key from HELLO"),
3084                                 1,
3085                                 GNUNET_NO);      
3086       GNUNET_free (n->public_key);
3087       n->public_key = NULL;
3088 #if DEBUG_CORE
3089   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3090               "GNUNET_HELLO_get_key returned awfully\n");
3091 #endif
3092       return;
3093     }
3094 }
3095
3096
3097 /**
3098  * Send our key (and encrypted PING) to the other peer.
3099  *
3100  * @param n the other peer
3101  */
3102 static void
3103 send_key (struct Neighbour *n)
3104 {
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;
3111
3112   if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3113     {
3114       GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3115       n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3116     }        
3117   if (n->pitr != NULL)
3118     {
3119 #if DEBUG_CORE
3120       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3121                   "Key exchange in progress with `%4s'.\n",
3122                   GNUNET_i2s (&n->peer));
3123 #endif
3124       return; /* already in progress */
3125     }
3126   if (GNUNET_YES != n->is_connected)
3127     {
3128       GNUNET_STATISTICS_update (stats, 
3129                                 gettext_noop ("# Asking transport to connect (for SET_KEY)"), 
3130                                 1, 
3131                                 GNUNET_NO);
3132       GNUNET_TRANSPORT_try_connect (transport,
3133                                     &n->peer);
3134       return; 
3135     }
3136 #if DEBUG_CORE
3137   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3138               "Asked to perform key exchange with `%4s'.\n",
3139               GNUNET_i2s (&n->peer));
3140 #endif
3141   if (n->public_key == NULL)
3142     {
3143       /* lookup n's public key, then try again */
3144 #if DEBUG_CORE
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));
3148 #endif
3149       GNUNET_assert (n->pitr == NULL);
3150       n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
3151                                          &n->peer,
3152                                          GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20),
3153                                          &process_hello_retry_send_key, n);
3154       return;
3155     }
3156   pos = n->encrypted_head;
3157   while (pos != NULL)
3158     {
3159       if (GNUNET_YES == pos->is_setkey)
3160         {
3161           if (pos->sender_status == n->status)
3162             {
3163 #if DEBUG_CORE
3164               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3165                           "`%s' message for `%4s' queued already\n",
3166                           "SET_KEY",
3167                           GNUNET_i2s (&n->peer));
3168 #endif
3169               goto trigger_processing;
3170             }
3171           GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
3172                                        n->encrypted_tail,
3173                                        pos);
3174           GNUNET_free (pos);
3175 #if DEBUG_CORE
3176           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3177                       "Removing queued `%s' message for `%4s', will create a new one\n",
3178                       "SET_KEY",
3179                       GNUNET_i2s (&n->peer));
3180 #endif
3181           break;
3182         }
3183       pos = pos->next;
3184     }
3185
3186   /* update status */
3187   switch (n->status)
3188     {
3189     case PEER_STATE_DOWN:
3190       n->status = PEER_STATE_KEY_SENT;
3191       break;
3192     case PEER_STATE_KEY_SENT:
3193       break;
3194     case PEER_STATE_KEY_RECEIVED:
3195       break;
3196     case PEER_STATE_KEY_CONFIRMED:
3197       break;
3198     default:
3199       GNUNET_break (0);
3200       break;
3201     }
3202   
3203
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,
3215                                      n->encrypted_tail,
3216                                      n->encrypted_tail,
3217                                      me);
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));
3223   sm->purpose.size =
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,
3233                                             sizeof (struct
3234                                                     GNUNET_CRYPTO_AesSessionKey),
3235                                             n->public_key,
3236                                             &sm->encrypted_key));
3237   GNUNET_assert (GNUNET_OK ==
3238                  GNUNET_CRYPTO_rsa_sign (my_private_key, &sm->purpose,
3239                                          &sm->signature));  
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;
3247 #if DEBUG_HANDSHAKE
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",
3250               "SET_KEY", "PING",
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)),
3255               pm->iv_seed);
3256 #endif
3257   do_encrypt (n,
3258               &iv,
3259               &pp.target,
3260               &pm->target,
3261               sizeof (struct PingMessage) -
3262               ((void *) &pm->target - (void *) pm));
3263   GNUNET_STATISTICS_update (stats, 
3264                             gettext_noop ("# SET_KEY and PING messages created"), 
3265                             1, 
3266                             GNUNET_NO);
3267 #if DEBUG_CORE
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,
3271               "SET_KEY");
3272 #endif
3273  trigger_processing:
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);    
3281 }
3282
3283
3284 /**
3285  * We received a SET_KEY message.  Validate and update
3286  * our key material and status.
3287  *
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)
3292  */
3293 static void
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);
3298
3299
3300
3301 /**
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.
3305  *
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
3310  */
3311 static void
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)
3316 {
3317   struct Neighbour *n = cls;
3318   struct SetKeyMessage *sm = n->skm;
3319
3320   if (err_msg != NULL)
3321   {
3322     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3323                 _("Error in communication with PEERINFO service\n"));
3324     /* return; */
3325   }
3326
3327   if (peer == NULL)
3328     {
3329       n->skm = NULL;
3330       n->pitr = NULL;
3331       if (n->public_key != NULL)
3332         {
3333 #if DEBUG_CORE
3334           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3335                       "Received `%s' for `%4s', continuing processing of `%s' message.\n",
3336                       "HELLO",
3337                       GNUNET_i2s (&n->peer),
3338                       "SET_KEY");
3339 #endif
3340           handle_set_key (n, sm, NULL, 0);
3341         }
3342       else
3343         {
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"),
3346                       "SET_KEY",
3347                       GNUNET_i2s (&n->peer));
3348         }
3349       GNUNET_free (sm);
3350       return;
3351     }
3352   if (n->public_key != NULL)
3353     return;                     /* multiple HELLOs match!? */
3354   n->public_key =
3355     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3356   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
3357     {
3358       GNUNET_break_op (0);
3359       GNUNET_free (n->public_key);
3360       n->public_key = NULL;
3361     }
3362 }
3363
3364
3365 /**
3366  * Merge the given performance data with the data we currently
3367  * track for the given neighbour.
3368  *
3369  * @param n neighbour
3370  * @param ats new performance data
3371  * @param ats_count number of records in ats
3372  */
3373 static void
3374 update_neighbour_performance (struct Neighbour *n,
3375                               const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3376                               uint32_t ats_count)
3377 {
3378   uint32_t i;
3379   unsigned int j;
3380
3381   if (ats_count == 0)
3382     return;
3383   for (i = 0; i < ats_count; i++)
3384     {
3385       for (j=0;j < n->ats_count; j++)
3386         {
3387           if (n->ats[j].type == ats[i].type)
3388             {
3389               n->ats[j].value = ats[i].value;
3390               break;
3391             }
3392         }
3393       if (j == n->ats_count)
3394         {
3395           GNUNET_array_append (n->ats,
3396                                n->ats_count,
3397                                ats[i]);
3398         }
3399     }
3400 }
3401
3402
3403 /**
3404  * We received a PING message.  Validate and transmit
3405  * PONG.
3406  *
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)
3411  */
3412 static void
3413 handle_ping (struct Neighbour *n,
3414              const struct PingMessage *m,
3415              const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3416              uint32_t ats_count)
3417 {
3418   struct PingMessage t;
3419   struct PongMessage tx;
3420   struct PongMessage *tp;
3421   struct MessageEntry *me;
3422   struct GNUNET_CRYPTO_AesInitializationVector iv;
3423
3424 #if DEBUG_CORE
3425   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3426               "Core service receives `%s' request from `%4s'.\n",
3427               "PING", GNUNET_i2s (&n->peer));
3428 #endif
3429   derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
3430   if (GNUNET_OK !=
3431       do_decrypt (n,
3432                   &iv,
3433                   &m->target,
3434                   &t.target,
3435                   sizeof (struct PingMessage) -
3436                   ((void *) &m->target - (void *) m)))
3437     return;
3438 #if DEBUG_HANDSHAKE
3439   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3440               "Decrypted `%s' to `%4s' with challenge %u decrypted using key %u, IV %u (salt %u)\n",
3441               "PING",
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)),
3446               m->iv_seed);
3447 #endif
3448   GNUNET_STATISTICS_update (stats,
3449                             gettext_noop ("# PING messages decrypted"), 
3450                             1,
3451                             GNUNET_NO);
3452   if (0 != memcmp (&t.target,
3453                    &my_identity, sizeof (struct GNUNET_PeerIdentity)))
3454     {
3455       char sender[9];
3456       char peer[9];
3457
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"),
3462                   sender,
3463                   GNUNET_i2s (&my_identity), 
3464                   peer);
3465       GNUNET_break_op (0);
3466       return;
3467     }
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,
3472                                      n->encrypted_tail,
3473                                      n->encrypted_tail,
3474                                      me);
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);
3486   do_encrypt (n,
3487               &iv,
3488               &tx.challenge,
3489               &tp->challenge,
3490               sizeof (struct PongMessage) -
3491               ((void *) &tp->challenge - (void *) tp));
3492   GNUNET_STATISTICS_update (stats, 
3493                             gettext_noop ("# PONG messages created"), 
3494                             1, 
3495                             GNUNET_NO);
3496 #if DEBUG_HANDSHAKE
3497   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3498               "Encrypting `%s' with challenge %u using key %u, IV %u (salt %u)\n",
3499               "PONG",
3500               (unsigned int) t.challenge,
3501               (unsigned int) n->encrypt_key.crc32,
3502               GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3503               tp->iv_seed);
3504 #endif
3505   /* trigger queue processing */
3506   process_encrypted_neighbour_queue (n);
3507 }
3508
3509
3510 /**
3511  * We received a PONG message.  Validate and update our status.
3512  *
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)
3517  */
3518 static void
3519 handle_pong (struct Neighbour *n, 
3520              const struct PongMessage *m,
3521              const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3522              uint32_t ats_count)
3523 {
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;
3529   size_t size;
3530
3531 #if DEBUG_HANDSHAKE
3532   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3533               "Core service receives `%s' response from `%4s'.\n",
3534               "PONG", GNUNET_i2s (&n->peer));
3535 #endif
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,
3539       &my_identity);
3540   if (GNUNET_OK !=
3541       do_decrypt (n,
3542                   &iv,
3543                   &m->challenge,
3544                   &t.challenge,
3545                   sizeof (struct PongMessage) -
3546                   ((void *) &m->challenge - (void *) m)))
3547     {
3548       GNUNET_break_op (0);
3549       return;
3550     }
3551   GNUNET_STATISTICS_update (stats, 
3552                             gettext_noop ("# PONG messages decrypted"), 
3553                             1, 
3554                             GNUNET_NO);
3555 #if DEBUG_HANDSHAKE
3556   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3557               "Decrypted `%s' from `%4s' with challenge %u using key %u, IV %u (salt %u)\n",
3558               "PONG",
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)),
3563               m->iv_seed);
3564 #endif
3565   if ((0 != memcmp (&t.target,
3566                     &n->peer,
3567                     sizeof (struct GNUNET_PeerIdentity))) ||
3568       (n->ping_challenge != t.challenge))
3569     {
3570       /* PONG malformed */
3571 #if DEBUG_CORE
3572       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3573                   "Received malformed `%s' wanted sender `%4s' with challenge %u\n",
3574                   "PONG", 
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);
3581 #endif
3582       GNUNET_break_op (n->ping_challenge != t.challenge);
3583       return;
3584     }
3585   switch (n->status)
3586     {
3587     case PEER_STATE_DOWN:
3588       GNUNET_break (0);         /* should be impossible */
3589       return;
3590     case PEER_STATE_KEY_SENT:
3591       GNUNET_break (0);         /* should be impossible, how did we decrypt? */
3592       return;
3593     case PEER_STATE_KEY_RECEIVED:
3594       GNUNET_STATISTICS_update (stats, 
3595                                 gettext_noop ("# Session keys confirmed via PONG"), 
3596                                 1, 
3597                                 GNUNET_NO);
3598       n->status = PEER_STATE_KEY_CONFIRMED;
3599       if (n->bw_out_external_limit.value__ != t.inbound_bw_limit.value__)
3600         {
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,
3605                                                  n->bw_out);       
3606           GNUNET_TRANSPORT_set_quota (transport,
3607                                       &n->peer,
3608                                       n->bw_in,
3609                                       n->bw_out);
3610         }
3611 #if DEBUG_CORE
3612       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3613                   "Confirmed key via `%s' message for peer `%4s'\n",
3614                   "PONG", GNUNET_i2s (&n->peer));
3615 #endif      
3616       if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3617         {
3618           GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3619           n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3620         }      
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)
3625         {
3626           GNUNET_break (0);
3627           /* recovery strategy: throw away performance data */
3628           GNUNET_array_grow (n->ats,
3629                              n->ats_count,
3630                              0);
3631           size = sizeof (struct PeerStatusNotifyMessage) +
3632             n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3633         }
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;
3639       mats = &cnm->ats;
3640       memcpy (mats,
3641               n->ats,
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, 
3646                            GNUNET_NO, 
3647                            GNUNET_CORE_OPTION_SEND_CONNECT);
3648       process_encrypted_neighbour_queue (n);
3649       /* fall-through! */
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);
3654       n->keep_alive_task 
3655         = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
3656                                         &send_keep_alive,
3657                                         n);
3658       handle_peer_status_change (n);
3659       break;
3660     default:
3661       GNUNET_break (0);
3662       break;
3663     }
3664 }
3665
3666
3667 /**
3668  * We received a SET_KEY message.  Validate and update
3669  * our key material and status.
3670  *
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)
3675  */
3676 static void
3677 handle_set_key (struct Neighbour *n, 
3678                 const struct SetKeyMessage *m,
3679                 const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3680                 uint32_t ats_count)
3681 {
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;
3688
3689 #if DEBUG_CORE
3690   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3691               "Core service receives `%s' request from `%4s'.\n",
3692               "SET_KEY", GNUNET_i2s (&n->peer));
3693 #endif
3694   if (n->public_key == NULL)
3695     {
3696       if (n->pitr != NULL)
3697         {
3698 #if DEBUG_CORE
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",
3701                       "SET_KEY");
3702 #endif
3703           return;
3704         }
3705 #if DEBUG_CORE
3706       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3707                   "Lacking public key for peer, trying to obtain one (handle_set_key).\n");
3708 #endif
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);
3713       n->skm = m_cpy;
3714       n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
3715                                          &n->peer,
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)"), 
3720                                 1, 
3721                                 GNUNET_NO);
3722       return;
3723     }
3724   if (0 != memcmp (&m->target,
3725                    &my_identity,
3726                    sizeof (struct GNUNET_PeerIdentity)))
3727     {
3728       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3729                   _("Received `%s' message that was for `%s', not for me.  Ignoring.\n"),
3730                   "SET_KEY",
3731                   GNUNET_i2s (&m->target));
3732       return;
3733     }
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)) ||
3739       (GNUNET_OK !=
3740        GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_KEY,
3741                                  &m->purpose, &m->signature, n->public_key)))
3742     {
3743       /* invalid signature */
3744       GNUNET_break_op (0);
3745       return;
3746     }
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))
3751     {
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);
3756       return;
3757     }
3758 #if DEBUG_CORE
3759   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
3760               "Decrypting key material.\n");
3761 #endif  
3762   if ((GNUNET_CRYPTO_rsa_decrypt (my_private_key,
3763                                   &m->encrypted_key,
3764                                   &k,
3765                                   sizeof (struct GNUNET_CRYPTO_AesSessionKey))
3766        != sizeof (struct GNUNET_CRYPTO_AesSessionKey)) ||
3767       (GNUNET_OK != GNUNET_CRYPTO_aes_check_session_key (&k)))
3768     {
3769       /* failed to decrypt !? */
3770       GNUNET_break_op (0);
3771       return;
3772     }
3773   GNUNET_STATISTICS_update (stats, 
3774                             gettext_noop ("# SET_KEY messages decrypted"), 
3775                             1, 
3776                             GNUNET_NO);
3777   n->decrypt_key = k;
3778   if (n->decrypt_key_created.abs_value != t.abs_value)
3779     {
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;
3784     }
3785   update_neighbour_performance (n, ats, ats_count);
3786   sender_status = (enum PeerStateMachine) ntohl (m->sender_status);
3787   switch (n->status)
3788     {
3789     case PEER_STATE_DOWN:
3790       n->status = PEER_STATE_KEY_RECEIVED;
3791 #if DEBUG_CORE
3792       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3793                   "Responding to `%s' with my own key.\n", "SET_KEY");
3794 #endif
3795       send_key (n);
3796       break;
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))
3802         {
3803 #if DEBUG_CORE
3804           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3805                       "Responding to `%s' with my own key (other peer has status %u).\n",
3806                       "SET_KEY",
3807                       (unsigned int) sender_status);
3808 #endif
3809           send_key (n);
3810         }
3811       break;
3812     case PEER_STATE_KEY_CONFIRMED:
3813       if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
3814           (sender_status != PEER_STATE_KEY_CONFIRMED))
3815         {         
3816 #if DEBUG_CORE
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",
3819                       "SET_KEY", 
3820                       (unsigned int) sender_status);
3821 #endif
3822           send_key (n);
3823         }
3824       break;
3825     default:
3826       GNUNET_break (0);
3827       break;
3828     }
3829   if (n->pending_ping != NULL)
3830     {
3831       ping = n->pending_ping;
3832       n->pending_ping = NULL;
3833       handle_ping (n, ping, NULL, 0);
3834       GNUNET_free (ping);
3835     }
3836   if (n->pending_pong != NULL)
3837     {
3838       pong = n->pending_pong;
3839       n->pending_pong = NULL;
3840       handle_pong (n, pong, NULL, 0);
3841       GNUNET_free (pong);
3842     }
3843 }
3844
3845
3846 /**
3847  * Send a P2P message to a client.
3848  *
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
3853  */
3854 static void
3855 send_p2p_message_to_client (struct Neighbour *sender,
3856                             struct Client *client,
3857                             const void *m, size_t msize)
3858 {
3859   size_t size = msize + sizeof (struct NotifyTrafficMessage) +
3860     (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3861   char buf[size];
3862   struct NotifyTrafficMessage *ntm;
3863   struct GNUNET_TRANSPORT_ATS_Information *ats;
3864
3865   if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
3866     {
3867       GNUNET_break (0);
3868       /* recovery strategy: throw performance data away... */
3869       GNUNET_array_grow (sender->ats,
3870                          sender->ats_count,
3871                          0);
3872       size = msize + sizeof (struct NotifyTrafficMessage) +
3873         (sender->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3874     }
3875 #if DEBUG_CORE
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));
3880 #endif
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;
3886   ats = &ntm->ats;
3887   memcpy (ats,
3888           sender->ats,
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],
3893           m, 
3894           msize);
3895   send_to_client (client, &ntm->header, GNUNET_YES);
3896 }
3897
3898
3899 /**
3900  * Deliver P2P message to interested clients.
3901  *
3902  * @param cls always NULL
3903  * @param client who sent us the message (struct Neighbour)
3904  * @param m the message
3905  */
3906 static void
3907 deliver_message (void *cls,
3908                  void *client,
3909                  const struct GNUNET_MessageHeader *m)
3910 {
3911   struct Neighbour *sender = client;
3912   size_t msize = ntohs (m->size);
3913   char buf[256];
3914   struct Client *cpos;
3915   uint16_t type;
3916   unsigned int tpos;
3917   int deliver_full;
3918   int dropped;
3919
3920   type = ntohs (m->type);
3921 #if DEBUG_CORE > 1
3922   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3923               "Received encapsulated message of type %u and size %u from `%4s'\n",
3924               (unsigned int) type,
3925               ntohs (m->size),
3926               GNUNET_i2s (&sender->peer));
3927 #endif
3928   GNUNET_snprintf (buf,
3929                    sizeof(buf),
3930                    gettext_noop ("# bytes of messages of type %u received"),
3931                    (unsigned int) type);
3932   GNUNET_STATISTICS_update (stats,
3933                             buf,
3934                             msize,
3935                             GNUNET_NO);
3936   dropped = GNUNET_YES;
3937   cpos = clients;
3938   while (cpos != NULL)
3939     {
3940       deliver_full = GNUNET_NO;
3941       if (0 != (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))
3942         deliver_full = GNUNET_YES;
3943       else
3944         {
3945           for (tpos = 0; tpos < cpos->tcnt; tpos++)
3946             {
3947               if (type != cpos->types[tpos])
3948                 continue;
3949               deliver_full = GNUNET_YES;
3950               break;
3951             }
3952         }
3953       if (GNUNET_YES == deliver_full)
3954         {
3955           send_p2p_message_to_client (sender, cpos, m, msize);
3956           dropped = GNUNET_NO;
3957         }
3958       else if (cpos->options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)
3959         {
3960           send_p2p_message_to_client (sender, cpos, m,
3961                                       sizeof (struct GNUNET_MessageHeader));
3962         }
3963       cpos = cpos->next;
3964     }
3965   if (dropped == GNUNET_YES)
3966     {
3967 #if DEBUG_CORE
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));
3972 #endif
3973       GNUNET_STATISTICS_update (stats,
3974                                 gettext_noop ("# messages not delivered to any client"), 
3975                                 1, GNUNET_NO);
3976     }
3977 }
3978
3979
3980 /**
3981  * We received an encrypted message.  Decrypt, validate and
3982  * pass on to the appropriate clients.
3983  *
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)
3988  */
3989 static void
3990 handle_encrypted_message (struct Neighbour *n,
3991                           const struct EncryptedMessage *m,
3992                           const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3993                           uint32_t ats_count)
3994 {
3995   size_t size = ntohs (m->header.size);
3996   char buf[size];
3997   struct EncryptedMessage *pt;  /* plaintext */
3998   GNUNET_HashCode ph;
3999   uint32_t snum;
4000   struct GNUNET_TIME_Absolute t;
4001   struct GNUNET_CRYPTO_AesInitializationVector iv;
4002   struct GNUNET_CRYPTO_AuthKey auth_key;
4003
4004 #if DEBUG_CORE
4005   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4006               "Core service receives `%s' request from `%4s'.\n",
4007               "ENCRYPTED_MESSAGE", GNUNET_i2s (&n->peer));
4008 #endif  
4009   /* validate hash */
4010   derive_auth_key (&auth_key,
4011                    &n->decrypt_key,
4012                    m->iv_seed,
4013                    n->decrypt_key_created);
4014   GNUNET_CRYPTO_hmac (&auth_key,
4015                       &m->sequence_number,
4016                       size - ENCRYPTED_HEADER_SIZE, &ph);
4017 #if DEBUG_HANDSHAKE
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),
4023               GNUNET_h2s (&ph));
4024 #endif
4025
4026   if (0 != memcmp (&ph,
4027                    &m->hmac,
4028                    sizeof (GNUNET_HashCode)))
4029     {
4030       /* checksum failed */
4031       GNUNET_break_op (0);
4032       return;
4033     }
4034   derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
4035   /* decrypt */
4036   if (GNUNET_OK !=
4037       do_decrypt (n,
4038                   &iv,
4039                   &m->sequence_number,
4040                   &buf[ENCRYPTED_HEADER_SIZE],
4041                   size - ENCRYPTED_HEADER_SIZE))
4042     return;
4043   pt = (struct EncryptedMessage *) buf;
4044
4045   /* validate sequence number */
4046   snum = ntohl (pt->sequence_number);
4047   if (n->last_sequence_number_received == snum)
4048     {
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)"),
4054                              size,
4055                              GNUNET_NO);      
4056       return;
4057     }
4058   if ((n->last_sequence_number_received > snum) &&
4059       (n->last_sequence_number_received - snum > 32))
4060     {
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)"),
4066                              size,
4067                              GNUNET_NO);      
4068       return;
4069     }
4070   if (n->last_sequence_number_received > snum)
4071     {
4072       unsigned int rotbit =
4073         1 << (n->last_sequence_number_received - snum - 1);
4074       if ((n->last_packets_bitmap & rotbit) != 0)
4075         {
4076           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4077                       "Received duplicate message, ignoring.\n");
4078           GNUNET_STATISTICS_set (stats,
4079                                  gettext_noop ("# bytes dropped (duplicates)"),
4080                                  size,
4081                                  GNUNET_NO);      
4082           /* duplicate, ignore */
4083           return;
4084         }
4085       n->last_packets_bitmap |= rotbit;
4086     }
4087   if (n->last_sequence_number_received < snum)
4088     {
4089       int shift = (snum - n->last_sequence_number_received);
4090       if (shift >= 8 * sizeof(n->last_packets_bitmap))
4091         n->last_packets_bitmap = 0;
4092       else
4093         n->last_packets_bitmap <<= shift;
4094       n->last_sequence_number_received = snum;
4095     }
4096
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)
4100     {
4101       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4102                   _
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)"),
4107                              size,
4108                              GNUNET_NO);      
4109       return;
4110     }
4111
4112   /* process decrypted message(s) */
4113   if (n->bw_out_external_limit.value__ != pt->inbound_bw_limit.value__)
4114     {
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));
4120 #endif
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,
4125                                              n->bw_out);
4126       GNUNET_TRANSPORT_set_quota (transport,
4127                                   &n->peer,
4128                                   n->bw_in,
4129                                   n->bw_out);
4130     }
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);
4134   n->keep_alive_task 
4135     = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
4136                                     &send_keep_alive,
4137                                     n);
4138   GNUNET_STATISTICS_update (stats,
4139                             gettext_noop ("# bytes of payload decrypted"),
4140                             size - sizeof (struct EncryptedMessage),
4141                             GNUNET_NO);
4142   handle_peer_status_change (n);
4143   update_neighbour_performance (n, ats, ats_count);
4144   if (GNUNET_OK != GNUNET_SERVER_mst_receive (mst, 
4145                                               n,
4146                                               &buf[sizeof (struct EncryptedMessage)], 
4147                                               size - sizeof (struct EncryptedMessage),
4148                                               GNUNET_YES, GNUNET_NO))
4149     GNUNET_break_op (0);
4150 }
4151
4152
4153 /**
4154  * Function called by the transport for each received message.
4155  *
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)
4161  */
4162 static void
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, 
4167                           uint32_t ats_count)
4168 {
4169   struct Neighbour *n;
4170   struct GNUNET_TIME_Absolute now;
4171   int up;
4172   uint16_t type;
4173   uint16_t size;
4174   int changed;
4175
4176 #if DEBUG_CORE > 1
4177   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4178               "Received message of type %u from `%4s', demultiplexing.\n",
4179               (unsigned int) ntohs (message->type), 
4180               GNUNET_i2s (peer));
4181 #endif
4182   if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
4183     {
4184       GNUNET_break (0);
4185       return;
4186     }
4187   n = find_neighbour (peer);
4188   if (n == NULL)
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);
4194   switch (type)
4195     {
4196     case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
4197       if (size != sizeof (struct SetKeyMessage))
4198         {
4199           GNUNET_break_op (0);
4200           return;
4201         }
4202       GNUNET_STATISTICS_update (stats,
4203                                 gettext_noop ("# session keys received"), 
4204                                 1, 
4205                                 GNUNET_NO);
4206       handle_set_key (n,
4207                       (const struct SetKeyMessage *) message,
4208                       ats, ats_count);
4209       break;
4210     case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
4211       if (size < sizeof (struct EncryptedMessage) +
4212           sizeof (struct GNUNET_MessageHeader))
4213         {
4214           GNUNET_break_op (0);
4215           return;
4216         }
4217       if ((n->status != PEER_STATE_KEY_RECEIVED) &&
4218           (n->status != PEER_STATE_KEY_CONFIRMED))
4219         {
4220           GNUNET_STATISTICS_update (stats,
4221                                     gettext_noop ("# failed to decrypt message (no session key)"), 
4222                                     1, 
4223                                     GNUNET_NO);
4224           send_key (n);
4225           return;
4226         }
4227       handle_encrypted_message (n, 
4228                                 (const struct EncryptedMessage *) message,
4229                                 ats, ats_count);
4230       break;
4231     case GNUNET_MESSAGE_TYPE_CORE_PING:
4232       if (size != sizeof (struct PingMessage))
4233         {
4234           GNUNET_break_op (0);
4235           return;
4236         }
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))
4240         {
4241 #if DEBUG_CORE > 1
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));
4245 #endif
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));
4249           return;
4250         }
4251       handle_ping (n, (const struct PingMessage *) message,
4252                    ats, ats_count);
4253       break;
4254     case GNUNET_MESSAGE_TYPE_CORE_PONG:
4255       if (size != sizeof (struct PongMessage))
4256         {
4257           GNUNET_break_op (0);
4258           return;
4259         }
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) )
4263         {
4264 #if DEBUG_CORE > 1
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));
4268 #endif
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));
4272           return;
4273         }
4274       handle_pong (n, (const struct PongMessage *) message,
4275                    ats, ats_count);
4276       break;
4277     default:
4278       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4279                   _("Unsupported message of type %u received.\n"),
4280                   (unsigned int) type);
4281       return;
4282     }
4283   if (n->status == PEER_STATE_KEY_CONFIRMED)
4284     {
4285       now = GNUNET_TIME_absolute_get ();
4286       n->last_activity = now;
4287       changed = GNUNET_YES;
4288       if (!up)
4289         {
4290           GNUNET_STATISTICS_update (stats, 
4291                                     gettext_noop ("# established sessions"), 
4292                                     1, 
4293                                     GNUNET_NO);
4294           n->time_established = now;
4295         }
4296       if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
4297         GNUNET_SCHEDULER_cancel (n->keep_alive_task);
4298       n->keep_alive_task 
4299         = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
4300                                         &send_keep_alive,
4301                                         n);
4302     }
4303   if (changed)
4304     handle_peer_status_change (n);
4305 }
4306
4307
4308 /**
4309  * Function that recalculates the bandwidth quota for the
4310  * given neighbour and transmits it to the transport service.
4311  * 
4312  * @param cls neighbour for the quota update
4313  * @param tc context
4314  */
4315 static void
4316 neighbour_quota_update (void *cls,
4317                         const struct GNUNET_SCHEDULER_TaskContext *tc)
4318 {
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;
4323   double pref_rel;
4324   double share;
4325   unsigned long long distributable;
4326   uint64_t need_per_peer;
4327   uint64_t need_per_second;
4328   unsigned int neighbour_count;
4329
4330 #if DEBUG_CORE > 1
4331   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4332               "Neighbour quota update calculation running for peer `%4s'\n",
4333               GNUNET_i2s (&n->peer));  
4334 #endif
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)
4342     return;
4343   if (preference_sum == 0)
4344     {
4345       pref_rel = 1.0 / (double) neighbour_count;
4346     }
4347   else
4348     {
4349       pref_rel = (double) n->current_preference / preference_sum;
4350     }
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;
4354
4355   /* calculate inbound bandwidth per peer */
4356   distributable = 0;
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);
4362   else
4363     q_in = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4364
4365   /* calculate outbound bandwidth per peer */
4366   distributable = 0;
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);
4372   else
4373     q_out = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4374   n->bw_out_internal_limit = q_out;
4375
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);
4378
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) )
4382     {
4383 #if DEBUG_CORE
4384       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4385                   "Forcing disconnect of `%4s' due to inactivity\n",
4386                   GNUNET_i2s (&n->peer));
4387 #endif
4388       q_in = GNUNET_BANDWIDTH_value_init (0); /* force disconnect */
4389     }
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__));
4399   #endif
4400   if ((n->bw_in.value__ != q_in.value__) || (n->bw_out.value__ != q_out_min.value__))
4401     {
4402           if (n->bw_in.value__ != q_in.value__)
4403                   n->bw_in = q_in;
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,
4408                                     &n->peer,
4409                                     n->bw_in,
4410                                     n->bw_out);
4411       handle_peer_status_change (n);
4412     }
4413   schedule_quota_update (n);
4414 }
4415
4416
4417 /**
4418  * Function called by transport to notify us that
4419  * a peer connected to us (on the network level).
4420  *
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)
4425  */
4426 static void
4427 handle_transport_notify_connect (void *cls,
4428                                  const struct GNUNET_PeerIdentity *peer,
4429                                  const struct GNUNET_TRANSPORT_ATS_Information *ats,
4430                                  uint32_t ats_count)
4431 {
4432   struct Neighbour *n;
4433
4434   if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
4435     {
4436       GNUNET_break (0);
4437       return;
4438     }
4439   n = find_neighbour (peer);
4440   if (n != NULL)
4441     {
4442       if (GNUNET_YES == n->is_connected)
4443         {
4444           /* duplicate connect notification!? */
4445           GNUNET_break (0);
4446           return;
4447         }
4448     }
4449   else
4450     {
4451       n = create_neighbour (peer);
4452     }
4453   GNUNET_STATISTICS_update (stats, 
4454                             gettext_noop ("# peers connected (transport)"), 
4455                             1, 
4456                             GNUNET_NO);
4457   n->is_connected = GNUNET_YES;      
4458   update_neighbour_performance (n, ats, ats_count);
4459   GNUNET_BANDWIDTH_tracker_init (&n->available_send_window,
4460                                  n->bw_out,
4461                                  MAX_WINDOW_TIME_S);
4462   GNUNET_BANDWIDTH_tracker_init (&n->available_recv_window,
4463                                  n->bw_in,
4464                                  MAX_WINDOW_TIME_S);  
4465 #if DEBUG_CORE
4466   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4467               "Received connection from `%4s'.\n",
4468               GNUNET_i2s (&n->peer));
4469 #endif
4470   GNUNET_TRANSPORT_set_quota (transport,
4471                               &n->peer,
4472                               n->bw_in,
4473                               n->bw_out);
4474   send_key (n); 
4475 }
4476
4477
4478 /**
4479  * Function called by transport telling us that a peer
4480  * disconnected.
4481  *
4482  * @param cls closure
4483  * @param peer the peer that disconnected
4484  */
4485 static void
4486 handle_transport_notify_disconnect (void *cls,
4487                                     const struct GNUNET_PeerIdentity *peer)
4488 {
4489   struct DisconnectNotifyMessage cnm;
4490   struct Neighbour *n;
4491   struct ClientActiveRequest *car;
4492   struct GNUNET_TIME_Relative left;
4493
4494 #if DEBUG_CORE
4495   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4496               "Peer `%4s' disconnected from us; received notification from transport.\n", 
4497               GNUNET_i2s (peer));
4498 #endif
4499   n = find_neighbour (peer);
4500   if (n == NULL)
4501     {
4502       GNUNET_break (0);
4503       return;
4504     }
4505   GNUNET_break (n->is_connected == GNUNET_YES);
4506   if (n->status == PEER_STATE_KEY_CONFIRMED)
4507     {
4508       cnm.header.size = htons (sizeof (struct DisconnectNotifyMessage));
4509       cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
4510       cnm.reserved = htonl (0);
4511       cnm.peer = *peer;
4512       send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_DISCONNECT);
4513       GNUNET_STATISTICS_update (stats, 
4514                                 gettext_noop ("# established sessions"), 
4515                                 -1, 
4516                                 GNUNET_NO);
4517     }
4518
4519   /* On transport disconnect transport doesn't cancel requests, so must do so here. */
4520   if (n->th != NULL)
4521     {
4522       GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
4523       n->th = NULL;
4524     }
4525   n->is_connected = GNUNET_NO;
4526   n->status = PEER_STATE_DOWN;
4527   while (NULL != (car = n->active_client_request_head))
4528     {
4529       GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
4530                                    n->active_client_request_tail,
4531                                    car);
4532       GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
4533                                             &n->peer.hashPubKey,
4534                                             car);
4535       GNUNET_free (car);
4536     }
4537
4538   GNUNET_STATISTICS_update (stats, 
4539                             gettext_noop ("# peers connected (transport)"), 
4540                             -1, 
4541                             GNUNET_NO);
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 (), 
4547                                                     left);
4548   n->dead_clean_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT,
4549                                                      &consider_free_task,
4550                                                      n);
4551 }
4552
4553
4554 /**
4555  * Wrapper around 'free_neighbour'; helper for 'cleaning_task'.
4556  */
4557 static int
4558 free_neighbour_helper (void *cls,
4559                        const GNUNET_HashCode *key,
4560                        void *value)
4561 {
4562   struct Neighbour *n = value;
4563
4564   free_neighbour (n);
4565   return GNUNET_OK;
4566 }
4567
4568
4569 /**
4570  * Last task run during shutdown.  Disconnects us from
4571  * the transport.
4572  */
4573 static void
4574 cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4575 {
4576   struct Client *c;
4577
4578 #if DEBUG_CORE
4579   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4580               "Core service shutting down.\n");
4581 #endif
4582   GNUNET_assert (transport != NULL);
4583   GNUNET_TRANSPORT_disconnect (transport);
4584   transport = NULL;
4585   GNUNET_CONTAINER_multihashmap_iterate (neighbours,
4586                                          &free_neighbour_helper,
4587                                          NULL);
4588   GNUNET_CONTAINER_multihashmap_destroy (neighbours);
4589   neighbours = NULL;
4590   GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), 0, GNUNET_NO);
4591   GNUNET_SERVER_notification_context_destroy (notifier);
4592   notifier = NULL;
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);
4597   if (stats != NULL)
4598     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
4599   if (peerinfo != NULL)
4600     GNUNET_PEERINFO_disconnect (peerinfo);
4601   if (mst != NULL)
4602     GNUNET_SERVER_mst_destroy (mst);
4603 }
4604
4605
4606 /**
4607  * Initiate core service.
4608  *
4609  * @param cls closure
4610  * @param server the initialized server
4611  * @param c configuration to use
4612  */
4613 static void
4614 run (void *cls,
4615      struct GNUNET_SERVER_Handle *server,
4616      const struct GNUNET_CONFIGURATION_Handle *c)
4617 {
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)},
4638     {NULL, NULL, 0, 0}
4639   };
4640   char *keyfile;
4641
4642   cfg = c;    
4643   /* parse configuration */
4644   if (
4645        (GNUNET_OK !=
4646         GNUNET_CONFIGURATION_get_value_number (c,
4647                                                "CORE",
4648                                                "TOTAL_QUOTA_IN",
4649                                                &bandwidth_target_in_bps)) ||
4650        (GNUNET_OK !=
4651         GNUNET_CONFIGURATION_get_value_number (c,
4652                                                "CORE",
4653                                                "TOTAL_QUOTA_OUT",
4654                                                &bandwidth_target_out_bps)) ||
4655        (GNUNET_OK !=
4656         GNUNET_CONFIGURATION_get_value_filename (c,
4657                                                  "GNUNETD",
4658                                                  "HOSTKEY", &keyfile)))
4659     {
4660       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4661                   _
4662                   ("Core service is lacking key configuration settings.  Exiting.\n"));
4663       GNUNET_SCHEDULER_shutdown ();
4664       return;
4665     }
4666   peerinfo = GNUNET_PEERINFO_connect (cfg);
4667   if (NULL == peerinfo)
4668     {
4669       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4670                   _("Could not access PEERINFO service.  Exiting.\n"));
4671       GNUNET_SCHEDULER_shutdown ();
4672       GNUNET_free (keyfile);
4673       return;
4674     }
4675   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
4676   GNUNET_free (keyfile);
4677   if (my_private_key == NULL)
4678     {
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 ();
4683       return;
4684     }
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, 
4696                                                         MAX_NOTIFY_QUEUE);
4697   GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
4698   /* setup transport connection */
4699   transport = GNUNET_TRANSPORT_connect (cfg,
4700                                         &my_identity,
4701                                         NULL,
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);
4707
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);
4710
4711   mst = GNUNET_SERVER_mst_create (&deliver_message,
4712                                   NULL);
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));
4719 }
4720
4721
4722
4723 /**
4724  * The main function for the transport service.
4725  *
4726  * @param argc number of arguments from the command line
4727  * @param argv command line arguments
4728  * @return 0 ok, 1 on error
4729  */
4730 int
4731 main (int argc, char *const *argv)
4732 {
4733   return (GNUNET_OK ==
4734           GNUNET_SERVICE_run (argc,
4735                               argv,
4736                               "core",
4737                               GNUNET_SERVICE_OPTION_NONE,
4738                               &run, NULL)) ? 0 : 1;
4739 }
4740
4741 /* end of gnunet-service-core.c */