pass ATS data to clients
[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   PEER_STATE_DOWN,
157   PEER_STATE_KEY_SENT,
158   PEER_STATE_KEY_RECEIVED,
159   PEER_STATE_KEY_CONFIRMED
160 };
161
162
163 /**
164  * Encapsulation for encrypted messages exchanged between
165  * peers.  Followed by the actual encrypted data.
166  */
167 struct EncryptedMessage
168 {
169   /**
170    * Message type is either CORE_ENCRYPTED_MESSAGE.
171    */
172   struct GNUNET_MessageHeader header;
173
174   /**
175    * Random value used for IV generation.
176    */
177   uint32_t iv_seed GNUNET_PACKED;
178
179   /**
180    * MAC of the encrypted message (starting at 'sequence_number'),
181    * used to verify message integrity. Everything after this value
182    * (excluding this value itself) will be encrypted and authenticated.
183    * ENCRYPTED_HEADER_SIZE must be set to the offset of the *next* field.
184    */
185   GNUNET_HashCode hmac;
186
187   /**
188    * Sequence number, in network byte order.  This field
189    * must be the first encrypted/decrypted field
190    */
191   uint32_t sequence_number GNUNET_PACKED;
192
193   /**
194    * Desired bandwidth (how much we should send to this peer / how
195    * much is the sender willing to receive)?
196    */
197   struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
198
199   /**
200    * Timestamp.  Used to prevent reply of ancient messages
201    * (recent messages are caught with the sequence number).
202    */
203   struct GNUNET_TIME_AbsoluteNBO timestamp;
204
205 };
206
207
208 /**
209  * Number of bytes (at the beginning) of "struct EncryptedMessage"
210  * that are NOT encrypted.
211  */
212 #define ENCRYPTED_HEADER_SIZE (offsetof(struct EncryptedMessage, sequence_number))
213
214
215 /**
216  * We're sending an (encrypted) PING to the other peer to check if he
217  * can decrypt.  The other peer should respond with a PONG with the
218  * same content, except this time encrypted with the receiver's key.
219  */
220 struct PingMessage
221 {
222   /**
223    * Message type is CORE_PING.
224    */
225   struct GNUNET_MessageHeader header;
226   
227   /**
228    * Seed for the IV
229    */
230   uint32_t iv_seed GNUNET_PACKED;
231
232   /**
233    * Intended target of the PING, used primarily to check
234    * that decryption actually worked.
235    */
236   struct GNUNET_PeerIdentity target;
237
238   /**
239    * Random number chosen to make reply harder.
240    */
241   uint32_t challenge GNUNET_PACKED;
242 };
243
244
245
246 /**
247  * Response to a PING.  Includes data from the original PING
248  * plus initial bandwidth quota information.
249  */
250 struct PongMessage
251 {
252   /**
253    * Message type is CORE_PONG.
254    */
255   struct GNUNET_MessageHeader header;
256     
257   /**
258    * Seed for the IV
259    */
260   uint32_t iv_seed GNUNET_PACKED;
261
262   /**
263    * Random number to make faking the reply harder.  Must be
264    * first field after header (this is where we start to encrypt!).
265    */
266   uint32_t challenge GNUNET_PACKED;
267
268   /**
269    * Desired bandwidth (how much we should send to this
270    * peer / how much is the sender willing to receive).
271    */
272   struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
273
274   /**
275    * Intended target of the PING, used primarily to check
276    * that decryption actually worked.
277    */
278   struct GNUNET_PeerIdentity target;
279 };
280
281
282 /**
283  * Message transmitted to set (or update) a session key.
284  */
285 struct SetKeyMessage
286 {
287
288   /**
289    * Message type is either CORE_SET_KEY.
290    */
291   struct GNUNET_MessageHeader header;
292
293   /**
294    * Status of the sender (should be in "enum PeerStateMachine"), nbo.
295    */
296   int32_t sender_status GNUNET_PACKED;
297
298   /**
299    * Purpose of the signature, will be
300    * GNUNET_SIGNATURE_PURPOSE_SET_KEY.
301    */
302   struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
303
304   /**
305    * At what time was this key created?
306    */
307   struct GNUNET_TIME_AbsoluteNBO creation_time;
308
309   /**
310    * The encrypted session key.
311    */
312   struct GNUNET_CRYPTO_RsaEncryptedData encrypted_key;
313
314   /**
315    * Who is the intended recipient?
316    */
317   struct GNUNET_PeerIdentity target;
318
319   /**
320    * Signature of the stuff above (starting at purpose).
321    */
322   struct GNUNET_CRYPTO_RsaSignature signature;
323
324 };
325
326
327 /**
328  * Message waiting for transmission. This struct
329  * is followed by the actual content of the message.
330  */
331 struct MessageEntry
332 {
333
334   /**
335    * We keep messages in a doubly linked list.
336    */
337   struct MessageEntry *next;
338
339   /**
340    * We keep messages in a doubly linked list.
341    */
342   struct MessageEntry *prev;
343
344   /**
345    * By when are we supposed to transmit this message?
346    */
347   struct GNUNET_TIME_Absolute deadline;
348
349   /**
350    * By when are we supposed to transmit this message (after
351    * giving slack)?
352    */
353   struct GNUNET_TIME_Absolute slack_deadline;
354
355   /**
356    * How important is this message to us?
357    */
358   unsigned int priority;
359
360   /**
361    * If this is a SET_KEY message, what was our connection status when this
362    * message was queued?
363    */
364   enum PeerStateMachine sender_status;
365
366   /**
367    * Is this a SET_KEY message?
368    */
369   int is_setkey;
370
371   /**
372    * How long is the message? (number of bytes following
373    * the "struct MessageEntry", but not including the
374    * size of "struct MessageEntry" itself!)
375    */
376   uint16_t size;
377
378   /**
379    * Was this message selected for transmission in the
380    * current round? GNUNET_YES or GNUNET_NO.
381    */
382   int8_t do_transmit;
383
384   /**
385    * Did we give this message some slack (delayed sending) previously
386    * (and hence should not give it any more slack)? GNUNET_YES or
387    * GNUNET_NO.
388    */
389   int8_t got_slack;
390
391 };
392
393
394 /**
395  * Record kept for each request for transmission issued by a 
396  * client that is still pending.
397  */
398 struct ClientActiveRequest;
399
400 /**
401  * Data kept per neighbouring peer.
402  */
403 struct Neighbour
404 {
405   /**
406    * We keep neighbours in a linked list (for now).
407    */
408   struct Neighbour *next;
409
410   /**
411    * Unencrypted messages destined for this peer.
412    */
413   struct MessageEntry *messages;
414
415   /**
416    * Head of the batched, encrypted message queue (already ordered,
417    * transmit starting with the head).
418    */
419   struct MessageEntry *encrypted_head;
420
421   /**
422    * Tail of the batched, encrypted message queue (already ordered,
423    * append new messages to tail)
424    */
425   struct MessageEntry *encrypted_tail;
426
427   /**
428    * Head of list of requests from clients for transmission to 
429    * this peer.
430    */
431   struct ClientActiveRequest *active_client_request_head;
432
433   /**
434    * Tail of list of requests from clients for transmission to 
435    * this peer.
436    */
437   struct ClientActiveRequest *active_client_request_tail;
438
439   /**
440    * Handle for pending requests for transmission to this peer
441    * with the transport service.  NULL if no request is pending.
442    */
443   struct GNUNET_TRANSPORT_TransmitHandle *th;
444
445   /**
446    * Public key of the neighbour, NULL if we don't have it yet.
447    */
448   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
449
450   /**
451    * We received a PING message before we got the "public_key"
452    * (or the SET_KEY).  We keep it here until we have a key
453    * to decrypt it.  NULL if no PING is pending.
454    */
455   struct PingMessage *pending_ping;
456
457   /**
458    * We received a PONG message before we got the "public_key"
459    * (or the SET_KEY).  We keep it here until we have a key
460    * to decrypt it.  NULL if no PONG is pending.
461    */
462   struct PongMessage *pending_pong;
463
464   /**
465    * Non-NULL if we are currently looking up HELLOs for this peer.
466    * for this peer.
467    */
468   struct GNUNET_PEERINFO_IteratorContext *pitr;
469
470   /**
471    * SetKeyMessage to transmit, NULL if we are not currently trying
472    * to send one.
473    */
474   struct SetKeyMessage *skm;
475
476   /**
477    * Performance data for the peer.
478    */ 
479   struct GNUNET_TRANSPORT_ATS_Information *ats;
480
481   /**
482    * Identity of the neighbour.
483    */
484   struct GNUNET_PeerIdentity peer;
485
486   /**
487    * Key we use to encrypt our messages for the other peer
488    * (initialized by us when we do the handshake).
489    */
490   struct GNUNET_CRYPTO_AesSessionKey encrypt_key;
491
492   /**
493    * Key we use to decrypt messages from the other peer
494    * (given to us by the other peer during the handshake).
495    */
496   struct GNUNET_CRYPTO_AesSessionKey decrypt_key;
497
498   /**
499    * ID of task used for re-trying plaintext scheduling.
500    */
501   GNUNET_SCHEDULER_TaskIdentifier retry_plaintext_task;
502
503   /**
504    * ID of task used for re-trying SET_KEY and PING message.
505    */
506   GNUNET_SCHEDULER_TaskIdentifier retry_set_key_task;
507
508   /**
509    * ID of task used for updating bandwidth quota for this neighbour.
510    */
511   GNUNET_SCHEDULER_TaskIdentifier quota_update_task;
512
513   /**
514    * ID of task used for sending keep-alive pings.
515    */
516   GNUNET_SCHEDULER_TaskIdentifier keep_alive_task;
517
518   /**
519    * ID of task used for cleaning up dead neighbour entries.
520    */
521   GNUNET_SCHEDULER_TaskIdentifier dead_clean_task;
522
523   /**
524    * At what time did we generate our encryption key?
525    */
526   struct GNUNET_TIME_Absolute encrypt_key_created;
527
528   /**
529    * At what time did the other peer generate the decryption key?
530    */
531   struct GNUNET_TIME_Absolute decrypt_key_created;
532
533   /**
534    * At what time did we initially establish (as in, complete session
535    * key handshake) this connection?  Should be zero if status != KEY_CONFIRMED.
536    */
537   struct GNUNET_TIME_Absolute time_established;
538
539   /**
540    * At what time did we last receive an encrypted message from the
541    * other peer?  Should be zero if status != KEY_CONFIRMED.
542    */
543   struct GNUNET_TIME_Absolute last_activity;
544
545   /**
546    * At what frequency are we currently re-trying SET_KEY messages?
547    */
548   struct GNUNET_TIME_Relative set_key_retry_frequency;
549
550   /**
551    * Tracking bandwidth for sending to this peer.
552    */
553   struct GNUNET_BANDWIDTH_Tracker available_send_window;
554
555   /**
556    * Tracking bandwidth for receiving from this peer.
557    */
558   struct GNUNET_BANDWIDTH_Tracker available_recv_window;
559
560   /**
561    * How valueable were the messages of this peer recently?
562    */
563   unsigned long long current_preference;
564
565   /**
566    * Number of entries in 'ats'.
567    */ 
568   unsigned int ats_count;
569
570   /**
571    * Bit map indicating which of the 32 sequence numbers before the last
572    * were received (good for accepting out-of-order packets and
573    * estimating reliability of the connection)
574    */
575   unsigned int last_packets_bitmap;
576
577   /**
578    * last sequence number received on this connection (highest)
579    */
580   uint32_t last_sequence_number_received;
581
582   /**
583    * last sequence number transmitted
584    */
585   uint32_t last_sequence_number_sent;
586
587   /**
588    * Available bandwidth in for this peer (current target).
589    */
590   struct GNUNET_BANDWIDTH_Value32NBO bw_in;    
591
592   /**
593    * Available bandwidth out for this peer (current target).
594    */
595   struct GNUNET_BANDWIDTH_Value32NBO bw_out;  
596
597   /**
598    * Internal bandwidth limit set for this peer (initially typically
599    * set to "-1").  Actual "bw_out" is MIN of
600    * "bpm_out_internal_limit" and "bw_out_external_limit".
601    */
602   struct GNUNET_BANDWIDTH_Value32NBO bw_out_internal_limit;
603
604   /**
605    * External bandwidth limit set for this peer by the
606    * peer that we are communicating with.  "bw_out" is MIN of
607    * "bw_out_internal_limit" and "bw_out_external_limit".
608    */
609   struct GNUNET_BANDWIDTH_Value32NBO bw_out_external_limit;
610
611   /**
612    * What was our PING challenge number (for this peer)?
613    */
614   uint32_t ping_challenge;
615
616   /**
617    * What is our connection status?
618    */
619   enum PeerStateMachine status;
620
621   /**
622    * Are we currently connected to this neighbour?
623    */ 
624   int is_connected;
625
626 };
627
628
629 /**
630  * Data structure for each client connected to the core service.
631  */
632 struct Client
633 {
634   /**
635    * Clients are kept in a linked list.
636    */
637   struct Client *next;
638
639   /**
640    * Handle for the client with the server API.
641    */
642   struct GNUNET_SERVER_Client *client_handle;
643
644   /**
645    * Array of the types of messages this peer cares
646    * about (with "tcnt" entries).  Allocated as part
647    * of this client struct, do not free!
648    */
649   const uint16_t *types;
650
651   /**
652    * Map of peer identities to active transmission requests of this
653    * client to the peer (of type 'struct ClientActiveRequest').
654    */
655   struct GNUNET_CONTAINER_MultiHashMap *requests;
656
657   /**
658    * Options for messages this client cares about,
659    * see GNUNET_CORE_OPTION_ values.
660    */
661   uint32_t options;
662
663   /**
664    * Number of types of incoming messages this client
665    * specifically cares about.  Size of the "types" array.
666    */
667   unsigned int tcnt;
668
669 };
670
671
672 /**
673  * Record kept for each request for transmission issued by a 
674  * client that is still pending.
675  */
676 struct ClientActiveRequest
677 {
678
679   /**
680    * Active requests are kept in a doubly-linked list of
681    * the respective target peer.
682    */
683   struct ClientActiveRequest *next;
684
685   /**
686    * Active requests are kept in a doubly-linked list of
687    * the respective target peer.
688    */
689   struct ClientActiveRequest *prev;
690
691   /**
692    * Handle to the client.
693    */
694   struct Client *client;
695
696   /**
697    * By what time would the client want to see this message out?
698    */
699   struct GNUNET_TIME_Absolute deadline;
700
701   /**
702    * How important is this request.
703    */
704   uint32_t priority;
705
706   /**
707    * How many more requests does this client have?
708    */
709   uint32_t queue_size;
710
711   /**
712    * How many bytes does the client intend to send?
713    */
714   uint16_t msize;
715
716   /**
717    * Unique request ID (in big endian).
718    */
719   uint16_t smr_id;
720   
721 };
722
723
724
725 /**
726  * Our public key.
727  */
728 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
729
730 /**
731  * Our identity.
732  */
733 static struct GNUNET_PeerIdentity my_identity;
734
735 /**
736  * Our private key.
737  */
738 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
739
740
741 /**
742  * Handle to peerinfo service.
743  */
744 static struct GNUNET_PEERINFO_Handle *peerinfo;
745
746 /**
747  * Our message stream tokenizer (for encrypted payload).
748  */
749 static struct GNUNET_SERVER_MessageStreamTokenizer *mst;
750
751 /**
752  * Our configuration.
753  */
754 const struct GNUNET_CONFIGURATION_Handle *cfg;
755
756 /**
757  * Transport service.
758  */
759 static struct GNUNET_TRANSPORT_Handle *transport;
760
761 /**
762  * Linked list of our clients.
763  */
764 static struct Client *clients;
765
766 /**
767  * Context for notifications we need to send to our clients.
768  */
769 static struct GNUNET_SERVER_NotificationContext *notifier;
770
771 /**
772  * We keep neighbours in a linked list (for now).
773  */
774 static struct Neighbour *neighbours;
775
776 /**
777  * For creating statistics.
778  */
779 static struct GNUNET_STATISTICS_Handle *stats;
780
781 /**
782  * Sum of all preferences among all neighbours.
783  */
784 static unsigned long long preference_sum;
785
786 /**
787  * Total number of neighbours we have.
788  */
789 static unsigned int neighbour_count;
790
791 /**
792  * How much inbound bandwidth are we supposed to be using per second?
793  * FIXME: this value is not used!
794  */
795 static unsigned long long bandwidth_target_in_bps;
796
797 /**
798  * How much outbound bandwidth are we supposed to be using per second?
799  */
800 static unsigned long long bandwidth_target_out_bps;
801
802 /**
803  * Derive an authentication key from "set key" information
804  */
805 static void
806 derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
807     const struct GNUNET_CRYPTO_AesSessionKey *skey,
808     uint32_t seed,
809     struct GNUNET_TIME_Absolute creation_time)
810 {
811   static const char ctx[] = "authentication key";
812   struct GNUNET_TIME_AbsoluteNBO ctbe;
813
814
815   ctbe = GNUNET_TIME_absolute_hton (creation_time);
816   GNUNET_CRYPTO_hmac_derive_key (akey,
817                                  skey,
818                                  &seed,
819                                  sizeof(seed),
820                                  &skey->key,
821                                  sizeof(skey->key),
822                                  &ctbe,
823                                  sizeof(ctbe),
824                                  ctx,
825                                  sizeof(ctx), NULL);
826 }
827
828
829 /**
830  * Derive an IV from packet information
831  */
832 static void
833 derive_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
834     const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed,
835     const struct GNUNET_PeerIdentity *identity)
836 {
837   static const char ctx[] = "initialization vector";
838
839   GNUNET_CRYPTO_aes_derive_iv (iv,
840                                skey,
841                                &seed,
842                                sizeof(seed),
843                                &identity->hashPubKey.bits,
844                                sizeof(identity->hashPubKey.bits),
845                                ctx,
846                                sizeof(ctx), NULL);
847 }
848
849 /**
850  * Derive an IV from pong packet information
851  */
852 static void
853 derive_pong_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
854     const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed,
855     uint32_t challenge, const struct GNUNET_PeerIdentity *identity)
856 {
857   static const char ctx[] = "pong initialization vector";
858
859   GNUNET_CRYPTO_aes_derive_iv (iv,
860                                skey,
861                                &seed,
862                                sizeof(seed),
863                                &identity->hashPubKey.bits,
864                                sizeof(identity->hashPubKey.bits),
865                                &challenge,
866                                sizeof(challenge),
867                                ctx,
868                                sizeof(ctx), NULL);
869 }
870
871
872 /**
873  * At what time should the connection to the given neighbour
874  * time out (given no further activity?)
875  *
876  * @param n neighbour in question
877  * @return absolute timeout
878  */
879 static struct GNUNET_TIME_Absolute 
880 get_neighbour_timeout (struct Neighbour *n)
881 {
882   return GNUNET_TIME_absolute_add (n->last_activity,
883                                    GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
884 }
885
886
887 /**
888  * A preference value for a neighbour was update.  Update
889  * the preference sum accordingly.
890  *
891  * @param inc how much was a preference value increased?
892  */
893 static void
894 update_preference_sum (unsigned long long inc)
895 {
896   struct Neighbour *n;
897   unsigned long long os;
898
899   os = preference_sum;
900   preference_sum += inc;
901   if (preference_sum >= os)
902     return; /* done! */
903   /* overflow! compensate by cutting all values in half! */
904   preference_sum = 0;
905   n = neighbours;
906   while (n != NULL)
907     {
908       n->current_preference /= 2;
909       preference_sum += n->current_preference;
910       n = n->next;
911     }    
912   GNUNET_STATISTICS_set (stats, gettext_noop ("# total peer preference"), preference_sum, GNUNET_NO);
913 }
914
915
916 /**
917  * Find the entry for the given neighbour.
918  *
919  * @param peer identity of the neighbour
920  * @return NULL if we are not connected, otherwise the
921  *         neighbour's entry.
922  */
923 static struct Neighbour *
924 find_neighbour (const struct GNUNET_PeerIdentity *peer)
925 {
926   struct Neighbour *ret;
927
928   ret = neighbours;
929   while ((ret != NULL) &&
930          (0 != memcmp (&ret->peer,
931                        peer, sizeof (struct GNUNET_PeerIdentity))))
932     ret = ret->next;
933   return ret;
934 }
935
936
937 /**
938  * Send a message to one of our clients.
939  *
940  * @param client target for the message
941  * @param msg message to transmit
942  * @param can_drop could this message be dropped if the
943  *        client's queue is getting too large?
944  */
945 static void
946 send_to_client (struct Client *client,
947                 const struct GNUNET_MessageHeader *msg, 
948                 int can_drop)
949 {
950 #if DEBUG_CORE_CLIENT
951   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
952               "Preparing to send %u bytes of message of type %u to client.\n",
953               (unsigned int) ntohs (msg->size),
954               (unsigned int) ntohs (msg->type));
955 #endif  
956   GNUNET_SERVER_notification_context_unicast (notifier,
957                                               client->client_handle,
958                                               msg,
959                                               can_drop);
960 }
961
962
963 /**
964  * Send a message to all of our current clients that have
965  * the right options set.
966  * 
967  * @param msg message to multicast
968  * @param can_drop can this message be discarded if the queue is too long
969  * @param options mask to use 
970  */
971 static void
972 send_to_all_clients (const struct GNUNET_MessageHeader *msg, 
973                      int can_drop,
974                      int options)
975 {
976   struct Client *c;
977
978   c = clients;
979   while (c != NULL)
980     {
981       if (0 != (c->options & options))
982         {
983 #if DEBUG_CORE_CLIENT
984           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
985                       "Sending message of type %u to client.\n",
986                       (unsigned int) ntohs (msg->type));
987 #endif
988           send_to_client (c, msg, can_drop);
989         }
990       c = c->next;
991     }
992 }
993
994
995 /**
996  * Function called by transport telling us that a peer
997  * changed status.
998  *
999  * @param n the peer that changed status
1000  */
1001 static void
1002 handle_peer_status_change (struct Neighbour *n)
1003 {
1004   struct PeerStatusNotifyMessage psnm;
1005
1006   if ( (! n->is_connected) ||
1007        (n->status != PEER_STATE_KEY_CONFIRMED) )
1008     return;
1009 #if DEBUG_CORE
1010   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1011               "Peer `%4s' changed status\n",
1012               GNUNET_i2s (&n->peer));
1013 #endif
1014   psnm.header.size = htons (sizeof (struct PeerStatusNotifyMessage));
1015   psnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE);
1016   psnm.ats_count = htonl (0);
1017   psnm.ats.type = htonl (0);
1018   psnm.ats.value = htonl (0);
1019   psnm.timeout = GNUNET_TIME_absolute_hton (get_neighbour_timeout (n));
1020   psnm.bandwidth_in = n->bw_in;
1021   psnm.bandwidth_out = n->bw_out;
1022   psnm.peer = n->peer;
1023   send_to_all_clients (&psnm.header, 
1024                        GNUNET_YES, 
1025                        GNUNET_CORE_OPTION_SEND_STATUS_CHANGE);
1026   GNUNET_STATISTICS_update (stats, 
1027                             gettext_noop ("# peer status changes"), 
1028                             1, 
1029                             GNUNET_NO);
1030 }
1031
1032
1033 /**
1034  * Go over our message queue and if it is not too long, go
1035  * over the pending requests from clients for this
1036  * neighbour and send some clients a 'READY' notification.
1037  *
1038  * @param n which peer to process
1039  */
1040 static void
1041 schedule_peer_messages (struct Neighbour *n)
1042 {
1043   struct SendMessageReady smr;
1044   struct ClientActiveRequest *car;
1045   struct ClientActiveRequest *pos;
1046   struct Client *c;
1047   struct MessageEntry *mqe;
1048   unsigned int queue_size;
1049   
1050   /* check if neighbour queue is empty enough! */
1051   queue_size = 0;
1052   mqe = n->messages;
1053   while (mqe != NULL) 
1054     {
1055       queue_size++;
1056       mqe = mqe->next;
1057     }
1058   if (queue_size >= MAX_PEER_QUEUE_SIZE)
1059     {
1060 #if DEBUG_CORE_CLIENT
1061       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1062                   "Not considering client transmission requests: queue full\n");
1063 #endif
1064       return; /* queue still full */
1065     }
1066   /* find highest priority request */
1067   pos = n->active_client_request_head;
1068   car = NULL;
1069   while (pos != NULL)
1070     {
1071       if ( (car == NULL) ||
1072            (pos->priority > car->priority) )
1073         car = pos;
1074       pos = pos->next;
1075     }
1076   if (car == NULL)
1077     return; /* no pending requests */
1078 #if DEBUG_CORE_CLIENT
1079   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080               "Permitting client transmission request to `%s'\n",
1081               GNUNET_i2s (&n->peer));
1082 #endif
1083   c = car->client;
1084   GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1085                                n->active_client_request_tail,
1086                                car);
1087   GNUNET_CONTAINER_multihashmap_remove (c->requests,
1088                                         &n->peer.hashPubKey,
1089                                         car);  
1090   smr.header.size = htons (sizeof (struct SendMessageReady));
1091   smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
1092   smr.size = htons (car->msize);
1093   smr.smr_id = car->smr_id;
1094   smr.peer = n->peer;
1095   send_to_client (c, &smr.header, GNUNET_NO);
1096   GNUNET_free (car);
1097 }
1098
1099
1100 /**
1101  * Handle CORE_SEND_REQUEST message.
1102  */
1103 static void
1104 handle_client_send_request (void *cls,
1105                             struct GNUNET_SERVER_Client *client,
1106                             const struct GNUNET_MessageHeader *message)
1107 {
1108   const struct SendMessageRequest *req;
1109   struct Neighbour *n;
1110   struct Client *c;
1111   struct ClientActiveRequest *car;
1112
1113   req = (const struct SendMessageRequest*) message;
1114   n = find_neighbour (&req->peer);
1115   if ( (n == NULL) ||
1116        (GNUNET_YES != n->is_connected) ||
1117        (n->status != PEER_STATE_KEY_CONFIRMED) )
1118     { 
1119       /* neighbour must have disconnected since request was issued,
1120          ignore (client will realize it once it processes the 
1121          disconnect notification) */
1122 #if DEBUG_CORE_CLIENT
1123   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1124               "Dropped client request for transmission (am disconnected)\n");
1125 #endif
1126       GNUNET_STATISTICS_update (stats, 
1127                                 gettext_noop ("# send requests dropped (disconnected)"), 
1128                                 1, 
1129                                 GNUNET_NO);
1130       GNUNET_SERVER_receive_done (client, GNUNET_OK);
1131       return;
1132     }
1133   c = clients;
1134   while ( (c != NULL) &&
1135           (c->client_handle != client) )
1136     c = c->next;
1137   if (c == NULL)
1138     {
1139       /* client did not send INIT first! */
1140       GNUNET_break (0);
1141       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1142       return;
1143     }
1144   if (c->requests == NULL)
1145     c->requests = GNUNET_CONTAINER_multihashmap_create (16);
1146 #if DEBUG_CORE_CLIENT
1147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1148               "Received client transmission request. queueing\n");
1149 #endif
1150   car = GNUNET_CONTAINER_multihashmap_get (c->requests,
1151                                            &req->peer.hashPubKey);
1152   if (car == NULL)
1153     {
1154       /* create new entry */
1155       car = GNUNET_malloc (sizeof (struct ClientActiveRequest));
1156       GNUNET_assert (GNUNET_OK ==
1157                      GNUNET_CONTAINER_multihashmap_put (c->requests,
1158                                                         &req->peer.hashPubKey,
1159                                                         car,
1160                                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1161       GNUNET_CONTAINER_DLL_insert (n->active_client_request_head,
1162                                    n->active_client_request_tail,
1163                                    car);
1164       car->client = c;
1165     }
1166   car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline);
1167   car->priority = ntohl (req->priority);
1168   car->queue_size = ntohl (req->queue_size);
1169   car->msize = ntohs (req->size);
1170   car->smr_id = req->smr_id;
1171   schedule_peer_messages (n);
1172   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1173 }
1174
1175
1176 /**
1177  * Handle CORE_INIT request.
1178  */
1179 static void
1180 handle_client_init (void *cls,
1181                     struct GNUNET_SERVER_Client *client,
1182                     const struct GNUNET_MessageHeader *message)
1183 {
1184   const struct InitMessage *im;
1185   struct InitReplyMessage irm;
1186   struct Client *c;
1187   uint16_t msize;
1188   const uint16_t *types;
1189   uint16_t *wtypes;
1190   struct Neighbour *n;
1191   struct ConnectNotifyMessage *cnm;
1192   char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
1193   struct GNUNET_TRANSPORT_ATS_Information *ats;
1194   size_t size;
1195   unsigned int i;
1196
1197 #if DEBUG_CORE_CLIENT
1198   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1199               "Client connecting to core service with `%s' message\n",
1200               "INIT");
1201 #endif
1202   /* check that we don't have an entry already */
1203   c = clients;
1204   while (c != NULL)
1205     {
1206       if (client == c->client_handle)
1207         {
1208           GNUNET_break (0);
1209           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1210           return;
1211         }
1212       c = c->next;
1213     }
1214   msize = ntohs (message->size);
1215   if (msize < sizeof (struct InitMessage))
1216     {
1217       GNUNET_break (0);
1218       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1219       return;
1220     }
1221   GNUNET_SERVER_notification_context_add (notifier, client);
1222   im = (const struct InitMessage *) message;
1223   types = (const uint16_t *) &im[1];
1224   msize -= sizeof (struct InitMessage);
1225   c = GNUNET_malloc (sizeof (struct Client) + msize);
1226   c->client_handle = client;
1227   c->next = clients;
1228   clients = c;
1229   c->tcnt = msize / sizeof (uint16_t);
1230   c->types = (const uint16_t *) &c[1];
1231   wtypes = (uint16_t *) &c[1];
1232   for (i=0;i<c->tcnt;i++)
1233     wtypes[i] = ntohs (types[i]);
1234   c->options = ntohl (im->options);
1235 #if DEBUG_CORE_CLIENT
1236   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1237               "Client %p is interested in %u message types\n",
1238               c,
1239               (unsigned int) c->tcnt);
1240 #endif
1241   /* send init reply message */
1242   irm.header.size = htons (sizeof (struct InitReplyMessage));
1243   irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
1244   irm.reserved = htonl (0);
1245   memcpy (&irm.publicKey,
1246           &my_public_key,
1247           sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1248 #if DEBUG_CORE_CLIENT
1249   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1250               "Sending `%s' message to client.\n", "INIT_REPLY");
1251 #endif
1252   send_to_client (c, &irm.header, GNUNET_NO);
1253   if (0 != (c->options & GNUNET_CORE_OPTION_SEND_CONNECT))
1254     {
1255       /* notify new client about existing neighbours */
1256       n = neighbours;
1257       while (n != NULL)
1258         {
1259           size = sizeof (struct ConnectNotifyMessage) +
1260             (n->ats_count+1) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1261           if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1262             {
1263               GNUNET_break (0);
1264               /* recovery strategy: throw away performance data */
1265               GNUNET_array_grow (n->ats,
1266                                  n->ats_count,
1267                                  0);
1268               size = sizeof (struct ConnectNotifyMessage) +
1269                 (n->ats_count+1) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1270             }
1271           cnm = (struct ConnectNotifyMessage*) buf;       
1272           cnm->header.size = htons (size);
1273           cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1274           cnm->ats_count = htonl (n->ats_count);
1275           ats = &cnm->ats;
1276           memcpy (ats,
1277                   n->ats,
1278                   sizeof (struct GNUNET_TRANSPORT_ATS_Information) * n->ats_count);
1279           ats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1280           ats[n->ats_count].value = htonl (0);
1281           if (n->status == PEER_STATE_KEY_CONFIRMED)
1282             {
1283 #if DEBUG_CORE_CLIENT
1284               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1285                           "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
1286 #endif
1287               cnm->peer = n->peer;
1288               send_to_client (c, &cnm->header, GNUNET_NO);
1289             }
1290           n = n->next;
1291         }
1292     }
1293   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1294 }
1295
1296
1297 /**
1298  * Free client request records.
1299  *
1300  * @param cls NULL
1301  * @param key identity of peer for which this is an active request
1302  * @param value the 'struct ClientActiveRequest' to free
1303  * @return GNUNET_YES (continue iteration)
1304  */
1305 static int
1306 destroy_active_client_request (void *cls,
1307                                const GNUNET_HashCode *key,
1308                                void *value)
1309 {
1310   struct ClientActiveRequest *car = value;
1311   struct Neighbour *n;
1312   struct GNUNET_PeerIdentity peer;
1313
1314   peer.hashPubKey = *key;
1315   n = find_neighbour (&peer);
1316   GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1317                                n->active_client_request_tail,
1318                                car);
1319   GNUNET_free (car);
1320   return GNUNET_YES;
1321 }
1322
1323
1324 /**
1325  * A client disconnected, clean up.
1326  *
1327  * @param cls closure
1328  * @param client identification of the client
1329  */
1330 static void
1331 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1332 {
1333   struct Client *pos;
1334   struct Client *prev;
1335
1336   if (client == NULL)
1337     return;
1338 #if DEBUG_CORE_CLIENT
1339   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1340               "Client %p has disconnected from core service.\n",
1341               client);
1342 #endif
1343   prev = NULL;
1344   pos = clients;
1345   while (pos != NULL)
1346     {
1347       if (client == pos->client_handle)
1348         break;
1349       prev = pos;
1350       pos = pos->next;
1351     }
1352   if (pos == NULL)
1353     {
1354       /* client never sent INIT */
1355       return;
1356     }
1357   if (prev == NULL)
1358     clients = pos->next;
1359   else
1360     prev->next = pos->next;
1361   if (pos->requests != NULL)
1362     {
1363       GNUNET_CONTAINER_multihashmap_iterate (pos->requests,
1364                                              &destroy_active_client_request,
1365                                              NULL);
1366       GNUNET_CONTAINER_multihashmap_destroy (pos->requests);
1367     }
1368   GNUNET_free (pos);
1369 }
1370
1371
1372 /**
1373  * Handle CORE_ITERATE_PEERS request.
1374  */
1375 static void
1376 handle_client_iterate_peers (void *cls,
1377                              struct GNUNET_SERVER_Client *client,
1378                              const struct GNUNET_MessageHeader *message)
1379
1380 {
1381   struct Neighbour *n;
1382   struct ConnectNotifyMessage cnm;
1383   struct GNUNET_MessageHeader done_msg;
1384   struct GNUNET_SERVER_TransmitContext *tc;
1385
1386   /* notify new client about existing neighbours */
1387   cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
1388   cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1389   done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1390   done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1391   tc = GNUNET_SERVER_transmit_context_create (client);
1392   n = neighbours;
1393   cnm.ats_count = htonl (0);
1394   cnm.ats.type = htonl (0);
1395   cnm.ats.value = htonl (0);
1396   while (n != NULL)
1397     {
1398       if (n->status == PEER_STATE_KEY_CONFIRMED)
1399         {
1400 #if DEBUG_CORE_CLIENT
1401           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1402                       "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
1403 #endif
1404           cnm.peer = n->peer;
1405           GNUNET_SERVER_transmit_context_append_message (tc, &cnm.header);
1406         }
1407       n = n->next;
1408     }
1409   GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
1410   GNUNET_SERVER_transmit_context_run (tc,
1411                                       GNUNET_TIME_UNIT_FOREVER_REL);
1412 }
1413
1414
1415 /**
1416  * Handle REQUEST_INFO request.
1417  */
1418 static void
1419 handle_client_request_info (void *cls,
1420                             struct GNUNET_SERVER_Client *client,
1421                             const struct GNUNET_MessageHeader *message)
1422 {
1423   const struct RequestInfoMessage *rcm;
1424   struct Client *pos;
1425   struct Neighbour *n;
1426   struct ConfigurationInfoMessage cim;
1427   int32_t want_reserv;
1428   int32_t got_reserv;
1429   unsigned long long old_preference;
1430
1431 #if DEBUG_CORE_CLIENT
1432   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1433               "Core service receives `%s' request.\n", "REQUEST_INFO");
1434 #endif
1435   pos = clients;
1436   while (pos != NULL)
1437     {
1438       if (client == pos->client_handle)
1439         break;
1440       pos = pos->next;
1441     }
1442   if (pos == NULL)
1443     {
1444       GNUNET_break (0);
1445       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1446       return;
1447     }
1448
1449   rcm = (const struct RequestInfoMessage *) message;
1450   n = find_neighbour (&rcm->peer);
1451   memset (&cim, 0, sizeof (cim));
1452   if (n != NULL) 
1453     {
1454       want_reserv = ntohl (rcm->reserve_inbound);
1455       if (n->bw_out_internal_limit.value__ != rcm->limit_outbound.value__)
1456         {
1457           n->bw_out_internal_limit = rcm->limit_outbound;
1458           if (n->bw_out.value__ != GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
1459                                                                n->bw_out_external_limit).value__)
1460             {
1461               n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
1462                                                       n->bw_out_external_limit);
1463               GNUNET_BANDWIDTH_tracker_update_quota (&n->available_recv_window,
1464                                                      n->bw_out);
1465               GNUNET_TRANSPORT_set_quota (transport,
1466                                           &n->peer,
1467                                           n->bw_in,
1468                                           n->bw_out,
1469                                           GNUNET_TIME_UNIT_FOREVER_REL,
1470                                           NULL, NULL); 
1471               handle_peer_status_change (n);
1472             }
1473         }
1474       if (want_reserv < 0)
1475         {
1476           got_reserv = want_reserv;
1477         }
1478       else if (want_reserv > 0)
1479         {
1480           if (GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window,
1481                                                   want_reserv).rel_value == 0)
1482             got_reserv = want_reserv;
1483           else
1484             got_reserv = 0; /* all or nothing */
1485         }
1486       else
1487         got_reserv = 0;
1488       GNUNET_BANDWIDTH_tracker_consume (&n->available_recv_window,
1489                                         got_reserv);
1490       old_preference = n->current_preference;
1491       n->current_preference += GNUNET_ntohll(rcm->preference_change);
1492       if (old_preference > n->current_preference) 
1493         {
1494           /* overflow; cap at maximum value */
1495           n->current_preference = ULLONG_MAX;
1496         }
1497       update_preference_sum (n->current_preference - old_preference);
1498 #if DEBUG_CORE_QUOTA
1499       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1500                   "Received reservation request for %d bytes for peer `%4s', reserved %d bytes\n",
1501                   (int) want_reserv,
1502                   GNUNET_i2s (&rcm->peer),
1503                   (int) got_reserv);
1504 #endif
1505       cim.reserved_amount = htonl (got_reserv);
1506       cim.rim_id = rcm->rim_id;
1507       cim.bw_out = n->bw_out;
1508       cim.preference = n->current_preference;
1509     }
1510   cim.header.size = htons (sizeof (struct ConfigurationInfoMessage));
1511   cim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO);
1512   cim.peer = rcm->peer;
1513 #if DEBUG_CORE_CLIENT
1514   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1515               "Sending `%s' message to client.\n", "CONFIGURATION_INFO");
1516 #endif
1517   send_to_client (pos, &cim.header, GNUNET_NO);
1518   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1519 }
1520
1521
1522 /**
1523  * Free the given entry for the neighbour (it has
1524  * already been removed from the list at this point).
1525  *
1526  * @param n neighbour to free
1527  */
1528 static void
1529 free_neighbour (struct Neighbour *n)
1530 {
1531   struct MessageEntry *m;
1532   struct ClientActiveRequest *car;
1533
1534 #if DEBUG_CORE
1535   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1536               "Destroying neighbour entry for peer `%4s'\n",
1537               GNUNET_i2s (&n->peer));
1538 #endif
1539   if (n->pitr != NULL)
1540     {
1541       GNUNET_PEERINFO_iterate_cancel (n->pitr);
1542       n->pitr = NULL;
1543     }
1544   if (n->skm != NULL)
1545     {
1546       GNUNET_free (n->skm);
1547       n->skm = NULL;
1548     }
1549   while (NULL != (m = n->messages))
1550     {
1551       n->messages = m->next;
1552       GNUNET_free (m);
1553     }
1554   while (NULL != (m = n->encrypted_head))
1555     {
1556       GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1557                                    n->encrypted_tail,
1558                                    m);
1559       GNUNET_free (m);
1560     }
1561   while (NULL != (car = n->active_client_request_head))
1562     {
1563       GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
1564                                    n->active_client_request_tail,
1565                                    car);
1566       GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
1567                                             &n->peer.hashPubKey,
1568                                             car);
1569       GNUNET_free (car);
1570     }
1571   if (NULL != n->th)
1572     {
1573       GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
1574       n->th = NULL;
1575     }
1576   if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
1577     GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
1578   if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
1579     GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
1580   if (n->quota_update_task != GNUNET_SCHEDULER_NO_TASK)
1581     GNUNET_SCHEDULER_cancel (n->quota_update_task);
1582   if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
1583     GNUNET_SCHEDULER_cancel (n->dead_clean_task);
1584   if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)    
1585       GNUNET_SCHEDULER_cancel (n->keep_alive_task);
1586   if (n->status == PEER_STATE_KEY_CONFIRMED)
1587     GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"), -1, GNUNET_NO);
1588   GNUNET_array_grow (n->ats, n->ats_count, 0);
1589   GNUNET_free_non_null (n->public_key);
1590   GNUNET_free_non_null (n->pending_ping);
1591   GNUNET_free_non_null (n->pending_pong);
1592   GNUNET_free (n);
1593 }
1594
1595
1596 /**
1597  * Check if we have encrypted messages for the specified neighbour
1598  * pending, and if so, check with the transport about sending them
1599  * out.
1600  *
1601  * @param n neighbour to check.
1602  */
1603 static void process_encrypted_neighbour_queue (struct Neighbour *n);
1604
1605
1606 /**
1607  * Encrypt size bytes from in and write the result to out.  Use the
1608  * key for outbound traffic of the given neighbour.
1609  *
1610  * @param n neighbour we are sending to
1611  * @param iv initialization vector to use
1612  * @param in ciphertext
1613  * @param out plaintext
1614  * @param size size of in/out
1615  * @return GNUNET_OK on success
1616  */
1617 static int
1618 do_encrypt (struct Neighbour *n,
1619             const struct GNUNET_CRYPTO_AesInitializationVector * iv,
1620             const void *in, void *out, size_t size)
1621 {
1622   if (size != (uint16_t) size)
1623     {
1624       GNUNET_break (0);
1625       return GNUNET_NO;
1626     }
1627   GNUNET_assert (size ==
1628                  GNUNET_CRYPTO_aes_encrypt (in,
1629                                             (uint16_t) size,
1630                                             &n->encrypt_key,
1631                                             iv, out));
1632   GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes encrypted"), size, GNUNET_NO);
1633 #if DEBUG_CORE
1634   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1635               "Encrypted %u bytes for `%4s' using key %u, IV %u\n",
1636               (unsigned int) size,
1637               GNUNET_i2s (&n->peer),
1638               (unsigned int) n->encrypt_key.crc32,
1639               GNUNET_CRYPTO_crc32_n (iv, sizeof(iv)));
1640 #endif
1641   return GNUNET_OK;
1642 }
1643
1644
1645 /**
1646  * Consider freeing the given neighbour since we may not need
1647  * to keep it around anymore.
1648  *
1649  * @param n neighbour to consider discarding
1650  */
1651 static void
1652 consider_free_neighbour (struct Neighbour *n);
1653
1654
1655 /**
1656  * Task triggered when a neighbour entry is about to time out 
1657  * (and we should prevent this by sending a PING).
1658  *
1659  * @param cls the 'struct Neighbour'
1660  * @param tc scheduler context (not used)
1661  */
1662 static void
1663 send_keep_alive (void *cls,
1664                  const struct GNUNET_SCHEDULER_TaskContext *tc)
1665 {
1666   struct Neighbour *n = cls;
1667   struct GNUNET_TIME_Relative retry;
1668   struct GNUNET_TIME_Relative left;
1669   struct MessageEntry *me;
1670   struct PingMessage pp;
1671   struct PingMessage *pm;
1672   struct GNUNET_CRYPTO_AesInitializationVector iv;
1673
1674   n->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
1675   /* send PING */
1676   me = GNUNET_malloc (sizeof (struct MessageEntry) +
1677                       sizeof (struct PingMessage));
1678   me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PING_DELAY);
1679   me->priority = PING_PRIORITY;
1680   me->size = sizeof (struct PingMessage);
1681   GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
1682                                      n->encrypted_tail,
1683                                      n->encrypted_tail,
1684                                      me);
1685   pm = (struct PingMessage *) &me[1];
1686   pm->header.size = htons (sizeof (struct PingMessage));
1687   pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
1688   pm->iv_seed = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
1689       UINT32_MAX);
1690   derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
1691   pp.challenge = n->ping_challenge;
1692   pp.target = n->peer;
1693 #if DEBUG_HANDSHAKE
1694   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695               "Encrypting `%s' message with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
1696               "PING", 
1697               (unsigned int) n->ping_challenge,
1698               GNUNET_i2s (&n->peer),
1699               (unsigned int) n->encrypt_key.crc32,
1700               GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
1701               pm->iv_seed);
1702 #endif
1703   do_encrypt (n,
1704               &iv,
1705               &pp.target,
1706               &pm->target,
1707               sizeof (struct PingMessage) -
1708               ((void *) &pm->target - (void *) pm));
1709   process_encrypted_neighbour_queue (n);
1710   /* reschedule PING job */
1711   left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
1712   retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1713                                     MIN_PING_FREQUENCY);
1714   n->keep_alive_task 
1715     = GNUNET_SCHEDULER_add_delayed (retry,
1716                                     &send_keep_alive,
1717                                     n);
1718
1719 }
1720
1721
1722 /**
1723  * Task triggered when a neighbour entry might have gotten stale.
1724  *
1725  * @param cls the 'struct Neighbour'
1726  * @param tc scheduler context (not used)
1727  */
1728 static void
1729 consider_free_task (void *cls,
1730                     const struct GNUNET_SCHEDULER_TaskContext *tc)
1731 {
1732   struct Neighbour *n = cls;
1733
1734   n->dead_clean_task = GNUNET_SCHEDULER_NO_TASK;
1735   consider_free_neighbour (n);
1736 }
1737
1738
1739 /**
1740  * Consider freeing the given neighbour since we may not need
1741  * to keep it around anymore.
1742  *
1743  * @param n neighbour to consider discarding
1744  */
1745 static void
1746 consider_free_neighbour (struct Neighbour *n)
1747
1748   struct Neighbour *pos;
1749   struct Neighbour *prev;
1750   struct GNUNET_TIME_Relative left;
1751
1752   if ( (n->th != NULL) ||
1753        (n->pitr != NULL) ||
1754        (GNUNET_YES == n->is_connected) )
1755     return; /* no chance */
1756     
1757   left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
1758   if (left.rel_value > 0)
1759     {
1760       if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
1761         GNUNET_SCHEDULER_cancel (n->dead_clean_task);
1762       n->dead_clean_task = GNUNET_SCHEDULER_add_delayed (left,
1763                                                          &consider_free_task,
1764                                                          n);
1765       return;
1766     }
1767   /* actually free the neighbour... */
1768   prev = NULL;
1769   pos = neighbours;
1770   while (pos != n)
1771     {
1772       prev = pos;
1773       pos = pos->next;
1774     }
1775   if (prev == NULL)
1776     neighbours = n->next;
1777   else
1778     prev->next = n->next;
1779   GNUNET_assert (neighbour_count > 0);
1780   neighbour_count--;
1781   GNUNET_STATISTICS_set (stats,
1782                          gettext_noop ("# neighbour entries allocated"), 
1783                          neighbour_count,
1784                          GNUNET_NO);
1785   free_neighbour (n);
1786 }
1787
1788
1789 /**
1790  * Function called when the transport service is ready to
1791  * receive an encrypted message for the respective peer
1792  *
1793  * @param cls neighbour to use message from
1794  * @param size number of bytes we can transmit
1795  * @param buf where to copy the message
1796  * @return number of bytes transmitted
1797  */
1798 static size_t
1799 notify_encrypted_transmit_ready (void *cls, size_t size, void *buf)
1800 {
1801   struct Neighbour *n = cls;
1802   struct MessageEntry *m;
1803   size_t ret;
1804   char *cbuf;
1805
1806   n->th = NULL;
1807   m = n->encrypted_head;
1808   if (m == NULL)
1809     {
1810 #if DEBUG_CORE
1811       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1812                   "Encrypted message queue empty, no messages added to buffer for `%4s'\n",
1813                   GNUNET_i2s (&n->peer));
1814 #endif
1815       return 0;
1816     }
1817   GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1818                                n->encrypted_tail,
1819                                m);
1820   ret = 0;
1821   cbuf = buf;
1822   if (buf != NULL)
1823     {
1824       GNUNET_assert (size >= m->size);
1825       memcpy (cbuf, &m[1], m->size);
1826       ret = m->size;
1827       GNUNET_BANDWIDTH_tracker_consume (&n->available_send_window,
1828                                         m->size);
1829 #if DEBUG_CORE
1830       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1831                   "Copied message of type %u and size %u into transport buffer for `%4s'\n",
1832                   (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
1833                   (unsigned int) ret, 
1834                   GNUNET_i2s (&n->peer));
1835 #endif
1836       process_encrypted_neighbour_queue (n);
1837     }
1838   else
1839     {
1840 #if DEBUG_CORE
1841       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1842                   "Transmission of message of type %u and size %u failed\n",
1843                   (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
1844                   (unsigned int) m->size);
1845 #endif
1846     }
1847   GNUNET_free (m);
1848   consider_free_neighbour (n);
1849   return ret;
1850 }
1851
1852
1853 /**
1854  * Check if we have plaintext messages for the specified neighbour
1855  * pending, and if so, consider batching and encrypting them (and
1856  * then trigger processing of the encrypted queue if needed).
1857  *
1858  * @param n neighbour to check.
1859  */
1860 static void process_plaintext_neighbour_queue (struct Neighbour *n);
1861
1862
1863 /**
1864  * Check if we have encrypted messages for the specified neighbour
1865  * pending, and if so, check with the transport about sending them
1866  * out.
1867  *
1868  * @param n neighbour to check.
1869  */
1870 static void
1871 process_encrypted_neighbour_queue (struct Neighbour *n)
1872 {
1873   struct MessageEntry *m;
1874  
1875   if (n->th != NULL)
1876     return;  /* request already pending */
1877   m = n->encrypted_head;
1878   if (m == NULL)
1879     {
1880       /* encrypted queue empty, try plaintext instead */
1881       process_plaintext_neighbour_queue (n);
1882       return;
1883     }
1884 #if DEBUG_CORE
1885   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1886               "Asking transport for transmission of %u bytes to `%4s' in next %llu ms\n",
1887               (unsigned int) m->size,
1888               GNUNET_i2s (&n->peer),
1889               (unsigned long long) GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value);
1890 #endif
1891   n->th =
1892     GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer,
1893                                             m->size,
1894                                             m->priority,
1895                                             GNUNET_TIME_absolute_get_remaining
1896                                             (m->deadline),
1897                                             &notify_encrypted_transmit_ready,
1898                                             n);
1899   if (n->th == NULL)
1900     {
1901       /* message request too large or duplicate request */
1902       GNUNET_break (0);
1903       /* discard encrypted message */
1904       GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
1905                                    n->encrypted_tail,
1906                                    m);
1907       GNUNET_free (m);
1908       process_encrypted_neighbour_queue (n);
1909     }
1910 }
1911
1912
1913 /**
1914  * Decrypt size bytes from in and write the result to out.  Use the
1915  * key for inbound traffic of the given neighbour.  This function does
1916  * NOT do any integrity-checks on the result.
1917  *
1918  * @param n neighbour we are receiving from
1919  * @param iv initialization vector to use
1920  * @param in ciphertext
1921  * @param out plaintext
1922  * @param size size of in/out
1923  * @return GNUNET_OK on success
1924  */
1925 static int
1926 do_decrypt (struct Neighbour *n,
1927             const struct GNUNET_CRYPTO_AesInitializationVector * iv,
1928             const void *in, void *out, size_t size)
1929 {
1930   if (size != (uint16_t) size)
1931     {
1932       GNUNET_break (0);
1933       return GNUNET_NO;
1934     }
1935   if ((n->status != PEER_STATE_KEY_RECEIVED) &&
1936       (n->status != PEER_STATE_KEY_CONFIRMED))
1937     {
1938       GNUNET_break_op (0);
1939       return GNUNET_SYSERR;
1940     }
1941   if (size !=
1942       GNUNET_CRYPTO_aes_decrypt (in,
1943                                  (uint16_t) size,
1944                                  &n->decrypt_key,
1945                                  iv,
1946                                  out))
1947     {
1948       GNUNET_break (0);
1949       return GNUNET_SYSERR;
1950     }
1951   GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes decrypted"), size, GNUNET_NO);
1952 #if DEBUG_CORE
1953   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1954               "Decrypted %u bytes from `%4s' using key %u, IV %u\n",
1955               (unsigned int) size, 
1956               GNUNET_i2s (&n->peer),
1957               (unsigned int) n->decrypt_key.crc32,
1958               GNUNET_CRYPTO_crc32_n (iv, sizeof(*iv)));
1959 #endif
1960   return GNUNET_OK;
1961 }
1962
1963
1964 /**
1965  * Select messages for transmission.  This heuristic uses a combination
1966  * of earliest deadline first (EDF) scheduling (with bounded horizon)
1967  * and priority-based discard (in case no feasible schedule exist) and
1968  * speculative optimization (defer any kind of transmission until
1969  * we either create a batch of significant size, 25% of max, or until
1970  * we are close to a deadline).  Furthermore, when scheduling the
1971  * heuristic also packs as many messages into the batch as possible,
1972  * starting with those with the earliest deadline.  Yes, this is fun.
1973  *
1974  * @param n neighbour to select messages from
1975  * @param size number of bytes to select for transmission
1976  * @param retry_time set to the time when we should try again
1977  *        (only valid if this function returns zero)
1978  * @return number of bytes selected, or 0 if we decided to
1979  *         defer scheduling overall; in that case, retry_time is set.
1980  */
1981 static size_t
1982 select_messages (struct Neighbour *n,
1983                  size_t size, struct GNUNET_TIME_Relative *retry_time)
1984 {
1985   struct MessageEntry *pos;
1986   struct MessageEntry *min;
1987   struct MessageEntry *last;
1988   unsigned int min_prio;
1989   struct GNUNET_TIME_Absolute t;
1990   struct GNUNET_TIME_Absolute now;
1991   struct GNUNET_TIME_Relative delta;
1992   uint64_t avail;
1993   struct GNUNET_TIME_Relative slack;     /* how long could we wait before missing deadlines? */
1994   size_t off;
1995   uint64_t tsize;
1996   unsigned int queue_size;
1997   int discard_low_prio;
1998
1999   GNUNET_assert (NULL != n->messages);
2000   now = GNUNET_TIME_absolute_get ();
2001   /* last entry in linked list of messages processed */
2002   last = NULL;
2003   /* should we remove the entry with the lowest
2004      priority from consideration for scheduling at the
2005      end of the loop? */
2006   queue_size = 0;
2007   tsize = 0;
2008   pos = n->messages;
2009   while (pos != NULL)
2010     {
2011       queue_size++;
2012       tsize += pos->size;
2013       pos = pos->next;
2014     }
2015   discard_low_prio = GNUNET_YES;
2016   while (GNUNET_YES == discard_low_prio)
2017     {
2018       min = NULL;
2019       min_prio = UINT_MAX;
2020       discard_low_prio = GNUNET_NO;
2021       /* calculate number of bytes available for transmission at time "t" */
2022       avail = GNUNET_BANDWIDTH_tracker_get_available (&n->available_send_window);
2023       t = now;
2024       /* how many bytes have we (hypothetically) scheduled so far */
2025       off = 0;
2026       /* maximum time we can wait before transmitting anything
2027          and still make all of our deadlines */
2028       slack = GNUNET_TIME_UNIT_FOREVER_REL;
2029       pos = n->messages;
2030       /* note that we use "*2" here because we want to look
2031          a bit further into the future; much more makes no
2032          sense since new message might be scheduled in the
2033          meantime... */
2034       while ((pos != NULL) && (off < size * 2))
2035         {         
2036           if (pos->do_transmit == GNUNET_YES)
2037             {
2038               /* already removed from consideration */
2039               pos = pos->next;
2040               continue;
2041             }
2042           if (discard_low_prio == GNUNET_NO)
2043             {
2044               delta = GNUNET_TIME_absolute_get_difference (t, pos->deadline);
2045               if (delta.rel_value > 0)
2046                 {
2047                   // FIXME: HUH? Check!
2048                   t = pos->deadline;
2049                   avail += GNUNET_BANDWIDTH_value_get_available_until (n->bw_out,
2050                                                                        delta);
2051                 }
2052               if (avail < pos->size)
2053                 {
2054                   // FIXME: HUH? Check!
2055                   discard_low_prio = GNUNET_YES;        /* we could not schedule this one! */
2056                 }
2057               else
2058                 {
2059                   avail -= pos->size;
2060                   /* update slack, considering both its absolute deadline
2061                      and relative deadlines caused by other messages
2062                      with their respective load */
2063                   slack = GNUNET_TIME_relative_min (slack,
2064                                                     GNUNET_BANDWIDTH_value_get_delay_for (n->bw_out,
2065                                                                                           avail));
2066                   if (pos->deadline.abs_value <= now.abs_value) 
2067                     {
2068                       /* now or never */
2069                       slack = GNUNET_TIME_UNIT_ZERO;
2070                     }
2071                   else if (GNUNET_YES == pos->got_slack)
2072                     {
2073                       /* should be soon now! */
2074                       slack = GNUNET_TIME_relative_min (slack,
2075                                                         GNUNET_TIME_absolute_get_remaining (pos->slack_deadline));
2076                     }
2077                   else
2078                     {
2079                       slack =
2080                         GNUNET_TIME_relative_min (slack, 
2081                                                   GNUNET_TIME_absolute_get_difference (now, pos->deadline));
2082                       pos->got_slack = GNUNET_YES;
2083                       pos->slack_deadline = GNUNET_TIME_absolute_min (pos->deadline,
2084                                                                       GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_MAX_CORK_DELAY));
2085                     }
2086                 }
2087             }
2088           off += pos->size;
2089           t = GNUNET_TIME_absolute_max (pos->deadline, t); // HUH? Check!
2090           if (pos->priority <= min_prio)
2091             {
2092               /* update min for discard */
2093               min_prio = pos->priority;
2094               min = pos;
2095             }
2096           pos = pos->next;
2097         }
2098       if (discard_low_prio)
2099         {
2100           GNUNET_assert (min != NULL);
2101           /* remove lowest-priority entry from consideration */
2102           min->do_transmit = GNUNET_YES;        /* means: discard (for now) */
2103         }
2104       last = pos;
2105     }
2106   /* guard against sending "tiny" messages with large headers without
2107      urgent deadlines */
2108   if ( (slack.rel_value > GNUNET_CONSTANTS_MAX_CORK_DELAY.rel_value) && 
2109        (size > 4 * off) &&
2110        (queue_size <= MAX_PEER_QUEUE_SIZE - 2) )
2111     {
2112       /* less than 25% of message would be filled with deadlines still
2113          being met if we delay by one second or more; so just wait for
2114          more data; but do not wait longer than 1s (since we don't want
2115          to delay messages for a really long time either). */
2116       *retry_time = GNUNET_CONSTANTS_MAX_CORK_DELAY;
2117       /* reset do_transmit values for next time */
2118       while (pos != last)
2119         {
2120           pos->do_transmit = GNUNET_NO;   
2121           pos = pos->next;
2122         }
2123       GNUNET_STATISTICS_update (stats, 
2124                                 gettext_noop ("# transmissions delayed due to corking"), 
2125                                 1, GNUNET_NO);
2126 #if DEBUG_CORE
2127       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2128                   "Deferring transmission for %llums due to underfull message buffer size (%u/%u)\n",
2129                   (unsigned long long) retry_time->rel_value,
2130                   (unsigned int) off,
2131                   (unsigned int) size);
2132 #endif
2133       return 0;
2134     }
2135   /* select marked messages (up to size) for transmission */
2136   off = 0;
2137   pos = n->messages;
2138   while (pos != last)
2139     {
2140       if ((pos->size <= size) && (pos->do_transmit == GNUNET_NO))
2141         {
2142           pos->do_transmit = GNUNET_YES;        /* mark for transmission */
2143           off += pos->size;
2144           size -= pos->size;
2145 #if DEBUG_CORE
2146           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2147                       "Selecting message of size %u for transmission\n",
2148                       (unsigned int) pos->size);
2149 #endif
2150         }
2151       else
2152         {
2153 #if DEBUG_CORE
2154           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2155                       "Not selecting message of size %u for transmission at this time (maximum is %u)\n",
2156                       (unsigned int) pos->size,
2157                       size);
2158 #endif
2159           pos->do_transmit = GNUNET_NO;   /* mark for not transmitting! */
2160         }
2161       pos = pos->next;
2162     }
2163 #if DEBUG_CORE
2164   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2165               "Selected %llu/%llu bytes of %u/%u plaintext messages for transmission to `%4s'.\n",
2166               (unsigned long long) off, (unsigned long long) tsize,
2167               queue_size, (unsigned int) MAX_PEER_QUEUE_SIZE,
2168               GNUNET_i2s (&n->peer));
2169 #endif
2170   return off;
2171 }
2172
2173
2174 /**
2175  * Batch multiple messages into a larger buffer.
2176  *
2177  * @param n neighbour to take messages from
2178  * @param buf target buffer
2179  * @param size size of buf
2180  * @param deadline set to transmission deadline for the result
2181  * @param retry_time set to the time when we should try again
2182  *        (only valid if this function returns zero)
2183  * @param priority set to the priority of the batch
2184  * @return number of bytes written to buf (can be zero)
2185  */
2186 static size_t
2187 batch_message (struct Neighbour *n,
2188                char *buf,
2189                size_t size,
2190                struct GNUNET_TIME_Absolute *deadline,
2191                struct GNUNET_TIME_Relative *retry_time,
2192                unsigned int *priority)
2193 {
2194   char ntmb[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
2195   struct NotifyTrafficMessage *ntm = (struct NotifyTrafficMessage*) ntmb;
2196   struct MessageEntry *pos;
2197   struct MessageEntry *prev;
2198   struct MessageEntry *next;
2199   size_t ret;
2200   
2201   ret = 0;
2202   *priority = 0;
2203   *deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2204   *retry_time = GNUNET_TIME_UNIT_FOREVER_REL;
2205   if (0 == select_messages (n, size, retry_time))
2206     {
2207 #if DEBUG_CORE
2208       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2209                   "No messages selected, will try again in %llu ms\n",
2210                   retry_time->rel_value);
2211 #endif
2212       return 0;
2213     }
2214   ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND);
2215   ntm->ats_count = htonl (0);
2216   ntm->ats.type = htonl (0);
2217   ntm->ats.value = htonl (0);
2218   ntm->peer = n->peer;
2219   pos = n->messages;
2220   prev = NULL;
2221   while ((pos != NULL) && (size >= sizeof (struct GNUNET_MessageHeader)))
2222     {
2223       next = pos->next;
2224       if (GNUNET_YES == pos->do_transmit)
2225         {
2226           GNUNET_assert (pos->size <= size);
2227           /* do notifications */
2228           /* FIXME: track if we have *any* client that wants
2229              full notifications and only do this if that is
2230              actually true */
2231           if (pos->size < GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct NotifyTrafficMessage))
2232             {
2233               memcpy (&ntm[1], &pos[1], pos->size);
2234               ntm->header.size = htons (sizeof (struct NotifyTrafficMessage) + 
2235                                         sizeof (struct GNUNET_MessageHeader));
2236               send_to_all_clients (&ntm->header,
2237                                    GNUNET_YES,
2238                                    GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
2239             }
2240           else
2241             {
2242               /* message too large for 'full' notifications, we do at
2243                  least the 'hdr' type */
2244               memcpy (&ntm[1],
2245                       &pos[1],
2246                       sizeof (struct GNUNET_MessageHeader));
2247             }
2248           ntm->header.size = htons (sizeof (struct NotifyTrafficMessage) + 
2249                                     pos->size);
2250           send_to_all_clients (&ntm->header,
2251                                GNUNET_YES,
2252                                GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);   
2253 #if DEBUG_HANDSHAKE
2254           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2255                       "Encrypting %u bytes with message of type %u and size %u\n",
2256                       pos->size,
2257                       (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->type),
2258                       (unsigned int) ntohs(((const struct GNUNET_MessageHeader*)&pos[1])->size));
2259 #endif
2260           /* copy for encrypted transmission */
2261           memcpy (&buf[ret], &pos[1], pos->size);
2262           ret += pos->size;
2263           size -= pos->size;
2264           *priority += pos->priority;
2265 #if DEBUG_CORE
2266           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2267                       "Adding plaintext message of size %u with deadline %llu ms to batch\n",
2268                       (unsigned int) pos->size,
2269                       (unsigned long long) GNUNET_TIME_absolute_get_remaining (pos->deadline).rel_value);
2270 #endif
2271           deadline->abs_value = GNUNET_MIN (deadline->abs_value, pos->deadline.abs_value);
2272           GNUNET_free (pos);
2273           if (prev == NULL)
2274             n->messages = next;
2275           else
2276             prev->next = next;
2277         }
2278       else
2279         {
2280           prev = pos;
2281         }
2282       pos = next;
2283     }
2284 #if DEBUG_CORE
2285   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2286               "Deadline for message batch is %llu ms\n",
2287               GNUNET_TIME_absolute_get_remaining (*deadline).rel_value);
2288 #endif
2289   return ret;
2290 }
2291
2292
2293 /**
2294  * Remove messages with deadlines that have long expired from
2295  * the queue.
2296  *
2297  * @param n neighbour to inspect
2298  */
2299 static void
2300 discard_expired_messages (struct Neighbour *n)
2301 {
2302   struct MessageEntry *prev;
2303   struct MessageEntry *next;
2304   struct MessageEntry *pos;
2305   struct GNUNET_TIME_Absolute now;
2306   struct GNUNET_TIME_Relative delta;
2307   int disc;
2308
2309   disc = GNUNET_NO;
2310   now = GNUNET_TIME_absolute_get ();
2311   prev = NULL;
2312   pos = n->messages;
2313   while (pos != NULL) 
2314     {
2315       next = pos->next;
2316       delta = GNUNET_TIME_absolute_get_difference (pos->deadline, now);
2317       if (delta.rel_value > PAST_EXPIRATION_DISCARD_TIME.rel_value)
2318         {
2319 #if DEBUG_CORE
2320           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2321                       "Message is %llu ms past due, discarding.\n",
2322                       delta.rel_value);
2323 #endif
2324           if (prev == NULL)
2325             n->messages = next;
2326           else
2327             prev->next = next;
2328           GNUNET_STATISTICS_update (stats, 
2329                                     gettext_noop ("# messages discarded (expired prior to transmission)"), 
2330                                     1, 
2331                                     GNUNET_NO);
2332           disc = GNUNET_YES;
2333           GNUNET_free (pos);
2334         }
2335       else
2336         prev = pos;
2337       pos = next;
2338     }
2339   if (GNUNET_YES == disc)
2340     schedule_peer_messages (n);
2341 }
2342
2343
2344 /**
2345  * Signature of the main function of a task.
2346  *
2347  * @param cls closure
2348  * @param tc context information (why was this task triggered now)
2349  */
2350 static void
2351 retry_plaintext_processing (void *cls,
2352                             const struct GNUNET_SCHEDULER_TaskContext *tc)
2353 {
2354   struct Neighbour *n = cls;
2355
2356   n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2357   process_plaintext_neighbour_queue (n);
2358 }
2359
2360
2361 /**
2362  * Send our key (and encrypted PING) to the other peer.
2363  *
2364  * @param n the other peer
2365  */
2366 static void send_key (struct Neighbour *n);
2367
2368 /**
2369  * Task that will retry "send_key" if our previous attempt failed
2370  * to yield a PONG.
2371  */
2372 static void
2373 set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2374 {
2375   struct Neighbour *n = cls;
2376
2377 #if DEBUG_CORE
2378   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2379               "Retrying key transmission to `%4s'\n",
2380               GNUNET_i2s (&n->peer));
2381 #endif
2382   n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
2383   n->set_key_retry_frequency =
2384     GNUNET_TIME_relative_multiply (n->set_key_retry_frequency, 2);
2385   send_key (n);
2386 }
2387
2388
2389 /**
2390  * Check if we have plaintext messages for the specified neighbour
2391  * pending, and if so, consider batching and encrypting them (and
2392  * then trigger processing of the encrypted queue if needed).
2393  *
2394  * @param n neighbour to check.
2395  */
2396 static void
2397 process_plaintext_neighbour_queue (struct Neighbour *n)
2398 {
2399   char pbuf[GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE + sizeof (struct EncryptedMessage)];        /* plaintext */
2400   size_t used;
2401   struct EncryptedMessage *em;  /* encrypted message */
2402   struct EncryptedMessage *ph;  /* plaintext header */
2403   struct MessageEntry *me;
2404   unsigned int priority;
2405   struct GNUNET_TIME_Absolute deadline;
2406   struct GNUNET_TIME_Relative retry_time;
2407   struct GNUNET_CRYPTO_AesInitializationVector iv;
2408   struct GNUNET_CRYPTO_AuthKey auth_key;
2409
2410   if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
2411     {
2412       GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
2413       n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK;
2414     }
2415   switch (n->status)
2416     {
2417     case PEER_STATE_DOWN:
2418       send_key (n);
2419 #if DEBUG_CORE
2420       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2421                   "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2422                   GNUNET_i2s(&n->peer));
2423 #endif
2424       return;
2425     case PEER_STATE_KEY_SENT:
2426       if (n->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK)
2427         n->retry_set_key_task
2428           = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2429                                           &set_key_retry_task, n);    
2430 #if DEBUG_CORE
2431       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2432                   "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2433                   GNUNET_i2s(&n->peer));
2434 #endif
2435       return;
2436     case PEER_STATE_KEY_RECEIVED:
2437       if (n->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK)        
2438         n->retry_set_key_task
2439           = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2440                                           &set_key_retry_task, n);        
2441 #if DEBUG_CORE
2442       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2443                   "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
2444                   GNUNET_i2s(&n->peer));
2445 #endif
2446       return;
2447     case PEER_STATE_KEY_CONFIRMED:
2448       /* ready to continue */
2449       break;
2450     }
2451   discard_expired_messages (n);
2452   if (n->messages == NULL)
2453     {
2454 #if DEBUG_CORE
2455       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2456                   "Plaintext message queue for `%4s' is empty.\n",
2457                   GNUNET_i2s(&n->peer));
2458 #endif
2459       return;                   /* no pending messages */
2460     }
2461   if (n->encrypted_head != NULL)
2462     {
2463 #if DEBUG_CORE
2464       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2465                   "Encrypted message queue for `%4s' is still full, delaying plaintext processing.\n",
2466                   GNUNET_i2s(&n->peer));
2467 #endif
2468       return;                   /* wait for messages already encrypted to be
2469                                    processed first! */
2470     }
2471   ph = (struct EncryptedMessage *) pbuf;
2472   deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
2473   priority = 0;
2474   used = sizeof (struct EncryptedMessage);
2475   used += batch_message (n,
2476                          &pbuf[used],
2477                          GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE,
2478                          &deadline, &retry_time, &priority);
2479   if (used == sizeof (struct EncryptedMessage))
2480     {
2481 #if DEBUG_CORE
2482       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2483                   "No messages selected for transmission to `%4s' at this time, will try again later.\n",
2484                   GNUNET_i2s(&n->peer));
2485 #endif
2486       /* no messages selected for sending, try again later... */
2487       n->retry_plaintext_task =
2488         GNUNET_SCHEDULER_add_delayed (retry_time,
2489                                       &retry_plaintext_processing, n);
2490       return;
2491     }
2492 #if DEBUG_CORE_QUOTA
2493   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2494               "Sending %u b/s as new limit to peer `%4s'\n",
2495               (unsigned int) ntohl (n->bw_in.value__),
2496               GNUNET_i2s (&n->peer));
2497 #endif
2498   ph->iv_seed = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
2499   ph->sequence_number = htonl (++n->last_sequence_number_sent);
2500   ph->inbound_bw_limit = n->bw_in;
2501   ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
2502
2503   /* setup encryption message header */
2504   me = GNUNET_malloc (sizeof (struct MessageEntry) + used);
2505   me->deadline = deadline;
2506   me->priority = priority;
2507   me->size = used;
2508   em = (struct EncryptedMessage *) &me[1];
2509   em->header.size = htons (used);
2510   em->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
2511   em->iv_seed = ph->iv_seed;
2512   derive_iv (&iv, &n->encrypt_key, ph->iv_seed, &n->peer);
2513   /* encrypt */
2514 #if DEBUG_HANDSHAKE
2515   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2516               "Encrypting %u bytes of plaintext messages for `%4s' for transmission in %llums.\n",
2517               (unsigned int) used - ENCRYPTED_HEADER_SIZE,
2518               GNUNET_i2s(&n->peer),
2519               (unsigned long long) GNUNET_TIME_absolute_get_remaining (deadline).rel_value);
2520 #endif
2521   GNUNET_assert (GNUNET_OK ==
2522                  do_encrypt (n,
2523                              &iv,
2524                              &ph->sequence_number,
2525                              &em->sequence_number, used - ENCRYPTED_HEADER_SIZE));
2526   derive_auth_key (&auth_key,
2527                    &n->encrypt_key,
2528                    ph->iv_seed,
2529                    n->encrypt_key_created);
2530   GNUNET_CRYPTO_hmac (&auth_key,
2531                       &em->sequence_number,
2532                       used - ENCRYPTED_HEADER_SIZE,
2533                       &em->hmac);
2534 #if DEBUG_HANDSHAKE
2535   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2536               "Authenticated %u bytes of ciphertext %u: `%s'\n",
2537               used - ENCRYPTED_HEADER_SIZE,
2538               GNUNET_CRYPTO_crc32_n (&em->sequence_number,
2539                   used - ENCRYPTED_HEADER_SIZE),
2540               GNUNET_h2s (&em->hmac));
2541 #endif
2542   /* append to transmission list */
2543   GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
2544                                      n->encrypted_tail,
2545                                      n->encrypted_tail,
2546                                      me);
2547   process_encrypted_neighbour_queue (n);
2548   schedule_peer_messages (n);
2549 }
2550
2551
2552 /**
2553  * Function that recalculates the bandwidth quota for the
2554  * given neighbour and transmits it to the transport service.
2555  * 
2556  * @param cls neighbour for the quota update
2557  * @param tc context
2558  */
2559 static void
2560 neighbour_quota_update (void *cls,
2561                         const struct GNUNET_SCHEDULER_TaskContext *tc);
2562
2563
2564 /**
2565  * Schedule the task that will recalculate the bandwidth
2566  * quota for this peer (and possibly force a disconnect of
2567  * idle peers by calculating a bandwidth of zero).
2568  */
2569 static void
2570 schedule_quota_update (struct Neighbour *n)
2571 {
2572   GNUNET_assert (n->quota_update_task ==
2573                  GNUNET_SCHEDULER_NO_TASK);
2574   n->quota_update_task
2575     = GNUNET_SCHEDULER_add_delayed (QUOTA_UPDATE_FREQUENCY,
2576                                     &neighbour_quota_update,
2577                                     n);
2578 }
2579
2580
2581 /**
2582  * Initialize a new 'struct Neighbour'.
2583  *
2584  * @param pid ID of the new neighbour
2585  * @return handle for the new neighbour
2586  */
2587 static struct Neighbour *
2588 create_neighbour (const struct GNUNET_PeerIdentity *pid)
2589 {
2590   struct Neighbour *n;
2591   struct GNUNET_TIME_Absolute now;
2592
2593 #if DEBUG_CORE
2594   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2595               "Creating neighbour entry for peer `%4s'\n",
2596               GNUNET_i2s (pid));
2597 #endif
2598   n = GNUNET_malloc (sizeof (struct Neighbour));
2599   n->next = neighbours;
2600   neighbours = n;
2601   neighbour_count++;
2602   GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), neighbour_count, GNUNET_NO);
2603   n->peer = *pid;
2604   GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
2605   now = GNUNET_TIME_absolute_get ();
2606   n->encrypt_key_created = now;
2607   n->last_activity = now;
2608   n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
2609   n->bw_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2610   n->bw_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2611   n->bw_out_internal_limit = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
2612   n->bw_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2613   n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
2614                                                 UINT32_MAX);
2615   neighbour_quota_update (n, NULL);
2616   consider_free_neighbour (n);
2617   return n;
2618 }
2619
2620
2621 /**
2622  * Handle CORE_SEND request.
2623  *
2624  * @param cls unused
2625  * @param client the client issuing the request
2626  * @param message the "struct SendMessage"
2627  */
2628 static void
2629 handle_client_send (void *cls,
2630                     struct GNUNET_SERVER_Client *client,
2631                     const struct GNUNET_MessageHeader *message)
2632 {
2633   const struct SendMessage *sm;
2634   struct Neighbour *n;
2635   struct MessageEntry *prev;
2636   struct MessageEntry *pos;
2637   struct MessageEntry *e; 
2638   struct MessageEntry *min_prio_entry;
2639   struct MessageEntry *min_prio_prev;
2640   unsigned int min_prio;
2641   unsigned int queue_size;
2642   uint16_t msize;
2643
2644   msize = ntohs (message->size);
2645   if (msize <
2646       sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader))
2647     {
2648       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));
2649       GNUNET_break (0);
2650       if (client != NULL)
2651         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2652       return;
2653     }
2654   sm = (const struct SendMessage *) message;
2655   msize -= sizeof (struct SendMessage);
2656   if (0 == memcmp (&sm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2657     {
2658       /* FIXME: should we not allow loopback-injection here? */
2659       GNUNET_break (0);
2660       if (client != NULL)
2661         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2662       return;
2663     }
2664   n = find_neighbour (&sm->peer);
2665   if (n == NULL)
2666     n = create_neighbour (&sm->peer);
2667 #if DEBUG_CORE
2668   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2669               "Core received `%s' request, queueing %u bytes of plaintext data for transmission to `%4s'.\n",
2670               "SEND",
2671               (unsigned int) msize, 
2672               GNUNET_i2s (&sm->peer));
2673 #endif
2674   discard_expired_messages (n);
2675   /* bound queue size */
2676   /* NOTE: this entire block to bound the queue size should be
2677      obsolete with the new client-request code and the
2678      'schedule_peer_messages' mechanism; we still have this code in
2679      here for now as a sanity check for the new mechanmism;
2680      ultimately, we should probably simply reject SEND messages that
2681      are not 'approved' (or provide a new core API for very unreliable
2682      delivery that always sends with priority 0).  Food for thought. */
2683   min_prio = UINT32_MAX;
2684   min_prio_entry = NULL;
2685   min_prio_prev = NULL;
2686   queue_size = 0;
2687   prev = NULL;
2688   pos = n->messages;
2689   while (pos != NULL) 
2690     {
2691       if (pos->priority <= min_prio)
2692         {
2693           min_prio_entry = pos;
2694           min_prio_prev = prev;
2695           min_prio = pos->priority;
2696         }
2697       queue_size++;
2698       prev = pos;
2699       pos = pos->next;
2700     }
2701   if (queue_size >= MAX_PEER_QUEUE_SIZE)
2702     {
2703       /* queue full */
2704       if (ntohl(sm->priority) <= min_prio)
2705         {
2706           /* discard new entry; this should no longer happen! */
2707           GNUNET_break (0);
2708 #if DEBUG_CORE
2709           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2710                       "Queue full (%u/%u), discarding new request (%u bytes of type %u)\n",
2711                       queue_size,
2712                       (unsigned int) MAX_PEER_QUEUE_SIZE,
2713                       (unsigned int) msize,
2714                       (unsigned int) ntohs (message->type));
2715 #endif
2716           GNUNET_STATISTICS_update (stats, 
2717                                     gettext_noop ("# discarded CORE_SEND requests"), 
2718                                     1, GNUNET_NO);
2719
2720           if (client != NULL)
2721             GNUNET_SERVER_receive_done (client, GNUNET_OK);
2722           return;
2723         }
2724       GNUNET_assert (min_prio_entry != NULL);
2725       /* discard "min_prio_entry" */
2726 #if DEBUG_CORE
2727       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2728                   "Queue full, discarding existing older request\n");
2729 #endif
2730           GNUNET_STATISTICS_update (stats, gettext_noop ("# discarded lower priority CORE_SEND requests"), 1, GNUNET_NO);
2731       if (min_prio_prev == NULL)
2732         n->messages = min_prio_entry->next;
2733       else
2734         min_prio_prev->next = min_prio_entry->next;      
2735       GNUNET_free (min_prio_entry);     
2736     }
2737
2738 #if DEBUG_CORE
2739   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2740               "Adding transmission request for `%4s' of size %u to queue\n",
2741               GNUNET_i2s (&sm->peer),
2742               (unsigned int) msize);
2743 #endif  
2744   e = GNUNET_malloc (sizeof (struct MessageEntry) + msize);
2745   e->deadline = GNUNET_TIME_absolute_ntoh (sm->deadline);
2746   e->priority = ntohl (sm->priority);
2747   e->size = msize;
2748   memcpy (&e[1], &sm[1], msize);
2749
2750   /* insert, keep list sorted by deadline */
2751   prev = NULL;
2752   pos = n->messages;
2753   while ((pos != NULL) && (pos->deadline.abs_value < e->deadline.abs_value))
2754     {
2755       prev = pos;
2756       pos = pos->next;
2757     }
2758   if (prev == NULL)
2759     n->messages = e;
2760   else
2761     prev->next = e;
2762   e->next = pos;
2763
2764   /* consider scheduling now */
2765   process_plaintext_neighbour_queue (n);
2766   if (client != NULL)
2767     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2768 }
2769
2770
2771 /**
2772  * Function called when the transport service is ready to
2773  * receive a message.  Only resets 'n->th' to NULL.
2774  *
2775  * @param cls neighbour to use message from
2776  * @param size number of bytes we can transmit
2777  * @param buf where to copy the message
2778  * @return number of bytes transmitted
2779  */
2780 static size_t
2781 notify_transport_connect_done (void *cls, size_t size, void *buf)
2782 {
2783   struct Neighbour *n = cls;
2784
2785   n->th = NULL;
2786   if (GNUNET_YES != n->is_connected)
2787     {
2788       /* transport should only call us to transmit a message after
2789        * telling us about a successful connection to the respective peer */
2790 #if DEBUG_CORE
2791       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout on notify connect!\n");
2792 #endif
2793       return 0;
2794     }
2795   if (buf == NULL)
2796     {
2797       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2798                   _("Failed to connect to `%4s': transport failed to connect\n"),
2799                   GNUNET_i2s (&n->peer));
2800       return 0;
2801     }
2802   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2803               _("TRANSPORT connection to peer `%4s' is up, trying to establish CORE connection\n"),
2804               GNUNET_i2s (&n->peer));
2805   if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
2806     GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
2807   n->retry_set_key_task = GNUNET_SCHEDULER_add_now (&set_key_retry_task,
2808                                                     n);
2809   return 0;
2810 }
2811
2812
2813 /**
2814  * Handle CORE_REQUEST_CONNECT request.
2815  *
2816  * @param cls unused
2817  * @param client the client issuing the request
2818  * @param message the "struct ConnectMessage"
2819  */
2820 static void
2821 handle_client_request_connect (void *cls,
2822                                struct GNUNET_SERVER_Client *client,
2823                                const struct GNUNET_MessageHeader *message)
2824 {
2825   const struct ConnectMessage *cm = (const struct ConnectMessage*) message;
2826   struct Neighbour *n;
2827   struct GNUNET_TIME_Relative timeout;
2828
2829   if (0 == memcmp (&cm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2830     {
2831       GNUNET_break (0);
2832       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2833       return;
2834     }
2835   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2836   n = find_neighbour (&cm->peer);
2837   if (n == NULL)
2838     n = create_neighbour (&cm->peer);
2839   if ( (GNUNET_YES == n->is_connected) ||
2840        (n->th != NULL) )
2841     {
2842       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2843                  "Core received `%s' request for `%4s', already connected!\n",
2844                  "REQUEST_CONNECT",
2845                  GNUNET_i2s (&cm->peer));
2846       return; /* already connected, or at least trying */
2847     }
2848   GNUNET_STATISTICS_update (stats, gettext_noop ("# connection requests received"), 1, GNUNET_NO);
2849
2850   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2851               "Core received `%s' request for `%4s', will try to establish connection\n",
2852               "REQUEST_CONNECT",
2853               GNUNET_i2s (&cm->peer));
2854
2855   timeout = GNUNET_TIME_relative_ntoh (cm->timeout);
2856   /* ask transport to connect to the peer */
2857   n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
2858                                                   &cm->peer,
2859                                                   sizeof (struct GNUNET_MessageHeader), 0,
2860                                                   timeout,
2861                                                   &notify_transport_connect_done,
2862                                                   n);
2863   GNUNET_break (NULL != n->th);
2864 }
2865
2866
2867 /**
2868  * PEERINFO is giving us a HELLO for a peer.  Add the public key to
2869  * the neighbour's struct and retry send_key.  Or, if we did not get a
2870  * HELLO, just do nothing.
2871  *
2872  * @param cls the 'struct Neighbour' to retry sending the key for
2873  * @param peer the peer for which this is the HELLO
2874  * @param hello HELLO message of that peer
2875  */
2876 static void
2877 process_hello_retry_send_key (void *cls,
2878                               const struct GNUNET_PeerIdentity *peer,
2879                               const struct GNUNET_HELLO_Message *hello)
2880 {
2881   struct Neighbour *n = cls;
2882
2883   if (peer == NULL)
2884     {
2885 #if DEBUG_CORE
2886       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2887                   "Entered `%s' and `%s' is NULL!\n",
2888                   "process_hello_retry_send_key",
2889                   "peer");
2890 #endif
2891       n->pitr = NULL;
2892       if (n->public_key != NULL)
2893         {
2894           if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
2895             {
2896               GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
2897               n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
2898             }      
2899           GNUNET_STATISTICS_update (stats,
2900                                     gettext_noop ("# SET_KEY messages deferred (need public key)"), 
2901                                     -1, 
2902                                     GNUNET_NO);
2903           send_key (n);
2904         }
2905       else
2906         {
2907 #if DEBUG_CORE
2908           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2909                       "Failed to obtain public key for peer `%4s', delaying processing of SET_KEY\n",
2910                       GNUNET_i2s (&n->peer));
2911 #endif
2912           GNUNET_STATISTICS_update (stats,
2913                                     gettext_noop ("# Delayed connecting due to lack of public key"),
2914                                     1,
2915                                     GNUNET_NO);      
2916           if (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task)
2917             n->retry_set_key_task
2918               = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
2919                                               &set_key_retry_task, n);
2920         }
2921       return;
2922     }
2923
2924 #if DEBUG_CORE
2925   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2926               "Entered `%s' for peer `%4s'\n",
2927               "process_hello_retry_send_key",
2928               GNUNET_i2s (peer));
2929 #endif
2930   if (n->public_key != NULL)
2931     {
2932       /* already have public key, why are we here? */
2933       GNUNET_break (0);
2934       return;
2935     }
2936
2937 #if DEBUG_CORE
2938   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2939               "Received new `%s' message for `%4s', initiating key exchange.\n",
2940               "HELLO",
2941               GNUNET_i2s (peer));
2942 #endif
2943   n->public_key =
2944     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2945   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
2946     {
2947       GNUNET_STATISTICS_update (stats,
2948                                 gettext_noop ("# Error extracting public key from HELLO"),
2949                                 1,
2950                                 GNUNET_NO);      
2951       GNUNET_free (n->public_key);
2952       n->public_key = NULL;
2953 #if DEBUG_CORE
2954   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2955               "GNUNET_HELLO_get_key returned awfully\n");
2956 #endif
2957       return;
2958     }
2959 }
2960
2961
2962 /**
2963  * Send our key (and encrypted PING) to the other peer.
2964  *
2965  * @param n the other peer
2966  */
2967 static void
2968 send_key (struct Neighbour *n)
2969 {
2970   struct MessageEntry *pos;
2971   struct SetKeyMessage *sm;
2972   struct MessageEntry *me;
2973   struct PingMessage pp;
2974   struct PingMessage *pm;
2975   struct GNUNET_CRYPTO_AesInitializationVector iv;
2976
2977   if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
2978     {
2979       GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
2980       n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
2981     }        
2982   if (n->pitr != NULL)
2983     {
2984 #if DEBUG_CORE
2985       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2986                   "Key exchange in progress with `%4s'.\n",
2987                   GNUNET_i2s (&n->peer));
2988 #endif
2989       return; /* already in progress */
2990     }
2991   if (GNUNET_YES != n->is_connected)
2992     {
2993 #if DEBUG_CORE
2994       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2995                   "Not yet connected to peer `%4s'!\n",
2996                   GNUNET_i2s (&n->peer));
2997 #endif
2998       if (NULL == n->th)
2999         {
3000           GNUNET_STATISTICS_update (stats, 
3001                                     gettext_noop ("# Asking transport to connect (for SET_KEY)"), 
3002                                     1, 
3003                                     GNUNET_NO);
3004           n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
3005                                                           &n->peer,
3006                                                           sizeof (struct SetKeyMessage) + sizeof (struct PingMessage),
3007                                                           0,
3008                                                           GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
3009                                                           &notify_encrypted_transmit_ready,
3010                                                           n);
3011         }
3012       return; 
3013     }
3014 #if DEBUG_CORE
3015   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3016               "Asked to perform key exchange with `%4s'.\n",
3017               GNUNET_i2s (&n->peer));
3018 #endif
3019   if (n->public_key == NULL)
3020     {
3021       /* lookup n's public key, then try again */
3022 #if DEBUG_CORE
3023       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3024                   "Lacking public key for `%4s', trying to obtain one (send_key).\n",
3025                   GNUNET_i2s (&n->peer));
3026 #endif
3027       GNUNET_assert (n->pitr == NULL);
3028       n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
3029                                          &n->peer,
3030                                          GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20),
3031                                          &process_hello_retry_send_key, n);
3032       return;
3033     }
3034   pos = n->encrypted_head;
3035   while (pos != NULL)
3036     {
3037       if (GNUNET_YES == pos->is_setkey)
3038         {
3039           if (pos->sender_status == n->status)
3040             {
3041 #if DEBUG_CORE
3042               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3043                           "`%s' message for `%4s' queued already\n",
3044                           "SET_KEY",
3045                           GNUNET_i2s (&n->peer));
3046 #endif
3047               goto trigger_processing;
3048             }
3049           GNUNET_CONTAINER_DLL_remove (n->encrypted_head,
3050                                        n->encrypted_tail,
3051                                        pos);
3052           GNUNET_free (pos);
3053 #if DEBUG_CORE
3054           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3055                       "Removing queued `%s' message for `%4s', will create a new one\n",
3056                       "SET_KEY",
3057                       GNUNET_i2s (&n->peer));
3058 #endif
3059           break;
3060         }
3061       pos = pos->next;
3062     }
3063
3064   /* update status */
3065   switch (n->status)
3066     {
3067     case PEER_STATE_DOWN:
3068       n->status = PEER_STATE_KEY_SENT;
3069       break;
3070     case PEER_STATE_KEY_SENT:
3071       break;
3072     case PEER_STATE_KEY_RECEIVED:
3073       break;
3074     case PEER_STATE_KEY_CONFIRMED:
3075       break;
3076     default:
3077       GNUNET_break (0);
3078       break;
3079     }
3080   
3081
3082   /* first, set key message */
3083   me = GNUNET_malloc (sizeof (struct MessageEntry) +
3084                       sizeof (struct SetKeyMessage) +
3085                       sizeof (struct PingMessage));
3086   me->deadline = GNUNET_TIME_relative_to_absolute (MAX_SET_KEY_DELAY);
3087   me->priority = SET_KEY_PRIORITY;
3088   me->size = sizeof (struct SetKeyMessage) + sizeof (struct PingMessage);
3089   me->is_setkey = GNUNET_YES;
3090   me->got_slack = GNUNET_YES; /* do not defer this one! */
3091   me->sender_status = n->status;
3092   GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
3093                                      n->encrypted_tail,
3094                                      n->encrypted_tail,
3095                                      me);
3096   sm = (struct SetKeyMessage *) &me[1];
3097   sm->header.size = htons (sizeof (struct SetKeyMessage));
3098   sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SET_KEY);
3099   sm->sender_status = htonl ((int32_t) ((n->status == PEER_STATE_DOWN) ?
3100                                         PEER_STATE_KEY_SENT : n->status));
3101   sm->purpose.size =
3102     htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3103            sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3104            sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
3105            sizeof (struct GNUNET_PeerIdentity));
3106   sm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_KEY);
3107   sm->creation_time = GNUNET_TIME_absolute_hton (n->encrypt_key_created);
3108   sm->target = n->peer;
3109   GNUNET_assert (GNUNET_OK ==
3110                  GNUNET_CRYPTO_rsa_encrypt (&n->encrypt_key,
3111                                             sizeof (struct
3112                                                     GNUNET_CRYPTO_AesSessionKey),
3113                                             n->public_key,
3114                                             &sm->encrypted_key));
3115   GNUNET_assert (GNUNET_OK ==
3116                  GNUNET_CRYPTO_rsa_sign (my_private_key, &sm->purpose,
3117                                          &sm->signature));  
3118   pm = (struct PingMessage *) &sm[1];
3119   pm->header.size = htons (sizeof (struct PingMessage));
3120   pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
3121   pm->iv_seed = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
3122   derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
3123   pp.challenge = n->ping_challenge;
3124   pp.target = n->peer;
3125 #if DEBUG_HANDSHAKE
3126   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3127               "Encrypting `%s' and `%s' messages with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
3128               "SET_KEY", "PING",
3129               (unsigned int) n->ping_challenge,
3130               GNUNET_i2s (&n->peer),
3131               (unsigned int) n->encrypt_key.crc32,
3132               GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3133               pm->iv_seed);
3134 #endif
3135   do_encrypt (n,
3136               &iv,
3137               &pp.target,
3138               &pm->target,
3139               sizeof (struct PingMessage) -
3140               ((void *) &pm->target - (void *) pm));
3141   GNUNET_STATISTICS_update (stats, 
3142                             gettext_noop ("# SET_KEY and PING messages created"), 
3143                             1, 
3144                             GNUNET_NO);
3145 #if DEBUG_CORE
3146   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3147               "Have %llu ms left for `%s' transmission.\n",
3148               (unsigned long long) GNUNET_TIME_absolute_get_remaining (me->deadline).rel_value,
3149               "SET_KEY");
3150 #endif
3151  trigger_processing:
3152   /* trigger queue processing */
3153   process_encrypted_neighbour_queue (n);
3154   if ( (n->status != PEER_STATE_KEY_CONFIRMED) &&
3155        (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task) )
3156     n->retry_set_key_task
3157       = GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
3158                                       &set_key_retry_task, n);    
3159 }
3160
3161
3162 /**
3163  * We received a SET_KEY message.  Validate and update
3164  * our key material and status.
3165  *
3166  * @param n the neighbour from which we received message m
3167  * @param m the set key message we received
3168  * @param ats performance data
3169  * @param ats_count number of entries in ats (excluding 0-termination)
3170  */
3171 static void
3172 handle_set_key (struct Neighbour *n,
3173                 const struct SetKeyMessage *m,
3174                 const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3175                 uint32_t ats_count);
3176
3177
3178
3179 /**
3180  * PEERINFO is giving us a HELLO for a peer.  Add the public key to
3181  * the neighbour's struct and retry handling the set_key message.  Or,
3182  * if we did not get a HELLO, just free the set key message.
3183  *
3184  * @param cls pointer to the set key message
3185  * @param peer the peer for which this is the HELLO
3186  * @param hello HELLO message of that peer
3187  */
3188 static void
3189 process_hello_retry_handle_set_key (void *cls,
3190                                     const struct GNUNET_PeerIdentity *peer,
3191                                     const struct GNUNET_HELLO_Message *hello)
3192 {
3193   struct Neighbour *n = cls;
3194   struct SetKeyMessage *sm = n->skm;
3195
3196   if (peer == NULL)
3197     {
3198       n->skm = NULL;
3199       n->pitr = NULL;
3200       if (n->public_key != NULL)
3201         {
3202 #if DEBUG_CORE
3203           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3204                       "Received `%s' for `%4s', continuing processing of `%s' message.\n",
3205                       "HELLO",
3206                       GNUNET_i2s (&n->peer),
3207                       "SET_KEY");
3208 #endif
3209           handle_set_key (n, sm, NULL, 0);
3210         }
3211       else
3212         {
3213           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3214                       _("Ignoring `%s' message due to lack of public key for peer `%4s' (failed to obtain one).\n"),
3215                       "SET_KEY",
3216                       GNUNET_i2s (&n->peer));
3217         }
3218       GNUNET_free (sm);
3219       return;
3220     }
3221   if (n->public_key != NULL)
3222     return;                     /* multiple HELLOs match!? */
3223   n->public_key =
3224     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3225   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
3226     {
3227       GNUNET_break_op (0);
3228       GNUNET_free (n->public_key);
3229       n->public_key = NULL;
3230     }
3231 }
3232
3233
3234 /**
3235  * Merge the given performance data with the data we currently
3236  * track for the given neighbour.
3237  *
3238  * @param n neighbour
3239  * @param ats new performance data
3240  * @param ats_count number of records in ats
3241  */
3242 static void
3243 update_neighbour_performance (struct Neighbour *n,
3244                               const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3245                               uint32_t ats_count)
3246 {
3247   uint32_t i;
3248   unsigned int j;
3249
3250   if (ats_count == 0)
3251     return;
3252   for (i=0;i<ats_count;i++)
3253     {
3254       for (j=0;j<n->ats_count;j++)
3255         {
3256           if (n->ats[j].type == ats[i].type)
3257             {
3258               n->ats[j].value = ats[i].value;
3259               break;
3260             }
3261         }
3262       if (j == n->ats_count)    
3263         GNUNET_array_append (n->ats,
3264                              n->ats_count,
3265                              *ats);     
3266     }
3267 }
3268
3269
3270 /**
3271  * We received a PING message.  Validate and transmit
3272  * PONG.
3273  *
3274  * @param n sender of the PING
3275  * @param m the encrypted PING message itself
3276  * @param ats performance data
3277  * @param ats_count number of entries in ats (excluding 0-termination)
3278  */
3279 static void
3280 handle_ping (struct Neighbour *n,
3281              const struct PingMessage *m,
3282              const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3283              uint32_t ats_count)
3284 {
3285   struct PingMessage t;
3286   struct PongMessage tx;
3287   struct PongMessage *tp;
3288   struct MessageEntry *me;
3289   struct GNUNET_CRYPTO_AesInitializationVector iv;
3290
3291 #if DEBUG_CORE
3292   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3293               "Core service receives `%s' request from `%4s'.\n",
3294               "PING", GNUNET_i2s (&n->peer));
3295 #endif
3296   derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
3297   if (GNUNET_OK !=
3298       do_decrypt (n,
3299                   &iv,
3300                   &m->target,
3301                   &t.target,
3302                   sizeof (struct PingMessage) -
3303                   ((void *) &m->target - (void *) m)))
3304     return;
3305 #if DEBUG_HANDSHAKE
3306   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3307               "Decrypted `%s' to `%4s' with challenge %u decrypted using key %u, IV %u (salt %u)\n",
3308               "PING",
3309               GNUNET_i2s (&t.target),
3310               (unsigned int) t.challenge,
3311               (unsigned int) n->decrypt_key.crc32,
3312               GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3313               m->iv_seed);
3314 #endif
3315   GNUNET_STATISTICS_update (stats,
3316                             gettext_noop ("# PING messages decrypted"), 
3317                             1,
3318                             GNUNET_NO);
3319   if (0 != memcmp (&t.target,
3320                    &my_identity, sizeof (struct GNUNET_PeerIdentity)))
3321     {
3322       GNUNET_break_op (0);
3323       return;
3324     }
3325   update_neighbour_performance (n, ats, ats_count);
3326   me = GNUNET_malloc (sizeof (struct MessageEntry) +
3327                       sizeof (struct PongMessage));
3328   GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head,
3329                                      n->encrypted_tail,
3330                                      n->encrypted_tail,
3331                                      me);
3332   me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PONG_DELAY);
3333   me->priority = PONG_PRIORITY;
3334   me->size = sizeof (struct PongMessage);
3335   tx.inbound_bw_limit = n->bw_in;
3336   tx.challenge = t.challenge;
3337   tx.target = t.target;
3338   tp = (struct PongMessage *) &me[1];
3339   tp->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG);
3340   tp->header.size = htons (sizeof (struct PongMessage));
3341   tp->iv_seed = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
3342   derive_pong_iv (&iv, &n->encrypt_key, tp->iv_seed, t.challenge, &n->peer);
3343   do_encrypt (n,
3344               &iv,
3345               &tx.challenge,
3346               &tp->challenge,
3347               sizeof (struct PongMessage) -
3348               ((void *) &tp->challenge - (void *) tp));
3349   GNUNET_STATISTICS_update (stats, 
3350                             gettext_noop ("# PONG messages created"), 
3351                             1, 
3352                             GNUNET_NO);
3353 #if DEBUG_HANDSHAKE
3354   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3355               "Encrypting `%s' with challenge %u using key %u, IV %u (salt %u)\n",
3356               "PONG",
3357               (unsigned int) t.challenge,
3358               (unsigned int) n->encrypt_key.crc32,
3359               GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3360               tp->iv_seed);
3361 #endif
3362   /* trigger queue processing */
3363   process_encrypted_neighbour_queue (n);
3364 }
3365
3366
3367 /**
3368  * We received a PONG message.  Validate and update our status.
3369  *
3370  * @param n sender of the PONG
3371  * @param m the encrypted PONG message itself
3372  * @param ats performance data
3373  * @param ats_count number of entries in ats (excluding 0-termination)
3374  */
3375 static void
3376 handle_pong (struct Neighbour *n, 
3377              const struct PongMessage *m,
3378              const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3379              uint32_t ats_count)
3380 {
3381   struct PongMessage t;
3382   struct ConnectNotifyMessage cnm;
3383   struct GNUNET_CRYPTO_AesInitializationVector iv;
3384
3385 #if DEBUG_CORE
3386   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3387               "Core service receives `%s' response from `%4s'.\n",
3388               "PONG", GNUNET_i2s (&n->peer));
3389 #endif
3390   /* mark as garbage, just to be sure */
3391   memset (&t, 255, sizeof (t));
3392   derive_pong_iv (&iv, &n->decrypt_key, m->iv_seed, n->ping_challenge,
3393       &my_identity);
3394   if (GNUNET_OK !=
3395       do_decrypt (n,
3396                   &iv,
3397                   &m->challenge,
3398                   &t.challenge,
3399                   sizeof (struct PongMessage) -
3400                   ((void *) &m->challenge - (void *) m)))
3401     {
3402       GNUNET_break_op (0);
3403       return;
3404     }
3405   GNUNET_STATISTICS_update (stats, 
3406                             gettext_noop ("# PONG messages decrypted"), 
3407                             1, 
3408                             GNUNET_NO);
3409 #if DEBUG_HANDSHAKE
3410   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3411               "Decrypted `%s' from `%4s' with challenge %u using key %u, IV %u (salt %u)\n",
3412               "PONG",
3413               GNUNET_i2s (&t.target),
3414               (unsigned int) t.challenge,
3415               (unsigned int) n->decrypt_key.crc32,
3416               GNUNET_CRYPTO_crc32_n (&iv, sizeof(iv)),
3417               m->iv_seed);
3418 #endif
3419   if ((0 != memcmp (&t.target,
3420                     &n->peer,
3421                     sizeof (struct GNUNET_PeerIdentity))) ||
3422       (n->ping_challenge != t.challenge))
3423     {
3424       /* PONG malformed */
3425 #if DEBUG_CORE
3426       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3427                   "Received malformed `%s' wanted sender `%4s' with challenge %u\n",
3428                   "PONG", 
3429                   GNUNET_i2s (&n->peer),
3430                   (unsigned int) n->ping_challenge);
3431       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3432                   "Received malformed `%s' received from `%4s' with challenge %u\n",
3433                   "PONG", GNUNET_i2s (&t.target), 
3434                   (unsigned int) t.challenge);
3435 #endif
3436       GNUNET_break_op (n->ping_challenge != t.challenge);
3437       return;
3438     }
3439   switch (n->status)
3440     {
3441     case PEER_STATE_DOWN:
3442       GNUNET_break (0);         /* should be impossible */
3443       return;
3444     case PEER_STATE_KEY_SENT:
3445       GNUNET_break (0);         /* should be impossible, how did we decrypt? */
3446       return;
3447     case PEER_STATE_KEY_RECEIVED:
3448       GNUNET_STATISTICS_update (stats, 
3449                                 gettext_noop ("# Session keys confirmed via PONG"), 
3450                                 1, 
3451                                 GNUNET_NO);
3452       n->status = PEER_STATE_KEY_CONFIRMED;
3453       if (n->bw_out_external_limit.value__ != t.inbound_bw_limit.value__)
3454         {
3455           n->bw_out_external_limit = t.inbound_bw_limit;
3456           n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
3457                                                   n->bw_out_internal_limit);
3458           GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
3459                                                  n->bw_out);       
3460           GNUNET_TRANSPORT_set_quota (transport,
3461                                       &n->peer,
3462                                       n->bw_in,
3463                                       n->bw_out,
3464                                       GNUNET_TIME_UNIT_FOREVER_REL,
3465                                       NULL, NULL); 
3466         }
3467 #if DEBUG_CORE
3468       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3469                   "Confirmed key via `%s' message for peer `%4s'\n",
3470                   "PONG", GNUNET_i2s (&n->peer));
3471 #endif      
3472       if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
3473         {
3474           GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
3475           n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
3476         }      
3477       cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
3478       cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
3479       cnm.ats_count = htonl (0);
3480       cnm.peer = n->peer;
3481       cnm.ats.type = htonl (0);
3482       cnm.ats.value = htonl (0);
3483       send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_CONNECT);
3484       process_encrypted_neighbour_queue (n);
3485       /* fall-through! */
3486     case PEER_STATE_KEY_CONFIRMED:
3487       n->last_activity = GNUNET_TIME_absolute_get ();
3488       if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
3489         GNUNET_SCHEDULER_cancel (n->keep_alive_task);
3490       n->keep_alive_task 
3491         = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
3492                                         &send_keep_alive,
3493                                         n);
3494       update_neighbour_performance (n, ats, ats_count);
3495       handle_peer_status_change (n);
3496       break;
3497     default:
3498       GNUNET_break (0);
3499       break;
3500     }
3501 }
3502
3503
3504 /**
3505  * We received a SET_KEY message.  Validate and update
3506  * our key material and status.
3507  *
3508  * @param n the neighbour from which we received message m
3509  * @param m the set key message we received
3510  * @param ats performance data
3511  * @param ats_count number of entries in ats (excluding 0-termination)
3512  */
3513 static void
3514 handle_set_key (struct Neighbour *n, 
3515                 const struct SetKeyMessage *m,
3516                 const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3517                 uint32_t ats_count)
3518 {
3519   struct SetKeyMessage *m_cpy;
3520   struct GNUNET_TIME_Absolute t;
3521   struct GNUNET_CRYPTO_AesSessionKey k;
3522   struct PingMessage *ping;
3523   struct PongMessage *pong;
3524   enum PeerStateMachine sender_status;
3525
3526 #if DEBUG_CORE
3527   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3528               "Core service receives `%s' request from `%4s'.\n",
3529               "SET_KEY", GNUNET_i2s (&n->peer));
3530 #endif
3531   if (n->public_key == NULL)
3532     {
3533       if (n->pitr != NULL)
3534         {
3535 #if DEBUG_CORE
3536           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3537                       "Ignoring `%s' message due to lack of public key for peer (still trying to obtain one).\n",
3538                       "SET_KEY");
3539 #endif
3540           return;
3541         }
3542 #if DEBUG_CORE
3543       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3544                   "Lacking public key for peer, trying to obtain one (handle_set_key).\n");
3545 #endif
3546       m_cpy = GNUNET_malloc (sizeof (struct SetKeyMessage));
3547       memcpy (m_cpy, m, sizeof (struct SetKeyMessage));
3548       /* lookup n's public key, then try again */
3549       GNUNET_assert (n->skm == NULL);
3550       n->skm = m_cpy;
3551       n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
3552                                          &n->peer,
3553                                          GNUNET_TIME_UNIT_MINUTES,
3554                                          &process_hello_retry_handle_set_key, n);
3555       GNUNET_STATISTICS_update (stats, 
3556                                 gettext_noop ("# SET_KEY messages deferred (need public key)"), 
3557                                 1, 
3558                                 GNUNET_NO);
3559       return;
3560     }
3561   if (0 != memcmp (&m->target,
3562                    &my_identity,
3563                    sizeof (struct GNUNET_PeerIdentity)))
3564     {
3565       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3566                   _("Received `%s' message that was for `%s', not for me.  Ignoring.\n"),
3567                   "SET_KEY",
3568                   GNUNET_i2s (&m->target));
3569       return;
3570     }
3571   if ((ntohl (m->purpose.size) !=
3572        sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3573        sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3574        sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
3575        sizeof (struct GNUNET_PeerIdentity)) ||
3576       (GNUNET_OK !=
3577        GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_KEY,
3578                                  &m->purpose, &m->signature, n->public_key)))
3579     {
3580       /* invalid signature */
3581       GNUNET_break_op (0);
3582       return;
3583     }
3584   t = GNUNET_TIME_absolute_ntoh (m->creation_time);
3585   if (((n->status == PEER_STATE_KEY_RECEIVED) ||
3586        (n->status == PEER_STATE_KEY_CONFIRMED)) &&
3587       (t.abs_value < n->decrypt_key_created.abs_value))
3588     {
3589       /* this could rarely happen due to massive re-ordering of
3590          messages on the network level, but is most likely either
3591          a bug or some adversary messing with us.  Report. */
3592       GNUNET_break_op (0);
3593       return;
3594     }
3595 #if DEBUG_CORE
3596   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
3597               "Decrypting key material.\n");
3598 #endif  
3599   if ((GNUNET_CRYPTO_rsa_decrypt (my_private_key,
3600                                   &m->encrypted_key,
3601                                   &k,
3602                                   sizeof (struct GNUNET_CRYPTO_AesSessionKey))
3603        != sizeof (struct GNUNET_CRYPTO_AesSessionKey)) ||
3604       (GNUNET_OK != GNUNET_CRYPTO_aes_check_session_key (&k)))
3605     {
3606       /* failed to decrypt !? */
3607       GNUNET_break_op (0);
3608       return;
3609     }
3610   GNUNET_STATISTICS_update (stats, 
3611                             gettext_noop ("# SET_KEY messages decrypted"), 
3612                             1, 
3613                             GNUNET_NO);
3614   n->decrypt_key = k;
3615   if (n->decrypt_key_created.abs_value != t.abs_value)
3616     {
3617       /* fresh key, reset sequence numbers */
3618       n->last_sequence_number_received = 0;
3619       n->last_packets_bitmap = 0;
3620       n->decrypt_key_created = t;
3621     }
3622   update_neighbour_performance (n, ats, ats_count);
3623   sender_status = (enum PeerStateMachine) ntohl (m->sender_status);
3624   switch (n->status)
3625     {
3626     case PEER_STATE_DOWN:
3627       n->status = PEER_STATE_KEY_RECEIVED;
3628 #if DEBUG_CORE
3629       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3630                   "Responding to `%s' with my own key.\n", "SET_KEY");
3631 #endif
3632       send_key (n);
3633       break;
3634     case PEER_STATE_KEY_SENT:
3635     case PEER_STATE_KEY_RECEIVED:
3636       n->status = PEER_STATE_KEY_RECEIVED;
3637       if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
3638           (sender_status != PEER_STATE_KEY_CONFIRMED))
3639         {
3640 #if DEBUG_CORE
3641           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3642                       "Responding to `%s' with my own key (other peer has status %u).\n",
3643                       "SET_KEY",
3644                       (unsigned int) sender_status);
3645 #endif
3646           send_key (n);
3647         }
3648       break;
3649     case PEER_STATE_KEY_CONFIRMED:
3650       if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
3651           (sender_status != PEER_STATE_KEY_CONFIRMED))
3652         {         
3653 #if DEBUG_CORE
3654           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3655                       "Responding to `%s' with my own key (other peer has status %u), I was already fully up.\n",
3656                       "SET_KEY", 
3657                       (unsigned int) sender_status);
3658 #endif
3659           send_key (n);
3660         }
3661       break;
3662     default:
3663       GNUNET_break (0);
3664       break;
3665     }
3666   if (n->pending_ping != NULL)
3667     {
3668       ping = n->pending_ping;
3669       n->pending_ping = NULL;
3670       handle_ping (n, ping, NULL, 0);
3671       GNUNET_free (ping);
3672     }
3673   if (n->pending_pong != NULL)
3674     {
3675       pong = n->pending_pong;
3676       n->pending_pong = NULL;
3677       handle_pong (n, pong, NULL, 0);
3678       GNUNET_free (pong);
3679     }
3680 }
3681
3682
3683 /**
3684  * Send a P2P message to a client.
3685  *
3686  * @param sender who sent us the message?
3687  * @param client who should we give the message to?
3688  * @param m contains the message to transmit
3689  * @param msize number of bytes in buf to transmit
3690  */
3691 static void
3692 send_p2p_message_to_client (struct Neighbour *sender,
3693                             struct Client *client,
3694                             const void *m, size_t msize)
3695 {
3696   size_t size = msize + sizeof (struct NotifyTrafficMessage) +
3697     (sender->ats_count+1) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3698   char buf[size];
3699   struct NotifyTrafficMessage *ntm;
3700   struct GNUNET_TRANSPORT_ATS_Information *ats;
3701
3702   if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
3703     {
3704       GNUNET_break (0);
3705       /* recovery strategy: throw performance data away... */
3706       GNUNET_array_grow (sender->ats,
3707                          sender->ats_count,
3708                          0);
3709       size = msize + sizeof (struct NotifyTrafficMessage) +
3710         (sender->ats_count+1) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
3711     }
3712 #if DEBUG_CORE
3713   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3714               "Core service passes message from `%4s' of type %u to client.\n",
3715               GNUNET_i2s(&sender->peer),
3716               (unsigned int) ntohs (((const struct GNUNET_MessageHeader *) m)->type));
3717 #endif
3718   ntm = (struct NotifyTrafficMessage *) buf;
3719   ntm->header.size = htons (size);
3720   ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
3721   ntm->ats_count = htonl (sender->ats_count);
3722   ntm->peer = sender->peer;
3723   ats = &ntm->ats;
3724   memcpy (ats,
3725           sender->ats,
3726           sizeof (struct GNUNET_TRANSPORT_ATS_Information) * sender->ats_count);
3727   ats[sender->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
3728   ats[sender->ats_count].value = htonl (0);  
3729   memcpy (&ats[sender->ats_count+1],
3730           m, 
3731           msize);
3732   send_to_client (client, &ntm->header, GNUNET_YES);
3733 }
3734
3735
3736 /**
3737  * Deliver P2P message to interested clients.
3738  *
3739  * @param cls always NULL
3740  * @param client who sent us the message (struct Neighbour)
3741  * @param m the message
3742  */
3743 static void
3744 deliver_message (void *cls,
3745                  void *client,
3746                  const struct GNUNET_MessageHeader *m)
3747 {
3748   struct Neighbour *sender = client;
3749   size_t msize = ntohs (m->size);
3750   char buf[256];
3751   struct Client *cpos;
3752   uint16_t type;
3753   unsigned int tpos;
3754   int deliver_full;
3755   int dropped;
3756
3757   type = ntohs (m->type);
3758 #if DEBUG_CORE
3759   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3760               "Received encapsulated message of type %u and size %u from `%4s'\n",
3761               (unsigned int) type,
3762               ntohs (m->size),
3763               GNUNET_i2s (&sender->peer));
3764 #endif
3765   GNUNET_snprintf (buf,
3766                    sizeof(buf),
3767                    gettext_noop ("# bytes of messages of type %u received"),
3768                    (unsigned int) type);
3769   GNUNET_STATISTICS_set (stats,
3770                          buf,
3771                          msize,
3772                          GNUNET_NO);     
3773   dropped = GNUNET_YES;
3774   cpos = clients;
3775   while (cpos != NULL)
3776     {
3777       deliver_full = GNUNET_NO;
3778       if (0 != (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))
3779         deliver_full = GNUNET_YES;
3780       else
3781         {
3782           for (tpos = 0; tpos < cpos->tcnt; tpos++)
3783             {
3784               if (type != cpos->types[tpos])
3785                 continue;
3786               deliver_full = GNUNET_YES;
3787               break;
3788             }
3789         }
3790       if (GNUNET_YES == deliver_full)
3791         {
3792           send_p2p_message_to_client (sender, cpos, m, msize);
3793           dropped = GNUNET_NO;
3794         }
3795       else if (cpos->options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)
3796         {
3797           send_p2p_message_to_client (sender, cpos, m,
3798                                       sizeof (struct GNUNET_MessageHeader));
3799         }
3800       cpos = cpos->next;
3801     }
3802   if (dropped == GNUNET_YES)
3803     {
3804 #if DEBUG_CORE
3805       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3806                   "Message of type %u from `%4s' not delivered to any client.\n",
3807                   (unsigned int) type,
3808                   GNUNET_i2s (&sender->peer));
3809 #endif
3810       GNUNET_STATISTICS_update (stats,
3811                                 gettext_noop ("# messages not delivered to any client"), 
3812                                 1, GNUNET_NO);
3813     }
3814 }
3815
3816
3817 /**
3818  * We received an encrypted message.  Decrypt, validate and
3819  * pass on to the appropriate clients.
3820  *
3821  * @param n target of the message
3822  * @param m encrypted message
3823  * @param ats performance data
3824  * @param ats_count number of entries in ats (excluding 0-termination)
3825  */
3826 static void
3827 handle_encrypted_message (struct Neighbour *n,
3828                           const struct EncryptedMessage *m,
3829                           const struct GNUNET_TRANSPORT_ATS_Information *ats, 
3830                           uint32_t ats_count)
3831 {
3832   size_t size = ntohs (m->header.size);
3833   char buf[size];
3834   struct EncryptedMessage *pt;  /* plaintext */
3835   GNUNET_HashCode ph;
3836   uint32_t snum;
3837   struct GNUNET_TIME_Absolute t;
3838   struct GNUNET_CRYPTO_AesInitializationVector iv;
3839   struct GNUNET_CRYPTO_AuthKey auth_key;
3840
3841 #if DEBUG_CORE
3842   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3843               "Core service receives `%s' request from `%4s'.\n",
3844               "ENCRYPTED_MESSAGE", GNUNET_i2s (&n->peer));
3845 #endif  
3846   /* validate hash */
3847   derive_auth_key (&auth_key,
3848                    &n->decrypt_key,
3849                    m->iv_seed,
3850                    n->decrypt_key_created);
3851   GNUNET_CRYPTO_hmac (&auth_key,
3852                       &m->sequence_number,
3853                       size - ENCRYPTED_HEADER_SIZE, &ph);
3854 #if DEBUG_HANDSHAKE
3855   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3856               "Re-Authenticated %u bytes of ciphertext (`%u'): `%s'\n",
3857               (unsigned int) size - ENCRYPTED_HEADER_SIZE,
3858               GNUNET_CRYPTO_crc32_n (&m->sequence_number,
3859                   size - ENCRYPTED_HEADER_SIZE),
3860               GNUNET_h2s (&ph));
3861 #endif
3862
3863   if (0 != memcmp (&ph,
3864                    &m->hmac,
3865                    sizeof (GNUNET_HashCode)))
3866     {
3867       /* checksum failed */
3868       GNUNET_break_op (0);
3869       return;
3870     }
3871   derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity);
3872   /* decrypt */
3873   if (GNUNET_OK !=
3874       do_decrypt (n,
3875                   &iv,
3876                   &m->sequence_number,
3877                   &buf[ENCRYPTED_HEADER_SIZE],
3878                   size - ENCRYPTED_HEADER_SIZE))
3879     return;
3880   pt = (struct EncryptedMessage *) buf;
3881
3882   /* validate sequence number */
3883   snum = ntohl (pt->sequence_number);
3884   if (n->last_sequence_number_received == snum)
3885     {
3886       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3887                   "Received duplicate message, ignoring.\n");
3888       /* duplicate, ignore */
3889       GNUNET_STATISTICS_set (stats,
3890                              gettext_noop ("# bytes dropped (duplicates)"),
3891                              size,
3892                              GNUNET_NO);      
3893       return;
3894     }
3895   if ((n->last_sequence_number_received > snum) &&
3896       (n->last_sequence_number_received - snum > 32))
3897     {
3898       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3899                   "Received ancient out of sequence message, ignoring.\n");
3900       /* ancient out of sequence, ignore */
3901       GNUNET_STATISTICS_set (stats,
3902                              gettext_noop ("# bytes dropped (out of sequence)"),
3903                              size,
3904                              GNUNET_NO);      
3905       return;
3906     }
3907   if (n->last_sequence_number_received > snum)
3908     {
3909       unsigned int rotbit =
3910         1 << (n->last_sequence_number_received - snum - 1);
3911       if ((n->last_packets_bitmap & rotbit) != 0)
3912         {
3913           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3914                       "Received duplicate message, ignoring.\n");
3915           GNUNET_STATISTICS_set (stats,
3916                                  gettext_noop ("# bytes dropped (duplicates)"),
3917                                  size,
3918                                  GNUNET_NO);      
3919           /* duplicate, ignore */
3920           return;
3921         }
3922       n->last_packets_bitmap |= rotbit;
3923     }
3924   if (n->last_sequence_number_received < snum)
3925     {
3926       int shift = (snum - n->last_sequence_number_received);
3927       if (shift >= 8 * sizeof(n->last_packets_bitmap))
3928         n->last_packets_bitmap = 0;
3929       else
3930         n->last_packets_bitmap <<= shift;
3931       n->last_sequence_number_received = snum;
3932     }
3933
3934   /* check timestamp */
3935   t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
3936   if (GNUNET_TIME_absolute_get_duration (t).rel_value > MAX_MESSAGE_AGE.rel_value)
3937     {
3938       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3939                   _
3940                   ("Message received far too old (%llu ms). Content ignored.\n"),
3941                   GNUNET_TIME_absolute_get_duration (t).rel_value);
3942       GNUNET_STATISTICS_set (stats,
3943                              gettext_noop ("# bytes dropped (ancient message)"),
3944                              size,
3945                              GNUNET_NO);      
3946       return;
3947     }
3948
3949   /* process decrypted message(s) */
3950   if (n->bw_out_external_limit.value__ != pt->inbound_bw_limit.value__)
3951     {
3952 #if DEBUG_CORE_SET_QUOTA
3953       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3954                   "Received %u b/s as new inbound limit for peer `%4s'\n",
3955                   (unsigned int) ntohl (pt->inbound_bw_limit.value__),
3956                   GNUNET_i2s (&n->peer));
3957 #endif
3958       n->bw_out_external_limit = pt->inbound_bw_limit;
3959       n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
3960                                               n->bw_out_internal_limit);
3961       GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
3962                                              n->bw_out);
3963       GNUNET_TRANSPORT_set_quota (transport,
3964                                   &n->peer,
3965                                   n->bw_in,
3966                                   n->bw_out,
3967                                   GNUNET_TIME_UNIT_FOREVER_REL,
3968                                   NULL, NULL); 
3969     }
3970   n->last_activity = GNUNET_TIME_absolute_get ();
3971   if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
3972     GNUNET_SCHEDULER_cancel (n->keep_alive_task);
3973   n->keep_alive_task 
3974     = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
3975                                     &send_keep_alive,
3976                                     n);
3977   GNUNET_STATISTICS_set (stats,
3978                          gettext_noop ("# bytes of payload decrypted"),
3979                          size - sizeof (struct EncryptedMessage),
3980                          GNUNET_NO);
3981   handle_peer_status_change (n);
3982   update_neighbour_performance (n, ats, ats_count);
3983   if (GNUNET_OK != GNUNET_SERVER_mst_receive (mst, 
3984                                               n,
3985                                               &buf[sizeof (struct EncryptedMessage)], 
3986                                               size - sizeof (struct EncryptedMessage),
3987                                               GNUNET_YES, GNUNET_NO))
3988     GNUNET_break_op (0);
3989 }
3990
3991
3992 /**
3993  * Function called by the transport for each received message.
3994  *
3995  * @param cls closure
3996  * @param peer (claimed) identity of the other peer
3997  * @param message the message
3998  * @param ats performance data
3999  * @param ats_count number of entries in ats (excluding 0-termination)
4000  */
4001 static void
4002 handle_transport_receive (void *cls,
4003                           const struct GNUNET_PeerIdentity *peer,
4004                           const struct GNUNET_MessageHeader *message,
4005                           const struct GNUNET_TRANSPORT_ATS_Information *ats, 
4006                           uint32_t ats_count)
4007 {
4008   struct Neighbour *n;
4009   struct GNUNET_TIME_Absolute now;
4010   int up;
4011   uint16_t type;
4012   uint16_t size;
4013   int changed;
4014
4015 #if DEBUG_CORE
4016   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4017               "Received message of type %u from `%4s', demultiplexing.\n",
4018               (unsigned int) ntohs (message->type), 
4019               GNUNET_i2s (peer));
4020 #endif
4021   if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
4022     {
4023       GNUNET_break (0);
4024       return;
4025     }
4026   n = find_neighbour (peer);
4027   if (n == NULL)
4028     n = create_neighbour (peer);
4029   changed = GNUNET_YES; /* FIXME... */
4030   up = (n->status == PEER_STATE_KEY_CONFIRMED);
4031   type = ntohs (message->type);
4032   size = ntohs (message->size);
4033   switch (type)
4034     {
4035     case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
4036       if (size != sizeof (struct SetKeyMessage))
4037         {
4038           GNUNET_break_op (0);
4039           return;
4040         }
4041       GNUNET_STATISTICS_update (stats, gettext_noop ("# session keys received"), 1, GNUNET_NO);
4042       handle_set_key (n,
4043                       (const struct SetKeyMessage *) message,
4044                       ats, ats_count);
4045       break;
4046     case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
4047       if (size < sizeof (struct EncryptedMessage) +
4048           sizeof (struct GNUNET_MessageHeader))
4049         {
4050           GNUNET_break_op (0);
4051           return;
4052         }
4053       if ((n->status != PEER_STATE_KEY_RECEIVED) &&
4054           (n->status != PEER_STATE_KEY_CONFIRMED))
4055         {
4056           GNUNET_break_op (0);
4057           return;
4058         }
4059       handle_encrypted_message (n, 
4060                                 (const struct EncryptedMessage *) message,
4061                                 ats, ats_count);
4062       break;
4063     case GNUNET_MESSAGE_TYPE_CORE_PING:
4064       if (size != sizeof (struct PingMessage))
4065         {
4066           GNUNET_break_op (0);
4067           return;
4068         }
4069       GNUNET_STATISTICS_update (stats, gettext_noop ("# PING messages received"), 1, GNUNET_NO);
4070       if ((n->status != PEER_STATE_KEY_RECEIVED) &&
4071           (n->status != PEER_STATE_KEY_CONFIRMED))
4072         {
4073 #if DEBUG_CORE
4074           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4075                       "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
4076                       "PING", GNUNET_i2s (&n->peer));
4077 #endif
4078           GNUNET_free_non_null (n->pending_ping);
4079           n->pending_ping = GNUNET_malloc (sizeof (struct PingMessage));
4080           memcpy (n->pending_ping, message, sizeof (struct PingMessage));
4081           return;
4082         }
4083       handle_ping (n, (const struct PingMessage *) message,
4084                    ats, ats_count);
4085       break;
4086     case GNUNET_MESSAGE_TYPE_CORE_PONG:
4087       if (size != sizeof (struct PongMessage))
4088         {
4089           GNUNET_break_op (0);
4090           return;
4091         }
4092       GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages received"), 1, GNUNET_NO);
4093       if ( (n->status != PEER_STATE_KEY_RECEIVED) &&
4094            (n->status != PEER_STATE_KEY_CONFIRMED) )
4095         {
4096 #if DEBUG_CORE
4097           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4098                       "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
4099                       "PONG", GNUNET_i2s (&n->peer));
4100 #endif
4101           GNUNET_free_non_null (n->pending_pong);
4102           n->pending_pong = GNUNET_malloc (sizeof (struct PongMessage));
4103           memcpy (n->pending_pong, message, sizeof (struct PongMessage));
4104           return;
4105         }
4106       handle_pong (n, (const struct PongMessage *) message,
4107                    ats, ats_count);
4108       break;
4109     default:
4110       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4111                   _("Unsupported message of type %u received.\n"),
4112                   (unsigned int) type);
4113       return;
4114     }
4115   if (n->status == PEER_STATE_KEY_CONFIRMED)
4116     {
4117       now = GNUNET_TIME_absolute_get ();
4118       n->last_activity = now;
4119       changed = GNUNET_YES;
4120       if (!up)
4121         {
4122           GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"), 1, GNUNET_NO);
4123           n->time_established = now;
4124         }
4125       if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
4126         GNUNET_SCHEDULER_cancel (n->keep_alive_task);
4127       n->keep_alive_task 
4128         = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
4129                                         &send_keep_alive,
4130                                         n);
4131     }
4132   if (changed)
4133     handle_peer_status_change (n);
4134 }
4135
4136
4137 /**
4138  * Function that recalculates the bandwidth quota for the
4139  * given neighbour and transmits it to the transport service.
4140  * 
4141  * @param cls neighbour for the quota update
4142  * @param tc context
4143  */
4144 static void
4145 neighbour_quota_update (void *cls,
4146                         const struct GNUNET_SCHEDULER_TaskContext *tc)
4147 {
4148   struct Neighbour *n = cls;
4149   struct GNUNET_BANDWIDTH_Value32NBO q_in;
4150   struct GNUNET_BANDWIDTH_Value32NBO q_out;
4151   struct GNUNET_BANDWIDTH_Value32NBO q_out_min;
4152   double pref_rel;
4153   double share;
4154   unsigned long long distributable;
4155   uint64_t need_per_peer;
4156   uint64_t need_per_second;
4157
4158 #if DEBUG_CORE
4159   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4160               "Neighbour quota update calculation running for peer `%4s'\n",
4161               GNUNET_i2s (&n->peer));  
4162 #endif
4163   n->quota_update_task = GNUNET_SCHEDULER_NO_TASK;
4164   /* calculate relative preference among all neighbours;
4165      divides by a bit more to avoid division by zero AND to
4166      account for possibility of new neighbours joining any time 
4167      AND to convert to double... */
4168   if (preference_sum == 0)
4169     {
4170       pref_rel = 1.0 / (double) neighbour_count;
4171     }
4172   else
4173     {
4174       pref_rel = n->current_preference / preference_sum;
4175     }
4176   need_per_peer = GNUNET_BANDWIDTH_value_get_available_until (MIN_BANDWIDTH_PER_PEER,
4177                                                               GNUNET_TIME_UNIT_SECONDS);  
4178   need_per_second = need_per_peer * neighbour_count;
4179
4180   /* calculate inbound bandwidth per peer */
4181   distributable = 0;
4182   if (bandwidth_target_in_bps > need_per_second)
4183     distributable = bandwidth_target_in_bps - need_per_second;
4184   share = distributable * pref_rel;
4185   if (share + need_per_peer > UINT32_MAX)
4186     q_in = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
4187   else
4188     q_in = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4189
4190   /* calculate outbound bandwidth per peer */
4191   distributable = 0;
4192   if (bandwidth_target_out_bps > need_per_second)
4193     distributable = bandwidth_target_out_bps - need_per_second;
4194   share = distributable * pref_rel;
4195   if (share + need_per_peer > UINT32_MAX)
4196     q_out = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
4197   else
4198     q_out = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
4199   n->bw_out_internal_limit = q_out;
4200
4201   q_out_min = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit, n->bw_out_internal_limit);
4202   GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window, n->bw_out);
4203
4204   /* check if we want to disconnect for good due to inactivity */
4205   if ( (GNUNET_TIME_absolute_get_duration (get_neighbour_timeout (n)).rel_value > 0) &&
4206        (GNUNET_TIME_absolute_get_duration (n->time_established).rel_value > GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value) )
4207     {
4208 #if DEBUG_CORE
4209       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4210                   "Forcing disconnect of `%4s' due to inactivity\n",
4211                   GNUNET_i2s (&n->peer));
4212 #endif
4213       q_in = GNUNET_BANDWIDTH_value_init (0); /* force disconnect */
4214     }
4215 #if DEBUG_CORE_QUOTA
4216   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4217               "Current quota for `%4s' is %u/%llu b/s in (old: %u b/s) / %u out (%u internal)\n",
4218               GNUNET_i2s (&n->peer),
4219               (unsigned int) ntohl (q_in.value__),
4220               bandwidth_target_out_bps,
4221               (unsigned int) ntohl (n->bw_in.value__),
4222               (unsigned int) ntohl (n->bw_out.value__),
4223               (unsigned int) ntohl (n->bw_out_internal_limit.value__));
4224   #endif
4225   if ((n->bw_in.value__ != q_in.value__) || (n->bw_out.value__ != q_out_min.value__))
4226     {
4227           if (n->bw_in.value__ != q_in.value__)
4228                   n->bw_in = q_in;
4229           if (n->bw_out.value__ != q_out_min.value__)
4230                   n->bw_out = q_out_min;
4231       if (GNUNET_YES == n->is_connected)
4232         GNUNET_TRANSPORT_set_quota (transport,
4233                                     &n->peer,
4234                                     n->bw_in,
4235                                     n->bw_out,
4236                                     GNUNET_TIME_UNIT_FOREVER_REL,
4237                                     NULL, NULL);
4238       handle_peer_status_change (n);
4239     }
4240   schedule_quota_update (n);
4241 }
4242
4243
4244 /**
4245  * Function called by transport to notify us that
4246  * a peer connected to us (on the network level).
4247  *
4248  * @param cls closure
4249  * @param peer the peer that connected
4250  * @param ats performance data
4251  * @param ats_count number of entries in ats (excluding 0-termination)
4252  */
4253 static void
4254 handle_transport_notify_connect (void *cls,
4255                                  const struct GNUNET_PeerIdentity *peer,
4256                                  const struct GNUNET_TRANSPORT_ATS_Information *ats,
4257                                  uint32_t ats_count)
4258 {
4259   struct Neighbour *n;
4260
4261   if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
4262     {
4263       GNUNET_break (0);
4264       return;
4265     }
4266   n = find_neighbour (peer);
4267   if (n != NULL)
4268     {
4269       if (GNUNET_YES == n->is_connected)
4270         {
4271           /* duplicate connect notification!? */
4272           GNUNET_break (0);
4273           return;
4274         }
4275     }
4276   else
4277     {
4278       n = create_neighbour (peer);
4279     }
4280   GNUNET_STATISTICS_update (stats, 
4281                             gettext_noop ("# peers connected (transport)"), 
4282                             1, 
4283                             GNUNET_NO);
4284   n->is_connected = GNUNET_YES;      
4285   update_neighbour_performance (n, ats, ats_count);
4286   GNUNET_BANDWIDTH_tracker_init (&n->available_send_window,
4287                                  n->bw_out,
4288                                  MAX_WINDOW_TIME_S);
4289   GNUNET_BANDWIDTH_tracker_init (&n->available_recv_window,
4290                                  n->bw_in,
4291                                  MAX_WINDOW_TIME_S);  
4292 #if DEBUG_CORE
4293   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4294               "Received connection from `%4s'.\n",
4295               GNUNET_i2s (&n->peer));
4296 #endif
4297   GNUNET_TRANSPORT_set_quota (transport,
4298                               &n->peer,
4299                               n->bw_in,
4300                               n->bw_out,
4301                               GNUNET_TIME_UNIT_FOREVER_REL,
4302                               NULL, NULL);
4303   send_key (n); 
4304 }
4305
4306
4307 /**
4308  * Function called by transport telling us that a peer
4309  * disconnected.
4310  *
4311  * @param cls closure
4312  * @param peer the peer that disconnected
4313  */
4314 static void
4315 handle_transport_notify_disconnect (void *cls,
4316                                     const struct GNUNET_PeerIdentity *peer)
4317 {
4318   struct DisconnectNotifyMessage cnm;
4319   struct Neighbour *n;
4320   struct ClientActiveRequest *car;
4321   struct GNUNET_TIME_Relative left;
4322
4323 #if DEBUG_CORE
4324   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4325               "Peer `%4s' disconnected from us; received notification from transport.\n", GNUNET_i2s (peer));
4326 #endif
4327
4328   n = find_neighbour (peer);
4329   if (n == NULL)
4330     {
4331       GNUNET_break (0);
4332       return;
4333     }
4334   GNUNET_break (n->is_connected);
4335   if (n->status == PEER_STATE_KEY_CONFIRMED)
4336     {
4337       cnm.header.size = htons (sizeof (struct DisconnectNotifyMessage));
4338       cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
4339       cnm.peer = *peer;
4340       send_to_all_clients (&cnm.header, GNUNET_NO, GNUNET_CORE_OPTION_SEND_DISCONNECT);
4341     }
4342   if (NULL != n->th)
4343     {
4344       GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
4345       n->th = NULL;
4346     }
4347   n->is_connected = GNUNET_NO;
4348   n->status = PEER_STATE_DOWN;
4349   while (NULL != (car = n->active_client_request_head))
4350     {
4351       GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
4352                                    n->active_client_request_tail,
4353                                    car);
4354       GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
4355                                             &n->peer.hashPubKey,
4356                                             car);
4357       GNUNET_free (car);
4358     }
4359
4360   GNUNET_STATISTICS_update (stats, 
4361                             gettext_noop ("# peers connected (transport)"), 
4362                             -1, 
4363                             GNUNET_NO);
4364   if (n->dead_clean_task != GNUNET_SCHEDULER_NO_TASK)
4365     GNUNET_SCHEDULER_cancel (n->dead_clean_task);
4366   left = GNUNET_TIME_relative_subtract (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
4367                                         GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT);
4368   n->last_activity = GNUNET_TIME_absolute_subtract (GNUNET_TIME_absolute_get (), 
4369                                                     left);
4370   n->dead_clean_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT,
4371                                                      &consider_free_task,
4372                                                      n);
4373 }
4374
4375
4376 /**
4377  * Last task run during shutdown.  Disconnects us from
4378  * the transport.
4379  */
4380 static void
4381 cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4382 {
4383   struct Neighbour *n;
4384   struct Client *c;
4385
4386 #if DEBUG_CORE
4387   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4388               "Core service shutting down.\n");
4389 #endif
4390   while (NULL != (n = neighbours))
4391     {
4392       neighbours = n->next;
4393       GNUNET_assert (neighbour_count > 0);
4394       neighbour_count--;
4395       free_neighbour (n);
4396     }
4397   GNUNET_assert (transport != NULL);
4398   GNUNET_TRANSPORT_disconnect (transport);
4399   transport = NULL;
4400   GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"), neighbour_count, GNUNET_NO);
4401   GNUNET_SERVER_notification_context_destroy (notifier);
4402   notifier = NULL;
4403   while (NULL != (c = clients))
4404     handle_client_disconnect (NULL, c->client_handle);
4405   if (my_private_key != NULL)
4406     GNUNET_CRYPTO_rsa_key_free (my_private_key);
4407   if (stats != NULL)
4408     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
4409   if (peerinfo != NULL)
4410     GNUNET_PEERINFO_disconnect (peerinfo);
4411   if (mst != NULL)
4412     GNUNET_SERVER_mst_destroy (mst);
4413 }
4414
4415
4416 /**
4417  * Initiate core service.
4418  *
4419  * @param cls closure
4420  * @param server the initialized server
4421  * @param c configuration to use
4422  */
4423 static void
4424 run (void *cls,
4425      struct GNUNET_SERVER_Handle *server,
4426      const struct GNUNET_CONFIGURATION_Handle *c)
4427 {
4428   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
4429     {&handle_client_init, NULL,
4430      GNUNET_MESSAGE_TYPE_CORE_INIT, 0},
4431     {&handle_client_iterate_peers, NULL,
4432      GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
4433      sizeof (struct GNUNET_MessageHeader)},
4434     {&handle_client_request_info, NULL,
4435      GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
4436      sizeof (struct RequestInfoMessage)},
4437     {&handle_client_send_request, NULL,
4438      GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
4439      sizeof (struct SendMessageRequest)},
4440     {&handle_client_send, NULL,
4441      GNUNET_MESSAGE_TYPE_CORE_SEND, 0},
4442     {&handle_client_request_connect, NULL,
4443      GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT,
4444      sizeof (struct ConnectMessage)},
4445     {NULL, NULL, 0, 0}
4446   };
4447   char *keyfile;
4448
4449   cfg = c;  
4450   /* parse configuration */
4451   if (
4452        (GNUNET_OK !=
4453         GNUNET_CONFIGURATION_get_value_number (c,
4454                                                "CORE",
4455                                                "TOTAL_QUOTA_IN",
4456                                                &bandwidth_target_in_bps)) ||
4457        (GNUNET_OK !=
4458         GNUNET_CONFIGURATION_get_value_number (c,
4459                                                "CORE",
4460                                                "TOTAL_QUOTA_OUT",
4461                                                &bandwidth_target_out_bps)) ||
4462        (GNUNET_OK !=
4463         GNUNET_CONFIGURATION_get_value_filename (c,
4464                                                  "GNUNETD",
4465                                                  "HOSTKEY", &keyfile)))
4466     {
4467       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4468                   _
4469                   ("Core service is lacking key configuration settings.  Exiting.\n"));
4470       GNUNET_SCHEDULER_shutdown ();
4471       return;
4472     }
4473   peerinfo = GNUNET_PEERINFO_connect (cfg);
4474   if (NULL == peerinfo)
4475     {
4476       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4477                   _("Could not access PEERINFO service.  Exiting.\n"));
4478       GNUNET_SCHEDULER_shutdown ();
4479       GNUNET_free (keyfile);
4480       return;
4481     }
4482   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
4483   GNUNET_free (keyfile);
4484   if (my_private_key == NULL)
4485     {
4486       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4487                   _("Core service could not access hostkey.  Exiting.\n"));
4488       GNUNET_PEERINFO_disconnect (peerinfo);
4489       GNUNET_SCHEDULER_shutdown ();
4490       return;
4491     }
4492   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
4493   GNUNET_CRYPTO_hash (&my_public_key,
4494                       sizeof (my_public_key), &my_identity.hashPubKey);
4495   /* setup notification */
4496   notifier = GNUNET_SERVER_notification_context_create (server, 
4497                                                         MAX_NOTIFY_QUEUE);
4498   GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
4499   /* setup transport connection */
4500   transport = GNUNET_TRANSPORT_connect (cfg,
4501                                         &my_identity,
4502                                         NULL,
4503                                         &handle_transport_receive,
4504                                         &handle_transport_notify_connect,
4505                                         &handle_transport_notify_disconnect);
4506   GNUNET_assert (NULL != transport);
4507   stats = GNUNET_STATISTICS_create ("core", cfg);
4508
4509   GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded CORE_SEND requests"), 0, GNUNET_NO);
4510   GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded lower priority CORE_SEND requests"), 0, GNUNET_NO);
4511
4512   mst = GNUNET_SERVER_mst_create (&deliver_message,
4513                                   NULL);
4514   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
4515                                 &cleaning_task, NULL);
4516   /* process client requests */
4517   GNUNET_SERVER_add_handlers (server, handlers);
4518   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4519               _("Core service of `%4s' ready.\n"), GNUNET_i2s (&my_identity));
4520 }
4521
4522
4523
4524 /**
4525  * The main function for the transport service.
4526  *
4527  * @param argc number of arguments from the command line
4528  * @param argv command line arguments
4529  * @return 0 ok, 1 on error
4530  */
4531 int
4532 main (int argc, char *const *argv)
4533 {
4534   return (GNUNET_OK ==
4535           GNUNET_SERVICE_run (argc,
4536                               argv,
4537                               "core",
4538                               GNUNET_SERVICE_OPTION_NONE,
4539                               &run, NULL)) ? 0 : 1;
4540 }
4541
4542 /* end of gnunet-service-core.c */