diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-12-10 14:56:34 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-12-10 14:56:34 +0100 |
commit | 08e22453a438c8a3f6135632a6ce39239b47d9f5 (patch) | |
tree | 0e2c5ddb717cbd1b0111b4f7650fe9022135bd2b /src/ats | |
parent | 5a1d7b406639cb12640c9906ca38c3c08f912a85 (diff) | |
download | gnunet-08e22453a438c8a3f6135632a6ce39239b47d9f5.tar.gz gnunet-08e22453a438c8a3f6135632a6ce39239b47d9f5.zip |
more work on simple plugin
Diffstat (limited to 'src/ats')
-rw-r--r-- | src/ats/plugin_ats2_simple.c | 271 |
1 files changed, 247 insertions, 24 deletions
diff --git a/src/ats/plugin_ats2_simple.c b/src/ats/plugin_ats2_simple.c index 689524ba4..55234f1bc 100644 --- a/src/ats/plugin_ats2_simple.c +++ b/src/ats/plugin_ats2_simple.c | |||
@@ -23,7 +23,7 @@ | |||
23 | * | 23 | * |
24 | * TODO: | 24 | * TODO: |
25 | * - subscribe to PEERSTORE when short on HELLOs (given application preferences!) | 25 | * - subscribe to PEERSTORE when short on HELLOs (given application preferences!) |
26 | * - keep track of HELLOs and when we tried them last => re-suggest | 26 | * - keep track of HELLOs and when we tried them last => re-suggest |
27 | * - sum up preferences per peer, keep totals! => PeerMap pid -> [preferences + sessions + addrs!] | 27 | * - sum up preferences per peer, keep totals! => PeerMap pid -> [preferences + sessions + addrs!] |
28 | * - sum up preferences overall, keep global sum => starting point for "proportional" | 28 | * - sum up preferences overall, keep global sum => starting point for "proportional" |
29 | * - store DLL of available sessions per peer | 29 | * - store DLL of available sessions per peer |
@@ -36,6 +36,12 @@ | |||
36 | 36 | ||
37 | 37 | ||
38 | /** | 38 | /** |
39 | * A handle for the proportional solver | ||
40 | */ | ||
41 | struct SimpleHandle; | ||
42 | |||
43 | |||
44 | /** | ||
39 | * Entry in list of addresses we could try per peer. | 45 | * Entry in list of addresses we could try per peer. |
40 | */ | 46 | */ |
41 | struct Hello | 47 | struct Hello |
@@ -50,7 +56,7 @@ struct Hello | |||
50 | * Kept in a DLL. | 56 | * Kept in a DLL. |
51 | */ | 57 | */ |
52 | struct Hello *prev; | 58 | struct Hello *prev; |
53 | 59 | ||
54 | /** | 60 | /** |
55 | * The address we could try. | 61 | * The address we could try. |
56 | */ | 62 | */ |
@@ -76,6 +82,13 @@ struct Hello | |||
76 | 82 | ||
77 | 83 | ||
78 | /** | 84 | /** |
85 | * Information about preferences and sessions we track | ||
86 | * per peer. | ||
87 | */ | ||
88 | struct Peer; | ||
89 | |||
90 | |||
91 | /** | ||
79 | * Internal representation of a session by the plugin. | 92 | * Internal representation of a session by the plugin. |
80 | * (If desired, plugin may just use NULL.) | 93 | * (If desired, plugin may just use NULL.) |
81 | */ | 94 | */ |
@@ -91,7 +104,7 @@ struct GNUNET_ATS_SessionHandle | |||
91 | * Kept in DLL per peer. | 104 | * Kept in DLL per peer. |
92 | */ | 105 | */ |
93 | struct GNUNET_ATS_SessionHandle *prev; | 106 | struct GNUNET_ATS_SessionHandle *prev; |
94 | 107 | ||
95 | /** | 108 | /** |
96 | * The session in the main ATS service. | 109 | * The session in the main ATS service. |
97 | */ | 110 | */ |
@@ -106,7 +119,12 @@ struct GNUNET_ATS_SessionHandle | |||
106 | * Hello matching this session, or NULL for none. | 119 | * Hello matching this session, or NULL for none. |
107 | */ | 120 | */ |
108 | struct Hello *hello; | 121 | struct Hello *hello; |
109 | 122 | ||
123 | /** | ||
124 | * Peer this session is for. | ||
125 | */ | ||
126 | struct Peer *peer; | ||
127 | |||
110 | /** | 128 | /** |
111 | * Address used by this session (largely for debugging). | 129 | * Address used by this session (largely for debugging). |
112 | */ | 130 | */ |
@@ -143,13 +161,28 @@ struct Peer | |||
143 | struct GNUNET_ATS_SessionHandle *sh_tail; | 161 | struct GNUNET_ATS_SessionHandle *sh_tail; |
144 | 162 | ||
145 | /** | 163 | /** |
164 | * Kept in a DLL. | ||
165 | */ | ||
166 | struct Hello *h_head; | ||
167 | |||
168 | /** | ||
169 | * Kept in a DLL. | ||
170 | */ | ||
171 | struct Hello *h_tail; | ||
172 | |||
173 | /** | ||
174 | * The handle for the proportional solver | ||
175 | */ | ||
176 | struct SimpleHandle *h; | ||
177 | |||
178 | /** | ||
146 | * Which peer is this for? | 179 | * Which peer is this for? |
147 | */ | 180 | */ |
148 | struct GNUNET_PeerIdentity pid; | 181 | struct GNUNET_PeerIdentity pid; |
149 | 182 | ||
150 | /** | 183 | /** |
151 | * Array where we sum up the bandwidth requests received indexed | 184 | * Array where we sum up the bandwidth requests received indexed |
152 | * by preference kind (see `struct GNUNET_MQ_PreferenceKind`) | 185 | * by preference kind (see `enum GNUNET_MQ_PreferenceKind`) |
153 | */ | 186 | */ |
154 | uint64_t bw_by_pk[GNUNET_MQ_PREFERENCE_COUNT]; | 187 | uint64_t bw_by_pk[GNUNET_MQ_PREFERENCE_COUNT]; |
155 | 188 | ||
@@ -162,8 +195,8 @@ struct Peer | |||
162 | /** | 195 | /** |
163 | * Task used to try again to suggest an address for this peer. | 196 | * Task used to try again to suggest an address for this peer. |
164 | */ | 197 | */ |
165 | struct GNUNET_SCHEDULER_TaskHandle *task; | 198 | struct GNUNET_SCHEDULER_Task *task; |
166 | 199 | ||
167 | }; | 200 | }; |
168 | 201 | ||
169 | 202 | ||
@@ -216,11 +249,147 @@ struct SimpleHandle | |||
216 | * Handle to the peerstore service. | 249 | * Handle to the peerstore service. |
217 | */ | 250 | */ |
218 | struct GNUNET_PEERSTORE_Handle *ps; | 251 | struct GNUNET_PEERSTORE_Handle *ps; |
219 | 252 | ||
220 | }; | 253 | }; |
221 | 254 | ||
222 | 255 | ||
223 | /** | 256 | /** |
257 | * Lookup peer in the peers map. | ||
258 | * | ||
259 | * @param h handle to look up in | ||
260 | * @param pid peer identity to look up by | ||
261 | * @return NULL for not found | ||
262 | */ | ||
263 | struct Peer * | ||
264 | lookup_peer (struct SimpleHandle *h, | ||
265 | const struct GNUNET_PeerIdentity *pid) | ||
266 | { | ||
267 | return GNUNET_CONTAINER_multipeermap_get (h->peers, | ||
268 | pid); | ||
269 | } | ||
270 | |||
271 | |||
272 | /** | ||
273 | * Check if there is _any_ interesting information left we | ||
274 | * store about the peer in @a p. | ||
275 | * | ||
276 | * @param p peer to test if we can drop the data structure | ||
277 | * @return #GNUNET_YES if no information is left in @a p | ||
278 | */ | ||
279 | static int | ||
280 | peer_test_dead (struct Peer *p) | ||
281 | { | ||
282 | for (enum GNUNET_MQ_PreferenceKind pk = 0; | ||
283 | pk < GNUNET_MQ_PREFERENCE_COUNT; | ||
284 | pk++) | ||
285 | if (0 != p->bw_by_pk[pk]) | ||
286 | return GNUNET_NO; | ||
287 | if (NULL != p->sh_head) | ||
288 | return GNUNET_NO; | ||
289 | return GNUNET_YES; | ||
290 | } | ||
291 | |||
292 | |||
293 | /** | ||
294 | * Function called by PEERSTORE for each matching record. | ||
295 | * | ||
296 | * @param cls closure with a `struct Peer` | ||
297 | * @param record peerstore record information | ||
298 | * @param emsg error message, or NULL if no errors | ||
299 | */ | ||
300 | static void | ||
301 | watch_cb (void *cls, | ||
302 | const struct GNUNET_PEERSTORE_Record *record, | ||
303 | const char *emsg) | ||
304 | { | ||
305 | struct Peer *p = cls; | ||
306 | |||
307 | // FIXME: process hello! | ||
308 | // check for expiration | ||
309 | // (add to p's doubly-linked list) | ||
310 | |||
311 | if (NULL == p->task) | ||
312 | { | ||
313 | // start suggestion task! | ||
314 | } | ||
315 | } | ||
316 | |||
317 | |||
318 | /** | ||
319 | * Find or add peer if necessary. | ||
320 | * | ||
321 | * @param h our plugin handle | ||
322 | * @param pid the peer identity to add/look for | ||
323 | * @return a peer handle | ||
324 | */ | ||
325 | static struct Peer * | ||
326 | peer_add (struct SimpleHandle *h, | ||
327 | const struct GNUNET_PeerIdentity *pid) | ||
328 | { | ||
329 | struct Peer *p = lookup_peer (h, | ||
330 | pid); | ||
331 | |||
332 | if (NULL != p) | ||
333 | return p; | ||
334 | p = GNUNET_new (struct Peer); | ||
335 | p->h = h; | ||
336 | p->pid = *pid; | ||
337 | p->wc = GNUNET_PEERSTORE_watch (h->ps, | ||
338 | "transport", | ||
339 | &p->pid, | ||
340 | "HELLO" /* key */, | ||
341 | &watch_cb, | ||
342 | p); | ||
343 | GNUNET_assert (GNUNET_YES == | ||
344 | GNUNET_CONTAINER_multipeermap_put (h->peers, | ||
345 | &p->pid, | ||
346 | p, | ||
347 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
348 | |||
349 | return p; | ||
350 | } | ||
351 | |||
352 | |||
353 | /** | ||
354 | * Free the entry (and associated tasks) of peer @a p. | ||
355 | * Note that @a p must be dead already (see #peer_test_dead()). | ||
356 | * | ||
357 | * @param p the peer to free | ||
358 | */ | ||
359 | static void | ||
360 | peer_free (struct Peer *p) | ||
361 | { | ||
362 | struct SimpleHandle *h = p->h; | ||
363 | struct Hello *hello; | ||
364 | |||
365 | GNUNET_assert (NULL == p->sh_head); | ||
366 | while (NULL != (hello = p->h_head)) | ||
367 | { | ||
368 | GNUNET_CONTAINER_DLL_remove (p->h_head, | ||
369 | p->h_tail, | ||
370 | hello); | ||
371 | GNUNET_assert (NULL == hello->sh); | ||
372 | GNUNET_free (hello); | ||
373 | } | ||
374 | if (NULL != p->task) | ||
375 | { | ||
376 | GNUNET_SCHEDULER_cancel (p->task); | ||
377 | p->task = NULL; | ||
378 | } | ||
379 | if (NULL != p->wc) | ||
380 | { | ||
381 | GNUNET_PEERSTORE_watch_cancel (p->wc); | ||
382 | p->wc = NULL; | ||
383 | } | ||
384 | GNUNET_assert (GNUNET_YES == | ||
385 | GNUNET_CONTAINER_multipeermap_remove (h->peers, | ||
386 | &p->pid, | ||
387 | p)); | ||
388 | GNUNET_free (p); | ||
389 | } | ||
390 | |||
391 | |||
392 | /** | ||
224 | * The world changed, recalculate our allocations. | 393 | * The world changed, recalculate our allocations. |
225 | */ | 394 | */ |
226 | static void | 395 | static void |
@@ -243,9 +412,12 @@ simple_preference_add (void *cls, | |||
243 | const struct GNUNET_ATS_Preference *pref) | 412 | const struct GNUNET_ATS_Preference *pref) |
244 | { | 413 | { |
245 | struct SimpleHandle *h = cls; | 414 | struct SimpleHandle *h = cls; |
246 | // Setup peer if necessary (-> including HELLO triggers!) | 415 | struct Peer *p = peer_add (h, |
247 | // add pref to bw_by_pk | 416 | &pref->peer); |
248 | // trigger update | 417 | |
418 | GNUNET_assert (pref->pk < GNUNET_MQ_PREFERENCE_COUNT); | ||
419 | p->bw_by_pk[pref->pk] += ntohl (pref->bw.value__); | ||
420 | update (h); | ||
249 | return NULL; | 421 | return NULL; |
250 | } | 422 | } |
251 | 423 | ||
@@ -254,20 +426,26 @@ simple_preference_add (void *cls, | |||
254 | * The plugin should end respecting a preference. | 426 | * The plugin should end respecting a preference. |
255 | * | 427 | * |
256 | * @param cls the closure | 428 | * @param cls the closure |
257 | * @param ph whatever @e preference_add returned | 429 | * @param ph whatever @e preference_add returned |
258 | * @param pref the preference to delete | 430 | * @param pref the preference to delete |
259 | * @return plugin's internal representation, or NULL | 431 | * @return plugin's internal representation, or NULL |
260 | */ | 432 | */ |
261 | static void | 433 | static void |
262 | simple_preference_del (void *cls, | 434 | simple_preference_del (void *cls, |
263 | struct GNUNET_ATS_PreferenceHandle *ph, | 435 | struct GNUNET_ATS_PreferenceHandle *ph, |
264 | const struct GNUNET_ATS_Preference *pref) | 436 | const struct GNUNET_ATS_Preference *pref) |
265 | { | 437 | { |
266 | struct SimpleHandle *h = cls; | 438 | struct SimpleHandle *h = cls; |
267 | // find peer | 439 | struct Peer *p = lookup_peer (h, |
268 | // subtract pref from bw_by_pk | 440 | &pref->peer); |
269 | // remove peer if otherwise dead | 441 | |
270 | // trigger update | 442 | GNUNET_assert (NULL != p); |
443 | GNUNET_assert (pref->pk < GNUNET_MQ_PREFERENCE_COUNT); | ||
444 | p->bw_by_pk[pref->pk] -= ntohl (pref->bw.value__); | ||
445 | if ( (0 == p->bw_by_pk[pref->pk]) && | ||
446 | (GNUNET_YES == peer_test_dead (p)) ) | ||
447 | peer_free (p); | ||
448 | update (h); | ||
271 | } | 449 | } |
272 | 450 | ||
273 | 451 | ||
@@ -286,11 +464,47 @@ simple_session_add (void *cls, | |||
286 | const char *address) | 464 | const char *address) |
287 | { | 465 | { |
288 | struct SimpleHandle *h = cls; | 466 | struct SimpleHandle *h = cls; |
467 | struct Peer *p = peer_add (h, | ||
468 | &data->peer); | ||
469 | struct Hello *hello; | ||
470 | size_t alen; | ||
471 | struct GNUNET_ATS_SessionHandle *sh; | ||
289 | 472 | ||
290 | // find or add peer if necessary | 473 | /* setup session handle */ |
291 | // setup session | 474 | if (NULL == address) |
292 | // match HELLO | 475 | alen = 0; |
293 | // trigger update | 476 | else |
477 | alen = strlen (address) + 1; | ||
478 | sh = GNUNET_malloc (sizeof (struct GNUNET_ATS_SessionHandle) + alen); | ||
479 | sh->peer = p; | ||
480 | sh->session = data->session; | ||
481 | sh->data = data; | ||
482 | if (NULL == address) | ||
483 | { | ||
484 | sh->address = NULL; | ||
485 | } | ||
486 | else | ||
487 | { | ||
488 | memcpy (&sh[1], | ||
489 | address, | ||
490 | alen); | ||
491 | sh->address = (const char *) &sh[1]; | ||
492 | } | ||
493 | GNUNET_CONTAINER_DLL_insert (p->sh_head, | ||
494 | p->sh_tail, | ||
495 | sh); | ||
496 | /* match HELLO */ | ||
497 | hello = p->h_head; | ||
498 | while ( (NULL != hello) && | ||
499 | (0 != strcmp (address, | ||
500 | hello->address)) ) | ||
501 | hello = hello->next; | ||
502 | if (NULL != hello) | ||
503 | { | ||
504 | hello->sh = sh; | ||
505 | sh->hello = hello; | ||
506 | } | ||
507 | update (h); | ||
294 | return NULL; | 508 | return NULL; |
295 | } | 509 | } |
296 | 510 | ||
@@ -309,7 +523,9 @@ simple_session_update (void *cls, | |||
309 | const struct GNUNET_ATS_SessionData *data) | 523 | const struct GNUNET_ATS_SessionData *data) |
310 | { | 524 | { |
311 | struct SimpleHandle *h = cls; | 525 | struct SimpleHandle *h = cls; |
312 | // trigger update | 526 | |
527 | sh->data = data; /* this statement should not really do anything... */ | ||
528 | update (h); | ||
313 | } | 529 | } |
314 | 530 | ||
315 | 531 | ||
@@ -326,9 +542,16 @@ simple_session_del (void *cls, | |||
326 | const struct GNUNET_ATS_SessionData *data) | 542 | const struct GNUNET_ATS_SessionData *data) |
327 | { | 543 | { |
328 | struct SimpleHandle *h = cls; | 544 | struct SimpleHandle *h = cls; |
329 | // tear down session | 545 | struct Peer *p = sh->peer; |
546 | |||
547 | // FIXME: tear down session | ||
330 | // del peer if otherwise dead | 548 | // del peer if otherwise dead |
331 | // trigger update | 549 | |
550 | |||
551 | if ( (NULL == p->sh_head) && | ||
552 | (GNUNET_YES == peer_test_dead (p)) ) | ||
553 | peer_free (p); | ||
554 | update (h); | ||
332 | } | 555 | } |
333 | 556 | ||
334 | 557 | ||