-doxygen
[oweals/gnunet.git] / src / transport / transport_api_blacklist.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file transport/transport_api_blacklist.c
23  * @brief library to access the blacklisting functions of the transport service
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_arm_service.h"
29 #include "gnunet_hello_lib.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet_transport_service.h"
32 #include "transport.h"
33
34 /**
35  * Handle for blacklisting requests.
36  */
37 struct GNUNET_TRANSPORT_Blacklist
38 {
39
40   /**
41    * Connection to transport service.
42    */
43   struct GNUNET_CLIENT_Connection *client;
44
45   /**
46    * Configuration to use.
47    */
48   const struct GNUNET_CONFIGURATION_Handle *cfg;
49
50   /**
51    * Pending handle for the current request.
52    */
53   struct GNUNET_CLIENT_TransmitHandle *th;
54
55   /**
56    * Function to call for determining if a peer is allowed
57    * to communicate with us.
58    */
59   GNUNET_TRANSPORT_BlacklistCallback cb;
60
61   /**
62    * Closure for 'cb'.
63    */
64   void *cb_cls;
65
66   /**
67    * Peer currently under consideration.
68    */
69   struct GNUNET_PeerIdentity peer;
70
71 };
72
73
74 /**
75  * Establish blacklist connection to transport service.
76  *
77  * @param br overall handle
78  */
79 static void
80 reconnect (struct GNUNET_TRANSPORT_Blacklist *br);
81
82
83 /**
84  * Send our reply to a blacklisting request.
85  *
86  * @param br our overall context
87  */
88 static void
89 reply (struct GNUNET_TRANSPORT_Blacklist *br);
90
91
92 /**
93  * Handle blacklist queries.
94  *
95  * @param cls our overall handle
96  * @param msg query
97  */
98 static void
99 query_handler (void *cls, const struct GNUNET_MessageHeader *msg)
100 {
101   struct GNUNET_TRANSPORT_Blacklist *br = cls;
102   const struct BlacklistMessage *bm;
103
104   GNUNET_assert (br != NULL);
105   if ((NULL == msg) ||
106       (ntohs (msg->size) != sizeof (struct BlacklistMessage)) ||
107       (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY))
108   {
109     reconnect (br);
110     return;
111   }
112   bm = (const struct BlacklistMessage *) msg;
113   GNUNET_break (0 == ntohl (bm->is_allowed));
114   br->peer = bm->peer;
115   reply (br);
116 }
117
118
119 /**
120  * Receive blacklist queries from transport service.
121  *
122  * @param br overall handle
123  */
124 static void
125 receive (struct GNUNET_TRANSPORT_Blacklist *br)
126 {
127   GNUNET_CLIENT_receive (br->client, &query_handler, br,
128                          GNUNET_TIME_UNIT_FOREVER_REL);
129 }
130
131
132 /**
133  * Transmit the blacklist initialization request to the service.
134  *
135  * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*)
136  * @param size number of bytes available in buf
137  * @param buf where the callee should write the message
138  * @return number of bytes written to buf
139  */
140 static size_t
141 transmit_blacklist_init (void *cls, size_t size, void *buf)
142 {
143   struct GNUNET_TRANSPORT_Blacklist *br = cls;
144   struct GNUNET_MessageHeader req;
145
146   br->th = NULL;
147   if (buf == NULL)
148   {
149     reconnect (br);
150     return 0;
151   }
152   req.size = htons (sizeof (struct GNUNET_MessageHeader));
153   req.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT);
154   memcpy (buf, &req, sizeof (req));
155   receive (br);
156   return sizeof (req);
157 }
158
159
160 /**
161  * Establish blacklist connection to transport service.
162  *
163  * @param br overall handle
164  */
165 static void
166 reconnect (struct GNUNET_TRANSPORT_Blacklist *br)
167 {
168   if (br->client != NULL)
169     GNUNET_CLIENT_disconnect (br->client);
170   br->client = GNUNET_CLIENT_connect ("transport", br->cfg);
171   GNUNET_assert (br->client != NULL);
172   br->th =
173       GNUNET_CLIENT_notify_transmit_ready (br->client,
174                                            sizeof (struct GNUNET_MessageHeader),
175                                            GNUNET_TIME_UNIT_FOREVER_REL,
176                                            GNUNET_YES, &transmit_blacklist_init,
177                                            br);
178 }
179
180
181 /**
182  * Transmit the blacklist response to the service.
183  *
184  * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*)
185  * @param size number of bytes available in buf
186  * @param buf where the callee should write the message
187  * @return number of bytes written to buf
188  */
189 static size_t
190 transmit_blacklist_reply (void *cls, size_t size, void *buf)
191 {
192   struct GNUNET_TRANSPORT_Blacklist *br = cls;
193   struct BlacklistMessage req;
194
195   br->th = NULL;
196   if (buf == NULL)
197   {
198     reconnect (br);
199     return 0;
200   }
201   req.header.size = htons (sizeof (req));
202   req.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY);
203   req.is_allowed = htonl (br->cb (br->cb_cls, &br->peer));
204   req.peer = br->peer;
205   memcpy (buf, &req, sizeof (req));
206   br->th = NULL;
207   receive (br);
208   return sizeof (req);
209 }
210
211
212 /**
213  * Send our reply to a blacklisting request.
214  *
215  * @param br our overall context
216  */
217 static void
218 reply (struct GNUNET_TRANSPORT_Blacklist *br)
219 {
220   GNUNET_assert (br->th == NULL);
221   br->th =
222       GNUNET_CLIENT_notify_transmit_ready (br->client,
223                                            sizeof (struct BlacklistMessage),
224                                            GNUNET_TIME_UNIT_FOREVER_REL,
225                                            GNUNET_NO, &transmit_blacklist_reply,
226                                            br);
227   if (br->th == NULL)
228   {
229     reconnect (br);
230     return;
231   }
232 }
233
234
235 /**
236  * Install a blacklist callback.  The service will be queried for all
237  * existing connections as well as any fresh connections to check if
238  * they are permitted.  If the blacklisting callback is unregistered,
239  * all hosts that were denied in the past will automatically be
240  * whitelisted again.  Cancelling the blacklist handle is also the
241  * only way to re-enable connections from peers that were previously
242  * blacklisted.
243  *
244  * @param cfg configuration to use
245  * @param cb callback to invoke to check if connections are allowed
246  * @param cb_cls closure for cb
247  * @return NULL on error, otherwise handle for cancellation
248  */
249 struct GNUNET_TRANSPORT_Blacklist *
250 GNUNET_TRANSPORT_blacklist (const struct GNUNET_CONFIGURATION_Handle *cfg,
251                             GNUNET_TRANSPORT_BlacklistCallback cb, void *cb_cls)
252 {
253   struct GNUNET_CLIENT_Connection *client;
254   struct GNUNET_TRANSPORT_Blacklist *ret;
255
256   client = GNUNET_CLIENT_connect ("transport", cfg);
257   if (NULL == client)
258     return NULL;
259   ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_Blacklist));
260   ret->client = client;
261   ret->cfg = cfg;
262   ret->cb = cb;
263   ret->cb_cls = cb_cls;
264   GNUNET_assert (ret->th == NULL);
265   ret->th =
266       GNUNET_CLIENT_notify_transmit_ready (client,
267                                            sizeof (struct GNUNET_MessageHeader),
268                                            GNUNET_TIME_UNIT_FOREVER_REL,
269                                            GNUNET_YES, &transmit_blacklist_init,
270                                            ret);
271   return ret;
272 }
273
274
275 /**
276  * Abort the blacklist.  Note that this function is the only way for
277  * removing a peer from the blacklist.
278  *
279  * @param br handle of the request that is to be cancelled
280  */
281 void
282 GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_Blacklist *br)
283 {
284   if (br->th != NULL)
285   {
286     GNUNET_CLIENT_notify_transmit_ready_cancel (br->th);
287     br->th = NULL;
288   }
289   GNUNET_CLIENT_disconnect (br->client);
290   GNUNET_free (br);
291 }
292
293
294 /* end of transport_api_blacklist.c */