aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-service-fs_pr.h
blob: abdb0c9f61765c85a8dbd4a6e6705b3c19f471ff (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
/*
     This file is part of GNUnet.
     Copyright (C) 2009, 2010, 2011 GNUnet e.V.

     GNUnet is free software: you can redistribute it and/or modify it
     under the terms of the GNU Affero General Public License as published
     by the Free Software Foundation, either version 3 of the License,
     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
     Affero General Public License for more details.
    
     You should have received a copy of the GNU Affero General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

     SPDX-License-Identifier: AGPL3.0-or-later
*/

/**
 * @file fs/gnunet-service-fs_pr.h
 * @brief API to handle pending requests
 * @author Christian Grothoff
 */
#ifndef GNUNET_SERVICE_FS_PR_H
#define GNUNET_SERVICE_FS_PR_H

#include "gnunet-service-fs.h"


/**
 * Options for pending requests (bits to be ORed).
 */
enum GSF_PendingRequestOptions
{

  /**
   * No special options (P2P-default).
   */
  GSF_PRO_DEFAULTS = 0,

  /**
   * Request must only be processed locally.
   */
  GSF_PRO_LOCAL_ONLY = 1,

  /**
   * Request must only be forwarded (no routing)
   */
  GSF_PRO_FORWARD_ONLY = 2,

  /**
   * Request persists indefinitely (no expiration).
   */
  GSF_PRO_REQUEST_NEVER_EXPIRES = 4,

  /**
   * Request is allowed to refresh bloomfilter and change mingle value.
   */
  GSF_PRO_BLOOMFILTER_FULL_REFRESH = 8,

  /**
   * Request priority is allowed to be exceeded.
   */
  GSF_PRO_PRIORITY_UNLIMITED = 16,

  /**
   * Option mask for typical local requests.
   */
  GSF_PRO_LOCAL_REQUEST =
      (GSF_PRO_BLOOMFILTER_FULL_REFRESH | GSF_PRO_PRIORITY_UNLIMITED | GSF_PRO_REQUEST_NEVER_EXPIRES)
};


/**
 * Public data (in the sense of not encapsulated within
 * 'gnunet-service-fs_pr', not in the sense of network-wide
 * known) associated with each pending request.
 */
struct GSF_PendingRequestData
{

  /**
   * Primary query hash for this request.
   */
  struct GNUNET_HashCode query;

  /**
   * Identity of a peer hosting the content, otherwise NULl.
   * Allocated after struct only if needed. Do not free!
   */
  const struct GNUNET_PeerIdentity *target;

  /**
   * Fields for the plan module to track a DLL with the request.
   */
  struct GSF_PendingRequestPlanBijection *pr_head;

  /**
   * Fields for the plan module to track a DLL with the request.
   */
  struct GSF_PendingRequestPlanBijection *pr_tail;

  /**
   * Current TTL for the request.
   */
  struct GNUNET_TIME_Absolute ttl;

  /**
   * When did we start with the request.
   */
  struct GNUNET_TIME_Absolute start_time;

  /**
   * Desired anonymity level.
   */
  uint32_t anonymity_level;

  /**
   * Priority that this request (still) has for us.
   */
  uint32_t priority;

  /**
   * Priority that this request (originally) had for us.
   */
  uint32_t original_priority;

  /**
   * Counter for how often this request has been transmitted (estimate,
   * because we might have the same request pending for multiple clients,
   * and of course because a transmission may have failed at a lower
   * layer).
   */
  uint32_t num_transmissions;

  /**
   * How much respect did we (in total) offer for this request so far (estimate,
   * because we might have the same request pending for multiple clients,
   * and of course because a transmission may have failed at a lower
   * layer).
   */
  uint32_t respect_offered;

  /**
   * Options for the request.
   */
  enum GSF_PendingRequestOptions options;

  /**
   * Type of the requested block.
   */
  enum GNUNET_BLOCK_Type type;

  /**
   * Number of results we have found for this request so far.
   */
  unsigned int results_found;

  /**
   * Has this request been started yet (local/p2p operations)?  Or are
   * we still constructing it?
   */
  int has_started;

};


/**
 * 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 the last time we've tried to get 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
 */
typedef void
(*GSF_PendingRequestReplyHandler) (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);


/**
 * Create a new pending request.
 *
 * @param options request options
 * @param type type of the block that is being requested
 * @param query key for the lookup
 * @param target preferred target for the request, NULL for none
 * @param bf_data raw data for bloom filter for known replies, can be NULL
 * @param bf_size number of bytes in bf_data
 * @param mingle mingle value for bf
 * @param anonymity_level desired anonymity level
 * @param priority maximum outgoing cummulative request priority to use
 * @param ttl current time-to-live for the request
 * @param sender_pid peer ID to use for the sender when forwarding, 0 for none;
 *                   reference counter is taken over by this function
 * @param origin_pid peer ID of origin of query (do not loop back)
 * @param replies_seen hash codes of known local replies
 * @param replies_seen_count size of the 'replies_seen' array
 * @param rh handle to call when we get a reply
 * @param rh_cls closure for rh
 * @return handle for the new pending request
 */
struct GSF_PendingRequest *
GSF_pending_request_create_ (enum GSF_PendingRequestOptions options,
                             enum GNUNET_BLOCK_Type type,
                             const struct GNUNET_HashCode *query,
                             const struct GNUNET_PeerIdentity *target,
                             const char *bf_data,
                             size_t bf_size,
                             uint32_t mingle,
                             uint32_t anonymity_level,
                             uint32_t priority,
                             int32_t ttl,
                             GNUNET_PEER_Id sender_pid,
                             GNUNET_PEER_Id origin_pid,
                             const struct GNUNET_HashCode *replies_seen,
                             unsigned int replies_seen_count,
                             GSF_PendingRequestReplyHandler rh,
                             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 @a replies_seen array
 */
void
GSF_pending_request_update_ (struct GSF_PendingRequest *pr,
                             const struct GNUNET_HashCode *replies_seen,
                             unsigned int replies_seen_count);


/**
 * Obtain the public data associated with a pending request
 *
 * @param pr pending request
 * @return associated public data
 */
struct GSF_PendingRequestData *
GSF_pending_request_get_data_ (struct GSF_PendingRequest *pr);


/**
 * Check if the given request is still active.
 *
 * @param pr pending request
 * @return #GNUNET_YES if the request is still active
 */
int
GSF_pending_request_test_active_ (struct GSF_PendingRequest *pr);


/**
 * Test if two pending requests are compatible (would generate
 * the same query modulo filters and should thus be processed
 * jointly).
 *
 * @param pra a pending request
 * @param prb another pending request
 * @return #GNUNET_OK if the requests are compatible
 */
int
GSF_pending_request_is_compatible_ (struct GSF_PendingRequest *pra,
                                    struct GSF_PendingRequest *prb);


/**
 * Generate the message corresponding to the given pending request for
 * transmission to other peers.
 *
 * @param pr request to generate the message for
 * @return envelope with the request message
 */
struct GNUNET_MQ_Envelope *
GSF_pending_request_get_message_ (struct GSF_PendingRequest *pr);


/**
 * Explicitly cancel a pending request.
 *
 * @param pr request to cancel
 * @param full_cleanup fully purge the request
 */
void
GSF_pending_request_cancel_ (struct GSF_PendingRequest *pr,
                             int full_cleanup);


/**
 * Signature of function called on each request.
 * (Note: 'subtype' of GNUNET_CONTAINER_HashMapIterator).
 *
 * @param cls closure
 * @param key query for the request
 * @param pr handle to the pending request
 * @return #GNUNET_YES to continue to iterate
 */
typedef int
(*GSF_PendingRequestIterator) (void *cls,
                               const struct GNUNET_HashCode *key,
                               struct GSF_PendingRequest *pr);


/**
 * Iterate over all pending requests.
 *
 * @param it function to call for each request
 * @param cls closure for it
 */
void
GSF_iterate_pending_requests_ (GSF_PendingRequestIterator it,
                               void *cls);


/**
 * Handle P2P "CONTENT" message.  Checks that the message is
 * well-formed and then checks if there are any pending requests for
 * this content and possibly passes it on (to local clients or other
 * peers).  Does NOT perform migration (content caching at this peer).
 *
 * @param cls the other peer involved (sender)
 * @param put the actual message
 */
void
handle_p2p_put (void *cls,
		const struct PutMessage *put);


/**
 * Consider looking up the data in the DHT (anonymity-level permitting).
 *
 * @param pr the pending request to process
 */
void
GSF_dht_lookup_ (struct GSF_PendingRequest *pr);


/**
 * Consider downloading via cadet (if possible)
 *
 * @param pr the pending request to process
 */
void
GSF_cadet_lookup_ (struct GSF_PendingRequest *pr);


/**
 * Function to be called after we're done processing
 * replies from the local lookup.
 *
 * @param cls closure
 * @param pr the pending request we were processing
 * @param result final datastore lookup result
 */
typedef void
(*GSF_LocalLookupContinuation) (void *cls,
                                struct GSF_PendingRequest *pr,
                                enum GNUNET_BLOCK_EvaluationResult result);


/**
 * Look up the request in the local datastore.
 *
 * @param pr the pending request to process
 * @param cont function to call at the end
 * @param cont_cls closure for @a cont
 */
void
GSF_local_lookup_ (struct GSF_PendingRequest *pr,
                   GSF_LocalLookupContinuation cont,
                   void *cont_cls);


/**
 * Is the given target a legitimate peer for forwarding the given request?
 *
 * @param pr request
 * @param target
 * @return #GNUNET_YES if this request could be forwarded to the given peer
 */
int
GSF_pending_request_test_target_ (struct GSF_PendingRequest *pr,
                                  const struct GNUNET_PeerIdentity *target);



/**
 * Setup the subsystem.
 */
void
GSF_pending_request_init_ (void);


/**
 * Shutdown the subsystem.
 */
void
GSF_pending_request_done_ (void);


#endif
/* end of gnunet-service-fs_pr.h */