GNUnet 0.28.0-dev.3-7-g31e20e2e6
 
Loading...
Searching...
No Matches
gnunet-service-seti.c File Reference
Include dependency graph for gnunet-service-seti.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  Listener
 A listener is inhabited by a client, and waits for evaluation requests from remote peers. More...
 

Macros

#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?
 

Enumerations

enum  IntersectionOperationPhase {
  PHASE_INITIAL , PHASE_COUNT_SENT , PHASE_BF_EXCHANGE , PHASE_MUST_SEND_DONE ,
  PHASE_DONE_RECEIVED , PHASE_FINISHED
}
 Current phase we are in for a intersection operation. More...
 

Functions

static void send_client_removed_element (struct Operation *op, struct GNUNET_SETI_Element *element)
 If applicable in the current operation mode, send a result message to the client indicating we removed an element.
 
static int _GSS_is_element_of_operation (struct ElementEntry *ee, struct Operation *op)
 Is element ee part of the set used by op?
 
static int filtered_map_initialization (void *cls, const struct GNUNET_HashCode *key, void *value)
 Fills the "my_elements" hashmap with all relevant elements.
 
static int iterator_bf_reduce (void *cls, const struct GNUNET_HashCode *key, void *value)
 Removes elements from our hashmap if they are not contained within the provided remote bloomfilter.
 
static int iterator_bf_create (void *cls, const struct GNUNET_HashCode *key, void *value)
 Create initial bloomfilter based on all the elements given.
 
static void _GSS_operation_destroy (struct Operation *op)
 Destroy the given operation.
 
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.
 
static void incoming_destroy (struct Operation *op)
 Destroy an incoming request from a remote peer.
 
static void send_client_done_and_destroy (void *cls)
 Signal to the client that the operation has finished and destroy the operation.
 
static void fail_intersection_operation (struct Operation *op)
 Inform the client that the intersection operation has failed, and proceed to destroy the evaluate operation.
 
static void send_bloomfilter (struct Operation *op)
 Send a bloomfilter to our peer.
 
static void finished_local_operations (void *cls)
 Remember that we are done dealing with the local client AND have sent the other peer our message that we are done, so we are not just waiting for the channel to die before telling the local client that we are done as our last act.
 
static void send_p2p_done (struct Operation *op)
 Notify the other peer that we are done.
 
static void send_remaining_elements (void *cls)
 Send all elements in the full result iterator.
 
static int initialize_map_unfiltered (void *cls, const struct GNUNET_HashCode *key, void *value)
 Fills the "my_elements" hashmap with the initial set of (non-deleted) elements from the set of the specification.
 
static void send_element_count (struct Operation *op)
 Send our element count to the peer, in case our element count is lower than theirs.
 
static void begin_bf_exchange (struct Operation *op)
 We go first, initialize our map with all elements and send the first Bloom filter.
 
static void handle_intersection_p2p_element_info (void *cls, const struct IntersectionElementInfoMessage *msg)
 Handle the initial struct IntersectionElementInfoMessage from a remote peer.
 
static void process_bf (struct Operation *op)
 Process a Bloomfilter once we got all the chunks.
 
static int check_intersection_p2p_bf (void *cls, const struct BFMessage *msg)
 Check an BF message from a remote peer.
 
static void handle_intersection_p2p_bf (void *cls, const struct BFMessage *msg)
 Handle an BF message from a remote peer.
 
static int filter_all (void *cls, const struct GNUNET_HashCode *key, void *value)
 Remove all elements from our hashmap.
 
static void handle_intersection_p2p_done (void *cls, const struct IntersectionDoneMessage *idm)
 Handle a done message from a remote peer.
 
static struct Operationget_incoming (uint32_t id)
 Get the incoming socket associated with the given id.
 
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.
 
static int destroy_elements_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
 Iterator over hash map entries to free element entries.
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *internal_cls)
 Clean up after a client has disconnected.
 
static int check_incoming_msg (void *cls, const struct OperationRequestMessage *msg)
 Check a request for a set operation from another peer.
 
static void handle_incoming_msg (void *cls, const struct OperationRequestMessage *msg)
 Handle a request for a set operation from another peer.
 
static void handle_client_create_set (void *cls, const struct GNUNET_SETI_CreateMessage *msg)
 Called when a client wants to create a new set.
 
static void incoming_timeout_cb (void *cls)
 Timeout happens iff:
 
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.
 
static void channel_end_cb (void *channel_ctx, const struct GNUNET_CADET_Channel *channel)
 Function called whenever a channel is destroyed.
 
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.
 
static void handle_client_listen (void *cls, const struct GNUNET_SETI_ListenMessage *msg)
 Called when a client wants to create a new listener.
 
static void handle_client_reject (void *cls, const struct GNUNET_SETI_RejectMessage *msg)
 Called when the listening client rejects an operation request by another peer.
 
static int check_client_set_add (void *cls, const struct GNUNET_SETI_ElementMessage *msg)
 Called when a client wants to add or remove an element to a set it inhabits.
 
static void handle_client_set_add (void *cls, const struct GNUNET_SETI_ElementMessage *msg)
 Called when a client wants to add an element to a set it inhabits.
 
static void advance_generation (struct Set *set)
 Advance the current generation of a set, adding exclusion ranges if necessary.
 
static int check_client_evaluate (void *cls, const struct GNUNET_SETI_EvaluateMessage *msg)
 Called when a client wants to initiate a set operation with another peer.
 
static void handle_client_evaluate (void *cls, const struct GNUNET_SETI_EvaluateMessage *msg)
 Called when a client wants to initiate a set operation with another peer.
 
static void handle_client_cancel (void *cls, const struct GNUNET_SETI_CancelMessage *msg)
 Handle a request from the client to cancel a running set operation.
 
static void handle_client_accept (void *cls, const struct GNUNET_SETI_AcceptMessage *msg)
 Handle a request from the client to accept a set operation that came from a remote peer.
 
static void shutdown_task (void *cls)
 Called to clean up, after a shutdown has been requested.
 
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.
 
 GNUNET_SERVICE_MAIN (GNUNET_OS_project_data_gnunet(), "seti", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(client_accept, GNUNET_MESSAGE_TYPE_SETI_ACCEPT, struct GNUNET_SETI_AcceptMessage, NULL), GNUNET_MQ_hd_var_size(client_set_add, GNUNET_MESSAGE_TYPE_SETI_ADD, struct GNUNET_SETI_ElementMessage, NULL), GNUNET_MQ_hd_fixed_size(client_create_set, GNUNET_MESSAGE_TYPE_SETI_CREATE, struct GNUNET_SETI_CreateMessage, NULL), GNUNET_MQ_hd_var_size(client_evaluate, GNUNET_MESSAGE_TYPE_SETI_EVALUATE, struct GNUNET_SETI_EvaluateMessage, NULL), GNUNET_MQ_hd_fixed_size(client_listen, GNUNET_MESSAGE_TYPE_SETI_LISTEN, struct GNUNET_SETI_ListenMessage, NULL), GNUNET_MQ_hd_fixed_size(client_reject, GNUNET_MESSAGE_TYPE_SETI_REJECT, struct GNUNET_SETI_RejectMessage, NULL), GNUNET_MQ_hd_fixed_size(client_cancel, GNUNET_MESSAGE_TYPE_SETI_CANCEL, struct GNUNET_SETI_CancelMessage, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro.
 

Variables

static struct GNUNET_CADET_Handlecadet
 Handle to the cadet service, used to listen for and connect to remote peers.
 
static struct GNUNET_STATISTICS_Handle_GSS_statistics
 Statistics handle.
 
static struct Listenerlistener_head
 Listeners are held in a doubly linked list.
 
static struct Listenerlistener_tail
 Listeners are held in a doubly linked list.
 
static unsigned int num_clients
 Number of active clients.
 
static int in_shutdown
 Are we in shutdown? if GNUNET_YES and the number of clients drops to zero, disconnect from CADET.
 
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.
 

Macro Definition Documentation

◆ 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 38 of file gnunet-service-seti.c.

Enumeration Type Documentation

◆ IntersectionOperationPhase

Current phase we are in for a intersection operation.

Enumerator
PHASE_INITIAL 

We are just starting.

PHASE_COUNT_SENT 

We have send the number of our elements to the other peer, but did not setup our element set yet.

PHASE_BF_EXCHANGE 

We have initialized our set and are now reducing it by exchanging Bloom filters until one party notices the their element hashes are equal.

PHASE_MUST_SEND_DONE 

We must next send the P2P DONE message (after finishing mostly with the local client).

Then we will wait for the channel to close.

PHASE_DONE_RECEIVED 

We have received the P2P DONE message, and must finish with the local client before terminating the channel.

PHASE_FINISHED 

The protocol is over.

Results may still have to be sent to the client.

Definition at line 44 of file gnunet-service-seti.c.

45{
50
56
63
69
75
81};
@ PHASE_INITIAL
We are just starting.
@ PHASE_DONE_RECEIVED
We have received the P2P DONE message, and must finish with the local client before terminating the c...
@ PHASE_FINISHED
The protocol is over.
@ PHASE_BF_EXCHANGE
We have initialized our set and are now reducing it by exchanging Bloom filters until one party notic...
@ PHASE_COUNT_SENT
We have send the number of our elements to the other peer, but did not setup our element set yet.
@ PHASE_MUST_SEND_DONE
We must next send the P2P DONE message (after finishing mostly with the local client).

Function Documentation

◆ send_client_removed_element()

static void send_client_removed_element ( struct Operation op,
struct GNUNET_SETI_Element element 
)
static

If applicable in the current operation mode, send a result message to the client indicating we removed an element.

Parameters
opintersection operation
elementelement to send

Definition at line 517 of file gnunet-service-seti.c.

519{
520 struct GNUNET_MQ_Envelope *ev;
521 struct GNUNET_SETI_ResultMessage *rm;
522
523 if (GNUNET_YES == op->return_intersection)
524 {
525 GNUNET_break (0);
526 return; /* Wrong mode for transmitting removed elements */
527 }
529 "Sending removed element (size %u) to client\n",
530 element->size);
532 "# Element removed messages sent",
533 1,
534 GNUNET_NO);
535 GNUNET_assert (0 != op->client_request_id);
536 ev = GNUNET_MQ_msg_extra (rm,
537 element->size,
539 if (NULL == ev)
540 {
541 GNUNET_break (0);
542 return;
543 }
545 rm->request_id = htonl (op->client_request_id);
546 rm->element_type = element->element_type;
547 GNUNET_memcpy (&rm[1],
548 element->data,
549 element->size);
550 GNUNET_MQ_send (op->set->cs->mq,
551 ev);
552}
static struct GNUNET_ARM_Operation * op
Current operation.
Definition gnunet-arm.c:143
static struct GNUNET_STATISTICS_Handle * _GSS_statistics
Statistics handle.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_DEBUG
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:305
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MESSAGE_TYPE_SETI_RESULT
Handle result message from operation.
@ GNUNET_SETI_STATUS_DEL_LOCAL
Element should be delete from the result set of the local peer, i.e.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
const void * data
Actual data of the element.
uint16_t element_type
Application-specific element type.
uint16_t size
Number of bytes in the buffer pointed to by data.
Message sent by the service to the client to indicate an element that is removed (set intersection) o...
Definition seti.h:192
uint32_t request_id
id the result belongs to
Definition seti.h:206
uint16_t element_type
Type of the element attached to the message, if any.
Definition seti.h:217
uint16_t result_status
Was the evaluation successful? Contains an enum GNUNET_SETI_Status in NBO.
Definition seti.h:212

References _GSS_statistics, GNUNET_SETI_Element::data, GNUNET_SETI_Element::element_type, GNUNET_SETI_ResultMessage::element_type, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SETI_RESULT, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_SETI_STATUS_DEL_LOCAL, GNUNET_STATISTICS_update(), GNUNET_YES, op, GNUNET_SETI_ResultMessage::request_id, GNUNET_SETI_ResultMessage::result_status, and GNUNET_SETI_Element::size.

Referenced by filter_all(), filtered_map_initialization(), and iterator_bf_reduce().

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 563 of file gnunet-service-seti.c.

565{
566 return op->generation_created >= ee->generation_added;
567}
unsigned int generation_added
Generation in which the element was added.

References ElementEntry::generation_added, and op.

Referenced by filtered_map_initialization(), and initialize_map_unfiltered().

Here is the caller graph for this function:

◆ filtered_map_initialization()

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

Fills the "my_elements" hashmap with all relevant elements.

Parameters
clsthe struct Operation * we are performing
keycurrent key code
valuethe struct ElementEntry * from the hash map
Returns
GNUNET_YES (we should continue to iterate)

Definition at line 579 of file gnunet-service-seti.c.

582{
583 struct Operation *op = cls;
584 struct ElementEntry *ee = value;
585 struct GNUNET_HashCode mutated_hash;
586
588 "FIMA called for %s:%u\n",
590 ee->element.size);
591
593 {
595 "Reduced initialization, not starting with %s:%u (wrong generation)\n",
597 ee->element.size);
598 return GNUNET_YES; /* element not valid in our operation's generation */
599 }
600
601 /* Test if element is in other peer's bloomfilter */
603 op->salt,
604 &mutated_hash);
606 "Testing mingled hash %s with salt %u\n",
607 GNUNET_h2s (&mutated_hash),
608 op->salt);
609 if (GNUNET_NO ==
611 &mutated_hash))
612 {
613 /* remove this element */
615 &ee->element);
617 "Reduced initialization, not starting with %s:%u\n",
619 ee->element.size);
620 return GNUNET_YES;
621 }
622 op->my_element_count++;
623 GNUNET_CRYPTO_hash_xor (&op->my_xor,
624 &ee->element_hash,
625 &op->my_xor);
627 "Filtered initialization of my_elements, adding %s:%u\n",
629 ee->element.size);
632 &ee->element_hash,
633 ee,
635
636 return GNUNET_YES;
637}
static char * value
Value of the record to add/remove.
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 send_client_removed_element(struct Operation *op, struct GNUNET_SETI_Element *element)
If applicable in the current operation mode, send a result message to the client indicating we remove...
void GNUNET_BLOCK_mingle_hash(const struct GNUNET_HashCode *in, uint32_t mingle_number, struct GNUNET_HashCode *hc)
Mingle hash with the mingle_number to produce different bits.
Definition block.c:96
bool GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
void GNUNET_CRYPTO_hash_xor(const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b, struct GNUNET_HashCode *result)
compute result = a ^ b
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
Information about an element element in the set.
struct GNUNET_SET_Element element
The actual element.
struct GNUNET_HashCode element_hash
Hash of the element.
A 512-bit hashcode.
uint16_t size
Number of bytes in the buffer pointed to by data.
Operation context used to execute a set operation.

References _GSS_is_element_of_operation(), ElementEntry::element, ElementEntry::element_hash, GNUNET_BLOCK_mingle_hash(), GNUNET_break, GNUNET_CONTAINER_bloomfilter_test(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash_xor(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_YES, op, send_client_removed_element(), GNUNET_SET_Element::size, and value.

Referenced by process_bf().

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

◆ iterator_bf_reduce()

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

Removes elements from our hashmap if they are not contained within the provided remote bloomfilter.

Parameters
clsclosure with the struct Operation *
keycurrent key code
valuevalue in the hash map
Returns
GNUNET_YES (we should continue to iterate)

Definition at line 650 of file gnunet-service-seti.c.

653{
654 struct Operation *op = cls;
655 struct ElementEntry *ee = value;
656 struct GNUNET_HashCode mutated_hash;
657
659 op->salt,
660 &mutated_hash);
662 "Testing mingled hash %s with salt %u\n",
663 GNUNET_h2s (&mutated_hash),
664 op->salt);
665 if (GNUNET_NO ==
667 &mutated_hash))
668 {
669 GNUNET_break (0 < op->my_element_count);
670 op->my_element_count--;
671 GNUNET_CRYPTO_hash_xor (&op->my_xor,
672 &ee->element_hash,
673 &op->my_xor);
675 "Bloom filter reduction of my_elements, removing %s:%u\n",
677 ee->element.size);
680 &ee->element_hash,
681 ee));
683 &ee->element);
684 }
685 else
686 {
688 "Bloom filter reduction of my_elements, keeping %s:%u\n",
690 ee->element.size);
691 }
692 return GNUNET_YES;
693}
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.

References ElementEntry::element, ElementEntry::element_hash, GNUNET_assert, GNUNET_BLOCK_mingle_hash(), GNUNET_break, GNUNET_CONTAINER_bloomfilter_test(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CRYPTO_hash_xor(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_YES, op, send_client_removed_element(), GNUNET_SET_Element::size, and value.

Referenced by process_bf().

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

◆ iterator_bf_create()

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

Create initial bloomfilter based on all the elements given.

Parameters
clsthe struct Operation *
keycurrent key code
valuethe struct ElementEntry to process
Returns
GNUNET_YES (we should continue to iterate)

Definition at line 705 of file gnunet-service-seti.c.

708{
709 struct Operation *op = cls;
710 struct ElementEntry *ee = value;
711 struct GNUNET_HashCode mutated_hash;
712
714 op->salt,
715 &mutated_hash);
717 "Initializing BF with hash %s with salt %u\n",
718 GNUNET_h2s (&mutated_hash),
719 op->salt);
721 &mutated_hash);
722 return GNUNET_YES;
723}
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.

References ElementEntry::element_hash, GNUNET_BLOCK_mingle_hash(), GNUNET_CONTAINER_bloomfilter_add(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_YES, op, and value.

Referenced by send_bloomfilter().

Here is the call graph for this function:
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 739 of file gnunet-service-seti.c.

740{
741 struct Set *set = op->set;
742 struct GNUNET_CADET_Channel *channel;
743
744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying operation %p\n", op);
745 GNUNET_assert (NULL == op->listener);
746 if (NULL != op->remote_bf)
747 {
749 op->remote_bf = NULL;
750 }
751 if (NULL != op->local_bf)
752 {
754 op->local_bf = NULL;
755 }
756 if (NULL != op->my_elements)
757 {
759 op->my_elements = NULL;
760 }
761 if (NULL != op->full_result_iter)
762 {
764 op->full_result_iter);
765 op->full_result_iter = NULL;
766 }
768 "Destroying intersection op state done\n");
769 if (NULL != set)
770 {
772 set->ops_tail,
773 op);
774 op->set = NULL;
775 }
776 if (NULL != op->context_msg)
777 {
778 GNUNET_free (op->context_msg);
779 op->context_msg = NULL;
780 }
781 if (NULL != (channel = op->channel))
782 {
783 /* This will free op; called conditionally as this helper function
784 is also called from within the channel disconnect handler. */
785 op->channel = NULL;
787 }
788 /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL,
789 * there was a channel end handler that will free 'op' on the call stack. */
790}
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associated with a filter in memory, flush to drive if needed (do not free the space on...
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition cadet_api.c:833
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
#define GNUNET_free(ptr)
Wrapper around free.
Opaque handle to a channel.
Definition cadet.h:116
A set that supports a specific operation with other peers.
struct Operation * ops_head
Evaluate operations are held in a linked list.
struct Operation * ops_tail
Evaluate operations are held in a linked list.

References GNUNET_assert, GNUNET_CADET_channel_destroy(), GNUNET_CONTAINER_bloomfilter_free(), GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterator_destroy(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, op, Set::ops_head, and Set::ops_tail.

Referenced by _GSS_operation_destroy2(), client_disconnect_cb(), fail_intersection_operation(), handle_client_cancel(), and send_client_done_and_destroy().

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 867 of file gnunet-service-seti.c.

868{
869 struct GNUNET_CADET_Channel *channel;
870
872 "channel_end_cb called\n");
873 if (NULL != (channel = op->channel))
874 {
875 /* This will free op; called conditionally as this helper function
876 is also called from within the channel disconnect handler. */
877 op->channel = NULL;
879 }
880 if (NULL != op->listener)
881 {
883 return;
884 }
885 if (NULL != op->set)
886 {
887 if (GNUNET_YES == op->channel_death_expected)
888 {
889 /* oh goodie, we are done! */
891 }
892 else
893 {
894 /* sorry, channel went down early, too bad. */
896 }
897 }
898 else
900 GNUNET_free (op);
901}
static void _GSS_operation_destroy(struct Operation *op)
Destroy the given operation.
static void send_client_done_and_destroy(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_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_YES, incoming_destroy(), op, and send_client_done_and_destroy().

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

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 808 of file gnunet-service-seti.c.

809{
810 struct Listener *listener;
811
813 "Destroying incoming operation %p\n",
814 op);
815 if (NULL != (listener = op->listener))
816 {
818 listener->op_tail,
819 op);
820 op->listener = NULL;
821 }
822 if (NULL != op->timeout_task)
823 {
824 GNUNET_SCHEDULER_cancel (op->timeout_task);
825 op->timeout_task = NULL;
826 }
828}
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:986
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:

◆ send_client_done_and_destroy()

static void send_client_done_and_destroy ( void *  cls)
static

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

Parameters
clsoperation to destroy

Definition at line 838 of file gnunet-service-seti.c.

839{
840 struct Operation *op = cls;
841 struct GNUNET_MQ_Envelope *ev;
842 struct GNUNET_SETI_ResultMessage *rm;
843
845 "Intersection succeeded, sending DONE to local client\n");
847 "# Intersection operations succeeded",
848 1,
849 GNUNET_NO);
850 ev = GNUNET_MQ_msg (rm,
852 rm->request_id = htonl (op->client_request_id);
854 rm->element_type = htons (0);
855 GNUNET_MQ_send (op->set->cs->mq,
856 ev);
858}
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
@ GNUNET_SETI_STATUS_DONE
Success, all elements have been sent (and received).

References _GSS_operation_destroy(), _GSS_statistics, GNUNET_SETI_ResultMessage::element_type, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_SETI_RESULT, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_NO, GNUNET_SETI_STATUS_DONE, GNUNET_STATISTICS_update(), op, GNUNET_SETI_ResultMessage::request_id, and GNUNET_SETI_ResultMessage::result_status.

Referenced by _GSS_operation_destroy2(), handle_intersection_p2p_done(), and send_remaining_elements().

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

◆ fail_intersection_operation()

static void fail_intersection_operation ( struct Operation op)
static

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

Parameters
opthe intersection operation to fail

Definition at line 911 of file gnunet-service-seti.c.

912{
913 struct GNUNET_MQ_Envelope *ev;
915
917 "Intersection operation failed\n");
919 "# Intersection operations failed",
920 1,
921 GNUNET_NO);
922 if (NULL != op->my_elements)
923 {
925 op->my_elements = NULL;
926 }
927 ev = GNUNET_MQ_msg (msg,
929 msg->result_status = htons (GNUNET_SETI_STATUS_FAILURE);
930 msg->request_id = htonl (op->client_request_id);
931 msg->element_type = htons (0);
932 GNUNET_MQ_send (op->set->cs->mq,
933 ev);
935}
struct GNUNET_MessageHeader * msg
Definition 005.c:2
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_SETI_STATUS_FAILURE
The other peer refused to do the operation with us, or something went wrong.

References _GSS_operation_destroy(), _GSS_statistics, GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_MESSAGE_TYPE_SETI_RESULT, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_NO, GNUNET_SETI_STATUS_FAILURE, GNUNET_STATISTICS_update(), msg, and op.

Referenced by handle_intersection_p2p_bf(), handle_intersection_p2p_done(), handle_intersection_p2p_element_info(), and process_bf().

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

◆ send_bloomfilter()

static void send_bloomfilter ( struct Operation op)
static

Send a bloomfilter to our peer.

After the result done message has been sent to the client, destroy the evaluate operation.

Parameters
opintersection operation

Definition at line 945 of file gnunet-service-seti.c.

946{
947 struct GNUNET_MQ_Envelope *ev;
948 struct BFMessage *msg;
949 uint32_t bf_size;
950 uint32_t bf_elementbits;
951 uint32_t chunk_size;
952 char *bf_data;
953 uint32_t offset;
954
955 /* We consider the ratio of the set sizes to determine
956 the number of bits per element, as the smaller set
957 should use more bits to maximize its set reduction
958 potential and minimize overall bandwidth consumption. */
959 bf_elementbits = 2 + ceil (log2 ((double)
960 (op->remote_element_count
961 / (double) op->my_element_count)));
962 if (bf_elementbits < 1)
963 bf_elementbits = 1; /* make sure k is not 0 */
964 /* optimize BF-size to ~50% of bits set */
965 bf_size = ceil ((double) (op->my_element_count
966 * bf_elementbits / log (2)));
968 "Sending Bloom filter (%u) of size %u bytes\n",
969 (unsigned int) bf_elementbits,
970 (unsigned int) bf_size);
971 op->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL,
972 bf_size,
973 bf_elementbits);
974 op->salt = GNUNET_CRYPTO_random_u32 (UINT32_MAX);
977 op);
978
979 /* send our Bloom filter */
981 "# Intersection Bloom filters sent",
982 1,
983 GNUNET_NO);
984 chunk_size = 60 * 1024 - sizeof(struct BFMessage);
985 if (bf_size <= chunk_size)
986 {
987 /* singlepart */
988 chunk_size = bf_size;
990 chunk_size,
994 op->local_bf,
995 (char *) &msg[1],
996 bf_size));
997 msg->sender_element_count = htonl (op->my_element_count);
998 msg->bloomfilter_total_length = htonl (bf_size);
999 msg->bits_per_element = htonl (bf_elementbits);
1000 msg->sender_mutator = htonl (op->salt);
1001 msg->element_xor_hash = op->my_xor;
1002 GNUNET_MQ_send (op->mq, ev);
1003 }
1004 else
1005 {
1006 /* multipart */
1007 bf_data = GNUNET_malloc (bf_size);
1010 op->local_bf,
1011 bf_data,
1012 bf_size));
1013 offset = 0;
1014 while (offset < bf_size)
1015 {
1016 if (bf_size - chunk_size < offset)
1017 chunk_size = bf_size - offset;
1019 chunk_size,
1021 GNUNET_memcpy (&msg[1],
1022 &bf_data[offset],
1023 chunk_size);
1024 offset += chunk_size;
1025 msg->sender_element_count = htonl (op->my_element_count);
1026 msg->bloomfilter_total_length = htonl (bf_size);
1027 msg->bits_per_element = htonl (bf_elementbits);
1028 msg->sender_mutator = htonl (op->salt);
1029 msg->element_xor_hash = op->my_xor;
1030 GNUNET_MQ_send (op->mq, ev);
1031 }
1032 GNUNET_free (bf_data);
1033 }
1035 op->local_bf = NULL;
1036}
static int iterator_bf_create(void *cls, const struct GNUNET_HashCode *key, void *value)
Create initial bloomfilter based on all the elements given.
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a Bloom filter from raw bits.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_bloomfilter_get_raw_data(const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size)
Copy the raw data of this Bloom filter into the given data array.
uint32_t GNUNET_CRYPTO_random_u32(uint32_t i)
Produce a random value.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
@ GNUNET_SYSERR
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_MESSAGE_TYPE_SETI_P2P_BF
Bloom filter message for intersection exchange started by Bob.
Bloom filter messages exchanged for set intersection calculation.

References _GSS_statistics, GNUNET_assert, GNUNET_CONTAINER_bloomfilter_free(), GNUNET_CONTAINER_bloomfilter_get_raw_data(), GNUNET_CONTAINER_bloomfilter_init(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SETI_P2P_BF, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_SYSERR, iterator_bf_create(), msg, and op.

Referenced by begin_bf_exchange(), and process_bf().

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

◆ finished_local_operations()

static void finished_local_operations ( void *  cls)
static

Remember that we are done dealing with the local client AND have sent the other peer our message that we are done, so we are not just waiting for the channel to die before telling the local client that we are done as our last act.

Parameters
clsthe struct Operation.

Definition at line 1048 of file gnunet-service-seti.c.

1049{
1050 struct Operation *op = cls;
1051
1053 "DONE sent to other peer, now waiting for other end to close the channel\n");
1054 op->phase = PHASE_FINISHED;
1055 op->channel_death_expected = GNUNET_YES;
1056}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_YES, op, and PHASE_FINISHED.

Referenced by send_p2p_done().

Here is the caller graph for this function:

◆ send_p2p_done()

static void send_p2p_done ( struct Operation op)
static

Notify the other peer that we are done.

Once this message is out, we still need to notify the local client that we are done.

Parameters
opoperation to notify for.

Definition at line 1067 of file gnunet-service-seti.c.

1068{
1069 struct GNUNET_MQ_Envelope *ev;
1070 struct IntersectionDoneMessage *idm;
1071
1073 GNUNET_assert (GNUNET_NO == op->channel_death_expected);
1074 ev = GNUNET_MQ_msg (idm,
1076 idm->final_element_count = htonl (op->my_element_count);
1077 idm->element_xor_hash = op->my_xor;
1080 op);
1081 GNUNET_MQ_send (op->mq,
1082 ev);
1083}
static void finished_local_operations(void *cls)
Remember that we are done dealing with the local client AND have sent the other peer our message that...
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition mq.c:655
#define GNUNET_MESSAGE_TYPE_SETI_P2P_DONE
Intersection operation is done.
Last message, send to confirm the final set.
uint32_t final_element_count
Final number of elements in intersection.
struct GNUNET_HashCode element_xor_hash
XOR of all hashes over all elements remaining in the set.

References IntersectionDoneMessage::element_xor_hash, IntersectionDoneMessage::final_element_count, finished_local_operations(), GNUNET_assert, GNUNET_MESSAGE_TYPE_SETI_P2P_DONE, GNUNET_MQ_msg, GNUNET_MQ_notify_sent(), GNUNET_MQ_send(), GNUNET_NO, op, and PHASE_MUST_SEND_DONE.

Referenced by process_bf(), and send_remaining_elements().

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

◆ send_remaining_elements()

static void send_remaining_elements ( void *  cls)
static

Send all elements in the full result iterator.

Parameters
clsthe struct Operation *

Definition at line 1092 of file gnunet-service-seti.c.

1093{
1094 struct Operation *op = cls;
1095 const void *nxt;
1096 const struct ElementEntry *ee;
1097 struct GNUNET_MQ_Envelope *ev;
1098 struct GNUNET_SETI_ResultMessage *rm;
1099 const struct GNUNET_SETI_Element *element;
1100 int res;
1101
1102 if (GNUNET_NO == op->return_intersection)
1103 {
1104 GNUNET_break (0);
1105 return; /* Wrong mode for transmitting removed elements */
1106 }
1108 op->full_result_iter,
1109 NULL,
1110 &nxt);
1111 if (GNUNET_NO == res)
1112 {
1114 "Sending done and destroy because iterator ran out\n");
1116 op->full_result_iter);
1117 op->full_result_iter = NULL;
1118 if (PHASE_DONE_RECEIVED == op->phase)
1119 {
1120 op->phase = PHASE_FINISHED;
1122 }
1123 else if (PHASE_MUST_SEND_DONE == op->phase)
1124 {
1125 send_p2p_done (op);
1126 }
1127 else
1128 {
1129 GNUNET_assert (0);
1130 }
1131 return;
1132 }
1133 ee = nxt;
1134 element = &ee->element;
1136 "Sending element %s:%u to client (full set)\n",
1137 GNUNET_h2s (&ee->element_hash),
1138 element->size);
1139 GNUNET_assert (0 != op->client_request_id);
1140 ev = GNUNET_MQ_msg_extra (rm,
1141 element->size,
1143 GNUNET_assert (NULL != ev);
1145 rm->request_id = htonl (op->client_request_id);
1146 rm->element_type = element->element_type;
1147 GNUNET_memcpy (&rm[1],
1148 element->data,
1149 element->size);
1152 op);
1153 GNUNET_MQ_send (op->set->cs->mq,
1154 ev);
1155}
static char * res
Currently read line or NULL on EOF.
static void send_p2p_done(struct Operation *op)
Notify the other peer that we are done.
static void send_remaining_elements(void *cls)
Send all elements in the full result iterator.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator's position.
@ GNUNET_SETI_STATUS_ADD_LOCAL
Element should be added to the result set of the local peer, i.e.
Element stored in a set.

References GNUNET_SETI_Element::data, ElementEntry::element, ElementEntry::element_hash, GNUNET_SETI_Element::element_type, GNUNET_SETI_ResultMessage::element_type, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_iterator_destroy(), GNUNET_CONTAINER_multihashmap_iterator_next(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SETI_RESULT, GNUNET_MQ_msg_extra, GNUNET_MQ_notify_sent(), GNUNET_MQ_send(), GNUNET_NO, GNUNET_SETI_STATUS_ADD_LOCAL, op, PHASE_DONE_RECEIVED, PHASE_FINISHED, PHASE_MUST_SEND_DONE, GNUNET_SETI_ResultMessage::request_id, res, GNUNET_SETI_ResultMessage::result_status, send_client_done_and_destroy(), send_p2p_done(), send_remaining_elements(), and GNUNET_SETI_Element::size.

Referenced by handle_intersection_p2p_done(), process_bf(), and send_remaining_elements().

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

◆ initialize_map_unfiltered()

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

Fills the "my_elements" hashmap with the initial set of (non-deleted) elements from the set of the specification.

Parameters
clsclosure with the struct Operation *
keycurrent key code for the element
valuevalue in the hash map with the struct ElementEntry *
Returns
GNUNET_YES (we should continue to iterate)

Definition at line 1168 of file gnunet-service-seti.c.

1171{
1172 struct ElementEntry *ee = value;
1173 struct Operation *op = cls;
1174
1176 return GNUNET_YES; /* element not live in operation's generation */
1177 GNUNET_CRYPTO_hash_xor (&op->my_xor,
1178 &ee->element_hash,
1179 &op->my_xor);
1181 "Initial full initialization of my_elements, adding %s:%u\n",
1182 GNUNET_h2s (&ee->element_hash),
1183 ee->element.size);
1186 &ee->element_hash,
1187 ee,
1189 return GNUNET_YES;
1190}

References _GSS_is_element_of_operation(), ElementEntry::element, ElementEntry::element_hash, GNUNET_break, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash_xor(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_YES, op, GNUNET_SET_Element::size, and value.

Referenced by begin_bf_exchange().

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

◆ send_element_count()

static void send_element_count ( struct Operation op)
static

Send our element count to the peer, in case our element count is lower than theirs.

Parameters
opintersection operation

Definition at line 1200 of file gnunet-service-seti.c.

1201{
1202 struct GNUNET_MQ_Envelope *ev;
1204
1206 "Sending our element count (%u)\n",
1207 op->my_element_count);
1208 ev = GNUNET_MQ_msg (msg,
1210 msg->sender_element_count = htonl (op->my_element_count);
1211 GNUNET_MQ_send (op->mq, ev);
1212}
#define GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO
Information about the element count for intersection.
During intersection, the first (and possibly second) message send it the number of elements in the se...

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO, GNUNET_MQ_msg, GNUNET_MQ_send(), msg, and op.

Referenced by handle_client_accept().

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

◆ begin_bf_exchange()

static void begin_bf_exchange ( struct Operation op)
static

We go first, initialize our map with all elements and send the first Bloom filter.

Parameters
opoperation to start exchange for

Definition at line 1222 of file gnunet-service-seti.c.

1223{
1224 op->phase = PHASE_BF_EXCHANGE;
1225 GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
1227 op);
1229}
static int initialize_map_unfiltered(void *cls, const struct GNUNET_HashCode *key, void *value)
Fills the "my_elements" hashmap with the initial set of (non-deleted) elements from the set of the sp...
static void send_bloomfilter(struct Operation *op)
Send a bloomfilter to our peer.

References GNUNET_CONTAINER_multihashmap_iterate(), initialize_map_unfiltered(), op, PHASE_BF_EXCHANGE, and send_bloomfilter().

Referenced by handle_client_accept(), and handle_intersection_p2p_element_info().

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

◆ handle_intersection_p2p_element_info()

static void handle_intersection_p2p_element_info ( void *  cls,
const struct IntersectionElementInfoMessage msg 
)
static

Handle the initial struct IntersectionElementInfoMessage from a remote peer.

Parameters
clsthe intersection operation
mhthe header of the message

Definition at line 1240 of file gnunet-service-seti.c.

1243{
1244 struct Operation *op = cls;
1245
1246 op->remote_element_count = ntohl (msg->sender_element_count);
1248 "Received remote element count (%u), I have %u\n",
1249 op->remote_element_count,
1250 op->my_element_count);
1251 if (((PHASE_INITIAL != op->phase) &&
1252 (PHASE_COUNT_SENT != op->phase)) ||
1253 (op->my_element_count > op->remote_element_count) ||
1254 (0 == op->my_element_count) ||
1255 (0 == op->remote_element_count))
1256 {
1257 GNUNET_break_op (0);
1259 return;
1260 }
1261 GNUNET_break (NULL == op->remote_bf);
1263 GNUNET_CADET_receive_done (op->channel);
1264}
static void begin_bf_exchange(struct Operation *op)
We go first, initialize our map with all elements and send the first Bloom filter.
static void fail_intersection_operation(struct Operation *op)
Inform the client that the intersection operation has failed, and proceed to destroy the evaluate ope...
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Indicate readiness to receive the next message on a channel.
Definition cadet_api.c:875
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.

References begin_bf_exchange(), fail_intersection_operation(), GNUNET_break, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, msg, op, PHASE_COUNT_SENT, and PHASE_INITIAL.

Here is the call graph for this function:

◆ process_bf()

static void process_bf ( struct Operation op)
static

Process a Bloomfilter once we got all the chunks.

Parameters
opthe intersection operation

Definition at line 1273 of file gnunet-service-seti.c.

1274{
1276 "Received BF in phase %u, foreign count is %u, my element count is %u/%u\n",
1277 op->phase,
1278 op->remote_element_count,
1279 op->my_element_count,
1280 GNUNET_CONTAINER_multihashmap_size (op->set->content->elements));
1281 switch (op->phase)
1282 {
1283 case PHASE_INITIAL:
1284 GNUNET_break_op (0);
1286 return;
1287 case PHASE_COUNT_SENT:
1288 /* This is the first BF being sent, build our initial map with
1289 filtering in place */
1290 op->my_element_count = 0;
1291 GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
1293 op);
1294 break;
1295 case PHASE_BF_EXCHANGE:
1296 /* Update our set by reduction */
1299 op);
1300 break;
1302 GNUNET_break_op (0);
1304 return;
1306 GNUNET_break_op (0);
1308 return;
1309 case PHASE_FINISHED:
1310 GNUNET_break_op (0);
1312 return;
1313 }
1315 op->remote_bf = NULL;
1316
1317 if ((0 == op->my_element_count) || /* fully disjoint */
1318 ((op->my_element_count == op->remote_element_count) &&
1319 (0 == GNUNET_memcmp (&op->my_xor,
1320 &op->other_xor))))
1321 {
1322 /* we are done */
1323 op->phase = PHASE_MUST_SEND_DONE;
1325 "Intersection succeeded, sending DONE to other peer\n");
1327 op->local_bf = NULL;
1328 if (GNUNET_YES == op->return_intersection)
1329 {
1331 "Sending full result set (%u elements)\n",
1332 GNUNET_CONTAINER_multihashmap_size (op->my_elements));
1333 op->full_result_iter
1335 op->my_elements);
1337 return;
1338 }
1339 send_p2p_done (op);
1340 return;
1341 }
1342 op->phase = PHASE_BF_EXCHANGE;
1344}
static int iterator_bf_reduce(void *cls, const struct GNUNET_HashCode *key, void *value)
Removes elements from our hashmap if they are not contained within the provided remote bloomfilter.
static int filtered_map_initialization(void *cls, const struct GNUNET_HashCode *key, void *value)
Fills the "my_elements" hashmap with all relevant elements.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.

References fail_intersection_operation(), filtered_map_initialization(), GNUNET_break_op, GNUNET_CONTAINER_bloomfilter_free(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_iterator_create(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcmp, GNUNET_YES, iterator_bf_reduce(), op, PHASE_BF_EXCHANGE, PHASE_COUNT_SENT, PHASE_DONE_RECEIVED, PHASE_FINISHED, PHASE_INITIAL, PHASE_MUST_SEND_DONE, send_bloomfilter(), send_p2p_done(), and send_remaining_elements().

Referenced by handle_intersection_p2p_bf().

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

◆ check_intersection_p2p_bf()

static int check_intersection_p2p_bf ( void *  cls,
const struct BFMessage msg 
)
static

Check an BF message from a remote peer.

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

Definition at line 1355 of file gnunet-service-seti.c.

1357{
1358 struct Operation *op = cls;
1359
1360 (void) op;
1361 return GNUNET_OK;
1362}
@ GNUNET_OK

References GNUNET_OK, and op.

◆ handle_intersection_p2p_bf()

static void handle_intersection_p2p_bf ( void *  cls,
const struct BFMessage msg 
)
static

Handle an BF message from a remote peer.

Parameters
clsthe intersection operation
msgthe header of the message

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

1374{
1375 struct Operation *op = cls;
1376 uint32_t bf_size;
1377 uint32_t chunk_size;
1378 uint32_t bf_bits_per_element;
1379
1380 switch (op->phase)
1381 {
1382 case PHASE_INITIAL:
1383 GNUNET_break_op (0);
1385 return;
1386
1387 case PHASE_COUNT_SENT:
1388 case PHASE_BF_EXCHANGE:
1389 bf_size = ntohl (msg->bloomfilter_total_length);
1390 bf_bits_per_element = ntohl (msg->bits_per_element);
1391 chunk_size = htons (msg->header.size) - sizeof(struct BFMessage);
1392 op->other_xor = msg->element_xor_hash;
1393 if (bf_size == chunk_size)
1394 {
1395 if (NULL != op->bf_data)
1396 {
1397 GNUNET_break_op (0);
1399 return;
1400 }
1401 /* single part, done here immediately */
1402 op->remote_bf
1403 = GNUNET_CONTAINER_bloomfilter_init ((const char *) &msg[1],
1404 bf_size,
1405 bf_bits_per_element);
1406 op->salt = ntohl (msg->sender_mutator);
1407 op->remote_element_count = ntohl (msg->sender_element_count);
1408 process_bf (op);
1409 break;
1410 }
1411 /* multipart chunk */
1412 if (NULL == op->bf_data)
1413 {
1414 /* first chunk, initialize */
1415 op->bf_data = GNUNET_malloc (bf_size);
1416 op->bf_data_size = bf_size;
1417 op->bf_bits_per_element = bf_bits_per_element;
1418 op->bf_data_offset = 0;
1419 op->salt = ntohl (msg->sender_mutator);
1420 op->remote_element_count = ntohl (msg->sender_element_count);
1421 }
1422 else
1423 {
1424 /* increment */
1425 if ((op->bf_data_size != bf_size) ||
1426 (op->bf_bits_per_element != bf_bits_per_element) ||
1427 (op->bf_data_offset + chunk_size > bf_size) ||
1428 (op->salt != ntohl (msg->sender_mutator)) ||
1429 (op->remote_element_count != ntohl (msg->sender_element_count)))
1430 {
1431 GNUNET_break_op (0);
1433 return;
1434 }
1435 }
1436 GNUNET_memcpy (&op->bf_data[op->bf_data_offset],
1437 (const char *) &msg[1],
1438 chunk_size);
1439 op->bf_data_offset += chunk_size;
1440 if (op->bf_data_offset == bf_size)
1441 {
1442 /* last chunk, run! */
1443 op->remote_bf
1445 bf_size,
1446 bf_bits_per_element);
1447 GNUNET_free (op->bf_data);
1448 op->bf_data = NULL;
1449 op->bf_data_size = 0;
1450 process_bf (op);
1451 }
1452 break;
1453
1454 default:
1455 GNUNET_break_op (0);
1457 return;
1458 }
1459 GNUNET_CADET_receive_done (op->channel);
1460}
static void process_bf(struct Operation *op)
Process a Bloomfilter once we got all the chunks.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
uint32_t bf_bits_per_element
size of the bloomfilter

References Operation::bf_bits_per_element, fail_intersection_operation(), GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_bloomfilter_init(), GNUNET_free, GNUNET_malloc, GNUNET_memcpy, msg, op, PHASE_BF_EXCHANGE, PHASE_COUNT_SENT, PHASE_INITIAL, process_bf(), and GNUNET_MessageHeader::size.

Here is the call graph for this function:

◆ filter_all()

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

Remove all elements from our hashmap.

Parameters
clsclosure with the struct Operation *
keycurrent key code
valuevalue in the hash map
Returns
GNUNET_YES (we should continue to iterate)

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

1475{
1476 struct Operation *op = cls;
1477 struct ElementEntry *ee = value;
1478
1479 GNUNET_break (0 < op->my_element_count);
1480 op->my_element_count--;
1481 GNUNET_CRYPTO_hash_xor (&op->my_xor,
1482 &ee->element_hash,
1483 &op->my_xor);
1485 "Final reduction of my_elements, removing %s:%u\n",
1486 GNUNET_h2s (&ee->element_hash),
1487 ee->element.size);
1490 &ee->element_hash,
1491 ee));
1493 &ee->element);
1494 return GNUNET_YES;
1495}

References ElementEntry::element, ElementEntry::element_hash, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CRYPTO_hash_xor(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_YES, op, send_client_removed_element(), GNUNET_SET_Element::size, and value.

Referenced by handle_intersection_p2p_done().

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

◆ handle_intersection_p2p_done()

static void handle_intersection_p2p_done ( void *  cls,
const struct IntersectionDoneMessage idm 
)
static

Handle a done message from a remote peer.

Parameters
clsthe intersection operation
mhthe message

Definition at line 1505 of file gnunet-service-seti.c.

1507{
1508 struct Operation *op = cls;
1509
1510 if (PHASE_BF_EXCHANGE != op->phase)
1511 {
1512 /* wrong phase to conclude? FIXME: Or should we allow this
1513 if the other peer has _initially_ already an empty set? */
1514 GNUNET_break_op (0);
1516 return;
1517 }
1518 if (0 == ntohl (idm->final_element_count))
1519 {
1520 /* other peer determined empty set is the intersection,
1521 remove all elements */
1523 &filter_all,
1524 op);
1525 }
1526 if ((op->my_element_count != ntohl (idm->final_element_count)) ||
1527 (0 != GNUNET_memcmp (&op->my_xor,
1528 &idm->element_xor_hash)))
1529 {
1530 /* Other peer thinks we are done, but we disagree on the result! */
1531 GNUNET_break_op (0);
1533 return;
1534 }
1536 "Got IntersectionDoneMessage, have %u elements in intersection\n",
1537 op->my_element_count);
1538 op->phase = PHASE_DONE_RECEIVED;
1539 GNUNET_CADET_receive_done (op->channel);
1540
1541 GNUNET_assert (GNUNET_NO == op->client_done_sent);
1542 if (GNUNET_YES == op->return_intersection)
1543 {
1545 "Sending full result set to client (%u elements)\n",
1546 GNUNET_CONTAINER_multihashmap_size (op->my_elements));
1547 op->full_result_iter
1550 return;
1551 }
1552 op->phase = PHASE_FINISHED;
1554}
static int filter_all(void *cls, const struct GNUNET_HashCode *key, void *value)
Remove all elements from our hashmap.

References IntersectionDoneMessage::element_xor_hash, fail_intersection_operation(), filter_all(), IntersectionDoneMessage::final_element_count, GNUNET_assert, GNUNET_break_op, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_iterator_create(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcmp, GNUNET_NO, GNUNET_YES, op, PHASE_BF_EXCHANGE, PHASE_DONE_RECEIVED, PHASE_FINISHED, send_client_done_and_destroy(), and send_remaining_elements().

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 1566 of file gnunet-service-seti.c.

1567{
1568 for (struct Listener *listener = listener_head; NULL != listener;
1569 listener = listener->next)
1570 {
1571 for (struct Operation *op = listener->op_head; NULL != op; op = op->next)
1572 if (op->suggest_id == id)
1573 return op;
1574 }
1575 return NULL;
1576}
static struct Listener * listener_head
Listeners are held in a doubly linked list.
struct GNUNET_ARM_Operation * next
This is a doubly-linked list.
Definition arm_api.c:45
struct Listener * next
Listeners are held in a doubly linked list.

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

Referenced by handle_client_accept(), and handle_client_reject().

Here is the caller graph for this function:

◆ client_connect_cb()

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

Callback called when a client connects to the service.

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

Definition at line 1588 of file gnunet-service-seti.c.

1591{
1592 struct ClientState *cs;
1593
1594 num_clients++;
1595 cs = GNUNET_new (struct ClientState);
1596 cs->client = c;
1597 cs->mq = mq;
1598 return cs;
1599}
static unsigned int num_clients
Number of active clients.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
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, ClientState::mq, 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 1611 of file gnunet-service-seti.c.

1614{
1615 struct ElementEntry *ee = value;
1616
1617 GNUNET_free (ee);
1618 return GNUNET_YES;
1619}

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 1630 of file gnunet-service-seti.c.

1633{
1634 struct ClientState *cs = internal_cls;
1635 struct Operation *op;
1636 struct Listener *listener;
1637 struct Set *set;
1638
1639 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, cleaning up\n");
1640 if (NULL != (set = cs->set))
1641 {
1642 struct SetContent *content = set->content;
1643
1644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying client's set\n");
1645 /* Destroy pending set operations */
1646 while (NULL != set->ops_head)
1648
1649 /* free set content (or at least decrement RC) */
1650 set->content = NULL;
1651 GNUNET_assert (0 != content->refcount);
1652 content->refcount--;
1653 if (0 == content->refcount)
1654 {
1655 GNUNET_assert (NULL != content->elements);
1658 NULL);
1660 content->elements = NULL;
1661 GNUNET_free (content);
1662 }
1663 GNUNET_free (set);
1664 }
1665
1666 if (NULL != (listener = cs->listener))
1667 {
1668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying client's listener\n");
1670 listener->open_port = NULL;
1671 while (NULL != (op = listener->op_head))
1672 {
1674 "Destroying incoming operation `%u' from peer `%s'\n",
1675 (unsigned int) op->client_request_id,
1676 GNUNET_i2s (&op->peer));
1678 }
1680 GNUNET_free (listener);
1681 }
1682 GNUNET_free (cs);
1683 num_clients--;
1684 if ((GNUNET_YES == in_shutdown) && (0 == num_clients))
1685 {
1686 if (NULL != cadet)
1687 {
1689 cadet = NULL;
1690 }
1691 }
1692}
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:777
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port.
Definition cadet_api.c:804
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_INFO
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 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, and ClientState::set.

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 1704 of file gnunet-service-seti.c.

1706{
1707 struct Operation *op = cls;
1708 struct Listener *listener = op->listener;
1709 const struct GNUNET_MessageHeader *nested_context;
1710
1711 /* double operation request */
1712 if (0 != op->suggest_id)
1713 {
1714 GNUNET_break_op (0);
1715 return GNUNET_SYSERR;
1716 }
1717 /* This should be equivalent to the previous condition, but can't hurt to check twice */
1718 if (NULL == listener)
1719 {
1720 GNUNET_break (0);
1721 return GNUNET_SYSERR;
1722 }
1723 nested_context = GNUNET_MQ_extract_nested_mh (msg);
1724 if ((NULL != nested_context) &&
1725 (ntohs (nested_context->size) > GNUNET_SETI_CONTEXT_MESSAGE_MAX_SIZE))
1726 {
1727 GNUNET_break_op (0);
1728 return GNUNET_SYSERR;
1729 }
1730 return GNUNET_OK;
1731}
#define GNUNET_MQ_extract_nested_mh(var)
Return a pointer to the message at the end of the given message.
#define GNUNET_SETI_CONTEXT_MESSAGE_MAX_SIZE
Maximum size of a context message for set operation requests.
Header for all communications.

References GNUNET_break, GNUNET_break_op, GNUNET_MQ_extract_nested_mh, GNUNET_OK, GNUNET_SETI_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
Returns
GNUNET_OK if the channel should be kept alive, GNUNET_SYSERR to destroy the channel

Definition at line 1752 of file gnunet-service-seti.c.

1754{
1755 struct Operation *op = cls;
1756 struct Listener *listener = op->listener;
1757 const struct GNUNET_MessageHeader *nested_context;
1758 struct GNUNET_MQ_Envelope *env;
1759 struct GNUNET_SETI_RequestMessage *cmsg;
1760
1761 nested_context = GNUNET_MQ_extract_nested_mh (msg);
1762 /* Make a copy of the nested_context (application-specific context
1763 information that is opaque to set) so we can pass it to the
1764 listener later on */
1765 if (NULL != nested_context)
1766 op->context_msg = GNUNET_copy_message (nested_context);
1767 op->remote_element_count = ntohl (msg->element_count);
1768 GNUNET_log (
1770 "Received P2P operation request (port %s) for active listener\n",
1771 GNUNET_h2s (&op->listener->app_id));
1772 GNUNET_assert (0 == op->suggest_id);
1773 if (0 == suggest_id)
1774 suggest_id++;
1775 op->suggest_id = suggest_id++;
1776 GNUNET_assert (NULL != op->timeout_task);
1777 GNUNET_SCHEDULER_cancel (op->timeout_task);
1778 op->timeout_task = NULL;
1781 op->context_msg);
1782 GNUNET_log (
1784 "Suggesting incoming request with accept id %u to listener %p of client %p\n",
1785 op->suggest_id,
1786 listener,
1787 listener->cs);
1788 cmsg->accept_id = htonl (op->suggest_id);
1789 cmsg->peer_id = op->peer;
1790 GNUNET_MQ_send (listener->cs->mq, env);
1791 /* NOTE: GNUNET_CADET_receive_done() will be called in
1792 #handle_client_accept() */
1793}
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static uint32_t suggest_id
Counter for allocating unique IDs for clients, used to identify incoming operation requests from remo...
struct GNUNET_MessageHeader * GNUNET_copy_message(const struct GNUNET_MessageHeader *msg)
Create a copy of the given message.
#define GNUNET_MQ_msg_nested_mh(mvar, type, mh)
Allocate a GNUNET_MQ_Envelope, and append a payload message after the given message struct.
#define GNUNET_MESSAGE_TYPE_SETI_REQUEST
Notify the client of an incoming request from a remote peer.
A request for an operation with another client.
Definition seti.h:124
struct GNUNET_PeerIdentity peer_id
Identity of the requesting peer.
Definition seti.h:139
uint32_t accept_id
ID of the to identify the request when accepting or rejecting it.
Definition seti.h:134
struct ClientState * cs
Client that owns the listener.

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

Here is the call graph for this function:

◆ handle_client_create_set()

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

Called when a client wants to create a new set.

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

Parameters
clsclient that sent the message
mmessage sent by the client

Definition at line 1805 of file gnunet-service-seti.c.

1807{
1808 struct ClientState *cs = cls;
1809 struct Set *set;
1810
1812 "Client created new intersection set\n");
1813 if (NULL != cs->set)
1814 {
1815 /* There can only be one set per client */
1816 GNUNET_break (0);
1818 return;
1819 }
1820 set = GNUNET_new (struct Set);
1821 set->content = GNUNET_new (struct SetContent);
1822 set->content->refcount = 1;
1824 GNUNET_YES);
1825 set->cs = cs;
1826 cs->set = set;
1828}
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2463
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2434

References ClientState::client, Set::content, Set::cs, SetContent::elements, GNUNET_break, GNUNET_CONTAINER_multihashmap_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_YES, SetContent::refcount, and ClientState::set.

Here is the call graph for this function:

◆ incoming_timeout_cb()

static void incoming_timeout_cb ( void *  cls)
static

Timeout happens iff:

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

Definition at line 1841 of file gnunet-service-seti.c.

1842{
1843 struct Operation *op = cls;
1844
1845 op->timeout_task = NULL;
1847 "Remote peer's incoming request timed out\n");
1849}

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

Referenced by channel_new_cb().

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

◆ channel_new_cb()

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

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

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

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

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

Definition at line 1869 of file gnunet-service-seti.c.

1872{
1873 struct Listener *listener = cls;
1874 struct Operation *op;
1875
1877 "New incoming channel\n");
1878 op = GNUNET_new (struct Operation);
1879 op->listener = listener;
1880 op->peer = *source;
1881 op->channel = channel;
1882 op->mq = GNUNET_CADET_get_mq (op->channel);
1883 op->salt = GNUNET_CRYPTO_random_u32 (UINT32_MAX);
1886 op);
1889 op);
1890 return op;
1891}
static GstElement * source
Appsrc instance into which we write data for the pipeline.
#define INCOMING_CHANNEL_TIMEOUT
How long do we hold on to an incoming channel if there is no local listener before giving up?
static void incoming_timeout_cb(void *cls)
Timeout happens iff:
struct GNUNET_MQ_Handle * GNUNET_CADET_get_mq(const struct GNUNET_CADET_Channel *channel)
Obtain the message queue for a connected channel.
Definition cadet_api.c:1081
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
struct GNUNET_CADET_Channel * channel
Channel to the peer.
struct Listener * listener
Port this operation runs on.

References Operation::channel, GNUNET_CADET_get_mq(), GNUNET_CONTAINER_DLL_insert, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, GNUNET_SCHEDULER_add_delayed(), INCOMING_CHANNEL_TIMEOUT, incoming_timeout_cb(), Operation::listener, op, Listener::op_head, Listener::op_tail, and source.

Referenced by handle_client_listen().

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

◆ channel_end_cb()

static void channel_end_cb ( void *  channel_ctx,
const struct GNUNET_CADET_Channel channel 
)
static

Function called whenever a channel is destroyed.

Should clean up any associated state. It must NOT call GNUNET_CADET_channel_destroy() on the channel.

The peer_disconnect function is part of a a virtual table set initially either when a peer creates a new channel with us, or once we create a new channel ourselves (evaluate).

Once we know the exact type of operation (union/intersection), the vt is replaced with an operation specific instance (GSS[op]_vt).

Parameters
channel_ctxplace where local state associated with the channel is stored
channelconnection to the other end (henceforth invalid)

Definition at line 1911 of file gnunet-service-seti.c.

1913{
1914 struct Operation *op = channel_ctx;
1915
1916 op->channel = NULL;
1918}

References _GSS_operation_destroy2(), and op.

Referenced by handle_client_evaluate(), and handle_client_listen().

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

◆ channel_window_cb()

static void channel_window_cb ( void *  cls,
const struct GNUNET_CADET_Channel channel,
int  window_size 
)
static

Function called whenever an MQ-channel's transmission window size changes.

The first callback in an outgoing channel will be with a non-zero value and will mean the channel is connected to the destination.

For an incoming channel it will be called immediately after the GNUNET_CADET_ConnectEventHandler, also with a non-zero value.

Parameters
clsChannel closure.
channelConnection to the other end (henceforth invalid).
window_sizeNew window size. If the is more messages than buffer size this value will be negative..

Definition at line 1936 of file gnunet-service-seti.c.

1939{
1940 /* FIXME: not implemented, we could do flow control here... */
1941}

Referenced by handle_client_evaluate(), and handle_client_listen().

Here is the caller graph for this function:

◆ handle_client_listen()

static void handle_client_listen ( void *  cls,
const struct GNUNET_SETI_ListenMessage msg 
)
static

Called when a client wants to create a new listener.

Parameters
clsclient that sent the message
msgmessage sent by the client

Definition at line 1951 of file gnunet-service-seti.c.

1953{
1954 struct ClientState *cs = cls;
1955 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1956 GNUNET_MQ_hd_var_size (incoming_msg,
1959 NULL),
1960 GNUNET_MQ_hd_fixed_size (intersection_p2p_element_info,
1963 NULL),
1964 GNUNET_MQ_hd_var_size (intersection_p2p_bf,
1966 struct BFMessage,
1967 NULL),
1968 GNUNET_MQ_hd_fixed_size (intersection_p2p_done,
1971 NULL),
1973 };
1974 struct Listener *listener;
1975
1976 if (NULL != cs->listener)
1977 {
1978 /* max. one active listener per client! */
1979 GNUNET_break (0);
1981 return;
1982 }
1983 listener = GNUNET_new (struct Listener);
1984 listener->cs = cs;
1985 cs->listener = listener;
1986 listener->app_id = msg->app_id;
1989 listener);
1991 "New listener for set intersection created (port %s)\n",
1992 GNUNET_h2s (&listener->app_id));
1994 &msg->app_id,
1996 listener,
1999 cadet_handlers);
2001}
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.
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.
static void channel_end_cb(void *channel_ctx, const struct GNUNET_CADET_Channel *channel)
Function called whenever a channel is destroyed.
struct GNUNET_CADET_Port * GNUNET_CADET_open_port(struct GNUNET_CADET_Handle *h, const struct GNUNET_HashCode *port, GNUNET_CADET_ConnectEventHandler connects, void *connects_cls, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Open a port to receive incoming MQ-based channels.
Definition cadet_api.c:966
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST
Request to begin set intersection operation.
Message handler for a specific message type.
struct GNUNET_HashCode app_id
Application ID for the operation, used to distinguish multiple operations of the same type with the s...

References Listener::app_id, cadet, channel_end_cb(), channel_new_cb(), channel_window_cb(), ClientState::client, Listener::cs, GNUNET_break, GNUNET_CADET_open_port(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_SETI_P2P_BF, GNUNET_MESSAGE_TYPE_SETI_P2P_DONE, GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO, GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST, GNUNET_MQ_handler_end, GNUNET_MQ_hd_fixed_size, GNUNET_MQ_hd_var_size, GNUNET_new, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), ClientState::listener, listener_head, listener_tail, msg, and Listener::open_port.

Here is the call graph for this function:

◆ handle_client_reject()

static void handle_client_reject ( void *  cls,
const struct GNUNET_SETI_RejectMessage msg 
)
static

Called when the listening client rejects an operation request by another peer.

Parameters
clsclient that sent the message
msgmessage sent by the client

Definition at line 2012 of file gnunet-service-seti.c.

2014{
2015 struct ClientState *cs = cls;
2016 struct Operation *op;
2017
2018 op = get_incoming (ntohl (msg->accept_reject_id));
2019 if (NULL == op)
2020 {
2021 /* no matching incoming operation for this reject;
2022 could be that the other peer already disconnected... */
2024 "Client rejected unknown operation %u\n",
2025 (unsigned int) ntohl (msg->accept_reject_id));
2027 return;
2028 }
2030 "Peer request (app %s) rejected by client\n",
2031 GNUNET_h2s (&cs->listener->app_id));
2034}
static struct Operation * get_incoming(uint32_t id)
Get the incoming socket associated with the given id.

References _GSS_operation_destroy2(), Listener::app_id, ClientState::client, get_incoming(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_h2s(), GNUNET_log, GNUNET_SERVICE_client_continue(), ClientState::listener, msg, and op.

Here is the call graph for this function:

◆ check_client_set_add()

static int check_client_set_add ( void *  cls,
const struct GNUNET_SETI_ElementMessage msg 
)
static

Called when a client wants to add or remove an element to a set it inhabits.

Parameters
clsclient that sent the message
msgmessage sent by the client

Definition at line 2044 of file gnunet-service-seti.c.

2046{
2047 /* NOTE: Technically, we should probably check with the
2048 block library whether the element we are given is well-formed */
2049 return GNUNET_OK;
2050}

References GNUNET_OK.

◆ handle_client_set_add()

static void handle_client_set_add ( void *  cls,
const struct GNUNET_SETI_ElementMessage msg 
)
static

Called when a client wants to add an element to a set it inhabits.

Parameters
clsclient that sent the message
msgmessage sent by the client

Definition at line 2060 of file gnunet-service-seti.c.

2062{
2063 struct ClientState *cs = cls;
2064 struct Set *set;
2065 struct GNUNET_SETI_Element el;
2066 struct ElementEntry *ee;
2067 struct GNUNET_HashCode hash;
2068
2069 if (NULL == (set = cs->set))
2070 {
2071 /* client without a set requested an operation */
2072 GNUNET_break (0);
2074 return;
2075 }
2077 el.size = ntohs (msg->header.size) - sizeof(*msg);
2078 el.data = &msg[1];
2079 el.element_type = ntohs (msg->element_type);
2081 &hash);
2083 &hash);
2084 if (NULL == ee)
2085 {
2087 "Client inserts element %s of size %u\n",
2088 GNUNET_h2s (&hash),
2089 el.size);
2090 ee = GNUNET_malloc (el.size + sizeof(*ee));
2091 ee->element.size = el.size;
2092 GNUNET_memcpy (&ee[1], el.data, el.size);
2093 ee->element.data = &ee[1];
2094 ee->element.element_type = el.element_type;
2095 ee->remote = GNUNET_NO;
2096 ee->element_hash = hash;
2099 set->content->elements,
2100 &ee->element_hash,
2101 ee,
2103 }
2104 else
2105 {
2107 "Client inserted element %s of size %u twice (ignored)\n",
2108 GNUNET_h2s (&hash),
2109 el.size);
2110 /* same element inserted twice */
2111 return;
2112 }
2114}
static struct GNUNET_IDENTITY_EgoLookup * el
Handle for our ego lookup.
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.
void GNUNET_SETI_element_hash(const struct GNUNET_SETI_Element *element, struct GNUNET_HashCode *ret_hash)
Hash a set element.
Definition seti_api.c:849
int remote
GNUNET_YES if the element is a remote element, and does not belong to the operation's set.
const void * data
Actual data of the element.
uint16_t element_type
Application-specific element type.
uint32_t current_set_element_count
Number of currently valid elements in the set which have not been removed.

References ClientState::client, Set::content, Set::current_set_element_count, GNUNET_SET_Element::data, el, ElementEntry::element, ElementEntry::element_hash, GNUNET_SET_Element::element_type, SetContent::elements, GNUNET_break, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_SETI_element_hash(), GNUNET_YES, msg, ElementEntry::remote, ClientState::set, GNUNET_MessageHeader::size, and GNUNET_SET_Element::size.

Here is the call graph for this function:

◆ advance_generation()

static void advance_generation ( struct Set set)
static

Advance the current generation of a set, adding exclusion ranges if necessary.

Parameters
setthe set where we want to advance the generation

Definition at line 2124 of file gnunet-service-seti.c.

2125{
2127 {
2128 set->content->latest_generation++;
2129 set->current_generation++;
2130 return;
2131 }
2133}
unsigned int latest_generation
FIXME: document!
unsigned int current_generation
Current generation, that is, number of previously executed operations and lazy copies on the underlyi...

References Set::content, Set::current_generation, GNUNET_assert, and SetContent::latest_generation.

Referenced by handle_client_accept(), and handle_client_evaluate().

Here is the caller graph for this function:

◆ check_client_evaluate()

static int check_client_evaluate ( void *  cls,
const struct GNUNET_SETI_EvaluateMessage msg 
)
static

Called when a client wants to initiate a set operation with another peer.

Initiates the CADET connection to the listener and sends the request.

Parameters
clsclient that sent the message
msgmessage sent by the client
Returns
GNUNET_OK if the message is well-formed

Definition at line 2146 of file gnunet-service-seti.c.

2148{
2149 /* FIXME: suboptimal, even if the context below could be NULL,
2150 there are malformed messages this does not check for... */
2151 return GNUNET_OK;
2152}

References GNUNET_OK.

◆ handle_client_evaluate()

static void handle_client_evaluate ( void *  cls,
const struct GNUNET_SETI_EvaluateMessage msg 
)
static

Called when a client wants to initiate a set operation with another peer.

Initiates the CADET connection to the listener and sends the request.

Parameters
clsclient that sent the message
msgmessage sent by the client

Definition at line 2164 of file gnunet-service-seti.c.

2166{
2167 struct ClientState *cs = cls;
2168 struct Operation *op = GNUNET_new (struct Operation);
2169 const struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
2170 GNUNET_MQ_hd_var_size (incoming_msg,
2173 op),
2174 GNUNET_MQ_hd_fixed_size (intersection_p2p_element_info,
2177 op),
2178 GNUNET_MQ_hd_var_size (intersection_p2p_bf,
2180 struct BFMessage,
2181 op),
2182 GNUNET_MQ_hd_fixed_size (intersection_p2p_done,
2185 op),
2187 };
2188 struct Set *set;
2189 const struct GNUNET_MessageHeader *context;
2190
2191 if (NULL == (set = cs->set))
2192 {
2193 GNUNET_break (0);
2194 GNUNET_free (op);
2196 return;
2197 }
2198 op->salt = GNUNET_CRYPTO_random_u32 (UINT32_MAX);
2199 op->peer = msg->target_peer;
2200 op->return_intersection = htonl (msg->return_intersection);
2201 fprintf (stderr,
2202 "Return intersection for evaluate is %d\n",
2203 op->return_intersection);
2204 op->client_request_id = ntohl (msg->request_id);
2206
2207 /* Advance generation values, so that
2208 mutations won't interfere with the running operation. */
2209 op->set = set;
2210 op->generation_created = set->current_generation;
2211 advance_generation (set);
2213 set->ops_tail,
2214 op);
2216 "Creating new CADET channel to port %s for set intersection\n",
2217 GNUNET_h2s (&msg->app_id));
2219 op,
2220 &msg->target_peer,
2221 &msg->app_id,
2224 cadet_handlers);
2225 op->mq = GNUNET_CADET_get_mq (op->channel);
2226 {
2227 struct GNUNET_MQ_Envelope *ev;
2228 struct OperationRequestMessage *msg_tmp;
2229
2230 ev = GNUNET_MQ_msg_nested_mh (msg_tmp,
2232 context);
2233 if (NULL == ev)
2234 {
2235 /* the context message is too large!? */
2236 GNUNET_break (0);
2238 return;
2239 }
2241 "Initiating intersection operation evaluation\n");
2242 /* we started the operation, thus we have to send the operation request */
2243 op->phase = PHASE_INITIAL;
2244 op->my_element_count = op->set->current_set_element_count;
2245 op->my_elements
2246 = GNUNET_CONTAINER_multihashmap_create (op->my_element_count,
2247 GNUNET_YES);
2248
2249 msg_tmp->element_count = htonl (op->my_element_count);
2250 GNUNET_MQ_send (op->mq,
2251 ev);
2252 op->phase = PHASE_COUNT_SENT;
2253 if (NULL != context)
2255 "Sent op request with context message\n");
2256 else
2258 "Sent op request without context message\n");
2259 }
2261}
static pa_context * context
Pulseaudio context.
static void advance_generation(struct Set *set)
Advance the current generation of a set, adding exclusion ranges if necessary.
struct GNUNET_CADET_Channel * GNUNET_CADET_channel_create(struct GNUNET_CADET_Handle *h, void *channel_cls, const struct GNUNET_PeerIdentity *destination, const struct GNUNET_HashCode *port, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Create a new channel towards a remote peer.
Definition cadet_api.c:1030
uint32_t element_count
For Intersection: my element count.

References advance_generation(), cadet, channel_end_cb(), channel_window_cb(), ClientState::client, context, Set::current_generation, OperationRequestMessage::element_count, GNUNET_break, GNUNET_CADET_channel_create(), GNUNET_CADET_get_mq(), GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_SETI_P2P_BF, GNUNET_MESSAGE_TYPE_SETI_P2P_DONE, GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO, GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST, GNUNET_MQ_extract_nested_mh, GNUNET_MQ_handler_end, GNUNET_MQ_hd_fixed_size, GNUNET_MQ_hd_var_size, GNUNET_MQ_msg_nested_mh, GNUNET_MQ_send(), GNUNET_new, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_YES, msg, op, Set::ops_head, Set::ops_tail, PHASE_COUNT_SENT, PHASE_INITIAL, and ClientState::set.

Here is the call graph for this function:

◆ handle_client_cancel()

static void handle_client_cancel ( void *  cls,
const struct GNUNET_SETI_CancelMessage msg 
)
static

Handle a request from the client to cancel a running set operation.

Parameters
clsthe client
msgthe message

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

2273{
2274 struct ClientState *cs = cls;
2275 struct Set *set;
2276 struct Operation *op;
2277 int found;
2278
2279 if (NULL == (set = cs->set))
2280 {
2281 /* client without a set requested an operation */
2282 GNUNET_break (0);
2284 return;
2285 }
2286 found = GNUNET_NO;
2287 for (op = set->ops_head; NULL != op; op = op->next)
2288 {
2289 if (op->client_request_id == ntohl (msg->request_id))
2290 {
2291 found = GNUNET_YES;
2292 break;
2293 }
2294 }
2295 if (GNUNET_NO == found)
2296 {
2297 /* It may happen that the operation was already destroyed due to
2298 * the other peer disconnecting. The client may not know about this
2299 * yet and try to cancel the (just barely non-existent) operation.
2300 * So this is not a hard error.
2301 *///
2303 "Client canceled non-existent op %u\n",
2304 (uint32_t) ntohl (msg->request_id));
2305 }
2306 else
2307 {
2309 "Client requested cancel for op %u\n",
2310 (uint32_t) ntohl (msg->request_id));
2312 }
2314}
struct Set * set
Set associated with the operation, NULL until the spec has been associated with a set.

References _GSS_operation_destroy(), ClientState::client, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_YES, msg, GNUNET_ARM_Operation::next, op, Set::ops_head, ClientState::set, and Operation::set.

Here is the call graph for this function:

◆ handle_client_accept()

static void handle_client_accept ( void *  cls,
const struct GNUNET_SETI_AcceptMessage msg 
)
static

Handle a request from the client to accept a set operation that came from a remote peer.

We forward the accept to the associated operation for handling

Parameters
clsthe client
msgthe message

Definition at line 2326 of file gnunet-service-seti.c.

2328{
2329 struct ClientState *cs = cls;
2330 struct Set *set;
2331 struct Operation *op;
2332 struct GNUNET_SETI_ResultMessage *result_message;
2333 struct GNUNET_MQ_Envelope *ev;
2334 struct Listener *listener;
2335
2336 if (NULL == (set = cs->set))
2337 {
2338 /* client without a set requested to accept */
2339 GNUNET_break (0);
2341 return;
2342 }
2343 op = get_incoming (ntohl (msg->accept_reject_id));
2344 if (NULL == op)
2345 {
2346 /* It is not an error if the set op does not exist -- it may
2347 * have been destroyed when the partner peer disconnected. */
2348 GNUNET_log (
2350 "Client %p accepted request %u of listener %p that is no longer active\n",
2351 cs,
2352 ntohl (msg->accept_reject_id),
2353 cs->listener);
2354 ev = GNUNET_MQ_msg (result_message,
2356 result_message->request_id = msg->request_id;
2357 result_message->result_status = htons (GNUNET_SETI_STATUS_FAILURE);
2358 GNUNET_MQ_send (set->cs->mq, ev);
2360 return;
2361 }
2363 "Client accepting request %u\n",
2364 (uint32_t) ntohl (msg->accept_reject_id));
2365 listener = op->listener;
2366 op->listener = NULL;
2367 op->return_intersection = htonl (msg->return_intersection);
2368 fprintf (stderr,
2369 "Return intersection for accept is %d\n",
2370 op->return_intersection);
2372 listener->op_tail,
2373 op);
2374 op->set = set;
2376 set->ops_tail,
2377 op);
2378 op->client_request_id = ntohl (msg->request_id);
2379
2380 /* Advance generation values, so that future mutations do not
2381 interfere with the running operation. */
2382 op->generation_created = set->current_generation;
2383 advance_generation (set);
2384 {
2386 "Accepting set intersection operation\n");
2387 op->phase = PHASE_INITIAL;
2388 op->my_element_count
2389 = op->set->current_set_element_count;
2390 op->my_elements
2392 GNUNET_MIN (op->my_element_count,
2393 op->remote_element_count),
2394 GNUNET_YES);
2395 if (op->remote_element_count < op->my_element_count)
2396 {
2397 /* If the other peer (Alice) has fewer elements than us (Bob),
2398 we just send the count as Alice should send the first BF */
2400 op->phase = PHASE_COUNT_SENT;
2401 }
2402 else
2403 {
2404 /* We have fewer elements, so we start with the BF */
2406 }
2407 }
2408 /* Now allow CADET to continue, as we did not do this in
2409 #handle_incoming_msg (as we wanted to first see if the
2410 local client would accept the request). */
2411 GNUNET_CADET_receive_done (op->channel);
2413}
static void send_element_count(struct Operation *op)
Send our element count to the peer, in case our element count is lower than theirs.
#define GNUNET_MIN(a, b)

References advance_generation(), begin_bf_exchange(), ClientState::client, Listener::cs, Set::cs, Set::current_generation, get_incoming(), GNUNET_break, GNUNET_CADET_receive_done(), GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_MESSAGE_TYPE_SETI_RESULT, GNUNET_MIN, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_SETI_STATUS_FAILURE, GNUNET_YES, ClientState::listener, ClientState::mq, msg, op, Listener::op_head, Listener::op_tail, Set::ops_head, Set::ops_tail, PHASE_COUNT_SENT, PHASE_INITIAL, GNUNET_SETI_ResultMessage::request_id, GNUNET_SETI_ResultMessage::result_status, send_element_count(), and ClientState::set.

Here is the call graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Called to clean up, after a shutdown has been requested.

Parameters
clsclosure, NULL

Definition at line 2422 of file gnunet-service-seti.c.

2423{
2424 /* Delay actual shutdown to allow service to disconnect clients */
2426 if (0 == num_clients)
2427 {
2428 if (NULL != cadet)
2429 {
2431 cadet = NULL;
2432 }
2433 }
2435 GNUNET_YES);
2437 "handled shutdown request\n");
2438}
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).

References _GSS_statistics, cadet, GNUNET_CADET_disconnect(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_STATISTICS_destroy(), GNUNET_YES, in_shutdown, and num_clients.

Here is the call graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle cfg,
struct GNUNET_SERVICE_Handle service 
)
static

Function called by the service's run method to run service-specific setup code.

Parameters
clsclosure
cfgconfiguration to use
servicethe initialized service

Definition at line 2450 of file gnunet-service-seti.c.

2453{
2454 /* FIXME: need to modify SERVICE (!) API to allow
2455 us to run a shutdown task *after* clients were
2456 forcefully disconnected! */
2458 NULL);
2460 cfg);
2462 if (NULL == cadet)
2463 {
2465 _ ("Could not connect to CADET service\n"));
2467 return;
2468 }
2469}
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition gnunet-arm.c:108
struct GNUNET_SCHEDULER_Task * shutdown_task
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition cadet_api.c:897
@ GNUNET_ERROR_TYPE_ERROR
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
#define _(String)
GNU gettext support macro.
Definition platform.h:179

References _, _GSS_statistics, cadet, cfg, GNUNET_CADET_connect(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_create(), and shutdown_task.

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

Define "main" method using service macro.

Variable Documentation

◆ cadet

struct GNUNET_CADET_Handle* cadet
static

Handle to the cadet service, used to listen for and connect to remote peers.

Definition at line 472 of file gnunet-service-seti.c.

Referenced by client_disconnect_cb(), handle_client_evaluate(), handle_client_listen(), run(), and shutdown_task().

◆ _GSS_statistics

◆ listener_head

struct Listener* listener_head
static

Listeners are held in a doubly linked list.

Definition at line 482 of file gnunet-service-seti.c.

Referenced by client_disconnect_cb(), get_incoming(), and handle_client_listen().

◆ listener_tail

struct Listener* listener_tail
static

Listeners are held in a doubly linked list.

Definition at line 487 of file gnunet-service-seti.c.

Referenced by client_disconnect_cb(), and handle_client_listen().

◆ num_clients

unsigned int num_clients
static

Number of active clients.

Definition at line 492 of file gnunet-service-seti.c.

Referenced by client_connect_cb(), client_disconnect_cb(), and shutdown_task().

◆ in_shutdown

int in_shutdown
static

Are we in shutdown? if GNUNET_YES and the number of clients drops to zero, disconnect from CADET.

Definition at line 498 of file gnunet-service-seti.c.

Referenced by client_disconnect_cb(), and shutdown_task().

◆ suggest_id

uint32_t suggest_id
static

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.

0 must not be used (reserved for uninitialized).

Definition at line 506 of file gnunet-service-seti.c.

Referenced by handle_incoming_msg().