/* * (c) Copyright, Real-Time Innovations, 2021. All rights reserved. * RTI grants Licensee a license to use, modify, compile, and create derivative * works of the software solely for use with RTI Connext DDS. Licensee may * redistribute copies of the software provided that all such copies are subject * to this license. The software is provided "as is", with no warranty of any * type, including any warranty for fitness for any purpose. RTI is under no * obligation to maintain or support the software. RTI shall not be liable for * any incidental or consequential damages arising out of the use or inability * to use the software. */ using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Omg.Dds.Subscription; using Rti.Dds.Core.Policy; using Rti.Dds.Domain; using Rti.Dds.Publication; using Rti.Dds.Subscription; using Rti.Dds.Topics; namespace BuiltinTopicsExample { /// /// Example application that publishes HelloWorld and monitors the built-in /// Participant and Subscription DataReaders. /// public sealed class HelloWorldPublisher : IHelloWorldApplication { private readonly DomainParticipant participant; private readonly DataWriter writer; private DataReader participantReader; private DataReader subscriptionReader; private readonly string expectedPassword; /// /// Creates a DomainParticipant, Topic, Publisher and DataWriter. /// public HelloWorldPublisher( int domainId, string expectedPassword, string topicName) { // Save the expected password. We will only communicate with // subscriptions that send this password via discovery. this.expectedPassword = expectedPassword; // Configure the participant QoS to increase the user data max length DomainParticipantQos participantQos = DomainParticipantFactory.Instance.DefaultParticipantQos .WithResourceLimits(policy => policy.ParticipantUserDataMaxLength = 1024); // Create the participant participant = DomainParticipantFactory.Instance.CreateParticipant( domainId, qos: participantQos, preEnableAction: p => { // The preEnableAction is executed right before the participant // is enabled and communication starts. By looking up the // built-in discovery readers here we ensure that // that they will receive all the discovery information. participantReader = p.BuiltinSubscriber .LookupDataReader( Subscriber.ParticipantBuiltinTopicName); // The DataAvailable event is called when another participant // is discovered and before this participant has started // communicating with it participantReader.DataAvailable += OnNewParticipant; subscriptionReader = p.BuiltinSubscriber .LookupDataReader( Subscriber.SubscriptionBuiltinTopicName); subscriptionReader.DataAvailable += OnNewSubscription; } ); // Create a topic, a publisher and a writer Topic topic = participant.CreateTopic(topicName); Publisher publisher = participant.CreatePublisher(); writer = publisher.CreateDataWriter(topic); } /// /// Publishes the data, which will only be received by the subscriptions /// whose participants have set the right password /// public async Task Run(int sampleCount, CancellationToken cancellationToken) { var sample = new HelloWorld(); for (int count = 0; count < sampleCount && !cancellationToken.IsCancellationRequested; count++) { // Modify the data to be sent here sample.x = (short)count; Console.WriteLine($"Writing HelloWorld, count {count}"); writer.Write(sample); await Task.Delay(1000, cancellationToken); } } private void OnNewParticipant(AnyDataReader _) { // Take all the data about new participants using LoanedSamples samples = participantReader .Select() .WithState(ViewState.New.And(InstanceState.Alive)) .Take(); foreach (var sample in samples) { if (!sample.Info.ValidData) { continue; } Console.WriteLine($"Discovered participant: {sample.Data}"); if (!IsAuthorized(sample.Data.UserData)) { // Disallow communication with participants that don't // provide the correct password participant.IgnoreParticipant(sample.Info.InstanceHandle); Console.WriteLine(" * Authorization DENIED"); } else { Console.WriteLine(" * Authorization OK"); } } } private void OnNewSubscription(AnyDataReader _) { // Take all the data about new subscriptions using LoanedSamples samples = subscriptionReader .Select() .WithState(ViewState.New.And(InstanceState.Alive)) .Take(); foreach (var sample in samples) { if (!sample.Info.ValidData) { continue; } Console.WriteLine($"Discovered subscription: {sample.Data}"); } } private bool IsAuthorized(UserData discoveredUserData) { // Convert the bytes back to char (assuming ASCII only) var password = new string(discoveredUserData.Value .Select(b => (char)b) .ToArray()); return password == expectedPassword; } /// /// Disposes all DDS entities created by this application. /// public void Dispose() => participant.Dispose(); } } // namespace BuiltinTopicsExample