Commit feb400cf authored by Pavel Vainerman's avatar Pavel Vainerman Committed by Pavel Vainerman

[unet-multicast]: config refactoring

parent f34a0dfa
......@@ -31,7 +31,7 @@ namespace uniset
{
public:
static std::unique_ptr<MulticastReceiveTransport> createFromXml(UniXML::iterator it, const std::string& defaultIP, int numChan, const std::string& defIface = "", const std::string& section = "receive");
static std::unique_ptr<MulticastReceiveTransport> createFromXml(UniXML::iterator it, int numChan);
static xmlNode* getReceiveListNode( UniXML::iterator root );
MulticastReceiveTransport( const std::string& bind, int port, const std::vector<Poco::Net::IPAddress>& joinGroups, const std::string& iface = "" );
......@@ -49,6 +49,7 @@ namespace uniset
bool isReadyForReceive( timeout_t tout ) override;
virtual ssize_t receive(void* r_buf, size_t sz) override;
std::string iface() const;
protected:
std::unique_ptr <MulticastSocketU> udp;
......@@ -63,7 +64,7 @@ namespace uniset
{
public:
static std::unique_ptr<MulticastSendTransport> createFromXml( UniXML::iterator it, const std::string& defaultIP, int numChan );
static std::unique_ptr<MulticastSendTransport> createFromXml( UniXML::iterator it, int numChan );
MulticastSendTransport(const std::string& sockHost, int sockPort, const std::string& groupHost, int groupPort, int ttl = 1 );
virtual ~MulticastSendTransport();
......
......@@ -1095,19 +1095,11 @@ void UNetExchange::initMulticastTransport( UniXML::iterator n_it,
const std::string& n_fvalue,
const std::string& prefix )
{
auto conf = uniset_conf();
const string default_ip = n_it.getProp("unet_multicast_ip");
const string default_ip2 = n_it.getProp("unet_multicast_ip2");
const string default_iface1 = n_it.getProp("unet_multicast_iface1");
const string default_iface2 = n_it.getProp("unet_multicast_iface2");
if( !n_it.goChildren() )
throw uniset::SystemError("(UNetExchange): Items not found for <nodes>");
xmlNode* selfNode = nullptr;
// init senders
for( ; n_it.getCurrent(); n_it.goNext() )
{
......@@ -1123,106 +1115,62 @@ void UNetExchange::initMulticastTransport( UniXML::iterator n_it,
string n = n_it.getProp("name");
if( n == conf->getLocalNodeName() )
if( n != conf->getLocalNodeName() )
{
selfNode = n_it.getCurrent();
if( no_sender )
{
unetinfo << myname << "(init): " << n_it.getProp("name") << " sender DISABLED." << endl;
break;
}
initMulticastReceiverForNode(n_it, prefix);
continue;
}
unetinfo << myname << "(init): " << n_it.getProp("name") << " init sender.." << endl;
if( no_sender )
{
unetinfo << myname << "(init): " << n_it.getProp("name") << " sender DISABLED." << endl;
break;
}
auto s1 = MulticastSendTransport::createFromXml(n_it, default_ip, 0);
unetinfo << myname << "(init): " << n_it.getProp("name") << " send (channel1) to multicast group: " << s1->getGroupAddress().toString() << endl;
// INIT SENDER
unetinfo << myname << "(init): " << n_it.getProp("name") << " init sender.." << endl;
sender = make_shared<UNetSender>(std::move(s1), shm, false, s_field, s_fvalue, "unet", prefix);
loga->add(sender->getLog());
auto s1 = MulticastSendTransport::createFromXml(n_it, 0);
unetinfo << myname << "(init): " << n_it.getProp("name") << " send (channel1) to multicast group: " << s1->getGroupAddress().toString() << endl;
try
{
sender2 = nullptr;
sender = make_shared<UNetSender>(std::move(s1), shm, false, s_field, s_fvalue, "unet", prefix);
loga->add(sender->getLog());
if( n_it.getProp("unet_multicast_ip2").empty() || !default_ip2.empty() )
{
auto s2 = MulticastSendTransport::createFromXml(n_it, default_ip2, 2);
try
{
sender2 = nullptr;
if( s2 )
unetinfo << myname << "(init): " << n_it.getProp("name") << " send (channel2) to multicast group: " << s2->getGroupAddress().toString() << endl;
if( n_it.getProp("unet_multicast_ip2").empty() )
{
auto s2 = MulticastSendTransport::createFromXml(n_it, 2);
sender2 = make_shared<UNetSender>(std::move(s2), shm, false, s_field, s_fvalue, "unet", prefix);
}
if( s2 )
unetinfo << myname << "(init): " << n_it.getProp("name") << " send (channel2) to multicast group: " << s2->getGroupAddress().toString() << endl;
if( sender2 )
loga->add(sender2->getLog());
else
unetwarn << myname << "(ignore): " << n_it.getProp("name") << " sender for Channel2 disabled " << endl;
}
catch( std::exception& ex )
{
// т.е. это "резервный канал", то игнорируем ошибку его создания
// при запуске "интерфейс" может быть и не доступен...
sender2 = nullptr;
unetcrit << myname << "(init): IGNORE! channel2 create error: " << ex.what() << endl;
sender2 = make_shared<UNetSender>(std::move(s2), shm, false, s_field, s_fvalue, "unet", prefix);
}
break;
if( sender2 )
loga->add(sender2->getLog());
else
unetwarn << myname << "(ignore): " << n_it.getProp("name") << " sender for Channel2 disabled " << endl;
}
}
// INIT RECEIVERS
if( selfNode == nullptr )
{
unetwarn << myname << "(init): IGNORE! RECEIVE DISABLED.." << endl;
return;
}
UniXML::iterator it(selfNode);
if( !it.getIntProp("unet_multicast_receive_from_all_nodes") )
{
initMulticastReceiverForNode(n_it, default_ip, default_ip2, default_iface1, default_iface2, "receive", prefix);
return;
}
unetwarn << myname << "(init): init multicast group from nodes.." << endl;
// init receivers (by nodes)
for( ; n_it.getCurrent(); n_it.goNext() )
{
if( n_it.getIntProp("unet_ignore") )
catch( std::exception& ex )
{
unetinfo << myname << "(init): " << n_it.getProp("name") << " unet_ignore.." << endl;
continue;
// т.е. это "резервный канал", то игнорируем ошибку его создания
// при запуске "интерфейс" может быть и не доступен...
sender2 = nullptr;
unetcrit << myname << "(init): IGNORE! channel2 create error: " << ex.what() << endl;
}
// проверяем фильтры для подсетей
if( !uniset::check_filter(n_it, n_field, n_fvalue) )
continue;
string n = n_it.getProp("name");
if( n == conf->getLocalNodeName() )
continue;
initMulticastReceiverForNode(n_it, default_ip, default_ip2, default_iface1, default_iface2, "send", prefix);
}
}
// ----------------------------------------------------------------------------
void UNetExchange::initMulticastReceiverForNode(UniXML::iterator n_it,
const std::string& default_ip,
const std::string& default_ip2,
const std::string& default_iface1,
const std::string& default_iface2,
const std::string& section,
const std::string& prefix )
void UNetExchange::initMulticastReceiverForNode( UniXML::iterator n_it, const std::string& prefix )
{
auto conf = uniset_conf();
unetinfo << myname << "(init): " << n_it.getProp("name") << " init receivers:" << endl;
auto transport1 = MulticastReceiveTransport::createFromXml(n_it, default_ip, 0, default_iface1, section);
auto transport1 = MulticastReceiveTransport::createFromXml(n_it, 0);
if( checkExistTransport(transport1->ID()) )
{
......@@ -1355,12 +1303,12 @@ void UNetExchange::initMulticastReceiverForNode(UniXML::iterator n_it,
{
ostringstream err;
err << myname << ": " << n_it.getProp("name") << " : Unknown ChannelSwitchCountID.. Not found id for '" << channelswitchcount_id << "'" << endl;
unetcrit << myname << "(init): " << err.str() << endl;
unetcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
}
unetinfo << myname << "(init): (node='" << n_it.getProp("name") << "') add channel1 receiver " << transport1->ID() << " iface: " << default_iface1 << endl;
unetinfo << myname << "(init): (node='" << n_it.getProp("name") << "') add channel1 receiver " << transport1->ID() << " iface: " << transport1->iface() << endl;
unetinfo << myname << "(init): receive (channel1) from multicast groups: " << endl;
for( const auto& gr : transport1->getGroups() )
......@@ -1383,16 +1331,16 @@ void UNetExchange::initMulticastReceiverForNode(UniXML::iterator n_it,
{
std::unique_ptr<MulticastReceiveTransport> transport2 = nullptr;
if (!n_it.getProp("unet_multicast_ip2").empty() || !default_ip2.empty())
transport2 = MulticastReceiveTransport::createFromXml(n_it, default_ip2, 2, default_iface2, section);
if (!n_it.getProp("unet_multicast_ip2").empty() )
transport2 = MulticastReceiveTransport::createFromXml(n_it, 2);
if( transport2 ) // создаём читателя по второму каналу
{
unetinfo << myname << "(init): (node='" << n_it.getProp("name") << "') add channel2 receiver " << transport2->ID() << " iface: " << default_iface2 << endl;
unetinfo << myname << "(init): (node='" << n_it.getProp("name") << "') add channel2 receiver " << transport2->ID() << " iface: " << transport2->iface() << endl;
unetinfo << myname << "(init): receive(channel2) from multicast groups: " << endl;
for( const auto& gr : transport2->getGroups() )
unetinfo << myname << "(init): " << gr.toString() << endl;
unetinfo << myname << "(init): " << gr.toString() << endl;
r2 = make_shared<UNetReceiver>(std::move(transport2), shm, false, prefix);
......
......@@ -101,50 +101,38 @@ namespace uniset
--prefix-nodes-confnode name. По умолчанию настройка ведётся по секции <nodes>
\section pgUNetUDP_ConfMulticast Пример конфигурирования (Multicast)
По умолчанию при считывании используется \b unet_multicast_ip (указанный в секции \<nodes>)
и \b id узла - в качестве порта.
По умолчанию при считывании используется \b unet_multicast_ip и \b id узла - в качестве порта.
Но можно переопределиять эти параметры, при помощи указания \b unet_multicast_port и/или \b unet_multicast_ip,
у конкретного узла (\<item>).
Группы для подписки описываются в специальной секции \b \<multicast>. Секция \b \<recevive> описывает группы на которые
подписывается узел. Секция \b \<send> описывает в какие группы данный узел будет посылать сообщения.
Секция \b \<receive> не является обязательной и если узел должен слушать все другие узлы, то достаточно у узла
прописать свойство \b unet_multicast_receive_from_all_nodes="1". При этом узел подпишется
на все группы указанные в секции \b \<send>(!) других узлов, секция \<receive> при этом игнорируется.
Если свойство \b unet_multicast_receive_from_all_nodes="0" или не указано и создана пустая секция \b \<receive/>,
то узел \b не будет слушать и получать сообщения.
В секции \b \<nodes param1 param2 ...> можно задавать умолчательный адрес \b unet_multicast_default_ip1=".." и \b unet_multicast_default_ip2="..".
Помимо этого можно определить умолчательный интерфейс на котором происходит подключение к группам
\b unet_multicast_default_iface1=".." и \b unet_multicast_default_iface2="..".
При этом в параметре unet_multicast_ip должен быть задан адрес multicast-групы на которую будет
подписываться каждый receiver и в которую будет писать соответствующий sender.
По умолчанию для подключения к группе используется интерфейс ANY, но параметром
unet_multicast_iface="192.168.1.1" можно задать интерфейс через который ожидаются multicast-пакеты.
\warning В текущей реализации поддерживается только одна <send><group .../></send>!
Для посылающего процесса можно определить параметр \b unet_multicast_ttl задающий время жизни multicast пакетов.
По умолчанию ttl=1. А так же определить ip для сокета параметром \b unet_multicast_sender_ip. По умолчанию "0.0.0.0".
В данной реализации поддерживается работа в два канала. Соответствующие настройки для второго канала имеют индекс "2".
unet_multicast_ip2, unet_multicast_port2, unet_multicast_iface2
\code
<nodes port="2809" unet_broadcast_ip="192.168.56.255">
<item ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел" unet_ignore="1" unet_multicast_port="3000" unet_multicast_ip="192.168.57.255">
<item ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел" unet_ignore="10">
<iocards>
...
</iocards>
</item>
<item ip="192.168.56.10" name="Node1" textname="Node1" unet_multicast_port="3001" unet_update_strategy="evloop"
unet_multicast_receive_from_all_nodes="1">
<multicast>
<send>
<group addr="239.255.1.1" addr2="239.255.2.1"/>
</send>
</multicast>
<item id="3001" ip="192.168.56.10" name="Node1" textname="Node1" unet_update_strategy="evloop"
unet_multicast_ip="224.0.0.1"
unet_multicast_port2="3031"
unet_multicast_ip2="225.0.0.1">
...
</item>
<item ip="192.168.56.11" name="Node2" textname="Node2" unet_multicast_port="3002">
<multicast>
<receive>
<group addr="239.255.1.1" addr2="239.255.2.1"/>
</receive>
<send>
<group addr="239.255.1.1" addr2="239.255.2.1"/>
</send>
</multicast>
<item id="3002" ip="192.168.56.11" name="Node2" textname="Node2">
unet_multicast_ip="224.0.0.2"
unet_multicast_port2="3032"
unet_multicast_ip2="225.0.0.2">
...
</item>
</nodes>
\endcode
......@@ -255,13 +243,7 @@ namespace uniset
void termReceivers();
void initMulticastTransport( UniXML::iterator nodes, const std::string& n_field, const std::string& n_fvalue, const std::string& prefix );
void initMulticastReceiverForNode( UniXML::iterator n_it,
const std::string& default_ip1,
const std::string& default_ip2,
const std::string& default_iface1,
const std::string& default_iface2,
const std::string& section,
const std::string& prefix);
void initMulticastReceiverForNode( UniXML::iterator n_it, const std::string& prefix );
void initUDPTransport(UniXML::iterator nodes, const std::string& n_field, const std::string& n_fvalue, const std::string& prefix);
void initIterators() noexcept;
......
......@@ -24,16 +24,16 @@ TEST_CASE("[UNetUDP]: multicast setup", "[unetudp][multicast][config]")
REQUIRE( it.getName() == "item" );
REQUIRE( it.getProp("name") == "localhost" );
REQUIRE_NOTHROW( MulticastReceiveTransport::createFromXml(it, "192.168.0.1", 0 ) );
REQUIRE_NOTHROW( MulticastReceiveTransport::createFromXml(it, "192.168.1.1", 2 ) );
REQUIRE_NOTHROW( MulticastSendTransport::createFromXml(it, "192.168.0.1", 0 ) );
REQUIRE_NOTHROW( MulticastSendTransport::createFromXml(it, "192.168.1.1", 2 ) );
REQUIRE_NOTHROW( MulticastReceiveTransport::createFromXml(it, 0 ) );
REQUIRE_NOTHROW( MulticastReceiveTransport::createFromXml(it, 2 ) );
REQUIRE_NOTHROW( MulticastSendTransport::createFromXml(it, 0 ) );
REQUIRE_NOTHROW( MulticastSendTransport::createFromXml(it, 2 ) );
auto t1 = MulticastReceiveTransport::createFromXml(it, "192.168.1.1", 2 );
REQUIRE( t1->toString() == "127.0.1.1:2999" );
auto t1 = MulticastReceiveTransport::createFromXml(it, 2);
REQUIRE( t1->toString() == "225.0.0.1:3030" );
auto t2 = MulticastSendTransport::createFromXml(it, "192.168.1.1", 2 );
REQUIRE( t2->toString() == "127.0.1.1:2999" );
auto t2 = MulticastSendTransport::createFromXml(it, 2);
REQUIRE( t2->toString() == "0.0.0.0:3030" );
}
// -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: multicast transport", "[unetudp][multicast][transport]")
......@@ -47,12 +47,12 @@ TEST_CASE("[UNetUDP]: multicast transport", "[unetudp][multicast][transport]")
REQUIRE( it.getName() == "item" );
REQUIRE( it.getProp("name") == "localhost" );
auto t1 = MulticastReceiveTransport::createFromXml(it, "0.0.0.0", 0 );
REQUIRE( t1->toString() == "0.0.0.0:3000" );
auto t1 = MulticastReceiveTransport::createFromXml(it, 0 );
REQUIRE( t1->toString() == "224.0.0.1:3000" );
REQUIRE( t1->createConnection(false, 5000, true) );
auto t2 = MulticastSendTransport::createFromXml(it, "127.0.0.1", 0 );
REQUIRE( t2->toString() == "127.0.0.1:3000" );
auto t2 = MulticastSendTransport::createFromXml(it, 0 );
REQUIRE( t2->toString() == "0.0.0.0:3000" );
REQUIRE( t2->getGroupAddress() == Poco::Net::SocketAddress("224.0.0.1", 3000) );
REQUIRE( t2->createConnection(false, 5000) );
......
......@@ -49,8 +49,8 @@ static void initHelpers()
{
std::vector<Poco::Net::IPAddress> groups;
groups.emplace_back("224.0.0.1");
udp_r = make_unique<MulticastReceiveTransport>("0.0.0.0", 3000, groups, "127.0.0.1");
REQUIRE( udp_r->toString() == "0.0.0.0:3000" );
udp_r = make_unique<MulticastReceiveTransport>("224.0.0.1", 3000, groups, "");
REQUIRE( udp_r->toString() == "224.0.0.1:3000" );
REQUIRE( udp_r->createConnection(false, 5000, true) );
// pause for igmp message
msleep(3000);
......@@ -58,8 +58,8 @@ static void initHelpers()
if( !udp_s )
{
udp_s = make_unique<MulticastSendTransport>("127.0.0.1", 3002, "224.0.0.1", 3002);
REQUIRE( udp_s->toString() == "127.0.0.1:3002" );
udp_s = make_unique<MulticastSendTransport>("0.0.0.0", 3002, "224.0.0.2", 3002);
REQUIRE( udp_s->toString() == "0.0.0.0:3002" );
REQUIRE( udp_s->createConnection(false, 5000) );
// pause for igmp message
msleep(3000);
......
......@@ -32,41 +32,20 @@
</settings>
<ObjectsMap idfromfile="1">
<nodes port="2809" unet_broadcast_ip="127.255.255.255" unet_broadcast_ip2="badip" unet_multicast_ip="0.0.0.0">
<item id="3000" ip="127.0.0.1" name="localhost" textname="Локальный узел" unet_ignore="0" unet_port="3000" unet_multicast_ip2="127.0.1.1" unet_multicast_port2="2999" unet_multicast_receive_from_all_nodes="1">
<multicast>
<receive>
<group addr="224.0.0.1" addr2="225.0.0.2"/>
<group addr="224.0.0.3" addr2="225.0.0.3"/>
</receive>
<send>
<group addr="224.0.0.1" addr2="225.0.0.1"/>
</send>
</multicast>
</item>
<nodes port="2809" unet_broadcast_ip="127.255.255.255" unet_broadcast_ip2="badip">
<item id="3000" ip="127.0.0.1" name="localhost" textname="Локальный узел" unet_ignore="0" unet_port="3000"
unet_multicast_ip="224.0.0.1"
unet_multicast_ip2="225.0.0.1"
unet_multicast_port2="3030"/>
<item id="3001" ip="127.0.0.1" name="localhost1" textname="Локальный узел" unet_ignore="1" unet_port="3001"/>
<item id="3002" ip="192.168.56.10" name="Node1" textname="Node1" unet_ignore="0" unet_respond_id="Node1_Not_Respond_S" unet_respond_invert="1" unet_channelswitchcount_id="Node1_ChannelSwitchCount_AS" unet_multicast_receive_from_all_nodes="1">
<multicast>
<receive>
<group addr="224.0.0.1" addr2="225.0.0.1"/>
<group addr="224.0.0.3" addr2="225.0.0.3"/>
</receive>
<send>
<group addr="224.0.0.2" addr2="225.0.0.2"/>
</send>
</multicast>
</item>
<item id="3003" ip="192.168.56.11" name="Node2" textname="Node2" unet_ignore="0" unet_respond_id="Node2_Respond_S" unet_lostpackets_id="Node2_LostPackets_AS" unet_numchannel_id="Node2_NumChannel_AS" unet_multicast_receive_from_all_nodes="1">
<multicast>
<receive>
<group addr="224.0.0.1" addr2="225.0.0.1"/>
<group addr="224.0.0.2" addr2="225.0.0.2"/>
</receive>
<send>
<group addr="224.0.0.3" addr2="225.0.0.3"/>
</send>
</multicast>
</item>
<item id="3002" ip="192.168.56.10" name="Node1" textname="Node1" unet_ignore="0" unet_respond_id="Node1_Not_Respond_S" unet_respond_invert="1" unet_channelswitchcount_id="Node1_ChannelSwitchCount_AS"
unet_multicast_ip="224.0.0.2"
unet_multicast_ip2="225.0.0.2"
unet_multicast_port2="3032"/>
<item id="3003" ip="192.168.56.11" name="Node2" textname="Node2" unet_ignore="0" unet_respond_id="Node2_Respond_S" unet_lostpackets_id="Node2_LostPackets_AS" unet_numchannel_id="Node2_NumChannel_AS"
unet_multicast_ip="224.0.0.3"
unet_multicast_ip2="225.0.0.3"
unet_multicast_port2="3033"/>
</nodes>
<!-- ************************ Датчики ********************** -->
<sensors name="Sensors">
......
......@@ -354,6 +354,13 @@ int main(int argc, char* argv[])
return 1;
}
if( verb )
{
cout << "(send): ip=" << s_host << ":" << port
<< " group=" << groups[0].toString() << ":" << port
<< endl;
}
// supporte only first group address
auto udp = std::make_shared<MulticastSendTransport>(s_host, port, groups[0].toString(), port);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment