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

Variables

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

Detailed Description

set union operation

Author
Florian Dold
Christian Grothoff
Elias Summermatter

Definition in file gnunet-service-setu.c.

Macro Definition Documentation

◆ LOG

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

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

◆ INCOMING_CHANNEL_TIMEOUT

#define INCOMING_CHANNEL_TIMEOUT   GNUNET_TIME_UNIT_MINUTES

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

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

◆ SE_STRATA_COUNT

#define SE_STRATA_COUNT   32

Number of IBFs in a strata estimator.

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

◆ SE_IBFS_TOTAL_SIZE

#define SE_IBFS_TOTAL_SIZE   632

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

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

◆ SE_IBF_HASH_NUM

#define SE_IBF_HASH_NUM   3

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

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

◆ MAX_BUCKETS_PER_MESSAGE

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

Number of buckets that can be transmitted in one message.

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

◆ MAX_IBF_SIZE

#define MAX_IBF_SIZE   1048576

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

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

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

◆ IBF_MIN_SIZE

#define IBF_MIN_SIZE   37

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

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

◆ DIFFERENTIAL_RTT_MEAN

#define DIFFERENTIAL_RTT_MEAN   3.65145

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

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

◆ SECURITY_LEVEL

#define SECURITY_LEVEL   80

Security level used for byzantine checks (2^80)

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

◆ PROBABILITY_FOR_NEW_ROUND

#define PROBABILITY_FOR_NEW_ROUND   0.15

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

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

◆ MEASURE_PERFORMANCE

#define MEASURE_PERFORMANCE   0

Measure the performance in a csv.

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

Enumeration Type Documentation

◆ UnionOperationPhase

Current phase we are in for a union operation.

Enumerator
PHASE_EXPECT_SE 

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

PHASE_EXPECT_IBF 

We sent the strata estimator, and expect an IBF.

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

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

After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS

PHASE_EXPECT_IBF_CONT 

Continuation for multi part IBFs.

PHASE_INVENTORY_ACTIVE 

We are decoding an IBF.

PHASE_INVENTORY_PASSIVE 

The other peer is decoding the IBF we just sent.

PHASE_FINISH_CLOSING 

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

PHASE_FINISH_WAITING 

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

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

PHASE_DONE 

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

PHASE_FULL_SENDING 

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

PHASE_EXPECT_SE 

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

PHASE_EXPECT_IBF 

We sent the strata estimator, and expect an IBF.

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

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

After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS

PHASE_EXPECT_IBF_LAST 

Continuation for multi part IBFs.

PHASE_ACTIVE_DECODING 

We are decoding an IBF.

PHASE_PASSIVE_DECODING 

The other peer is decoding the IBF we just sent.

PHASE_FINISH_CLOSING 

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

PHASE_FINISH_WAITING 

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

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

PHASE_FINISHED 

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

PHASE_FULL_SENDING 

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

PHASE_FULL_RECEIVING 

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

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

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

◆ MODE_OF_OPERATION

Different modes of operations.

Enumerator
DIFFERENTIAL_SYNC 

Mode just synchronizes the difference between sets.

FULL_SYNC_LOCAL_SENDING_FIRST 

Mode send full set sending local set first.

FULL_SYNC_REMOTE_SENDING_FIRST 

Mode request full set from remote peer.

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

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

◆ MESSAGE_CONTROL_FLOW_STATE

Different states to control the messages flow in differential mode.

Enumerator
MSG_CFS_UNINITIALIZED 

Initial message state.

MSG_CFS_SENT 

Track that a message has been sent.

MSG_CFS_EXPECTED 

Track that receiving this message is expected.

MSG_CFS_RECEIVED 

Track that message has been received.

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

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

◆ MESSAGE_TYPE

Message types to track in message control flow.

Enumerator
OFFER_MESSAGE 

Offer message type.

DEMAND_MESSAGE 

Demand message type.

ELEMENT_MESSAGE 

Element message type.

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

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

Function Documentation

◆ estimate_best_mode_of_operation()

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

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

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

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

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

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

Here is the caller graph for this function:

◆ check_valid_phase()

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

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

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

Iterate over allowed phases

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

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

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

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

Here is the caller graph for this function:

◆ update_message_control_flow()

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

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

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

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

Check logic for forbidden messages

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

Set state of message

Check if state is allowed

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

1230 {
1231  struct messageControlFlowElement *cfe = NULL;
1232  enum MESSAGE_CONTROL_FLOW_STATE *mcfs;
1233 
1238  cfe = GNUNET_CONTAINER_multihashmap_get (hash_map, hash_code);
1239  if ((ELEMENT_MESSAGE == mt) && (cfe != NULL))
1240  {
1241  if ((new_mcfs != MSG_CFS_SENT) && (MSG_CFS_RECEIVED != cfe->offer))
1242  {
1244  "Received an element without sent offer!\n");
1245  return GNUNET_NO;
1246  }
1247  /* Check that only requested elements are received! */
1248  if ((ELEMENT_MESSAGE == mt) && (new_mcfs != MSG_CFS_SENT) && (cfe->demand !=
1249  MSG_CFS_SENT))
1250  {
1252  "Received an element that was not demanded\n");
1253  return GNUNET_NO;
1254  }
1255  }
1256 
1261  if (NULL == cfe)
1262  {
1263  cfe = GNUNET_new (struct messageControlFlowElement);
1264  if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (hash_map, hash_code,
1265  cfe,
1267  {
1268  GNUNET_free (cfe);
1269  return GNUNET_SYSERR;
1270  }
1271  }
1272 
1277  if (OFFER_MESSAGE == mt)
1278  {
1279  mcfs = &cfe->offer;
1280  }
1281  else if (DEMAND_MESSAGE == mt)
1282  {
1283  mcfs = &cfe->demand;
1284  }
1285  else if (ELEMENT_MESSAGE == mt)
1286  {
1287  mcfs = &cfe->element;
1288  }
1289  else
1290  {
1291  return GNUNET_SYSERR;
1292  }
1293 
1298  if (new_mcfs <= *mcfs)
1299  {
1300  return GNUNET_NO;
1301  }
1302 
1303  *mcfs = new_mcfs;
1304  return GNUNET_YES;
1305 }
MESSAGE_CONTROL_FLOW_STATE
Different states to control the messages flow in differential mode.
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#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.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
Definition: crypto_hash.c:321
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:340
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:364
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
If a value with the given key exists, replace it.

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

Referenced by send_full_set().

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

◆ destroy_key_to_element_iter()

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

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

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

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

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

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

Referenced by _GSS_operation_destroy().

Here is the caller graph for this function:

◆ send_client_done()

static void send_client_done ( void *  cls)
static

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

Parameters
clsoperation to destroy

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

1481 {
1482  struct Operation *op = cls;
1483  struct GNUNET_MQ_Envelope *ev;
1484  struct GNUNET_SETU_ResultMessage *rm;
1485 
1486  if (GNUNET_YES == op->client_done_sent)
1487  return;
1488  if (PHASE_FINISHED != op->phase)
1489  {
1491  "Union operation failed\n");
1493  "# Union operations failed",
1494  1,
1495  GNUNET_NO);
1498  rm->request_id = htonl (op->client_request_id);
1499  rm->element_type = htons (0);
1500  GNUNET_MQ_send (op->set->cs->mq,
1501  ev);
1502  return;
1503  }
1504 
1505  op->client_done_sent = GNUNET_YES;
1506 
1508  "# Union operations succeeded",
1509  1,
1510  GNUNET_NO);
1512  "Signalling client that union operation is done\n");
1513  ev = GNUNET_MQ_msg (rm,
1515  rm->request_id = htonl (op->client_request_id);
1516  rm->result_status = htons (GNUNET_SETU_STATUS_DONE);
1517  rm->element_type = htons (0);
1519  op->key_to_element));
1520  GNUNET_MQ_send (op->set->cs->mq,
1521  ev);
1522 }
static struct GNUNET_STATISTICS_Handle * _GSS_statistics
Statistics handle.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:36
unsigned int GNUNET_CONTAINER_multihashmap32_size(const struct GNUNET_CONTAINER_MultiHashMap32 *map)
Get the number of key-value pairs in the map.
@ 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:355
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
#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
Definition: gnunet_common.h:95

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:

◆ _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 1570 of file gnunet-service-setu.c.

1571 {
1572  struct Set *set = op->set;
1573  struct GNUNET_CADET_Channel *channel;
1574 
1576  "Destroying union operation %p\n",
1577  op);
1578  GNUNET_assert (NULL == op->listener);
1579  /* check if the op was canceled twice */
1580  if (NULL != op->remote_ibf)
1581  {
1582  ibf_destroy (op->remote_ibf);
1583  op->remote_ibf = NULL;
1584  }
1585  if (NULL != op->demanded_hashes)
1586  {
1587  GNUNET_CONTAINER_multihashmap_destroy (op->demanded_hashes);
1588  op->demanded_hashes = NULL;
1589  }
1590  if (NULL != op->local_ibf)
1591  {
1592  ibf_destroy (op->local_ibf);
1593  op->local_ibf = NULL;
1594  }
1595  if (NULL != op->se)
1596  {
1598  op->se = NULL;
1599  }
1600  if (NULL != op->key_to_element)
1601  {
1604  NULL);
1605  GNUNET_CONTAINER_multihashmap32_destroy (op->key_to_element);
1606  op->key_to_element = NULL;
1607  }
1608  if (NULL != set)
1609  {
1611  set->ops_tail,
1612  op);
1613  op->set = NULL;
1614  }
1615  if (NULL != op->context_msg)
1616  {
1617  GNUNET_free (op->context_msg);
1618  op->context_msg = NULL;
1619  }
1620  if (NULL != (channel = op->channel))
1621  {
1622  /* This will free op; called conditionally as this helper function
1623  is also called from within the channel disconnect handler. */
1624  op->channel = NULL;
1625  GNUNET_CADET_channel_destroy (channel);
1626  }
1627  /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL,
1628  * there was a channel end handler that will free 'op' on the call stack. */
1629 }
void strata_estimator_destroy(struct StrataEstimator *se)
Destroy a strata estimator, free all of its resources.
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.
#define GNUNET_log(kind,...)
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:837
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MulitHashMapIterator32Callback 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.
void ibf_destroy(struct InvertibleBloomFilter *ibf)
Destroy all resources associated with the invertible bloom filter.
Definition: ibf.c:403
Opaque handle to a channel.
Definition: cadet.h:117
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(), GNUNET_assert, GNUNET_CADET_channel_destroy(), GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap32_destroy(), GNUNET_CONTAINER_multihashmap32_iterate(), GNUNET_CONTAINER_multihashmap_destroy(), 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 1676 of file gnunet-service-setu.c.

1677 {
1678  struct GNUNET_CADET_Channel *channel;
1679 
1680  if (NULL != (channel = op->channel))
1681  {
1682  /* This will free op; called conditionally as this helper function
1683  is also called from within the channel disconnect handler. */
1684  op->channel = NULL;
1685  GNUNET_CADET_channel_destroy (channel);
1686  }
1687  if (NULL != op->listener)
1688  {
1689  incoming_destroy (op);
1690  return;
1691  }
1692  if (NULL != op->set)
1693  send_client_done (op);
1695  GNUNET_free (op);
1696 }
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 1647 of file gnunet-service-setu.c.

1648 {
1649  struct Listener *listener;
1650 
1652  "Destroying incoming operation %p\n",
1653  op);
1654  if (NULL != (listener = op->listener))
1655  {
1657  listener->op_tail,
1658  op);
1659  op->listener = NULL;
1660  }
1661  if (NULL != op->timeout_task)
1662  {
1663  GNUNET_SCHEDULER_cancel (op->timeout_task);
1664  op->timeout_task = NULL;
1665  }
1667 }
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:972
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 1706 of file gnunet-service-setu.c.

1707 {
1708  struct GNUNET_MQ_Envelope *ev;
1710 
1712  "union operation failed\n");
1714  msg->result_status = htons (GNUNET_SETU_STATUS_FAILURE);
1715  msg->request_id = htonl (op->client_request_id);
1716  msg->element_type = htons (0);
1717  GNUNET_MQ_send (op->set->cs->mq,
1718  ev);
1720 }
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 1734 of file gnunet-service-setu.c.

1735 {
1736  if (GNUNET_YES != op->byzantine)
1737  return;
1738 
1739  int security_level_lb = -1 * SECURITY_LEVEL;
1740  uint64_t duplicates = op->received_fresh - op->received_total;
1741 
1742  /*
1743  * Protect full sync from receiving double element when in FULL SENDING
1744  */
1745  if (PHASE_FULL_SENDING == op->phase)
1746  {
1747  if (duplicates > 0)
1748  {
1750  "PROTOCOL VIOLATION: Received duplicate element in full receiving "
1751  "mode of operation this is not allowed! Duplicates: %llu\n",
1752  (unsigned long long) duplicates);
1753  GNUNET_break_op (0);
1755  return;
1756  }
1757 
1758  }
1759 
1760  /*
1761  * Protect full sync with probabilistic algorithm
1762  */
1763  if (PHASE_FULL_RECEIVING == op->phase)
1764  {
1765  if (0 == op->remote_set_diff)
1766  op->remote_set_diff = 1;
1767 
1768  long double base = (1 - (long double) (op->remote_set_diff
1769  / (long double) (op->initial_size
1770  + op->
1771  remote_set_diff)));
1772  long double exponent = (op->received_total - (op->received_fresh * ((long
1773  double)
1774  op->
1775  initial_size
1776  / (long
1777  double)
1778  op->
1779  remote_set_diff)));
1780  long double value = exponent * (log2l (base) / log2l (2));
1781  if ((value < security_level_lb) || (value > SECURITY_LEVEL) )
1782  {
1784  "PROTOCOL VIOLATION: Other peer violated probabilistic rule for receiving "
1785  "to many duplicated full element : %LF\n",
1786  value);
1787  GNUNET_break_op (0);
1789  return;
1790  }
1791  }
1792 }
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 1800 of file gnunet-service-setu.c.

1801 {
1802  double probability = op->differential_sync_iterations * (log2l (
1804  / log2l (2));
1805  if ((-1 * SECURITY_LEVEL) > probability)
1806  {
1808  "PROTOCOL VIOLATION: Other peer violated probabilistic rule for to many active passive "
1809  "switches in differential sync: %u\n",
1810  op->differential_sync_iterations);
1811  GNUNET_break_op (0);
1813  return;
1814  }
1815 }
#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 1800 of file gnunet-service-setu.c.

1827 {
1828  struct IBF_Key key;
1829  uint16_t salt = 0;
1830 
1832  GNUNET_CRYPTO_kdf (&key, sizeof(key),
1833  src, sizeof *src,
1834  &salt, sizeof(salt),
1835  NULL, 0));
1836  return key;
1837 }
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calcualations.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:90

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

Here is the caller graph for this function:

◆ op_get_element_iterator()

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

Iterator over the mapping from IBF keys to element entries.

Checks if we have an element with a given GNUNET_HashCode.

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

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

1871 {
1872  struct GetElementContext *ctx = cls;
1873  struct KeyEntry *k = value;
1874 
1875  GNUNET_assert (NULL != k);
1877  &ctx->hash))
1878  {
1879  ctx->k = k;
1880  return GNUNET_NO;
1881  }
1882  return GNUNET_YES;
1883 }
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
Definition: crypto_hash.c:201
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 1895 of file gnunet-service-setu.c.

1897 {
1898  int ret;
1899  struct IBF_Key ibf_key;
1900  struct GetElementContext ctx = { { { 0 } }, 0 };
1901 
1902  ctx.hash = *element_hash;
1903 
1904  ibf_key = get_ibf_key (element_hash);
1906  (uint32_t) ibf_key.key_val,
1908  &ctx);
1909 
1910  /* was the iteration aborted because we found the element? */
1911  if (GNUNET_SYSERR == ret)
1912  {
1913  GNUNET_assert (NULL != ctx.k);
1914  return ctx.k;
1915  }
1916  return NULL;
1917 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct IBF_Key get_ibf_key(const struct GNUNET_HashCode *src)
Derive the IBF key from a hash code and a salt.
static int op_get_element_iterator(void *cls, uint32_t key, void *value)
Iterator over the mapping from IBF keys to element entries.
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MulitHashMapIterator32Callback 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 1935 of file gnunet-service-setu.c.

1938 {
1939  struct IBF_Key ibf_key;
1940  struct KeyEntry *k;
1941 
1942  ibf_key = get_ibf_key (&ee->element_hash);
1943  k = GNUNET_new (struct KeyEntry);
1944  k->element = ee;
1945  k->ibf_key = ibf_key;
1946  k->received = received;
1948  GNUNET_CONTAINER_multihashmap32_put (op->key_to_element,
1949  (uint32_t) ibf_key.key_val,
1950  k,
1952 }
int 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 1960 of file gnunet-service-setu.c.

1963 {
1964  int s = (salt * 7) % 64;
1965  uint64_t x = k_in->key_val;
1966 
1967  /* rotate ibf key */
1968  x = (x >> s) | (x << (64 - s));
1969  k_out->key_val = x;
1970 }

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 1977 of file gnunet-service-setu.c.

1980 {
1981  int s = (salt * 7) % 64;
1982  uint64_t x = k_in->key_val;
1983 
1984  x = (x << s) | (x >> (64 - s));
1985  k_out->key_val = x;
1986 }

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 1997 of file gnunet-service-setu.c.

2000 {
2001  struct Operation *op = cls;
2002  struct KeyEntry *ke = value;
2003  struct IBF_Key salted_key;
2004 
2006  "[OP %p] inserting %lx (hash %s) into ibf\n",
2007  op,
2008  (unsigned long) ke->ibf_key.key_val,
2009  GNUNET_h2s (&ke->element->element_hash));
2010  salt_key (&ke->ibf_key,
2011  op->salt_send,
2012  &salted_key);
2013  ibf_insert (op->local_ibf, salted_key);
2014  return GNUNET_YES;
2015 }
static void salt_key(const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
Modify an IBF key k_in based on the salt, returning a salted key in k_out.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
void ibf_insert(struct InvertibleBloomFilter *ibf, struct IBF_Key key)
Insert a key into an IBF.
Definition: ibf.c:167

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 2026 of file gnunet-service-setu.c.

2028 {
2029  return ee->generation >= op->generation_created;
2030 }
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 2044 of file gnunet-service-setu.c.

2047 {
2048  struct Operation *op = cls;
2049  struct ElementEntry *ee = value;
2050 
2051  /* make sure that the element belongs to the set at the time
2052  * of creating the operation */
2053  if (GNUNET_NO ==
2055  op))
2056  return GNUNET_YES;
2057  GNUNET_assert (GNUNET_NO == ee->remote);
2059  ee,
2060  GNUNET_NO);
2061  return GNUNET_YES;
2062 }
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 2071 of file gnunet-service-setu.c.

2072 {
2073  unsigned int len;
2074 
2075  GNUNET_assert (NULL == op->key_to_element);
2076  len = GNUNET_CONTAINER_multihashmap_size (op->set->content->elements);
2077  op->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
2078  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
2080  op);
2081 }
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static int init_key_to_element_iterator(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator for initializing the key-to-element mapping of a union operation.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.

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

Referenced by handle_client_accept(), and handle_client_evaluate().

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

◆ prepare_ibf()

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

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

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

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

2095 {
2096  GNUNET_assert (NULL != op->key_to_element);
2097 
2098  if (NULL != op->local_ibf)
2099  ibf_destroy (op->local_ibf);
2100  // op->local_ibf = ibf_create (size, SE_IBF_HASH_NUM);
2101  op->local_ibf = ibf_create (size,
2102  ((uint8_t) op->ibf_number_buckets_per_element));
2103  if (NULL == op->local_ibf)
2104  {
2106  "Failed to allocate local IBF\n");
2107  return GNUNET_SYSERR;
2108  }
2111  op);
2112  return GNUNET_OK;
2113 }
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:67
struct InvertibleBloomFilter * ibf_create(uint32_t size, uint8_t hash_num)
Create an invertible bloom filter.
Definition: ibf.c:79

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 2126 of file gnunet-service-setu.c.

2128 {
2129  uint64_t buckets_sent = 0;
2130  struct InvertibleBloomFilter *ibf;
2131  op->differential_sync_iterations++;
2132 
2136  uint32_t ibf_min_size = IBF_MIN_SIZE;
2137 
2138  if (ibf_size < ibf_min_size)
2139  {
2140  ibf_size = ibf_min_size;
2141  }
2142  if (GNUNET_OK !=
2143  prepare_ibf (op, ibf_size))
2144  {
2145  /* allocation failed */
2146  return GNUNET_SYSERR;
2147  }
2148 
2150  "sending ibf of size %u\n",
2151  (unsigned int) ibf_size);
2152 
2153  {
2154  char name[64];
2155 
2157  sizeof(name),
2158  "# sent IBF (order %u)",
2159  ibf_size);
2161  }
2162 
2163  ibf = op->local_ibf;
2164 
2165  while (buckets_sent < ibf_size)
2166  {
2167  unsigned int buckets_in_message;
2168  struct GNUNET_MQ_Envelope *ev;
2169  struct IBFMessage *msg;
2170 
2171  buckets_in_message = ibf_size - buckets_sent;
2172  /* limit to maximum */
2173  if (buckets_in_message > MAX_BUCKETS_PER_MESSAGE)
2174  buckets_in_message = MAX_BUCKETS_PER_MESSAGE;
2175 
2176 #if MEASURE_PERFORMANCE
2177  perf_store.ibf.sent += 1;
2178  perf_store.ibf.sent_var_bytes += (buckets_in_message * IBF_BUCKET_SIZE);
2179 #endif
2180  ev = GNUNET_MQ_msg_extra (msg,
2181  buckets_in_message * IBF_BUCKET_SIZE,
2183  msg->ibf_size = ibf_size;
2184  msg->offset = htonl (buckets_sent);
2185  msg->salt = htonl (op->salt_send);
2186  msg->ibf_counter_bit_length = ibf_get_max_counter (ibf);
2187 
2188 
2189  ibf_write_slice (ibf, buckets_sent,
2190  buckets_in_message, &msg[1], msg->ibf_counter_bit_length);
2191  buckets_sent += buckets_in_message;
2193  "ibf chunk size %u, %llu/%u sent\n",
2194  (unsigned int) buckets_in_message,
2195  (unsigned long long) buckets_sent,
2196  (unsigned int) ibf_size);
2197  GNUNET_MQ_send (op->mq, ev);
2198  }
2199 
2200  /* The other peer must decode the IBF, so
2201  * we're passive. */
2202  op->phase = PHASE_PASSIVE_DECODING;
2203  return GNUNET_OK;
2204 }
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:52
#define GNUNET_MESSAGE_TYPE_SETU_P2P_IBF
Invertible bloom filter.
const char * name
void ibf_write_slice(const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_t count, void *buf)
Write buckets from an ibf to a buffer.
Definition: ibf.c:290
#define IBF_BUCKET_SIZE
Size of one ibf bucket in bytes.
Definition: ibf.h:72
uint8_t ibf_get_max_counter(struct InvertibleBloomFilter *ibf)
Returns the minimal bytes needed to store the counter of the IBF.
Definition: ibf.c:298
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 2215 of file gnunet-service-setu.c.

2217 {
2220  return (((int) (diff * ibf_bucket_number_factor)) | 1);
2221 
2222 }

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 2226 of file gnunet-service-setu.c.

2228 {
2229  unsigned int next_size = (unsigned int) ((last_ibf_size * 2)
2230  - (ibf_bucket_number_factor
2231  * decoded_elements));
2234  return next_size | 1;
2235 }

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 2248 of file gnunet-service-setu.c.

2251 {
2252  struct Operation *op = cls;
2253  struct GNUNET_SETU_ElementMessage *emsg;
2254  struct ElementEntry *ee = value;
2255  struct GNUNET_SETU_Element *el = &ee->element;
2256  struct GNUNET_MQ_Envelope *ev;
2257 
2259  "Sending element %s\n",
2260  GNUNET_h2s (key));
2261 #if MEASURE_PERFORMANCE
2262  perf_store.element_full.received += 1;
2263  perf_store.element_full.received_var_bytes += el->size;
2264 #endif
2265  ev = GNUNET_MQ_msg_extra (emsg,
2266  el->size,
2268  emsg->element_type = htons (el->element_type);
2269  GNUNET_memcpy (&emsg[1],
2270  el->data,
2271  el->size);
2272  GNUNET_MQ_send (op->mq,
2273  ev);
2274  return GNUNET_YES;
2275 }
static struct GNUNET_IDENTITY_EgoLookup * el
EgoLookup.
Definition: gnunet-abd.c:51
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT
Send a set element, not as response to a demand but because we're sending the full set.
struct GNUNET_SET_Element element
The actual element.
uint16_t element_type
Type of the element to add or remove.
Definition: setu.h:335

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

Referenced by send_full_set().

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

◆ send_full_set()

static void send_full_set ( struct Operation op)
static

Switch to full set transmission for op.

Parameters
opoperation to switch to full set transmission.

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

2285 {
2286  struct GNUNET_MQ_Envelope *ev;
2287 
2288  op->phase = PHASE_FULL_SENDING;
2290  "Dedicing to transmit the full set\n");
2291  /* FIXME: use a more memory-friendly way of doing this with an
2292  iterator, just as we do in the non-full case! */
2293 
2294  // Randomize Elements to send
2295  op->set->content->elements_randomized = GNUNET_CONTAINER_multihashmap_create (
2296  32,GNUNET_NO);
2297  op->set->content->elements_randomized_salt = GNUNET_CRYPTO_random_u64 (
2299  UINT64_MAX);
2300  (void) GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
2301  &
2303  op);
2304 
2306  op->set->content->elements_randomized,
2308  op);
2309 #if MEASURE_PERFORMANCE
2310  perf_store.full_done.sent += 1;
2311 #endif
2313  GNUNET_MQ_send (op->mq,
2314  ev);
2315 }
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)
Random on unsigned 64-bit values.
@ 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:76
#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 2325 of file gnunet-service-setu.c.

2327 {
2328  struct Operation *op = cls;
2329  int is_compressed;
2330  size_t len;
2331 
2332  if (op->phase != PHASE_EXPECT_SE)
2333  {
2334  GNUNET_break (0);
2335  return GNUNET_SYSERR;
2336  }
2337  is_compressed = (GNUNET_MESSAGE_TYPE_SETU_P2P_SEC == htons (
2338  msg->header.type));
2339  len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
2340  if ((GNUNET_NO == is_compressed) &&
2342  {
2343  GNUNET_break (0);
2344  return GNUNET_SYSERR;
2345  }
2346  return GNUNET_OK;
2347 }
#define SE_STRATA_COUNT
Number of IBFs in a strata estimator.
#define SE_IBFS_TOTAL_SIZE
Primes for all 4 different strata estimators 61,67,71,73,79,83,89,97 348 Based on the bsc thesis of E...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_SEC
Compressed strata estimator.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Strata estimator together with the peer's overall set size.

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

◆ handle_union_p2p_strata_estimator()

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

Handle a strata estimator from a remote peer.

Parameters
clsthe union operation
msgthe message

Check that the message is received only in supported phase

Only allow 1,2,4,8 SEs

Calculate avg element size if not initial sync

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

2359 {
2360 #if MEASURE_PERFORMANCE
2361  perf_store.se.received += 1;
2362  perf_store.se.received_var_bytes += ntohs (msg->header.size) - sizeof(struct
2364 #endif
2365  struct Operation *op = cls;
2366  struct MultiStrataEstimator *remote_se;
2367  unsigned int diff;
2368  uint64_t other_size;
2369  size_t len;
2370  int is_compressed;
2371  op->local_element_count = GNUNET_CONTAINER_multihashmap_size (
2372  op->set->content->elements);
2373  // Setting peer site to receiving peer
2374  op->peer_site = 1;
2375 
2379  uint8_t allowed_phases[] = {PHASE_EXPECT_SE};
2380  if (GNUNET_OK !=
2381  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
2382  {
2383  GNUNET_break (0);
2385  return;
2386  }
2387 
2389  if ((msg->se_count > 8) || (__builtin_popcount ((int) msg->se_count) != 1))
2390  {
2392  "PROTOCOL VIOLATION: Invalid number of se transmitted by other peer %u\n",
2393  msg->se_count);
2394  GNUNET_break_op (0);
2396  return;
2397  }
2398 
2399  is_compressed = (GNUNET_MESSAGE_TYPE_SETU_P2P_SEC == htons (
2400  msg->header.type));
2402  "# bytes of SE received",
2403  ntohs (msg->header.size),
2404  GNUNET_NO);
2405  len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
2406  other_size = GNUNET_ntohll (msg->set_size);
2407  op->remote_element_count = other_size;
2408 
2409  if (op->byzantine_upper_bound < op->remote_element_count)
2410  {
2412  "Exceeded configured upper bound <%lu> of element: %u\n",
2413  op->byzantine_upper_bound,
2414  op->remote_element_count);
2416  return;
2417  }
2418 
2421  SE_IBF_HASH_NUM);
2422  if (NULL == remote_se)
2423  {
2424  /* insufficient resources, fail */
2426  return;
2427  }
2428  if (GNUNET_OK !=
2430  len,
2431  is_compressed,
2432  msg->se_count,
2434  remote_se))
2435  {
2436  /* decompression failed */
2437  strata_estimator_destroy (remote_se);
2439  return;
2440  }
2441  GNUNET_assert (NULL != op->se);
2442  strata_estimator_difference (remote_se,
2443  op->se);
2444 
2445  /* Calculate remote local diff */
2446  long diff_remote = remote_se->stratas[0]->strata[0]->remote_decoded_count;
2447  long diff_local = remote_se->stratas[0]->strata[0]->local_decoded_count;
2448 
2449  /* Prevent estimations from overshooting max element */
2450  if (diff_remote + op->remote_element_count > op->byzantine_upper_bound)
2451  diff_remote = op->byzantine_upper_bound - op->remote_element_count;
2452  if (diff_local + op->local_element_count > op->byzantine_upper_bound)
2453  diff_local = op->byzantine_upper_bound - op->local_element_count;
2454  if ((diff_remote < 0) || (diff_local < 0))
2455  {
2456  strata_estimator_destroy (remote_se);
2458  "PROTOCOL VIOLATION: More element is set as upper boundary or other peer is "
2459  "malicious: remote diff %ld, local diff: %ld\n",
2460  diff_remote, diff_local);
2461  GNUNET_break_op (0);
2463  return;
2464  }
2465 
2466  /* Make estimation more precise in initial sync cases */
2467  if (0 == op->remote_element_count)
2468  {
2469  diff_remote = 0;
2470  diff_local = op->local_element_count;
2471  }
2472  if (0 == op->local_element_count)
2473  {
2474  diff_local = 0;
2475  diff_remote = op->remote_element_count;
2476  }
2477 
2478  diff = diff_remote + diff_local;
2479  op->remote_set_diff = diff_remote;
2480 
2482  uint64_t avg_element_size = 0;
2483  if (0 < op->local_element_count)
2484  {
2485  op->total_elements_size_local = 0;
2486  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
2487  &
2489  op);
2490  avg_element_size = op->total_elements_size_local / op->local_element_count;
2491  }
2492 
2493  op->mode_of_operation = estimate_best_mode_of_operation (avg_element_size,
2495  op->set->content->
2496  elements),
2497  op->
2498  remote_element_count,
2499  diff_remote,
2500  diff_local,
2501  op->
2502  rtt_bandwidth_tradeoff,
2503  op->
2504  ibf_bucket_number_factor);
2505 
2506 #if MEASURE_PERFORMANCE
2507  perf_store.se_diff_local = diff_local;
2508  perf_store.se_diff_remote = diff_remote;
2509  perf_store.se_diff = diff;
2510  perf_store.mode_of_operation = op->mode_of_operation;
2511 #endif
2512 
2513  strata_estimator_destroy (remote_se);
2515  op->se = NULL;
2517  "got se diff=%d, using ibf size %d\n",
2518  diff,
2519  1U << get_size_from_difference (diff, op->ibf_number_buckets_per_element,
2520  op->ibf_bucket_number_factor));
2521 
2522  {
2523  char *set_debug;
2524 
2525  set_debug = getenv ("GNUNET_SETU_BENCHMARK");
2526  if ((NULL != set_debug) &&
2527  (0 == strcmp (set_debug, "1")))
2528  {
2529  FILE *f = fopen ("set.log", "a");
2530  fprintf (f, "%llu\n", (unsigned long long) diff);
2531  fclose (f);
2532  }
2533  }
2534 
2535  if ((GNUNET_YES == op->byzantine) &&
2536  (other_size < op->byzantine_lower_bound))
2537  {
2538  GNUNET_break (0);
2540  return;
2541  }
2542 
2543  if ((GNUNET_YES == op->force_full) ||
2544  (op->mode_of_operation != DIFFERENTIAL_SYNC))
2545  {
2547  "Deciding to go for full set transmission (diff=%d, own set=%llu)\n",
2548  diff,
2549  (unsigned long long) op->initial_size);
2551  "# of full sends",
2552  1,
2553  GNUNET_NO);
2554  if (FULL_SYNC_LOCAL_SENDING_FIRST == op->mode_of_operation)
2555  {
2556  struct TransmitFullMessage *signal_msg;
2557  struct GNUNET_MQ_Envelope *ev;
2558  ev = GNUNET_MQ_msg_extra (signal_msg,sizeof(struct TransmitFullMessage),
2560  signal_msg->remote_set_difference = htonl (diff_local);
2561  signal_msg->remote_set_size = htonl (op->local_element_count);
2562  signal_msg->local_set_difference = htonl (diff_remote);
2563  GNUNET_MQ_send (op->mq,
2564  ev);
2565  send_full_set (op);
2566  }
2567  else
2568  {
2569  struct GNUNET_MQ_Envelope *ev;
2570 
2572  "Telling other peer that we expect its full set\n");
2573  op->phase = PHASE_FULL_RECEIVING;
2574 #if MEASURE_PERFORMANCE
2575  perf_store.request_full.sent += 1;
2576 #endif
2577  struct TransmitFullMessage *signal_msg;
2578  ev = GNUNET_MQ_msg_extra (signal_msg,sizeof(struct TransmitFullMessage),
2580  signal_msg->remote_set_difference = htonl (diff_local);
2581  signal_msg->remote_set_size = htonl (op->local_element_count);
2582  signal_msg->local_set_difference = htonl (diff_remote);
2583  GNUNET_MQ_send (op->mq,
2584  ev);
2585  }
2586  }
2587  else
2588  {
2590  "# of ibf sends",
2591  1,
2592  GNUNET_NO);
2593  if (GNUNET_OK !=
2594  send_ibf (op,
2596  op->ibf_number_buckets_per_element,
2597  op->ibf_bucket_number_factor)))
2598  {
2599  /* Internal error, best we can do is shut the connection */
2601  "Failed to send IBF, closing connection\n");
2603  return;
2604  }
2605  }
2606  GNUNET_CADET_receive_done (op->channel);
2607 }
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.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:53
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Send an ack on the channel to confirm the processing of a message.
Definition: cadet_api.c:888
#define GNUNET_MESSAGE_TYPE_SETU_P2P_SEND_FULL
Signals other peer that all elements are sent.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL
Demand the whole element from the other peer, given only the hash code.
int remote_decoded_count
If an IBF is decoded this count stores how many elements are on the remote site.
Definition: ibf.h:108
int local_decoded_count
If an IBF is decoded this count stores how many elements are on the local site.
Definition: ibf.h:101
struct StrataEstimator ** stratas
Array of strata estimators.
struct InvertibleBloomFilter ** strata
The IBFs of this strata estimator.
Message which signals to other peer that we are sending full set.
uint32_t local_set_difference
Local set difference calculated with strata estimator.
uint32_t remote_set_difference
Remote set difference calculated with strata estimator.
uint32_t remote_set_size
Total remote set size.

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

Here is the call graph for this function:

◆ send_offers_iterator()

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

Iterator to send elements to a remote peer.

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

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

2621 {
2622  struct SendElementClosure *sec = cls;
2623  struct Operation *op = sec->op;
2624  struct KeyEntry *ke = value;
2625  struct GNUNET_MQ_Envelope *ev;
2626  struct GNUNET_MessageHeader *mh;
2627 
2628  /* Detect 32-bit key collision for the 64-bit IBF keys. */
2629  if (ke->ibf_key.key_val != sec->ibf_key.key_val)
2630  {
2631  op->active_passive_switch_required = true;
2632  return GNUNET_YES;
2633  }
2634 
2635  /* Prevent implementation from sending a offer multiple times in case of roll switch */
2636  if (GNUNET_YES ==
2638  op->message_control_flow,
2639  &ke->element->element_hash,
2640  OFFER_MESSAGE)
2641  )
2642  {
2644  "Skipping already sent processed element offer!\n");
2645  return GNUNET_YES;
2646  }
2647 
2648  /* Save send offer message for message control */
2649  if (GNUNET_YES !=
2651  op->message_control_flow,
2652  MSG_CFS_SENT,
2653  &ke->element->element_hash,
2654  OFFER_MESSAGE)
2655  )
2656  {
2658  "Double offer message sent found!\n");
2659  GNUNET_break (0);
2661  return GNUNET_NO;
2662  }
2663  ;
2664 
2665  /* Mark element to be expected to received */
2666  if (GNUNET_YES !=
2668  op->message_control_flow,
2670  &ke->element->element_hash,
2672  )
2673  {
2675  "Double demand received found!\n");
2676  GNUNET_break (0);
2678  return GNUNET_NO;
2679  }
2680  ;
2681 #if MEASURE_PERFORMANCE
2682  perf_store.offer.sent += 1;
2683  perf_store.offer.sent_var_bytes += sizeof(struct GNUNET_HashCode);
2684 #endif
2686  sizeof(struct GNUNET_HashCode),
2688  GNUNET_assert (NULL != ev);
2689  *(struct GNUNET_HashCode *) &mh[1] = ke->element->element_hash;
2691  "[OP %p] sending element offer (%s) to peer\n",
2692  op,
2693  GNUNET_h2s (&ke->element->element_hash));
2694  GNUNET_MQ_send (op->mq, ev);
2695  return GNUNET_YES;
2696 }
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:88
#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 2706 of file gnunet-service-setu.c.

2708 {
2709  struct SendElementClosure send_cls;
2710 
2711  send_cls.ibf_key = ibf_key;
2712  send_cls.op = op;
2714  op->key_to_element,
2715  (uint32_t) ibf_key.
2716  key_val,
2718  &send_cls);
2719 }
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 2730 of file gnunet-service-setu.c.

2731 {
2732  struct IBF_Key key;
2733  struct IBF_Key last_key;
2734  int side;
2735  unsigned int num_decoded;
2736  struct InvertibleBloomFilter *diff_ibf;
2737 
2739 
2740  if (GNUNET_OK !=
2741  prepare_ibf (op,
2742  op->remote_ibf->size))
2743  {
2744  GNUNET_break (0);
2745  /* allocation failed */
2746  return GNUNET_SYSERR;
2747  }
2748 
2749  diff_ibf = ibf_dup (op->local_ibf);
2750  ibf_subtract (diff_ibf,
2751  op->remote_ibf);
2752 
2753  ibf_destroy (op->remote_ibf);
2754  op->remote_ibf = NULL;
2755 
2757  "decoding IBF (size=%u)\n",
2758  diff_ibf->size);
2759 
2760  num_decoded = 0;
2761  key.key_val = 0; /* just to avoid compiler thinking we use undef'ed variable */
2762 
2763  while (1)
2764  {
2765  int res;
2766  int cycle_detected = GNUNET_NO;
2767 
2768  last_key = key;
2769 
2770  res = ibf_decode (diff_ibf,
2771  &side,
2772  &key);
2773  if (res == GNUNET_OK)
2774  {
2776  "decoded ibf key %lx\n",
2777  (unsigned long) key.key_val);
2778  num_decoded += 1;
2779  if ((num_decoded > diff_ibf->size) ||
2780  ((num_decoded > 1) &&
2781  (last_key.key_val == key.key_val)))
2782  {
2784  "detected cyclic ibf (decoded %u/%u)\n",
2785  num_decoded,
2786  diff_ibf->size);
2787  cycle_detected = GNUNET_YES;
2788  }
2789  }
2790  if ((GNUNET_SYSERR == res) ||
2791  (GNUNET_YES == cycle_detected))
2792  {
2793  uint32_t next_size;
2796  next_size = get_next_ibf_size (op->ibf_bucket_number_factor, num_decoded,
2797  diff_ibf->size);
2800  uint32_t ibf_min_size = IBF_MIN_SIZE | 1;
2801 
2802  if (next_size<ibf_min_size)
2803  next_size = ibf_min_size;
2804 
2805 
2806  if (next_size <= MAX_IBF_SIZE)
2807  {
2809  "decoding failed, sending larger ibf (size %u)\n",
2810  next_size);
2812  "# of IBF retries",
2813  1,
2814  GNUNET_NO);
2815 #if MEASURE_PERFORMANCE
2816  perf_store.active_passive_switches += 1;
2817 #endif
2818 
2819  op->salt_send = op->salt_receive++;
2820 
2821  if (GNUNET_OK !=
2822  send_ibf (op, next_size))
2823  {
2824  /* Internal error, best we can do is shut the connection */
2826  "Failed to send IBF, closing connection\n");
2828  ibf_destroy (diff_ibf);
2829  return GNUNET_SYSERR;
2830  }
2831  }
2832  else
2833  {
2835  "# of failed union operations (too large)",
2836  1,
2837  GNUNET_NO);
2838  // XXX: Send the whole set, element-by-element
2840  "set union failed: reached ibf limit\n");
2842  ibf_destroy (diff_ibf);
2843  return GNUNET_SYSERR;
2844  }
2845  break;
2846  }
2847  if (GNUNET_NO == res)
2848  {
2849  struct GNUNET_MQ_Envelope *ev;
2850 
2852  "transmitted all values, sending DONE\n");
2853 
2854 #if MEASURE_PERFORMANCE
2855  perf_store.done.sent += 1;
2856 #endif
2858  GNUNET_MQ_send (op->mq, ev);
2859  /* We now wait until we get a DONE message back
2860  * and then wait for our MQ to be flushed and all our
2861  * demands be delivered. */
2862  break;
2863  }
2864  if (1 == side)
2865  {
2866  struct IBF_Key unsalted_key;
2867  unsalt_key (&key,
2868  op->salt_receive,
2869  &unsalted_key);
2871  unsalted_key);
2872  }
2873  else if (-1 == side)
2874  {
2875  struct GNUNET_MQ_Envelope *ev;
2876  struct InquiryMessage *msg;
2877 
2878 #if MEASURE_PERFORMANCE
2879  perf_store.inquery.sent += 1;
2880  perf_store.inquery.sent_var_bytes += sizeof(struct IBF_Key);
2881 #endif
2882 
2884  struct GNUNET_HashContext *hashed_key_context =
2886  struct GNUNET_HashCode *hashed_key = (struct
2888  sizeof(struct GNUNET_HashCode));
2890  GNUNET_CRYPTO_hash_context_read (hashed_key_context,
2891  &key,
2892  sizeof(struct IBF_Key));
2893  GNUNET_CRYPTO_hash_context_finish (hashed_key_context,
2894  hashed_key);
2895  GNUNET_CONTAINER_multihashmap_put (op->inquiries_sent,
2896  hashed_key,
2897  &mcfs,
2899  );
2900 
2901  /* It may be nice to merge multiple requests, but with CADET's corking it is not worth
2902  * the effort additional complexity. */
2903  ev = GNUNET_MQ_msg_extra (msg,
2904  sizeof(struct IBF_Key),
2906  msg->salt = htonl (op->salt_receive);
2907  GNUNET_memcpy (&msg[1],
2908  &key,
2909  sizeof(struct IBF_Key));
2911  "sending element inquiry for IBF key %lx\n",
2912  (unsigned long) key.key_val);
2913  GNUNET_MQ_send (op->mq, ev);
2914  }
2915  else
2916  {
2917  GNUNET_assert (0);
2918  }
2919  }
2920  ibf_destroy (diff_ibf);
2921  return GNUNET_OK;
2922 }
static int res
static unsigned int get_next_ibf_size(float ibf_bucket_number_factor, unsigned int decoded_elements, unsigned int last_ibf_size)
#define MAX_IBF_SIZE
The maximum size of an ibf we use is MAX_IBF_SIZE=2^20.
void send_offers_for_key(struct Operation *op, struct IBF_Key ibf_key)
Send offers (in the form of GNUNET_Hash-es) to the remote peer for the given IBF key.
static void unsalt_key(const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
Reverse modification done in the salt_key function.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_DONE
Set operation is done.
#define GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY
Tell the other peer to send us a list of hashes that match an IBF key.
void ibf_subtract(struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2)
Subtract ibf2 from ibf1, storing the result in ibf1.
Definition: ibf.c:356
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:228
struct InvertibleBloomFilter * ibf_dup(const struct InvertibleBloomFilter *ibf)
Create a copy of an IBF, the copy has to be destroyed properly.
Definition: ibf.c:379
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 2933 of file gnunet-service-setu.c.

2935 {
2936  return GNUNET_OK;
2937 }

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 2947 of file gnunet-service-setu.c.

2949 {
2950  struct Operation *op = cls;
2951 
2955  uint8_t allowed_phases[] = {PHASE_EXPECT_IBF};
2956  if (GNUNET_OK !=
2957  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
2958  {
2959  GNUNET_break (0);
2961  return;
2962  }
2963 
2965  op->remote_element_count = ntohl (msg->remote_set_size);
2966  op->remote_set_diff = ntohl (msg->remote_set_difference);
2967  op->local_set_diff = ntohl (msg->local_set_difference);
2968 
2971  {
2973  "PROTOCOL VIOLATION: Parameters transmitted from other peer do not satisfie byzantine "
2974  "criteria\n");
2975  GNUNET_break_op (0);
2977  return;
2978  }
2979 
2981  op->local_element_count = GNUNET_CONTAINER_multihashmap_size (
2982  op->set->content->elements);
2983  uint64_t avg_element_size = 0;
2984  if (0 < op->local_element_count)
2985  {
2986  op->total_elements_size_local = 0;
2987  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
2988  &
2990  op);
2991  avg_element_size = op->total_elements_size_local / op->local_element_count;
2992  }
2993 
2995  int mode_of_operation = estimate_best_mode_of_operation (avg_element_size,
2996  op->
2998  op->
3000  op->local_set_diff,
3001  op->remote_set_diff,
3002  op->
3004  op->
3007  {
3009  "PROTOCOL VIOLATION: Remote peer choose to send his full set first but correct mode would have been"
3010  " : %d\n", mode_of_operation);
3011  GNUNET_break_op (0);
3013  return;
3014  }
3015  op->phase = PHASE_FULL_RECEIVING;
3016 }
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 3030 of file gnunet-service-setu.c.

3032 {
3033  struct Operation *op = cls;
3034  unsigned int buckets_in_message;
3035 
3036  buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
3037  / IBF_BUCKET_SIZE;
3038  if (0 == buckets_in_message)
3039  {
3040  GNUNET_break_op (0);
3041  return GNUNET_SYSERR;
3042  }
3043  if ((ntohs (msg->header.size) - sizeof *msg) != buckets_in_message
3044  * IBF_BUCKET_SIZE)
3045  {
3046  GNUNET_break_op (0);
3047  return GNUNET_SYSERR;
3048  }
3049  if (op->phase == PHASE_EXPECT_IBF_LAST)
3050  {
3051  if (ntohl (msg->offset) != op->ibf_buckets_received)
3052  {
3053  GNUNET_break_op (0);
3054  return GNUNET_SYSERR;
3055  }
3056 
3057  if (msg->ibf_size != op->remote_ibf->size)
3058  {
3059  GNUNET_break_op (0);
3060  return GNUNET_SYSERR;
3061  }
3062  if (ntohl (msg->salt) != op->salt_receive)
3063  {
3064  GNUNET_break_op (0);
3065  return GNUNET_SYSERR;
3066  }
3067  }
3068  else if ((op->phase != PHASE_PASSIVE_DECODING) &&
3069  (op->phase != PHASE_EXPECT_IBF))
3070  {
3071  GNUNET_break_op (0);
3072  return GNUNET_SYSERR;
3073  }
3074 
3075  return GNUNET_OK;
3076 }

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 3089 of file gnunet-service-setu.c.

3091 {
3092  struct Operation *op = cls;
3093  unsigned int buckets_in_message;
3097  uint8_t allowed_phases[] = {PHASE_EXPECT_IBF, PHASE_EXPECT_IBF_LAST,
3099  if (GNUNET_OK !=
3100  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3101  {
3102  GNUNET_break (0);
3104  return;
3105  }
3106  op->differential_sync_iterations++;
3108  op->active_passive_switch_required = false;
3109 
3110 #if MEASURE_PERFORMANCE
3111  perf_store.ibf.received += 1;
3112  perf_store.ibf.received_var_bytes += (ntohs (msg->header.size) - sizeof *msg);
3113 #endif
3114 
3115  buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
3116  / IBF_BUCKET_SIZE;
3117  if ((op->phase == PHASE_PASSIVE_DECODING) ||
3118  (op->phase == PHASE_EXPECT_IBF))
3119  {
3120  op->phase = PHASE_EXPECT_IBF_LAST;
3121  GNUNET_assert (NULL == op->remote_ibf);
3123  "Creating new ibf of size %u\n",
3124  ntohl (msg->ibf_size));
3125  // op->remote_ibf = ibf_create (1 << msg->order, SE_IBF_HASH_NUM);
3126  op->remote_ibf = ibf_create (msg->ibf_size,
3127  ((uint8_t) op->ibf_number_buckets_per_element));
3128  op->salt_receive = ntohl (msg->salt);
3130  "Receiving new IBF with salt %u\n",
3131  op->salt_receive);
3132  if (NULL == op->remote_ibf)
3133  {
3135  "Failed to parse remote IBF, closing connection\n");
3137  return;
3138  }
3139  op->ibf_buckets_received = 0;
3140  if (0 != ntohl (msg->offset))
3141  {
3142  GNUNET_break_op (0);
3144  return;
3145  }
3146  }
3147  else
3148  {
3151  "Received more of IBF\n");
3152  }
3153  GNUNET_assert (NULL != op->remote_ibf);
3154 
3155  ibf_read_slice (&msg[1],
3156  op->ibf_buckets_received,
3157  buckets_in_message,
3158  op->remote_ibf, msg->ibf_counter_bit_length);
3159  op->ibf_buckets_received += buckets_in_message;
3160 
3161  if (op->ibf_buckets_received == op->remote_ibf->size)
3162  {
3164  "received full ibf\n");
3165  op->phase = PHASE_ACTIVE_DECODING;
3166  if (GNUNET_OK !=
3167  decode_and_send (op))
3168  {
3169  /* Internal error, best we can do is shut down */
3171  "Failed to decode IBF, closing connection\n");
3173  return;
3174  }
3175  }
3176  GNUNET_CADET_receive_done (op->channel);
3177 }
static int decode_and_send(struct Operation *op)
Decode which elements are missing on each side, and send the appropriate offers and inquiries.
static void check_max_differential_rounds(struct Operation *op)
Limit active passive switches in differential sync to configured security level.
void ibf_read_slice(const void *buf, uint32_t start, uint32_t count, struct InvertibleBloomFilter *ibf)
Read buckets from a buffer into an ibf.
Definition: ibf.c:323

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 3189 of file gnunet-service-setu.c.

3192 {
3193  struct GNUNET_MQ_Envelope *ev;
3194  struct GNUNET_SETU_ResultMessage *rm;
3195 
3197  "sending element (size %u) to client\n",
3198  element->size);
3199  GNUNET_assert (0 != op->client_request_id);
3200  ev = GNUNET_MQ_msg_extra (rm,
3201  element->size,
3203  if (NULL == ev)
3204  {
3205  GNUNET_MQ_discard (ev);
3206  GNUNET_break (0);
3207  return;
3208  }
3209  rm->result_status = htons (status);
3210  rm->request_id = htonl (op->client_request_id);
3211  rm->element_type = htons (element->element_type);
3213  op->key_to_element));
3214  GNUNET_memcpy (&rm[1],
3215  element->data,
3216  element->size);
3217  GNUNET_MQ_send (op->set->cs->mq,
3218  ev);
3219 }
uint16_t status
See PRISM_STATUS_*-constants.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:323
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 3228 of file gnunet-service-setu.c.

3229 {
3230  unsigned int num_demanded;
3231 
3232  num_demanded = GNUNET_CONTAINER_multihashmap_size (
3233  op->demanded_hashes);
3234  int send_done = GNUNET_CONTAINER_multihashmap_iterate (
3235  op->message_control_flow,
3236  &
3238  op);
3239  if (PHASE_FINISH_WAITING == op->phase)
3240  {
3242  "In PHASE_FINISH_WAITING, pending %u demands -> %d\n",
3243  num_demanded, op->peer_site);
3244  if (-1 != send_done)
3245  {
3246  struct GNUNET_MQ_Envelope *ev;
3247 
3248  op->phase = PHASE_FINISHED;
3249 #if MEASURE_PERFORMANCE
3250  perf_store.done.sent += 1;
3251 #endif
3253  GNUNET_MQ_send (op->mq,
3254  ev);
3255  /* We now wait until the other peer sends P2P_OVER
3256  * after it got all elements from us. */
3257  }
3258  }
3259  if (PHASE_FINISH_CLOSING == op->phase)
3260  {
3262  "In PHASE_FINISH_CLOSING, pending %u demands %d\n",
3263  num_demanded, op->peer_site);
3264  if (-1 != send_done)
3265  {
3266  op->phase = PHASE_FINISHED;
3267  send_client_done (op);
3269  }
3270  }
3271 }
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 3281 of file gnunet-service-setu.c.

3283 {
3284  struct Operation *op = cls;
3285 
3286  if (0 == GNUNET_CONTAINER_multihashmap_size (op->demanded_hashes))
3287  {
3288  GNUNET_break_op (0);
3289  return GNUNET_SYSERR;
3290  }
3291  return GNUNET_OK;
3292 }

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 3304 of file gnunet-service-setu.c.

3306 {
3307  struct Operation *op = cls;
3308  struct ElementEntry *ee;
3309  struct KeyEntry *ke;
3310  uint16_t element_size;
3311 
3315  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING,
3317  if (GNUNET_OK !=
3318  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3319  {
3320  GNUNET_break (0);
3322  return;
3323  }
3324 
3325  element_size = ntohs (emsg->header.size) - sizeof(struct
3327 #if MEASURE_PERFORMANCE
3328  perf_store.element.received += 1;
3329  perf_store.element.received_var_bytes += element_size;
3330 #endif
3331 
3332  ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
3333  GNUNET_memcpy (&ee[1],
3334  &emsg[1],
3335  element_size);
3336  ee->element.size = element_size;
3337  ee->element.data = &ee[1];
3338  ee->element.element_type = ntohs (emsg->element_type);
3339  ee->remote = GNUNET_YES;
3341  &ee->element_hash);
3342  if (GNUNET_NO ==
3343  GNUNET_CONTAINER_multihashmap_remove (op->demanded_hashes,
3344  &ee->element_hash,
3345  NULL))
3346  {
3347  /* We got something we didn't demand, since it's not in our map. */
3348  GNUNET_break_op (0);
3350  return;
3351  }
3352 
3353  if (GNUNET_OK !=
3355  op->message_control_flow,
3357  &ee->element_hash,
3359  )
3360  {
3362  "An element has been received more than once!\n");
3363  GNUNET_break (0);
3365  return;
3366  }
3367 
3369  "Got element (size %u, hash %s) from peer\n",
3370  (unsigned int) element_size,
3371  GNUNET_h2s (&ee->element_hash));
3372 
3374  "# received elements",
3375  1,
3376  GNUNET_NO);
3378  "# exchanged elements",
3379  1,
3380  GNUNET_NO);
3381 
3382  op->received_total++;
3383 
3384  ke = op_get_element (op,
3385  &ee->element_hash);
3386  if (NULL != ke)
3387  {
3388  /* Got repeated element. Should not happen since
3389  * we track demands. */
3391  "# repeated elements",
3392  1,
3393  GNUNET_NO);
3394  ke->received = GNUNET_YES;
3395  GNUNET_free (ee);
3396  }
3397  else
3398  {
3400  "Registering new element from remote peer\n");
3401  op->received_fresh++;
3403  /* only send results immediately if the client wants it */
3405  &ee->element,
3407  }
3408 
3409  if ((op->received_total > 8) &&
3410  (op->received_fresh < op->received_total / 3))
3411  {
3412  /* The other peer gave us lots of old elements, there's something wrong. */
3413  GNUNET_break_op (0);
3415  return;
3416  }
3417  GNUNET_CADET_receive_done (op->channel);
3418  maybe_finish (op);
3419 }
static struct KeyEntry * op_get_element(struct Operation *op, const struct GNUNET_HashCode *element_hash)
Determine whether the given element is already in the operation's element set.
static void maybe_finish(struct Operation *op)
Tests if the operation is finished, and if so notify.
static void send_client_element(struct Operation *op, const struct GNUNET_SETU_Element *element, enum GNUNET_SETU_Status status)
Send a result message to the client indicating that there is a new element.
int 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:916
@ GNUNET_SETU_STATUS_ADD_LOCAL
Element should be added to the result set of the local peer, i.e.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SETU_ADD.
Definition: setu.h:330
uint16_t size
Number of bytes in the buffer pointed to by data.
const void * data
Actual data of the element.
uint16_t element_type
Application-specific element type.

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

Here is the call graph for this function:

◆ check_union_p2p_full_element()

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

Check a full element message from a remote peer.

Parameters
clsthe union operation
emsgthe message

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

3431 {
3432  struct Operation *op = cls;
3433 
3434  (void) op;
3435 
3436  // FIXME: check that we expect full elements here?
3437  return GNUNET_OK;
3438 }

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 3448 of file gnunet-service-setu.c.

3450 {
3451  struct Operation *op = cls;
3452  struct ElementEntry *ee;
3453  struct KeyEntry *ke;
3454  uint16_t element_size;
3455 
3459  uint8_t allowed_phases[] = {PHASE_FULL_RECEIVING, PHASE_FULL_SENDING};
3460  if (GNUNET_OK !=
3461  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3462  {
3463  GNUNET_break (0);
3465  return;
3466  }
3467 
3468  element_size = ntohs (emsg->header.size)
3469  - sizeof(struct GNUNET_SETU_ElementMessage);
3470 
3471 #if MEASURE_PERFORMANCE
3472  perf_store.element_full.received += 1;
3473  perf_store.element_full.received_var_bytes += element_size;
3474 #endif
3475 
3476  ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
3477  GNUNET_memcpy (&ee[1], &emsg[1], element_size);
3478  ee->element.size = element_size;
3479  ee->element.data = &ee[1];
3480  ee->element.element_type = ntohs (emsg->element_type);
3481  ee->remote = GNUNET_YES;
3483  &ee->element_hash);
3485  "Got element (full diff, size %u, hash %s) from peer\n",
3486  (unsigned int) element_size,
3487  GNUNET_h2s (&ee->element_hash));
3488 
3490  "# received elements",
3491  1,
3492  GNUNET_NO);
3494  "# exchanged elements",
3495  1,
3496  GNUNET_NO);
3497 
3498  op->received_total++;
3499  ke = op_get_element (op,
3500  &ee->element_hash);
3501  if (NULL != ke)
3502  {
3504  "# repeated elements",
3505  1,
3506  GNUNET_NO);
3508  ke->received = GNUNET_YES;
3509  GNUNET_free (ee);
3510  }
3511  else
3512  {
3514  "Registering new element from remote peer\n");
3515  op->received_fresh++;
3517  /* only send results immediately if the client wants it */
3519  &ee->element,
3521  }
3522 
3523 
3524  if ((GNUNET_YES == op->byzantine) &&
3525  (op->received_total > op->remote_element_count) )
3526  {
3527  /* The other peer gave us lots of old elements, there's something wrong. */
3529  "Other peer sent %llu elements while pretending to have %llu elements, failing operation\n",
3530  (unsigned long long) op->received_total,
3531  (unsigned long long) op->remote_element_count);
3532  GNUNET_break_op (0);
3534  return;
3535  }
3536  GNUNET_CADET_receive_done (op->channel);
3537 }
static void full_sync_plausibility_check(struct Operation *op)
Function that checks if full sync is plausible.

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

Here is the call graph for this function:

◆ check_union_p2p_inquiry()

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

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

Parameters
clsthe union operation
msgthe message

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

3550 {
3551  struct Operation *op = cls;
3552  unsigned int num_keys;
3553 
3554  if (op->phase != PHASE_PASSIVE_DECODING)
3555  {
3556  GNUNET_break_op (0);
3557  return GNUNET_SYSERR;
3558  }
3559  num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
3560  / sizeof(struct IBF_Key);
3561  if ((ntohs (msg->header.size) - sizeof(struct InquiryMessage))
3562  != num_keys * sizeof(struct IBF_Key))
3563  {
3564  GNUNET_break_op (0);
3565  return GNUNET_SYSERR;
3566  }
3567  return GNUNET_OK;
3568 }

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 3578 of file gnunet-service-setu.c.

3580 {
3581  struct Operation *op = cls;
3582  const struct IBF_Key *ibf_key;
3583  unsigned int num_keys;
3584 
3588  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING};
3589  if (GNUNET_OK !=
3590  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3591  {
3592  GNUNET_break (0);
3594  return;
3595  }
3596 
3597 #if MEASURE_PERFORMANCE
3598  perf_store.inquery.received += 1;
3599  perf_store.inquery.received_var_bytes += (ntohs (msg->header.size)
3600  - sizeof(struct InquiryMessage));
3601 #endif
3602 
3604  "Received union inquiry\n");
3605  num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
3606  / sizeof(struct IBF_Key);
3607  ibf_key = (const struct IBF_Key *) &msg[1];
3608 
3610  struct GNUNET_HashContext *hashed_key_context =
3612  struct GNUNET_HashCode *hashed_key = (struct GNUNET_HashCode*) GNUNET_malloc (
3613  sizeof(struct GNUNET_HashCode));;
3615  GNUNET_CRYPTO_hash_context_read (hashed_key_context,
3616  &ibf_key,
3617  sizeof(struct IBF_Key));
3618  GNUNET_CRYPTO_hash_context_finish (hashed_key_context,
3619  hashed_key);
3620  GNUNET_CONTAINER_multihashmap_put (op->inquiries_sent,
3621  hashed_key,
3622  &mcfs,
3624  );
3625 
3626  while (0 != num_keys--)
3627  {
3628  struct IBF_Key unsalted_key;
3629  unsalt_key (ibf_key,
3630  ntohl (msg->salt),
3631  &unsalted_key);
3633  unsalted_key);
3634  ibf_key++;
3635  }
3636  GNUNET_CADET_receive_done (op->channel);
3637 }

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 3651 of file gnunet-service-setu.c.

3654 {
3655  struct Operation *op = cls;
3656  struct KeyEntry *ke = value;
3657  struct GNUNET_MQ_Envelope *ev;
3658  struct GNUNET_SETU_ElementMessage *emsg;
3659  struct ElementEntry *ee = ke->element;
3660 
3661  if (GNUNET_YES == ke->received)
3662  return GNUNET_YES;
3663 #if MEASURE_PERFORMANCE
3664  perf_store.element_full.received += 1;
3665 #endif
3666  ev = GNUNET_MQ_msg_extra (emsg,
3667  ee->element.size,
3669  GNUNET_memcpy (&emsg[1],
3670  ee->element.data,
3671  ee->element.size);
3672  emsg->element_type = htons (ee->element.element_type);
3673  GNUNET_MQ_send (op->mq,
3674  ev);
3675  return GNUNET_YES;
3676 }

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 3686 of file gnunet-service-setu.c.

3688 {
3689  return GNUNET_OK;
3690 }

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 3694 of file gnunet-service-setu.c.

3696 {
3697  struct Operation *op = cls;
3698 
3702  uint8_t allowed_phases[] = {PHASE_EXPECT_IBF};
3703  if (GNUNET_OK !=
3704  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3705  {
3706  GNUNET_break (0);
3708  return;
3709  }
3710 
3711  op->remote_element_count = ntohl (msg->remote_set_size);
3712  op->remote_set_diff = ntohl (msg->remote_set_difference);
3713  op->local_set_diff = ntohl (msg->local_set_difference);
3714 
3715 
3717  {
3719  "PROTOCOL VIOLATION: Parameters transmitted from other peer do not satisfie byzantine "
3720  "criteria\n");
3721  GNUNET_break_op (0);
3723  return;
3724  }
3725 
3726 #if MEASURE_PERFORMANCE
3727  perf_store.request_full.received += 1;
3728 #endif
3729 
3731  "Received request for full set transmission\n");
3732 
3734  op->local_element_count = GNUNET_CONTAINER_multihashmap_size (
3735  op->set->content->elements);
3736  uint64_t avg_element_size = 0;
3737  if (0 < op->local_element_count)
3738  {
3739  op->total_elements_size_local = 0;
3740  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
3741  &
3743  op);
3744  avg_element_size = op->total_elements_size_local / op->local_element_count;
3745  }
3746 
3747  int mode_of_operation = estimate_best_mode_of_operation (avg_element_size,
3748  op->
3750  op->
3752  op->local_set_diff,
3753  op->remote_set_diff,
3754  op->
3756  op->
3759  {
3761  "PROTOCOL VIOLATION: Remote peer choose to request the full set first but correct mode would have been"
3762  " : %d\n", mode_of_operation);
3763  GNUNET_break_op (0);
3765  return;
3766  }
3767 
3768  // FIXME: we need to check that our set is larger than the
3769  // byzantine_lower_bound by some threshold
3770  send_full_set (op);
3771  GNUNET_CADET_receive_done (op->channel);
3772 }

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 3782 of file gnunet-service-setu.c.

3784 {
3785  struct Operation *op = cls;
3786 
3790  uint8_t allowed_phases[] = {PHASE_FULL_SENDING, PHASE_FULL_RECEIVING};
3791  if (GNUNET_OK !=
3792  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3793  {
3794  GNUNET_break (0);
3796  return;
3797  }
3798 
3799 #if MEASURE_PERFORMANCE
3800  perf_store.full_done.received += 1;
3801 #endif
3802 
3803  switch (op->phase)
3804  {
3805  case PHASE_FULL_RECEIVING:
3806  {
3807  struct GNUNET_MQ_Envelope *ev;
3808 
3809  if ((GNUNET_YES == op->byzantine) &&
3810  (op->received_total != op->remote_element_count) )
3811  {
3812  /* The other peer gave not enough elements before sending full done, there's something wrong. */
3814  "Other peer sent only %llu/%llu fresh elements, failing operation\n",
3815  (unsigned long long) op->received_total,
3816  (unsigned long long) op->remote_element_count);
3817  GNUNET_break_op (0);
3819  return;
3820  }
3821 
3823  "got FULL DONE, sending elements that other peer is missing\n");
3824 
3825  /* send all the elements that did not come from the remote peer */
3828  op);
3829 #if MEASURE_PERFORMANCE
3830  perf_store.full_done.sent += 1;
3831 #endif
3833  GNUNET_MQ_send (op->mq,
3834  ev);
3835  op->phase = PHASE_FINISHED;
3836  /* we now wait until the other peer sends us the OVER message*/
3837  }
3838  break;
3839 
3840  case PHASE_FULL_SENDING:
3841  {
3843  "got FULL DONE, finishing\n");
3844  /* We sent the full set, and got the response for that. We're done. */
3845  op->phase = PHASE_FINISHED;
3846  GNUNET_CADET_receive_done (op->channel);
3847  send_client_done (op);
3849  return;
3850  }
3851 
3852  default:
3854  "Handle full done phase is %u\n",
3855  (unsigned) op->phase);
3856  GNUNET_break_op (0);
3858  return;
3859  }
3860  GNUNET_CADET_receive_done (op->channel);
3861 }
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 3873 of file gnunet-service-setu.c.

3875 {
3876  struct Operation *op = cls;
3877  unsigned int num_hashes;
3878 
3879  (void) op;
3880  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
3881  / sizeof(struct GNUNET_HashCode);
3882  if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
3883  != num_hashes * sizeof(struct GNUNET_HashCode))
3884  {
3885  GNUNET_break_op (0);
3886  return GNUNET_SYSERR;
3887  }
3888  return GNUNET_OK;
3889 }

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 3900 of file gnunet-service-setu.c.

3902 {
3903  struct Operation *op = cls;
3904  struct ElementEntry *ee;
3905  struct GNUNET_SETU_ElementMessage *emsg;
3906  const struct GNUNET_HashCode *hash;
3907  unsigned int num_hashes;
3908  struct GNUNET_MQ_Envelope *ev;
3909 
3913  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING,
3915  if (GNUNET_OK !=
3916  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
3917  {
3918  GNUNET_break (0);
3920  return;
3921  }
3922 #if MEASURE_PERFORMANCE
3923  perf_store.demand.received += 1;
3924  perf_store.demand.received_var_bytes += (ntohs (mh->size) - sizeof(struct
3926 #endif
3927 
3928  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
3929  / sizeof(struct GNUNET_HashCode);
3930  for (hash = (const struct GNUNET_HashCode *) &mh[1];
3931  num_hashes > 0;
3932  hash++, num_hashes--)
3933  {
3934  ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
3935  hash);
3936  if (NULL == ee)
3937  {
3938  /* Demand for non-existing element. */
3939  GNUNET_break_op (0);
3941  return;
3942  }
3943 
3944  /* Save send demand message for message control */
3945  if (GNUNET_YES !=
3947  op->message_control_flow,
3949  &ee->element_hash,
3951  )
3952  {
3954  "Double demand message received found!\n");
3955  GNUNET_break (0);
3957  return;
3958  }
3959  ;
3960 
3961  /* Mark element to be expected to received */
3962  if (GNUNET_YES !=
3964  op->message_control_flow,
3965  MSG_CFS_SENT,
3966  &ee->element_hash,
3968  )
3969  {
3971  "Double element message sent found!\n");
3972  GNUNET_break (0);
3974  return;
3975  }
3977  {
3978  /* Probably confused lazily copied sets. */
3979  GNUNET_break_op (0);
3981  return;
3982  }
3983 #if MEASURE_PERFORMANCE
3984  perf_store.element.sent += 1;
3985  perf_store.element.sent_var_bytes += ee->element.size;
3986 #endif
3987  ev = GNUNET_MQ_msg_extra (emsg,
3988  ee->element.size,
3990  GNUNET_memcpy (&emsg[1],
3991  ee->element.data,
3992  ee->element.size);
3993  emsg->reserved = htons (0);
3994  emsg->element_type = htons (ee->element.element_type);
3996  "[OP %p] Sending demanded element (size %u, hash %s) to peer\n",
3997  op,
3998  (unsigned int) ee->element.size,
3999  GNUNET_h2s (&ee->element_hash));
4000  GNUNET_MQ_send (op->mq, ev);
4002  "# exchanged elements",
4003  1,
4004  GNUNET_NO);
4005  if (op->symmetric)
4007  &ee->element,
4009  }
4010  GNUNET_CADET_receive_done (op->channel);
4011  maybe_finish (op);
4012 }
#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 4023 of file gnunet-service-setu.c.

4025 {
4026  struct Operation *op = cls;
4027  unsigned int num_hashes;
4028 
4029  /* look up elements and send them */
4030  if ((op->phase != PHASE_PASSIVE_DECODING) &&
4031  (op->phase != PHASE_ACTIVE_DECODING))
4032  {
4033  GNUNET_break_op (0);
4034  return GNUNET_SYSERR;
4035  }
4036  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
4037  / sizeof(struct GNUNET_HashCode);
4038  if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader)) !=
4039  num_hashes * sizeof(struct GNUNET_HashCode))
4040  {
4041  GNUNET_break_op (0);
4042  return GNUNET_SYSERR;
4043  }
4044  return GNUNET_OK;
4045 }

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 4056 of file gnunet-service-setu.c.

4058 {
4059  struct Operation *op = cls;
4060  const struct GNUNET_HashCode *hash;
4061  unsigned int num_hashes;
4065  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING};
4066  if (GNUNET_OK !=
4067  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
4068  {
4069  GNUNET_break (0);
4071  return;
4072  }
4073 
4074 #if MEASURE_PERFORMANCE
4075  perf_store.offer.received += 1;
4076  perf_store.offer.received_var_bytes += (ntohs (mh->size) - sizeof(struct
4078 #endif
4079 
4080  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
4081  / sizeof(struct GNUNET_HashCode);
4082  for (hash = (const struct GNUNET_HashCode *) &mh[1];
4083  num_hashes > 0;
4084  hash++, num_hashes--)
4085  {
4086  struct ElementEntry *ee;
4087  struct GNUNET_MessageHeader *demands;
4088  struct GNUNET_MQ_Envelope *ev;
4089 
4090  ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
4091  hash);
4092  if (NULL != ee)
4094  continue;
4095 
4096  if (GNUNET_YES ==
4097  GNUNET_CONTAINER_multihashmap_contains (op->demanded_hashes,
4098  hash))
4099  {
4101  "Skipped sending duplicate demand\n");
4102  continue;
4103  }
4104 
4107  op->demanded_hashes,
4108  hash,
4109  NULL,
4111 
4113  "[OP %p] Requesting element (hash %s)\n",
4114  op, GNUNET_h2s (hash));
4115 
4116 #if MEASURE_PERFORMANCE
4117  perf_store.demand.sent += 1;
4118  perf_store.demand.sent_var_bytes += sizeof(struct GNUNET_HashCode);
4119 #endif
4120  /* Save send demand message for message control */
4121  if (GNUNET_YES !=
4123  op->message_control_flow,
4124  MSG_CFS_SENT,
4125  hash,
4126  DEMAND_MESSAGE))
4127  {
4129  "Double demand message sent found!\n");
4130  GNUNET_break (0);
4132  return;
4133  }
4134 
4135  /* Mark offer as received received */
4136  if (GNUNET_YES !=
4138  op->message_control_flow,
4140  hash,
4141  OFFER_MESSAGE))
4142  {
4144  "Double offer message received found!\n");
4145  GNUNET_break (0);
4147  return;
4148  }
4149  /* Mark element to be expected to received */
4150  if (GNUNET_YES !=
4152  op->message_control_flow,
4154  hash,
4155  ELEMENT_MESSAGE))
4156  {
4158  "Element already expected!\n");
4159  GNUNET_break (0);
4161  return;
4162  }
4163  ev = GNUNET_MQ_msg_header_extra (demands,
4164  sizeof(struct GNUNET_HashCode),
4166  GNUNET_memcpy (&demands[1],
4167  hash,
4168  sizeof(struct GNUNET_HashCode));
4169  GNUNET_MQ_send (op->mq, ev);
4170  }
4171  GNUNET_CADET_receive_done (op->channel);
4172 }
int 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 4182 of file gnunet-service-setu.c.

4184 {
4185  struct Operation *op = cls;
4186 
4190  uint8_t allowed_phases[] = {PHASE_ACTIVE_DECODING, PHASE_PASSIVE_DECODING};
4191  if (GNUNET_OK !=
4192  check_valid_phase (allowed_phases,sizeof(allowed_phases),op))
4193  {
4194  GNUNET_break (0);
4196  return;
4197  }
4198 
4199  if (op->active_passive_switch_required)
4200  {
4202  "PROTOCOL VIOLATION: Received done but role change is necessary\n");
4203  GNUNET_break (0);
4205  return;
4206  }
4207 
4208 #if MEASURE_PERFORMANCE
4209  perf_store.done.received += 1;
4210 #endif
4211  switch (op->phase)
4212  {
4214  /* We got all requests, but still have to send our elements in response. */
4215  op->phase = PHASE_FINISH_WAITING;
4217  "got DONE (as passive partner), waiting for our demands to be satisfied\n");
4218  /* The active peer is done sending offers
4219  * and inquiries. This means that all
4220  * our responses to that (demands and offers)
4221  * must be in flight (queued or in mesh).
4222  *
4223  * We should notify the active peer once
4224  * all our demands are satisfied, so that the active
4225  * peer can quit if we gave it everything.
4226  */GNUNET_CADET_receive_done (op->channel);
4227  maybe_finish (op);
4228  return;
4229  case PHASE_ACTIVE_DECODING:
4231  "got DONE (as active partner), waiting to finish\n");
4232  /* All demands of the other peer are satisfied,
4233  * and we processed all offers, thus we know
4234  * exactly what our demands must be.
4235  *
4236  * We'll close the channel
4237  * to the other peer once our demands are met.
4238  */op->phase = PHASE_FINISH_CLOSING;
4239  GNUNET_CADET_receive_done (op->channel);
4240  maybe_finish (op);
4241  return;
4242  default:
4243  GNUNET_break_op (0);
4245  return;
4246  }
4247 }

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 4257 of file gnunet-service-setu.c.

4259 {
4260 #if MEASURE_PERFORMANCE
4261  perf_store.over.received += 1;
4262 #endif
4263  send_client_done (cls);
4264 }

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 4276 of file gnunet-service-setu.c.

4277 {
4278  for (struct Listener *listener = listener_head;
4279  NULL != listener;
4280  listener = listener->next)
4281  {
4282  for (struct Operation *op = listener->op_head;
4283  NULL != op;
4284  op = op->next)
4285  if (op->suggest_id == id)
4286  return op;
4287  }
4288  return NULL;
4289 }
static struct Listener * listener_head
Listeners are held in a doubly linked list.
struct GNUNET_ARM_Operation * next
This is a doubly-linked list.
Definition: arm_api.c:45
struct Listener * next
Listeners are held in a doubly linked list.

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

Referenced by handle_client_accept(), and handle_client_reject().

Here is the caller graph for this function:

◆ client_connect_cb()

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

Callback called when a client connects to the service.

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

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

4304 {
4305  struct ClientState *cs;
4306 
4307  num_clients++;
4308  cs = GNUNET_new (struct ClientState);
4309  cs->client = c;
4310  cs->mq = mq;
4311  return cs;
4312 }
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 4324 of file gnunet-service-setu.c.

4327 {
4328  struct ElementEntry *ee = value;
4329 
4330  GNUNET_free (ee);
4331  return GNUNET_YES;
4332 }

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 4343 of file gnunet-service-setu.c.

4346 {
4347  struct ClientState *cs = internal_cls;
4348  struct Operation *op;
4349  struct Listener *listener;
4350  struct Set *set;
4351 
4353  "Client disconnected, cleaning up\n");
4354  if (NULL != (set = cs->set))
4355  {
4356  struct SetContent *content = set->content;
4357 
4359  "Destroying client's set\n");
4360  /* Destroy pending set operations */
4361  while (NULL != set->ops_head)
4363 
4364  /* Destroy operation-specific state */
4365  if (NULL != set->se)
4366  {
4368  set->se = NULL;
4369  }
4370  /* free set content (or at least decrement RC) */
4371  set->content = NULL;
4372  GNUNET_assert (0 != content->refcount);
4373  content->refcount--;
4374  if (0 == content->refcount)
4375  {
4376  GNUNET_assert (NULL != content->elements);
4379  NULL);
4381  content->elements = NULL;
4382  GNUNET_free (content);
4383  }
4384  GNUNET_free (set);
4385  }
4386 
4387  if (NULL != (listener = cs->listener))
4388  {
4390  "Destroying client's listener\n");
4391  GNUNET_CADET_close_port (listener->open_port);
4392  listener->open_port = NULL;
4393  while (NULL != (op = listener->op_head))
4394  {
4396  "Destroying incoming operation `%u' from peer `%s'\n",
4397  (unsigned int) op->client_request_id,
4398  GNUNET_i2s (&op->peer));
4399  incoming_destroy (op);
4400  }
4402  listener_tail,
4403  listener);
4404  GNUNET_free (listener);
4405  }
4406  GNUNET_free (cs);
4407  num_clients--;
4408  if ( (GNUNET_YES == in_shutdown) &&
4409  (0 == num_clients) )
4410  {
4411  if (NULL != cadet)
4412  {
4414  cadet = NULL;
4415  }
4416  }
4417 }
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:775
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port().
Definition: cadet_api.c:808
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 4429 of file gnunet-service-setu.c.

4431 {
4432  struct Operation *op = cls;
4433  struct Listener *listener = op->listener;
4434  const struct GNUNET_MessageHeader *nested_context;
4435 
4436  /* double operation request */
4437  if (0 != op->suggest_id)
4438  {
4439  GNUNET_break_op (0);
4440  return GNUNET_SYSERR;
4441  }
4442  /* This should be equivalent to the previous condition, but can't hurt to check twice */
4443  if (NULL == listener)
4444  {
4445  GNUNET_break (0);
4446  return GNUNET_SYSERR;
4447  }
4448  nested_context = GNUNET_MQ_extract_nested_mh (msg);
4449  if ((NULL != nested_context) &&
4450  (ntohs (nested_context->size) > GNUNET_SETU_CONTEXT_MESSAGE_MAX_SIZE))
4451  {
4452  GNUNET_break_op (0);
4453  return GNUNET_SYSERR;
4454  }
4455  return GNUNET_OK;
4456 }
#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 4475 of file gnunet-service-setu.c.

4477 {
4478  struct Operation *op = cls;
4479  struct Listener *listener = op->listener;
4480  const struct GNUNET_MessageHeader *nested_context;
4481  struct GNUNET_MQ_Envelope *env;
4482  struct GNUNET_SETU_RequestMessage *cmsg;
4483 
4484  nested_context = GNUNET_MQ_extract_nested_mh (msg);
4485  /* Make a copy of the nested_context (application-specific context
4486  information that is opaque to set) so we can pass it to the
4487  listener later on */
4488  if (NULL != nested_context)
4489  op->context_msg = GNUNET_copy_message (nested_context);
4490  op->remote_element_count = ntohl (msg->element_count);
4491  GNUNET_log (
4493  "Received P2P operation request (port %s) for active listener\n",
4494  GNUNET_h2s (&op->listener->app_id));
4495  GNUNET_assert (0 == op->suggest_id);
4496  if (0 == suggest_id)
4497  suggest_id++;
4498  op->suggest_id = suggest_id++;
4499  GNUNET_assert (NULL != op->timeout_task);
4500  GNUNET_SCHEDULER_cancel (op->timeout_task);
4501  op->timeout_task = NULL;
4502