nicer log messages
[oweals/gnunet.git] / src / core / gnunet-service-core.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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 2, 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  * TODO:
27  * TESTING:
28  * - write test for basic core functions:
29  *   + connect to peer
30  *   + transmit (encrypted) message [with handshake]
31  *   + receive (encrypted) message, forward plaintext to clients
32  * POST-TESTING:
33  * - revisit API (which arguments are used, needed)?
34  * - add code to bound queue size when handling client's SEND message
35  * - add code to bound message queue size when passing messages to clients
36  * - add code to discard_expired_messages
37  * - add code to re-transmit key if first attempt failed
38  *   + timeout on connect / key exchange, etc.
39  *   + timeout for automatic re-try, etc.
40  * - add code to give up re-transmission of key if many attempts fail
41  * - add code to send PINGs if we are about to time-out otherwise
42  * ? add heuristic to do another send_key in "handle_set_key"
43  *   in case previous attempt failed / didn't work / persist
44  *   (but don't do it always to avoid storm of SET_KEY's going
45  *   back and forth!) --- alternatively, add "status" field
46  *   of the other peer to the set key message, that way we'd
47  *   know for sure!
48  * - check that hostkey used by transport (for HELLOs) is the
49  *   same as the hostkey that we are using!
50  * - free list of clients on exit
51  * - topology management:
52  *   + bootstrapping (transport offer hello, plugins)
53  *   + internal neighbour selection
54  *   + update bandwidth usage statistics
55  *   + bandwidth allocation (transport set quota)
56  * - optimize lookup (many O(n) list traversals
57  *   could ideally be changed to O(1) hash map lookups)
58  */
59 #include "platform.h"
60 #include "gnunet_util_lib.h"
61 #include "gnunet_hello_lib.h"
62 #include "gnunet_peerinfo_service.h"
63 #include "gnunet_protocols.h"
64 #include "gnunet_signatures.h"
65 #include "gnunet_transport_service.h"
66 #include "core.h"
67
68
69 /**
70  * Receive and send buffer windows grow over time.  For
71  * how long can 'unused' bandwidth accumulate before we
72  * need to cap it?  (specified in ms).
73  */
74 #define MAX_WINDOW_TIME (5 * 60 * 1000)
75
76
77 /**
78  * Amount of bytes per minute (in/out) to assume initially
79  * (before either peer has communicated any particular
80  * preference).  Should be rather low.
81  */
82 #define DEFAULT_BPM_IN_OUT 2048
83
84
85 /**
86  * What is the maximum delay for a SET_KEY message?
87  */
88 #define MAX_SET_KEY_DELAY GNUNET_TIME_UNIT_SECONDS
89
90
91 /**
92  * What how long do we wait for SET_KEY confirmation initially?
93  */
94 #define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
95
96
97 /**
98  * What is the maximum delay for a PING message?
99  */
100 #define MAX_PING_DELAY GNUNET_TIME_UNIT_SECONDS
101
102
103 /**
104  * What is the maximum delay for a PONG message?
105  */
106 #define MAX_PONG_DELAY GNUNET_TIME_UNIT_SECONDS
107
108
109 /**
110  * What is the priority for a SET_KEY message?
111  */
112 #define SET_KEY_PRIORITY 0xFFFFFF
113
114
115 /**
116  * What is the priority for a PING message?
117  */
118 #define PING_PRIORITY 0xFFFFFF
119
120
121 /**
122  * What is the priority for a PONG message?
123  */
124 #define PONG_PRIORITY 0xFFFFFF
125
126
127 /**
128  * What is the maximum age of a message for us to consider
129  * processing it?  Note that this looks at the timestamp used
130  * by the other peer, so clock skew between machines does
131  * come into play here.  So this should be picked high enough
132  * so that a little bit of clock skew does not prevent peers
133  * from connecting to us.
134  */
135 #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
136
137
138 /**
139  * What is the maximum size for encrypted messages?  Note that this
140  * number imposes a clear limit on the maximum size of any message.
141  * Set to a value close to 64k but not so close that transports will
142  * have trouble with their headers.
143  */
144 #define MAX_ENCRYPTED_MESSAGE_SIZE (63 * 1024)
145
146
147 /**
148  * State machine for our P2P encryption handshake.  Everyone starts in
149  * "DOWN", if we receive the other peer's key (other peer initiated)
150  * we start in state RECEIVED (since we will immediately send our
151  * own); otherwise we start in SENT.  If we get back a PONG from
152  * within either state, we move up to CONFIRMED (the PONG will always
153  * be sent back encrypted with the key we sent to the other peer).
154  */
155 enum PeerStateMachine
156 {
157   PEER_STATE_DOWN,
158   PEER_STATE_KEY_SENT,
159   PEER_STATE_KEY_RECEIVED,
160   PEER_STATE_KEY_CONFIRMED
161 };
162
163
164 /**
165  * Number of bytes (at the beginning) of "struct EncryptedMessage"
166  * that are NOT encrypted.
167  */
168 #define ENCRYPTED_HEADER_SIZE (sizeof(struct GNUNET_MessageHeader) + sizeof(uint32_t) + sizeof(GNUNET_HashCode))
169
170 /**
171  * Encapsulation for encrypted messages exchanged between
172  * peers.  Followed by the actual encrypted data.
173  */
174 struct EncryptedMessage
175 {
176   /**
177    * Message type is either CORE_ENCRYPTED_MESSAGE.
178    */
179   struct GNUNET_MessageHeader header;
180
181   /**
182    * Always zero.
183    */
184   uint32_t reserved GNUNET_PACKED;
185
186   /**
187    * Hash of the plaintext, used to verify message integrity;
188    * ALSO used as the IV for the symmetric cipher!  Everything
189    * after this hash will be encrypted.  ENCRYPTED_HEADER_SIZE
190    * must be set to the offset of the next field.
191    */
192   GNUNET_HashCode plaintext_hash;
193
194   /**
195    * Sequence number, in network byte order.  This field
196    * must be the first encrypted/decrypted field and the
197    * first byte that is hashed for the plaintext hash.
198    */
199   uint32_t sequence_number GNUNET_PACKED;
200
201   /**
202    * Desired bandwidth (how much we should send to this
203    * peer / how much is the sender willing to receive),
204    * in bytes per minute.
205    */
206   uint32_t inbound_bpm_limit GNUNET_PACKED;
207
208   /**
209    * Timestamp.  Used to prevent reply of ancient messages
210    * (recent messages are caught with the sequence number).
211    */
212   struct GNUNET_TIME_AbsoluteNBO timestamp;
213
214 };
215
216 /**
217  * We're sending an (encrypted) PING to the other peer to check if he
218  * can decrypt.  The other peer should respond with a PONG with the
219  * same content, except this time encrypted with the receiver's key.
220  */
221 struct PingMessage
222 {
223   /**
224    * Message type is either CORE_PING or CORE_PONG.
225    */
226   struct GNUNET_MessageHeader header;
227
228   /**
229    * Random number chosen to make reply harder.
230    */
231   uint32_t challenge GNUNET_PACKED;
232
233   /**
234    * Intended target of the PING, used primarily to check
235    * that decryption actually worked.
236    */
237   struct GNUNET_PeerIdentity target;
238 };
239
240
241 /**
242  * Message transmitted to set (or update) a session key.
243  */
244 struct SetKeyMessage
245 {
246
247   /**
248    * Message type is either CORE_SET_KEY.
249    */
250   struct GNUNET_MessageHeader header;
251
252   /**
253    * Status of the sender (should be in "enum PeerStateMachine"), nbo.
254    */
255   int32_t sender_status GNUNET_PACKED;
256
257   /**
258    * Purpose of the signature, will be
259    * GNUNET_SIGNATURE_PURPOSE_SET_KEY.
260    */
261   struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
262
263   /**
264    * At what time was this key created?
265    */
266   struct GNUNET_TIME_AbsoluteNBO creation_time;
267
268   /**
269    * The encrypted session key.
270    */
271   struct GNUNET_CRYPTO_RsaEncryptedData encrypted_key;
272
273   /**
274    * Who is the intended recipient?
275    */
276   struct GNUNET_PeerIdentity target;
277
278   /**
279    * Signature of the stuff above (starting at purpose).
280    */
281   struct GNUNET_CRYPTO_RsaSignature signature;
282
283 };
284
285
286 /**
287  * Message waiting for transmission. This struct
288  * is followed by the actual content of the message.
289  */
290 struct MessageEntry
291 {
292
293   /**
294    * We keep messages in a linked list (for now).
295    */
296   struct MessageEntry *next;
297
298   /**
299    * By when are we supposed to transmit this message?
300    */
301   struct GNUNET_TIME_Absolute deadline;
302
303   /**
304    * How important is this message to us?
305    */
306   unsigned int priority;
307
308   /**
309    * How long is the message? (number of bytes following
310    * the "struct MessageEntry", but not including the
311    * size of "struct MessageEntry" itself!)
312    */
313   uint16_t size;
314
315   /**
316    * Was this message selected for transmission in the
317    * current round? GNUNET_YES or GNUNET_NO.
318    */
319   int16_t do_transmit;
320
321 };
322
323
324 struct Neighbour
325 {
326   /**
327    * We keep neighbours in a linked list (for now).
328    */
329   struct Neighbour *next;
330
331   /**
332    * Unencrypted messages destined for this peer.
333    */
334   struct MessageEntry *messages;
335
336   /**
337    * Head of the batched, encrypted message queue (already ordered,
338    * transmit starting with the head).
339    */
340   struct MessageEntry *encrypted_head;
341
342   /**
343    * Tail of the batched, encrypted message queue (already ordered,
344    * append new messages to tail)
345    */
346   struct MessageEntry *encrypted_tail;
347
348   /**
349    * Handle for pending requests for transmission to this peer
350    * with the transport service.  NULL if no request is pending.
351    */
352   struct GNUNET_TRANSPORT_TransmitHandle *th;
353
354   /**
355    * Public key of the neighbour, NULL if we don't have it yet.
356    */
357   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
358
359   /**
360    * We received a PING message before we got the "public_key"
361    * (or the SET_KEY).  We keep it here until we have a key
362    * to decrypt it.  NULL if no PING is pending.
363    */
364   struct PingMessage *pending_ping;
365
366   /**
367    * Identity of the neighbour.
368    */
369   struct GNUNET_PeerIdentity peer;
370
371   /**
372    * Key we use to encrypt our messages for the other peer
373    * (initialized by us when we do the handshake).
374    */
375   struct GNUNET_CRYPTO_AesSessionKey encrypt_key;
376
377   /**
378    * Key we use to decrypt messages from the other peer
379    * (given to us by the other peer during the handshake).
380    */
381   struct GNUNET_CRYPTO_AesSessionKey decrypt_key;
382
383   /**
384    * ID of task used for re-trying plaintext scheduling.
385    */
386   GNUNET_SCHEDULER_TaskIdentifier retry_plaintext_task;
387
388   /**
389    * ID of task used for re-trying SET_KEY and PING message.
390    */
391   GNUNET_SCHEDULER_TaskIdentifier retry_set_key_task;
392
393   /**
394    * At what time did we generate our encryption key?
395    */
396   struct GNUNET_TIME_Absolute encrypt_key_created;
397
398   /**
399    * At what time did the other peer generate the decryption key?
400    */
401   struct GNUNET_TIME_Absolute decrypt_key_created;
402
403   /**
404    * At what time did we initially establish (as in, complete session
405    * key handshake) this connection?  Should be zero if status != KEY_CONFIRMED.
406    */
407   struct GNUNET_TIME_Absolute time_established;
408
409   /**
410    * At what time did we last receive an encrypted message from the
411    * other peer?  Should be zero if status != KEY_CONFIRMED.
412    */
413   struct GNUNET_TIME_Absolute last_activity;
414
415   /**
416    * Last latency observed from this peer.
417    */
418   struct GNUNET_TIME_Relative last_latency;
419
420   /**
421    * At what frequency are we currently re-trying SET KEY messages?
422    */
423   struct GNUNET_TIME_Relative set_key_retry_frequency;
424
425   /**
426    * Time of our last update to the "available_send_window".
427    */
428   struct GNUNET_TIME_Absolute last_asw_update;
429
430   /**
431    * Time of our last update to the "available_recv_window".
432    */
433   struct GNUNET_TIME_Absolute last_arw_update;
434
435   /**
436    * Number of bytes that we are eligible to transmit to this
437    * peer at this point.  Incremented every minute by max_out_bpm,
438    * bounded by max_bpm (no back-log larger than MAX_BUF_FACT minutes,
439    * bandwidth-hogs are sampled at a frequency of about 78s!);
440    * may get negative if we have VERY high priority content.
441    */
442   long long available_send_window;
443
444   /**
445    * How much downstream capacity of this peer has been reserved for
446    * our traffic?  (Our clients can request that a certain amount of
447    * bandwidth is available for replies to them; this value is used to
448    * make sure that this reserved amount of bandwidth is actually
449    * available).
450    */
451   long long available_recv_window;
452
453   /**
454    * How valueable were the messages of this peer recently?
455    */
456   double current_preference;
457
458   /**
459    * Bit map indicating which of the 32 sequence numbers before the last
460    * were received (good for accepting out-of-order packets and
461    * estimating reliability of the connection)
462    */
463   unsigned int last_packets_bitmap;
464
465   /**
466    * Number of messages in the message queue for this peer.
467    */
468   unsigned int message_queue_size;
469
470   /**
471    * last sequence number received on this connection (highest)
472    */
473   uint32_t last_sequence_number_received;
474
475   /**
476    * last sequence number transmitted
477    */
478   uint32_t last_sequence_number_sent;
479
480   /**
481    * Available bandwidth in for this peer (current target).
482    */
483   uint32_t bpm_in;
484
485   /**
486    * Available bandwidth out for this peer (current target).
487    */
488   uint32_t bpm_out;
489
490   /**
491    * Internal bandwidth limit set for this peer (initially
492    * typcially set to "-1").  "bpm_out" is MAX of
493    * "bpm_out_internal_limit" and "bpm_out_external_limit".
494    */
495   uint32_t bpm_out_internal_limit;
496
497   /**
498    * External bandwidth limit set for this peer by the
499    * peer that we are communicating with.  "bpm_out" is MAX of
500    * "bpm_out_internal_limit" and "bpm_out_external_limit".
501    */
502   uint32_t bpm_out_external_limit;
503
504   /**
505    * What was our PING challenge number?
506    */
507   uint32_t ping_challenge;
508
509   /**
510    * What is our connection status?
511    */
512   enum PeerStateMachine status;
513
514 };
515
516
517 /**
518  * Events are messages for clients.  The struct
519  * itself is followed by the actual message.
520  */
521 struct Event
522 {
523   /**
524    * This is a linked list.
525    */
526   struct Event *next;
527
528   /**
529    * Size of the message.
530    */
531   size_t size;
532
533   /**
534    * Could this event be dropped if this queue
535    * is getting too large? (NOT YET USED!)
536    */
537   int can_drop;
538
539 };
540
541
542 /**
543  * Data structure for each client connected to the core service.
544  */
545 struct Client
546 {
547   /**
548    * Clients are kept in a linked list.
549    */
550   struct Client *next;
551
552   /**
553    * Handle for the client with the server API.
554    */
555   struct GNUNET_SERVER_Client *client_handle;
556
557   /**
558    * Linked list of messages we still need to deliver to
559    * this client.
560    */
561   struct Event *event_head;
562
563   /**
564    * Tail of the linked list of events.
565    */
566   struct Event *event_tail;
567
568   /**
569    * Current transmit handle, NULL if no transmission request
570    * is pending.
571    */
572   struct GNUNET_NETWORK_TransmitHandle *th;
573
574   /**
575    * Array of the types of messages this peer cares
576    * about (with "tcnt" entries).  Allocated as part
577    * of this client struct, do not free!
578    */
579   uint16_t *types;
580
581   /**
582    * Options for messages this client cares about,
583    * see GNUNET_CORE_OPTION_ values.
584    */
585   uint32_t options;
586
587   /**
588    * Number of types of incoming messages this client
589    * specifically cares about.  Size of the "types" array.
590    */
591   unsigned int tcnt;
592
593 };
594
595
596 /**
597  * Our public key.
598  */
599 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
600
601 /**
602  * Our identity.
603  */
604 static struct GNUNET_PeerIdentity my_identity;
605
606 /**
607  * Our private key.
608  */
609 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
610
611 /**
612  * Our scheduler.
613  */
614 struct GNUNET_SCHEDULER_Handle *sched;
615
616 /**
617  * Our configuration.
618  */
619 struct GNUNET_CONFIGURATION_Handle *cfg;
620
621 /**
622  * Our server.
623  */
624 static struct GNUNET_SERVER_Handle *server;
625
626 /**
627  * Transport service.
628  */
629 static struct GNUNET_TRANSPORT_Handle *transport;
630
631 /**
632  * We keep neighbours in a linked list (for now).
633  */
634 static struct Neighbour *neighbours;
635
636 /**
637  * Linked list of our clients.
638  */
639 static struct Client *clients;
640
641
642 /**
643  * Recalculate the number of bytes we expect to
644  * receive or transmit in a given window.
645  *
646  * @param window pointer to the byte counter (updated)
647  * @param ts pointer to the timestamp (updated)
648  * @param bpm number of bytes per minute that should
649  *        be added to the window.
650  */
651 static void
652 update_window (long long *window,
653                struct GNUNET_TIME_Absolute *ts, unsigned int bpm)
654 {
655   struct GNUNET_TIME_Relative since;
656
657   since = GNUNET_TIME_absolute_get_duration (*ts);
658   if (since.value < 60 * 1000)
659     return;                     /* not even a minute has passed */
660   *ts = GNUNET_TIME_absolute_get ();
661   *window += (bpm * since.value) / 60 / 1000;
662   if (*window > MAX_WINDOW_TIME * bpm)
663     *window = MAX_WINDOW_TIME * bpm;
664 }
665
666
667 /**
668  * Find the entry for the given neighbour.
669  *
670  * @param peer identity of the neighbour
671  * @return NULL if we are not connected, otherwise the
672  *         neighbour's entry.
673  */
674 static struct Neighbour *
675 find_neighbour (const struct GNUNET_PeerIdentity *peer)
676 {
677   struct Neighbour *ret;
678
679   ret = neighbours;
680   while ((ret != NULL) &&
681          (0 != memcmp (&ret->peer,
682                        peer, sizeof (struct GNUNET_PeerIdentity))))
683     ret = ret->next;
684   return ret;
685 }
686
687
688 /**
689  * Find the entry for the given client.
690  *
691  * @param client handle for the client
692  * @return NULL if we are not connected, otherwise the
693  *         client's struct.
694  */
695 static struct Client *
696 find_client (const struct GNUNET_SERVER_Client *client)
697 {
698   struct Client *ret;
699
700   ret = clients;
701   while ((ret != NULL) && (client != ret->client_handle))
702     ret = ret->next;
703   return ret;
704 }
705
706
707 /**
708  * If necessary, initiate a request with the server to
709  * transmit messages from the queue of the given client.
710  * @param client who to transfer messages to
711  */
712 static void request_transmit (struct Client *client);
713
714
715 /**
716  * Client is ready to receive data, provide it.
717  * @param cls closure
718  * @param size number of bytes available in buf
719  * @param buf where the callee should write the message
720  * @return number of bytes written to buf
721  */
722 static size_t
723 do_client_transmit (void *cls, size_t size, void *buf)
724 {
725   struct Client *client = cls;
726   struct Event *e;
727   char *tgt;
728   size_t ret;
729
730   client->th = NULL;
731 #if DEBUG_CORE_CLIENT
732   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
733               "Client ready to receive %u bytes.\n", size);
734 #endif
735   if (buf == NULL)
736     {
737 #if DEBUG_CORE
738       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
739                   "Failed to transmit data to client (disconnect)?\n");
740 #endif
741       return 0;                 /* we'll surely get a disconnect soon... */
742     }
743   tgt = buf;
744   ret = 0;
745   while ((NULL != (e = client->event_head)) && (e->size <= size))
746     {
747       memcpy (&tgt[ret], &e[1], e->size);
748       size -= e->size;
749       ret += e->size;
750       client->event_head = e->next;
751       GNUNET_free (e);
752     }
753   GNUNET_assert (ret > 0);
754   if (client->event_head == NULL)
755     client->event_tail = NULL;
756 #if DEBUG_CORE_CLIENT
757   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
758               "Transmitting %u bytes to client\n", ret);
759 #endif
760   request_transmit (client);
761   return ret;
762 }
763
764
765 /**
766  * If necessary, initiate a request with the server to
767  * transmit messages from the queue of the given client.
768  * @param client who to transfer messages to
769  */
770 static void
771 request_transmit (struct Client *client)
772 {
773
774   if (NULL != client->th)
775     return;                     /* already pending */
776   if (NULL == client->event_head)
777     return;                     /* no more events pending */
778 #if DEBUG_CORE_CLIENT
779   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
780               "Asking server to transmit %u bytes to client\n",
781               client->event_head->size);
782 #endif
783   client->th
784     = GNUNET_SERVER_notify_transmit_ready (client->client_handle,
785                                            client->event_head->size,
786                                            GNUNET_TIME_UNIT_FOREVER_REL,
787                                            &do_client_transmit, client);
788 }
789
790
791 /**
792  * Send a message to one of our clients.
793  * @param client target for the message
794  * @param msg message to transmit
795  * @param can_drop could this message be dropped if the
796  *        client's queue is getting too large?
797  */
798 static void
799 send_to_client (struct Client *client,
800                 const struct GNUNET_MessageHeader *msg, int can_drop)
801 {
802   struct Event *e;
803   uint16_t msize;
804
805 #if DEBUG_CORE_CLIENT
806   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
807               "Preparing to send message of type %u to client.\n",
808               ntohs (msg->type));
809 #endif
810   msize = ntohs (msg->size);
811   e = GNUNET_malloc (sizeof (struct Event) + msize);
812   /* append */
813   if (client->event_tail != NULL)
814     client->event_tail->next = e;
815   else
816     client->event_head = e;
817   client->event_tail = e;
818   e->can_drop = can_drop;
819   e->size = msize;
820   memcpy (&e[1], msg, msize);
821   request_transmit (client);
822 }
823
824
825 /**
826  * Send a message to all of our current clients.
827  */
828 static void
829 send_to_all_clients (const struct GNUNET_MessageHeader *msg, int can_drop)
830 {
831   struct Client *c;
832
833   c = clients;
834   while (c != NULL)
835     {
836       send_to_client (c, msg, can_drop);
837       c = c->next;
838     }
839 }
840
841
842 /**
843  * Handle CORE_INIT request.
844  */
845 static void
846 handle_client_init (void *cls,
847                     struct GNUNET_SERVER_Client *client,
848                     const struct GNUNET_MessageHeader *message)
849 {
850   const struct InitMessage *im;
851   struct InitReplyMessage irm;
852   struct Client *c;
853   uint16_t msize;
854   const uint16_t *types;
855   struct Neighbour *n;
856   struct ConnectNotifyMessage cnm;
857
858 #if DEBUG_CORE_CLIENT
859   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
860               "Client connecting to core service with `%s' message\n",
861               "INIT");
862 #endif
863   /* check that we don't have an entry already */
864   c = clients;
865   while (c != NULL)
866     {
867       if (client == c->client_handle)
868         {
869           GNUNET_break (0);
870           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
871           return;
872         }
873       c = c->next;
874     }
875   msize = ntohs (message->size);
876   if (msize < sizeof (struct InitMessage))
877     {
878       GNUNET_break (0);
879       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
880       return;
881     }
882   im = (const struct InitMessage *) message;
883   types = (const uint16_t *) &im[1];
884   msize -= sizeof (struct InitMessage);
885   c = GNUNET_malloc (sizeof (struct Client) + msize);
886   c->client_handle = client;
887   c->next = clients;
888   clients = c;
889   memcpy (&c[1], types, msize);
890   c->types = (uint16_t *) & c[1];
891   c->options = ntohl (im->options);
892   c->tcnt = msize / sizeof (uint16_t);
893   /* send init reply message */
894   irm.header.size = htons (sizeof (struct InitReplyMessage));
895   irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
896   irm.reserved = htonl (0);
897   memcpy (&irm.publicKey,
898           &my_public_key,
899           sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
900 #if DEBUG_CORE_CLIENT
901   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
902               "Sending `%s' message to client.\n", "INIT_REPLY");
903 #endif
904   send_to_client (c, &irm.header, GNUNET_NO);
905   /* notify new client about existing neighbours */
906   cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
907   cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
908   n = neighbours;
909   while (n != NULL)
910     {
911 #if DEBUG_CORE_CLIENT
912       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
913                   "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
914 #endif
915       cnm.bpm_available = htonl (n->bpm_out);
916       cnm.last_activity = GNUNET_TIME_absolute_hton (n->last_activity);
917       cnm.peer = n->peer;
918       send_to_client (c, &cnm.header, GNUNET_NO);
919       n = n->next;
920     }
921   GNUNET_SERVER_receive_done (client, GNUNET_OK);
922 }
923
924
925 /**
926  * A client disconnected, clean up.
927  *
928  * @param cls closure
929  * @param client identification of the client
930  */
931 static void
932 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
933 {
934   struct Client *pos;
935   struct Client *prev;
936
937 #if DEBUG_CORE_CLIENT
938   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
939               "Client has disconnected from core service.\n");
940 #endif
941   prev = NULL;
942   pos = clients;
943   while (pos != NULL)
944     {
945       if (client == pos->client_handle)
946         {
947           if (prev == NULL)
948             clients = pos->next;
949           else
950             prev->next = pos->next;
951           if (pos->th != NULL)
952             GNUNET_NETWORK_notify_transmit_ready_cancel (pos->th);
953           GNUNET_free (pos);
954           return;
955         }
956       prev = pos;
957       pos = pos->next;
958     }
959   /* client never sent INIT */
960 }
961
962
963 /**
964  * Handle REQUEST_CONFIGURE request.
965  */
966 static void
967 handle_client_request_configure (void *cls,
968                                  struct GNUNET_SERVER_Client *client,
969                                  const struct GNUNET_MessageHeader *message)
970 {
971   const struct RequestConfigureMessage *rcm;
972   struct Neighbour *n;
973   struct ConfigurationInfoMessage cim;
974   struct Client *c;
975   int reserv;
976
977 #if DEBUG_CORE_CLIENT
978   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
979               "Core service receives `%s' request.\n", "CONFIGURE");
980 #endif
981   rcm = (const struct RequestConfigureMessage *) message;
982   n = find_neighbour (&rcm->peer);
983   memset (&cim, 0, sizeof (cim));
984   if ((n != NULL) && (n->status == PEER_STATE_KEY_CONFIRMED))
985     {
986       n->bpm_out_internal_limit = ntohl (rcm->limit_outbound_bpm);
987       n->bpm_out = GNUNET_MAX (n->bpm_out_internal_limit,
988                                n->bpm_out_external_limit);
989       reserv = ntohl (rcm->reserve_inbound);
990       if (reserv < 0)
991         {
992           n->available_recv_window += reserv;
993         }
994       else if (reserv > 0)
995         {
996           update_window (&n->available_recv_window,
997                          &n->last_arw_update, n->bpm_in);
998           if (n->available_recv_window < reserv)
999             reserv = n->available_recv_window;
1000           n->available_recv_window -= reserv;
1001         }
1002       n->current_preference += rcm->preference_change;
1003       if (n->current_preference < 0)
1004         n->current_preference = 0;
1005       cim.reserved_amount = htonl (reserv);
1006       cim.bpm_in = htonl (n->bpm_in);
1007       cim.bpm_out = htonl (n->bpm_out);
1008       cim.latency = GNUNET_TIME_relative_hton (n->last_latency);
1009       cim.preference = n->current_preference;
1010     }
1011   cim.header.size = htons (sizeof (struct ConfigurationInfoMessage));
1012   cim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO);
1013   cim.peer = rcm->peer;
1014   c = find_client (client);
1015   if (c == NULL)
1016     {
1017       GNUNET_break (0);
1018       return;
1019     }
1020 #if DEBUG_CORE_CLIENT
1021   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1022               "Sending `%s' message to client.\n", "CONFIGURATION_INFO");
1023 #endif
1024   send_to_client (c, &cim.header, GNUNET_NO);
1025 }
1026
1027
1028 /**
1029  * Check if we have encrypted messages for the specified neighbour
1030  * pending, and if so, check with the transport about sending them
1031  * out.
1032  *
1033  * @param n neighbour to check.
1034  */
1035 static void process_encrypted_neighbour_queue (struct Neighbour *n);
1036
1037
1038 /**
1039  * Function called when the transport service is ready to
1040  * receive an encrypted message for the respective peer
1041  *
1042  * @param cls neighbour to use message from
1043  * @param size number of bytes we can transmit
1044  * @param buf where to copy the message
1045  * @return number of bytes transmitted
1046  */
1047 static size_t
1048 notify_encrypted_transmit_ready (void *cls, size_t size, void *buf)
1049 {
1050   struct Neighbour *n = cls;
1051   struct MessageEntry *m;
1052   size_t ret;
1053   char *cbuf;
1054
1055   n->th = NULL;
1056   GNUNET_assert (NULL != (m = n->encrypted_head));
1057   n->encrypted_head = m->next;
1058   if (m->next == NULL)
1059     n->encrypted_tail = NULL;
1060   ret = 0;
1061   cbuf = buf;
1062   if (buf != NULL)
1063     {
1064       GNUNET_assert (size >= m->size);
1065       memcpy (cbuf, &m[1], m->size);
1066       ret = m->size;
1067       process_encrypted_neighbour_queue (n);
1068       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1069                   "Copied message of type %u and size %u into transport buffer for `%4s'\n",
1070                   ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
1071                   ret, GNUNET_i2s (&n->peer));
1072     }
1073   else
1074     {
1075       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1076                   "Transmission for message of type %u and size %u failed\n",
1077                   ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
1078                   m->size);
1079     }
1080   GNUNET_free (m);
1081   return ret;
1082 }
1083
1084
1085 /**
1086  * Check if we have plaintext messages for the specified neighbour
1087  * pending, and if so, consider batching and encrypting them (and
1088  * then trigger processing of the encrypted queue if needed).
1089  *
1090  * @param n neighbour to check.
1091  */
1092 static void process_plaintext_neighbour_queue (struct Neighbour *n);
1093
1094
1095 /**
1096  * Check if we have encrypted messages for the specified neighbour
1097  * pending, and if so, check with the transport about sending them
1098  * out.
1099  *
1100  * @param n neighbour to check.
1101  */
1102 static void
1103 process_encrypted_neighbour_queue (struct Neighbour *n)
1104 {
1105   if (n->th != NULL)
1106     return;  /* request already pending */
1107   if (n->encrypted_head == NULL)
1108     {
1109       /* encrypted queue empty, try plaintext instead */
1110       process_plaintext_neighbour_queue (n);
1111       return;
1112     }
1113   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1114               "Asking transport for transmission of %u bytes to `%4s' in next %llu ms\n",
1115               n->encrypted_head->size,
1116               GNUNET_i2s (&n->peer),
1117               GNUNET_TIME_absolute_get_remaining (n->
1118                                                   encrypted_head->deadline).
1119               value);
1120   n->th =
1121     GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer,
1122                                             n->encrypted_head->size,
1123                                             GNUNET_TIME_absolute_get_remaining
1124                                             (n->encrypted_head->deadline),
1125                                             &notify_encrypted_transmit_ready,
1126                                             n);
1127   if (n->th == NULL)
1128     {
1129       /* message request too large (oops) */
1130       GNUNET_break (0);
1131       /* FIXME: handle error somehow! */
1132     }
1133 }
1134
1135
1136 /**
1137  * Decrypt size bytes from in and write the result to out.  Use the
1138  * key for inbound traffic of the given neighbour.  This function does
1139  * NOT do any integrity-checks on the result.
1140  *
1141  * @param n neighbour we are receiving from
1142  * @param iv initialization vector to use
1143  * @param in ciphertext
1144  * @param out plaintext
1145  * @param size size of in/out
1146  * @return GNUNET_OK on success
1147  */
1148 static int
1149 do_decrypt (struct Neighbour *n,
1150             const GNUNET_HashCode * iv,
1151             const void *in, void *out, size_t size)
1152 {
1153   if (size != (uint16_t) size)
1154     {
1155       GNUNET_break (0);
1156       return GNUNET_NO;
1157     }
1158   if ((n->status != PEER_STATE_KEY_RECEIVED) &&
1159       (n->status != PEER_STATE_KEY_CONFIRMED))
1160     {
1161       GNUNET_break_op (0);
1162       return GNUNET_SYSERR;
1163     }
1164   if (size !=
1165       GNUNET_CRYPTO_aes_decrypt (&n->decrypt_key,
1166                                  in,
1167                                  (uint16_t) size,
1168                                  (const struct
1169                                   GNUNET_CRYPTO_AesInitializationVector *) iv,
1170                                  out))
1171     {
1172       GNUNET_break (0);
1173       return GNUNET_SYSERR;
1174     }
1175   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1176               "Decrypted %u bytes from `%4s' using key %u\n",
1177               size, GNUNET_i2s (&n->peer), n->decrypt_key.crc32);
1178   return GNUNET_OK;
1179 }
1180
1181
1182 /**
1183  * Encrypt size bytes from in and write the result to out.  Use the
1184  * key for outbound traffic of the given neighbour.
1185  *
1186  * @param n neighbour we are sending to
1187  * @param iv initialization vector to use
1188  * @param in ciphertext
1189  * @param out plaintext
1190  * @param size size of in/out
1191  * @return GNUNET_OK on success
1192  */
1193 static int
1194 do_encrypt (struct Neighbour *n,
1195             const GNUNET_HashCode * iv,
1196             const void *in, void *out, size_t size)
1197 {
1198   if (size != (uint16_t) size)
1199     {
1200       GNUNET_break (0);
1201       return GNUNET_NO;
1202     }
1203   GNUNET_assert (size ==
1204                  GNUNET_CRYPTO_aes_encrypt (in,
1205                                             (uint16_t) size,
1206                                             &n->encrypt_key,
1207                                             (const struct
1208                                              GNUNET_CRYPTO_AesInitializationVector
1209                                              *) iv, out));
1210   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1211               "Encrypted %u bytes for `%4s' using key %u\n", size,
1212               GNUNET_i2s (&n->peer), n->encrypt_key.crc32);
1213   return GNUNET_OK;
1214 }
1215
1216
1217 /**
1218  * Select messages for transmission.  This heuristic uses a combination
1219  * of earliest deadline first (EDF) scheduling (with bounded horizon)
1220  * and priority-based discard (in case no feasible schedule exist) and
1221  * speculative optimization (defer any kind of transmission until
1222  * we either create a batch of significant size, 25% of max, or until
1223  * we are close to a deadline).  Furthermore, when scheduling the
1224  * heuristic also packs as many messages into the batch as possible,
1225  * starting with those with the earliest deadline.  Yes, this is fun.
1226  *
1227  * @param n neighbour to select messages from
1228  * @param size number of bytes to select for transmission
1229  * @param retry_time set to the time when we should try again
1230  *        (only valid if this function returns zero)
1231  * @return number of bytes selected, or 0 if we decided to
1232  *         defer scheduling overall; in that case, retry_time is set.
1233  */
1234 static size_t
1235 select_messages (struct Neighbour *n,
1236                  size_t size, struct GNUNET_TIME_Relative *retry_time)
1237 {
1238   struct MessageEntry *pos;
1239   struct MessageEntry *min;
1240   struct MessageEntry *last;
1241   unsigned int min_prio;
1242   struct GNUNET_TIME_Absolute t;
1243   struct GNUNET_TIME_Absolute now;
1244   uint64_t delta;
1245   uint64_t avail;
1246   unsigned long long slack;     /* how long could we wait before missing deadlines? */
1247   size_t off;
1248   int discard_low_prio;
1249
1250   GNUNET_assert (NULL != n->messages);
1251   now = GNUNET_TIME_absolute_get ();
1252   /* last entry in linked list of messages processed */
1253   last = NULL;
1254   /* should we remove the entry with the lowest
1255      priority from consideration for scheduling at the
1256      end of the loop? */
1257   discard_low_prio = GNUNET_YES;
1258   while (GNUNET_YES == discard_low_prio)
1259     {
1260       min = NULL;
1261       min_prio = -1;
1262       discard_low_prio = GNUNET_NO;
1263       /* number of bytes available for transmission at time "t" */
1264       avail = n->available_send_window;
1265       t = n->last_asw_update;
1266       /* how many bytes have we (hyptothetically) scheduled so far */
1267       off = 0;
1268       /* maximum time we can wait before transmitting anything
1269          and still make all of our deadlines */
1270       slack = -1;
1271
1272       pos = n->messages;
1273       /* note that we use "*2" here because we want to look
1274          a bit further into the future; much more makes no
1275          sense since new message might be scheduled in the
1276          meantime... */
1277       while ((pos != NULL) && (off < size * 2))
1278         {
1279           if (pos->do_transmit == GNUNET_YES)
1280             {
1281               /* already removed from consideration */
1282               pos = pos->next;
1283               continue;
1284             }
1285           if (discard_low_prio == GNUNET_NO)
1286             {
1287               delta = pos->deadline.value;
1288               if (delta < t.value)
1289                 delta = 0;
1290               else
1291                 delta = t.value - delta;
1292               avail += delta * n->bpm_out / 1000 / 60;
1293               if (avail < pos->size)
1294                 {
1295                   discard_low_prio = GNUNET_YES;        /* we could not schedule this one! */
1296                 }
1297               else
1298                 {
1299                   avail -= pos->size;
1300                   /* update slack, considering both its absolute deadline
1301                      and relative deadlines caused by other messages
1302                      with their respective load */
1303                   slack = GNUNET_MIN (slack, avail / n->bpm_out);
1304                   if (pos->deadline.value < now.value)
1305                     slack = 0;
1306                   else
1307                     slack =
1308                       GNUNET_MIN (slack, pos->deadline.value - now.value);
1309                 }
1310             }
1311           off += pos->size;
1312           t.value = GNUNET_MAX (pos->deadline.value, t.value);
1313           if (pos->priority <= min_prio)
1314             {
1315               /* update min for discard */
1316               min_prio = pos->priority;
1317               min = pos;
1318             }
1319           pos = pos->next;
1320         }
1321       if (discard_low_prio)
1322         {
1323           GNUNET_assert (min != NULL);
1324           /* remove lowest-priority entry from consideration */
1325           min->do_transmit = GNUNET_YES;        /* means: discard (for now) */
1326         }
1327       last = pos;
1328     }
1329   /* guard against sending "tiny" messages with large headers without
1330      urgent deadlines */
1331   if ((slack > 1000) && (size > 4 * off))
1332     {
1333       /* less than 25% of message would be filled with
1334          deadlines still being met if we delay by one
1335          second or more; so just wait for more data */
1336       retry_time->value = slack / 2;
1337       /* reset do_transmit values for next time */
1338       while (pos != last)
1339         {
1340           pos->do_transmit = GNUNET_NO;
1341           pos = pos->next;
1342         }
1343       return 0;
1344     }
1345   /* select marked messages (up to size) for transmission */
1346   off = 0;
1347   pos = n->messages;
1348   while (pos != last)
1349     {
1350       if ((pos->size <= size) && (pos->do_transmit == GNUNET_NO))
1351         {
1352           pos->do_transmit = GNUNET_YES;        /* mark for transmission */
1353           off += pos->size;
1354           size -= pos->size;
1355         }
1356       else
1357         pos->do_transmit = GNUNET_NO;   /* mark for not transmitting! */
1358       pos = pos->next;
1359     }
1360   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1361               "Selected %u bytes of plaintext messages for transmission to `%4s'.\n",
1362               off, GNUNET_i2s (&n->peer));
1363   return off;
1364 }
1365
1366
1367 /**
1368  * Batch multiple messages into a larger buffer.
1369  *
1370  * @param n neighbour to take messages from
1371  * @param buf target buffer
1372  * @param size size of buf
1373  * @param deadline set to transmission deadline for the result
1374  * @param retry_time set to the time when we should try again
1375  *        (only valid if this function returns zero)
1376  * @param priority set to the priority of the batch
1377  * @return number of bytes written to buf (can be zero)
1378  */
1379 static size_t
1380 batch_message (struct Neighbour *n,
1381                char *buf,
1382                size_t size,
1383                struct GNUNET_TIME_Absolute *deadline,
1384                struct GNUNET_TIME_Relative *retry_time,
1385                unsigned int *priority)
1386 {
1387   struct MessageEntry *pos;
1388   struct MessageEntry *prev;
1389   struct MessageEntry *next;
1390   size_t ret;
1391
1392   ret = 0;
1393   *priority = 0;
1394   *deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
1395   *retry_time = GNUNET_TIME_UNIT_FOREVER_REL;
1396   if (0 == select_messages (n, size, retry_time))
1397     {
1398       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1399                   "No messages selected, will try again in %llu ms\n",
1400                   retry_time->value);
1401       return 0;
1402     }
1403   pos = n->messages;
1404   prev = NULL;
1405   while ((pos != NULL) && (size >= sizeof (struct GNUNET_MessageHeader)))
1406     {
1407       next = pos->next;
1408       if (GNUNET_YES == pos->do_transmit)
1409         {
1410           GNUNET_assert (pos->size <= size);
1411           memcpy (&buf[ret], &pos[1], pos->size);
1412           ret += pos->size;
1413           size -= pos->size;
1414           *priority += pos->priority;
1415           deadline->value = GNUNET_MIN (deadline->value, pos->deadline.value);
1416           GNUNET_free (pos);
1417           if (prev == NULL)
1418             n->messages = next;
1419           else
1420             prev->next = next;
1421         }
1422       else
1423         {
1424           prev = pos;
1425         }
1426       pos = next;
1427     }
1428   return ret;
1429 }
1430
1431
1432 /**
1433  * Remove messages with deadlines that have long expired from
1434  * the queue.
1435  *
1436  * @param n neighbour to inspect
1437  */
1438 static void
1439 discard_expired_messages (struct Neighbour *n)
1440 {
1441   /* FIXME */
1442 }
1443
1444
1445 /**
1446  * Signature of the main function of a task.
1447  *
1448  * @param cls closure
1449  * @param tc context information (why was this task triggered now)
1450  */
1451 static void
1452 retry_plaintext_processing (void *cls,
1453                             const struct GNUNET_SCHEDULER_TaskContext *tc)
1454 {
1455   struct Neighbour *n = cls;
1456
1457   n->retry_plaintext_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1458   process_plaintext_neighbour_queue (n);
1459 }
1460
1461
1462 /**
1463  * Send our key (and encrypted PING) to the other peer.
1464  *
1465  * @param n the other peer
1466  */
1467 static void send_key (struct Neighbour *n);
1468
1469
1470 /**
1471  * Check if we have plaintext messages for the specified neighbour
1472  * pending, and if so, consider batching and encrypting them (and
1473  * then trigger processing of the encrypted queue if needed).
1474  *
1475  * @param n neighbour to check.
1476  */
1477 static void
1478 process_plaintext_neighbour_queue (struct Neighbour *n)
1479 {
1480   char pbuf[MAX_ENCRYPTED_MESSAGE_SIZE];        /* plaintext */
1481   size_t used;
1482   size_t esize;
1483   struct EncryptedMessage *em;  /* encrypted message */
1484   struct EncryptedMessage *ph;  /* plaintext header */
1485   struct MessageEntry *me;
1486   unsigned int priority;
1487   struct GNUNET_TIME_Absolute deadline;
1488   struct GNUNET_TIME_Relative retry_time;
1489
1490   if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1491     {
1492       GNUNET_SCHEDULER_cancel (sched, n->retry_plaintext_task);
1493       n->retry_plaintext_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1494     }
1495   switch (n->status)
1496     {
1497     case PEER_STATE_DOWN:
1498       send_key (n);
1499       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1500                   "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
1501                   GNUNET_i2s(&n->peer));
1502       return;
1503     case PEER_STATE_KEY_SENT:
1504       GNUNET_assert (n->retry_set_key_task !=
1505                      GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
1506       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1507                   "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
1508                   GNUNET_i2s(&n->peer));
1509       return;
1510     case PEER_STATE_KEY_RECEIVED:
1511       GNUNET_assert (n->retry_set_key_task !=
1512                      GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
1513       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1514                   "Not yet connected to `%4s', deferring processing of plaintext messages.\n",
1515                   GNUNET_i2s(&n->peer));
1516       return;
1517     case PEER_STATE_KEY_CONFIRMED:
1518       /* ready to continue */
1519       break;
1520     }
1521   if (n->messages == NULL)
1522     {
1523       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1524                   "Plaintext message queue for `%4s' is empty.\n",
1525                   GNUNET_i2s(&n->peer));
1526       return;                   /* no pending messages */
1527     }
1528   discard_expired_messages (n);
1529   if (n->encrypted_head != NULL)
1530     {
1531       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1532                   "Encrypted message queue for `%4s' is still full, delaying plaintext processing.\n",
1533                   GNUNET_i2s(&n->peer));
1534       return;                   /* wait for messages already encrypted to be
1535                                    processed first! */
1536     }
1537   ph = (struct EncryptedMessage *) pbuf;
1538   deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
1539   priority = 0;
1540   used = sizeof (struct EncryptedMessage);
1541
1542   used += batch_message (n,
1543                          &pbuf[used],
1544                          MAX_ENCRYPTED_MESSAGE_SIZE - used,
1545                          &deadline, &retry_time, &priority);
1546   if (used == sizeof (struct EncryptedMessage))
1547     {
1548       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1549                   "No messages selected for transmission to `%4s' at this time, will try again later.\n",
1550                   GNUNET_i2s(&n->peer));
1551       /* no messages selected for sending, try again later... */
1552       n->retry_plaintext_task =
1553         GNUNET_SCHEDULER_add_delayed (sched,
1554                                       GNUNET_NO,
1555                                       GNUNET_SCHEDULER_PRIORITY_IDLE,
1556                                       GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1557                                       retry_time,
1558                                       &retry_plaintext_processing, n);
1559       return;
1560     }
1561
1562   ph->sequence_number = htonl (++n->last_sequence_number_sent);
1563   ph->inbound_bpm_limit = htonl (n->bpm_in);
1564   ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1565
1566   /* setup encryption message header */
1567   me = GNUNET_malloc (sizeof (struct MessageEntry) + used);
1568   me->deadline = deadline;
1569   me->priority = priority;
1570   me->size = used;
1571   em = (struct EncryptedMessage *) &me[1];
1572   em->header.size = htons (used);
1573   em->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
1574   em->reserved = htonl (0);
1575   esize = used - ENCRYPTED_HEADER_SIZE;
1576   GNUNET_CRYPTO_hash (&ph->sequence_number, esize, &em->plaintext_hash);
1577   /* encrypt */
1578   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1579               "Encrypting %u bytes of plaintext messages for `%4s' for transmission.\n",
1580               esize,
1581               GNUNET_i2s(&n->peer));
1582   GNUNET_assert (GNUNET_OK ==
1583                  do_encrypt (n,
1584                              &em->plaintext_hash,
1585                              &ph->sequence_number,
1586                              &em->sequence_number, esize));
1587   /* append to transmission list */
1588   if (n->encrypted_tail == NULL)
1589     n->encrypted_head = me;
1590   else
1591     n->encrypted_tail->next = me;
1592   n->encrypted_tail = me;
1593   process_encrypted_neighbour_queue (n);
1594 }
1595
1596
1597 /**
1598  * Handle CORE_SEND request.
1599  */
1600 static void
1601 handle_client_send (void *cls,
1602                     struct GNUNET_SERVER_Client *client,
1603                     const struct GNUNET_MessageHeader *message);
1604
1605
1606 /**
1607  * Function called to notify us that we either succeeded
1608  * or failed to connect (at the transport level) to another
1609  * peer.  We should either free the message we were asked
1610  * to transmit or re-try adding it to the queue.
1611  *
1612  * @param cls closure
1613  * @param size number of bytes available in buf
1614  * @param buf where the callee should write the message
1615  * @return number of bytes written to buf
1616  */
1617 static size_t
1618 send_connect_continuation (void *cls, size_t size, void *buf)
1619 {
1620   struct SendMessage *sm = cls;
1621
1622   if (buf == NULL)
1623     {
1624       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1625                   "Asked to send message to disconnected peer `%4s' and connection failed.  Discarding message.\n",
1626                   GNUNET_i2s (&sm->peer));
1627       GNUNET_free (sm);
1628       /* FIXME: do we need to do something here to let the
1629          client know about the failure!? */
1630       return 0;
1631     }
1632   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1633               "Connection to peer `%4s' succeeded, retrying original transmission request\n",
1634               GNUNET_i2s (&sm->peer));
1635   handle_client_send (NULL, NULL, &sm->header);
1636   GNUNET_free (sm);
1637   return 0;
1638 }
1639
1640
1641 /**
1642  * Handle CORE_SEND request.
1643  */
1644 static void
1645 handle_client_send (void *cls,
1646                     struct GNUNET_SERVER_Client *client,
1647                     const struct GNUNET_MessageHeader *message)
1648 {
1649   const struct SendMessage *sm;
1650   struct SendMessage *smc;
1651   const struct GNUNET_MessageHeader *mh;
1652   struct Neighbour *n;
1653   struct MessageEntry *pred;
1654   struct MessageEntry *pos;
1655   struct MessageEntry *e;
1656   uint16_t msize;
1657
1658   msize = ntohs (message->size);
1659   if (msize <
1660       sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader))
1661     {
1662       GNUNET_break (0);
1663       if (client != NULL)
1664         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1665       return;
1666     }
1667   sm = (const struct SendMessage *) message;
1668   msize -= sizeof (struct SendMessage);
1669   mh = (const struct GNUNET_MessageHeader *) &sm[1];
1670   if (msize != ntohs (mh->size))
1671     {
1672       GNUNET_break (0);
1673       if (client != NULL)
1674         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1675       return;
1676     }
1677   n = find_neighbour (&sm->peer);
1678   if (n == NULL)
1679     {
1680       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1681                   "Core received `%s' request for `%4s', will try to establish connection within %llu ms\n",
1682                   "SEND",
1683                   GNUNET_i2s (&sm->peer),
1684                   sm->deadline.value);
1685       msize += sizeof (struct SendMessage);
1686       /* ask transport to connect to the peer */
1687       /* FIXME: this code does not handle the
1688          case where we get multiple SendMessages before
1689          transport responds to this request;
1690          => need to track pending requests! */
1691       smc = GNUNET_malloc (msize);
1692       memcpy (smc, sm, msize);
1693       GNUNET_TRANSPORT_notify_transmit_ready (transport,
1694                                               &sm->peer,
1695                                               0,
1696                                               GNUNET_TIME_absolute_get_remaining
1697                                               (GNUNET_TIME_absolute_ntoh
1698                                                (sm->deadline)),
1699                                               &send_connect_continuation,
1700                                               smc);
1701       if (client != NULL)
1702         GNUNET_SERVER_receive_done (client, GNUNET_OK);
1703       return;
1704     }
1705   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1706               "Core received `%s' request, queueing %u bytes of plaintext data for transmission to `%4s'.\n",
1707               "SEND",
1708               msize, 
1709               GNUNET_i2s (&sm->peer));
1710   /* FIXME: consider bounding queue size */
1711   e = GNUNET_malloc (sizeof (struct MessageEntry) + msize);
1712   e->deadline = GNUNET_TIME_absolute_ntoh (sm->deadline);
1713   e->priority = ntohl (sm->priority);
1714   e->size = msize;
1715   memcpy (&e[1], mh, msize);
1716
1717   /* insert, keep list sorted by deadline */
1718   pred = NULL;
1719   pos = n->messages;
1720   while ((pos != NULL) && (pos->deadline.value < e->deadline.value))
1721     {
1722       pred = pos;
1723       pos = pos->next;
1724     }
1725   if (pred == NULL)
1726     n->messages = e;
1727   else
1728     pred->next = e;
1729   e->next = pos;
1730
1731   /* consider scheduling now */
1732   process_plaintext_neighbour_queue (n);
1733   if (client != NULL)
1734     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1735 }
1736
1737
1738 /**
1739  * List of handlers for the messages understood by this
1740  * service.
1741  */
1742 static struct GNUNET_SERVER_MessageHandler handlers[] = {
1743   {&handle_client_init, NULL,
1744    GNUNET_MESSAGE_TYPE_CORE_INIT, 0},
1745   {&handle_client_request_configure, NULL,
1746    GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONFIGURE,
1747    sizeof (struct RequestConfigureMessage)},
1748   {&handle_client_send, NULL,
1749    GNUNET_MESSAGE_TYPE_CORE_SEND, 0},
1750   {NULL, NULL, 0, 0}
1751 };
1752
1753
1754 /**
1755  * PEERINFO is giving us a HELLO for a peer.  Add the
1756  * public key to the neighbour's struct and retry
1757  * send_key.  Or, if we did not get a HELLO, just do
1758  * nothing.
1759  *
1760  * @param cls NULL
1761  * @param peer the peer for which this is the HELLO
1762  * @param hello HELLO message of that peer
1763  * @param trust amount of trust we currently have in that peer
1764  */
1765 static void
1766 process_hello_retry_send_key (void *cls,
1767                               const struct GNUNET_PeerIdentity *peer,
1768                               const struct GNUNET_HELLO_Message *hello,
1769                               uint32_t trust)
1770 {
1771   struct Neighbour *n;
1772
1773   if (peer == NULL)
1774     return;
1775   n = find_neighbour (peer);
1776   if (n == NULL)
1777     return;
1778   if (n->public_key != NULL)
1779     return;
1780   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1781               "Received new `%s' message for `%4s', initiating key exchange.\n",
1782               "HELLO",
1783               GNUNET_i2s (peer));
1784   n->public_key =
1785     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1786   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
1787     {
1788       GNUNET_free (n->public_key);
1789       n->public_key = NULL;
1790       return;
1791     }
1792   send_key (n);
1793 }
1794
1795
1796 /**
1797  * Task that will retry "send_key" if our previous attempt failed
1798  * to yield a PONG.
1799  */
1800 static void
1801 set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1802 {
1803   struct Neighbour *n = cls;
1804
1805   GNUNET_assert (n->status != PEER_STATE_KEY_CONFIRMED);
1806   n->retry_set_key_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1807   n->set_key_retry_frequency =
1808     GNUNET_TIME_relative_multiply (n->set_key_retry_frequency, 2);
1809   send_key (n);
1810 }
1811
1812
1813 /**
1814  * Send our key (and encrypted PING) to the other peer.
1815  *
1816  * @param n the other peer
1817  */
1818 static void
1819 send_key (struct Neighbour *n)
1820 {
1821   struct SetKeyMessage *sm;
1822   struct MessageEntry *me;
1823   struct PingMessage pp;
1824   struct PingMessage *pm;
1825
1826   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1827               "Asked to perform key exchange with `%4s'.\n",
1828               GNUNET_i2s (&n->peer));
1829   if (n->public_key == NULL)
1830     {
1831       /* lookup n's public key, then try again */
1832       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1833                   "Lacking public key for `%4s', trying to obtain one.\n",
1834                   GNUNET_i2s (&n->peer));
1835       GNUNET_PEERINFO_for_all (cfg,
1836                                sched,
1837                                &n->peer,
1838                                0,
1839                                GNUNET_TIME_UNIT_MINUTES,
1840                                &process_hello_retry_send_key, NULL);
1841       return;
1842     }
1843   /* first, set key message */
1844   me = GNUNET_malloc (sizeof (struct MessageEntry) +
1845                       sizeof (struct SetKeyMessage));
1846   me->deadline = GNUNET_TIME_relative_to_absolute (MAX_SET_KEY_DELAY);
1847   me->priority = SET_KEY_PRIORITY;
1848   me->size = sizeof (struct SetKeyMessage);
1849   if (n->encrypted_head == NULL)
1850     n->encrypted_head = me;
1851   else
1852     n->encrypted_tail->next = me;
1853   n->encrypted_tail = me;
1854   sm = (struct SetKeyMessage *) &me[1];
1855   sm->header.size = htons (sizeof (struct SetKeyMessage));
1856   sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SET_KEY);
1857   sm->sender_status = htonl ((int32_t) ((n->status == PEER_STATE_DOWN) ?
1858                                         PEER_STATE_KEY_SENT : n->status));
1859   sm->purpose.size =
1860     htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
1861            sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1862            sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
1863            sizeof (struct GNUNET_PeerIdentity));
1864   sm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_KEY);
1865   sm->creation_time = GNUNET_TIME_absolute_hton (n->encrypt_key_created);
1866   sm->target = n->peer;
1867   GNUNET_assert (GNUNET_OK ==
1868                  GNUNET_CRYPTO_rsa_encrypt (&n->encrypt_key,
1869                                             sizeof (struct
1870                                                     GNUNET_CRYPTO_AesSessionKey),
1871                                             n->public_key,
1872                                             &sm->encrypted_key));
1873   GNUNET_assert (GNUNET_OK ==
1874                  GNUNET_CRYPTO_rsa_sign (my_private_key, &sm->purpose,
1875                                          &sm->signature));
1876
1877   /* second, encrypted PING message */
1878   me = GNUNET_malloc (sizeof (struct MessageEntry) +
1879                       sizeof (struct PingMessage));
1880   me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PING_DELAY);
1881   me->priority = PING_PRIORITY;
1882   me->size = sizeof (struct PingMessage);
1883   n->encrypted_tail->next = me;
1884   n->encrypted_tail = me;
1885   pm = (struct PingMessage *) &me[1];
1886   pm->header.size = htons (sizeof (struct PingMessage));
1887   pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
1888   pp.challenge = htonl (n->ping_challenge);
1889   pp.target = n->peer;
1890   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1891               "Encrypting `%s' and `%s' messages for `%4s'.\n",
1892               "SET_KEY", "PING", GNUNET_i2s (&n->peer));
1893   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1894               "Sending `%s' to `%4s' with challenge %u encrypted using key %u\n",
1895               "PING",
1896               GNUNET_i2s (&n->peer), n->ping_challenge, n->encrypt_key.crc32);
1897   do_encrypt (n,
1898               &n->peer.hashPubKey,
1899               &pp.challenge,
1900               &pm->challenge,
1901               sizeof (struct PingMessage) -
1902               sizeof (struct GNUNET_MessageHeader));
1903   /* update status */
1904   switch (n->status)
1905     {
1906     case PEER_STATE_DOWN:
1907       n->status = PEER_STATE_KEY_SENT;
1908       break;
1909     case PEER_STATE_KEY_SENT:
1910       break;
1911     case PEER_STATE_KEY_RECEIVED:
1912       break;
1913     case PEER_STATE_KEY_CONFIRMED:
1914       GNUNET_break (0);
1915       break;
1916     default:
1917       GNUNET_break (0);
1918       break;
1919     }
1920   /* trigger queue processing */
1921   process_encrypted_neighbour_queue (n);
1922   if (n->status != PEER_STATE_KEY_CONFIRMED)
1923     n->retry_set_key_task
1924       = GNUNET_SCHEDULER_add_delayed (sched,
1925                                       GNUNET_NO,
1926                                       GNUNET_SCHEDULER_PRIORITY_KEEP,
1927                                       GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1928                                       n->set_key_retry_frequency,
1929                                       &set_key_retry_task, n);
1930 }
1931
1932
1933 /**
1934  * We received a SET_KEY message.  Validate and update
1935  * our key material and status.
1936  *
1937  * @param n the neighbour from which we received message m
1938  * @param m the set key message we received
1939  */
1940 static void
1941 handle_set_key (struct Neighbour *n, const struct SetKeyMessage *m);
1942
1943
1944 /**
1945  * PEERINFO is giving us a HELLO for a peer.  Add the public key to
1946  * the neighbour's struct and retry handling the set_key message.  Or,
1947  * if we did not get a HELLO, just free the set key message.
1948  *
1949  * @param cls pointer to the set key message
1950  * @param peer the peer for which this is the HELLO
1951  * @param hello HELLO message of that peer
1952  * @param trust amount of trust we currently have in that peer
1953  */
1954 static void
1955 process_hello_retry_handle_set_key (void *cls,
1956                                     const struct GNUNET_PeerIdentity *peer,
1957                                     const struct GNUNET_HELLO_Message *hello,
1958                                     uint32_t trust)
1959 {
1960   struct SetKeyMessage *sm = cls;
1961   struct Neighbour *n;
1962
1963   if (peer == NULL)
1964     {
1965       GNUNET_free (sm);
1966       return;
1967     }
1968   n = find_neighbour (peer);
1969   if (n == NULL)
1970     {
1971       GNUNET_break (0);
1972       return;
1973     }
1974   if (n->public_key != NULL)
1975     return;                     /* multiple HELLOs match!? */
1976   n->public_key =
1977     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1978   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
1979     {
1980       GNUNET_break_op (0);
1981       GNUNET_free (n->public_key);
1982       n->public_key = NULL;
1983       return;
1984     }
1985   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1986               "Received `%s' for `%4s', continuing processing of `%s' message.\n",
1987               "HELLO", GNUNET_i2s (peer), "SET_KEY");
1988   handle_set_key (n, sm);
1989 }
1990
1991
1992 /**
1993  * We received a PING message.  Validate and transmit
1994  * PONG.
1995  *
1996  * @param n sender of the PING
1997  * @param m the encrypted PING message itself
1998  */
1999 static void
2000 handle_ping (struct Neighbour *n, const struct PingMessage *m)
2001 {
2002   struct PingMessage t;
2003   struct PingMessage *tp;
2004   struct MessageEntry *me;
2005
2006   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2007               "Core service receives `%s' request from `%4s'.\n",
2008               "PING", GNUNET_i2s (&n->peer));
2009   if (GNUNET_OK !=
2010       do_decrypt (n,
2011                   &my_identity.hashPubKey,
2012                   &m->challenge,
2013                   &t.challenge,
2014                   sizeof (struct PingMessage) -
2015                   sizeof (struct GNUNET_MessageHeader)))
2016     return;
2017   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2018               "Decrypted `%s' to `%4s' with challenge %u decrypted using key %u\n",
2019               "PING",
2020               GNUNET_i2s (&t.target),
2021               ntohl (t.challenge), n->decrypt_key.crc32);
2022   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2023               "Target of `%s' request is `%4s'.\n",
2024               "PING", GNUNET_i2s (&t.target));
2025   if (0 != memcmp (&t.target,
2026                    &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2027     {
2028       GNUNET_break_op (0);
2029       return;
2030     }
2031   me = GNUNET_malloc (sizeof (struct MessageEntry) +
2032                       sizeof (struct PingMessage));
2033   if (n->encrypted_tail != NULL)
2034     n->encrypted_tail->next = me;
2035   else
2036     {
2037       n->encrypted_tail = me;
2038       n->encrypted_head = me;
2039     }
2040   me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PONG_DELAY);
2041   me->priority = PONG_PRIORITY;
2042   me->size = sizeof (struct PingMessage);
2043   tp = (struct PingMessage *) &me[1];
2044   tp->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG);
2045   tp->header.size = htons (sizeof (struct PingMessage));
2046   do_encrypt (n,
2047               &my_identity.hashPubKey,
2048               &t.challenge,
2049               &tp->challenge,
2050               sizeof (struct PingMessage) -
2051               sizeof (struct GNUNET_MessageHeader));
2052   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2053               "Encrypting `%s' with challenge %u using key %u\n", "PONG",
2054               ntohl (t.challenge), n->encrypt_key.crc32);
2055   /* trigger queue processing */
2056   process_encrypted_neighbour_queue (n);
2057 }
2058
2059
2060 /**
2061  * We received a SET_KEY message.  Validate and update
2062  * our key material and status.
2063  *
2064  * @param n the neighbour from which we received message m
2065  * @param m the set key message we received
2066  */
2067 static void
2068 handle_set_key (struct Neighbour *n, const struct SetKeyMessage *m)
2069 {
2070   struct SetKeyMessage *m_cpy;
2071   struct GNUNET_TIME_Absolute t;
2072   struct GNUNET_CRYPTO_AesSessionKey k;
2073   struct PingMessage *ping;
2074   enum PeerStateMachine sender_status;
2075
2076   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2077               "Core service receives `%s' request from `%4s'.\n",
2078               "SET_KEY", GNUNET_i2s (&n->peer));
2079   if (n->public_key == NULL)
2080     {
2081       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2082                   "Lacking public key for peer, trying to obtain one.\n");
2083       m_cpy = GNUNET_malloc (sizeof (struct SetKeyMessage));
2084       memcpy (m_cpy, m, sizeof (struct SetKeyMessage));
2085       /* lookup n's public key, then try again */
2086       GNUNET_PEERINFO_for_all (cfg,
2087                                sched,
2088                                &n->peer,
2089                                0,
2090                                GNUNET_TIME_UNIT_MINUTES,
2091                                &process_hello_retry_handle_set_key, m_cpy);
2092       return;
2093     }
2094   if ((ntohl (m->purpose.size) !=
2095        sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
2096        sizeof (struct GNUNET_TIME_AbsoluteNBO) +
2097        sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
2098        sizeof (struct GNUNET_PeerIdentity)) ||
2099       (GNUNET_OK !=
2100        GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_KEY,
2101                                  &m->purpose, &m->signature, n->public_key)))
2102     {
2103       /* invalid signature */
2104       GNUNET_break_op (0);
2105       return;
2106     }
2107   t = GNUNET_TIME_absolute_ntoh (m->creation_time);
2108   if (((n->status == PEER_STATE_KEY_RECEIVED) ||
2109        (n->status == PEER_STATE_KEY_CONFIRMED)) &&
2110       (t.value < n->decrypt_key_created.value))
2111     {
2112       /* this could rarely happen due to massive re-ordering of
2113          messages on the network level, but is most likely either
2114          a bug or some adversary messing with us.  Report. */
2115       GNUNET_break_op (0);
2116       return;
2117     }
2118   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decrypting key material.\n");
2119   if ((GNUNET_CRYPTO_rsa_decrypt (my_private_key,
2120                                   &m->encrypted_key,
2121                                   &k,
2122                                   sizeof (struct GNUNET_CRYPTO_AesSessionKey))
2123        != sizeof (struct GNUNET_CRYPTO_AesSessionKey)) ||
2124       (GNUNET_OK != GNUNET_CRYPTO_aes_check_session_key (&k)))
2125     {
2126       /* failed to decrypt !? */
2127       GNUNET_break_op (0);
2128       return;
2129     }
2130
2131   n->decrypt_key = k;
2132   if (n->decrypt_key_created.value != t.value)
2133     {
2134       /* fresh key, reset sequence numbers */
2135       n->last_sequence_number_received = 0;
2136       n->last_packets_bitmap = 0;
2137       n->decrypt_key_created = t;
2138     }
2139   sender_status = (enum PeerStateMachine) ntohl (m->sender_status);
2140   switch (n->status)
2141     {
2142     case PEER_STATE_DOWN:
2143       n->status = PEER_STATE_KEY_RECEIVED;
2144       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2145                   "Responding to `%s' with my own key.\n", "SET_KEY");
2146       send_key (n);
2147       break;
2148     case PEER_STATE_KEY_SENT:
2149     case PEER_STATE_KEY_RECEIVED:
2150       n->status = PEER_STATE_KEY_RECEIVED;
2151       if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
2152           (sender_status != PEER_STATE_KEY_CONFIRMED))
2153         {
2154           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2155                       "Responding to `%s' with my own key (other peer has status %u).\n",
2156                       "SET_KEY", sender_status);
2157           send_key (n);
2158         }
2159       break;
2160     case PEER_STATE_KEY_CONFIRMED:
2161       if ((sender_status != PEER_STATE_KEY_RECEIVED) &&
2162           (sender_status != PEER_STATE_KEY_CONFIRMED))
2163         {
2164           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2165                       "Responding to `%s' with my own key (other peer has status %u), I was already fully up.\n",
2166                       "SET_KEY", sender_status);
2167           send_key (n);
2168         }
2169       break;
2170     default:
2171       GNUNET_break (0);
2172       break;
2173     }
2174   if (n->pending_ping != NULL)
2175     {
2176       ping = n->pending_ping;
2177       n->pending_ping = NULL;
2178       handle_ping (n, ping);
2179       GNUNET_free (ping);
2180     }
2181 }
2182
2183
2184 /**
2185  * We received a PONG message.  Validate and update
2186  * our status.
2187  *
2188  * @param n sender of the PONG
2189  * @param m the encrypted PONG message itself
2190  */
2191 static void
2192 handle_pong (struct Neighbour *n, const struct PingMessage *m)
2193 {
2194   struct PingMessage t;
2195
2196   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2197               "Core service receives `%s' request from `%4s'.\n",
2198               "PONG", GNUNET_i2s (&n->peer));
2199   if (GNUNET_OK !=
2200       do_decrypt (n,
2201                   &n->peer.hashPubKey,
2202                   &m->challenge,
2203                   &t.challenge,
2204                   sizeof (struct PingMessage) -
2205                   sizeof (struct GNUNET_MessageHeader)))
2206     return;
2207   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2208               "Decrypted `%s' from `%4s' with challenge %u using key %u\n",
2209               "PONG",
2210               GNUNET_i2s (&t.target),
2211               ntohl (t.challenge), n->decrypt_key.crc32);
2212   if ((0 != memcmp (&t.target,
2213                     &n->peer,
2214                     sizeof (struct GNUNET_PeerIdentity))) ||
2215       (n->ping_challenge != ntohl (t.challenge)))
2216     {
2217       /* PONG malformed */
2218       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2219                   "Received malfromed `%s' wanted sender `%4s' with challenge %u\n",
2220                   "PONG", GNUNET_i2s (&n->peer), n->ping_challenge);
2221       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2222                   "Received malfromed `%s' received from `%4s' with challenge %u\n",
2223                   "PONG", GNUNET_i2s (&t.target), ntohl (t.challenge));
2224       GNUNET_break_op (0);
2225       return;
2226     }
2227   switch (n->status)
2228     {
2229     case PEER_STATE_DOWN:
2230       GNUNET_break (0);         /* should be impossible */
2231       return;
2232     case PEER_STATE_KEY_SENT:
2233       GNUNET_break (0);         /* should be impossible, how did we decrypt? */
2234       return;
2235     case PEER_STATE_KEY_RECEIVED:
2236       n->status = PEER_STATE_KEY_CONFIRMED;
2237       if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
2238         {
2239           GNUNET_SCHEDULER_cancel (sched, n->retry_set_key_task);
2240           n->retry_set_key_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
2241         }
2242       process_encrypted_neighbour_queue (n);
2243       break;
2244     case PEER_STATE_KEY_CONFIRMED:
2245       /* duplicate PONG? */
2246       break;
2247     default:
2248       GNUNET_break (0);
2249       break;
2250     }
2251 }
2252
2253
2254 /**
2255  * Send a P2P message to a client.
2256  *
2257  * @param sender who sent us the message?
2258  * @param client who should we give the message to?
2259  * @param m contains the message to transmit
2260  * @param msize number of bytes in buf to transmit
2261  */
2262 static void
2263 send_p2p_message_to_client (struct Neighbour *sender,
2264                             struct Client *client,
2265                             const void *m, size_t msize)
2266 {
2267   char buf[msize + sizeof (struct NotifyTrafficMessage)];
2268   struct NotifyTrafficMessage *ntm;
2269
2270   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2271               "Core service passes message from `%4s' of type %u to client.\n",
2272               GNUNET_i2s(&sender->peer),
2273               ntohs (((const struct GNUNET_MessageHeader *) m)->type));
2274   ntm = (struct NotifyTrafficMessage *) buf;
2275   ntm->header.size = htons (msize + sizeof (struct NotifyTrafficMessage));
2276   ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
2277   ntm->reserved = htonl (0);
2278   ntm->peer = sender->peer;
2279   memcpy (&ntm[1], m, msize);
2280   send_to_client (client, &ntm->header, GNUNET_YES);
2281 }
2282
2283
2284 /**
2285  * Deliver P2P message to interested clients.
2286  *
2287  * @param sender who sent us the message?
2288  * @param m the message
2289  * @param msize size of the message (including header)
2290  */
2291 static void
2292 deliver_message (struct Neighbour *sender,
2293                  const struct GNUNET_MessageHeader *m, size_t msize)
2294 {
2295   struct Client *cpos;
2296   uint16_t type;
2297   unsigned int tpos;
2298   int deliver_full;
2299
2300   type = ntohs (m->type);
2301   cpos = clients;
2302   while (cpos != NULL)
2303     {
2304       deliver_full = GNUNET_NO;
2305       if (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)
2306         deliver_full = GNUNET_YES;
2307       else
2308         {
2309           for (tpos = 0; tpos < cpos->tcnt; tpos++)
2310             {
2311               if (type != cpos->types[tpos])
2312                 continue;
2313               deliver_full = GNUNET_YES;
2314               break;
2315             }
2316         }
2317       if (GNUNET_YES == deliver_full)
2318         send_p2p_message_to_client (sender, cpos, m, msize);
2319       else if (cpos->options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)
2320         send_p2p_message_to_client (sender, cpos, m,
2321                                     sizeof (struct GNUNET_MessageHeader));
2322       cpos = cpos->next;
2323     }
2324 }
2325
2326
2327 /**
2328  * Align P2P message and then deliver to interested clients.
2329  *
2330  * @param sender who sent us the message?
2331  * @param buffer unaligned (!) buffer containing message
2332  * @param msize size of the message (including header)
2333  */
2334 static void
2335 align_and_deliver (struct Neighbour *sender, const char *buffer, size_t msize)
2336 {
2337   char abuf[msize];
2338
2339   /* TODO: call to statistics? */
2340   memcpy (abuf, buffer, msize);
2341   deliver_message (sender, (const struct GNUNET_MessageHeader *) abuf, msize);
2342 }
2343
2344
2345 /**
2346  * Deliver P2P messages to interested clients.
2347  *
2348  * @param sender who sent us the message?
2349  * @param buffer buffer containing messages, can be modified
2350  * @param buffer_size size of the buffer (overall)
2351  * @param offset offset where messages in the buffer start
2352  */
2353 static void
2354 deliver_messages (struct Neighbour *sender,
2355                   const char *buffer, size_t buffer_size, size_t offset)
2356 {
2357   struct GNUNET_MessageHeader *mhp;
2358   struct GNUNET_MessageHeader mh;
2359   uint16_t msize;
2360   int need_align;
2361
2362   while (offset + sizeof (struct GNUNET_MessageHeader) <= buffer_size)
2363     {
2364       if (0 != offset % sizeof (uint16_t))
2365         {
2366           /* outch, need to copy to access header */
2367           memcpy (&mh, &buffer[offset], sizeof (struct GNUNET_MessageHeader));
2368           mhp = &mh;
2369         }
2370       else
2371         {
2372           /* can access header directly */
2373           mhp = (struct GNUNET_MessageHeader *) &buffer[offset];
2374         }
2375       msize = ntohs (mhp->size);
2376       if (msize + offset > buffer_size)
2377         {
2378           /* malformed message, header says it is larger than what
2379              would fit into the overall buffer */
2380           GNUNET_break_op (0);
2381           break;
2382         }
2383 #if HAVE_UNALIGNED_64_ACCESS
2384       need_align = (0 != offset % 4) ? GNUNET_YES : GNUNET_NO;
2385 #else
2386       need_align = (0 != offset % 8) ? GNUNET_YES : GNUNET_NO;
2387 #endif
2388       if (GNUNET_YES == need_align)
2389         align_and_deliver (sender, &buffer[offset], msize);
2390       else
2391         deliver_message (sender,
2392                          (const struct GNUNET_MessageHeader *)
2393                          &buffer[offset], msize);
2394       offset += msize;
2395     }
2396 }
2397
2398
2399 /**
2400  * We received an encrypted message.  Decrypt, validate and
2401  * pass on to the appropriate clients.
2402  */
2403 static void
2404 handle_encrypted_message (struct Neighbour *n,
2405                           const struct EncryptedMessage *m)
2406 {
2407   size_t size = ntohs (m->header.size);
2408   char buf[size];
2409   struct EncryptedMessage *pt;  /* plaintext */
2410   GNUNET_HashCode ph;
2411   size_t off;
2412   uint32_t snum;
2413   struct GNUNET_TIME_Absolute t;
2414
2415   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2416               "Core service receives `%s' request from `%4s'.\n",
2417               "ENCRYPTED_MESSAGE", GNUNET_i2s (&n->peer));
2418   /* decrypt */
2419   if (GNUNET_OK !=
2420       do_decrypt (n,
2421                   &m->plaintext_hash,
2422                   &m->sequence_number,
2423                   &buf[ENCRYPTED_HEADER_SIZE], size - ENCRYPTED_HEADER_SIZE))
2424     return;
2425   pt = (struct EncryptedMessage *) buf;
2426
2427   /* validate hash */
2428   GNUNET_CRYPTO_hash (&pt->sequence_number,
2429                       size - ENCRYPTED_HEADER_SIZE, &ph);
2430   if (0 != memcmp (&ph, &m->plaintext_hash, sizeof (GNUNET_HashCode)))
2431     {
2432       /* checksum failed */
2433       GNUNET_break_op (0);
2434       return;
2435     }
2436
2437   /* validate sequence number */
2438   snum = ntohl (pt->sequence_number);
2439   if (n->last_sequence_number_received == snum)
2440     {
2441       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2442                   "Received duplicate message, ignoring.\n");
2443       /* duplicate, ignore */
2444       return;
2445     }
2446   if ((n->last_sequence_number_received > snum) &&
2447       (n->last_sequence_number_received - snum > 32))
2448     {
2449       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2450                   "Received ancient out of sequence message, ignoring.\n");
2451       /* ancient out of sequence, ignore */
2452       return;
2453     }
2454   if (n->last_sequence_number_received > snum)
2455     {
2456       unsigned int rotbit =
2457         1 << (n->last_sequence_number_received - snum - 1);
2458       if ((n->last_packets_bitmap & rotbit) != 0)
2459         {
2460           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2461                       "Received duplicate message, ignoring.\n");
2462           /* duplicate, ignore */
2463           return;
2464         }
2465       n->last_packets_bitmap |= rotbit;
2466     }
2467   if (n->last_sequence_number_received < snum)
2468     {
2469       n->last_packets_bitmap <<= (snum - n->last_sequence_number_received);
2470       n->last_sequence_number_received = snum;
2471     }
2472
2473   /* check timestamp */
2474   t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
2475   if (GNUNET_TIME_absolute_get_duration (t).value > MAX_MESSAGE_AGE.value)
2476     {
2477       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2478                   _
2479                   ("Message received far too old (%llu ms). Content ignored.\n"),
2480                   GNUNET_TIME_absolute_get_duration (t).value);
2481       return;
2482     }
2483
2484   /* process decrypted message(s) */
2485   n->bpm_out_external_limit = ntohl (pt->inbound_bpm_limit);
2486   n->bpm_out = GNUNET_MAX (n->bpm_out_external_limit,
2487                            n->bpm_out_internal_limit);
2488   n->last_activity = GNUNET_TIME_absolute_get ();
2489   off = sizeof (struct EncryptedMessage);
2490   deliver_messages (n, buf, size, off);
2491 }
2492
2493
2494 /**
2495  * Function called by the transport for each received message.
2496  *
2497  * @param cls closure
2498  * @param latency estimated latency for communicating with the
2499  *             given peer
2500  * @param peer (claimed) identity of the other peer
2501  * @param message the message
2502  */
2503 static void
2504 handle_transport_receive (void *cls,
2505                           struct GNUNET_TIME_Relative latency,
2506                           const struct GNUNET_PeerIdentity *peer,
2507                           const struct GNUNET_MessageHeader *message)
2508 {
2509   struct Neighbour *n;
2510   struct GNUNET_TIME_Absolute now;
2511   int up;
2512   uint16_t type;
2513   uint16_t size;
2514
2515   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2516               "Received message of type %u from `%4s', demultiplexing.\n",
2517               ntohs (message->type), GNUNET_i2s (peer));
2518   n = find_neighbour (peer);
2519   if (n == NULL)
2520     {
2521       GNUNET_break (0);
2522       return;
2523     }
2524   n->last_latency = latency;
2525   up = n->status == PEER_STATE_KEY_CONFIRMED;
2526   type = ntohs (message->type);
2527   size = ntohs (message->size);
2528   switch (type)
2529     {
2530     case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
2531       if (size != sizeof (struct SetKeyMessage))
2532         {
2533           GNUNET_break_op (0);
2534           return;
2535         }
2536       handle_set_key (n, (const struct SetKeyMessage *) message);
2537       break;
2538     case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
2539       if (size < sizeof (struct EncryptedMessage) +
2540           sizeof (struct GNUNET_MessageHeader))
2541         {
2542           GNUNET_break_op (0);
2543           return;
2544         }
2545       if ((n->status != PEER_STATE_KEY_RECEIVED) &&
2546           (n->status != PEER_STATE_KEY_CONFIRMED))
2547         {
2548           GNUNET_break_op (0);
2549           return;
2550         }
2551       handle_encrypted_message (n, (const struct EncryptedMessage *) message);
2552       break;
2553     case GNUNET_MESSAGE_TYPE_CORE_PING:
2554       if (size != sizeof (struct PingMessage))
2555         {
2556           GNUNET_break_op (0);
2557           return;
2558         }
2559       if ((n->status != PEER_STATE_KEY_RECEIVED) &&
2560           (n->status != PEER_STATE_KEY_CONFIRMED))
2561         {
2562           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2563                       "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
2564                       "PING", GNUNET_i2s (&n->peer));
2565           GNUNET_free_non_null (n->pending_ping);
2566           n->pending_ping = GNUNET_malloc (sizeof (struct PingMessage));
2567           memcpy (n->pending_ping, message, sizeof (struct PingMessage));
2568           return;
2569         }
2570       handle_ping (n, (const struct PingMessage *) message);
2571       break;
2572     case GNUNET_MESSAGE_TYPE_CORE_PONG:
2573       if (size != sizeof (struct PingMessage))
2574         {
2575           GNUNET_break_op (0);
2576           return;
2577         }
2578       if ((n->status != PEER_STATE_KEY_SENT) &&
2579           (n->status != PEER_STATE_KEY_RECEIVED) &&
2580           (n->status != PEER_STATE_KEY_CONFIRMED))
2581         {
2582           /* could not decrypt pong, oops! */
2583           GNUNET_break_op (0);
2584           return;
2585         }
2586       handle_pong (n, (const struct PingMessage *) message);
2587       break;
2588     default:
2589       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2590                   _("Unsupported message of type %u received.\n"), type);
2591       return;
2592     }
2593   if (n->status == PEER_STATE_KEY_CONFIRMED)
2594     {
2595       now = GNUNET_TIME_absolute_get ();
2596       n->last_activity = now;
2597       if (!up)
2598         n->time_established = now;
2599     }
2600 }
2601
2602
2603 /**
2604  * Function called by transport to notify us that
2605  * a peer connected to us (on the network level).
2606  *
2607  * @param cls closure
2608  * @param peer the peer that connected
2609  * @param latency current latency of the connection
2610  */
2611 static void
2612 handle_transport_notify_connect (void *cls,
2613                                  const struct GNUNET_PeerIdentity *peer,
2614                                  struct GNUNET_TIME_Relative latency)
2615 {
2616   struct Neighbour *n;
2617   struct GNUNET_TIME_Absolute now;
2618   struct ConnectNotifyMessage cnm;
2619
2620   n = find_neighbour (peer);
2621   if (n != NULL)
2622     {
2623       /* duplicate connect notification!? */
2624       GNUNET_break (0);
2625       return;
2626     }
2627   now = GNUNET_TIME_absolute_get ();
2628   n = GNUNET_malloc (sizeof (struct Neighbour));
2629   n->next = neighbours;
2630   neighbours = n;
2631   n->peer = *peer;
2632   n->last_latency = latency;
2633   GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key);
2634   n->encrypt_key_created = now;
2635   n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
2636   n->last_asw_update = now;
2637   n->last_arw_update = now;
2638   n->bpm_in = DEFAULT_BPM_IN_OUT;
2639   n->bpm_out = DEFAULT_BPM_IN_OUT;
2640   n->bpm_out_internal_limit = (uint32_t) - 1;
2641   n->bpm_out_external_limit = DEFAULT_BPM_IN_OUT;
2642   n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2643                                                 (uint32_t) - 1);
2644   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2645               "Received connection from `%4s'.\n",
2646               GNUNET_i2s (&n->peer));
2647   cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
2648   cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
2649   cnm.bpm_available = htonl (DEFAULT_BPM_IN_OUT);
2650   cnm.peer = *peer;
2651   cnm.last_activity = GNUNET_TIME_absolute_hton (now);
2652   send_to_all_clients (&cnm.header, GNUNET_YES);
2653 }
2654
2655
2656 /**
2657  * Free the given entry for the neighbour (it has
2658  * already been removed from the list at this point).
2659  * @param n neighbour to free
2660  */
2661 static void
2662 free_neighbour (struct Neighbour *n)
2663 {
2664   struct MessageEntry *m;
2665
2666   while (NULL != (m = n->messages))
2667     {
2668       n->messages = m->next;
2669       GNUNET_free (m);
2670     }
2671   while (NULL != (m = n->encrypted_head))
2672     {
2673       n->encrypted_head = m->next;
2674       GNUNET_free (m);
2675     }
2676   if (NULL != n->th)
2677     GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
2678   if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
2679     GNUNET_SCHEDULER_cancel (sched, n->retry_plaintext_task);
2680   if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
2681     GNUNET_SCHEDULER_cancel (sched, n->retry_set_key_task);
2682   GNUNET_free_non_null (n->public_key);
2683   GNUNET_free_non_null (n->pending_ping);
2684   GNUNET_free (n);
2685 }
2686
2687
2688 /**
2689  * Function called by transport telling us that a peer
2690  * disconnected.
2691  *
2692  * @param cls closure
2693  * @param peer the peer that disconnected
2694  */
2695 static void
2696 handle_transport_notify_disconnect (void *cls,
2697                                     const struct GNUNET_PeerIdentity *peer)
2698 {
2699   struct ConnectNotifyMessage cnm;
2700   struct Neighbour *n;
2701   struct Neighbour *p;
2702
2703   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2704               "Peer `%4s' disconnected from us.\n", GNUNET_i2s (peer));
2705   p = NULL;
2706   n = neighbours;
2707   while ((n != NULL) &&
2708          (0 != memcmp (&n->peer, peer, sizeof (struct GNUNET_PeerIdentity))))
2709     {
2710       p = n;
2711       n = n->next;
2712     }
2713   if (n == NULL)
2714     {
2715       GNUNET_break (0);
2716       return;
2717     }
2718   if (p == NULL)
2719     neighbours = n->next;
2720   else
2721     p->next = n->next;
2722   cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
2723   cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
2724   cnm.bpm_available = htonl (0);
2725   cnm.peer = *peer;
2726   cnm.last_activity = GNUNET_TIME_absolute_hton (n->last_activity);
2727   send_to_all_clients (&cnm.header, GNUNET_YES);
2728   free_neighbour (n);
2729 }
2730
2731
2732 /**
2733  * Last task run during shutdown.  Disconnects us from
2734  * the transport.
2735  */
2736 static void
2737 cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2738 {
2739   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2740               "Core service shutting down.\n");
2741   GNUNET_assert (transport != NULL);
2742   GNUNET_TRANSPORT_disconnect (transport);
2743   transport = NULL;
2744 }
2745
2746
2747 /**
2748  * Initiate core service.
2749  *
2750  * @param cls closure
2751  * @param s scheduler to use
2752  * @param serv the initialized server
2753  * @param c configuration to use
2754  */
2755 static void
2756 run (void *cls,
2757      struct GNUNET_SCHEDULER_Handle *s,
2758      struct GNUNET_SERVER_Handle *serv, struct GNUNET_CONFIGURATION_Handle *c)
2759 {
2760 #if 0
2761   unsigned long long qin;
2762   unsigned long long qout;
2763   unsigned long long tneigh;
2764 #endif
2765   char *keyfile;
2766
2767   sched = s;
2768   cfg = c;
2769   /* parse configuration */
2770   if (
2771 #if 0
2772        (GNUNET_OK !=
2773         GNUNET_CONFIGURATION_get_value_number (c,
2774                                                "CORE",
2775                                                "XX",
2776                                                &qin)) ||
2777        (GNUNET_OK !=
2778         GNUNET_CONFIGURATION_get_value_number (c,
2779                                                "CORE",
2780                                                "YY",
2781                                                &qout)) ||
2782        (GNUNET_OK !=
2783         GNUNET_CONFIGURATION_get_value_number (c,
2784                                                "CORE",
2785                                                "ZZ_LIMIT", &tneigh)) ||
2786 #endif
2787        (GNUNET_OK !=
2788         GNUNET_CONFIGURATION_get_value_filename (c,
2789                                                  "GNUNETD",
2790                                                  "HOSTKEY", &keyfile)))
2791     {
2792       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2793                   _
2794                   ("Core service is lacking key configuration settings.  Exiting.\n"));
2795       GNUNET_SCHEDULER_shutdown (s);
2796       return;
2797     }
2798   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
2799   GNUNET_free (keyfile);
2800   if (my_private_key == NULL)
2801     {
2802       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2803                   _("Core service could not access hostkey.  Exiting.\n"));
2804       GNUNET_SCHEDULER_shutdown (s);
2805       return;
2806     }
2807   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
2808   GNUNET_CRYPTO_hash (&my_public_key,
2809                       sizeof (my_public_key), &my_identity.hashPubKey);
2810   /* setup notification */
2811   server = serv;
2812   GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
2813   /* setup transport connection */
2814   transport = GNUNET_TRANSPORT_connect (sched,
2815                                         cfg,
2816                                         NULL,
2817                                         &handle_transport_receive,
2818                                         &handle_transport_notify_connect,
2819                                         &handle_transport_notify_disconnect);
2820   GNUNET_assert (NULL != transport);
2821   GNUNET_SCHEDULER_add_delayed (sched,
2822                                 GNUNET_YES,
2823                                 GNUNET_SCHEDULER_PRIORITY_IDLE,
2824                                 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
2825                                 GNUNET_TIME_UNIT_FOREVER_REL,
2826                                 &cleaning_task, NULL);
2827   /* process client requests */
2828   GNUNET_SERVER_add_handlers (server, handlers);
2829   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2830               _("Core service of `%4s' ready.\n"), GNUNET_i2s (&my_identity));
2831 }
2832
2833
2834 /**
2835  * Function called during shutdown.  Clean up our state.
2836  */
2837 static void
2838 cleanup (void *cls, struct GNUNET_CONFIGURATION_Handle *cfg)
2839 {
2840   struct Neighbour *n;
2841
2842   if (my_private_key != NULL)
2843     GNUNET_CRYPTO_rsa_key_free (my_private_key);
2844   while (NULL != (n = neighbours))
2845     {
2846       neighbours = n->next;
2847       free_neighbour (n);
2848     }
2849   /*
2850      FIXME:
2851      - free clients
2852    */
2853 }
2854
2855
2856 /**
2857  * The main function for the transport service.
2858  *
2859  * @param argc number of arguments from the command line
2860  * @param argv command line arguments
2861  * @return 0 ok, 1 on error
2862  */
2863 int
2864 main (int argc, char *const *argv)
2865 {
2866   return (GNUNET_OK ==
2867           GNUNET_SERVICE_run (argc,
2868                               argv,
2869                               "core", &run, NULL, &cleanup, NULL)) ? 0 : 1;
2870 }
2871
2872 /* end of gnunet-service-core.c */