aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-12-10 14:56:34 +0100
committerChristian Grothoff <christian@grothoff.org>2018-12-10 14:56:34 +0100
commit08e22453a438c8a3f6135632a6ce39239b47d9f5 (patch)
tree0e2c5ddb717cbd1b0111b4f7650fe9022135bd2b
parent5a1d7b406639cb12640c9906ca38c3c08f912a85 (diff)
downloadgnunet-08e22453a438c8a3f6135632a6ce39239b47d9f5.tar.gz
gnunet-08e22453a438c8a3f6135632a6ce39239b47d9f5.zip
more work on simple plugin
-rw-r--r--src/ats/plugin_ats2_simple.c271
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 */
41struct 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 */
41struct Hello 47struct 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 */
88struct 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 */
263struct Peer *
264lookup_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 */
279static int
280peer_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 */
300static void
301watch_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 */
325static struct Peer *
326peer_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 */
359static void
360peer_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 */
226static void 395static 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 */
261static void 433static void
262simple_preference_del (void *cls, 434simple_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