aboutsummaryrefslogtreecommitdiff
path: root/src/peerinfo/gnunet-peerinfo-gtk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/peerinfo/gnunet-peerinfo-gtk.c')
-rw-r--r--src/peerinfo/gnunet-peerinfo-gtk.c299
1 files changed, 267 insertions, 32 deletions
diff --git a/src/peerinfo/gnunet-peerinfo-gtk.c b/src/peerinfo/gnunet-peerinfo-gtk.c
index 90d501ac..28838b48 100644
--- a/src/peerinfo/gnunet-peerinfo-gtk.c
+++ b/src/peerinfo/gnunet-peerinfo-gtk.c
@@ -25,15 +25,60 @@
25 */ 25 */
26#include "gnunet_gtk.h" 26#include "gnunet_gtk.h"
27#include <gnunet/gnunet_peerinfo_service.h> 27#include <gnunet/gnunet_peerinfo_service.h>
28#include <gnunet/gnunet_transport_service.h>
29#include <gnunet/gnunet_core_service.h>
30#include "gnunet-peerinfo-gtk-flags.h"
31
32
33/**
34 * Information we track for each peer outside of the model.
35 */
36struct PeerInfo
37{
38 /**
39 * Reference to the peer in the view.
40 */
41 GtkTreeRowReference *rr;
42
43 /**
44 * Handle to an active lookup for addresses of this peer, or NULL.
45 */
46 struct GNUNET_TRANSPORT_PeerAddressLookupContext *palc;
47
48 /**
49 * Location where we store all addresses that were found during the 'palc' iteration.
50 */
51 char *palc_accumulator;
52
53 /**
54 * Total number of addresses found.
55 */
56 guint palc_counter;
57
58};
59
28 60
29/** 61/**
30 * Handle to our main loop. 62 * Handle to our main loop.
31 */ 63 */
32static struct GNUNET_GTK_MainLoop *ml; 64static struct GNUNET_GTK_MainLoop *ml;
33 65
66/**
67 * Handle for our notifications from peerinfo about new peers.
68 */
34static struct GNUNET_PEERINFO_NotifyContext *pnc; 69static struct GNUNET_PEERINFO_NotifyContext *pnc;
35 70
36/** 71/**
72 * Handle to core service.
73 */
74static struct GNUNET_CORE_Handle *core;
75
76/**
77 * Map of peer identities to the respective PeerInfo for our view.
78 */
79static struct GNUNET_CONTAINER_MultiHashMap *peer2info;
80
81/**
37 * Should gnunet-peerinfo-gtk start in tray mode? 82 * Should gnunet-peerinfo-gtk start in tray mode?
38 */ 83 */
39static int tray_only; 84static int tray_only;
@@ -48,6 +93,7 @@ get_configuration ()
48 return GNUNET_GTK_main_loop_get_configuration (ml); 93 return GNUNET_GTK_main_loop_get_configuration (ml);
49} 94}
50 95
96
51/** 97/**
52 * Get an object from the main window. 98 * Get an object from the main window.
53 * 99 *
@@ -62,6 +108,35 @@ get_object (const char *name)
62 108
63 109
64/** 110/**
111 * Function called on each entry in the 'peer2info' map
112 * to free the associated path.
113 *
114 * @param cls unused
115 * @param key peer identity
116 * @param value the 'struct PeerInfo'
117 * @return GNUNET_OK (continue to iterate)
118 */
119static int
120free_paths (void *cls,
121 const GNUNET_HashCode *key,
122 void *value)
123{
124 struct PeerInfo *info = value;
125
126 if (NULL != info->palc)
127 {
128 GNUNET_TRANSPORT_peer_address_lookup_cancel (info->palc);
129 info->palc = NULL;
130 GNUNET_free (info->palc_accumulator);
131 info->palc_accumulator = NULL;
132 }
133 gtk_tree_row_reference_free (info->rr);
134 GNUNET_free (info);
135 return GNUNET_OK;
136}
137
138
139/**
65 * Task run on shutdown. 140 * Task run on shutdown.
66 * 141 *
67 * @param cls unused 142 * @param cls unused
@@ -73,6 +148,79 @@ shutdown_task (void *cls,
73{ 148{
74 GNUNET_PEERINFO_notify_cancel (pnc); 149 GNUNET_PEERINFO_notify_cancel (pnc);
75 pnc = NULL; 150 pnc = NULL;
151 if (NULL != core)
152 {
153 GNUNET_CORE_disconnect (core);
154 core = NULL;
155 }
156 GNUNET_CONTAINER_multihashmap_iterate (peer2info,
157 &free_paths,
158 NULL);
159 GNUNET_CONTAINER_multihashmap_destroy (peer2info);
160 peer2info = NULL;
161 GNUNET_PEERINFO_GTK_flags_shutdown ();
162}
163
164
165/**
166 * Function to call with a binary format of an address
167 *
168 * @param cls the 'struct PeerInfo' for which this is a valid address
169 * @param address NULL on error, otherwise 0-terminated printable UTF-8 string
170 */
171static void
172peer_address_cb (void *cls,
173 const char *address)
174{
175 struct PeerInfo *info = cls;
176 char *tmp;
177 GtkListStore *ls;
178 GtkTreeModel *tm;
179 GtkTreeIter iter;
180 GtkTreePath *path;
181 const char *colon;
182 const char *dot;
183 char *country;
184
185 if (NULL == address)
186 {
187 /* last address, store information in model */
188 country = NULL;
189 colon = strstr (info->palc_accumulator, ":");
190 if (NULL != colon)
191 {
192 for (dot = colon - 1; dot != info->palc_accumulator; dot--)
193 if ('.' == *dot)
194 break;
195 if ('.' == *dot)
196 country = GNUNET_strndup (&dot[1], (colon - dot) - 1);
197 }
198 ls = GTK_LIST_STORE (get_object ("GNUNET_PEERINFO_GTK_list_store"));
199 tm = GTK_TREE_MODEL (ls);
200 path = gtk_tree_row_reference_get_path (info->rr);
201 GNUNET_assert (NULL != path);
202 GNUNET_assert (TRUE ==
203 gtk_tree_model_get_iter (tm, &iter, path));
204 gtk_tree_path_free (path);
205 gtk_list_store_set (ls, &iter,
206 1, info->palc_counter,
207 2, country,
208 3, GNUNET_PEERINFO_GTK_get_flag (country),
209 6, &info->palc_accumulator[1],
210 -1);
211 GNUNET_free_non_null (country);
212 info->palc = NULL;
213 GNUNET_free (info->palc_accumulator);
214 info->palc_accumulator = NULL;
215 return;
216 }
217 GNUNET_asprintf (&tmp,
218 "%s|%s",
219 info->palc_accumulator,
220 address);
221 GNUNET_free (info->palc_accumulator);
222 info->palc_accumulator = tmp;
223 info->palc_counter++;
76} 224}
77 225
78 226
@@ -93,46 +241,124 @@ peerinfo_processor (void *cls,
93 GtkListStore *ls; 241 GtkListStore *ls;
94 GtkTreeModel *tm; 242 GtkTreeModel *tm;
95 GtkTreeIter iter; 243 GtkTreeIter iter;
96 int found;
97 gchar *pid;
98 const char *npid; 244 const char *npid;
99 struct GNUNET_CRYPTO_HashAsciiEncoded enc; 245 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
246 struct PeerInfo *info;
247 GtkTreePath *path;
100 248
101 GNUNET_CRYPTO_hash_to_enc (&peer->hashPubKey, &enc);
102 npid = (const char *) &enc;
103 ls = GTK_LIST_STORE (get_object ("GNUNET_PEERINFO_GTK_list_store")); 249 ls = GTK_LIST_STORE (get_object ("GNUNET_PEERINFO_GTK_list_store"));
250 if (NULL == ls)
251 {
252 GNUNET_break (0);
253 return;
254 }
104 tm = GTK_TREE_MODEL (ls); 255 tm = GTK_TREE_MODEL (ls);
105 found = GNUNET_NO; 256 info = GNUNET_CONTAINER_multihashmap_get (peer2info,
106 if (TRUE == gtk_tree_model_get_iter_first (tm, &iter)) 257 &peer->hashPubKey);
107 { 258 if (NULL == info)
108 do
109 { 259 {
110 pid = NULL; 260 GNUNET_CRYPTO_hash_to_enc (&peer->hashPubKey, &enc);
111 gtk_tree_model_get (tm, &iter, 0, &pid, -1); 261 npid = (const char *) &enc;
112 if (pid != NULL) 262 gtk_list_store_append (ls, &iter);
113 { 263 gtk_list_store_set (ls, &iter,
114 if (0 == strcmp (pid, npid)) 264 0, npid,
115 { 265 1, 0 /* number of known addresses */ ,
116 found = GNUNET_YES; 266 2, "" /* country name */ ,
117 g_free (pid); 267 3, NULL /* country flag */ ,
118 break; 268 4, (guint64) 0 /* bandwidth-in */ ,
119 } 269 5, (guint64) 0 /* bandwidth-out */ ,
120 } 270 6, "" /* addresses as strings */,
121 g_free (pid); 271 -1);
272 path = gtk_tree_model_get_path (tm, &iter);
273 info = GNUNET_malloc (sizeof (struct PeerInfo));
274 info->rr = gtk_tree_row_reference_new (tm, path);
275 GNUNET_assert (NULL != info->rr);
276 gtk_tree_path_free (path);
277 GNUNET_CONTAINER_multihashmap_put (peer2info,
278 &peer->hashPubKey,
279 info,
280 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
122 } 281 }
123 while ((found == GNUNET_NO) && 282 if (NULL == info->palc)
124 (TRUE == gtk_tree_model_iter_next (tm, &iter))); 283 {
125 } 284 info->palc_accumulator = GNUNET_strdup ("|");
126 if (found == GNUNET_NO) 285 info->palc_counter = 0;
127 gtk_list_store_append (ls, &iter); 286 info->palc = GNUNET_TRANSPORT_peer_address_lookup (get_configuration(),
287 peer,
288 GNUNET_TIME_UNIT_MINUTES,
289 &peer_address_cb,
290 info);
291 }
292
293}
294
295
296/**
297 * Function called after GNUNET_CORE_connect has succeeded
298 * (or failed for good). Note that the private key of the
299 * peer is intentionally not exposed here; if you need it,
300 * your process should try to read the private key file
301 * directly (which should work if you are authorized...).
302 *
303 * @param cls closure
304 * @param server handle to the server, NULL if we failed
305 * @param my_identity ID of this peer, NULL if we failed
306 * @param publicKey public key of this peer, NULL if we failed
307 */
308static void
309init_cb (void *cls,
310 struct GNUNET_CORE_Handle * server,
311 const struct GNUNET_PeerIdentity *
312 my_identity,
313 const struct
314 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded
315 * publicKey)
316{
317 /* FIXME: should probably do something to my 'own' entry
318 in the peerinfo list to make it stand out */
319}
320
321
322/**
323 * Method called whenever a given peer has a status change.
324 *
325 * @param cls closure
326 * @param peer peer identity this notification is about
327 * @param timeout absolute time when this peer will time out
328 * unless we see some further activity from it
329 * @param bandwidth_in available amount of inbound bandwidth
330 * @param bandwidth_out available amount of outbound bandwidth
331 * @param atsi performance data for the connection
332 */
333static void
334status_cb (void *cls,
335 const struct GNUNET_PeerIdentity * peer,
336 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
337 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
338 struct GNUNET_TIME_Absolute timeout,
339 const struct GNUNET_TRANSPORT_ATS_Information* atsi)
340{
341 struct PeerInfo *info;
342 GtkListStore *ls;
343 GtkTreeModel *tm;
344 GtkTreeIter iter;
345 GtkTreePath *path;
346
347 info = GNUNET_CONTAINER_multihashmap_get (peer2info,
348 &peer->hashPubKey);
349 if (NULL == info)
350 return; /* should rarely happen... */
351 ls = GTK_LIST_STORE (get_object ("GNUNET_PEERINFO_GTK_list_store"));
352 tm = GTK_TREE_MODEL (ls);
353 path = gtk_tree_row_reference_get_path (info->rr);
354 GNUNET_assert (NULL != path);
355 GNUNET_assert (TRUE ==
356 gtk_tree_model_get_iter (tm, &iter, path));
357 gtk_tree_path_free (path);
128 gtk_list_store_set (ls, &iter, 358 gtk_list_store_set (ls, &iter,
129 0, npid, 359 4, (guint64) ntohl (bandwidth_in.value__),
130 1, 0 /* number of known addresses */ , 360 5, (guint64) ntohl (bandwidth_out.value__),
131 2, "" /* country name */ , 361 -1);
132 3, NULL /* country flag */ ,
133 4, 0 /* bandwidth */ ,
134 5, "" /* addresses as strings */,
135 -1);
136} 362}
137 363
138 364
@@ -160,6 +386,7 @@ run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
160 386
161 GNUNET_GTK_set_icon_search_path (); 387 GNUNET_GTK_set_icon_search_path ();
162 GNUNET_GTK_setup_nls (); 388 GNUNET_GTK_setup_nls ();
389 peer2info = GNUNET_CONTAINER_multihashmap_create (256);
163 pnc = GNUNET_PEERINFO_notify (get_configuration(), 390 pnc = GNUNET_PEERINFO_notify (get_configuration(),
164 &peerinfo_processor, NULL); 391 &peerinfo_processor, NULL);
165 if (pnc == NULL) 392 if (pnc == NULL)
@@ -167,6 +394,14 @@ run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
167 fprintf (stderr, _("Failed to initialize communication with peerinfo service!\n")); 394 fprintf (stderr, _("Failed to initialize communication with peerinfo service!\n"));
168 exit (1); 395 exit (1);
169 } 396 }
397 core = GNUNET_CORE_connect (get_configuration(),
398 1, NULL,
399 &init_cb,
400 NULL, NULL,
401 &status_cb,
402 NULL, GNUNET_NO,
403 NULL, GNUNET_NO,
404 NULL);
170 405
171 /* setup main window */ 406 /* setup main window */
172 main_window = 407 main_window =