From bc0e1c956bef848d2569e0c56ccbda13597418f7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 30 Jan 2011 16:02:52 +0000 Subject: [PATCH] stuff --- src/fs/gnunet-service-fs.c | 3 +- src/fs/gnunet-service-fs_cp.c | 284 +++++++++++++++++++++++ src/fs/gnunet-service-fs_cp.h | 205 ++++++++++++----- src/fs/gnunet-service-fs_lc.c | 420 ++++++++++++++++++++++++++++++++++ src/fs/gnunet-service-fs_lc.h | 44 +--- src/fs/gnunet-service-fs_pr.h | 62 ++--- 6 files changed, 896 insertions(+), 122 deletions(-) create mode 100644 src/fs/gnunet-service-fs_cp.c create mode 100644 src/fs/gnunet-service-fs_lc.c diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c index fb275f1b4..a9a3b7c5f 100644 --- a/src/fs/gnunet-service-fs.c +++ b/src/fs/gnunet-service-fs.c @@ -445,8 +445,7 @@ struct ClientList struct ClientList *next; /** - * ID of a client making a request, NULL if this entry is for a - * peer. + * ID of a client. */ struct GNUNET_SERVER_Client *client; diff --git a/src/fs/gnunet-service-fs_cp.c b/src/fs/gnunet-service-fs_cp.c new file mode 100644 index 000000000..6f3f06d3f --- /dev/null +++ b/src/fs/gnunet-service-fs_cp.c @@ -0,0 +1,284 @@ +/* + This file is part of GNUnet. + (C) 2011 Christian Grothoff (and other contributing authors) + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file fs/gnunet-service-fs_cp.c + * @brief API to handle 'connected peers' + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet-service-fs.h" +#include "gnunet-service-fs_cp.h" + + +struct GSF_PeerTransmitHandle +{ + + /** + * Time when this transmission request was issued. + */ + struct GNUNET_TIME_Absolute transmission_request_start_time; + + +}; + + +/** + * A connected peer. + */ +struct GSF_ConnectedPeer +{ + + /** + * Performance data for this peer. + */ + struct GSF_PeerPerformanceData ppd; + + /** + * Time until when we blocked this peer from migrating + * data to us. + */ + struct GNUNET_TIME_Absolute last_migration_block; + + /** + * Handle for an active request for transmission to this + * peer, or NULL. + */ + struct GNUNET_CORE_TransmitHandle *cth; + + /** + * Messages (replies, queries, content migration) we would like to + * send to this peer in the near future. Sorted by priority, head. + */ + struct GSF_PeerTransmitHandle *pth_head; + + /** + * Messages (replies, queries, content migration) we would like to + * send to this peer in the near future. Sorted by priority, tail. + */ + struct GSF_PeerTransmitHandle *pth_tail; + + /** + * Context of our GNUNET_CORE_peer_change_preference call (or NULL). + */ + struct GNUNET_CORE_InformationRequestContext *irc; + + /** + * ID of delay task for scheduling transmission. + */ + GNUNET_SCHEDULER_TaskIdentifier delayed_transmission_request_task; + + /** + * Increase in traffic preference still to be submitted + * to the core service for this peer. + */ + uint64_t inc_preference; + + /** + * Trust rating for this peer + */ + uint32_t trust; + + /** + * Trust rating for this peer on disk. + */ + uint32_t disk_trust; + + /** + * The peer's identity. + */ + GNUNET_PEER_Id pid; + + /** + * Which offset in "last_p2p_replies" will be updated next? + * (we go round-robin). + */ + unsigned int last_p2p_replies_woff; + + /** + * Which offset in "last_client_replies" will be updated next? + * (we go round-robin). + */ + unsigned int last_client_replies_woff; + + /** + * Current offset into 'last_request_times' ring buffer. + */ + unsigned int last_request_times_off; + +}; + + +/** + * A peer connected to us. Setup the connected peer + * records. + * + * @param peer identity of peer that connected + * @param atsi performance data for the connection + * @return handle to connected peer entry + */ +struct GSF_ConnectedPeer * +GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) +{ + // FIXME + return NULL; +} + + +/** + * Transmit a message to the given peer as soon as possible. + * If the peer disconnects before the transmission can happen, + * the callback is invoked with a 'NULL' buffer. + * + * @param peer target peer + * @param is_query is this a query (GNUNET_YES) or content (GNUNET_NO) + * @param priority how important is this request? + * @param timeout when does this request timeout (call gmc with error) + * @param size number of bytes we would like to send to the peer + * @param gmc function to call to get the message + * @param gmc_cls closure for gmc + * @return handle to cancel request + */ +struct GSF_PeerTransmitHandle * +GSF_peer_transmit_ (struct GSF_ConnectedPeer *peer, + int is_query, + uint32_t priority, + struct GNUNET_TIME_Relative timeout, + size_t size, + GSF_GetMessageCallback gmc, + void *gmc_cls) +{ + // FIXME + return NULL; +} + + +/** + * Cancel an earlier request for transmission. + */ +void +GSF_peer_transmit_cancel_ (struct GSF_PeerTransmitHandle *pth) +{ +} + + +/** + * Report on receiving a reply; update the performance record of the given peer. + * + * @param peer responding peer (will be updated) + * @param request_time time at which the original query was transmitted + * @param request_priority priority of the original request + * @param initiator_client local client on responsible for query (or NULL) + * @param initiator_peer other peer responsible for query (or NULL) + */ +void +GSF_peer_update_performance_ (struct GSF_ConnectedPeer *peer, + GNUNET_TIME_Absolute request_time, + uint32_t request_priority, + const struct GSF_LocalClient *initiator_client, + const struct GSF_ConnectedPeer *initiator_peer) +{ +} + + +/** + * Method called whenever a given peer has a status change. + * + * @param cls closure + * @param peer peer identity this notification is about + * @param bandwidth_in available amount of inbound bandwidth + * @param bandwidth_out available amount of outbound bandwidth + * @param timeout absolute time when this peer will time out + * unless we see some further activity from it + * @param atsi status information + */ +void +GSF_peer_status_handler_ (void *cls, + const struct GNUNET_PeerIdentity *peer, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, + struct GNUNET_TIME_Absolute timeout, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) +{ +} + + +/** + * A peer disconnected from us. Tear down the connected peer + * record. + * + * @param cls unused + * @param peer identity of peer that connected + */ +void +GSF_peer_disconnect_handler_ (void *cls, + const struct GNUNET_PeerIdentity *peer) +{ +} + + +/** + * Iterate over all connected peers. + * + * @param it function to call for each peer + * @param it_cls closure for it + */ +void +GSF_iterate_connected_peers_ (GSF_ConnectedPeerIterator it, + void *it_cls) +{ +} + + +/** + * Try to reserve bandwidth (to receive data FROM the given peer). + * This function must only be called ONCE per connected peer at a + * time; it can be called again after the 'rc' callback was invoked. + * If the peer disconnects, the request is (silently!) ignored (and + * the requester is responsible to register for notification about the + * peer disconnect if any special action needs to be taken in this + * case). + * + * @param cp peer to reserve bandwidth from + * @param size number of bytes to reserve + * @param rc function to call upon reservation success or failure + * @param rc_cls closure for rc + */ +void +GSF_connected_peer_reserve_ (struct GSF_ConnectedPeer *cp, + size_t size, + GSF_PeerReserveCallback rc, + void *rc_cls) +{ + // FIXME: should we allow queueing multiple reservation requests? + // FIXME: what about cancellation? + // FIXME: change docu on peer disconnect handling? + if (NULL != cp->irc) + { + rc (rc_cls, cp, GNUNET_NO); + return; + } + // FIXME... +} + + +#endif +/* end of gnunet-service-fs_cp.h */ diff --git a/src/fs/gnunet-service-fs_cp.h b/src/fs/gnunet-service-fs_cp.h index f6d6e7a0a..8886199b5 100644 --- a/src/fs/gnunet-service-fs_cp.h +++ b/src/fs/gnunet-service-fs_cp.h @@ -30,16 +30,90 @@ /** - * A peer connected to us. Setup the connected peer - * records. + * Performance data kept for a peer. + */ +struct GSF_PeerPerformanceData +{ + + /** + * Transport performance data. + */ + struct GNUNET_TRANSPORT_ATS_Information *atsi; + + /** + * List of the last clients for which this peer successfully + * answered a query. + */ + struct GSF_LocalClient *last_client_replies[CS2P_SUCCESS_LIST_SIZE]; + + /** + * List of the last PIDs for which + * this peer successfully answered a query; + * We use 0 to indicate no successful reply. + */ + GNUNET_PEER_Id last_p2p_replies[P2P_SUCCESS_LIST_SIZE]; + + /** + * Average delay between sending the peer a request and + * getting a reply (only calculated over the requests for + * which we actually got a reply). Calculated + * as a moving average: new_delay = ((n-1)*last_delay+curr_delay) / n + */ + struct GNUNET_TIME_Relative avg_reply_delay; + + /** + * Point in time until which this peer does not want us to migrate content + * to it. + */ + struct GNUNET_TIME_Absolute migration_blocked_until; + + /** + * Transmission times for the last MAX_QUEUE_PER_PEER + * requests for this peer. Used as a ring buffer, current + * offset is stored in 'last_request_times_off'. If the + * oldest entry is more recent than the 'avg_delay', we should + * not send any more requests right now. + */ + struct GNUNET_TIME_Absolute last_request_times[MAX_QUEUE_PER_PEER]; + + /** + * How long does it typically take for us to transmit a message + * to this peer? (delay between the request being issued and + * the callback being invoked). + */ + struct GNUNET_LOAD_Value *transmission_delay; + + /** + * Average priority of successful replies. Calculated + * as a moving average: new_avg = ((n-1)*last_avg+curr_prio) / n + */ + double avg_priority; + + /** + * Number of pending queries (replies are not counted) + */ + unsigned int pending_queries; + + /** + * Number of pending replies (queries are not counted) + */ + unsigned int pending_replies; + +}; + + +/** + * Signature of function called on a connected peer. * - * @param peer identity of peer that connected - * @param atsi performance data for the connection - * @return handle to connected peer entry + * @param cls closure + * @param peer identity of the peer + * @param cp handle to the connected peer record + * @param perf peer performance data */ -struct GSF_ConnectedPeer * -GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_TRANSPORT_ATS_Information *atsi); +typedef void (*GSF_ConnectedPeerIterator)(void *cls, + const struct GNUNET_PeerIdentity *peer, + struct GSF_ConnectedPeer *cp, + const struct GSF_PeerPerformanceData *ppd); /** @@ -55,23 +129,85 @@ typedef size_t (*GSF_GetMessageCallback)(void *cls, void *buf); +/** + * Signature of function called on a reservation success or failure. + * + * @param cls closure + * @param cp handle to the connected peer record + * @param success GNUNET_YES on success, GNUNET_NO on failure + */ +typedef void (*GSF_PeerReserveCallback)(void *cls, + struct GSF_ConnectedPeer *cp, + int success); + + +/** + * Handle to cancel a transmission request. + */ +struct GSF_PeerTransmitHandle; + + +/** + * A peer connected to us. Setup the connected peer + * records. + * + * @param peer identity of peer that connected + * @param atsi performance data for the connection + * @return handle to connected peer entry + */ +struct GSF_ConnectedPeer * +GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_TRANSPORT_ATS_Information *atsi); + + /** * Transmit a message to the given peer as soon as possible. * If the peer disconnects before the transmission can happen, * the callback is invoked with a 'NULL' buffer. * * @param peer target peer + * @param is_query is this a query (GNUNET_YES) or content (GNUNET_NO) + * @param priority how important is this request? + * @param timeout when does this request timeout (call gmc with error) * @param size number of bytes we would like to send to the peer * @param gmc function to call to get the message * @param gmc_cls closure for gmc + * @return handle to cancel request */ -void +struct GSF_PeerTransmitHandle * GSF_peer_transmit_ (struct GSF_ConnectedPeer *peer, + int is_query, + uint32_t priority, + struct GNUNET_TIME_Relative timeout, size_t size, GSF_GetMessageCallback gmc, void *gmc_cls); +/** + * Cancel an earlier request for transmission. + */ +void +GSF_peer_transmit_cancel_ (struct GSF_PeerTransmitHandle *pth); + + +/** + * Report on receiving a reply; update the performance record of the given peer. + * + * @param peer responding peer (will be updated) + * @param request_time time at which the original query was transmitted + * @param request_priority priority of the original request + * @param initiator_client local client on responsible for query (or NULL) + * @param initiator_peer other peer responsible for query (or NULL) + */ +void +GSF_peer_update_performance_ (struct GSF_ConnectedPeer *peer, + GNUNET_TIME_Absolute request_time, + uint32_t request_priority, + const struct GSF_LocalClient *initiator_client, + const struct GSF_ConnectedPeer *initiator_peer); + + /** * Method called whenever a given peer has a status change. * @@ -105,15 +241,13 @@ GSF_peer_disconnect_handler_ (void *cls, /** - * Signature of function called on a connected peer. + * Notification that a local client disconnected. Clean up all of our + * references to the given handle. * - * @param cls closure - * @param peer identity of the peer - * @param cp handle to the connected peer record + * @param lc handle to the local client (henceforth invalid) */ -typedef void (*GSF_ConnectedPeerIterator)(void *cls, - const struct GNUNET_PeerIdentity *peer, - struct GSF_ConnectedPeer *cp); +void +GSF_handle_local_client_disconnect_ (const struct GSF_LocalClient *lc); /** @@ -127,42 +261,9 @@ GSF_iterate_connected_peers_ (GSF_ConnectedPeerIterator it, void *it_cls); -/** - * Register callback to invoke on peer disconnect. - * - * @param cp peer to monitor - * @param it function to call on disconnect - * @param it_cls closure for it - */ -void -GSF_connected_peer_register_disconnect_callback_ (struct GSF_ConnectedPeer *cp, - GSF_ConnectedPeerIterator it, - void *it_cls); - - -/** - * Unregister callback to invoke on peer disconnect. - * - * @param cp peer to stop monitoring - * @param it function to no longer call on disconnect - * @param it_cls closure for it - */ -void -GSF_connected_peer_unregister_disconnect_callback_ (struct GSF_ConnectedPeer *cp, - GSF_ConnectedPeerIterator it, - void *it_cls); - - -/** - * Signature of function called on a reservation success. - * - * @param cls closure - * @param cp handle to the connected peer record - */ -typedef void (*GSF_PeerReserveCallback)(void *cls, - struct GSF_ConnectedPeer *cp); - - +// FIXME: should we allow queueing multiple reservation requests? +// FIXME: what about cancellation? +// FIXME: change docu on peer disconnect handling? /** * Try to reserve bandwidth (to receive data FROM the given peer). * This function must only be called ONCE per connected peer at a diff --git a/src/fs/gnunet-service-fs_lc.c b/src/fs/gnunet-service-fs_lc.c new file mode 100644 index 000000000..2113a4498 --- /dev/null +++ b/src/fs/gnunet-service-fs_lc.c @@ -0,0 +1,420 @@ +/* + This file is part of GNUnet. + (C) 2011 Christian Grothoff (and other contributing authors) + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file fs/gnunet-service-fs_lc.c + * @brief API to handle 'connected peers' + * @author Christian Grothoff + */ + +#include "platform.h" +#include "gnunet-service-fs_lc.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; + +}; + + + +/** + * 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_CONNECTION_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 ( (pos != NULL) && + (pos->client != client) ) + pos = pos->next; + if (pos != NULL) + return pos; + pos = GNUNET_malloc (sizeof (struct GSF_LocalClient)); + pos->client = client; + GNUNET_CONTAINER_DLL_insert (client_head, + client_tail, + pos); + return pos; +} + + +/** + * Handle START_SEARCH-message (search request from local client). + * + * @param cls closure + * @param client identification of the client + * @param message the actual message + */ +void +GSF_local_client_start_search_handler_ (void *cls, + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + static GNUNET_HashCode all_zeros; + const struct SearchMessage *sm; + struct GSF_LocalClient *lc; + struct ClientRequest *cr; + struct GSF_PendingRequest *pr; + 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 (GNUNET_HashCode)) ) + { + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, + GNUNET_SYSERR); + return; + } + GNUNET_STATISTICS_update (stats, + gettext_noop ("# client searches received"), + 1, + GNUNET_NO); + sc = (msize - sizeof (struct SearchMessage)) / sizeof (GNUNET_HashCode); + sm = (const struct SearchMessage*) message; + type = ntohl (sm->type); +#if DEBUG_FS + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received request for `%s' of type %u from local client\n", + GNUNET_h2s (&sm->query), + (unsigned int) type); +#endif + lc = GSF_local_client_lookup_ (client); + + + /* detect duplicate KBLOCK requests */ + if ( (type == GNUNET_BLOCK_TYPE_FS_KBLOCK) || + (type == GNUNET_BLOCK_TYPE_FS_NBLOCK) || + (type == GNUNET_BLOCK_TYPE_ANY) ) + { + cr = lc->cr_head; + while ( (cl != NULL) && + ( (0 != memcmp (GSF_pending_request_get_query_ (cr->pr), + &sm->query, + sizeof (GNUNET_HashCode))) || + (GSF_pending_request_get_type_ (cr->pr) != type) ) ) + cr = cr->next; + if (crl != NULL) + { +#if DEBUG_FS + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Have existing request, merging content-seen lists.\n"); +#endif + GSF_pending_request_update_ (cr->pr, + &sm[1], + sc); + GNUNET_STATISTICS_update (stats, + gettext_noop ("# client searches updated (merged content seen list)"), + 1, + GNUNET_NO); + GNUNET_SERVER_receive_done (client, + GNUNET_OK); + return; + } + } + + GNUNET_STATISTICS_update (stats, + gettext_noop ("# client searches active"), + 1, + GNUNET_NO); + cr = GNUNET_malloc (sizeof (struct ClientRequest)); + cr->lc = lc; + GNUNET_CONTAINER_DLL_insert (lc->cr_head, + lc->cr_tail, + cr); + options = GSF_PRO_LOCAL_REQUEST; + if (0 != (1 & ntohl (sm->options))) + options |= GSF_PRO_LOCAL_ONLY; + cr->pr = GSF_pending_request_create (options, + + type, + &sm->query, + (type == GNUNET_BLOCK_TYPE_SBLOCK) + ? &sm->target /* namespace */ + : NULL, + (0 != memcmp (&sm->target, + &all_zeros, + sizeof (GNUNET_HashCode))) + ? &sm->target, + : NULL, + NULL /* bf */, 0 /* mingle */, + ntohl (sm->anonymity_level), + 0 /* priority */, + &sm[1], sc, + &client_response_handler, + cr); + // FIXME: start local processing and/or P2P processing? +} + + +/** + * 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 buf + * @param buf where the callee should write the message + * @return number of bytes written to 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; + + cl->th = NULL; + if (NULL == buf) + return 0; + msize = 0; + while ( (NULL != (res = lc->res_head) ) && + (res->msize <= size) ) + { + memcpy (&cbuf[msize], &res[1], res->msize); + msize += res->msize; + size -= res->msize; + GNUNET_CONTAINER_DLL_remove (cl->res_head, + cl->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_CONTAINER_DLL_insert_tail (lc->res_head, + lc->res_tail, + res); + if (NULL == lc->tc) + lc->tc = GNUNET_CLIENT_notify_transmit_ready (lc->client, + msize, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_NO, + &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, + const struct GNUNET_SERVER_Client *client) +{ + struct GSF_LocalClient *pos; + struct DisconnectCallback *dc; + struct ClientRequest *cr; + struct ClientResponse *res; + + pos = client_head; + while ( (pos != NULL) && + (pos->client != client) ) + pos = pos->next; + if (pos == NULL) + return pos; + while (NULL != (cr = pos->cr_head)) + { + GNUNET_CONTAINER_DLL_remove (pos->cr_head, + pos->cr_tail, + cr); + GSF_pending_request_cancel_ (cr->pr); + GNUNET_free (cr); + } + while (NULL != (res = pos->res_head)) + { + GNUNET_CONTAINER_DLL_remove (pos->res_head, + pos->res_tail, + res); + GNUNET_free (res); + } + if (pos->th != NULL) + { + GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th); + pos->th = NULL; + } + GSF_handle_local_client_disconnect_ (pos); + GNUNET_free (pos); +} + + +/* end of gnunet-service-fs_lc.c */ diff --git a/src/fs/gnunet-service-fs_lc.h b/src/fs/gnunet-service-fs_lc.h index 2663fbc67..e9b77aa59 100644 --- a/src/fs/gnunet-service-fs_lc.h +++ b/src/fs/gnunet-service-fs_lc.h @@ -67,53 +67,15 @@ GSF_local_client_transmit_ (struct GSF_LocalClient *lc, /** - * A local client disconnected from us. Tear down the local client - * record. + * A client disconnected from us. Tear down the local client record. * * @param cls unused * @param client handle of the client */ void -GSF_local_client_disconnect_handler_ (void *cls, - const struct GNUNET_SERVER_Client *client); +GSF_client_disconnect_handler_ (void *cls, + const struct GNUNET_SERVER_Client *client); - -/** - * Signature of function called on a local client - * - * @param cls closure - * @param lc local client handle - */ -typedef int (*GSF_LocalClientIterator)(void *cls, - struct GSF_LocalClient *lc); - - - -/** - * Register callback to invoke on local client disconnect. - * - * @param lc client to monitor - * @param it function to call on disconnect - * @param it_cls closure for it - */ -void -GSF_local_client_register_disconnect_callback_ (struct GSF_LocalClient *lc, - GSF_LocalClientIterator it, - void *it_cls); - - -/** - * Register callback to invoke on local client disconnect. - * - * @param lc client to stop monitoring - * @param it function to no longer call on disconnect - * @param it_cls closure for it - */ -void -GSF_local_client_unregister_disconnect_callback_ (struct GSF_LocalClient *lc, - GSF_PendingRequestIterator it, - void *it_cls); - #endif /* end of gnunet-service-fs_lc.h */ diff --git a/src/fs/gnunet-service-fs_pr.h b/src/fs/gnunet-service-fs_pr.h index b4dd82839..24107534f 100644 --- a/src/fs/gnunet-service-fs_pr.h +++ b/src/fs/gnunet-service-fs_pr.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010 Christian Grothoff (and other contributing authors) + (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -119,6 +119,40 @@ GSF_pending_request_create_ (enum GSF_PendingRequestOptions options, void *rh_cls); +/** + * Update a given pending request with additional replies + * that have been seen. + * + * @param pr request to update + * @param replies_seen hash codes of replies that we've seen + * @param replies_seen_count size of the replies_seen array + */ +void +GSF_pending_request_update_ (struct GSF_PendingRequest *pr, + const GNUNET_HashCode *replies_seen, + unsigned int replies_seen_count); + + +/** + * Get the query for a given pending request. + * + * @param pr the request + * @return pointer to the query (only valid as long as pr is valid) + */ +const GNUNET_HashCode * +GSF_pending_request_get_query_ (const struct GSF_PendingRequest *pr); + + +/** + * Get the type of a given pending request. + * + * @param pr the request + * @return query type + */ +enum GNUNET_BLOCK_Type +GSF_pending_request_get_type_ (const struct GSF_PendingRequest *pr); + + /** * Generate the message corresponding to the given pending request for * transmission to other peers (or at least determine its size). @@ -167,31 +201,5 @@ GSF_iterate_pending_requests_ (GSF_PendingRequestIterator it, -/** - * Register callback to invoke on request destruction. - * - * @param pr request to monitor - * @param it function to call on destruction - * @param it_cls closure for it - */ -void -GSF_pending_request_register_destroy_callback_ (struct GSF_PendingRequest *pr, - GSF_PendingRequestIterator it, - void *it_cls); - - -/** - * Unregister callback to invoke on request destruction. - * - * @param pr request to stop monitoring - * @param it function to no longer call on destruction - * @param it_cls closure for it - */ -void -GSF_pending_request_unregister_destroy_callback_ (struct GSF_PendingRequest *pr, - GSF_PendingRequestIterator it, - void *it_cls); - - #endif /* end of gnunet-service-fs_pr.h */ -- 2.25.1