2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018, 2019 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file transport/gnunet-communicator-tcp.c
23 * @brief Transport plugin using TCP.
24 * @author Christian Grothoff
27 * - lots of basic adaptations (see FIXMEs)
28 * - better message queue management
29 * - actually encrypt, hmac, decrypt
34 #include "gnunet_util_lib.h"
35 #include "gnunet_protocols.h"
36 #include "gnunet_signatures.h"
37 #include "gnunet_constants.h"
38 #include "gnunet_nt_lib.h"
39 #include "gnunet_statistics_service.h"
40 #include "gnunet_transport_communication_service.h"
43 * How many messages do we keep at most in the queue to the
44 * transport service before we start to drop (default,
45 * can be changed via the configuration file).
46 * Should be _below_ the level of the communicator API, as
47 * otherwise we may read messages just to have them dropped
48 * by the communicator API.
50 #define DEFAULT_MAX_QUEUE_LENGTH 8
53 * Size of our IO buffers for ciphertext data. Must be at
54 * least UINT_MAX + sizeof (struct TCPBox).
56 #define BUF_SIZE (2 * 64 * 1024 + sizeof (struct TCPBox))
59 * How often do we rekey based on time (at least)
61 #define REKEY_TIME_INTERVAL GNUNET_TIME_UNIT_DAYS
64 * How often do we rekey based on number of bytes transmitted?
65 * (additionally randomized).
67 #define REKEY_MAX_BYTES (1024LLU * 1024 * 1024 * 4LLU)
70 * Address prefix used by the communicator.
72 #define COMMUNICATOR_ADDRESS_PREFIX "tcp"
75 * Configuration section used by the communicator.
77 #define COMMUNICATOR_CONFIG_SECTION "communicator-tcp"
79 GNUNET_NETWORK_STRUCT_BEGIN
83 * Signature we use to verify that the ephemeral key was really chosen by
84 * the specified sender.
86 struct TcpHandshakeSignature
89 * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE
91 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
94 * Identity of the inititor of the TCP connection (TCP client).
96 struct GNUNET_PeerIdentity sender;
99 * Presumed identity of the target of the TCP connection (TCP server)
101 struct GNUNET_PeerIdentity receiver;
104 * Ephemeral key used by the @e sender.
106 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
109 * Monotonic time of @e sender, to possibly help detect replay attacks
110 * (if receiver persists times by sender).
112 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
117 * Encrypted continuation of TCP initial handshake.
119 struct TCPConfirmation
124 struct GNUNET_PeerIdentity sender;
127 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE
129 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
132 * Monotonic time of @e sender, to possibly help detect replay attacks
133 * (if receiver persists times by sender).
135 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
141 * TCP message box. Always sent encrypted!
147 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX. Warning: the
148 * header size EXCLUDES the size of the `struct TCPBox`. We usually
149 * never do this, but here the payload may truly be 64k *after* the
150 * TCPBox (as we have no MTU)!!
152 struct GNUNET_MessageHeader header;
155 * HMAC for the following encrypted message. Yes, we MUST use
156 * mac-then-encrypt here, as we want to hide the message sizes on
157 * the wire (zero plaintext design!). Using CTR mode padding oracle
158 * attacks do not apply. Besides, due to the use of ephemeral keys
159 * (hopefully with effective replay protection from monotonic time!)
160 * the attacker is limited in using the oracle.
162 struct GNUNET_ShortHashCode hmac;
164 /* followed by as may bytes of payload as indicated in @e header,
165 excluding the TCPBox itself! */
171 * TCP rekey message box. Always sent encrypted! Data after
172 * this message will use the new key.
178 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY.
180 struct GNUNET_MessageHeader header;
183 * HMAC for the following encrypted message. Yes, we MUST use
184 * mac-then-encrypt here, as we want to hide the message sizes on
185 * the wire (zero plaintext design!). Using CTR mode padding oracle
186 * attacks do not apply. Besides, due to the use of ephemeral keys
187 * (hopefully with effective replay protection from monotonic time!)
188 * the attacker is limited in using the oracle.
190 struct GNUNET_ShortHashCode hmac;
195 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
198 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY
200 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
203 * Monotonic time of @e sender, to possibly help detect replay attacks
204 * (if receiver persists times by sender).
206 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
212 * TCP finish. Sender asks for the connection to be closed.
213 * Needed/useful in case we drop RST/FIN packets on the GNUnet
214 * port due to the possibility of malicious RST/FIN injection.
220 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH.
222 struct GNUNET_MessageHeader header;
225 * HMAC for the following encrypted message. Yes, we MUST use
226 * mac-then-encrypt here, as we want to hide the message sizes on
227 * the wire (zero plaintext design!). Using CTR mode padding oracle
228 * attacks do not apply. Besides, due to the use of ephemeral keys
229 * (hopefully with effective replay protection from monotonic time!)
230 * the attacker is limited in using the oracle.
232 struct GNUNET_ShortHashCode hmac;
237 GNUNET_NETWORK_STRUCT_END
241 * Handle for a queue.
247 * To whom are we talking to.
249 struct GNUNET_PeerIdentity target;
252 * socket that we transmit all data with on this queue
254 struct GNUNET_NETWORK_Handle *sock;
257 * cipher for decryption of incoming data.
259 gcry_cipher_hd_t in_cipher;
262 * cipher for encryption of outgoing data.
264 gcry_cipher_hd_t out_cipher;
267 * Shared secret for HMAC verification on incoming data.
269 struct GNUNET_HashCode in_hmac;
272 * Shared secret for HMAC generation on outgoing data, ratcheted after
275 struct GNUNET_HashCode out_hmac;
278 * Our ephemeral key. Stored here temporarily during rekeying / key generation.
280 struct GNUNET_CRYPTO_EcdhePrivateKey ephemeral;
283 * ID of read task for this connection.
285 struct GNUNET_SCHEDULER_Task *read_task;
288 * ID of write task for this connection.
290 struct GNUNET_SCHEDULER_Task *write_task;
293 * Address of the other peer.
295 struct sockaddr *address;
298 * How many more bytes may we sent with the current @e out_cipher
299 * before we should rekey?
301 uint64_t rekey_left_bytes;
304 * Until what time may we sent with the current @e out_cipher
305 * before we should rekey?
307 struct GNUNET_TIME_Absolute rekey_time;
310 * Length of the address.
312 socklen_t address_len;
315 * Message queue we are providing for the #ch.
317 struct GNUNET_MQ_Handle *mq;
320 * handle for this queue with the #ch.
322 struct GNUNET_TRANSPORT_QueueHandle *qh;
325 * Number of bytes we currently have in our write queue.
327 unsigned long long bytes_in_queue;
330 * Buffer for reading ciphertext from network into.
332 char cread_buf[BUF_SIZE];
335 * buffer for writing ciphertext to network.
337 char cwrite_buf[BUF_SIZE];
340 * Plaintext buffer for decrypted plaintext.
342 char pread_buf[UINT16_MAX + 1 + sizeof (struct TCPBox)];
345 * Plaintext buffer for messages to be encrypted.
347 char pwrite_buf[UINT16_MAX + 1 + sizeof (struct TCPBox)];
350 * At which offset in the ciphertext read buffer should we
351 * append more ciphertext for transmission next?
356 * At which offset in the ciphertext write buffer should we
357 * append more ciphertext from reading next?
362 * At which offset in the plaintext input buffer should we
363 * append more plaintext from decryption next?
368 * At which offset in the plaintext output buffer should we
369 * append more plaintext for encryption next?
374 * Timeout for this queue.
376 struct GNUNET_TIME_Absolute timeout;
379 * Which network type does this queue use?
381 enum GNUNET_NetworkType nt;
384 * Is MQ awaiting a #GNUNET_MQ_impl_send_continue() call?
386 int mq_awaits_continue;
389 * Did we enqueue a finish message and are closing down the queue?
394 * #GNUNET_YES after #inject_key() placed the rekey message into the
395 * plaintext buffer. Once the plaintext buffer is drained, this
396 * means we must switch to the new key material.
405 static struct GNUNET_SCHEDULER_Task *listen_task;
408 * Number of messages we currently have in our queues towards the transport service.
410 static unsigned long long delivering_messages;
413 * Maximum queue length before we stop reading towards the transport service.
415 static unsigned long long max_queue_length;
418 * For logging statistics.
420 static struct GNUNET_STATISTICS_Handle *stats;
425 static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
428 * Queues (map from peer identity to `struct Queue`)
430 static struct GNUNET_CONTAINER_MultiPeerMap *queue_map;
435 static struct GNUNET_NETWORK_Handle *listen_sock;
438 * Handle to the operation that publishes our address.
440 static struct GNUNET_TRANSPORT_AddressIdentifier *ai;
445 static struct GNUNET_PeerIdentity my_identity;
450 static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
455 static const struct GNUNET_CONFIGURATION_Handle *cfg;
459 * We have been notified that our listen socket has something to
460 * read. Do the read and reschedule this function to be called again
461 * once more is available.
466 listen_cb (void *cls);
470 * Functions with this signature are called whenever we need
471 * to close a queue due to a disconnect or failure to
472 * establish a connection.
474 * @param queue queue to close down
477 queue_destroy (struct Queue *queue)
479 struct GNUNET_MQ_Handle *mq;
481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
482 "Disconnecting queue for peer `%s'\n",
483 GNUNET_i2s (&queue->target));
484 if (NULL != (mq = queue->mq))
487 GNUNET_MQ_destroy (mq);
489 GNUNET_assert (GNUNET_YES ==
490 GNUNET_CONTAINER_multipeermap_remove (queue_map,
493 GNUNET_STATISTICS_set (stats,
495 GNUNET_CONTAINER_multipeermap_size (queue_map),
497 if (NULL != queue->read_task)
499 GNUNET_SCHEDULER_cancel (queue->read_task);
500 queue->read_task = NULL;
502 if (NULL != queue->write_task)
504 GNUNET_SCHEDULER_cancel (queue->write_task);
505 queue->write_task = NULL;
507 GNUNET_NETWORK_socket_close (queue->sock);
508 gcry_cipher_close (queue->in_cipher);
509 gcry_cipher_close (queue->out_cipher);
510 GNUNET_free (queue->address);
512 if (NULL == listen_task)
513 listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
522 * Compute @a mac over @a buf, and ratched the @a hmac_secret.
524 * @param[in,out] hmac_secret secret for HMAC calculation
525 * @param buf buffer to MAC
526 * @param buf_size number of bytes in @a buf
527 * @param smac[out] where to write the HMAC
530 hmac (struct GNUNET_HashCode *hmac_secret,
533 struct GNUNET_ShortHashCode *smac)
535 struct GNUNET_HashCode mac;
537 GNUNET_CRYPTO_hmac_raw (hmac_secret,
538 sizeof (struct GNUNET_HashCode),
542 /* truncate to `struct GNUNET_ShortHashCode` */
545 sizeof (struct GNUNET_ShortHashCode));
546 /* ratchet hmac key */
547 GNUNET_CRYPTO_hash (hmac_secret,
548 sizeof (struct GNUNET_HashCode),
554 * Append a 'finish' message to the outgoing transmission. Once the
555 * finish has been transmitted, destroy the queue.
557 * @param queue queue to shut down nicely
560 queue_finish (struct Queue *queue)
562 // FIXME: try to send 'finish' message first!?
563 queue_destroy (queue);
568 * Queue read task. If we hit the timeout, disconnect it
570 * @param cls the `struct Queue *` to disconnect
573 queue_read (void *cls)
575 struct Queue *queue = cls;
576 struct GNUNET_TIME_Relative left;
579 queue->read_task = NULL;
580 /* FIXME: perform read! */
581 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
582 &queue->cread_buf[queue->cread_off],
583 BUF_SIZE - queue->cread_off);
586 // FIXME: error handling...
589 /* update queue timeout */
590 queue->cread_off += rcvd;
591 if (queue->pread_off < sizeof (queue->pread_buf))
595 /* FIXME: check plaintext for complete messages, if complete, hand to CORE */
596 /* FIXME: CORE flow control: suspend doing more until CORE has ACKed */
599 if (BUF_SIZE == queue->cread_off)
600 return; /* buffer full, suspend reading */
601 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
602 if (0 != left.rel_value_us)
604 /* not actually our turn yet, but let's at least update
605 the monitor, it may think we're about to die ... */
607 = GNUNET_SCHEDULER_add_read_net (left,
614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
615 "Queue %p was idle for %s, disconnecting\n",
617 GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
619 queue_finish (queue);
624 * Increment queue timeout due to activity. We do not immediately
625 * notify the monitor here as that might generate excessive
628 * @param queue queue for which the timeout should be rescheduled
631 reschedule_queue_timeout (struct Queue *queue)
633 GNUNET_assert (NULL != queue->read_task);
635 = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
640 * Convert TCP bind specification to a `struct sockaddr *`
642 * @param bindto bind specification to convert
643 * @param[out] sock_len set to the length of the address
644 * @return converted bindto specification
646 static struct sockaddr *
647 tcp_address_to_sockaddr (const char *bindto,
653 /* FIXME: parse, allocate, return! */
659 * Setup @a cipher based on shared secret @a dh and decrypting
662 * @param dh shared secret
663 * @param pid decrypting peer's identity
664 * @param cipher[out] cipher to initialize
665 * @param hmac_key[out] HMAC key to initialize
668 setup_cipher (const struct GNUNET_HashCode *dh,
669 const struct GNUNET_PeerIdentity *pid,
670 gcry_cipher_hd_t *cipher,
671 struct GNUNET_HashCode *hmac_key)
676 gcry_cipher_open (cipher,
677 GCRY_CIPHER_AES256 /* low level: go for speed */,
678 GCRY_CIPHER_MODE_CTR,
680 GNUNET_assert (GNUNET_YES ==
681 GNUNET_CRYPTO_kdf (key,
690 gcry_cipher_setkey (*cipher,
693 GNUNET_assert (GNUNET_YES ==
694 GNUNET_CRYPTO_kdf (ctr,
703 gcry_cipher_setctr (*cipher,
706 GNUNET_assert (GNUNET_YES ==
707 GNUNET_CRYPTO_kdf (hmac_key,
708 sizeof (struct GNUNET_HashCode),
720 * Setup cipher of @a queue for decryption.
722 * @param ephemeral ephemeral key we received from the other peer
723 * @param queue[in,out] queue to initialize decryption cipher for
726 setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
729 struct GNUNET_HashCode dh;
731 GNUNET_CRYPTO_eddsa_ecdh (my_private_key,
742 * Setup cipher for outgoing data stream based on target and
743 * our ephemeral private key.
745 * @param queue queue to setup outgoing (encryption) cipher for
748 setup_out_cipher (struct Queue *queue)
750 struct GNUNET_HashCode dh;
752 GNUNET_CRYPTO_ecdh_eddsa (&queue->ephemeral,
753 &queue->target.public_key,
755 /* we don't need the private key anymore, drop it! */
756 memset (&queue->ephemeral,
758 sizeof (queue->ephemeral));
764 queue->rekey_time = GNUNET_TIME_relative_to_absolute (REKEY_TIME_INTERVAL);
765 queue->rekey_left_bytes = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
771 * Inject a `struct TCPRekey` message into the queue's plaintext
774 * @param queue queue to perform rekeying on
777 inject_rekey (struct Queue *queue)
779 struct TCPRekey rekey;
780 struct TcpHandshakeSignature thp;
782 GNUNET_assert (0 == queue->pwrite_off);
786 GNUNET_assert (GNUNET_OK ==
787 GNUNET_CRYPTO_ecdhe_key_create2 (&queue->ephemeral));
788 rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY);
789 rekey.header.size = ntohs (sizeof (rekey));
790 GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral,
792 rekey.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
793 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY);
794 thp.purpose.size = htonl (sizeof (thp));
795 thp.sender = my_identity;
796 thp.receiver = queue->target;
797 thp.ephemeral = rekey.ephemeral;
798 thp.monotonic_time = rekey.monotonic_time;
799 GNUNET_assert (GNUNET_OK ==
800 GNUNET_CRYPTO_eddsa_sign (my_private_key,
803 hmac (&queue->out_hmac,
807 memcpy (queue->pwrite_buf,
810 queue->rekey_state = GNUNET_YES;
815 * We encrypted the rekey message, now update actually swap the key
816 * material and update the key freshness parameters of @a queue.
819 switch_key (struct Queue *queue)
821 queue->rekey_state = GNUNET_NO;
822 gcry_cipher_close (queue->out_cipher);
823 setup_out_cipher (queue);
828 * We have been notified that our socket is ready to write.
829 * Then reschedule this function to be called again once more is available.
831 * @param cls a `struct Queue`
834 queue_write (void *cls)
836 struct Queue *queue = cls;
839 queue->write_task = NULL;
840 sent = GNUNET_NETWORK_socket_send (queue->sock,
847 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
849 queue_destroy (queue);
854 size_t usent = (size_t) sent;
856 memmove (queue->cwrite_buf,
857 &queue->cwrite_buf[sent],
858 queue->cwrite_off - sent);
859 /* FIXME: update queue timeout */
861 /* can we encrypt more? (always encrypt full messages, needed
862 such that #mq_cancel() can work!) */
863 if (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE)
866 gcry_cipher_encrypt (queue->out_cipher,
867 &queue->cwrite_buf[queue->cwrite_off],
871 if (queue->rekey_left_bytes > queue->pwrite_off)
872 queue->rekey_left_bytes -= queue->pwrite_off;
874 queue->rekey_left_bytes = 0;
875 queue->cwrite_off += queue->pwrite_off;
876 queue->pwrite_off = 0;
878 if ( (GNUNET_YES == queue->rekey_state) &&
879 (0 == queue->pwrite_off) )
881 if ( (0 == queue->pwrite_off) &&
882 ( (0 == queue->rekey_left_bytes) ||
883 (0 == GNUNET_TIME_absolute_get_remaining (queue->rekey_time).rel_value_us) ) )
884 inject_rekey (queue);
885 if ( (0 == queue->pwrite_off) &&
886 (! queue->finishing) &&
887 (queue->mq_awaits_continue) )
889 queue->mq_awaits_continue = GNUNET_NO;
890 GNUNET_MQ_impl_send_continue (queue->mq);
892 /* do we care to write more? */
893 if (0 < queue->cwrite_off)
895 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
903 * Signature of functions implementing the sending functionality of a
906 * @param mq the message queue
907 * @param msg the message to send
908 * @param impl_state our `struct Queue`
911 mq_send (struct GNUNET_MQ_Handle *mq,
912 const struct GNUNET_MessageHeader *msg,
915 struct Queue *queue = impl_state;
916 uint16_t msize = ntohs (msg->size);
919 GNUNET_assert (mq == queue->mq);
920 GNUNET_assert (0 == queue->pread_off);
921 box.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX);
922 box.header.size = htons (msize);
923 hmac (&queue->out_hmac,
927 memcpy (&queue->pread_buf[queue->pread_off],
930 queue->pread_off += sizeof (box);
931 memcpy (&queue->pread_buf[queue->pread_off],
934 queue->pread_off += msize;
935 GNUNET_assert (NULL != queue->sock);
936 if (NULL == queue->write_task)
938 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
946 * Signature of functions implementing the destruction of a message
947 * queue. Implementations must not free @a mq, but should take care
950 * @param mq the message queue to destroy
951 * @param impl_state our `struct Queue`
954 mq_destroy (struct GNUNET_MQ_Handle *mq,
957 struct Queue *queue = impl_state;
962 queue_finish (queue);
968 * Implementation function that cancels the currently sent message.
970 * @param mq message queue
971 * @param impl_state our `struct Queue`
974 mq_cancel (struct GNUNET_MQ_Handle *mq,
977 struct Queue *queue = impl_state;
979 GNUNET_assert (0 != queue->pwrite_off);
980 queue->pwrite_off = 0;
985 * Generic error handler, called with the appropriate
986 * error code and the same closure specified at the creation of
988 * Not every message queue implementation supports an error handler.
990 * @param cls our `struct Queue`
991 * @param error error code
995 enum GNUNET_MQ_Error error)
997 struct Queue *queue = cls;
999 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1000 "MQ error in queue to %s: %d\n",
1001 GNUNET_i2s (&queue->target),
1003 queue_finish (queue);
1008 * Creates a new outbound queue the transport service will use to send
1009 * data to another peer.
1011 * @param sock the queue's socket
1012 * @param target the target peer
1013 * @param cs inbound or outbound queue
1014 * @param in the address
1015 * @param in_len number of bytes in @a in
1016 * @return the queue or NULL of max connections exceeded
1018 static struct Queue *
1019 setup_queue (struct GNUNET_NETWORK_Handle *sock,
1020 const struct GNUNET_PeerIdentity *target,
1021 enum GNUNET_TRANSPORT_ConnectionStatus cs,
1022 const struct sockaddr *in,
1025 struct Queue *queue;
1027 queue = GNUNET_new (struct Queue);
1028 queue->target = *target;
1029 queue->address = GNUNET_memdup (in,
1031 queue->address_len = in_len;
1033 queue->nt = 0; // FIXME: determine NT!
1034 (void) GNUNET_CONTAINER_multipeermap_put (queue_map,
1037 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1038 GNUNET_STATISTICS_set (stats,
1040 GNUNET_CONTAINER_multipeermap_size (queue_map),
1043 = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1045 = GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1050 = GNUNET_MQ_queue_for_callbacks (&mq_send,
1060 switch (queue->address->sa_family)
1063 GNUNET_asprintf (&foreign_addr,
1065 COMMUNICATOR_ADDRESS_PREFIX,
1070 GNUNET_asprintf (&foreign_addr,
1072 COMMUNICATOR_ADDRESS_PREFIX,
1080 = GNUNET_TRANSPORT_communicator_mq_add (ch,
1087 GNUNET_free (foreign_addr);
1094 * We have been notified that our listen socket has something to
1095 * read. Do the read and reschedule this function to be called again
1096 * once more is available.
1101 listen_cb (void *cls);
1105 * We have been notified that our listen socket has something to
1106 * read. Do the read and reschedule this function to be called again
1107 * once more is available.
1112 listen_cb (void *cls)
1114 struct Queue *queue;
1115 struct sockaddr_storage in;
1117 struct GNUNET_NETWORK_Handle *sock;
1120 GNUNET_assert (NULL != listen_sock);
1121 addrlen = sizeof (in);
1125 sock = GNUNET_NETWORK_socket_accept (listen_sock,
1126 (struct sockaddr *) &in,
1128 if ( (NULL == sock) &&
1129 ( (EMFILE == errno) ||
1130 (ENFILE == errno) ) )
1131 return; /* system limit reached, wait until connection goes down */
1132 listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1136 if ( (NULL == sock) &&
1137 ( (EAGAIN == errno) ||
1138 (ENOBUFS == errno) ) )
1142 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1147 // FIXME: setup proto-queue first here, until we have received the starting
1149 queue = setup_queue (sock,
1150 GNUNET_TRANSPORT_CS_INBOUND,
1151 (struct sockaddr *) &in,
1155 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1156 _("Maximum number of TCP connections exceeded, dropping incoming connection\n"));
1164 * Function called by the transport service to initialize a
1165 * message queue given address information about another peer.
1166 * If and when the communication channel is established, the
1167 * communicator must call #GNUNET_TRANSPORT_communicator_mq_add()
1168 * to notify the service that the channel is now up. It is
1169 * the responsibility of the communicator to manage sane
1170 * retries and timeouts for any @a peer/@a address combination
1171 * provided by the transport service. Timeouts and retries
1172 * do not need to be signalled to the transport service.
1174 * @param cls closure
1175 * @param peer identity of the other peer
1176 * @param address where to send the message, human-readable
1177 * communicator-specific format, 0-terminated, UTF-8
1178 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is invalid
1182 const struct GNUNET_PeerIdentity *peer,
1183 const char *address)
1185 struct Queue *queue;
1187 struct sockaddr *in;
1189 struct GNUNET_NETWORK_Handle *sock;
1190 struct GNUNET_CRYPTO_EcdhePublicKey epub;
1191 struct TcpHandshakeSignature ths;
1192 struct TCPConfirmation tc;
1194 if (0 != strncmp (address,
1195 COMMUNICATOR_ADDRESS_PREFIX "-",
1196 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
1198 GNUNET_break_op (0);
1199 return GNUNET_SYSERR;
1201 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
1202 in = tcp_address_to_sockaddr (path,
1205 sock = GNUNET_NETWORK_socket_create (in->sa_family,
1210 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1211 "socket(%d) failed: %s",
1215 return GNUNET_SYSERR;
1218 GNUNET_NETWORK_socket_connect (sock,
1222 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1223 "connect to `%s' failed: %s",
1226 GNUNET_NETWORK_socket_close (sock);
1228 return GNUNET_SYSERR;
1230 queue = setup_queue (sock,
1232 GNUNET_TRANSPORT_CS_OUTBOUND,
1238 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1239 "Failed to setup queue to %s at `%s'\n",
1242 GNUNET_NETWORK_socket_close (sock);
1245 GNUNET_assert (GNUNET_OK ==
1246 GNUNET_CRYPTO_ecdhe_key_create2 (&queue->ephemeral));
1247 GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral,
1249 setup_out_cipher (queue);
1250 memcpy (queue->cwrite_buf,
1253 queue->cwrite_off = sizeof (epub);
1254 /* compute 'tc' and append in encrypted format to cwrite_buf */
1255 tc.sender = my_identity;
1256 tc.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1257 ths.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE);
1258 ths.purpose.size = htonl (sizeof (ths));
1259 ths.sender = my_identity;
1260 ths.receiver = queue->target;
1261 ths.ephemeral = epub;
1262 ths.monotonic_time = tc.monotonic_time;
1263 GNUNET_assert (GNUNET_OK ==
1264 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1268 gcry_cipher_encrypt (queue->out_cipher,
1269 &queue->cwrite_buf[queue->cwrite_off],
1273 queue->cwrite_off += sizeof (tc);
1280 * Iterator over all message queues to clean up.
1283 * @param target unused
1284 * @param value the queue to destroy
1285 * @return #GNUNET_OK to continue to iterate
1288 get_queue_delete_it (void *cls,
1289 const struct GNUNET_PeerIdentity *target,
1292 struct Queue *queue = value;
1296 queue_destroy (queue);
1302 * Shutdown the UNIX communicator.
1304 * @param cls NULL (always)
1307 do_shutdown (void *cls)
1309 if (NULL != listen_task)
1311 GNUNET_SCHEDULER_cancel (listen_task);
1314 if (NULL != listen_sock)
1316 GNUNET_break (GNUNET_OK ==
1317 GNUNET_NETWORK_socket_close (listen_sock));
1320 GNUNET_CONTAINER_multipeermap_iterate (queue_map,
1321 &get_queue_delete_it,
1323 GNUNET_CONTAINER_multipeermap_destroy (queue_map);
1326 GNUNET_TRANSPORT_communicator_address_remove (ai);
1331 GNUNET_TRANSPORT_communicator_disconnect (ch);
1336 GNUNET_STATISTICS_destroy (stats,
1340 if (NULL != my_private_key)
1342 GNUNET_free (my_private_key);
1343 my_private_key = NULL;
1349 * Function called when the transport service has received an
1350 * acknowledgement for this communicator (!) via a different return
1353 * Not applicable for TCP.
1355 * @param cls closure
1356 * @param sender which peer sent the notification
1357 * @param msg payload
1360 enc_notify_cb (void *cls,
1361 const struct GNUNET_PeerIdentity *sender,
1362 const struct GNUNET_MessageHeader *msg)
1367 GNUNET_break_op (0);
1372 * Setup communicator and launch network interactions.
1374 * @param cls NULL (always)
1375 * @param args remaining command-line arguments
1376 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1377 * @param c configuration
1382 const char *cfgfile,
1383 const struct GNUNET_CONFIGURATION_Handle *c)
1386 struct sockaddr *in;
1393 GNUNET_CONFIGURATION_get_value_filename (cfg,
1394 COMMUNICATOR_CONFIG_SECTION,
1398 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1399 COMMUNICATOR_CONFIG_SECTION,
1404 GNUNET_CONFIGURATION_get_value_number (cfg,
1405 COMMUNICATOR_CONFIG_SECTION,
1408 max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
1410 in = tcp_address_to_sockaddr (bindto,
1414 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1415 "Failed to setup TCP socket address with path `%s'\n",
1417 GNUNET_free (bindto);
1420 listen_sock = GNUNET_NETWORK_socket_create (in->sa_family,
1423 if (NULL == listen_sock)
1425 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1428 GNUNET_free (bindto);
1432 GNUNET_NETWORK_socket_bind (listen_sock,
1436 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
1439 GNUNET_NETWORK_socket_close (listen_sock);
1442 GNUNET_free (bindto);
1446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1449 stats = GNUNET_STATISTICS_create ("C-TCP",
1451 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1453 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1454 if (NULL == my_private_key)
1456 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1457 _("Transport service is lacking key configuration settings. Exiting.\n"));
1458 GNUNET_SCHEDULER_shutdown ();
1461 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1462 &my_identity.public_key);
1464 listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1468 queue_map = GNUNET_CONTAINER_multipeermap_create (10,
1470 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
1471 COMMUNICATOR_CONFIG_SECTION,
1472 COMMUNICATOR_ADDRESS_PREFIX,
1473 GNUNET_TRANSPORT_CC_RELIABLE,
1481 GNUNET_SCHEDULER_shutdown ();
1482 GNUNET_free (bindto);
1485 // FIXME: bindto is wrong here, we MUST get our external
1486 // IP address and really look at 'in' here as we might
1487 // be bound to loopback or some other specific IP address!
1488 GNUNET_asprintf (&my_addr,
1490 COMMUNICATOR_ADDRESS_PREFIX,
1492 GNUNET_free (bindto);
1493 // FIXME: based on our bindto, we might not be able to tell the
1494 // network type yet! What to do here!?
1495 ai = GNUNET_TRANSPORT_communicator_address_add (ch,
1497 GNUNET_NT_LOOPBACK, // FIXME: wrong NT!
1498 GNUNET_TIME_UNIT_FOREVER_REL);
1499 GNUNET_free (my_addr);
1504 * The main function for the UNIX communicator.
1506 * @param argc number of arguments from the command line
1507 * @param argv command line arguments
1508 * @return 0 ok, 1 on error
1514 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1515 GNUNET_GETOPT_OPTION_END
1520 GNUNET_STRINGS_get_utf8_args (argc, argv,
1526 GNUNET_PROGRAM_run (argc, argv,
1527 "gnunet-communicator-tcp",
1528 _("GNUnet TCP communicator"),
1532 GNUNET_free ((void*) argv);
1537 #if defined(LINUX) && defined(__GLIBC__)
1541 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1543 void __attribute__ ((constructor))
1544 GNUNET_ARM_memory_init ()
1546 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1547 mallopt (M_TOP_PAD, 1 * 1024);
1552 /* end of gnunet-communicator-tcp.c */