aboutsummaryrefslogtreecommitdiff
path: root/src/transport
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 /src/transport
parente8bc962b2ed43e194ba124537573da236786e82c (diff)
downloadgnunet-541caf3dec54aaee621fed935e667f9ee423ef31.tar.gz
gnunet-541caf3dec54aaee621fed935e667f9ee423ef31.zip
towards fixing blacklisting APIs and implementation
Diffstat (limited to 'src/transport')
-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
5 files changed, 248 insertions, 334 deletions
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 */