GNUnet 0.28.1-dev.4-8-g14b9efcb0
 
Loading...
Searching...
No Matches
gnunet-communicator-tcp.c File Reference

Transport plugin using TCP. More...

Include dependency graph for gnunet-communicator-tcp.c:

Go to the source code of this file.

Data Structures

struct  TcpHandshakeSignature
 Signature we use to verify that the ephemeral key was really chosen by the specified sender. More...
 
struct  TcpHandshakeAckSignature
 Signature we use to verify that the ack from the receiver of the ephemeral key was really send by the specified sender. More...
 
struct  TCPConfirmation
 Encrypted continuation of TCP initial handshake. More...
 
struct  TCPConfirmationAck
 Ack for the encrypted continuation of TCP initial handshake. More...
 
struct  TCPBox
 TCP message box. More...
 
struct  TCPRekey
 TCP rekey message box. More...
 
struct  TcpRekeySignature
 Signature we use to verify that the ephemeral key was really chosen by the specified sender. More...
 
struct  TCPFinish
 TCP finish. More...
 
struct  TCPNATProbeMessage
 Basically a WELCOME message, but with the purpose of giving the waiting peer a client handle to use. More...
 
struct  PendingReversal
 Struct for pending nat reversals. More...
 
struct  ListenTask
 Struct to use as closure. More...
 
struct  Queue
 Handle for a queue. More...
 
struct  ProtoQueue
 Handle for an incoming connection where we do not yet have enough information to setup a full queue. More...
 
struct  PortOnlyIpv4Ipv6
 In case of port only configuration we like to bind to ipv4 and ipv6 addresses. More...
 
struct  Addresses
 DLL to store the addresses we like to register at NAT service. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "communicator-tcp", __VA_ARGS__)
 
#define NAT_TIMEOUT   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
 How long until we give up on establishing an NAT connection? Must be > 4 RTT.
 
#define ADDRESS_VALIDITY_PERIOD    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
 How long do we believe our addresses to remain up (before the other peer should revalidate).
 
#define DEFAULT_MAX_QUEUE_LENGTH   8
 How many messages do we keep at most in the queue to the transport service before we start to drop (default, can be changed via the configuration file).
 
#define BUF_SIZE   (2 * 64 * 1024 + sizeof(struct TCPBox))
 Size of our IO buffers for ciphertext data.
 
#define TCP_QUEUE_GONE   SIZE_MAX
 Sentinel returned by try_handle_plaintext() to say that it destroyed the queue it was given.
 
#define DEFAULT_REKEY_INTERVAL   GNUNET_TIME_UNIT_DAYS
 How often do we rekey based on time (at least)
 
#define PROTO_QUEUE_TIMEOUT   GNUNET_TIME_UNIT_MINUTES
 How long do we wait until we must have received the initial KX?
 
#define FINISH_TIMEOUT
 How long do we wait for a queue we are finishing to flush its GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH before we tear it down regardless? If the peer is gone the socket may never become writable again, and until queue_destroy() runs, transport (and thus CORE) is not told that this queue is dead.
 
#define REKEY_MAX_BYTES   (1024LLU * 1024 * 400)
 How often do we rekey based on number of bytes transmitted? (additionally randomized).
 
#define INITIAL_KX_SIZE
 Size of the initial key exchange message sent first in both directions.
 
#define INITIAL_CORE_KX_SIZE
 Size of the initial core key exchange messages.
 
#define COMMUNICATOR_ADDRESS_PREFIX   "tcp"
 Address prefix used by the communicator.
 
#define COMMUNICATOR_CONFIG_SECTION   "communicator-tcp"
 Configuration section used by the communicator.
 

Functions

static void listen_cb (void *cls)
 We have been notified that our listen socket has something to read.
 
static void eddsa_priv_to_hpke_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *edpk, struct GNUNET_CRYPTO_HpkePrivateKey *pk)
 
static void eddsa_pub_to_hpke_key (const struct GNUNET_CRYPTO_EddsaPublicKey *edpk, struct GNUNET_CRYPTO_HpkePublicKey *pk)
 
static void queue_destroy (struct Queue *queue)
 Functions with this signature are called whenever we need to close a queue due to a disconnect or failure to establish a connection.
 
static void calculate_hmac (struct GNUNET_CRYPTO_AuthKey *hmac_secret, const void *buf, size_t buf_size, struct GNUNET_ShortHashCode *smac)
 Compute mac over buf, and ratched the hmac_secret.
 
static void queue_write (void *cls)
 We have been notified that our socket is ready to write.
 
static void finish_timeout_cb (void *cls)
 We gave the queue a chance to flush its finish message and it did not take it (most likely because the peer is gone and the socket never became writable again).
 
static void queue_finish (struct Queue *queue)
 Append a 'finish' message to the outgoing transmission.
 
static void queue_read (void *cls)
 Queue read task.
 
static void core_read_finished_cb (void *cls, int success)
 Core tells us it is done processing a message that transport received on a queue with status success.
 
static void pass_plaintext_to_core (struct Queue *queue, const void *plaintext, size_t plaintext_len)
 We received plaintext_len bytes of plaintext on queue.
 
static void setup_cipher (const struct GNUNET_ShortHashCode *prk, const struct GNUNET_PeerIdentity *pid, gcry_cipher_hd_t *cipher, struct GNUNET_CRYPTO_AuthKey *hmac_key)
 Setup cipher based on shared secret dh and decrypting peer pid.
 
static void rekey_monotime_store_cb (void *cls, int success)
 Callback called when peerstore store operation for rekey monotime value is finished.
 
static void rekey_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY where found.
 
static void setup_in_cipher_elligator (const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct Queue *queue)
 Setup cipher of queue for decryption from an elligator representative.
 
static void setup_in_cipher (const struct GNUNET_CRYPTO_HpkeEncapsulation *ephemeral, struct Queue *queue)
 Setup cipher of queue for decryption.
 
static void do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
 Handle rekey message on queue.
 
static void handshake_ack_monotime_store_cb (void *cls, int success)
 Callback called when peerstore store operation for handshake ack monotime value is finished.
 
static void handshake_ack_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK where found.
 
static void send_challenge (struct GNUNET_CRYPTO_ChallengeNonceP challenge, struct Queue *queue)
 Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
 
static void setup_out_cipher (struct Queue *queue, struct GNUNET_ShortHashCode *dh)
 Setup cipher for outgoing data stream based on target and our ephemeral private key.
 
static void inject_rekey (struct Queue *queue)
 Inject a struct TCPRekey message into the queue's plaintext buffer.
 
static void pending_reversal_key (const struct sockaddr *in, const struct GNUNET_PeerIdentity *target, struct GNUNET_HashCode *key)
 Compute the key under which a pending NAT reversal request to target at in is stored in pending_reversals.
 
static int pending_reversals_delete_it (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static void check_and_remove_pending_reversal (struct sockaddr *in, sa_family_t sa_family, const struct GNUNET_PeerIdentity *sender)
 We got a connection with sender at in, so a NAT reversal we may have requested for that peer has served its purpose (or will never do so).
 
static void free_proto_queue (struct ProtoQueue *pq)
 Closes socket and frees memory associated with pq.
 
static void proto_queue_write (void *cls)
 We have been notified that our socket is ready to write.
 
static size_t try_handle_plaintext (struct Queue *queue)
 Test if we have received a full message in plaintext.
 
static struct sockaddr * tcp_address_to_sockaddr_numeric_v6 (socklen_t *sock_len, struct sockaddr_in6 v6, unsigned int port)
 Convert a struct sockaddr_in6 to astruct sockaddr *`.
 
static struct sockaddr * tcp_address_to_sockaddr_numeric_v4 (socklen_t *sock_len, struct sockaddr_in v4, unsigned int port)
 Convert a struct sockaddr_in4 to astruct sockaddr *`.
 
static struct PortOnlyIpv4Ipv6tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port)
 Convert TCP bind specification to a struct PortOnlyIpv4Ipv6 *
 
static char * extract_address (const char *bindto)
 This Method extracts the address part of the BINDTO string.
 
static unsigned int extract_port (const char *addr_and_port)
 This Method extracts the port part of the BINDTO string.
 
static struct sockaddr * tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
 Convert TCP bind specification to a struct sockaddr *
 
static void mq_send (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
 Signature of functions implementing the sending functionality of a message queue.
 
static void mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Signature of functions implementing the destruction of a message queue.
 
static void mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Implementation function that cancels the currently sent message.
 
static void mq_error (void *cls, enum GNUNET_MQ_Error error)
 Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.
 
static void boot_queue (struct Queue *queue)
 Add the given queue to our internal data structure.
 
static void transmit_kx (struct Queue *queue, const struct GNUNET_CRYPTO_HpkeEncapsulation *c)
 Generate and transmit our ephemeral key and the signature for the initial KX with the other peer.
 
static void start_initial_kx_out (struct Queue *queue)
 Initialize our key material for outgoing transmissions and inform the other peer about it.
 
static void handshake_monotime_store_cb (void *cls, int success)
 Callback called when peerstore store operation for handshake monotime is finished.
 
static void handshake_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE where found.
 
static int decrypt_and_check_tc (struct Queue *queue, struct TCPConfirmation *tc, char *ibuf)
 We have received the first bytes from the other side on a queue.
 
static void queue_read_kx (void *cls)
 Read from the socket of the queue until we have enough data to initialize the decryption logic and can switch to regular reading.
 
static void proto_read_kx (void *cls)
 Read from the socket of the proto queue until we have enough data to upgrade to full queue.
 
static struct ProtoQueuecreate_proto_queue (struct GNUNET_NETWORK_Handle *sock, struct sockaddr *in, socklen_t addrlen)
 
static void try_connection_reversal (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 
static void pending_reversal_timeout (void *cls)
 
static int mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
 Function called by the transport service to initialize a message queue given address information about another peer.
 
static int get_lt_delete_it (void *cls, const struct GNUNET_HashCode *key, void *value)
 Iterator over all ListenTasks to clean up.
 
static int get_queue_delete_it (void *cls, const struct GNUNET_HashCode *target, void *value)
 Iterator over all message queues to clean up.
 
static void do_shutdown (void *cls)
 Shutdown the UNIX communicator.
 
static void enc_notify_cb (void *cls, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg)
 Function called when the transport service has received an acknowledgement for this communicator (!) via a different return path.
 
static void nat_address_cb (void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
 Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of 'valid' addresses changes.
 
static void add_addr (struct sockaddr *in, socklen_t in_len)
 This method adds addresses to the DLL, that are later register at the NAT service.
 
static int init_socket (struct sockaddr *addr, socklen_t in_len)
 This method launch network interactions for each address we like to bind to.
 
static void nat_register ()
 This method reads from the DLL addrs_head to register them at the NAT service.
 
static void init_socket_resolv (void *cls, const struct sockaddr *addr, socklen_t in_len)
 This method is the callback called by the resolver API, and wraps method init_socket.
 
static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
 Setup communicator and launch network interactions.
 
int main (int argc, char *const *argv)
 The main function for the UNIX communicator.
 

Variables

static unsigned long long max_queue_length
 Maximum queue length before we stop reading towards the transport service.
 
static struct GNUNET_PILS_KeyRingkey_ring
 For PILS.
 
static struct GNUNET_PILS_Handlepils
 For PILS.
 
static struct GNUNET_STATISTICS_Handlestats
 For logging statistics.
 
static struct GNUNET_TRANSPORT_CommunicatorHandlech
 Our environment.
 
static struct GNUNET_CONTAINER_MultiHashMapqueue_map
 Queues (map from peer identity to struct Queue)
 
static struct GNUNET_CONTAINER_MultiHashMaplt_map
 ListenTasks (map from socket to struct ListenTask)
 
static unsigned long long rekey_max_bytes
 The rekey byte maximum.
 
static struct GNUNET_TIME_Relative rekey_interval
 The rekey interval.
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Our configuration.
 
static struct GNUNET_NT_InterfaceScanneris
 Network scanner to determine network types.
 
static struct GNUNET_NAT_Handlenat
 Connection to NAT service.
 
static struct ProtoQueueproto_head
 Protoqueues DLL head.
 
static struct ProtoQueueproto_tail
 Protoqueues DLL tail.
 
struct GNUNET_RESOLVER_RequestHandleresolve_request_handle
 Handle for DNS lookup of bindto address.
 
static struct Addressesaddrs_head
 Head of DLL with addresses we like to register at NAT service.
 
static struct Addressesaddrs_tail
 Head of DLL with addresses we like to register at NAT service.
 
static int addrs_lens
 Number of addresses in the DLL for register at NAT service.
 
static struct GNUNET_PEERSTORE_Handlepeerstore
 Database for peer's HELLOs.
 
static int shutdown_running = GNUNET_NO
 A flag indicating we are already doing a shutdown.
 
static int disable_v6
 IPv6 disabled.
 
static unsigned int bind_port
 The port the communicator should be assigned to.
 
static struct GNUNET_CONTAINER_MultiHashMappending_reversals
 Map of pending reversals.
 

Detailed Description

Transport plugin using TCP.

Author
Christian Grothoff

TODO:

  • support NAT connection reversal method (#5529)
  • support other TCP-specific NAT traversal methods (#5531)

Definition in file gnunet-communicator-tcp.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "communicator-tcp", __VA_ARGS__)

Definition at line 45 of file gnunet-communicator-tcp.c.

◆ NAT_TIMEOUT

How long until we give up on establishing an NAT connection? Must be > 4 RTT.

Definition at line 52 of file gnunet-communicator-tcp.c.

◆ ADDRESS_VALIDITY_PERIOD

#define ADDRESS_VALIDITY_PERIOD    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)

How long do we believe our addresses to remain up (before the other peer should revalidate).

Definition at line 58 of file gnunet-communicator-tcp.c.

144{
149
153 struct GNUNET_PeerIdentity sender;
154
159
163 struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral;
164
169 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
170
174 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
175};
176
182{
187
192
197
203
208};
209
213struct TCPConfirmation
214{
219
224
230
235
236};
237
242{
243
244
249
254
259
265
270
271};
272
276struct TCPBox
277{
285
295
296 /* followed by as may bytes of payload as indicated in @e header,
297 excluding the TCPBox itself! */
298};
299
300
305struct TCPRekey
306{
311
321
326
331
337};
338
344{
349
354
359
364
370};
371
377struct TCPFinish
378{
383
393};
394
400{
405
410};
411
413
417struct PendingReversal
418{
419 /*
420 * Timeout task.
421 */
423
428
432 struct sockaddr *in;
433};
434
438struct ListenTask
439{
444
449};
450
454struct Queue
455{
460
465
470
475
479 gcry_cipher_hd_t in_cipher;
480
484 gcry_cipher_hd_t out_cipher;
485
489 struct GNUNET_HashCode key;
490
495
501
506
511
518
522 struct sockaddr *address;
523
528 uint64_t rekey_left_bytes;
529
535
539 socklen_t address_len;
540
544 struct GNUNET_MQ_Handle *mq;
545
550
554 unsigned long long bytes_in_queue;
555
559 char cread_buf[BUF_SIZE];
560
564 char cwrite_buf[BUF_SIZE];
565
569 char pread_buf[UINT16_MAX + 1 + sizeof(struct TCPBox)];
570
574 char pwrite_buf[UINT16_MAX + 1 + sizeof(struct TCPBox)];
575
580 size_t cread_off;
581
586 size_t cwrite_off;
587
592 size_t pread_off;
593
598 size_t pwrite_off;
599
604
612 unsigned int backpressure;
613
618
623
628
632 int finishing;
633
640 int destroyed;
641
646 int rekeyed;
647
652
657
662
667
672
677
682
687
692
697
702
706 // TODO remove?
707 size_t unverified_size;
708
713};
714
715
720struct ProtoQueue
721{
725 struct ProtoQueue *next;
726
730 struct ProtoQueue *prev;
731
736
741
746
750 char write_buf[sizeof (struct TCPNATProbeMessage)];
751
755 size_t write_off;
756
761
765 struct sockaddr *address;
766
770 socklen_t address_len;
771
776
781 char ibuf[INITIAL_KX_SIZE];
782
786 size_t ibuf_off;
787};
788
792struct PortOnlyIpv4Ipv6
793{
797 struct sockaddr *addr_ipv4;
798
802 socklen_t addr_len_ipv4;
803
807 struct sockaddr *addr_ipv6;
808
812 socklen_t addr_len_ipv6;
813
814};
815
819struct Addresses
820{
824 struct Addresses *next;
825
829 struct Addresses *prev;
830
834 struct sockaddr *addr;
835
839 socklen_t addr_len;
840
841};
842
843
847static unsigned long long max_queue_length;
848
852static struct GNUNET_PILS_KeyRing *key_ring;
853
857static struct GNUNET_PILS_Handle *pils;
858
862static struct GNUNET_STATISTICS_Handle *stats;
863
868
873
878
882static unsigned long long rekey_max_bytes;
883
888
892static const struct GNUNET_CONFIGURATION_Handle *cfg;
893
897static struct GNUNET_NT_InterfaceScanner *is;
898
902static struct GNUNET_NAT_Handle *nat;
903
907static struct ProtoQueue *proto_head;
908
912static struct ProtoQueue *proto_tail;
913
918
922static struct Addresses *addrs_head;
923
927static struct Addresses *addrs_tail;
928
932static int addrs_lens;
933
938
942static int shutdown_running = GNUNET_NO;
943
947static int disable_v6;
948
952static unsigned int bind_port;
953
958
966static void
967listen_cb (void *cls);
968
969static void
972{
974 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
975 key.eddsa_key = *edpk;
977 pk);
978}
979
980
981static void
984{
986 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
987 key.eddsa_key = *edpk;
989}
990
991
999static void
1000queue_destroy (struct Queue *queue)
1001{
1002 struct ListenTask *lt = NULL;
1003 struct GNUNET_HashCode h_sock;
1004 int sockfd;
1005
1006 if (NULL != queue->listen_sock)
1007 {
1008 sockfd = GNUNET_NETWORK_get_fd (queue->listen_sock);
1009 GNUNET_CRYPTO_hash (&sockfd,
1010 sizeof(int),
1011 &h_sock);
1012
1014 }
1015
1017 "Disconnecting queue for peer `%s'\n",
1018 GNUNET_i2s (&queue->target));
1019 if (NULL != queue->rekey_monotime_sc)
1020 {
1021 GNUNET_PEERSTORE_store_cancel (queue->rekey_monotime_sc);
1022 queue->rekey_monotime_sc = NULL;
1023 }
1024 if (NULL != queue->handshake_monotime_sc)
1025 {
1026 GNUNET_PEERSTORE_store_cancel (queue->handshake_monotime_sc);
1027 queue->handshake_monotime_sc = NULL;
1028 }
1029 if (NULL != queue->handshake_ack_monotime_sc)
1030 {
1031 GNUNET_PEERSTORE_store_cancel (queue->handshake_ack_monotime_sc);
1032 queue->handshake_ack_monotime_sc = NULL;
1033 }
1034 if (NULL != queue->rekey_monotime_get)
1035 {
1036 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1037 queue->rekey_monotime_get = NULL;
1038 }
1039 if (NULL != queue->handshake_monotime_get)
1040 {
1041 GNUNET_PEERSTORE_iteration_stop (queue->handshake_monotime_get);
1042 queue->handshake_monotime_get = NULL;
1043 }
1044 if (NULL != queue->handshake_ack_monotime_get)
1045 {
1046 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1047 queue->handshake_ack_monotime_get = NULL;
1048 }
1049 if (NULL != queue->qh)
1050 {
1052 queue->qh = NULL;
1053 }
1055 GNUNET_YES ==
1058 "# queues active",
1060 GNUNET_NO);
1061 if (NULL != queue->finish_task)
1062 {
1063 GNUNET_SCHEDULER_cancel (queue->finish_task);
1064 queue->finish_task = NULL;
1065 }
1066 if (NULL != queue->read_task)
1067 {
1068 GNUNET_SCHEDULER_cancel (queue->read_task);
1069 queue->read_task = NULL;
1070 }
1071 if (NULL != queue->write_task)
1072 {
1073 GNUNET_SCHEDULER_cancel (queue->write_task);
1074 queue->write_task = NULL;
1075 }
1077 {
1079 "closing socket failed\n");
1080 }
1081 gcry_cipher_close (queue->in_cipher);
1082 gcry_cipher_close (queue->out_cipher);
1083 GNUNET_free (queue->address);
1084 if (0 != queue->backpressure)
1085 queue->destroyed = GNUNET_YES;
1086 else
1088
1089 if (NULL == lt)
1090 return;
1091
1092 if ((! shutdown_running) && (NULL == lt->listen_task))
1093 {
1095 "add read net listen\n");
1098 lt->listen_sock,
1099 &listen_cb,
1100 lt);
1101 }
1102 else
1103 GNUNET_free (lt);
1104}
1105
1106
1115static void
1116calculate_hmac (struct GNUNET_CRYPTO_AuthKey *hmac_secret,
1117 const void *buf,
1118 size_t buf_size,
1119 struct GNUNET_ShortHashCode *smac)
1120{
1121 struct GNUNET_HashCode mac;
1122
1123 GNUNET_CRYPTO_hmac (hmac_secret,
1124 buf,
1125 buf_size,
1126 &mac);
1127 /* truncate to `struct GNUNET_ShortHashCode` */
1128 memcpy (smac, &mac, sizeof(struct GNUNET_ShortHashCode));
1129 /* ratchet hmac key */
1130 GNUNET_CRYPTO_hash (hmac_secret,
1131 sizeof(struct GNUNET_HashCode),
1132 (struct GNUNET_HashCode*) hmac_secret);
1133}
1134
1135
1136static void
1137queue_write (void *cls);
1138
1139
1148static void
1149finish_timeout_cb (void *cls)
1150{
1151 struct Queue *queue = cls;
1152
1153 queue->finish_task = NULL;
1155 "Queue to %s did not flush its FINISH in time, tearing it down\n",
1156 GNUNET_i2s (&queue->target));
1158}
1159
1160
1167static void
1168queue_finish (struct Queue *queue)
1169{
1170 struct TCPFinish fin;
1171
1172 if (GNUNET_YES == queue->destroyed)
1173 return; /* socket is already gone, we only await backpressure draining */
1174 memset (&fin, 0, sizeof(fin));
1175 fin.header.size = htons (sizeof(fin));
1176 fin.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH);
1177 calculate_hmac (&queue->out_hmac, &fin, sizeof(fin), &fin.hmac);
1178 /* if there is any message left in pwrite_buf, we
1179 overwrite it (possibly dropping the last message
1180 from CORE hard here) */
1181 memcpy (queue->pwrite_buf, &fin, sizeof(fin));
1182 queue->pwrite_off = sizeof(fin);
1183 /* This flag will ensure that #queue_write() no longer
1184 notifies CORE about the possibility of sending
1185 more data, and that #queue_write() will call
1186 #queue_destroy() once the @c fin was fully written. */
1187 queue->finishing = GNUNET_YES;
1188 /* ... but #queue_write() only ever re-arms itself while it still has data
1189 buffered, and #mq_send() returns early for a finishing queue. So unless
1190 we arm the write task here, nothing writes the @c fin, #queue_destroy()
1191 is never reached, and transport is never told that this queue died: it
1192 keeps scheduling transmissions that #mq_send() silently drops, and CORE
1193 never learns about the disconnect. */
1194 if (NULL == queue->write_task)
1195 queue->write_task =
1197 queue->sock,
1198 &queue_write,
1199 queue);
1200 /* And if the peer is gone, the socket may never become writable at all. */
1201 if (NULL == queue->finish_task)
1204 queue);
1205}
1206
1207
1213static void
1214queue_read (void *cls);
1215
1216
1224static void
1225core_read_finished_cb (void *cls, int success)
1226{
1227 struct Queue *queue = cls;
1228 if (GNUNET_OK != success)
1230 "# messages lost in communicator API towards CORE",
1231 1,
1232 GNUNET_NO);
1233 if (NULL == queue)
1234 return;
1235
1237 "backpressure %u\n",
1238 queue->backpressure);
1239
1240 queue->backpressure--;
1241 /* handle deferred queue destruction */
1242 if ((queue->destroyed) && (0 == queue->backpressure))
1243 {
1245 return;
1246 }
1247 else if (GNUNET_YES != queue->destroyed)
1248 {
1249 queue->timeout =
1251 );
1252 /* possibly unchoke reading, now that CORE made progress */
1253 if (NULL == queue->read_task)
1254 queue->read_task =
1256 queue->timeout),
1257 queue->sock,
1258 &queue_read,
1259 queue);
1260 }
1261}
1262
1263
1273static void
1275 const void *plaintext,
1276 size_t plaintext_len)
1277{
1278 const struct GNUNET_MessageHeader *hdr = plaintext;
1279 int ret;
1280
1282 "pass message from %s to core\n",
1283 GNUNET_i2s (&queue->target));
1284
1285 if (ntohs (hdr->size) != plaintext_len)
1286 {
1287 /* NOTE: If we ever allow multiple CORE messages in one
1288 BOX, this will have to change! */
1289 GNUNET_break (0);
1290 return;
1291 }
1293 &queue->target,
1294 hdr,
1297 queue);
1299 "passed to core\n");
1300 if (GNUNET_OK == ret)
1301 queue->backpressure++;
1302 GNUNET_break (GNUNET_NO != ret); /* backpressure not working!? */
1303 if (GNUNET_SYSERR == ret)
1305 "# bytes lost due to CORE not running",
1306 plaintext_len,
1307 GNUNET_NO);
1308}
1309
1310
1320static void
1321setup_cipher (const struct GNUNET_ShortHashCode *prk,
1322 const struct GNUNET_PeerIdentity *pid,
1323 gcry_cipher_hd_t *cipher,
1324 struct GNUNET_CRYPTO_AuthKey *hmac_key)
1325{
1326 char key[256 / 8];
1327 char ctr[128 / 8];
1328
1329 GNUNET_assert (0 == gcry_cipher_open (cipher,
1330 GCRY_CIPHER_AES256 /* low level: go for speed */
1331 ,
1332 GCRY_CIPHER_MODE_CTR,
1333 0 /* flags */));
1336 key,
1337 sizeof(key),
1338 prk,
1339 GNUNET_CRYPTO_kdf_arg_string ("gnunet-communicator-tcp-key"))
1340 );
1341 GNUNET_assert (0 == gcry_cipher_setkey (*cipher, key, sizeof(key)));
1344 ctr,
1345 sizeof(ctr),
1346 prk,
1347 GNUNET_CRYPTO_kdf_arg_string ("gnunet-communicator-tcp-ctr"))
1348 );
1349 gcry_cipher_setctr (*cipher, ctr, sizeof(ctr));
1352 hmac_key,
1353 sizeof(struct GNUNET_HashCode),
1354 prk,
1355 GNUNET_CRYPTO_kdf_arg_string ("gnunet-communicator-hmac")));
1356}
1357
1358
1364static void
1365rekey_monotime_store_cb (void *cls, int success)
1366{
1367 struct Queue *queue = cls;
1368 if (GNUNET_OK != success)
1369 {
1371 "Failed to store rekey monotonic time in PEERSTORE!\n");
1372 }
1373 queue->rekey_monotime_sc = NULL;
1374 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1375}
1376
1377
1385static void
1386rekey_monotime_cb (void *cls,
1387 const struct GNUNET_PEERSTORE_Record *record,
1388 const char *emsg)
1389{
1390 struct Queue *queue = cls;
1391 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1392 struct GNUNET_TIME_Absolute mt;
1393 const struct GNUNET_PeerIdentity *pid;
1394 struct GNUNET_TIME_AbsoluteNBO *rekey_monotonic_time;
1395
1396 (void) emsg;
1397
1398 rekey_monotonic_time = &queue->rekey_monotonic_time;
1399 pid = &queue->target;
1400 if (NULL == record)
1401 {
1402 queue->rekey_monotime_get = NULL;
1403 return;
1404 }
1405 if (sizeof(*mtbe) != record->value_size)
1406 {
1407 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1408 GNUNET_break (0);
1409 return;
1410 }
1411 mtbe = record->value;
1412 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1413 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1414 queue->rekey_monotonic_time).abs_value_us)
1415 {
1417 "Queue from %s dropped, rekey monotime in the past\n",
1418 GNUNET_i2s (&queue->target));
1419 GNUNET_break (0);
1420 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1421 queue->rekey_monotime_get = NULL;
1422 // FIXME: Why should we try to gracefully finish here??
1424 return;
1425 }
1426 queue->rekey_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
1427 "transport_tcp_communicator",
1428 pid,
1430 rekey_monotonic_time,
1431 sizeof(*
1432 rekey_monotonic_time),
1436 queue);
1437}
1438
1439
1446static void
1448 const struct GNUNET_CRYPTO_HpkeEncapsulation *c,
1449 struct Queue *queue)
1450{
1451 const struct GNUNET_PeerIdentity *my_identity;
1453 struct GNUNET_CRYPTO_HpkePrivateKey my_hpke_key;
1454 struct GNUNET_ShortHashCode k;
1455
1459
1460 eddsa_priv_to_hpke_key (my_private_key, &my_hpke_key);
1461
1463 c,
1464 &k);
1465 setup_cipher (&k, my_identity, &queue->in_cipher, &queue->in_hmac);
1466}
1467
1468
1475static void
1476setup_in_cipher (const struct GNUNET_CRYPTO_HpkeEncapsulation *ephemeral,
1477 struct Queue *queue)
1478{
1479 const struct GNUNET_PeerIdentity *my_identity;
1481 struct GNUNET_ShortHashCode k;
1482
1486
1488 setup_cipher (&k, my_identity, &queue->in_cipher, &queue->in_hmac);
1489}
1490
1491
1500static void
1501do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
1502{
1503 const struct GNUNET_PeerIdentity *my_identity;
1504 struct TcpRekeySignature thp;
1505
1508
1509 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1510 thp.purpose.size = htonl (sizeof(thp));
1512 "do_rekey size %u\n",
1513 thp.purpose.size);
1514 thp.sender = queue->target;
1516 "sender %s\n",
1517 GNUNET_p2s (&thp.sender.public_key));
1519 "sender %s\n",
1520 GNUNET_p2s (&queue->target.public_key));
1521 thp.receiver = *my_identity;
1523 "receiver %s\n",
1524 GNUNET_p2s (&thp.receiver.public_key));
1525 thp.ephemeral = rekey->ephemeral;
1527 "ephemeral %s\n",
1528 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
1529 );
1530 thp.monotonic_time = rekey->monotonic_time;
1532 "time %s\n",
1534 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1535 GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp)));
1536 if (GNUNET_OK !=
1539 &thp,
1540 &rekey->sender_sig,
1541 &queue->target.public_key))
1542 {
1543 GNUNET_break (0);
1544 // FIXME Why should we try to gracefully finish here?
1546 return;
1547 }
1548 queue->rekey_monotonic_time = rekey->monotonic_time;
1549 queue->rekey_monotime_get = GNUNET_PEERSTORE_iteration_start (peerstore,
1550 "transport_tcp_communicator",
1551 &queue->target,
1553 &
1555 queue);
1556 gcry_cipher_close (queue->in_cipher);
1557 queue->rekeyed = GNUNET_YES;
1558 setup_in_cipher (&rekey->ephemeral, queue);
1559}
1560
1561
1567static void
1568handshake_ack_monotime_store_cb (void *cls, int success)
1569{
1570 struct Queue *queue = cls;
1571
1572 if (GNUNET_OK != success)
1573 {
1575 "Failed to store handshake ack monotonic time in PEERSTORE!\n");
1576 }
1577 queue->handshake_ack_monotime_sc = NULL;
1578 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1579}
1580
1581
1589static void
1590handshake_ack_monotime_cb (void *cls,
1591 const struct GNUNET_PEERSTORE_Record *record,
1592 const char *emsg)
1593{
1594 struct Queue *queue = cls;
1595 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1596 struct GNUNET_TIME_Absolute mt;
1597 const struct GNUNET_PeerIdentity *pid;
1598 struct GNUNET_TIME_AbsoluteNBO *handshake_ack_monotonic_time;
1599
1600 (void) emsg;
1601
1602 handshake_ack_monotonic_time = &queue->handshake_ack_monotonic_time;
1603 pid = &queue->target;
1604 if (NULL == record)
1605 {
1606 queue->handshake_ack_monotime_get = NULL;
1607 return;
1608 }
1609 if (sizeof(*mtbe) != record->value_size)
1610 {
1611 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1612 GNUNET_break (0);
1613 return;
1614 }
1615 mtbe = record->value;
1616 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1617 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1618 queue->handshake_ack_monotonic_time).abs_value_us)
1619 {
1621 "Queue from %s dropped, handshake ack monotime in the past\n",
1622 GNUNET_i2s (&queue->target));
1623 GNUNET_break (0);
1624 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1625 queue->handshake_ack_monotime_get = NULL;
1626 // FIXME: Why should we try to gracefully finish here?
1628 return;
1629 }
1630 queue->handshake_ack_monotime_sc =
1632 "transport_tcp_communicator",
1633 pid,
1635 handshake_ack_monotonic_time,
1636 sizeof(*handshake_ack_monotonic_time),
1640 queue);
1641}
1642
1643
1650static void
1652 struct Queue *queue)
1653{
1654 const struct GNUNET_PeerIdentity *my_identity;
1656 struct TCPConfirmationAck tca;
1657 struct TcpHandshakeAckSignature thas;
1658
1662
1664 "sending challenge\n");
1665
1666 tca.header.type = ntohs (
1668 tca.header.size = ntohs (sizeof(tca));
1669 tca.challenge = challenge;
1670 tca.sender = *my_identity;
1671 tca.monotonic_time =
1673 thas.purpose.purpose = htonl (
1675 thas.purpose.size = htonl (sizeof(thas));
1676 thas.sender = *my_identity;
1677 thas.receiver = queue->target;
1678 thas.monotonic_time = tca.monotonic_time;
1679 thas.challenge = tca.challenge;
1681 &thas,
1682 &tca.sender_sig);
1683 GNUNET_assert (0 ==
1684 gcry_cipher_encrypt (queue->out_cipher,
1685 &queue->cwrite_buf[queue->cwrite_off],
1686 sizeof(tca),
1687 &tca,
1688 sizeof(tca)));
1689 queue->cwrite_off += sizeof(tca);
1691 "sending challenge done\n");
1692}
1693
1694
1701static void
1703{
1704 setup_cipher (dh, &queue->target, &queue->out_cipher, &queue->out_hmac);
1706 queue->rekey_left_bytes =
1708}
1709
1710
1717static void
1718inject_rekey (struct Queue *queue)
1719{
1720 const struct GNUNET_PeerIdentity *my_identity;
1722 struct TCPRekey rekey;
1723 struct TcpRekeySignature thp;
1724 struct GNUNET_ShortHashCode k;
1725
1729
1730 GNUNET_assert (0 == queue->pwrite_off);
1731 memset (&rekey, 0, sizeof(rekey));
1732 GNUNET_CRYPTO_eddsa_kem_encaps (&queue->target.public_key, &rekey.ephemeral,
1733 &k);
1735 rekey.header.size = ntohs (sizeof(rekey));
1736 rekey.monotonic_time =
1738 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1739 thp.purpose.size = htonl (sizeof(thp));
1741 "inject_rekey size %u\n",
1742 thp.purpose.size);
1743 thp.sender = *my_identity;
1745 "sender %s\n",
1746 GNUNET_p2s (&thp.sender.public_key));
1747 thp.receiver = queue->target;
1749 "receiver %s\n",
1750 GNUNET_p2s (&thp.receiver.public_key));
1751 thp.ephemeral = rekey.ephemeral;
1753 "ephemeral %s\n",
1754 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
1755 );
1756 thp.monotonic_time = rekey.monotonic_time;
1758 "time %s\n",
1760 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1762 &thp,
1763 &rekey.sender_sig);
1764 calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac);
1765 /* Encrypt rekey message with 'old' cipher */
1766 GNUNET_assert (0 ==
1767 gcry_cipher_encrypt (queue->out_cipher,
1768 &queue->cwrite_buf[queue->cwrite_off],
1769 sizeof(rekey),
1770 &rekey,
1771 sizeof(rekey)));
1772 queue->cwrite_off += sizeof(rekey);
1773 /* Setup new cipher for successive messages */
1774 gcry_cipher_close (queue->out_cipher);
1775 setup_out_cipher (queue, &k);
1776}
1777
1778
1794static void
1795pending_reversal_key (const struct sockaddr *in,
1796 const struct GNUNET_PeerIdentity *target,
1797 struct GNUNET_HashCode *key)
1798{
1799 struct sockaddr_in v4;
1800 struct GNUNET_HashContext *hsh;
1801
1802 GNUNET_assert (AF_INET == in->sa_family);
1803 GNUNET_memcpy (&v4, in, sizeof(v4));
1804 v4.sin_port = 0;
1806 GNUNET_CRYPTO_hash_context_read (hsh, &v4, sizeof(v4));
1807 GNUNET_CRYPTO_hash_context_read (hsh, target, sizeof(*target));
1809}
1810
1811
1812static int
1814 const struct GNUNET_HashCode *key,
1815 void *value)
1816{
1817 struct PendingReversal *pending_reversal = value;
1818 (void) cls;
1819
1820 if (NULL != pending_reversal->timeout_task)
1821 {
1822 GNUNET_SCHEDULER_cancel (pending_reversal->timeout_task);
1823 pending_reversal->timeout_task = NULL;
1824 }
1827 key,
1828 pending_reversal));
1829 GNUNET_free (pending_reversal->in);
1830 GNUNET_free (pending_reversal);
1831 return GNUNET_OK;
1832}
1833
1834
1848static void
1849check_and_remove_pending_reversal (struct sockaddr *in, sa_family_t sa_family,
1850 const struct GNUNET_PeerIdentity *sender)
1851{
1852 if (AF_INET == sa_family)
1853 {
1854 struct PendingReversal *pending_reversal;
1855 struct GNUNET_HashCode key;
1856
1857 pending_reversal_key (in, sender, &key);
1859 &key);
1860 if (NULL != pending_reversal)
1861 {
1863 "Removing completed pending reversal for `%s' at `%s'\n",
1864 GNUNET_i2s (&pending_reversal->target),
1865 GNUNET_a2s (in, sizeof (struct sockaddr)));
1866 pending_reversals_delete_it (NULL, &key, pending_reversal);
1867 }
1868 }
1869}
1870
1871
1877static void
1878free_proto_queue (struct ProtoQueue *pq)
1879{
1880 if (NULL != pq->listen_sock)
1881 {
1883 pq->listen_sock = NULL;
1884 }
1885 if (NULL != pq->read_task)
1886 {
1888 pq->read_task = NULL;
1889 }
1890 if (NULL != pq->write_task)
1891 {
1893 pq->write_task = NULL;
1894 }
1895 /* NOTE: deliberately no #check_and_remove_pending_reversal() here. A proto
1896 queue is anonymous -- we have not completed the KX, so we do not know
1897 which peer this was. Dropping "the" pending reversal for the IP used to
1898 cancel the reversal of an unrelated peer that happens to sit behind the
1899 same NAT. A reversal that truly went nowhere expires on #NAT_TIMEOUT. */
1901 GNUNET_free (pq->address);
1903 GNUNET_free (pq);
1904}
1905
1906
1913static void
1914proto_queue_write (void *cls)
1915{
1916 struct ProtoQueue *pq = cls;
1917 ssize_t sent;
1918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In proto queue write\n");
1919 pq->write_task = NULL;
1920 if (0 != pq->write_off)
1921 {
1922 sent = GNUNET_NETWORK_socket_send (pq->sock,
1923 pq->write_buf,
1924 pq->write_off);
1926 "Sent %lu bytes to TCP queue\n", sent);
1927 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1928 {
1930 free_proto_queue (pq);
1931 return;
1932 }
1933 if (sent > 0)
1934 {
1935 size_t usent = (size_t) sent;
1936 pq->write_off -= usent;
1937 memmove (pq->write_buf,
1938 &pq->write_buf[usent],
1939 pq->write_off);
1940 }
1941 }
1942 /* do we care to write more? */
1943 if ((0 < pq->write_off))
1944 pq->write_task =
1946 pq->sock,
1948 pq);
1949}
1950
1951
1958static void
1959queue_write (void *cls)
1960{
1961 struct Queue *queue = cls;
1962 ssize_t sent;
1963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n");
1964 queue->write_task = NULL;
1965 if (0 != queue->cwrite_off)
1966 {
1967 sent = GNUNET_NETWORK_socket_send (queue->sock,
1968 queue->cwrite_buf,
1969 queue->cwrite_off);
1971 "Sent %lu bytes to TCP queue\n", sent);
1972 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1973 {
1976 return;
1977 }
1978 if (sent > 0)
1979 {
1980 size_t usent = (size_t) sent;
1981 queue->cwrite_off -= usent;
1982 memmove (queue->cwrite_buf,
1983 &queue->cwrite_buf[usent],
1984 queue->cwrite_off);
1985 queue->timeout =
1988 }
1989 }
1990 {
1991 /* can we encrypt more? (always encrypt full messages, needed
1992 such that #mq_cancel() can work!)
1993
1994 NOTE: this used to be gated on a `we_do_not_need_to_rekey' flag
1995 computed as `0 < rekey_left_bytes - (cwrite_off + pwrite_off +
1996 sizeof (struct TCPRekey))'. That subtraction is unsigned, so it
1997 wrapped to a huge value precisely when the rekey budget was about to
1998 run out -- inverting the test it was meant to express, and reporting
1999 "no rekey needed" even for a @e rekey_left_bytes of zero. The single
2000 value it did get right, exact equality, was worse still: it let the
2001 branch below call #inject_rekey() with a non-empty @e pwrite_buf,
2002 which that function asserts against, and if neither rekey trigger
2003 held it wedged this queue into a busy write loop that never drained
2004 @e pwrite_buf again -- a stall the peer sees as silence while the
2005 socket stays open and the communicator keeps reporting the queue up.
2006
2007 Encrypting a message first and rekeying immediately afterwards
2008 overshoots the byte budget by at most one message, which against the
2009 400 MB default is noise. */
2010 if ((queue->pwrite_off > 0) &&
2011 (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE))
2012 {
2014 "Encrypting %lu bytes\n", queue->pwrite_off);
2015 GNUNET_assert (0 ==
2016 gcry_cipher_encrypt (queue->out_cipher,
2017 &queue->cwrite_buf[queue->cwrite_off],
2018 queue->pwrite_off,
2019 queue->pwrite_buf,
2020 queue->pwrite_off));
2021 if (queue->rekey_left_bytes > queue->pwrite_off)
2022 queue->rekey_left_bytes -= queue->pwrite_off;
2023 else
2024 queue->rekey_left_bytes = 0;
2025 queue->cwrite_off += queue->pwrite_off;
2026 queue->pwrite_off = 0;
2027 }
2028 /* Rekey once the byte budget is spent or the interval elapsed.
2029 #inject_rekey() requires an empty plaintext buffer (it asserts on it)
2030 and enough room in the ciphertext buffer; if either is missing we
2031 simply rekey on a later #queue_write(), which the write task above
2032 keeps arming for as long as anything is still buffered. */
2033 if (((0 == queue->rekey_left_bytes) ||
2035 queue->rekey_time).rel_value_us)) &&
2036 ((0 == queue->pwrite_off) &&
2037 (queue->cwrite_off + sizeof (struct TCPRekey) <= BUF_SIZE)))
2038 {
2040 }
2041 }
2042 if ((0 == queue->pwrite_off) && (! queue->finishing) &&
2043 (GNUNET_YES == queue->mq_awaits_continue))
2044 {
2045 queue->mq_awaits_continue = GNUNET_NO;
2047 }
2048 /* did we just finish writing 'finish'? */
2049 if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing))
2050 {
2052 "Finishing queue\n");
2054 return;
2055 }
2056 /* do we care to write more? */
2057 if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off))
2058 queue->write_task =
2060 queue->sock,
2061 &queue_write,
2062 queue);
2063}
2064
2065
2073static size_t
2075{
2076 const struct GNUNET_MessageHeader *hdr;
2077 const struct TCPConfirmationAck *tca;
2078 const struct TCPBox *box;
2079 const struct TCPRekey *rekey;
2080 const struct TCPFinish *fin;
2081 struct TCPRekey rekeyz;
2082 struct TCPFinish finz;
2083 struct GNUNET_ShortHashCode tmac;
2084 uint16_t type;
2085 size_t size = 0;
2086 struct TcpHandshakeAckSignature thas;
2087 const struct GNUNET_PeerIdentity *my_identity;
2088 const struct GNUNET_CRYPTO_ChallengeNonceP challenge = queue->challenge;
2089
2091 "try handle plaintext!\n");
2092
2093 hdr = (const struct GNUNET_MessageHeader *) queue->pread_buf;
2094 if ((sizeof(*hdr) > queue->pread_off))
2095 {
2097 "Handling plaintext, not even a header!\n");
2098 return 0; /* not even a header */
2099 }
2100
2101 if ((GNUNET_YES != queue->initial_core_kx_done) && (queue->unverified_size >
2103 {
2105 "Already received data of size %lu bigger than KX size %lu!\n",
2106 queue->unverified_size,
2108 GNUNET_break_op (0);
2110 return 0;
2111 }
2112
2113 type = ntohs (hdr->type);
2114 switch (type)
2115 {
2117 tca = (const struct TCPConfirmationAck *) queue->pread_buf;
2119 "start processing ack\n");
2120 if (sizeof(*tca) > queue->pread_off)
2121 {
2123 "Handling plaintext size of tca greater than pread offset.\n")
2124 ;
2125 return 0;
2126 }
2127 if (ntohs (hdr->size) != sizeof(*tca))
2128 {
2130 "Handling plaintext size does not match message type.\n");
2131 GNUNET_break_op (0);
2133 return 0;
2134 }
2135
2138
2139 thas.purpose.purpose = htonl (
2141 thas.purpose.size = htonl (sizeof(thas));
2142 thas.sender = tca->sender;
2143 thas.receiver = *my_identity;
2144 thas.monotonic_time = tca->monotonic_time;
2145 thas.challenge = tca->challenge;
2146
2149 &thas,
2150 &tca->sender_sig,
2151 &tca->sender.public_key))
2152 {
2154 "Verification of signature failed!\n");
2155 GNUNET_break (0);
2157 return 0;
2158 }
2159 if (0 != GNUNET_memcmp (&tca->challenge, &challenge))
2160 {
2162 "Challenge in TCPConfirmationAck not correct!\n");
2163 GNUNET_break (0);
2165 return 0;
2166 }
2167
2168 queue->handshake_ack_monotime_get = GNUNET_PEERSTORE_iteration_start (
2169 peerstore,
2170 "transport_tcp_communicator",
2171 &queue->target,
2174 queue);
2175
2177 "Handling plaintext, ack processed!\n");
2178
2180 {
2181 send_challenge (queue->challenge_received, queue);
2182 queue->write_task =
2184 queue->sock,
2185 &queue_write,
2186 queue);
2187 }
2188 else if (GNUNET_TRANSPORT_CS_OUTBOUND == queue->cs)
2189 {
2191 queue->address->sa_family,
2192 &queue->target);
2193 }
2194
2199 queue->initial_core_kx_done = GNUNET_YES;
2200
2201 {
2202 char *foreign_addr;
2203
2204 switch (queue->address->sa_family)
2205 {
2206 case AF_INET:
2207 GNUNET_asprintf (&foreign_addr,
2208 "%s-%s",
2210 GNUNET_a2s (queue->address, queue->address_len));
2211 break;
2212
2213 case AF_INET6:
2214 GNUNET_asprintf (&foreign_addr,
2215 "%s-%s",
2217 GNUNET_a2s (queue->address, queue->address_len));
2218 break;
2219
2220 default:
2221 GNUNET_assert (0);
2222 }
2224 &queue->target,
2225 foreign_addr,
2226 UINT16_MAX, /* no MTU */
2228 0, /* Priority */
2229 queue->nt,
2230 queue->cs,
2231 queue->mq);
2232
2233 GNUNET_free (foreign_addr);
2234 }
2235
2236 size = ntohs (hdr->size);
2237 break;
2239 /* Special case: header size excludes box itself! */
2240 box = (const struct TCPBox *) queue->pread_buf;
2241 if (ntohs (hdr->size) + sizeof(struct TCPBox) > queue->pread_off)
2242 return 0;
2243 calculate_hmac (&queue->in_hmac, &box[1], ntohs (hdr->size), &tmac);
2244 if (0 != memcmp (&tmac, &box->hmac, sizeof(tmac)))
2245 {
2246 GNUNET_break_op (0);
2248 return 0;
2249 }
2250 pass_plaintext_to_core (queue, (const void *) &box[1], ntohs (hdr->size));
2251 size = ntohs (hdr->size) + sizeof(*box);
2253 "Handling plaintext, box processed!\n");
2255 "# bytes decrypted with BOX",
2256 size,
2257 GNUNET_NO);
2259 "# messages decrypted with BOX",
2260 1,
2261 GNUNET_NO);
2262 break;
2263
2265 rekey = (const struct TCPRekey *) queue->pread_buf;
2266 if (sizeof(*rekey) > queue->pread_off)
2267 return 0;
2268 if (ntohs (hdr->size) != sizeof(*rekey))
2269 {
2270 GNUNET_break_op (0);
2272 return 0;
2273 }
2274 rekeyz = *rekey;
2275 memset (&rekeyz.hmac, 0, sizeof(rekeyz.hmac));
2276 calculate_hmac (&queue->in_hmac, &rekeyz, sizeof(rekeyz), &tmac);
2277 if (0 != memcmp (&tmac, &rekey->hmac, sizeof(tmac)))
2278 {
2279 GNUNET_break_op (0);
2281 return 0;
2282 }
2283 do_rekey (queue, rekey);
2284 size = ntohs (hdr->size);
2286 "Handling plaintext, rekey processed!\n");
2288 "# rekeying successful",
2289 1,
2290 GNUNET_NO);
2291 break;
2292
2294 fin = (const struct TCPFinish *) queue->pread_buf;
2295 if (sizeof(*fin) > queue->pread_off)
2296 return 0;
2297 if (ntohs (hdr->size) != sizeof(*fin))
2298 {
2299 GNUNET_break_op (0);
2301 return 0;
2302 }
2303 finz = *fin;
2304 memset (&finz.hmac, 0, sizeof(finz.hmac));
2305 calculate_hmac (&queue->in_hmac, &finz, sizeof(finz), &tmac);
2306 if (0 != memcmp (&tmac, &fin->hmac, sizeof(tmac)))
2307 {
2308 GNUNET_break_op (0);
2310 return 0;
2311 }
2312 /* handle FINISH by destroying queue */
2314 "Handling plaintext, finish processed!\n");
2316 /* NOTE: must return here rather than `break'. #queue_destroy() releases
2317 @a queue outright once its backpressure has drained, so neither the
2318 @e unverified_size accounting below nor #queue_read()'s loop may look
2319 at it again. Falling through also hit `GNUNET_assert (0 != size)'
2320 with @a size still zero -- receiving a perfectly ordinary FINISH thus
2321 aborted the communicator, taking every other queue down with it. */
2322 return TCP_QUEUE_GONE;
2323
2324 default:
2326 "Handling plaintext, nothing processed!\n");
2327 GNUNET_break_op (0);
2329 return 0;
2330 }
2331 GNUNET_assert (0 != size);
2332 if (-1 != queue->unverified_size)
2333 queue->unverified_size += size;
2334 return size;
2335}
2336
2337
2343static void
2344queue_read (void *cls)
2345{
2346 struct Queue *queue = cls;
2347 struct GNUNET_TIME_Relative left;
2348 ssize_t rcvd;
2349
2350 queue->read_task = NULL;
2351 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2352 &queue->cread_buf[queue->cread_off],
2353 BUF_SIZE - queue->cread_off);
2355 "Received %zd bytes from TCP queue\n", rcvd);
2356 if (-1 == rcvd)
2357 {
2358 if ((EAGAIN != errno) && (EINTR != errno))
2359 {
2362 return;
2363 }
2364 /* try again */
2365 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2366 if (0 != left.rel_value_us)
2367 {
2368 queue->read_task =
2370 return;
2371 }
2373 "Queue %p was idle for %s, disconnecting\n",
2374 queue,
2377 GNUNET_YES));
2379 return;
2380 }
2381 if (0 == rcvd)
2382 {
2383 /* Orderly shutdown of connection */
2385 "Socket for queue %p seems to have been closed\n", queue);
2387 return;
2388 }
2389 queue->timeout =
2391 queue->cread_off += rcvd;
2392 while ((queue->pread_off < sizeof(queue->pread_buf)) &&
2393 (queue->cread_off > 0))
2394 {
2395 size_t max = GNUNET_MIN (sizeof(queue->pread_buf) - queue->pread_off,
2396 queue->cread_off);
2397 size_t done;
2398 size_t total;
2399 size_t old_pread_off = queue->pread_off;
2400
2401 GNUNET_assert (0 ==
2402 gcry_cipher_decrypt (queue->in_cipher,
2403 &queue->pread_buf[queue->pread_off],
2404 max,
2405 queue->cread_buf,
2406 max));
2407 queue->pread_off += max;
2408 total = 0;
2409 while (0 != (done = try_handle_plaintext (queue)))
2410 {
2411 if (TCP_QUEUE_GONE == done)
2412 return; /* @a queue was destroyed under us, do not touch it */
2413 /* 'done' bytes of plaintext were used, shift buffer */
2414 GNUNET_assert (done <= queue->pread_off);
2415 /* NOTE: this memmove() could possibly sometimes be
2416 avoided if we pass 'total' into try_handle_plaintext()
2417 and use it at an offset into the buffer there! */
2418 memmove (queue->pread_buf,
2419 &queue->pread_buf[done],
2420 queue->pread_off - done);
2421 queue->pread_off -= done;
2422 total += done;
2423 /* The last plaintext was a rekey, abort for now */
2424 if (GNUNET_YES == queue->rekeyed)
2425 break;
2426 }
2427 /* when we encounter a rekey message, the decryption above uses the
2428 wrong key for everything after the rekey; in that case, we have
2429 to re-do the decryption at 'total' instead of at 'max'.
2430 However, we have to take into account that the plaintext buffer may have
2431 already contained data and not jumped too far ahead in the ciphertext.
2432 If there is no rekey and the last message is incomplete (max > total),
2433 it is safe to keep the decryption so we shift by 'max' */
2434 if (GNUNET_YES == queue->rekeyed)
2435 {
2436 max = total - old_pread_off;
2437 queue->rekeyed = GNUNET_NO;
2438 queue->pread_off = 0;
2439 }
2440 memmove (queue->cread_buf, &queue->cread_buf[max], queue->cread_off - max);
2441 queue->cread_off -= max;
2442 }
2443 if (BUF_SIZE == queue->cread_off)
2444 return; /* buffer full, suspend reading */
2445 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2446 if (0 != left.rel_value_us)
2447 {
2448 if (max_queue_length > queue->backpressure)
2449 {
2450 /* continue reading */
2451 queue->read_task =
2453 }
2454 return;
2455 }
2457 "Queue %p was idle for %s, disconnecting\n",
2458 queue,
2461 GNUNET_YES));
2463}
2464
2465
2473static struct sockaddr *
2474tcp_address_to_sockaddr_numeric_v6 (socklen_t *sock_len,
2475 struct sockaddr_in6 v6,
2476 unsigned int port)
2477{
2478 struct sockaddr *in;
2479
2480 v6.sin6_family = AF_INET6;
2481 v6.sin6_port = htons ((uint16_t) port);
2482#if HAVE_SOCKADDR_IN_SIN_LEN
2483 v6.sin6_len = sizeof(struct sockaddr_in6);
2484#endif
2485 v6.sin6_flowinfo = 0;
2486 v6.sin6_scope_id = 0;
2487 in = GNUNET_memdup (&v6, sizeof(v6));
2488 *sock_len = sizeof(struct sockaddr_in6);
2489
2490 return in;
2491}
2492
2493
2501static struct sockaddr *
2502tcp_address_to_sockaddr_numeric_v4 (socklen_t *sock_len,
2503 struct sockaddr_in v4,
2504 unsigned int port)
2505{
2506 struct sockaddr *in;
2507
2508 v4.sin_family = AF_INET;
2509 v4.sin_port = htons ((uint16_t) port);
2510#if HAVE_SOCKADDR_IN_SIN_LEN
2511 v4.sin_len = sizeof(struct sockaddr_in);
2512#endif
2513 in = GNUNET_memdup (&v4, sizeof(v4));
2514 *sock_len = sizeof(struct sockaddr_in);
2515 return in;
2516}
2517
2518
2525static struct PortOnlyIpv4Ipv6 *
2526tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port)
2527{
2528 struct PortOnlyIpv4Ipv6 *po;
2529 struct sockaddr_in *i4;
2530 struct sockaddr_in6 *i6;
2531 socklen_t sock_len_ipv4;
2532 socklen_t sock_len_ipv6;
2533
2534 /* interpreting value as just a PORT number */
2535 if (*port > UINT16_MAX)
2536 {
2538 "BINDTO specification `%s' invalid: value too large for port\n",
2539 bindto);
2540 return NULL;
2541 }
2542
2543 po = GNUNET_new (struct PortOnlyIpv4Ipv6);
2544
2545 if (GNUNET_YES == disable_v6)
2546 {
2547 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2548 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2549 *port);
2550 po->addr_len_ipv4 = sock_len_ipv4;
2551 }
2552 else
2553 {
2554
2555 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2556 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2557 *port);
2558 po->addr_len_ipv4 = sock_len_ipv4;
2559
2560 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
2561 po->addr_ipv6 = tcp_address_to_sockaddr_numeric_v6 (&sock_len_ipv6, *i6,
2562 *port);
2563
2564 po->addr_len_ipv6 = sock_len_ipv6;
2565
2566 GNUNET_free (i6);
2567 }
2568
2569 GNUNET_free (i4);
2570
2571 return po;
2572}
2573
2574
2581static char *
2582extract_address (const char *bindto)
2583{
2584 char *addr;
2585 char *start;
2586 char *token;
2587 char *cp;
2588 char *rest = NULL;
2589
2591 "extract address with bindto %s\n",
2592 bindto);
2593
2594 if (NULL == bindto)
2596 "bindto is NULL\n");
2597
2598 cp = GNUNET_strdup (bindto);
2599
2601 "extract address 2\n");
2602
2603 start = cp;
2604 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
2605 {
2606 start++; /* skip over '['*/
2607 cp[strlen (cp) - 1] = '\0'; /* eat ']'*/
2608 addr = GNUNET_strdup (start);
2609 }
2610 else
2611 {
2612 token = strtok_r (cp, "]", &rest);
2613 if (strlen (bindto) == strlen (token))
2614 {
2615 token = strtok_r (cp, ":", &rest);
2616 addr = GNUNET_strdup (token);
2617 }
2618 else
2619 {
2620 token++;
2621 addr = GNUNET_strdup (token);
2622 }
2623 }
2624
2626 "tcp address: %s\n",
2627 addr);
2628 GNUNET_free (cp);
2629 return addr;
2630}
2631
2632
2639static unsigned int
2640extract_port (const char *addr_and_port)
2641{
2642 unsigned int port;
2643 char dummy[2];
2644 char *token;
2645 char *addr;
2646 char *colon;
2647 char *cp;
2648 char *rest = NULL;
2649
2650 if (NULL != addr_and_port)
2651 {
2652 cp = GNUNET_strdup (addr_and_port);
2653 token = strtok_r (cp, "]", &rest);
2654 if (strlen (addr_and_port) == strlen (token))
2655 {
2656 colon = strrchr (cp, ':');
2657 if (NULL == colon)
2658 {
2659 GNUNET_free (cp);
2660 return 0;
2661 }
2662 addr = colon;
2663 addr++;
2664 }
2665 else
2666 {
2667 token = strtok_r (NULL, "]", &rest);
2668 if (NULL == token)
2669 {
2670 GNUNET_free (cp);
2671 return 0;
2672 }
2673 else
2674 {
2675 addr = token;
2676 addr++;
2677 }
2678 }
2679
2680
2681 if (1 == sscanf (addr, "%u%1s", &port, dummy))
2682 {
2683 /* interpreting value as just a PORT number */
2684 if (port > UINT16_MAX)
2685 {
2687 "Port `%u' invalid: value too large for port\n",
2688 port);
2689 GNUNET_free (cp);
2690 return 0;
2691 }
2692 }
2693 else
2694 {
2696 "BINDTO specification invalid: last ':' not followed by number\n");
2697 GNUNET_free (cp);
2698 return 0;
2699 }
2700 GNUNET_free (cp);
2701 }
2702 else
2703 {
2705 "return 0\n");
2706 /* interpret missing port as 0, aka pick any free one */
2707 port = 0;
2708 }
2709
2710 return port;
2711}
2712
2713
2721static struct sockaddr *
2722tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
2723{
2724 struct sockaddr *in;
2725 unsigned int port;
2726 struct sockaddr_in v4;
2727 struct sockaddr_in6 v6;
2728 char *start;
2729
2730 memset (&v4, 0, sizeof(v4));
2731 start = extract_address (bindto);
2732 GNUNET_assert (NULL != start);
2734 "start %s\n",
2735 start);
2736
2738 "!bindto %s\n",
2739 bindto);
2740
2741
2742 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
2743 {
2744 port = extract_port (bindto);
2745
2747 "port %u\n",
2748 port);
2749
2750 in = tcp_address_to_sockaddr_numeric_v4 (sock_len, v4, port);
2751 }
2752 else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
2753 {
2754 port = extract_port (bindto);
2755 in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port);
2756 }
2757 else
2758 {
2759 GNUNET_assert (0);
2760 }
2761
2763 return in;
2764}
2765
2766
2775static void
2776mq_send (struct GNUNET_MQ_Handle *mq,
2777 const struct GNUNET_MessageHeader *msg,
2778 void *impl_state)
2779{
2780 struct Queue *queue = impl_state;
2781 uint16_t msize = ntohs (msg->size);
2782 struct TCPBox box;
2784 "In MQ send. Queue finishing: %s; write task running: %s\n",
2785 (GNUNET_YES == queue->finishing) ? "yes" : "no",
2786 (NULL == queue->write_task) ? "yes" : "no");
2787 GNUNET_assert (mq == queue->mq);
2788 queue->mq_awaits_continue = GNUNET_YES;
2789 if (GNUNET_YES == queue->finishing)
2790 return; /* this queue is dying, drop msg */
2791 GNUNET_assert (0 == queue->pwrite_off);
2792 box.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX);
2793 box.header.size = htons (msize);
2794 calculate_hmac (&queue->out_hmac, msg, msize, &box.hmac);
2795 memcpy (&queue->pwrite_buf[queue->pwrite_off], &box, sizeof(box));
2796 queue->pwrite_off += sizeof(box);
2797 memcpy (&queue->pwrite_buf[queue->pwrite_off], msg, msize);
2798 queue->pwrite_off += msize;
2800 "%lu bytes of plaintext to send\n", queue->pwrite_off);
2801 GNUNET_assert (NULL != queue->sock);
2802 if (NULL == queue->write_task)
2803 queue->write_task =
2805 queue->sock,
2806 &queue_write,
2807 queue);
2808}
2809
2810
2819static void
2820mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state)
2821{
2822 struct Queue *queue = impl_state;
2823
2824 if (mq == queue->mq)
2825 {
2826 queue->mq = NULL;
2828 }
2829}
2830
2831
2838static void
2839mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
2840{
2841 struct Queue *queue = impl_state;
2842
2843 GNUNET_assert (0 != queue->pwrite_off);
2844 queue->pwrite_off = 0;
2845}
2846
2847
2857static void
2858mq_error (void *cls, enum GNUNET_MQ_Error error)
2859{
2860 struct Queue *queue = cls;
2861
2863 "MQ error in queue to %s: %d\n",
2864 GNUNET_i2s (&queue->target),
2865 (int) error);
2867}
2868
2869
2877static void
2878boot_queue (struct Queue *queue)
2879{
2880 queue->nt =
2881 GNUNET_NT_scanner_get_type (is, queue->address, queue->address_len);
2883 queue_map,
2884 &queue->key,
2885 queue,
2888 "# queues active",
2890 GNUNET_NO);
2891 queue->timeout =
2894 &mq_destroy,
2895 &mq_cancel,
2896 queue,
2897 NULL,
2898 &mq_error,
2899 queue);
2900}
2901
2902
2913static void
2914transmit_kx (struct Queue *queue,
2915 const struct GNUNET_CRYPTO_HpkeEncapsulation *c)
2916{
2917 const struct GNUNET_PeerIdentity *my_identity;
2919 struct TcpHandshakeSignature ths;
2920 struct TCPConfirmation tc;
2921
2925
2926 memcpy (queue->cwrite_buf, c, sizeof(*c));
2927 queue->cwrite_off = sizeof(*c);
2928 /* compute 'tc' and append in encrypted format to cwrite_buf */
2929 tc.sender = *my_identity;
2930 tc.monotonic_time =
2932 GNUNET_CRYPTO_random_block (&tc.challenge,
2933 sizeof(tc.challenge));
2934 ths.purpose.purpose = htonl (
2936 ths.purpose.size = htonl (sizeof(ths));
2937 ths.sender = *my_identity;
2938 ths.receiver = queue->target;
2939 ths.ephemeral = *c;
2940 ths.monotonic_time = tc.monotonic_time;
2941 ths.challenge = tc.challenge;
2943 &ths,
2944 &tc.sender_sig);
2945 GNUNET_assert (0 ==
2946 gcry_cipher_encrypt (queue->out_cipher,
2947 &queue->cwrite_buf[queue->cwrite_off],
2948 sizeof(tc),
2949 &tc,
2950 sizeof(tc)));
2951 queue->challenge = tc.challenge;
2952 queue->cwrite_off += sizeof(tc);
2953
2955 "handshake written\n");
2956}
2957
2958
2966static void
2968{
2970 struct GNUNET_ShortHashCode k;
2971
2973 &c, &k);
2974 setup_out_cipher (queue, &k);
2975 transmit_kx (queue, &c);
2976}
2977
2978
2984static void
2985handshake_monotime_store_cb (void *cls, int success)
2986{
2987 struct Queue *queue = cls;
2988 if (GNUNET_OK != success)
2989 {
2991 "Failed to store handshake monotonic time in PEERSTORE!\n");
2992 }
2993 queue->handshake_monotime_sc = NULL;
2994 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
2995}
2996
2997
3005static void
3006handshake_monotime_cb (void *cls,
3007 const struct GNUNET_PEERSTORE_Record *record,
3008 const char *emsg)
3009{
3010 struct Queue *queue = cls;
3011 struct GNUNET_TIME_AbsoluteNBO *mtbe;
3012 struct GNUNET_TIME_Absolute mt;
3013 const struct GNUNET_PeerIdentity *pid;
3014 struct GNUNET_TIME_AbsoluteNBO *handshake_monotonic_time;
3015
3016 (void) emsg;
3017
3018 handshake_monotonic_time = &queue->handshake_monotonic_time;
3019 pid = &queue->target;
3021 "tcp handshake with us %s\n",
3023 if (NULL == record)
3024 {
3025 queue->handshake_monotime_get = NULL;
3026 return;
3027 }
3029 "tcp handshake from peer %s\n",
3030 GNUNET_i2s (pid));
3031 if (sizeof(*mtbe) != record->value_size)
3032 {
3033 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
3034 GNUNET_break (0);
3035 return;
3036 }
3037 mtbe = record->value;
3038 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
3039 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
3040 queue->handshake_monotonic_time).abs_value_us)
3041 {
3043 "Queue from %s dropped, handshake monotime in the past\n",
3044 GNUNET_i2s (&queue->target));
3045 GNUNET_break (0);
3046 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
3047 queue->handshake_ack_monotime_get = NULL;
3049 return;
3050 }
3051 queue->handshake_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
3052 "transport_tcp_communicator",
3053 pid,
3055 handshake_monotonic_time,
3056 sizeof(*
3057 handshake_monotonic_time),
3060 &
3062 queue);
3063}
3064
3065
3077static int
3079 struct TCPConfirmation *tc,
3080 char *ibuf)
3081{
3082 const struct GNUNET_PeerIdentity *my_identity;
3083 struct TcpHandshakeSignature ths;
3085
3088
3090 0 ==
3091 gcry_cipher_decrypt (queue->in_cipher,
3092 tc,
3093 sizeof(*tc),
3094 &ibuf[sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)],
3095 sizeof(*tc)));
3096 ths.purpose.purpose = htonl (
3098 ths.purpose.size = htonl (sizeof(ths));
3099 ths.sender = tc->sender;
3100 ths.receiver = *my_identity;
3101 memcpy (&ths.ephemeral, ibuf, sizeof(struct GNUNET_CRYPTO_EcdhePublicKey));
3102 ths.monotonic_time = tc->monotonic_time;
3103 ths.challenge = tc->challenge;
3106 &ths,
3107 &tc->sender_sig,
3108 &tc->sender.public_key);
3109 if (GNUNET_YES == ret)
3110 queue->handshake_monotime_get =
3112 "transport_tcp_communicator",
3113 &queue->target,
3116 queue);
3117 return ret;
3118}
3119
3120
3128static void
3129queue_read_kx (void *cls)
3130{
3131 struct Queue *queue = cls;
3132 ssize_t rcvd;
3133 struct GNUNET_TIME_Relative left;
3134 struct TCPConfirmation tc;
3135
3136 queue->read_task = NULL;
3137 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
3138 if (0 == left.rel_value_us)
3139 {
3141 return;
3142 }
3143 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
3144 &queue->cread_buf[queue->cread_off],
3145 BUF_SIZE - queue->cread_off);
3147 "Received %lu bytes to write in buffer of size %lu for KX from queue %p (expires in %"
3148 PRIu64 ")\n",
3149 rcvd, BUF_SIZE - queue->cread_off, queue, left.rel_value_us);
3150 if (-1 == rcvd)
3151 {
3152 if ((EAGAIN != errno) && (EINTR != errno))
3153 {
3156 return;
3157 }
3158 queue->read_task =
3160 return;
3161 }
3162 if (0 == rcvd)
3163 {
3164 /* Orderly shutdown of connection */
3166 "Socket for queue %p seems to have been closed\n", queue);
3168 return;
3169 }
3170 queue->cread_off += rcvd;
3171 if (queue->cread_off < INITIAL_KX_SIZE)
3172 {
3173 /* read more */
3175 "%lu/%lu bytes of KX read. Rescheduling...\n",
3176 queue->cread_off, INITIAL_KX_SIZE);
3177 queue->read_task =
3179 return;
3180 }
3181 /* we got all the data, let's find out who we are talking to! */
3183 (const struct GNUNET_CRYPTO_HpkeEncapsulation*)
3184 queue->cread_buf,
3185 queue);
3186 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
3187 {
3189 "Invalid TCP KX received from %s\n",
3190 GNUNET_a2s (queue->address, queue->address_len));
3192 return;
3193 }
3194 if (0 !=
3195 memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
3196 {
3198 "Invalid sender in TCP KX received from %s\n",
3199 GNUNET_a2s (queue->address, queue->address_len));
3201 return;
3202 }
3203 send_challenge (tc.challenge, queue);
3204 queue->write_task =
3206 queue->sock,
3207 &queue_write,
3208 queue);
3209
3210 /* update queue timeout */
3211 queue->timeout =
3213 /* prepare to continue with regular read task immediately */
3214 memmove (queue->cread_buf,
3215 &queue->cread_buf[INITIAL_KX_SIZE],
3216 queue->cread_off - (INITIAL_KX_SIZE));
3218 "cread_off is %lu bytes before adjusting\n",
3219 queue->cread_off);
3220 queue->cread_off -= INITIAL_KX_SIZE;
3222 "cread_off set to %lu bytes\n",
3223 queue->cread_off);
3225}
3226
3227
3234static void
3235proto_read_kx (void *cls)
3236{
3237 struct ProtoQueue *pq = cls;
3238 ssize_t rcvd;
3239 struct GNUNET_TIME_Relative left;
3240 struct Queue *queue;
3241 struct TCPConfirmation tc;
3243
3244 pq->read_task = NULL;
3246 if (0 == left.rel_value_us)
3247 {
3248 free_proto_queue (pq);
3249 return;
3250 }
3251 rcvd = GNUNET_NETWORK_socket_recv (pq->sock,
3252 &pq->ibuf[pq->ibuf_off],
3253 sizeof(pq->ibuf) - pq->ibuf_off);
3255 "Proto received %lu bytes for KX\n", rcvd);
3256 if (-1 == rcvd)
3257 {
3258 if ((EAGAIN != errno) && (EINTR != errno))
3259 {
3261 free_proto_queue (pq);
3262 return;
3263 }
3264 /* try again */
3265 pq->read_task =
3267 return;
3268 }
3269 if (0 == rcvd)
3270 {
3271 /* Orderly shutdown of connection */
3273 "Socket for proto queue %p seems to have been closed\n", pq);
3274 free_proto_queue (pq);
3275 return;
3276 }
3277 pq->ibuf_off += rcvd;
3278 if (sizeof (struct TCPNATProbeMessage) == pq->ibuf_off)
3279 {
3280 struct TCPNATProbeMessage *pm = (struct TCPNATProbeMessage *) pq->ibuf;
3281
3283 &pm->clientIdentity);
3284
3285 queue = GNUNET_new (struct Queue);
3286 queue->target = pm->clientIdentity;
3287 eddsa_pub_to_hpke_key (&queue->target.public_key,
3288 &queue->target_hpke_key);
3291 }
3292 else if (pq->ibuf_off < sizeof(pq->ibuf))
3293 {
3294 /* read more */
3295 pq->read_task =
3297 return;
3298 }
3299 else
3300 {
3301 /* we got all the data, let's find out who we are talking to! */
3302 queue = GNUNET_new (struct Queue);
3304 (const struct GNUNET_CRYPTO_HpkeEncapsulation *) pq->
3305 ibuf,
3306 queue);
3307 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
3308 {
3310 "Invalid TCP KX received from %s\n",
3311 GNUNET_a2s (pq->address, pq->address_len));
3312 gcry_cipher_close (queue->in_cipher);
3314 free_proto_queue (pq);
3315 return;
3316 }
3317 queue->target = tc.sender;
3318 eddsa_pub_to_hpke_key (&queue->target.public_key,
3319 &queue->target_hpke_key);
3322 }
3323 queue->address = pq->address; /* steals reference */
3324 queue->address_len = pq->address_len;
3325 queue->listen_sock = pq->listen_sock;
3326 queue->sock = pq->sock;
3327
3329 "created queue with target %s\n",
3330 GNUNET_i2s (&queue->target));
3331
3333 "start kx proto\n");
3334
3336 boot_queue (queue);
3337 queue->read_task =
3339 queue->sock,
3340 read_task,
3341 queue);
3342 queue->write_task =
3344 queue->sock,
3345 &queue_write,
3346 queue);
3347 // TODO To early! Move it somewhere else.
3348 // send_challenge (tc.challenge, queue);
3349 queue->challenge_received = tc.challenge;
3350
3352 GNUNET_free (pq);
3353}
3354
3355
3356static struct ProtoQueue *
3358 struct sockaddr *in,
3359 socklen_t addrlen)
3360{
3361 struct ProtoQueue *pq = GNUNET_new (struct ProtoQueue);
3362
3363 if (NULL == sock)
3364 {
3365 // sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
3366 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 0);
3367 if (NULL == sock)
3368 {
3370 "socket(%d) failed: %s",
3371 in->sa_family,
3372 strerror (errno));
3373 GNUNET_free (in);
3374 GNUNET_free (pq);
3375 return NULL;
3376 }
3377 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, addrlen)) &&
3378 (errno != EINPROGRESS))
3379 {
3381 "connect to `%s' failed: %s",
3382 GNUNET_a2s (in, addrlen),
3383 strerror (errno));
3385 GNUNET_free (in);
3386 GNUNET_free (pq);
3387 return NULL;
3388 }
3389 }
3390 pq->address_len = addrlen;
3391 pq->address = in;
3393 pq->sock = sock;
3395 pq->sock,
3397 pq);
3399
3400 return pq;
3401}
3402
3403
3411static void
3412listen_cb (void *cls)
3413{
3414 struct sockaddr_storage in;
3415 socklen_t addrlen;
3416 struct GNUNET_NETWORK_Handle *sock;
3417 struct ListenTask *lt;
3418 struct sockaddr *in_addr;
3419
3421 "listen_cb\n");
3422
3423 lt = cls;
3424
3425 lt->listen_task = NULL;
3426 GNUNET_assert (NULL != lt->listen_sock);
3427 addrlen = sizeof(in);
3428 memset (&in, 0, sizeof(in));
3430 (struct sockaddr*) &in,
3431 &addrlen);
3432 if ((NULL == sock) && ((EMFILE == errno) || (ENFILE == errno)))
3433 return; /* system limit reached, wait until connection goes down */
3435 lt->listen_sock,
3436 &listen_cb,
3437 lt);
3438 if ((NULL == sock) && ((EAGAIN == errno) || (ENOBUFS == errno)))
3439 return;
3440 if (NULL == sock)
3441 {
3443 return;
3444 }
3445 in_addr = GNUNET_memdup (&in, addrlen);
3446 create_proto_queue (sock, in_addr, addrlen);
3447}
3448
3449
3450static void
3451try_connection_reversal (void *cls,
3452 const struct sockaddr *addr,
3453 socklen_t addrlen)
3454{
3455 const struct GNUNET_PeerIdentity *my_identity;
3456 struct TCPNATProbeMessage pm;
3457 struct ProtoQueue *pq;
3458 struct sockaddr *in_addr;
3459 (void) cls;
3460
3463
3465 "addr->sa_family %d\n",
3466 addr->sa_family);
3468 "Try to connect back\n");
3469 in_addr = GNUNET_memdup (addr, addrlen);
3471 "in_addr->sa_family %d\n",
3472 in_addr->sa_family);
3473 pq = create_proto_queue (NULL, in_addr, addrlen);
3474 if (NULL != pq)
3475 {
3476 pm.header.size = htons (sizeof(struct TCPNATProbeMessage));
3477 pm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
3478 pm.clientIdentity = *my_identity;
3479 memcpy (pq->write_buf, &pm, sizeof(struct TCPNATProbeMessage));
3480 pq->write_off = sizeof(struct TCPNATProbeMessage);
3482 pq->sock,
3484 pq);
3485 }
3486 else
3487 {
3489 "Couldn't create ProtoQueue for sending TCPNATProbeMessage\n");
3490 }
3491}
3492
3493
3494static void
3495pending_reversal_timeout (void *cls)
3496{
3497 struct PendingReversal *pending_reversal = cls;
3498 struct GNUNET_HashCode key;
3499
3500 pending_reversal->timeout_task = NULL;
3501 pending_reversal_key (pending_reversal->in,
3502 &pending_reversal->target,
3503 &key);
3505 &key,
3506 pending_reversal))
3508 "No pending reversal found for address %s\n",
3509 GNUNET_a2s (pending_reversal->in,
3510 sizeof (struct sockaddr)));
3511 GNUNET_free (pending_reversal->in);
3512 GNUNET_free (pending_reversal);
3513}
3514
3515
3534static int
3535mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
3536{
3537 struct sockaddr *in;
3538 socklen_t in_len = 0;
3539 const char *path;
3540 struct sockaddr_in *v4;
3541 struct sockaddr_in6 *v6;
3542 unsigned int is_natd = GNUNET_NO;
3543 struct GNUNET_HashCode key;
3544 struct GNUNET_HashCode queue_map_key;
3545 struct GNUNET_HashContext *hsh;
3546 struct Queue *queue;
3547
3549 "Connecting to %s at %s\n",
3550 GNUNET_i2s (peer),
3551 address);
3552 if (0 != strncmp (address,
3554 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
3555 {
3556 GNUNET_break_op (0);
3557 return GNUNET_SYSERR;
3558 }
3559 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
3560 in = tcp_address_to_sockaddr (path, &in_len);
3561
3562 if (NULL == in)
3563 {
3565 "Failed to setup TCP socket address\n");
3566 return GNUNET_SYSERR;
3567 }
3568
3570 "in %s\n",
3571 GNUNET_a2s (in, in_len));
3572
3573 if (AF_INET6 == in->sa_family)
3574 {
3575 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *) in;
3576
3577 /* A link-local address is only meaningful together with the interface
3578 it was learned on, and that scope does not survive being carried to
3579 another host in a HELLO. connect() to one with a zero scope id fails
3580 with EINVAL every single time, so trying is pure noise: peers gossip
3581 these by the dozen and each attempt logged a WARNING. */
3582 if (IN6_IS_ADDR_LINKLOCAL (&v6->sin6_addr) && (0 == v6->sin6_scope_id))
3583 {
3585 "Skipping unusable link-local address `%s' for `%s'\n",
3586 address,
3587 GNUNET_i2s (peer));
3588 GNUNET_free (in);
3589 return GNUNET_SYSERR;
3590 }
3591 }
3592
3595 GNUNET_CRYPTO_hash_context_read (hsh, peer, sizeof (*peer));
3596 GNUNET_CRYPTO_hash_context_finish (hsh, &queue_map_key);
3598
3599 if (NULL != queue)
3600 {
3602 "Queue for %s already exists or is in construction\n", address);
3603 GNUNET_free (in);
3604 return GNUNET_NO;
3605 }
3606 switch (in->sa_family)
3607 {
3608 case AF_INET:
3609 v4 = (struct sockaddr_in *) in;
3610 if (0 == v4->sin_port)
3611 {
3612 is_natd = GNUNET_YES;
3613 pending_reversal_key (in, peer, &key);
3616 &key))
3617 {
3619 "There is already a request reversal for `%s' at `%s'\n",
3620 GNUNET_i2s (peer),
3621 address);
3622 GNUNET_free (in);
3623 return GNUNET_SYSERR;
3624 }
3625 }
3626 break;
3627
3628 case AF_INET6:
3629 if (GNUNET_YES == disable_v6)
3630 {
3632 "IPv6 disabled, skipping %s\n", address);
3633 GNUNET_free (in);
3634 return GNUNET_SYSERR;
3635 }
3636 v6 = (struct sockaddr_in6 *) in;
3637 if (0 == v6->sin6_port)
3638 {
3640 "Request reversal for `%s' at `%s' not possible for an IPv6 address\n",
3641 GNUNET_i2s (peer),
3642 address);
3643 GNUNET_free (in);
3644 return GNUNET_SYSERR;
3645 }
3646 break;
3647
3648 default:
3649 GNUNET_assert (0);
3650 }
3651
3652 if (GNUNET_YES == is_natd)
3653 {
3654 struct sockaddr_in local_sa;
3655 struct PendingReversal *pending_reversal;
3656
3657 memset (&local_sa, 0, sizeof(local_sa));
3658 local_sa.sin_family = AF_INET;
3659 local_sa.sin_port = htons (bind_port);
3660 /* We leave sin_address at 0, let the kernel figure it out,
3661 even if our bind() is more specific. (May want to reconsider
3662 later.) */
3663 if (GNUNET_OK != GNUNET_NAT_request_reversal (nat, &local_sa, v4))
3664 {
3666 "request reversal for `%s' at `%s' failed\n",
3667 GNUNET_i2s (peer),
3668 address);
3669 GNUNET_free (in);
3670 return GNUNET_SYSERR;
3671 }
3672 pending_reversal = GNUNET_new (struct PendingReversal);
3673 pending_reversal->in = in;
3676 &key,
3677 pending_reversal,
3679 pending_reversal->target = *peer;
3680 pending_reversal->timeout_task = GNUNET_SCHEDULER_add_delayed (
3683 pending_reversal);
3685 "Created NAT WAIT connection to `%s' at `%s'\n",
3686 GNUNET_i2s (peer),
3687 GNUNET_a2s (in, sizeof (struct sockaddr)));
3688 }
3689 else
3690 {
3691 struct GNUNET_NETWORK_Handle *sock;
3692
3693 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM,
3694 IPPROTO_TCP);
3695 if (NULL == sock)
3696 {
3698 "socket(%d) failed: %s",
3699 in->sa_family,
3700 strerror (errno));
3701 GNUNET_free (in);
3702 return GNUNET_SYSERR;
3703 }
3704 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
3705 (errno != EINPROGRESS))
3706 {
3708 "connect to `%s' failed: %s",
3709 address,
3710 strerror (errno));
3712 GNUNET_free (in);
3713 return GNUNET_SYSERR;
3714 }
3715
3716 queue = GNUNET_new (struct Queue);
3717 queue->target = *peer;
3718 eddsa_pub_to_hpke_key (&queue->target.public_key, &queue->target_hpke_key);
3719 queue->key = queue_map_key;
3720 queue->address = in;
3721 queue->address_len = in_len;
3722 queue->sock = sock;
3724 boot_queue (queue);
3726 "booted queue with target %s\n",
3727 GNUNET_i2s (&queue->target));
3728 // queue->mq_awaits_continue = GNUNET_YES;
3729 queue->read_task =
3731 queue->sock,
3733 queue);
3734
3735
3737 "start kx mq_init\n");
3738
3740 queue->write_task =
3742 queue->sock,
3743 &queue_write,
3744 queue);
3745 }
3746
3747 return GNUNET_OK;
3748}
3749
3750
3759static int
3760get_lt_delete_it (void *cls,
3761 const struct GNUNET_HashCode *key,
3762 void *value)
3763{
3764 struct ListenTask *lt = value;
3765
3766 (void) cls;
3767 (void) key;
3768 if (NULL != lt->listen_task)
3769 {
3771 lt->listen_task = NULL;
3772 }
3773 if (NULL != lt->listen_sock)
3774 {
3776 lt->listen_sock = NULL;
3777 }
3778 GNUNET_free (lt);
3779 return GNUNET_OK;
3780}
3781
3782
3791static int
3792get_queue_delete_it (void *cls,
3793 const struct GNUNET_HashCode *target,
3794 void *value)
3795{
3796 struct Queue *queue = value;
3797
3798 (void) cls;
3799 (void) target;
3801 return GNUNET_OK;
3802}
3803
3804
3810static void
3811do_shutdown (void *cls)
3812{
3814 "Shutdown %s!\n",
3815 shutdown_running ? "running" : "not running");
3816
3818 return;
3819 else
3821
3822 while (NULL != proto_head)
3824 if (NULL != nat)
3825 {
3827 nat = NULL;
3828 }
3836 if (NULL != ch)
3837 {
3840 ch = NULL;
3841 }
3842 if (NULL != stats)
3843 {
3845 stats = NULL;
3846 }
3847 if (NULL != is)
3848 {
3850 is = NULL;
3851 }
3852 if (NULL != pils)
3853 {
3855 pils = NULL;
3856 }
3857 if (NULL != key_ring)
3858 {
3860 key_ring = NULL;
3861 }
3862 if (NULL != peerstore)
3863 {
3865 peerstore = NULL;
3866 }
3867 if (NULL != resolve_request_handle)
3868 {
3871 }
3873 "Shutdown done!\n");
3874}
3875
3876
3888static void
3889enc_notify_cb (void *cls,
3890 const struct GNUNET_PeerIdentity *sender,
3891 const struct GNUNET_MessageHeader *msg)
3892{
3893 (void) cls;
3894 (void) sender;
3895 (void) msg;
3896 GNUNET_break_op (0);
3897}
3898
3899
3913static void
3914nat_address_cb (void *cls,
3915 void **app_ctx,
3916 int add_remove,
3918 const struct sockaddr *addr,
3919 socklen_t addrlen)
3920{
3921 char *my_addr;
3923
3925 "nat address cb %s %s\n",
3926 add_remove ? "add" : "remove",
3927 GNUNET_a2s (addr, addrlen));
3928
3929 if (GNUNET_YES == add_remove)
3930 {
3932
3933 GNUNET_asprintf (&my_addr,
3934 "%s-%s",
3936 GNUNET_a2s (addr, addrlen));
3937 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3938 ai =
3940 my_addr,
3941 nt,
3943 GNUNET_free (my_addr);
3944 *app_ctx = ai;
3945 }
3946 else
3947 {
3948 ai = *app_ctx;
3950 *app_ctx = NULL;
3951 }
3952}
3953
3954
3958static void
3959add_addr (struct sockaddr *in, socklen_t in_len)
3960{
3961
3962 struct Addresses *saddrs;
3963
3965 "add address %s\n",
3966 GNUNET_a2s (in, in_len));
3967
3968 saddrs = GNUNET_new (struct Addresses);
3969 saddrs->addr = in;
3970 saddrs->addr_len = in_len;
3972
3974 "after add address %s\n",
3975 GNUNET_a2s (in, in_len));
3976
3978 "add address %s\n",
3979 GNUNET_a2s (saddrs->addr, saddrs->addr_len));
3980
3981 addrs_lens++;
3982}
3983
3984
3992static int
3993init_socket (struct sockaddr *addr,
3994 socklen_t in_len)
3995{
3996 struct sockaddr_storage in_sto;
3997 socklen_t sto_len;
3998 struct GNUNET_NETWORK_Handle *listen_sock;
3999 struct ListenTask *lt;
4000 int sockfd;
4001 struct GNUNET_HashCode h_sock;
4002
4003 if (NULL == addr)
4004 {
4006 "Address is NULL.\n");
4007 return GNUNET_SYSERR;
4008 }
4009
4011 "address %s\n",
4012 GNUNET_a2s (addr, in_len));
4013
4014 listen_sock =
4015 GNUNET_NETWORK_socket_create (addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
4016 if (NULL == listen_sock)
4017 {
4019 return GNUNET_SYSERR;
4020 }
4021
4022 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, addr, in_len))
4023 {
4025 GNUNET_NETWORK_socket_close (listen_sock);
4026 listen_sock = NULL;
4027 return GNUNET_SYSERR;
4028 }
4029
4030 if (GNUNET_OK !=
4031 GNUNET_NETWORK_socket_listen (listen_sock,
4032 5))
4033 {
4035 "listen");
4036 GNUNET_NETWORK_socket_close (listen_sock);
4037 listen_sock = NULL;
4038 return GNUNET_SYSERR;
4039 }
4040
4041 /* We might have bound to port 0, allowing the OS to figure it out;
4042 thus, get the real IN-address from the socket */
4043 sto_len = sizeof(in_sto);
4044
4045 if (0 != getsockname (GNUNET_NETWORK_get_fd (listen_sock),
4046 (struct sockaddr *) &in_sto,
4047 &sto_len))
4048 {
4049 memcpy (&in_sto, addr, in_len);
4050 sto_len = in_len;
4051 }
4052
4053 // addr = (struct sockaddr *) &in_sto;
4054 in_len = sto_len;
4056 "Bound to `%s'\n",
4057 GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len));
4058 if (NULL == stats)
4059 stats = GNUNET_STATISTICS_create ("communicator-tcp", cfg);
4060
4061 if (NULL == is)
4063
4064 /* start listening */
4065
4066 lt = GNUNET_new (struct ListenTask);
4067 lt->listen_sock = listen_sock;
4068
4070 listen_sock,
4071 &listen_cb,
4072 lt);
4073
4075 "creating hash\n");
4076 sockfd = GNUNET_NETWORK_get_fd (lt->listen_sock);
4077 GNUNET_CRYPTO_hash (&sockfd,
4078 sizeof(int),
4079 &h_sock);
4080
4082 "creating map\n");
4083 if (NULL == lt_map)
4085
4087 "creating map entry\n");
4090 &h_sock,
4091 lt,
4093
4095 "map entry created\n");
4096
4097 if (NULL == queue_map)
4099
4100 if (NULL == ch)
4105 &mq_init,
4106 NULL,
4108 NULL,
4109 NULL);
4110
4111 if (NULL == ch)
4112 {
4113 GNUNET_break (0);
4114 if (NULL != resolve_request_handle)
4117 return GNUNET_SYSERR;
4118 }
4119
4120 add_addr (addr, in_len);
4121 return GNUNET_OK;
4122
4123}
4124
4125
4129static void
4130nat_register ()
4131{
4132 struct sockaddr **saddrs;
4133 socklen_t *saddr_lens;
4134 int i;
4135 size_t len;
4136
4138 "starting nat register!\n");
4139 len = 0;
4140 i = 0;
4141 saddrs = GNUNET_malloc ((addrs_lens) * sizeof(struct sockaddr *));
4142 saddr_lens = GNUNET_malloc ((addrs_lens) * sizeof(socklen_t));
4143 for (struct Addresses *pos = addrs_head; NULL != pos; pos = pos->next)
4144 {
4146 "registering address %s\n",
4147 GNUNET_a2s (pos->addr, pos->addr_len));
4148
4149 saddr_lens[i] = pos->addr_len;
4150 len += saddr_lens[i];
4151 saddrs[i] = GNUNET_memdup (pos->addr, saddr_lens[i]);
4152 i++;
4153 }
4154
4156 "registering addresses %lu %lu %lu %lu\n",
4157 (addrs_lens) * sizeof(struct sockaddr *),
4158 (addrs_lens) * sizeof(socklen_t),
4159 len,
4163 IPPROTO_TCP,
4164 addrs_lens,
4165 (const struct sockaddr **) saddrs,
4166 saddr_lens,
4169 NULL /* closure */);
4170 for (i = addrs_lens - 1; i >= 0; i--)
4171 GNUNET_free (saddrs[i]);
4172 GNUNET_free (saddrs);
4173 GNUNET_free (saddr_lens);
4174
4175 if (NULL == nat)
4176 {
4177 GNUNET_break (0);
4178 if (NULL != resolve_request_handle)
4181 }
4182}
4183
4184
4192static void
4193init_socket_resolv (void *cls,
4194 const struct sockaddr *addr,
4195 socklen_t in_len)
4196{
4197 struct sockaddr_in *v4;
4198 struct sockaddr_in6 *v6;
4199 struct sockaddr *in;
4200
4201 (void) cls;
4202 if (NULL != addr)
4203 {
4204 if (AF_INET == addr->sa_family)
4205 {
4206 v4 = (struct sockaddr_in *) addr;
4207 in = tcp_address_to_sockaddr_numeric_v4 (&in_len, *v4, bind_port);// _global);
4208 }
4209 else if (AF_INET6 == addr->sa_family)
4210 {
4211 v6 = (struct sockaddr_in6 *) addr;
4212 in = tcp_address_to_sockaddr_numeric_v6 (&in_len, *v6, bind_port);// _global);
4213 }
4214 else
4215 {
4217 "Address family %u not suitable (not AF_INET %u nor AF_INET6 %u \n",
4218 addr->sa_family,
4219 AF_INET,
4220 AF_INET6);
4221 return;
4222 }
4223 init_socket (in, in_len);
4224 }
4225 else
4226 {
4228 "Address is NULL. This might be an error or the resolver finished resolving.\n");
4229 if (NULL == addrs_head)
4230 {
4232 "Resolver finished resolving, but we do not listen to an address!.\n");
4233 return;
4234 }
4235 nat_register ();
4236 }
4237}
4238
4239
4248static void
4249run (void *cls,
4250 char *const *args,
4251 const char *cfgfile,
4252 const struct GNUNET_CONFIGURATION_Handle *c)
4253{
4254 char *bindto;
4255 struct sockaddr *in;
4256 socklen_t in_len;
4257 struct sockaddr_in v4;
4258 struct sockaddr_in6 v6;
4259 char *start;
4260 unsigned int port;
4261 char dummy[2];
4262 char *rest = NULL;
4263 struct PortOnlyIpv4Ipv6 *po;
4264 socklen_t addr_len_ipv4;
4265 socklen_t addr_len_ipv6;
4266
4267 (void) cls;
4268
4270 memset (&v4,0,sizeof(struct sockaddr_in));
4271 memset (&v6,0,sizeof(struct sockaddr_in6));
4272 cfg = c;
4273 if (GNUNET_OK !=
4276 "BINDTO",
4277 &bindto))
4278 {
4281 "BINDTO");
4282 return;
4283 }
4284 if (GNUNET_OK !=
4287 "MAX_QUEUE_LENGTH",
4289 {
4291 }
4292 if (GNUNET_OK !=
4295 "REKEY_INTERVAL",
4297 {
4299 }
4300 if (GNUNET_OK !=
4303 "REKEY_MAX_BYTES",
4305 {
4307 }
4309 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
4310 (GNUNET_YES ==
4313 "DISABLE_V6")))
4314 {
4316 }
4318 GNUNET_assert (NULL != key_ring);
4319 pils = GNUNET_PILS_connect (cfg, NULL, NULL);
4320 GNUNET_assert (NULL != pils);
4322 if (NULL == peerstore)
4323 {
4324 GNUNET_free (bindto);
4325 GNUNET_break (0);
4327 return;
4328 }
4329
4331
4332 if (1 == sscanf (bindto, "%u%1s", &bind_port, dummy))
4333 {
4337 "address po %s\n",
4339 if (NULL != po->addr_ipv4)
4340 {
4342 }
4343 if (NULL != po->addr_ipv6)
4344 {
4347 }
4348 GNUNET_free (po);
4349 nat_register ();
4350 GNUNET_free (bindto);
4351 return;
4352 }
4353
4354 start = extract_address (bindto);
4355 // FIXME: check for NULL == start...
4356 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
4357 {
4358 bind_port = extract_port (bindto);
4359
4361 init_socket (in, in_len);
4362 nat_register ();
4364 GNUNET_free (bindto);
4365 return;
4366 }
4367
4368 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
4369 {
4370 bind_port = extract_port (bindto);
4372 init_socket (in, in_len);
4373 nat_register ();
4375 GNUNET_free (bindto);
4376 return;
4377 }
4378
4379 bind_port = extract_port (bindto);
4381 ":",
4382 &rest),
4383 AF_UNSPEC,
4386 &port);
4387
4388 GNUNET_free (bindto);
4390}
4391
4392
4400int
4401main (int argc, char *const *argv)
4402{
4403 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4405 };
4406 int ret;
4407
4409 "Starting tcp communicator\n");
4410
4411 ret = (GNUNET_OK ==
4413 argc,
4414 argv,
4415 "gnunet-communicator-tcp",
4416 _ ("GNUnet TCP communicator"),
4417 options,
4418 &run,
4419 NULL))
4420 ? 0
4421 : 1;
4422 return ret;
4423}
4424
4425
4426/* end of gnunet-communicator-tcp.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MessageHeader * msg
Definition 005.c:2
int main()
Program to simulate results from GCP_get_desirability_of_path() for various plausible inputs.
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static void queue_finish(struct Queue *queue)
Append a 'finish' message to the outgoing transmission.
static void transmit_kx(struct Queue *queue, const struct GNUNET_CRYPTO_HpkeEncapsulation *c)
Generate and transmit our ephemeral key and the signature for the initial KX with the other peer.
static void boot_queue(struct Queue *queue)
Add the given queue to our internal data structure.
static unsigned int bind_port
The port the communicator should be assigned to.
static size_t try_handle_plaintext(struct Queue *queue)
Test if we have received a full message in plaintext.
static void pass_plaintext_to_core(struct Queue *queue, const void *plaintext, size_t plaintext_len)
We received plaintext_len bytes of plaintext on queue.
static struct sockaddr * tcp_address_to_sockaddr_numeric_v6(socklen_t *sock_len, struct sockaddr_in6 v6, unsigned int port)
Convert a struct sockaddr_in6 to astruct sockaddr *`.
#define TCP_QUEUE_GONE
Sentinel returned by try_handle_plaintext() to say that it destroyed the queue it was given.
#define COMMUNICATOR_ADDRESS_PREFIX
Address prefix used by the communicator.
static void mq_destroy(struct GNUNET_MQ_Handle *mq, void *impl_state)
Signature of functions implementing the destruction of a message queue.
static void finish_timeout_cb(void *cls)
We gave the queue a chance to flush its finish message and it did not take it (most likely because th...
#define ADDRESS_VALIDITY_PERIOD
How long do we believe our addresses to remain up (before the other peer should revalidate).
static struct PortOnlyIpv4Ipv6 * tcp_address_to_sockaddr_port_only(const char *bindto, unsigned int *port)
Convert TCP bind specification to a struct PortOnlyIpv4Ipv6 *
static void setup_in_cipher(const struct GNUNET_CRYPTO_HpkeEncapsulation *ephemeral, struct Queue *queue)
Setup cipher of queue for decryption.
static void eddsa_pub_to_hpke_key(const struct GNUNET_CRYPTO_EddsaPublicKey *edpk, struct GNUNET_CRYPTO_HpkePublicKey *pk)
#define INITIAL_CORE_KX_SIZE
Size of the initial core key exchange messages.
static void do_rekey(struct Queue *queue, const struct TCPRekey *rekey)
Handle rekey message on queue.
static void calculate_hmac(struct GNUNET_CRYPTO_AuthKey *hmac_secret, const void *buf, size_t buf_size, struct GNUNET_ShortHashCode *smac)
Compute mac over buf, and ratched the hmac_secret.
static struct ProtoQueue * create_proto_queue(struct GNUNET_NETWORK_Handle *sock, struct sockaddr *in, socklen_t addrlen)
static int init_socket(struct sockaddr *addr, socklen_t in_len)
This method launch network interactions for each address we like to bind to.
static void try_connection_reversal(void *cls, const struct sockaddr *addr, socklen_t addrlen)
static void eddsa_priv_to_hpke_key(const struct GNUNET_CRYPTO_EddsaPrivateKey *edpk, struct GNUNET_CRYPTO_HpkePrivateKey *pk)
static struct GNUNET_NT_InterfaceScanner * is
Network scanner to determine network types.
static void listen_cb(void *cls)
We have been notified that our listen socket has something to read.
static void rekey_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY where...
static int disable_v6
IPv6 disabled.
static struct GNUNET_CONTAINER_MultiHashMap * pending_reversals
Map of pending reversals.
static struct GNUNET_STATISTICS_Handle * stats
For logging statistics.
static void queue_destroy(struct Queue *queue)
Functions with this signature are called whenever we need to close a queue due to a disconnect or fai...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static void enc_notify_cb(void *cls, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg)
Function called when the transport service has received an acknowledgement for this communicator (!...
static void handshake_ack_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for handshake ack monotime value is finished.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static int pending_reversals_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
static struct ProtoQueue * proto_tail
Protoqueues DLL tail.
static void queue_read_kx(void *cls)
Read from the socket of the queue until we have enough data to initialize the decryption logic and ca...
static int get_lt_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over all ListenTasks to clean up.
static void inject_rekey(struct Queue *queue)
Inject a struct TCPRekey message into the queue's plaintext buffer.
static struct GNUNET_TIME_Relative rekey_interval
The rekey interval.
#define NAT_TIMEOUT
How long until we give up on establishing an NAT connection? Must be > 4 RTT.
#define BUF_SIZE
Size of our IO buffers for ciphertext data.
static void pending_reversal_key(const struct sockaddr *in, const struct GNUNET_PeerIdentity *target, struct GNUNET_HashCode *key)
Compute the key under which a pending NAT reversal request to target at in is stored in pending_rever...
#define COMMUNICATOR_CONFIG_SECTION
Configuration section used by the communicator.
static struct GNUNET_CONTAINER_MultiHashMap * queue_map
Queues (map from peer identity to struct Queue)
static void proto_read_kx(void *cls)
Read from the socket of the proto queue until we have enough data to upgrade to full queue.
static void nat_address_cb(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of ...
static struct sockaddr * tcp_address_to_sockaddr_numeric_v4(socklen_t *sock_len, struct sockaddr_in v4, unsigned int port)
Convert a struct sockaddr_in4 to astruct sockaddr *`.
static void check_and_remove_pending_reversal(struct sockaddr *in, sa_family_t sa_family, const struct GNUNET_PeerIdentity *sender)
We got a connection with sender at in, so a NAT reversal we may have requested for that peer has serv...
static void init_socket_resolv(void *cls, const struct sockaddr *addr, socklen_t in_len)
This method is the callback called by the resolver API, and wraps method init_socket.
static struct GNUNET_TRANSPORT_CommunicatorHandle * ch
Our environment.
#define FINISH_TIMEOUT
How long do we wait for a queue we are finishing to flush its GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FI...
static unsigned long long max_queue_length
Maximum queue length before we stop reading towards the transport service.
struct GNUNET_RESOLVER_RequestHandle * resolve_request_handle
Handle for DNS lookup of bindto address.
static void nat_register()
This method reads from the DLL addrs_head to register them at the NAT service.
static void setup_out_cipher(struct Queue *queue, struct GNUNET_ShortHashCode *dh)
Setup cipher for outgoing data stream based on target and our ephemeral private key.
static int addrs_lens
Number of addresses in the DLL for register at NAT service.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Setup communicator and launch network interactions.
static struct GNUNET_NAT_Handle * nat
Connection to NAT service.
static void pending_reversal_timeout(void *cls)
#define PROTO_QUEUE_TIMEOUT
How long do we wait until we must have received the initial KX?
static void queue_read(void *cls)
Queue read task.
static struct GNUNET_PILS_KeyRing * key_ring
For PILS.
#define REKEY_MAX_BYTES
How often do we rekey based on number of bytes transmitted? (additionally randomized).
static int get_queue_delete_it(void *cls, const struct GNUNET_HashCode *target, void *value)
Iterator over all message queues to clean up.
static void mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
#define INITIAL_KX_SIZE
Size of the initial key exchange message sent first in both directions.
static void handshake_ack_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_A...
static int mq_init(void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
Function called by the transport service to initialize a message queue given address information abou...
static void proto_queue_write(void *cls)
We have been notified that our socket is ready to write.
static void handshake_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for handshake monotime is finished.
static void send_challenge(struct GNUNET_CRYPTO_ChallengeNonceP challenge, struct Queue *queue)
Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
static void rekey_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for rekey monotime value is finished.
static char * extract_address(const char *bindto)
This Method extracts the address part of the BINDTO string.
static struct ProtoQueue * proto_head
Protoqueues DLL head.
static int shutdown_running
A flag indicating we are already doing a shutdown.
static int decrypt_and_check_tc(struct Queue *queue, struct TCPConfirmation *tc, char *ibuf)
We have received the first bytes from the other side on a queue.
#define DEFAULT_REKEY_INTERVAL
How often do we rekey based on time (at least)
static void queue_write(void *cls)
We have been notified that our socket is ready to write.
static void add_addr(struct sockaddr *in, socklen_t in_len)
This method adds addresses to the DLL, that are later register at the NAT service.
static void handshake_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE w...
static struct Addresses * addrs_head
Head of DLL with addresses we like to register at NAT service.
static struct sockaddr * tcp_address_to_sockaddr(const char *bindto, socklen_t *sock_len)
Convert TCP bind specification to a struct sockaddr *
static struct Addresses * addrs_tail
Head of DLL with addresses we like to register at NAT service.
static void setup_in_cipher_elligator(const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct Queue *queue)
Setup cipher of queue for decryption from an elligator representative.
#define DEFAULT_MAX_QUEUE_LENGTH
How many messages do we keep at most in the queue to the transport service before we start to drop (d...
static void mq_error(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
static unsigned int extract_port(const char *addr_and_port)
This Method extracts the port part of the BINDTO string.
static void mq_send(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue.
static struct GNUNET_PILS_Handle * pils
For PILS.
static void start_initial_kx_out(struct Queue *queue)
Initialize our key material for outgoing transmissions and inform the other peer about it.
static void setup_cipher(const struct GNUNET_ShortHashCode *prk, const struct GNUNET_PeerIdentity *pid, gcry_cipher_hd_t *cipher, struct GNUNET_CRYPTO_AuthKey *hmac_key)
Setup cipher based on shared secret dh and decrypting peer pid.
static void free_proto_queue(struct ProtoQueue *pq)
Closes socket and frees memory associated with pq.
static struct GNUNET_CONTAINER_MultiHashMap * lt_map
ListenTasks (map from socket to struct ListenTask)
static unsigned long long rekey_max_bytes
The rekey byte maximum.
static void core_read_finished_cb(void *cls, int success)
Core tells us it is done processing a message that transport received on a queue with status success.
static struct GNUNET_SCHEDULER_Task * write_task
ID of write task.
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * address
GNS address for this phone.
struct GNUNET_HashCode key
The key used in the DHT.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
struct GNUNET_CRYPTO_BlindablePrivateKey pk
Private key from command line option, or NULL.
struct GNUNET_SCHEDULER_Task * read_task
static void queue(const char *label, uint32_t rd_count, struct GNUNET_GNSRECORD_Data *rd, const struct Zone *zone)
Add hostname to the list of requests to be made.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key
The current private key.
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:624
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:647
struct GNUNET_PILS_KeyRing * GNUNET_PILS_create_key_ring(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_SCHEDULER_TaskCallback init_cb, void *cls)
Create a key ring handle to use the current peer identity key.
Definition pils_api.c:1008
void GNUNET_PILS_destroy_key_ring(struct GNUNET_PILS_KeyRing *key_ring)
Destroy a key ring handle and free its memory.
Definition pils_api.c:1068
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:875
const struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_PILS_key_ring_get_private_key(const struct GNUNET_PILS_KeyRing *key_ring)
Return the current private key of a given key ring handle.
Definition pils_api.c:1091
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK
Signature by a peer sending back the nonce received at initial handshake.
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY
Signature used by TCP communicator rekey.
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE
Signature used by TCP communicator handshake.
void GNUNET_TRANSPORT_communicator_address_remove(struct GNUNET_TRANSPORT_AddressIdentifier *ai)
Notify transport service about an address that this communicator no longer provides for this peer.
int GNUNET_TRANSPORT_communicator_receive(struct GNUNET_TRANSPORT_CommunicatorHandle *handle, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative expected_addr_validity, GNUNET_TRANSPORT_MessageCompletedCallback cb, void *cb_cls)
Notify transport service that the communicator has received a message.
void GNUNET_TRANSPORT_communicator_mq_del(struct GNUNET_TRANSPORT_QueueHandle *qh)
Notify transport service that an MQ became unavailable due to a disconnect or timeout.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
struct GNUNET_TRANSPORT_QueueHandle * GNUNET_TRANSPORT_communicator_mq_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const struct GNUNET_PeerIdentity *peer, const char *address, uint32_t mtu, uint64_t q_len, uint32_t priority, enum GNUNET_NetworkType nt, enum GNUNET_TRANSPORT_ConnectionStatus cs, struct GNUNET_MQ_Handle *mq)
Notify transport service that a MQ became available due to an "inbound" connection or because the com...
void GNUNET_TRANSPORT_communicator_disconnect(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Disconnect from the transport service.
GNUNET_TRANSPORT_ConnectionStatus
Possible states of a connection.
struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section_name, const char *addr_prefix, enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls, GNUNET_TRANSPORT_CommunicatorNotify notify_cb, void *notify_cb_cls, GNUNET_TRANSPORT_StartBurstNotify sb)
Connect to the transport service.
struct GNUNET_TRANSPORT_AddressIdentifier * GNUNET_TRANSPORT_communicator_address_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const char *address, enum GNUNET_NetworkType nt, struct GNUNET_TIME_Relative expiration)
Notify transport service about an address that this communicator provides for this peer.
void GNUNET_TRANSPORT_communicator_address_remove_all(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Notify transport service that this communicator no longer provides all its addresses for this peer.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
@ GNUNET_TRANSPORT_CS_INBOUND
this is an inbound connection (communicator initiated)
@ GNUNET_TRANSPORT_CS_OUTBOUND
this is an outbound connection (transport initiated)
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private EdDSA key.
uint64_t GNUNET_CRYPTO_random_u64(uint64_t max)
Generate a random unsigned 64-bit value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_elligator_kem_encaps(const struct GNUNET_CRYPTO_HpkePublicKey *pkR, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *shared_secret)
Carries out ecdh encapsulation with given public key and the private key from a freshly created ephem...
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_elligator_kem_decaps(const struct GNUNET_CRYPTO_HpkePrivateKey *skR, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *shared_secret)
Carries out ecdh decapsulation with own private key and the representative of the received public key...
void GNUNET_CRYPTO_random_block(void *buffer, size_t length)
Fill block with a random values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
#define GNUNET_CRYPTO_eddsa_sign(priv, ps, sig)
EdDSA sign a given block.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_GETOPT_OPTION_END
Marker for the end of the list of options.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
#define GNUNET_CRYPTO_hkdf_expand(result, out_len, prk,...)
HKDF-Expand using SHA256.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
#define GNUNET_CRYPTO_kdf_arg_string(d)
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_sk_to_x25519(const struct GNUNET_CRYPTO_BlindablePrivateKey *sk, struct GNUNET_CRYPTO_HpkePrivateKey *sk_enc)
Convert a GNUnet identity key to a key sutiable for HPKE (X25519)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_pk_to_x25519(const struct GNUNET_CRYPTO_BlindablePublicKey *pk, struct GNUNET_CRYPTO_HpkePublicKey *pk_enc)
Convert a GNUnet identity key to a key sutiable for HPKE (X25519)
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
@ GNUNET_PUBLIC_KEY_TYPE_EDDSA
EDDSA identity.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * GNUNET_e2s(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
const char * GNUNET_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition mq.c:514
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition mq.c:469
int GNUNET_NAT_request_reversal(struct GNUNET_NAT_Handle *nh, const struct sockaddr_in *local_sa, const struct sockaddr_in *remote_sa)
We learned about a peer (possibly behind NAT) so run the gnunet-nat-client to send dummy ICMP respons...
Definition nat_api.c:675
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
Definition network.c:392
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition network.c:508
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition network.c:1000
ssize_t GNUNET_NETWORK_socket_recv(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length)
Read data from a connected socket (always non-blocking).
Definition network.c:716
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:832
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_connect(const struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Connect a socket to some remote address.
Definition network.c:601
ssize_t GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc, const void *buffer, size_t length)
Send data (always non-blocking).
Definition network.c:737
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition network.c:79
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition network.c:439
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition network.c:651
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
void GNUNET_NT_scanner_done(struct GNUNET_NT_InterfaceScanner *is)
Terminate interface scanner.
Definition nt.c:428
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init(void)
Initialize the address characterization client handle.
Definition nt.c:407
enum GNUNET_NetworkType GNUNET_NT_scanner_get_type(struct GNUNET_NT_InterfaceScanner *is, const struct sockaddr *addr, socklen_t addrlen)
Returns where the address is located: loopback, LAN or WAN.
Definition nt.c:309
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE
Key used to store sender's monotonic time from handshake message.
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK
Key used to store sender's monotonic time from handshake ack message.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY
Key used to store sender's monotonic time from rekey message.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition program.c:406
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK
TCP communicator confirmation ack.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE
TCP NAT probe message, send from NAT'd peer to other peer to establish bi-directional communication.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH
TCP communicator end of stream.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX
TCP communicator payload box.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY
TCP communicator rekey message.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1517
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1588
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:610
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_monotonic(const struct GNUNET_CONFIGURATION_Handle *cfg)
Obtain the current time and make sure it is monotonically increasing.
Definition time.c:860
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:671
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define max(x, y)
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:436
static void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition socks.c:330
DLL to store the addresses we like to register at NAT service.
struct Addresses * next
Kept in a DLL.
struct Addresses * prev
Kept in a DLL.
struct sockaddr * addr
Address we like to register at NAT service.
socklen_t addr_len
Length of address we like to register at NAT service.
Internal representation of the hash map.
type for (message) authentication keys
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
Type of a nonce used for challenges.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
Private ECC key encoded for transmission.
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
A public key used for decryption.
A public key used for encryption.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
Definition of a command line option.
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Header for all communications.
Handle for active NAT registrations.
Definition nat_api.c:72
handle to a socket
Definition network.c:53
Handle to the interface scanner.
Definition nt.c:104
Handle to the PEERSTORE service.
Context for a iterate request.
Context for a store request.
A handle for the PILS service.
Definition pils_api.c:86
A simplified handle for using the peer identity key.
Definition pils_api.c:149
The identity of the host (wraps the signing key of the peer).
Handle to a request given to the resolver.
Entry in list of pending tasks.
Definition scheduler.c:141
Handle for the service.
A 256-bit hashcode.
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Internal representation of an address a communicator is currently providing for the transport service...
Opaque handle to the transport service for communicators.
struct GNUNET_MQ_Handle * mq
Queue to talk to the transport service.
Handle returned to identify the internal data structure the transport API has created to manage a mes...
Struct to use as closure.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
struct GNUNET_SCHEDULER_Task * listen_task
ID of listen task.
Struct for pending nat reversals.
struct sockaddr * in
Address the reversal was send to.
struct GNUNET_SCHEDULER_Task * timeout_task
struct GNUNET_PeerIdentity target
To whom are we like to talk to.
In case of port only configuration we like to bind to ipv4 and ipv6 addresses.
struct sockaddr * addr_ipv4
Ipv4 address we like to bind to.
struct sockaddr * addr_ipv6
Ipv6 address we like to bind to.
socklen_t addr_len_ipv6
Length of ipv6 address.
socklen_t addr_len_ipv4
Length of ipv4 address.
Handle for an incoming connection where we do not yet have enough information to setup a full queue.
socklen_t address_len
Length of the address.
struct GNUNET_SCHEDULER_Task * write_task
ID of write task for this connection.
char write_buf[sizeof(struct TCPNATProbeMessage)]
buffer for writing struct TCPNATProbeMessage to network.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
size_t ibuf_off
Current offset for reading into ibuf.
struct GNUNET_TIME_Absolute timeout
Timeout for this protoqueue.
struct GNUNET_NETWORK_Handle * sock
socket that we transmit all data with on this queue
struct sockaddr * address
Address of the other peer.
struct ProtoQueue * prev
Kept in a DLL.
char ibuf[(sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)+sizeof(struct TCPConfirmation))]
Buffer for reading all the information we need to upgrade from protoqueue to queue.
size_t write_off
Offset of the buffer?
struct GNUNET_SCHEDULER_Task * read_task
ID of read task for this connection.
struct ProtoQueue * next
Kept in a DLL.
Handle for a queue.
unsigned int backpressure
How may messages did we pass from this queue to CORE for which we have yet to receive an acknowledgem...
struct GNUNET_NETWORK_Handle * sock
socket that we transmit all data with on this queue
struct GNUNET_PEERSTORE_IterateContext * handshake_ack_monotime_get
Iteration Context for retrieving the monotonic time send with the handshake ack.
int rekeyed
GNUNET_YES if we just rekeyed and must thus possibly re-decrypt ciphertext.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
size_t unverified_size
Size of data received without KX challenge played back.
struct GNUNET_SCHEDULER_Task * finish_task
ID of the task that tears this queue down once we gave up on flushing the GNUNET_MESSAGE_TYPE_COMMUNI...
struct GNUNET_TRANSPORT_QueueHandle * qh
handle for this queue with the ch.
int finishing
Did we enqueue a finish message and are closing down the queue?
int initial_core_kx_done
Has the initial (core) handshake already happened?
struct GNUNET_HashCode key
Key in hash map.
socklen_t address_len
Length of the address.
struct GNUNET_CRYPTO_AuthKey in_hmac
Shared secret for HMAC verification on incoming data.
struct GNUNET_MQ_Handle * mq
Message queue we are providing for the ch.
unsigned long long bytes_in_queue
Number of bytes we currently have in our write queue.
char pread_buf[UINT16_MAX+1+sizeof(struct TCPBox)]
Plaintext buffer for decrypted plaintext.
int destroyed
Did we technically destroy this queue, but kept the allocation around because of backpressure not bei...
struct GNUNET_PEERSTORE_StoreContext * rekey_monotime_sc
Store Context for retrieving the monotonic time send with key for rekeying.
size_t cwrite_off
At which offset in the ciphertext write buffer should we append more ciphertext from reading next?
struct GNUNET_PEERSTORE_IterateContext * rekey_monotime_get
Iteration Context for retrieving the monotonic time send with key for rekeying.
char cread_buf[(2 *64 *1024+sizeof(struct TCPBox))]
Buffer for reading ciphertext from network into.
struct GNUNET_CRYPTO_HpkePublicKey target_hpke_key
To whom are we talking to.
enum GNUNET_NetworkType nt
Which network type does this queue use?
struct GNUNET_CRYPTO_ChallengeNonceP challenge_received
Challenge value received.
uint64_t rekey_left_bytes
How many more bytes may we sent with the current out_cipher before we should rekey?
int mq_awaits_continue
Is MQ awaiting a GNUNET_MQ_impl_send_continue() call?
gcry_cipher_hd_t in_cipher
cipher for decryption of incoming data.
struct GNUNET_PEERSTORE_StoreContext * handshake_ack_monotime_sc
Store Context for retrieving the monotonic time send with the handshake ack.
struct GNUNET_SCHEDULER_Task * write_task
ID of write task for this connection.
size_t pwrite_off
At which offset in the plaintext output buffer should we append more plaintext for encryption next?
struct GNUNET_TIME_Absolute timeout
Timeout for this queue.
size_t cread_off
At which offset in the ciphertext read buffer should we append more ciphertext for transmission next?
struct GNUNET_TIME_Absolute rekey_time
Until what time may we sent with the current out_cipher before we should rekey?
struct GNUNET_PeerIdentity target
To whom are we talking to.
char cwrite_buf[(2 *64 *1024+sizeof(struct TCPBox))]
buffer for writing ciphertext to network.
struct GNUNET_PEERSTORE_StoreContext * handshake_monotime_sc
Store Context for retrieving the monotonic time send with the handshake.
size_t pread_off
At which offset in the plaintext input buffer should we append more plaintext from decryption next?
struct GNUNET_SCHEDULER_Task * read_task
ID of read task for this connection.
enum GNUNET_TRANSPORT_ConnectionStatus cs
The connection status of this queue.
gcry_cipher_hd_t out_cipher
cipher for encryption of outgoing data.
char pwrite_buf[UINT16_MAX+1+sizeof(struct TCPBox)]
Plaintext buffer for messages to be encrypted.
struct GNUNET_PEERSTORE_IterateContext * handshake_monotime_get
Iteration Context for retrieving the monotonic time send with the handshake.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
struct sockaddr * address
Address of the other peer.
struct GNUNET_CRYPTO_AuthKey out_hmac
Shared secret for HMAC generation on outgoing data, ratcheted after each operation.
struct GNUNET_TIME_AbsoluteNBO handshake_ack_monotonic_time
Monotonic time value for handshake ack message.
struct GNUNET_TIME_AbsoluteNBO rekey_monotonic_time
Monotonic time value for rekey message.
struct GNUNET_TIME_AbsoluteNBO handshake_monotonic_time
Monotonic time value for handshake message.
TCP message box.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX.
struct GNUNET_ShortHashCode hmac
HMAC for the following encrypted message.
Ack for the encrypted continuation of TCP initial handshake.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Sender's signature of type GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK.
struct GNUNET_PeerIdentity sender
Sender's identity.
Encrypted continuation of TCP initial handshake.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Sender's signature of type GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE.
struct GNUNET_PeerIdentity sender
Sender's identity.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH.
struct GNUNET_ShortHashCode hmac
HMAC for the following encrypted message.
Basically a WELCOME message, but with the purpose of giving the waiting peer a client handle to use.
struct GNUNET_PeerIdentity clientIdentity
Identity of the sender of the message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
TCP rekey message box.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Sender's signature of type GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral
New ephemeral key.
struct GNUNET_ShortHashCode hmac
HMAC for the following encrypted message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY.
Signature we use to verify that the ack from the receiver of the ephemeral key was really send by the...
struct GNUNET_PeerIdentity sender
Identity of the inititor of the TCP connection (TCP client).
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_PeerIdentity receiver
Presumed identity of the target of the TCP connection (TCP server)
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
Signature we use to verify that the ephemeral key was really chosen by the specified sender.
Signature we use to verify that the ephemeral key was really chosen by the specified sender.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral
Ephemeral key used by the sender.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY.
struct GNUNET_PeerIdentity sender
Identity of the inititor of the TCP connection (TCP client).
struct GNUNET_PeerIdentity receiver
Presumed identity of the target of the TCP connection (TCP server)
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...

◆ DEFAULT_MAX_QUEUE_LENGTH

#define DEFAULT_MAX_QUEUE_LENGTH   8

How many messages do we keep at most in the queue to the transport service before we start to drop (default, can be changed via the configuration file).

Should be below the level of the communicator API, as otherwise we may read messages just to have them dropped by the communicator API.

Definition at line 69 of file gnunet-communicator-tcp.c.

◆ BUF_SIZE

#define BUF_SIZE   (2 * 64 * 1024 + sizeof(struct TCPBox))

Size of our IO buffers for ciphertext data.

Must be at least UINT_MAX + sizeof (struct TCPBox).

Definition at line 75 of file gnunet-communicator-tcp.c.

◆ TCP_QUEUE_GONE

#define TCP_QUEUE_GONE   SIZE_MAX

Sentinel returned by try_handle_plaintext() to say that it destroyed the queue it was given.

Distinct from 0 ("no complete message yet") because the caller must stop touching the queue entirely, not merely stop the parse loop. No real message consumes this many bytes.

Definition at line 83 of file gnunet-communicator-tcp.c.

◆ DEFAULT_REKEY_INTERVAL

#define DEFAULT_REKEY_INTERVAL   GNUNET_TIME_UNIT_DAYS

How often do we rekey based on time (at least)

Definition at line 88 of file gnunet-communicator-tcp.c.

◆ PROTO_QUEUE_TIMEOUT

#define PROTO_QUEUE_TIMEOUT   GNUNET_TIME_UNIT_MINUTES

How long do we wait until we must have received the initial KX?

Definition at line 93 of file gnunet-communicator-tcp.c.

◆ FINISH_TIMEOUT

#define FINISH_TIMEOUT
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486

How long do we wait for a queue we are finishing to flush its GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH before we tear it down regardless? If the peer is gone the socket may never become writable again, and until queue_destroy() runs, transport (and thus CORE) is not told that this queue is dead.

Definition at line 102 of file gnunet-communicator-tcp.c.

◆ REKEY_MAX_BYTES

#define REKEY_MAX_BYTES   (1024LLU * 1024 * 400)

How often do we rekey based on number of bytes transmitted? (additionally randomized).

Currently 400 MB

Definition at line 109 of file gnunet-communicator-tcp.c.

◆ INITIAL_KX_SIZE

#define INITIAL_KX_SIZE
Value:
(sizeof(struct GNUNET_CRYPTO_EcdhePublicKey) \
+ sizeof(struct TCPConfirmation))

Size of the initial key exchange message sent first in both directions.

Definition at line 115 of file gnunet-communicator-tcp.c.

◆ INITIAL_CORE_KX_SIZE

#define INITIAL_CORE_KX_SIZE
Value:
(sizeof(struct EphemeralKeyMessage) \
+ sizeof(struct PingMessage) \
+ sizeof(struct PongMessage))
Message transmitted with the signed ephemeral key of a peer.
We're sending an (encrypted) PING to the other peer to check if it can decrypt.
Response to a PING.

Size of the initial core key exchange messages.

Definition at line 122 of file gnunet-communicator-tcp.c.

◆ COMMUNICATOR_ADDRESS_PREFIX

#define COMMUNICATOR_ADDRESS_PREFIX   "tcp"

Address prefix used by the communicator.

Definition at line 130 of file gnunet-communicator-tcp.c.

◆ COMMUNICATOR_CONFIG_SECTION

#define COMMUNICATOR_CONFIG_SECTION   "communicator-tcp"

Configuration section used by the communicator.

Definition at line 135 of file gnunet-communicator-tcp.c.

Function Documentation

◆ listen_cb()

static void listen_cb ( void *  cls)
static

We have been notified that our listen socket has something to read.

Do the read and reschedule this function to be called again once more is available.

Parameters
clsNULL

Do the read and reschedule this function to be called again once more is available.

Parameters
clsListenTask with listening socket and task

Definition at line 3413 of file gnunet-communicator-tcp.c.

3414{
3415 struct sockaddr_storage in;
3416 socklen_t addrlen;
3417 struct GNUNET_NETWORK_Handle *sock;
3418 struct ListenTask *lt;
3419 struct sockaddr *in_addr;
3420
3422 "listen_cb\n");
3423
3424 lt = cls;
3425
3426 lt->listen_task = NULL;
3427 GNUNET_assert (NULL != lt->listen_sock);
3428 addrlen = sizeof(in);
3429 memset (&in, 0, sizeof(in));
3431 (struct sockaddr*) &in,
3432 &addrlen);
3433 if ((NULL == sock) && ((EMFILE == errno) || (ENFILE == errno)))
3434 return; /* system limit reached, wait until connection goes down */
3436 lt->listen_sock,
3437 &listen_cb,
3438 lt);
3439 if ((NULL == sock) && ((EAGAIN == errno) || (ENOBUFS == errno)))
3440 return;
3441 if (NULL == sock)
3442 {
3444 return;
3445 }
3446 in_addr = GNUNET_memdup (&in, addrlen);
3447 create_proto_queue (sock, in_addr, addrlen);
3448}

References create_proto_queue(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror, GNUNET_memdup, GNUNET_NETWORK_socket_accept(), GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, listen_cb(), ListenTask::listen_sock, and ListenTask::listen_task.

Referenced by init_socket(), listen_cb(), and queue_destroy().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ eddsa_priv_to_hpke_key()

static void eddsa_priv_to_hpke_key ( const struct GNUNET_CRYPTO_EddsaPrivateKey edpk,
struct GNUNET_CRYPTO_HpkePrivateKey pk 
)
static

Definition at line 971 of file gnunet-communicator-tcp.c.

973{
975 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
976 key.eddsa_key = *edpk;
978 pk);
979}

References GNUNET_CRYPTO_hpke_sk_to_x25519(), GNUNET_PUBLIC_KEY_TYPE_EDDSA, key, and pk.

Referenced by setup_in_cipher_elligator().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ eddsa_pub_to_hpke_key()

static void eddsa_pub_to_hpke_key ( const struct GNUNET_CRYPTO_EddsaPublicKey edpk,
struct GNUNET_CRYPTO_HpkePublicKey pk 
)
static

Definition at line 983 of file gnunet-communicator-tcp.c.

985{
987 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
988 key.eddsa_key = *edpk;
990}

References GNUNET_CRYPTO_hpke_pk_to_x25519(), GNUNET_PUBLIC_KEY_TYPE_EDDSA, key, and pk.

Referenced by mq_init(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_destroy()

static void queue_destroy ( struct Queue queue)
static

Functions with this signature are called whenever we need to close a queue due to a disconnect or failure to establish a connection.

Parameters
queuequeue to close down

Definition at line 1001 of file gnunet-communicator-tcp.c.

1002{
1003 struct ListenTask *lt = NULL;
1004 struct GNUNET_HashCode h_sock;
1005 int sockfd;
1006
1007 if (NULL != queue->listen_sock)
1008 {
1009 sockfd = GNUNET_NETWORK_get_fd (queue->listen_sock);
1010 GNUNET_CRYPTO_hash (&sockfd,
1011 sizeof(int),
1012 &h_sock);
1013
1015 }
1016
1018 "Disconnecting queue for peer `%s'\n",
1019 GNUNET_i2s (&queue->target));
1020 if (NULL != queue->rekey_monotime_sc)
1021 {
1022 GNUNET_PEERSTORE_store_cancel (queue->rekey_monotime_sc);
1023 queue->rekey_monotime_sc = NULL;
1024 }
1025 if (NULL != queue->handshake_monotime_sc)
1026 {
1027 GNUNET_PEERSTORE_store_cancel (queue->handshake_monotime_sc);
1028 queue->handshake_monotime_sc = NULL;
1029 }
1030 if (NULL != queue->handshake_ack_monotime_sc)
1031 {
1032 GNUNET_PEERSTORE_store_cancel (queue->handshake_ack_monotime_sc);
1033 queue->handshake_ack_monotime_sc = NULL;
1034 }
1035 if (NULL != queue->rekey_monotime_get)
1036 {
1037 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1038 queue->rekey_monotime_get = NULL;
1039 }
1040 if (NULL != queue->handshake_monotime_get)
1041 {
1042 GNUNET_PEERSTORE_iteration_stop (queue->handshake_monotime_get);
1043 queue->handshake_monotime_get = NULL;
1044 }
1045 if (NULL != queue->handshake_ack_monotime_get)
1046 {
1047 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1048 queue->handshake_ack_monotime_get = NULL;
1049 }
1050 if (NULL != queue->qh)
1051 {
1053 queue->qh = NULL;
1054 }
1056 GNUNET_YES ==
1059 "# queues active",
1061 GNUNET_NO);
1062 if (NULL != queue->finish_task)
1063 {
1064 GNUNET_SCHEDULER_cancel (queue->finish_task);
1065 queue->finish_task = NULL;
1066 }
1067 if (NULL != queue->read_task)
1068 {
1069 GNUNET_SCHEDULER_cancel (queue->read_task);
1070 queue->read_task = NULL;
1071 }
1072 if (NULL != queue->write_task)
1073 {
1074 GNUNET_SCHEDULER_cancel (queue->write_task);
1075 queue->write_task = NULL;
1076 }
1078 {
1080 "closing socket failed\n");
1081 }
1082 gcry_cipher_close (queue->in_cipher);
1083 gcry_cipher_close (queue->out_cipher);
1084 GNUNET_free (queue->address);
1085 if (0 != queue->backpressure)
1086 queue->destroyed = GNUNET_YES;
1087 else
1089
1090 if (NULL == lt)
1091 return;
1092
1093 if ((! shutdown_running) && (NULL == lt->listen_task))
1094 {
1096 "add read net listen\n");
1099 lt->listen_sock,
1100 &listen_cb,
1101 lt);
1102 }
1103 else
1104 GNUNET_free (lt);
1105}

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_NETWORK_get_fd(), GNUNET_NETWORK_socket_close(), GNUNET_NO, GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store_cancel(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_set(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_communicator_mq_del(), GNUNET_YES, listen_cb(), ListenTask::listen_sock, ListenTask::listen_task, lt_map, queue(), queue_map, shutdown_running, and stats.

Referenced by finish_timeout_cb(), get_queue_delete_it(), queue_read(), queue_read_kx(), queue_write(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_hmac()

static void calculate_hmac ( struct GNUNET_CRYPTO_AuthKey hmac_secret,
const void *  buf,
size_t  buf_size,
struct GNUNET_ShortHashCode smac 
)
static

Compute mac over buf, and ratched the hmac_secret.

Parameters
[in,out]hmac_secretsecret for HMAC calculation
bufbuffer to MAC
buf_sizenumber of bytes in buf
[out]smacwhere to write the HMAC

Definition at line 1117 of file gnunet-communicator-tcp.c.

1121{
1122 struct GNUNET_HashCode mac;
1123
1124 GNUNET_CRYPTO_hmac (hmac_secret,
1125 buf,
1126 buf_size,
1127 &mac);
1128 /* truncate to `struct GNUNET_ShortHashCode` */
1129 memcpy (smac, &mac, sizeof(struct GNUNET_ShortHashCode));
1130 /* ratchet hmac key */
1131 GNUNET_CRYPTO_hash (hmac_secret,
1132 sizeof(struct GNUNET_HashCode),
1133 (struct GNUNET_HashCode*) hmac_secret);
1134}

References GNUNET_CRYPTO_hash(), and GNUNET_CRYPTO_hmac().

Referenced by inject_rekey(), mq_send(), queue_finish(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_write()

static void queue_write ( void *  cls)
static

We have been notified that our socket is ready to write.

Then reschedule this function to be called again once more is available.

Parameters
clsa struct Queue

Definition at line 1960 of file gnunet-communicator-tcp.c.

1961{
1962 struct Queue *queue = cls;
1963 ssize_t sent;
1964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n");
1965 queue->write_task = NULL;
1966 if (0 != queue->cwrite_off)
1967 {
1968 sent = GNUNET_NETWORK_socket_send (queue->sock,
1969 queue->cwrite_buf,
1970 queue->cwrite_off);
1972 "Sent %lu bytes to TCP queue\n", sent);
1973 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1974 {
1977 return;
1978 }
1979 if (sent > 0)
1980 {
1981 size_t usent = (size_t) sent;
1982 queue->cwrite_off -= usent;
1983 memmove (queue->cwrite_buf,
1984 &queue->cwrite_buf[usent],
1985 queue->cwrite_off);
1986 queue->timeout =
1989 }
1990 }
1991 {
1992 /* can we encrypt more? (always encrypt full messages, needed
1993 such that #mq_cancel() can work!)
1994
1995 NOTE: this used to be gated on a `we_do_not_need_to_rekey' flag
1996 computed as `0 < rekey_left_bytes - (cwrite_off + pwrite_off +
1997 sizeof (struct TCPRekey))'. That subtraction is unsigned, so it
1998 wrapped to a huge value precisely when the rekey budget was about to
1999 run out -- inverting the test it was meant to express, and reporting
2000 "no rekey needed" even for a @e rekey_left_bytes of zero. The single
2001 value it did get right, exact equality, was worse still: it let the
2002 branch below call #inject_rekey() with a non-empty @e pwrite_buf,
2003 which that function asserts against, and if neither rekey trigger
2004 held it wedged this queue into a busy write loop that never drained
2005 @e pwrite_buf again -- a stall the peer sees as silence while the
2006 socket stays open and the communicator keeps reporting the queue up.
2007
2008 Encrypting a message first and rekeying immediately afterwards
2009 overshoots the byte budget by at most one message, which against the
2010 400 MB default is noise. */
2011 if ((queue->pwrite_off > 0) &&
2012 (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE))
2013 {
2015 "Encrypting %lu bytes\n", queue->pwrite_off);
2016 GNUNET_assert (0 ==
2017 gcry_cipher_encrypt (queue->out_cipher,
2018 &queue->cwrite_buf[queue->cwrite_off],
2019 queue->pwrite_off,
2020 queue->pwrite_buf,
2021 queue->pwrite_off));
2022 if (queue->rekey_left_bytes > queue->pwrite_off)
2023 queue->rekey_left_bytes -= queue->pwrite_off;
2024 else
2025 queue->rekey_left_bytes = 0;
2026 queue->cwrite_off += queue->pwrite_off;
2027 queue->pwrite_off = 0;
2028 }
2029 /* Rekey once the byte budget is spent or the interval elapsed.
2030 #inject_rekey() requires an empty plaintext buffer (it asserts on it)
2031 and enough room in the ciphertext buffer; if either is missing we
2032 simply rekey on a later #queue_write(), which the write task above
2033 keeps arming for as long as anything is still buffered. */
2034 if (((0 == queue->rekey_left_bytes) ||
2036 queue->rekey_time).rel_value_us)) &&
2037 ((0 == queue->pwrite_off) &&
2038 (queue->cwrite_off + sizeof (struct TCPRekey) <= BUF_SIZE)))
2039 {
2041 }
2042 }
2043 if ((0 == queue->pwrite_off) && (! queue->finishing) &&
2044 (GNUNET_YES == queue->mq_awaits_continue))
2045 {
2046 queue->mq_awaits_continue = GNUNET_NO;
2048 }
2049 /* did we just finish writing 'finish'? */
2050 if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing))
2051 {
2053 "Finishing queue\n");
2055 return;
2056 }
2057 /* do we care to write more? */
2058 if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off))
2059 queue->write_task =
2061 queue->sock,
2062 &queue_write,
2063 queue);
2064}

References BUF_SIZE, GNUNET_assert, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror, GNUNET_MQ_impl_send_continue(), GNUNET_NETWORK_socket_send(), GNUNET_NO, GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, inject_rekey(), queue(), queue_destroy(), queue_write(), and GNUNET_TIME_Relative::rel_value_us.

Referenced by mq_init(), mq_send(), proto_read_kx(), queue_finish(), queue_read_kx(), queue_write(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ finish_timeout_cb()

static void finish_timeout_cb ( void *  cls)
static

We gave the queue a chance to flush its finish message and it did not take it (most likely because the peer is gone and the socket never became writable again).

Tear it down anyway: until queue_destroy() runs, transport keeps believing this queue works.

Parameters
clsthe struct Queue * to destroy

Definition at line 1150 of file gnunet-communicator-tcp.c.

1151{
1152 struct Queue *queue = cls;
1153
1154 queue->finish_task = NULL;
1156 "Queue to %s did not flush its FINISH in time, tearing it down\n",
1157 GNUNET_i2s (&queue->target));
1159}

References Queue::finish_task, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, queue(), and queue_destroy().

Referenced by queue_finish().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_finish()

static void queue_finish ( struct Queue queue)
static

Append a 'finish' message to the outgoing transmission.

Once the finish has been transmitted, destroy the queue.

Parameters
queuequeue to shut down nicely

Definition at line 1169 of file gnunet-communicator-tcp.c.

1170{
1171 struct TCPFinish fin;
1172
1173 if (GNUNET_YES == queue->destroyed)
1174 return; /* socket is already gone, we only await backpressure draining */
1175 memset (&fin, 0, sizeof(fin));
1176 fin.header.size = htons (sizeof(fin));
1177 fin.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH);
1178 calculate_hmac (&queue->out_hmac, &fin, sizeof(fin), &fin.hmac);
1179 /* if there is any message left in pwrite_buf, we
1180 overwrite it (possibly dropping the last message
1181 from CORE hard here) */
1182 memcpy (queue->pwrite_buf, &fin, sizeof(fin));
1183 queue->pwrite_off = sizeof(fin);
1184 /* This flag will ensure that #queue_write() no longer
1185 notifies CORE about the possibility of sending
1186 more data, and that #queue_write() will call
1187 #queue_destroy() once the @c fin was fully written. */
1188 queue->finishing = GNUNET_YES;
1189 /* ... but #queue_write() only ever re-arms itself while it still has data
1190 buffered, and #mq_send() returns early for a finishing queue. So unless
1191 we arm the write task here, nothing writes the @c fin, #queue_destroy()
1192 is never reached, and transport is never told that this queue died: it
1193 keeps scheduling transmissions that #mq_send() silently drops, and CORE
1194 never learns about the disconnect. */
1195 if (NULL == queue->write_task)
1196 queue->write_task =
1198 queue->sock,
1199 &queue_write,
1200 queue);
1201 /* And if the peer is gone, the socket may never become writable at all. */
1202 if (NULL == queue->finish_task)
1205 queue);
1206}

References calculate_hmac(), FINISH_TIMEOUT, finish_timeout_cb(), GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, TCPFinish::header, TCPFinish::hmac, queue(), queue_write(), GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by do_rekey(), handshake_ack_monotime_cb(), handshake_monotime_cb(), mq_destroy(), mq_error(), rekey_monotime_cb(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_read()

static void queue_read ( void *  cls)
static

Queue read task.

If we hit the timeout, disconnect it

Parameters
clsthe struct Queue * to disconnect

Definition at line 2345 of file gnunet-communicator-tcp.c.

2346{
2347 struct Queue *queue = cls;
2348 struct GNUNET_TIME_Relative left;
2349 ssize_t rcvd;
2350
2351 queue->read_task = NULL;
2352 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2353 &queue->cread_buf[queue->cread_off],
2354 BUF_SIZE - queue->cread_off);
2356 "Received %zd bytes from TCP queue\n", rcvd);
2357 if (-1 == rcvd)
2358 {
2359 if ((EAGAIN != errno) && (EINTR != errno))
2360 {
2363 return;
2364 }
2365 /* try again */
2366 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2367 if (0 != left.rel_value_us)
2368 {
2369 queue->read_task =
2371 return;
2372 }
2374 "Queue %p was idle for %s, disconnecting\n",
2375 queue,
2378 GNUNET_YES));
2380 return;
2381 }
2382 if (0 == rcvd)
2383 {
2384 /* Orderly shutdown of connection */
2386 "Socket for queue %p seems to have been closed\n", queue);
2388 return;
2389 }
2390 queue->timeout =
2392 queue->cread_off += rcvd;
2393 while ((queue->pread_off < sizeof(queue->pread_buf)) &&
2394 (queue->cread_off > 0))
2395 {
2396 size_t max = GNUNET_MIN (sizeof(queue->pread_buf) - queue->pread_off,
2397 queue->cread_off);
2398 size_t done;
2399 size_t total;
2400 size_t old_pread_off = queue->pread_off;
2401
2402 GNUNET_assert (0 ==
2403 gcry_cipher_decrypt (queue->in_cipher,
2404 &queue->pread_buf[queue->pread_off],
2405 max,
2406 queue->cread_buf,
2407 max));
2408 queue->pread_off += max;
2409 total = 0;
2410 while (0 != (done = try_handle_plaintext (queue)))
2411 {
2412 if (TCP_QUEUE_GONE == done)
2413 return; /* @a queue was destroyed under us, do not touch it */
2414 /* 'done' bytes of plaintext were used, shift buffer */
2415 GNUNET_assert (done <= queue->pread_off);
2416 /* NOTE: this memmove() could possibly sometimes be
2417 avoided if we pass 'total' into try_handle_plaintext()
2418 and use it at an offset into the buffer there! */
2419 memmove (queue->pread_buf,
2420 &queue->pread_buf[done],
2421 queue->pread_off - done);
2422 queue->pread_off -= done;
2423 total += done;
2424 /* The last plaintext was a rekey, abort for now */
2425 if (GNUNET_YES == queue->rekeyed)
2426 break;
2427 }
2428 /* when we encounter a rekey message, the decryption above uses the
2429 wrong key for everything after the rekey; in that case, we have
2430 to re-do the decryption at 'total' instead of at 'max'.
2431 However, we have to take into account that the plaintext buffer may have
2432 already contained data and not jumped too far ahead in the ciphertext.
2433 If there is no rekey and the last message is incomplete (max > total),
2434 it is safe to keep the decryption so we shift by 'max' */
2435 if (GNUNET_YES == queue->rekeyed)
2436 {
2437 max = total - old_pread_off;
2438 queue->rekeyed = GNUNET_NO;
2439 queue->pread_off = 0;
2440 }
2441 memmove (queue->cread_buf, &queue->cread_buf[max], queue->cread_off - max);
2442 queue->cread_off -= max;
2443 }
2444 if (BUF_SIZE == queue->cread_off)
2445 return; /* buffer full, suspend reading */
2446 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2447 if (0 != left.rel_value_us)
2448 {
2449 if (max_queue_length > queue->backpressure)
2450 {
2451 /* continue reading */
2452 queue->read_task =
2454 }
2455 return;
2456 }
2458 "Queue %p was idle for %s, disconnecting\n",
2459 queue,
2462 GNUNET_YES));
2464}

References BUF_SIZE, GNUNET_assert, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_log_strerror, GNUNET_MIN, GNUNET_NETWORK_socket_recv(), GNUNET_NO, GNUNET_SCHEDULER_add_read_net(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, max, max_queue_length, queue(), queue_destroy(), queue_read(), GNUNET_TIME_Relative::rel_value_us, TCP_QUEUE_GONE, and try_handle_plaintext().

Referenced by core_read_finished_cb(), proto_read_kx(), queue_read(), and queue_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ core_read_finished_cb()

static void core_read_finished_cb ( void *  cls,
int  success 
)
static

Core tells us it is done processing a message that transport received on a queue with status success.

Parameters
clsa struct Queue * where the message originally came from
successGNUNET_OK on success

Definition at line 1226 of file gnunet-communicator-tcp.c.

1227{
1228 struct Queue *queue = cls;
1229 if (GNUNET_OK != success)
1231 "# messages lost in communicator API towards CORE",
1232 1,
1233 GNUNET_NO);
1234 if (NULL == queue)
1235 return;
1236
1238 "backpressure %u\n",
1239 queue->backpressure);
1240
1241 queue->backpressure--;
1242 /* handle deferred queue destruction */
1243 if ((queue->destroyed) && (0 == queue->backpressure))
1244 {
1246 return;
1247 }
1248 else if (GNUNET_YES != queue->destroyed)
1249 {
1250 queue->timeout =
1252 );
1253 /* possibly unchoke reading, now that CORE made progress */
1254 if (NULL == queue->read_task)
1255 queue->read_task =
1257 queue->timeout),
1258 queue->sock,
1259 &queue_read,
1260 queue);
1261 }
1262}

References GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, queue(), queue_read(), and stats.

Referenced by pass_plaintext_to_core().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pass_plaintext_to_core()

static void pass_plaintext_to_core ( struct Queue queue,
const void *  plaintext,
size_t  plaintext_len 
)
static

We received plaintext_len bytes of plaintext on queue.

Pass it on to CORE. If transmission is actually happening, increase backpressure counter.

Parameters
queuethe queue that received the plaintext
plaintextthe plaintext that was received
plaintext_lennumber of bytes of plaintext received

Definition at line 1275 of file gnunet-communicator-tcp.c.

1278{
1279 const struct GNUNET_MessageHeader *hdr = plaintext;
1280 int ret;
1281
1283 "pass message from %s to core\n",
1284 GNUNET_i2s (&queue->target));
1285
1286 if (ntohs (hdr->size) != plaintext_len)
1287 {
1288 /* NOTE: If we ever allow multiple CORE messages in one
1289 BOX, this will have to change! */
1290 GNUNET_break (0);
1291 return;
1292 }
1294 &queue->target,
1295 hdr,
1298 queue);
1300 "passed to core\n");
1301 if (GNUNET_OK == ret)
1302 queue->backpressure++;
1303 GNUNET_break (GNUNET_NO != ret); /* backpressure not working!? */
1304 if (GNUNET_SYSERR == ret)
1306 "# bytes lost due to CORE not running",
1307 plaintext_len,
1308 GNUNET_NO);
1309}

References ADDRESS_VALIDITY_PERIOD, ch, core_read_finished_cb(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TRANSPORT_communicator_receive(), queue(), ret, GNUNET_MessageHeader::size, and stats.

Referenced by try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_cipher()

static void setup_cipher ( const struct GNUNET_ShortHashCode prk,
const struct GNUNET_PeerIdentity pid,
gcry_cipher_hd_t *  cipher,
struct GNUNET_CRYPTO_AuthKey hmac_key 
)
static

Setup cipher based on shared secret dh and decrypting peer pid.

Parameters
dhshared secret
piddecrypting peer's identity
[out]ciphercipher to initialize
[out]hmac_keyHMAC key to initialize

Definition at line 1322 of file gnunet-communicator-tcp.c.

1326{
1327 char key[256 / 8];
1328 char ctr[128 / 8];
1329
1330 GNUNET_assert (0 == gcry_cipher_open (cipher,
1331 GCRY_CIPHER_AES256 /* low level: go for speed */
1332 ,
1333 GCRY_CIPHER_MODE_CTR,
1334 0 /* flags */));
1337 key,
1338 sizeof(key),
1339 prk,
1340 GNUNET_CRYPTO_kdf_arg_string ("gnunet-communicator-tcp-key"))
1341 );
1342 GNUNET_assert (0 == gcry_cipher_setkey (*cipher, key, sizeof(key)));
1345 ctr,
1346 sizeof(ctr),
1347 prk,
1348 GNUNET_CRYPTO_kdf_arg_string ("gnunet-communicator-tcp-ctr"))
1349 );
1350 gcry_cipher_setctr (*cipher, ctr, sizeof(ctr));
1353 hmac_key,
1354 sizeof(struct GNUNET_HashCode),
1355 prk,
1356 GNUNET_CRYPTO_kdf_arg_string ("gnunet-communicator-hmac")));
1357}

References GNUNET_assert, GNUNET_CRYPTO_hkdf_expand, GNUNET_CRYPTO_kdf_arg_string, GNUNET_YES, and key.

Referenced by setup_in_cipher(), setup_in_cipher_elligator(), and setup_out_cipher().

Here is the caller graph for this function:

◆ rekey_monotime_store_cb()

static void rekey_monotime_store_cb ( void *  cls,
int  success 
)
static

Callback called when peerstore store operation for rekey monotime value is finished.

Parameters
clsQueue context the store operation was executed.
successStore operation was successful (GNUNET_OK) or not.

Definition at line 1366 of file gnunet-communicator-tcp.c.

1367{
1368 struct Queue *queue = cls;
1369 if (GNUNET_OK != success)
1370 {
1372 "Failed to store rekey monotonic time in PEERSTORE!\n");
1373 }
1374 queue->rekey_monotime_sc = NULL;
1375 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1376}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_PEERSTORE_iteration_next(), and queue().

Referenced by rekey_monotime_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ rekey_monotime_cb()

static void rekey_monotime_cb ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY where found.

Parameters
clsQueue context the store operation was executed.
recordThe record found or NULL if there is no record left.
emsgMessage from peerstore.

Definition at line 1387 of file gnunet-communicator-tcp.c.

1390{
1391 struct Queue *queue = cls;
1392 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1393 struct GNUNET_TIME_Absolute mt;
1394 const struct GNUNET_PeerIdentity *pid;
1395 struct GNUNET_TIME_AbsoluteNBO *rekey_monotonic_time;
1396
1397 (void) emsg;
1398
1399 rekey_monotonic_time = &queue->rekey_monotonic_time;
1400 pid = &queue->target;
1401 if (NULL == record)
1402 {
1403 queue->rekey_monotime_get = NULL;
1404 return;
1405 }
1406 if (sizeof(*mtbe) != record->value_size)
1407 {
1408 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1409 GNUNET_break (0);
1410 return;
1411 }
1412 mtbe = record->value;
1413 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1414 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1415 queue->rekey_monotonic_time).abs_value_us)
1416 {
1418 "Queue from %s dropped, rekey monotime in the past\n",
1419 GNUNET_i2s (&queue->target));
1420 GNUNET_break (0);
1421 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1422 queue->rekey_monotime_get = NULL;
1423 // FIXME: Why should we try to gracefully finish here??
1425 return;
1426 }
1427 queue->rekey_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
1428 "transport_tcp_communicator",
1429 pid,
1431 rekey_monotonic_time,
1432 sizeof(*
1433 rekey_monotonic_time),
1437 queue);
1438}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_log, GNUNET_PEERSTORE_iteration_next(), GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_REPLACE, GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY, GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_UNIT_FOREVER_ABS, peerstore, queue(), queue_finish(), record(), and rekey_monotime_store_cb().

Referenced by do_rekey().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_in_cipher_elligator()

static void setup_in_cipher_elligator ( const struct GNUNET_CRYPTO_HpkeEncapsulation c,
struct Queue queue 
)
static

Setup cipher of queue for decryption from an elligator representative.

Parameters
ephemeralephemeral key we received from the other peer (elligator representative)
[in,out]queuequeue to initialize decryption cipher for

Definition at line 1448 of file gnunet-communicator-tcp.c.

1451{
1452 const struct GNUNET_PeerIdentity *my_identity;
1454 struct GNUNET_CRYPTO_HpkePrivateKey my_hpke_key;
1455 struct GNUNET_ShortHashCode k;
1456
1460
1461 eddsa_priv_to_hpke_key (my_private_key, &my_hpke_key);
1462
1464 c,
1465 &k);
1466 setup_cipher (&k, my_identity, &queue->in_cipher, &queue->in_hmac);
1467}

References eddsa_priv_to_hpke_key(), GNUNET_assert, GNUNET_CRYPTO_hpke_elligator_kem_decaps(), GNUNET_PILS_get_identity(), GNUNET_PILS_key_ring_get_private_key(), key_ring, my_identity, my_private_key, pils, queue(), and setup_cipher().

Referenced by proto_read_kx(), and queue_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_in_cipher()

static void setup_in_cipher ( const struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral,
struct Queue queue 
)
static

Setup cipher of queue for decryption.

Parameters
ephemeralephemeral key we received from the other peer
[in,out]queuequeue to initialize decryption cipher for

Definition at line 1477 of file gnunet-communicator-tcp.c.

References GNUNET_assert, GNUNET_CRYPTO_eddsa_kem_decaps(), GNUNET_PILS_get_identity(), GNUNET_PILS_key_ring_get_private_key(), key_ring, my_identity, my_private_key, pils, queue(), and setup_cipher().

Referenced by do_rekey().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_rekey()

static void do_rekey ( struct Queue queue,
const struct TCPRekey rekey 
)
static

Handle rekey message on queue.

The message was already HMAC'ed, but we should additionally still check the signature. Then we need to stop the old cipher and start afresh.

Parameters
queuethe queue rekey was received on
rekeythe rekey message

Definition at line 1502 of file gnunet-communicator-tcp.c.

1503{
1504 const struct GNUNET_PeerIdentity *my_identity;
1505 struct TcpRekeySignature thp;
1506
1509
1510 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1511 thp.purpose.size = htonl (sizeof(thp));
1513 "do_rekey size %u\n",
1514 thp.purpose.size);
1515 thp.sender = queue->target;
1517 "sender %s\n",
1518 GNUNET_p2s (&thp.sender.public_key));
1520 "sender %s\n",
1521 GNUNET_p2s (&queue->target.public_key));
1522 thp.receiver = *my_identity;
1524 "receiver %s\n",
1525 GNUNET_p2s (&thp.receiver.public_key));
1526 thp.ephemeral = rekey->ephemeral;
1528 "ephemeral %s\n",
1529 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
1530 );
1531 thp.monotonic_time = rekey->monotonic_time;
1533 "time %s\n",
1535 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1536 GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp)));
1537 if (GNUNET_OK !=
1540 &thp,
1541 &rekey->sender_sig,
1542 &queue->target.public_key))
1543 {
1544 GNUNET_break (0);
1545 // FIXME Why should we try to gracefully finish here?
1547 return;
1548 }
1549 queue->rekey_monotonic_time = rekey->monotonic_time;
1550 queue->rekey_monotime_get = GNUNET_PEERSTORE_iteration_start (peerstore,
1551 "transport_tcp_communicator",
1552 &queue->target,
1554 &
1556 queue);
1557 gcry_cipher_close (queue->in_cipher);
1558 queue->rekeyed = GNUNET_YES;
1559 setup_in_cipher (&rekey->ephemeral, queue);
1560}

References TCPRekey::ephemeral, TcpRekeySignature::ephemeral, GNUNET_assert, GNUNET_break, GNUNET_CRYPTO_eddsa_verify, GNUNET_e2s(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_OK, GNUNET_p2s(), GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY, GNUNET_PILS_get_identity(), GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY, GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_absolute_ntoh(), GNUNET_YES, TCPRekey::monotonic_time, TcpRekeySignature::monotonic_time, my_identity, peerstore, pils, GNUNET_PeerIdentity::public_key, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpRekeySignature::purpose, queue(), queue_finish(), TcpRekeySignature::receiver, rekey_monotime_cb(), TcpRekeySignature::sender, TCPRekey::sender_sig, setup_in_cipher(), and GNUNET_CRYPTO_SignaturePurpose::size.

Referenced by try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handshake_ack_monotime_store_cb()

static void handshake_ack_monotime_store_cb ( void *  cls,
int  success 
)
static

Callback called when peerstore store operation for handshake ack monotime value is finished.

Parameters
clsQueue context the store operation was executed.
successStore operation was successful (GNUNET_OK) or not.

Definition at line 1569 of file gnunet-communicator-tcp.c.

1570{
1571 struct Queue *queue = cls;
1572
1573 if (GNUNET_OK != success)
1574 {
1576 "Failed to store handshake ack monotonic time in PEERSTORE!\n");
1577 }
1578 queue->handshake_ack_monotime_sc = NULL;
1579 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1580}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_PEERSTORE_iteration_next(), and queue().

Referenced by handshake_ack_monotime_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handshake_ack_monotime_cb()

static void handshake_ack_monotime_cb ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK where found.

Parameters
clsQueue context the store operation was executed.
recordThe record found or NULL if there is no record left.
emsgMessage from peerstore.

Definition at line 1591 of file gnunet-communicator-tcp.c.

1594{
1595 struct Queue *queue = cls;
1596 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1597 struct GNUNET_TIME_Absolute mt;
1598 const struct GNUNET_PeerIdentity *pid;
1599 struct GNUNET_TIME_AbsoluteNBO *handshake_ack_monotonic_time;
1600
1601 (void) emsg;
1602
1603 handshake_ack_monotonic_time = &queue->handshake_ack_monotonic_time;
1604 pid = &queue->target;
1605 if (NULL == record)
1606 {
1607 queue->handshake_ack_monotime_get = NULL;
1608 return;
1609 }
1610 if (sizeof(*mtbe) != record->value_size)
1611 {
1612 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1613 GNUNET_break (0);
1614 return;
1615 }
1616 mtbe = record->value;
1617 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1618 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
1619 queue->handshake_ack_monotonic_time).abs_value_us)
1620 {
1622 "Queue from %s dropped, handshake ack monotime in the past\n",
1623 GNUNET_i2s (&queue->target));
1624 GNUNET_break (0);
1625 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1626 queue->handshake_ack_monotime_get = NULL;
1627 // FIXME: Why should we try to gracefully finish here?
1629 return;
1630 }
1631 queue->handshake_ack_monotime_sc =
1633 "transport_tcp_communicator",
1634 pid,
1636 handshake_ack_monotonic_time,
1637 sizeof(*handshake_ack_monotonic_time),
1641 queue);
1642}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_log, GNUNET_PEERSTORE_iteration_next(), GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_REPLACE, GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK, GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_UNIT_FOREVER_ABS, handshake_ack_monotime_store_cb(), peerstore, queue(), queue_finish(), and record().

Referenced by try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_challenge()

static void send_challenge ( struct GNUNET_CRYPTO_ChallengeNonceP  challenge,
struct Queue queue 
)
static

Sending challenge with TcpConfirmationAck back to sender of ephemeral key.

Parameters
tcThe TCPConfirmation originally send.
queueThe queue context.

Definition at line 1652 of file gnunet-communicator-tcp.c.

1654{
1655 const struct GNUNET_PeerIdentity *my_identity;
1657 struct TCPConfirmationAck tca;
1658 struct TcpHandshakeAckSignature thas;
1659
1663
1665 "sending challenge\n");
1666
1667 tca.header.type = ntohs (
1669 tca.header.size = ntohs (sizeof(tca));
1670 tca.challenge = challenge;
1671 tca.sender = *my_identity;
1672 tca.monotonic_time =
1674 thas.purpose.purpose = htonl (
1676 thas.purpose.size = htonl (sizeof(thas));
1677 thas.sender = *my_identity;
1678 thas.receiver = queue->target;
1679 thas.monotonic_time = tca.monotonic_time;
1680 thas.challenge = tca.challenge;
1682 &thas,
1683 &tca.sender_sig);
1684 GNUNET_assert (0 ==
1685 gcry_cipher_encrypt (queue->out_cipher,
1686 &queue->cwrite_buf[queue->cwrite_off],
1687 sizeof(tca),
1688 &tca,
1689 sizeof(tca)));
1690 queue->cwrite_off += sizeof(tca);
1692 "sending challenge done\n");
1693}

References cfg, TcpHandshakeAckSignature::challenge, TCPConfirmationAck::challenge, GNUNET_assert, GNUNET_CRYPTO_eddsa_sign, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK, GNUNET_PILS_get_identity(), GNUNET_PILS_key_ring_get_private_key(), GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK, GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), TCPConfirmationAck::header, key_ring, TcpHandshakeAckSignature::monotonic_time, TCPConfirmationAck::monotonic_time, my_identity, my_private_key, pils, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpHandshakeAckSignature::purpose, queue(), TcpHandshakeAckSignature::receiver, TcpHandshakeAckSignature::sender, TCPConfirmationAck::sender, TCPConfirmationAck::sender_sig, GNUNET_MessageHeader::size, GNUNET_CRYPTO_SignaturePurpose::size, and GNUNET_MessageHeader::type.

Referenced by queue_read_kx(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_out_cipher()

static void setup_out_cipher ( struct Queue queue,
struct GNUNET_ShortHashCode dh 
)
static

Setup cipher for outgoing data stream based on target and our ephemeral private key.

Parameters
queuequeue to setup outgoing (encryption) cipher for

Definition at line 1703 of file gnunet-communicator-tcp.c.

1704{
1705 setup_cipher (dh, &queue->target, &queue->out_cipher, &queue->out_hmac);
1707 queue->rekey_left_bytes =
1709}

References GNUNET_CRYPTO_random_u64(), GNUNET_TIME_relative_to_absolute(), queue(), rekey_interval, rekey_max_bytes, and setup_cipher().

Referenced by inject_rekey(), and start_initial_kx_out().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ inject_rekey()

static void inject_rekey ( struct Queue queue)
static

Inject a struct TCPRekey message into the queue's plaintext buffer.

Parameters
queuequeue to perform rekeying on

Definition at line 1719 of file gnunet-communicator-tcp.c.

1720{
1721 const struct GNUNET_PeerIdentity *my_identity;
1723 struct TCPRekey rekey;
1724 struct TcpRekeySignature thp;
1725 struct GNUNET_ShortHashCode k;
1726
1730
1731 GNUNET_assert (0 == queue->pwrite_off);
1732 memset (&rekey, 0, sizeof(rekey));
1733 GNUNET_CRYPTO_eddsa_kem_encaps (&queue->target.public_key, &rekey.ephemeral,
1734 &k);
1735 rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY);
1736 rekey.header.size = ntohs (sizeof(rekey));
1737 rekey.monotonic_time =
1739 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1740 thp.purpose.size = htonl (sizeof(thp));
1742 "inject_rekey size %u\n",
1743 thp.purpose.size);
1744 thp.sender = *my_identity;
1746 "sender %s\n",
1747 GNUNET_p2s (&thp.sender.public_key));
1748 thp.receiver = queue->target;
1750 "receiver %s\n",
1751 GNUNET_p2s (&thp.receiver.public_key));
1752 thp.ephemeral = rekey.ephemeral;
1754 "ephemeral %s\n",
1755 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
1756 );
1757 thp.monotonic_time = rekey.monotonic_time;
1759 "time %s\n",
1761 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1763 &thp,
1764 &rekey.sender_sig);
1765 calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac);
1766 /* Encrypt rekey message with 'old' cipher */
1767 GNUNET_assert (0 ==
1768 gcry_cipher_encrypt (queue->out_cipher,
1769 &queue->cwrite_buf[queue->cwrite_off],
1770 sizeof(rekey),
1771 &rekey,
1772 sizeof(rekey)));
1773 queue->cwrite_off += sizeof(rekey);
1774 /* Setup new cipher for successive messages */
1775 gcry_cipher_close (queue->out_cipher);
1776 setup_out_cipher (queue, &k);
1777}

References calculate_hmac(), cfg, TCPRekey::ephemeral, TcpRekeySignature::ephemeral, GNUNET_assert, GNUNET_CRYPTO_eddsa_kem_encaps(), GNUNET_CRYPTO_eddsa_sign, GNUNET_e2s(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY, GNUNET_p2s(), GNUNET_PILS_get_identity(), GNUNET_PILS_key_ring_get_private_key(), GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY, GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_absolute_ntoh(), TCPRekey::header, TCPRekey::hmac, key_ring, TCPRekey::monotonic_time, TcpRekeySignature::monotonic_time, my_identity, my_private_key, pils, GNUNET_PeerIdentity::public_key, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpRekeySignature::purpose, queue(), TcpRekeySignature::receiver, TcpRekeySignature::sender, TCPRekey::sender_sig, setup_out_cipher(), GNUNET_MessageHeader::size, GNUNET_CRYPTO_SignaturePurpose::size, and GNUNET_MessageHeader::type.

Referenced by queue_write().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pending_reversal_key()

static void pending_reversal_key ( const struct sockaddr *  in,
const struct GNUNET_PeerIdentity target,
struct GNUNET_HashCode key 
)
static

Compute the key under which a pending NAT reversal request to target at in is stored in pending_reversals.

The peer identity MUST be part of the key: the addresses we request a reversal for have their port set to zero (that is what marks them as "behind a NAT"), and several peers can sit behind the same NAT and thus share one IP. Keying on the address alone made the second such peer collide with the first, so that mq_init() refused to ever create a queue for it ("There is already a request reversal") until NAT_TIMEOUT.

Parameters
inaddress the reversal is sent to, the port is ignored
targetpeer we would like to talk to
[out]keyset to the hash map key

Definition at line 1796 of file gnunet-communicator-tcp.c.

1799{
1800 struct sockaddr_in v4;
1801 struct GNUNET_HashContext *hsh;
1802
1803 GNUNET_assert (AF_INET == in->sa_family);
1804 GNUNET_memcpy (&v4, in, sizeof(v4));
1805 v4.sin_port = 0;
1807 GNUNET_CRYPTO_hash_context_read (hsh, &v4, sizeof(v4));
1808 GNUNET_CRYPTO_hash_context_read (hsh, target, sizeof(*target));
1810}

References GNUNET_assert, GNUNET_CRYPTO_hash_context_finish(), GNUNET_CRYPTO_hash_context_read(), GNUNET_CRYPTO_hash_context_start(), GNUNET_memcpy, and key.

Referenced by check_and_remove_pending_reversal(), mq_init(), and pending_reversal_timeout().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pending_reversals_delete_it()

static int pending_reversals_delete_it ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 1814 of file gnunet-communicator-tcp.c.

1817{
1818 struct PendingReversal *pending_reversal = value;
1819 (void) cls;
1820
1821 if (NULL != pending_reversal->timeout_task)
1822 {
1823 GNUNET_SCHEDULER_cancel (pending_reversal->timeout_task);
1824 pending_reversal->timeout_task = NULL;
1825 }
1828 key,
1829 pending_reversal));
1830 GNUNET_free (pending_reversal->in);
1831 GNUNET_free (pending_reversal);
1832 return GNUNET_OK;
1833}

References GNUNET_assert, GNUNET_CONTAINER_multihashmap_remove(), GNUNET_free, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_YES, PendingReversal::in, key, pending_reversals, PendingReversal::timeout_task, and value.

Referenced by check_and_remove_pending_reversal(), and do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_and_remove_pending_reversal()

static void check_and_remove_pending_reversal ( struct sockaddr *  in,
sa_family_t  sa_family,
const struct GNUNET_PeerIdentity sender 
)
static

We got a connection with sender at in, so a NAT reversal we may have requested for that peer has served its purpose (or will never do so).

Drop it, freeing the slot for further reversal requests.

Note that this must be scoped to sender: another peer behind the same NAT may have a reversal of its own pending at the very same IP, and that one is none of our business here.

Parameters
inaddress we are talking to the peer at
sa_familyaddress family of in
senderidentity of the peer at in

Definition at line 1850 of file gnunet-communicator-tcp.c.

1852{
1853 if (AF_INET == sa_family)
1854 {
1855 struct PendingReversal *pending_reversal;
1856 struct GNUNET_HashCode key;
1857
1858 pending_reversal_key (in, sender, &key);
1860 &key);
1861 if (NULL != pending_reversal)
1862 {
1864 "Removing completed pending reversal for `%s' at `%s'\n",
1865 GNUNET_i2s (&pending_reversal->target),
1866 GNUNET_a2s (in, sizeof (struct sockaddr)));
1867 pending_reversals_delete_it (NULL, &key, pending_reversal);
1868 }
1869 }
1870}

References GNUNET_a2s(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, key, pending_reversal_key(), pending_reversals, pending_reversals_delete_it(), and PendingReversal::target.

Referenced by proto_read_kx(), and try_handle_plaintext().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_proto_queue()

static void free_proto_queue ( struct ProtoQueue pq)
static

Closes socket and frees memory associated with pq.

Parameters
pqproto queue to free

Definition at line 1879 of file gnunet-communicator-tcp.c.

1880{
1881 if (NULL != pq->listen_sock)
1882 {
1884 pq->listen_sock = NULL;
1885 }
1886 if (NULL != pq->read_task)
1887 {
1889 pq->read_task = NULL;
1890 }
1891 if (NULL != pq->write_task)
1892 {
1894 pq->write_task = NULL;
1895 }
1896 /* NOTE: deliberately no #check_and_remove_pending_reversal() here. A proto
1897 queue is anonymous -- we have not completed the KX, so we do not know
1898 which peer this was. Dropping "the" pending reversal for the IP used to
1899 cancel the reversal of an unrelated peer that happens to sit behind the
1900 same NAT. A reversal that truly went nowhere expires on #NAT_TIMEOUT. */
1902 GNUNET_free (pq->address);
1904 GNUNET_free (pq);
1905}

References ProtoQueue::address, GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_SCHEDULER_cancel(), ProtoQueue::listen_sock, proto_head, proto_tail, ProtoQueue::read_task, ProtoQueue::sock, and ProtoQueue::write_task.

Referenced by do_shutdown(), proto_queue_write(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ proto_queue_write()

static void proto_queue_write ( void *  cls)
static

We have been notified that our socket is ready to write.

Then reschedule this function to be called again once more is available.

Parameters
clsa struct ProtoQueue

Definition at line 1915 of file gnunet-communicator-tcp.c.

1916{
1917 struct ProtoQueue *pq = cls;
1918 ssize_t sent;
1919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In proto queue write\n");
1920 pq->write_task = NULL;
1921 if (0 != pq->write_off)
1922 {
1923 sent = GNUNET_NETWORK_socket_send (pq->sock,
1924 pq->write_buf,
1925 pq->write_off);
1927 "Sent %lu bytes to TCP queue\n", sent);
1928 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1929 {
1931 free_proto_queue (pq);
1932 return;
1933 }
1934 if (sent > 0)
1935 {
1936 size_t usent = (size_t) sent;
1937 pq->write_off -= usent;
1938 memmove (pq->write_buf,
1939 &pq->write_buf[usent],
1940 pq->write_off);
1941 }
1942 }
1943 /* do we care to write more? */
1944 if ((0 < pq->write_off))
1945 pq->write_task =
1947 pq->sock,
1949 pq);
1950}

References free_proto_queue(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_send(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, proto_queue_write(), ProtoQueue::sock, ProtoQueue::write_buf, ProtoQueue::write_off, and ProtoQueue::write_task.

Referenced by proto_queue_write(), and try_connection_reversal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_handle_plaintext()

static size_t try_handle_plaintext ( struct Queue queue)
static

Test if we have received a full message in plaintext.

If so, handle it.

Parameters
queuequeue to process inbound plaintext for
Returns
number of bytes of plaintext handled, 0 for none

Once we received this ack, we consider this a verified connection. FIXME: I am not sure this logic is sane here.

Definition at line 2075 of file gnunet-communicator-tcp.c.

2076{
2077 const struct GNUNET_MessageHeader *hdr;
2078 const struct TCPConfirmationAck *tca;
2079 const struct TCPBox *box;
2080 const struct TCPRekey *rekey;
2081 const struct TCPFinish *fin;
2082 struct TCPRekey rekeyz;
2083 struct TCPFinish finz;
2084 struct GNUNET_ShortHashCode tmac;
2085 uint16_t type;
2086 size_t size = 0;
2087 struct TcpHandshakeAckSignature thas;
2088 const struct GNUNET_PeerIdentity *my_identity;
2089 const struct GNUNET_CRYPTO_ChallengeNonceP challenge = queue->challenge;
2090
2092 "try handle plaintext!\n");
2093
2094 hdr = (const struct GNUNET_MessageHeader *) queue->pread_buf;
2095 if ((sizeof(*hdr) > queue->pread_off))
2096 {
2098 "Handling plaintext, not even a header!\n");
2099 return 0; /* not even a header */
2100 }
2101
2102 if ((GNUNET_YES != queue->initial_core_kx_done) && (queue->unverified_size >
2104 {
2106 "Already received data of size %lu bigger than KX size %lu!\n",
2107 queue->unverified_size,
2109 GNUNET_break_op (0);
2111 return 0;
2112 }
2113
2114 type = ntohs (hdr->type);
2115 switch (type)
2116 {
2118 tca = (const struct TCPConfirmationAck *) queue->pread_buf;
2120 "start processing ack\n");
2121 if (sizeof(*tca) > queue->pread_off)
2122 {
2124 "Handling plaintext size of tca greater than pread offset.\n")
2125 ;
2126 return 0;
2127 }
2128 if (ntohs (hdr->size) != sizeof(*tca))
2129 {
2131 "Handling plaintext size does not match message type.\n");
2132 GNUNET_break_op (0);
2134 return 0;
2135 }
2136
2139
2140 thas.purpose.purpose = htonl (
2142 thas.purpose.size = htonl (sizeof(thas));
2143 thas.sender = tca->sender;
2144 thas.receiver = *my_identity;
2145 thas.monotonic_time = tca->monotonic_time;
2146 thas.challenge = tca->challenge;
2147
2150 &thas,
2151 &tca->sender_sig,
2152 &tca->sender.public_key))
2153 {
2155 "Verification of signature failed!\n");
2156 GNUNET_break (0);
2158 return 0;
2159 }
2160 if (0 != GNUNET_memcmp (&tca->challenge, &challenge))
2161 {
2163 "Challenge in TCPConfirmationAck not correct!\n");
2164 GNUNET_break (0);
2166 return 0;
2167 }
2168
2169 queue->handshake_ack_monotime_get = GNUNET_PEERSTORE_iteration_start (
2170 peerstore,
2171 "transport_tcp_communicator",
2172 &queue->target,
2175 queue);
2176
2178 "Handling plaintext, ack processed!\n");
2179
2181 {
2182 send_challenge (queue->challenge_received, queue);
2183 queue->write_task =
2185 queue->sock,
2186 &queue_write,
2187 queue);
2188 }
2189 else if (GNUNET_TRANSPORT_CS_OUTBOUND == queue->cs)
2190 {
2192 queue->address->sa_family,
2193 &queue->target);
2194 }
2195
2200 queue->initial_core_kx_done = GNUNET_YES;
2201
2202 {
2203 char *foreign_addr;
2204
2205 switch (queue->address->sa_family)
2206 {
2207 case AF_INET:
2208 GNUNET_asprintf (&foreign_addr,
2209 "%s-%s",
2211 GNUNET_a2s (queue->address, queue->address_len));
2212 break;
2213
2214 case AF_INET6:
2215 GNUNET_asprintf (&foreign_addr,
2216 "%s-%s",
2218 GNUNET_a2s (queue->address, queue->address_len));
2219 break;
2220
2221 default:
2222 GNUNET_assert (0);
2223 }
2225 &queue->target,
2226 foreign_addr,
2227 UINT16_MAX, /* no MTU */
2229 0, /* Priority */
2230 queue->nt,
2231 queue->cs,
2232 queue->mq);
2233
2234 GNUNET_free (foreign_addr);
2235 }
2236
2237 size = ntohs (hdr->size);
2238 break;
2240 /* Special case: header size excludes box itself! */
2241 box = (const struct TCPBox *) queue->pread_buf;
2242 if (ntohs (hdr->size) + sizeof(struct TCPBox) > queue->pread_off)
2243 return 0;
2244 calculate_hmac (&queue->in_hmac, &box[1], ntohs (hdr->size), &tmac);
2245 if (0 != memcmp (&tmac, &box->hmac, sizeof(tmac)))
2246 {
2247 GNUNET_break_op (0);
2249 return 0;
2250 }
2251 pass_plaintext_to_core (queue, (const void *) &box[1], ntohs (hdr->size));
2252 size = ntohs (hdr->size) + sizeof(*box);
2254 "Handling plaintext, box processed!\n");
2256 "# bytes decrypted with BOX",
2257 size,
2258 GNUNET_NO);
2260 "# messages decrypted with BOX",
2261 1,
2262 GNUNET_NO);
2263 break;
2264
2266 rekey = (const struct TCPRekey *) queue->pread_buf;
2267 if (sizeof(*rekey) > queue->pread_off)
2268 return 0;
2269 if (ntohs (hdr->size) != sizeof(*rekey))
2270 {
2271 GNUNET_break_op (0);
2273 return 0;
2274 }
2275 rekeyz = *rekey;
2276 memset (&rekeyz.hmac, 0, sizeof(rekeyz.hmac));
2277 calculate_hmac (&queue->in_hmac, &rekeyz, sizeof(rekeyz), &tmac);
2278 if (0 != memcmp (&tmac, &rekey->hmac, sizeof(tmac)))
2279 {
2280 GNUNET_break_op (0);
2282 return 0;
2283 }
2284 do_rekey (queue, rekey);
2285 size = ntohs (hdr->size);
2287 "Handling plaintext, rekey processed!\n");
2289 "# rekeying successful",
2290 1,
2291 GNUNET_NO);
2292 break;
2293
2295 fin = (const struct TCPFinish *) queue->pread_buf;
2296 if (sizeof(*fin) > queue->pread_off)
2297 return 0;
2298 if (ntohs (hdr->size) != sizeof(*fin))
2299 {
2300 GNUNET_break_op (0);
2302 return 0;
2303 }
2304 finz = *fin;
2305 memset (&finz.hmac, 0, sizeof(finz.hmac));
2306 calculate_hmac (&queue->in_hmac, &finz, sizeof(finz), &tmac);
2307 if (0 != memcmp (&tmac, &fin->hmac, sizeof(tmac)))
2308 {
2309 GNUNET_break_op (0);
2311 return 0;
2312 }
2313 /* handle FINISH by destroying queue */
2315 "Handling plaintext, finish processed!\n");
2317 /* NOTE: must return here rather than `break'. #queue_destroy() releases
2318 @a queue outright once its backpressure has drained, so neither the
2319 @e unverified_size accounting below nor #queue_read()'s loop may look
2320 at it again. Falling through also hit `GNUNET_assert (0 != size)'
2321 with @a size still zero -- receiving a perfectly ordinary FINISH thus
2322 aborted the communicator, taking every other queue down with it. */
2323 return TCP_QUEUE_GONE;
2324
2325 default:
2327 "Handling plaintext, nothing processed!\n");
2328 GNUNET_break_op (0);
2330 return 0;
2331 }
2332 GNUNET_assert (0 != size);
2333 if (-1 != queue->unverified_size)
2334 queue->unverified_size += size;
2335 return size;
2336}

References calculate_hmac(), ch, TcpHandshakeAckSignature::challenge, TCPConfirmationAck::challenge, check_and_remove_pending_reversal(), COMMUNICATOR_ADDRESS_PREFIX, do_rekey(), GNUNET_a2s(), GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CRYPTO_eddsa_verify, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_memcmp, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY, GNUNET_NO, GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK, GNUNET_PILS_get_identity(), GNUNET_SCHEDULER_add_write_net(), GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_communicator_mq_add(), GNUNET_TRANSPORT_CS_INBOUND, GNUNET_TRANSPORT_CS_OUTBOUND, GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, GNUNET_YES, handshake_ack_monotime_cb(), TCPBox::hmac, TCPRekey::hmac, TCPFinish::hmac, INITIAL_CORE_KX_SIZE, TcpHandshakeAckSignature::monotonic_time, TCPConfirmationAck::monotonic_time, GNUNET_TRANSPORT_CommunicatorHandle::mq, my_identity, pass_plaintext_to_core(), peerstore, pils, GNUNET_PeerIdentity::public_key, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpHandshakeAckSignature::purpose, queue(), queue_destroy(), queue_finish(), queue_write(), TcpHandshakeAckSignature::receiver, send_challenge(), TcpHandshakeAckSignature::sender, TCPConfirmationAck::sender, TCPConfirmationAck::sender_sig, GNUNET_MessageHeader::size, GNUNET_CRYPTO_SignaturePurpose::size, size, stats, TCP_QUEUE_GONE, type, and GNUNET_MessageHeader::type.

Referenced by queue_read().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ tcp_address_to_sockaddr_numeric_v6()

static struct sockaddr * tcp_address_to_sockaddr_numeric_v6 ( socklen_t *  sock_len,
struct sockaddr_in6  v6,
unsigned int  port 
)
static

Convert a struct sockaddr_in6 to astruct sockaddr *`.

Parameters
[out]sock_lenset to the length of the address.
v6The sockaddr_in6 to be converted.
Returns
The struct sockaddr *.

Definition at line 2475 of file gnunet-communicator-tcp.c.

2478{
2479 struct sockaddr *in;
2480
2481 v6.sin6_family = AF_INET6;
2482 v6.sin6_port = htons ((uint16_t) port);
2483#if HAVE_SOCKADDR_IN_SIN_LEN
2484 v6.sin6_len = sizeof(struct sockaddr_in6);
2485#endif
2486 v6.sin6_flowinfo = 0;
2487 v6.sin6_scope_id = 0;
2488 in = GNUNET_memdup (&v6, sizeof(v6));
2489 *sock_len = sizeof(struct sockaddr_in6);
2490
2491 return in;
2492}

References GNUNET_memdup, and port.

Referenced by init_socket_resolv(), run(), tcp_address_to_sockaddr(), and tcp_address_to_sockaddr_port_only().

Here is the caller graph for this function:

◆ tcp_address_to_sockaddr_numeric_v4()

static struct sockaddr * tcp_address_to_sockaddr_numeric_v4 ( socklen_t *  sock_len,
struct sockaddr_in  v4,
unsigned int  port 
)
static

Convert a struct sockaddr_in4 to astruct sockaddr *`.

Parameters
[out]sock_lenset to the length of the address.
v4The sockaddr_in4 to be converted.
Returns
The struct sockaddr *.

Definition at line 2503 of file gnunet-communicator-tcp.c.

2506{
2507 struct sockaddr *in;
2508
2509 v4.sin_family = AF_INET;
2510 v4.sin_port = htons ((uint16_t) port);
2511#if HAVE_SOCKADDR_IN_SIN_LEN
2512 v4.sin_len = sizeof(struct sockaddr_in);
2513#endif
2514 in = GNUNET_memdup (&v4, sizeof(v4));
2515 *sock_len = sizeof(struct sockaddr_in);
2516 return in;
2517}

References GNUNET_memdup, and port.

Referenced by init_socket_resolv(), run(), tcp_address_to_sockaddr(), and tcp_address_to_sockaddr_port_only().

Here is the caller graph for this function:

◆ tcp_address_to_sockaddr_port_only()

static struct PortOnlyIpv4Ipv6 * tcp_address_to_sockaddr_port_only ( const char *  bindto,
unsigned int *  port 
)
static

Convert TCP bind specification to a struct PortOnlyIpv4Ipv6 *

Parameters
bindtobind specification to convert.
Returns
The converted bindto specification.

Definition at line 2527 of file gnunet-communicator-tcp.c.

2528{
2529 struct PortOnlyIpv4Ipv6 *po;
2530 struct sockaddr_in *i4;
2531 struct sockaddr_in6 *i6;
2532 socklen_t sock_len_ipv4;
2533 socklen_t sock_len_ipv6;
2534
2535 /* interpreting value as just a PORT number */
2536 if (*port > UINT16_MAX)
2537 {
2539 "BINDTO specification `%s' invalid: value too large for port\n",
2540 bindto);
2541 return NULL;
2542 }
2543
2544 po = GNUNET_new (struct PortOnlyIpv4Ipv6);
2545
2546 if (GNUNET_YES == disable_v6)
2547 {
2548 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2549 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2550 *port);
2551 po->addr_len_ipv4 = sock_len_ipv4;
2552 }
2553 else
2554 {
2555
2556 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2557 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2558 *port);
2559 po->addr_len_ipv4 = sock_len_ipv4;
2560
2561 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
2562 po->addr_ipv6 = tcp_address_to_sockaddr_numeric_v6 (&sock_len_ipv6, *i6,
2563 *port);
2564
2565 po->addr_len_ipv6 = sock_len_ipv6;
2566
2567 GNUNET_free (i6);
2568 }
2569
2570 GNUNET_free (i4);
2571
2572 return po;
2573}

References PortOnlyIpv4Ipv6::addr_ipv4, PortOnlyIpv4Ipv6::addr_ipv6, PortOnlyIpv4Ipv6::addr_len_ipv4, PortOnlyIpv4Ipv6::addr_len_ipv6, disable_v6, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_new, GNUNET_YES, port, tcp_address_to_sockaddr_numeric_v4(), and tcp_address_to_sockaddr_numeric_v6().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ extract_address()

static char * extract_address ( const char *  bindto)
static

This Method extracts the address part of the BINDTO string.

Parameters
bindtoString we extract the address part from.
Returns
The extracted address string.

Definition at line 2583 of file gnunet-communicator-tcp.c.

2584{
2585 char *addr;
2586 char *start;
2587 char *token;
2588 char *cp;
2589 char *rest = NULL;
2590
2592 "extract address with bindto %s\n",
2593 bindto);
2594
2595 if (NULL == bindto)
2597 "bindto is NULL\n");
2598
2599 cp = GNUNET_strdup (bindto);
2600
2602 "extract address 2\n");
2603
2604 start = cp;
2605 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
2606 {
2607 start++; /* skip over '['*/
2608 cp[strlen (cp) - 1] = '\0'; /* eat ']'*/
2609 addr = GNUNET_strdup (start);
2610 }
2611 else
2612 {
2613 token = strtok_r (cp, "]", &rest);
2614 if (strlen (bindto) == strlen (token))
2615 {
2616 token = strtok_r (cp, ":", &rest);
2617 addr = GNUNET_strdup (token);
2618 }
2619 else
2620 {
2621 token++;
2622 addr = GNUNET_strdup (token);
2623 }
2624 }
2625
2627 "tcp address: %s\n",
2628 addr);
2629 GNUNET_free (cp);
2630 return addr;
2631}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_strdup, and start.

Referenced by run(), and tcp_address_to_sockaddr().

Here is the caller graph for this function:

◆ extract_port()

static unsigned int extract_port ( const char *  addr_and_port)
static

This Method extracts the port part of the BINDTO string.

Parameters
addr_and_portString we extract the port from.
Returns
The extracted port as unsigned int.

Definition at line 2641 of file gnunet-communicator-tcp.c.

2642{
2643 unsigned int port;
2644 char dummy[2];
2645 char *token;
2646 char *addr;
2647 char *colon;
2648 char *cp;
2649 char *rest = NULL;
2650
2651 if (NULL != addr_and_port)
2652 {
2653 cp = GNUNET_strdup (addr_and_port);
2654 token = strtok_r (cp, "]", &rest);
2655 if (strlen (addr_and_port) == strlen (token))
2656 {
2657 colon = strrchr (cp, ':');
2658 if (NULL == colon)
2659 {
2660 GNUNET_free (cp);
2661 return 0;
2662 }
2663 addr = colon;
2664 addr++;
2665 }
2666 else
2667 {
2668 token = strtok_r (NULL, "]", &rest);
2669 if (NULL == token)
2670 {
2671 GNUNET_free (cp);
2672 return 0;
2673 }
2674 else
2675 {
2676 addr = token;
2677 addr++;
2678 }
2679 }
2680
2681
2682 if (1 == sscanf (addr, "%u%1s", &port, dummy))
2683 {
2684 /* interpreting value as just a PORT number */
2685 if (port > UINT16_MAX)
2686 {
2688 "Port `%u' invalid: value too large for port\n",
2689 port);
2690 GNUNET_free (cp);
2691 return 0;
2692 }
2693 }
2694 else
2695 {
2697 "BINDTO specification invalid: last ':' not followed by number\n");
2698 GNUNET_free (cp);
2699 return 0;
2700 }
2701 GNUNET_free (cp);
2702 }
2703 else
2704 {
2706 "return 0\n");
2707 /* interpret missing port as 0, aka pick any free one */
2708 port = 0;
2709 }
2710
2711 return port;
2712}

References dummy, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_strdup, and port.

Referenced by run(), and tcp_address_to_sockaddr().

Here is the caller graph for this function:

◆ tcp_address_to_sockaddr()

static struct sockaddr * tcp_address_to_sockaddr ( const char *  bindto,
socklen_t *  sock_len 
)
static

Convert TCP bind specification to a struct sockaddr *

Parameters
bindtobind specification to convert
[out]sock_lenset to the length of the address
Returns
converted bindto specification

Definition at line 2723 of file gnunet-communicator-tcp.c.

2724{
2725 struct sockaddr *in;
2726 unsigned int port;
2727 struct sockaddr_in v4;
2728 struct sockaddr_in6 v6;
2729 char *start;
2730
2731 memset (&v4, 0, sizeof(v4));
2732 start = extract_address (bindto);
2733 GNUNET_assert (NULL != start);
2735 "start %s\n",
2736 start);
2737
2739 "!bindto %s\n",
2740 bindto);
2741
2742
2743 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
2744 {
2745 port = extract_port (bindto);
2746
2748 "port %u\n",
2749 port);
2750
2751 in = tcp_address_to_sockaddr_numeric_v4 (sock_len, v4, port);
2752 }
2753 else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
2754 {
2755 port = extract_port (bindto);
2756 in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port);
2757 }
2758 else
2759 {
2760 GNUNET_assert (0);
2761 }
2762
2764 return in;
2765}

References extract_address(), extract_port(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, port, start, tcp_address_to_sockaddr_numeric_v4(), and tcp_address_to_sockaddr_numeric_v6().

Referenced by mq_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_send()

static void mq_send ( struct GNUNET_MQ_Handle mq,
const struct GNUNET_MessageHeader msg,
void *  impl_state 
)
static

Signature of functions implementing the sending functionality of a message queue.

Parameters
mqthe message queue
msgthe message to send
impl_stateour struct Queue

Definition at line 2777 of file gnunet-communicator-tcp.c.

2780{
2781 struct Queue *queue = impl_state;
2782 uint16_t msize = ntohs (msg->size);
2783 struct TCPBox box;
2785 "In MQ send. Queue finishing: %s; write task running: %s\n",
2786 (GNUNET_YES == queue->finishing) ? "yes" : "no",
2787 (NULL == queue->write_task) ? "yes" : "no");
2788 GNUNET_assert (mq == queue->mq);
2789 queue->mq_awaits_continue = GNUNET_YES;
2790 if (GNUNET_YES == queue->finishing)
2791 return; /* this queue is dying, drop msg */
2792 GNUNET_assert (0 == queue->pwrite_off);
2793 box.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX);
2794 box.header.size = htons (msize);
2795 calculate_hmac (&queue->out_hmac, msg, msize, &box.hmac);
2796 memcpy (&queue->pwrite_buf[queue->pwrite_off], &box, sizeof(box));
2797 queue->pwrite_off += sizeof(box);
2798 memcpy (&queue->pwrite_buf[queue->pwrite_off], msg, msize);
2799 queue->pwrite_off += msize;
2801 "%lu bytes of plaintext to send\n", queue->pwrite_off);
2802 GNUNET_assert (NULL != queue->sock);
2803 if (NULL == queue->write_task)
2804 queue->write_task =
2806 queue->sock,
2807 &queue_write,
2808 queue);
2809}

References calculate_hmac(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX, GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, TCPBox::header, TCPBox::hmac, mq, msg, queue(), queue_write(), GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by boot_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_destroy()

static void mq_destroy ( struct GNUNET_MQ_Handle mq,
void *  impl_state 
)
static

Signature of functions implementing the destruction of a message queue.

Implementations must not free mq, but should take care of impl_state.

Parameters
mqthe message queue to destroy
impl_stateour struct Queue

Definition at line 2821 of file gnunet-communicator-tcp.c.

2822{
2823 struct Queue *queue = impl_state;
2824
2825 if (mq == queue->mq)
2826 {
2827 queue->mq = NULL;
2829 }
2830}

References mq, Queue::mq, queue(), and queue_finish().

Referenced by boot_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_cancel()

static void mq_cancel ( struct GNUNET_MQ_Handle mq,
void *  impl_state 
)
static

Implementation function that cancels the currently sent message.

Parameters
mqmessage queue
impl_stateour struct Queue

Definition at line 2840 of file gnunet-communicator-tcp.c.

2841{
2842 struct Queue *queue = impl_state;
2843
2844 GNUNET_assert (0 != queue->pwrite_off);
2845 queue->pwrite_off = 0;
2846}

References GNUNET_assert, and queue().

Referenced by boot_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_error()

static void mq_error ( void *  cls,
enum GNUNET_MQ_Error  error 
)
static

Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.

Not every message queue implementation supports an error handler.

Parameters
clsour struct Queue
errorerror code

Definition at line 2859 of file gnunet-communicator-tcp.c.

2860{
2861 struct Queue *queue = cls;
2862
2864 "MQ error in queue to %s: %d\n",
2865 GNUNET_i2s (&queue->target),
2866 (int) error);
2868}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_log, queue(), and queue_finish().

Referenced by boot_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ boot_queue()

static void boot_queue ( struct Queue queue)
static

Add the given queue to our internal data structure.

Setup the MQ processing and inform transport that the queue is ready. Must be called after the KX for outgoing messages has been bootstrapped.

Parameters
queuequeue to boot

Definition at line 2879 of file gnunet-communicator-tcp.c.

2880{
2881 queue->nt =
2882 GNUNET_NT_scanner_get_type (is, queue->address, queue->address_len);
2884 queue_map,
2885 &queue->key,
2886 queue,
2889 "# queues active",
2891 GNUNET_NO);
2892 queue->timeout =
2895 &mq_destroy,
2896 &mq_cancel,
2897 queue,
2898 NULL,
2899 &mq_error,
2900 queue);
2901}

References GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_MQ_queue_for_callbacks(), GNUNET_NO, GNUNET_NT_scanner_get_type(), GNUNET_STATISTICS_set(), GNUNET_TIME_relative_to_absolute(), is, mq_cancel(), mq_destroy(), mq_error(), mq_send(), queue(), queue_map, and stats.

Referenced by mq_init(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transmit_kx()

static void transmit_kx ( struct Queue queue,
const struct GNUNET_CRYPTO_HpkeEncapsulation c 
)
static

Generate and transmit our ephemeral key and the signature for the initial KX with the other peer.

Must be called first, before any other bytes are ever written to the output buffer. Note that our cipher must already be initialized when calling this function. Helper function for start_initial_kx_out().

Parameters
queuequeue to do KX for
epubour public key for the KX

Definition at line 2915 of file gnunet-communicator-tcp.c.

2917{
2918 const struct GNUNET_PeerIdentity *my_identity;
2920 struct TcpHandshakeSignature ths;
2921 struct TCPConfirmation tc;
2922
2926
2927 memcpy (queue->cwrite_buf, c, sizeof(*c));
2928 queue->cwrite_off = sizeof(*c);
2929 /* compute 'tc' and append in encrypted format to cwrite_buf */
2930 tc.sender = *my_identity;
2931 tc.monotonic_time =
2933 GNUNET_CRYPTO_random_block (&tc.challenge,
2934 sizeof(tc.challenge));
2935 ths.purpose.purpose = htonl (
2937 ths.purpose.size = htonl (sizeof(ths));
2938 ths.sender = *my_identity;
2939 ths.receiver = queue->target;
2940 ths.ephemeral = *c;
2941 ths.monotonic_time = tc.monotonic_time;
2942 ths.challenge = tc.challenge;
2944 &ths,
2945 &tc.sender_sig);
2946 GNUNET_assert (0 ==
2947 gcry_cipher_encrypt (queue->out_cipher,
2948 &queue->cwrite_buf[queue->cwrite_off],
2949 sizeof(tc),
2950 &tc,
2951 sizeof(tc)));
2952 queue->challenge = tc.challenge;
2953 queue->cwrite_off += sizeof(tc);
2954
2956 "handshake written\n");
2957}

References cfg, TcpHandshakeSignature::challenge, TcpHandshakeSignature::ephemeral, GNUNET_assert, GNUNET_CRYPTO_eddsa_sign, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_PILS_get_identity(), GNUNET_PILS_key_ring_get_private_key(), GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE, GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), key_ring, TcpHandshakeSignature::monotonic_time, my_identity, my_private_key, pils, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpHandshakeSignature::purpose, queue(), TcpHandshakeSignature::receiver, TcpHandshakeSignature::sender, GNUNET_CRYPTO_SignaturePurpose::size, and tc.

Referenced by start_initial_kx_out().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_initial_kx_out()

static void start_initial_kx_out ( struct Queue queue)
static

Initialize our key material for outgoing transmissions and inform the other peer about it.

Must be called first before any data is sent.

Parameters
queuethe queue to setup

Definition at line 2968 of file gnunet-communicator-tcp.c.

2969{
2971 struct GNUNET_ShortHashCode k;
2972
2974 &c, &k);
2975 setup_out_cipher (queue, &k);
2976 transmit_kx (queue, &c);
2977}

References GNUNET_CRYPTO_hpke_elligator_kem_encaps(), queue(), setup_out_cipher(), and transmit_kx().

Referenced by mq_init(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handshake_monotime_store_cb()

static void handshake_monotime_store_cb ( void *  cls,
int  success 
)
static

Callback called when peerstore store operation for handshake monotime is finished.

Parameters
clsQueue context the store operation was executed.
successStore operation was successful (GNUNET_OK) or not.

Definition at line 2986 of file gnunet-communicator-tcp.c.

2987{
2988 struct Queue *queue = cls;
2989 if (GNUNET_OK != success)
2990 {
2992 "Failed to store handshake monotonic time in PEERSTORE!\n");
2993 }
2994 queue->handshake_monotime_sc = NULL;
2995 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
2996}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_PEERSTORE_iteration_next(), and queue().

Referenced by handshake_monotime_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handshake_monotime_cb()

static void handshake_monotime_cb ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE where found.

Parameters
clsQueue context the store operation was executed.
recordThe record found or NULL if there is no record left.
emsgMessage from peerstore.

Definition at line 3007 of file gnunet-communicator-tcp.c.

3010{
3011 struct Queue *queue = cls;
3012 struct GNUNET_TIME_AbsoluteNBO *mtbe;
3013 struct GNUNET_TIME_Absolute mt;
3014 const struct GNUNET_PeerIdentity *pid;
3015 struct GNUNET_TIME_AbsoluteNBO *handshake_monotonic_time;
3016
3017 (void) emsg;
3018
3019 handshake_monotonic_time = &queue->handshake_monotonic_time;
3020 pid = &queue->target;
3022 "tcp handshake with us %s\n",
3024 if (NULL == record)
3025 {
3026 queue->handshake_monotime_get = NULL;
3027 return;
3028 }
3030 "tcp handshake from peer %s\n",
3031 GNUNET_i2s (pid));
3032 if (sizeof(*mtbe) != record->value_size)
3033 {
3034 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
3035 GNUNET_break (0);
3036 return;
3037 }
3038 mtbe = record->value;
3039 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
3040 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
3041 queue->handshake_monotonic_time).abs_value_us)
3042 {
3044 "Queue from %s dropped, handshake monotime in the past\n",
3045 GNUNET_i2s (&queue->target));
3046 GNUNET_break (0);
3047 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
3048 queue->handshake_ack_monotime_get = NULL;
3050 return;
3051 }
3052 queue->handshake_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
3053 "transport_tcp_communicator",
3054 pid,
3056 handshake_monotonic_time,
3057 sizeof(*
3058 handshake_monotonic_time),
3061 &
3063 queue);
3064}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_log, GNUNET_PEERSTORE_iteration_next(), GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_REPLACE, GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE, GNUNET_PILS_get_identity(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_UNIT_FOREVER_ABS, handshake_monotime_store_cb(), peerstore, pils, queue(), queue_finish(), and record().

Referenced by decrypt_and_check_tc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ decrypt_and_check_tc()

static int decrypt_and_check_tc ( struct Queue queue,
struct TCPConfirmation tc,
char *  ibuf 
)
static

We have received the first bytes from the other side on a queue.

Decrypt the tc contained in ibuf and check the signature. Note that setup_in_cipher() must have already been called.

Parameters
queuequeue to decrypt initial bytes from other peer for
[out]tcwhere to store the result
ibufincoming data, of size INITIAL_KX_SIZE
Returns
GNUNET_OK if the signature was OK, GNUNET_SYSERR if not

Definition at line 3079 of file gnunet-communicator-tcp.c.

3082{
3083 const struct GNUNET_PeerIdentity *my_identity;
3084 struct TcpHandshakeSignature ths;
3086
3089
3091 0 ==
3092 gcry_cipher_decrypt (queue->in_cipher,
3093 tc,
3094 sizeof(*tc),
3095 &ibuf[sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)],
3096 sizeof(*tc)));
3097 ths.purpose.purpose = htonl (
3099 ths.purpose.size = htonl (sizeof(ths));
3100 ths.sender = tc->sender;
3101 ths.receiver = *my_identity;
3102 memcpy (&ths.ephemeral, ibuf, sizeof(struct GNUNET_CRYPTO_EcdhePublicKey));
3103 ths.monotonic_time = tc->monotonic_time;
3104 ths.challenge = tc->challenge;
3107 &ths,
3108 &tc->sender_sig,
3109 &tc->sender.public_key);
3110 if (GNUNET_YES == ret)
3111 queue->handshake_monotime_get =
3113 "transport_tcp_communicator",
3114 &queue->target,
3117 queue);
3118 return ret;
3119}

References TcpHandshakeSignature::challenge, TcpHandshakeSignature::ephemeral, GNUNET_assert, GNUNET_CRYPTO_eddsa_verify, GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE, GNUNET_PILS_get_identity(), GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE, GNUNET_YES, handshake_monotime_cb(), TcpHandshakeSignature::monotonic_time, my_identity, peerstore, pils, GNUNET_CRYPTO_SignaturePurpose::purpose, TcpHandshakeSignature::purpose, queue(), TcpHandshakeSignature::receiver, ret, TcpHandshakeSignature::sender, GNUNET_CRYPTO_SignaturePurpose::size, and tc.

Referenced by proto_read_kx(), and queue_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_read_kx()

static void queue_read_kx ( void *  cls)
static

Read from the socket of the queue until we have enough data to initialize the decryption logic and can switch to regular reading.

Parameters
clsa struct Queue

Definition at line 3130 of file gnunet-communicator-tcp.c.

3131{
3132 struct Queue *queue = cls;
3133 ssize_t rcvd;
3134 struct GNUNET_TIME_Relative left;
3135 struct TCPConfirmation tc;
3136
3137 queue->read_task = NULL;
3138 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
3139 if (0 == left.rel_value_us)
3140 {
3142 return;
3143 }
3144 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
3145 &queue->cread_buf[queue->cread_off],
3146 BUF_SIZE - queue->cread_off);
3148 "Received %lu bytes to write in buffer of size %lu for KX from queue %p (expires in %"
3149 PRIu64 ")\n",
3150 rcvd, BUF_SIZE - queue->cread_off, queue, left.rel_value_us);
3151 if (-1 == rcvd)
3152 {
3153 if ((EAGAIN != errno) && (EINTR != errno))
3154 {
3157 return;
3158 }
3159 queue->read_task =
3161 return;
3162 }
3163 if (0 == rcvd)
3164 {
3165 /* Orderly shutdown of connection */
3167 "Socket for queue %p seems to have been closed\n", queue);
3169 return;
3170 }
3171 queue->cread_off += rcvd;
3172 if (queue->cread_off < INITIAL_KX_SIZE)
3173 {
3174 /* read more */
3176 "%lu/%lu bytes of KX read. Rescheduling...\n",
3177 queue->cread_off, INITIAL_KX_SIZE);
3178 queue->read_task =
3180 return;
3181 }
3182 /* we got all the data, let's find out who we are talking to! */
3184 (const struct GNUNET_CRYPTO_HpkeEncapsulation*)
3185 queue->cread_buf,
3186 queue);
3187 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
3188 {
3190 "Invalid TCP KX received from %s\n",
3191 GNUNET_a2s (queue->address, queue->address_len));
3193 return;
3194 }
3195 if (0 !=
3196 memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
3197 {
3199 "Invalid sender in TCP KX received from %s\n",
3200 GNUNET_a2s (queue->address, queue->address_len));
3202 return;
3203 }
3204 send_challenge (tc.challenge, queue);
3205 queue->write_task =
3207 queue->sock,
3208 &queue_write,
3209 queue);
3210
3211 /* update queue timeout */
3212 queue->timeout =
3214 /* prepare to continue with regular read task immediately */
3215 memmove (queue->cread_buf,
3216 &queue->cread_buf[INITIAL_KX_SIZE],
3217 queue->cread_off - (INITIAL_KX_SIZE));
3219 "cread_off is %lu bytes before adjusting\n",
3220 queue->cread_off);
3221 queue->cread_off -= INITIAL_KX_SIZE;
3223 "cread_off set to %lu bytes\n",
3224 queue->cread_off);
3226}

References BUF_SIZE, decrypt_and_check_tc(), GNUNET_a2s(), GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_recv(), GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_FOREVER_REL, INITIAL_KX_SIZE, queue(), queue_destroy(), queue_read(), queue_read_kx(), queue_write(), GNUNET_TIME_Relative::rel_value_us, send_challenge(), setup_in_cipher_elligator(), and tc.

Referenced by mq_init(), proto_read_kx(), and queue_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ proto_read_kx()

static void proto_read_kx ( void *  cls)
static

Read from the socket of the proto queue until we have enough data to upgrade to full queue.

Parameters
clsa struct ProtoQueue

Definition at line 3236 of file gnunet-communicator-tcp.c.

3237{
3238 struct ProtoQueue *pq = cls;
3239 ssize_t rcvd;
3240 struct GNUNET_TIME_Relative left;
3241 struct Queue *queue;
3242 struct TCPConfirmation tc;
3244
3245 pq->read_task = NULL;
3247 if (0 == left.rel_value_us)
3248 {
3249 free_proto_queue (pq);
3250 return;
3251 }
3252 rcvd = GNUNET_NETWORK_socket_recv (pq->sock,
3253 &pq->ibuf[pq->ibuf_off],
3254 sizeof(pq->ibuf) - pq->ibuf_off);
3256 "Proto received %lu bytes for KX\n", rcvd);
3257 if (-1 == rcvd)
3258 {
3259 if ((EAGAIN != errno) && (EINTR != errno))
3260 {
3262 free_proto_queue (pq);
3263 return;
3264 }
3265 /* try again */
3266 pq->read_task =
3268 return;
3269 }
3270 if (0 == rcvd)
3271 {
3272 /* Orderly shutdown of connection */
3274 "Socket for proto queue %p seems to have been closed\n", pq);
3275 free_proto_queue (pq);
3276 return;
3277 }
3278 pq->ibuf_off += rcvd;
3279 if (sizeof (struct TCPNATProbeMessage) == pq->ibuf_off)
3280 {
3281 struct TCPNATProbeMessage *pm = (struct TCPNATProbeMessage *) pq->ibuf;
3282
3284 &pm->clientIdentity);
3285
3286 queue = GNUNET_new (struct Queue);
3287 queue->target = pm->clientIdentity;
3288 eddsa_pub_to_hpke_key (&queue->target.public_key,
3289 &queue->target_hpke_key);
3292 }
3293 else if (pq->ibuf_off < sizeof(pq->ibuf))
3294 {
3295 /* read more */
3296 pq->read_task =
3298 return;
3299 }
3300 else
3301 {
3302 /* we got all the data, let's find out who we are talking to! */
3303 queue = GNUNET_new (struct Queue);
3305 (const struct GNUNET_CRYPTO_HpkeEncapsulation *) pq->
3306 ibuf,
3307 queue);
3308 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
3309 {
3311 "Invalid TCP KX received from %s\n",
3312 GNUNET_a2s (pq->address, pq->address_len));
3313 gcry_cipher_close (queue->in_cipher);
3315 free_proto_queue (pq);
3316 return;
3317 }
3318 queue->target = tc.sender;
3319 eddsa_pub_to_hpke_key (&queue->target.public_key,
3320 &queue->target_hpke_key);
3323 }
3324 queue->address = pq->address; /* steals reference */
3325 queue->address_len = pq->address_len;
3326 queue->listen_sock = pq->listen_sock;
3327 queue->sock = pq->sock;
3328
3330 "created queue with target %s\n",
3331 GNUNET_i2s (&queue->target));
3332
3334 "start kx proto\n");
3335
3337 boot_queue (queue);
3338 queue->read_task =
3340 queue->sock,
3341 read_task,
3342 queue);
3343 queue->write_task =
3345 queue->sock,
3346 &queue_write,
3347 queue);
3348 // TODO To early! Move it somewhere else.
3349 // send_challenge (tc.challenge, queue);
3350 queue->challenge_received = tc.challenge;
3351
3353 GNUNET_free (pq);
3354}

References ProtoQueue::address, ProtoQueue::address_len, boot_queue(), check_and_remove_pending_reversal(), TCPNATProbeMessage::clientIdentity, decrypt_and_check_tc(), eddsa_pub_to_hpke_key(), free_proto_queue(), GNUNET_a2s(), GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_recv(), GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_CS_INBOUND, GNUNET_TRANSPORT_CS_OUTBOUND, ProtoQueue::ibuf, ProtoQueue::ibuf_off, ProtoQueue::listen_sock, proto_head, proto_read_kx(), proto_tail, queue(), queue_read(), queue_read_kx(), queue_write(), read_task, ProtoQueue::read_task, GNUNET_TIME_Relative::rel_value_us, setup_in_cipher_elligator(), ProtoQueue::sock, start_initial_kx_out(), tc, and ProtoQueue::timeout.

Referenced by create_proto_queue(), and proto_read_kx().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_proto_queue()

static struct ProtoQueue * create_proto_queue ( struct GNUNET_NETWORK_Handle sock,
struct sockaddr *  in,
socklen_t  addrlen 
)
static

Definition at line 3358 of file gnunet-communicator-tcp.c.

3361{
3362 struct ProtoQueue *pq = GNUNET_new (struct ProtoQueue);
3363
3364 if (NULL == sock)
3365 {
3366 // sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
3367 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 0);
3368 if (NULL == sock)
3369 {
3371 "socket(%d) failed: %s",
3372 in->sa_family,
3373 strerror (errno));
3374 GNUNET_free (in);
3375 GNUNET_free (pq);
3376 return NULL;
3377 }
3378 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, addrlen)) &&
3379 (errno != EINPROGRESS))
3380 {
3382 "connect to `%s' failed: %s",
3383 GNUNET_a2s (in, addrlen),
3384 strerror (errno));
3386 GNUNET_free (in);
3387 GNUNET_free (pq);
3388 return NULL;
3389 }
3390 }
3391 pq->address_len = addrlen;
3392 pq->address = in;
3394 pq->sock = sock;
3396 pq->sock,
3398 pq);
3400
3401 return pq;
3402}

References ProtoQueue::address, ProtoQueue::address_len, GNUNET_a2s(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_connect(), GNUNET_NETWORK_socket_create(), GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_relative_to_absolute(), proto_head, PROTO_QUEUE_TIMEOUT, proto_read_kx(), proto_tail, ProtoQueue::read_task, ProtoQueue::sock, and ProtoQueue::timeout.

Referenced by listen_cb(), and try_connection_reversal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_connection_reversal()

static void try_connection_reversal ( void *  cls,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Definition at line 3452 of file gnunet-communicator-tcp.c.

3455{
3456 const struct GNUNET_PeerIdentity *my_identity;
3457 struct TCPNATProbeMessage pm;
3458 struct ProtoQueue *pq;
3459 struct sockaddr *in_addr;
3460 (void) cls;
3461
3464
3466 "addr->sa_family %d\n",
3467 addr->sa_family);
3469 "Try to connect back\n");
3470 in_addr = GNUNET_memdup (addr, addrlen);
3472 "in_addr->sa_family %d\n",
3473 in_addr->sa_family);
3474 pq = create_proto_queue (NULL, in_addr, addrlen);
3475 if (NULL != pq)
3476 {
3477 pm.header.size = htons (sizeof(struct TCPNATProbeMessage));
3478 pm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
3479 pm.clientIdentity = *my_identity;
3480 memcpy (pq->write_buf, &pm, sizeof(struct TCPNATProbeMessage));
3481 pq->write_off = sizeof(struct TCPNATProbeMessage);
3483 pq->sock,
3485 pq);
3486 }
3487 else
3488 {
3490 "Couldn't create ProtoQueue for sending TCPNATProbeMessage\n");
3491 }
3492}

References TCPNATProbeMessage::clientIdentity, create_proto_queue(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_memdup, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE, GNUNET_PILS_get_identity(), GNUNET_SCHEDULER_add_write_net(), TCPNATProbeMessage::header, my_identity, pils, PROTO_QUEUE_TIMEOUT, proto_queue_write(), GNUNET_MessageHeader::size, ProtoQueue::sock, GNUNET_MessageHeader::type, ProtoQueue::write_buf, ProtoQueue::write_off, and ProtoQueue::write_task.

Referenced by nat_register().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pending_reversal_timeout()

static void pending_reversal_timeout ( void *  cls)
static

Definition at line 3496 of file gnunet-communicator-tcp.c.

3497{
3498 struct PendingReversal *pending_reversal = cls;
3499 struct GNUNET_HashCode key;
3500
3501 pending_reversal->timeout_task = NULL;
3502 pending_reversal_key (pending_reversal->in,
3503 &pending_reversal->target,
3504 &key);
3506 &key,
3507 pending_reversal))
3509 "No pending reversal found for address %s\n",
3510 GNUNET_a2s (pending_reversal->in,
3511 sizeof (struct sockaddr)));
3512 GNUNET_free (pending_reversal->in);
3513 GNUNET_free (pending_reversal);
3514}

References GNUNET_a2s(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_NO, PendingReversal::in, key, pending_reversal_key(), pending_reversals, PendingReversal::target, and PendingReversal::timeout_task.

Referenced by mq_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_init()

static int mq_init ( void *  cls,
const struct GNUNET_PeerIdentity peer,
const char *  address 
)
static

Function called by the transport service to initialize a message queue given address information about another peer.

If and when the communication channel is established, the communicator must call GNUNET_TRANSPORT_communicator_mq_add() to notify the service that the channel is now up. It is the responsibility of the communicator to manage sane retries and timeouts for any peer/address combination provided by the transport service. Timeouts and retries do not need to be signalled to the transport service.

Parameters
clsclosure
peeridentity of the other peer
addresswhere to send the message, human-readable communicator-specific format, 0-terminated, UTF-8
Returns
GNUNET_OK on success, GNUNET_SYSERR if the provided address is invalid

Definition at line 3536 of file gnunet-communicator-tcp.c.

3537{
3538 struct sockaddr *in;
3539 socklen_t in_len = 0;
3540 const char *path;
3541 struct sockaddr_in *v4;
3542 struct sockaddr_in6 *v6;
3543 unsigned int is_natd = GNUNET_NO;
3544 struct GNUNET_HashCode key;
3545 struct GNUNET_HashCode queue_map_key;
3546 struct GNUNET_HashContext *hsh;
3547 struct Queue *queue;
3548
3550 "Connecting to %s at %s\n",
3551 GNUNET_i2s (peer),
3552 address);
3553 if (0 != strncmp (address,
3555 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
3556 {
3557 GNUNET_break_op (0);
3558 return GNUNET_SYSERR;
3559 }
3560 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
3561 in = tcp_address_to_sockaddr (path, &in_len);
3562
3563 if (NULL == in)
3564 {
3566 "Failed to setup TCP socket address\n");
3567 return GNUNET_SYSERR;
3568 }
3569
3571 "in %s\n",
3572 GNUNET_a2s (in, in_len));
3573
3574 if (AF_INET6 == in->sa_family)
3575 {
3576 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *) in;
3577
3578 /* A link-local address is only meaningful together with the interface
3579 it was learned on, and that scope does not survive being carried to
3580 another host in a HELLO. connect() to one with a zero scope id fails
3581 with EINVAL every single time, so trying is pure noise: peers gossip
3582 these by the dozen and each attempt logged a WARNING. */
3583 if (IN6_IS_ADDR_LINKLOCAL (&v6->sin6_addr) && (0 == v6->sin6_scope_id))
3584 {
3586 "Skipping unusable link-local address `%s' for `%s'\n",
3587 address,
3588 GNUNET_i2s (peer));
3589 GNUNET_free (in);
3590 return GNUNET_SYSERR;
3591 }
3592 }
3593
3596 GNUNET_CRYPTO_hash_context_read (hsh, peer, sizeof (*peer));
3597 GNUNET_CRYPTO_hash_context_finish (hsh, &queue_map_key);
3599
3600 if (NULL != queue)
3601 {
3603 "Queue for %s already exists or is in construction\n", address);
3604 GNUNET_free (in);
3605 return GNUNET_NO;
3606 }
3607 switch (in->sa_family)
3608 {
3609 case AF_INET:
3610 v4 = (struct sockaddr_in *) in;
3611 if (0 == v4->sin_port)
3612 {
3613 is_natd = GNUNET_YES;
3614 pending_reversal_key (in, peer, &key);
3617 &key))
3618 {
3620 "There is already a request reversal for `%s' at `%s'\n",
3621 GNUNET_i2s (peer),
3622 address);
3623 GNUNET_free (in);
3624 return GNUNET_SYSERR;
3625 }
3626 }
3627 break;
3628
3629 case AF_INET6:
3630 if (GNUNET_YES == disable_v6)
3631 {
3633 "IPv6 disabled, skipping %s\n", address);
3634 GNUNET_free (in);
3635 return GNUNET_SYSERR;
3636 }
3637 v6 = (struct sockaddr_in6 *) in;
3638 if (0 == v6->sin6_port)
3639 {
3641 "Request reversal for `%s' at `%s' not possible for an IPv6 address\n",
3642 GNUNET_i2s (peer),
3643 address);
3644 GNUNET_free (in);
3645 return GNUNET_SYSERR;
3646 }
3647 break;
3648
3649 default:
3650 GNUNET_assert (0);
3651 }
3652
3653 if (GNUNET_YES == is_natd)
3654 {
3655 struct sockaddr_in local_sa;
3656 struct PendingReversal *pending_reversal;
3657
3658 memset (&local_sa, 0, sizeof(local_sa));
3659 local_sa.sin_family = AF_INET;
3660 local_sa.sin_port = htons (bind_port);
3661 /* We leave sin_address at 0, let the kernel figure it out,
3662 even if our bind() is more specific. (May want to reconsider
3663 later.) */
3664 if (GNUNET_OK != GNUNET_NAT_request_reversal (nat, &local_sa, v4))
3665 {
3667 "request reversal for `%s' at `%s' failed\n",
3668 GNUNET_i2s (peer),
3669 address);
3670 GNUNET_free (in);
3671 return GNUNET_SYSERR;
3672 }
3673 pending_reversal = GNUNET_new (struct PendingReversal);
3674 pending_reversal->in = in;
3677 &key,
3678 pending_reversal,
3680 pending_reversal->target = *peer;
3681 pending_reversal->timeout_task = GNUNET_SCHEDULER_add_delayed (
3684 pending_reversal);
3686 "Created NAT WAIT connection to `%s' at `%s'\n",
3687 GNUNET_i2s (peer),
3688 GNUNET_a2s (in, sizeof (struct sockaddr)));
3689 }
3690 else
3691 {
3692 struct GNUNET_NETWORK_Handle *sock;
3693
3694 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM,
3695 IPPROTO_TCP);
3696 if (NULL == sock)
3697 {
3699 "socket(%d) failed: %s",
3700 in->sa_family,
3701 strerror (errno));
3702 GNUNET_free (in);
3703 return GNUNET_SYSERR;
3704 }
3705 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
3706 (errno != EINPROGRESS))
3707 {
3709 "connect to `%s' failed: %s",
3710 address,
3711 strerror (errno));
3713 GNUNET_free (in);
3714 return GNUNET_SYSERR;
3715 }
3716
3717 queue = GNUNET_new (struct Queue);
3718 queue->target = *peer;
3719 eddsa_pub_to_hpke_key (&queue->target.public_key, &queue->target_hpke_key);
3720 queue->key = queue_map_key;
3721 queue->address = in;
3722 queue->address_len = in_len;
3723 queue->sock = sock;
3725 boot_queue (queue);
3727 "booted queue with target %s\n",
3728 GNUNET_i2s (&queue->target));
3729 // queue->mq_awaits_continue = GNUNET_YES;
3730 queue->read_task =
3732 queue->sock,
3734 queue);
3735
3736
3738 "start kx mq_init\n");
3739
3741 queue->write_task =
3743 queue->sock,
3744 &queue_write,
3745 queue);
3746 }
3747
3748 return GNUNET_OK;
3749}

References address, bind_port, boot_queue(), COMMUNICATOR_ADDRESS_PREFIX, disable_v6, eddsa_pub_to_hpke_key(), GNUNET_a2s(), GNUNET_assert, GNUNET_break_op, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash_context_finish(), GNUNET_CRYPTO_hash_context_read(), GNUNET_CRYPTO_hash_context_start(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_NAT_request_reversal(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_connect(), GNUNET_NETWORK_socket_create(), GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_write_net(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_CS_OUTBOUND, GNUNET_YES, PendingReversal::in, key, nat, NAT_TIMEOUT, pending_reversal_key(), pending_reversal_timeout(), pending_reversals, queue(), queue_map, queue_read_kx(), queue_write(), start_initial_kx_out(), PendingReversal::target, tcp_address_to_sockaddr(), and PendingReversal::timeout_task.

Referenced by init_socket().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_lt_delete_it()

static int get_lt_delete_it ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Iterator over all ListenTasks to clean up.

Parameters
clsNULL
keyunused
valuethe ListenTask to cancel.
Returns
GNUNET_OK to continue to iterate

Definition at line 3761 of file gnunet-communicator-tcp.c.

3764{
3765 struct ListenTask *lt = value;
3766
3767 (void) cls;
3768 (void) key;
3769 if (NULL != lt->listen_task)
3770 {
3772 lt->listen_task = NULL;
3773 }
3774 if (NULL != lt->listen_sock)
3775 {
3777 lt->listen_sock = NULL;
3778 }
3779 GNUNET_free (lt);
3780 return GNUNET_OK;
3781}

References GNUNET_break, GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_SCHEDULER_cancel(), key, ListenTask::listen_sock, ListenTask::listen_task, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_queue_delete_it()

static int get_queue_delete_it ( void *  cls,
const struct GNUNET_HashCode target,
void *  value 
)
static

Iterator over all message queues to clean up.

Parameters
clsNULL
targetunused
valuethe queue to destroy
Returns
GNUNET_OK to continue to iterate

Definition at line 3793 of file gnunet-communicator-tcp.c.

3796{
3797 struct Queue *queue = value;
3798
3799 (void) cls;
3800 (void) target;
3802 return GNUNET_OK;
3803}

References GNUNET_OK, queue(), queue_destroy(), Queue::target, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_shutdown()

static void do_shutdown ( void *  cls)
static

Shutdown the UNIX communicator.

Parameters
clsNULL (always)

Definition at line 3812 of file gnunet-communicator-tcp.c.

3813{
3815 "Shutdown %s!\n",
3816 shutdown_running ? "running" : "not running");
3817
3819 return;
3820 else
3822
3823 while (NULL != proto_head)
3825 if (NULL != nat)
3826 {
3828 nat = NULL;
3829 }
3837 if (NULL != ch)
3838 {
3841 ch = NULL;
3842 }
3843 if (NULL != stats)
3844 {
3846 stats = NULL;
3847 }
3848 if (NULL != is)
3849 {
3851 is = NULL;
3852 }
3853 if (NULL != pils)
3854 {
3856 pils = NULL;
3857 }
3858 if (NULL != key_ring)
3859 {
3861 key_ring = NULL;
3862 }
3863 if (NULL != peerstore)
3864 {
3866 peerstore = NULL;
3867 }
3868 if (NULL != resolve_request_handle)
3869 {
3872 }
3874 "Shutdown done!\n");
3875}

References ch, free_proto_queue(), get_lt_delete_it(), get_queue_delete_it(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NAT_unregister(), GNUNET_NT_scanner_done(), GNUNET_PEERSTORE_disconnect(), GNUNET_PILS_destroy_key_ring(), GNUNET_PILS_disconnect(), GNUNET_RESOLVER_request_cancel(), GNUNET_STATISTICS_destroy(), GNUNET_TRANSPORT_communicator_address_remove_all(), GNUNET_TRANSPORT_communicator_disconnect(), GNUNET_YES, is, key_ring, lt_map, nat, peerstore, pending_reversals, pending_reversals_delete_it(), pils, proto_head, queue_map, resolve_request_handle, shutdown_running, and stats.

Here is the call graph for this function:

◆ enc_notify_cb()

static void enc_notify_cb ( void *  cls,
const struct GNUNET_PeerIdentity sender,
const struct GNUNET_MessageHeader msg 
)
static

Function called when the transport service has received an acknowledgement for this communicator (!) via a different return path.

Not applicable for TCP.

Parameters
clsclosure
senderwhich peer sent the notification
msgpayload

Definition at line 3890 of file gnunet-communicator-tcp.c.

3893{
3894 (void) cls;
3895 (void) sender;
3896 (void) msg;
3897 GNUNET_break_op (0);
3898}

References GNUNET_break_op, and msg.

Referenced by init_socket().

Here is the caller graph for this function:

◆ nat_address_cb()

static void nat_address_cb ( void *  cls,
void **  app_ctx,
int  add_remove,
enum GNUNET_NAT_AddressClass  ac,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of 'valid' addresses changes.

Parameters
clsclosure
[in,out]app_ctxlocation where the app can store stuff on add and retrieve it on remove
add_removeGNUNET_YES to add a new public IP address, GNUNET_NO to remove a previous (now invalid) one
acaddress class the address belongs to
addreither the previous or the new public IP address
addrlenactual length of the addr

Definition at line 3915 of file gnunet-communicator-tcp.c.

3921{
3922 char *my_addr;
3924
3926 "nat address cb %s %s\n",
3927 add_remove ? "add" : "remove",
3928 GNUNET_a2s (addr, addrlen));
3929
3930 if (GNUNET_YES == add_remove)
3931 {
3933
3934 GNUNET_asprintf (&my_addr,
3935 "%s-%s",
3937 GNUNET_a2s (addr, addrlen));
3938 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3939 ai =
3941 my_addr,
3942 nt,
3944 GNUNET_free (my_addr);
3945 *app_ctx = ai;
3946 }
3947 else
3948 {
3949 ai = *app_ctx;
3951 *app_ctx = NULL;
3952 }
3953}

References ai, ch, COMMUNICATOR_ADDRESS_PREFIX, GNUNET_a2s(), GNUNET_asprintf(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NT_scanner_get_type(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_communicator_address_add(), GNUNET_TRANSPORT_communicator_address_remove(), GNUNET_YES, is, and nt.

Referenced by nat_register().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_addr()

static void add_addr ( struct sockaddr *  in,
socklen_t  in_len 
)
static

This method adds addresses to the DLL, that are later register at the NAT service.

Definition at line 3960 of file gnunet-communicator-tcp.c.

3961{
3962
3963 struct Addresses *saddrs;
3964
3966 "add address %s\n",
3967 GNUNET_a2s (in, in_len));
3968
3969 saddrs = GNUNET_new (struct Addresses);
3970 saddrs->addr = in;
3971 saddrs->addr_len = in_len;
3973
3975 "after add address %s\n",
3976 GNUNET_a2s (in, in_len));
3977
3979 "add address %s\n",
3980 GNUNET_a2s (saddrs->addr, saddrs->addr_len));
3981
3982 addrs_lens++;
3983}

References Addresses::addr, Addresses::addr_len, addrs_head, addrs_lens, addrs_tail, GNUNET_a2s(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and GNUNET_new.

Referenced by init_socket().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_socket()

static int init_socket ( struct sockaddr *  addr,
socklen_t  in_len 
)
static

This method launch network interactions for each address we like to bind to.

Parameters
addrThe address we will listen to.
in_lenThe length of the address we will listen to.
Returns
GNUNET_SYSERR in case of error. GNUNET_OK in case we are successfully listen to the address.

Definition at line 3994 of file gnunet-communicator-tcp.c.

3996{
3997 struct sockaddr_storage in_sto;
3998 socklen_t sto_len;
3999 struct GNUNET_NETWORK_Handle *listen_sock;
4000 struct ListenTask *lt;
4001 int sockfd;
4002 struct GNUNET_HashCode h_sock;
4003
4004 if (NULL == addr)
4005 {
4007 "Address is NULL.\n");
4008 return GNUNET_SYSERR;
4009 }
4010
4012 "address %s\n",
4013 GNUNET_a2s (addr, in_len));
4014
4015 listen_sock =
4016 GNUNET_NETWORK_socket_create (addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
4017 if (NULL == listen_sock)
4018 {
4020 return GNUNET_SYSERR;
4021 }
4022
4023 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, addr, in_len))
4024 {
4026 GNUNET_NETWORK_socket_close (listen_sock);
4027 listen_sock = NULL;
4028 return GNUNET_SYSERR;
4029 }
4030
4031 if (GNUNET_OK !=
4032 GNUNET_NETWORK_socket_listen (listen_sock,
4033 5))
4034 {
4036 "listen");
4037 GNUNET_NETWORK_socket_close (listen_sock);
4038 listen_sock = NULL;
4039 return GNUNET_SYSERR;
4040 }
4041
4042 /* We might have bound to port 0, allowing the OS to figure it out;
4043 thus, get the real IN-address from the socket */
4044 sto_len = sizeof(in_sto);
4045
4046 if (0 != getsockname (GNUNET_NETWORK_get_fd (listen_sock),
4047 (struct sockaddr *) &in_sto,
4048 &sto_len))
4049 {
4050 memcpy (&in_sto, addr, in_len);
4051 sto_len = in_len;
4052 }
4053
4054 // addr = (struct sockaddr *) &in_sto;
4055 in_len = sto_len;
4057 "Bound to `%s'\n",
4058 GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len));
4059 if (NULL == stats)
4060 stats = GNUNET_STATISTICS_create ("communicator-tcp", cfg);
4061
4062 if (NULL == is)
4064
4065 /* start listening */
4066
4067 lt = GNUNET_new (struct ListenTask);
4068 lt->listen_sock = listen_sock;
4069
4071 listen_sock,
4072 &listen_cb,
4073 lt);
4074
4076 "creating hash\n");
4077 sockfd = GNUNET_NETWORK_get_fd (lt->listen_sock);
4078 GNUNET_CRYPTO_hash (&sockfd,
4079 sizeof(int),
4080 &h_sock);
4081
4083 "creating map\n");
4084 if (NULL == lt_map)
4086
4088 "creating map entry\n");
4091 &h_sock,
4092 lt,
4094
4096 "map entry created\n");
4097
4098 if (NULL == queue_map)
4100
4101 if (NULL == ch)
4106 &mq_init,
4107 NULL,
4109 NULL,
4110 NULL);
4111
4112 if (NULL == ch)
4113 {
4114 GNUNET_break (0);
4115 if (NULL != resolve_request_handle)
4118 return GNUNET_SYSERR;
4119 }
4120
4121 add_addr (addr, in_len);
4122 return GNUNET_OK;
4123
4124}

References add_addr(), cfg, ch, COMMUNICATOR_ADDRESS_PREFIX, COMMUNICATOR_CONFIG_SECTION, enc_notify_cb(), GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_get_fd(), GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_NETWORK_socket_listen(), GNUNET_new, GNUNET_NO, GNUNET_NT_scanner_init(), GNUNET_OK, GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_create(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_CC_RELIABLE, GNUNET_TRANSPORT_communicator_connect(), is, listen_cb(), ListenTask::listen_sock, ListenTask::listen_task, lt_map, mq_init(), queue_map, resolve_request_handle, and stats.

Referenced by init_socket_resolv(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ nat_register()

static void nat_register ( )
static

This method reads from the DLL addrs_head to register them at the NAT service.

Definition at line 4131 of file gnunet-communicator-tcp.c.

4132{
4133 struct sockaddr **saddrs;
4134 socklen_t *saddr_lens;
4135 int i;
4136 size_t len;
4137
4139 "starting nat register!\n");
4140 len = 0;
4141 i = 0;
4142 saddrs = GNUNET_malloc ((addrs_lens) * sizeof(struct sockaddr *));
4143 saddr_lens = GNUNET_malloc ((addrs_lens) * sizeof(socklen_t));
4144 for (struct Addresses *pos = addrs_head; NULL != pos; pos = pos->next)
4145 {
4147 "registering address %s\n",
4148 GNUNET_a2s (pos->addr, pos->addr_len));
4149
4150 saddr_lens[i] = pos->addr_len;
4151 len += saddr_lens[i];
4152 saddrs[i] = GNUNET_memdup (pos->addr, saddr_lens[i]);
4153 i++;
4154 }
4155
4157 "registering addresses %lu %lu %lu %lu\n",
4158 (addrs_lens) * sizeof(struct sockaddr *),
4159 (addrs_lens) * sizeof(socklen_t),
4160 len,
4164 IPPROTO_TCP,
4165 addrs_lens,
4166 (const struct sockaddr **) saddrs,
4167 saddr_lens,
4170 NULL /* closure */);
4171 for (i = addrs_lens - 1; i >= 0; i--)
4172 GNUNET_free (saddrs[i]);
4173 GNUNET_free (saddrs);
4174 GNUNET_free (saddr_lens);
4175
4176 if (NULL == nat)
4177 {
4178 GNUNET_break (0);
4179 if (NULL != resolve_request_handle)
4182 }
4183}

References addrs_head, addrs_lens, cfg, COMMUNICATOR_CONFIG_SECTION, GNUNET_a2s(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_memdup, GNUNET_NAT_register(), GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_shutdown(), nat, nat_address_cb(), Addresses::next, resolve_request_handle, and try_connection_reversal().

Referenced by init_socket_resolv(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_socket_resolv()

static void init_socket_resolv ( void *  cls,
const struct sockaddr *  addr,
socklen_t  in_len 
)
static

This method is the callback called by the resolver API, and wraps method init_socket.

Parameters
clsThe port we will bind to.
addrThe address we will bind to.
in_lenThe length of the address we will bind to.

Definition at line 4194 of file gnunet-communicator-tcp.c.

4197{
4198 struct sockaddr_in *v4;
4199 struct sockaddr_in6 *v6;
4200 struct sockaddr *in;
4201
4202 (void) cls;
4203 if (NULL != addr)
4204 {
4205 if (AF_INET == addr->sa_family)
4206 {
4207 v4 = (struct sockaddr_in *) addr;
4208 in = tcp_address_to_sockaddr_numeric_v4 (&in_len, *v4, bind_port);// _global);
4209 }
4210 else if (AF_INET6 == addr->sa_family)
4211 {
4212 v6 = (struct sockaddr_in6 *) addr;
4213 in = tcp_address_to_sockaddr_numeric_v6 (&in_len, *v6, bind_port);// _global);
4214 }
4215 else
4216 {
4218 "Address family %u not suitable (not AF_INET %u nor AF_INET6 %u \n",
4219 addr->sa_family,
4220 AF_INET,
4221 AF_INET6);
4222 return;
4223 }
4224 init_socket (in, in_len);
4225 }
4226 else
4227 {
4229 "Address is NULL. This might be an error or the resolver finished resolving.\n");
4230 if (NULL == addrs_head)
4231 {
4233 "Resolver finished resolving, but we do not listen to an address!.\n");
4234 return;
4235 }
4236 nat_register ();
4237 }
4238}

References addrs_head, bind_port, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, init_socket(), nat_register(), tcp_address_to_sockaddr_numeric_v4(), and tcp_address_to_sockaddr_numeric_v6().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
char *const *  args,
const char *  cfgfile,
const struct GNUNET_CONFIGURATION_Handle c 
)
static

Setup communicator and launch network interactions.

Parameters
clsNULL (always)
argsremaining command-line arguments
cfgfilename of the configuration file used (for saving, can be NULL!)
cconfiguration

Definition at line 4250 of file gnunet-communicator-tcp.c.

4254{
4255 char *bindto;
4256 struct sockaddr *in;
4257 socklen_t in_len;
4258 struct sockaddr_in v4;
4259 struct sockaddr_in6 v6;
4260 char *start;
4261 unsigned int port;
4262 char dummy[2];
4263 char *rest = NULL;
4264 struct PortOnlyIpv4Ipv6 *po;
4265 socklen_t addr_len_ipv4;
4266 socklen_t addr_len_ipv6;
4267
4268 (void) cls;
4269
4271 memset (&v4,0,sizeof(struct sockaddr_in));
4272 memset (&v6,0,sizeof(struct sockaddr_in6));
4273 cfg = c;
4274 if (GNUNET_OK !=
4277 "BINDTO",
4278 &bindto))
4279 {
4282 "BINDTO");
4283 return;
4284 }
4285 if (GNUNET_OK !=
4288 "MAX_QUEUE_LENGTH",
4290 {
4292 }
4293 if (GNUNET_OK !=
4296 "REKEY_INTERVAL",
4298 {
4300 }
4301 if (GNUNET_OK !=
4304 "REKEY_MAX_BYTES",
4306 {
4308 }
4310 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
4311 (GNUNET_YES ==
4314 "DISABLE_V6")))
4315 {
4317 }
4319 GNUNET_assert (NULL != key_ring);
4320 pils = GNUNET_PILS_connect (cfg, NULL, NULL);
4321 GNUNET_assert (NULL != pils);
4323 if (NULL == peerstore)
4324 {
4325 GNUNET_free (bindto);
4326 GNUNET_break (0);
4328 return;
4329 }
4330
4332
4333 if (1 == sscanf (bindto, "%u%1s", &bind_port, dummy))
4334 {
4338 "address po %s\n",
4340 if (NULL != po->addr_ipv4)
4341 {
4343 }
4344 if (NULL != po->addr_ipv6)
4345 {
4348 }
4349 GNUNET_free (po);
4350 nat_register ();
4351 GNUNET_free (bindto);
4352 return;
4353 }
4354
4355 start = extract_address (bindto);
4356 // FIXME: check for NULL == start...
4357 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
4358 {
4359 bind_port = extract_port (bindto);
4360
4362 init_socket (in, in_len);
4363 nat_register ();
4365 GNUNET_free (bindto);
4366 return;
4367 }
4368
4369 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
4370 {
4371 bind_port = extract_port (bindto);
4373 init_socket (in, in_len);
4374 nat_register ();
4376 GNUNET_free (bindto);
4377 return;
4378 }
4379
4380 bind_port = extract_port (bindto);
4382 ":",
4383 &rest),
4384 AF_UNSPEC,
4387 &port);
4388
4389 GNUNET_free (bindto);
4391}

References PortOnlyIpv4Ipv6::addr_ipv4, PortOnlyIpv4Ipv6::addr_ipv6, PortOnlyIpv4Ipv6::addr_len_ipv4, PortOnlyIpv4Ipv6::addr_len_ipv6, bind_port, cfg, COMMUNICATOR_CONFIG_SECTION, DEFAULT_MAX_QUEUE_LENGTH, DEFAULT_REKEY_INTERVAL, disable_v6, do_shutdown, dummy, extract_address(), extract_port(), GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_time(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONTAINER_multihashmap_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_log_config_missing(), GNUNET_NETWORK_test_pf(), GNUNET_NO, GNUNET_OK, GNUNET_PEERSTORE_connect(), GNUNET_PILS_connect(), GNUNET_PILS_create_key_ring(), GNUNET_RESOLVER_ip_get(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_TIME_UNIT_MINUTES, GNUNET_YES, init_socket(), init_socket_resolv(), key_ring, max_queue_length, nat_register(), peerstore, pending_reversals, pils, port, rekey_interval, REKEY_MAX_BYTES, rekey_max_bytes, resolve_request_handle, start, tcp_address_to_sockaddr_numeric_v4(), tcp_address_to_sockaddr_numeric_v6(), and tcp_address_to_sockaddr_port_only().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *const *  argv 
)

The main function for the UNIX communicator.

Parameters
argcnumber of arguments from the command line
argvcommand line arguments
Returns
0 ok, 1 on error

Definition at line 4402 of file gnunet-communicator-tcp.c.

4403{
4404 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4406 };
4407 int ret;
4408
4410 "Starting tcp communicator\n");
4411
4412 ret = (GNUNET_OK ==
4414 argc,
4415 argv,
4416 "gnunet-communicator-tcp",
4417 _ ("GNUnet TCP communicator"),
4418 options,
4419 &run,
4420 NULL))
4421 ? 0
4422 : 1;
4423 return ret;
4424}

References _, GNUNET_ERROR_TYPE_DEBUG, GNUNET_GETOPT_OPTION_END, GNUNET_log, GNUNET_OK, GNUNET_OS_project_data_gnunet(), GNUNET_PROGRAM_run(), options, ret, and run().

Here is the call graph for this function:

Variable Documentation

◆ max_queue_length

unsigned long long max_queue_length
static

Maximum queue length before we stop reading towards the transport service.

Definition at line 848 of file gnunet-communicator-tcp.c.

Referenced by queue_read(), queue_read(), and run().

◆ key_ring

◆ pils

◆ stats

◆ ch

◆ queue_map

struct GNUNET_CONTAINER_MultiHashMap* queue_map
static

Queues (map from peer identity to struct Queue)

Definition at line 873 of file gnunet-communicator-tcp.c.

Referenced by boot_queue(), do_shutdown(), init_socket(), mq_init(), and queue_destroy().

◆ lt_map

struct GNUNET_CONTAINER_MultiHashMap* lt_map
static

ListenTasks (map from socket to struct ListenTask)

Definition at line 878 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), init_socket(), and queue_destroy().

◆ rekey_max_bytes

unsigned long long rekey_max_bytes
static

The rekey byte maximum.

Definition at line 883 of file gnunet-communicator-tcp.c.

Referenced by run(), setup_out_cipher(), and setup_out_cipher().

◆ rekey_interval

struct GNUNET_TIME_Relative rekey_interval
static

The rekey interval.

Definition at line 888 of file gnunet-communicator-tcp.c.

Referenced by run(), run(), setup_out_cipher(), and setup_out_cipher().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

Definition at line 893 of file gnunet-communicator-tcp.c.

Referenced by init_socket(), inject_rekey(), nat_register(), run(), send_challenge(), and transmit_kx().

◆ is

struct GNUNET_NT_InterfaceScanner* is
static

Network scanner to determine network types.

Definition at line 898 of file gnunet-communicator-tcp.c.

Referenced by boot_queue(), do_shutdown(), init_socket(), and nat_address_cb().

◆ nat

struct GNUNET_NAT_Handle* nat
static

Connection to NAT service.

Definition at line 903 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), mq_init(), and nat_register().

◆ proto_head

struct ProtoQueue* proto_head
static

◆ proto_tail

struct ProtoQueue* proto_tail
static

◆ resolve_request_handle

struct GNUNET_RESOLVER_RequestHandle* resolve_request_handle

Handle for DNS lookup of bindto address.

Definition at line 918 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), do_shutdown(), init_socket(), init_socket(), nat_register(), and run().

◆ addrs_head

struct Addresses* addrs_head
static

Head of DLL with addresses we like to register at NAT service.

Definition at line 923 of file gnunet-communicator-tcp.c.

Referenced by add_addr(), init_socket_resolv(), and nat_register().

◆ addrs_tail

struct Addresses* addrs_tail
static

Head of DLL with addresses we like to register at NAT service.

Definition at line 928 of file gnunet-communicator-tcp.c.

Referenced by add_addr().

◆ addrs_lens

int addrs_lens
static

Number of addresses in the DLL for register at NAT service.

Definition at line 933 of file gnunet-communicator-tcp.c.

Referenced by add_addr(), add_addr(), and nat_register().

◆ peerstore

◆ shutdown_running

int shutdown_running = GNUNET_NO
static

A flag indicating we are already doing a shutdown.

Definition at line 943 of file gnunet-communicator-tcp.c.

Referenced by do_shutdown(), and queue_destroy().

◆ disable_v6

int disable_v6
static

IPv6 disabled.

Definition at line 948 of file gnunet-communicator-tcp.c.

Referenced by mq_init(), run(), and tcp_address_to_sockaddr_port_only().

◆ bind_port

unsigned int bind_port
static

The port the communicator should be assigned to.

Definition at line 953 of file gnunet-communicator-tcp.c.

Referenced by init_socket_resolv(), mq_init(), mq_init(), run(), and run().

◆ pending_reversals