/* * Copyright (c) 2024 Real-Time Innovations, Inc. All rights reserved. * No duplications, whole or partial, manual or electronic, may be made * without express written permission. Any such copies, or revisions thereof, * must display this notice unaltered. * This code contains trade secrets of Real-Time Innovations, Inc. */ #ifndef netio_sender_h #define netio_sender_h #include "netio/netio_dll.h" #include "netio/netio_log.h" #include "netio/netio_common.h" #include "netio/netio_configurator.h" #ifdef __cplusplus extern "C" { #endif struct RTIClock; struct REDABuffer; struct REDAExclusiveArea; struct REDAWorker; struct REDAWeakReference; struct REDADatabase; /* ================================================================= */ /* Component: Sender */ /* ================================================================= */ /*e \file * \ingroup RTINetioSenderComponent * \brief Sender component interfaces and definitions. */ /* ================================================================= */ /* Sender Property */ /* ================================================================= */ /*e \defgroup RTINetioSenderPropertyClass RTINetioSenderProperty * \ingroup RTINetioSenderComponent * \brief Transport independent property class. * @see RTINetioSender_new */ struct RTINetioSenderProperty { /*e Control destination table growth. Helps avoid memory allocation. */ struct REDAFastBufferPoolGrowthProperty destinationGrowth; /*e Control resource table growth. Helps avoid memory allocation. */ struct REDAFastBufferPoolGrowthProperty resourceGrowth; /*e Control smart destination reference growth. * Helps avoid memory allocation. * Any destination that is chained with reference (reliable writer without * content filtered topic) will use this whether the resource is shared or * not, so this is expected to grow faster than the destination or the * underlying resource. I would recommend at least 8 times the * destinationGrowth. */ struct REDAFastBufferPoolGrowthProperty destinationReferenceGrowth; /*e * Print warning message when RTINetioSender_send operation time exceeds * sendTimeBasedLoggingThreshold. * Default: INFINITE */ RTINtpTime sendTimeBasedLoggingThreshold; }; /*e \ingroup RTINetioSenderPropertyClass * \brief Use to initialize the property on the stack before modifying the * relevant property. */ #define RTI_NETIO_SENDER_PROPERTY_DEFAULT { \ {32, REDA_FAST_BUFFER_POOL_UNLIMITED, REDA_FAST_BUFFER_POOL_UNLIMITED}, \ {2*32, REDA_FAST_BUFFER_POOL_UNLIMITED, REDA_FAST_BUFFER_POOL_UNLIMITED}, \ {8*32, REDA_FAST_BUFFER_POOL_UNLIMITED, REDA_FAST_BUFFER_POOL_UNLIMITED}, \ {RTI_NTP_TIME_SEC_MAX, RTI_NTP_TIME_FRAC_AUTO} \ } /* ================================================================= */ /* Destination Group class */ /* ================================================================= */ /*e \defgroup RTINetioSenderDestinationGroupClass RTINetioSenderDestinationGroup * \ingroup RTINetioSenderComponent * \brief Logical set of destinations that are frequently sent together. * * While the sender can send to any arbitrary array of previously added * destinations, a typical pattern is that a set of destinations (not * necessarily disjoint) are used together over and over. This * (opaque) class provides the performance optimization in such cases. * * @mtsafety The group can be modified while another thread is iterating * through the list while sending. The group cannot be modified concurrently. * We use RTINetioSender's built in MT protection while adding and removing * destinations. * * @see RTINetioSender_createDestinationGroup */ /*e \ingroup RTINetioSenderDestinationGroupClass * \brief Implementation. */ struct RTINetioSenderDestinationGroup; /* ================================================================= */ /* Sender class */ /* ================================================================= */ /*e \defgroup RTINetioSenderClass RTINetioSender * \ingroup RTINetioSenderComponent * \brief The Sender API * * See RTINetio_Sender_public UML diagram. */ /*e \ingroup RTINetioSenderClass * \brief Abstracts the transport resources that send messages. * * Can send messages in gather send manner to multiple destinations * over installed transport plugins. */ struct RTINetioSender; /*e \ingroup RTINetioSenderClass * \brief Create a new logical set of destinations * @post An existing destination may be added to the group. */ extern RTINetioDllExport struct RTINetioSenderDestinationGroup * RTINetioSender_createDestinationGroup(struct RTINetioSender *me); /*e \ingroup RTINetioSenderClass * \brief Destroy the logical set of destinations * * @post destinations in the group are NOT removed; only the group is destroyed. */ extern RTINetioDllExport void RTINetioSender_destroyDestinationGroup( struct RTINetioSender *me, struct RTINetioSenderDestinationGroup *group); /*e * \ingroup RTINetioSenderClass * \brief Add a new message destination. * * A destination is in turn maps to a remote message entryport, * identified by its address (which may be a multicast group) and port. * In case of multicast, the destination will spell out to a logical * group of all SendResources with the same address, port, * and cos that send using different interfaces, served by different * transport plugin intsances. * * @pre Valid arguments. * * @post Sender caches the SendResource that can serve the specified * destination. The cached SendResource will be dispatched in future * call (not necessarily the very next) of RTINetioSender_sendFast. * * @param destinationWROut. \b Out. Weak reference to the destination. * Storage must be provided by the caller. * * @param destinationGroupInOut. \b InOut. The group to which the destination * should belong. Optional. Sender provides MT safety for changing of * the group, so the user can put the destination group in read only area. * * @param destinationIn \b In. Intended destination. * * @param increaseRefCountIn \b In. Indicates the destination ref count must be * increased for an existing destination. * * The \b destinationIn.locator.transport should be the class of * transport plugin instances for which this destination is relevant. * * The \b destinationIn.locator.address should be the address (unicast or * multicast group) of a remote endpoint to which messages are to * be sent. * * The \b destinationIn.locator.port should be whatever the remote * receiver's entryport's port is for proper communication. That is, * may NOT be INVALID. * * The \b destinationIn.cos is a hint to a transport plugin, when creating * the underlying SendResource. For example, to create a special socket * with IP_TOS option, look at this parameter to decide whether to * perform setsockopt(IP_TOS). Note that this CoS is independent of * CoS of entryport. See RTI_NETIO_TRANSPORT_COS_DEFAULT. * * The \b destinationIn.aliasList is a NULL terminated * list of names (length up to RTI_NETIO_ALIAS_LIST_LENGTH_MAX) of the * desired transport plugin instances. Together with transport class * and serviceRange of a transport plugin instance, this restricts which * transport plugin instances will attempt to serve a destination. * * @return RTI_TRUE on success, RTI_FALSE otherwise. * * @see RTINetioSender_sendFast RTINetioSender_removeDestination */ extern RTINetioDllExport RTIBool RTINetioSender_addDestination( struct RTINetioSender *me, RTIBool *foundMoreThanProvidedForOut, int *pluginArrayLengthInOut, NDDS_Transport_Plugin **pluginArrayInOut, int pluginArrayCapacityIn, struct REDAWeakReference *destinationWROut, struct RTINetioSenderDestinationGroup *destinationGroupInOut, const struct RTINetioLocatorInfo *destinationIn, RTIBool increaseRefCountIn, struct REDAWorker *worker); /*e \ingroup RTINetioSenderClass * \brief Remove destination. * * @pre A valid sender and a valid destination WR * cached from RTINetioSender_addDestination. * * @post The destination description is made invalid. * * @param destinationGroup. \b InOut. The group to which the destination * belonged. Optional. Sender provides MT safety for changing of the group, * so the user can put the destination group in read only area. * * @param destinationWRIn. \b In. Weak reference to the destination (as * returned by addDestination()). If all reference to this destination * is removed, the destination is removed from the group. * * @see RTINetioSender_addDestination */ extern RTINetioDllExport void RTINetioSender_removeDestination( struct RTINetioSender *me, struct RTINetioSenderDestinationGroup *destinationGroupInOut, const struct REDAWeakReference *destinationWRIn, struct REDAWorker *worker); typedef enum { RTI_NETIO_SENDER_COMBINE_DESTINATIONS_RETCODE_OK_EQUIVALENT, RTI_NETIO_SENDER_COMBINE_DESTINATIONS_RETCODE_OK_DIFFERENT, RTI_NETIO_SENDER_COMBINE_DESTINATIONS_RETCODE_ERROR } RTINetioSenderCombineDestinationsRetcode; /* * Check if two destinations are equivalent, potentially calling the underlying * transports state so they can combine the information of a new destination * with the information of an existing and equivalent destination. * * @param me Sender handling the destinations. * @param existingDestination Existing destination represented by a locator * info. * @param newDestination New destination represented by a locator. * @param combineDestinations If true, if the two destinations are equivalent, * update underlying transports. * @param worker Thread worker. */ extern RTINetioDllExport RTINetioSenderCombineDestinationsRetcode RTINetioSender_checkAndCombineEquivalentDestinations( struct RTINetioSender *me, const struct RTINetioLocatorInfo *existingDestination, const struct RTINetioLocator *newDestination, RTIBool combineDestinations, struct REDAWorker *worker); /*e \ingroup RTINetioSenderClass * \brief Get locator from weak-reference. */ extern RTINetioDllExport RTIBool RTINetioSender_getLocatorFromWR( struct RTINetioSender *me, struct RTINetioLocator *locatorOut, struct REDAWeakReference *locatorWR, struct REDAWorker *worker); /*e * \ingroup RTINetioSenderClass * * @brief Get the weak reference that matches the provided locatorInfo if * it exists. * * @param me sender * @param destinationWR Out. Populated with weak reference if it is found. * @param locatorInfoIn locator info to look for weak reference for. * @param worker worker * * @return RTI_FALSE if failure, RTI_TRUE if success */ extern RTINetioDllExport RTIBool RTINetioSender_getWRFromLocatorInfo( struct RTINetioSender *me, struct REDAWeakReference *destinationWR, const struct RTINetioLocatorInfo *locatorInfoIn, struct REDAWorker *worker); /*e \ingroup RTINetioSenderClass * \brief Prepare the sender for destruction. * * @pre Sender is no longer used. It is NOT a precondition to remove all * destinations, since that is taken care of internally. * * @post Sender invalidated and all transport SendResources created through * this sender are destroyed eventually by the reaper thread. The sender will * eventually move to STOPPED state, at which point it is safe to call * RTINetioSender_delete * * @see RTINetioSender_removeDestination */ extern RTINetioDllExport RTIBool RTINetioSender_shutdown( struct RTINetioSender *me, struct REDAWorker *worker); /*e \ingroup RTINetioSenderClass * \brief Destructor * * @pre sender stopped */ extern RTINetioDllExport void RTINetioSender_delete( struct RTINetioSender *me, struct REDAWorker *worker); /*e \ingroup RTINetioSenderClass * \brief Create a new sender. * * @param clockIn \b In. Used for timestamping. * @param dbIn \b In. In-memory database. * @param shutdownListenerIn \b In. Because of complex object interactions, the * sender may NOT be deleted at any time if there is an object * that use this sender. In that case, that object can implement * the RTIEventActiveObjectListener#onStopped method to be called back * when the sender is ok to be destroyed. If there is no such * interaction, this argument may be NULL. * @param configuratorIn \b In. Netio configurator object. * @param propertyIn \b In. NULL if default property is to be used. * @param woker \b In. Worker. * * @return Pointer to the new sender on success, NULL on failure. * * @see RTINetioSender_enable */ extern RTINetioDllExport struct RTINetioSender *RTINetioSender_new( struct RTIClock *clockIn, struct REDADatabase *dbIn, struct RTIEventActiveObjectListener *shutdownListenerIn, struct RTINetioConfigurator* configuratorIn, const struct RTINetioSenderProperty *propertyIn, struct REDAWorker *worker); #ifdef __cplusplus } /* extern "C" */ #endif #include "netio/netio_sender_impl.h" #endif /* netio_sender_h */