/*
This file is part of GNUnet.
(C) 2010,2011 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 3, 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/gnunet-service-transport_clients.c
* @brief plugin management API
* @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet-service-transport_blacklist.h"
#include "gnunet-service-transport_clients.h"
#include "gnunet-service-transport_hello.h"
#include "gnunet-service-transport_neighbours.h"
#include "gnunet-service-transport_plugins.h"
#include "gnunet-service-transport_validation.h"
#include "gnunet-service-transport_manipulation.h"
#include "gnunet-service-transport.h"
#include "transport.h"
/**
* How many messages can we have pending for a given client process
* before we start to drop incoming messages? We typically should
* have only one client and so this would be the primary buffer for
* messages, so the number should be chosen rather generously.
*
* The expectation here is that most of the time the queue is large
* enough so that a drop is virtually never required. Note that
* this value must be about as large as 'TOTAL_MSGS' in the
* 'test_transport_api_reliability.c', otherwise that testcase may
* fail.
*/
#define MAX_PENDING (128 * 1024)
/**
* Linked list of messages to be transmitted to the client. Each
* entry is followed by the actual message.
*/
struct ClientMessageQueueEntry
{
/**
* This is a doubly-linked list.
*/
struct ClientMessageQueueEntry *next;
/**
* This is a doubly-linked list.
*/
struct ClientMessageQueueEntry *prev;
};
/**
* Client connected to the transport service.
*/
struct TransportClient
{
/**
* This is a doubly-linked list.
*/
struct TransportClient *next;
/**
* This is a doubly-linked list.
*/
struct TransportClient *prev;
/**
* Handle to the client.
*/
struct GNUNET_SERVER_Client *client;
/**
* Linked list of messages yet to be transmitted to
* the client.
*/
struct ClientMessageQueueEntry *message_queue_head;
/**
* Tail of linked list of messages yet to be transmitted to the
* client.
*/
struct ClientMessageQueueEntry *message_queue_tail;
/**
* Current transmit request handle.
*/
struct GNUNET_SERVER_TransmitHandle *th;
/**
* Length of the list of messages pending for this client.
*/
unsigned int message_count;
/**
* Is this client interested in payload messages?
*/
int send_payload;
};
/**
* Context for address to string operations
*/
struct AddressToStringContext
{
/**
* This is a doubly-linked list.
*/
struct AddressToStringContext *next;
/**
* This is a doubly-linked list.
*/
struct AddressToStringContext *prev;
/**
* Transmission context
*/
struct GNUNET_SERVER_TransmitContext* tc;
};
/**
* Client monitoring changes of active addresses of our neighbours.
*/
struct MonitoringClient
{
/**
* This is a doubly-linked list.
*/
struct MonitoringClient *next;
/**
* This is a doubly-linked list.
*/
struct MonitoringClient *prev;
/**
* Handle to the client.
*/
struct GNUNET_SERVER_Client *client;
/**
* Peer identity to monitor the addresses of.
* Zero to monitor all neighrours.
*/
struct GNUNET_PeerIdentity peer;
};
/**
* Head of linked list of all clients to this service.
*/
static struct TransportClient *clients_head;
/**
* Tail of linked list of all clients to this service.
*/
static struct TransportClient *clients_tail;
/**
* Head of linked list of all pending address iterations
*/
struct AddressToStringContext *a2s_head;
/**
* Tail of linked list of all pending address iterations
*/
struct AddressToStringContext *a2s_tail;
/**
* Head of linked list of monitoring clients.
*/
static struct MonitoringClient *monitoring_clients_head;
/**
* Tail of linked list of monitoring clients.
*/
static struct MonitoringClient *monitoring_clients_tail;
/**
* Notification context, to send updates on changes to active addresses
* of our neighbours.
*/
struct GNUNET_SERVER_NotificationContext *nc = NULL;
/**
* Find the internal handle associated with the given client handle
*
* @param client server's client handle to look up
* @return internal client handle
*/
static struct TransportClient *
lookup_client (struct GNUNET_SERVER_Client *client)
{
struct TransportClient *tc;
tc = clients_head;
while (tc != NULL)
{
if (tc->client == client)
return tc;
tc = tc->next;
}
return NULL;
}
/**
* Create the internal handle for the given server client handle
*
* @param client server's client handle to create our internal handle for
* @return fresh internal client handle
*/
static struct TransportClient *
setup_client (struct GNUNET_SERVER_Client *client)
{
struct TransportClient *tc;
GNUNET_assert (lookup_client (client) == NULL);
tc = GNUNET_malloc (sizeof (struct TransportClient));
tc->client = client;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc);
return tc;
}
/**
* Find the handle to the monitoring client associated with the given
* client handle
*
* @param client server's client handle to look up
* @return handle to the monitoring client
*/
static