#include "CUnit/Theory.h"
#include "dds/ddsrt/cdtors.h"
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/endian.h"
#include "dds/ddsrt/environ.h"
#include "dds/ddsi/ddsi_iid.h"
#include "dds/ddsi/ddsi_proxy_participant.h"
#include "dds/ddsi/ddsi_entity_index.h"
#include "dds/ddsi/ddsi_domaingv.h"
#include "dds/ddsi/ddsi_thread.h"
#include "dds/ddsi/ddsi_init.h"
#include "dds/ddsi/ddsi_plist.h"
#include "dds/ddsi/ddsi_serdata.h"
#include "dds/ddsc/dds_data_type_properties.h"
#include "ddsi__addrset.h"
#include "ddsi__participant.h"
#include "ddsi__proxy_participant.h"
#include "ddsi__endpoint.h"
#include "ddsi__proxy_endpoint.h"
#include "ddsi__plist.h"
#include "ddsi__radmin.h"
#include "ddsi__xmsg.h"
#include "ddsi__vendor.h"
#include "ddsi__receive.h"
#include "ddsi__tran.h"
#include "ddsi__protocol.h"
#include "ddsi__radmin.h"
#include "ddsi__wraddrset.h"
#include "ddsi__vnet.h"
static struct ddsi_cfgst *cfgst;
static struct ddsi_domaingv gv;
static void setup (void)
{
ddsrt_init ();
ddsi_iid_init ();
ddsi_thread_states_init ();
const char *config = "";
(void) ddsrt_getenv ("CYCLONEDDS_URI", &config);
cfgst = ddsi_config_init (config, &gv.config, 0);
assert (cfgst != NULL);
ddsi_config_prep (&gv, cfgst);
gv.config.multiple_recv_threads = false;
ddsi_init (&gv, NULL);
ddsi_vnet_init (&gv, "psmx", DDSI_LOCATOR_KIND_PSMX);
}
static void teardown (void)
{
ddsi_fini (&gv);
ddsi_config_fini (cfgst);
ddsi_iid_fini ();
ddsi_thread_states_fini ();
ddsrt_fini ();
}
static void setup_and_start (void)
{
setup ();
dds_log_cfg_init (&gv.logconfig, gv.config.domainId, DDS_LC_CONTENT , stdout, stdout);
ddsi_set_deafmute (&gv, true, true, DDS_INFINITY);
ddsi_start (&gv);
struct ddsi_thread_state * const thrst = ddsi_lookup_thread_state ();
assert (thrst->state == DDSI_THREAD_STATE_LAZILY_CREATED);
thrst->state = DDSI_THREAD_STATE_ALIVE;
ddsrt_atomic_stvoidp (&thrst->gv, &gv);
}
static void stop_and_teardown (void)
{
struct ddsi_thread_state * const thrst = ddsi_lookup_thread_state ();
thrst->state = DDSI_THREAD_STATE_LAZILY_CREATED;
ddsi_stop (&gv);
teardown ();
}
static void sertype_free (struct ddsi_sertype *st) { (void) st; }
static void whc_free (struct ddsi_whc *whc) { (void) whc; }
static void whc_get_state (const struct ddsi_whc *whc, struct ddsi_whc_state *st)
{
(void) whc;
st->max_seq = st->min_seq = st->unacked_bytes = 0;
}
static uint32_t whc_remove_acked_messages (struct ddsi_whc *whc, ddsi_seqno_t max_drop_seq, struct ddsi_whc_state *whcst, struct ddsi_whc_node **deferred_free_list)
{
(void) whc; (void) max_drop_seq; (void) whcst; (void) deferred_free_list;
return 0;
}
static void whc_free_deferred_free_list (struct ddsi_whc *whc, struct ddsi_whc_node *deferred_free_list)
{
(void) whc; (void) deferred_free_list;
}
static void ddsi_wraddrset_some_cases (int casenumber, int cost, bool wr_psmx, const int nrds[4])
{
#define UNILOC(k) { .kind = DDSI_LOCATOR_KIND_UDPv4, .address = {0,0,0,0, 0,0,0,0, 0,0,0,0, 192,16,1,k+1}, .port = 7410 }
#define PSMXLOC(k) { .kind = DDSI_LOCATOR_KIND_PSMX, .address = {k+1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, .port = 123 }
const ddsi_locator_t ucloc[4] = { UNILOC(0), UNILOC(1), UNILOC(2), UNILOC(3) };
const ddsi_locator_t psmxloc[4] = { PSMXLOC(0), PSMXLOC(1), PSMXLOC(2), PSMXLOC(3) };
const ddsi_locator_t mcloc = {
.kind = DDSI_LOCATOR_KIND_UDPv4, .address = {0,0,0,0, 0,0,0,0, 0,0,0,0, 239,255,0,1}, .port = 7400
};
#define UNILOC1(k) { .next = NULL, .loc = ucloc[k] }
const struct ddsi_locators_one ucloc1[4] = { UNILOC1(0), UNILOC1(1), UNILOC1(2), UNILOC1(3) };
const struct ddsi_locators_one mcloc1 = { .next = NULL, .loc = mcloc };
#define UNILOCS(k) { .n = 1, .first = (struct ddsi_locators_one *) &ucloc1[k], .last = (struct ddsi_locators_one *) &ucloc1[k] }
const ddsi_locators_t uclocs[4] = { UNILOCS(0), UNILOCS(1), UNILOCS(2), UNILOCS(3) };
const ddsi_locators_t mclocs = { .n = 1, .first = (struct ddsi_locators_one *) &mcloc1, .last = (struct ddsi_locators_one *) &mcloc1 };
#define PLIST_PP(k) { \
.present = PP_UNICAST_LOCATOR | PP_MULTICAST_LOCATOR | PP_DEFAULT_UNICAST_LOCATOR | PP_DEFAULT_MULTICAST_LOCATOR, \
.unicast_locators = uclocs[k], \
.multicast_locators = mclocs, \
.default_unicast_locators = uclocs[k], \
.default_multicast_locators = mclocs, \
.metatraffic_unicast_locators = uclocs[k], \
.metatraffic_multicast_locators = mclocs, \
.qos = { \
.present = DDSI_QP_LIVELINESS, \
.liveliness = { .kind = DDS_LIVELINESS_AUTOMATIC, .lease_duration = DDS_INFINITY } \
} \
}
const ddsi_plist_t plist_pp[4] = { PLIST_PP(0), PLIST_PP(1), PLIST_PP(2), PLIST_PP(3) };
ddsi_guid_t wrppguid, rdppguid[4][3];
setup_and_start ();
ddsi_thread_state_awake (ddsi_lookup_thread_state(), &gv);
ddsi_generate_participant_guid (&wrppguid, &gv);
ddsi_new_participant (&wrppguid, &gv, 0, &plist_pp[0]);
const struct ddsi_sertype st = {
.ops = &(struct ddsi_sertype_ops){ .free = sertype_free },
.serdata_ops = &(struct ddsi_serdata_ops){ NULL },
.serdata_basehash = 0,
.has_key = 0,
.request_keyhash = 0,
.is_memcpy_safe = 1,
.allowed_data_representation = DDS_DATA_REPRESENTATION_RESTRICT_DEFAULT,
.type_name = "Q",
.gv = DDSRT_ATOMIC_VOIDP_INIT (&gv),
.flags_refc = DDSRT_ATOMIC_UINT32_INIT (0),
.base_sertype = NULL,
.sizeof_type = 8,
.data_type_props = DDS_DATA_TYPE_IS_MEMCPY_SAFE
};
struct ddsi_participant *pp = ddsi_entidx_lookup_participant_guid (gv.entity_index, &wrppguid);
struct ddsi_writer *wr;
ddsi_guid_t wrguid;
struct ddsi_psmx_locators_set psmx_locs = { .length = 1, .locators = (struct ddsi_locator *) &psmxloc[0] };
struct ddsi_whc whc = {
.ops = &(struct ddsi_whc_ops){
.get_state = whc_get_state,
.remove_acked_messages = whc_remove_acked_messages,
.free_deferred_free_list = whc_free_deferred_free_list,
.free = whc_free
}
};
dds_return_t ret = ddsi_generate_writer_guid (&wrguid, pp, &st);
assert (ret == DDS_RETCODE_OK);
(void) ret;
ddsi_new_writer (&wr, &wrguid, NULL, pp, "Q", &st, &ddsi_default_qos_writer, &whc, NULL, NULL, wr_psmx ? &psmx_locs : NULL);
assert (ddsi_entidx_lookup_writer_guid (gv.entity_index, &wrguid));
struct ddsi_tran_conn fake_conn = {
.m_factory = ddsi_factory_find_supported_kind (&gv, DDSI_LOCATOR_KIND_PSMX),
.m_interf = &(struct ddsi_network_interface){
.prefer_multicast = false,
.priority = 1000000
}
};
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < nrds[i]; j++)
{
rdppguid[i][j] = (ddsi_guid_t){
.prefix = { .u = { 0, (unsigned) i, (unsigned) j } },
.entityid = { .u = DDSI_ENTITYID_PARTICIPANT }
};
struct ddsi_addrset *proxypp_as = ddsi_new_addrset ();
struct ddsi_proxy_participant *proxy_participant;
ddsi_locator_t loc = ucloc[i]; loc.port = 1000 + (unsigned) j;
ddsi_add_locator_to_addrset (&gv, proxypp_as, &loc);
ddsi_add_locator_to_addrset (&gv, proxypp_as, &mcloc);
ddsi_new_proxy_participant (&proxy_participant, &gv, &rdppguid[i][j], 0, proxypp_as, ddsi_ref_addrset (proxypp_as), &plist_pp[i], DDS_INFINITY, DDSI_VENDORID_ECLIPSE, ddsrt_time_wallclock (), 1);
assert (proxy_participant != NULL);
const ddsi_guid_t rdguid = {
.prefix = rdppguid[i][j].prefix,
.entityid = { .u = DDSI_ENTITYID_ALLOCSTEP | DDSI_ENTITYID_SOURCE_USER | DDSI_ENTITYID_KIND_READER_NO_KEY }
};
ddsi_plist_t plist_rd = { .present = 0, .qos = ddsi_default_qos_reader };
plist_rd.qos.present |= DDSI_QP_TOPIC_NAME | DDSI_QP_TYPE_NAME;
plist_rd.qos.reliability.kind = DDS_RELIABILITY_RELIABLE;
plist_rd.qos.topic_name = "Q";
plist_rd.qos.type_name = "Q";
struct ddsi_addrset *rd_as = ddsi_new_addrset ();
ddsi_add_locator_to_addrset (&gv, rd_as, &loc);
ddsi_add_locator_to_addrset (&gv, rd_as, &mcloc);
if (i == 0)
{
ddsi_add_xlocator_to_addrset (&gv, rd_as, &(ddsi_xlocator_t){ .conn = &fake_conn, .c = psmxloc[i] });
}
struct ddsi_proxy_reader *proxy_reader;
#if DDSRT_HAVE_SSM
ddsi_new_proxy_reader (&proxy_reader, &gv, &rdppguid[i][j], &rdguid, rd_as, &plist_rd, ddsrt_time_wallclock (), 1, false);
#else
ddsi_new_proxy_reader (&proxy_reader, &gv, &rdppguid[i][j], &rdguid, rd_as, &plist_rd, ddsrt_time_wallclock (), 1);
#endif
assert (proxy_reader);
ddsi_unref_addrset (rd_as);
}
}
if (casenumber == 0)
DDS_CLOG (DDS_LC_CONTENT, &gv.logconfig, " #rd/host cost: addresses\n");
DDS_CLOG (DDS_LC_CONTENT, &gv.logconfig, "%2d ", casenumber+1);
for (int i = 0; i < 4; i++)
DDS_CLOG (DDS_LC_CONTENT, &gv.logconfig, " %d", nrds[i]);
DDS_CLOG (DDS_LC_CONTENT, &gv.logconfig, " %2dms", cost);
ddsi_log_addrset (&gv, DDS_LC_CONTENT, ": {", wr->as);
DDS_CLOG (DDS_LC_CONTENT, &gv.logconfig, " }");
if (wr->c.psmx_locators.length)
DDS_CLOG (DDS_LC_CONTENT, &gv.logconfig, " + psmx");
DDS_CLOG (DDS_LC_CONTENT, &gv.logconfig, "\n");
ddsi_thread_state_asleep (ddsi_lookup_thread_state ());
stop_and_teardown ();
}
CU_Test (ddsi_wraddrset, some_cases)
{
const struct {
int nrds[4];
int cost;
} cases[] = {
{{0, 0, 0, 0}, 7},
{{1, 0, 0, 0}, 7},
{{2, 0, 0, 0}, 7},
{{0, 1, 1, 0}, 7},
{{1, 1, 0, 0}, 8},
{{1, 1, 1, 0}, 8},
{{2, 1, 0, 0}, 12},
{{2, 1, 1, 0}, 16},
{{3, 1, 1, 0}, 16},
{{2, 1, 1, 1}, 20}
};
for (size_t k = 0; k < sizeof (cases) / sizeof (cases[0]); k++)
{
ddsi_wraddrset_some_cases ((int) k, cases[k].cost, true, cases[k].nrds);
}
CU_PASS ("I want to keep this code, but I don't know yet what the test expectation should be ...");
}