From 3926d80e05c1145d84f807224e6cb30eee4c1b40 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 21 Jan 2010 12:27:29 +0000 Subject: blacklisting API implementation --- src/transport/transport_api_blacklist.c | 386 ++++++++++++++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 src/transport/transport_api_blacklist.c (limited to 'src/transport/transport_api_blacklist.c') diff --git a/src/transport/transport_api_blacklist.c b/src/transport/transport_api_blacklist.c new file mode 100644 index 000000000..d33c4123c --- /dev/null +++ b/src/transport/transport_api_blacklist.c @@ -0,0 +1,386 @@ +/* + This file is part of GNUnet. + (C) 2010 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file transport/transport_api_blacklist.c + * @brief library to access the blacklisting functions of the transport service + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_client_lib.h" +#include "gnunet_arm_service.h" +#include "gnunet_hello_lib.h" +#include "gnunet_protocols.h" +#include "gnunet_server_lib.h" +#include "gnunet_time_lib.h" +#include "gnunet_transport_service.h" +#include "transport.h" + +/** + * Handle for blacklisting requests. + */ +struct GNUNET_TRANSPORT_BlacklistRequest +{ + + /** + * Connection to transport service. + */ + struct GNUNET_CLIENT_Connection * client; + + /** + * Function to call when done. + */ + GNUNET_SCHEDULER_Task cont; + + /** + * Clsoure for 'cont'. + */ + void *cont_cls; + + /** + * Scheduler to use. + */ + struct GNUNET_SCHEDULER_Handle *sched; + + /** + * Pending handle for the blacklisting request. + */ + struct GNUNET_CLIENT_TransmitHandle *th; + + /** + * How long should 'peer' be blacklisted? + */ + struct GNUNET_TIME_Absolute duration; + + /** + * Which peer is being blacklisted? + */ + struct GNUNET_PeerIdentity peer; + +}; + + +/** + * Function called to notify a client about the socket + * begin ready to queue more data. "buf" will be + * NULL and "size" zero if the socket was closed for + * writing in the meantime. + * + * @param cls closure + * @param size number of bytes available in buf + * @param buf where the callee should write the message + * @return number of bytes written to buf + */ +static size_t +transmit_blacklist_request (void *cls, + size_t size, void *buf) +{ + struct GNUNET_TRANSPORT_BlacklistRequest *br = cls; + struct BlacklistMessage req; + + if (buf == NULL) + { + GNUNET_SCHEDULER_add_continuation (br->sched, + br->cont, + br->cont_cls, + GNUNET_SCHEDULER_REASON_TIMEOUT); + GNUNET_free (br); + return 0; + } + req.header.size = htons (sizeof (req)); + req.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST); + req.reserved = htonl (0); + req.peer = br->peer; + req.until = GNUNET_TIME_absolute_hton (br->duration); + memcpy (buf, &req, sizeof (req)); + GNUNET_SCHEDULER_add_continuation (br->sched, + br->cont, + br->cont_cls, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + GNUNET_free (br); + return sizeof (req); +} + + +/** + * Blacklist a peer for a given period of time. All connections + * (inbound and outbound) to a peer that is blacklisted will be + * dropped (as soon as we learn who the connection is for). A second + * call to this function for the same peer overrides previous + * blacklisting requests. + * + * @param sched scheduler to use + * @param cfg configuration to use + * @param peer identity of peer to blacklist + * @param duration how long to blacklist, use GNUNET_TIME_UNIT_ZERO to + * re-enable connections + * @param timeout when should this operation (trying to establish the + * blacklisting time out) + * @param cont continuation to call once the request has been processed + * @param cont_cls closure for cont + * @return NULL on error, otherwise handle for cancellation + */ +struct GNUNET_TRANSPORT_BlacklistRequest * +GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched, + const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_PeerIdentity *peer, + struct GNUNET_TIME_Relative duration, + struct GNUNET_TIME_Relative timeout, + GNUNET_SCHEDULER_Task cont, + void *cont_cls) +{ + struct GNUNET_CLIENT_Connection * client; + struct GNUNET_TRANSPORT_BlacklistRequest *ret; + + client = GNUNET_CLIENT_connect (sched, "transport", cfg); + if (NULL == client) + return NULL; + ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_BlacklistRequest)); + ret->client = client; + ret->peer = *peer; + ret->duration = GNUNET_TIME_relative_to_absolute (duration); + ret->sched = sched; + ret->cont = cont; + ret->cont_cls = cont_cls; + ret->th = GNUNET_CLIENT_notify_transmit_ready (client, + sizeof (struct BlacklistMessage), + timeout, + GNUNET_YES, + &transmit_blacklist_request, + ret); + GNUNET_assert (NULL != ret->th); + return ret; +} + + +/** + * Abort transmitting the blacklist request. Note that this function + * is NOT for removing a peer from the blacklist (for that, call + * GNUNET_TRANSPORT_blacklist with a duration of zero). This function + * is only for aborting the transmission of a blacklist request + * (i.e. because of shutdown). + * + * @param br handle of the request that is to be cancelled + */ +void +GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_BlacklistRequest * br) +{ + GNUNET_CLIENT_notify_transmit_ready_cancel (br->th); + GNUNET_free (br); +} + + +/** + * Handle for blacklist notifications. + */ +struct GNUNET_TRANSPORT_BlacklistNotification +{ + + /** + * Function to call whenever there is a change. + */ + GNUNET_TRANSPORT_BlacklistCallback notify; + + /** + * Closure for notify. + */ + void *notify_cls; + + /** + * Scheduler to use. + */ + struct GNUNET_SCHEDULER_Handle *sched; + + /** + * Configuration to use. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Connection to transport service. + */ + struct GNUNET_CLIENT_Connection * client; + + /** + * Pending handle for the notification request. + */ + struct GNUNET_CLIENT_TransmitHandle *th; +}; + + +/** + * Send a request to receive blacklisting notifications + * + * @param bn context to initialize + */ +static void +request_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn); + + +/** + * Destroy the existing connection to the transport service and + * setup a new one (the existing one had serious problems). + * + * @param bn context to re-initialize + */ +static void +retry_get_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn) +{ + GNUNET_CLIENT_disconnect (bn->client); + bn->client = GNUNET_CLIENT_connect (bn->sched, "transport", bn->cfg); + request_notifications (bn); +} + + +/** + * Function called whenever we get a blacklisting notification. + * Pass it on to the callback and wait for more. + * + * @param cls our 'struct GNUNET_TRANSPORT_BlacklistNotification *' + * @param msg the blacklisting notification, NULL on error + */ +static void +recv_blacklist_info (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + struct GNUNET_TRANSPORT_BlacklistNotification *bn = cls; + const struct BlacklistMessage *req; + + if ( (msg == NULL) || + (sizeof(struct BlacklistMessage) != ntohs(msg->size)) || + (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST != ntohs(msg->type)) ) + { + retry_get_notifications (bn); + return; + } + req = (const struct BlacklistMessage*) msg; + bn->notify (bn->notify_cls, + &req->peer, + GNUNET_TIME_absolute_ntoh (req->until)); + GNUNET_CLIENT_receive (bn->client, + &recv_blacklist_info, + bn, + GNUNET_TIME_UNIT_FOREVER_REL); +} + + +/** + * Function called to notify a client about the socket + * begin ready to queue more data. "buf" will be + * NULL and "size" zero if the socket was closed for + * writing in the meantime. + * + * @param cls closure + * @param size number of bytes available in buf + * @param buf where the callee should write the message + * @return number of bytes written to buf + */ +static size_t +transmit_notify_request (void *cls, + size_t size, void *buf) +{ + struct GNUNET_TRANSPORT_BlacklistNotification *bn = cls; + struct GNUNET_MessageHeader hdr; + + bn->th = NULL; + if (buf == NULL) + { + retry_get_notifications (bn); + return 0; + } + GNUNET_assert (size >= sizeof(hdr)); + hdr.size = htons (sizeof (hdr)); + hdr.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_NOTIFY); + memcpy (buf, &hdr, sizeof(hdr)); + return sizeof(hdr); +} + + +/** + * Send a request to receive blacklisting notifications + * + * @param bn context to initialize + */ +static void +request_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn) +{ + GNUNET_assert (bn->client != NULL); + bn->th = GNUNET_CLIENT_notify_transmit_ready (bn->client, + sizeof (struct GNUNET_MessageHeader), + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, + &transmit_notify_request, + bn); + GNUNET_assert (bn->th != NULL); + GNUNET_CLIENT_receive (bn->client, + &recv_blacklist_info, + bn, + GNUNET_TIME_UNIT_FOREVER_REL); +} + + +/** + * Call a function whenever a peer's blacklisting status changes. + * + * @param sched scheduler to use + * @param cfg configuration to use + * @param bc function to call on status changes + * @param bc_cls closure for bc + * @return NULL on error, otherwise handle for cancellation + */ +struct GNUNET_TRANSPORT_BlacklistNotification * +GNUNET_TRANSPORT_blacklist_notify (struct GNUNET_SCHEDULER_Handle *sched, + const struct GNUNET_CONFIGURATION_Handle *cfg, + GNUNET_TRANSPORT_BlacklistCallback bc, + void *bc_cls) +{ + struct GNUNET_TRANSPORT_BlacklistNotification *ret; + struct GNUNET_CLIENT_Connection * client; + + client = GNUNET_CLIENT_connect (sched, "transport", cfg); + if (NULL == client) + return NULL; + ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_BlacklistNotification)); + ret->client = client; + ret->sched = sched; + ret->cfg = cfg; + ret->notify = bc; + ret->notify_cls = bc_cls; + request_notifications (ret); + return ret; +} + + +/** + * Stop calling the notification callback associated with + * the given blacklist notification. + * + * @param bn handle of the request that is to be cancelled + */ +void +GNUNET_TRANSPORT_blacklist_notify_cancel (struct GNUNET_TRANSPORT_BlacklistNotification * bn) +{ + if (bn->th != NULL) + GNUNET_CLIENT_notify_transmit_ready_cancel (bn->th); + GNUNET_CLIENT_disconnect (bn->client); + GNUNET_free (bn); +} + +/* end of transport_api_blacklist.c */ -- cgit v1.2.3