- 版本:
OpenDDS 3.21
- 测试程序主流程
- 配置文件
[common]
DCPSDefaultDiscovery=DEFAULT_RTPS
DCPSGlobalTransportConfig=$file
[transport/the_rtps_transport]
transport_type=rtps_udp
-
- 发布程序
- 创建一个DomainParticipantFactory
- 发布程序
DDS::DomainParticipantFactory_var dpf = TheParticipantFactoryWithArgs(argc, argv)
-
-
- 创建一个DomainParticipant
-
DDS::DomainParticipant_var participant = dpf->create_participant(42,
PARTICIPANT_QOS_DEFAULT,
0,
OpenDDS::DCPS::DEFAULT_STATUS_MASK)
-
-
- 创建一个Topic
-
Messenger::MessageTypeSupport_var ts =new Messenger::MessageTypeSupportImpl
ts->register_type(participant, "")
CORBA::String_var type_name = ts->get_type_name();
DDS::Topic_var topic = participant->create_topic("Movie Discussion List",
type_name,
TOPIC_QOS_DEFAULT,
0,
OpenDDS::DCPS::DEFAULT_STATUS_MASK)
-
-
- 创建一个Publisher
-
DDS::Publisher_var publisher = participant->create_publisher(PUBLISHER_QOS_DEFAULT,
0,
OpenDDS::DCPS::DEFAULT_STATUS_MASK)
-
-
- 创建一个datawriter
-
DDS::DataWriter_var writer = publisher->create_datawriter(topic,
DATAWRITER_QOS_DEFAULT,
0,
OpenDDS::DCPS::DEFAULT_STATUS_MASK)
-
-
- 创建一个messagedatawriter
-
Messenger::MessageDataWriter_var message_writer = Messenger::MessageDataWriter::_narrow(writer)
DDS::StatusCondition_var condition = writer->get_statuscondition()
-
-
- 构造一个消息
-
Messenger::Message message;
message.subject_id = 99;
message.from = "Comic Book Guy";
message.subject = "Review";
message.text = "Worst. Movie. Ever.";
message.count = 0;
-
-
- 循环发送消息
-
for (int i = 0; i < 10; ++i) {
DDS::ReturnCode_t error = message_writer->write(message, DDS::HANDLE_NIL)
}
-
- 订阅程序
- 创建一个DomainParticipantFactory
- 订阅程序
DDS::DomainParticipantFactory_var dpf = TheParticipantFactoryWithArgs(argc, argv)
-
-
- 创建一个DomainParticipant
-
DDS::DomainParticipant_var participant = dpf->create_participant(42,
PARTICIPANT_QOS_DEFAULT,
0,
OpenDDS::DCPS::DEFAULT_STATUS_MASK)
-
-
- 创建一个Topic
-
Messenger::MessageTypeSupport_var ts =new Messenger::MessageTypeSupportImpl
ts->register_type(participant, "")
CORBA::String_var type_name = ts->get_type_name();
DDS::Topic_var topic = participant->create_topic("Movie Discussion List",
type_name,
TOPIC_QOS_DEFAULT,
0,
OpenDDS::DCPS::DEFAULT_STATUS_MASK)
-
-
- 创建一个Subscriber
-
DDS::Subscriber_var subscriber =
participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT,
0,
OpenDDS::DCPS::DEFAULT_STATUS_MASK);
-
-
- 创建一个datareader
-
DDS::DataReaderListener_var listener(new DataReaderListenerImpl); // on_data_available()在这个类里面实现,用于接收消息
DDS::DataReaderQos reader_qos; //QOS类型设置
subscriber->get_default_datareader_qos(reader_qos);
reader_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS;
DDS::DataReader_var reader =
subscriber->create_datareader(topic,
reader_qos,
listener,
OpenDDS::DCPS::DEFAULT_STATUS_MASK);
-
-
- 创建一个messagedatareader
-
Messenger::MessageDataReader_var reader_i =
Messenger::MessageDataReader::_narrow(reader);
-
-
- 接收消息
-
void
DataReaderListenerImpl::on_data_available(DDS::DataReader_ptr reader)
{
Messenger::MessageDataReader_var reader_i =
Messenger::MessageDataReader::_narrow(reader);
Messenger::Message message;
DDS::SampleInfo info;
const DDS::ReturnCode_t error = reader_i->take_next_sample(message, info);
if (error == DDS::RETCODE_OK) {
std::cout << "SampleInfo.sample_rank = " << info.sample_rank << std::endl;
std::cout << "SampleInfo.instance_state = " << OpenDDS::DCPS::InstanceState::instance_state_mask_string(info.instance_state) << std::endl;
if (info.valid_data) {
std::cout << "Message: subject = " << message.subject.in() << std::endl
<< " subject_id = " << message.subject_id << std::endl
<< " from = " << message.from.in() << std::endl
<< " count = " << message.count << std::endl
<< " text = " << message.text.in() << std::endl;
}
}
- 如何解析用户参数
TheParticipantFactoryWithArgs(argc, argv)
TheParticipantFactoryWithArgs 定义如下:
#define TheParticipantFactoryWithArgs(argc, argv) TheServiceParticipant->get_domain_participant_factory(argc, argv)
所以,会调用到如下接口:
DDS::DomainParticipantFactory_ptr
Service_Participant::get_domain_participant_factory(int &argc,
ACE_TCHAR *argv[])
{
if (parse_args(argc, argv) != 0) {
return DDS::DomainParticipantFactory::_nil();
}
//如果 .ini 配置文件存在,则打开配置文件
FILE* in = ACE_OS::fopen(config_fname.c_str(), ACE_TEXT("r"));
if (this->load_configuration() != 0)
}
-
- Service_Participant::parse_args实现
int Service_Participant::parse_args(int& argc, ACE_TCHAR* argv[])
{
// Process logging options first, so they are in effect if we need to log
// while processing other options.
ACE_Arg_Shifter log_arg_shifter(argc, argv);
while (log_arg_shifter.is_anything_left()) {
const ACE_TCHAR* currentArg = 0;
if ((currentArg = log_arg_shifter.get_the_parameter(ACE_TEXT("-ORBLogFile"))) != 0) {
set_log_file_name(ACE_TEXT_ALWAYS_CHAR(currentArg));
log_arg_shifter.consume_arg();
got_log_fname = true;
} else if ((currentArg = log_arg_shifter.get_the_parameter(ACE_TEXT("-ORBVerboseLogging"))) != 0) {
set_log_verbose(ACE_OS::atoi(currentArg));
log_arg_shifter.consume_arg();
got_log_verbose = true;
} else {
log_arg_shifter.ignore_arg();
}
}
ACE_Arg_Shifter arg_shifter(argc, argv);
while (arg_shifter.is_anything_left()) {
const ACE_TCHAR* currentArg = 0;
if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSDebugLevel"))) != 0) {
set_DCPS_debug_level(ACE_OS::atoi(currentArg));
arg_shifter.consume_arg();
got_debug_level = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSInfoRepo"))) != 0) {
this->set_repo_ior(currentArg, Discovery::DEFAULT_REPO);
arg_shifter.consume_arg();
got_info = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSRTISerialization"))) != 0) {
if (ACE_OS::atoi(currentArg) == 0) {
ACE_ERROR((LM_WARNING,
ACE_TEXT("(%P|%t) WARNING: Service_Participant::parse_args ")
ACE_TEXT("Argument ignored: DCPSRTISerialization is required to be enabled\n")));
}
arg_shifter.consume_arg();
got_use_rti_serialization = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSChunks"))) != 0) {
n_chunks_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_chunks = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSChunkAssociationMultiplier"))) != 0) {
association_chunk_multiplier_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_chunk_association_multiplier = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSConfigFile"))) != 0) { //如果用户传入了一个配置文件,则会使用该 ini 配置文件
config_fname = currentArg;
arg_shifter.consume_arg();
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSLivelinessFactor"))) != 0) {
liveliness_factor_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_liveliness_factor = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSBitTransportPort"))) != 0) {
/// No need to guard this insertion as we are still single
/// threaded here.
this->bit_transport_port_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_bit_transport_port = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSBitTransportIPAddress"))) != 0) {
/// No need to guard this insertion as we are still single
/// threaded here.
this->bit_transport_ip_ = currentArg;
arg_shifter.consume_arg();
got_bit_transport_ip = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSBitLookupDurationMsec"))) != 0) {
bit_lookup_duration_msec_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_bit_lookup_duration_msec = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSGlobalTransportConfig"))) != 0) {
global_transport_config_ = currentArg;
arg_shifter.consume_arg();
got_global_transport_config = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSBit"))) != 0) {
bit_enabled_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_bit_flag = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSTransportDebugLevel"))) != 0) {
OpenDDS::DCPS::Transport_debug_level = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_transport_debug_level = true;
#ifndef OPENDDS_NO_PERSISTENCE_PROFILE
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSPersistentDataDir"))) != 0) {
this->persistent_data_dir_ = ACE_TEXT_ALWAYS_CHAR(currentArg);
arg_shifter.consume_arg();
got_persistent_data_dir = true;
#endif
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSPendingTimeout"))) != 0) {
pending_timeout_ = TimeDuration(ACE_OS::atoi(currentArg));
arg_shifter.consume_arg();
got_pending_timeout = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSPublisherContentFilter"))) != 0) {
this->publisher_content_filter_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_publisher_content_filter = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSDefaultDiscovery"))) != 0) {
this->defaultDiscovery_ = ACE_TEXT_ALWAYS_CHAR(currentArg);
arg_shifter.consume_arg();
got_default_discovery = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSBidirGIOP"))) != 0) {
bidir_giop_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_bidir_giop = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSThreadStatusInterval"))) != 0) {
thread_status_manager_.thread_status_interval(TimeDuration(ACE_OS::atoi(currentArg)));
arg_shifter.consume_arg();
got_thread_status_interval = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-FederationRecoveryDuration"))) != 0) {
this->federation_recovery_duration_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-FederationInitialBackoffSeconds"))) != 0) {
this->federation_initial_backoff_seconds_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-FederationBackoffMultiplier"))) != 0) {
this->federation_backoff_multiplier_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-FederationLivelinessDuration"))) != 0) {
this->federation_liveliness_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSDefaultAddress"))) != 0) {
ACE_INET_Addr addr;
if (addr.set(u_short(0), currentArg)) {
ACE_ERROR_RETURN((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: Service_Participant::parse_args: ")
ACE_TEXT("failed to parse default address %C\n"),
currentArg),
-1);
}
default_address_ = NetworkAddress(addr);
arg_shifter.consume_arg();
got_default_address = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSMonitor"))) != 0) {
this->monitor_enabled_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_monitor = true;
#if defined(OPENDDS_SECURITY)
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSSecurityDebugLevel"))) != 0) {
security_debug.set_debug_level(ACE_OS::atoi(currentArg));
arg_shifter.consume_arg();
got_security_debug = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSSecurityDebug"))) != 0) {
security_debug.parse_flags(currentArg);
arg_shifter.consume_arg();
got_security_debug = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSSecurityFakeEncryption"))) != 0) {
security_debug.fake_encryption = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_security_fake_encryption = true;
// Must be last "-DCPSSecurity*" option, see comment above this arg parsing loop
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSSecurity"))) != 0) {
security_enabled_ = ACE_OS::atoi(currentArg);
arg_shifter.consume_arg();
got_security_flag = true;
#endif
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSTypeObjectEncoding"))) != 0) {
type_object_encoding(ACE_TEXT_ALWAYS_CHAR(currentArg));
arg_shifter.consume_arg();
got_type_object_encoding = true;
} else if ((currentArg = arg_shifter.get_the_parameter(ACE_TEXT("-DCPSLogLevel"))) != 0) {
log_level.set_from_string(ACE_TEXT_ALWAYS_CHAR(currentArg));
arg_shifter.consume_arg();
got_log_level = true;
} else {
arg_shifter.ignore_arg();
}
}
// Indicates successful parsing of the command line
return 0;
}
-
- Service_Participant::load_configuration 实现
int
Service_Participant::load_configuration()
{
ACE_Configuration_Heap cf;
int status = 0;
ACE_Ini_ImpExp import(cf);
status = import.import_config(config_fname.c_str());
status = this->load_configuration(cf, config_fname.c_str());
return status;
}
-
- Service_Participant::load_configuration
对于 INI 文件中,每个字段的解析,都是在这个函数中完成的
int
Service_Participant::load_configuration(
ACE_Configuration_Heap& config,
const ACE_TCHAR* filename)
{
// Domain config is loaded after Discovery (see below). Since the domain
// could be a domain_range that specifies the DiscoveryTemplate, check
// for config templates before loading any config information.
ACE_TString section_name;
int status = this->load_common_configuration(config, filename);
if (status != 0) {
ACE_ERROR_RETURN((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: Service_Participant::load_configuration ")
ACE_TEXT("load_common_configuration () returned %d\n"),
status),
-1);
}
// Register static discovery.
this->add_discovery(static_rchandle_cast<Discovery>(StaticDiscovery::instance()));
// load any discovery configuration templates before rtps discovery
// this will populate the domain_range_templates_
status = this->load_domain_ranges(config);
// load any rtps_discovery templates
status = this->load_discovery_templates(config);
status = this->load_discovery_configuration(config, RTPS_SECTION_NAME);
status = this->load_discovery_configuration(config, REPO_SECTION_NAME);
// load any transport configuration templates before the transport config
status = TransportRegistry::instance()->load_transport_templates(config);
status = TransportRegistry::instance()->load_transport_configuration(
ACE_TEXT_ALWAYS_CHAR(filename), config);
if (this->global_transport_config_ != ACE_TEXT("")) {
TransportConfig_rch config = TransportRegistry::instance()->get_config(
ACE_TEXT_ALWAYS_CHAR(this->global_transport_config_.c_str()));
if (config) {
TransportRegistry::instance()->global_config(config);
} else if (TheTransportRegistry->config_has_transport_template(global_transport_config_)) {
}
// Needs to be loaded after the [rtps_discovery/*] and [repository/*]
// sections to allow error reporting on bad discovery config names.
// Also loaded after the transport configuration so that
// DefaultTransportConfig within [domain/*] can use TransportConfig objects.
status = this->load_domain_configuration(config, filename);
// Needs to be loaded after transport configs and instances and domains.
try {
status = StaticDiscovery::instance()->load_configuration(config);
return 0;
}
- 中心式管理进程InfoRepo
dds\InfoRepo\DCPSInfoRepo.cpp
int
ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
try {
InfoRepo infoRepo(argc, argv);
InfoRepo_Shutdown ir_shutdown(infoRepo);
Service_Shutdown service_shutdown(ir_shutdown);
infoRepo.run();
} catch (InfoRepo::InitError& ex) {
std::cerr << "Unexpected initialization Error: "
<< ex.msg_ << std::endl;
return 1;
} catch (const CORBA::Exception& ex) {
ex._tao_print_exception("ERROR: DDS DCPS Info Repo caught exception");
return 1;
}
return 0;
}
InfoRepo::InfoRepo(int argc, ACE_TCHAR *argv[])
: ior_file_(ACE_TEXT("repo.ior"))
, listen_address_given_(0)
#ifdef DDS_HAS_MINIMUM_BIT
, use_bits_(false)
#else
, use_bits_(true)
#endif
, resurrect_(true)
, finalized_(false)
, servant_finalized_(false)
, federator_(this->federatorConfig_)
, federatorConfig_(argc, argv)
, lock_()
, cond_(lock_)
, shutdown_complete_(false)
, shutdown_signal_(0)
, dispatch_cleanup_delay_(30,0)
{
try {
this->init();
} catch (...) {
this->finalize();
throw;
}
}
- create_participant流程分析
- BUILTIN EntityID
/// Entity Id values specified in Version 2.1 of RTPS specification.
const EntityId_t ENTITYID_UNKNOWN = { {0x00,0x00,0x00}, 0x00};
const EntityId_t ENTITYID_PARTICIPANT = { {0x00,0x00,0x01}, 0xc1};
const EntityId_t ENTITYID_SEDP_BUILTIN_TOPIC_WRITER = { {0x00,0x00,0x02}, 0xc2};
const EntityId_t ENTITYID_SEDP_BUILTIN_TOPIC_READER = { {0x00,0x00,0x02}, 0xc7};
const EntityId_t ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER = { {0x00,0x00,0x03}, 0xc2};
const EntityId_t ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER = { {0x00,0x00,0x03}, 0xc7};
const EntityId_t ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER = { {0x00,0x00,0x04}, 0xc2};
const EntityId_t ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER = { {0x00,0x00,0x04}, 0xc7};
const EntityId_t ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER = { {0x00,0x01,0x00}, 0xc2};
const EntityId_t ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER = { {0x00,0x01,0x00}, 0xc7};
const EntityId_t ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER = { {0x00,0x02,0x00}, 0xc2};
const EntityId_t ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER = { {0x00,0x02,0x00}, 0xc7};
-
- BUILT_IN_TOPIC
const char* const BUILT_IN_PARTICIPANT_TOPIC = "DCPSParticipant";
const char* const BUILT_IN_PARTICIPANT_TOPIC_TYPE = "PARTICIPANT_BUILT_IN_TOPIC_TYPE";
const char* const BUILT_IN_TOPIC_TOPIC = "DCPSTopic";
const char* const BUILT_IN_TOPIC_TOPIC_TYPE = "TOPIC_BUILT_IN_TOPIC_TYPE";
const char* const BUILT_IN_SUBSCRIPTION_TOPIC = "DCPSSubscription";
const char* const BUILT_IN_SUBSCRIPTION_TOPIC_TYPE = "SUBSCRIPTION_BUILT_IN_TOPIC_TYPE";
const char* const BUILT_IN_PUBLICATION_TOPIC = "DCPSPublication";
const char* const BUILT_IN_PUBLICATION_TOPIC_TYPE = "PUBLICATION_BUILT_IN_TOPIC_TYPE";
const char* const BUILT_IN_PARTICIPANT_LOCATION_TOPIC = "OpenDDSParticipantLocation";
const char* const BUILT_IN_PARTICIPANT_LOCATION_TOPIC_TYPE = "PARTICIPANT_LOCATION_BUILT_IN_TOPIC_TYPE";
const char* const BUILT_IN_CONNECTION_RECORD_TOPIC = "OpenDDSConnectionRecord";
const char* const BUILT_IN_CONNECTION_RECORD_TOPIC_TYPE = "CONNECTION_RECORD_BUILT_IN_TOPIC_TYPE";
const char* const BUILT_IN_INTERNAL_THREAD_TOPIC = "OpenDDSInternalThread";
const char* const BUILT_IN_INTERNAL_THREAD_TOPIC_TYPE = "INTERNAL_THREAD_BUILT_IN_TOPIC_TYPE";
-
- DomainParticipantFactoryImpl::create_participant
DDS::DomainParticipant_ptr
DomainParticipantFactoryImpl::create_participant(
DDS::DomainId_t domainId,
const DDS::DomainParticipantQos & qos,
DDS::DomainParticipantListener_ptr a_listener,
DDS::StatusMask mask)
{
DDS::DomainParticipantQos par_qos = qos;
if (par_qos == PARTICIPANT_QOS_DEFAULT) {
get_default_participant_qos(par_qos);
}
if (!Qos_Helper::valid(par_qos)) {
if (DCPS_debug_level > 0) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: ")
ACE_TEXT("DomainParticipantFactoryImpl::create_participant, ")
ACE_TEXT("invalid qos.\n")));
}
return DDS::DomainParticipant::_nil();
}
if (!Qos_Helper::consistent(par_qos)) {
if (DCPS_debug_level > 0) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: ")
ACE_TEXT("DomainParticipantFactoryImpl::create_participant, ")
ACE_TEXT("inconsistent qos.\n")));
}
return DDS::DomainParticipant::_nil();
}
RcHandle<DomainParticipantImpl> dp =
make_rch<DomainParticipantImpl>(ref(participant_handles_), domainId, par_qos, a_listener, mask);
if (qos_.entity_factory.autoenable_created_entities) {
if (dp->enable() != DDS::RETCODE_OK) {
if (DCPS_debug_level > 0) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: ")
ACE_TEXT("DomainParticipantFactoryImpl::create_participant, ")
ACE_TEXT("unable to enable DomainParticipant.\n")));
}
return DDS::DomainParticipant::_nil();
}
}
// if the specified transport is a transport template then create a new transport
// instance for the new participant if per_participant is set (checked before creating instance).
ACE_TString transport_base_config_name;
TheServiceParticipant->get_transport_base_config_name(domainId, transport_base_config_name);
if (TheTransportRegistry->config_has_transport_template(transport_base_config_name)) {
OPENDDS_STRING transport_config_name = ACE_TEXT_ALWAYS_CHAR(transport_base_config_name.c_str());
OPENDDS_STRING transport_instance_name = dp->get_unique_id();
// unique config and instance names are returned in transport_config_name and transport_instance_name
const bool ret = TheTransportRegistry->create_new_transport_instance_for_participant(domainId, transport_config_name, transport_instance_name);
if (ret) {
TheTransportRegistry->bind_config(transport_config_name, dp.in());
TheTransportRegistry->update_config_template_instance_info(transport_config_name, transport_instance_name);
} else {
if (DCPS_debug_level > 0) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: ")
ACE_TEXT("DomainParticipantFactoryImpl::create_participant, ")
ACE_TEXT("could not create new transport instance for participant.\n")));
}
return DDS::DomainParticipant::_nil();
}
}
ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex,
guard,
participants_protector_,
DDS::DomainParticipant::_nil());
participants_[domainId].insert(dp);
return dp._retn();
}
-
- DomainParticipantImpl::enable
DDS::ReturnCode_t
DomainParticipantImpl::enable()
{
//According spec:
// - Calling enable on an already enabled Entity returns OK and has no
// effect.
// - Calling enable on an Entity whose factory is not enabled will fail
// and return PRECONDITION_NOT_MET.
if (this->is_enabled()) {
return DDS::RETCODE_OK;
}
#ifdef OPENDDS_SECURITY
if (!security_config_ && TheServiceParticipant->get_security()) {
security_config_ = TheSecurityRegistry->default_config();
if (!security_config_) {
security_config_ = TheSecurityRegistry->builtin_config();
TheSecurityRegistry->default_config(security_config_);
}
}
#endif
Discovery_rch disco = TheServiceParticipant->get_discovery(domain_id_);
if (disco.is_nil()) {
if (DCPS_debug_level > 0) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable, ")
ACE_TEXT("no discovery found for domain id: %d.\n"), domain_id_));
}
return DDS::RETCODE_ERROR;
}
#ifdef OPENDDS_SECURITY
if (TheServiceParticipant->get_security() && !security_config_) {
if (DCPS::security_debug.new_entity_error) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable, ")
ACE_TEXT("DCPSSecurity flag is set, but unable to load security plugin configuration.\n")));
}
return DDS::RETCODE_ERROR;
}
#endif
AddDomainStatus value = {GUID_UNKNOWN, false};
#ifdef OPENDDS_SECURITY
if (TheServiceParticipant->get_security() && security_config_->qos_implies_security(qos_)) {
Security::Authentication_var auth = security_config_->get_authentication();
DDS::Security::SecurityException se;
DDS::Security::ValidationResult_t val_res =
auth->validate_local_identity(id_handle_, dp_id_, domain_id_, qos_, disco->generate_participant_guid(), se);
/* TODO - Handle VALIDATION_PENDING_RETRY */
if (val_res != DDS::Security::VALIDATION_OK) {
if (DCPS::security_debug.new_entity_error) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable, ")
ACE_TEXT("Unable to validate local identity. SecurityException[%d.%d]: %C\n"),
se.code, se.minor_code, se.message.in()));
}
return DDS::Security::RETCODE_NOT_ALLOWED_BY_SECURITY;
}
Security::AccessControl_var access = security_config_->get_access_control();
perm_handle_ = access->validate_local_permissions(auth, id_handle_, domain_id_, qos_, se);
if (perm_handle_ == DDS::HANDLE_NIL) {
if (DCPS::security_debug.new_entity_error) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable, ")
ACE_TEXT("Unable to validate local permissions. SecurityException[%d.%d]: %C\n"),
se.code, se.minor_code, se.message.in()));
}
return DDS::Security::RETCODE_NOT_ALLOWED_BY_SECURITY;
}
const bool check_create = access->check_create_participant(perm_handle_, domain_id_, qos_, se);
if (!check_create) {
if (DCPS::security_debug.new_entity_error) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable, ")
ACE_TEXT("Unable to create participant. SecurityException[%d.%d]: %C\n"),
se.code, se.minor_code, se.message.in()));
}
return DDS::Security::RETCODE_NOT_ALLOWED_BY_SECURITY;
}
DDS::Security::ParticipantSecurityAttributes part_sec_attr;
const bool check_part_sec_attr = access->get_participant_sec_attributes(perm_handle_, part_sec_attr, se);
if (!check_part_sec_attr) {
if (DCPS::security_debug.new_entity_error) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable,")
ACE_TEXT("Unable to get participant security attributes. SecurityException[%d.%d]: %C\n"),
se.code, se.minor_code, se.message.in()));
}
return DDS::RETCODE_ERROR;
}
if (part_sec_attr.is_rtps_protected) { // DDS-Security v1.1 8.4.2.4 Table 27 is_rtps_protected
if (part_sec_attr.allow_unauthenticated_participants) {
if (DCPS::security_debug.new_entity_error) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable, ")
ACE_TEXT("allow_unauthenticated_participants is not possible with is_rtps_protected\n")));
}
return DDS::Security::RETCODE_NOT_ALLOWED_BY_SECURITY;
}
const Security::CryptoKeyFactory_var crypto = security_config_->get_crypto_key_factory();
part_crypto_handle_ = crypto->register_local_participant(id_handle_, perm_handle_,
Util::filter_properties(qos_.property.value, "dds.sec.crypto."), part_sec_attr, se);
if (part_crypto_handle_ == DDS::HANDLE_NIL) {
if (DCPS::security_debug.new_entity_error) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable, ")
ACE_TEXT("Unable to register local participant. SecurityException[%d.%d]: %C\n"),
se.code, se.minor_code, se.message.in()));
}
return DDS::RETCODE_ERROR;
}
} else {
part_crypto_handle_ = DDS::HANDLE_NIL;
}
value = disco->add_domain_participant_secure(domain_id_, qos_, type_lookup_service_,
dp_id_, id_handle_, perm_handle_, part_crypto_handle_);
if (value.id == GUID_UNKNOWN) {
if (DCPS::security_debug.new_entity_error) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable, ")
ACE_TEXT("add_domain_participant_secure returned invalid id.\n")));
}
return DDS::RETCODE_ERROR;
}
} else {
#endif
value = disco->add_domain_participant(domain_id_, qos_, type_lookup_service_);
if (value.id == GUID_UNKNOWN) {
if (DCPS_debug_level > 0) {
ACE_ERROR((LM_ERROR,
ACE_TEXT("(%P|%t) ERROR: DomainParticipantImpl::enable, ")
ACE_TEXT("add_domain_participant returned invalid id.\n")));
}
return DDS::RETCODE_ERROR;
}
#ifdef OPENDDS_SECURITY
}
#endif
dp_id_ = value.id;
federated_ = value.federated;
if (monitor_) {
monitor_->report();
}
if (TheServiceParticipant->monitor_) {
TheServiceParticipant->monitor_->report();
}
const DDS::ReturnCode_t ret = this->set_enabled();
if (DCPS_debug_level > 1) {
ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) DomainParticipantImpl::enable: ")
ACE_TEXT("enabled participant %C in domain %d\n"),
LogGuid(dp_id_).c_str(), domain_id_));
}
if (ret == DDS::RETCODE_OK && !TheTransientKludge->is_enabled()) {
Discovery_rch disc = TheServiceParticipant->get_discovery(this->domain_id_);
this->bit_subscriber_ = disc->init_bit(this);
}
if (ret != DDS::RETCODE_OK) {
return ret;
}
if (qos_.entity_factory.autoenable_created_entities) {
for (TopicMap::iterator it = topics_.begin(); it != topics_.end(); ++it) {
it->second.pair_.svt_->enable();
}
for (PublisherSet::iterator it = publishers_.begin(); it != publishers_.end(); ++it) {
it->svt_->enable();
}
for (SubscriberSet::iterator it = subscribers_.begin(); it != subscribers_.end(); ++it) {
it->svt_->enable();
}
}
return DDS::RETCODE_OK;
}
-
- RtpsDiscovery::add_domain_participant
DCPS::AddDomainStatus
RtpsDiscovery::add_domain_participant(DDS::DomainId_t domain,
const DDS::DomainParticipantQos& qos,
XTypes::TypeLookupService_rch tls)
{
DCPS::AddDomainStatus ads = {OpenDDS::DCPS::RepoId(), false /*federated*/};
{
ACE_GUARD_RETURN(ACE_Thread_Mutex, g, lock_, ads);
const OPENDDS_STRING guid_interface = config_->guid_interface();
if (!guid_interface.empty()) {
if (guid_gen_.interfaceName(guid_interface.c_str()) != 0) {
if (DCPS::DCPS_debug_level) {
ACE_DEBUG((LM_WARNING, "(%P|%t) RtpsDiscovery::add_domain_participant()"
" - attempt to use specific network interface %C MAC addr for"
" GUID generation failed.\n", guid_interface.c_str()));
}
}
}
guid_gen_.populate(ads.id);
}
ads.id.entityId = ENTITYID_PARTICIPANT;
try {
const DCPS::RcHandle<Spdp> spdp(DCPS::make_rch<Spdp>(domain, ref(ads.id), qos, this, tls));
// ads.id may change during Spdp constructor
ACE_GUARD_RETURN(ACE_Thread_Mutex, g, participants_lock_, ads);
participants_[domain][ads.id] = spdp;
} catch (const std::exception& e) {
ads.id = GUID_UNKNOWN;
ACE_ERROR((LM_ERROR, "(%P|%t) RtpsDiscovery::add_domain_participant() - "
"failed to initialize RTPS Simple Participant Discovery Protocol: %C\n",
e.what()));
}
return ads;
}
-
- SPDP
- Spdp::Spdp
- SPDP
Spdp::Spdp(DDS::DomainId_t domain,
RepoId& guid,
const DDS::DomainParticipantQos& qos,
RtpsDiscovery* disco,
XTypes::TypeLookupService_rch tls)
: qos_(qos)
, disco_(disco)
, config_(disco_->config())
, lease_duration_(disco_->config()->lease_duration())
, lease_extension_(disco_->config()->lease_extension())
, domain_(domain)
, guid_(guid)
, participant_discovered_at_(MonotonicTimePoint::now().to_monotonic_time())
, is_application_participant_(false)
, tport_(DCPS::make_rch<SpdpTransport>(rchandle_from(this)))
, initialized_flag_(false)
, eh_shutdown_(false)
, shutdown_cond_(lock_)
, shutdown_flag_(false)
, available_builtin_endpoints_(0)
, sedp_(DCPS::make_rch<Sedp>(guid_, DCPS::ref(*this), DCPS::ref(lock_)))
#ifdef OPENDDS_SECURITY
, available_extended_builtin_endpoints_(0)
, security_config_()
, security_enabled_(false)
, identity