GNUnet 0.25.2-11-g84e94e98c
 
Loading...
Searching...
No Matches
gnunet-communicator-libp2p.c File Reference

Very first draft of a gnunet libp2p communicator. More...

#include "platform.h"
#include "gnunet_common.h"
#include "gnunet_util_lib.h"
#include "gnunet_pils_service.h"
#include "gnunet_core_service.h"
#include "gnunet_peerstore_service.h"
#include "gnunet_protocols.h"
#include "gnunet_signatures.h"
#include "gnunet_constants.h"
#include "gnunet_nat_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet_transport_communication_service.h"
#include "gnunet_resolver_service.h"
#include <libp2p/basic/scheduler.hpp>
#include <libp2p/common/literals.hpp>
#include <libp2p/injector/host_injector.hpp>
#include <libp2p/layer/websocket/ws_adaptor.hpp>
#include <libp2p/log/configurator.hpp>
#include <libp2p/log/logger.hpp>
#include <libp2p/protocol/echo.hpp>
Include dependency graph for gnunet-communicator-libp2p.c:

Go to the source code of this file.

Data Structures

struct  Queue
 Handle for a queue. 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__)
 

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 (struct GNUNET_CRYPTO_EddsaPrivateKey *edpk, struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
 
static void eddsa_pub_to_hpke_key (struct GNUNET_CRYPTO_EddsaPublicKey *edpk, struct GNUNET_CRYPTO_EcdhePublicKey *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_HashCode *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_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_HashCode *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 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, struct GNUNET_PeerIdentity *sender)
 
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 void 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 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 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 enum GNUNET_GenericReturnValue load_ikm ()
 FIXME: We could alternatively ask PILS for de/encaps, but at a high cost wrt async RPC calls...
 
static int init_socket (struct sockaddr *addr, socklen_t in_len)
 This method launch network interactions for each address we like to bind to.
 
void pid_change_cb (void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *addr_hash)
 
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 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 struct GNUNET_PeerIdentity my_identity
 Our public key.
 
static struct GNUNET_CRYPTO_EddsaPrivateKeymy_private_key
 Our private key.
 
static struct GNUNET_CRYPTO_EcdhePrivateKey my_x25519_private_key
 Our private key.
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Our configuration.
 
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 struct GNUNET_PEERSTORE_Handlepeerstore
 Database for peer's HELLOs.
 
static int shutdown_running = GNUNET_NO
 A flag indicating we are already doing a shutdown.
 

Detailed Description

Very first draft of a gnunet libp2p communicator.

This is not in any way in a working or compiling state

Author
ch3

Definition in file gnunet-communicator-libp2p.c.

Macro Definition Documentation

◆ LOG

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

Definition at line 53 of file gnunet-communicator-libp2p.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 2478 of file gnunet-communicator-libp2p.c.

2479{
2480 struct sockaddr_storage in;
2481 socklen_t addrlen;
2482 struct GNUNET_NETWORK_Handle *sock;
2483 struct ListenTask *lt;
2484 struct sockaddr *in_addr;
2485
2487 "listen_cb\n");
2488
2489 lt = cls;
2490
2491 lt->listen_task = NULL;
2492 GNUNET_assert (NULL != lt->listen_sock);
2493 addrlen = sizeof(in);
2494 memset (&in, 0, sizeof(in));
2496 (struct sockaddr*) &in,
2497 &addrlen);
2498 if ((NULL == sock) && ((EMFILE == errno) || (ENFILE == errno)))
2499 return; /* system limit reached, wait until connection goes down */
2501 lt->listen_sock,
2502 &listen_cb,
2503 lt);
2504 if ((NULL == sock) && ((EAGAIN == errno) || (ENOBUFS == errno)))
2505 return;
2506 if (NULL == sock)
2507 {
2509 return;
2510 }
2511 in_addr = GNUNET_memdup (&in, addrlen);
2512 create_proto_queue (sock, in_addr, addrlen);
2513}
static struct ProtoQueue * create_proto_queue(struct GNUNET_NETWORK_Handle *sock, struct sockaddr *in, socklen_t addrlen)
static void listen_cb(void *cls)
We have been notified that our listen socket has something to read.
#define GNUNET_log(kind,...)
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#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...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
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
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:1511
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
handle to a socket
Definition network.c:53
Struct to use as closure.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
struct GNUNET_SCHEDULER_Task * listen_task
ID of listen task.

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 GNUNET_SET_listen(), GNUNET_SETI_listen(), GNUNET_SETU_listen(), 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 ( struct GNUNET_CRYPTO_EddsaPrivateKey edpk,
struct GNUNET_CRYPTO_EcdhePrivateKey pk 
)
static

Definition at line 191 of file gnunet-communicator-libp2p.c.

193{
195 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
196 key.eddsa_key = *edpk;
198}
struct GNUNET_HashCode key
The key used in the DHT.
struct GNUNET_CRYPTO_BlindablePrivateKey pk
Private key from command line option, or NULL.
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)
@ GNUNET_PUBLIC_KEY_TYPE_EDDSA
EDDSA identity.
A private key for an identity as per LSD0001.

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

Referenced by pid_change_cb().

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 ( struct GNUNET_CRYPTO_EddsaPublicKey edpk,
struct GNUNET_CRYPTO_EcdhePublicKey pk 
)
static

Definition at line 202 of file gnunet-communicator-libp2p.c.

204{
206 key.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
207 key.eddsa_key = *edpk;
209}
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)
An identity key as per LSD0001.

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 220 of file gnunet-communicator-libp2p.c.

221{
222 struct ListenTask *lt = NULL;
223 struct GNUNET_HashCode h_sock;
224 int sockfd;
225
226 if (NULL != queue->listen_sock)
227 {
228 sockfd = GNUNET_NETWORK_get_fd (queue->listen_sock);
229 GNUNET_CRYPTO_hash (&sockfd,
230 sizeof(int),
231 &h_sock);
232
234 }
235
237 "Disconnecting queue for peer `%s'\n",
238 GNUNET_i2s (&queue->target));
239 if (NULL != queue->rekey_monotime_sc)
240 {
241 GNUNET_PEERSTORE_store_cancel (queue->rekey_monotime_sc);
242 queue->rekey_monotime_sc = NULL;
243 }
244 if (NULL != queue->handshake_monotime_sc)
245 {
246 GNUNET_PEERSTORE_store_cancel (queue->handshake_monotime_sc);
247 queue->handshake_monotime_sc = NULL;
248 }
249 if (NULL != queue->handshake_ack_monotime_sc)
250 {
251 GNUNET_PEERSTORE_store_cancel (queue->handshake_ack_monotime_sc);
252 queue->handshake_ack_monotime_sc = NULL;
253 }
254 if (NULL != queue->rekey_monotime_get)
255 {
256 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
257 queue->rekey_monotime_get = NULL;
258 }
259 if (NULL != queue->handshake_monotime_get)
260 {
261 GNUNET_PEERSTORE_iteration_stop (queue->handshake_monotime_get);
262 queue->handshake_monotime_get = NULL;
263 }
264 if (NULL != queue->handshake_ack_monotime_get)
265 {
266 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
267 queue->handshake_ack_monotime_get = NULL;
268 }
269 if (NULL != queue->qh)
270 {
272 queue->qh = NULL;
273 }
275 GNUNET_YES ==
278 "# queues active",
280 GNUNET_NO);
281 if (NULL != queue->read_task)
282 {
283 GNUNET_SCHEDULER_cancel (queue->read_task);
284 queue->read_task = NULL;
285 }
286 if (NULL != queue->write_task)
287 {
288 GNUNET_SCHEDULER_cancel (queue->write_task);
289 queue->write_task = NULL;
290 }
292 {
294 "closing socket failed\n");
295 }
296 gcry_cipher_close (queue->in_cipher);
297 gcry_cipher_close (queue->out_cipher);
298 GNUNET_free (queue->address);
299 if (0 != queue->backpressure)
300 queue->destroyed = GNUNET_YES;
301 else
303
304 if (NULL == lt)
305 return;
306
307 if ((! shutdown_running) && (NULL == lt->listen_task))
308 {
310 "add read net listen\n");
313 lt->listen_sock,
314 &listen_cb,
315 lt);
316 }
317 else
318 GNUNET_free (lt);
319}
static struct GNUNET_STATISTICS_Handle * stats
For logging statistics.
static struct GNUNET_CONTAINER_MultiHashMap * queue_map
Queues (map from peer identity to struct Queue)
static int shutdown_running
A flag indicating we are already doing a shutdown.
static struct GNUNET_CONTAINER_MultiHashMap * lt_map
ListenTasks (map from socket to struct ListenTask)
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.
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.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
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.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_ERROR
#define GNUNET_free(ptr)
Wrapper around free.
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:1001
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
A 512-bit hashcode.

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 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_HashCode 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 331 of file gnunet-communicator-libp2p.c.

335{
336 struct GNUNET_HashCode mac;
337
338 GNUNET_CRYPTO_hmac_raw (hmac_secret,
339 sizeof(struct GNUNET_HashCode),
340 buf,
341 buf_size,
342 &mac);
343 /* truncate to `struct GNUNET_ShortHashCode` */
344 memcpy (smac, &mac, sizeof(struct GNUNET_ShortHashCode));
345 /* ratchet hmac key */
346 GNUNET_CRYPTO_hash (hmac_secret,
347 sizeof(struct GNUNET_HashCode),
348 hmac_secret);
349}
void GNUNET_CRYPTO_hmac_raw(const void *key, size_t key_len, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104) TODO: Shouldn't this be the standard hmac function and the abo...
A 256-bit hashcode.

References GNUNET_CRYPTO_hash(), and GNUNET_CRYPTO_hmac_raw().

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_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 359 of file gnunet-communicator-libp2p.c.

360{
361 struct TCPFinish fin;
362
363 memset (&fin, 0, sizeof(fin));
364 fin.header.size = htons (sizeof(fin));
365 fin.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH);
366 calculate_hmac (&queue->out_hmac, &fin, sizeof(fin), &fin.hmac);
367 /* if there is any message left in pwrite_buf, we
368 overwrite it (possibly dropping the last message
369 from CORE hard here) */
370 memcpy (queue->pwrite_buf, &fin, sizeof(fin));
371 queue->pwrite_off = sizeof(fin);
372 /* This flag will ensure that #queue_write() no longer
373 notifies CORE about the possibility of sending
374 more data, and that #queue_write() will call
375 #queue_destroy() once the @c fin was fully written. */
376 queue->finishing = GNUNET_YES;
377}
static void calculate_hmac(struct GNUNET_HashCode *hmac_secret, const void *buf, size_t buf_size, struct GNUNET_ShortHashCode *smac)
Compute mac over buf, and ratched the hmac_secret.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH
TCP communicator end of stream.

References calculate_hmac(), GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH, GNUNET_YES, TCPFinish::header, TCPFinish::hmac, queue(), 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 1423 of file gnunet-communicator-libp2p.c.

1424{
1425 struct Queue *queue = cls;
1426 struct GNUNET_TIME_Relative left;
1427 ssize_t rcvd;
1428
1429 queue->read_task = NULL;
1430 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
1431 &queue->cread_buf[queue->cread_off],
1432 BUF_SIZE - queue->cread_off);
1434 "Received %zd bytes from TCP queue\n", rcvd);
1435 if (-1 == rcvd)
1436 {
1437 if ((EAGAIN != errno) && (EINTR != errno))
1438 {
1441 return;
1442 }
1443 /* try again */
1444 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
1445 if (0 != left.rel_value_us)
1446 {
1447 queue->read_task =
1449 return;
1450 }
1452 "Queue %p was idle for %s, disconnecting\n",
1453 queue,
1456 GNUNET_YES));
1458 return;
1459 }
1460 if (0 == rcvd)
1461 {
1462 /* Orderly shutdown of connection */
1464 "Socket for queue %p seems to have been closed\n", queue);
1466 return;
1467 }
1468 queue->timeout =
1470 queue->cread_off += rcvd;
1471 while ((queue->pread_off < sizeof(queue->pread_buf)) &&
1472 (queue->cread_off > 0))
1473 {
1474 size_t max = GNUNET_MIN (sizeof(queue->pread_buf) - queue->pread_off,
1475 queue->cread_off);
1476 size_t done;
1477 size_t total;
1478 size_t old_pread_off = queue->pread_off;
1479
1480 GNUNET_assert (0 ==
1481 gcry_cipher_decrypt (queue->in_cipher,
1482 &queue->pread_buf[queue->pread_off],
1483 max,
1484 queue->cread_buf,
1485 max));
1486 queue->pread_off += max;
1487 total = 0;
1488 while (0 != (done = try_handle_plaintext (queue)))
1489 {
1490 /* 'done' bytes of plaintext were used, shift buffer */
1491 GNUNET_assert (done <= queue->pread_off);
1492 /* NOTE: this memmove() could possibly sometimes be
1493 avoided if we pass 'total' into try_handle_plaintext()
1494 and use it at an offset into the buffer there! */
1495 memmove (queue->pread_buf,
1496 &queue->pread_buf[done],
1497 queue->pread_off - done);
1498 queue->pread_off -= done;
1499 total += done;
1500 /* The last plaintext was a rekey, abort for now */
1501 if (GNUNET_YES == queue->rekeyed)
1502 break;
1503 }
1504 /* when we encounter a rekey message, the decryption above uses the
1505 wrong key for everything after the rekey; in that case, we have
1506 to re-do the decryption at 'total' instead of at 'max'.
1507 However, we have to take into account that the plaintext buffer may have
1508 already contained data and not jumped too far ahead in the ciphertext.
1509 If there is no rekey and the last message is incomplete (max > total),
1510 it is safe to keep the decryption so we shift by 'max' */
1511 if (GNUNET_YES == queue->rekeyed)
1512 {
1513 max = total - old_pread_off;
1514 queue->rekeyed = GNUNET_NO;
1515 queue->pread_off = 0;
1516 }
1517 memmove (queue->cread_buf, &queue->cread_buf[max], queue->cread_off - max);
1518 queue->cread_off -= max;
1519 }
1520 if (BUF_SIZE == queue->cread_off)
1521 return; /* buffer full, suspend reading */
1522 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
1523 if (0 != left.rel_value_us)
1524 {
1525 if (max_queue_length > queue->backpressure)
1526 {
1527 /* continue reading */
1528 queue->read_task =
1530 }
1531 return;
1532 }
1534 "Queue %p was idle for %s, disconnecting\n",
1535 queue,
1538 GNUNET_YES));
1540}
static size_t try_handle_plaintext(struct Queue *queue)
Test if we have received a full message in plaintext.
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 void queue_read(void *cls)
Queue read task.
#define BUF_SIZE
Size of our IO buffers for ciphertext data.
static unsigned long long max_queue_length
Maximum queue length before we stop reading towards the transport service.
#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?
#define GNUNET_MIN(a, b)
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:717
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:599
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
#define max(x, y)
Time for relative time used by GNUnet, in microseconds.
Handle for a queue.

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, 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 397 of file gnunet-communicator-libp2p.c.

398{
399 struct Queue *queue = cls;
400 if (GNUNET_OK != success)
402 "# messages lost in communicator API towards CORE",
403 1,
404 GNUNET_NO);
405 if (NULL == queue)
406 return;
407
409 "backpressure %u\n",
410 queue->backpressure);
411
412 queue->backpressure--;
413 /* handle deferred queue destruction */
414 if ((queue->destroyed) && (0 == queue->backpressure))
415 {
417 return;
418 }
419 else if (GNUNET_YES != queue->destroyed)
420 {
421 queue->timeout =
423 );
424 /* possibly unchoke reading, now that CORE made progress */
425 if (NULL == queue->read_task)
426 queue->read_task =
428 queue->timeout),
429 queue->sock,
430 &queue_read,
431 queue);
432 }
433}
@ GNUNET_OK
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.

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 446 of file gnunet-communicator-libp2p.c.

449{
450 const struct GNUNET_MessageHeader *hdr = plaintext;
451 int ret;
452
454 "pass message from %s to core\n",
455 GNUNET_i2s (&queue->target));
456
457 if (ntohs (hdr->size) != plaintext_len)
458 {
459 /* NOTE: If we ever allow multiple CORE messages in one
460 BOX, this will have to change! */
461 GNUNET_break (0);
462 return;
463 }
465 &queue->target,
466 hdr,
469 queue);
471 "passed to core\n");
472 if (GNUNET_OK == ret)
473 queue->backpressure++;
474 GNUNET_break (GNUNET_NO != ret); /* backpressure not working!? */
475 if (GNUNET_SYSERR == ret)
477 "# bytes lost due to CORE not running",
478 plaintext_len,
479 GNUNET_NO);
480}
static int ret
Final status code.
Definition gnunet-arm.c:93
#define ADDRESS_VALIDITY_PERIOD
How long do we believe our addresses to remain up (before the other peer should revalidate).
static struct GNUNET_TRANSPORT_CommunicatorHandle * ch
Our environment.
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.
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.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
Header for all communications.

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_HashCode 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 493 of file gnunet-communicator-libp2p.c.

497{
498 char key[256 / 8];
499 char ctr[128 / 8];
500
501 GNUNET_assert (0 == gcry_cipher_open (cipher,
502 GCRY_CIPHER_AES256 /* low level: go for speed */
503 ,
504 GCRY_CIPHER_MODE_CTR,
505 0 /* flags */));
508 sizeof(key),
509 prk,
510 "gnunet-communicator-tcp-key",
511 strlen (
512 "gnunet-communicator-tcp-key"),
513 NULL,
514 0));
515 GNUNET_assert (0 == gcry_cipher_setkey (*cipher, key, sizeof(key)));
518 sizeof(ctr),
519 prk,
520 "gnunet-communicator-tcp-ctr",
521 strlen (
522 "gnunet-communicator-tcp-ctr"),
523 NULL,
524 0));
525 gcry_cipher_setctr (*cipher, ctr, sizeof(ctr));
528 sizeof(struct GNUNET_HashCode),
529 prk,
530 "gnunet-communicator-hmac",
531 strlen ("gnunet-communicator-hmac"),
532 NULL,
533 0));
534}
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hkdf_expand(void *result, size_t out_len, const struct GNUNET_ShortHashCode *prk,...)
HKDF-Expand using SHA256.

References GNUNET_assert, GNUNET_CRYPTO_hkdf_expand(), GNUNET_YES, and key.

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

Here is the call graph for this function:
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 543 of file gnunet-communicator-libp2p.c.

544{
545 struct Queue *queue = cls;
546 if (GNUNET_OK != success)
547 {
549 "Failed to store rekey monotonic time in PEERSTORE!\n");
550 }
551 queue->rekey_monotime_sc = NULL;
552 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
553}
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.

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 564 of file gnunet-communicator-libp2p.c.

567{
568 struct Queue *queue = cls;
569 struct GNUNET_TIME_AbsoluteNBO *mtbe;
570 struct GNUNET_TIME_Absolute mt;
571 const struct GNUNET_PeerIdentity *pid;
572 struct GNUNET_TIME_AbsoluteNBO *rekey_monotonic_time;
573
574 (void) emsg;
575
576 rekey_monotonic_time = &queue->rekey_monotonic_time;
577 pid = &queue->target;
578 if (NULL == record)
579 {
580 queue->rekey_monotime_get = NULL;
581 return;
582 }
583 if (sizeof(*mtbe) != record->value_size)
584 {
585 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
586 GNUNET_break (0);
587 return;
588 }
589 mtbe = record->value;
590 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
591 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
592 queue->rekey_monotonic_time).abs_value_us)
593 {
595 "Queue from %s dropped, rekey monotime in the past\n",
596 GNUNET_i2s (&queue->target));
597 GNUNET_break (0);
598 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
599 queue->rekey_monotime_get = NULL;
600 // FIXME: Why should we try to gracefully finish here??
602 return;
603 }
604 queue->rekey_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
605 "transport_tcp_communicator",
606 pid,
608 rekey_monotonic_time,
609 sizeof(*
610 rekey_monotonic_time),
614 queue);
615}
static void queue_finish(struct Queue *queue)
Append a 'finish' message to the outgoing transmission.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static void rekey_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for rekey monotime value is finished.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
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_REKEY
Key used to store sender's monotonic time from rekey message.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
The identity of the host (wraps the signing key of the peer).
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.

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, pid, 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 625 of file gnunet-communicator-libp2p.c.

628{
629 struct GNUNET_ShortHashCode k;
630
632 setup_cipher (&k, &my_identity, &queue->in_cipher, &queue->in_hmac);
633}
static struct GNUNET_PeerIdentity my_identity
Our public key.
static void setup_cipher(const struct GNUNET_ShortHashCode *prk, const struct GNUNET_PeerIdentity *pid, gcry_cipher_hd_t *cipher, struct GNUNET_HashCode *hmac_key)
Setup cipher based on shared secret dh and decrypting peer pid.
static struct GNUNET_CRYPTO_EcdhePrivateKey my_x25519_private_key
Our private key.
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...

References GNUNET_CRYPTO_hpke_elligator_kem_decaps(), my_identity, my_x25519_private_key, 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 643 of file gnunet-communicator-libp2p.c.

645{
646 struct GNUNET_ShortHashCode k;
647
649 setup_cipher (&k, &my_identity, &queue->in_cipher, &queue->in_hmac);
650}
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_private_key
Our private key.
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.

References GNUNET_CRYPTO_eddsa_kem_decaps(), my_identity, my_private_key, 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 662 of file gnunet-communicator-libp2p.c.

663{
664 struct TcpRekeySignature thp;
665
667 thp.purpose.size = htonl (sizeof(thp));
669 "do_rekey size %u\n",
670 thp.purpose.size);
671 thp.sender = queue->target;
673 "sender %s\n",
674 GNUNET_p2s (&thp.sender.public_key));
676 "sender %s\n",
677 GNUNET_p2s (&queue->target.public_key));
678 thp.receiver = my_identity;
680 "receiver %s\n",
681 GNUNET_p2s (&thp.receiver.public_key));
682 thp.ephemeral = rekey->ephemeral;
684 "ephemeral %s\n",
685 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
686 );
687 thp.monotonic_time = rekey->monotonic_time;
689 "time %s\n",
691 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
692 GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp)));
693 if (GNUNET_OK !=
696 &thp,
697 &rekey->sender_sig,
698 &queue->target.public_key))
699 {
700 GNUNET_break (0);
701 // FIXME Why should we try to gracefully finish here?
703 return;
704 }
705 queue->rekey_monotonic_time = rekey->monotonic_time;
706 queue->rekey_monotime_get = GNUNET_PEERSTORE_iteration_start (peerstore,
707 "transport_tcp_communicator",
708 &queue->target,
710 &
712 queue);
713 gcry_cipher_close (queue->in_cipher);
714 queue->rekeyed = GNUNET_YES;
716}
static void setup_in_cipher(const struct GNUNET_CRYPTO_HpkeEncapsulation *ephemeral, struct Queue *queue)
Setup cipher of queue for decryption.
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...
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY
Signature used by TCP communicator rekey.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
const char * GNUNET_e2s(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
const char * GNUNET_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
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.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:660
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
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 (!...
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.
Signature we use to verify that the ephemeral key was really chosen by the specified sender.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY.

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_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, 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 725 of file gnunet-communicator-libp2p.c.

726{
727 struct Queue *queue = cls;
728
729 if (GNUNET_OK != success)
730 {
732 "Failed to store handshake ack monotonic time in PEERSTORE!\n");
733 }
734 queue->handshake_ack_monotime_sc = NULL;
735 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
736}

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 747 of file gnunet-communicator-libp2p.c.

750{
751 struct Queue *queue = cls;
752 struct GNUNET_TIME_AbsoluteNBO *mtbe;
753 struct GNUNET_TIME_Absolute mt;
754 const struct GNUNET_PeerIdentity *pid;
755 struct GNUNET_TIME_AbsoluteNBO *handshake_ack_monotonic_time;
756
757 (void) emsg;
758
759 handshake_ack_monotonic_time = &queue->handshake_ack_monotonic_time;
760 pid = &queue->target;
761 if (NULL == record)
762 {
763 queue->handshake_ack_monotime_get = NULL;
764 return;
765 }
766 if (sizeof(*mtbe) != record->value_size)
767 {
768 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
769 GNUNET_break (0);
770 return;
771 }
772 mtbe = record->value;
773 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
774 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
775 queue->handshake_ack_monotonic_time).abs_value_us)
776 {
778 "Queue from %s dropped, handshake ack monotime in the past\n",
779 GNUNET_i2s (&queue->target));
780 GNUNET_break (0);
781 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
782 queue->handshake_ack_monotime_get = NULL;
783 // FIXME: Why should we try to gracefully finish here?
785 return;
786 }
787 queue->handshake_ack_monotime_sc =
789 "transport_tcp_communicator",
790 pid,
792 handshake_ack_monotonic_time,
793 sizeof(*handshake_ack_monotonic_time),
797 queue);
798}
static void handshake_ack_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for handshake ack monotime value is finished.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK
Key used to store sender's monotonic time from handshake ack message.

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, pid, 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 808 of file gnunet-communicator-libp2p.c.

810{
811 struct TCPConfirmationAck tca;
812 struct TcpHandshakeAckSignature thas;
813
815 "sending challenge\n");
816
817 tca.header.type = ntohs (
819 tca.header.size = ntohs (sizeof(tca));
820 tca.challenge = challenge;
821 tca.sender = my_identity;
822 tca.monotonic_time =
824 thas.purpose.purpose = htonl (
826 thas.purpose.size = htonl (sizeof(thas));
827 thas.sender = my_identity;
828 thas.receiver = queue->target;
829 thas.monotonic_time = tca.monotonic_time;
830 thas.challenge = tca.challenge;
832 &thas,
833 &tca.sender_sig);
834 GNUNET_assert (0 ==
835 gcry_cipher_encrypt (queue->out_cipher,
836 &queue->cwrite_buf[queue->cwrite_off],
837 sizeof(tca),
838 &tca,
839 sizeof(tca)));
840 queue->cwrite_off += sizeof(tca);
842 "sending challenge done\n");
843}
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK
Signature by a peer sending back the nonce received at initial handshake.
#define GNUNET_CRYPTO_eddsa_sign(priv, ps, sig)
EdDSA sign a given block.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK
TCP communicator confirmation ack.
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
Ack for the encrypted continuation of TCP initial handshake.
Signature we use to verify that the ack from the receiver of the ephemeral key was really send by the...
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.

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_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK, GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), TCPConfirmationAck::header, TcpHandshakeAckSignature::monotonic_time, TCPConfirmationAck::monotonic_time, my_identity, my_private_key, 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 853 of file gnunet-communicator-libp2p.c.

854{
855 setup_cipher (dh, &queue->target, &queue->out_cipher, &queue->out_hmac);
857 queue->rekey_left_bytes =
859}
static struct GNUNET_TIME_Relative rekey_interval
The rekey interval.
static unsigned long long rekey_max_bytes
The rekey byte maximum.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).

References GNUNET_CRYPTO_QUALITY_WEAK, 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 869 of file gnunet-communicator-libp2p.c.

870{
871 struct TCPRekey rekey;
872 struct TcpRekeySignature thp;
873 struct GNUNET_ShortHashCode k;
874
875 GNUNET_assert (0 == queue->pwrite_off);
876 memset (&rekey, 0, sizeof(rekey));
877 GNUNET_CRYPTO_eddsa_kem_encaps (&queue->target.public_key, &rekey.ephemeral,
878 &k);
879 rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY);
880 rekey.header.size = ntohs (sizeof(rekey));
881 rekey.monotonic_time =
883 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
884 thp.purpose.size = htonl (sizeof(thp));
886 "inject_rekey size %u\n",
887 thp.purpose.size);
888 thp.sender = my_identity;
890 "sender %s\n",
891 GNUNET_p2s (&thp.sender.public_key));
892 thp.receiver = queue->target;
894 "receiver %s\n",
895 GNUNET_p2s (&thp.receiver.public_key));
896 thp.ephemeral = rekey.ephemeral;
898 "ephemeral %s\n",
899 GNUNET_e2s ((struct GNUNET_CRYPTO_EcdhePublicKey*) &thp.ephemeral)
900 );
901 thp.monotonic_time = rekey.monotonic_time;
903 "time %s\n",
905 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
907 &thp,
908 &rekey.sender_sig);
909 calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac);
910 /* Encrypt rekey message with 'old' cipher */
911 GNUNET_assert (0 ==
912 gcry_cipher_encrypt (queue->out_cipher,
913 &queue->cwrite_buf[queue->cwrite_off],
914 sizeof(rekey),
915 &rekey,
916 sizeof(rekey)));
917 queue->cwrite_off += sizeof(rekey);
918 /* Setup new cipher for successive messages */
919 gcry_cipher_close (queue->out_cipher);
921}
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.
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_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY
TCP communicator rekey message.
TCP rekey message box.

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_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, TCPRekey::monotonic_time, TcpRekeySignature::monotonic_time, my_identity, my_private_key, 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 mq_send_d(), and queue_write().

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 925 of file gnunet-communicator-libp2p.c.

928{
929 struct PendingReversal *pending_reversal = value;
930 (void) cls;
931
932 if (NULL != pending_reversal->timeout_task)
933 {
934 GNUNET_SCHEDULER_cancel (pending_reversal->timeout_task);
935 pending_reversal->timeout_task = NULL;
936 }
939 key,
940 pending_reversal));
941 GNUNET_free (pending_reversal->in);
942 GNUNET_free (pending_reversal);
943 return GNUNET_OK;
944}
static struct GNUNET_CONTAINER_MultiHashMap * pending_reversals
Map of pending reversals.
static char * value
Value of the record to add/remove.
Struct for pending nat reversals.
struct sockaddr * in
Address the reversal was send to.
struct GNUNET_SCHEDULER_Task * timeout_task

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,
struct GNUNET_PeerIdentity sender 
)
static

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

950{
951 if (AF_INET == sa_family)
952 {
953 struct PendingReversal *pending_reversal;
954 struct GNUNET_HashCode key;
955 struct sockaddr_in *natted_address;
956
957 natted_address = GNUNET_memdup (in, sizeof (struct sockaddr));
958 natted_address->sin_port = 0;
959 GNUNET_CRYPTO_hash (natted_address,
960 sizeof(struct sockaddr),
961 &key);
962
964 &key);
965 if (NULL != pending_reversal && (NULL == sender ||
966 0 != memcmp (sender,
967 &pending_reversal->target,
968 sizeof(struct
970 {
972 "Removing invalid pending reversal for `%s'at `%s'\n",
973 GNUNET_i2s (&pending_reversal->target),
974 GNUNET_a2s (in, sizeof (struct sockaddr)));
975 pending_reversals_delete_it (NULL, &key, pending_reversal);
976 }
977 GNUNET_free (natted_address);
978 }
979}
static int pending_reversals_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
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).
struct GNUNET_PeerIdentity target
To whom are we like to talk to.

References GNUNET_a2s(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memdup, key, pending_reversals, pending_reversals_delete_it(), and PendingReversal::target.

Referenced by free_proto_queue(), 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 988 of file gnunet-communicator-libp2p.c.

989{
990 if (NULL != pq->listen_sock)
991 {
993 pq->listen_sock = NULL;
994 }
995 if (NULL != pq->read_task)
996 {
998 pq->read_task = NULL;
999 }
1000 if (NULL != pq->write_task)
1001 {
1003 pq->write_task = NULL;
1004 }
1005 check_and_remove_pending_reversal (pq->address, pq->address->sa_family, NULL);
1007 GNUNET_free (pq->address);
1009 GNUNET_free (pq);
1010}
static void check_and_remove_pending_reversal(struct sockaddr *in, sa_family_t sa_family, struct GNUNET_PeerIdentity *sender)
static struct ProtoQueue * proto_tail
Protoqueues DLL tail.
static struct ProtoQueue * proto_head
Protoqueues DLL head.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
struct GNUNET_SCHEDULER_Task * write_task
ID of write task for this connection.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
struct GNUNET_NETWORK_Handle * sock
socket that we transmit all data with on this queue
struct sockaddr * address
Address of the other peer.
struct GNUNET_SCHEDULER_Task * read_task
ID of read task for this connection.

References ProtoQueue::address, check_and_remove_pending_reversal(), 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 1020 of file gnunet-communicator-libp2p.c.

1021{
1022 struct ProtoQueue *pq = cls;
1023 ssize_t sent;
1024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In proto queue write\n");
1025 pq->write_task = NULL;
1026 if (0 != pq->write_off)
1027 {
1028 sent = GNUNET_NETWORK_socket_send (pq->sock,
1029 pq->write_buf,
1030 pq->write_off);
1032 "Sent %lu bytes to TCP queue\n", sent);
1033 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1034 {
1036 free_proto_queue (pq);
1037 return;
1038 }
1039 if (sent > 0)
1040 {
1041 size_t usent = (size_t) sent;
1042 pq->write_off -= usent;
1043 memmove (pq->write_buf,
1044 &pq->write_buf[usent],
1045 pq->write_off);
1046 }
1047 }
1048 /* do we care to write more? */
1049 if ((0 < pq->write_off))
1050 pq->write_task =
1052 pq->sock,
1054 pq);
1055}
static void proto_queue_write(void *cls)
We have been notified that our socket is ready to write.
static void free_proto_queue(struct ProtoQueue *pq)
Closes socket and frees memory associated with pq.
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:738
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:1582
Handle for an incoming connection where we do not yet have enough information to setup a full queue.
char write_buf[sizeof(struct TCPNATProbeMessage)]
buffer for writing struct TCPNATProbeMessage to network.
size_t write_off
Offset of the buffer?

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().

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 1065 of file gnunet-communicator-libp2p.c.

1066{
1067 struct Queue *queue = cls;
1068 ssize_t sent;
1069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n");
1070 queue->write_task = NULL;
1071 if (0 != queue->cwrite_off)
1072 {
1073 sent = GNUNET_NETWORK_socket_send (queue->sock,
1074 queue->cwrite_buf,
1075 queue->cwrite_off);
1077 "Sent %lu bytes to TCP queue\n", sent);
1078 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1079 {
1082 return;
1083 }
1084 if (sent > 0)
1085 {
1086 size_t usent = (size_t) sent;
1087 queue->cwrite_off -= usent;
1088 memmove (queue->cwrite_buf,
1089 &queue->cwrite_buf[usent],
1090 queue->cwrite_off);
1091 queue->timeout =
1094 }
1095 }
1096 {
1097 /* can we encrypt more? (always encrypt full messages, needed
1098 such that #mq_cancel() can work!) */
1099 unsigned int we_do_not_need_to_rekey = (0 < queue->rekey_left_bytes
1100 - (queue->cwrite_off
1101 + queue->pwrite_off
1102 + sizeof (struct TCPRekey)));
1103 if (we_do_not_need_to_rekey &&
1104 (queue->pwrite_off > 0) &&
1105 (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE))
1106 {
1108 "Encrypting %lu bytes\n", queue->pwrite_off);
1109 GNUNET_assert (0 ==
1110 gcry_cipher_encrypt (queue->out_cipher,
1111 &queue->cwrite_buf[queue->cwrite_off],
1112 queue->pwrite_off,
1113 queue->pwrite_buf,
1114 queue->pwrite_off));
1115 if (queue->rekey_left_bytes > queue->pwrite_off)
1116 queue->rekey_left_bytes -= queue->pwrite_off;
1117 else
1118 queue->rekey_left_bytes = 0;
1119 queue->cwrite_off += queue->pwrite_off;
1120 queue->pwrite_off = 0;
1121 }
1122 // if ((-1 != unverified_size)&& ((0 == queue->pwrite_off) &&
1123 if (((0 == queue->rekey_left_bytes) ||
1125 queue->rekey_time).rel_value_us)) &&
1126 (((0 == queue->pwrite_off) || ! we_do_not_need_to_rekey) &&
1127 (queue->cwrite_off + sizeof (struct TCPRekey) <= BUF_SIZE)))
1128 {
1130 }
1131 }
1132 if ((0 == queue->pwrite_off) && (! queue->finishing) &&
1133 (GNUNET_YES == queue->mq_awaits_continue))
1134 {
1135 queue->mq_awaits_continue = GNUNET_NO;
1137 }
1138 /* did we just finish writing 'finish'? */
1139 if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing))
1140 {
1142 "Finishing queue\n");
1144 return;
1145 }
1146 /* do we care to write more? */
1147 if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off))
1148 queue->write_task =
1150 queue->sock,
1151 &queue_write,
1152 queue);
1153}
static void inject_rekey(struct Queue *queue)
Inject a struct TCPRekey message into the queue's plaintext buffer.
static void queue_write(void *cls)
We have been notified that our socket is ready to write.
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:437
uint64_t rel_value_us
The actual value.

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_read_kx(), queue_write(), and try_handle_plaintext().

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 1164 of file gnunet-communicator-libp2p.c.

1165{
1166 const struct GNUNET_MessageHeader *hdr;
1167 const struct TCPConfirmationAck *tca;
1168 const struct TCPBox *box;
1169 const struct TCPRekey *rekey;
1170 const struct TCPFinish *fin;
1171 struct TCPRekey rekeyz;
1172 struct TCPFinish finz;
1173 struct GNUNET_ShortHashCode tmac;
1174 uint16_t type;
1175 size_t size = 0;
1176 struct TcpHandshakeAckSignature thas;
1177 const struct GNUNET_CRYPTO_ChallengeNonceP challenge = queue->challenge;
1178
1180 "try handle plaintext!\n");
1181
1182 hdr = (const struct GNUNET_MessageHeader *) queue->pread_buf;
1183 if ((sizeof(*hdr) > queue->pread_off))
1184 {
1186 "Handling plaintext, not even a header!\n");
1187 return 0; /* not even a header */
1188 }
1189
1190 if ((GNUNET_YES != queue->initial_core_kx_done) && (queue->unverified_size >
1192 {
1194 "Already received data of size %lu bigger than KX size %lu!\n",
1195 queue->unverified_size,
1197 GNUNET_break_op (0);
1199 return 0;
1200 }
1201
1202 type = ntohs (hdr->type);
1203 switch (type)
1204 {
1206 tca = (const struct TCPConfirmationAck *) queue->pread_buf;
1208 "start processing ack\n");
1209 if (sizeof(*tca) > queue->pread_off)
1210 {
1212 "Handling plaintext size of tca greater than pread offset.\n")
1213 ;
1214 return 0;
1215 }
1216 if (ntohs (hdr->size) != sizeof(*tca))
1217 {
1219 "Handling plaintext size does not match message type.\n");
1220 GNUNET_break_op (0);
1222 return 0;
1223 }
1224
1225 thas.purpose.purpose = htonl (
1227 thas.purpose.size = htonl (sizeof(thas));
1228 thas.sender = tca->sender;
1229 thas.receiver = my_identity;
1230 thas.monotonic_time = tca->monotonic_time;
1231 thas.challenge = tca->challenge;
1232
1235 &thas,
1236 &tca->sender_sig,
1237 &tca->sender.public_key))
1238 {
1240 "Verification of signature failed!\n");
1241 GNUNET_break (0);
1243 return 0;
1244 }
1245 if (0 != GNUNET_memcmp (&tca->challenge, &challenge))
1246 {
1248 "Challenge in TCPConfirmationAck not correct!\n");
1249 GNUNET_break (0);
1251 return 0;
1252 }
1253
1254 queue->handshake_ack_monotime_get = GNUNET_PEERSTORE_iteration_start (
1255 peerstore,
1256 "transport_tcp_communicator",
1257 &queue->target,
1260 queue);
1261
1263 "Handling plaintext, ack processed!\n");
1264
1266 {
1267 send_challenge (queue->challenge_received, queue);
1268 queue->write_task =
1270 queue->sock,
1271 &queue_write,
1272 queue);
1273 }
1274 else if (GNUNET_TRANSPORT_CS_OUTBOUND == queue->cs)
1275 {
1277 queue->address->sa_family, NULL);
1278 }
1279
1284 queue->initial_core_kx_done = GNUNET_YES;
1285
1286 {
1287 char *foreign_addr;
1288
1289 switch (queue->address->sa_family)
1290 {
1291 case AF_INET:
1292 GNUNET_asprintf (&foreign_addr,
1293 "%s-%s",
1295 GNUNET_a2s (queue->address, queue->address_len));
1296 break;
1297
1298 case AF_INET6:
1299 GNUNET_asprintf (&foreign_addr,
1300 "%s-%s",
1302 GNUNET_a2s (queue->address, queue->address_len));
1303 break;
1304
1305 default:
1306 GNUNET_assert (0);
1307 }
1309 &queue->target,
1310 foreign_addr,
1311 UINT16_MAX, /* no MTU */
1313 0, /* Priority */
1314 queue->nt,
1315 queue->cs,
1316 queue->mq);
1317
1318 GNUNET_free (foreign_addr);
1319 }
1320
1321 size = ntohs (hdr->size);
1322 break;
1324 /* Special case: header size excludes box itself! */
1325 box = (const struct TCPBox *) queue->pread_buf;
1326 if (ntohs (hdr->size) + sizeof(struct TCPBox) > queue->pread_off)
1327 return 0;
1328 calculate_hmac (&queue->in_hmac, &box[1], ntohs (hdr->size), &tmac);
1329 if (0 != memcmp (&tmac, &box->hmac, sizeof(tmac)))
1330 {
1331 GNUNET_break_op (0);
1333 return 0;
1334 }
1335 pass_plaintext_to_core (queue, (const void *) &box[1], ntohs (hdr->size));
1336 size = ntohs (hdr->size) + sizeof(*box);
1338 "Handling plaintext, box processed!\n");
1340 "# bytes decrypted with BOX",
1341 size,
1342 GNUNET_NO);
1344 "# messages decrypted with BOX",
1345 1,
1346 GNUNET_NO);
1347 break;
1348
1350 rekey = (const struct TCPRekey *) queue->pread_buf;
1351 if (sizeof(*rekey) > queue->pread_off)
1352 return 0;
1353 if (ntohs (hdr->size) != sizeof(*rekey))
1354 {
1355 GNUNET_break_op (0);
1357 return 0;
1358 }
1359 rekeyz = *rekey;
1360 memset (&rekeyz.hmac, 0, sizeof(rekeyz.hmac));
1361 calculate_hmac (&queue->in_hmac, &rekeyz, sizeof(rekeyz), &tmac);
1362 if (0 != memcmp (&tmac, &rekey->hmac, sizeof(tmac)))
1363 {
1364 GNUNET_break_op (0);
1366 return 0;
1367 }
1368 do_rekey (queue, rekey);
1369 size = ntohs (hdr->size);
1371 "Handling plaintext, rekey processed!\n");
1373 "# rekeying successful",
1374 1,
1375 GNUNET_NO);
1376 break;
1377
1379 fin = (const struct TCPFinish *) queue->pread_buf;
1380 if (sizeof(*fin) > queue->pread_off)
1381 return 0;
1382 if (ntohs (hdr->size) != sizeof(*fin))
1383 {
1384 GNUNET_break_op (0);
1386 return 0;
1387 }
1388 finz = *fin;
1389 memset (&finz.hmac, 0, sizeof(finz.hmac));
1390 calculate_hmac (&queue->in_hmac, &finz, sizeof(finz), &tmac);
1391 if (0 != memcmp (&tmac, &fin->hmac, sizeof(tmac)))
1392 {
1393 GNUNET_break_op (0);
1395 return 0;
1396 }
1397 /* handle FINISH by destroying queue */
1400 "Handling plaintext, finish processed!\n");
1401 break;
1402
1403 default:
1405 "Handling plaintext, nothing processed!\n");
1406 GNUNET_break_op (0);
1408 return 0;
1409 }
1410 GNUNET_assert (0 != size);
1411 if (-1 != queue->unverified_size)
1412 queue->unverified_size += size;
1413 return size;
1414}
#define COMMUNICATOR_ADDRESS_PREFIX
Address prefix used by the communicator.
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 do_rekey(struct Queue *queue, const struct TCPRekey *rekey)
Handle rekey message on queue.
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 void send_challenge(struct GNUNET_CRYPTO_ChallengeNonceP challenge, struct Queue *queue)
Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
#define INITIAL_CORE_KX_SIZE
Size of the initial core key exchange messages.
static uint32_t type
Type string converted to DNS type value.
#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...
@ GNUNET_TRANSPORT_CS_INBOUND
this is an inbound connection (communicator initiated)
@ GNUNET_TRANSPORT_CS_OUTBOUND
this is an outbound connection (transport initiated)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX
TCP communicator payload box.
static unsigned int size
Size of the "table".
Definition peer.c:68
Type of a nonce used for challenges.
struct GNUNET_MQ_Handle * mq
Queue to talk to the transport service.
TCP message box.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.

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_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, 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, 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 1551 of file gnunet-communicator-libp2p.c.

1554{
1555 struct sockaddr *in;
1556
1557 v6.sin6_family = AF_INET6;
1558 v6.sin6_port = htons ((uint16_t) port);
1559#if HAVE_SOCKADDR_IN_SIN_LEN
1560 v6.sin6_len = sizeof(struct sockaddr_in6);
1561#endif
1562 v6.sin6_flowinfo = 0;
1563 v6.sin6_scope_id = 0;
1564 in = GNUNET_memdup (&v6, sizeof(v6));
1565 *sock_len = sizeof(struct sockaddr_in6);
1566
1567 return in;
1568}
static uint16_t port
Port number.
Definition gnunet-bcd.c:146

References GNUNET_memdup, and port.

Referenced by 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 1579 of file gnunet-communicator-libp2p.c.

1582{
1583 struct sockaddr *in;
1584
1585 v4.sin_family = AF_INET;
1586 v4.sin_port = htons ((uint16_t) port);
1587#if HAVE_SOCKADDR_IN_SIN_LEN
1588 v4.sin_len = sizeof(struct sockaddr_in);
1589#endif
1590 in = GNUNET_memdup (&v4, sizeof(v4));
1591 *sock_len = sizeof(struct sockaddr_in);
1592 return in;
1593}

References GNUNET_memdup, and port.

Referenced by 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 1603 of file gnunet-communicator-libp2p.c.

1604{
1605 struct PortOnlyIpv4Ipv6 *po;
1606 struct sockaddr_in *i4;
1607 struct sockaddr_in6 *i6;
1608 socklen_t sock_len_ipv4;
1609 socklen_t sock_len_ipv6;
1610
1611 /* interpreting value as just a PORT number */
1612 if (*port > UINT16_MAX)
1613 {
1615 "BINDTO specification `%s' invalid: value too large for port\n",
1616 bindto);
1617 return NULL;
1618 }
1619
1620 po = GNUNET_new (struct PortOnlyIpv4Ipv6);
1621
1622 if (GNUNET_YES == disable_v6)
1623 {
1624 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
1625 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
1626 *port);
1627 po->addr_len_ipv4 = sock_len_ipv4;
1628 }
1629 else
1630 {
1631
1632 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
1633 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
1634 *port);
1635 po->addr_len_ipv4 = sock_len_ipv4;
1636
1637 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
1638 po->addr_ipv6 = tcp_address_to_sockaddr_numeric_v6 (&sock_len_ipv6, *i6,
1639 *port);
1640
1641 po->addr_len_ipv6 = sock_len_ipv6;
1642
1643 GNUNET_free (i6);
1644 }
1645
1646 GNUNET_free (i4);
1647
1648 return po;
1649}
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 int disable_v6
Disable IPv6.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
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.

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 1659 of file gnunet-communicator-libp2p.c.

1660{
1661 char *addr;
1662 char *start;
1663 char *token;
1664 char *cp;
1665 char *rest = NULL;
1666
1668 "extract address with bindto %s\n",
1669 bindto);
1670
1671 if (NULL == bindto)
1673 "bindto is NULL\n");
1674
1675 cp = GNUNET_strdup (bindto);
1676
1678 "extract address 2\n");
1679
1680 start = cp;
1681 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
1682 {
1683 start++; /* skip over '['*/
1684 cp[strlen (cp) - 1] = '\0'; /* eat ']'*/
1685 addr = GNUNET_strdup (start);
1686 }
1687 else
1688 {
1689 token = strtok_r (cp, "]", &rest);
1690 if (strlen (bindto) == strlen (token))
1691 {
1692 token = strtok_r (cp, ":", &rest);
1693 addr = GNUNET_strdup (token);
1694 }
1695 else
1696 {
1697 token++;
1698 addr = GNUNET_strdup (token);
1699 }
1700 }
1701
1703 "tcp address: %s\n",
1704 addr);
1705 GNUNET_free (cp);
1706 return addr;
1707}
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.

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

Referenced by 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 1717 of file gnunet-communicator-libp2p.c.

1718{
1719 unsigned int port;
1720 char dummy[2];
1721 char *token;
1722 char *addr;
1723 char *colon;
1724 char *cp;
1725 char *rest = NULL;
1726
1727 if (NULL != addr_and_port)
1728 {
1729 cp = GNUNET_strdup (addr_and_port);
1730 token = strtok_r (cp, "]", &rest);
1731 if (strlen (addr_and_port) == strlen (token))
1732 {
1733 colon = strrchr (cp, ':');
1734 if (NULL == colon)
1735 {
1736 GNUNET_free (cp);
1737 return 0;
1738 }
1739 addr = colon;
1740 addr++;
1741 }
1742 else
1743 {
1744 token = strtok_r (NULL, "]", &rest);
1745 if (NULL == token)
1746 {
1747 GNUNET_free (cp);
1748 return 0;
1749 }
1750 else
1751 {
1752 addr = token;
1753 addr++;
1754 }
1755 }
1756
1757
1758 if (1 == sscanf (addr, "%u%1s", &port, dummy))
1759 {
1760 /* interpreting value as just a PORT number */
1761 if (port > UINT16_MAX)
1762 {
1764 "Port `%u' invalid: value too large for port\n",
1765 port);
1766 GNUNET_free (cp);
1767 return 0;
1768 }
1769 }
1770 else
1771 {
1773 "BINDTO specification invalid: last ':' not followed by number\n");
1774 GNUNET_free (cp);
1775 return 0;
1776 }
1777 GNUNET_free (cp);
1778 }
1779 else
1780 {
1782 "return 0\n");
1783 /* interpret missing port as 0, aka pick any free one */
1784 port = 0;
1785 }
1786
1787 return port;
1788}
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.

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

Referenced by 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 1799 of file gnunet-communicator-libp2p.c.

1800{
1801 struct sockaddr *in;
1802 unsigned int port;
1803 struct sockaddr_in v4;
1804 struct sockaddr_in6 v6;
1805 char *start;
1806
1807 memset (&v4, 0, sizeof(v4));
1808 start = extract_address (bindto);
1809 GNUNET_assert (NULL != start);
1811 "start %s\n",
1812 start);
1813
1815 "!bindto %s\n",
1816 bindto);
1817
1818
1819 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
1820 {
1821 port = extract_port (bindto);
1822
1824 "port %u\n",
1825 port);
1826
1827 in = tcp_address_to_sockaddr_numeric_v4 (sock_len, v4, port);
1828 }
1829 else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
1830 {
1831 port = extract_port (bindto);
1832 in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port);
1833 }
1834 else
1835 {
1836 GNUNET_assert (0);
1837 }
1838
1840 return in;
1841}
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.

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 1853 of file gnunet-communicator-libp2p.c.

1856{
1857 struct Queue *queue = impl_state;
1858 uint16_t msize = ntohs (msg->size);
1859 struct TCPBox box;
1861 "In MQ send. Queue finishing: %s; write task running: %s\n",
1862 (GNUNET_YES == queue->finishing) ? "yes" : "no",
1863 (NULL == queue->write_task) ? "yes" : "no");
1864 GNUNET_assert (mq == queue->mq);
1865 queue->mq_awaits_continue = GNUNET_YES;
1866 if (GNUNET_YES == queue->finishing)
1867 return; /* this queue is dying, drop msg */
1868 GNUNET_assert (0 == queue->pwrite_off);
1869 box.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX);
1870 box.header.size = htons (msize);
1871 calculate_hmac (&queue->out_hmac, msg, msize, &box.hmac);
1872 memcpy (&queue->pwrite_buf[queue->pwrite_off], &box, sizeof(box));
1873 queue->pwrite_off += sizeof(box);
1874 memcpy (&queue->pwrite_buf[queue->pwrite_off], msg, msize);
1875 queue->pwrite_off += msize;
1877 "%lu bytes of plaintext to send\n", queue->pwrite_off);
1878 GNUNET_assert (NULL != queue->sock);
1879 if (NULL == queue->write_task)
1880 queue->write_task =
1882 queue->sock,
1883 &queue_write,
1884 queue);
1885}
struct GNUNET_MessageHeader * msg
Definition 005.c:2
static struct GNUNET_SCHEDULER_Task * write_task
ID of write task.
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.

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 1897 of file gnunet-communicator-libp2p.c.

1898{
1899 struct Queue *queue = impl_state;
1900
1901 if (mq == queue->mq)
1902 {
1903 queue->mq = NULL;
1905 }
1906}
struct GNUNET_MQ_Handle * mq
Message queue we are providing for the ch.

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 1916 of file gnunet-communicator-libp2p.c.

1917{
1918 struct Queue *queue = impl_state;
1919
1920 GNUNET_assert (0 != queue->pwrite_off);
1921 queue->pwrite_off = 0;
1922}

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 1935 of file gnunet-communicator-libp2p.c.

1936{
1937 struct Queue *queue = cls;
1938
1940 "MQ error in queue to %s: %d\n",
1941 GNUNET_i2s (&queue->target),
1942 (int) error);
1944}

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 1955 of file gnunet-communicator-libp2p.c.

1956{
1957 queue->nt =
1958 GNUNET_NT_scanner_get_type (is, queue->address, queue->address_len);
1960 queue_map,
1961 &queue->key,
1962 queue,
1965 "# queues active",
1967 GNUNET_NO);
1968 queue->timeout =
1971 &mq_destroy,
1972 &mq_cancel,
1973 queue,
1974 NULL,
1975 &mq_error,
1976 queue);
1977}
static struct GNUNET_TESTING_Interpreter * is
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 c...
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.
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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
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:482
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

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 1991 of file gnunet-communicator-libp2p.c.

1993{
1994 struct TcpHandshakeSignature ths;
1995 struct TCPConfirmation tc;
1996
1997 memcpy (queue->cwrite_buf, c, sizeof(*c));
1998 queue->cwrite_off = sizeof(*c);
1999 /* compute 'tc' and append in encrypted format to cwrite_buf */
2000 tc.sender = my_identity;
2001 tc.monotonic_time =
2004 &tc.challenge,
2005 sizeof(tc.challenge));
2006 ths.purpose.purpose = htonl (
2008 ths.purpose.size = htonl (sizeof(ths));
2009 ths.sender = my_identity;
2010 ths.receiver = queue->target;
2011 ths.ephemeral = *c;
2012 ths.monotonic_time = tc.monotonic_time;
2013 ths.challenge = tc.challenge;
2015 &ths,
2016 &tc.sender_sig);
2017 GNUNET_assert (0 ==
2018 gcry_cipher_encrypt (queue->out_cipher,
2019 &queue->cwrite_buf[queue->cwrite_off],
2020 sizeof(tc),
2021 &tc,
2022 sizeof(tc)));
2023 queue->challenge = tc.challenge;
2024 queue->cwrite_off += sizeof(tc);
2025
2027 "handshake written\n");
2028}
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE
Signature used by TCP communicator handshake.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:431
Encrypted continuation of TCP initial handshake.
Signature we use to verify that the ephemeral key was really chosen by the specified sender.

References cfg, TcpHandshakeSignature::challenge, TcpHandshakeSignature::ephemeral, GNUNET_assert, GNUNET_CRYPTO_eddsa_sign, GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE, GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), TcpHandshakeSignature::monotonic_time, my_identity, my_private_key, 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 2039 of file gnunet-communicator-libp2p.c.

2040{
2042 struct GNUNET_ShortHashCode k;
2043
2045 &c, &k);
2046 setup_out_cipher (queue, &k);
2047 transmit_kx (queue, &c);
2048}
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.
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...
HPKE DHKEM encapsulation (X25519) See RFC 9180.

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 2057 of file gnunet-communicator-libp2p.c.

2058{
2059 struct Queue *queue = cls;
2060 if (GNUNET_OK != success)
2061 {
2063 "Failed to store handshake monotonic time in PEERSTORE!\n");
2064 }
2065 queue->handshake_monotime_sc = NULL;
2066 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
2067}

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 2078 of file gnunet-communicator-libp2p.c.

2081{
2082 struct Queue *queue = cls;
2083 struct GNUNET_TIME_AbsoluteNBO *mtbe;
2084 struct GNUNET_TIME_Absolute mt;
2085 const struct GNUNET_PeerIdentity *pid;
2086 struct GNUNET_TIME_AbsoluteNBO *handshake_monotonic_time;
2087
2088 (void) emsg;
2089
2090 handshake_monotonic_time = &queue->handshake_monotonic_time;
2091 pid = &queue->target;
2093 "tcp handshake with us %s\n",
2095 if (NULL == record)
2096 {
2097 queue->handshake_monotime_get = NULL;
2098 return;
2099 }
2101 "tcp handshake from peer %s\n",
2102 GNUNET_i2s (pid));
2103 if (sizeof(*mtbe) != record->value_size)
2104 {
2105 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
2106 GNUNET_break (0);
2107 return;
2108 }
2109 mtbe = record->value;
2110 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
2111 if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
2112 queue->handshake_monotonic_time).abs_value_us)
2113 {
2115 "Queue from %s dropped, handshake monotime in the past\n",
2116 GNUNET_i2s (&queue->target));
2117 GNUNET_break (0);
2118 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
2119 queue->handshake_ack_monotime_get = NULL;
2121 return;
2122 }
2123 queue->handshake_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
2124 "transport_tcp_communicator",
2125 pid,
2127 handshake_monotonic_time,
2128 sizeof(*
2129 handshake_monotonic_time),
2132 &
2134 queue);
2135}
static void handshake_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for handshake monotime is finished.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE
Key used to store sender's monotonic time from handshake message.

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_TIME_absolute_ntoh(), GNUNET_TIME_UNIT_FOREVER_ABS, handshake_monotime_store_cb(), my_identity, peerstore, pid, 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 2150 of file gnunet-communicator-libp2p.c.

2153{
2154 struct TcpHandshakeSignature ths;
2156
2158 0 ==
2159 gcry_cipher_decrypt (queue->in_cipher,
2160 tc,
2161 sizeof(*tc),
2162 &ibuf[sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)],
2163 sizeof(*tc)));
2164 ths.purpose.purpose = htonl (
2166 ths.purpose.size = htonl (sizeof(ths));
2167 ths.sender = tc->sender;
2168 ths.receiver = my_identity;
2169 memcpy (&ths.ephemeral, ibuf, sizeof(struct GNUNET_CRYPTO_EcdhePublicKey));
2170 ths.monotonic_time = tc->monotonic_time;
2171 ths.challenge = tc->challenge;
2174 &ths,
2175 &tc->sender_sig,
2176 &tc->sender.public_key);
2177 if (GNUNET_YES == ret)
2178 queue->handshake_monotime_get =
2180 "transport_tcp_communicator",
2181 &queue->target,
2184 queue);
2185 return ret;
2186}
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...
GNUNET_GenericReturnValue
Named constants for return values.

References TcpHandshakeSignature::challenge, TcpHandshakeSignature::ephemeral, GNUNET_assert, GNUNET_CRYPTO_eddsa_verify, GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE, GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE, GNUNET_YES, handshake_monotime_cb(), TcpHandshakeSignature::monotonic_time, my_identity, peerstore, 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 2197 of file gnunet-communicator-libp2p.c.

2198{
2199 struct Queue *queue = cls;
2200 ssize_t rcvd;
2201 struct GNUNET_TIME_Relative left;
2202 struct TCPConfirmation tc;
2203
2204 queue->read_task = NULL;
2205 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2206 if (0 == left.rel_value_us)
2207 {
2209 return;
2210 }
2211 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2212 &queue->cread_buf[queue->cread_off],
2213 BUF_SIZE - queue->cread_off);
2215 "Received %lu bytes to write in buffer of size %lu for KX from queue %p (expires in %"
2216 PRIu64 ")\n",
2217 rcvd, BUF_SIZE - queue->cread_off, queue, left.rel_value_us);
2218 if (-1 == rcvd)
2219 {
2220 if ((EAGAIN != errno) && (EINTR != errno))
2221 {
2224 return;
2225 }
2226 queue->read_task =
2228 return;
2229 }
2230 if (0 == rcvd)
2231 {
2232 /* Orderly shutdown of connection */
2234 "Socket for queue %p seems to have been closed\n", queue);
2236 return;
2237 }
2238 queue->cread_off += rcvd;
2239 if (queue->cread_off < INITIAL_KX_SIZE)
2240 {
2241 /* read more */
2243 "%lu/%lu bytes of KX read. Rescheduling...\n",
2244 queue->cread_off, INITIAL_KX_SIZE);
2245 queue->read_task =
2247 return;
2248 }
2249 /* we got all the data, let's find out who we are talking to! */
2251 (const struct GNUNET_CRYPTO_HpkeEncapsulation*)
2252 queue->cread_buf,
2253 queue);
2254 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
2255 {
2257 "Invalid TCP KX received from %s\n",
2258 GNUNET_a2s (queue->address, queue->address_len));
2260 return;
2261 }
2262 if (0 !=
2263 memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
2264 {
2266 "Invalid sender in TCP KX received from %s\n",
2267 GNUNET_a2s (queue->address, queue->address_len));
2269 return;
2270 }
2271 send_challenge (tc.challenge, queue);
2272 queue->write_task =
2274 queue->sock,
2275 &queue_write,
2276 queue);
2277
2278 /* update queue timeout */
2279 queue->timeout =
2281 /* prepare to continue with regular read task immediately */
2282 memmove (queue->cread_buf,
2283 &queue->cread_buf[INITIAL_KX_SIZE],
2284 queue->cread_off - (INITIAL_KX_SIZE));
2286 "cread_off is %lu bytes before adjusting\n",
2287 queue->cread_off);
2288 queue->cread_off -= INITIAL_KX_SIZE;
2290 "cread_off set to %lu bytes\n",
2291 queue->cread_off);
2293}
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 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 setup_in_cipher_elligator(const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct Queue *queue)
Setup cipher of queue for decryption from an elligator representative.
#define INITIAL_KX_SIZE
Size of the initial key exchange message sent first in both directions.
@ GNUNET_ERROR_TYPE_INFO
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:1304

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 2303 of file gnunet-communicator-libp2p.c.

2304{
2305 struct ProtoQueue *pq = cls;
2306 ssize_t rcvd;
2307 struct GNUNET_TIME_Relative left;
2308 struct Queue *queue;
2309 struct TCPConfirmation tc;
2311
2312 pq->read_task = NULL;
2314 if (0 == left.rel_value_us)
2315 {
2316 free_proto_queue (pq);
2317 return;
2318 }
2319 rcvd = GNUNET_NETWORK_socket_recv (pq->sock,
2320 &pq->ibuf[pq->ibuf_off],
2321 sizeof(pq->ibuf) - pq->ibuf_off);
2323 "Proto received %lu bytes for KX\n", rcvd);
2324 if (-1 == rcvd)
2325 {
2326 if ((EAGAIN != errno) && (EINTR != errno))
2327 {
2329 free_proto_queue (pq);
2330 return;
2331 }
2332 /* try again */
2333 pq->read_task =
2335 return;
2336 }
2337 if (0 == rcvd)
2338 {
2339 /* Orderly shutdown of connection */
2341 "Socket for proto queue %p seems to have been closed\n", pq);
2342 free_proto_queue (pq);
2343 return;
2344 }
2345 pq->ibuf_off += rcvd;
2346 if (sizeof (struct TCPNATProbeMessage) == pq->ibuf_off)
2347 {
2348 struct TCPNATProbeMessage *pm = (struct TCPNATProbeMessage *) pq->ibuf;
2349
2351 &pm->clientIdentity);
2352
2353 queue = GNUNET_new (struct Queue);
2354 queue->target = pm->clientIdentity;
2355 eddsa_pub_to_hpke_key (&queue->target.public_key, &queue->target_hpke_key);
2358 }
2359 else if (pq->ibuf_off > sizeof(pq->ibuf))
2360 {
2361 /* read more */
2362 pq->read_task =
2364 return;
2365 }
2366 else
2367 {
2368 /* we got all the data, let's find out who we are talking to! */
2369 queue = GNUNET_new (struct Queue);
2371 (const struct GNUNET_CRYPTO_HpkeEncapsulation *) pq->
2372 ibuf,
2373 queue);
2374 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
2375 {
2377 "Invalid TCP KX received from %s\n",
2378 GNUNET_a2s (pq->address, pq->address_len));
2379 gcry_cipher_close (queue->in_cipher);
2381 free_proto_queue (pq);
2382 return;
2383 }
2384 queue->target = tc.sender;
2385 eddsa_pub_to_hpke_key (&queue->target.public_key, &queue->target_hpke_key);
2388 }
2389 queue->address = pq->address; /* steals reference */
2390 queue->address_len = pq->address_len;
2391 queue->listen_sock = pq->listen_sock;
2392 queue->sock = pq->sock;
2393
2395 "created queue with target %s\n",
2396 GNUNET_i2s (&queue->target));
2397
2399 "start kx proto\n");
2400
2402 boot_queue (queue);
2403 queue->read_task =
2405 queue->sock,
2406 read_task,
2407 queue);
2408 queue->write_task =
2410 queue->sock,
2411 &queue_write,
2412 queue);
2413 // TODO To early! Move it somewhere else.
2414 // send_challenge (tc.challenge, queue);
2415 queue->challenge_received = tc.challenge;
2416
2418 GNUNET_free (pq);
2419}
static void boot_queue(struct Queue *queue)
Add the given queue to our internal data structure.
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 eddsa_pub_to_hpke_key(struct GNUNET_CRYPTO_EddsaPublicKey *edpk, struct GNUNET_CRYPTO_EcdhePublicKey *pk)
static void start_initial_kx_out(struct Queue *queue)
Initialize our key material for outgoing transmissions and inform the other peer about it.
struct GNUNET_SCHEDULER_Task * read_task
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
socklen_t address_len
Length of the address.
size_t ibuf_off
Current offset for reading into ibuf.
struct GNUNET_TIME_Absolute timeout
Timeout for this protoqueue.
char ibuf[(sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)+sizeof(struct TCPConfirmation))]
Buffer for reading all the information we need to upgrade from protoqueue to queue.
Basically a WELCOME message, but with the purpose of giving the waiting peer a client handle to use.

References ProtoQueue::address, ProtoQueue::address_len, boot_queue(), check_and_remove_pending_reversal(), 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, pm, 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 2423 of file gnunet-communicator-libp2p.c.

2426{
2427 struct ProtoQueue *pq = GNUNET_new (struct ProtoQueue);
2428
2429 if (NULL == sock)
2430 {
2431 // sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
2432 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 0);
2433 if (NULL == sock)
2434 {
2436 "socket(%d) failed: %s",
2437 in->sa_family,
2438 strerror (errno));
2439 GNUNET_free (in);
2440 GNUNET_free (pq);
2441 return NULL;
2442 }
2443 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, addrlen)) &&
2444 (errno != EINPROGRESS))
2445 {
2447 "connect to `%s' failed: %s",
2448 GNUNET_a2s (in, addrlen),
2449 strerror (errno));
2451 GNUNET_free (in);
2452 GNUNET_free (pq);
2453 return NULL;
2454 }
2455 }
2456 pq->address_len = addrlen;
2457 pq->address = in;
2459 pq->sock = sock;
2461 pq->sock,
2463 pq);
2465
2466 return pq;
2467}
#define PROTO_QUEUE_TIMEOUT
How long do we wait until we must have received the initial KX?
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:833
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:602

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().

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 2517 of file gnunet-communicator-libp2p.c.

2518{
2519 struct sockaddr *in = cls;
2520 struct PendingReversal *pending_reversal;
2521 struct GNUNET_HashCode key;
2522
2524 sizeof(struct sockaddr),
2525 &key);
2527 &key);
2528
2529 GNUNET_assert (NULL != pending_reversal);
2530
2532 &key,
2533 pending_reversal))
2535 "No pending reversal found for address %s\n",
2536 GNUNET_a2s (in, sizeof (struct sockaddr)));
2537 GNUNET_free (pending_reversal->in);
2538 GNUNET_free (pending_reversal);
2539}

References GNUNET_a2s(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_NO, PendingReversal::in, key, and pending_reversals.

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 2561 of file gnunet-communicator-libp2p.c.

2562{
2563 struct sockaddr *in;
2564 socklen_t in_len = 0;
2565 const char *path;
2566 struct sockaddr_in *v4;
2567 struct sockaddr_in6 *v6;
2568 unsigned int is_natd = GNUNET_NO;
2569 struct GNUNET_HashCode key;
2570 struct GNUNET_HashCode queue_map_key;
2571 struct GNUNET_HashContext *hsh;
2572 struct Queue *queue;
2573
2575 "Connecting to %s at %s\n",
2576 GNUNET_i2s (peer),
2577 address);
2578 if (0 != strncmp (address,
2580 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
2581 {
2582 GNUNET_break_op (0);
2583 return GNUNET_SYSERR;
2584 }
2585 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
2586 in = tcp_address_to_sockaddr (path, &in_len);
2587
2588 if (NULL == in)
2589 {
2591 "Failed to setup TCP socket address\n");
2592 return GNUNET_SYSERR;
2593 }
2594
2596 "in %s\n",
2597 GNUNET_a2s (in, in_len));
2598
2601 GNUNET_CRYPTO_hash_context_read (hsh, peer, sizeof (*peer));
2602 GNUNET_CRYPTO_hash_context_finish (hsh, &queue_map_key);
2604
2605 if (NULL != queue)
2606 {
2608 "Queue for %s already exists or is in construction\n", address);
2609 GNUNET_free (in);
2610 return GNUNET_NO;
2611 }
2612 switch (in->sa_family)
2613 {
2614 case AF_INET:
2615 v4 = (struct sockaddr_in *) in;
2616 if (0 == v4->sin_port)
2617 {
2618 is_natd = GNUNET_YES;
2620 sizeof(struct sockaddr),
2621 &key);
2624 &key))
2625 {
2627 "There is already a request reversal for `%s'at `%s'\n",
2628 GNUNET_i2s (peer),
2629 address);
2630 GNUNET_free (in);
2631 return GNUNET_SYSERR;
2632 }
2633 }
2634 break;
2635
2636 case AF_INET6:
2637 if (GNUNET_YES == disable_v6)
2638 {
2640 "IPv6 disabled, skipping %s\n", address);
2641 GNUNET_free (in);
2642 return GNUNET_SYSERR;
2643 }
2644 v6 = (struct sockaddr_in6 *) in;
2645 if (0 == v6->sin6_port)
2646 {
2648 "Request reversal for `%s' at `%s' not possible for an IPv6 address\n",
2649 GNUNET_i2s (peer),
2650 address);
2651 GNUNET_free (in);
2652 return GNUNET_SYSERR;
2653 }
2654 break;
2655
2656 default:
2657 GNUNET_assert (0);
2658 }
2659
2660 if (GNUNET_YES == is_natd)
2661 {
2662 struct sockaddr_in local_sa;
2663 struct PendingReversal *pending_reversal;
2664
2665 memset (&local_sa, 0, sizeof(local_sa));
2666 local_sa.sin_family = AF_INET;
2667 local_sa.sin_port = htons (bind_port);
2668 /* We leave sin_address at 0, let the kernel figure it out,
2669 even if our bind() is more specific. (May want to reconsider
2670 later.) */
2671 if (GNUNET_OK != GNUNET_NAT_request_reversal (nat, &local_sa, v4))
2672 {
2674 "request reversal for `%s' at `%s' failed\n",
2675 GNUNET_i2s (peer),
2676 address);
2677 GNUNET_free (in);
2678 return GNUNET_SYSERR;
2679 }
2680 pending_reversal = GNUNET_new (struct PendingReversal);
2681 pending_reversal->in = in;
2684 &key,
2685 pending_reversal,
2687 pending_reversal->target = *peer;
2689 &
2691 in);
2693 "Created NAT WAIT connection to `%s' at `%s'\n",
2694 GNUNET_i2s (peer),
2695 GNUNET_a2s (in, sizeof (struct sockaddr)));
2696 }
2697 else
2698 {
2699 struct GNUNET_NETWORK_Handle *sock;
2700
2701 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM,
2702 IPPROTO_TCP);
2703 if (NULL == sock)
2704 {
2706 "socket(%d) failed: %s",
2707 in->sa_family,
2708 strerror (errno));
2709 GNUNET_free (in);
2710 return GNUNET_SYSERR;
2711 }
2712 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
2713 (errno != EINPROGRESS))
2714 {
2716 "connect to `%s' failed: %s",
2717 address,
2718 strerror (errno));
2720 GNUNET_free (in);
2721 return GNUNET_SYSERR;
2722 }
2723
2724 queue = GNUNET_new (struct Queue);
2725 queue->target = *peer;
2726 eddsa_pub_to_hpke_key (&queue->target.public_key, &queue->target_hpke_key);
2727 queue->key = queue_map_key;
2728 queue->address = in;
2729 queue->address_len = in_len;
2730 queue->sock = sock;
2732 boot_queue (queue);
2734 "booted queue with target %s\n",
2735 GNUNET_i2s (&queue->target));
2736 // queue->mq_awaits_continue = GNUNET_YES;
2737 queue->read_task =
2739 queue->sock,
2741 queue);
2742
2743
2745 "start kx mq_init\n");
2746
2748 queue->write_task =
2750 queue->sock,
2751 &queue_write,
2752 queue);
2753 }
2754
2755 return GNUNET_OK;
2756}
static struct GNUNET_NAT_Handle * nat
Connection to NAT service.
static void pending_reversal_timeout(void *cls)
static struct sockaddr * tcp_address_to_sockaddr(const char *bindto, socklen_t *sock_len)
Convert TCP bind specification to a struct sockaddr *
static unsigned int bind_port
The port the communicator should be assigned to.
#define NAT_TIMEOUT
How long until we give up on establishing an NAT connection? Must be > 4 RTT.
static char * address
GNS address for this phone.
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).
@ 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...
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
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_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:1277

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(), 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_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 2768 of file gnunet-communicator-libp2p.c.

2771{
2772 struct ListenTask *lt = value;
2773
2774 (void) cls;
2775 (void) key;
2776 if (NULL != lt->listen_task)
2777 {
2779 lt->listen_task = NULL;
2780 }
2781 if (NULL != lt->listen_sock)
2782 {
2784 lt->listen_sock = NULL;
2785 }
2786 GNUNET_free (lt);
2787 return GNUNET_OK;
2788}

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 2800 of file gnunet-communicator-libp2p.c.

2803{
2804 struct Queue *queue = value;
2805
2806 (void) cls;
2807 (void) target;
2809 return GNUNET_OK;
2810}
struct GNUNET_PeerIdentity target
To whom are we talking to.

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 2819 of file gnunet-communicator-libp2p.c.

2820{
2822 "Shutdown %s!\n",
2823 shutdown_running ? "running" : "not running");
2824
2826 return;
2827 else
2829
2830 while (NULL != proto_head)
2832 if (NULL != nat)
2833 {
2835 nat = NULL;
2836 }
2844 if (NULL != ch)
2845 {
2848 ch = NULL;
2849 }
2850 if (NULL != stats)
2851 {
2853 stats = NULL;
2854 }
2855 if (NULL != my_private_key)
2856 {
2858 my_private_key = NULL;
2859 }
2860 if (NULL != is)
2861 {
2863 is = NULL;
2864 }
2865 if (NULL != pils)
2866 {
2868 pils = NULL;
2869 }
2870 if (NULL != peerstore)
2871 {
2873 peerstore = NULL;
2874 }
2875 if (NULL != resolve_request_handle)
2876 {
2879 }
2881 "Shutdown done!\n");
2882}
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 struct GNUNET_PILS_Handle * pils
For PILS.
struct GNUNET_RESOLVER_RequestHandle * resolve_request_handle
Handle for DNS lookup of bindto address.
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:390
void GNUNET_TRANSPORT_communicator_disconnect(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Disconnect from the transport service.
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.
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_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
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
void GNUNET_NT_scanner_done(struct GNUNET_NT_InterfaceScanner *is)
Terminate interface scanner.
Definition nt.c:428
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).

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_free, GNUNET_log, GNUNET_NAT_unregister(), GNUNET_NT_scanner_done(), GNUNET_PEERSTORE_disconnect(), GNUNET_PILS_disconnect(), GNUNET_RESOLVER_request_cancel(), GNUNET_STATISTICS_destroy(), GNUNET_TRANSPORT_communicator_address_remove_all(), GNUNET_TRANSPORT_communicator_disconnect(), GNUNET_YES, is, lt_map, my_private_key, 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 2897 of file gnunet-communicator-libp2p.c.

2900{
2901 (void) cls;
2902 (void) sender;
2903 (void) msg;
2904 GNUNET_break_op (0);
2905}

References GNUNET_break_op, and msg.

Referenced by init_socket().

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 2912 of file gnunet-communicator-libp2p.c.

2913{
2914
2915 struct Addresses *saddrs;
2916
2918 "add address %s\n",
2919 GNUNET_a2s (in, in_len));
2920
2921 saddrs = GNUNET_new (struct Addresses);
2922 saddrs->addr = in;
2923 saddrs->addr_len = in_len;
2925
2927 "after add address %s\n",
2928 GNUNET_a2s (in, in_len));
2929
2931 "add address %s\n",
2932 GNUNET_a2s (saddrs->addr, saddrs->addr_len));
2933
2934 addrs_lens++;
2935}
static struct Addresses * addrs_head
Head of DLL with addresses we like to register at NAT service.
static struct Addresses * addrs_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.
DLL to store the addresses we like to register at NAT service.
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.

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:

◆ load_ikm()

static enum GNUNET_GenericReturnValue load_ikm ( )
static

FIXME: We could alternatively ask PILS for de/encaps, but at a high cost wrt async RPC calls...

Get the initial secret key for generating the peer id. This is supposed to be generated at random once in the lifetime of a peer, so all generated peer ids use the same initial secret key to obtain the same peer id per set of addresses.

First check whether there's already a initial secret key. If so: return it. If no initial secret key exists yet, generate at random and store it where it will be found.

Parameters
initialsecret key the memory the initial secret key can be written to.

Definition at line 2952 of file gnunet-communicator-libp2p.c.

2953{
2954 char *filename;
2955 struct GNUNET_DISK_FileHandle *filehandle;
2956 int ret;
2957
2958 if (GNUNET_OK !=
2960 "pils",
2961 "SECRET_KEY_FILE",
2962 &filename))
2963 {
2965 "PILS service is lacking initial secret key file configuration setting. Exiting\n");
2966 return GNUNET_SYSERR;
2967 }
2968 if (NULL == filename)
2969 return GNUNET_SYSERR;
2971 if (GNUNET_SYSERR == ret)
2972 return GNUNET_SYSERR;
2973 if (GNUNET_NO == ret)
2974 {
2975 /* File does not exist - generate a new initial secret key and save it */
2976 // TODO consider the case that the file exists and ist not readable
2978 ikm,
2979 sizeof ikm);
2981 {
2983 "PILS service cannot create dir for saving initial secret key file. Exiting\n");
2984 return GNUNET_SYSERR;
2985 }
2986 filehandle = GNUNET_DISK_file_open (filename,
2990 | // would
2991 // the
2992 // group
2993 // need
2994 // read
2995 // perm?
2997 if (NULL == filehandle)
2998 {
3000 "PILS service had an issue with opening the initial secret key file. Exiting\n");
3001 GNUNET_DISK_file_close (filehandle);
3002 return GNUNET_SYSERR;
3003 }
3004 ret = GNUNET_DISK_file_write (filehandle,
3005 ikm,
3006 sizeof ikm);
3007 GNUNET_DISK_file_close (filehandle);
3008 if (sizeof ikm != ret)
3009 {
3011 "PILS service had an issue with writing the initial secret key to file. Exiting\n")
3012 ;
3013 return GNUNET_SYSERR;
3014 }
3015 }
3016 else
3017 {
3018 /* File existes - just read from it */
3019 off_t size;
3021 "PILS is going to read initial secret key from file %s\n",
3022 filename);
3023 filehandle = GNUNET_DISK_file_open (filename,
3026 if (NULL == filehandle)
3027 {
3029 " Not able to open file\n");
3030 return GNUNET_SYSERR;
3031 }
3032 if (GNUNET_OK != GNUNET_DISK_file_handle_size (filehandle, &size))
3033 {
3035 " File has the wrong size %lu\n",
3036 size);
3037 GNUNET_DISK_file_close (filehandle);
3038 return GNUNET_SYSERR;
3039 }
3040 if (sizeof ikm != size)
3041 {
3043 " Something is wrong with the file size, expected: %lu size, got: %lu\n",
3044 size,
3045 sizeof ikm);
3046 GNUNET_DISK_file_close (filehandle);
3047 return GNUNET_SYSERR;
3048 }
3049 ret = GNUNET_DISK_file_read (filehandle,
3050 ikm,
3051 sizeof ikm);
3052 GNUNET_DISK_file_close (filehandle);
3053 if (sizeof ikm != ret)
3054 {
3056 " Read initial secret key with wrong size %u, expected %lu\n", ret,
3057 sizeof ikm);
3058 return GNUNET_SYSERR;
3059 }
3060
3061 }
3062 return GNUNET_OK;
3063}
#define LOG(kind,...)
static char * filename
static unsigned char ikm[256/8]
The initial key material for the peer.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition disk.c:1258
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition disk.c:710
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test_read(const char *fil)
Check that fil corresponds to a filename and the file has read permissions.
Definition disk.c:540
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition disk.c:1332
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition disk.c:633
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition disk.c:673
enum GNUNET_GenericReturnValue GNUNET_DISK_file_handle_size(struct GNUNET_DISK_FileHandle *fh, off_t *size)
Get the size of an open file.
Definition disk.c:206
@ GNUNET_DISK_OPEN_READ
Open the file for reading.
@ GNUNET_DISK_OPEN_WRITE
Open the file for writing.
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_NONE
Nobody is allowed to do anything to the file.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
Handle used to access files (and pipes).

References cfg, filename, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_DISK_directory_create_for_file(), GNUNET_DISK_file_close(), GNUNET_DISK_file_handle_size(), GNUNET_DISK_file_open(), GNUNET_DISK_file_read(), GNUNET_DISK_file_test_read(), GNUNET_DISK_file_write(), GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_OPEN_READ, GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_NONE, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, ikm, LOG, ret, and size.

Referenced by run().

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 3074 of file gnunet-communicator-libp2p.c.

3076{
3077 struct sockaddr_storage in_sto;
3078 socklen_t sto_len;
3079 struct GNUNET_NETWORK_Handle *listen_sock;
3080 struct ListenTask *lt;
3081 int sockfd;
3082 struct GNUNET_HashCode h_sock;
3083
3084 if (NULL == addr)
3085 {
3087 "Address is NULL.\n");
3088 return GNUNET_SYSERR;
3089 }
3090
3092 "address %s\n",
3093 GNUNET_a2s (addr, in_len));
3094
3095 listen_sock =
3096 GNUNET_NETWORK_socket_create (addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
3097 if (NULL == listen_sock)
3098 {
3100 return GNUNET_SYSERR;
3101 }
3102
3103 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, addr, in_len))
3104 {
3106 GNUNET_NETWORK_socket_close (listen_sock);
3107 listen_sock = NULL;
3108 return GNUNET_SYSERR;
3109 }
3110
3111 if (GNUNET_OK !=
3112 GNUNET_NETWORK_socket_listen (listen_sock,
3113 5))
3114 {
3116 "listen");
3117 GNUNET_NETWORK_socket_close (listen_sock);
3118 listen_sock = NULL;
3119 return GNUNET_SYSERR;
3120 }
3121
3122 /* We might have bound to port 0, allowing the OS to figure it out;
3123 thus, get the real IN-address from the socket */
3124 sto_len = sizeof(in_sto);
3125
3126 if (0 != getsockname (GNUNET_NETWORK_get_fd (listen_sock),
3127 (struct sockaddr *) &in_sto,
3128 &sto_len))
3129 {
3130 memcpy (&in_sto, addr, in_len);
3131 sto_len = in_len;
3132 }
3133
3134 // addr = (struct sockaddr *) &in_sto;
3135 in_len = sto_len;
3137 "Bound to `%s'\n",
3138 GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len));
3139 if (NULL == stats)
3140 stats = GNUNET_STATISTICS_create ("communicator-tcp", cfg);
3141
3142 if (NULL == is)
3144
3145 /* start listening */
3146
3147 lt = GNUNET_new (struct ListenTask);
3148 lt->listen_sock = listen_sock;
3149
3151 listen_sock,
3152 &listen_cb,
3153 lt);
3154
3156 "creating hash\n");
3157 sockfd = GNUNET_NETWORK_get_fd (lt->listen_sock);
3158 GNUNET_CRYPTO_hash (&sockfd,
3159 sizeof(int),
3160 &h_sock);
3161
3163 "creating map\n");
3164 if (NULL == lt_map)
3166
3168 "creating map entry\n");
3171 &h_sock,
3172 lt,
3174
3176 "map entry created\n");
3177
3178 if (NULL == queue_map)
3180
3181 if (NULL == ch)
3186 &mq_init,
3187 NULL,
3189 NULL,
3190 NULL);
3191
3192 if (NULL == ch)
3193 {
3194 GNUNET_break (0);
3195 if (NULL != resolve_request_handle)
3198 return GNUNET_SYSERR;
3199 }
3200
3201 add_addr (addr, in_len);
3202 return GNUNET_OK;
3203
3204}
#define COMMUNICATOR_CONFIG_SECTION
Configuration section used by the 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 (!...
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 add_addr(struct sockaddr *in, socklen_t in_len)
This method adds addresses to the DLL, that are later register at the NAT service.
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.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
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:652
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init(void)
Initialize the address characterization client handle.
Definition nt.c:407
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:567
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.

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 run().

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

◆ pid_change_cb()

void pid_change_cb ( void *  cls,
const struct GNUNET_HELLO_Parser parser,
const struct GNUNET_HashCode addr_hash 
)

Definition at line 3208 of file gnunet-communicator-libp2p.c.

3211{
3213 "Got PID to derive from `%s':\n",
3214 GNUNET_h2s (addr_hash));
3215 if (NULL == my_private_key)
3217
3219 (uint8_t*) ikm,
3220 addr_hash,
3226}
static void eddsa_priv_to_hpke_key(struct GNUNET_CRYPTO_EddsaPrivateKey *edpk, struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
void GNUNET_PILS_derive_pid(size_t seed_key_bytes, const uint8_t seed_key[seed_key_bytes], const struct GNUNET_HashCode *addrs_hash, struct GNUNET_CRYPTO_EddsaPrivateKey *outkey)
Generate the peer id from the addresses hash and the initial secret key.
Definition pils_api.c:507
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition crypto_ecc.c:201
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
Private ECC key encoded for transmission.
struct GNUNET_CRYPTO_EddsaPublicKey public_key

References eddsa_priv_to_hpke_key(), GNUNET_CRYPTO_eddsa_key_get_public(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_new, GNUNET_PILS_derive_pid(), ikm, LOG, my_identity, my_private_key, my_x25519_private_key, and GNUNET_PeerIdentity::public_key.

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 3238 of file gnunet-communicator-libp2p.c.

3242{
3243 struct sockaddr *in;
3244
3245 (void) cls;
3246
3247 cfg = c;
3248 if (GNUNET_OK !=
3251 "REKEY_INTERVAL",
3253 {
3255 }
3256 load_ikm ();
3258 GNUNET_assert (NULL != pils);
3260 if (NULL == peerstore)
3261 {
3262 GNUNET_free (bindto);
3263 GNUNET_break (0);
3265 return;
3266 }
3267
3269
3270 if (1 == sscanf (bindto, "%u%1s", &bind_port, dummy))
3271 {
3273 addr_len_ipv4 = po->addr_len_ipv4;
3275 "address po %s\n",
3276 GNUNET_a2s (po->addr_ipv4, addr_len_ipv4));
3277 if (NULL != po->addr_ipv4)
3278 {
3279 init_socket (po->addr_ipv4, addr_len_ipv4);
3280 }
3281 if (NULL != po->addr_ipv6)
3282 {
3283 addr_len_ipv6 = po->addr_len_ipv6;
3284 init_socket (po->addr_ipv6, addr_len_ipv6);
3285 }
3286
3287 // The following snippet is taken from https://github.com/libp2p/cpp-libp2p/blob/master/example/01-echo/libp2p_echo_client.cpp
3288 // and needs to be wrapped to c for being able to be called from within
3289 // this communicator.
3290 // It is merely there as a reminder of the needed functions and general
3291 // structure in order to send something via the c++ implementation of
3292 // libp2p.
3293 //
3294 // post(
3295 // *context,
3296 // [log,
3297 // host{std::move(host)},
3298 // &echo,
3299 // &message,
3300 // argv, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3301 // sch] {
3302 // auto server_ma_res =
3303 // libp2p::multi::Multiaddress::create(argv[1]); // NOLINT
3304 // if (!server_ma_res) {
3305 // log->error("unable to create server multiaddress: {}",
3306 // server_ma_res.error());
3307 // std::exit(EXIT_FAILURE);
3308 // }
3309 // const auto &server_ma = server_ma_res.value();
3310
3311 // auto server_peer_id_str = server_ma.getPeerId();
3312 // if (!server_peer_id_str) {
3313 // log->error("unable to get peer id");
3314 // std::exit(EXIT_FAILURE);
3315 // }
3316
3317 // auto server_peer_id_res =
3318 // libp2p::peer::PeerId::fromBase58(*server_peer_id_str);
3319 // if (!server_peer_id_res) {
3320 // log->error("Unable to decode peer id from base 58: {}",
3321 // server_peer_id_res.error());
3322 // std::exit(EXIT_FAILURE);
3323 // }
3324
3325 // const auto &server_peer_id = server_peer_id_res.value();
3326
3327 // auto peer_info = libp2p::peer::PeerInfo{server_peer_id, {server_ma}};
3328
3329 // // create Host object and open a stream through it
3330 // host->newStream(
3331 // peer_info,
3332 // {echo.getProtocolId()},
3333 // [log, &echo, &message, sch](auto &&stream_res) {
3334 // if (!stream_res) {
3335 // log->error("Cannot connect to server: {}", stream_res.error());
3336 // std::exit(EXIT_FAILURE);
3337 // }
3338
3339 // auto stream_p = std::move(stream_res.value().stream);
3340
3341 // auto echo_client = echo.createClient(stream_p);
3342
3343 // if (message.size() < 120) {
3344 // log->info("SENDING {}", message);
3345 // } else {
3346 // log->info("SENDING {} bytes", message.size());
3347 // }
3348
3349 // sch->schedule(
3350 // [log, message, stream = std::move(stream_p), echo_client] {
3351 // echo_client->sendAnd(
3352 // message,
3353 // [log,
3354 // stream = std::move(stream)](auto &&response_result) {
3355 // if (response_result.has_error()) {
3356 // log->info("Error happened: {}",
3357 // response_result.error());
3358 // stream->close(
3359 // [log](auto &&) { std::exit(EXIT_SUCCESS); });
3360 // return;
3361 // }
3362 // auto &resp = response_result.value();
3363 // if (resp.size() < 120) {
3364 // log->info("RESPONSE {}", resp);
3365 // } else {
3366 // log->info("RESPONSE size={}", resp.size());
3367 // }
3368 // stream->close(
3369 // [](auto &&) { std::exit(EXIT_SUCCESS); });
3370 // });
3371 // },
3372 // std::chrono::milliseconds(1000));
3373 // });
3374 // });
3375
3376 GNUNET_free (po);
3377 GNUNET_free (bindto);
3378 return;
3379 }
3380}
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
void pid_change_cb(void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *addr_hash)
static struct PortOnlyIpv4Ipv6 * tcp_address_to_sockaddr_port_only(const char *bindto, unsigned int *port)
Convert TCP bind specification to a struct PortOnlyIpv4Ipv6 *
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 enum GNUNET_GenericReturnValue load_ikm()
FIXME: We could alternatively ask PILS for de/encaps, but at a high cost wrt async RPC calls....
#define DEFAULT_REKEY_INTERVAL
How often do we rekey based on time (at least)
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:367
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.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
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:1339

References bind_port, cfg, COMMUNICATOR_CONFIG_SECTION, DEFAULT_REKEY_INTERVAL, do_shutdown, dummy, GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_CONFIGURATION_get_value_time(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_OK, GNUNET_PEERSTORE_connect(), GNUNET_PILS_connect(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), init_socket(), load_ikm(), peerstore, pid_change_cb(), pils, rekey_interval, 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 3391 of file gnunet-communicator-libp2p.c.

3392{
3393 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3395 };
3396 int ret;
3397
3399 "Starting tcp communicator\n");
3400
3401 ret = (GNUNET_OK ==
3403 argc,
3404 argv,
3405 "gnunet-communicator-libp2p",
3406 _ ("GNUnet libp2p communicator"),
3407 options,
3408 &run,
3409 NULL))
3410 ? 0
3411 : 1;
3412 return ret;
3413}
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Setup communicator and launch network interactions.
#define GNUNET_GETOPT_OPTION_END
Marker for the end of the list of options.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
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:407
#define _(String)
GNU gettext support macro.
Definition platform.h:179
Definition of a command line option.

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

◆ pils

struct GNUNET_PILS_Handle* pils
static

For PILS.

Definition at line 118 of file gnunet-communicator-libp2p.c.

Referenced by do_shutdown(), and run().

◆ stats

◆ ch

Our environment.

Definition at line 128 of file gnunet-communicator-libp2p.c.

Referenced by do_shutdown(), init_socket(), pass_plaintext_to_core(), and try_handle_plaintext().

◆ queue_map

struct GNUNET_CONTAINER_MultiHashMap* queue_map
static

Queues (map from peer identity to struct Queue)

Definition at line 133 of file gnunet-communicator-libp2p.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 138 of file gnunet-communicator-libp2p.c.

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

◆ my_identity

◆ my_private_key

struct GNUNET_CRYPTO_EddsaPrivateKey* my_private_key
static

◆ my_x25519_private_key

struct GNUNET_CRYPTO_EcdhePrivateKey my_x25519_private_key
static

Our private key.

Definition at line 153 of file gnunet-communicator-libp2p.c.

Referenced by pid_change_cb(), and setup_in_cipher_elligator().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

Definition at line 158 of file gnunet-communicator-libp2p.c.

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

◆ addrs_head

struct Addresses* addrs_head
static

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

Definition at line 163 of file gnunet-communicator-libp2p.c.

Referenced by add_addr().

◆ addrs_tail

struct Addresses* addrs_tail
static

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

Definition at line 168 of file gnunet-communicator-libp2p.c.

Referenced by add_addr().

◆ peerstore

◆ shutdown_running

int shutdown_running = GNUNET_NO
static

A flag indicating we are already doing a shutdown.

Definition at line 178 of file gnunet-communicator-libp2p.c.

Referenced by do_shutdown(), and queue_destroy().