aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-04-18 20:23:40 +0000
committerChristian Grothoff <christian@grothoff.org>2010-04-18 20:23:40 +0000
commit541caf3dec54aaee621fed935e667f9ee423ef31 (patch)
tree6f80958e68541ce071bc557bbfc168644963c473
parente8bc962b2ed43e194ba124537573da236786e82c (diff)
downloadgnunet-541caf3dec54aaee621fed935e667f9ee423ef31.tar.gz
gnunet-541caf3dec54aaee621fed935e667f9ee423ef31.zip
towards fixing blacklisting APIs and implementation
-rw-r--r--TODO16
-rw-r--r--src/core/core.h13
-rw-r--r--src/core/core_api.c28
-rw-r--r--src/core/gnunet-service-core.c14
-rw-r--r--src/core/test_core_api.c6
-rw-r--r--src/core/test_core_api_start_only.c6
-rw-r--r--src/fs/gnunet-service-fs.c1
-rw-r--r--src/hostlist/gnunet-daemon-hostlist.c2
-rw-r--r--src/include/gnunet_core_service.h4
-rw-r--r--src/include/gnunet_protocols.h15
-rw-r--r--src/include/gnunet_transport_service.h97
-rw-r--r--src/testing/test_testing_topology.c3
-rw-r--r--src/testing/testing.c4
-rw-r--r--src/topology/gnunet-daemon-topology.c278
-rw-r--r--src/transport/Makefile.am3
-rw-r--r--src/transport/gnunet-service-transport_blacklist.c142
-rw-r--r--src/transport/gnunet-service-transport_blacklist.h35
-rw-r--r--src/transport/transport.h17
-rw-r--r--src/transport/transport_api_blacklist.c385
19 files changed, 347 insertions, 722 deletions
diff --git a/TODO b/TODO
index 2054d5df1..d4bed6bc1 100644
--- a/TODO
+++ b/TODO
@@ -2,20 +2,10 @@
2* PEERINFO: [CG] 2* PEERINFO: [CG]
3 - trust: need *fast* way to check/update trust in peers 3 - trust: need *fast* way to check/update trust in peers
4 (async peerinfo would not be right; certainly not with the current API) 4 (async peerinfo would not be right; certainly not with the current API)
5* TRANSPORT: [CG]
6 - need to implement and test new blacklisting code (server-side only, client API exists)
5* TOPOLOGY: [CG] 7* TOPOLOGY: [CG]
6 - If the topology daemon crashes, peers that were put on the 8 - needs more testing (especially F2F topology) -- need transport blacklisting to be implemented first!
7 blacklist with transport will never be removed from it (until
8 transport service dies); we should use the blacklist notification
9 API to learn about the exact set of blacklisted peers at all times
10 (FIXME: the transport_api implementation of blacklisting
11 also does not work nicely for this since it won't let us know about
12 disconnect-reconnect events and the implicit whitelisting
13 that might happen here; that's not so bad since we will
14 re-blacklist on pre-connect attempts anyway, so this is
15 a minor issue; OTOH, we might want to be more explicit about
16 allowing/forbidding connects on pre-connect to avoid
17 entering connect attempts to just be blacklisted shortly afterwards).
18 - needs more testing (especially F2F topology)
19* FS: [CG] 9* FS: [CG]
20 - support recursive download even if filename is NULL and we hence 10 - support recursive download even if filename is NULL and we hence
21 do not generate files on disk (use temp_filename) 11 do not generate files on disk (use temp_filename)
diff --git a/src/core/core.h b/src/core/core.h
index 45d138140..f91995734 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -43,13 +43,12 @@
43 * transmitted to the client. 43 * transmitted to the client.
44 */ 44 */
45#define GNUNET_CORE_OPTION_NOTHING 0 45#define GNUNET_CORE_OPTION_NOTHING 0
46#define GNUNET_CORE_OPTION_SEND_PRE_CONNECT 1 46#define GNUNET_CORE_OPTION_SEND_CONNECT 1
47#define GNUNET_CORE_OPTION_SEND_CONNECT 2 47#define GNUNET_CORE_OPTION_SEND_DISCONNECT 2
48#define GNUNET_CORE_OPTION_SEND_DISCONNECT 4 48#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 4
49#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 8 49#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 8
50#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 16 50#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 16
51#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32 51#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 32
52#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 64
53 52
54 53
55/** 54/**
diff --git a/src/core/core_api.c b/src/core/core_api.c
index 4672c7843..42e8f1c06 100644
--- a/src/core/core_api.c
+++ b/src/core/core_api.c
@@ -56,12 +56,6 @@ struct GNUNET_CORE_Handle
56 GNUNET_CORE_StartupCallback init; 56 GNUNET_CORE_StartupCallback init;
57 57
58 /** 58 /**
59 * Function to call whenever we're notified about a peer connecting
60 * (pre-connects, no session key exchange yet).
61 */
62 GNUNET_CORE_ConnectEventHandler pre_connects;
63
64 /**
65 * Function to call whenever we're notified about a peer connecting. 59 * Function to call whenever we're notified about a peer connecting.
66 */ 60 */
67 GNUNET_CORE_ConnectEventHandler connects; 61 GNUNET_CORE_ConnectEventHandler connects;
@@ -406,23 +400,6 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg)
406#endif 400#endif
407 switch (ntohs (msg->type)) 401 switch (ntohs (msg->type))
408 { 402 {
409 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT:
410 if (NULL == h->pre_connects)
411 {
412 GNUNET_break (0);
413 break;
414 }
415 if (msize != sizeof (struct ConnectNotifyMessage))
416 {
417 GNUNET_break (0);
418 break;
419 }
420 cnm = (const struct ConnectNotifyMessage *) msg;
421 h->pre_connects (h->cls,
422 &cnm->peer,
423 GNUNET_TIME_relative_ntoh (cnm->latency),
424 ntohl (cnm->distance));
425 break;
426 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT: 403 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT:
427 if (NULL == h->connects) 404 if (NULL == h->connects)
428 { 405 {
@@ -662,8 +639,6 @@ transmit_start (void *cls, size_t size, void *buf)
662 init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT); 639 init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT);
663 init->header.size = htons (msize); 640 init->header.size = htons (msize);
664 opt = GNUNET_CORE_OPTION_NOTHING; 641 opt = GNUNET_CORE_OPTION_NOTHING;
665 if (h->pre_connects != NULL)
666 opt |= GNUNET_CORE_OPTION_SEND_PRE_CONNECT;
667 if (h->connects != NULL) 642 if (h->connects != NULL)
668 opt |= GNUNET_CORE_OPTION_SEND_CONNECT; 643 opt |= GNUNET_CORE_OPTION_SEND_CONNECT;
669 if (h->disconnects != NULL) 644 if (h->disconnects != NULL)
@@ -705,7 +680,6 @@ transmit_start (void *cls, size_t size, void *buf)
705 * @param cls closure for the various callbacks that follow (including handlers in the handlers array) 680 * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
706 * @param init callback to call on timeout or once we have successfully 681 * @param init callback to call on timeout or once we have successfully
707 * connected to the core service; note that timeout is only meaningful if init is not NULL 682 * connected to the core service; note that timeout is only meaningful if init is not NULL
708 * @param pre_connects function to call on peer pre-connect (no session key yet), can be NULL
709 * @param connects function to call on peer connect, can be NULL 683 * @param connects function to call on peer connect, can be NULL
710 * @param disconnects function to call on peer disconnect / timeout, can be NULL 684 * @param disconnects function to call on peer disconnect / timeout, can be NULL
711 * @param inbound_notify function to call for all inbound messages, can be NULL 685 * @param inbound_notify function to call for all inbound messages, can be NULL
@@ -726,7 +700,6 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
726 struct GNUNET_TIME_Relative timeout, 700 struct GNUNET_TIME_Relative timeout,
727 void *cls, 701 void *cls,
728 GNUNET_CORE_StartupCallback init, 702 GNUNET_CORE_StartupCallback init,
729 GNUNET_CORE_ConnectEventHandler pre_connects,
730 GNUNET_CORE_ConnectEventHandler connects, 703 GNUNET_CORE_ConnectEventHandler connects,
731 GNUNET_CORE_DisconnectEventHandler disconnects, 704 GNUNET_CORE_DisconnectEventHandler disconnects,
732 GNUNET_CORE_MessageCallback inbound_notify, 705 GNUNET_CORE_MessageCallback inbound_notify,
@@ -742,7 +715,6 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
742 h->cfg = cfg; 715 h->cfg = cfg;
743 h->cls = cls; 716 h->cls = cls;
744 h->init = init; 717 h->init = init;
745 h->pre_connects = pre_connects;
746 h->connects = connects; 718 h->connects = connects;
747 h->disconnects = disconnects; 719 h->disconnects = disconnects;
748 h->inbound_notify = inbound_notify; 720 h->inbound_notify = inbound_notify;
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index 044b7496e..bad6f05d3 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -3450,13 +3450,6 @@ handle_transport_receive (void *cls,
3450 (n->status != PEER_STATE_KEY_CONFIRMED)) 3450 (n->status != PEER_STATE_KEY_CONFIRMED))
3451 { 3451 {
3452 GNUNET_break_op (0); 3452 GNUNET_break_op (0);
3453 /* blacklist briefly (?); might help recover (?) */
3454 GNUNET_TRANSPORT_blacklist (sched, cfg,
3455 &n->peer,
3456 GNUNET_TIME_UNIT_SECONDS,
3457 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
3458 5),
3459 NULL, NULL);
3460 return; 3453 return;
3461 } 3454 }
3462 handle_encrypted_message (n, (const struct EncryptedMessage *) message); 3455 handle_encrypted_message (n, (const struct EncryptedMessage *) message);
@@ -3626,7 +3619,6 @@ handle_transport_notify_connect (void *cls,
3626 unsigned int distance) 3619 unsigned int distance)
3627{ 3620{
3628 struct Neighbour *n; 3621 struct Neighbour *n;
3629 struct ConnectNotifyMessage cnm;
3630 3622
3631 if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity))) 3623 if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
3632 { 3624 {
@@ -3665,12 +3657,6 @@ handle_transport_notify_connect (void *cls,
3665 "Received connection from `%4s'.\n", 3657 "Received connection from `%4s'.\n",
3666 GNUNET_i2s (&n->peer)); 3658 GNUNET_i2s (&n->peer));
3667#endif 3659#endif
3668 cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
3669 cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT);
3670 cnm.distance = htonl (n->last_distance);
3671 cnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
3672 cnm.peer = *peer;
3673 send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_PRE_CONNECT);
3674 GNUNET_TRANSPORT_set_quota (transport, 3660 GNUNET_TRANSPORT_set_quota (transport,
3675 &n->peer, 3661 &n->peer,
3676 n->bw_in, 3662 n->bw_in,
diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c
index 78d6b7fe1..6b8387461 100644
--- a/src/core/test_core_api.c
+++ b/src/core/test_core_api.c
@@ -229,8 +229,7 @@ init_notify (void *cls,
229 p2.cfg, 229 p2.cfg,
230 TIMEOUT, 230 TIMEOUT,
231 &p2, 231 &p2,
232 &init_notify, 232 &init_notify,
233 NULL,
234 &connect_notify, 233 &connect_notify,
235 &disconnect_notify, 234 &disconnect_notify,
236 &inbound_notify, 235 &inbound_notify,
@@ -325,8 +324,7 @@ run (void *cls,
325 TIMEOUT, 324 TIMEOUT,
326 &p1, 325 &p1,
327 &init_notify, 326 &init_notify,
328 NULL, 327 &connect_notify,
329 &connect_notify,
330 &disconnect_notify, 328 &disconnect_notify,
331 &inbound_notify, 329 &inbound_notify,
332 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); 330 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);
diff --git a/src/core/test_core_api_start_only.c b/src/core/test_core_api_start_only.c
index e8bfdd4e5..86eff056c 100644
--- a/src/core/test_core_api_start_only.c
+++ b/src/core/test_core_api_start_only.c
@@ -130,8 +130,7 @@ init_notify (void *cls,
130 p2.cfg, 130 p2.cfg,
131 TIMEOUT, 131 TIMEOUT,
132 &p2, 132 &p2,
133 &init_notify, 133 &init_notify,
134 NULL,
135 &connect_notify, 134 &connect_notify,
136 &disconnect_notify, 135 &disconnect_notify,
137 &inbound_notify, 136 &inbound_notify,
@@ -185,8 +184,7 @@ run (void *cls,
185 TIMEOUT, 184 TIMEOUT,
186 &p1, 185 &p1,
187 &init_notify, 186 &init_notify,
188 NULL, 187 &connect_notify,
189 &connect_notify,
190 &disconnect_notify, 188 &disconnect_notify,
191 &inbound_notify, 189 &inbound_notify,
192 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); 190 GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index faf436bc0..0d1d3d9e4 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -3025,7 +3025,6 @@ main_init (struct GNUNET_SCHEDULER_Handle *s,
3025 GNUNET_TIME_UNIT_FOREVER_REL, 3025 GNUNET_TIME_UNIT_FOREVER_REL,
3026 NULL, 3026 NULL,
3027 NULL, 3027 NULL,
3028 NULL,
3029 &peer_connect_handler, 3028 &peer_connect_handler,
3030 &peer_disconnect_handler, 3029 &peer_disconnect_handler,
3031 NULL, GNUNET_NO, 3030 NULL, GNUNET_NO,
diff --git a/src/hostlist/gnunet-daemon-hostlist.c b/src/hostlist/gnunet-daemon-hostlist.c
index c06ee5f56..ca0f11cae 100644
--- a/src/hostlist/gnunet-daemon-hostlist.c
+++ b/src/hostlist/gnunet-daemon-hostlist.c
@@ -296,7 +296,7 @@ run (void *cls,
296 GNUNET_TIME_UNIT_FOREVER_REL, 296 GNUNET_TIME_UNIT_FOREVER_REL,
297 NULL, 297 NULL,
298 &core_init, 298 &core_init,
299 NULL, &connect_handler, &disconnect_handler, 299 &connect_handler, &disconnect_handler,
300 NULL, GNUNET_NO, 300 NULL, GNUNET_NO,
301 NULL, GNUNET_NO, 301 NULL, GNUNET_NO,
302 learning? learn_handlers : no_learn_handlers); 302 learning? learn_handlers : no_learn_handlers);
diff --git a/src/include/gnunet_core_service.h b/src/include/gnunet_core_service.h
index 47b8d6f98..b7dc6f7da 100644
--- a/src/include/gnunet_core_service.h
+++ b/src/include/gnunet_core_service.h
@@ -51,7 +51,7 @@ struct GNUNET_CORE_Handle;
51 51
52 52
53/** 53/**
54 * Method called whenever a given peer either connects. 54 * Method called whenever a given peer connects.
55 * 55 *
56 * @param cls closure 56 * @param cls closure
57 * @param peer peer identity this notification is about 57 * @param peer peer identity this notification is about
@@ -164,7 +164,6 @@ typedef void
164 * @param cls closure for the various callbacks that follow (including handlers in the handlers array) 164 * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
165 * @param init callback to call on timeout or once we have successfully 165 * @param init callback to call on timeout or once we have successfully
166 * connected to the core service; note that timeout is only meaningful if init is not NULL 166 * connected to the core service; note that timeout is only meaningful if init is not NULL
167 * @param pre_connects function to call on peer pre-connect (no session key yet), can be NULL
168 * @param connects function to call on peer connect, can be NULL 167 * @param connects function to call on peer connect, can be NULL
169 * @param disconnects function to call on peer disconnect / timeout, can be NULL 168 * @param disconnects function to call on peer disconnect / timeout, can be NULL
170 * @param inbound_notify function to call for all inbound messages, can be NULL 169 * @param inbound_notify function to call for all inbound messages, can be NULL
@@ -200,7 +199,6 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
200 struct GNUNET_TIME_Relative timeout, 199 struct GNUNET_TIME_Relative timeout,
201 void *cls, 200 void *cls,
202 GNUNET_CORE_StartupCallback init, 201 GNUNET_CORE_StartupCallback init,
203 GNUNET_CORE_ConnectEventHandler pre_connects,
204 GNUNET_CORE_ConnectEventHandler connects, 202 GNUNET_CORE_ConnectEventHandler connects,
205 GNUNET_CORE_DisconnectEventHandler disconnects, 203 GNUNET_CORE_DisconnectEventHandler disconnects,
206 GNUNET_CORE_MessageCallback inbound_notify, 204 GNUNET_CORE_MessageCallback inbound_notify,
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 602137f98..d992c9fb7 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -174,16 +174,19 @@ extern "C"
174#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY 28 174#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY 28
175 175
176/** 176/**
177 * Change in blacklisting status of a peer. 177 * Register a client that wants to do blacklisting.
178 */ 178 */
179#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST 29 179#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT 29
180 180
181/** 181/**
182 * Request to transport to notify us about any blacklisting status 182 * Query to a blacklisting client (is this peer blacklisted)?
183 * changes on this connection (and to immediately send all
184 * active blacklist entries).
185 */ 183 */
186#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_NOTIFY 30 184#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY 30
185
186/**
187 * Reply from blacklisting client (answer to blacklist query).
188 */
189#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY 31
187 190
188/** 191/**
189 * Transport PING message 192 * Transport PING message
diff --git a/src/include/gnunet_transport_service.h b/src/include/gnunet_transport_service.h
index 711ebb599..57bdecd17 100644
--- a/src/include/gnunet_transport_service.h
+++ b/src/include/gnunet_transport_service.h
@@ -299,99 +299,52 @@ GNUNET_TRANSPORT_address_lookup (struct GNUNET_SCHEDULER_Handle *sched,
299 299
300 300
301/** 301/**
302 * Handle for blacklisting requests. 302 * Handle for blacklisting peers.
303 */ 303 */
304struct GNUNET_TRANSPORT_BlacklistRequest; 304struct GNUNET_TRANSPORT_Blacklist;
305 305
306 306
307/** 307/**
308 * Blacklist a peer for a given period of time. All connections 308 * Function that decides if a connection is acceptable or not.
309 * (inbound and outbound) to a peer that is blacklisted will be
310 * dropped (as soon as we learn who the connection is for). A second
311 * call to this function for the same peer overrides previous
312 * blacklisting requests.
313 *
314 * @param sched scheduler to use
315 * @param cfg configuration to use
316 * @param peer identity of peer to blacklist
317 * @param duration how long to blacklist, use GNUNET_TIME_UNIT_ZERO to
318 * re-enable connections
319 * @param timeout when should this operation (trying to establish the
320 * blacklisting time out)
321 * @param cont continuation to call once the request has been processed
322 * @param cont_cls closure for cont
323 * @return NULL on error, otherwise handle for cancellation
324 */
325struct GNUNET_TRANSPORT_BlacklistRequest *
326GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched,
327 const struct GNUNET_CONFIGURATION_Handle *cfg,
328 const struct GNUNET_PeerIdentity *peer,
329 struct GNUNET_TIME_Relative duration,
330 struct GNUNET_TIME_Relative timeout,
331 GNUNET_SCHEDULER_Task cont,
332 void *cont_cls);
333
334
335/**
336 * Abort transmitting the blacklist request. Note that this function
337 * is NOT for removing a peer from the blacklist (for that, call
338 * GNUNET_TRANSPORT_blacklist with a duration of zero). This function
339 * is only for aborting the transmission of a blacklist request
340 * (i.e. because of shutdown).
341 *
342 * @param br handle of the request that is to be cancelled
343 */
344void
345GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_BlacklistRequest * br);
346
347
348/**
349 * Handle for blacklist notifications.
350 */
351struct GNUNET_TRANSPORT_BlacklistNotification;
352
353
354/**
355 * Signature of function called whenever the blacklist status of
356 * a peer changes. This includes changes to the duration of the
357 * blacklist status as well as the expiration of an existing
358 * blacklist status.
359 * 309 *
360 * @param cls closure 310 * @param cls closure
361 * @param peer identity of peer with the change 311 * @param pid peer to approve or disapproave
362 * @param until GNUNET_TIME_UNIT_ZERO_ABS if the peer is no 312 * @return GNUNET_OK if the connection is allowed
363 * longer blacklisted, otherwise the time at
364 * which the current blacklisting will expire
365 */ 313 */
366typedef void (*GNUNET_TRANSPORT_BlacklistCallback)(void *cls, 314typedef int (*GNUNET_TRANSPORT_BlacklistCallback)(void *cls,
367 const struct GNUNET_PeerIdentity *peer, 315 const struct GNUNET_PeerIdentity *pid);
368 struct GNUNET_TIME_Absolute until);
369 316
370 317
371/** 318/**
372 * Call a function whenever a peer's blacklisting status changes. 319 * Install a blacklist callback. The service will be queried for all
320 * existing connections as well as any fresh connections to check if
321 * they are permitted. If the blacklisting callback is unregistered,
322 * all hosts that were denied in the past will automatically be
323 * whitelisted again. Cancelling the blacklist handle is also the
324 * only way to re-enable connections from peers that were previously
325 * blacklisted.
373 * 326 *
374 * @param sched scheduler to use 327 * @param sched scheduler to use
375 * @param cfg configuration to use 328 * @param cfg configuration to use
376 * @param bc function to call on status changes 329 * @param cb callback to invoke to check if connections are allowed
377 * @param bc_cls closure for bc 330 * @param cb_cls closure for cb
378 * @return NULL on error, otherwise handle for cancellation 331 * @return NULL on error, otherwise handle for cancellation
379 */ 332 */
380struct GNUNET_TRANSPORT_BlacklistNotification * 333struct GNUNET_TRANSPORT_Blacklist *
381GNUNET_TRANSPORT_blacklist_notify (struct GNUNET_SCHEDULER_Handle *sched, 334GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched,
382 const struct GNUNET_CONFIGURATION_Handle *cfg, 335 const struct GNUNET_CONFIGURATION_Handle *cfg,
383 GNUNET_TRANSPORT_BlacklistCallback bc, 336 GNUNET_TRANSPORT_BlacklistCallback cb,
384 void *bc_cls); 337 void *cb_cls);
385 338
386 339
387/** 340/**
388 * Stop calling the notification callback associated with 341 * Abort the blacklist. Note that this function is the only way for
389 * the given blacklist notification. 342 * removing a peer from the blacklist.
390 * 343 *
391 * @param bn handle of the request that is to be cancelled 344 * @param br handle of the request that is to be cancelled
392 */ 345 */
393void 346void
394GNUNET_TRANSPORT_blacklist_notify_cancel (struct GNUNET_TRANSPORT_BlacklistNotification * bn); 347GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_Blacklist *br);
395 348
396 349
397 350
diff --git a/src/testing/test_testing_topology.c b/src/testing/test_testing_topology.c
index 7f5411fc4..4c7fc01ba 100644
--- a/src/testing/test_testing_topology.c
+++ b/src/testing/test_testing_topology.c
@@ -392,8 +392,7 @@ setup_handlers ()
392 temp_daemon->cfg, 392 temp_daemon->cfg,
393 TIMEOUT, 393 TIMEOUT,
394 new_connection, 394 new_connection,
395 &init_notify, 395 &init_notify,
396 NULL,
397 NULL, 396 NULL,
398 NULL, 397 NULL,
399 NULL, 398 NULL,
diff --git a/src/testing/testing.c b/src/testing/testing.c
index 2b9b560fa..eae5076e0 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -265,7 +265,7 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
265 ARM_START_WAIT, 265 ARM_START_WAIT,
266 d, 266 d,
267 &testing_init, 267 &testing_init,
268 NULL, NULL, NULL, 268 NULL, NULL,
269 NULL, GNUNET_NO, 269 NULL, GNUNET_NO,
270 NULL, GNUNET_NO, no_handlers); 270 NULL, GNUNET_NO, no_handlers);
271 break; 271 break;
@@ -904,7 +904,7 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
904 timeout, 904 timeout,
905 ctx, 905 ctx,
906 NULL, 906 NULL,
907 NULL, &connect_notify, NULL, 907 &connect_notify, NULL,
908 NULL, GNUNET_NO, 908 NULL, GNUNET_NO,
909 NULL, GNUNET_NO, no_handlers); 909 NULL, GNUNET_NO, no_handlers);
910 if (ctx->d1core == NULL) 910 if (ctx->d1core == NULL)
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c
index b175d82ae..0aca503c1 100644
--- a/src/topology/gnunet-daemon-topology.c
+++ b/src/topology/gnunet-daemon-topology.c
@@ -106,12 +106,6 @@ struct Peer
106 struct GNUNET_CONTAINER_BloomFilter *filter; 106 struct GNUNET_CONTAINER_BloomFilter *filter;
107 107
108 /** 108 /**
109 * Our request handle for *whitelisting* this peer (NULL if
110 * no whitelisting request is pending).
111 */
112 struct GNUNET_TRANSPORT_BlacklistRequest *wh;
113
114 /**
115 * Until what time should we not try to connect again 109 * Until what time should we not try to connect again
116 * to this peer? 110 * to this peer?
117 */ 111 */
@@ -153,39 +147,6 @@ struct Peer
153 */ 147 */
154 int is_connected; 148 int is_connected;
155 149
156 /**
157 * Are we currently blocking this peer (via blacklist)?
158 */
159 int is_blocked;
160
161};
162
163
164/**
165 * Entry in linked list of active 'disconnect' requests that we have issued.
166 */
167struct DisconnectList
168{
169 /**
170 * This is a doubly-linked list.
171 */
172 struct DisconnectList *next;
173
174 /**
175 * This is a doubly-linked list.
176 */
177 struct DisconnectList *prev;
178
179 /**
180 * Our request handle.
181 */
182 struct GNUNET_TRANSPORT_BlacklistRequest *rh;
183
184 /**
185 * Peer we tried to disconnect.
186 */
187 struct GNUNET_PeerIdentity peer;
188
189}; 150};
190 151
191 152
@@ -233,6 +194,11 @@ static struct GNUNET_CONTAINER_MultiHashMap *peers;
233static struct GNUNET_STATISTICS_Handle *stats; 194static struct GNUNET_STATISTICS_Handle *stats;
234 195
235/** 196/**
197 * Blacklist (NULL if we have none).
198 */
199static struct GNUNET_TRANSPORT_Blacklist *blacklist;
200
201/**
236 * Flag to disallow non-friend connections (pure F2F mode). 202 * Flag to disallow non-friend connections (pure F2F mode).
237 */ 203 */
238static int friends_only; 204static int friends_only;
@@ -263,119 +229,31 @@ static unsigned int friend_count;
263 */ 229 */
264static int autoconnect; 230static int autoconnect;
265 231
266/**
267 * Head of doubly-linked list of active 'disconnect' requests that we have issued.
268 */
269static struct DisconnectList *disconnect_head;
270
271/**
272 * Head of doubly-linked list of active 'disconnect' requests that we have issued.
273 */
274static struct DisconnectList *disconnect_tail;
275
276 232
277/** 233/**
278 * Function called once our request to 'disconnect' a peer 234 * Function that decides if a connection is acceptable or not.
279 * has completed. 235 * If we have a blacklist, only friends are allowed, so the check
236 * is rather simple.
280 * 237 *
281 * @param cls our 'struct DisconnectList' 238 * @param cls closure
282 * @param tc unused 239 * @param pid peer to approve or disapproave
240 * @return GNUNET_OK if the connection is allowed
283 */ 241 */
284static void 242static int
285disconnect_done (void *cls, 243blacklist_check (void *cls,
286 const struct GNUNET_SCHEDULER_TaskContext *tc) 244 const struct GNUNET_PeerIdentity *pid)
287{ 245{
288 struct DisconnectList *dl = cls; 246 struct Peer *pos;
289 247
248 pos = GNUNET_CONTAINER_multihashmap_get (peers, &pid->hashPubKey);
249 if ( (pos != NULL) &&
250 (pos->is_friend == GNUNET_YES) )
251 return GNUNET_OK;
290 GNUNET_STATISTICS_update (stats, 252 GNUNET_STATISTICS_update (stats,
291 gettext_noop ("# peers blacklisted"), 253 gettext_noop ("# peers blacklisted"),
292 1, 254 1,
293 GNUNET_NO); 255 GNUNET_NO);
294 GNUNET_CONTAINER_DLL_remove (disconnect_head, 256 return GNUNET_SYSERR;
295 disconnect_tail,
296 dl);
297 GNUNET_free (dl);
298}
299
300
301/**
302 * Force a disconnect from the specified peer.
303 *
304 * @param pl peer to disconnect
305 */
306static void
307force_disconnect (struct Peer *pl)
308{
309 const struct GNUNET_PeerIdentity *peer = &pl->pid;
310 struct DisconnectList *dl;
311
312 if (NULL != pl->wh)
313 {
314 GNUNET_TRANSPORT_blacklist_cancel (pl->wh);
315 pl->wh = NULL;
316 }
317 pl->is_blocked = GNUNET_YES;
318 dl = GNUNET_malloc (sizeof (struct DisconnectList));
319 dl->peer = *peer;
320 GNUNET_CONTAINER_DLL_insert (disconnect_head,
321 disconnect_tail,
322 dl);
323 dl->rh = GNUNET_TRANSPORT_blacklist (sched, cfg,
324 peer,
325 GNUNET_TIME_UNIT_FOREVER_REL,
326 GNUNET_TIME_UNIT_FOREVER_REL,
327 &disconnect_done,
328 dl);
329}
330
331
332
333/**
334 * Function called once our request to 'whitelist' a peer
335 * has completed.
336 *
337 * @param cls our 'struct Peer'
338 * @param tc unused
339 */
340static void
341whitelist_done (void *cls,
342 const struct GNUNET_SCHEDULER_TaskContext *tc)
343{
344 struct Peer *pl = cls;
345
346 pl->wh = NULL;
347 GNUNET_STATISTICS_update (stats,
348 gettext_noop ("# peers blacklisted"),
349 -1,
350 GNUNET_NO);
351}
352
353
354/**
355 * Whitelist the given peer (if it was blacklisted before).
356 *
357 * @param cls closure (not used)
358 * @param pid identity of the peer
359 * @param value peer to free
360 * @return GNUNET_YES (always: continue to iterate)
361 */
362static int
363whitelist_peer (void *cls,
364 const GNUNET_HashCode *pid,
365 void *value)
366{
367 struct Peer *pl = value;
368
369 if (! pl->is_blocked)
370 return GNUNET_YES;
371 pl->wh = GNUNET_TRANSPORT_blacklist (sched, cfg,
372 &pl->pid,
373 GNUNET_TIME_UNIT_ZERO,
374 GNUNET_TIME_UNIT_FOREVER_REL,
375 &whitelist_done,
376 pl);
377 pl->is_blocked = GNUNET_NO;
378 return GNUNET_YES;
379} 257}
380 258
381 259
@@ -386,22 +264,11 @@ whitelist_peer (void *cls,
386static void 264static void
387whitelist_peers () 265whitelist_peers ()
388{ 266{
389 struct DisconnectList *dl; 267 if (blacklist != NULL)
390
391 /* first, cancel all blacklisting requests */
392 while (NULL != (dl = disconnect_head))
393 { 268 {
394 GNUNET_CONTAINER_DLL_remove (disconnect_head, 269 GNUNET_TRANSPORT_blacklist_cancel (blacklist);
395 disconnect_tail, 270 blacklist = NULL;
396 dl);
397 GNUNET_TRANSPORT_blacklist_cancel (dl->rh);
398 GNUNET_free (dl);
399 } 271 }
400 /* then, specifically whitelist all peers that we
401 know to have blacklisted */
402 GNUNET_CONTAINER_multihashmap_iterate (peers,
403 &whitelist_peer,
404 NULL);
405} 272}
406 273
407 274
@@ -477,8 +344,6 @@ free_peer (void *cls,
477 pos)); 344 pos));
478 if (pos->hello_req != NULL) 345 if (pos->hello_req != NULL)
479 GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req); 346 GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req);
480 if (pos->wh != NULL)
481 GNUNET_TRANSPORT_blacklist_cancel (pos->wh);
482 if (pos->connect_req != NULL) 347 if (pos->connect_req != NULL)
483 GNUNET_CORE_peer_request_connect_cancel (pos->connect_req); 348 GNUNET_CORE_peer_request_connect_cancel (pos->connect_req);
484 if (pos->hello_delay_task != GNUNET_SCHEDULER_NO_TASK) 349 if (pos->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
@@ -521,8 +386,6 @@ attempt_connect (struct Peer *pos)
521 return; 386 return;
522 if (GNUNET_OK != is_connection_allowed (pos)) 387 if (GNUNET_OK != is_connection_allowed (pos))
523 return; 388 return;
524 if (GNUNET_YES == pos->is_blocked)
525 return;
526 if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).value > 0) 389 if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).value > 0)
527 return; 390 return;
528 if (GNUNET_YES == pos->is_friend) 391 if (GNUNET_YES == pos->is_friend)
@@ -593,7 +456,6 @@ remove_from_greylist (void *cls,
593 pos); 456 pos);
594 } 457 }
595 if ( (GNUNET_NO == pos->is_friend) && 458 if ( (GNUNET_NO == pos->is_friend) &&
596 (GNUNET_NO == pos->is_blocked) &&
597 (GNUNET_NO == pos->is_connected) ) 459 (GNUNET_NO == pos->is_connected) )
598 { 460 {
599 free_peer (NULL, &pos->pid.hashPubKey, pos); 461 free_peer (NULL, &pos->pid.hashPubKey, pos);
@@ -863,18 +725,7 @@ connect_notify (void *cls,
863 if (pos == NULL) 725 if (pos == NULL)
864 { 726 {
865 pos = make_peer (peer, NULL, GNUNET_NO); 727 pos = make_peer (peer, NULL, GNUNET_NO);
866 if (GNUNET_OK != is_connection_allowed (pos)) 728 GNUNET_break (GNUNET_OK == is_connection_allowed (pos));
867 {
868 GNUNET_assert (pos->is_friend == GNUNET_NO);
869 pos->is_connected = GNUNET_YES;
870#if DEBUG_TOPOLOGY
871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
872 "Connection to `%s' is forbidden, forcing disconnect!\n",
873 GNUNET_i2s (peer));
874#endif
875 force_disconnect (pos);
876 return;
877 }
878 } 729 }
879 else 730 else
880 { 731 {
@@ -899,35 +750,6 @@ connect_notify (void *cls,
899 750
900 751
901/** 752/**
902 * Disconnect from all non-friends (we're below quota).
903 *
904 * @param cls closure, not used
905 * @param pid identity of a peer
906 * @param value 'struct Peer*' for the peer
907 * @return GNUNET_YES (continue to iterate)
908 */
909static int
910drop_non_friends (void *cls,
911 const GNUNET_HashCode *pid,
912 void *value)
913{
914 struct Peer *pos = value;
915
916 if ( (GNUNET_NO == pos->is_friend) &&
917 (GNUNET_YES == pos->is_connected) )
918 {
919#if DEBUG_TOPOLOGY
920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
921 "Connection to `%s' is not from a friend, forcing disconnect!\n",
922 GNUNET_i2s (&pos->pid));
923#endif
924 force_disconnect (pos);
925 }
926 return GNUNET_YES;
927}
928
929
930/**
931 * Try to add more peers to our connection set. 753 * Try to add more peers to our connection set.
932 * 754 *
933 * @param cls closure, not used 755 * @param cls closure, not used
@@ -995,17 +817,10 @@ disconnect_notify (void *cls,
995 GNUNET_CONTAINER_multihashmap_iterate (peers, 817 GNUNET_CONTAINER_multihashmap_iterate (peers,
996 &try_add_peers, 818 &try_add_peers,
997 NULL); 819 NULL);
998 if (friend_count < minimum_friend_count) 820 if ( (friend_count < minimum_friend_count) &&
999 { 821 (blacklist == NULL) )
1000 /* disconnect from all non-friends */ 822 blacklist = GNUNET_TRANSPORT_blacklist (sched, cfg,
1001#if DEBUG_TOPOLOGY 823 &blacklist_check, NULL);
1002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1003 "Not enough friendly connections, dropping all non-friend connections\n");
1004#endif
1005 GNUNET_CONTAINER_multihashmap_iterate (peers,
1006 &drop_non_friends,
1007 NULL);
1008 }
1009} 824}
1010 825
1011 826
@@ -1389,13 +1204,21 @@ handle_encrypted_hello (void *cls,
1389 GNUNET_NO); 1204 GNUNET_NO);
1390 peer = GNUNET_CONTAINER_multihashmap_get (peers, 1205 peer = GNUNET_CONTAINER_multihashmap_get (peers,
1391 &pid.hashPubKey); 1206 &pid.hashPubKey);
1392 if ( (peer != NULL) && 1207 if (peer == NULL)
1393 (peer->is_blocked) ) 1208 {
1394 return GNUNET_OK; /* ignore: currently blocked */ 1209 if ( (GNUNET_YES == friends_only) ||
1395 if ( (GNUNET_YES == friends_only) && 1210 (friend_count < minimum_friend_count) )
1396 ( (peer == NULL) || 1211 return GNUNET_OK;
1397 (GNUNET_YES != peer->is_friend) ) ) 1212 }
1398 return GNUNET_OK; /* ignore: not a friend */ 1213 else
1214 {
1215 if ( (GNUNET_YES != peer->is_friend) &&
1216 (GNUNET_YES == friends_only) )
1217 return GNUNET_OK;
1218 if ( (GNUNET_YES != peer->is_friend) &&
1219 (friend_count < minimum_friend_count) )
1220 return GNUNET_OK;
1221 }
1399 if (transport != NULL) 1222 if (transport != NULL)
1400 GNUNET_TRANSPORT_offer_hello (transport, 1223 GNUNET_TRANSPORT_offer_hello (transport,
1401 message); 1224 message);
@@ -1468,8 +1291,6 @@ static void
1468cleaning_task (void *cls, 1291cleaning_task (void *cls,
1469 const struct GNUNET_SCHEDULER_TaskContext *tc) 1292 const struct GNUNET_SCHEDULER_TaskContext *tc)
1470{ 1293{
1471 struct DisconnectList *dl;
1472
1473 if (NULL != peerinfo_notify) 1294 if (NULL != peerinfo_notify)
1474 { 1295 {
1475 GNUNET_PEERINFO_notify_cancel (peerinfo_notify); 1296 GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
@@ -1486,14 +1307,7 @@ cleaning_task (void *cls,
1486 GNUNET_CORE_disconnect (handle); 1307 GNUNET_CORE_disconnect (handle);
1487 handle = NULL; 1308 handle = NULL;
1488 } 1309 }
1489 while (NULL != (dl = disconnect_head)) 1310 whitelist_peers ();
1490 {
1491 GNUNET_CONTAINER_DLL_remove (disconnect_head,
1492 disconnect_tail,
1493 dl);
1494 GNUNET_TRANSPORT_blacklist_cancel (dl->rh);
1495 GNUNET_free (dl);
1496 }
1497 if (stats != NULL) 1311 if (stats != NULL)
1498 { 1312 {
1499 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 1313 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
@@ -1560,6 +1374,9 @@ run (void *cls,
1560 minimum_friend_count, 1374 minimum_friend_count,
1561 autoconnect ? "autoconnect enabled" : "autoconnect disabled"); 1375 autoconnect ? "autoconnect enabled" : "autoconnect disabled");
1562#endif 1376#endif
1377 if (friend_count < minimum_friend_count)
1378 blacklist = GNUNET_TRANSPORT_blacklist (sched, cfg,
1379 &blacklist_check, NULL);
1563 transport = GNUNET_TRANSPORT_connect (sched, 1380 transport = GNUNET_TRANSPORT_connect (sched,
1564 cfg, 1381 cfg,
1565 NULL, 1382 NULL,
@@ -1571,7 +1388,6 @@ run (void *cls,
1571 GNUNET_TIME_UNIT_FOREVER_REL, 1388 GNUNET_TIME_UNIT_FOREVER_REL,
1572 NULL, 1389 NULL,
1573 &core_init, 1390 &core_init,
1574 NULL,
1575 &connect_notify, 1391 &connect_notify,
1576 &disconnect_notify, 1392 &disconnect_notify,
1577 NULL, GNUNET_NO, 1393 NULL, GNUNET_NO,
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 70c6c6c75..71e6470e3 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -57,8 +57,7 @@ gnunet_transport_LDADD = \
57 $(GN_LIBINTL) 57 $(GN_LIBINTL)
58 58
59gnunet_service_transport_SOURCES = \ 59gnunet_service_transport_SOURCES = \
60 gnunet-service-transport.c plugin_transport.h \ 60 gnunet-service-transport.c plugin_transport.h
61 gnunet-service-transport_blacklist.c gnunet-service-transport_blacklist.h
62gnunet_service_transport_LDADD = \ 61gnunet_service_transport_LDADD = \
63 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 62 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
64 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 63 $(top_builddir)/src/statistics/libgnunetstatistics.la \
diff --git a/src/transport/gnunet-service-transport_blacklist.c b/src/transport/gnunet-service-transport_blacklist.c
index 8f78f498f..08ed2c9d2 100644
--- a/src/transport/gnunet-service-transport_blacklist.c
+++ b/src/transport/gnunet-service-transport_blacklist.c
@@ -43,32 +43,75 @@ struct BlacklistEntry
43 struct GNUNET_PeerIdentity peer; 43 struct GNUNET_PeerIdentity peer;
44 44
45 /** 45 /**
46 * How long until this entry times out? 46 * Client responsible for this entry.
47 */ 47 */
48 struct GNUNET_TIME_Absolute until; 48 struct GNUNET_SERVER_Client *client;
49
50};
51
52
53/**
54 * Information kept for each client registered to perform
55 * blacklisting.
56 */
57struct Blacklisters
58{
59 /**
60 * This is a linked list.
61 */
62 struct Blacklisters *next;
63
64 /**
65 * This is a linked list.
66 */
67 struct Blacklisters *prev;
49 68
50 /** 69 /**
51 * Task scheduled to run the moment the time does run out. 70 * Client responsible for this entry.
52 */ 71 */
53 GNUNET_SCHEDULER_TaskIdentifier timeout_task; 72 struct GNUNET_SERVER_Client *client;
73
54}; 74};
55 75
56 76
57/** 77/**
78 * State of blacklist check to be performed for each
79 * connecting peer.
80 */
81struct BlacklistCheck
82{
83
84
85
86 /**
87 * Identity of the peer being checked.
88 */
89 struct GNUNET_PeerIdentity peer;
90
91 /**
92 * Clients we still need to ask.
93 */
94 struct GNUNET_SERVER_Client *pending;
95
96};
97
98
99
100/**
58 * Map of blacklisted peers (maps from peer identities 101 * Map of blacklisted peers (maps from peer identities
59 * to 'struct BlacklistEntry*' values). 102 * to 'struct BlacklistEntry*' values).
60 */ 103 */
61static struct GNUNET_CONTAINER_MultiHashMap *blacklist; 104static struct GNUNET_CONTAINER_MultiHashMap *blacklist;
62 105
63/** 106/**
64 * Notifications for blacklisting. 107 * Head of DLL of blacklisting clients.
65 */ 108 */
66static struct GNUNET_SERVER_NotificationContext *blacklist_notifiers; 109static struct Blacklisters *bl_head;
67 110
68/** 111/**
69 * Our scheduler. 112 * Tail of DLL of blacklisting clients.
70 */ 113 */
71static struct GNUNET_SCHEDULER_Handle *sched; 114static struct Blacklisters *bl_tail;
72 115
73 116
74/** 117/**
@@ -86,8 +129,6 @@ free_blacklist_entry (void *cls,
86{ 129{
87 struct BlacklistEntry *be = value; 130 struct BlacklistEntry *be = value;
88 131
89 GNUNET_SCHEDULER_cancel (sched,
90 be->timeout_task);
91 GNUNET_free (be); 132 GNUNET_free (be);
92 return GNUNET_YES; 133 return GNUNET_YES;
93} 134}
@@ -108,37 +149,28 @@ shutdown_task (void *cls,
108 NULL); 149 NULL);
109 GNUNET_CONTAINER_multihashmap_destroy (blacklist); 150 GNUNET_CONTAINER_multihashmap_destroy (blacklist);
110 blacklist = NULL; 151 blacklist = NULL;
111 GNUNET_SERVER_notification_context_destroy (blacklist_notifiers);
112 blacklist_notifiers = NULL;
113} 152}
114 153
115 154
116/** 155/**
117 * Task run when a blacklist entry times out. 156 * Handle a request to start a blacklist.
118 * 157 *
119 * @param cls closure (the 'struct BlacklistEntry*') 158 * @param cls closure (always NULL)
120 * @param tc scheduler context (unused) 159 * @param client identification of the client
160 * @param message the actual message
121 */ 161 */
122static void 162void
123timeout_task (void *cls, 163GNUNET_TRANSPORT_handle_blacklist_init (void *cls,
124 const struct GNUNET_SCHEDULER_TaskContext *tc) 164 struct GNUNET_SERVER_Client *client,
165 const struct GNUNET_MessageHeader *message)
125{ 166{
126 struct BlacklistEntry *be = cls; 167 struct Blacklisters *bl;
127 struct BlacklistMessage msg; 168
128 169 bl = GNUNET_malloc (sizeof (struct Blacklisters));
129 be->timeout_task = GNUNET_SCHEDULER_NO_TASK; 170 bl->client = client;
130 msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST); 171 GNUNET_SERVER_client_keep (client);
131 msg.header.size = htons (sizeof (struct BlacklistMessage)); 172 GNUNET_CONTAINER_DLL_insert (bl_head, bl_tail, bl);
132 msg.reserved = htonl (0); 173 /* FIXME: confirm that all existing connections are OK! */
133 msg.peer = be->peer;
134 msg.until = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_ZERO_ABS);
135 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (blacklist,
136 &be->peer.hashPubKey,
137 be));
138 GNUNET_free (be);
139 GNUNET_SERVER_notification_context_broadcast (blacklist_notifiers,
140 &msg.header,
141 GNUNET_NO);
142} 174}
143 175
144 176
@@ -150,38 +182,33 @@ timeout_task (void *cls,
150 * @param message the actual message 182 * @param message the actual message
151 */ 183 */
152void 184void
153GNUNET_TRANSPORT_handle_blacklist (void *cls, 185GNUNET_TRANSPORT_handle_blacklist_reply (void *cls,
154 struct GNUNET_SERVER_Client *client, 186 struct GNUNET_SERVER_Client *client,
155 const struct GNUNET_MessageHeader *message) 187 const struct GNUNET_MessageHeader *message)
156{ 188{
157 struct BlacklistEntry *be; 189 struct Blacklisters *bl;
158 const struct BlacklistMessage *msg = (const struct BlacklistMessage*) message; 190 const struct BlacklistMessage *msg = (const struct BlacklistMessage*) message;
159 191
160 be = GNUNET_CONTAINER_multihashmap_get (blacklist, 192 bl = bl_head;
161 &msg->peer.hashPubKey); 193 while ( (bl != NULL) &&
162 if (be != NULL) 194 (bl->client != client) )
195 bl = bl->next;
196 if (bl == NULL)
163 { 197 {
164 GNUNET_SCHEDULER_cancel (sched, 198 GNUNET_SERVER_client_done (client, GNUNET_SYSERR);
165 be->timeout_task); 199 return;
166 } 200 }
167 else 201 if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
168 { 202 {
169 be = GNUNET_malloc (sizeof (struct BlacklistEntry)); 203 be = GNUNET_malloc (sizeof (struct BlacklistEntry));
170 be->peer = msg->peer; 204 be->peer = msg->peer;
205 be->client = client;
171 GNUNET_CONTAINER_multihashmap_put (blacklist, 206 GNUNET_CONTAINER_multihashmap_put (blacklist,
172 &msg->peer.hashPubKey, 207 &msg->peer.hashPubKey,
173 be, 208 be,
174 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 209 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
175 } 210 }
176 be->until = GNUNET_TIME_absolute_ntoh (msg->until); 211 /* FIXME: trigger continuation... */
177 be->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
178 GNUNET_TIME_absolute_get_remaining (be->until),
179 &timeout_task,
180 be);
181 GNUNET_SERVER_notification_context_broadcast (blacklist_notifiers,
182 &msg->header,
183 GNUNET_NO);
184 GNUNET_SERVER_receive_done (client, GNUNET_OK);
185} 212}
186 213
187 214
@@ -243,7 +270,9 @@ GNUNET_TRANSPORT_handle_blacklist_notify (void *cls,
243int 270int
244GNUNET_TRANSPORT_blacklist_check (const struct GNUNET_PeerIdentity *id) 271GNUNET_TRANSPORT_blacklist_check (const struct GNUNET_PeerIdentity *id)
245{ 272{
246 return GNUNET_CONTAINER_multihashmap_contains (blacklist, &id->hashPubKey); 273 if (GNUNET_CONTAINER_multihashmap_contains (blacklist, &id->hashPubKey))
274 return GNUNET_YES;
275
247} 276}
248 277
249 278
@@ -263,7 +292,6 @@ GNUNET_TRANSPORT_blacklist_init (struct GNUNET_SERVER_Handle *server,
263 GNUNET_TIME_UNIT_FOREVER_REL, 292 GNUNET_TIME_UNIT_FOREVER_REL,
264 &shutdown_task, 293 &shutdown_task,
265 NULL); 294 NULL);
266 blacklist_notifiers = GNUNET_SERVER_notification_context_create (server, 0);
267} 295}
268 296
269 297
diff --git a/src/transport/gnunet-service-transport_blacklist.h b/src/transport/gnunet-service-transport_blacklist.h
index 92f81a2e9..32e26431e 100644
--- a/src/transport/gnunet-service-transport_blacklist.h
+++ b/src/transport/gnunet-service-transport_blacklist.h
@@ -31,16 +31,16 @@
31#include "transport.h" 31#include "transport.h"
32 32
33/** 33/**
34 * Handle a request to blacklist a peer. 34 * Handle a request to start a blacklist.
35 * 35 *
36 * @param cls closure (always NULL) 36 * @param cls closure (always NULL)
37 * @param client identification of the client 37 * @param client identification of the client
38 * @param message the actual message 38 * @param message the actual message
39 */ 39 */
40void 40void
41GNUNET_TRANSPORT_handle_blacklist (void *cls, 41GNUNET_TRANSPORT_handle_blacklist_init (void *cls,
42 struct GNUNET_SERVER_Client *client, 42 struct GNUNET_SERVER_Client *client,
43 const struct GNUNET_MessageHeader *message); 43 const struct GNUNET_MessageHeader *message);
44 44
45 45
46/** 46/**
@@ -51,30 +51,9 @@ GNUNET_TRANSPORT_handle_blacklist (void *cls,
51 * @param message the actual message 51 * @param message the actual message
52 */ 52 */
53void 53void
54GNUNET_TRANSPORT_handle_blacklist_notify (void *cls, 54GNUNET_TRANSPORT_handle_blacklist_reply (void *cls,
55 struct GNUNET_SERVER_Client *client, 55 struct GNUNET_SERVER_Client *client,
56 const struct GNUNET_MessageHeader *message); 56 const struct GNUNET_MessageHeader *message);
57
58
59/**
60 * Is the given peer currently blacklisted?
61 *
62 * @param id identity of the peer
63 * @return GNUNET_YES if the peer is blacklisted, GNUNET_NO if not
64 */
65int
66GNUNET_TRANSPORT_blacklist_check (const struct GNUNET_PeerIdentity *id);
67
68
69/**
70 * Initialize the blacklisting subsystem.
71 *
72 * @param server server we handle requests from (transport service server)
73 * @param s scheduler to use
74 */
75void
76GNUNET_TRANSPORT_blacklist_init (struct GNUNET_SERVER_Handle *server,
77 struct GNUNET_SCHEDULER_Handle *s);
78 57
79 58
80#endif 59#endif
diff --git a/src/transport/transport.h b/src/transport/transport.h
index d66b87b35..b2ef01bb5 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -268,27 +268,22 @@ struct BlacklistMessage
268{ 268{
269 269
270 /** 270 /**
271 * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST 271 * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY or
272 * GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY.
272 */ 273 */
273 struct GNUNET_MessageHeader header; 274 struct GNUNET_MessageHeader header;
274 275
275 /** 276 /**
276 * Reserved (for alignment). 277 * 0 for the query, GNUNET_OK (allowed) or GNUNET_SYSERR (disallowed)
278 * for the response.
277 */ 279 */
278 uint32_t reserved GNUNET_PACKED; 280 uint32_t is_allowed GNUNET_PACKED;
279 281
280 /** 282 /**
281 * Which peer is being blacklisted (or has seen its 283 * Which peer is being blacklisted or queried?
282 * blacklisting expire)?
283 */ 284 */
284 struct GNUNET_PeerIdentity peer; 285 struct GNUNET_PeerIdentity peer;
285 286
286 /**
287 * Until what time is this peer blacklisted (zero for
288 * no longer blacklisted).
289 */
290 struct GNUNET_TIME_AbsoluteNBO until;
291
292}; 287};
293 288
294 289
diff --git a/src/transport/transport_api_blacklist.c b/src/transport/transport_api_blacklist.c
index c8838f1b6..5d2d616e8 100644
--- a/src/transport/transport_api_blacklist.c
+++ b/src/transport/transport_api_blacklist.c
@@ -36,7 +36,7 @@
36/** 36/**
37 * Handle for blacklisting requests. 37 * Handle for blacklisting requests.
38 */ 38 */
39struct GNUNET_TRANSPORT_BlacklistRequest 39struct GNUNET_TRANSPORT_Blacklist
40{ 40{
41 41
42 /** 42 /**
@@ -45,342 +45,255 @@ struct GNUNET_TRANSPORT_BlacklistRequest
45 struct GNUNET_CLIENT_Connection * client; 45 struct GNUNET_CLIENT_Connection * client;
46 46
47 /** 47 /**
48 * Function to call when done. 48 * Scheduler to use.
49 */
50 GNUNET_SCHEDULER_Task cont;
51
52 /**
53 * Clsoure for 'cont'.
54 */ 49 */
55 void *cont_cls; 50 struct GNUNET_SCHEDULER_Handle *sched;
56 51
57 /** 52 /**
58 * Scheduler to use. 53 * Configuration to use.
59 */ 54 */
60 struct GNUNET_SCHEDULER_Handle *sched; 55 const struct GNUNET_CONFIGURATION_Handle *cfg;
61 56
62 /** 57 /**
63 * Pending handle for the blacklisting request. 58 * Pending handle for the current request.
64 */ 59 */
65 struct GNUNET_CLIENT_TransmitHandle *th; 60 struct GNUNET_CLIENT_TransmitHandle *th;
66 61
67 /** 62 /**
68 * How long should 'peer' be blacklisted? 63 * Function to call for determining if a peer is allowed
64 * to communicate with us.
69 */ 65 */
70 struct GNUNET_TIME_Absolute duration; 66 GNUNET_TRANSPORT_BlacklistCallback cb;
71 67
72 /** 68 /**
73 * Which peer is being blacklisted? 69 * Closure for 'cb'.
70 */
71 void *cb_cls;
72
73 /**
74 * Peer currently under consideration.
74 */ 75 */
75 struct GNUNET_PeerIdentity peer; 76 struct GNUNET_PeerIdentity peer;
76 77
77}; 78};
78 79
79 80
80/** 81/**
81 * Function called to notify a client about the socket 82 * Establish blacklist connection to transport service.
82 * begin ready to queue more data. "buf" will be
83 * NULL and "size" zero if the socket was closed for
84 * writing in the meantime.
85 * 83 *
86 * @param cls closure 84 * @param br overall handle
87 * @param size number of bytes available in buf
88 * @param buf where the callee should write the message
89 * @return number of bytes written to buf
90 */ 85 */
91static size_t 86static void
92transmit_blacklist_request (void *cls, 87reconnect (struct GNUNET_TRANSPORT_Blacklist *br);
93 size_t size, void *buf)
94{
95 struct GNUNET_TRANSPORT_BlacklistRequest *br = cls;
96 struct BlacklistMessage req;
97
98 if (buf == NULL)
99 {
100 GNUNET_SCHEDULER_add_continuation (br->sched,
101 br->cont,
102 br->cont_cls,
103 GNUNET_SCHEDULER_REASON_TIMEOUT);
104 GNUNET_free (br);
105 return 0;
106 }
107 req.header.size = htons (sizeof (req));
108 req.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST);
109 req.reserved = htonl (0);
110 req.peer = br->peer;
111 req.until = GNUNET_TIME_absolute_hton (br->duration);
112 memcpy (buf, &req, sizeof (req));
113 GNUNET_SCHEDULER_add_continuation (br->sched,
114 br->cont,
115 br->cont_cls,
116 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
117 GNUNET_free (br);
118 return sizeof (req);
119}
120 88
121 89
122/** 90/**
123 * Blacklist a peer for a given period of time. All connections 91 * Send our reply to a blacklisting request.
124 * (inbound and outbound) to a peer that is blacklisted will be
125 * dropped (as soon as we learn who the connection is for). A second
126 * call to this function for the same peer overrides previous
127 * blacklisting requests.
128 * 92 *
129 * @param sched scheduler to use 93 * @param br our overall context
130 * @param cfg configuration to use
131 * @param peer identity of peer to blacklist
132 * @param duration how long to blacklist, use GNUNET_TIME_UNIT_ZERO to
133 * re-enable connections
134 * @param timeout when should this operation (trying to establish the
135 * blacklisting time out)
136 * @param cont continuation to call once the request has been processed
137 * @param cont_cls closure for cont
138 * @return NULL on error, otherwise handle for cancellation
139 */ 94 */
140struct GNUNET_TRANSPORT_BlacklistRequest * 95static void
141GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched, 96reply (struct GNUNET_TRANSPORT_Blacklist *br);
142 const struct GNUNET_CONFIGURATION_Handle *cfg,
143 const struct GNUNET_PeerIdentity *peer,
144 struct GNUNET_TIME_Relative duration,
145 struct GNUNET_TIME_Relative timeout,
146 GNUNET_SCHEDULER_Task cont,
147 void *cont_cls)
148{
149 struct GNUNET_CLIENT_Connection * client;
150 struct GNUNET_TRANSPORT_BlacklistRequest *ret;
151
152 client = GNUNET_CLIENT_connect (sched, "transport", cfg);
153 if (NULL == client)
154 return NULL;
155 ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_BlacklistRequest));
156 ret->client = client;
157 ret->peer = *peer;
158 ret->duration = GNUNET_TIME_relative_to_absolute (duration);
159 ret->sched = sched;
160 ret->cont = cont;
161 ret->cont_cls = cont_cls;
162 ret->th = GNUNET_CLIENT_notify_transmit_ready (client,
163 sizeof (struct BlacklistMessage),
164 timeout,
165 GNUNET_YES,
166 &transmit_blacklist_request,
167 ret);
168 GNUNET_assert (NULL != ret->th);
169 return ret;
170}
171 97
172 98
173/** 99/**
174 * Abort transmitting the blacklist request. Note that this function 100 * Handle blacklist queries.
175 * is NOT for removing a peer from the blacklist (for that, call
176 * GNUNET_TRANSPORT_blacklist with a duration of zero). This function
177 * is only for aborting the transmission of a blacklist request
178 * (i.e. because of shutdown).
179 * 101 *
180 * @param br handle of the request that is to be cancelled 102 * @param cls our overall handle
103 * @param msg query
181 */ 104 */
182void 105static void
183GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_BlacklistRequest * br) 106query_handler (void *cls,
184{ 107 const struct GNUNET_MessageHeader *msg)
185 GNUNET_CLIENT_notify_transmit_ready_cancel (br->th);
186 GNUNET_free (br);
187}
188
189
190/**
191 * Handle for blacklist notifications.
192 */
193struct GNUNET_TRANSPORT_BlacklistNotification
194{ 108{
195 109 struct GNUNET_TRANSPORT_Blacklist *br = cls;
196 /** 110 const struct BlacklistMessage *bm;
197 * Function to call whenever there is a change.
198 */
199 GNUNET_TRANSPORT_BlacklistCallback notify;
200
201 /**
202 * Closure for notify.
203 */
204 void *notify_cls;
205
206 /**
207 * Scheduler to use.
208 */
209 struct GNUNET_SCHEDULER_Handle *sched;
210
211 /**
212 * Configuration to use.
213 */
214 const struct GNUNET_CONFIGURATION_Handle *cfg;
215 111
216 /** 112 if ( (ntohs(msg->size) != sizeof (struct BlacklistMessage)) ||
217 * Connection to transport service. 113 (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY) )
218 */ 114 {
219 struct GNUNET_CLIENT_Connection * client; 115 reconnect (br);
220 116 return;
221 /** 117 }
222 * Pending handle for the notification request. 118 bm = (const struct BlacklistMessage *)msg;
223 */ 119 GNUNET_break (0 == ntohl (bm->is_allowed));
224 struct GNUNET_CLIENT_TransmitHandle *th; 120 br->peer = bm->peer;
225}; 121 reply (br);
122}
226 123
227 124
228/** 125/**
229 * Send a request to receive blacklisting notifications 126 * Receive blacklist queries from transport service.
230 * 127 *
231 * @param bn context to initialize 128 * @param br overall handle
232 */ 129 */
233static void 130static void
234request_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn); 131receive (struct GNUNET_TRANSPORT_Blacklist *br)
132{
133 GNUNET_CLIENT_receive (br->client,
134 &query_handler,
135 br,
136 GNUNET_TIME_UNIT_FOREVER_REL);
137}
235 138
236 139
237/** 140/**
238 * Destroy the existing connection to the transport service and 141 * Transmit the blacklist initialization request to the service.
239 * setup a new one (the existing one had serious problems). 142 *
240 * 143 * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*)
241 * @param bn context to re-initialize 144 * @param size number of bytes available in buf
145 * @param buf where the callee should write the message
146 * @return number of bytes written to buf
242 */ 147 */
243static void 148static size_t
244retry_get_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn) 149transmit_blacklist_init (void *cls,
150 size_t size, void *buf)
245{ 151{
246 GNUNET_CLIENT_disconnect (bn->client, GNUNET_NO); 152 struct GNUNET_TRANSPORT_Blacklist *br = cls;
247 bn->client = GNUNET_CLIENT_connect (bn->sched, "transport", bn->cfg); 153 struct GNUNET_MessageHeader req;
248 request_notifications (bn); 154
155 if (buf == NULL)
156 {
157 reconnect (br);
158 return 0;
159 }
160 req.size = htons (sizeof (struct GNUNET_MessageHeader));
161 req.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT);
162 memcpy (buf, &req, sizeof (req));
163 receive (br);
164 return sizeof (req);
249} 165}
250 166
251 167
252/** 168/**
253 * Function called whenever we get a blacklisting notification. 169 * Establish blacklist connection to transport service.
254 * Pass it on to the callback and wait for more.
255 * 170 *
256 * @param cls our 'struct GNUNET_TRANSPORT_BlacklistNotification *' 171 * @param br overall handle
257 * @param msg the blacklisting notification, NULL on error
258 */ 172 */
259static void 173static void
260recv_blacklist_info (void *cls, 174reconnect (struct GNUNET_TRANSPORT_Blacklist *br)
261 const struct GNUNET_MessageHeader *msg)
262{ 175{
263 struct GNUNET_TRANSPORT_BlacklistNotification *bn = cls; 176 if (br->client != NULL)
264 const struct BlacklistMessage *req; 177 GNUNET_CLIENT_disconnect (br->client, GNUNET_NO);
265 178 br->client = GNUNET_CLIENT_connect (br->sched,
266 if ( (msg == NULL) || 179 "transport",
267 (sizeof(struct BlacklistMessage) != ntohs(msg->size)) || 180 br->cfg);
268 (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST != ntohs(msg->type)) ) 181 br->th = GNUNET_CLIENT_notify_transmit_ready (br->client,
269 { 182 sizeof (struct GNUNET_MessageHeader),
270 retry_get_notifications (bn); 183 GNUNET_TIME_UNIT_FOREVER_REL,
271 return; 184 GNUNET_YES,
272 } 185 &transmit_blacklist_init,
273 req = (const struct BlacklistMessage*) msg; 186 br);
274 bn->notify (bn->notify_cls,
275 &req->peer,
276 GNUNET_TIME_absolute_ntoh (req->until));
277 GNUNET_CLIENT_receive (bn->client,
278 &recv_blacklist_info,
279 bn,
280 GNUNET_TIME_UNIT_FOREVER_REL);
281} 187}
282 188
283 189
284/** 190/**
285 * Function called to notify a client about the socket 191 * Transmit the blacklist response to the service.
286 * begin ready to queue more data. "buf" will be
287 * NULL and "size" zero if the socket was closed for
288 * writing in the meantime.
289 * 192 *
290 * @param cls closure 193 * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*)
291 * @param size number of bytes available in buf 194 * @param size number of bytes available in buf
292 * @param buf where the callee should write the message 195 * @param buf where the callee should write the message
293 * @return number of bytes written to buf 196 * @return number of bytes written to buf
294 */ 197 */
295static size_t 198static size_t
296transmit_notify_request (void *cls, 199transmit_blacklist_reply (void *cls,
297 size_t size, void *buf) 200 size_t size, void *buf)
298{ 201{
299 struct GNUNET_TRANSPORT_BlacklistNotification *bn = cls; 202 struct GNUNET_TRANSPORT_Blacklist *br = cls;
300 struct GNUNET_MessageHeader hdr; 203 struct BlacklistMessage req;
301 204
302 bn->th = NULL;
303 if (buf == NULL) 205 if (buf == NULL)
304 { 206 {
305 retry_get_notifications (bn); 207 reconnect (br);
306 return 0; 208 return 0;
307 } 209 }
308 GNUNET_assert (size >= sizeof(hdr)); 210 req.header.size = htons (sizeof (req));
309 hdr.size = htons (sizeof (hdr)); 211 req.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY);
310 hdr.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_NOTIFY); 212 req.is_allowed = htonl (br->cb (br->cb_cls, &br->peer));
311 memcpy (buf, &hdr, sizeof(hdr)); 213 req.peer = br->peer;
312 return sizeof(hdr); 214 memcpy (buf, &req, sizeof (req));
215 receive (br);
216 return sizeof (req);
313} 217}
314 218
315 219
316/** 220/**
317 * Send a request to receive blacklisting notifications 221 * Send our reply to a blacklisting request.
318 * 222 *
319 * @param bn context to initialize 223 * @param br our overall context
320 */ 224 */
321static void 225static void
322request_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn) 226reply (struct GNUNET_TRANSPORT_Blacklist *br)
323{ 227{
324 GNUNET_assert (bn->client != NULL); 228 br->th = GNUNET_CLIENT_notify_transmit_ready (br->client,
325 bn->th = GNUNET_CLIENT_notify_transmit_ready (bn->client, 229 sizeof (struct BlacklistMessage),
326 sizeof (struct GNUNET_MessageHeader),
327 GNUNET_TIME_UNIT_FOREVER_REL, 230 GNUNET_TIME_UNIT_FOREVER_REL,
328 GNUNET_YES, 231 GNUNET_NO,
329 &transmit_notify_request, 232 &transmit_blacklist_reply,
330 bn); 233 br);
331 GNUNET_assert (bn->th != NULL); 234 if (br->th == NULL)
332 GNUNET_CLIENT_receive (bn->client, 235 {
333 &recv_blacklist_info, 236 reconnect (br);
334 bn, 237 return;
335 GNUNET_TIME_UNIT_FOREVER_REL); 238 }
336} 239}
337 240
338 241
339/** 242/**
340 * Call a function whenever a peer's blacklisting status changes. 243 * Install a blacklist callback. The service will be queried for all
244 * existing connections as well as any fresh connections to check if
245 * they are permitted. If the blacklisting callback is unregistered,
246 * all hosts that were denied in the past will automatically be
247 * whitelisted again. Cancelling the blacklist handle is also the
248 * only way to re-enable connections from peers that were previously
249 * blacklisted.
341 * 250 *
342 * @param sched scheduler to use 251 * @param sched scheduler to use
343 * @param cfg configuration to use 252 * @param cfg configuration to use
344 * @param bc function to call on status changes 253 * @param cb callback to invoke to check if connections are allowed
345 * @param bc_cls closure for bc 254 * @param cb_cls closure for cb
346 * @return NULL on error, otherwise handle for cancellation 255 * @return NULL on error, otherwise handle for cancellation
347 */ 256 */
348struct GNUNET_TRANSPORT_BlacklistNotification * 257struct GNUNET_TRANSPORT_Blacklist *
349GNUNET_TRANSPORT_blacklist_notify (struct GNUNET_SCHEDULER_Handle *sched, 258GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched,
350 const struct GNUNET_CONFIGURATION_Handle *cfg, 259 const struct GNUNET_CONFIGURATION_Handle *cfg,
351 GNUNET_TRANSPORT_BlacklistCallback bc, 260 GNUNET_TRANSPORT_BlacklistCallback cb,
352 void *bc_cls) 261 void *cb_cls)
353{ 262{
354 struct GNUNET_TRANSPORT_BlacklistNotification *ret;
355 struct GNUNET_CLIENT_Connection * client; 263 struct GNUNET_CLIENT_Connection * client;
264 struct GNUNET_TRANSPORT_Blacklist *ret;
356 265
357 client = GNUNET_CLIENT_connect (sched, "transport", cfg); 266 client = GNUNET_CLIENT_connect (sched, "transport", cfg);
358 if (NULL == client) 267 if (NULL == client)
359 return NULL; 268 return NULL;
360 ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_BlacklistNotification)); 269 ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_Blacklist));
361 ret->client = client; 270 ret->client = client;
362 ret->sched = sched; 271 ret->sched = sched;
363 ret->cfg = cfg; 272 ret->cfg = cfg;
364 ret->notify = bc; 273 ret->th = GNUNET_CLIENT_notify_transmit_ready (client,
365 ret->notify_cls = bc_cls; 274 sizeof (struct GNUNET_MessageHeader),
366 request_notifications (ret); 275 GNUNET_TIME_UNIT_FOREVER_REL,
276 GNUNET_YES,
277 &transmit_blacklist_init,
278 ret);
367 return ret; 279 return ret;
368} 280}
369 281
370 282
371/** 283/**
372 * Stop calling the notification callback associated with 284 * Abort the blacklist. Note that this function is the only way for
373 * the given blacklist notification. 285 * removing a peer from the blacklist.
374 * 286 *
375 * @param bn handle of the request that is to be cancelled 287 * @param br handle of the request that is to be cancelled
376 */ 288 */
377void 289void
378GNUNET_TRANSPORT_blacklist_notify_cancel (struct GNUNET_TRANSPORT_BlacklistNotification * bn) 290GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_Blacklist *br)
379{ 291{
380 if (bn->th != NULL) 292 if (br->th != NULL)
381 GNUNET_CLIENT_notify_transmit_ready_cancel (bn->th); 293 GNUNET_CLIENT_notify_transmit_ready_cancel (br->th);
382 GNUNET_CLIENT_disconnect (bn->client, GNUNET_NO); 294 GNUNET_CLIENT_disconnect (br->client, GNUNET_NO);
383 GNUNET_free (bn); 295 GNUNET_free (br);
384} 296}
385 297
298
386/* end of transport_api_blacklist.c */ 299/* end of transport_api_blacklist.c */