/*
This file is part of GNUnet.
(C) 2009, 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 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 integration-tests/connection_watchdog.c
* @brief tool to monitor core and transport connections for consistency
* @author Matthias Wachs
*/
#include "platform.h"
#include "gnunet_common.h"
#include "gnunet_constants.h"
#include "gnunet_arm_service.h"
#include "gnunet_core_service.h"
#include "gnunet_getopt_lib.h"
#include "gnunet_os_lib.h"
#include "gnunet_program_lib.h"
#include "gnunet_scheduler_lib.h"
#include "gnunet_transport_service.h"
#include "gnunet_statistics_service.h"
#define CHECK_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
#define STATS_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
#define REPEATED_STATS_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
#define STATS_VALUES 4
/**
* Final status code.
*/
static int ret;
static int ping;
static int have_tcp;
static int have_udp;
static int have_http;
static int have_https;
static int have_unix;
static struct GNUNET_TRANSPORT_Handle *th;
static struct GNUNET_CORE_Handle *ch;
static struct GNUNET_PeerIdentity my_peer_id;
static const struct GNUNET_CONFIGURATION_Handle *mycfg;
static struct GNUNET_STATISTICS_Handle *stats;
static unsigned int transport_connections;
static unsigned int core_connections;
static GNUNET_SCHEDULER_TaskIdentifier check_task;
static GNUNET_SCHEDULER_TaskIdentifier statistics_task;
static uint64_t statistics_transport_connections;
static uint64_t statistics_transport_tcp_connections;
static uint64_t statistics_core_neighbour_entries;
static uint64_t statistics_core_entries_session_map;
int stat_check_running;
static struct GNUNET_CONTAINER_MultiHashMap *peers;
struct PeerContainer
{
struct GNUNET_PeerIdentity id;
int transport_connected;
int core_connected;
struct GNUNET_TRANSPORT_TransmitHandle *th_ping;
struct GNUNET_CORE_TransmitHandle *ch_ping;
struct GNUNET_TRANSPORT_TransmitHandle *th_pong;
struct GNUNET_CORE_TransmitHandle *ch_pong;
};
enum protocol
{
tcp,
udp,
unixdomain
};
struct TransportPlugin
{
/**
* This is a doubly-linked list.
*/
struct TransportPlugin *next;
/**
* This is a doubly-linked list.
*/
struct TransportPlugin *prev;
/**
* Short name for the plugin (i.e. "tcp").
*/
char *short_name;
int port;
int protocol;
};
struct TransportPlugin *phead;
struct TransportPlugin *ptail;
static int
map_check_it (void *cls,
const struct GNUNET_HashCode * key,
void *value)
{
int *fail = cls;
struct PeerContainer *pc = value;
if (pc->core_connected != pc->transport_connected)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Inconsistent peer `%s': TRANSPORT %s <-> CORE %s\n",
GNUNET_i2s (&pc->id),
(GNUNET_YES == pc->transport_connected) ? "YES" : "NO",
(GNUNET_YES == pc->core_connected) ? "YES" : "NO");
(*fail) ++;
}
return GNUNET_OK;
}
static int
map_cleanup_it (void *cls,
const struct GNUNET_HashCode * key,
void *value)
{
struct PeerContainer *pc = value;
GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove(peers, key, value));
if (NULL != pc->th_ping)
{
GNUNET_TRANSPORT_notify_transmit_ready_cancel(pc->th_ping);
pc->th_ping = NULL;
}
if (NULL != pc->th_pong)
{
GNUNET_TRANSPORT_notify_transmit_ready_cancel(pc->th_pong);
pc->th_pong = NULL;
}
if (NULL != pc->ch_ping)
{
GNUNET_CORE_notify_transmit_ready_cancel (pc->ch_ping);
pc->ch_ping = NULL;
}
if (NULL != pc->