gnunet-secushare/src/multicast/test_multicast_2peers.c

521 строка
16 KiB
C
Исходник Обычный вид История

2019-02-11 19:39:36 +00:00
/*
* This file is part of GNUnet
* Copyright (C) 2013 GNUnet e.V.
*
* GNUnet is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* 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
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
* @file multicast/test_multicast_2peers.c
* @brief Tests for the Multicast API with two peers doing the ping
* pong test.
* @author xrs
*/
#include <inttypes.h>
#include "platform.h"
#include "gnunet_crypto_lib.h"
#include "gnunet_common.h"
#include "gnunet_util_lib.h"
#include "gnunet_testbed_service.h"
#include "gnunet_multicast_service.h"
#define NUM_PEERS 2
static struct GNUNET_TESTBED_Operation *op0;
static struct GNUNET_TESTBED_Operation *op1;
static struct GNUNET_TESTBED_Operation *pi_op0;
static struct GNUNET_TESTBED_Operation *pi_op1;
static struct GNUNET_TESTBED_Peer **peers;
const struct GNUNET_PeerIdentity *peer_id[2];
static struct GNUNET_SCHEDULER_Task *timeout_tid;
static struct GNUNET_MULTICAST_Origin *origin;
static struct GNUNET_MULTICAST_Member *member;
struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key;
struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
/**
* Global result for testcase.
*/
static int result;
/**
* Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
* Cleans up.
*/
static void
shutdown_task (void *cls)
{
if (NULL != op0)
{
GNUNET_TESTBED_operation_done (op0);
op0 = NULL;
}
if (NULL != op1)
{
GNUNET_TESTBED_operation_done (op1);
op1 = NULL;
}
if (NULL != pi_op0)
{
GNUNET_TESTBED_operation_done (pi_op0);
pi_op0 = NULL;
}
if (NULL != pi_op1)
{
GNUNET_TESTBED_operation_done (pi_op1);
pi_op1 = NULL;
}
if (NULL != timeout_tid)
{
GNUNET_SCHEDULER_cancel (timeout_tid);
timeout_tid = NULL;
}
}
static void
timeout_task (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Timeout!\n");
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}
static void
member_join_request (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
const struct GNUNET_MessageHeader *join_msg,
struct GNUNET_MULTICAST_JoinHandle *jh)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Member sent a join request.\n");
}
static int
notify (void *cls,
size_t *data_size,
void *data)
{
char text[] = "ping";
*data_size = strlen(text)+1;
GNUNET_memcpy(data, text, *data_size);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Member sents message to origin: %s\n", text);
return GNUNET_YES;
}
static void
member_join_decision (void *cls,
int is_admitted,
const struct GNUNET_PeerIdentity *peer,
uint16_t relay_count,
const struct GNUNET_PeerIdentity *relays,
const struct GNUNET_MessageHeader *join_msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Member received a decision from origin: %s\n",
(GNUNET_YES == is_admitted)
? "accepted"
: "rejected");
if (GNUNET_YES == is_admitted)
{
struct GNUNET_MULTICAST_MemberTransmitHandle *req;
// FIXME: move to MQ-style API!
req = GNUNET_MULTICAST_member_to_origin (member,
0,
&notify,
NULL);
}
}
static void
member_message (void *cls,
const struct GNUNET_MULTICAST_MessageHeader *msg)
{
if (0 != strncmp ("pong", (char *)&msg[1], 4))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "member did not receive pong\n");
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"member receives: %s\n", (char *)&msg[1]);
// Testcase ends here.
result = GNUNET_YES;
GNUNET_SCHEDULER_shutdown ();
}
static void
origin_join_request (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
const struct GNUNET_MessageHeader *join_msg,
struct GNUNET_MULTICAST_JoinHandle *jh)
{
struct GNUNET_MessageHeader *join_resp;
uint8_t data_size = ntohs (join_msg->size);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"origin got a join request...\n");
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"origin receives: '%s'\n", (char *)&join_msg[1]);
const char data[] = "Come in!";
data_size = strlen (data) + 1;
join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
join_resp->size = htons (sizeof (join_resp) + data_size);
join_resp->type = htons (123);
GNUNET_memcpy (&join_resp[1], data, data_size);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"origin sends: '%s'\n", data);
GNUNET_MULTICAST_join_decision (jh,
GNUNET_YES,
0,
NULL,
join_resp);
GNUNET_free (join_resp);
result = GNUNET_OK;
}
int
origin_notify (void *cls,
size_t *data_size,
void *data)
{
char text[] = "pong";
*data_size = strlen(text)+1;
GNUNET_memcpy (data,
text,
*data_size);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin sends (to all): %s\n", text);
return GNUNET_YES;
}
static void
origin_request (void *cls,
const struct GNUNET_MULTICAST_RequestHeader *req)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin receives: %s\n", (char *)&req[1]);
if (0 != strncmp ("ping", (char *)&req[1], 4))
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "origin didn't reveice a correct request");
GNUNET_MULTICAST_origin_to_all (origin,
0,
0,
origin_notify,
NULL);
}
static void
origin_message (void *cls,
const struct GNUNET_MULTICAST_MessageHeader *msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
}
static void
service_connect1 (void *cls,
struct GNUNET_TESTBED_Operation *op,
void *ca_result,
const char *emsg)
{
member = ca_result;
if (NULL == member)
{
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}
else
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to multicast service of member\n");
}
}
static void
multicast_da1 (void *cls,
void * op_result)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Member parting from multicast group\n");
GNUNET_MULTICAST_member_part (member, NULL, NULL);
}
static void *
multicast_ca1 (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct GNUNET_MessageHeader *join_msg;
void *ret;
// Get members keys
member_key = GNUNET_CRYPTO_ecdsa_key_create ();
GNUNET_CRYPTO_ecdsa_key_get_public (member_key, &member_pub_key);
char data[] = "Hi, can I enter?";
uint8_t data_size = strlen (data) + 1;
join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
join_msg->size = htons (sizeof (join_msg) + data_size);
join_msg->type = htons (123);
GNUNET_memcpy (&join_msg[1], data, data_size);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Members tries to join multicast group\n");
ret = GNUNET_MULTICAST_member_join (cfg,
&group_pub_key,
member_key,
peer_id[0],
0,
NULL,
join_msg, /* join message */
member_join_request,
member_join_decision,
NULL, /* no test for member_replay_frag */
NULL, /* no test for member_replay_msg */
member_message,
NULL);
GNUNET_free (join_msg);
return ret;
}
static void
peer_information_cb (void *cls,
struct GNUNET_TESTBED_Operation *op,
const struct GNUNET_TESTBED_PeerInformation *pinfo,
const char *emsg)
{
int i = (int) (long) cls;
if (NULL == pinfo)
{
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_shutdown ();
}
peer_id[i] = pinfo->result.id;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Got peer information of %s (%s)\n", (0==i)?"origin":"member" ,GNUNET_i2s(pinfo->result.id));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Create member peer\n");
if (0 == i)
{
/* connect to multicast service of member */
op1 = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */
peers[1], /* The peer whose service to connect to */
"multicast", /* The name of the service */
service_connect1, /* callback to call after a handle to service
is opened */
NULL, /* closure for the above callback */
multicast_ca1, /* callback to call with peer's configuration;
this should open the needed service connection */
multicast_da1, /* callback to be called when closing the
opened service connection */
NULL); /* closure for the above two callbacks */
}
}
/**
* Test logic of peer "0" being origin starts here.
*
* @param cls closure, for the example: NULL
* @param op should be equal to "dht_op"
* @param ca_result result of the connect operation, the
* connection to the DHT service
* @param emsg error message, if testbed somehow failed to
* connect to the DHT.
*/
static void
service_connect0 (void *cls,
struct GNUNET_TESTBED_Operation *op,
void *ca_result,
const char *emsg)
{
origin = ca_result;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Connected to multicast service of origin\n");
// Get GNUnet identity of origin
pi_op0 = GNUNET_TESTBED_peer_get_information (peers[0],
GNUNET_TESTBED_PIT_IDENTITY,
peer_information_cb,
(void *) 0);
// Get GNUnet identity of member
pi_op1 = GNUNET_TESTBED_peer_get_information (peers[1],
GNUNET_TESTBED_PIT_IDENTITY,
peer_information_cb,
(void *) 1);
/* Connection to service successful. Here we'd usually do something with
* the service. */
result = GNUNET_OK;
//GNUNET_SCHEDULER_shutdown (); /* Also kills the testbed */
}
/**
* Function run when service multicast has started and is providing us
* with a configuration file.
*/
static void *
multicast_ca0 (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
group_key = GNUNET_CRYPTO_eddsa_key_create ();
GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);
return GNUNET_MULTICAST_origin_start (cfg,
group_key,
0,
origin_join_request,
NULL, /* no test for origin_replay_frag */
NULL, /* no test for origin_replay_msg */
origin_request,
origin_message,
NULL);
}
static void
multicast_da0 (void *cls,
void *op_result)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Origin closes multicast group\n");
GNUNET_MULTICAST_origin_stop (origin, NULL, NULL);
}
/**
* Main function inovked from TESTBED once all of the
* peers are up and running. This one then connects
* just to the multicast service of peer 0 and 1.
* Peer 0 is going to be origin.
* Peer 1 is going to be one member.
* Origin will start a multicast group and the member will try to join it.
* After that we execute some multicast test.
*
* @param cls closure
* @param h the run handle
* @param peers started peers for the test
* @param num_peers size of the 'peers' array
* @param links_succeeded number of links between peers that were created
* @param links_failed number of links testbed was unable to establish
*/
static void
testbed_master (void *cls,
struct GNUNET_TESTBED_RunHandle *h,
unsigned int num_peers,
struct GNUNET_TESTBED_Peer **p,
unsigned int links_succeeded,
unsigned int links_failed)
{
/* Testbed is ready with peers running and connected in a pre-defined overlay
topology (FIXME) */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Connected to testbed_master()\n");
peers = p;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Create origin peer\n");
op0 = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */
peers[0], /* The peer whose service to connect to */
"multicast", /* The name of the service */
service_connect0, /* callback to call after a handle to service
is opened */
NULL, /* closure for the above callback */
multicast_ca0, /* callback to call with peer's configuration;
this should open the needed service connection */
multicast_da0, /* callback to be called when closing the
opened service connection */
NULL); /* closure for the above two callbacks */
GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */
/* Schedule the shutdown task with a delay of a few Seconds */
timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 50),
&timeout_task, NULL);
}
int
main (int argc, char *argv[])
{
int ret;
result = GNUNET_SYSERR;
ret = GNUNET_TESTBED_test_run
("test-multicast-2peers", /* test case name */
"test_multicast.conf", /* template configuration */
NUM_PEERS, /* number of peers to start */
0LL, /* Event mask - set to 0 for no event notifications */
NULL, /* Controller event callback */
NULL, /* Closure for controller event callback */
testbed_master, /* continuation callback to be called when testbed setup is complete */
NULL); /* Closure for the test_master callback */
if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
return 1;
return 0;
}
/* end of test_multicast_2peers.c */