diff options
Diffstat (limited to 'src/peerinfo/gnunet-peerinfo-gtk.c')
-rw-r--r-- | src/peerinfo/gnunet-peerinfo-gtk.c | 299 |
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 | */ | ||
36 | struct 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 | */ |
32 | static struct GNUNET_GTK_MainLoop *ml; | 64 | static struct GNUNET_GTK_MainLoop *ml; |
33 | 65 | ||
66 | /** | ||
67 | * Handle for our notifications from peerinfo about new peers. | ||
68 | */ | ||
34 | static struct GNUNET_PEERINFO_NotifyContext *pnc; | 69 | static struct GNUNET_PEERINFO_NotifyContext *pnc; |
35 | 70 | ||
36 | /** | 71 | /** |
72 | * Handle to core service. | ||
73 | */ | ||
74 | static struct GNUNET_CORE_Handle *core; | ||
75 | |||
76 | /** | ||
77 | * Map of peer identities to the respective PeerInfo for our view. | ||
78 | */ | ||
79 | static 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 | */ |
39 | static int tray_only; | 84 | static 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 | */ | ||
119 | static int | ||
120 | free_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 | */ | ||
171 | static void | ||
172 | peer_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 | */ | ||
308 | static void | ||
309 | init_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 | */ | ||
333 | static void | ||
334 | status_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 = |