aboutsummaryrefslogtreecommitdiff
path: root/src/fs
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs')
-rw-r--r--src/fs/gnunet-service-fs.c3
-rw-r--r--src/fs/gnunet-service-fs_cp.c284
-rw-r--r--src/fs/gnunet-service-fs_cp.h205
-rw-r--r--src/fs/gnunet-service-fs_lc.c420
-rw-r--r--src/fs/gnunet-service-fs_lc.h44
-rw-r--r--src/fs/gnunet-service-fs_pr.h62
6 files changed, 896 insertions, 122 deletions
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
445 struct ClientList *next; 445 struct ClientList *next;
446 446
447 /** 447 /**
448 * ID of a client making a request, NULL if this entry is for a 448 * ID of a client.
449 * peer.
450 */ 449 */
451 struct GNUNET_SERVER_Client *client; 450 struct GNUNET_SERVER_Client *client;
452 451
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 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file fs/gnunet-service-fs_cp.c
23 * @brief API to handle 'connected peers'
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet-service-fs.h"
28#include "gnunet-service-fs_cp.h"
29
30
31struct GSF_PeerTransmitHandle
32{
33
34 /**
35 * Time when this transmission request was issued.
36 */
37 struct GNUNET_TIME_Absolute transmission_request_start_time;
38
39
40};
41
42
43/**
44 * A connected peer.
45 */
46struct GSF_ConnectedPeer
47{
48
49 /**
50 * Performance data for this peer.
51 */
52 struct GSF_PeerPerformanceData ppd;
53
54 /**
55 * Time until when we blocked this peer from migrating
56 * data to us.
57 */
58 struct GNUNET_TIME_Absolute last_migration_block;
59
60 /**
61 * Handle for an active request for transmission to this
62 * peer, or NULL.
63 */
64 struct GNUNET_CORE_TransmitHandle *cth;
65
66 /**
67 * Messages (replies, queries, content migration) we would like to
68 * send to this peer in the near future. Sorted by priority, head.
69 */
70 struct GSF_PeerTransmitHandle *pth_head;
71
72 /**
73 * Messages (replies, queries, content migration) we would like to
74 * send to this peer in the near future. Sorted by priority, tail.
75 */
76 struct GSF_PeerTransmitHandle *pth_tail;
77
78 /**
79 * Context of our GNUNET_CORE_peer_change_preference call (or NULL).
80 */
81 struct GNUNET_CORE_InformationRequestContext *irc;
82
83 /**
84 * ID of delay task for scheduling transmission.
85 */
86 GNUNET_SCHEDULER_TaskIdentifier delayed_transmission_request_task;
87
88 /**
89 * Increase in traffic preference still to be submitted
90 * to the core service for this peer.
91 */
92 uint64_t inc_preference;
93
94 /**
95 * Trust rating for this peer
96 */
97 uint32_t trust;
98
99 /**
100 * Trust rating for this peer on disk.
101 */
102 uint32_t disk_trust;
103
104 /**
105 * The peer's identity.
106 */
107 GNUNET_PEER_Id pid;
108
109 /**
110 * Which offset in "last_p2p_replies" will be updated next?
111 * (we go round-robin).
112 */
113 unsigned int last_p2p_replies_woff;
114
115 /**
116 * Which offset in "last_client_replies" will be updated next?
117 * (we go round-robin).
118 */
119 unsigned int last_client_replies_woff;
120
121 /**
122 * Current offset into 'last_request_times' ring buffer.
123 */
124 unsigned int last_request_times_off;
125
126};
127
128
129/**
130 * A peer connected to us. Setup the connected peer
131 * records.
132 *
133 * @param peer identity of peer that connected
134 * @param atsi performance data for the connection
135 * @return handle to connected peer entry
136 */
137struct GSF_ConnectedPeer *
138GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer,
139 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
140{
141 // FIXME
142 return NULL;
143}
144
145
146/**
147 * Transmit a message to the given peer as soon as possible.
148 * If the peer disconnects before the transmission can happen,
149 * the callback is invoked with a 'NULL' buffer.
150 *
151 * @param peer target peer
152 * @param is_query is this a query (GNUNET_YES) or content (GNUNET_NO)
153 * @param priority how important is this request?
154 * @param timeout when does this request timeout (call gmc with error)
155 * @param size number of bytes we would like to send to the peer
156 * @param gmc function to call to get the message
157 * @param gmc_cls closure for gmc
158 * @return handle to cancel request
159 */
160struct GSF_PeerTransmitHandle *
161GSF_peer_transmit_ (struct GSF_ConnectedPeer *peer,
162 int is_query,
163 uint32_t priority,
164 struct GNUNET_TIME_Relative timeout,
165 size_t size,
166 GSF_GetMessageCallback gmc,
167 void *gmc_cls)
168{
169 // FIXME
170 return NULL;
171}
172
173
174/**
175 * Cancel an earlier request for transmission.
176 */
177void
178GSF_peer_transmit_cancel_ (struct GSF_PeerTransmitHandle *pth)
179{
180}
181
182
183/**
184 * Report on receiving a reply; update the performance record of the given peer.
185 *
186 * @param peer responding peer (will be updated)
187 * @param request_time time at which the original query was transmitted
188 * @param request_priority priority of the original request
189 * @param initiator_client local client on responsible for query (or NULL)
190 * @param initiator_peer other peer responsible for query (or NULL)
191 */
192void
193GSF_peer_update_performance_ (struct GSF_ConnectedPeer *peer,
194 GNUNET_TIME_Absolute request_time,
195 uint32_t request_priority,
196 const struct GSF_LocalClient *initiator_client,
197 const struct GSF_ConnectedPeer *initiator_peer)
198{
199}
200
201
202/**
203 * Method called whenever a given peer has a status change.
204 *
205 * @param cls closure
206 * @param peer peer identity this notification is about
207 * @param bandwidth_in available amount of inbound bandwidth
208 * @param bandwidth_out available amount of outbound bandwidth
209 * @param timeout absolute time when this peer will time out
210 * unless we see some further activity from it
211 * @param atsi status information
212 */
213void
214GSF_peer_status_handler_ (void *cls,
215 const struct GNUNET_PeerIdentity *peer,
216 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
217 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
218 struct GNUNET_TIME_Absolute timeout,
219 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
220{
221}
222
223
224/**
225 * A peer disconnected from us. Tear down the connected peer
226 * record.
227 *
228 * @param cls unused
229 * @param peer identity of peer that connected
230 */
231void
232GSF_peer_disconnect_handler_ (void *cls,
233 const struct GNUNET_PeerIdentity *peer)
234{
235}
236
237
238/**
239 * Iterate over all connected peers.
240 *
241 * @param it function to call for each peer
242 * @param it_cls closure for it
243 */
244void
245GSF_iterate_connected_peers_ (GSF_ConnectedPeerIterator it,
246 void *it_cls)
247{
248}
249
250
251/**
252 * Try to reserve bandwidth (to receive data FROM the given peer).
253 * This function must only be called ONCE per connected peer at a
254 * time; it can be called again after the 'rc' callback was invoked.
255 * If the peer disconnects, the request is (silently!) ignored (and
256 * the requester is responsible to register for notification about the
257 * peer disconnect if any special action needs to be taken in this
258 * case).
259 *
260 * @param cp peer to reserve bandwidth from
261 * @param size number of bytes to reserve
262 * @param rc function to call upon reservation success or failure
263 * @param rc_cls closure for rc
264 */
265void
266GSF_connected_peer_reserve_ (struct GSF_ConnectedPeer *cp,
267 size_t size,
268 GSF_PeerReserveCallback rc,
269 void *rc_cls)
270{
271 // FIXME: should we allow queueing multiple reservation requests?
272 // FIXME: what about cancellation?
273 // FIXME: change docu on peer disconnect handling?
274 if (NULL != cp->irc)
275 {
276 rc (rc_cls, cp, GNUNET_NO);
277 return;
278 }
279 // FIXME...
280}
281
282
283#endif
284/* 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 @@
30 30
31 31
32/** 32/**
33 * A peer connected to us. Setup the connected peer 33 * Performance data kept for a peer.
34 * records. 34 */
35struct GSF_PeerPerformanceData
36{
37
38 /**
39 * Transport performance data.
40 */
41 struct GNUNET_TRANSPORT_ATS_Information *atsi;
42
43 /**
44 * List of the last clients for which this peer successfully
45 * answered a query.
46 */
47 struct GSF_LocalClient *last_client_replies[CS2P_SUCCESS_LIST_SIZE];
48
49 /**
50 * List of the last PIDs for which
51 * this peer successfully answered a query;
52 * We use 0 to indicate no successful reply.
53 */
54 GNUNET_PEER_Id last_p2p_replies[P2P_SUCCESS_LIST_SIZE];
55
56 /**
57 * Average delay between sending the peer a request and
58 * getting a reply (only calculated over the requests for
59 * which we actually got a reply). Calculated
60 * as a moving average: new_delay = ((n-1)*last_delay+curr_delay) / n
61 */
62 struct GNUNET_TIME_Relative avg_reply_delay;
63
64 /**
65 * Point in time until which this peer does not want us to migrate content
66 * to it.
67 */
68 struct GNUNET_TIME_Absolute migration_blocked_until;
69
70 /**
71 * Transmission times for the last MAX_QUEUE_PER_PEER
72 * requests for this peer. Used as a ring buffer, current
73 * offset is stored in 'last_request_times_off'. If the
74 * oldest entry is more recent than the 'avg_delay', we should
75 * not send any more requests right now.
76 */
77 struct GNUNET_TIME_Absolute last_request_times[MAX_QUEUE_PER_PEER];
78
79 /**
80 * How long does it typically take for us to transmit a message
81 * to this peer? (delay between the request being issued and
82 * the callback being invoked).
83 */
84 struct GNUNET_LOAD_Value *transmission_delay;
85
86 /**
87 * Average priority of successful replies. Calculated
88 * as a moving average: new_avg = ((n-1)*last_avg+curr_prio) / n
89 */
90 double avg_priority;
91
92 /**
93 * Number of pending queries (replies are not counted)
94 */
95 unsigned int pending_queries;
96
97 /**
98 * Number of pending replies (queries are not counted)
99 */
100 unsigned int pending_replies;
101
102};
103
104
105/**
106 * Signature of function called on a connected peer.
35 * 107 *
36 * @param peer identity of peer that connected 108 * @param cls closure
37 * @param atsi performance data for the connection 109 * @param peer identity of the peer
38 * @return handle to connected peer entry 110 * @param cp handle to the connected peer record
111 * @param perf peer performance data
39 */ 112 */
40struct GSF_ConnectedPeer * 113typedef void (*GSF_ConnectedPeerIterator)(void *cls,
41GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer, 114 const struct GNUNET_PeerIdentity *peer,
42 const struct GNUNET_TRANSPORT_ATS_Information *atsi); 115 struct GSF_ConnectedPeer *cp,
116 const struct GSF_PeerPerformanceData *ppd);
43 117
44 118
45/** 119/**
@@ -56,23 +130,85 @@ typedef size_t (*GSF_GetMessageCallback)(void *cls,
56 130
57 131
58/** 132/**
133 * Signature of function called on a reservation success or failure.
134 *
135 * @param cls closure
136 * @param cp handle to the connected peer record
137 * @param success GNUNET_YES on success, GNUNET_NO on failure
138 */
139typedef void (*GSF_PeerReserveCallback)(void *cls,
140 struct GSF_ConnectedPeer *cp,
141 int success);
142
143
144/**
145 * Handle to cancel a transmission request.
146 */
147struct GSF_PeerTransmitHandle;
148
149
150/**
151 * A peer connected to us. Setup the connected peer
152 * records.
153 *
154 * @param peer identity of peer that connected
155 * @param atsi performance data for the connection
156 * @return handle to connected peer entry
157 */
158struct GSF_ConnectedPeer *
159GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer,
160 const struct GNUNET_TRANSPORT_ATS_Information *atsi);
161
162
163/**
59 * Transmit a message to the given peer as soon as possible. 164 * Transmit a message to the given peer as soon as possible.
60 * If the peer disconnects before the transmission can happen, 165 * If the peer disconnects before the transmission can happen,
61 * the callback is invoked with a 'NULL' buffer. 166 * the callback is invoked with a 'NULL' buffer.
62 * 167 *
63 * @param peer target peer 168 * @param peer target peer
169 * @param is_query is this a query (GNUNET_YES) or content (GNUNET_NO)
170 * @param priority how important is this request?
171 * @param timeout when does this request timeout (call gmc with error)
64 * @param size number of bytes we would like to send to the peer 172 * @param size number of bytes we would like to send to the peer
65 * @param gmc function to call to get the message 173 * @param gmc function to call to get the message
66 * @param gmc_cls closure for gmc 174 * @param gmc_cls closure for gmc
175 * @return handle to cancel request
67 */ 176 */
68void 177struct GSF_PeerTransmitHandle *
69GSF_peer_transmit_ (struct GSF_ConnectedPeer *peer, 178GSF_peer_transmit_ (struct GSF_ConnectedPeer *peer,
179 int is_query,
180 uint32_t priority,
181 struct GNUNET_TIME_Relative timeout,
70 size_t size, 182 size_t size,
71 GSF_GetMessageCallback gmc, 183 GSF_GetMessageCallback gmc,
72 void *gmc_cls); 184 void *gmc_cls);
73 185
74 186
75/** 187/**
188 * Cancel an earlier request for transmission.
189 */
190void
191GSF_peer_transmit_cancel_ (struct GSF_PeerTransmitHandle *pth);
192
193
194/**
195 * Report on receiving a reply; update the performance record of the given peer.
196 *
197 * @param peer responding peer (will be updated)
198 * @param request_time time at which the original query was transmitted
199 * @param request_priority priority of the original request
200 * @param initiator_client local client on responsible for query (or NULL)
201 * @param initiator_peer other peer responsible for query (or NULL)
202 */
203void
204GSF_peer_update_performance_ (struct GSF_ConnectedPeer *peer,
205 GNUNET_TIME_Absolute request_time,
206 uint32_t request_priority,
207 const struct GSF_LocalClient *initiator_client,
208 const struct GSF_ConnectedPeer *initiator_peer);
209
210
211/**
76 * Method called whenever a given peer has a status change. 212 * Method called whenever a given peer has a status change.
77 * 213 *
78 * @param cls closure 214 * @param cls closure
@@ -105,15 +241,13 @@ GSF_peer_disconnect_handler_ (void *cls,
105 241
106 242
107/** 243/**
108 * Signature of function called on a connected peer. 244 * Notification that a local client disconnected. Clean up all of our
245 * references to the given handle.
109 * 246 *
110 * @param cls closure 247 * @param lc handle to the local client (henceforth invalid)
111 * @param peer identity of the peer
112 * @param cp handle to the connected peer record
113 */ 248 */
114typedef void (*GSF_ConnectedPeerIterator)(void *cls, 249void
115 const struct GNUNET_PeerIdentity *peer, 250GSF_handle_local_client_disconnect_ (const struct GSF_LocalClient *lc);
116 struct GSF_ConnectedPeer *cp);
117 251
118 252
119/** 253/**
@@ -127,42 +261,9 @@ GSF_iterate_connected_peers_ (GSF_ConnectedPeerIterator it,
127 void *it_cls); 261 void *it_cls);
128 262
129 263
130/** 264// FIXME: should we allow queueing multiple reservation requests?
131 * Register callback to invoke on peer disconnect. 265// FIXME: what about cancellation?
132 * 266// FIXME: change docu on peer disconnect handling?
133 * @param cp peer to monitor
134 * @param it function to call on disconnect
135 * @param it_cls closure for it
136 */
137void
138GSF_connected_peer_register_disconnect_callback_ (struct GSF_ConnectedPeer *cp,
139 GSF_ConnectedPeerIterator it,
140 void *it_cls);
141
142
143/**
144 * Unregister callback to invoke on peer disconnect.
145 *
146 * @param cp peer to stop monitoring
147 * @param it function to no longer call on disconnect
148 * @param it_cls closure for it
149 */
150void
151GSF_connected_peer_unregister_disconnect_callback_ (struct GSF_ConnectedPeer *cp,
152 GSF_ConnectedPeerIterator it,
153 void *it_cls);
154
155
156/**
157 * Signature of function called on a reservation success.
158 *
159 * @param cls closure
160 * @param cp handle to the connected peer record
161 */
162typedef void (*GSF_PeerReserveCallback)(void *cls,
163 struct GSF_ConnectedPeer *cp);
164
165
166/** 267/**
167 * Try to reserve bandwidth (to receive data FROM the given peer). 268 * Try to reserve bandwidth (to receive data FROM the given peer).
168 * This function must only be called ONCE per connected peer at a 269 * 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 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file fs/gnunet-service-fs_lc.c
23 * @brief API to handle 'connected peers'
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet-service-fs_lc.h"
29
30
31/**
32 * Doubly-linked list of requests we are performing
33 * on behalf of the same client.
34 */
35struct ClientRequest
36{
37
38 /**
39 * This is a doubly-linked list.
40 */
41 struct ClientRequest *next;
42
43 /**
44 * This is a doubly-linked list.
45 */
46 struct ClientRequest *prev;
47
48 /**
49 * Request this entry represents.
50 */
51 struct GSF_PendingRequest *pr;
52
53 /**
54 * Client list this request belongs to.
55 */
56 struct GSF_LocalClient *lc;
57
58};
59
60
61
62/**
63 * Replies to be transmitted to the client. The actual
64 * response message is allocated after this struct.
65 */
66struct ClientResponse
67{
68 /**
69 * This is a doubly-linked list.
70 */
71 struct ClientResponse *next;
72
73 /**
74 * This is a doubly-linked list.
75 */
76 struct ClientResponse *prev;
77
78 /**
79 * Client list entry this response belongs to.
80 */
81 struct GSF_LocalClient *lc;
82
83 /**
84 * Number of bytes in the response.
85 */
86 size_t msize;
87};
88
89
90
91/**
92 * A local client.
93 */
94struct GSF_LocalClient
95{
96
97 /**
98 * We keep clients in a DLL.
99 */
100 struct GSF_LocalClient *next;
101
102 /**
103 * We keep clients in a DLL.
104 */
105 struct GSF_LocalClient *prev;
106
107 /**
108 * ID of the client.
109 */
110 struct GNUNET_SERVER_Client *client;
111
112 /**
113 * Head of list of requests performed on behalf
114 * of this client right now.
115 */
116 struct ClientRequest *cr_head;
117
118 /**
119 * Tail of list of requests performed on behalf
120 * of this client right now.
121 */
122 struct ClientRequest *cr_tail;
123
124 /**
125 * Head of linked list of responses.
126 */
127 struct ClientResponse *res_head;
128
129 /**
130 * Tail of linked list of responses.
131 */
132 struct ClientResponse *res_tail;
133
134 /**
135 * Context for sending replies.
136 */
137 struct GNUNET_CONNECTION_TransmitHandle *th;
138
139};
140
141
142/**
143 * Head of linked list of our local clients.
144 */
145static struct GSF_LocalClient *client_head;
146
147
148/**
149 * Head of linked list of our local clients.
150 */
151static struct GSF_LocalClient *client_tail;
152
153
154/**
155 * Look up a local client record or create one if it
156 * doesn't exist yet.
157 *
158 * @param client handle of the client
159 * @return handle to local client entry
160 */
161struct GSF_LocalClient *
162GSF_local_client_lookup_ (struct GNUNET_SERVER_Client *client)
163{
164 struct GSF_LocalClient *pos;
165
166 pos = client_head;
167 while ( (pos != NULL) &&
168 (pos->client != client) )
169 pos = pos->next;
170 if (pos != NULL)
171 return pos;
172 pos = GNUNET_malloc (sizeof (struct GSF_LocalClient));
173 pos->client = client;
174 GNUNET_CONTAINER_DLL_insert (client_head,
175 client_tail,
176 pos);
177 return pos;
178}
179
180
181/**
182 * Handle START_SEARCH-message (search request from local client).
183 *
184 * @param cls closure
185 * @param client identification of the client
186 * @param message the actual message
187 */
188void
189GSF_local_client_start_search_handler_ (void *cls,
190 struct GNUNET_SERVER_Client *client,
191 const struct GNUNET_MessageHeader *message)
192{
193 static GNUNET_HashCode all_zeros;
194 const struct SearchMessage *sm;
195 struct GSF_LocalClient *lc;
196 struct ClientRequest *cr;
197 struct GSF_PendingRequest *pr;
198 uint16_t msize;
199 unsigned int sc;
200 enum GNUNET_BLOCK_Type type;
201 enum GSF_PendingRequestOptions options;
202
203 msize = ntohs (message->size);
204 if ( (msize < sizeof (struct SearchMessage)) ||
205 (0 != (msize - sizeof (struct SearchMessage)) % sizeof (GNUNET_HashCode)) )
206 {
207 GNUNET_break (0);
208 GNUNET_SERVER_receive_done (client,
209 GNUNET_SYSERR);
210 return;
211 }
212 GNUNET_STATISTICS_update (stats,
213 gettext_noop ("# client searches received"),
214 1,
215 GNUNET_NO);
216 sc = (msize - sizeof (struct SearchMessage)) / sizeof (GNUNET_HashCode);
217 sm = (const struct SearchMessage*) message;
218 type = ntohl (sm->type);
219#if DEBUG_FS
220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
221 "Received request for `%s' of type %u from local client\n",
222 GNUNET_h2s (&sm->query),
223 (unsigned int) type);
224#endif
225 lc = GSF_local_client_lookup_ (client);
226
227
228 /* detect duplicate KBLOCK requests */
229 if ( (type == GNUNET_BLOCK_TYPE_FS_KBLOCK) ||
230 (type == GNUNET_BLOCK_TYPE_FS_NBLOCK) ||
231 (type == GNUNET_BLOCK_TYPE_ANY) )
232 {
233 cr = lc->cr_head;
234 while ( (cl != NULL) &&
235 ( (0 != memcmp (GSF_pending_request_get_query_ (cr->pr),
236 &sm->query,
237 sizeof (GNUNET_HashCode))) ||
238 (GSF_pending_request_get_type_ (cr->pr) != type) ) )
239 cr = cr->next;
240 if (crl != NULL)
241 {
242#if DEBUG_FS
243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
244 "Have existing request, merging content-seen lists.\n");
245#endif
246 GSF_pending_request_update_ (cr->pr,
247 &sm[1],
248 sc);
249 GNUNET_STATISTICS_update (stats,
250 gettext_noop ("# client searches updated (merged content seen list)"),
251 1,
252 GNUNET_NO);
253 GNUNET_SERVER_receive_done (client,
254 GNUNET_OK);
255 return;
256 }
257 }
258
259 GNUNET_STATISTICS_update (stats,
260 gettext_noop ("# client searches active"),
261 1,
262 GNUNET_NO);
263 cr = GNUNET_malloc (sizeof (struct ClientRequest));
264 cr->lc = lc;
265 GNUNET_CONTAINER_DLL_insert (lc->cr_head,
266 lc->cr_tail,
267 cr);
268 options = GSF_PRO_LOCAL_REQUEST;
269 if (0 != (1 & ntohl (sm->options)))
270 options |= GSF_PRO_LOCAL_ONLY;
271 cr->pr = GSF_pending_request_create (options,
272
273 type,
274 &sm->query,
275 (type == GNUNET_BLOCK_TYPE_SBLOCK)
276 ? &sm->target /* namespace */
277 : NULL,
278 (0 != memcmp (&sm->target,
279 &all_zeros,
280 sizeof (GNUNET_HashCode)))
281 ? &sm->target,
282 : NULL,
283 NULL /* bf */, 0 /* mingle */,
284 ntohl (sm->anonymity_level),
285 0 /* priority */,
286 &sm[1], sc,
287 &client_response_handler,
288 cr);
289 // FIXME: start local processing and/or P2P processing?
290}
291
292
293/**
294 * Transmit the given message by copying it to the target buffer
295 * "buf". "buf" will be NULL and "size" zero if the socket was closed
296 * for writing in the meantime. In that case, do nothing
297 * (the disconnect or shutdown handler will take care of the rest).
298 * If we were able to transmit messages and there are still more
299 * pending, ask core again for further calls to this function.
300 *
301 * @param cls closure, pointer to the 'struct GSF_LocalClient'
302 * @param size number of bytes available in buf
303 * @param buf where the callee should write the message
304 * @return number of bytes written to buf
305 */
306static size_t
307transmit_to_client (void *cls,
308 size_t size,
309 void *buf)
310{
311 struct GSF_LocalClient *lc = cls;
312 char *cbuf = buf;
313 struct ClientResponse *res;
314 size_t msize;
315
316 cl->th = NULL;
317 if (NULL == buf)
318 return 0;
319 msize = 0;
320 while ( (NULL != (res = lc->res_head) ) &&
321 (res->msize <= size) )
322 {
323 memcpy (&cbuf[msize], &res[1], res->msize);
324 msize += res->msize;
325 size -= res->msize;
326 GNUNET_CONTAINER_DLL_remove (cl->res_head,
327 cl->res_tail,
328 res);
329 GNUNET_free (res);
330 }
331 if (NULL != res)
332 lc->th = GNUNET_SERVER_notify_transmit_ready (lc->client,
333 res->msize,
334 GNUNET_TIME_UNIT_FOREVER_REL,
335 &transmit_to_client,
336 lc);
337 return msize;
338}
339
340
341/**
342 * Transmit a message to the given local client as soon as possible.
343 * If the client disconnects before transmission, the message is
344 * simply discarded.
345 *
346 * @param lc recipient
347 * @param msg message to transmit to client
348 */
349void
350GSF_local_client_transmit_ (struct GSF_LocalClient *lc,
351 const struct GNUNET_MessageHeader *msg)
352{
353 struct ClientResponse *res;
354 size_t msize;
355
356 msize = ntohs (msg->size);
357 res = GNUNET_malloc (sizeof (struct ClientResponse) + msize);
358 res->lc = lc;
359 res->msize = msize;
360 GNUNET_CONTAINER_DLL_insert_tail (lc->res_head,
361 lc->res_tail,
362 res);
363 if (NULL == lc->tc)
364 lc->tc = GNUNET_CLIENT_notify_transmit_ready (lc->client,
365 msize,
366 GNUNET_TIME_UNIT_FOREVER_REL,
367 GNUNET_NO,
368 &transmit_to_client,
369 lc);
370}
371
372
373/**
374 * A client disconnected from us. Tear down the local client
375 * record.
376 *
377 * @param cls unused
378 * @param client handle of the client
379 */
380void
381GSF_client_disconnect_handler_ (void *cls,
382 const struct GNUNET_SERVER_Client *client)
383{
384 struct GSF_LocalClient *pos;
385 struct DisconnectCallback *dc;
386 struct ClientRequest *cr;
387 struct ClientResponse *res;
388
389 pos = client_head;
390 while ( (pos != NULL) &&
391 (pos->client != client) )
392 pos = pos->next;
393 if (pos == NULL)
394 return pos;
395 while (NULL != (cr = pos->cr_head))
396 {
397 GNUNET_CONTAINER_DLL_remove (pos->cr_head,
398 pos->cr_tail,
399 cr);
400 GSF_pending_request_cancel_ (cr->pr);
401 GNUNET_free (cr);
402 }
403 while (NULL != (res = pos->res_head))
404 {
405 GNUNET_CONTAINER_DLL_remove (pos->res_head,
406 pos->res_tail,
407 res);
408 GNUNET_free (res);
409 }
410 if (pos->th != NULL)
411 {
412 GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
413 pos->th = NULL;
414 }
415 GSF_handle_local_client_disconnect_ (pos);
416 GNUNET_free (pos);
417}
418
419
420/* 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,
67 67
68 68
69/** 69/**
70 * A local client disconnected from us. Tear down the local client 70 * A client disconnected from us. Tear down the local client record.
71 * record.
72 * 71 *
73 * @param cls unused 72 * @param cls unused
74 * @param client handle of the client 73 * @param client handle of the client
75 */ 74 */
76void 75void
77GSF_local_client_disconnect_handler_ (void *cls, 76GSF_client_disconnect_handler_ (void *cls,
78 const struct GNUNET_SERVER_Client *client); 77 const struct GNUNET_SERVER_Client *client);
79 78
80 79
81
82/**
83 * Signature of function called on a local client
84 *
85 * @param cls closure
86 * @param lc local client handle
87 */
88typedef int (*GSF_LocalClientIterator)(void *cls,
89 struct GSF_LocalClient *lc);
90
91
92
93/**
94 * Register callback to invoke on local client disconnect.
95 *
96 * @param lc client to monitor
97 * @param it function to call on disconnect
98 * @param it_cls closure for it
99 */
100void
101GSF_local_client_register_disconnect_callback_ (struct GSF_LocalClient *lc,
102 GSF_LocalClientIterator it,
103 void *it_cls);
104
105
106/**
107 * Register callback to invoke on local client disconnect.
108 *
109 * @param lc client to stop monitoring
110 * @param it function to no longer call on disconnect
111 * @param it_cls closure for it
112 */
113void
114GSF_local_client_unregister_disconnect_callback_ (struct GSF_LocalClient *lc,
115 GSF_PendingRequestIterator it,
116 void *it_cls);
117
118#endif 80#endif
119/* end of gnunet-service-fs_lc.h */ 81/* 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 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009, 2010 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -120,6 +120,40 @@ GSF_pending_request_create_ (enum GSF_PendingRequestOptions options,
120 120
121 121
122/** 122/**
123 * Update a given pending request with additional replies
124 * that have been seen.
125 *
126 * @param pr request to update
127 * @param replies_seen hash codes of replies that we've seen
128 * @param replies_seen_count size of the replies_seen array
129 */
130void
131GSF_pending_request_update_ (struct GSF_PendingRequest *pr,
132 const GNUNET_HashCode *replies_seen,
133 unsigned int replies_seen_count);
134
135
136/**
137 * Get the query for a given pending request.
138 *
139 * @param pr the request
140 * @return pointer to the query (only valid as long as pr is valid)
141 */
142const GNUNET_HashCode *
143GSF_pending_request_get_query_ (const struct GSF_PendingRequest *pr);
144
145
146/**
147 * Get the type of a given pending request.
148 *
149 * @param pr the request
150 * @return query type
151 */
152enum GNUNET_BLOCK_Type
153GSF_pending_request_get_type_ (const struct GSF_PendingRequest *pr);
154
155
156/**
123 * Generate the message corresponding to the given pending request for 157 * Generate the message corresponding to the given pending request for
124 * transmission to other peers (or at least determine its size). 158 * transmission to other peers (or at least determine its size).
125 * 159 *
@@ -167,31 +201,5 @@ GSF_iterate_pending_requests_ (GSF_PendingRequestIterator it,
167 201
168 202
169 203
170/**
171 * Register callback to invoke on request destruction.
172 *
173 * @param pr request to monitor
174 * @param it function to call on destruction
175 * @param it_cls closure for it
176 */
177void
178GSF_pending_request_register_destroy_callback_ (struct GSF_PendingRequest *pr,
179 GSF_PendingRequestIterator it,
180 void *it_cls);
181
182
183/**
184 * Unregister callback to invoke on request destruction.
185 *
186 * @param pr request to stop monitoring
187 * @param it function to no longer call on destruction
188 * @param it_cls closure for it
189 */
190void
191GSF_pending_request_unregister_destroy_callback_ (struct GSF_PendingRequest *pr,
192 GSF_PendingRequestIterator it,
193 void *it_cls);
194
195
196#endif 204#endif
197/* end of gnunet-service-fs_pr.h */ 205/* end of gnunet-service-fs_pr.h */