GNUnet 0.21.1
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
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 (...
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,...

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

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 1191 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 GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_NO, GNUNET_YES, LOG, op, and phase.

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 {
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.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_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.
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:366
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:390
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
Definition: crypto_hash.c:350

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);
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:78
#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 1556 of file gnunet-service-setu.c.

1559{
1561 return GNUNET_YES;
1562}

References GNUNET_free, GNUNET_YES, and value.

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);
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;
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 ibf_destroy(struct InvertibleBloomFilter *ibf)
Destroy all resources associated with the invertible bloom filter.
Definition: ibf.c:404
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,...)
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;
1709 }
1710 if (NULL != op->listener)
1711 {
1713 return;
1714 }
1715 if (NULL != op->set)
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:981
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 1849 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.
Definition: gnunet-scrypt.c:34
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

References GNUNET_assert, GNUNET_CRYPTO_kdf(), GNUNET_OK, key, and salt.

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

Here is the call graph for this function:
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_FS_Handle * ctx
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:221
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
Final status code.
Definition: gnunet-arm.c:94
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
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,
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}
void ibf_insert(struct InvertibleBloomFilter *ibf, struct IBF_Key key)
Insert a key into an IBF.
Definition: ibf.c:168
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).

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;
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}
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.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.

References GNUNET_assert, GNUNET_CONTAINER_multihashmap32_create(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_size(), init_key_to_element_iterator(), 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}
struct InvertibleBloomFilter * ibf_create(uint32_t size, uint8_t hash_num)
Create an invertible bloom filter.
Definition: ibf.c:80
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

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 !=
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
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}
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
static char * name
Name (label) of the records to list.
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:63
#define GNUNET_MESSAGE_TYPE_SETU_P2P_IBF
Invertible bloom filter.
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
Handle to identity lookup.
#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:87
#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...
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.
#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.
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, 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 <%"PRIu64"> of element: %u\n",
2436 op->byzantine_upper_bound,
2437 op->remote_element_count);
2439 return;
2440 }
2441
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)
Indicate readiness to receive the next message on a channel.
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, 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,
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,
2676 &ke->element->element_hash,
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,
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:99
#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. */
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}
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
static char * res
Currently read line or NULL on EOF.
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.
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)
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
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)
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 !=
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}
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
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.

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}
static int status
The program status; 0 for success.
Definition: gnunet-nse.c:39
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);
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;
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 void maybe_finish(struct Operation *op)
Tests if the operation is finished, and if so notify.
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 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, 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, 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 {
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);
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,
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 ==
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,
4148 hash,
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,
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,
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;
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, Listener::next, GNUNET_ARM_Operation::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");
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));
4423 }
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 GNUNET_SYSERR;
4477 }
4478 return GNUNET_OK;
4479}
#define GNUNET_MQ_extract_nested_mh(var)
Return a pointer to the message at the end of the given message.
#define GNUNET_SETU_CONTEXT_MESSAGE_MAX_SIZE
Maximum size of a context message for set operation requests.

References GNUNET_break, GNUNET_break_op, GNUNET_MQ_extract_nested_mh, GNUNET_OK, GNUNET_SETU_CONTEXT_MESSAGE_MAX_SIZE, GNUNET_SYSERR, msg, op, and GNUNET_MessageHeader::size.

◆ handle_incoming_msg()

static void handle_incoming_msg ( void *  cls,
const struct OperationRequestMessage msg 
)
static

Handle a request for a set operation from another peer.

Checks if we have a listener waiting for such a request (and in that case initiates asking the listener about accepting the connection). If no listener is waiting, we queue the operation request in hope that a listener shows up soon (before timeout).

This msg is expected as the first and only msg handled through the non-operation bound virtual table, acceptance of this operation replaces our virtual table and subsequent msgs would be routed differently (as we then know what type of operation this is).

Parameters
clsthe operation state
msgthe received message

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

4500{
4501 struct Operation *op = cls;
4502 struct Listener *listener = op->listener;
4503 const struct GNUNET_MessageHeader *nested_context;
4504 struct GNUNET_MQ_Envelope *env;
4505 struct GNUNET_SETU_RequestMessage *cmsg;
4506
4507 nested_context = GNUNET_MQ_extract_nested_mh (msg);
4508 /* Make a copy of the nested_context (application-specific context
4509 information that is opaque to set) so we can pass it to the
4510 listener later on */
4511 if (NULL != nested_context)
4512 op->context_msg = GNUNET_copy_message (nested_context);
4513 op->remote_element_count = ntohl (msg->element_count);
4514 GNUNET_log (
4516 "Received P2P operation request (port %s) for active listener\n",
4517 GNUNET_h2s (&op->listener->app_id));
4518 GNUNET_assert (0 == op->suggest_id);
4519 if (0 == suggest_id)
4520 suggest_id++;
4521 op->suggest_id = suggest_id++;
4522 GNUNET_assert (NULL != op->timeout_task);
4523 GNUNET_SCHEDULER_cancel (op->timeout_task);
4524 op->timeout_task = NULL;
4527 op->context_msg);
4528 GNUNET_log (
4530 "Suggesting incoming request with accept id %u to listener %p of client %p\n",
4531 op->suggest_id,
4532 listener,
4533 listener->cs);
4534 cmsg->accept_id = htonl (op->suggest_id);
4535 cmsg->peer_id = op->peer;
4536 GNUNET_MQ_send (listener->cs->mq,
4537 env);
4538 /* NOTE: GNUNET_CADET_receive_done() will be called in
4539 #handle_client_accept() */
4540}
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static uint32_t suggest_id
Counter for allocating unique IDs for clients, used to identify incoming operation requests from remo...
struct GNUNET_MessageHeader * GNUNET_copy_message(const struct GNUNET_MessageHeader *msg)
Create a copy of the given message.
#define GNUNET_MQ_msg_nested_mh(mvar, type, mh)
Allocate a GNUNET_MQ_Envelope, and append a payload message after the given message struct.
#define GNUNET_MESSAGE_TYPE_SETU_REQUEST
Notify the client of an incoming request from a remote peer.
A request for an operation with another client.
Definition: setu.h:175
struct GNUNET_PeerIdentity peer_id
Identity of the requesting peer.
Definition: setu.h:190
uint32_t accept_id
ID of the to identify the request when accepting or rejecting it.
Definition: setu.h:185
struct ClientState * cs
Client that owns the listener.

References GNUNET_SETU_RequestMessage::accept_id, Listener::cs, env, GNUNET_assert, GNUNET_copy_message(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_SETU_REQUEST, GNUNET_MQ_extract_nested_mh, GNUNET_MQ_msg_nested_mh, GNUNET_MQ_send(), GNUNET_SCHEDULER_cancel(), ClientState::mq, msg, op, GNUNET_SETU_RequestMessage::peer_id, and suggest_id.

Here is the call graph for this function:

◆ handle_client_create_set()

static void handle_client_create_set ( void *  cls,
const struct GNUNET_SETU_CreateMessage msg 
)
static

Called when a client wants to create a new set.

This is typically the first request from a client, and includes the type of set operation to be performed.

Parameters
clsclient that sent the message
mmessage sent by the client

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

4554{
4555 struct ClientState *cs = cls;
4556 struct Set *set;
4557
4559 "Client created new set for union operation\n");
4560 if (NULL != cs->set)
4561 {
4562 /* There can only be one set per client */
4563 GNUNET_break (0);
4565 return;
4566 }
4567 set = GNUNET_new (struct Set);
4568 {
4569 struct MultiStrataEstimator *se;
4570
4574 if (NULL == se)
4575 {
4577 "Failed to allocate strata estimator\n");
4578 GNUNET_free (set);
4580 return;
4581 }
4582 set->se = se;
4583 }
4584 set->content = GNUNET_new (struct SetContent);
4585 set->content->refcount = 1;
4587 GNUNET_YES);
4588 set->cs = cs;
4589 cs->set = set;
4591}
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2484
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2455

References ClientState::client, Set::content, Set::cs, SetContent::elements, GNUNET_break, GNUNET_CONTAINER_multihashmap_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_YES, SetContent::refcount, Set::se, SE_IBF_HASH_NUM, SE_IBFS_TOTAL_SIZE, SE_STRATA_COUNT, ClientState::set, and strata_estimator_create().

Here is the call graph for this function:

◆ incoming_timeout_cb()

static void incoming_timeout_cb ( void *  cls)
static

Timeout happens iff:

Parameters
clschannel context
tccontext information (why was this task triggered now)

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

4605{
4606 struct Operation *op = cls;
4607
4608 op->timeout_task = NULL;
4610 "Remote peer's incoming request timed out\n");
4612}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, incoming_destroy(), and op.

Referenced by channel_new_cb().

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

◆ channel_new_cb()

static void * channel_new_cb ( void *  cls,
struct GNUNET_CADET_Channel channel,
const struct GNUNET_PeerIdentity source 
)
static

Method called whenever another peer has added us to a channel the other peer initiated.

Only called (once) upon reception of data from a channel we listen on.

The channel context represents the operation itself and gets added to a DLL, from where it gets looked up when our local listener client responds to a proposed/suggested operation or connects and associates with this operation.

Parameters
clsclosure
channelnew handle to the channel
sourcepeer that started the channel
Returns
initial channel context for the channel returns NULL on error

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

4635{
4636 struct Listener *listener = cls;
4637 struct Operation *op;
4638
4640 "New incoming channel\n");
4641 op = GNUNET_new (struct Operation);
4642 op->listener = listener;
4643 op->peer = *