/*
This file is part of GNUnet.
Copyright (C) 2012-2014 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3, or (at your
option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/**
* @file set/set_api.c
* @brief api for the set service
* @author Florian Dold
* @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_client_lib.h"
#include "gnunet_set_service.h"
#include "set.h"
#define LOG(kind,...) GNUNET_log_from (kind, "set-api",__VA_ARGS__)
struct SetCopyRequest
{
struct SetCopyRequest *next;
struct SetCopyRequest *prev;
void *cls;
GNUNET_SET_CopyReadyCallback cb;
};
/**
* Opaque handle to a set.
*/
struct GNUNET_SET_Handle
{
/**
* Client connected to the set service.
*/
struct GNUNET_CLIENT_Connection *client;
/**
* Message queue for @e client.
*/
struct GNUNET_MQ_Handle *mq;
/**
* Linked list of operations on the set.
*/
struct GNUNET_SET_OperationHandle *ops_head;
/**
* Linked list of operations on the set.
*/
struct GNUNET_SET_OperationHandle *ops_tail;
/**
* Callback for the current iteration over the set,
* NULL if no iterator is active.
*/
GNUNET_SET_ElementIterator iterator;
/**
* Closure for @e iterator
*/
void *iterator_cls;
/**
* Should the set be destroyed once all operations are gone?
*/
int destroy_requested;
/**
* Has the set become invalid (e.g. service died)?
*/
int invalid;
/**
* Both client and service count the number of iterators
* created so far to match replies with iterators.
*/
uint16_t iteration_id;
/**
* Configuration, needed when creating (lazy) copies.
*/
const struct GNUNET_CONFIGURATION_Handle *cfg;
/**
* Doubly linked list of copy requests.
*/
struct SetCopyRequest *copy_req_head;
/**
* Doubly linked list of copy requests.
*/
struct SetCopyRequest *copy_req_tail;
};
/**
* Handle for a set operation request from another peer.
*/
struct GNUNET_SET_Request
{
/**
* Id of the request, used to identify the request when
* accepting/rejecting it.
*/
uint32_t accept_id;
/**
* Has the request been accepted already?
* #GNUNET_YES/#GNUNET_NO
*/
int accepted;
};
/**
* Handle to an operation. Only known to the service after committing
* the handle with a set.
*/
struct GNUNET_SET_OperationHandle
{
/**
* Function to be called when we have a result,
* or an error.
*/
GNUNET_SET_ResultIterator result_cb;
/**
* Closure for @e result_cb.
*/
void *result_cls;
/**
* Local set used for the operation,
* NULL if no set has been provided by conclude yet.
*/
struct GNUNET_SET_Handle *set;
/**
* Message sent to the server on calling conclude,
* NULL if conclude has been called.
*/
struct GNUNET_MQ_Envelope *conclude_mqm;
/**
* Address of the request if in the conclude message,
* used to patch the request id into the message when the set is known.
*/
uint32_t *request_id_addr;
/**
* Handles are kept in a linked list.
*/
struct GNUNET_SET_OperationHandle *prev;
/**
* Handles are kept in a linked list.
*/
struct GNUNET_SET_OperationHandle *next;
/**
* Request ID to identify the operation within the set.
*/
uint32_t request_id;
};
/**
* Opaque handle to a listen operation.
*/
struct GNUNET_SET_ListenHandle
{
/**
* Connection to the service.
*/
struct GNUNET_CLIENT_Connection *client;
/**
* Message queue for the client.
*/
struct GNUNET_MQ_Handle* mq;
/**
* Configuration handle for the listener, stored
* here to be able to reconnect transparently on
* connection failure.
*/
const struct GNUNET_CONFIGURATION_Handle *cfg;
/**
* Function to call on a new incoming request,
* or on error.
*/
GNUNET_SET_ListenCallback listen_cb;
/**
* Closure for @e listen_cb.
*/
void *listen_cls;
/**
* Application ID we listen for.
*/
struct GNUNET_HashCode app_id;
/**
* Time to wait until we try to reconnect on failure.
*/
struct GNUNET_TIME_Relative reconnect_backoff;
/**
* Task for reconnecting when the listener fails.
*/
struct GNUNET_SCHEDULER_Task * reconnect_task;
/**
* Operation we listen for.
*/
enum GNUNET_SET_OperationType operation;
};
/* mutual recursion with handle_copy_lazy */
static struct GNUNET_SET_Handle *
create_internal (const struct GNUNET_CONFIGURATION_Handle *cfg,
enum GNUNET_SET_OperationType op,
uint32_t *cookie);
/**
* Handle element for iteration over the set. Notifies the
* iterator and sends an acknowledgement to the service.
*
* @param cls the `struct GNUNET_SET_Handle *`
* @param mh the message
*/
static void
handle_copy_lazy (void *cls,
const struct GNUNET_MessageHeader *mh<