GNUnet  0.10.x
Functions
gnunet-service-set_union.h File Reference

two-peer set operations More...

#include "gnunet-service-set.h"
#include "gnunet-service-set_protocol.h"
Include dependency graph for gnunet-service-set_union.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int check_union_p2p_strata_estimator (void *cls, const struct StrataEstimatorMessage *msg)
 Handle a strata estimator from a remote peer. More...
 
void handle_union_p2p_strata_estimator (void *cls, const struct StrataEstimatorMessage *msg)
 Handle a strata estimator from a remote peer. More...
 
int check_union_p2p_ibf (void *cls, const struct IBFMessage *msg)
 Check an IBF message from a remote peer. More...
 
void handle_union_p2p_ibf (void *cls, const struct IBFMessage *msg)
 Handle an IBF message from a remote peer. More...
 
int check_union_p2p_elements (void *cls, const struct GNUNET_SET_ElementMessage *emsg)
 Check an element message from a remote peer. More...
 
void handle_union_p2p_elements (void *cls, const struct GNUNET_SET_ElementMessage *emsg)
 Handle an element message from a remote peer. More...
 
int check_union_p2p_full_element (void *cls, const struct GNUNET_SET_ElementMessage *emsg)
 Check a full element message from a remote peer. More...
 
void handle_union_p2p_full_element (void *cls, const struct GNUNET_SET_ElementMessage *emsg)
 Handle an element message from a remote peer. More...
 
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...
 
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...
 
void handle_union_p2p_request_full (void *cls, const struct GNUNET_MessageHeader *mh)
 Handle a request for full set transmission. More...
 
void handle_union_p2p_full_done (void *cls, const struct GNUNET_MessageHeader *mh)
 Handle a "full done" message. More...
 
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...
 
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...
 
int check_union_p2p_offer (void *cls, const struct GNUNET_MessageHeader *mh)
 Check offer (of struct GNUNET_HashCodes). More...
 
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...
 
void handle_union_p2p_done (void *cls, const struct GNUNET_MessageHeader *mh)
 Handle a done message from a remote peer. More...
 
void handle_union_p2p_over (void *cls, const struct GNUNET_MessageHeader *mh)
 Handle an over message from a remote peer. More...
 

Detailed Description

two-peer set operations

Author
Florian Dold
Christian Grothoff

Definition in file gnunet-service-set_union.h.

Function Documentation

◆ check_union_p2p_strata_estimator()

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

Handle a strata estimator from a remote peer.

Parameters
clsthe union operation
msgthe message

Definition at line 815 of file gnunet-service-set_union.c.

References GNUNET_break, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, StrataEstimatorMessage::header, IBF_BUCKET_SIZE, len, op, OperationState::phase, PHASE_EXPECT_SE, SE_IBF_SIZE, SE_STRATA_COUNT, GNUNET_MessageHeader::size, Operation::state, and GNUNET_MessageHeader::type.

817 {
818  struct Operation *op = cls;
819  int is_compressed;
820  size_t len;
821 
822  if (op->state->phase != PHASE_EXPECT_SE)
823  {
824  GNUNET_break(0);
825  return GNUNET_SYSERR;
826  }
827  is_compressed = (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC == htons(msg->header.type));
828  len = ntohs(msg->header.size) - sizeof(struct StrataEstimatorMessage);
829  if ((GNUNET_NO == is_compressed) &&
831  {
832  GNUNET_break(0);
833  return GNUNET_SYSERR;
834  }
835  return GNUNET_OK;
836 }
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE(C)
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
We sent the request message, and expect a strata estimator.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC
Compressed strata estimator.
enum IntersectionOperationPhase phase
Current state of the operation.
#define IBF_BUCKET_SIZE
Size of one ibf bucket in bytes.
Definition: ibf.h:69
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
Strata estimator together with the peer's overall set size.
Operation context used to execute a set operation.
#define SE_IBF_SIZE
Size of the IBFs in the strata estimator.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
#define SE_STRATA_COUNT
Number of IBFs in a strata estimator.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...

◆ handle_union_p2p_strata_estimator()

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

Handle a strata estimator from a remote peer.

Parameters
clsthe union operation
msgthe message

Definition at line 846 of file gnunet-service-set_union.c.

References _GSS_statistics, Operation::byzantine, Operation::channel, removetrailingwhitespace::f, fail_union_operation(), Operation::force_full, get_order_from_difference(), getenv(), GNUNET_assert, GNUNET_break, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC, GNUNET_MQ_msg_header, GNUNET_MQ_send(), GNUNET_NO, GNUNET_ntohll(), GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_YES, StrataEstimatorMessage::header, OperationState::initial_size, len, LOG, Operation::mq, op, OperationState::phase, PHASE_EXPECT_IBF, OperationState::se, SE_IBF_HASH_NUM, SE_IBF_SIZE, SE_STRATA_COUNT, send_full_set(), send_ibf(), StrataEstimatorMessage::set_size, GNUNET_MessageHeader::size, Operation::state, strata_estimator_create(), strata_estimator_destroy(), strata_estimator_difference(), strata_estimator_read(), and GNUNET_MessageHeader::type.

848 {
849  struct Operation *op = cls;
850  struct StrataEstimator *remote_se;
851  unsigned int diff;
852  uint64_t other_size;
853  size_t len;
854  int is_compressed;
855 
856  is_compressed = (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC == htons(msg->header.type));
858  "# bytes of SE received",
859  ntohs(msg->header.size),
860  GNUNET_NO);
861  len = ntohs(msg->header.size) - sizeof(struct StrataEstimatorMessage);
862  other_size = GNUNET_ntohll(msg->set_size);
864  SE_IBF_SIZE,
866  if (NULL == remote_se)
867  {
868  /* insufficient resources, fail */
870  return;
871  }
872  if (GNUNET_OK !=
873  strata_estimator_read(&msg[1],
874  len,
875  is_compressed,
876  remote_se))
877  {
878  /* decompression failed */
879  strata_estimator_destroy(remote_se);
881  return;
882  }
883  GNUNET_assert(NULL != op->state->se);
884  diff = strata_estimator_difference(remote_se,
885  op->state->se);
886 
887  if (diff > 200)
888  diff = diff * 3 / 2;
889 
890  strata_estimator_destroy(remote_se);
892  op->state->se = NULL;
894  "got se diff=%d, using ibf size %d\n",
895  diff,
896  1U << get_order_from_difference(diff));
897 
898  {
899  char *set_debug;
900 
901  set_debug = getenv("GNUNET_SET_BENCHMARK");
902  if ((NULL != set_debug) &&
903  (0 == strcmp(set_debug, "1")))
904  {
905  FILE *f = fopen("set.log", "a");
906  fprintf(f, "%llu\n", (unsigned long long)diff);
907  fclose(f);
908  }
909  }
910 
911  if ((GNUNET_YES == op->byzantine) &&
912  (other_size < op->byzantine_lower_bound))
913  {
914  GNUNET_break(0);
916  return;
917  }
918 
919  if ((GNUNET_YES == op->force_full) ||
920  (diff > op->state->initial_size / 4) ||
921  (0 == other_size))
922  {
924  "Deciding to go for full set transmission (diff=%d, own set=%u)\n",
925  diff,
926  op->state->initial_size);
928  "# of full sends",
929  1,
930  GNUNET_NO);
931  if ((op->state->initial_size <= other_size) ||
932  (0 == other_size))
933  {
934  send_full_set(op);
935  }
936  else
937  {
938  struct GNUNET_MQ_Envelope *ev;
939 
941  "Telling other peer that we expect its full set\n");
944  GNUNET_MQ_send(op->mq,
945  ev);
946  }
947  }
948  else
949  {
951  "# of ibf sends",
952  1,
953  GNUNET_NO);
954  if (GNUNET_OK !=
955  send_ibf(op,
957  {
958  /* Internal error, best we can do is shut the connection */
960  "Failed to send IBF, closing connection\n");
962  return;
963  }
964  }
966 }
We sent the strata estimator, and expect an IBF.
#define LOG(kind,...)
static unsigned int get_order_from_difference(unsigned int diff)
Compute the necessary order of an ibf from the size of the symmetric set difference.
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.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_CADET_Channel * channel
Channel to the peer.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE(C)
#define GNUNET_NO
Definition: gnunet_common.h:78
uint64_t initial_size
Initial size of our set, just before the operation started.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
A handle to a strata estimator.
struct GNUNET_STATISTICS_Handle * _GSS_statistics
Statistics handle.
static int send_ibf(struct Operation *op, uint16_t ibf_order)
Send an ibf of appropriate size.
struct StrataEstimator * se
Copy of the set&#39;s strata estimator at the time of creation of this operation.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC
Compressed strata estimator.
void strata_estimator_destroy(struct StrataEstimator *se)
Destroy a strata estimator, free all of its resources.
enum IntersectionOperationPhase phase
Current state of the operation.
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 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL
Demand the whole element from the other peer, given only the hash code.
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.
int byzantine
GNUNET_YES to fail operations where Byzantine faults are suspected
char * getenv()
Strata estimator together with the peer&#39;s overall set size.
unsigned int strata_estimator_difference(const struct StrataEstimator *se1, const struct StrataEstimator *se2)
Estimate set difference with two strata estimators, i.e.
Operation context used to execute a set operation.
#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
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:951
struct GNUNET_MQ_Handle * mq
Message queue for the channel.
#define SE_IBF_SIZE
Size of the IBFs in the strata estimator.
#define SE_IBF_HASH_NUM
The hash num parameter for the difference digests and strata estimators.
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
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:351
static void send_full_set(struct Operation *op)
Switch to full set transmission for op.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
#define SE_STRATA_COUNT
Number of IBFs in a strata estimator.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
int force_full
Always send full sets, even if delta operations would be more efficient.
Here is the call graph for this function:

◆ check_union_p2p_ibf()

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

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 1199 of file gnunet-service-set_union.c.

References GNUNET_break_op, GNUNET_OK, GNUNET_SET_OPERATION_UNION, GNUNET_SYSERR, IBFMessage::header, IBF_BUCKET_SIZE, OperationState::ibf_buckets_received, msg, IBFMessage::offset, op, Set::operation, IBFMessage::order, OperationState::phase, PHASE_EXPECT_IBF, PHASE_EXPECT_IBF_CONT, PHASE_INVENTORY_PASSIVE, OperationState::remote_ibf, IBFMessage::salt, OperationState::salt_receive, Operation::set, InvertibleBloomFilter::size, GNUNET_MessageHeader::size, and Operation::state.

1201 {
1202  struct Operation *op = cls;
1203  unsigned int buckets_in_message;
1204 
1206  {
1207  GNUNET_break_op(0);
1208  return GNUNET_SYSERR;
1209  }
1210  buckets_in_message = (ntohs(msg->header.size) - sizeof *msg) / IBF_BUCKET_SIZE;
1211  if (0 == buckets_in_message)
1212  {
1213  GNUNET_break_op(0);
1214  return GNUNET_SYSERR;
1215  }
1216  if ((ntohs(msg->header.size) - sizeof *msg) != buckets_in_message * IBF_BUCKET_SIZE)
1217  {
1218  GNUNET_break_op(0);
1219  return GNUNET_SYSERR;
1220  }
1221  if (op->state->phase == PHASE_EXPECT_IBF_CONT)
1222  {
1223  if (ntohl(msg->offset) != op->state->ibf_buckets_received)
1224  {
1225  GNUNET_break_op(0);
1226  return GNUNET_SYSERR;
1227  }
1228  if (1 << msg->order != op->state->remote_ibf->size)
1229  {
1230  GNUNET_break_op(0);
1231  return GNUNET_SYSERR;
1232  }
1233  if (ntohl(msg->salt) != op->state->salt_receive)
1234  {
1235  GNUNET_break_op(0);
1236  return GNUNET_SYSERR;
1237  }
1238  }
1239  else if ((op->state->phase != PHASE_INVENTORY_PASSIVE) &&
1240  (op->state->phase != PHASE_EXPECT_IBF))
1241  {
1242  GNUNET_break_op(0);
1243  return GNUNET_SYSERR;
1244  }
1245 
1246  return GNUNET_OK;
1247 }
We sent the strata estimator, and expect an IBF.
uint32_t offset
Offset of the strata in the rest of the message.
The other peer is decoding the IBF we just sent.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
struct InvertibleBloomFilter * remote_ibf
The IBF we currently receive.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
uint32_t size
How many cells does this IBF have?
Definition: ibf.h:83
uint32_t salt_receive
Salt for the IBF we&#39;ve received and that we&#39;re currently decoding.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
uint8_t order
Order of the whole ibf, where num_buckets = 2^order.
enum IntersectionOperationPhase phase
Current state of the operation.
#define IBF_BUCKET_SIZE
Size of one ibf bucket in bytes.
Definition: ibf.h:69
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF.
unsigned int ibf_buckets_received
Number of ibf buckets already received into the remote_ibf.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
enum GNUNET_SET_OperationType operation
Type of operation supported for this set.
Operation context used to execute a set operation.
uint32_t salt
Salt used when hashing elements for this IBF.
Continuation for multi part IBFs.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Set union, return all elements that are in at least one of the sets.

◆ handle_union_p2p_ibf()

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

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

Definition at line 1260 of file gnunet-service-set_union.c.

References Operation::channel, decode_and_send(), fail_union_operation(), GNUNET_assert, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, IBFMessage::header, IBF_BUCKET_SIZE, OperationState::ibf_buckets_received, ibf_create(), ibf_read_slice(), LOG, msg, IBFMessage::offset, op, IBFMessage::order, OperationState::phase, PHASE_EXPECT_IBF, PHASE_EXPECT_IBF_CONT, PHASE_INVENTORY_ACTIVE, PHASE_INVENTORY_PASSIVE, OperationState::remote_ibf, IBFMessage::salt, OperationState::salt_receive, SE_IBF_HASH_NUM, InvertibleBloomFilter::size, GNUNET_MessageHeader::size, and Operation::state.

1262 {
1263  struct Operation *op = cls;
1264  unsigned int buckets_in_message;
1265 
1266  buckets_in_message = (ntohs(msg->header.size) - sizeof *msg) / IBF_BUCKET_SIZE;
1267  if ((op->state->phase == PHASE_INVENTORY_PASSIVE) ||
1268  (op->state->phase == PHASE_EXPECT_IBF))
1269  {
1271  GNUNET_assert(NULL == op->state->remote_ibf);
1273  "Creating new ibf of size %u\n",
1274  1 << msg->order);
1275  op->state->remote_ibf = ibf_create(1 << msg->order, SE_IBF_HASH_NUM);
1276  op->state->salt_receive = ntohl(msg->salt);
1278  "Receiving new IBF with salt %u\n",
1279  op->state->salt_receive);
1280  if (NULL == op->state->remote_ibf)
1281  {
1283  "Failed to parse remote IBF, closing connection\n");
1285  return;
1286  }
1287  op->state->ibf_buckets_received = 0;
1288  if (0 != ntohl(msg->offset))
1289  {
1290  GNUNET_break_op(0);
1292  return;
1293  }
1294  }
1295  else
1296  {
1299  "Received more of IBF\n");
1300  }
1301  GNUNET_assert(NULL != op->state->remote_ibf);
1302 
1303  ibf_read_slice(&msg[1],
1305  buckets_in_message,
1306  op->state->remote_ibf);
1307  op->state->ibf_buckets_received += buckets_in_message;
1308 
1309  if (op->state->ibf_buckets_received == op->state->remote_ibf->size)
1310  {
1312  "received full ibf\n");
1314  if (GNUNET_OK !=
1315  decode_and_send(op))
1316  {
1317  /* Internal error, best we can do is shut down */
1319  "Failed to decode IBF, closing connection\n");
1321  return;
1322  }
1323  }
1325 }
We sent the strata estimator, and expect an IBF.
uint32_t offset
Offset of the strata in the rest of the message.
The other peer is decoding the IBF we just sent.
#define LOG(kind,...)
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct InvertibleBloomFilter * remote_ibf
The IBF we currently receive.
We are decoding an IBF.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_CADET_Channel * channel
Channel to the peer.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
uint32_t size
How many cells does this IBF have?
Definition: ibf.h:83
uint32_t salt_receive
Salt for the IBF we&#39;ve received and that we&#39;re currently decoding.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
static int decode_and_send(struct Operation *op)
Decode which elements are missing on each side, and send the appropriate offers and inquiries...
uint8_t order
Order of the whole ibf, where num_buckets = 2^order.
enum IntersectionOperationPhase phase
Current state of the operation.
#define IBF_BUCKET_SIZE
Size of one ibf bucket in bytes.
Definition: ibf.h:69
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF.
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation...
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:318
unsigned int ibf_buckets_received
Number of ibf buckets already received into the remote_ibf.
struct InvertibleBloomFilter * ibf_create(uint32_t size, uint8_t hash_num)
Create an invertible bloom filter.
Definition: ibf.c:76
Operation context used to execute a set operation.
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:951
uint32_t salt
Salt used when hashing elements for this IBF.
#define SE_IBF_HASH_NUM
The hash num parameter for the difference digests and strata estimators.
Continuation for multi part IBFs.
#define GNUNET_log(kind,...)
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Here is the call graph for this function:

◆ check_union_p2p_elements()

int check_union_p2p_elements ( void *  cls,
const struct GNUNET_SET_ElementMessage emsg 
)

Check an element message from a remote peer.

Parameters
clsthe union operation
emsgthe message

Definition at line 1472 of file gnunet-service-set_union.c.

References OperationState::demanded_hashes, GNUNET_break_op, GNUNET_CONTAINER_multihashmap_size(), GNUNET_OK, GNUNET_SET_OPERATION_UNION, GNUNET_SYSERR, op, Set::operation, Operation::set, and Operation::state.

1474 {
1475  struct Operation *op = cls;
1476 
1478  {
1479  GNUNET_break_op(0);
1480  return GNUNET_SYSERR;
1481  }
1483  {
1484  GNUNET_break_op(0);
1485  return GNUNET_SYSERR;
1486  }
1487  return GNUNET_OK;
1488 }
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
enum GNUNET_SET_OperationType operation
Type of operation supported for this set.
Operation context used to execute a set operation.
struct GNUNET_CONTAINER_MultiHashMap * demanded_hashes
Hashes for elements that we have demanded from the other peer.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Set union, return all elements that are in at least one of the sets.
Here is the call graph for this function:

◆ handle_union_p2p_elements()

void handle_union_p2p_elements ( void *  cls,
const struct GNUNET_SET_ElementMessage emsg 
)

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

Definition at line 1500 of file gnunet-service-set_union.c.

References _GSS_statistics, Operation::channel, GNUNET_SET_Element::data, OperationState::demanded_hashes, ElementEntry::element, ElementEntry::element_hash, element_size, GNUNET_SET_Element::element_type, GNUNET_SET_ElementMessage::element_type, fail_union_operation(), GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_h2s(), GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_SET_element_hash(), GNUNET_SET_RESULT_ADDED, GNUNET_SET_RESULT_SYMMETRIC, GNUNET_SET_STATUS_ADD_LOCAL, GNUNET_SET_STATUS_OK, GNUNET_STATISTICS_update(), GNUNET_YES, GNUNET_SET_ElementMessage::header, LOG, maybe_finish(), op, op_get_element(), op_register_element(), KeyEntry::received, OperationState::received_fresh, OperationState::received_total, ElementEntry::remote, Operation::result_mode, send_client_element(), GNUNET_SET_Element::size, GNUNET_MessageHeader::size, and Operation::state.

1502 {
1503  struct Operation *op = cls;
1504  struct ElementEntry *ee;
1505  struct KeyEntry *ke;
1506  uint16_t element_size;
1507 
1508  element_size = ntohs(emsg->header.size) - sizeof(struct GNUNET_SET_ElementMessage);
1509  ee = GNUNET_malloc(sizeof(struct ElementEntry) + element_size);
1510  GNUNET_memcpy(&ee[1],
1511  &emsg[1],
1512  element_size);
1513  ee->element.size = element_size;
1514  ee->element.data = &ee[1];
1515  ee->element.element_type = ntohs(emsg->element_type);
1516  ee->remote = GNUNET_YES;
1518  &ee->element_hash);
1519  if (GNUNET_NO ==
1521  &ee->element_hash,
1522  NULL))
1523  {
1524  /* We got something we didn't demand, since it's not in our map. */
1525  GNUNET_break_op(0);
1527  return;
1528  }
1529 
1531  "Got element (size %u, hash %s) from peer\n",
1532  (unsigned int)element_size,
1533  GNUNET_h2s(&ee->element_hash));
1534 
1536  "# received elements",
1537  1,
1538  GNUNET_NO);
1540  "# exchanged elements",
1541  1,
1542  GNUNET_NO);
1543 
1544  op->state->received_total++;
1545 
1546  ke = op_get_element(op, &ee->element_hash);
1547  if (NULL != ke)
1548  {
1549  /* Got repeated element. Should not happen since
1550  * we track demands. */
1552  "# repeated elements",
1553  1,
1554  GNUNET_NO);
1555  ke->received = GNUNET_YES;
1556  GNUNET_free(ee);
1557  }
1558  else
1559  {
1561  "Registering new element from remote peer\n");
1562  op->state->received_fresh++;
1564  /* only send results immediately if the client wants it */
1565  switch (op->result_mode)
1566  {
1569  break;
1570 
1573  break;
1574 
1575  default:
1576  /* Result mode not supported, should have been caught earlier. */
1577  GNUNET_break(0);
1578  break;
1579  }
1580  }
1581 
1582  if ((op->state->received_total > 8) &&
1583  (op->state->received_fresh < op->state->received_total / 3))
1584  {
1585  /* The other peer gave us lots of old elements, there's something wrong. */
1586  GNUNET_break_op(0);
1588  return;
1589  }
1591  maybe_finish(op);
1592 }
Client gets only elements that have been added to the set.
#define LOG(kind,...)
enum GNUNET_SET_ResultMode result_mode
When are elements sent to the client, and which elements are sent?
uint32_t received_fresh
Number of elements we received from the other peer that were not in the local set yet...
static unsigned int element_size
int received
Did we receive this element? Even if element->is_foreign is false, we might have received the element...
struct GNUNET_HashCode element_hash
Hash of the element.
Element should be added to the result set of the local peer, i.e.
struct GNUNET_CADET_Channel * channel
Channel to the peer.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_ADD or GNUNET_MESSAGE_TYPE_SET_REMOVE.
Definition: set.h:278
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_NO
Definition: gnunet_common.h:78
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1241
uint16_t element_type
Type of the element to add or remove.
Definition: set.h:283
const void * data
Actual data of the element.
struct GNUNET_STATISTICS_Handle * _GSS_statistics
Statistics handle.
The key entry is used to associate an ibf key with an element.
uint32_t received_total
Total number of elements received from the other peer.
Information about an element element in the set.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
Everything went ok, we are transmitting an element of the result (in set, or to be removed from set...
int remote
GNUNET_YES if the element is a remote element, and does not belong to the operation&#39;s set...
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.
Client gets notified of the required changes for both the local and the remote set.
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation...
static void op_register_element(struct Operation *op, struct ElementEntry *ee, int received)
Insert an element into the union operation&#39;s key-to-element mapping.
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&#39;s element set.
Operation context used to execute a set operation.
static void send_client_element(struct Operation *op, struct GNUNET_SET_Element *element, int status)
Send a result message to the client indicating that there is a new element.
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:951
static void maybe_finish(struct Operation *op)
Tests if the operation is finished, and if so notify.
uint16_t size
Number of bytes in the buffer pointed to by data.
Message sent by client to the service to add or remove an element to/from the set.
Definition: set.h:273
struct GNUNET_SET_Element element
The actual element.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_CONTAINER_MultiHashMap * demanded_hashes
Hashes for elements that we have demanded from the other peer.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t element_type
Application-specific element type.
Here is the call graph for this function:

◆ check_union_p2p_full_element()

int check_union_p2p_full_element ( void *  cls,
const struct GNUNET_SET_ElementMessage emsg 
)

Check a full element message from a remote peer.

Parameters
clsthe union operation
emsgthe message

Definition at line 1602 of file gnunet-service-set_union.c.

References GNUNET_break_op, GNUNET_OK, GNUNET_SET_OPERATION_UNION, GNUNET_SYSERR, op, Set::operation, and Operation::set.

1604 {
1605  struct Operation *op = cls;
1606 
1608  {
1609  GNUNET_break_op(0);
1610  return GNUNET_SYSERR;
1611  }
1612  // FIXME: check that we expect full elements here?
1613  return GNUNET_OK;
1614 }
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
enum GNUNET_SET_OperationType operation
Type of operation supported for this set.
Operation context used to execute a set operation.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Set union, return all elements that are in at least one of the sets.

◆ handle_union_p2p_full_element()

void handle_union_p2p_full_element ( void *  cls,
const struct GNUNET_SET_ElementMessage emsg 
)

Handle an element message from a remote peer.

Parameters
clsthe union operation
emsgthe message

Definition at line 1624 of file gnunet-service-set_union.c.

References _GSS_statistics, Operation::byzantine, Operation::channel, GNUNET_SET_Element::data, ElementEntry::element, ElementEntry::element_hash, element_size, GNUNET_SET_Element::element_type, GNUNET_SET_ElementMessage::element_type, fail_union_operation(), 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_SET_element_hash(), GNUNET_SET_RESULT_ADDED, GNUNET_SET_RESULT_SYMMETRIC, GNUNET_SET_STATUS_ADD_LOCAL, GNUNET_SET_STATUS_OK, GNUNET_STATISTICS_update(), GNUNET_YES, GNUNET_SET_ElementMessage::header, LOG, op, op_get_element(), op_register_element(), KeyEntry::received, OperationState::received_fresh, OperationState::received_total, ElementEntry::remote, Operation::result_mode, send_client_element(), GNUNET_SET_Element::size, GNUNET_MessageHeader::size, and Operation::state.

1626 {
1627  struct Operation *op = cls;
1628  struct ElementEntry *ee;
1629  struct KeyEntry *ke;
1630  uint16_t element_size;
1631 
1632  element_size = ntohs(emsg->header.size) - sizeof(struct GNUNET_SET_ElementMessage);
1633  ee = GNUNET_malloc(sizeof(struct ElementEntry) + element_size);
1634  GNUNET_memcpy(&ee[1], &emsg[1], element_size);
1635  ee->element.size = element_size;
1636  ee->element.data = &ee[1];
1637  ee->element.element_type = ntohs(emsg->element_type);
1638  ee->remote = GNUNET_YES;
1640 
1642  "Got element (full diff, size %u, hash %s) from peer\n",
1643  (unsigned int)element_size,
1644  GNUNET_h2s(&ee->element_hash));
1645 
1647  "# received elements",
1648  1,
1649  GNUNET_NO);
1651  "# exchanged elements",
1652  1,
1653  GNUNET_NO);
1654 
1655  op->state->received_total++;
1656 
1657  ke = op_get_element(op, &ee->element_hash);
1658  if (NULL != ke)
1659  {
1660  /* Got repeated element. Should not happen since
1661  * we track demands. */
1663  "# repeated elements",
1664  1,
1665  GNUNET_NO);
1666  ke->received = GNUNET_YES;
1667  GNUNET_free(ee);
1668  }
1669  else
1670  {
1672  "Registering new element from remote peer\n");
1673  op->state->received_fresh++;
1675  /* only send results immediately if the client wants it */
1676  switch (op->result_mode)
1677  {
1680  break;
1681 
1684  break;
1685 
1686  default:
1687  /* Result mode not supported, should have been caught earlier. */
1688  GNUNET_break(0);
1689  break;
1690  }
1691  }
1692 
1693  if ((GNUNET_YES == op->byzantine) &&
1694  (op->state->received_total > 384 + op->state->received_fresh * 4) &&
1695  (op->state->received_fresh < op->state->received_total / 6))
1696  {
1697  /* The other peer gave us lots of old elements, there's something wrong. */
1699  "Other peer sent only %llu/%llu fresh elements, failing operation\n",
1700  (unsigned long long)op->state->received_fresh,
1701  (unsigned long long)op->state->received_total);
1702  GNUNET_break_op(0);
1704  return;
1705  }
1707 }
Client gets only elements that have been added to the set.
#define LOG(kind,...)
enum GNUNET_SET_ResultMode result_mode
When are elements sent to the client, and which elements are sent?
uint32_t received_fresh
Number of elements we received from the other peer that were not in the local set yet...
static unsigned int element_size
int received
Did we receive this element? Even if element->is_foreign is false, we might have received the element...
struct GNUNET_HashCode element_hash
Hash of the element.
Element should be added to the result set of the local peer, i.e.
struct GNUNET_CADET_Channel * channel
Channel to the peer.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_ADD or GNUNET_MESSAGE_TYPE_SET_REMOVE.
Definition: set.h:278
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_NO
Definition: gnunet_common.h:78
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void GNUNET_SET_element_hash(const struct GNUNET_SET_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition: set_api.c:1241
uint16_t element_type
Type of the element to add or remove.
Definition: set.h:283
const void * data
Actual data of the element.
struct GNUNET_STATISTICS_Handle * _GSS_statistics
Statistics handle.
The key entry is used to associate an ibf key with an element.
uint32_t received_total
Total number of elements received from the other peer.
Information about an element element in the set.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
Everything went ok, we are transmitting an element of the result (in set, or to be removed from set...
int remote
GNUNET_YES if the element is a remote element, and does not belong to the operation&#39;s set...
Client gets notified of the required changes for both the local and the remote set.
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation...
static void op_register_element(struct Operation *op, struct ElementEntry *ee, int received)
Insert an element into the union operation&#39;s key-to-element mapping.
int byzantine
GNUNET_YES to fail operations where Byzantine faults are suspected
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&#39;s element set.
Operation context used to execute a set operation.
static void send_client_element(struct Operation *op, struct GNUNET_SET_Element *element, int status)
Send a result message to the client indicating that there is a new element.
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:951
uint16_t size
Number of bytes in the buffer pointed to by data.
Message sent by client to the service to add or remove an element to/from the set.
Definition: set.h:273
struct GNUNET_SET_Element element
The actual element.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t element_type
Application-specific element type.
Here is the call graph for this function:

◆ check_union_p2p_inquiry()

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

Parameters
clsthe union operation
msgthe message

Definition at line 1718 of file gnunet-service-set_union.c.

References GNUNET_break_op, GNUNET_OK, GNUNET_SET_OPERATION_UNION, GNUNET_SYSERR, InquiryMessage::header, op, Set::operation, OperationState::phase, PHASE_INVENTORY_PASSIVE, Operation::set, GNUNET_MessageHeader::size, and Operation::state.

1720 {
1721  struct Operation *op = cls;
1722  unsigned int num_keys;
1723 
1725  {
1726  GNUNET_break_op(0);
1727  return GNUNET_SYSERR;
1728  }
1729  if (op->state->phase != PHASE_INVENTORY_PASSIVE)
1730  {
1731  GNUNET_break_op(0);
1732  return GNUNET_SYSERR;
1733  }
1734  num_keys = (ntohs(msg->header.size) - sizeof(struct InquiryMessage))
1735  / sizeof(struct IBF_Key);
1736  if ((ntohs(msg->header.size) - sizeof(struct InquiryMessage))
1737  != num_keys * sizeof(struct IBF_Key))
1738  {
1739  GNUNET_break_op(0);
1740  return GNUNET_SYSERR;
1741  }
1742  return GNUNET_OK;
1743 }
The other peer is decoding the IBF we just sent.
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
enum IntersectionOperationPhase phase
Current state of the operation.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
enum GNUNET_SET_OperationType operation
Type of operation supported for this set.
Operation context used to execute a set operation.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Keys that can be inserted into and removed from an IBF.
Definition: ibf.h:45
Set union, return all elements that are in at least one of the sets.

◆ handle_union_p2p_inquiry()

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

Parameters
clsthe union operation
msgthe message

Definition at line 1754 of file gnunet-service-set_union.c.

References Operation::channel, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, InquiryMessage::header, LOG, op, InquiryMessage::salt, send_offers_for_key(), GNUNET_MessageHeader::size, and unsalt_key().

1756 {
1757  struct Operation *op = cls;
1758  const struct IBF_Key *ibf_key;
1759  unsigned int num_keys;
1760 
1762  "Received union inquiry\n");
1763  num_keys = (ntohs(msg->header.size) - sizeof(struct InquiryMessage))
1764  / sizeof(struct IBF_Key);
1765  ibf_key = (const struct IBF_Key *)&msg[1];
1766  while (0 != num_keys--)
1767  {
1768  struct IBF_Key unsalted_key;
1769 
1770  unsalt_key(ibf_key,
1771  ntohl(msg->salt),
1772  &unsalted_key);
1774  unsalted_key);
1775  ibf_key++;
1776  }
1778 }
#define LOG(kind,...)
struct GNUNET_CADET_Channel * channel
Channel to the peer.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static 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.
Operation context used to execute a set operation.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF.
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:951
static void unsalt_key(const struct IBF_Key *k_in, uint32_t salt, struct IBF_Key *k_out)
FIXME.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Keys that can be inserted into and removed from an IBF.
Definition: ibf.h:45
uint32_t salt
Salt used when hashing elements for this inquiry.
Here is the call graph for this function:

◆ handle_union_p2p_request_full()

void handle_union_p2p_request_full ( void *  cls,
const struct GNUNET_MessageHeader mh 
)

Handle a request for full set transmission.

cls closure, a set union operation

Parameters
mhthe demand message

Definition at line 1824 of file gnunet-service-set_union.c.

References Operation::channel, fail_union_operation(), GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_SET_OPERATION_UNION, LOG, op, Set::operation, OperationState::phase, PHASE_EXPECT_IBF, send_full_set(), Operation::set, and Operation::state.

1826 {
1827  struct Operation *op = cls;
1828 
1830  "Received request for full set transmission\n");
1832  {
1833  GNUNET_break_op(0);
1835  return;
1836  }
1837  if (PHASE_EXPECT_IBF != op->state->phase)
1838  {
1839  GNUNET_break_op(0);
1841  return;
1842  }
1843 
1844  // FIXME: we need to check that our set is larger than the
1845  // byzantine_lower_bound by some threshold
1846  send_full_set(op);
1848 }
We sent the strata estimator, and expect an IBF.
#define LOG(kind,...)
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
struct GNUNET_CADET_Channel * channel
Channel to the peer.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
enum IntersectionOperationPhase phase
Current state of the operation.
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation...
enum GNUNET_SET_OperationType operation
Type of operation supported for this set.
Operation context used to execute a set operation.
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:951
static void send_full_set(struct Operation *op)
Switch to full set transmission for op.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Set union, return all elements that are in at least one of the sets.
Here is the call graph for this function:

◆ handle_union_p2p_full_done()

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

Handle a "full done" message.

cls closure, a set union operation

Parameters
mhthe demand message

Definition at line 1858 of file gnunet-service-set_union.c.

References _GSS_operation_destroy2(), Operation::channel, fail_union_operation(), GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap32_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE, GNUNET_MQ_msg_header, GNUNET_MQ_send(), OperationState::key_to_element, LOG, Operation::mq, op, OperationState::phase, PHASE_DONE, PHASE_EXPECT_IBF, PHASE_FULL_SENDING, send_client_done(), send_missing_full_elements_iter(), and Operation::state.

1860 {
1861  struct Operation *op = cls;
1862 
1863  switch (op->state->phase)
1864  {
1865  case PHASE_EXPECT_IBF:
1866  {
1867  struct GNUNET_MQ_Envelope *ev;
1868 
1870  "got FULL DONE, sending elements that other peer is missing\n");
1871 
1872  /* send all the elements that did not come from the remote peer */
1875  op);
1876 
1878  GNUNET_MQ_send(op->mq,
1879  ev);
1880  op->state->phase = PHASE_DONE;
1881  /* we now wait until the other peer sends us the OVER message*/
1882  }
1883  break;
1884 
1885  case PHASE_FULL_SENDING:
1886  {
1888  "got FULL DONE, finishing\n");
1889  /* We sent the full set, and got the response for that. We're done. */
1890  op->state->phase = PHASE_DONE;
1892  send_client_done(op);
1894  return;
1895  }
1896  break;
1897 
1898  default:
1900  "Handle full done phase is %u\n",
1901  (unsigned)op->state->phase);
1902  GNUNET_break_op(0);
1904  return;
1905  }
1907 }
We sent the strata estimator, and expect an IBF.
struct GNUNET_CONTAINER_MultiHashMap32 * key_to_element
Maps unsalted IBF-Keys to elements.
#define LOG(kind,...)
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MulitHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CADET_Channel * channel
Channel to the peer.
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...
static void send_client_done(void *cls)
Signal to the client that the operation has finished and destroy the operation.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
enum IntersectionOperationPhase phase
Current state of the operation.
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation...
Operation context used to execute a set operation.
#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
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:951
struct GNUNET_MQ_Handle * mq
Message queue for the channel.
#define GNUNET_log(kind,...)
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE
Request all missing elements from the other peer, based on their sets and the elements we previously ...
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_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:351
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
In the ultimate phase, we wait until our demands are satisfied and then quit (sending another DONE me...
After sending the full set, wait for responses with the elements that the local peer is missing...
Here is the call graph for this function:

◆ check_union_p2p_demand()

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.

cls closure, a set union operation

Parameters
mhthe demand message
Returns
GNUNET_OK if mh is well-formed

Definition at line 1919 of file gnunet-service-set_union.c.

References GNUNET_break_op, GNUNET_OK, GNUNET_SET_OPERATION_UNION, GNUNET_SYSERR, op, Set::operation, Operation::set, and GNUNET_MessageHeader::size.

1921 {
1922  struct Operation *op = cls;
1923  unsigned int num_hashes;
1924 
1926  {
1927  GNUNET_break_op(0);
1928  return GNUNET_SYSERR;
1929  }
1930  num_hashes = (ntohs(mh->size) - sizeof(struct GNUNET_MessageHeader))
1931  / sizeof(struct GNUNET_HashCode);
1932  if ((ntohs(mh->size) - sizeof(struct GNUNET_MessageHeader))
1933  != num_hashes * sizeof(struct GNUNET_HashCode))
1934  {
1935  GNUNET_break_op(0);
1936  return GNUNET_SYSERR;
1937  }
1938  return GNUNET_OK;
1939 }
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
A 512-bit hashcode.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
enum GNUNET_SET_OperationType operation
Type of operation supported for this set.
Operation context used to execute a set operation.
Header for all communications.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Set union, return all elements that are in at least one of the sets.

◆ handle_union_p2p_demand()

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.

cls closure, a set union operation

Parameters
mhthe demand message

Definition at line 1950 of file gnunet-service-set_union.c.

References _GSS_is_element_of_operation(), _GSS_statistics, Operation::channel, Set::content, GNUNET_SET_Element::data, ElementEntry::element, ElementEntry::element_hash, GNUNET_SET_Element::element_type, GNUNET_SET_ElementMessage::element_type, SetContent::elements, fail_union_operation(), GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_SET_RESULT_ADDED, GNUNET_SET_RESULT_SYMMETRIC, GNUNET_SET_STATUS_ADD_REMOTE, GNUNET_STATISTICS_update(), LOG, op, GNUNET_SET_ElementMessage::reserved, send_client_element(), Operation::set, GNUNET_SET_Element::size, and GNUNET_MessageHeader::size.

1952 {
1953  struct Operation *op = cls;
1954  struct ElementEntry *ee;
1955  struct GNUNET_SET_ElementMessage *emsg;
1956  const struct GNUNET_HashCode *hash;
1957  unsigned int num_hashes;
1958  struct GNUNET_MQ_Envelope *ev;
1959 
1960  num_hashes = (ntohs(mh->size) - sizeof(struct GNUNET_MessageHeader))
1961  / sizeof(struct GNUNET_HashCode);
1962  for (hash = (const struct GNUNET_HashCode *)&mh[1];
1963  num_hashes > 0;
1964  hash++, num_hashes--)
1965  {
1967  hash);
1968  if (NULL == ee)
1969  {
1970  /* Demand for non-existing element. */
1971  GNUNET_break_op(0);
1973  return;
1974  }
1975  if (GNUNET_NO == _GSS_is_element_of_operation(ee, op))
1976  {
1977  /* Probably confused lazily copied sets. */
1978  GNUNET_break_op(0);
1980  return;
1981  }
1983  GNUNET_memcpy(&emsg[1], ee->element.data, ee->element.size);
1984  emsg->reserved = htons(0);
1985  emsg->element_type = htons(ee->element.element_type);
1987  "[OP %x] Sending demanded element (size %u, hash %s) to peer\n",
1988  (void *)op,
1989  (unsigned int)ee->element.size,
1990  GNUNET_h2s(&ee->element_hash));
1991  GNUNET_MQ_send(op->mq, ev);
1993  "# exchanged elements",
1994  1,
1995  GNUNET_NO);
1996 
1997  switch (op->result_mode)
1998  {
2000  /* Nothing to do. */
2001  break;
2002 
2005  break;
2006 
2007  default:
2008  /* Result mode not supported, should have been caught earlier. */
2009  GNUNET_break(0);
2010  break;
2011  }
2012  }
2013  GNUNET_CADET_receive_done(op->channel);
2014 }
Client gets only elements that have been added to the set.
#define LOG(kind,...)
#define GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS
Actual set elements.
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
int _GSS_is_element_of_operation(struct ElementEntry *ee, struct Operation *op)
Is element ee part of the set used by op?
Element should be added to the result set of the remote peer, i.e.
struct GNUNET_HashCode element_hash
Hash of the element.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_NO
Definition: gnunet_common.h:78
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
uint16_t element_type
Type of the element to add or remove.
Definition: set.h:283
const void * data
Actual data of the element.
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.
struct GNUNET_STATISTICS_Handle * _GSS_statistics
Statistics handle.
#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
Information about an element element in the set.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
A 512-bit hashcode.
Client gets notified of the required changes for both the local and the remote set.
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation...
Operation context used to execute a set operation.
static void send_client_element(struct Operation *op, struct GNUNET_SET_Element *element, int status)
Send a result message to the client indicating that there is a new element.
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:951
uint16_t reserved
For alignment, always zero.
Definition: set.h:288
uint16_t size
Number of bytes in the buffer pointed to by data.
Message sent by client to the service to add or remove an element to/from the set.
Definition: set.h:273
struct GNUNET_SET_Element element
The actual element.
struct GNUNET_CONTAINER_MultiHashMap * elements
Maps struct GNUNET_HashCode * to struct ElementEntry *.
Header for all communications.
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:351
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
uint16_t element_type
Application-specific element type.
struct SetContent * content
Content, possibly shared by multiple sets, and thus reference counted.
Here is the call graph for this function:

◆ check_union_p2p_offer()

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

Check offer (of struct GNUNET_HashCodes).

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

Definition at line 2025 of file gnunet-service-set_union.c.

References GNUNET_break_op, GNUNET_OK, GNUNET_SET_OPERATION_UNION, GNUNET_SYSERR, op, Set::operation, OperationState::phase, PHASE_INVENTORY_ACTIVE, PHASE_INVENTORY_PASSIVE, Operation::set, GNUNET_MessageHeader::size, and Operation::state.

2027 {
2028  struct Operation *op = cls;
2029  unsigned int num_hashes;
2030 
2032  {
2033  GNUNET_break_op(0);
2034  return GNUNET_SYSERR;
2035  }
2036  /* look up elements and send them */
2037  if ((op->state->phase != PHASE_INVENTORY_PASSIVE) &&
2039  {
2040  GNUNET_break_op(0);
2041  return GNUNET_SYSERR;
2042  }
2043  num_hashes = (ntohs(mh->size) - sizeof(struct GNUNET_MessageHeader))
2044  / sizeof(struct GNUNET_HashCode);
2045  if ((ntohs(mh->size) - sizeof(struct GNUNET_MessageHeader)) !=
2046  num_hashes * sizeof(struct GNUNET_HashCode))
2047  {
2048  GNUNET_break_op(0);
2049  return GNUNET_SYSERR;
2050  }
2051  return GNUNET_OK;
2052 }
The other peer is decoding the IBF we just sent.
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
We are decoding an IBF.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
enum IntersectionOperationPhase phase
Current state of the operation.
A 512-bit hashcode.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
enum GNUNET_SET_OperationType operation
Type of operation supported for this set.
Operation context used to execute a set operation.
Header for all communications.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Set union, return all elements that are in at least one of the sets.

◆ handle_union_p2p_offer()

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

Parameters
clsthe union operation
mhthe message

Definition at line 2063 of file gnunet-service-set_union.c.

References _GSS_is_element_of_operation(), Operation::channel, Set::content, OperationState::demanded_hashes, SetContent::elements, GNUNET_assert, 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_h2s(), GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND, GNUNET_MQ_msg_header_extra, GNUNET_MQ_send(), GNUNET_OK, GNUNET_YES, LOG, op, Operation::set, GNUNET_MessageHeader::size, and Operation::state.

2065 {
2066  struct Operation *op = cls;
2067  const struct GNUNET_HashCode *hash;
2068  unsigned int num_hashes;
2069 
2070  num_hashes = (ntohs(mh->size) - sizeof(struct GNUNET_MessageHeader))
2071  / sizeof(struct GNUNET_HashCode);
2072  for (hash = (const struct GNUNET_HashCode *)&mh[1];
2073  num_hashes > 0;
2074  hash++, num_hashes--)
2075  {
2076  struct ElementEntry *ee;
2077  struct GNUNET_MessageHeader *demands;
2078  struct GNUNET_MQ_Envelope *ev;
2079 
2081  hash);
2082  if (NULL != ee)
2084  continue;
2085 
2086  if (GNUNET_YES ==
2088  hash))
2089  {
2091  "Skipped sending duplicate demand\n");
2092  continue;
2093  }
2094 
2097  hash,
2098  NULL,
2100 
2102  "[OP %x] Requesting element (hash %s)\n",
2103  (void *)op, GNUNET_h2s(hash));
2104  ev = GNUNET_MQ_msg_header_extra(demands,
2105  sizeof(struct GNUNET_HashCode),
2107  GNUNET_memcpy(&demands[1],
2108  hash,
2109  sizeof(struct GNUNET_HashCode));
2110  GNUNET_MQ_send(op->mq, ev);
2111  }
2112  GNUNET_CADET_receive_done(op->channel);
2113 }
#define LOG(kind,...)
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
int _GSS_is_element_of_operation(struct ElementEntry *ee, struct Operation *op)
Is element ee part of the set used by op?
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
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)...
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.
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
Information about an element element in the set.
A 512-bit hashcode.
#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
Operation context used to execute a set operation.
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_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:951
struct GNUNET_CONTAINER_MultiHashMap * elements
Maps struct GNUNET_HashCode * to struct ElementEntry *.
Header for all communications.
#define GNUNET_YES
Definition: gnunet_common.h:77
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:351
struct GNUNET_CONTAINER_MultiHashMap * demanded_hashes
Hashes for elements that we have demanded from the other peer.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND
Demand the whole element from the other peer, given only the hash code.
struct SetContent * content
Content, possibly shared by multiple sets, and thus reference counted.
Here is the call graph for this function:

◆ handle_union_p2p_done()

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

Handle a done message from a remote peer.

Parameters
clsthe union operation
mhthe message

Definition at line 2123 of file gnunet-service-set_union.c.

References Operation::channel, fail_union_operation(), GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_SET_OPERATION_UNION, LOG, maybe_finish(), op, Set::operation, OperationState::phase, PHASE_FINISH_CLOSING, PHASE_FINISH_WAITING, PHASE_INVENTORY_ACTIVE, PHASE_INVENTORY_PASSIVE, Operation::set, and Operation::state.

2125 {
2126  struct Operation *op = cls;
2127 
2129  {
2130  GNUNET_break_op(0);
2132  return;
2133  }
2134  switch (op->state->phase)
2135  {
2137  /* We got all requests, but still have to send our elements in response. */
2139 
2141  "got DONE (as passive partner), waiting for our demands to be satisfied\n");
2142  /* The active peer is done sending offers
2143  * and inquiries. This means that all
2144  * our responses to that (demands and offers)
2145  * must be in flight (queued or in mesh).
2146  *
2147  * We should notify the active peer once
2148  * all our demands are satisfied, so that the active
2149  * peer can quit if we gave it everything.
2150  */
2152  maybe_finish(op);
2153  return;
2154 
2157  "got DONE (as active partner), waiting to finish\n");
2158  /* All demands of the other peer are satisfied,
2159  * and we processed all offers, thus we know
2160  * exactly what our demands must be.
2161  *
2162  * We'll close the channel
2163  * to the other peer once our demands are met.
2164  */
2167  maybe_finish(op);
2168  return;
2169 
2170  default:
2171  GNUNET_break_op(0);
2173  return;
2174  }
2175 }
The other peer is decoding the IBF we just sent.
#define LOG(kind,...)
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set...
We are decoding an IBF.
struct GNUNET_CADET_Channel * channel
Channel to the peer.
The protocol is almost finished, but we still have to flush our message queue and/or expect some elem...
In the penultimate phase, we wait until all our demands are satisfied.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
enum IntersectionOperationPhase phase
Current state of the operation.
static void fail_union_operation(struct Operation *op)
Inform the client that the union operation has failed, and proceed to destroy the evaluate operation...
enum GNUNET_SET_OperationType operation
Type of operation supported for this set.
Operation context used to execute a set operation.
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:951
static void maybe_finish(struct Operation *op)
Tests if the operation is finished, and if so notify.
struct OperationState * state
Operation-specific operation state.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
Set union, return all elements that are in at least one of the sets.
Here is the call graph for this function:

◆ handle_union_p2p_over()

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

Handle an over message from a remote peer.

Parameters
clsthe union operation
mhthe message

Handle an over message from a remote peer.

Parameters
clsthe union operation
mhthe message

Definition at line 2184 of file gnunet-service-set_union.c.

References send_client_done().

2186 {
2187  send_client_done(cls);
2188 }
static void send_client_done(void *cls)
Signal to the client that the operation has finished and destroy the operation.
Here is the call graph for this function: