GNUnet  0.19.3
gnunet-service-setu.c File Reference

set union operation More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_statistics_service.h"
#include "ibf.h"
#include "gnunet_protocols.h"
#include "gnunet_applications.h"
#include "gnunet_cadet_service.h"
#include "gnunet-service-setu_strata_estimator.h"
#include "gnunet-service-setu_protocol.h"
#include <gcrypt.h>
#include "gnunet_setu_service.h"
#include "setu.h"
Include dependency graph for gnunet-service-setu.c:

Go to the source code of this file.

Data Structures

struct  ElementEntry
 Information about an element element in the set. More...
 
struct  ClientState
 State we keep per client. More...
 
struct  Operation
 Operation context used to execute a set operation. More...
 
struct  SetContent
 SetContent stores the actual set elements, which may be shared by multiple generations derived from one set. More...
 
struct  Set
 A set that supports a specific operation with other peers. More...
 
struct  KeyEntry
 The key entry is used to associate an ibf key with an element. More...
 
struct  SendElementClosure
 Used as a closure for sending elements with a specific IBF key. More...
 
struct  Listener
 A listener is inhabited by a client, and waits for evaluation requests from remote peers. More...
 
struct  messageControlFlowElement
 Struct to tracked messages in message control flow. More...
 
struct  GetElementContext
 Context for op_get_element_iterator. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "setu", __VA_ARGS__)
 
#define INCOMING_CHANNEL_TIMEOUT   GNUNET_TIME_UNIT_MINUTES
 How long do we hold on to an incoming channel if there is no local listener before giving up? More...
 
#define SE_STRATA_COUNT   32
 Number of IBFs in a strata estimator. More...
 
#define SE_IBFS_TOTAL_SIZE   632
 Primes for all 4 different strata estimators 61,67,71,73,79,83,89,97 348 Based on the bsc thesis of Elias Summermatter (2021) More...
 
#define SE_IBF_HASH_NUM   3
 The hash num parameter for the difference digests and strata estimators. More...
 
#define MAX_BUCKETS_PER_MESSAGE   ((1 << 16) / IBF_BUCKET_SIZE)
 Number of buckets that can be transmitted in one message. More...
 
#define MAX_IBF_SIZE   1048576
 The maximum size of an ibf we use is MAX_IBF_SIZE=2^20. More...
 
#define IBF_MIN_SIZE   37
 Minimal size of an ibf Based on the bsc thesis of Elias Summermatter (2021) More...
 
#define DIFFERENTIAL_RTT_MEAN   3.65145
 AVG RTT for differential sync when k=2 and Factor = 2 Based on the bsc thesis of Elias Summermatter (2021) More...
 
#define SECURITY_LEVEL   80
 Security level used for byzantine checks (2^80) More...
 
#define PROBABILITY_FOR_NEW_ROUND   0.15
 Is the estimated probability for a new round this values is based on the bsc thesis of Elias Summermatter (2021) More...
 
#define MEASURE_PERFORMANCE   0
 Measure the performance in a csv. More...
 

Enumerations

enum  UnionOperationPhase {
  PHASE_EXPECT_SE , PHASE_EXPECT_IBF , PHASE_EXPECT_IBF_CONT , PHASE_INVENTORY_ACTIVE ,
  PHASE_INVENTORY_PASSIVE , PHASE_FINISH_CLOSING , PHASE_FINISH_WAITING , PHASE_DONE ,
  PHASE_FULL_SENDING , PHASE_EXPECT_SE , PHASE_EXPECT_IBF , PHASE_EXPECT_IBF_LAST ,
  PHASE_ACTIVE_DECODING , PHASE_PASSIVE_DECODING , PHASE_FINISH_CLOSING , PHASE_FINISH_WAITING ,
  PHASE_FINISHED , PHASE_FULL_SENDING , PHASE_FULL_RECEIVING
}
 Current phase we are in for a union operation. More...
 
enum  MODE_OF_OPERATION { DIFFERENTIAL_SYNC , FULL_SYNC_LOCAL_SENDING_FIRST , FULL_SYNC_REMOTE_SENDING_FIRST }
 Different modes of operations. More...
 
enum  MESSAGE_CONTROL_FLOW_STATE { MSG_CFS_UNINITIALIZED , MSG_CFS_SENT , MSG_CFS_EXPECTED , MSG_CFS_RECEIVED }
 Different states to control the messages flow in differential mode. More...
 
enum  MESSAGE_TYPE { OFFER_MESSAGE , DEMAND_MESSAGE , ELEMENT_MESSAGE }
 Message types to track in message control flow. More...
 

Functions

static uint8_t estimate_best_mode_of_operation (uint64_t avg_element_size, uint64_t local_set_size, uint64_t remote_set_size, uint64_t est_set_diff_remote, uint64_t est_set_diff_local, uint64_t bandwith_latency_tradeoff, uint64_t ibf_bucket_number_factor)
 Function that chooses the optimal mode of operation depending on operation parameters. More...
 
static enum GNUNET_GenericReturnValue check_valid_phase (const uint8_t allowed_phases[], size_t size_phases, struct Operation *op)
 Validates the if a message is received in a correct phase. More...
 
static int update_message_control_flow (struct GNUNET_CONTAINER_MultiHashMap *hash_map, enum MESSAGE_CONTROL_FLOW_STATE new_mcfs, const struct GNUNET_HashCode *hash_code, enum MESSAGE_TYPE mt)
 Function to update, track and validate message received in differential sync. More...
 
static int is_message_in_message_control_flow (struct GNUNET_CONTAINER_MultiHashMap *hash_map, struct GNUNET_HashCode *hash_code, enum MESSAGE_TYPE mt)
 Validate if a message in differential sync si already received before. More...
 
static int determinate_done_message_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
 Iterator for determining if all demands have been satisfied. More...
 
static int determinate_avg_element_size_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
 Iterator for determining average size. More...
 
static int create_randomized_element_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
 Create randomized element hashmap for full sending. More...
 
static int destroy_key_to_element_iter (void *cls, uint32_t key, void *value)
 Iterator over hash map entries, called to destroy the linked list of colliding ibf key entries. More...
 
static void send_client_done (void *cls)
 Signal to the client that the operation has finished and destroy the operation. More...
 
static int check_byzantine_bounds (struct Operation *op)
 Check if all given byzantine parameters are in given boundaries. More...
 
static enum GNUNET_GenericReturnValue free_values_iter (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static void _GSS_operation_destroy (struct Operation *op)
 Destroy the given operation. More...
 
static void _GSS_operation_destroy2 (struct Operation *op)
 This function probably should not exist and be replaced by inlining more specific logic in the various places where it is called. More...
 
static void incoming_destroy (struct Operation *op)
 Destroy an incoming request from a remote peer. More...
 
static void fail_union_operation (struct Operation *op)
 Inform the client that the union operation has failed, and proceed to destroy the evaluate operation. More...
 
static void full_sync_plausibility_check (struct Operation *op)
 Function that checks if full sync is plausible. More...
 
static void check_max_differential_rounds (struct Operation *op)
 Limit active passive switches in differential sync to configured security level. More...
 
static struct IBF_Key get_ibf_key (const struct GNUNET_HashCode *src)
 Derive the IBF key from a hash code and a salt. More...
 
static int op_get_element_iterator (void *cls, uint32_t key, void *value)
 Iterator over the mapping from IBF keys to element entries. More...
 
static struct KeyEntryop_get_element (struct Operation *op, const struct GNUNET_HashCode *element_hash)
 Determine whether the given element is already in the operation's element set. More...
 
static void op_register_element (struct Operation *op, struct ElementEntry *ee, int received)
 Insert an element into the union operation's key-to-element mapping. More...
 
static void salt_key (const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
 Modify an IBF key k_in based on the salt, returning a salted key in k_out. More...
 
static void unsalt_key (const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
 Reverse modification done in the salt_key function. More...
 
static int prepare_ibf_iterator (void *cls, uint32_t key, void *value)
 Insert a key into an ibf. More...
 
static int _GSS_is_element_of_operation (struct ElementEntry *ee, struct Operation *op)
 Is element ee part of the set used by op? More...
 
static int init_key_to_element_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
 Iterator for initializing the key-to-element mapping of a union operation. More...
 
static void initialize_key_to_element (struct Operation *op)
 Initialize the IBF key to element mapping local to this set operation. More...
 
static int prepare_ibf (struct Operation *op, uint32_t size)
 Create an ibf with the operation's elements of the specified size. More...
 
static int send_ibf (struct Operation *op, uint32_t ibf_size)
 Send an ibf of appropriate size. More...
 
static unsigned int get_size_from_difference (unsigned int diff, int number_buckets_per_element, float ibf_bucket_number_factor)
 Compute the necessary order of an ibf from the size of the symmetric set difference. More...
 
static unsigned int get_next_ibf_size (float ibf_bucket_number_factor, unsigned int decoded_elements, unsigned int last_ibf_size)
 
static int send_full_element_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
 Send a set element. More...
 
static void send_full_set (struct Operation *op)
 Switch to full set transmission for op. More...
 
static int check_union_p2p_strata_estimator (void *cls, const struct StrataEstimatorMessage *msg)
 Handle a strata estimator from a remote peer. More...
 
static void handle_union_p2p_strata_estimator (void *cls, const struct StrataEstimatorMessage *msg)
 Handle a strata estimator from a remote peer. More...
 
static int send_offers_iterator (void *cls, uint32_t key, void *value)
 Iterator to send elements to a remote peer. More...
 
void send_offers_for_key (struct Operation *op, struct IBF_Key ibf_key)
 Send offers (in the form of GNUNET_Hash-es) to the remote peer for the given IBF key. More...
 
static int decode_and_send (struct Operation *op)
 Decode which elements are missing on each side, and send the appropriate offers and inquiries. More...
 
static int check_union_p2p_send_full (void *cls, const struct TransmitFullMessage *msg)
 Check send full message received from other peer. More...
 
static void handle_union_p2p_send_full (void *cls, const struct TransmitFullMessage *msg)
 Handle send full message received from other peer. More...
 
static int check_union_p2p_ibf (void *cls, const struct IBFMessage *msg)
 Check an IBF message from a remote peer. More...
 
static void handle_union_p2p_ibf (void *cls, const struct IBFMessage *msg)
 Handle an IBF message from a remote peer. More...
 
static void send_client_element (struct Operation *op, const struct GNUNET_SETU_Element *element, enum GNUNET_SETU_Status status)
 Send a result message to the client indicating that there is a new element. More...
 
static void maybe_finish (struct Operation *op)
 Tests if the operation is finished, and if so notify. More...
 
static int check_union_p2p_elements (void *cls, const struct GNUNET_SETU_ElementMessage *emsg)
 Check an element message from a remote peer. More...
 
static void handle_union_p2p_elements (void *cls, const struct GNUNET_SETU_ElementMessage *emsg)
 Handle an element message from a remote peer. More...
 
static int check_union_p2p_full_element (void *cls, const struct GNUNET_SETU_ElementMessage *emsg)
 Check a full element message from a remote peer. More...
 
static void handle_union_p2p_full_element (void *cls, const struct GNUNET_SETU_ElementMessage *emsg)
 Handle an element message from a remote peer. More...
 
static int check_union_p2p_inquiry (void *cls, const struct InquiryMessage *msg)
 Send offers (for GNUNET_Hash-es) in response to inquiries (for IBF_Key-s). More...
 
static void handle_union_p2p_inquiry (void *cls, const struct InquiryMessage *msg)
 Send offers (for GNUNET_Hash-es) in response to inquiries (for IBF_Key-s). More...
 
static int send_missing_full_elements_iter (void *cls, uint32_t key, void *value)
 Iterator over hash map entries, called to destroy the linked list of colliding ibf key entries. More...
 
static int check_union_p2p_request_full (void *cls, const struct TransmitFullMessage *mh)
 Handle a request for full set transmission. More...
 
static void handle_union_p2p_request_full (void *cls, const struct TransmitFullMessage *msg)
 
static void handle_union_p2p_full_done (void *cls, const struct GNUNET_MessageHeader *mh)
 Handle a "full done" message. More...
 
static int check_union_p2p_demand (void *cls, const struct GNUNET_MessageHeader *mh)
 Check a demand by the other peer for elements based on a list of struct GNUNET_HashCodes. More...
 
static void handle_union_p2p_demand (void *cls, const struct GNUNET_MessageHeader *mh)
 Handle a demand by the other peer for elements based on a list of struct GNUNET_HashCodes. More...
 
static int check_union_p2p_offer (void *cls, const struct GNUNET_MessageHeader *mh)
 Check offer (of struct GNUNET_HashCodes). More...
 
static void handle_union_p2p_offer (void *cls, const struct GNUNET_MessageHeader *mh)
 Handle offers (of struct GNUNET_HashCodes) and respond with demands (of struct GNUNET_HashCodes). More...
 
static void handle_union_p2p_done (void *cls, const struct GNUNET_MessageHeader *mh)
 Handle a done message from a remote peer. More...
 
static void handle_union_p2p_over (void *cls, const struct GNUNET_MessageHeader *mh)
 Handle a over message from a remote peer. More...
 
static struct Operationget_incoming (uint32_t id)
 Get the incoming socket associated with the given id. More...
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
 Callback called when a client connects to the service. More...
 
static int destroy_elements_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
 Iterator over hash map entries to free element entries. More...
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *internal_cls)
 Clean up after a client has disconnected. More...
 
static int check_incoming_msg (void *cls, const struct OperationRequestMessage *msg)
 Check a request for a set operation from another peer. More...
 
static void handle_incoming_msg (void *cls, const struct OperationRequestMessage *msg)
 Handle a request for a set operation from another peer. More...
 
static void handle_client_create_set (void *cls, const struct GNUNET_SETU_CreateMessage *msg)
 Called when a client wants to create a new set. More...
 
static void incoming_timeout_cb (void *cls)
 Timeout happens iff: More...
 
static void * channel_new_cb (void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *source)
 Method called whenever another peer has added us to a channel the other peer initiated. More...
 
static void channel_end_cb (void *channel_ctx, const struct GNUNET_CADET_Channel *channel)
 Function called whenever a channel is destroyed. More...
 
static void channel_window_cb (void *cls, const struct GNUNET_CADET_Channel *channel, int window_size)
 Function called whenever an MQ-channel's transmission window size changes. More...
 
static void handle_client_listen (void *cls, const struct GNUNET_SETU_ListenMessage *msg)
 Called when a client wants to create a new listener. More...
 
static void handle_client_reject (void *cls, const struct GNUNET_SETU_RejectMessage *msg)
 Called when the listening client rejects an operation request by another peer. More...
 
static int check_client_set_add (void *cls, const struct GNUNET_SETU_ElementMessage *msg)
 Called when a client wants to add or remove an element to a set it inhabits. More...
 
static void handle_client_set_add (void *cls, const struct GNUNET_SETU_ElementMessage *msg)
 Called when a client wants to add or remove an element to a set it inhabits. More...
 
static void advance_generation (struct Set *set)
 Advance the current generation of a set, adding exclusion ranges if necessary. More...
 
static int check_client_evaluate (void *cls, const struct GNUNET_SETU_EvaluateMessage *msg)
 Called when a client wants to initiate a set operation with another peer. More...
 
static void handle_client_evaluate (void *cls, const struct GNUNET_SETU_EvaluateMessage *msg)
 Called when a client wants to initiate a set operation with another peer. More...
 
static void handle_client_cancel (void *cls, const struct GNUNET_SETU_CancelMessage *msg)
 Handle a request from the client to cancel a running set operation. More...
 
static void handle_client_accept (void *cls, const struct GNUNET_SETU_AcceptMessage *msg)
 Handle a request from the client to accept a set operation that came from a remote peer. More...
 
static void shutdown_task (void *cls)
 Called to clean up, after a shutdown has been requested. More...
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *service)
 Function called by the service's run method to run service-specific setup code. More...
 
 GNUNET_SERVICE_MAIN ("set", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(client_accept, GNUNET_MESSAGE_TYPE_SETU_ACCEPT, struct GNUNET_SETU_AcceptMessage, NULL), GNUNET_MQ_hd_var_size(client_set_add, GNUNET_MESSAGE_TYPE_SETU_ADD, struct GNUNET_SETU_ElementMessage, NULL), GNUNET_MQ_hd_fixed_size(client_create_set, GNUNET_MESSAGE_TYPE_SETU_CREATE, struct GNUNET_SETU_CreateMessage, NULL), GNUNET_MQ_hd_var_size(client_evaluate, GNUNET_MESSAGE_TYPE_SETU_EVALUATE, struct GNUNET_SETU_EvaluateMessage, NULL), GNUNET_MQ_hd_fixed_size(client_listen, GNUNET_MESSAGE_TYPE_SETU_LISTEN, struct GNUNET_SETU_ListenMessage, NULL), GNUNET_MQ_hd_fixed_size(client_reject, GNUNET_MESSAGE_TYPE_SETU_REJECT, struct GNUNET_SETU_RejectMessage, NULL), GNUNET_MQ_hd_fixed_size(client_cancel, GNUNET_MESSAGE_TYPE_SETU_CANCEL, struct GNUNET_SETU_CancelMessage, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro. More...
 

Variables

static struct GNUNET_CADET_Handlecadet
 Handle to the cadet service, used to listen for and connect to remote peers. More...
 
static struct GNUNET_STATISTICS_Handle_GSS_statistics
 Statistics handle. More...
 
static struct Listenerlistener_head
 Listeners are held in a doubly linked list. More...
 
static struct Listenerlistener_tail
 Listeners are held in a doubly linked list. More...
 
static unsigned int num_clients
 Number of active clients. More...
 
static int in_shutdown
 Are we in shutdown? if GNUNET_YES and the number of clients drops to zero, disconnect from CADET. More...
 
static uint32_t suggest_id
 Counter for allocating unique IDs for clients, used to identify incoming operation requests from remote peers, that the client can choose to accept or refuse. More...
 

Detailed Description

set union operation

Author
Florian Dold
Christian Grothoff
Elias Summermatter

Definition in file gnunet-service-setu.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "setu", __VA_ARGS__)

Definition at line 41 of file gnunet-service-setu.c.

◆ INCOMING_CHANNEL_TIMEOUT

#define INCOMING_CHANNEL_TIMEOUT   GNUNET_TIME_UNIT_MINUTES

How long do we hold on to an incoming channel if there is no local listener before giving up?

Definition at line 47 of file gnunet-service-setu.c.

◆ SE_STRATA_COUNT

#define SE_STRATA_COUNT   32

Number of IBFs in a strata estimator.

Definition at line 52 of file gnunet-service-setu.c.

◆ SE_IBFS_TOTAL_SIZE

#define SE_IBFS_TOTAL_SIZE   632

Primes for all 4 different strata estimators 61,67,71,73,79,83,89,97 348 Based on the bsc thesis of Elias Summermatter (2021)

Definition at line 59 of file gnunet-service-setu.c.

◆ SE_IBF_HASH_NUM

#define SE_IBF_HASH_NUM   3

The hash num parameter for the difference digests and strata estimators.

Definition at line 64 of file gnunet-service-setu.c.

◆ MAX_BUCKETS_PER_MESSAGE

#define MAX_BUCKETS_PER_MESSAGE   ((1 << 16) / IBF_BUCKET_SIZE)

Number of buckets that can be transmitted in one message.

Definition at line 69 of file gnunet-service-setu.c.

◆ MAX_IBF_SIZE

#define MAX_IBF_SIZE   1048576

The maximum size of an ibf we use is MAX_IBF_SIZE=2^20.

Choose this value so that computing the IBF is still cheaper than transmitting all values.

Definition at line 76 of file gnunet-service-setu.c.

◆ IBF_MIN_SIZE

#define IBF_MIN_SIZE   37

Minimal size of an ibf Based on the bsc thesis of Elias Summermatter (2021)

Definition at line 83 of file gnunet-service-setu.c.

◆ DIFFERENTIAL_RTT_MEAN

#define DIFFERENTIAL_RTT_MEAN   3.65145

AVG RTT for differential sync when k=2 and Factor = 2 Based on the bsc thesis of Elias Summermatter (2021)

Definition at line 89 of file gnunet-service-setu.c.

◆ SECURITY_LEVEL

#define SECURITY_LEVEL   80

Security level used for byzantine checks (2^80)

Definition at line 95 of file gnunet-service-setu.c.

◆ PROBABILITY_FOR_NEW_ROUND

#define PROBABILITY_FOR_NEW_ROUND   0.15

Is the estimated probability for a new round this values is based on the bsc thesis of Elias Summermatter (2021)

Definition at line 102 of file gnunet-service-setu.c.

◆ MEASURE_PERFORMANCE

#define MEASURE_PERFORMANCE   0

Measure the performance in a csv.

Definition at line 108 of file gnunet-service-setu.c.

Enumeration Type Documentation

◆ UnionOperationPhase

Current phase we are in for a union operation.

Enumerator
PHASE_EXPECT_SE 

We sent the request message, and expect a strata estimator.

PHASE_EXPECT_IBF 

We sent the strata estimator, and expect an IBF.

This phase is entered once upon initialization and later via #PHASE_EXPECT_ELEMENTS_AND_REQUESTS.

XXX: could use better wording. XXX: repurposed to also expect a "request full set" message, should be renamed

After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS

PHASE_EXPECT_IBF_CONT 

Continuation for multi part IBFs.

PHASE_INVENTORY_ACTIVE 

We are decoding an IBF.

PHASE_INVENTORY_PASSIVE 

The other peer is decoding the IBF we just sent.

PHASE_FINISH_CLOSING 

The protocol is almost finished, but we still have to flush our message queue and/or expect some elements.

PHASE_FINISH_WAITING 

In the penultimate phase, we wait until all our demands are satisfied.

Then we send a done message, and wait for another done message.

PHASE_DONE 

In the ultimate phase, we wait until our demands are satisfied and then quit (sending another DONE message).

PHASE_FULL_SENDING 

After sending the full set, wait for responses with the elements that the local peer is missing.

PHASE_EXPECT_SE 

We sent the request message, and expect a strata estimator.

PHASE_EXPECT_IBF 

We sent the strata estimator, and expect an IBF.

This phase is entered once upon initialization and later via #PHASE_EXPECT_ELEMENTS_AND_REQUESTS.

XXX: could use better wording. XXX: repurposed to also expect a "request full set" message, should be renamed

After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS

PHASE_EXPECT_IBF_LAST 

Continuation for multi part IBFs.

PHASE_ACTIVE_DECODING 

We are decoding an IBF.

PHASE_PASSIVE_DECODING 

The other peer is decoding the IBF we just sent.

PHASE_FINISH_CLOSING 

The protocol is almost finished, but we still have to flush our message queue and/or expect some elements.

PHASE_FINISH_WAITING 

In the penultimate phase, we wait until all our demands are satisfied.

Then we send a done message, and wait for another done message.

PHASE_FINISHED 

In the ultimate phase, we wait until our demands are satisfied and then quit (sending another DONE message).

PHASE_FULL_SENDING 

After sending the full set, wait for responses with the elements that the local peer is missing.

PHASE_FULL_RECEIVING 

Phase that receives full set first and then sends elements that are the local peer missing.

Definition at line 114 of file gnunet-service-setu.c.

115 {
120 
131 
136 
141 
146 
152 
158 
164 
170 
176 };
@ PHASE_FINISH_CLOSING
The protocol is almost finished, but we still have to flush our message queue and/or expect some elem...
@ PHASE_EXPECT_SE
We sent the request message, and expect a strata estimator.
@ PHASE_EXPECT_IBF_LAST
Continuation for multi part IBFs.
@ PHASE_FULL_RECEIVING
Phase that receives full set first and then sends elements that are the local peer missing.
@ PHASE_FINISH_WAITING
In the penultimate phase, we wait until all our demands are satisfied.
@ PHASE_FINISHED
In the ultimate phase, we wait until our demands are satisfied and then quit (sending another DONE me...
@ PHASE_PASSIVE_DECODING
The other peer is decoding the IBF we just sent.
@ PHASE_ACTIVE_DECODING
We are decoding an IBF.
@ PHASE_FULL_SENDING
After sending the full set, wait for responses with the elements that the local peer is missing.
@ PHASE_EXPECT_IBF
We sent the strata estimator, and expect an IBF.

◆ MODE_OF_OPERATION

Different modes of operations.

Enumerator
DIFFERENTIAL_SYNC 

Mode just synchronizes the difference between sets.

FULL_SYNC_LOCAL_SENDING_FIRST 

Mode send full set sending local set first.

FULL_SYNC_REMOTE_SENDING_FIRST 

Mode request full set from remote peer.

Definition at line 182 of file gnunet-service-setu.c.

183 {
188 
193 
198 };
@ DIFFERENTIAL_SYNC
Mode just synchronizes the difference between sets.
@ FULL_SYNC_LOCAL_SENDING_FIRST
Mode send full set sending local set first.
@ FULL_SYNC_REMOTE_SENDING_FIRST
Mode request full set from remote peer.

◆ MESSAGE_CONTROL_FLOW_STATE

Different states to control the messages flow in differential mode.

Enumerator
MSG_CFS_UNINITIALIZED 

Initial message state.

MSG_CFS_SENT 

Track that a message has been sent.

MSG_CFS_EXPECTED 

Track that receiving this message is expected.

MSG_CFS_RECEIVED 

Track that message has been received.

Definition at line 813 of file gnunet-service-setu.c.

814 {
819 
823  MSG_CFS_SENT,
824 
829 
834 };
@ MSG_CFS_EXPECTED
Track that receiving this message is expected.
@ MSG_CFS_SENT
Track that a message has been sent.
@ MSG_CFS_UNINITIALIZED
Initial message state.
@ MSG_CFS_RECEIVED
Track that message has been received.

◆ MESSAGE_TYPE

Message types to track in message control flow.

Enumerator
OFFER_MESSAGE 

Offer message type.

DEMAND_MESSAGE 

Demand message type.

ELEMENT_MESSAGE 

Element message type.

Definition at line 840 of file gnunet-service-setu.c.

841 {
846 
851 
856 };
@ DEMAND_MESSAGE
Demand message type.
@ OFFER_MESSAGE
Offer message type.
@ ELEMENT_MESSAGE
Element message type.

Function Documentation

◆ estimate_best_mode_of_operation()

static uint8_t estimate_best_mode_of_operation ( uint64_t  avg_element_size,
uint64_t  local_set_size,
uint64_t  remote_set_size,
uint64_t  est_set_diff_remote,
uint64_t  est_set_diff_local,
uint64_t  bandwith_latency_tradeoff,
uint64_t  ibf_bucket_number_factor 
)
static

Function that chooses the optimal mode of operation depending on operation parameters.

Parameters
avg_element_size
local_set_size
remote_set_size
est_set_diff_remote
est_set_diff_local
bandwith_latency_tradeoff
ibf_bucket_number_factor
Returns
calcuated mode of operation

Definition at line 1051 of file gnunet-service-setu.c.

1058 {
1059 
1060  /*
1061  * In case of initial sync fall to predefined states
1062  */
1063 
1064  if (0 == local_set_size)
1066  if (0 == remote_set_size)
1068 
1069  /*
1070  * Calculate bytes for full Sync
1071  */
1072 
1073  uint8_t sizeof_full_done_header = 4;
1074  uint8_t sizeof_done_header = 4;
1075  uint8_t rtt_min_full = 2;
1076  uint8_t sizeof_request_full = 4;
1077  uint64_t estimated_total_diff = (est_set_diff_remote + est_set_diff_local);
1078 
1079  /* Estimate byte required if we send first */
1080  uint64_t total_elements_to_send_local_send_first = est_set_diff_remote
1081  + local_set_size;
1082 
1083  uint64_t total_bytes_full_local_send_first = (avg_element_size
1084  *
1085  total_elements_to_send_local_send_first) \
1086  + (
1087  total_elements_to_send_local_send_first * sizeof(struct
1089  + (sizeof_full_done_header * 2) \
1090  + rtt_min_full
1091  * bandwith_latency_tradeoff;
1092 
1093  /* Estimate bytes required if we request from remote peer */
1094  uint64_t total_elements_to_send_remote_send_first = est_set_diff_local
1095  + remote_set_size;
1096 
1097  uint64_t total_bytes_full_remote_send_first = (avg_element_size
1098  *
1099  total_elements_to_send_remote_send_first) \
1100  + (
1101  total_elements_to_send_remote_send_first * sizeof(struct
1103  + (sizeof_full_done_header * 2) \
1104  + (rtt_min_full + 0.5)
1105  * bandwith_latency_tradeoff \
1106  + sizeof_request_full;
1107 
1108  /*
1109  * Calculate bytes for differential Sync
1110  */
1111 
1112  /* Estimate bytes required by IBF transmission*/
1113 
1114  long double ibf_bucket_count = estimated_total_diff
1115  * ibf_bucket_number_factor;
1116 
1117  if (ibf_bucket_count <= IBF_MIN_SIZE)
1118  {
1119  ibf_bucket_count = IBF_MIN_SIZE;
1120  }
1121  uint64_t ibf_message_count = ceil ( ((float) ibf_bucket_count)
1122  / ((float) MAX_BUCKETS_PER_MESSAGE));
1123 
1124  uint64_t estimated_counter_size = ceil (
1125  MIN (2 * log2l (((float) local_set_size)
1126  / ((float) ibf_bucket_count)),
1127  log2l (local_set_size)));
1128 
1129  long double counter_bytes = (float) estimated_counter_size / 8;
1130 
1131  uint64_t ibf_bytes = ceil ((sizeof (struct IBFMessage) * ibf_message_count)
1132  * 1.2 \
1133  + (ibf_bucket_count * sizeof(struct IBF_Key)) * 1.2 \
1134  + (ibf_bucket_count * sizeof(struct IBF_KeyHash))
1135  * 1.2 \
1136  + (ibf_bucket_count * counter_bytes) * 1.2);
1137 
1138  /* Estimate full byte count for differential sync */
1139  uint64_t element_size = (avg_element_size
1140  + sizeof (struct GNUNET_SETU_ElementMessage)) \
1141  * estimated_total_diff;
1142  uint64_t done_size = sizeof_done_header;
1143  uint64_t inquery_size = (sizeof (struct IBF_Key)
1144  + sizeof (struct InquiryMessage))
1145  * estimated_total_diff;
1146  uint64_t demand_size =
1147  (sizeof(struct GNUNET_HashCode) + sizeof(struct GNUNET_MessageHeader))
1148  * estimated_total_diff;
1149  uint64_t offer_size = (sizeof (struct GNUNET_HashCode)
1150  + sizeof (struct GNUNET_MessageHeader))
1151  * estimated_total_diff;
1152 
1153  uint64_t total_bytes_diff = (element_size + done_size + inquery_size
1154  + demand_size + offer_size + ibf_bytes) \
1156  * bandwith_latency_tradeoff);
1157 
1158  uint64_t full_min = MIN (total_bytes_full_local_send_first,
1159  total_bytes_full_remote_send_first);
1160 
1161  /* Decide between full and differential sync */
1162 
1163  if (full_min < total_bytes_diff)
1164  {
1165  /* Decide between sending all element first or receiving all elements */
1166  if (total_bytes_full_remote_send_first > total_bytes_full_local_send_first)
1167  {
1169  }
1170  else
1171  {
1173  }
1174  }
1175  else
1176  {
1177  return DIFFERENTIAL_SYNC;
1178  }
1179 }
#define IBF_MIN_SIZE
Minimal size of an ibf Based on the bsc thesis of Elias Summermatter (2021)
#define MAX_BUCKETS_PER_MESSAGE
Number of buckets that can be transmitted in one message.
#define DIFFERENTIAL_RTT_MEAN
AVG RTT for differential sync when k=2 and Factor = 2 Based on the bsc thesis of Elias Summermatter (...
static unsigned int element_size
A 512-bit hashcode.
Header for all communications.
Message sent by client to the service to add an element to the set.
Definition: setu.h:326
Message containing buckets of an invertible bloom filter.
Hash of an IBF key.
Definition: ibf.h:55
Keys that can be inserted into and removed from an IBF.
Definition: ibf.h:46
estimate_best_mode_of_operation (uint64_t avg_element_size, uint64_t local_set_size,...

Referenced by handle_union_p2p_request_full(), handle_union_p2p_send_full(), and handle_union_p2p_strata_estimator().

Here is the caller graph for this function:

◆ check_valid_phase()

static enum GNUNET_GenericReturnValue check_valid_phase ( const uint8_t  allowed_phases[],
size_t  size_phases,
struct Operation op 
)
static

Validates the if a message is received in a correct phase.

Parameters
allowed_phases
size_phases
op
Returns
GNUNET_YES if message permitted in phase and GNUNET_NO if not permitted in given phase

Iterate over allowed phases

Definition at line 1051 of file gnunet-service-setu.c.

1194 {
1198  for (uint32_t phase_ctr = 0; phase_ctr < size_phases; phase_ctr++)
1199  {
1200  uint8_t phase = allowed_phases[phase_ctr];
1201  if (phase == op->phase)
1202  {
1204  "Message received in valid phase\n");
1205  return GNUNET_YES;
1206  }
1207  }
1209  "Received message in invalid phase: %u\n", op->phase);
1210  return GNUNET_NO;
1211 }
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
static unsigned int phase
Processing stage that we are in.
Definition: gnunet-arm.c:114
#define LOG(kind,...)
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG

References DIFFERENTIAL_RTT_MEAN, DIFFERENTIAL_SYNC, element_size, FULL_SYNC_LOCAL_SENDING_FIRST, FULL_SYNC_REMOTE_SENDING_FIRST, IBF_MIN_SIZE, and MAX_BUCKETS_PER_MESSAGE.

Referenced by handle_union_p2p_demand(), handle_union_p2p_done(), handle_union_p2p_elements(), handle_union_p2p_full_done(), handle_union_p2p_full_element(), handle_union_p2p_ibf(), handle_union_p2p_inquiry(), handle_union_p2p_offer(), handle_union_p2p_request_full(), handle_union_p2p_send_full(), and handle_union_p2p_strata_estimator().

Here is the caller graph for this function:

◆ update_message_control_flow()

static int update_message_control_flow ( struct GNUNET_CONTAINER_MultiHashMap hash_map,
enum MESSAGE_CONTROL_FLOW_STATE  new_mcfs,
const struct GNUNET_HashCode hash_code,
enum MESSAGE_TYPE  mt 
)
static

Function to update, track and validate message received in differential sync.

This function tracks states of messages and check it against different constraints as described in Summermatter's BSc Thesis (2021)

Parameters
hash_mapHashmap to store message control flow
new_mcfsThe new message control flow state an given message type should be set to
hash_codeHash code of the element
mtThe message type for which the message control flow state should be set
Returns
GNUNET_YES message is valid in message control flow GNUNET_NO when message is not valid at this point in message flow

Check logic for forbidden messages

In case the element hash is not in the hashmap create a new entry

Set state of message

Check if state is allowed

Definition at line 1226 of file gnunet-service-setu.c.

1230 {
1231  struct messageControlFlowElement *cfe = NULL;
1232  enum MESSAGE_CONTROL_FLOW_STATE *mcfs;
1233 
1238  cfe = GNUNET_CONTAINER_multihashmap_get (hash_map, hash_code);
1239  if ((ELEMENT_MESSAGE == mt) && (cfe != NULL))
1240  {
1241  if ((new_mcfs != MSG_CFS_SENT) && (MSG_CFS_RECEIVED != cfe->offer))
1242  {
1244  "Received an element without sent offer!\n");
1245  return GNUNET_NO;
1246  }
1247  /* Check that only requested elements are received! */
1248  if ((ELEMENT_MESSAGE == mt) && (new_mcfs != MSG_CFS_SENT) && (cfe->demand !=
1249  MSG_CFS_SENT))
1250  {
1252  "Received an element that was not demanded\n");
1253  return GNUNET_NO;
1254  }
1255  }
1256 
1261  if (NULL == cfe)
1262  {
1263  cfe = GNUNET_new (struct messageControlFlowElement);
1264  if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (hash_map, hash_code,
1265  cfe,
1267  {
1268  GNUNET_free (cfe);
1269  return GNUNET_SYSERR;
1270  }
1271  }
1272 
1277  if (OFFER_MESSAGE == mt)
1278  {
1279  mcfs = &cfe->offer;
1280  }
1281  else if (DEMAND_MESSAGE == mt)
1282  {
1283  mcfs = &cfe->demand;
1284  }
1285  else if (ELEMENT_MESSAGE == mt)
1286  {
1287  mcfs = &cfe->element;
1288  }
1289  else
1290  {
1291  return GNUNET_SYSERR;
1292  }
1293 
1298  if (new_mcfs <= *mcfs)
1299  {
1300  return GNUNET_NO;
1301  }
1302 
1303  *mcfs = new_mcfs;
1304  return GNUNET_YES;
1305 }
MESSAGE_CONTROL_FLOW_STATE
Different states to control the messages flow in differential mode.
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.
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.
@ 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...
@ GNUNET_SYSERR
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
Struct to tracked messages in message control flow.
enum MESSAGE_CONTROL_FLOW_STATE element
Track the message control state of the element message.
enum MESSAGE_CONTROL_FLOW_STATE offer
Track the message control state of the offer message.
enum MESSAGE_CONTROL_FLOW_STATE demand
Track the message control state of the demand message.

References messageControlFlowElement::demand, DEMAND_MESSAGE, messageControlFlowElement::element, ELEMENT_MESSAGE, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_new, GNUNET_NO, GNUNET_SYSERR, GNUNET_YES, LOG, MSG_CFS_RECEIVED, MSG_CFS_SENT, messageControlFlowElement::offer, and OFFER_MESSAGE.

Referenced by handle_union_p2p_demand(), handle_union_p2p_elements(), handle_union_p2p_offer(), and send_offers_iterator().

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

◆ is_message_in_message_control_flow()

static int is_message_in_message_control_flow ( struct GNUNET_CONTAINER_MultiHashMap hash_map,
struct GNUNET_HashCode hash_code,
enum MESSAGE_TYPE  mt 
)
static

Validate if a message in differential sync si already received before.

Parameters
hash_map
hash_code
mt
Returns
GNUNET_YES when message is already in store if message is not in store return GNUNET_NO

Set state of message

Evaluate if set is in message

Definition at line 1316 of file gnunet-service-setu.c.

1320 {
1321  struct messageControlFlowElement *cfe = NULL;
1322  enum MESSAGE_CONTROL_FLOW_STATE *mcfs;
1323 
1324  cfe = GNUNET_CONTAINER_multihashmap_get (hash_map, hash_code);
1325 
1330  if (cfe != NULL)
1331  {
1332  if (OFFER_MESSAGE == mt)
1333  {
1334  mcfs = &cfe->offer;
1335  }
1336  else if (DEMAND_MESSAGE == mt)
1337  {
1338  mcfs = &cfe->demand;
1339  }
1340  else if (ELEMENT_MESSAGE == mt)
1341  {
1342  mcfs = &cfe->element;
1343  }
1344  else
1345  {
1346  return GNUNET_SYSERR;
1347  }
1348 
1352  if (*mcfs != MSG_CFS_UNINITIALIZED)
1353  {
1354  return GNUNET_YES;
1355  }
1356  }
1357  return GNUNET_NO;
1358 }

References messageControlFlowElement::demand, DEMAND_MESSAGE, messageControlFlowElement::element, ELEMENT_MESSAGE, GNUNET_CONTAINER_multihashmap_get(), GNUNET_NO, GNUNET_SYSERR, GNUNET_YES, MSG_CFS_UNINITIALIZED, messageControlFlowElement::offer, and OFFER_MESSAGE.

Referenced by send_offers_iterator().

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

◆ determinate_done_message_iterator()

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

Iterator for determining if all demands have been satisfied.

Parameters
clsthe union operation struct Operation *
keyunused
valuethe struct ElementEntry * to insert into the key-to-element mapping
Returns
GNUNET_YES (to continue iterating)

Definition at line 1372 of file gnunet-service-setu.c.

1375 {
1376  struct messageControlFlowElement *mcfe = value;
1377 
1378  if (((mcfe->element == MSG_CFS_SENT) || (mcfe->element == MSG_CFS_RECEIVED) ))
1379  {
1380  return GNUNET_YES;
1381  }
1382  return GNUNET_NO;
1383 }
static char * value
Value of the record to add/remove.

References messageControlFlowElement::element, GNUNET_NO, GNUNET_YES, MSG_CFS_RECEIVED, MSG_CFS_SENT, and value.

Referenced by maybe_finish().

Here is the caller graph for this function:

◆ determinate_avg_element_size_iterator()

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

Iterator for determining average size.

Parameters
clsthe union operation struct Operation *
keyunused
valuethe struct ElementEntry * to insert into the key-to-element mapping
Returns
GNUNET_YES (to continue iterating)

Definition at line 1396 of file gnunet-service-setu.c.

1399 {
1400  struct Operation *op = cls;
1401  struct GNUNET_SETU_Element *element = value;
1402  op->total_elements_size_local += element->size;
1403  return GNUNET_YES;
1404 }
Element stored in a set.
uint16_t size
Number of bytes in the buffer pointed to by data.
Operation context used to execute a set operation.

References GNUNET_YES, op, GNUNET_SETU_Element::size, and value.

Referenced by handle_client_accept(), handle_union_p2p_request_full(), handle_union_p2p_send_full(), and handle_union_p2p_strata_estimator().

Here is the caller graph for this function:

◆ create_randomized_element_iterator()

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

Create randomized element hashmap for full sending.

Parameters
clsthe union operation struct Operation *
keyunused
valuethe struct ElementEntry * to insert into the key-to-element mapping
Returns
GNUNET_YES (to continue iterating)

Hash element with new salt to randomize hashmap

Definition at line 1417 of file gnunet-service-setu.c.

1420 {
1421  struct Operation *op = cls;
1422 
1423  struct GNUNET_HashContext *hashed_key_context =
1425  struct GNUNET_HashCode new_key;
1426 
1430  GNUNET_CRYPTO_hash_context_read (hashed_key_context,
1431  &key,
1432  sizeof(struct IBF_Key));
1433  GNUNET_CRYPTO_hash_context_read (hashed_key_context,
1434  &op->set->content->elements_randomized_salt,
1435  sizeof(uint32_t));
1436  GNUNET_CRYPTO_hash_context_finish (hashed_key_context,
1437  &new_key);
1438  GNUNET_CONTAINER_multihashmap_put (op->set->content->elements_randomized,
1439  &new_key,value,
1441  return GNUNET_YES;
1442 }
struct GNUNET_HashCode key
The key used in the DHT.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
If a value with the given key exists, replace it.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
Definition: crypto_hash.c:349
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
Definition: crypto_hash.c:365
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:389

References GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE, GNUNET_CRYPTO_hash_context_finish(), GNUNET_CRYPTO_hash_context_read(), GNUNET_CRYPTO_hash_context_start(), GNUNET_YES, key, op, and value.

Referenced by send_full_set().

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

◆ destroy_key_to_element_iter()

static int destroy_key_to_element_iter ( void *  cls,
uint32_t  key,
void *  value 
)
static

Iterator over hash map entries, called to destroy the linked list of colliding ibf key entries.

Parameters
clsclosure
keycurrent key code
valuevalue in the hash map
Returns
GNUNET_YES if we should continue to iterate, GNUNET_NO if not.

Definition at line 1456 of file gnunet-service-setu.c.

1459 {
1460  struct KeyEntry *k = value;
1461 
1462  GNUNET_assert (NULL != k);
1463  if (GNUNET_YES == k->element->remote)
1464  {
1465  GNUNET_free (k->element);
1466  k->element = NULL;
1467  }
1468  GNUNET_free (k);
1469  return GNUNET_YES;
1470 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int remote
GNUNET_YES if the element is a remote element, and does not belong to the operation's set.
The key entry is used to associate an ibf key with an element.
struct ElementEntry * element
The actual element associated with the key.

References KeyEntry::element, GNUNET_assert, GNUNET_free, GNUNET_YES, ElementEntry::remote, and value.

Referenced by _GSS_operation_destroy().

Here is the caller graph for this function:

◆ send_client_done()

static void send_client_done ( void *  cls)
static

Signal to the client that the operation has finished and destroy the operation.

Parameters
clsoperation to destroy

Definition at line 1480 of file gnunet-service-setu.c.

1481 {
1482  struct Operation *op = cls;
1483  struct GNUNET_MQ_Envelope *ev;
1484  struct GNUNET_SETU_ResultMessage *rm;
1485 
1486  if (GNUNET_YES == op->client_done_sent)
1487  return;
1488  if (PHASE_FINISHED != op->phase)
1489  {
1491  "Union operation failed\n");
1493  "# Union operations failed",
1494  1,
1495  GNUNET_NO);
1498  rm->request_id = htonl (op->client_request_id);
1499  rm->element_type = htons (0);
1500  GNUNET_MQ_send (op->set->cs->mq,
1501  ev);
1502  return;
1503  }
1504 
1505  op->client_done_sent = GNUNET_YES;
1506 
1508  "# Union operations succeeded",
1509  1,
1510  GNUNET_NO);
1512  "Signalling client that union operation is done\n");
1513  ev = GNUNET_MQ_msg (rm,
1515  rm->request_id = htonl (op->client_request_id);
1516  rm->result_status = htons (GNUNET_SETU_STATUS_DONE);
1517  rm->element_type = htons (0);
1519  op->key_to_element));
1520  GNUNET_MQ_send (op->set->cs->mq,
1521  ev);
1522 }
static struct GNUNET_STATISTICS_Handle * _GSS_statistics
Statistics handle.
unsigned int GNUNET_CONTAINER_multihashmap32_size(const struct GNUNET_CONTAINER_MultiHashMap32 *map)
Get the number of key-value pairs in the map.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_INFO
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:304
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:77
#define GNUNET_MESSAGE_TYPE_SETU_RESULT
Handle result message from operation.
@ GNUNET_SETU_STATUS_DONE
Success, all elements have been sent (and received).
@ GNUNET_SETU_STATUS_FAILURE
The other peer refused to do the operation with us, or something went wrong.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
Message sent by the service to the client to indicate an element that is removed (set intersection) o...
Definition: setu.h:290
uint64_t current_size
Current set size.
Definition: setu.h:299
uint16_t result_status
Was the evaluation successful? Contains an enum GNUNET_SETU_Status in NBO.
Definition: setu.h:310
uint16_t element_type
Type of the element attached to the message, if any.
Definition: setu.h:315
uint32_t request_id
id the result belongs to
Definition: setu.h:304

References _GSS_statistics, GNUNET_SETU_ResultMessage::current_size, GNUNET_SETU_ResultMessage::element_type, GNUNET_CONTAINER_multihashmap32_size(), GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_htonll(), GNUNET_MESSAGE_TYPE_SETU_RESULT, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_NO, GNUNET_SETU_STATUS_DONE, GNUNET_SETU_STATUS_FAILURE, GNUNET_STATISTICS_update(), GNUNET_YES, LOG, op, PHASE_FINISHED, GNUNET_SETU_ResultMessage::request_id, and GNUNET_SETU_ResultMessage::result_status.

Referenced by _GSS_operation_destroy2(), handle_union_p2p_full_done(), handle_union_p2p_over(), and maybe_finish().

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

◆ check_byzantine_bounds()

static int check_byzantine_bounds ( struct Operation op)
static

Check if all given byzantine parameters are in given boundaries.

Parameters
op
Returns
indicator if all given byzantine parameters are in given boundaries

Check upper byzantine bounds

Check lower byzantine bounds

Definition at line 1532 of file gnunet-service-setu.c.

1533 {
1534  if (op->byzantine != GNUNET_YES)
1535  return GNUNET_OK;
1536 
1540  if (op->remote_element_count + op->remote_set_diff >
1541  op->byzantine_upper_bound)
1542  return GNUNET_SYSERR;
1543  if (op->local_element_count + op->local_set_diff > op->byzantine_upper_bound)
1544  return GNUNET_SYSERR;
1545 
1549  if (op->remote_element_count < op->byzantine_lower_bound)
1550  return GNUNET_SYSERR;
1551  return GNUNET_OK;
1552 }
@ GNUNET_OK

References GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, and op.

Referenced by handle_union_p2p_request_full(), and handle_union_p2p_send_full().

Here is the caller graph for this function:

◆ free_values_iter()

static enum GNUNET_GenericReturnValue free_values_iter ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 1532 of file gnunet-service-setu.c.

1559 {
1560  GNUNET_free (value);
1561  return GNUNET_YES;
1562 }

Referenced by _GSS_operation_destroy().

Here is the caller graph for this function:

◆ _GSS_operation_destroy()

static void _GSS_operation_destroy ( struct Operation op)
static

Destroy the given operation.

Used for any operation where both peers were known and that thus actually had a vt and channel. Must not be used for operations where 'listener' is still set and we do not know the other peer.

Call the implementation-specific cancel function of the operation. Disconnects from the remote peer. Does not disconnect the client, as there may be multiple operations per set.

Parameters
opoperation to destroy

Definition at line 1580 of file gnunet-service-setu.c.

1581 {
1582  struct Set *set = op->set;
1583  struct GNUNET_CADET_Channel *channel;
1584 
1586  "Destroying union operation %p\n",
1587  op);
1588  GNUNET_assert (NULL == op->listener);
1589  /* check if the op was canceled twice */
1590  if (NULL != op->remote_ibf)
1591  {
1592  ibf_destroy (op->remote_ibf);
1593  op->remote_ibf = NULL;
1594  }
1595  if (NULL != op->demanded_hashes)
1596  {
1597  GNUNET_CONTAINER_multihashmap_destroy (op->demanded_hashes);
1598  op->demanded_hashes = NULL;
1599  }
1600  if (NULL != op->local_ibf)
1601  {
1602  ibf_destroy (op->local_ibf);
1603  op->local_ibf = NULL;
1604  }
1605  if (NULL != op->se)
1606  {
1608  op->se = NULL;
1609  }
1610  if (NULL != op->key_to_element)
1611  {
1614  NULL);
1615  GNUNET_CONTAINER_multihashmap32_destroy (op->key_to_element);
1616  op->key_to_element = NULL;
1617  }
1618  if (NULL != op->message_control_flow)
1619  {
1620  GNUNET_CONTAINER_multihashmap_iterate (op->message_control_flow,
1622  NULL);
1623  GNUNET_CONTAINER_multihashmap_destroy (op->message_control_flow);
1624  op->message_control_flow = NULL;
1625  }
1626  if (NULL != op->inquiries_sent)
1627  {
1628  GNUNET_CONTAINER_multihashmap_destroy (op->inquiries_sent);
1629  op->inquiries_sent = NULL;
1630  }
1631  if (NULL != set)
1632  {
1634  set->ops_tail,
1635  op);
1636  op->set = NULL;
1637  }
1638  if (NULL != op->context_msg)
1639  {
1640  GNUNET_free (op->context_msg);
1641  op->context_msg = NULL;
1642  }
1643  if (NULL != (channel = op->channel))
1644  {
1645  /* This will free op; called conditionally as this helper function
1646  is also called from within the channel disconnect handler. */
1647  op->channel = NULL;
1648  GNUNET_CADET_channel_destroy (channel);
1649  }
1650  /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL,
1651  * there was a channel end handler that will free 'op' on the call stack. */
1652 }
void strata_estimator_destroy(struct StrataEstimator *se)
Destroy a strata estimator, free all of its resources.
static enum GNUNET_GenericReturnValue free_values_iter(void *cls, const struct GNUNET_HashCode *key, void *value)
static int destroy_key_to_element_iter(void *cls, uint32_t key, void *value)
Iterator over hash map entries, called to destroy the linked list of colliding ibf key entries.
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:830
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
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_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
#define GNUNET_log(kind,...)
void ibf_destroy(struct InvertibleBloomFilter *ibf)
Destroy all resources associated with the invertible bloom filter.
Definition: ibf.c:404
Opaque handle to a channel.
Definition: cadet.h:116
A set that supports a specific operation with other peers.
struct Operation * ops_head
Evaluate operations are held in a linked list.
struct Operation * ops_tail
Evaluate operations are held in a linked list.

References destroy_key_to_element_iter(), free_values_iter(), GNUNET_assert, GNUNET_CADET_channel_destroy(), GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap32_destroy(), GNUNET_CONTAINER_multihashmap32_iterate(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, ibf_destroy(), op, Set::ops_head, Set::ops_tail, and strata_estimator_destroy().

Referenced by _GSS_operation_destroy2(), client_disconnect_cb(), fail_union_operation(), and handle_client_cancel().

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

◆ _GSS_operation_destroy2()

static void _GSS_operation_destroy2 ( struct Operation op)
static

This function probably should not exist and be replaced by inlining more specific logic in the various places where it is called.

Definition at line 1699 of file gnunet-service-setu.c.

1700 {
1701  struct GNUNET_CADET_Channel *channel;
1702 
1703  if (NULL != (channel = op->channel))
1704  {
1705  /* This will free op; called conditionally as this helper function
1706  is also called from within the channel disconnect handler. */
1707  op->channel = NULL;
1708  GNUNET_CADET_channel_destroy (channel);
1709  }
1710  if (NULL != op->listener)
1711  {
1712  incoming_destroy (op);
1713  return;
1714  }
1715  if (NULL != op->set)
1716  send_client_done (op);
1718  GNUNET_free (op);
1719 }
static void _GSS_operation_destroy(struct Operation *op)
Destroy the given operation.
static void send_client_done(void *cls)
Signal to the client that the operation has finished and destroy the operation.
static void incoming_destroy(struct Operation *op)
Destroy an incoming request from a remote peer.

References _GSS_operation_destroy(), GNUNET_CADET_channel_destroy(), GNUNET_free, incoming_destroy(), op, and send_client_done().

Referenced by channel_end_cb(), handle_client_reject(), handle_union_p2p_full_done(), incoming_destroy(), and maybe_finish().

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

◆ incoming_destroy()

static void incoming_destroy ( struct Operation op)
static

Destroy an incoming request from a remote peer.

Parameters
opremote request to destroy

Definition at line 1670 of file gnunet-service-setu.c.

1671 {
1672  struct Listener *listener;
1673 
1675  "Destroying incoming operation %p\n",
1676  op);
1677  if (NULL != (listener = op->listener))
1678  {
1680  listener->op_tail,
1681  op);
1682  op->listener = NULL;
1683  }
1684  if (NULL != op->timeout_task)
1685  {
1686  GNUNET_SCHEDULER_cancel (op->timeout_task);
1687  op->timeout_task = NULL;
1688  }
1690 }
static void _GSS_operation_destroy2(struct Operation *op)
This function probably should not exist and be replaced by inlining more specific logic in the variou...
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
A listener is inhabited by a client, and waits for evaluation requests from remote peers.
struct Operation * op_tail
Tail of DLL of operations this listener is responsible for.
struct Operation * op_head
Head of DLL of operations this listener is responsible for.

References _GSS_operation_destroy2(), GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SCHEDULER_cancel(), op, Listener::op_head, and Listener::op_tail.

Referenced by _GSS_operation_destroy2(), client_disconnect_cb(), and incoming_timeout_cb().

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

◆ fail_union_operation()

static void fail_union_operation ( struct Operation op)
static

Inform the client that the union operation has failed, and proceed to destroy the evaluate operation.

Parameters
opthe union operation to fail

Definition at line 1729 of file gnunet-service-setu.c.

1730 {
1731  struct GNUNET_MQ_Envelope *ev;
1733 
1735  "union operation failed\n");
1737  msg->result_status = htons (GNUNET_SETU_STATUS_FAILURE);
1738  msg->request_id = htonl (op->client_request_id);
1739  msg->element_type = htons (0);
1740  GNUNET_MQ_send (op->set->cs->mq,
1741  ev);
1743 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2

References _GSS_operation_destroy(), GNUNET_ERROR_TYPE_WARNING, GNUNET_MESSAGE_TYPE_SETU_RESULT, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SETU_STATUS_FAILURE, LOG, msg, and op.

Referenced by check_max_differential_rounds(), decode_and_send(), full_sync_plausibility_check(), handle_union_p2p_demand(), handle_union_p2p_done(), handle_union_p2p_elements(), handle_union_p2p_full_done(), handle_union_p2p_full_element(), handle_union_p2p_ibf(), handle_union_p2p_inquiry(), handle_union_p2p_offer(), handle_union_p2p_request_full(), handle_union_p2p_send_full(), handle_union_p2p_strata_estimator(), and send_offers_iterator().

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

◆ full_sync_plausibility_check()

static void full_sync_plausibility_check ( struct Operation op)
static

Function that checks if full sync is plausible.

Parameters
initial_local_elements_in_set
estimated_set_difference
repeated_elements
fresh_elements
op
Returns
GNUNET_OK if

Definition at line 1757 of file gnunet-service-setu.c.

1758 {
1759  if (GNUNET_YES != op->byzantine)
1760  return;
1761 
1762  int security_level_lb = -1 * SECURITY_LEVEL;
1763  uint64_t duplicates = op->received_fresh - op->received_total;
1764 
1765  /*
1766  * Protect full sync from receiving double element when in FULL SENDING
1767  */
1768  if (PHASE_FULL_SENDING == op->phase)
1769  {
1770  if (duplicates > 0)
1771  {
1773  "PROTOCOL VIOLATION: Received duplicate element in full receiving "
1774  "mode of operation this is not allowed! Duplicates: %llu\n",
1775  (unsigned long long) duplicates);
1776  GNUNET_break_op (0);
1778  return;
1779  }
1780 
1781  }
1782 
1783  /*
1784  * Protect full sync with probabilistic algorithm
1785  */
1786  if (PHASE_FULL_RECEIVING == op->phase)
1787  {
1788  if (0 == op->remote_set_diff)
1789  op->remote_set_diff = 1;
1790 
1791  long double base = (1 - (long double) (op->remote_set_diff
1792  / (long double) (op->initial_size
1793  + op->
1794  remote_set_diff)));
1795  long double exponent = (op->received_total - (op->received_fresh * ((long
1796  double)
1797  op->
1798  initial_size
1799  / (long
1800  double)
1801  op->
1802  remote_set_diff)));
1803  long double value = exponent * (log2l (base) / log2l (2));
1804  if ((value < security_level_lb) || (value > SECURITY_LEVEL) )
1805  {
1807  "PROTOCOL VIOLATION: Other peer violated probabilistic rule for receiving "
1808  "to many duplicated full element : %LF\n",
1809  value);
1810  GNUNET_break_op (0);
1812  return;
1813  }
1814  }
1815 }
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation.
#define SECURITY_LEVEL
Security level used for byzantine checks (2^80)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.

References fail_union_operation(), GNUNET_break_op, GNUNET_ERROR_TYPE_ERROR, GNUNET_YES, LOG, op, PHASE_FULL_RECEIVING, PHASE_FULL_SENDING, SECURITY_LEVEL, and value.

Referenced by handle_union_p2p_full_element().

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

◆ check_max_differential_rounds()

static void check_max_differential_rounds ( struct Operation op)
static

Limit active passive switches in differential sync to configured security level.

Parameters
op

Definition at line 1823 of file gnunet-service-setu.c.

1824 {
1825  double probability = op->differential_sync_iterations * (log2l (
1827  / log2l (2));
1828  if ((-1 * SECURITY_LEVEL) > probability)
1829  {
1831  "PROTOCOL VIOLATION: Other peer violated probabilistic rule for to many active passive "
1832  "switches in differential sync: %u\n",
1833  op->differential_sync_iterations);
1834  GNUNET_break_op (0);
1836  return;
1837  }
1838 }
#define PROBABILITY_FOR_NEW_ROUND
Is the estimated probability for a new round this values is based on the bsc thesis of Elias Summerma...

References fail_union_operation(), GNUNET_break_op, GNUNET_ERROR_TYPE_ERROR, LOG, op, PROBABILITY_FOR_NEW_ROUND, and SECURITY_LEVEL.

Referenced by handle_union_p2p_ibf().

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

◆ get_ibf_key()

static struct IBF_Key get_ibf_key ( const struct GNUNET_HashCode src)
static

Derive the IBF key from a hash code and a salt.

Parameters
srcthe hash code
Returns
the derived IBF key

Definition at line 1823 of file gnunet-service-setu.c.

1850 {
1851  struct IBF_Key key;
1852  uint16_t salt = 0;
1853 
1855  GNUNET_CRYPTO_kdf (&key, sizeof(key),
1856  src, sizeof *src,
1857  &salt, sizeof(salt),
1858  NULL, 0));
1859  return key;
1860 }
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calcualations.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:70

Referenced by handle_client_set_add(), op_get_element(), and op_register_element().

Here is the caller graph for this function:

◆ op_get_element_iterator()

static int op_get_element_iterator ( void *  cls,
uint32_t  key,
void *  value 
)
static

Iterator over the mapping from IBF keys to element entries.

Checks if we have an element with a given GNUNET_HashCode.

Parameters
clsclosure
keycurrent key code
valuevalue in the hash map
Returns
GNUNET_YES if we should search further, GNUNET_NO if we've found the element.

Definition at line 1891 of file gnunet-service-setu.c.

1894 {
1895  struct GetElementContext *ctx = cls;
1896  struct KeyEntry *k = value;
1897 
1898  GNUNET_assert (NULL != k);
1900  &ctx->hash))
1901  {
1902  ctx->k = k;
1903  return GNUNET_NO;
1904  }
1905  return GNUNET_YES;
1906 }
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
Definition: crypto_hash.c:220
struct GNUNET_HashCode element_hash
Hash of the element.
Context for op_get_element_iterator.

References ctx, KeyEntry::element, ElementEntry::element_hash, GNUNET_assert, GNUNET_CRYPTO_hash_cmp(), GNUNET_NO, GNUNET_YES, and value.

Referenced by op_get_element().

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

◆ op_get_element()

static struct KeyEntry* op_get_element ( struct Operation op,
const struct GNUNET_HashCode element_hash 
)
static

Determine whether the given element is already in the operation's element set.

Parameters
opoperation that should be tested for 'element_hash'
element_hashhash of the element to look for
Returns
GNUNET_YES if the element has been found, GNUNET_NO otherwise

Definition at line 1918 of file gnunet-service-setu.c.

1920 {
1921  int ret;
1922  struct IBF_Key ibf_key;
1923  struct GetElementContext ctx = { { { 0 } }, 0 };
1924 
1925  ctx.hash = *element_hash;
1926 
1927  ibf_key = get_ibf_key (element_hash);
1929  (uint32_t) ibf_key.key_val,
1931  &ctx);
1932 
1933  /* was the iteration aborted because we found the element? */
1934  if (GNUNET_SYSERR == ret)
1935  {
1936  GNUNET_assert (NULL != ctx.k);
1937  return ctx.k;
1938  }
1939  return NULL;
1940 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct IBF_Key get_ibf_key(const struct GNUNET_HashCode *src)
Derive the IBF key from a hash code and a salt.
static int op_get_element_iterator(void *cls, uint32_t key, void *value)
Iterator over the mapping from IBF keys to element entries.
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.

References ctx, get_ibf_key(), GNUNET_assert, GNUNET_CONTAINER_multihashmap32_get_multiple(), GNUNET_SYSERR, IBF_Key::key_val, op, op_get_element_iterator(), and ret.

Referenced by handle_union_p2p_elements(), and handle_union_p2p_full_element().

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

◆ op_register_element()

static void op_register_element ( struct Operation op,
struct ElementEntry ee,
int  received 
)
static

Insert an element into the union operation's key-to-element mapping.

Takes ownership of 'ee'. Note that this does not insert the element in the set, only in the operation's key-element mapping. This is done to speed up re-tried operations, if some elements were transmitted, and then the IBF fails to decode.

XXX: clarify ownership, doesn't sound right.

Parameters
opthe union operation
eethe element entry
receivedwas this element received from the remote peer?

Definition at line 1958 of file gnunet-service-setu.c.

1961 {
1962  struct IBF_Key ibf_key;
1963  struct KeyEntry *k;
1964 
1965  ibf_key = get_ibf_key (&ee->element_hash);
1966  k = GNUNET_new (struct KeyEntry);
1967  k->element = ee;
1968  k->ibf_key = ibf_key;
1969  k->received = received;
1971  GNUNET_CONTAINER_multihashmap32_put (op->key_to_element,
1972  (uint32_t) ibf_key.key_val,
1973  k,
1975 }
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_put(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t 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.
uint64_t key_val
Definition: ibf.h:47
struct IBF_Key ibf_key
IBF key for the entry, derived from the current salt.
int received
Did we receive this element? Even if element->is_foreign is false, we might have received the element...

References KeyEntry::element, ElementEntry::element_hash, get_ibf_key(), GNUNET_assert, GNUNET_CONTAINER_multihashmap32_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_new, GNUNET_OK, KeyEntry::ibf_key, IBF_Key::key_val, op, and KeyEntry::received.

Referenced by handle_union_p2p_elements(), handle_union_p2p_full_element(), and init_key_to_element_iterator().

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

◆ salt_key()

static void salt_key ( const struct IBF_Key k_in,
uint32_t  salt,
struct IBF_Key k_out 
)
static

Modify an IBF key k_in based on the salt, returning a salted key in k_out.

Definition at line 1983 of file gnunet-service-setu.c.

1986 {
1987  int s = (salt * 7) % 64;
1988  uint64_t x = k_in->key_val;
1989 
1990  /* rotate ibf key */
1991  x = (x >> s) | (x << (64 - s));
1992  k_out->key_val = x;
1993 }

References IBF_Key::key_val, and salt.

Referenced by prepare_ibf_iterator().

Here is the caller graph for this function:

◆ unsalt_key()

static void unsalt_key ( const struct IBF_Key k_in,
uint32_t  salt,
struct IBF_Key k_out 
)
static

Reverse modification done in the salt_key function.

Definition at line 2000 of file gnunet-service-setu.c.

2003 {
2004  int s = (salt * 7) % 64;
2005  uint64_t x = k_in->key_val;
2006 
2007  x = (x << s) | (x >> (64 - s));
2008  k_out->key_val = x;
2009 }

References IBF_Key::key_val, and salt.

Referenced by decode_and_send(), and handle_union_p2p_inquiry().

Here is the caller graph for this function:

◆ prepare_ibf_iterator()

static int prepare_ibf_iterator ( void *  cls,
uint32_t  key,
void *  value 
)
static

Insert a key into an ibf.

Parameters
clsthe ibf
keyunused
valuethe key entry to get the key from

Definition at line 2020 of file gnunet-service-setu.c.

2023 {
2024  struct Operation *op = cls;
2025  struct KeyEntry *ke = value;
2026  struct IBF_Key salted_key;
2027 
2029  "[OP %p] inserting %lx (hash %s) into ibf\n",
2030  op,
2031  (unsigned long) ke->ibf_key.key_val,
2032  GNUNET_h2s (&ke->element->element_hash));
2033  salt_key (&ke->ibf_key,
2034  op->salt_send,
2035  &salted_key);
2036  ibf_insert (op->local_ibf, salted_key);
2037  return GNUNET_YES;
2038 }
static void salt_key(const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
Modify an IBF key k_in based on the salt, returning a salted key in k_out.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
void ibf_insert(struct InvertibleBloomFilter *ibf, struct IBF_Key key)
Insert a key into an IBF.
Definition: ibf.c:168

References KeyEntry::element, ElementEntry::element_hash, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_YES, ibf_insert(), KeyEntry::ibf_key, IBF_Key::key_val, LOG, op, salt_key(), and value.

Referenced by prepare_ibf().

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

◆ _GSS_is_element_of_operation()

static int _GSS_is_element_of_operation ( struct ElementEntry ee,
struct Operation op 
)
static

Is element ee part of the set used by op?

Parameters
eeelement to test
opoperation the defines the set and its generation
Returns
GNUNET_YES if the element is in the set, GNUNET_NO if not

Definition at line 2049 of file gnunet-service-setu.c.

2051 {
2052  return ee->generation >= op->generation_created;
2053 }
unsigned int generation
First generation that includes this element.

References ElementEntry::generation, and op.

Referenced by handle_union_p2p_demand(), handle_union_p2p_offer(), and init_key_to_element_iterator().

Here is the caller graph for this function:

◆ init_key_to_element_iterator()

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

Iterator for initializing the key-to-element mapping of a union operation.

Parameters
clsthe union operation struct Operation *
keyunused
valuethe struct ElementEntry * to insert into the key-to-element mapping
Returns
GNUNET_YES (to continue iterating)

Definition at line 2067 of file gnunet-service-setu.c.

2070 {
2071  struct Operation *op = cls;
2072  struct ElementEntry *ee = value;
2073 
2074  /* make sure that the element belongs to the set at the time
2075  * of creating the operation */
2076  if (GNUNET_NO ==
2078  op))
2079  return GNUNET_YES;
2080  GNUNET_assert (GNUNET_NO == ee->remote);
2082  ee,
2083  GNUNET_NO);
2084  return GNUNET_YES;
2085 }
static int _GSS_is_element_of_operation(struct ElementEntry *ee, struct Operation *op)
Is element ee part of the set used by op?
static void op_register_element(struct Operation *op, struct ElementEntry *ee, int received)
Insert an element into the union operation's key-to-element mapping.
Information about an element element in the set.

References _GSS_is_element_of_operation(), GNUNET_assert, GNUNET_NO, GNUNET_YES, op, op_register_element(), ElementEntry::remote, and value.

Referenced by initialize_key_to_element().

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

◆ initialize_key_to_element()

static void initialize_key_to_element ( struct Operation op)
static

Initialize the IBF key to element mapping local to this set operation.

Parameters
opthe set union operation

Definition at line 2094 of file gnunet-service-setu.c.

2095 {
2096  unsigned int len;
2097 
2098  GNUNET_assert (NULL == op->key_to_element);
2099  len = GNUNET_CONTAINER_multihashmap_size (op->set->content->elements);
2100  op->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
2101  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
2103  op);
2104 }
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static int init_key_to_element_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator for initializing the key-to-element mapping of a union operation.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.

References GNUNET_assert, GNUNET_CONTAINER_multihashmap32_create(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_size(), init_key_to_element_iterator(), len, and op.

Referenced by handle_client_accept(), and handle_client_evaluate().

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

◆ prepare_ibf()

static int prepare_ibf ( struct Operation op,
uint32_t  size 
)
static

Create an ibf with the operation's elements of the specified size.

Parameters
opthe union operation
sizesize of the ibf to create
Returns
GNUNET_OK on success, GNUNET_SYSERR on failure

Definition at line 2116 of file gnunet-service-setu.c.

2118 {
2119  GNUNET_assert (NULL != op->key_to_element);
2120 
2121  if (NULL != op->local_ibf)
2122  ibf_destroy (op->local_ibf);
2123  // op->local_ibf = ibf_create (size, SE_IBF_HASH_NUM);
2124  op->local_ibf = ibf_create (size,
2125  ((uint8_t) op->ibf_number_buckets_per_element));
2126  if (NULL == op->local_ibf)
2127  {
2129  "Failed to allocate local IBF\n");
2130  return GNUNET_SYSERR;
2131  }
2134  op);
2135  return GNUNET_OK;
2136 }
static int prepare_ibf_iterator(void *cls, uint32_t key, void *value)
Insert a key into an ibf.
static unsigned int size
Size of the "table".
Definition: peer.c:68
struct InvertibleBloomFilter * ibf_create(uint32_t size, uint8_t hash_num)
Create an invertible bloom filter.
Definition: ibf.c:80

References GNUNET_assert, GNUNET_CONTAINER_multihashmap32_iterate(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_SYSERR, ibf_create(), ibf_destroy(), op, prepare_ibf_iterator(), and size.

Referenced by decode_and_send(), and send_ibf().

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

◆ send_ibf()

static int send_ibf ( struct Operation op,
uint32_t  ibf_size 
)
static

Send an ibf of appropriate size.

Fragments the IBF into multiple messages if necessary.

Parameters
opthe union operation
ibf_orderorder of the ibf to send, size=2^order
Returns
GNUNET_OK on success, GNUNET_SYSERR on failure

Enforce min size of IBF

Definition at line 2149 of file gnunet-service-setu.c.

2151 {
2152  uint64_t buckets_sent = 0;
2153  struct InvertibleBloomFilter *ibf;
2154  op->differential_sync_iterations++;
2155 
2159  uint32_t ibf_min_size = IBF_MIN_SIZE;
2160 
2161  if (ibf_size < ibf_min_size)
2162  {
2163  ibf_size = ibf_min_size;
2164  }
2165  if (GNUNET_OK !=
2166  prepare_ibf (op, ibf_size))
2167  {
2168  /* allocation failed */
2169  return GNUNET_SYSERR;
2170  }
2171 
2173  "sending ibf of size %u\n",
2174  (unsigned int) ibf_size);
2175 
2176  {
2177  char name[64];
2178 
2180  sizeof(name),
2181  "# sent IBF (order %u)",
2182  ibf_size);
2184  }
2185 
2186  ibf = op->local_ibf;
2187 
2188  while (buckets_sent < ibf_size)
2189  {
2190  unsigned int buckets_in_message;
2191  struct GNUNET_MQ_Envelope *ev;
2192  struct IBFMessage *msg;
2193 
2194  buckets_in_message = ibf_size - buckets_sent;
2195  /* limit to maximum */
2196  if (buckets_in_message > MAX_BUCKETS_PER_MESSAGE)
2197  buckets_in_message = MAX_BUCKETS_PER_MESSAGE;
2198 
2199 #if MEASURE_PERFORMANCE
2200  perf_store.ibf.sent += 1;
2201  perf_store.ibf.sent_var_bytes += (buckets_in_message * IBF_BUCKET_SIZE);
2202 #endif
2203  ev = GNUNET_MQ_msg_extra (msg,
2204  buckets_in_message * IBF_BUCKET_SIZE,
2206  msg->ibf_size = ibf_size;
2207  msg->offset = htonl (buckets_sent);
2208  msg->salt = htonl (op->salt_send);
2209  msg->ibf_counter_bit_length = ibf_get_max_counter (ibf);
2210 
2211 
2212  ibf_write_slice (ibf, buckets_sent,
2213  buckets_in_message, &msg[1], msg->ibf_counter_bit_length);
2214  buckets_sent += buckets_in_message;
2216  "ibf chunk size %u, %llu/%u sent\n",
2217  (unsigned int) buckets_in_message,
2218  (unsigned long long) buckets_sent,
2219  (unsigned int) ibf_size);
2220  GNUNET_MQ_send (op->mq, ev);
2221  }
2222 
2223  /* The other peer must decode the IBF, so
2224  * we're passive. */
2225  op->phase = PHASE_PASSIVE_DECODING;
2226  return GNUNET_OK;
2227 }
static int prepare_ibf(struct Operation *op, uint32_t size)
Create an ibf with the operation's elements of the specified size.
static unsigned int ibf_size
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:62
#define GNUNET_MESSAGE_TYPE_SETU_P2P_IBF
Invertible bloom filter.
const char * name
void ibf_write_slice(const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_t count, void *buf)
Write buckets from an ibf to a buffer.
Definition: ibf.c:291
#define IBF_BUCKET_SIZE
Size of one ibf bucket in bytes.
Definition: ibf.h:72
uint8_t ibf_get_max_counter(struct InvertibleBloomFilter *ibf)
Returns the minimal bytes needed to store the counter of the IBF.
Definition: ibf.c:287
Invertible bloom filter (IBF).
Definition: ibf.h:83

References _GSS_statistics, GNUNET_ERROR_TYPE_DEBUG, GNUNET_MESSAGE_TYPE_SETU_P2P_IBF, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_OK, GNUNET_snprintf(), GNUNET_STATISTICS_update(), GNUNET_SYSERR, IBF_BUCKET_SIZE, ibf_get_max_counter(), IBF_MIN_SIZE, ibf_size, ibf_write_slice(), LOG, MAX_BUCKETS_PER_MESSAGE, msg, name, op, PHASE_PASSIVE_DECODING, and prepare_ibf().

Referenced by decode_and_send(), and handle_union_p2p_strata_estimator().

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

◆ get_size_from_difference()

static unsigned int get_size_from_difference ( unsigned int  diff,
int  number_buckets_per_element,
float  ibf_bucket_number_factor 
)
static

Compute the necessary order of an ibf from the size of the symmetric set difference.

Parameters
diffthe difference
Returns
the required size of the ibf

Make ibf estimation size odd reasoning can be found in BSc Thesis of Elias Summermatter (2021) in section 3.11

Definition at line 2238 of file gnunet-service-setu.c.

2240 {
2243  return (((int) (diff * ibf_bucket_number_factor)) | 1);
2244 
2245 }

Referenced by handle_union_p2p_strata_estimator().

Here is the caller graph for this function:

◆ get_next_ibf_size()

static unsigned int get_next_ibf_size ( float  ibf_bucket_number_factor,
unsigned int  decoded_elements,
unsigned int  last_ibf_size 
)
static

Make ibf estimation size odd reasoning can be found in BSc Thesis of Elias Summermatter (2021) in section 3.11

Definition at line 2249 of file gnunet-service-setu.c.

2251 {
2252  unsigned int next_size = (unsigned int) ((last_ibf_size * 2)
2253  - (ibf_bucket_number_factor
2254  * decoded_elements));
2257  return next_size | 1;
2258 }

References consensus-simulation::int.

Referenced by decode_and_send().

Here is the caller graph for this function:

◆ send_full_element_iterator()

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

Send a set element.

Parameters
clsthe union operation struct Operation *
keyunused
valuethe struct ElementEntry * to insert into the key-to-element mapping
Returns
GNUNET_YES (to continue iterating)

Definition at line 2271 of file gnunet-service-setu.c.

2274 {
2275  struct Operation *op = cls;
2276  struct GNUNET_SETU_ElementMessage *emsg;
2277  struct ElementEntry *ee = value;
2278  struct GNUNET_SETU_Element *el = &ee->element;
2279  struct GNUNET_MQ_Envelope *ev;
2280 
2282  "Sending element %s\n",
2283  GNUNET_h2s (key));
2284 #if MEASURE_PERFORMANCE
2285  perf_store.element_full.received += 1;
2286  perf_store.element_full.received_var_bytes += el->size;
2287 #endif
2288  ev = GNUNET_MQ_msg_extra (emsg,
2289  el->size,
2291  emsg->element_type = htons (el->element_type);
2292  GNUNET_memcpy (&emsg[1],
2293  el->data,
2294  el->size);
2295  GNUNET_MQ_send (op->mq,
2296  ev);
2297  return GNUNET_YES;
2298 }
static struct GNUNET_IDENTITY_EgoLookup * el
EgoLookup.
Definition: gnunet-abd.c:51
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT
Send a set element, not as response to a demand but because we're sending the full set.
struct GNUNET_SET_Element element
The actual element.
uint16_t element_type
Type of the element to add or remove.
Definition: setu.h:335

References el, ElementEntry::element, GNUNET_SETU_ElementMessage::element_type, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_YES, key, LOG, op, and value.

Referenced by send_full_set().

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

◆ send_full_set()

static void send_full_set ( struct Operation op)
static

Switch to full set transmission for op.

Parameters
opoperation to switch to full set transmission.

Definition at line 2307 of file gnunet-service-setu.c.

2308 {
2309  struct GNUNET_MQ_Envelope *ev;
2310 
2311  op->phase = PHASE_FULL_SENDING;
2313  "Dedicing to transmit the full set\n");
2314  /* FIXME: use a more memory-friendly way of doing this with an
2315  iterator, just as we do in the non-full case! */
2316 
2317  // Randomize Elements to send
2318  op->set->content->elements_randomized = GNUNET_CONTAINER_multihashmap_create (
2319  32,GNUNET_NO);
2320  op->set->content->elements_randomized_salt = GNUNET_CRYPTO_random_u64 (
2322  UINT64_MAX);
2323  (void) GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
2324  &
2326  op);
2327 
2329  op->set->content->elements_randomized,
2331  op);
2332 #if MEASURE_PERFORMANCE
2333  perf_store.full_done.sent += 1;
2334 #endif
2336  GNUNET_MQ_send (op->mq,
2337  ev);
2338 }
static int create_randomized_element_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Create randomized element hashmap for full sending.
static int send_full_element_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Send a set element.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
#define GNUNET_MQ_msg_header(type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header.
Definition: gnunet_mq_lib.h:86
#define GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE
Request all missing elements from the other peer, based on their sets and the elements we previously ...

References create_randomized_element_iterator(), GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_u64(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE, GNUNET_MQ_msg_header, GNUNET_MQ_send(), GNUNET_NO, LOG, op, PHASE_FULL_SENDING, and send_full_element_iterator().

Referenced by handle_union_p2p_request_full(), and handle_union_p2p_strata_estimator().

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

◆ check_union_p2p_strata_estimator()

static int check_union_p2p_strata_estimator ( void *  cls,
const struct StrataEstimatorMessage msg 
)
static

Handle a strata estimator from a remote peer.

Parameters
clsthe union operation
msgthe message

Definition at line 2348 of file gnunet-service-setu.c.

2350 {
2351  struct Operation *op = cls;
2352  int is_compressed;
2353  size_t len;
2354 
2355  if (op->phase != PHASE_EXPECT_SE)
2356  {
2357  GNUNET_break (0);
2358  return GNUNET_SYSERR;
2359  }
2360  is_compressed = (GNUNET_MESSAGE_TYPE_SETU_P2P_SEC == htons (
2361  msg->header.type));
2362  len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
2363  if ((GNUNET_NO == is_compressed) &&
2365  {
2366  GNUNET_break (0);
2367  return GNUNET_SYSERR;
2368  }
2369  return GNUNET_OK;
2370 }
#define SE_STRATA_COUNT
Number of IBFs in a strata estimator.
#define SE_IBFS_TOTAL_SIZE
Primes for all 4 different strata estimators 61,67,71,73,79,83,89,97 348 Based on the bsc thesis of E...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_SEC
Compressed strata estimator.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Strata estimator together with the peer's overall set size.

References GNUNET_break, GNUNET_MESSAGE_TYPE_SETU_P2P_SEC, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, IBF_BUCKET_SIZE, len, msg, op, PHASE_EXPECT_SE, SE_IBFS_TOTAL_SIZE, SE_STRATA_COUNT, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

◆ handle_union_p2p_strata_estimator()

static void handle_union_p2p_strata_estimator ( void *  cls,
const struct StrataEstimatorMessage msg 
)
static

Handle a strata estimator from a remote peer.

Parameters
clsthe union operation
msgthe message

Check that the message is received only in supported phase

Only allow 1,2,4,8 SEs

Calculate avg element size if not initial sync

Definition at line 2380 of file gnunet-service-setu.c.

2382 {
2383 #if MEASURE_PERFORMANCE
2384  perf_store.se.received += 1;
2385  perf_store.se.received_var_bytes += ntohs (msg->header.size) - sizeof(struct
2387 #endif
2388  struct Operation *op = cls;
2389  struct MultiStrataEstimator *remote_se;
2390  unsigned int diff;
2391  uint64_t other_size;
2392  size_t len;
2393  int is_compressed;
2394  op->local_element_count = GNUNET_CONTAINER_multihashmap_size (
2395  op->set->content->elements);
2396  // Setting peer site to receiving peer
2397  op->peer_site = 1;
2398 
2402  uint8_t allowed_phases[] = {PHASE_EXPECT_SE};
2403  if (GNUNET_OK !=
2404  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
2405  {
2406  GNUNET_break (0);
2408  return;
2409  }
2410 
2412  if ((msg->se_count > 8) || (__builtin_popcount ((int) msg->se_count) != 1))
2413  {
2415  "PROTOCOL VIOLATION: Invalid number of se transmitted by other peer %u\n",
2416  msg->se_count);
2417  GNUNET_break_op (0);
2419  return;
2420  }
2421 
2422  is_compressed = (GNUNET_MESSAGE_TYPE_SETU_P2P_SEC == htons (
2423  msg->header.type));
2425  "# bytes of SE received",
2426  ntohs (msg->header.size),
2427  GNUNET_NO);
2428  len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
2429  other_size = GNUNET_ntohll (msg->set_size);
2430  op->remote_element_count = other_size;
2431 
2432  if (op->byzantine_upper_bound < op->remote_element_count)
2433  {
2435  "Exceeded configured upper bound <%lu> of element: %u\n",
2436  op->byzantine_upper_bound,
2437  op->remote_element_count);
2439  return;
2440  }
2441 
2444  SE_IBF_HASH_NUM);
2445  if (NULL == remote_se)
2446  {
2447  /* insufficient resources, fail */
2449  return;
2450  }
2451  if (GNUNET_OK !=
2453  len,
2454  is_compressed,
2455  msg->se_count,
2457  remote_se))
2458  {
2459  /* decompression failed */
2460  strata_estimator_destroy (remote_se);
2462  return;
2463  }
2464  GNUNET_assert (NULL != op->se);
2465  strata_estimator_difference (remote_se,
2466  op->se);
2467 
2468  /* Calculate remote local diff */
2469  long diff_remote = remote_se->stratas[0]->strata[0]->remote_decoded_count;
2470  long diff_local = remote_se->stratas[0]->strata[0]->local_decoded_count;
2471 
2472  /* Prevent estimations from overshooting max element */
2473  if (diff_remote + op->remote_element_count > op->byzantine_upper_bound)
2474  diff_remote = op->byzantine_upper_bound - op->remote_element_count;
2475  if (diff_local + op->local_element_count > op->byzantine_upper_bound)
2476  diff_local = op->byzantine_upper_bound - op->local_element_count;
2477  if ((diff_remote < 0) || (diff_local < 0))
2478  {
2479  strata_estimator_destroy (remote_se);
2481  "PROTOCOL VIOLATION: More element is set as upper boundary or other peer is "
2482  "malicious: remote diff %ld, local diff: %ld\n",
2483  diff_remote, diff_local);
2484  GNUNET_break_op (0);
2486  return;
2487  }
2488 
2489  /* Make estimation more precise in initial sync cases */
2490  if (0 == op->remote_element_count)
2491  {
2492  diff_remote = 0;
2493  diff_local = op->local_element_count;
2494  }
2495  if (0 == op->local_element_count)
2496  {
2497  diff_local = 0;
2498  diff_remote = op->remote_element_count;
2499  }
2500 
2501  diff = diff_remote + diff_local;
2502  op->remote_set_diff = diff_remote;
2503 
2505  uint64_t avg_element_size = 0;
2506  if (0 < op->local_element_count)
2507  {
2508  op->total_elements_size_local = 0;
2509  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
2510  &
2512  op);
2513  avg_element_size = op->total_elements_size_local / op->local_element_count;
2514  }
2515 
2516  op->mode_of_operation = estimate_best_mode_of_operation (avg_element_size,
2518  op->set->content->
2519  elements),
2520  op->
2521  remote_element_count,
2522  diff_remote,
2523  diff_local,
2524  op->
2525  rtt_bandwidth_tradeoff,
2526  op->
2527  ibf_bucket_number_factor);
2528 
2529 #if MEASURE_PERFORMANCE
2530  perf_store.se_diff_local = diff_local;
2531  perf_store.se_diff_remote = diff_remote;
2532  perf_store.se_diff = diff;
2533  perf_store.mode_of_operation = op->mode_of_operation;
2534 #endif
2535 
2536  strata_estimator_destroy (remote_se);
2538  op->se = NULL;
2540  "got se diff=%d, using ibf size %d\n",
2541  diff,
2542  1U << get_size_from_difference (diff, op->ibf_number_buckets_per_element,
2543  op->ibf_bucket_number_factor));
2544 
2545  {
2546  char *set_debug;
2547 
2548  set_debug = getenv ("GNUNET_SETU_BENCHMARK");
2549  if ((NULL != set_debug) &&
2550  (0 == strcmp (set_debug, "1")))
2551  {
2552  FILE *f = fopen ("set.log", "a");
2553  fprintf (f, "%llu\n", (unsigned long long) diff);
2554  fclose (f);
2555  }
2556  }
2557 
2558  if ((GNUNET_YES == op->byzantine) &&
2559  (other_size < op->byzantine_lower_bound))
2560  {
2561  GNUNET_break (0);
2563  return;
2564  }
2565 
2566  if ((GNUNET_YES == op->force_full) ||
2567  (op->mode_of_operation != DIFFERENTIAL_SYNC))
2568  {
2570  "Deciding to go for full set transmission (diff=%d, own set=%llu)\n",
2571  diff,
2572  (unsigned long long) op->initial_size);
2574  "# of full sends",
2575  1,
2576  GNUNET_NO);
2577  if (FULL_SYNC_LOCAL_SENDING_FIRST == op->mode_of_operation)
2578  {
2579  struct TransmitFullMessage *signal_msg;
2580  struct GNUNET_MQ_Envelope *ev;
2581  ev = GNUNET_MQ_msg_extra (signal_msg,sizeof(struct TransmitFullMessage),
2583  signal_msg->remote_set_difference = htonl (diff_local);
2584  signal_msg->remote_set_size = htonl (op->local_element_count);
2585  signal_msg->local_set_difference = htonl (diff_remote);
2586  GNUNET_MQ_send (op->mq,
2587  ev);
2588  send_full_set (op);
2589  }
2590  else
2591  {
2592  struct GNUNET_MQ_Envelope *ev;
2593 
2595  "Telling other peer that we expect its full set\n");
2596  op->phase = PHASE_FULL_RECEIVING;
2597 #if MEASURE_PERFORMANCE
2598  perf_store.request_full.sent += 1;
2599 #endif
2600  struct TransmitFullMessage *signal_msg;
2601  ev = GNUNET_MQ_msg_extra (signal_msg,sizeof(struct TransmitFullMessage),
2603  signal_msg->remote_set_difference = htonl (diff_local);
2604  signal_msg->remote_set_size = htonl (op->local_element_count);
2605  signal_msg->local_set_difference = htonl (diff_remote);
2606  GNUNET_MQ_send (op->mq,
2607  ev);
2608  }
2609  }
2610  else
2611  {
2613  "# of ibf sends",
2614  1,
2615  GNUNET_NO);
2616  if (GNUNET_OK !=
2617  send_ibf (op,
2619  op->ibf_number_buckets_per_element,
2620  op->ibf_bucket_number_factor)))
2621  {
2622  /* Internal error, best we can do is shut the connection */
2624  "Failed to send IBF, closing connection\n");
2626  return;
2627  }
2628  }
2629  GNUNET_CADET_receive_done (op->channel);
2630 }
char * getenv()
unsigned int strata_estimator_difference(const struct StrataEstimator *se1, const struct StrataEstimator *se2)
Estimate set difference with two strata estimators, i.e.
struct StrataEstimator * strata_estimator_create(unsigned int strata_count, uint32_t ibf_size, uint8_t ibf_hashnum)
Create a new strata estimator with the given parameters.
int strata_estimator_read(const void *buf, size_t buf_len, int is_compressed, struct StrataEstimator *se)
Read strata from the buffer into the given strata estimator.
static void send_full_set(struct Operation *op)
Switch to full set transmission for op.
static unsigned int get_size_from_difference(unsigned int diff, int number_buckets_per_element, float ibf_bucket_number_factor)
Compute the necessary order of an ibf from the size of the symmetric set difference.
static int determinate_avg_element_size_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator for determining average size.
static enum GNUNET_GenericReturnValue check_valid_phase(const uint8_t allowed_phases[], size_t size_phases, struct Operation *op)
Validates the if a message is received in a correct phase.
static int send_ibf(struct Operation *op, uint32_t ibf_size)
Send an ibf of appropriate size.
static uint8_t estimate_best_mode_of_operation(uint64_t avg_element_size, uint64_t local_set_size, uint64_t remote_set_size, uint64_t est_set_diff_remote, uint64_t est_set_diff_local, uint64_t bandwith_latency_tradeoff, uint64_t ibf_bucket_number_factor)
Function that chooses the optimal mode of operation depending on operation parameters.
#define SE_IBF_HASH_NUM
The hash num parameter for the difference digests and strata estimators.
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Send an ack on the channel to confirm the processing of a message.
Definition: cadet_api.c:872
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
#define GNUNET_MESSAGE_TYPE_SETU_P2P_SEND_FULL
Signals other peer that all elements are sent.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL
Demand the whole element from the other peer, given only the hash code.
int remote_decoded_count
If an IBF is decoded this count stores how many elements are on the remote site.
Definition: ibf.h:108
int local_decoded_count
If an IBF is decoded this count stores how many elements are on the local site.
Definition: ibf.h:101
struct StrataEstimator ** stratas
Array of strata estimators.
struct InvertibleBloomFilter ** strata
The IBFs of this strata estimator.
Message which signals to other peer that we are sending full set.
uint32_t local_set_difference
Local set difference calculated with strata estimator.
uint32_t remote_set_difference
Remote set difference calculated with strata estimator.
uint32_t remote_set_size
Total remote set size.

References _GSS_statistics, check_valid_phase(), determinate_avg_element_size_iterator(), DIFFERENTIAL_SYNC, estimate_best_mode_of_operation(), removetrailingwhitespace::f, fail_union_operation(), FULL_SYNC_LOCAL_SENDING_FIRST, get_size_from_difference(), getenv(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL, GNUNET_MESSAGE_TYPE_SETU_P2P_SEC, GNUNET_MESSAGE_TYPE_SETU_P2P_SEND_FULL, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_ntohll(), GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_YES, len, InvertibleBloomFilter::local_decoded_count, TransmitFullMessage::local_set_difference, LOG, msg, op, PHASE_EXPECT_SE, PHASE_FULL_RECEIVING, InvertibleBloomFilter::remote_decoded_count, TransmitFullMessage::remote_set_difference, TransmitFullMessage::remote_set_size, SE_IBF_HASH_NUM, SE_IBFS_TOTAL_SIZE, SE_STRATA_COUNT, send_full_set(), send_ibf(), GNUNET_MessageHeader::size, StrataEstimator::strata, strata_estimator_create(), strata_estimator_destroy(), strata_estimator_difference(), strata_estimator_read(), MultiStrataEstimator::stratas, and GNUNET_MessageHeader::type.

Here is the call graph for this function:

◆ send_offers_iterator()

static int send_offers_iterator ( void *  cls,
uint32_t  key,
void *  value 
)
static

Iterator to send elements to a remote peer.

Parameters
clsclosure with the element key and the union operation
keyignored
valuethe key entry

Definition at line 2641 of file gnunet-service-setu.c.

2644 {
2645  struct SendElementClosure *sec = cls;
2646  struct Operation *op = sec->op;
2647  struct KeyEntry *ke = value;
2648  struct GNUNET_MQ_Envelope *ev;
2649  struct GNUNET_MessageHeader *mh;
2650 
2651  /* Detect 32-bit key collision for the 64-bit IBF keys. */
2652  if (ke->ibf_key.key_val != sec->ibf_key.key_val)
2653  {
2654  op->active_passive_switch_required = true;
2655  return GNUNET_YES;
2656  }
2657 
2658  /* Prevent implementation from sending a offer multiple times in case of roll switch */
2659  if (GNUNET_YES ==
2661  op->message_control_flow,
2662  &ke->element->element_hash,
2663  OFFER_MESSAGE)
2664  )
2665  {
2667  "Skipping already sent processed element offer!\n");
2668  return GNUNET_YES;
2669  }
2670 
2671  /* Save send offer message for message control */
2672  if (GNUNET_YES !=
2674  op->message_control_flow,
2675  MSG_CFS_SENT,
2676  &ke->element->element_hash,
2677  OFFER_MESSAGE)
2678  )
2679  {
2681  "Double offer message sent found!\n");
2682  GNUNET_break (0);
2684  return GNUNET_NO;
2685  }
2686  ;
2687 
2688  /* Mark element to be expected to received */
2689  if (GNUNET_YES !=
2691  op->message_control_flow,
2693  &ke->element->element_hash,
2695  )
2696  {
2698  "Double demand received found!\n");
2699  GNUNET_break (0);
2701  return GNUNET_NO;
2702  }
2703  ;
2704 #if MEASURE_PERFORMANCE
2705  perf_store.offer.sent += 1;
2706  perf_store.offer.sent_var_bytes += sizeof(struct GNUNET_HashCode);
2707 #endif
2709  sizeof(struct GNUNET_HashCode),
2711  GNUNET_assert (NULL != ev);
2712  *(struct GNUNET_HashCode *) &mh[1] = ke->element->element_hash;
2714  "[OP %p] sending element offer (%s) to peer\n",
2715  op,
2716  GNUNET_h2s (&ke->element->element_hash));
2717  GNUNET_MQ_send (op->mq, ev);
2718  return GNUNET_YES;
2719 }
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
static int update_message_control_flow(struct GNUNET_CONTAINER_MultiHashMap *hash_map, enum MESSAGE_CONTROL_FLOW_STATE new_mcfs, const struct GNUNET_HashCode *hash_code, enum MESSAGE_TYPE mt)
Function to update, track and validate message received in differential sync.
static int is_message_in_message_control_flow(struct GNUNET_CONTAINER_MultiHashMap *hash_map, struct GNUNET_HashCode *hash_code, enum MESSAGE_TYPE mt)
Validate if a message in differential sync si already received before.
#define GNUNET_MQ_msg_header_extra(mh, esize, type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header and extra space.
Definition: gnunet_mq_lib.h:98
#define GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER
Tell the other peer which hashes match a given IBF key.
Used as a closure for sending elements with a specific IBF key.
struct Operation * op
Operation for which the elements should be sent.
struct IBF_Key ibf_key
The IBF key whose matching elements should be sent.

References DEMAND_MESSAGE, KeyEntry::element, ElementEntry::element_hash, fail_union_operation(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_h2s(), GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER, GNUNET_MQ_msg_header_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_YES, KeyEntry::ibf_key, SendElementClosure::ibf_key, is_message_in_message_control_flow(), IBF_Key::key_val, LOG, mh, MSG_CFS_EXPECTED, MSG_CFS_SENT, OFFER_MESSAGE, op, SendElementClosure::op, update_message_control_flow(), and value.

Referenced by send_offers_for_key().

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

◆ send_offers_for_key()

void send_offers_for_key ( struct Operation op,
struct IBF_Key  ibf_key 
)

Send offers (in the form of GNUNET_Hash-es) to the remote peer for the given IBF key.

Parameters
opunion operation
ibf_keyIBF key of interest

Definition at line 2729 of file gnunet-service-setu.c.

2731 {
2732  struct SendElementClosure send_cls;
2733 
2734  send_cls.ibf_key = ibf_key;
2735  send_cls.op = op;
2737  op->key_to_element,
2738  (uint32_t) ibf_key.
2739  key_val,
2741  &send_cls);
2742 }
static int send_offers_iterator(void *cls, uint32_t key, void *value)
Iterator to send elements to a remote peer.

References GNUNET_CONTAINER_multihashmap32_get_multiple(), SendElementClosure::ibf_key, op, SendElementClosure::op, and send_offers_iterator().

Referenced by decode_and_send(), and handle_union_p2p_inquiry().

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

◆ decode_and_send()

static int decode_and_send ( struct Operation op)
static

Decode which elements are missing on each side, and send the appropriate offers and inquiries.

Parameters
opunion operation
Returns
GNUNET_OK on success, GNUNET_SYSERR on failure

Enforce odd ibf size

Make ibf estimation size odd reasoning can be found in BSc Thesis of Elias Summermatter (2021) in section 3.11

Add sent inquiries to hashmap for flow control

Definition at line 2753 of file gnunet-service-setu.c.

2754 {
2755  struct IBF_Key key;
2756  struct IBF_Key last_key;
2757  int side;
2758  unsigned int num_decoded;
2759  struct InvertibleBloomFilter *diff_ibf;
2760 
2762 
2763  if (GNUNET_OK !=
2764  prepare_ibf (op,
2765  op->remote_ibf->size))
2766  {
2767  GNUNET_break (0);
2768  /* allocation failed */
2769  return GNUNET_SYSERR;
2770  }
2771 
2772  diff_ibf = ibf_dup (op->local_ibf);
2773  ibf_subtract (diff_ibf,
2774  op->remote_ibf);
2775 
2776  ibf_destroy (op->remote_ibf);
2777  op->remote_ibf = NULL;
2778 
2780  "decoding IBF (size=%u)\n",
2781  diff_ibf->size);
2782 
2783  num_decoded = 0;
2784  key.key_val = 0; /* just to avoid compiler thinking we use undef'ed variable */
2785 
2786  while (1)
2787  {
2788  int res;
2789  int cycle_detected = GNUNET_NO;
2790 
2791  last_key = key;
2792 
2793  res = ibf_decode (diff_ibf,
2794  &side,
2795  &key);
2796  if (res == GNUNET_OK)
2797  {
2799  "decoded ibf key %lx\n",
2800  (unsigned long) key.key_val);
2801  num_decoded += 1;
2802  if ((num_decoded > diff_ibf->size) ||
2803  ((num_decoded > 1) &&
2804  (last_key.key_val == key.key_val)))
2805  {
2807  "detected cyclic ibf (decoded %u/%u)\n",
2808  num_decoded,
2809  diff_ibf->size);
2810  cycle_detected = GNUNET_YES;
2811  }
2812  }
2813  if ((GNUNET_SYSERR == res) ||
2814  (GNUNET_YES == cycle_detected))
2815  {
2816  uint32_t next_size;
2819  next_size = get_next_ibf_size (op->ibf_bucket_number_factor, num_decoded,
2820  diff_ibf->size);
2823  uint32_t ibf_min_size = IBF_MIN_SIZE | 1;
2824 
2825  if (next_size<ibf_min_size)
2826  next_size = ibf_min_size;
2827 
2828 
2829  if (next_size <= MAX_IBF_SIZE)
2830  {
2832  "decoding failed, sending larger ibf (size %u)\n",
2833  next_size);
2835  "# of IBF retries",
2836  1,
2837  GNUNET_NO);
2838 #if MEASURE_PERFORMANCE
2839  perf_store.active_passive_switches += 1;
2840 #endif
2841 
2842  op->salt_send = op->salt_receive++;
2843 
2844  if (GNUNET_OK !=
2845  send_ibf (op, next_size))
2846  {
2847  /* Internal error, best we can do is shut the connection */
2849  "Failed to send IBF, closing connection\n");
2851  ibf_destroy (diff_ibf);
2852  return GNUNET_SYSERR;
2853  }
2854  }
2855  else
2856  {
2858  "# of failed union operations (too large)",
2859  1,
2860  GNUNET_NO);
2861  // XXX: Send the whole set, element-by-element
2863  "set union failed: reached ibf limit\n");
2865  ibf_destroy (diff_ibf);
2866  return GNUNET_SYSERR;
2867  }
2868  break;
2869  }
2870  if (GNUNET_NO == res)
2871  {
2872  struct GNUNET_MQ_Envelope *ev;
2873 
2875  "transmitted all values, sending DONE\n");
2876 
2877 #if MEASURE_PERFORMANCE
2878  perf_store.done.sent += 1;
2879 #endif
2881  GNUNET_MQ_send (op->mq, ev);
2882  /* We now wait until we get a DONE message back
2883  * and then wait for our MQ to be flushed and all our
2884  * demands be delivered. */
2885  break;
2886  }
2887  if (1 == side)
2888  {
2889  struct IBF_Key unsalted_key;
2890  unsalt_key (&key,
2891  op->salt_receive,
2892  &unsalted_key);
2894  unsalted_key);
2895  }
2896  else if (-1 == side)
2897  {
2898  struct GNUNET_MQ_Envelope *ev;
2899  struct InquiryMessage *msg;
2900 
2901 #if MEASURE_PERFORMANCE
2902  perf_store.inquery.sent += 1;
2903  perf_store.inquery.sent_var_bytes += sizeof(struct IBF_Key);
2904 #endif
2905 
2907  struct GNUNET_HashContext *hashed_key_context =
2909  struct GNUNET_HashCode *hashed_key = (struct
2911  sizeof(struct GNUNET_HashCode));
2913  GNUNET_CRYPTO_hash_context_read (hashed_key_context,
2914  &key,
2915  sizeof(struct IBF_Key));
2916  GNUNET_CRYPTO_hash_context_finish (hashed_key_context,
2917  hashed_key);
2918  GNUNET_CONTAINER_multihashmap_put (op->inquiries_sent,
2919  hashed_key,
2920  &mcfs,
2922  );
2923 
2924  /* It may be nice to merge multiple requests, but with CADET's corking it is not worth
2925  * the effort additional complexity. */
2926  ev = GNUNET_MQ_msg_extra (msg,
2927  sizeof(struct IBF_Key),
2929  msg->salt = htonl (op->salt_receive);
2930  GNUNET_memcpy (&msg[1],
2931  &key,
2932  sizeof(struct IBF_Key));
2934  "sending element inquiry for IBF key %lx\n",
2935  (unsigned long) key.key_val);
2936  GNUNET_MQ_send (op->mq, ev);
2937  }
2938  else
2939  {
2940  GNUNET_assert (0);
2941  }
2942  }
2943  ibf_destroy (diff_ibf);
2944  return GNUNET_OK;
2945 }
static int res
static unsigned int get_next_ibf_size(float ibf_bucket_number_factor, unsigned int decoded_elements, unsigned int last_ibf_size)
#define MAX_IBF_SIZE
The maximum size of an ibf we use is MAX_IBF_SIZE=2^20.
void send_offers_for_key(struct Operation *op, struct IBF_Key ibf_key)
Send offers (in the form of GNUNET_Hash-es) to the remote peer for the given IBF key.
static void unsalt_key(const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
Reverse modification done in the salt_key function.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_DONE
Set operation is done.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY
Tell the other peer to send us a list of hashes that match an IBF key.
void ibf_subtract(struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2)
Subtract ibf2 from ibf1, storing the result in ibf1.
Definition: ibf.c:357
int ibf_decode(struct InvertibleBloomFilter *ibf, int *ret_side, struct IBF_Key *ret_id)
Decode and remove an element from the IBF, if possible.
Definition: ibf.c:229
struct InvertibleBloomFilter * ibf_dup(const struct InvertibleBloomFilter *ibf)
Create a copy of an IBF, the copy has to be destroyed properly.
Definition: ibf.c:380
uint32_t size
How many cells does this IBF have?
Definition: ibf.h:87

References _GSS_statistics, fail_union_operation(), get_next_ibf_size(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE, GNUNET_CRYPTO_hash_context_finish(), GNUNET_CRYPTO_hash_context_read(), GNUNET_CRYPTO_hash_context_start(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SETU_P2P_DONE, GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY, GNUNET_MQ_msg_extra, GNUNET_MQ_msg_header, GNUNET_MQ_send(), GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_YES, ibf_decode(), ibf_destroy(), ibf_dup(), IBF_MIN_SIZE, ibf_subtract(), key, IBF_Key::key_val, LOG, MAX_IBF_SIZE, msg, MSG_CFS_SENT, op, PHASE_ACTIVE_DECODING, prepare_ibf(), res, send_ibf(), send_offers_for_key(), InvertibleBloomFilter::size, and unsalt_key().

Referenced by handle_union_p2p_ibf().

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

◆ check_union_p2p_send_full()

static int check_union_p2p_send_full ( void *  cls,
const struct TransmitFullMessage msg 
)
static

Check send full message received from other peer.

Parameters
cls
msg
Returns

Definition at line 2956 of file gnunet-service-setu.c.

2958 {
2959  return GNUNET_OK;
2960 }

References GNUNET_OK.

◆ handle_union_p2p_send_full()

static void handle_union_p2p_send_full ( void *  cls,
const struct TransmitFullMessage msg 
)
static

Handle send full message received from other peer.

Parameters
cls
msg

Check that the message is received only in supported phase

write received values to operator

Check byzantine limits

Calculate avg element size if not initial sync

Validate mode of operation

Definition at line 2970 of file gnunet-service-setu.c.

2972 {
2973  struct Operation *op = cls;
2974 
2978  uint8_t allowed_phases[] = {PHASE_EXPECT_IBF};
2979  if (GNUNET_OK !=
2980  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
2981  {
2982  GNUNET_break (0);
2984  return;
2985  }
2986 
2988  op->remote_element_count = ntohl (msg->remote_set_size);
2989  op->remote_set_diff = ntohl (msg->remote_set_difference);
2990  op->local_set_diff = ntohl (msg->local_set_difference);
2991 
2994  {
2996  "PROTOCOL VIOLATION: Parameters transmitted from other peer do not satisfie byzantine "
2997  "criteria\n");
2998  GNUNET_break_op (0);
3000  return;
3001  }
3002 
3004  op->local_element_count = GNUNET_CONTAINER_multihashmap_size (
3005  op->set->content->elements);
3006  uint64_t avg_element_size = 0;
3007  if (0 < op->local_element_count)
3008  {
3009  op->total_elements_size_local = 0;
3010  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
3011  &
3013  op);
3014  avg_element_size = op->total_elements_size_local / op->local_element_count;
3015  }
3016 
3018  int mode_of_operation = estimate_best_mode_of_operation (avg_element_size,
3019  op->
3021  op->
3023  op->local_set_diff,
3024  op->remote_set_diff,
3025  op->
3027  op->
3030  {
3032  "PROTOCOL VIOLATION: Remote peer choose to send his full set first but correct mode would have been"
3033  " : %d\n", mode_of_operation);
3034  GNUNET_break_op (0);
3036  return;
3037  }
3038  op->phase = PHASE_FULL_RECEIVING;
3039 }
static int check_byzantine_bounds(struct Operation *op)
Check if all given byzantine parameters are in given boundaries.
uint8_t ibf_bucket_number_factor
Set difference is multiplied with this factor to gennerate large enough IBF.
uint8_t mode_of_operation
Mode of operation that was chosen by the algorithm.
uint64_t rtt_bandwidth_tradeoff
User defined Bandwidth Round Trips Tradeoff.
uint64_t local_element_count
Local peer element count.
uint32_t remote_element_count
Remote peers element count.

References check_byzantine_bounds(), check_valid_phase(), determinate_avg_element_size_iterator(), estimate_best_mode_of_operation(), fail_union_operation(), FULL_SYNC_LOCAL_SENDING_FIRST, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_ERROR_TYPE_ERROR, GNUNET_OK, Operation::ibf_bucket_number_factor, Operation::local_element_count, LOG, Operation::mode_of_operation, msg, op, PHASE_EXPECT_IBF, PHASE_FULL_RECEIVING, Operation::remote_element_count, and Operation::rtt_bandwidth_tradeoff.

Here is the call graph for this function:

◆ check_union_p2p_ibf()

static int check_union_p2p_ibf ( void *  cls,
const struct IBFMessage msg 
)
static

Check an IBF message from a remote peer.

Reassemble the IBF from multiple pieces, and process the whole IBF once possible.

Parameters
clsthe union operation
msgthe header of the message
Returns
GNUNET_OK if msg is well-formed

Definition at line 3053 of file gnunet-service-setu.c.

3055 {
3056  struct Operation *op = cls;
3057  unsigned int buckets_in_message;
3058 
3059  buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
3060  / IBF_BUCKET_SIZE;
3061  if (0 == buckets_in_message)
3062  {
3063  GNUNET_break_op (0);
3064  return GNUNET_SYSERR;
3065  }
3066  if ((ntohs (msg->header.size) - sizeof *msg) != buckets_in_message
3067  * IBF_BUCKET_SIZE)
3068  {
3069  GNUNET_break_op (0);
3070  return GNUNET_SYSERR;
3071  }
3072  if (op->phase == PHASE_EXPECT_IBF_LAST)
3073  {
3074  if (ntohl (msg->offset) != op->ibf_buckets_received)
3075  {
3076  GNUNET_break_op (0);
3077  return GNUNET_SYSERR;
3078  }
3079 
3080  if (msg->ibf_size != op->remote_ibf->size)
3081  {
3082  GNUNET_break_op (0);
3083  return GNUNET_SYSERR;
3084  }
3085  if (ntohl (msg->salt) != op->salt_receive)
3086  {
3087  GNUNET_break_op (0);
3088  return GNUNET_SYSERR;
3089  }
3090  }
3091  else if ((op->phase != PHASE_PASSIVE_DECODING) &&
3092  (op->phase != PHASE_EXPECT_IBF))
3093  {
3094  GNUNET_break_op (0);
3095  return GNUNET_SYSERR;
3096  }
3097 
3098  return GNUNET_OK;
3099 }

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, IBF_BUCKET_SIZE, msg, op, PHASE_EXPECT_IBF, PHASE_EXPECT_IBF_LAST, PHASE_PASSIVE_DECODING, and GNUNET_MessageHeader::size.

◆ handle_union_p2p_ibf()

static void handle_union_p2p_ibf ( void *  cls,
const struct IBFMessage msg 
)
static

Handle an IBF message from a remote peer.

Reassemble the IBF from multiple pieces, and process the whole IBF once possible.

Parameters
clsthe union operation
msgthe header of the message

Check that the message is received only in supported phase

Definition at line 3112 of file gnunet-service-setu.c.

3114 {
3115  struct Operation *op = cls;
3116  unsigned int buckets_in_message;
3120  uint8_t allowed_phases[] = {PHASE_EXPECT_IBF, PHASE_EXPECT_IBF_LAST,
3122  if (GNUNET_OK !=
3123  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3124  {
3125  GNUNET_break (0);
3127  return;
3128  }
3129  op->differential_sync_iterations++;
3131  op->active_passive_switch_required = false;
3132 
3133 #if MEASURE_PERFORMANCE
3134  perf_store.ibf.received += 1;
3135  perf_store.ibf.received_var_bytes += (ntohs (msg->header.size) - sizeof *msg);
3136 #endif
3137 
3138  buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
3139  / IBF_BUCKET_SIZE;
3140  if ((op->phase == PHASE_PASSIVE_DECODING) ||
3141  (op->phase == PHASE_EXPECT_IBF))
3142  {
3143  op->phase = PHASE_EXPECT_IBF_LAST;
3144  GNUNET_assert (NULL == op->remote_ibf);
3146  "Creating new ibf of size %u\n",
3147  ntohl (msg->ibf_size));
3148  // op->remote_ibf = ibf_create (1 << msg->order, SE_IBF_HASH_NUM);
3149  op->remote_ibf = ibf_create (msg->ibf_size,
3150  ((uint8_t) op->ibf_number_buckets_per_element));
3151  op->salt_receive = ntohl (msg->salt);
3153  "Receiving new IBF with salt %u\n",
3154  op->salt_receive);
3155  if (NULL == op->remote_ibf)
3156  {
3158  "Failed to parse remote IBF, closing connection\n");
3160  return;
3161  }
3162  op->ibf_buckets_received = 0;
3163  if (0 != ntohl (msg->offset))
3164  {
3165  GNUNET_break_op (0);
3167  return;
3168  }
3169  }
3170  else
3171  {
3174  "Received more of IBF\n");
3175  }
3176  GNUNET_assert (NULL != op->remote_ibf);
3177 
3178  ibf_read_slice (&msg[1],
3179  op->ibf_buckets_received,
3180  buckets_in_message,
3181  op->remote_ibf, msg->ibf_counter_bit_length);
3182  op->ibf_buckets_received += buckets_in_message;
3183 
3184  if (op->ibf_buckets_received == op->remote_ibf->size)
3185  {
3187  "received full ibf\n");
3188  op->phase = PHASE_ACTIVE_DECODING;
3189  if (GNUNET_OK !=
3190  decode_and_send (op))
3191  {
3192  /* Internal error, best we can do is shut down */
3194  "Failed to decode IBF, closing connection\n");
3196  return;
3197  }
3198  }
3199  GNUNET_CADET_receive_done (op->channel);
3200 }
static int decode_and_send(struct Operation *op)
Decode which elements are missing on each side, and send the appropriate offers and inquiries.
static void check_max_differential_rounds(struct Operation *op)
Limit active passive switches in differential sync to configured security level.
void ibf_read_slice(const void *buf, uint32_t start, uint32_t count, struct InvertibleBloomFilter *ibf)
Read buckets from a buffer into an ibf.
Definition: ibf.c:324

References check_max_differential_rounds(), check_valid_phase(), decode_and_send(), fail_union_operation(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, IBF_BUCKET_SIZE, ibf_create(), ibf_read_slice(), LOG, msg, op, PHASE_ACTIVE_DECODING, PHASE_EXPECT_IBF, PHASE_EXPECT_IBF_LAST, PHASE_PASSIVE_DECODING, and GNUNET_MessageHeader::size.

Here is the call graph for this function:

◆ send_client_element()

static void send_client_element ( struct Operation op,
const struct GNUNET_SETU_Element element,
enum GNUNET_SETU_Status  status 
)
static

Send a result message to the client indicating that there is a new element.

Parameters
opunion operation
elementelement to send
statusstatus to send with the new element

Definition at line 3212 of file gnunet-service-setu.c.

3215 {
3216  struct GNUNET_MQ_Envelope *ev;
3217  struct GNUNET_SETU_ResultMessage *rm;
3218 
3220  "sending element (size %u) to client\n",
3221  element->size);
3222  GNUNET_assert (0 != op->client_request_id);
3223  ev = GNUNET_MQ_msg_extra (rm,
3224  element->size,
3226  if (NULL == ev)
3227  {
3228  GNUNET_MQ_discard (ev);
3229  GNUNET_break (0);
3230  return;
3231  }
3232  rm->result_status = htons (status);
3233  rm->request_id = htonl (op->client_request_id);
3234  rm->element_type = htons (element->element_type);
3236  op->key_to_element));
3237  GNUNET_memcpy (&rm[1],
3238  element->data,
3239  element->size);
3240  GNUNET_MQ_send (op->set->cs->mq,
3241  ev);
3242 }
uint16_t status
See PRISM_STATUS_*-constants.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:285
uint16_t element_type
Application-specific element type.
const void * data
Actual data of the element.

References GNUNET_SETU_ResultMessage::current_size, GNUNET_SETU_Element::data, GNUNET_SETU_Element::element_type, GNUNET_SETU_ResultMessage::element_type, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap32_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_htonll(), GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SETU_RESULT, GNUNET_MQ_discard(), GNUNET_MQ_msg_extra, GNUNET_MQ_send(), LOG, op, GNUNET_SETU_ResultMessage::request_id, GNUNET_SETU_ResultMessage::result_status, GNUNET_SETU_Element::size, and status.

Referenced by handle_union_p2p_demand(), handle_union_p2p_elements(), and handle_union_p2p_full_element().

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

◆ maybe_finish()

static void maybe_finish ( struct Operation op)
static

Tests if the operation is finished, and if so notify.

Parameters
opoperation to check

Definition at line 3251 of file gnunet-service-setu.c.

3252 {
3253  unsigned int num_demanded;
3254 
3255  num_demanded = GNUNET_CONTAINER_multihashmap_size (
3256  op->demanded_hashes);
3257  int send_done = GNUNET_CONTAINER_multihashmap_iterate (
3258  op->message_control_flow,
3259  &
3261  op);
3262  if (PHASE_FINISH_WAITING == op->phase)
3263  {
3265  "In PHASE_FINISH_WAITING, pending %u demands -> %d\n",
3266  num_demanded, op->peer_site);
3267  if (-1 != send_done)
3268  {
3269  struct GNUNET_MQ_Envelope *ev;
3270 
3271  op->phase = PHASE_FINISHED;
3272 #if MEASURE_PERFORMANCE
3273  perf_store.done.sent += 1;
3274 #endif
3276  GNUNET_MQ_send (op->mq,
3277  ev);
3278  /* We now wait until the other peer sends P2P_OVER
3279  * after it got all elements from us. */
3280  }
3281  }
3282  if (PHASE_FINISH_CLOSING == op->phase)
3283  {
3285  "In PHASE_FINISH_CLOSING, pending %u demands %d\n",
3286  num_demanded, op->peer_site);
3287  if (-1 != send_done)
3288  {
3289  op->phase = PHASE_FINISHED;
3290  send_client_done (op);
3292  }
3293  }
3294 }
static int determinate_done_message_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator for determining if all demands have been satisfied.

References _GSS_operation_destroy2(), determinate_done_message_iterator(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_MESSAGE_TYPE_SETU_P2P_DONE, GNUNET_MQ_msg_header, GNUNET_MQ_send(), LOG, op, PHASE_FINISH_CLOSING, PHASE_FINISH_WAITING, PHASE_FINISHED, and send_client_done().

Referenced by handle_union_p2p_demand(), handle_union_p2p_done(), and handle_union_p2p_elements().

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

◆ check_union_p2p_elements()

static int check_union_p2p_elements ( void *  cls,
const struct GNUNET_SETU_ElementMessage emsg 
)
static

Check an element message from a remote peer.

Parameters
clsthe union operation
emsgthe message

Definition at line 3304 of file gnunet-service-setu.c.

3306 {
3307  struct Operation *op = cls;
3308 
3309  if (0 == GNUNET_CONTAINER_multihashmap_size (op->demanded_hashes))
3310  {
3311  GNUNET_break_op (0);
3312  return GNUNET_SYSERR;
3313  }
3314  return GNUNET_OK;
3315 }

References GNUNET_break_op, GNUNET_CONTAINER_multihashmap_size(), GNUNET_OK, GNUNET_SYSERR, and op.

Here is the call graph for this function:

◆ handle_union_p2p_elements()

static void handle_union_p2p_elements ( void *  cls,
const struct GNUNET_SETU_ElementMessage emsg 
)
static

Handle an element message from a remote peer.

Sent by the other peer either because we decoded an IBF and placed a demand, or because the other peer switched to full set transmission.

Parameters
clsthe union operation
emsgthe message

Check that the message is received only in supported phase

Definition at line 3327 of file gnunet-service-setu.c.

3329 {
3330  struct Operation *op = cls;
3331  struct ElementEntry *ee;
3332  struct KeyEntry *ke;
3333  uint16_t element_size;
3334 
3338  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING,
3340  if (GNUNET_OK !=
3341  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3342  {
3343  GNUNET_break (0);
3345  return;
3346  }
3347 
3348  element_size = ntohs (emsg->header.size) - sizeof(struct
3350 #if MEASURE_PERFORMANCE
3351  perf_store.element.received += 1;
3352  perf_store.element.received_var_bytes += element_size;
3353 #endif
3354 
3355  ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
3356  GNUNET_memcpy (&ee[1],
3357  &emsg[1],
3358  element_size);
3359  ee->element.size = element_size;
3360  ee->element.data = &ee[1];
3361  ee->element.element_type = ntohs (emsg->element_type);
3362  ee->remote = GNUNET_YES;
3364  &ee->element_hash);
3365  if (GNUNET_NO ==
3366  GNUNET_CONTAINER_multihashmap_remove (op->demanded_hashes,
3367  &ee->element_hash,
3368  NULL))
3369  {
3370  /* We got something we didn't demand, since it's not in our map. */
3371  GNUNET_break_op (0);
3373  return;
3374  }
3375 
3376  if (GNUNET_OK !=
3378  op->message_control_flow,
3380  &ee->element_hash,
3382  )
3383  {
3385  "An element has been received more than once!\n");
3386  GNUNET_break (0);
3388  return;
3389  }
3390 
3392  "Got element (size %u, hash %s) from peer\n",
3393  (unsigned int) element_size,
3394  GNUNET_h2s (&ee->element_hash));
3395 
3397  "# received elements",
3398  1,
3399  GNUNET_NO);
3401  "# exchanged elements",
3402  1,
3403  GNUNET_NO);
3404 
3405  op->received_total++;
3406 
3407  ke = op_get_element (op,
3408  &ee->element_hash);
3409  if (NULL != ke)
3410  {
3411  /* Got repeated element. Should not happen since
3412  * we track demands. */
3414  "# repeated elements",
3415  1,
3416  GNUNET_NO);
3417  ke->received = GNUNET_YES;
3418  GNUNET_free (ee);
3419  }
3420  else
3421  {
3423  "Registering new element from remote peer\n");
3424  op->received_fresh++;
3426  /* only send results immediately if the client wants it */
3428  &ee->element,
3430  }
3431 
3432  if ((op->received_total > 8) &&
3433  (op->received_fresh < op->received_total / 3))
3434  {
3435  /* The other peer gave us lots of old elements, there's something wrong. */
3436  GNUNET_break_op (0);
3438  return;
3439  }
3440  GNUNET_CADET_receive_done (op->channel);
3441  maybe_finish (op);
3442 }
static struct KeyEntry * op_get_element(struct Operation *op, const struct GNUNET_HashCode *element_hash)
Determine whether the given element is already in the operation's element set.
static void maybe_finish(struct Operation *op)
Tests if the operation is finished, and if so notify.
static void send_client_element(struct Operation *op, const struct GNUNET_SETU_Element *element, enum GNUNET_SETU_Status status)
Send a result message to the client indicating that there is a new element.
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.
void GNUNET_SETU_element_hash(const struct GNUNET_SETU_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: setu_api.c:890
@ GNUNET_SETU_STATUS_ADD_LOCAL
Element should be added to the result set of the local peer, i.e.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SETU_ADD.
Definition: setu.h:330
uint16_t size
Number of bytes in the buffer pointed to by data.
const void * data
Actual data of the element.
uint16_t element_type
Application-specific element type.

References _GSS_statistics, check_valid_phase(), GNUNET_SET_Element::data, ElementEntry::element, ElementEntry::element_hash, ELEMENT_MESSAGE, element_size, GNUNET_SET_Element::element_type, GNUNET_SETU_ElementMessage::element_type, fail_union_operation(), GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_h2s(), GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_SETU_element_hash(), GNUNET_SETU_STATUS_ADD_LOCAL, GNUNET_STATISTICS_update(), GNUNET_YES, GNUNET_SETU_ElementMessage::header, LOG, maybe_finish(), MSG_CFS_RECEIVED, op, op_get_element(), op_register_element(), PHASE_ACTIVE_DECODING, PHASE_FINISH_CLOSING, PHASE_FINISH_WAITING, PHASE_PASSIVE_DECODING, KeyEntry::received, ElementEntry::remote, send_client_element(), GNUNET_MessageHeader::size, GNUNET_SET_Element::size, and update_message_control_flow().

Here is the call graph for this function:

◆ check_union_p2p_full_element()

static int check_union_p2p_full_element ( void *  cls,
const struct GNUNET_SETU_ElementMessage emsg 
)
static

Check a full element message from a remote peer.

Parameters
clsthe union operation
emsgthe message

Definition at line 3452 of file gnunet-service-setu.c.

3454 {
3455  struct Operation *op = cls;
3456 
3457  (void) op;
3458 
3459  // FIXME: check that we expect full elements here?
3460  return GNUNET_OK;
3461 }

References GNUNET_OK, and op.

◆ handle_union_p2p_full_element()

static void handle_union_p2p_full_element ( void *  cls,
const struct GNUNET_SETU_ElementMessage emsg 
)
static

Handle an element message from a remote peer.

Parameters
clsthe union operation
emsgthe message

Check that the message is received only in supported phase

Definition at line 3471 of file gnunet-service-setu.c.

3473 {
3474  struct Operation *op = cls;
3475  struct ElementEntry *ee;
3476  struct KeyEntry *ke;
3477  uint16_t element_size;
3478 
3482  uint8_t allowed_phases[] = {PHASE_FULL_RECEIVING, PHASE_FULL_SENDING};
3483  if (GNUNET_OK !=
3484  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3485  {
3486  GNUNET_break (0);
3488  return;
3489  }
3490 
3491  element_size = ntohs (emsg->header.size)
3492  - sizeof(struct GNUNET_SETU_ElementMessage);
3493 
3494 #if MEASURE_PERFORMANCE
3495  perf_store.element_full.received += 1;
3496  perf_store.element_full.received_var_bytes += element_size;
3497 #endif
3498 
3499  ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
3500  GNUNET_memcpy (&ee[1], &emsg[1], element_size);
3501  ee->element.size = element_size;
3502  ee->element.data = &ee[1];
3503  ee->element.element_type = ntohs (emsg->element_type);
3504  ee->remote = GNUNET_YES;
3506  &ee->element_hash);
3508  "Got element (full diff, size %u, hash %s) from peer\n",
3509  (unsigned int) element_size,
3510  GNUNET_h2s (&ee->element_hash));
3511 
3513  "# received elements",
3514  1,
3515  GNUNET_NO);
3517  "# exchanged elements",
3518  1,
3519  GNUNET_NO);
3520 
3521  op->received_total++;
3522  ke = op_get_element (op,
3523  &ee->element_hash);
3524  if (NULL != ke)
3525  {
3527  "# repeated elements",
3528  1,
3529  GNUNET_NO);
3531  ke->received = GNUNET_YES;
3532  GNUNET_free (ee);
3533  }
3534  else
3535  {
3537  "Registering new element from remote peer\n");
3538  op->received_fresh++;
3540  /* only send results immediately if the client wants it */
3542  &ee->element,
3544  }
3545 
3546 
3547  if ((GNUNET_YES == op->byzantine) &&
3548  (op->received_total > op->remote_element_count) )
3549  {
3550  /* The other peer gave us lots of old elements, there's something wrong. */
3552  "Other peer sent %llu elements while pretending to have %llu elements, failing operation\n",
3553  (unsigned long long) op->received_total,
3554  (unsigned long long) op->remote_element_count);
3555  GNUNET_break_op (0);
3557  return;
3558  }
3559  GNUNET_CADET_receive_done (op->channel);
3560 }
static void full_sync_plausibility_check(struct Operation *op)
Function that checks if full sync is plausible.

References _GSS_statistics, check_valid_phase(), GNUNET_SET_Element::data, ElementEntry::element, ElementEntry::element_hash, element_size, GNUNET_SET_Element::element_type, GNUNET_SETU_ElementMessage::element_type, fail_union_operation(), full_sync_plausibility_check(), GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_h2s(), GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_SETU_element_hash(), GNUNET_SETU_STATUS_ADD_LOCAL, GNUNET_STATISTICS_update(), GNUNET_YES, GNUNET_SETU_ElementMessage::header, LOG, op, op_get_element(), op_register_element(), PHASE_FULL_RECEIVING, PHASE_FULL_SENDING, KeyEntry::received, ElementEntry::remote, send_client_element(), GNUNET_MessageHeader::size, and GNUNET_SET_Element::size.

Here is the call graph for this function:

◆ check_union_p2p_inquiry()

static int check_union_p2p_inquiry ( void *  cls,
const struct InquiryMessage msg 
)
static

Send offers (for GNUNET_Hash-es) in response to inquiries (for IBF_Key-s).

Parameters
clsthe union operation
msgthe message

Definition at line 3571 of file gnunet-service-setu.c.

3573 {
3574  struct Operation *op = cls;
3575  unsigned int num_keys;
3576 
3577  if (op->phase != PHASE_PASSIVE_DECODING)
3578  {
3579  GNUNET_break_op (0);
3580  return GNUNET_SYSERR;
3581  }
3582  num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
3583  / sizeof(struct IBF_Key);
3584  if ((ntohs (msg->header.size) - sizeof(struct InquiryMessage))
3585  != num_keys * sizeof(struct IBF_Key))
3586  {
3587  GNUNET_break_op (0);
3588  return GNUNET_SYSERR;
3589  }
3590  return GNUNET_OK;
3591 }

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, msg, op, PHASE_PASSIVE_DECODING, and GNUNET_MessageHeader::size.

◆ handle_union_p2p_inquiry()

static void handle_union_p2p_inquiry ( void *  cls,
const struct InquiryMessage msg 
)
static

Send offers (for GNUNET_Hash-es) in response to inquiries (for IBF_Key-s).

Parameters
clsthe union operation
msgthe message

Check that the message is received only in supported phase

Add received inquiries to hashmap for flow control

Definition at line 3601 of file gnunet-service-setu.c.

3603 {
3604  struct Operation *op = cls;
3605  const struct IBF_Key *ibf_key;
3606  unsigned int num_keys;
3607 
3611  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING};
3612  if (GNUNET_OK !=
3613  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3614  {
3615  GNUNET_break (0);
3617  return;
3618  }
3619 
3620 #if MEASURE_PERFORMANCE
3621  perf_store.inquery.received += 1;
3622  perf_store.inquery.received_var_bytes += (ntohs (msg->header.size)
3623  - sizeof(struct InquiryMessage));
3624 #endif
3625 
3627  "Received union inquiry\n");
3628  num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
3629  / sizeof(struct IBF_Key);
3630  ibf_key = (const struct IBF_Key *) &msg[1];
3631 
3633  struct GNUNET_HashContext *hashed_key_context =
3635  struct GNUNET_HashCode *hashed_key = (struct GNUNET_HashCode*) GNUNET_malloc (
3636  sizeof(struct GNUNET_HashCode));;
3638  GNUNET_CRYPTO_hash_context_read (hashed_key_context,
3639  &ibf_key,
3640  sizeof(struct IBF_Key));
3641  GNUNET_CRYPTO_hash_context_finish (hashed_key_context,
3642  hashed_key);
3643  GNUNET_CONTAINER_multihashmap_put (op->inquiries_sent,
3644  hashed_key,
3645  &mcfs,
3647  );
3648 
3649  while (0 != num_keys--)
3650  {
3651  struct IBF_Key unsalted_key;
3652  unsalt_key (ibf_key,
3653  ntohl (msg->salt),
3654  &unsalted_key);
3656  unsalted_key);
3657  ibf_key++;
3658  }
3659  GNUNET_CADET_receive_done (op->channel);
3660 }

References check_valid_phase(), fail_union_operation(), GNUNET_break, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE, GNUNET_CRYPTO_hash_context_finish(), GNUNET_CRYPTO_hash_context_read(), GNUNET_CRYPTO_hash_context_start(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_malloc, GNUNET_OK, LOG, msg, MSG_CFS_RECEIVED, op, PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING, send_offers_for_key(), GNUNET_MessageHeader::size, and unsalt_key().

Here is the call graph for this function:

◆ send_missing_full_elements_iter()

static int send_missing_full_elements_iter ( void *  cls,
uint32_t  key,
void *  value 
)
static

Iterator over hash map entries, called to destroy the linked list of colliding ibf key entries.

Parameters
clsclosure
keycurrent key code
valuevalue in the hash map
Returns
GNUNET_YES if we should continue to iterate, GNUNET_NO if not.

Definition at line 3674 of file gnunet-service-setu.c.

3677 {
3678  struct Operation *op = cls;
3679  struct KeyEntry *ke = value;
3680  struct GNUNET_MQ_Envelope *ev;
3681  struct GNUNET_SETU_ElementMessage *emsg;
3682  struct ElementEntry *ee = ke->element;
3683 
3684  if (GNUNET_YES == ke->received)
3685  return GNUNET_YES;
3686 #if MEASURE_PERFORMANCE
3687  perf_store.element_full.received += 1;
3688 #endif
3689  ev = GNUNET_MQ_msg_extra (emsg,
3690  ee->element.size,
3692  GNUNET_memcpy (&emsg[1],
3693  ee->element.data,
3694  ee->element.size);
3695  emsg->element_type = htons (ee->element.element_type);
3696  GNUNET_MQ_send (op->mq,
3697  ev);
3698  return GNUNET_YES;
3699 }

References GNUNET_SET_Element::data, ElementEntry::element, KeyEntry::element, GNUNET_SET_Element::element_type, GNUNET_SETU_ElementMessage::element_type, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_YES, op, KeyEntry::received, GNUNET_SET_Element::size, and value.

Referenced by handle_union_p2p_full_done().

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

◆ check_union_p2p_request_full()

static int check_union_p2p_request_full ( void *  cls,
const struct TransmitFullMessage mh 
)
static

Handle a request for full set transmission.

Parameters
clsclosure, a set union operation
mhthe demand message

Definition at line 3709 of file gnunet-service-setu.c.

3711 {
3712  return GNUNET_OK;
3713 }

References GNUNET_OK.

◆ handle_union_p2p_request_full()

static void handle_union_p2p_request_full ( void *  cls,
const struct TransmitFullMessage msg 
)
static

Check that the message is received only in supported phase

Calculate avg element size if not initial sync

Definition at line 3717 of file gnunet-service-setu.c.

3719 {
3720  struct Operation *op = cls;
3721 
3725  uint8_t allowed_phases[] = {PHASE_EXPECT_IBF};
3726  if (GNUNET_OK !=
3727  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3728  {
3729  GNUNET_break (0);
3731  return;
3732  }
3733 
3734  op->remote_element_count = ntohl (msg->remote_set_size);
3735  op->remote_set_diff = ntohl (msg->remote_set_difference);
3736  op->local_set_diff = ntohl (msg->local_set_difference);
3737 
3738 
3740  {
3742  "PROTOCOL VIOLATION: Parameters transmitted from other peer do not satisfie byzantine "
3743  "criteria\n");
3744  GNUNET_break_op (0);
3746  return;
3747  }
3748 
3749 #if MEASURE_PERFORMANCE
3750  perf_store.request_full.received += 1;
3751 #endif
3752 
3754  "Received request for full set transmission\n");
3755 
3757  op->local_element_count = GNUNET_CONTAINER_multihashmap_size (
3758  op->set->content->elements);
3759  uint64_t avg_element_size = 0;
3760  if (0 < op->local_element_count)
3761  {
3762  op->total_elements_size_local = 0;
3763  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
3764  &
3766  op);
3767  avg_element_size = op->total_elements_size_local / op->local_element_count;
3768  }
3769 
3770  int mode_of_operation = estimate_best_mode_of_operation (avg_element_size,
3771  op->
3773  op->
3775  op->local_set_diff,
3776  op->remote_set_diff,
3777  op->
3779  op->
3782  {
3784  "PROTOCOL VIOLATION: Remote peer choose to request the full set first but correct mode would have been"
3785  " : %d\n", mode_of_operation);
3786  GNUNET_break_op (0);
3788  return;
3789  }
3790 
3791  // FIXME: we need to check that our set is larger than the
3792  // byzantine_lower_bound by some threshold
3793  send_full_set (op);
3794  GNUNET_CADET_receive_done (op->channel);
3795 }

References check_byzantine_bounds(), check_valid_phase(), determinate_avg_element_size_iterator(), estimate_best_mode_of_operation(), fail_union_operation(), FULL_SYNC_REMOTE_SENDING_FIRST, GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_OK, Operation::ibf_bucket_number_factor, Operation::local_element_count, LOG, Operation::mode_of_operation, msg, op, PHASE_EXPECT_IBF, Operation::remote_element_count, Operation::rtt_bandwidth_tradeoff, and send_full_set().

Here is the call graph for this function:

◆ handle_union_p2p_full_done()

static void handle_union_p2p_full_done ( void *  cls,
const struct GNUNET_MessageHeader mh 
)
static

Handle a "full done" message.

Parameters
clsclosure, a set union operation
mhthe demand message

Check that the message is received only in supported phase

Definition at line 3805 of file gnunet-service-setu.c.

3807 {
3808  struct Operation *op = cls;
3809 
3813  uint8_t allowed_phases[] = {PHASE_FULL_SENDING, PHASE_FULL_RECEIVING};
3814  if (GNUNET_OK !=
3815  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3816  {
3817  GNUNET_break (0);
3819  return;
3820  }
3821 
3822 #if MEASURE_PERFORMANCE
3823  perf_store.full_done.received += 1;
3824 #endif
3825 
3826  switch (op->phase)
3827  {
3828  case PHASE_FULL_RECEIVING:
3829  {
3830  struct GNUNET_MQ_Envelope *ev;
3831 
3832  if ((GNUNET_YES == op->byzantine) &&
3833  (op->received_total != op->remote_element_count) )
3834  {
3835  /* The other peer gave not enough elements before sending full done, there's something wrong. */
3837  "Other peer sent only %llu/%llu fresh elements, failing operation\n",
3838  (unsigned long long) op->received_total,
3839  (unsigned long long) op->remote_element_count);
3840  GNUNET_break_op (0);
3842  return;
3843  }
3844 
3846  "got FULL DONE, sending elements that other peer is missing\n");
3847 
3848  /* send all the elements that did not come from the remote peer */
3851  op);
3852 #if MEASURE_PERFORMANCE
3853  perf_store.full_done.sent += 1;
3854 #endif
3856  GNUNET_MQ_send (op->mq,
3857  ev);
3858  op->phase = PHASE_FINISHED;
3859  /* we now wait until the other peer sends us the OVER message*/
3860  }
3861  break;
3862 
3863  case PHASE_FULL_SENDING:
3864  {
3866  "got FULL DONE, finishing\n");
3867  /* We sent the full set, and got the response for that. We're done. */
3868  op->phase = PHASE_FINISHED;
3869  GNUNET_CADET_receive_done (op->channel);
3870  send_client_done (op);
3872  return;
3873  }
3874 
3875  default:
3877  "Handle full done phase is %u\n",
3878  (unsigned) op->phase);
3879  GNUNET_break_op (0);
3881  return;
3882  }
3883  GNUNET_CADET_receive_done (op->channel);
3884 }
static int send_missing_full_elements_iter(void *cls, uint32_t key, void *value)
Iterator over hash map entries, called to destroy the linked list of colliding ibf key entries.

References _GSS_operation_destroy2(), check_valid_phase(), fail_union_operation(), GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap32_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE, GNUNET_MQ_msg_header, GNUNET_MQ_send(), GNUNET_OK, GNUNET_YES, LOG, op, PHASE_FINISHED, PHASE_FULL_RECEIVING, PHASE_FULL_SENDING, send_client_done(), and send_missing_full_elements_iter().

Here is the call graph for this function:

◆ check_union_p2p_demand()

static int check_union_p2p_demand ( void *  cls,
const struct GNUNET_MessageHeader mh 
)
static

Check a demand by the other peer for elements based on a list of struct GNUNET_HashCodes.

Parameters
clsclosure, a set union operation
mhthe demand message
Returns
GNUNET_OK if mh is well-formed

Definition at line 3896 of file gnunet-service-setu.c.

3898 {
3899  struct Operation *op = cls;
3900  unsigned int num_hashes;
3901 
3902  (void) op;
3903  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
3904  / sizeof(struct GNUNET_HashCode);
3905  if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
3906  != num_hashes * sizeof(struct GNUNET_HashCode))
3907  {
3908  GNUNET_break_op (0);
3909  return GNUNET_SYSERR;
3910  }
3911  return GNUNET_OK;
3912 }

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, mh, and op.

◆ handle_union_p2p_demand()

static void handle_union_p2p_demand ( void *  cls,
const struct GNUNET_MessageHeader mh 
)
static

Handle a demand by the other peer for elements based on a list of struct GNUNET_HashCodes.

Parameters
clsclosure, a set union operation
mhthe demand message

Check that the message is received only in supported phase

Definition at line 3923 of file gnunet-service-setu.c.

3925 {
3926  struct Operation *op = cls;
3927  struct ElementEntry *ee;
3928  struct GNUNET_SETU_ElementMessage *emsg;
3929  const struct GNUNET_HashCode *hash;
3930  unsigned int num_hashes;
3931  struct GNUNET_MQ_Envelope *ev;
3932 
3936  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING,
3938  if (GNUNET_OK !=
3939  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3940  {
3941  GNUNET_break (0);
3943  return;
3944  }
3945 #if MEASURE_PERFORMANCE
3946  perf_store.demand.received += 1;
3947  perf_store.demand.received_var_bytes += (ntohs (mh->size) - sizeof(struct
3949 #endif
3950 
3951  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
3952  / sizeof(struct GNUNET_HashCode);
3953  for (hash = (const struct GNUNET_HashCode *) &mh[1];
3954  num_hashes > 0;
3955  hash++, num_hashes--)
3956  {
3957  ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
3958  hash);
3959  if (NULL == ee)
3960  {
3961  /* Demand for non-existing element. */
3962  GNUNET_break_op (0);
3964  return;
3965  }
3966 
3967  /* Save send demand message for message control */
3968  if (GNUNET_YES !=
3970  op->message_control_flow,
3972  &ee->element_hash,
3974  )
3975  {
3977  "Double demand message received found!\n");
3978  GNUNET_break (0);
3980  return;
3981  }
3982  ;
3983 
3984  /* Mark element to be expected to received */
3985  if (GNUNET_YES !=
3987  op->message_control_flow,
3988  MSG_CFS_SENT,
3989  &ee->element_hash,
3991  )
3992  {
3994  "Double element message sent found!\n");
3995  GNUNET_break (0);
3997  return;
3998  }
4000  {
4001  /* Probably confused lazily copied sets. */
4002  GNUNET_break_op (0);
4004  return;
4005  }
4006 #if MEASURE_PERFORMANCE
4007  perf_store.element.sent += 1;
4008  perf_store.element.sent_var_bytes += ee->element.size;
4009 #endif
4010  ev = GNUNET_MQ_msg_extra (emsg,
4011  ee->element.size,
4013  GNUNET_memcpy (&emsg[1],
4014  ee->element.data,
4015  ee->element.size);
4016  emsg->reserved = htons (0);
4017  emsg->element_type = htons (ee->element.element_type);
4019  "[OP %p] Sending demanded element (size %u, hash %s) to peer\n",
4020  op,
4021  (unsigned int) ee->element.size,
4022  GNUNET_h2s (&ee->element_hash));
4023  GNUNET_MQ_send (op->mq, ev);
4025  "# exchanged elements",
4026  1,
4027  GNUNET_NO);
4028  if (op->symmetric)
4030  &ee->element,
4032  }
4033  GNUNET_CADET_receive_done (op->channel);
4034  maybe_finish (op);
4035 }
#define GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS
Actual set elements.
@ GNUNET_SETU_STATUS_ADD_REMOTE
Element should be added to the result set of the remote peer, i.e.
uint16_t reserved
For alignment, always zero.
Definition: setu.h:340

References _GSS_is_element_of_operation(), _GSS_statistics, check_valid_phase(), GNUNET_SET_Element::data, DEMAND_MESSAGE, ElementEntry::element, ElementEntry::element_hash, ELEMENT_MESSAGE, GNUNET_SET_Element::element_type, GNUNET_SETU_ElementMessage::element_type, fail_union_operation(), GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_h2s(), GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_OK, GNUNET_SETU_STATUS_ADD_REMOTE, GNUNET_STATISTICS_update(), GNUNET_YES, LOG, maybe_finish(), mh, MSG_CFS_RECEIVED, MSG_CFS_SENT, op, PHASE_ACTIVE_DECODING, PHASE_FINISH_WAITING, PHASE_PASSIVE_DECODING, GNUNET_SETU_ElementMessage::reserved, send_client_element(), GNUNET_SET_Element::size, and update_message_control_flow().

Here is the call graph for this function:

◆ check_union_p2p_offer()

static int check_union_p2p_offer ( void *  cls,
const struct GNUNET_MessageHeader mh 
)
static

Check offer (of struct GNUNET_HashCodes).

Parameters
clsthe union operation
mhthe message
Returns
GNUNET_OK if mh is well-formed

Definition at line 4046 of file gnunet-service-setu.c.

4048 {
4049  struct Operation *op = cls;
4050  unsigned int num_hashes;
4051 
4052  /* look up elements and send them */
4053  if ((op->phase != PHASE_PASSIVE_DECODING) &&
4054  (op->phase != PHASE_ACTIVE_DECODING))
4055  {
4056  GNUNET_break_op (0);
4057  return GNUNET_SYSERR;
4058  }
4059  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
4060  / sizeof(struct GNUNET_HashCode);
4061  if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader)) !=
4062  num_hashes * sizeof(struct GNUNET_HashCode))
4063  {
4064  GNUNET_break_op (0);
4065  return GNUNET_SYSERR;
4066  }
4067  return GNUNET_OK;
4068 }

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, mh, op, PHASE_ACTIVE_DECODING, and PHASE_PASSIVE_DECODING.

◆ handle_union_p2p_offer()

static void handle_union_p2p_offer ( void *  cls,
const struct GNUNET_MessageHeader mh 
)
static

Handle offers (of struct GNUNET_HashCodes) and respond with demands (of struct GNUNET_HashCodes).

Parameters
clsthe union operation
mhthe message

Check that the message is received only in supported phase

Definition at line 4079 of file gnunet-service-setu.c.

4081 {
4082  struct Operation *op = cls;
4083  const struct GNUNET_HashCode *hash;
4084  unsigned int num_hashes;
4088  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING};
4089  if (GNUNET_OK !=
4090  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
4091  {
4092  GNUNET_break (0);
4094  return;
4095  }
4096 
4097 #if MEASURE_PERFORMANCE
4098  perf_store.offer.received += 1;
4099  perf_store.offer.received_var_bytes += (ntohs (mh->size) - sizeof(struct
4101 #endif
4102 
4103  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
4104  / sizeof(struct GNUNET_HashCode);
4105  for (hash = (const struct GNUNET_HashCode *) &mh[1];
4106  num_hashes > 0;
4107  hash++, num_hashes--)
4108  {
4109  struct ElementEntry *ee;
4110  struct GNUNET_MessageHeader *demands;
4111  struct GNUNET_MQ_Envelope *ev;
4112 
4113  ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
4114  hash);
4115  if (NULL != ee)
4117  continue;
4118 
4119  if (GNUNET_YES ==
4120  GNUNET_CONTAINER_multihashmap_contains (op->demanded_hashes,
4121  hash))
4122  {
4124  "Skipped sending duplicate demand\n");
4125  continue;
4126  }
4127 
4130  op->demanded_hashes,
4131  hash,
4132  NULL,
4134 
4136  "[OP %p] Requesting element (hash %s)\n",
4137  op, GNUNET_h2s (hash));
4138 
4139 #if MEASURE_PERFORMANCE
4140  perf_store.demand.sent += 1;
4141  perf_store.demand.sent_var_bytes += sizeof(struct GNUNET_HashCode);
4142 #endif
4143  /* Save send demand message for message control */
4144  if (GNUNET_YES !=
4146  op->message_control_flow,
4147  MSG_CFS_SENT,
4148  hash,
4149  DEMAND_MESSAGE))
4150  {
4152  "Double demand message sent found!\n");
4153  GNUNET_break (0);
4155  return;
4156  }
4157 
4158  /* Mark offer as received received */
4159  if (GNUNET_YES !=
4161  op->message_control_flow,
4163  hash,
4164  OFFER_MESSAGE))
4165  {
4167  "Double offer message received found!\n");
4168  GNUNET_break (0);
4170  return;
4171  }
4172  /* Mark element to be expected to received */
4173  if (GNUNET_YES !=
4175  op->message_control_flow,
4177  hash,
4178  ELEMENT_MESSAGE))
4179  {
4181  "Element already expected!\n");
4182  GNUNET_break (0);
4184  return;
4185  }
4186  ev = GNUNET_MQ_msg_header_extra (demands,
4187  sizeof(struct GNUNET_HashCode),
4189  GNUNET_memcpy (&demands[1],
4190  hash,
4191  sizeof(struct GNUNET_HashCode));
4192  GNUNET_MQ_send (op->mq, ev);
4193  }
4194  GNUNET_CADET_receive_done (op->channel);
4195 }
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_FAST
, ' bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE...
#define GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND
Demand the whole element from the other peer, given only the hash code.

References _GSS_is_element_of_operation(), check_valid_phase(), DEMAND_MESSAGE, ELEMENT_MESSAGE, fail_union_operation(), GNUNET_assert, GNUNET_break, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_h2s(), GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND, GNUNET_MQ_msg_header_extra, GNUNET_MQ_send(), GNUNET_OK, GNUNET_YES, LOG, mh, MSG_CFS_EXPECTED, MSG_CFS_RECEIVED, MSG_CFS_SENT, OFFER_MESSAGE, op, PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING, and update_message_control_flow().

Here is the call graph for this function:

◆ handle_union_p2p_done()

static void handle_union_p2p_done ( void *  cls,
const struct GNUNET_MessageHeader mh 
)
static

Handle a done message from a remote peer.

Parameters
clsthe union operation
mhthe message

Check that the message is received only in supported phase

Definition at line 4205 of file gnunet-service-setu.c.

4207 {
4208  struct Operation *op = cls;
4209 
4213  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING};
4214  if (GNUNET_OK !=
4215  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
4216  {
4217  GNUNET_break (0);
4219  return;
4220  }
4221 
4222  if (op->active_passive_switch_required)
4223  {
4225  "PROTOCOL VIOLATION: Received done but role change is necessary\n");
4226  GNUNET_break (0);
4228  return;
4229  }
4230 
4231 #if MEASURE_PERFORMANCE
4232  perf_store.done.received += 1;
4233 #endif
4234  switch (op->phase)
4235  {
4237  /* We got all requests, but still have to send our elements in response. */
4238  op->phase = PHASE_FINISH_WAITING;
4240  "got DONE (as passive partner), waiting for our demands to be satisfied\n");
4241  /* The active peer is done sending offers
4242  * and inquiries. This means that all
4243  * our responses to that (demands and offers)
4244  * must be in flight (queued or in mesh).
4245  *
4246  * We should notify the active peer once
4247  * all our demands are satisfied, so that the active
4248  * peer can quit if we gave it everything.
4249  */GNUNET_CADET_receive_done (op->channel);
4250  maybe_finish (op);
4251  return;
4252  case PHASE_ACTIVE_DECODING:
4254  "got DONE (as active partner), waiting to finish\n");
4255  /* All demands of the other peer are satisfied,
4256  * and we processed all offers, thus we know
4257  * exactly what our demands must be.
4258  *
4259  * We'll close the channel
4260  * to the other peer once our demands are met.
4261  */op->phase = PHASE_FINISH_CLOSING;
4262  GNUNET_CADET_receive_done (op->channel);
4263  maybe_finish (op);
4264  return;
4265  default:
4266  GNUNET_break_op (0);
4268  return;
4269  }
4270 }

References check_valid_phase(), fail_union_operation(), GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_OK, LOG, maybe_finish(), op, PHASE_ACTIVE_DECODING, PHASE_FINISH_CLOSING, PHASE_FINISH_WAITING, and PHASE_PASSIVE_DECODING.

Here is the call graph for this function:

◆ handle_union_p2p_over()

static void handle_union_p2p_over ( void *  cls,
const struct GNUNET_MessageHeader mh 
)
static

Handle a over message from a remote peer.

Parameters
clsthe union operation
mhthe message

Definition at line 4280 of file gnunet-service-setu.c.

4282 {
4283 #if MEASURE_PERFORMANCE
4284  perf_store.over.received += 1;
4285 #endif
4286  send_client_done (cls);
4287 }

References send_client_done().

Here is the call graph for this function:

◆ get_incoming()

static struct Operation* get_incoming ( uint32_t  id)
static

Get the incoming socket associated with the given id.

Parameters
listenerthe listener to look in
idid to look for
Returns
the incoming socket associated with the id, or NULL if there is none

Definition at line 4299 of file gnunet-service-setu.c.

4300 {
4301  for (struct Listener *listener = listener_head;
4302  NULL != listener;
4303  listener = listener->next)
4304  {
4305  for (struct Operation *op = listener->op_head;
4306  NULL != op;
4307  op = op->next)
4308  if (op->suggest_id == id)
4309  return op;
4310  }
4311  return NULL;
4312 }
static struct Listener * listener_head
Listeners are held in a doubly linked list.
struct GNUNET_ARM_Operation * next
This is a doubly-linked list.
Definition: arm_api.c:45
struct Listener * next
Listeners are held in a doubly linked list.

References Operation::listener, listener_head, GNUNET_ARM_Operation::next, Listener::next, op, and Listener::op_head.

Referenced by handle_client_accept(), and handle_client_reject().

Here is the caller graph for this function:

◆ client_connect_cb()

static void* client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client c,
struct GNUNET_MQ_Handle mq 
)
static

Callback called when a client connects to the service.

Parameters
clsclosure for the service
cthe new client that connected to the service
mqthe message queue used to send messages to the client
Returns
struct ClientState

Definition at line 4324 of file gnunet-service-setu.c.

4327 {
4328  struct ClientState *cs;
4329 
4330  num_clients++;
4331  cs = GNUNET_new (struct ClientState);
4332  cs->client = c;
4333  cs->mq = mq;
4334  return cs;
4335 }
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
static unsigned int num_clients
Number of active clients.
State we keep per client.
struct GNUNET_MQ_Handle * mq
MQ to talk to client.
struct GNUNET_SERVICE_Client * client
Client this is about.

References ClientState::client, GNUNET_new, mq, ClientState::mq, and num_clients.

◆ destroy_elements_iterator()

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

Iterator over hash map entries to free element entries.

Parameters
clsclosure
keycurrent key code
valuea struct ElementEntry * to be free'd
Returns
GNUNET_YES (continue to iterate)

Definition at line 4347 of file gnunet-service-setu.c.

4350 {
4351  struct ElementEntry *ee = value;
4352 
4353  GNUNET_free (ee);
4354  return GNUNET_YES;
4355 }

References GNUNET_free, GNUNET_YES, and value.

Referenced by client_disconnect_cb().

Here is the caller graph for this function:

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
void *  internal_cls 
)
static

Clean up after a client has disconnected.

Parameters
clsclosure, unused
clientthe client to clean up after
internal_clsthe struct ClientState

Definition at line 4366 of file gnunet-service-setu.c.

4369 {
4370  struct ClientState *cs = internal_cls;
4371  struct Operation *op;
4372  struct Listener *listener;
4373  struct Set *set;
4374 
4376  "Client disconnected, cleaning up\n");
4377  if (NULL != (set = cs->set))
4378  {
4379  struct SetContent *content = set->content;
4380 
4382  "Destroying client's set\n");
4383  /* Destroy pending set operations */
4384  while (NULL != set->ops_head)
4386 
4387  /* Destroy operation-specific state */
4388  if (NULL != set->se)
4389  {
4391  set->se = NULL;
4392  }
4393  /* free set content (or at least decrement RC) */
4394  set->content = NULL;
4395  GNUNET_assert (0 != content->refcount);
4396  content->refcount--;
4397  if (0 == content->refcount)
4398  {
4399  GNUNET_assert (NULL != content->elements);
4402  NULL);
4404  content->elements = NULL;
4405  GNUNET_free (content);
4406  }
4407  GNUNET_free (set);
4408  }
4409 
4410  if (NULL != (listener = cs->listener))
4411  {
4413  "Destroying client's listener\n");
4414  GNUNET_CADET_close_port (listener->open_port);
4415  listener->open_port = NULL;
4416  while (NULL != (op = listener->op_head))
4417  {
4419  "Destroying incoming operation `%u' from peer `%s'\n",
4420  (unsigned int) op->client_request_id,
4421  GNUNET_i2s (&op->peer));
4422  incoming_destroy (op);
4423  }
4425  listener_tail,
4426  listener);
4427  GNUNET_free (listener);
4428  }
4429  GNUNET_free (cs);
4430  num_clients--;
4431  if ( (GNUNET_YES == in_shutdown) &&
4432  (0 == num_clients) )
4433  {
4434  if (NULL != cadet)
4435  {
4437  cadet = NULL;
4438  }
4439  }
4440 }
static struct GNUNET_CADET_Handle * cadet
Handle to the cadet service, used to listen for and connect to remote peers.
static int in_shutdown
Are we in shutdown? if GNUNET_YES and the number of clients drops to zero, disconnect from CADET.
static int destroy_elements_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over hash map entries to free element entries.
static struct Listener * listener_tail
Listeners are held in a doubly linked list.
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:774
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port.
Definition: cadet_api.c:801
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
struct Listener * listener
Listener, if associated with the client, otherwise NULL.
struct Set * set
Set, if associated with the client, otherwise NULL.
struct GNUNET_CADET_Port * open_port
The port we are listening on with CADET.
SetContent stores the actual set elements, which may be shared by multiple generations derived from o...
struct GNUNET_CONTAINER_MultiHashMap * elements
Maps struct GNUNET_HashCode * to struct ElementEntry *.
unsigned int refcount
Number of references to the content.
struct MultiStrataEstimator * se
The strata estimator is only generated once for each set.
struct SetContent * content
Content, possibly shared by multiple sets, and thus reference counted.
struct ClientState * cs
Client that owns the set.

References _GSS_operation_destroy(), cadet, Set::content, Set::cs, destroy_elements_iterator(), SetContent::elements, GNUNET_assert, GNUNET_CADET_close_port(), GNUNET_CADET_disconnect(), GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_YES, in_shutdown, incoming_destroy(), ClientState::listener, listener_head, listener_tail, num_clients, op, Listener::op_head, Listener::open_port, Set::ops_head, SetContent::refcount, Set::se, ClientState::set, and strata_estimator_destroy().

Here is the call graph for this function:

◆ check_incoming_msg()

static int check_incoming_msg ( void *  cls,
const struct OperationRequestMessage msg 
)
static

Check a request for a set operation from another peer.

Parameters
clsthe operation state
msgthe received message
Returns
GNUNET_OK if the channel should be kept alive, GNUNET_SYSERR to destroy the channel

Definition at line 4452 of file gnunet-service-setu.c.

4454 {
4455  struct Operation *op = cls;
4456  struct Listener *listener = op->listener;
4457  const struct GNUNET_MessageHeader *nested_context;
4458 
4459  /* double operation request */
4460  if (0 != op->suggest_id)
4461  {
4462  GNUNET_break_op (0);
4463  return GNUNET_SYSERR;
4464  }
4465  /* This should be equivalent to the previous condition, but can't hurt to check twice */
4466  if (NULL == listener)
4467  {
4468  GNUNET_break (0);
4469  return GNUNET_SYSERR;
4470  }
4471  nested_context = GNUNET_MQ_extract_nested_mh (msg);
4472  if ((NULL != nested_context) &&
4473  (ntohs (nested_context->size) > GNUNET_SETU_CONTEXT_MESSAGE_MAX_SIZE))
4474  {
4475  GNUNET_break_op (0);
4476  return