gnunet-service-fs.c gnunet-service-fs.h \
gnunet-service-fs_cp.c gnunet-service-fs_cp.h \
gnunet-service-fs_indexing.c gnunet-service-fs_indexing.h \
- gnunet-service-fs_lc.c gnunet-service-fs_lc.h \
gnunet-service-fs_pe.c gnunet-service-fs_pe.h \
gnunet-service-fs_pr.c gnunet-service-fs_pr.h \
gnunet-service-fs_push.c gnunet-service-fs_push.h \
#define INSANE_STATISTICS GNUNET_NO
+
+/**
+ * Doubly-linked list of requests we are performing
+ * on behalf of the same client.
+ */
+struct ClientRequest
+{
+
+ /**
+ * This is a doubly-linked list.
+ */
+ struct ClientRequest *next;
+
+ /**
+ * This is a doubly-linked list.
+ */
+ struct ClientRequest *prev;
+
+ /**
+ * Request this entry represents.
+ */
+ struct GSF_PendingRequest *pr;
+
+ /**
+ * Client list this request belongs to.
+ */
+ struct GSF_LocalClient *lc;
+
+ /**
+ * Task scheduled to destroy the request.
+ */
+ struct GNUNET_SCHEDULER_Task * kill_task;
+
+};
+
+
+/**
+ * Replies to be transmitted to the client. The actual
+ * response message is allocated after this struct.
+ */
+struct ClientResponse
+{
+ /**
+ * This is a doubly-linked list.
+ */
+ struct ClientResponse *next;
+
+ /**
+ * This is a doubly-linked list.
+ */
+ struct ClientResponse *prev;
+
+ /**
+ * Client list entry this response belongs to.
+ */
+ struct GSF_LocalClient *lc;
+
+ /**
+ * Number of bytes in the response.
+ */
+ size_t msize;
+};
+
+
+/**
+ * Information we track while handling an index
+ * start request from a client.
+ */
+struct IndexStartContext
+{
+
+ /**
+ * This is a doubly linked list.
+ */
+ struct IndexStartContext *next;
+
+ /**
+ * This is a doubly linked list.
+ */
+ struct IndexStartContext *prev;
+
+ /**
+ * Name of the indexed file.
+ */
+ char *filename;
+
+ /**
+ * Context for transmitting confirmation to client.
+ */
+ struct GSF_LocalClient *lc;
+
+ /**
+ * Context for hashing of the file.
+ */
+ struct GNUNET_CRYPTO_FileHashContext *fhc;
+
+ /**
+ * Hash of the contents of the file.
+ */
+ struct GNUNET_HashCode file_id;
+
+};
+
+
+/**
+ * A local client.
+ */
+struct GSF_LocalClient
+{
+
+ /**
+ * ID of the client.
+ */
+ struct GNUNET_SERVICE_Client *client;
+
+ /**
+ * Queue for sending replies.
+ */
+ struct GNUNET_MQ_Handle *mq;
+
+ /**
+ * Head of list of requests performed on behalf
+ * of this client right now.
+ */
+ struct ClientRequest *cr_head;
+
+ /**
+ * Tail of list of requests performed on behalf
+ * of this client right now.
+ */
+ struct ClientRequest *cr_tail;
+
+ /**
+ * This is a doubly linked list.
+ */
+ struct IndexStartContext *isc_head;
+
+ /**
+ * This is a doubly linked list.
+ */
+ struct IndexStartContext *isc_tail;
+
+ /**
+ * Head of linked list of responses.
+ */
+ struct ClientResponse *res_head;
+
+ /**
+ * Tail of linked list of responses.
+ */
+ struct ClientResponse *res_tail;
+
+};
+
+
/* ****************************** globals ****************************** */
/**
*/
int GSF_enable_randomized_delays;
+/**
+ * Identity of this peer.
+ */
+struct GNUNET_PeerIdentity GSF_my_id;
+
/* ***************************** locals ******************************* */
/**
*/
static struct GNUNET_LOAD_Value *datastore_get_load;
+
/**
- * Identity of this peer.
+ * Creates a fresh local client handle.
+ *
+ * @param cls NULL
+ * @param client handle of the client
+ * @param mq message queue for @a client
+ * @return handle to local client entry
*/
-struct GNUNET_PeerIdentity GSF_my_id;
+static void *
+client_connect_cb (void *cls,
+ struct GNUNET_SERVICE_Client *client,
+ struct GNUNET_MQ_Handle *mq)
+{
+ struct GSF_LocalClient *pos;
+
+ pos = GNUNET_new (struct GSF_LocalClient);
+ pos->client = client;
+ pos->mq = mq;
+ return pos;
+}
+
+
+/**
+ * Free the given client request.
+ *
+ * @param cls the client request to free
+ */
+static void
+client_request_destroy (void *cls)
+{
+ struct ClientRequest *cr = cls;
+ struct GSF_LocalClient *lc = cr->lc;
+
+ cr->kill_task = NULL;
+ GNUNET_CONTAINER_DLL_remove (lc->cr_head,
+ lc->cr_tail,
+ cr);
+ GSF_pending_request_cancel_ (cr->pr,
+ GNUNET_YES);
+ GNUNET_STATISTICS_update (GSF_stats,
+ gettext_noop ("# client searches active"),
+ -1,
+ GNUNET_NO);
+ GNUNET_free (cr);
+}
+
+
+/**
+ * Handle a reply to a pending request. Also called if a request
+ * expires (then with data == NULL). The handler may be called
+ * many times (depending on the request type), but will not be
+ * called during or after a call to #GSF_pending_request_cancel()
+ * and will also not be called anymore after a call signalling
+ * expiration.
+ *
+ * @param cls user-specified closure
+ * @param eval evaluation of the result
+ * @param pr handle to the original pending request
+ * @param reply_anonymity_level anonymity level for the reply, UINT32_MAX for "unknown"
+ * @param expiration when does @a data expire?
+ * @param last_transmission when was the last time we've tried to download this block? (FOREVER if unknown)
+ * @param type type of the block
+ * @param data response data, NULL on request expiration
+ * @param data_len number of bytes in @a data
+ */
+static void
+client_response_handler (void *cls,
+ enum GNUNET_BLOCK_EvaluationResult eval,
+ struct GSF_PendingRequest *pr,
+ uint32_t reply_anonymity_level,
+ struct GNUNET_TIME_Absolute expiration,
+ struct GNUNET_TIME_Absolute last_transmission,
+ enum GNUNET_BLOCK_Type type,
+ const void *data,
+ size_t data_len)
+{
+ struct ClientRequest *cr = cls;
+ struct GSF_LocalClient *lc;
+ struct GNUNET_MQ_Envelope *env;
+ struct ClientPutMessage *pm;
+ const struct GSF_PendingRequestData *prd;
+
+ if (NULL == data)
+ {
+ /* local-only request, with no result, clean up. */
+ if (NULL == cr->kill_task)
+ cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy,
+ cr);
+ return;
+ }
+ prd = GSF_pending_request_get_data_ (pr);
+ GNUNET_break (type != GNUNET_BLOCK_TYPE_ANY);
+ if ((prd->type != type) && (prd->type != GNUNET_BLOCK_TYPE_ANY))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_STATISTICS_update (GSF_stats,
+ gettext_noop
+ ("# replies received for local clients"), 1,
+ GNUNET_NO);
+ GNUNET_assert (pr == cr->pr);
+ lc = cr->lc;
+ env = GNUNET_MQ_msg_extra (pm,
+ data_len,
+ GNUNET_MESSAGE_TYPE_FS_PUT);
+ pm->type = htonl (type);
+ pm->expiration = GNUNET_TIME_absolute_hton (expiration);
+ pm->last_transmission = GNUNET_TIME_absolute_hton (last_transmission);
+ pm->num_transmissions = htonl (prd->num_transmissions);
+ pm->respect_offered = htonl (prd->respect_offered);
+ GNUNET_memcpy (&pm[1],
+ data,
+ data_len);
+ GNUNET_MQ_send (lc->mq,
+ env);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Queued reply to query `%s' for local client\n",
+ GNUNET_h2s (&prd->query));
+ if (GNUNET_BLOCK_EVALUATION_OK_LAST != eval)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Evaluation %d - keeping query alive\n",
+ (int) eval);
+ return;
+ }
+ if (NULL == cr->kill_task)
+ cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy,
+ cr);
+}
+
+
+/**
+ * A client disconnected from us. Tear down the local client
+ * record.
+ *
+ * @param cls unused
+ * @param client handle of the client
+ * @param app_ctx the `struct GSF_LocalClient`
+ */
+static void
+client_disconnect_cb (void *cls,
+ struct GNUNET_SERVICE_Client *client,
+ void *app_ctx)
+{
+ struct GSF_LocalClient *lc = app_ctx;
+ struct IndexStartContext *isc;
+ struct ClientRequest *cr;
+ struct ClientResponse *res;
+
+ while (NULL != (cr = lc->cr_head))
+ {
+ if (NULL != cr->kill_task)
+ GNUNET_SCHEDULER_cancel (cr->kill_task);
+ client_request_destroy (cr);
+ }
+ while (NULL != (res = lc->res_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (lc->res_head,
+ lc->res_tail,
+ res);
+ GNUNET_free (res);
+ }
+ while (NULL != (isc = lc->isc_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (lc->isc_head,
+ lc->isc_tail,
+ isc);
+ GNUNET_CRYPTO_hash_file_cancel (isc->fhc);
+ GNUNET_free (isc);
+ }
+ GNUNET_free (lc);
+}
+
+
+
/**
const struct PutMessage *put)
{
enum GNUNET_BLOCK_Type type;
-
+
type = ntohl (put->type);
if (GNUNET_BLOCK_TYPE_FS_ONDEMAND == type)
{
unsigned int bm;
unsigned int bits;
size_t bfsize;
-
+
msize = ntohs (gm->header.size);
bm = ntohl (gm->hash_bitmap);
bits = 0;
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
- }
- return GNUNET_OK;
+ }
+ return GNUNET_OK;
}
* result status). Also signal that we can now
* receive more request information from the client.
*
- * @param cls the client doing the request (`struct GNUNET_SERVER_Client`)
+ * @param cls the client doing the request (`struct GSF_LocalClient`)
* @param pr the pending request we were processing
* @param result final datastore lookup result
*/
struct GSF_PendingRequest *pr,
enum GNUNET_BLOCK_EvaluationResult result)
{
- struct GNUNET_SERVER_Client *client = cls;
+ struct GSF_LocalClient *lc = cls;
struct GSF_PendingRequestData *prd;
- GNUNET_SERVER_receive_done (client,
- GNUNET_OK);
+ GNUNET_SERVICE_client_continue (lc->client);
if (GNUNET_BLOCK_EVALUATION_OK_LAST == result)
return; /* we're done, 'pr' was already destroyed... */
prd = GSF_pending_request_get_data_ (pr);
break;
}
}
- GSF_consider_forwarding (NULL, pr, result);
+ GSF_consider_forwarding (NULL,
+ pr,
+ result);
+}
+
+
+/**
+ * Check #GNUNET_MESSAGE_TYPE_FS_START_SEARCH-message (search request
+ * from client).
+ *
+ * @param cls identification of the client
+ * @param sm the actual message
+ * @return #GNUNET_OK if @a sm is well-formed
+ */
+static int
+check_client_start_search (void *cls,
+ const struct SearchMessage *sm)
+{
+ uint16_t msize;
+
+ msize = ntohs (sm->header.size) - sizeof (struct SearchMessage);
+ if (0 != msize % sizeof (struct GNUNET_HashCode))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
}
* Handle #GNUNET_MESSAGE_TYPE_FS_START_SEARCH-message (search request
* from client).
*
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
+ * Responsible for creating the request entry itself and setting
+ * up reply callback and cancellation on client disconnect.
+ *
+ * @param cls identification of the client
+ * @param sm the actual message
*/
static void
-handle_start_search (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
+handle_client_start_search (void *cls,
+ const struct SearchMessage *sm)
{
- struct GSF_PendingRequest *pr;
- int ret;
-
- pr = NULL;
- ret = GSF_local_client_start_search_handler_ (client,
- message,
- &pr);
- switch (ret)
- {
- case GNUNET_SYSERR:
- GNUNET_SERVER_receive_done (client,
- GNUNET_SYSERR);
- break;
- case GNUNET_NO:
- GNUNET_SERVER_receive_done (client,
- GNUNET_OK);
- break;
- case GNUNET_YES:
- GSF_pending_request_get_data_ (pr)->has_started = GNUNET_YES;
- GSF_local_lookup_ (pr,
- &start_p2p_processing,
- client);
- break;
- default:
- GNUNET_assert (0);
+ static struct GNUNET_PeerIdentity all_zeros;
+ struct GSF_LocalClient *lc = cls;
+ struct ClientRequest *cr;
+ struct GSF_PendingRequestData *prd;
+ uint16_t msize;
+ unsigned int sc;
+ enum GNUNET_BLOCK_Type type;
+ enum GSF_PendingRequestOptions options;
+
+ GNUNET_STATISTICS_update (GSF_stats,
+ gettext_noop ("# client searches received"),
+ 1,
+ GNUNET_NO);
+ msize = ntohs (sm->header.size) - sizeof (struct SearchMessage);
+ sc = msize / sizeof (struct GNUNET_HashCode);
+ type = ntohl (sm->type);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received request for `%s' of type %u from local client\n",
+ GNUNET_h2s (&sm->query),
+ (unsigned int) type);
+ cr = NULL;
+ /* detect duplicate UBLOCK requests */
+ if ((type == GNUNET_BLOCK_TYPE_FS_UBLOCK) ||
+ (type == GNUNET_BLOCK_TYPE_ANY))
+ {
+ cr = lc->cr_head;
+ while (NULL != cr)
+ {
+ prd = GSF_pending_request_get_data_ (cr->pr);
+ /* only unify with queries that hae not yet started local processing
+ (SEARCH_MESSAGE_OPTION_CONTINUED was always set) and that have a
+ matching query and type */
+ if ((GNUNET_YES != prd->has_started) &&
+ (0 != memcmp (&prd->query,
+ &sm->query,
+ sizeof (struct GNUNET_HashCode))) &&
+ (prd->type == type))
+ break;
+ cr = cr->next;
+ }
+ }
+ if (NULL != cr)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Have existing request, merging content-seen lists.\n");
+ GSF_pending_request_update_ (cr->pr,
+ (const struct GNUNET_HashCode *) &sm[1],
+ sc);
+ GNUNET_STATISTICS_update (GSF_stats,
+ gettext_noop ("# client searches updated (merged content seen list)"),
+ 1,
+ GNUNET_NO);
+ }
+ else
+ {
+ GNUNET_STATISTICS_update (GSF_stats,
+ gettext_noop ("# client searches active"),
+ 1,
+ GNUNET_NO);
+ cr = GNUNET_new (struct ClientRequest);
+ cr->lc = lc;
+ GNUNET_CONTAINER_DLL_insert (lc->cr_head,
+ lc->cr_tail,
+ cr);
+ options = GSF_PRO_LOCAL_REQUEST;
+ if (0 != (SEARCH_MESSAGE_OPTION_LOOPBACK_ONLY & ntohl (sm->options)))
+ options |= GSF_PRO_LOCAL_ONLY;
+ cr->pr = GSF_pending_request_create_ (options, type,
+ &sm->query,
+ (0 !=
+ memcmp (&sm->target,
+ &all_zeros,
+ sizeof (struct GNUNET_PeerIdentity)))
+ ? &sm->target : NULL, NULL, 0,
+ 0 /* bf */ ,
+ ntohl (sm->anonymity_level),
+ 0 /* priority */ ,
+ 0 /* ttl */ ,
+ 0 /* sender PID */ ,
+ 0 /* origin PID */ ,
+ (const struct GNUNET_HashCode *) &sm[1], sc,
+ &client_response_handler,
+ cr);
}
+ if (0 != (SEARCH_MESSAGE_OPTION_CONTINUED & ntohl (sm->options)))
+ {
+ GNUNET_SERVICE_client_continue (lc->client);
+ return;
+ }
+ GSF_pending_request_get_data_ (cr->pr)->has_started = GNUNET_YES;
+ GSF_local_lookup_ (cr->pr,
+ &start_p2p_processing,
+ lc);
}
/**
* Handle request to sign a LOC URI (from client).
*
- * @param cls closure (NULL)
- * @param client identification of the client
- * @param message the actual message
+ * @param cls identification of the client
+ * @param msg the actual message
*/
static void
-handle_loc_sign (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
+handle_client_loc_sign (void *cls,
+ const struct RequestLocSignatureMessage *msg)
{
- const struct RequestLocSignatureMessage *msg;
+ struct GSF_LocalClient *lc = cls;
struct GNUNET_FS_Uri base;
struct GNUNET_FS_Uri *loc;
- struct ResponseLocSignatureMessage resp;
- struct GSF_LocalClient *lc;
+ struct GNUNET_MQ_Envelope *env;
+ struct ResponseLocSignatureMessage *resp;
- msg = (const struct RequestLocSignatureMessage *) message;
GNUNET_break (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT ==
ntohl (msg->purpose));
base.type = GNUNET_FS_URI_CHK;
loc = GNUNET_FS_uri_loc_create (&base,
pk,
GNUNET_TIME_absolute_ntoh (msg->expiration_time));
- resp.header.size = htons (sizeof (struct ResponseLocSignatureMessage));
- resp.header.type = htons (GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGNATURE);
- resp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT);
- resp.expiration_time = GNUNET_TIME_absolute_hton (loc->data.loc.expirationTime);
- resp.signature = loc->data.loc.contentSignature;
- resp.peer = loc->data.loc.peer;
+ env = GNUNET_MQ_msg (resp,
+ GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGNATURE);
+ resp->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT);
+ resp->expiration_time = GNUNET_TIME_absolute_hton (loc->data.loc.expirationTime);
+ resp->signature = loc->data.loc.contentSignature;
+ resp->peer = loc->data.loc.peer;
GNUNET_FS_uri_destroy (loc);
- lc = GSF_local_client_lookup_ (client);
- GSF_local_client_transmit_ (lc,
- &resp.header);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ GNUNET_MQ_send (lc->mq,
+ env);
+ GNUNET_SERVICE_client_continue (lc->client);
+}
+
+
+/**
+ * Check INDEX_START-message.
+ *
+ * @param cls identification of the client
+ * @param ism the actual message
+ * @return #GNUNET_OK if @a ism is well-formed
+ */
+static int
+check_client_index_start (void *cls,
+ const struct IndexStartMessage *ism)
+{
+ uint16_t msize;
+ char *fn;
+
+ msize = ntohs (ism->header.size);
+ if (((const char *) ism)[msize - 1] != '\0')
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (0 != ism->reserved)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]);
+ if (NULL == fn)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (fn);
+ return GNUNET_OK;
+}
+
+
+/**
+ * We've validated the hash of the file we're about to index. Signal
+ * success to the client and update our internal data structures.
+ *
+ * @param isc the data about the index info entry for the request
+ */
+static void
+signal_index_ok (struct IndexStartContext *isc)
+{
+ struct GSF_LocalClient *lc = isc->lc;
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_MessageHeader *msg;
+
+ GNUNET_FS_add_to_index (isc->filename,
+ &isc->file_id);
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
+ GNUNET_MQ_send (lc->mq,
+ env);
+ GNUNET_free (isc->filename);
+ GNUNET_free (isc);
+ GNUNET_SERVICE_client_continue (lc->client);
+}
+
+
+/**
+ * Function called once the hash computation over an
+ * indexed file has completed.
+ *
+ * @param cls closure, our publishing context
+ * @param res resulting hash, NULL on error
+ */
+static void
+hash_for_index_val (void *cls,
+ const struct GNUNET_HashCode *res)
+{
+ struct IndexStartContext *isc = cls;
+ struct GSF_LocalClient *lc = isc->lc;
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_MessageHeader *msg;
+
+ GNUNET_CONTAINER_DLL_remove (lc->isc_head,
+ lc->isc_tail,
+ isc);
+ isc->fhc = NULL;
+ if ( (NULL == res) ||
+ (0 != memcmp (res,
+ &isc->file_id,
+ sizeof (struct GNUNET_HashCode))))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Hash mismatch trying to index file `%s' which does not have hash `%s'\n"),
+ isc->filename,
+ GNUNET_h2s (&isc->file_id));
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED);
+ GNUNET_MQ_send (lc->mq,
+ env);
+ GNUNET_SERVICE_client_continue (lc->client);
+ GNUNET_free (isc);
+ return;
+ }
+ signal_index_ok (isc);
+}
+
+
+/**
+ * Handle INDEX_START-message.
+ *
+ * @param cls identification of the client
+ * @param message the actual message
+ */
+static void
+handle_client_index_start (void *cls,
+ const struct IndexStartMessage *ism)
+{
+ struct GSF_LocalClient *lc = cls;
+ struct IndexStartContext *isc;
+ char *fn;
+ uint64_t dev;
+ uint64_t ino;
+ uint64_t mydev;
+ uint64_t myino;
+
+ fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]);
+ GNUNET_assert (NULL != fn);
+ dev = GNUNET_ntohll (ism->device);
+ ino = GNUNET_ntohll (ism->inode);
+ isc = GNUNET_new (struct IndexStartContext);
+ isc->filename = fn;
+ isc->file_id = ism->file_id;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received START_INDEX message for file `%s'\n",
+ isc->filename);
+ isc->lc = lc;
+ mydev = 0;
+ myino = 0;
+ if ( ( (dev != 0) ||
+ (ino != 0) ) &&
+ (GNUNET_OK == GNUNET_DISK_file_get_identifiers (fn,
+ &mydev,
+ &myino)) &&
+ (dev == mydev) &&
+ (ino == myino) )
+ {
+ /* fast validation OK! */
+ signal_index_ok (isc);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Mismatch in file identifiers (%llu != %llu or %u != %u), need to hash.\n",
+ (unsigned long long) ino,
+ (unsigned long long) myino,
+ (unsigned int) dev,
+ (unsigned int) mydev);
+ /* slow validation, need to hash full file (again) */
+ GNUNET_CONTAINER_DLL_insert (lc->isc_head,
+ lc->isc_tail,
+ isc);
+ isc->fhc = GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE,
+ isc->filename,
+ HASHING_BLOCKSIZE,
+ &hash_for_index_val,
+ isc);
+ if (NULL == isc->fhc)
+ hash_for_index_val (isc,
+ NULL);
+}
+
+
+/**
+ * Handle INDEX_LIST_GET-message.
+ *
+ * @param cls closure
+ * @param message the actual message
+ */
+static void
+handle_client_index_list_get (void *cls,
+ const struct GNUNET_MessageHeader *message)
+{
+ struct GSF_LocalClient *lc = cls;
+
+ GNUNET_FS_indexing_send_list (lc->mq);
+ GNUNET_SERVICE_client_continue (lc->client);
+}
+
+
+/**
+ * Handle UNINDEX-message.
+ *
+ * @param cls identification of the client
+ * @param message the actual message
+ */
+static void
+handle_client_unindex (void *cls,
+ const struct UnindexMessage *um)
+{
+ struct GSF_LocalClient *lc = cls;
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_MessageHeader *msg;
+ int found;
+
+ GNUNET_break (0 == um->reserved);
+ found = GNUNET_FS_indexing_do_unindex (&um->file_id);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client requested unindexing of file `%s': %s\n",
+ GNUNET_h2s (&um->file_id),
+ found ? "found" : "not found");
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK);
+ GNUNET_MQ_send (lc->mq,
+ env);
+ GNUNET_SERVICE_client_continue (lc->client);
}
GSF_pending_request_done_ ();
GSF_plan_done ();
GSF_connected_peer_done_ ();
- GNUNET_DATASTORE_disconnect (GSF_dsh, GNUNET_NO);
+ GNUNET_DATASTORE_disconnect (GSF_dsh,
+ GNUNET_NO);
GSF_dsh = NULL;
GNUNET_DHT_disconnect (GSF_dht);
GSF_dht = NULL;
/**
* Process fs requests.
*
- * @param server the initialized server
* @param c configuration to use
*/
static int
-main_init (struct GNUNET_SERVER_Handle *server,
- const struct GNUNET_CONFIGURATION_Handle *c)
+main_init (const struct GNUNET_CONFIGURATION_Handle *c)
{
struct GNUNET_MQ_MessageHandler no_p2p_handlers[] = {
GNUNET_MQ_handler_end ()
NULL),
GNUNET_MQ_handler_end ()
};
- static const struct GNUNET_SERVER_MessageHandler handlers[] = {
- { &GNUNET_FS_handle_index_start, NULL,
- GNUNET_MESSAGE_TYPE_FS_INDEX_START, 0 },
- { &GNUNET_FS_handle_index_list_get, NULL,
- GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET,
- sizeof (struct GNUNET_MessageHeader) },
- { &GNUNET_FS_handle_unindex, NULL,
- GNUNET_MESSAGE_TYPE_FS_UNINDEX,
- sizeof (struct UnindexMessage) },
- { &handle_start_search, NULL,
- GNUNET_MESSAGE_TYPE_FS_START_SEARCH, 0 },
- { &handle_loc_sign, NULL,
- GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGN,
- sizeof (struct RequestLocSignatureMessage) },
- {NULL, NULL, 0, 0}
- };
int anon_p2p_off;
char *keyfile;
"core");
return GNUNET_SYSERR;
}
- GNUNET_SERVER_disconnect_notify (server,
- &GSF_client_disconnect_handler_,
- NULL);
- GNUNET_SERVER_add_handlers (server, handlers);
cover_age_task =
GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY,
&age_cover_counters,
* Process fs requests.
*
* @param cls closure
- * @param server the initialized server
* @param cfg configuration to use
+ * @param service the initialized service
*/
static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
+run (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_SERVICE_Handle *service)
{
unsigned long long dqs;
GSF_cfg = cfg;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_size (GSF_cfg, "fs", "DATASTORE_QUEUE_SIZE",
+ GNUNET_CONFIGURATION_get_value_size (GSF_cfg,
+ "fs",
+ "DATASTORE_QUEUE_SIZE",
&dqs))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO,
- "fs", "DATASTORE_QUEUE_SIZE");
+ "fs",
+ "DATASTORE_QUEUE_SIZE");
dqs = 1024;
}
GSF_datastore_queue_size = (unsigned int) dqs;
GSF_plan_init ();
GSF_pending_request_init_ ();
GSF_connected_peer_init_ ();
- GSF_ats = GNUNET_ATS_performance_init (GSF_cfg, &update_latencies, NULL);
+ GSF_ats = GNUNET_ATS_performance_init (GSF_cfg,
+ &update_latencies,
+ NULL);
GSF_push_init_ ();
GSF_put_init_ ();
- if ((GNUNET_OK != GNUNET_FS_indexing_init (cfg, GSF_dsh)) ||
- (GNUNET_OK != main_init (server, cfg)))
+ if ( (GNUNET_OK != GNUNET_FS_indexing_init (cfg,
+ GSF_dsh)) ||
+ (GNUNET_OK != main_init (cfg)) )
{
GNUNET_SCHEDULER_shutdown ();
shutdown_task (NULL);
/**
- * The main function for the fs service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
+ * Define "main" method using service macro.
*/
-int
-main (int argc, char *const *argv)
-{
- return (GNUNET_OK ==
- GNUNET_SERVICE_run (argc, argv, "fs", GNUNET_SERVICE_OPTION_NONE,
- &run, NULL)) ? 0 : 1;
-}
+GNUNET_SERVICE_MAIN
+("fs",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_var_size (client_index_start,
+ GNUNET_MESSAGE_TYPE_FS_INDEX_START,
+ struct IndexStartMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (client_index_list_get,
+ GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET,
+ struct GNUNET_MessageHeader,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (client_unindex,
+ GNUNET_MESSAGE_TYPE_FS_UNINDEX,
+ struct UnindexMessage,
+ NULL),
+ GNUNET_MQ_hd_var_size (client_start_search,
+ GNUNET_MESSAGE_TYPE_FS_START_SEARCH,
+ struct SearchMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (client_loc_sign,
+ GNUNET_MESSAGE_TYPE_FS_REQUEST_LOC_SIGN,
+ struct RequestLocSignatureMessage,
+ NULL),
+ GNUNET_MQ_handler_end ());
+
/* end of gnunet-service-fs.c */
GSF_update_datastore_delay_ (struct GNUNET_TIME_Absolute start);
-
#endif
/* end of gnunet-service-fs.h */
/**
* Head of linked list of indexed files.
+ * FIXME: we don't need both a DLL and a hashmap here!
*/
static struct IndexInfo *indexed_files_head;
struct IndexInfo *pos;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg, "FS", "INDEXDB", &fn))
+ GNUNET_CONFIGURATION_get_value_filename (cfg, "FS",
+ "INDEXDB",
+ &fn))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
- "fs", "INDEXDB");
+ "fs",
+ "INDEXDB");
return;
}
wh = GNUNET_BIO_write_open (fn);
if (NULL == wh)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
- _("Could not open `%s'.\n"), fn);
+ _("Could not open `%s'.\n"),
+ fn);
GNUNET_free (fn);
return;
}
for (pos = indexed_files_head; NULL != pos; pos = pos->next)
if ((GNUNET_OK !=
- GNUNET_BIO_write (wh, &pos->file_id, sizeof (struct GNUNET_HashCode))) ||
- (GNUNET_OK != GNUNET_BIO_write_string (wh, pos->filename)))
+ GNUNET_BIO_write (wh,
+ &pos->file_id,
+ sizeof (struct GNUNET_HashCode))) ||
+ (GNUNET_OK !=
+ GNUNET_BIO_write_string (wh,
+ pos->filename)))
break;
if (GNUNET_OK != GNUNET_BIO_write_close (wh))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
- _("Error writing `%s'.\n"), fn);
+ _("Error writing `%s'.\n"),
+ fn);
GNUNET_free (fn);
return;
}
char *emsg;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg, "FS", "INDEXDB", &fn))
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "FS",
+ "INDEXDB",
+ &fn))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
- "fs", "INDEXDB");
+ "fs",
+ "INDEXDB");
return;
}
if (GNUNET_NO == GNUNET_DISK_file_test (fn))
if (NULL == rh)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
- _("Could not open `%s'.\n"), fn);
+ _("Could not open `%s'.\n"),
+ fn);
GNUNET_free (fn);
return;
}
- while ((GNUNET_OK ==
- GNUNET_BIO_read (rh, "Hash of indexed file", &hc,
- sizeof (struct GNUNET_HashCode))) &&
- (GNUNET_OK ==
- GNUNET_BIO_read_string (rh, "Name of indexed file", &fname,
- 1024 * 16)) && (fname != NULL))
+ while ( (GNUNET_OK ==
+ GNUNET_BIO_read (rh,
+ "Hash of indexed file",
+ &hc,
+ sizeof (struct GNUNET_HashCode))) &&
+ (GNUNET_OK ==
+ GNUNET_BIO_read_string (rh,
+ "Name of indexed file",
+ &fname,
+ 1024 * 16)) &&
+ (fname != NULL) )
{
slen = strlen (fname) + 1;
pos = GNUNET_malloc (sizeof (struct IndexInfo) + slen);
}
-/**
- * We've validated the hash of the file we're about to index. Signal
- * success to the client and update our internal data structures.
- *
- * @param ii the index info entry for the request
- */
-static void
-signal_index_ok (struct IndexInfo *ii)
-{
- struct IndexInfo *ir;
- if (GNUNET_SYSERR ==
- GNUNET_CONTAINER_multihashmap_put (ifm, &ii->file_id,
- ii,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
- {
- ir = GNUNET_CONTAINER_multihashmap_get (ifm,
- &ii->file_id);
- GNUNET_assert (NULL != ir);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _
- ("Index request received for file `%s' is already indexed as `%s'. Permitting anyway.\n"),
- ii->filename,
- ir->filename);
- GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0,
- GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
- GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES);
- GNUNET_free (ii);
- return;
- }
- GNUNET_CONTAINER_DLL_insert (indexed_files_head,
- indexed_files_tail,
- ii);
- write_index_list ();
- GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0,
- GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
- GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES);
- ii->tc = NULL;
-}
-
-
-/**
- * Function called once the hash computation over an
- * indexed file has completed.
- *
- * @param cls closure, our publishing context
- * @param res resulting hash, NULL on error
- */
-static void
-hash_for_index_val (void *cls, const struct GNUNET_HashCode * res)
-{
- struct IndexInfo *ii = cls;
-
- ii->fhc = NULL;
- if ((res == NULL) ||
- (0 != memcmp (res, &ii->file_id, sizeof (struct GNUNET_HashCode))))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Hash mismatch trying to index file `%s' which has hash `%s'\n"),
- ii->filename, GNUNET_h2s (res));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wanted `%s'\n",
- GNUNET_h2s (&ii->file_id));
- GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0,
- GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED);
- GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES);
- GNUNET_free (ii);
- return;
- }
- signal_index_ok (ii);
-}
-
-
-/**
- * Handle INDEX_START-message.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-void
-GNUNET_FS_handle_index_start (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- const struct IndexStartMessage *ism;
- char *fn;
- uint16_t msize;
- struct IndexInfo *ii;
- size_t slen;
- uint64_t dev;
- uint64_t ino;
- uint64_t mydev;
- uint64_t myino;
-
- msize = ntohs (message->size);
- if ((msize <= sizeof (struct IndexStartMessage)) ||
- (((const char *) message)[msize - 1] != '\0'))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- ism = (const struct IndexStartMessage *) message;
- if (0 != ism->reserved)
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]);
- if (fn == NULL)
- {
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- dev = GNUNET_ntohll (ism->device);
- ino = GNUNET_ntohll (ism->inode);
- ism = (const struct IndexStartMessage *) message;
- slen = strlen (fn) + 1;
- ii = GNUNET_malloc (sizeof (struct IndexInfo) + slen);
- ii->filename = (const char *) &ii[1];
- GNUNET_memcpy (&ii[1], fn, slen);
- ii->file_id = ism->file_id;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message for file `%s'\n",
- "START_INDEX", ii->filename);
- ii->tc = GNUNET_SERVER_transmit_context_create (client);
- mydev = 0;
- myino = 0;
- if (((dev != 0) || (ino != 0)) &&
- (GNUNET_OK == GNUNET_DISK_file_get_identifiers (fn, &mydev, &myino)) &&
- ((dev == mydev) && (ino == myino)))
- {
- /* fast validation OK! */
- signal_index_ok (ii);
- GNUNET_free (fn);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Mismatch in file identifiers (%llu != %llu or %u != %u), need to hash.\n",
- (unsigned long long) ino, (unsigned long long) myino,
- (unsigned int) dev, (unsigned int) mydev);
- /* slow validation, need to hash full file (again) */
- ii->fhc =
- GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE, fn,
- HASHING_BLOCKSIZE, &hash_for_index_val, ii);
- if (ii->fhc == NULL)
- hash_for_index_val (ii, NULL);
- GNUNET_free (fn);
-}
-
-
-/**
- * Handle INDEX_LIST_GET-message.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-void
-GNUNET_FS_handle_index_list_get (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct GNUNET_SERVER_TransmitContext *tc;
- struct IndexInfoMessage *iim;
- char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
- size_t slen;
- const char *fn;
- struct IndexInfo *pos;
-
- tc = GNUNET_SERVER_transmit_context_create (client);
- iim = (struct IndexInfoMessage *) buf;
- for (pos = indexed_files_head; NULL != pos; pos = pos->next)
- {
- fn = pos->filename;
- slen = strlen (fn) + 1;
- if (slen + sizeof (struct IndexInfoMessage) >=
- GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break (0);
- break;
- }
- iim->header.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY);
- iim->header.size = htons (slen + sizeof (struct IndexInfoMessage));
- iim->reserved = 0;
- iim->file_id = pos->file_id;
- GNUNET_memcpy (&iim[1], fn, slen);
- GNUNET_SERVER_transmit_context_append_message (tc, &iim->header);
- }
- GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
- GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END);
- GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_MINUTES);
-}
-
-
-/**
- * Handle UNINDEX-message.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-void
-GNUNET_FS_handle_unindex (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- const struct UnindexMessage *um;
- struct IndexInfo *pos;
- struct GNUNET_SERVER_TransmitContext *tc;
- int found;
-
- um = (const struct UnindexMessage *) message;
- if (0 != um->reserved)
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- found = GNUNET_NO;
- for (pos = indexed_files_head; NULL != pos; pos = pos->next)
- {
- if (0 == memcmp (&pos->file_id, &um->file_id, sizeof (struct GNUNET_HashCode)))
- {
- GNUNET_CONTAINER_DLL_remove (indexed_files_head,
- indexed_files_tail,
- pos);
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_remove (ifm, &pos->file_id,
- pos));
- GNUNET_free (pos);
- found = GNUNET_YES;
- break;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Client requested unindexing of file `%s': %s\n",
- GNUNET_h2s (&um->file_id), found ? "found" : "not found");
- if (GNUNET_YES == found)
- write_index_list ();
- tc = GNUNET_SERVER_transmit_context_create (client);
- GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
- GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK);
- GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_MINUTES);
-}
-
-
/**
* Continuation called from datastore's remove
* function.
* @return GNUNET_OK on success
*/
int
-GNUNET_FS_handle_on_demand_block (const struct GNUNET_HashCode * key, uint32_t size,
- const void *data, enum GNUNET_BLOCK_Type type,
- uint32_t priority, uint32_t anonymity,
+GNUNET_FS_handle_on_demand_block (const struct GNUNET_HashCode * key,
+ uint32_t size,
+ const void *data,
+ enum GNUNET_BLOCK_Type type,
+ uint32_t priority,
+ uint32_t anonymity,
struct GNUNET_TIME_Absolute expiration,
uint64_t uid,
GNUNET_DATASTORE_DatumProcessor cont,
if (size != sizeof (struct OnDemandBlock))
{
GNUNET_break (0);
- GNUNET_DATASTORE_remove (dsh, key, size, data, -1, -1,
+ GNUNET_DATASTORE_remove (dsh,
+ key,
+ size,
+ data,
+ -1,
+ -1,
&remove_cont, NULL);
return GNUNET_SYSERR;
}
odb = (const struct OnDemandBlock *) data;
off = GNUNET_ntohll (odb->offset);
- ii = GNUNET_CONTAINER_multihashmap_get (ifm, &odb->file_id);
+ ii = GNUNET_CONTAINER_multihashmap_get (ifm,
+ &odb->file_id);
if (NULL == ii)
{
GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to find index %s\n",
+ GNUNET_h2s (&odb->file_id));
return GNUNET_SYSERR;
}
fn = ii->filename;
if ((NULL == fn) || (0 != ACCESS (fn, R_OK)))
{
GNUNET_STATISTICS_update (GSF_stats,
- gettext_noop
- ("# index blocks removed: original file inaccessible"),
- 1, GNUNET_YES);
- GNUNET_DATASTORE_remove (dsh, key, size, data, -1, -1,
- &remove_cont, NULL);
+ gettext_noop ("# index blocks removed: original file inaccessible"),
+ 1,
+ GNUNET_YES);
+ GNUNET_DATASTORE_remove (dsh,
+ key,
+ size,
+ data,
+ -1,
+ -1,
+ &remove_cont,
+ NULL);
return GNUNET_SYSERR;
}
- if ((NULL ==
- (fh =
- GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ,
- GNUNET_DISK_PERM_NONE))) ||
- (off != GNUNET_DISK_file_seek (fh, off, GNUNET_DISK_SEEK_SET)) ||
- (-1 == (nsize = GNUNET_DISK_file_read (fh, ndata, sizeof (ndata)))))
+ if ( (NULL ==
+ (fh =
+ GNUNET_DISK_file_open (fn,
+ GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_NONE))) ||
+ (off != GNUNET_DISK_file_seek (fh,
+ off,
+ GNUNET_DISK_SEEK_SET)) ||
+ (-1 == (nsize = GNUNET_DISK_file_read (fh,
+ ndata,
+ sizeof (ndata)))) )
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Could not access indexed file `%s' (%s) at offset %llu: %s\n"),
- GNUNET_h2s (&odb->file_id), fn, (unsigned long long) off,
+ _("Could not access indexed file `%s' (%s) at offset %llu: %s\n"),
+ GNUNET_h2s (&odb->file_id),
+ fn,
+ (unsigned long long) off,
(fn == NULL) ? _("not indexed") : STRERROR (errno));
if (fh != NULL)
GNUNET_DISK_file_close (fh);
- GNUNET_DATASTORE_remove (dsh, key, size, data, -1, -1,
- &remove_cont, NULL);
+ GNUNET_DATASTORE_remove (dsh,
+ key,
+ size,
+ data,
+ -1,
+ -1,
+ &remove_cont,
+ NULL);
return GNUNET_SYSERR;
}
GNUNET_DISK_file_close (fh);
- GNUNET_CRYPTO_hash (ndata, nsize, &nkey);
- GNUNET_CRYPTO_hash_to_aes_key (&nkey, &skey, &iv);
- GNUNET_CRYPTO_symmetric_encrypt (ndata, nsize, &skey, &iv, edata);
- GNUNET_CRYPTO_hash (edata, nsize, &query);
- if (0 != memcmp (&query, key, sizeof (struct GNUNET_HashCode)))
+ GNUNET_CRYPTO_hash (ndata,
+ nsize,
+ &nkey);
+ GNUNET_CRYPTO_hash_to_aes_key (&nkey,
+ &skey,
+ &iv);
+ GNUNET_CRYPTO_symmetric_encrypt (ndata,
+ nsize,
+ &skey,
+ &iv,
+ edata);
+ GNUNET_CRYPTO_hash (edata,
+ nsize,
+ &query);
+ if (0 != memcmp (&query,
+ key,
+ sizeof (struct GNUNET_HashCode)))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Indexed file `%s' changed at offset %llu\n"), fn,
+ _("Indexed file `%s' changed at offset %llu\n"),
+ fn,
(unsigned long long) off);
- GNUNET_DATASTORE_remove (dsh, key, size, data, -1, -1,
- &remove_cont, NULL);
+ GNUNET_DATASTORE_remove (dsh,
+ key,
+ size,
+ data,
+ -1,
+ -1,
+ &remove_cont,
+ NULL);
return GNUNET_SYSERR;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "On-demand encoded block for query `%s'\n", GNUNET_h2s (key));
- cont (cont_cls, key, nsize, edata, GNUNET_BLOCK_TYPE_FS_DBLOCK, priority,
- anonymity, expiration, uid);
+ "On-demand encoded block for query `%s'\n",
+ GNUNET_h2s (key));
+ cont (cont_cls,
+ key,
+ nsize,
+ edata,
+ GNUNET_BLOCK_TYPE_FS_DBLOCK,
+ priority,
+ anonymity,
+ expiration,
+ uid);
return GNUNET_OK;
}
+/**
+ * Transmit information about indexed files to @a mq.
+ *
+ * @param mq message queue to send information to
+ */
+void
+GNUNET_FS_indexing_send_list (struct GNUNET_MQ_Handle *mq)
+{
+ struct GNUNET_MQ_Envelope *env;
+ struct IndexInfoMessage *iim;
+ struct GNUNET_MessageHeader *iem;
+ size_t slen;
+ const char *fn;
+ struct IndexInfo *pos;
+
+ for (pos = indexed_files_head; NULL != pos; pos = pos->next)
+ {
+ fn = pos->filename;
+ slen = strlen (fn) + 1;
+ if (slen + sizeof (struct IndexInfoMessage) >=
+ GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ {
+ GNUNET_break (0);
+ break;
+ }
+ env = GNUNET_MQ_msg_extra (iim,
+ slen,
+ GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY);
+ iim->reserved = 0;
+ iim->file_id = pos->file_id;
+ GNUNET_memcpy (&iim[1],
+ fn,
+ slen);
+ GNUNET_MQ_send (mq,
+ env);
+ }
+ env = GNUNET_MQ_msg (iem,
+ GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END);
+ GNUNET_MQ_send (mq,
+ env);
+}
+
+
+/**
+ * Remove a file from the index.
+ *
+ * @param fid identifier of the file to remove
+ * @return #GNUNET_YES if the @a fid was found
+ */
+int
+GNUNET_FS_indexing_do_unindex (const struct GNUNET_HashCode *fid)
+{
+ struct IndexInfo *pos;
+
+ for (pos = indexed_files_head; NULL != pos; pos = pos->next)
+ {
+ if (0 == memcmp (&pos->file_id,
+ fid,
+ sizeof (struct GNUNET_HashCode)))
+ {
+ GNUNET_CONTAINER_DLL_remove (indexed_files_head,
+ indexed_files_tail,
+ pos);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_remove (ifm,
+ &pos->file_id,
+ pos));
+ GNUNET_free (pos);
+ write_index_list ();
+ return GNUNET_YES;
+ }
+ }
+ return GNUNET_NO;
+}
+
+
+/**
+ * Add the given file to the list of indexed files.
+ *
+ * @param filename name of the file
+ * @param file_id hash identifier for @a filename
+ */
+void
+GNUNET_FS_add_to_index (const char *filename,
+ const struct GNUNET_HashCode *file_id)
+{
+ struct IndexInfo *ii;
+ size_t slen;
+
+ ii = GNUNET_CONTAINER_multihashmap_get (ifm,
+ file_id);
+ if (NULL != ii)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Index request received for file `%s' is already indexed as `%s'. Permitting anyway.\n"),
+ filename,
+ ii->filename);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding file %s to index as %s\n",
+ filename,
+ GNUNET_h2s (file_id));
+ slen = strlen (filename) + 1;
+ ii = GNUNET_malloc (sizeof (struct IndexInfo) + slen);
+ ii->file_id = *file_id;
+ ii->filename = (const char *) &ii[1];
+ memcpy (&ii[1],
+ filename,
+ slen);
+ GNUNET_CONTAINER_DLL_insert (indexed_files_head,
+ indexed_files_tail,
+ ii);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (ifm,
+ &ii->file_id,
+ ii,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ write_index_list ();
+}
+
+
/**
* Shutdown the module.
*/
GNUNET_CRYPTO_hash_file_cancel (pos->fhc);
GNUNET_break (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_remove (ifm,
- &pos->file_id, pos));
+ &pos->file_id,
+ pos));
GNUNET_free (pos);
}
GNUNET_CONTAINER_multihashmap_destroy (ifm);
{
cfg = c;
dsh = d;
- ifm = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_YES);
+ ifm = GNUNET_CONTAINER_multihashmap_create (128,
+ GNUNET_YES);
read_index_list ();
return GNUNET_OK;
}
* @param uid unique identifier for the datum;
* maybe 0 if no unique identifier is available
* @param cont function to call with the actual block (at most once, on success)
- * @param cont_cls closure for cont
- * @return GNUNET_OK on success
+ * @param cont_cls closure for @a cont
+ * @return #GNUNET_OK on success
*/
int
GNUNET_FS_handle_on_demand_block (const struct GNUNET_HashCode * key, uint32_t size,
GNUNET_DATASTORE_DatumProcessor cont,
void *cont_cls);
+
/**
- * Handle INDEX_START-message.
+ * Transmit information about indexed files to @a mq.
*
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
+ * @param mq message queue to send information to
*/
void
-GNUNET_FS_handle_index_start (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message);
+GNUNET_FS_indexing_send_list (struct GNUNET_MQ_Handle *mq);
/**
- * Handle INDEX_LIST_GET-message.
+ * Remove a file from the index.
*
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
+ * @param fid identifier of the file to remove
+ * @return #GNUNET_YES if the @a fid was found
*/
-void
-GNUNET_FS_handle_index_list_get (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message);
+int
+GNUNET_FS_indexing_do_unindex (const struct GNUNET_HashCode *fid);
/**
- * Handle UNINDEX-message.
+ * Add the given file to the list of indexed files.
*
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
+ * @param filename name of the file
+ * @param file_id hash identifier for @a filename
*/
void
-GNUNET_FS_handle_unindex (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message);
+GNUNET_FS_add_to_index (const char *filename,
+ const struct GNUNET_HashCode *file_id);
/**
#include "gnunet-service-fs_pr.h"
-/**
- * Doubly-linked list of requests we are performing
- * on behalf of the same client.
- */
-struct ClientRequest
-{
-
- /**
- * This is a doubly-linked list.
- */
- struct ClientRequest *next;
-
- /**
- * This is a doubly-linked list.
- */
- struct ClientRequest *prev;
-
- /**
- * Request this entry represents.
- */
- struct GSF_PendingRequest *pr;
-
- /**
- * Client list this request belongs to.
- */
- struct GSF_LocalClient *lc;
-
- /**
- * Task scheduled to destroy the request.
- */
- struct GNUNET_SCHEDULER_Task * kill_task;
-
-};
-
-
-/**
- * Replies to be transmitted to the client. The actual
- * response message is allocated after this struct.
- */
-struct ClientResponse
-{
- /**
- * This is a doubly-linked list.
- */
- struct ClientResponse *next;
-
- /**
- * This is a doubly-linked list.
- */
- struct ClientResponse *prev;
-
- /**
- * Client list entry this response belongs to.
- */
- struct GSF_LocalClient *lc;
-
- /**
- * Number of bytes in the response.
- */
- size_t msize;
-};
-
-
-/**
- * A local client.
- */
-struct GSF_LocalClient
-{
-
- /**
- * We keep clients in a DLL.
- */
- struct GSF_LocalClient *next;
-
- /**
- * We keep clients in a DLL.
- */
- struct GSF_LocalClient *prev;
-
- /**
- * ID of the client.
- */
- struct GNUNET_SERVER_Client *client;
-
- /**
- * Head of list of requests performed on behalf
- * of this client right now.
- */
- struct ClientRequest *cr_head;
-
- /**
- * Tail of list of requests performed on behalf
- * of this client right now.
- */
- struct ClientRequest *cr_tail;
-
- /**
- * Head of linked list of responses.
- */
- struct ClientResponse *res_head;
-
- /**
- * Tail of linked list of responses.
- */
- struct ClientResponse *res_tail;
-
- /**
- * Context for sending replies.
- */
- struct GNUNET_SERVER_TransmitHandle *th;
-
-};
-
-
-/**
- * Head of linked list of our local clients.
- */
-static struct GSF_LocalClient *client_head;
-
-/**
- * Head of linked list of our local clients.
- */
-static struct GSF_LocalClient *client_tail;
-
-
-/**
- * Look up a local client record or create one if it
- * doesn't exist yet.
- *
- * @param client handle of the client
- * @return handle to local client entry
- */
-struct GSF_LocalClient *
-GSF_local_client_lookup_ (struct GNUNET_SERVER_Client *client)
-{
- struct GSF_LocalClient *pos;
-
- pos = client_head;
- while ((NULL != pos) && (pos->client != client))
- pos = pos->next;
- if (NULL != pos)
- return pos;
- pos = GNUNET_new (struct GSF_LocalClient);
- pos->client = client;
- GNUNET_CONTAINER_DLL_insert (client_head,
- client_tail,
- pos);
- return pos;
-}
-
-
-/**
- * Free the given client request.
- *
- * @param cls the client request to free
- */
-static void
-client_request_destroy (void *cls)
-{
- struct ClientRequest *cr = cls;
- struct GSF_LocalClient *lc;
-
- cr->kill_task = NULL;
- lc = cr->lc;
- GNUNET_CONTAINER_DLL_remove (lc->cr_head,
- lc->cr_tail,
- cr);
- GSF_pending_request_cancel_ (cr->pr,
- GNUNET_YES);
- GNUNET_STATISTICS_update (GSF_stats,
- gettext_noop ("# client searches active"),
- -1,
- GNUNET_NO);
- GNUNET_free (cr);
-}
-
-
-/**
- * Handle a reply to a pending request. Also called if a request
- * expires (then with data == NULL). The handler may be called
- * many times (depending on the request type), but will not be
- * called during or after a call to #GSF_pending_request_cancel()
- * and will also not be called anymore after a call signalling
- * expiration.
- *
- * @param cls user-specified closure
- * @param eval evaluation of the result
- * @param pr handle to the original pending request
- * @param reply_anonymity_level anonymity level for the reply, UINT32_MAX for "unknown"
- * @param expiration when does @a data expire?
- * @param last_transmission when was the last time we've tried to download this block? (FOREVER if unknown)
- * @param type type of the block
- * @param data response data, NULL on request expiration
- * @param data_len number of bytes in @a data
- */
-static void
-client_response_handler (void *cls,
- enum GNUNET_BLOCK_EvaluationResult eval,
- struct GSF_PendingRequest *pr,
- uint32_t reply_anonymity_level,
- struct GNUNET_TIME_Absolute expiration,
- struct GNUNET_TIME_Absolute last_transmission,
- enum GNUNET_BLOCK_Type type,
- const void *data,
- size_t data_len)
-{
- struct ClientRequest *cr = cls;
- struct GSF_LocalClient *lc;
- struct ClientPutMessage *pm;
- const struct GSF_PendingRequestData *prd;
- size_t msize;
-
- if (NULL == data)
- {
- /* local-only request, with no result, clean up. */
- if (NULL == cr->kill_task)
- cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy,
- cr);
- return;
- }
- prd = GSF_pending_request_get_data_ (pr);
- GNUNET_break (type != GNUNET_BLOCK_TYPE_ANY);
- if ((prd->type != type) && (prd->type != GNUNET_BLOCK_TYPE_ANY))
- {
- GNUNET_break (0);
- return;
- }
- GNUNET_STATISTICS_update (GSF_stats,
- gettext_noop
- ("# replies received for local clients"), 1,
- GNUNET_NO);
- GNUNET_assert (pr == cr->pr);
- lc = cr->lc;
- msize = sizeof (struct ClientPutMessage) + data_len;
- {
- char buf[msize] GNUNET_ALIGN;
-
- pm = (struct ClientPutMessage *) buf;
- pm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_PUT);
- pm->header.size = htons (msize);
- pm->type = htonl (type);
- pm->expiration = GNUNET_TIME_absolute_hton (expiration);
- pm->last_transmission = GNUNET_TIME_absolute_hton (last_transmission);
- pm->num_transmissions = htonl (prd->num_transmissions);
- pm->respect_offered = htonl (prd->respect_offered);
- GNUNET_memcpy (&pm[1], data, data_len);
- GSF_local_client_transmit_ (lc, &pm->header);
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Queued reply to query `%s' for local client\n",
- GNUNET_h2s (&prd->query));
- if (GNUNET_BLOCK_EVALUATION_OK_LAST != eval)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Evaluation %d - keeping query alive\n",
- (int) eval);
- return;
- }
- if (NULL == cr->kill_task)
- cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy, cr);
-}
-
-
-/**
- * Handle START_SEARCH-message (search request from local client).
- * Only responsible for creating the request entry itself and setting
- * up reply callback and cancellation on client disconnect. Does NOT
- * execute the actual request strategy (planning).
- *
- * @param client identification of the client
- * @param message the actual message
- * @param prptr where to store the pending request handle for the request
- * @return #GNUNET_YES to start local processing,
- * #GNUNET_NO to not (yet) start local processing,
- * #GNUNET_SYSERR on error
- */
-int
-GSF_local_client_start_search_handler_ (struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message,
- struct GSF_PendingRequest **prptr)
-{
- static struct GNUNET_PeerIdentity all_zeros;
- const struct SearchMessage *sm;
- struct GSF_LocalClient *lc;
- struct ClientRequest *cr;
- struct GSF_PendingRequestData *prd;
- uint16_t msize;
- unsigned int sc;
- enum GNUNET_BLOCK_Type type;
- enum GSF_PendingRequestOptions options;
-
- msize = ntohs (message->size);
- if ((msize < sizeof (struct SearchMessage)) ||
- (0 != (msize - sizeof (struct SearchMessage)) % sizeof (struct GNUNET_HashCode)))
- {
- GNUNET_break (0);
- *prptr = NULL;
- return GNUNET_SYSERR;
- }
- GNUNET_STATISTICS_update (GSF_stats,
- gettext_noop ("# client searches received"),
- 1,
- GNUNET_NO);
- sc = (msize - sizeof (struct SearchMessage)) / sizeof (struct GNUNET_HashCode);
- sm = (const struct SearchMessage *) message;
- type = ntohl (sm->type);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received request for `%s' of type %u from local client\n",
- GNUNET_h2s (&sm->query), (unsigned int) type);
- lc = GSF_local_client_lookup_ (client);
- cr = NULL;
- /* detect duplicate UBLOCK requests */
- if ((type == GNUNET_BLOCK_TYPE_FS_UBLOCK) ||
- (type == GNUNET_BLOCK_TYPE_ANY))
- {
- cr = lc->cr_head;
- while (NULL != cr)
- {
- prd = GSF_pending_request_get_data_ (cr->pr);
- /* only unify with queries that hae not yet started local processing
- (SEARCH_MESSAGE_OPTION_CONTINUED was always set) and that have a
- matching query and type */
- if ((GNUNET_YES != prd->has_started) &&
- (0 != memcmp (&prd->query,
- &sm->query,
- sizeof (struct GNUNET_HashCode))) &&
- (prd->type == type))
- break;
- cr = cr->next;
- }
- }
- if (NULL != cr)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Have existing request, merging content-seen lists.\n");
- GSF_pending_request_update_ (cr->pr,
- (const struct GNUNET_HashCode *) &sm[1],
- sc);
- GNUNET_STATISTICS_update (GSF_stats,
- gettext_noop
- ("# client searches updated (merged content seen list)"),
- 1, GNUNET_NO);
- }
- else
- {
- GNUNET_STATISTICS_update (GSF_stats,
- gettext_noop ("# client searches active"), 1,
- GNUNET_NO);
- cr = GNUNET_new (struct ClientRequest);
- cr->lc = lc;
- GNUNET_CONTAINER_DLL_insert (lc->cr_head,
- lc->cr_tail,
- cr);
- options = GSF_PRO_LOCAL_REQUEST;
- if (0 != (SEARCH_MESSAGE_OPTION_LOOPBACK_ONLY & ntohl (sm->options)))
- options |= GSF_PRO_LOCAL_ONLY;
- cr->pr = GSF_pending_request_create_ (options, type,
- &sm->query,
- (0 !=
- memcmp (&sm->target, &all_zeros,
- sizeof (struct GNUNET_PeerIdentity)))
- ? &sm->target : NULL, NULL, 0,
- 0 /* bf */ ,
- ntohl (sm->anonymity_level),
- 0 /* priority */ ,
- 0 /* ttl */ ,
- 0 /* sender PID */ ,
- 0 /* origin PID */ ,
- (const struct GNUNET_HashCode *) &sm[1], sc,
- &client_response_handler, cr);
- }
- *prptr = cr->pr;
- return (0 !=
- (SEARCH_MESSAGE_OPTION_CONTINUED & ntohl (sm->options))) ? GNUNET_NO :
- GNUNET_YES;
-}
-
-
-/**
- * Transmit the given message by copying it to the target buffer
- * "buf". "buf" will be NULL and "size" zero if the socket was closed
- * for writing in the meantime. In that case, do nothing
- * (the disconnect or shutdown handler will take care of the rest).
- * If we were able to transmit messages and there are still more
- * pending, ask core again for further calls to this function.
- *
- * @param cls closure, pointer to the `struct GSF_LocalClient`
- * @param size number of bytes available in @a buf
- * @param buf where the callee should write the message
- * @return number of bytes written to @a buf
- */
-static size_t
-transmit_to_client (void *cls,
- size_t size,
- void *buf)
-{
- struct GSF_LocalClient *lc = cls;
- char *cbuf = buf;
- struct ClientResponse *res;
- size_t msize;
-
- lc->th = NULL;
- if (NULL == buf)
- return 0;
- msize = 0;
- while ((NULL != (res = lc->res_head)) && (res->msize <= size))
- {
- GNUNET_memcpy (&cbuf[msize], &res[1], res->msize);
- msize += res->msize;
- size -= res->msize;
- GNUNET_CONTAINER_DLL_remove (lc->res_head, lc->res_tail, res);
- GNUNET_free (res);
- }
- if (NULL != res)
- lc->th =
- GNUNET_SERVER_notify_transmit_ready (lc->client, res->msize,
- GNUNET_TIME_UNIT_FOREVER_REL,
- &transmit_to_client, lc);
- return msize;
-}
-
-
-/**
- * Transmit a message to the given local client as soon as possible.
- * If the client disconnects before transmission, the message is
- * simply discarded.
- *
- * @param lc recipient
- * @param msg message to transmit to client
- */
-void
-GSF_local_client_transmit_ (struct GSF_LocalClient *lc,
- const struct GNUNET_MessageHeader *msg)
-{
- struct ClientResponse *res;
- size_t msize;
-
- msize = ntohs (msg->size);
- res = GNUNET_malloc (sizeof (struct ClientResponse) + msize);
- res->lc = lc;
- res->msize = msize;
- GNUNET_memcpy (&res[1],
- msg,
- msize);
- GNUNET_CONTAINER_DLL_insert_tail (lc->res_head,
- lc->res_tail,
- res);
- if (NULL == lc->th)
- lc->th =
- GNUNET_SERVER_notify_transmit_ready (lc->client, msize,
- GNUNET_TIME_UNIT_FOREVER_REL,
- &transmit_to_client, lc);
-}
-
-
-/**
- * A client disconnected from us. Tear down the local client
- * record.
- *
- * @param cls unused
- * @param client handle of the client
- */
-void
-GSF_client_disconnect_handler_ (void *cls,
- struct GNUNET_SERVER_Client *client)
-{
- struct GSF_LocalClient *pos;
- struct ClientRequest *cr;
- struct ClientResponse *res;
-
- pos = client_head;
- while ((pos != NULL) && (pos->client != client))
- pos = pos->next;
- if (NULL == pos)
- return;
- while (NULL != (cr = pos->cr_head))
- {
- if (NULL != cr->kill_task)
- GNUNET_SCHEDULER_cancel (cr->kill_task);
- client_request_destroy (cr);
- }
- while (NULL != (res = pos->res_head))
- {
- GNUNET_CONTAINER_DLL_remove (pos->res_head, pos->res_tail, res);
- GNUNET_free (res);
- }
- if (NULL != pos->th)
- {
- GNUNET_SERVER_notify_transmit_ready_cancel (pos->th);
- pos->th = NULL;
- }
- GSF_handle_local_client_disconnect_ (pos);
- GNUNET_CONTAINER_DLL_remove (client_head, client_tail, pos);
- GNUNET_free (pos);
-}
-
/* end of gnunet-service-fs_lc.c */
#include "gnunet-service-fs.h"
-/**
- * Look up a local client record or create one if it
- * doesn't exist yet.
- *
- * @param client handle of the client
- * @return handle to local client entry
- */
-struct GSF_LocalClient *
-GSF_local_client_lookup_ (struct GNUNET_SERVER_Client *client);
-
-
-/**
- * Handle START_SEARCH-message (search request from local client).
- * Only responsible for creating the request entry itself and setting
- * up reply callback and cancellation on client disconnect. Does NOT
- * execute the actual request strategy (planning).
- *
- * @param client identification of the client
- * @param message the actual message
- * @param prptr where to store the pending request handle for the request
- * @return GNUNET_YES to start local processing,
- * GNUNET_NO to not (yet) start local processing,
- * GNUNET_SYSERR on error
- */
-int
-GSF_local_client_start_search_handler_ (struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader
- *message,
- struct GSF_PendingRequest **prptr);
-
-
-/**
- * Transmit a message to the given local client as soon as possible.
- * If the client disconnects before transmission, the message is
- * simply discarded.
- *
- * @param lc recipient
- * @param msg message to transmit to client
- */
-void
-GSF_local_client_transmit_ (struct GSF_LocalClient *lc,
- const struct GNUNET_MessageHeader *msg);
-
-
-/**
- * A client disconnected from us. Tear down the local client record.
- *
- * @param cls unused
- * @param client handle of the client
- */
-void
-GSF_client_disconnect_handler_ (void *cls, struct GNUNET_SERVER_Client *client);
-
-
#endif
/* end of gnunet-service-fs_lc.h */