/*
This file is part of GNUnet.
Copyright (C) 2010-2015 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/**
* @file ats/test_ats_lib.c
* @brief test ATS library with a generic interpreter for running ATS tests
* @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_ats_service.h"
#include "gnunet_testing_lib.h"
#include "test_ats_lib.h"
/**
* Information about the last address suggestion we got for a peer.
*/
struct AddressSuggestData
{
/**
* Which session were we given?
*/
struct GNUNET_ATS_Session *session;
/**
* What address was assigned?
*/
struct GNUNET_HELLO_Address *address;
/**
* Outbound bandwidth assigned.
*/
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
/**
* Inbound bandwidth assigned.
*/
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
/**
* Was the bandwidth assigned non-zero?
*/
int active;
};
/**
* Information about the last address information we got for an address.
*/
struct AddressInformationData
{
/**
* What address is this data about?
*/
struct GNUNET_HELLO_Address *address;
/**
* Which properties were given?
*/
struct GNUNET_ATS_Properties properties;
/**
* Outbound bandwidth reported.
*/
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
/**
* Inbound bandwidth reported.
*/
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
/**
* Was the address said to be 'active'?
*/
int active;
};
/**
* Scheduling handle
*/
static struct GNUNET_ATS_SchedulingHandle *sched_ats;
/**
* Connectivity handle
*/
static struct GNUNET_ATS_ConnectivityHandle *con_ats;
/**
* Performance handle
*/
static struct GNUNET_ATS_PerformanceHandle *perf_ats;
/**
* Handle for the interpreter task.
*/
static struct GNUNET_SCHEDULER_Task *interpreter_task;
/**
* Map from peer identities to the last address suggestion
* `struct AddressSuggestData` we got for the respective peer.
*/
static struct GNUNET_CONTAINER_MultiPeerMap *p2asd;
/**
* Map from peer identities to the last address information
* sets for all addresses of this peer. Each peer is mapped
* to one or more `struct AddressInformationData` entries.
*/
static struct GNUNET_CONTAINER_MultiPeerMap *p2aid;
/**
* Global timeout for the test.
*/
static struct GNUNET_TIME_Relative TIMEOUT;
/**
* Return value from #main().
*/
static int ret;
/**
* Current global command offset into the #commands array.
*/
static unsigned int off;
/**
* Commands for the current test.
*/
static struct Command *test_commands;
/**
* Free `struct AddressSuggestData` entry.
*
* @param cls NULL
* @param key ignored
* @param value the `struct AddressSuggestData` to release
* @return #GNUNET_OK (continue to iterate)
*/
static int
free_asd (void *cls,
const struct GNUNET_PeerIdentity *key,
void *value)
{
struct AddressSuggestData *asd = value;
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multipeermap_remove (p2asd,
key,
asd));
GNUNET_free_non_null (asd->address);
GNUNET_free (asd);
return GNUNET_OK;
}
/**
* Free `struct AddressInformationData` entry.
*
* @param cls NULL
* @param key ignored
* @param value the `struct AddressSuggestData` to release
* @return #GNUNET_OK (continue to iterate)
*/
static int
free_aid (void *cls,
const struct GNUNET_PeerIdentity *key,
void *value)
{
struct AddressInformationData *aid = value;
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multipeermap_remove (p2aid,
key,
aid));
GNUNET_free (aid->address);
GNUNET_free (aid);
return GNUNET_OK;
}
/**
* Find latest address suggestion made for the given peer.
*
* @param pid peer to look up
* @return NULL if peer was never involved
*/
static struct AddressSuggestData *
find_address_suggestion (const struct GNUNET_PeerIdentity *pid)
{
return GNUNET_CONTAINER_multipeermap_get (p2asd,
pid);
}
/**
* Closure for #match_address()
*/
struct MatchAddressContext
{
/**
* Address to find.
*/
const struct GNUNET_HELLO_Address *addr;
/**
* Where to return address information if found.
*/
struct AddressInformationData *ret;
};
/**
* Find matching address information.
*
* @param cls a `struct MatchAddressContext`
* @param key unused
* @param value a `struct AddressInformationData`
* @return #GNUNET_OK if not found
*/
static int
match_address (void *cls,
const struct GNUNET_PeerIdentity *key,
void *value)
{
struct MatchAddressContext *mac = cls;
struct AddressInformationData *aid = value;
if (0 == GNUNET_HELLO_address_cmp (mac->addr,
aid->address))
{
mac->ret = aid;
return GNUNET_NO;