diff --git a/.azure/templates/build-test.yml b/.azure/templates/build-test.yml index f8076a12..db55d0fc 100644 --- a/.azure/templates/build-test.yml +++ b/.azure/templates/build-test.yml @@ -79,7 +79,7 @@ steps: pre-commit run --all-files name: run_pre_commit - bash: | - pip install gcovr --user --upgrade + pip install gcovr==5.0 --user --upgrade condition: eq(variables['coverage'], 'on') name: install_gcovr - bash: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 06648da8..f046b631 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # cmake_minimum_required(VERSION 3.10) -project(CycloneDDS VERSION 0.9.0 LANGUAGES C) +project(CycloneDDS VERSION 0.9.1 LANGUAGES C) if(CMAKE_VERSION VERSION_LESS 3.12) # GENERATE_EXPORT_HEADER requires a C++ compiler up to version 3.12 enable_language(CXX) @@ -346,4 +346,4 @@ if(DEFINED ENV{LIB_FUZZING_ENGINE}) add_subdirectory(fuzz) endif() -include(CMakeCPack.cmake) \ No newline at end of file +include(CMakeCPack.cmake) diff --git a/README.md b/README.md index 9b5ec01a..5da77b67 100644 --- a/README.md +++ b/README.md @@ -4,249 +4,30 @@ [![License](https://img.shields.io/badge/License-EPL%202.0-blue)](https://choosealicense.com/licenses/epl-2.0/) [![License](https://img.shields.io/badge/License-EDL%201.0-blue)](https://choosealicense.com/licenses/edl-1.0/) -# Eclipse Cyclone DDS +# This branch supports CycloneDDS over FreeRTOS-Plus-TCP stack on FreeRTOS. +CycloneDDS looks have support on FreeRTOS+LWIP Stack, +however lacking FreeRTOS-Plus-TCP Stack support +This change managed to add +TCP support + +* base CycloneDDS version0.9.1 +* ddsrt socket / thread ... + +[Changes] ++TCP socket +ddsrt header and source +sockaddr ifaddr +.init_array section +log sink +multicast/unicast peer define in xml +TLS-Thread_Local_Storage from FreeRTOS SW impl instread of toolchain +sock_waitset +sock fdset +sendmsg/recvmsg for UDP +dds_align from 0.10.2 +FragmentSize for jumbo and normal + +# DDS Readme refer to master readme +Link: +https://github.com/polejoe/cycloneDDS_RTOS/blob/master/README.md -Eclipse Cyclone DDS is a very performant and robust open-source DDS implementation. Cyclone DDS is developed completely in the open as an Eclipse IoT project -(see [eclipse-cyclone-dds](https://projects.eclipse.org/projects/iot.cyclonedds)) with a growing list of [adopters](https://iot.eclipse.org/adopters/?#iot.cyclonedds) (if you're one of them, please add your [logo](https://github.com/EclipseFdn/iot.eclipse.org/issues/new?template=adopter_request.md)). It is a tier-1 middleware for the Robot Operating System [ROS 2](https://docs.ros.org/en/rolling/). -* [Getting Started](#getting-started) -* [Performance](#performance) -* [Configuration](#configuration) - -> Consult the [roadmap](ROADMAP.md) for a high-level overview of upcoming features. - -# Getting Started - -## Building Eclipse Cyclone DDS - -In order to build Cyclone DDS you need a Linux, Mac or Windows 10 machine (or, with some caveats, a *BSD, OpenIndiana or a Solaris 2.6 one) with the following installed on your host: - - * C compiler (most commonly GCC on Linux, Visual Studio on Windows, Xcode on macOS); - * GIT version control system; - * [CMake](https://cmake.org/download/), version 3.10 or later; - * [OpenSSL](https://www.openssl.org/), preferably version 1.1 or later if you want to use TLS over - TCP. You can explicitly disable it by setting ``ENABLE_SSL=NO``, which is very useful for - reducing the footprint or when the FindOpenSSL CMake script gives you trouble; - * Optionally [Bison](https://www.gnu.org/software/bison/) parser generator. A cached source is checked into the repository. - -If you want to play around with the parser you will need to install the bison parser generator. On Ubuntu ``apt install bison`` should do the trick for getting it installed. -On Windows, installing chocolatey and ``choco install winflexbison3`` should get you a long way. On macOS, ``brew install bison`` is easiest. - -To obtain Eclipse Cyclone DDS, do - - $ git clone https://github.com/eclipse-cyclonedds/cyclonedds.git - $ cd cyclonedds - $ mkdir build - -Depending on whether you want to develop applications using Cyclone DDS or contribute to it you can -follow different procedures - -### For application developers - -To build and install the required libraries needed to develop your own applications using Cyclone -DDS requires a few simple steps. There are some small differences between Linux and macOS on the one -hand, and Windows on the other. For Linux or macOS: - - $ cd build - $ cmake -DCMAKE_INSTALL_PREFIX= -DBUILD_EXAMPLES=ON .. - $ cmake --build . - -and for Windows: - - $ cd build - $ cmake -G "" -DCMAKE_INSTALL_PREFIX= -DBUILD_EXAMPLES=ON .. - $ cmake --build . - -where you should replace ```` by the directory under which you would like to -install Cyclone DDS and ```` by one of the ways -CMake [generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) offer for -generating build files. For example, "Visual Studio 15 2017 Win64" would target a 64-bit build -using Visual Studio 2017. - -To install it after a successful build, do: - - $ cmake --build . --target install - -which will copy everything to: - - * ``/lib`` - * ``/bin`` - * ``/include/ddsc`` - * ``/share/CycloneDDS`` - -Depending on the installation location you may need administrator privileges. - -At this point you are ready to use Eclipse Cyclone DDS in your own projects. - -Note that the default build type is a release build with debug information included -(RelWithDebInfo), which is generally the most convenient type of build to use from applications -because of a good mix between performance and still being able to debug things. If you'd rather -have a Debug or pure Release build, set ``CMAKE_BUILD_TYPE`` accordingly. - -### Contributing to Eclipse Cyclone DDS - -We very much welcome all contributions to the project, whether that is questions, examples, bug -fixes, enhancements or improvements to the documentation, or anything else really. When considering -contributing code, it might be good to know that build configurations for Travis CI and AppVeyor are -present in the repository and that there is a test suite using CTest and CUnit that can be built -locally if desired. To build it, set the cmake variable ``BUILD_TESTING`` to on when configuring, e.g.: - - $ cd build - $ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON .. - $ cmake --build . - $ ctest - -Such a build requires the presence of [CUnit](http://cunit.sourceforge.net/). You can install this -yourself, or you can choose to instead rely on the [Conan](https://conan.io) packaging system that -the CI build infrastructure also uses. In that case, install Conan and do: - - $ conan install .. --build missing - -in the build directory prior to running cmake. - -For Windows, depending on the generator, you might also need to add switches to select the architecture -and build type, e.g., ``conan install -s arch=x86_64 -s build_type=Debug ..`` This will automatically -download and/or build CUnit (and, at the moment, OpenSSL). - -## Documentation - -The documentation is still rather limited, and at the moment only available in the sources (in the -form of restructured text files in ``docs`` and Doxygen comments in the header files), or as -a -[PDF](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/pdf/CycloneDDS-0.1.0.pdf). The -intent is to automate the process of building the documentation and have them available in more -convenient formats and in the usual locations. - -## Building and Running the Roundtrip Example - -We will show you how to build and run an example program that measures latency. The examples are -built automatically when you build Cyclone DDS, so you don't need to follow these steps to be able -to run the program, it is merely to illustrate the process. - - $ mkdir roundtrip - $ cd roundtrip - $ cmake /share/CycloneDDS/examples/roundtrip - $ cmake --build . - -On one terminal start the application that will be responding to pings: - - $ ./RoundtripPong - -On another terminal, start the application that will be sending the pings: - - $ ./RoundtripPing 0 0 0 - # payloadSize: 0 | numSamples: 0 | timeOut: 0 - # Waiting for startup jitter to stabilise - # Warm up complete. - # Latency measurements (in us) - # Latency [us] Write-access time [us] Read-access time [us] - # Seconds Count median min 99% max Count median min Count median min - 1 28065 17 16 23 87 28065 8 6 28065 1 0 - 2 28115 17 16 23 46 28115 8 6 28115 1 0 - 3 28381 17 16 22 46 28381 8 6 28381 1 0 - 4 27928 17 16 24 127 27928 8 6 27928 1 0 - 5 28427 17 16 20 47 28427 8 6 28427 1 0 - 6 27685 17 16 26 51 27685 8 6 27685 1 0 - 7 28391 17 16 23 47 28391 8 6 28391 1 0 - 8 27938 17 16 24 63 27938 8 6 27938 1 0 - 9 28242 17 16 24 132 28242 8 6 28242 1 0 - 10 28075 17 16 23 46 28075 8 6 28075 1 0 - -The numbers above were measured on Mac running a 4.2 GHz Intel Core i7 on December 12th 2018. From -these numbers you can see how the roundtrip is very stable and the minimal latency is now down to 17 -micro-seconds (used to be 25 micro-seconds) on this HW. - -# Performance - -Reliable message throughput is over 1MS/s for very small samples and is roughly 90% of GbE with 100 -byte samples, and latency is about 30us when measured using [ddsperf](src/tools/ddsperf) between two -Intel(R) Xeon(R) CPU E3-1270 V2 @ 3.50GHz (that's 2012 hardware ...) running Ubuntu 16.04, with the -executables built on Ubuntu 18.04 using gcc 7.4.0 for a default (i.e., "RelWithDebInfo") build. - -ThroughputThroughput - -This is with the subscriber in listener mode, using asynchronous delivery for the throughput -test. The configuration is a marginally tweaked out-of-the-box configuration: an increased maximum -message size and fragment size, and an increased high-water mark for the reliability window on the -writer side. For details, see the [scripts](examples/perfscript) directory, -the -[environment details](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/config.txt) and -the -[throughput](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/sub.log) and -[latency](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/ping.log) data -underlying the graphs. These also include CPU usage ([throughput](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/throughput-async-listener-cpu.png) and [latency](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/latency-sync-listener-bwcpu.png)) and [memory usage](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/throughput-async-listener-memory.png). - -# Configuration - -The out-of-the-box configuration should usually be fine, but there are a great many options that can -be tweaked by creating an XML file with the desired settings and defining the ``CYCLONEDDS_URI`` to -point to it. E.g. (on Linux): - - $ cat cyclonedds.xml - - - - - - - - default - 65500B - 4000B - - - - 500kB - - - - config - stdout - - - - $ export CYCLONEDDS_URI=file://$PWD/cyclonedds.xml - -(on Windows, one would have to use ``set CYCLONEDDS_URI=file://...`` instead.) - -This example shows a few things: - -* ``Interfaces`` can be used to override the interfaces selected by default. Members are - * ``NetworkInterface[@autodetermine]`` tells Cyclone DDS to autoselect the interface it deems best. - * ``NetworkInterface[@name]`` specifies the name of an interface to select (not shown above, alternative for autodetermine). - * ``NetworkInterface[@ip]`` specifies the ipv4/ipv6 address of an interface to select (not shown above, alternative for autodetermine). - * ``NetworkInterface[@multicast]`` specifies whether multicast should be used on this interface. - The default value 'default' means Cyclone DDS will check the OS reported flags of the interface - and enable multicast if it is supported. Use 'true' to ignore what the OS reports and enable it - anyway and 'false' to always disable multicast on this interface. - * ``NetworkInterface[@priority]`` specifies the priority of an interface. The default value (``default``) - means priority ``0`` for normal interfaces and ``2`` for loopback interfaces. -* ``AllowMulticast`` configures the circumstances under which multicast will be used. If the - selected interface doesn't support it, it obviously won't be used (``false``); but if it does - support it, the type of the network adapter determines the default value. For a wired network, it - will use multicast for initial discovery as well as for data when there are multiple peers that - the data needs to go to (``true``); but on a WiFi network it will use it only for initial - discovery (``spdp``), because multicast on WiFi is very unreliable. -* ``Verbosity`` allows control over the tracing, "config" dumps the configuration to the trace - output (which defaults to "cyclonedds.log"). Which interface is used, what multicast settings are - used, etc., is all in the trace. Setting the verbosity to "finest" gives way more output on the - inner workings, and there are various other levels as well. -* ``MaxMessageSize`` and ``FragmentSize`` control the maximum size of the RTPS messages (basically - the size of the UDP payload), and the size of the fragments into which very large samples get - split (which needs to be "a bit" less). Large values such as these typically improve performance - over the (current) default values. -* ``WhcHigh`` determines when the sender will wait for acknowledgements from the readers because it - has buffered too much unacknowledged data. There is some auto-tuning, the (current) default value - is a bit small to get really high throughput. - -Background information on configuring Cyclone DDS can be found -[here](docs/manual/config.rst) and a list of settings is -[available](docs/manual/options.md). - -# Trademarks - -* "Eclipse Cyclone DDS" and "Cyclone DDS" are trademarks of the Eclipse Foundation. - -* "DDS" is a trademark of the Object Management Group, Inc. - -* "ROS" is a trademark of Open Source Robotics Foundation, Inc. diff --git a/cmake/CheckHashScript.cmake b/cmake/CheckHashScript.cmake index 4edc4bb2..f6f90218 100644 --- a/cmake/CheckHashScript.cmake +++ b/cmake/CheckHashScript.cmake @@ -3,11 +3,11 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/Modules") include(HashUtilities) check_hashes( - OUTVAR _test + _test HASH_FILES ${HASH_FILES} APPEND_FILES ${APPEND_FILES} ) if (NOT ${_test}) message(FATAL_ERROR "Not up to date") -endif() \ No newline at end of file +endif() diff --git a/cmake/Modules/FindLcov.cmake b/cmake/Modules/FindLcov.cmake index dc2eebb7..de4aba52 100644 --- a/cmake/Modules/FindLcov.cmake +++ b/cmake/Modules/FindLcov.cmake @@ -78,7 +78,7 @@ include(FindPackageHandleStandardArgs) find_program(LCOV_BIN lcov) find_program(GENINFO_BIN geninfo) find_program(GENHTML_BIN genhtml) -find_package_handle_standard_args(lcov +find_package_handle_standard_args(Lcov REQUIRED_VARS LCOV_BIN GENINFO_BIN GENHTML_BIN ) diff --git a/docs/dev/xtypes_relnotes.md b/docs/dev/xtypes_relnotes.md new file mode 100644 index 00000000..90415773 --- /dev/null +++ b/docs/dev/xtypes_relnotes.md @@ -0,0 +1,44 @@ +# Cyclone XTypes support + +## Release 0.9 + +### Type System + +- The following data types are not supported: map, bitset, wide-strings, char16, float128 +- For the C language binding, additionally the following types are not supported as part of a type’s key: union, sequence +- Union types: + - Using bitmask type as discriminator is not supported + - Inheritance (7.2.2.4.5) is not supported + - Extensibility `mutable` for unions is not supported +- The Dynamic Language Binding (7.5.2) is not supported (7.6.6, DynamicData and DynamicType API). Note: the Python API supports dynamic types without requiring a separate API. +- The built-in TypeLookup service (7.6.3.3) has no support for requesting type dependencies (service operation `getTypeDependencies`, section 7.6.3.3.4.1) and replying to a request of this type. + - Because of this, handling `PublicationBuiltinTopicData` or `SubscriptionBuiltinTopicData` with an incomplete set of dependent types (i.e. number of entries in `dependent_typeids` is less than `dependent_typeid_count`) may result in a failure to match a reader with a writer. +- In case a union has a default case, the C (de)serializer requires that the default case comes last because of a limitation of the IDL compiler. +- Using the `try_construct` annotation (7.2.2.7) with a parameter other than `DISCARD` (the default) is not supported. +- The C deserializer does not support explicit defaults for members of an aggregated type (`default` annotation) +- External (7.3.1.2.1.4) collections element types not supported (e.g. `sequence<@external b>`) +- Using `default_literal` (7.3.1.2.1.10) to set the default for enumerated types is not supported +- Default extensibility is `final` rather than `appendable` to maintain backwards compatibility with DDS implementations that do not support XTypes (including Cyclone DDS versions prior to 0.9.0). The IDL compiler has command-line option to select a different default. + +### Type Representation + +- Type Object type representation + - Recursive types are not supported (Strongly Connected Components, 7.3.4.9) + - User-defined annotations (7.3.1.2.4) and `verbatim` annotations (7.3.2.5.1.1) are not included in complete type objects +- IDL type representation + - Pragma declarations other than `keylist` are not supported + - Alternative Annotation Syntax (7.3.1.2.3) is not supported + - `verbatim` annotation (7.3.2.5.1.1) is not supported + - `ignore_literal_names` annotation (7.3.1.2.1.11) is not supported + - `non_serialized` annotation (7.3.1.2.1.14) is not supported +- XML (7.3.2) and XSD (7.3.3) type representation not supported + +### Data Representation + +- Default data representation is XCDR1 for `@final` types without optional members to maintain backwards compatibility with DDS implementations that do not support XTypes (including Cyclone DDS versions prior to 0.9.0). + + All other types require XCDR2: following 7.6.3.1.1 there is no need to support XCDR1 for interoperating with DDS implementations (ignoring those that only support XTypes 1.0 or 1.1, but not 1.2 or later). + + The C serializer does not support PL-CDR version 1 nor optional members in PLAIN-CDR version 1. + +- XML data representation (7.4.4) is not supported \ No newline at end of file diff --git a/package.xml b/package.xml index 34ea4fbc..8a8b152e 100644 --- a/package.xml +++ b/package.xml @@ -2,7 +2,7 @@ cyclonedds - 0.9.0 + 0.9.1 Eclipse Cyclone DDS is a very performant and robust open-source DDS implementation. Cyclone DDS is developed completely in the open as an Eclipse IoT project. Eclipse Foundation, Inc. Eclipse Public License 2.0 diff --git a/ports/android/README.md b/ports/android/README.md index 0888e8f5..0173ce12 100644 --- a/ports/android/README.md +++ b/ports/android/README.md @@ -16,7 +16,7 @@ document. [1]: https://developer.android.com/studio [2]: https://stackoverflow.com/questions/43923996/adb-root-is-not-working-on-emulator-cannot-run-as-root-in-production-builds - * Download [Android Studio](1) and extract the archive. + * Download [Android Studio][1] and extract the archive. * Run `android-studio/bin/studio.sh` to launch the *Android Studio Setup Wizard* and install the *Android SDK*. Select the *Android Virtual Device* @@ -38,7 +38,7 @@ document. to download the emulator image. When the download is finished, select *Q*, click *Next*, then *Finish* to create the *Android Virtual Device (AVD)*. -> As can be read from [this StackOverflow post](2), it is important to NOT +> As can be read from [this StackOverflow post][2], it is important to NOT > select a *Google Play* image, as these images do not allow you to gain > root privileges. @@ -48,9 +48,9 @@ document. [3]: https://developer.android.com/ndk/guides/cmake [4]: https://developer.android.com/ndk/guides/cmake#variables -The [Android NDK supports CMake](3) via a toolchain file. Build parameters +The [Android NDK supports CMake][3] via a toolchain file. Build parameters such as ABI can specified on the command line. For the complete list of -supported variables, consult the [Toolchain Arguments](4) section. +supported variables, consult the [Toolchain Arguments][4] section. ``` $ cd cyclonedds @@ -137,7 +137,7 @@ $ ip rule add from all lookup main pref 99 * You should now be able to ping the host from the emulator and vice versa. -> The [KDE Community Wiki](5) is an excellent source of information on the +> The [KDE Community Wiki][5] is an excellent source of information on the > Android emulator. The second-to-last instruction stems from there and was > vital to establish communication between the emulator and the host. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ac30414c..8c0049c7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ option(ENABLE_LIFESPAN "Enable Lifespan QoS support" ON) option(ENABLE_DEADLINE_MISSED "Enable Deadline Missed QoS support" ON) option(ENABLE_NETWORK_PARTITIONS "Enable network partition support" ON) option(ENABLE_SOURCE_SPECIFIC_MULTICAST "Enable support for source-specific multicast" ON) +option(ENABLE_IPV6 "Enable ipv6 support" ON) option(ENABLE_TYPE_DISCOVERY "Enable Type Discovery support" OFF) option(ENABLE_TOPIC_DISCOVERY "Enable Topic Discovery support" OFF) if(ENABLE_TOPIC_DISCOVERY) diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h index ea0e7055..291e5d9c 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h @@ -26,6 +26,9 @@ #include #include "dds/export.h" #include "dds/features.h" +#ifdef DDSRT_WITH_FREERTOSTCP +#include "dds/ddsrt/align.h" +#endif #include "dds/ddsc/dds_public_alloc.h" #include "dds/ddsc/dds_opcodes.h" diff --git a/src/core/ddsc/include/dds/export.h b/src/core/ddsc/include/dds/export.h new file mode 100755 index 00000000..30103d12 --- /dev/null +++ b/src/core/ddsc/include/dds/export.h @@ -0,0 +1,50 @@ + +#ifndef DDS_EXPORT_H +#define DDS_EXPORT_H + +#ifdef DDS_STATIC_DEFINE +# define DDS_EXPORT +# define DDS_NO_EXPORT +#else +# ifndef DDS_EXPORT +# ifdef ddsc_EXPORTS + /* We are building this library */ +# define DDS_EXPORT +# else + /* We are using this library */ +# define DDS_EXPORT +# endif +# endif + +# ifndef DDS_NO_EXPORT +# define DDS_NO_EXPORT +# endif +#endif + +#ifndef DDS_DEPRECATED +# define DDS_DEPRECATED +#endif + +#ifndef DDS_DEPRECATED_EXPORT +# define DDS_DEPRECATED_EXPORT DDS_EXPORT DDS_DEPRECATED +#endif + +#ifndef DDS_DEPRECATED_NO_EXPORT +# define DDS_DEPRECATED_NO_EXPORT DDS_NO_EXPORT DDS_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef DDS_NO_DEPRECATED +# define DDS_NO_DEPRECATED +# endif +#endif + +#ifndef DDS_INLINE_EXPORT +# if __MINGW32__ && (!defined(__clang__) || !defined(ddsc_EXPORTS)) +# define DDS_INLINE_EXPORT +# else +# define DDS_INLINE_EXPORT DDS_EXPORT +# endif +#endif + +#endif /* DDS_EXPORT_H */ diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index fd2a31da..43f96adb 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -374,6 +374,8 @@ void dds__builtin_init (struct dds_domain *dom) { dds_qos_t *qos = dds__create_builtin_qos (); + DDS_LOG(DDS_LC_CONFIG, " dds__builtin_init ..."); + dom->btif.arg = dom; dom->btif.builtintopic_get_tkmap_entry = dds__builtin_get_tkmap_entry; dom->btif.builtintopic_is_builtintopic = dds__builtin_is_builtintopic; @@ -415,6 +417,8 @@ void dds__builtin_init (struct dds_domain *dom) dom->builtintopic_writer_subscriptions = new_local_orphan_writer (&dom->gv, to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER), DDS_BUILTIN_TOPIC_SUBSCRIPTION_NAME, dom->builtin_reader_type, qos, builtintopic_whc_new (DSBT_READER, gh)); thread_state_asleep (lookup_thread_state ()); + DDS_LOG(DDS_LC_CONFIG, " builtin_topics writer done"); + dds_delete_qos (qos); /* ddsi_sertype_init initializes the refcount to 1 and dds_sertopic_register_locked increments diff --git a/src/core/ddsc/src/dds_domain.c b/src/core/ddsc/src/dds_domain.c index dfb6b802..81afea50 100644 --- a/src/core/ddsc/src/dds_domain.c +++ b/src/core/ddsc/src/dds_domain.c @@ -120,6 +120,7 @@ static dds_entity_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i break; } domain->m_id = domain->gv.config.domainId; + DDS_ILOG (DDS_LC_CONFIG, domain->m_id, " domain 0X%08x / 0x%08x config init done \n", domain->m_id, domain_id); if (rtps_config_prep (&domain->gv, domain->cfgst) != 0) { @@ -127,6 +128,7 @@ static dds_entity_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i domh = DDS_RETCODE_ERROR; goto fail_rtps_config; } + DDS_ILOG (DDS_LC_CONFIG, domain->m_id, " rtps_config_prep done \n"); if (rtps_init (&domain->gv) < 0) { @@ -134,6 +136,7 @@ static dds_entity_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i domh = DDS_RETCODE_ERROR; goto fail_rtps_init; } + DDS_ILOG (DDS_LC_CONFIG, domain->m_id, " rtps_init done! \n"); #ifdef DDS_HAS_SHM // if DDS_HAS_SHM is enabled the iceoryx runtime was created in rtps_init and is ready @@ -151,6 +154,7 @@ static dds_entity_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i domain to configured to do so. */ if (domain->gv.config.liveliness_monitoring) { + DDS_ILOG (DDS_LC_CONFIG, domain->m_id, " liveliness monitor thread start ... \n"); if (dds_global.threadmon_count++ == 0) { /* FIXME: configure settings */ @@ -169,9 +173,11 @@ static dds_entity_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i goto fail_threadmon_start; } } + DDS_ILOG (DDS_LC_CONFIG, domain->m_id, " liveliness monitor thread start! \n"); } dds__builtin_init (domain); + DDS_ILOG (DDS_LC_CONFIG, domain->m_id, " dds__builtin_init done! \n"); /* Set additional default participant properties */ @@ -187,10 +193,21 @@ static dds_entity_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i domh = DDS_RETCODE_ERROR; goto fail_rtps_start; } + DDS_LOG(DDS_LC_CONFIG, " rtps_start done!"); if (domain->gv.config.liveliness_monitoring) ddsi_threadmon_register_domain (dds_global.threadmon, &domain->gv); dds_entity_init_complete (&domain->m_entity); + + #if 0 // def DDSRT_WITH_FREERTOSTCP + /* CAUTION: NEVER open this slice unless in UT itself. */ + sleep(2U); /* wait thread wrapper */ + DDS_LOG(DDS_LC_CONFIG, " @@@@@@@@@@@@@@@@@@ domain init threads dump"); + /* dump all threads created in domain_init */ + //eth_run_cli("ps"); + sleep(1U); + #endif + return domh; fail_rtps_start: @@ -234,6 +251,8 @@ static dds_entity_t dds_domain_create_internal_xml_or_raw (dds_domain **domain_o if (dom) { + DDS_LOG (DDS_LC_CONFIG, " find dom %p", dom); + if (!implicit) domh = DDS_RETCODE_PRECONDITION_NOT_MET; else @@ -254,18 +273,22 @@ static dds_entity_t dds_domain_create_internal_xml_or_raw (dds_domain **domain_o } else { + DDS_LOG (DDS_LC_CONFIG, " create dom ..."); dom = dds_alloc (sizeof (*dom)); if ((domh = dds_domain_init (dom, id, config, implicit)) < 0) - dds_free (dom); + { dds_free (dom); } else { + DDS_LOG (DDS_LC_CONFIG, " dom created, domh = 0x%x ", domh); ddsrt_mutex_lock (&dom->m_entity.m_mutex); ddsrt_avl_insert (&dds_domaintree_def, &dds_global.m_domains, dom); dds_entity_register_child (&dds_global.m_entity, &dom->m_entity); + DDS_LOG (DDS_LC_CONFIG, " register domain to global done "); if (implicit) { dds_entity_add_ref_locked (&dom->m_entity); dds_handle_repin (&dom->m_entity.m_hdllink); + DDS_LOG (DDS_LC_CONFIG, " dom->m_entity.m_hdllink.hdl = 0x%x ", dom->m_entity.m_hdllink.hdl); } domh = dom->m_entity.m_hdllink.hdl; ddsrt_mutex_unlock (&dom->m_entity.m_mutex); diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index e4252e02..4c9154cc 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -52,6 +52,10 @@ dds_cyclonedds_entity dds_global; #define CDDS_STATE_STARTING 1u #define CDDS_STATE_READY 2u #define CDDS_STATE_STOPPING 3u + +#ifdef DDSRT_WITH_FREERTOSTCP +#define MAX_THREAD_NUM 32 +#endif static ddsrt_atomic_uint32_t dds_state = DDSRT_ATOMIC_UINT32_INIT (CDDS_STATE_ZERO); static void common_cleanup (void) @@ -112,7 +116,11 @@ dds_return_t dds_init (void) ddsrt_mutex_init (&dds_global.m_mutex); ddsrt_cond_init (&dds_global.m_cond); ddsi_iid_init (); + #ifdef DDSRT_WITH_FREERTOSTCP + thread_states_init (MAX_THREAD_NUM); + #else thread_states_init (128); + #endif if (dds_handle_server_init () != DDS_RETCODE_OK) { diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 9cba6a57..c9a977ad 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -91,6 +91,9 @@ const struct dds_entity_deriver dds_entity_deriver_participant = { .refresh_statistics = dds_entity_deriver_dummy_refresh_statistics }; +#ifdef DDSRT_WITH_FREERTOSTCP +char dds_peer[16] = {0}; +#endif dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_t *qos, const dds_listener_t *listener) { dds_domain *dom; @@ -99,6 +102,29 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ dds_participant * pp; ddsi_plist_t plist; dds_qos_t *new_qos = NULL; + +#ifdef DDSRT_WITH_FREERTOSTCP + /* Make sure DDS instance is initialized. */ + if ((ret = dds_init ()) < 0) + goto err_dds_init; + + char xml[1024]; + memset(xml, 0, sizeof(xml)); + if (inet_addr(dds_peer) == 0) + { + strncpy(dds_peer, "192.168.11.2", sizeof(dds_peer)); + dds_peer[sizeof(dds_peer) - 1] = '\0'; + } + + snprintf(xml, sizeof(xml) - 1, "\ +\ + \ +\ +", dds_peer); + const char *config = xml; + DDS_WARNING(" participant xml [%s] !", xml); + //DDS_WARNING(" participant peer using [%s] !", dds_peer); +#else const char *config = ""; /* Make sure DDS instance is initialized. */ @@ -106,6 +132,8 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ goto err_dds_init; (void) ddsrt_getenv ("CYCLONEDDS_URI", &config); +#endif + if ((ret = dds_domain_create_internal (&dom, domain, true, config)) < 0) goto err_domain_create; @@ -143,6 +171,7 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ ret = DDS_RETCODE_ERROR; goto err_new_participant; } + DDS_INFO(" built-in participant done !"); pp = dds_alloc (sizeof (*pp)); if ((ret = dds_entity_init (&pp->m_entity, &dom->m_entity, DDS_KIND_PARTICIPANT, false, true, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK)) < 0) @@ -160,6 +189,7 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ ddsrt_mutex_unlock (&dom->m_entity.m_mutex); dds_entity_init_complete (&pp->m_entity); + /* drop temporary extra ref to domain, dds_init */ dds_entity_unpin_and_drop_ref (&dom->m_entity); dds_entity_unpin_and_drop_ref (&dds_global.m_entity); diff --git a/src/core/ddsi/defconfig.c b/src/core/ddsi/defconfig.c index beae4e51..1f76f41d 100644 --- a/src/core/ddsi/defconfig.c +++ b/src/core/ddsi/defconfig.c @@ -14,7 +14,11 @@ void ddsi_config_init_default (struct ddsi_config *cfg) cfg->externalMaskString = "0.0.0.0"; cfg->allowMulticast = UINT32_C (2147483648); cfg->multicast_ttl = INT32_C (32); + #ifdef DDSRT_WITH_FREERTOSTCP + cfg->transport_selector = INT32_C (DDSI_TRANS_UDP); + #else cfg->transport_selector = INT32_C (1); + #endif cfg->enableMulticastLoopback = INT32_C (1); cfg->max_msg_size = UINT32_C (14720); cfg->max_rexmit_msg_size = UINT32_C (1456); @@ -58,8 +62,13 @@ void ddsi_config_init_default (struct ddsi_config *cfg) cfg->const_hb_intv_min = INT64_C (5000000); cfg->const_hb_intv_sched_min = INT64_C (20000000); cfg->const_hb_intv_sched_max = INT64_C (8000000000); + #ifdef DDSRT_WITH_FREERTOSTCP + cfg->max_queued_rexmit_bytes = UINT32_C (33554432); /* 524288->32M: > 4K framesize */ + cfg->max_queued_rexmit_msgs = UINT32_C (18000); /* 200->20480: > 4K framesize / fragmen_size */ + #else cfg->max_queued_rexmit_bytes = UINT32_C (524288); cfg->max_queued_rexmit_msgs = UINT32_C (200); + #endif cfg->writer_linger_duration = INT64_C (1000000000); cfg->socket_rcvbuf_size.min.isdefault = 1; cfg->socket_rcvbuf_size.max.isdefault = 1; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_cfgelems.h b/src/core/ddsi/include/dds/ddsi/ddsi_cfgelems.h index 5b5b3db8..d1e3e867 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_cfgelems.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_cfgelems.h @@ -15,6 +15,10 @@ #include "dds/features.h" +#ifdef DDSRT_WITH_FREERTOSTCP +#warning " debug rtos tcp stack including " +#include "dds/ddsrt/sockets/freertos_plus_tcp.h" +#endif static struct cfgelem network_interface_attributes[] = { STRING("autodetermine", NULL, 1, "false", @@ -156,7 +160,16 @@ static struct cfgelem general_cfgelems[] = { "translated to an internal address by replacing the network portion of " "the external address with the corresponding portion of the preferred " "network interface address. This option is IPv4-only.

")), - LIST("AllowMulticast", NULL, 1, "default", + LIST("AllowMulticast", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP +/* + * he "spdp" leaves multicast enabled for initial discovery only + * https://github.com/ros2/rmw_cyclonedds/issues/251 + */ + "spdp", +#else + "default", +#endif MEMBER(allowMulticast), FUNCTIONS(0, uf_allow_multicast, 0, pf_allow_multicast), DESCRIPTION( @@ -212,19 +225,34 @@ static struct cfgelem general_cfgelems[] = { "packets, to bypass the local routing tables. This is generally useful " "only when the routing tables cannot be trusted, which is highly " "unusual.

")), - ENUM("UseIPv6", NULL, 1, "default", + ENUM("UseIPv6", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP + "false", +#else + "default", +#endif MEMBER(compat_use_ipv6), FUNCTIONS(0, uf_boolean_default, 0, pf_nop), DESCRIPTION("

Deprecated (use Transport instead)

"), VALUES("false","true","default")), - ENUM("Transport", NULL, 1, "default", + ENUM("Transport", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP + "udp", +#else + "default", +#endif MEMBER(transport_selector), FUNCTIONS(0, uf_transport_selector, 0, pf_transport_selector), DESCRIPTION( "

This element allows selecting the transport to be used (udp, udp6, " "tcp, tcp6, raweth)

"), VALUES("default","udp","udp6","tcp","tcp6","raweth")), - BOOL("EnableMulticastLoopback", NULL, 1, "true", + BOOL("EnableMulticastLoopback", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP + "false", +#else + "true", +#endif MEMBER(enableMulticastLoopback), FUNCTIONS(0, uf_boolean, 0, pf_boolean), DESCRIPTION( @@ -234,7 +262,21 @@ static struct cfgelem general_cfgelems[] = { "communications, but if a node runs only a single Cyclone DDS service " "and does not host any other DDSI-capable programs, it should be set " "to \"false\" for improved performance.

")), - STRING("MaxMessageSize", NULL, 1, "14720 B", + + STRING("MaxMessageSize", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP +/* ddsi_config.max_msg_size and fragment_size will decide how many fragments in single submsg. + * keep this below MTU if STACK not support IP fragments + */ + #ifdef EQOS_TX_JUMBO_ENABLED + "8972 B", + #else + "1456 B", + #endif + +#else + "14720 B", +#endif MEMBER(max_msg_size), FUNCTIONS(0, uf_memsize, 0, pf_memsize), DESCRIPTION( @@ -246,7 +288,16 @@ static struct cfgelem general_cfgelems[] = { "

On some networks it may be necessary to set this item to keep the " "packetsize below the MTU to prevent IP fragmentation.

"), UNIT("memsize")), - STRING("MaxRexmitMessageSize", NULL, 1, "1456 B", + STRING("MaxRexmitMessageSize", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP + #ifdef EQOS_TX_JUMBO_ENABLED + "8972 B", + #else + "1464 B", + #endif +#else + "1456 B", +#endif MEMBER(max_rexmit_msg_size), FUNCTIONS(0, uf_memsize, 0, pf_memsize), DESCRIPTION( @@ -258,7 +309,17 @@ static struct cfgelem general_cfgelems[] = { "

On some networks it may be necessary to set this item to keep the " "packetsize below the MTU to prevent IP fragmentation.

"), UNIT("memsize")), - STRING("FragmentSize", NULL, 1, "1344 B", + STRING("FragmentSize", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP + #ifdef EQOS_TX_JUMBO_ENABLED + /* ipMAX_UDP_PAYLOAD_LENGTH(8972) > $FragSize + 20(RTPS_HDR) + 12(INFO_TS) + 36(DATA_HDR) + 28(HEART_BEAT) */ + "8864 B", + #else + "1400 B", + #endif +#else + "1344 B", +#endif MEMBER(fragment_size), FUNCTIONS(0, uf_memsize16, 0, pf_memsize16), DESCRIPTION( @@ -938,7 +999,15 @@ static struct cfgelem internal_watermarks_cfgelems[] = { "expressed in bytes. A suspended writer resumes transmitting when its " "Cyclone DDS WHC shrinks to this size.

"), UNIT("memsize")), - STRING("WhcHigh", NULL, 1, "500 kB", + STRING("WhcHigh", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP + /* 512K->24M: > 4K RGB888 framesize + * ALSO to be sure seqeunce limitation defined in idl + */ + "24576 kB", +#else + "500 kB", +#endif MEMBER(whc_highwater_mark), FUNCTIONS(0, uf_memsize, 0, pf_memsize), DESCRIPTION( @@ -1282,7 +1351,16 @@ static struct cfgelem internal_cfgelems[] = { "

This element allows configuring the base interval for sending " "writer heartbeats and the bounds within which it can vary.

"), UNIT("duration_inf")), - STRING("MaxQueuedRexmitBytes", NULL, 1, "512 kB", + + STRING("MaxQueuedRexmitBytes", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP + /* 512K->24M: > 4K RGB888 framesize + * ALSO to be sure seqeunce limitation defined in idl + */ + "24576 kB", +#else + "512 kB", +#endif MEMBER(max_queued_rexmit_bytes), FUNCTIONS(0, uf_memsize, 0, pf_memsize), DESCRIPTION( @@ -1292,7 +1370,14 @@ static struct cfgelem internal_cfgelems[] = { "NackDelay * AuxiliaryBandwidthLimit. It must be large enough to " "contain the largest sample that may need to be retransmitted.

"), UNIT("memsize")), - INT("MaxQueuedRexmitMessages", NULL, 1, "200", + + INT("MaxQueuedRexmitMessages", NULL, 1, +#ifdef DDSRT_WITH_FREERTOSTCP + /* 200->20480: > 4K framesize / fragmen_size */ + "20480", +#else + "200", +#endif MEMBER(max_queued_rexmit_msgs), FUNCTIONS(0, uf_uint, 0, pf_uint), DESCRIPTION( @@ -1804,7 +1889,11 @@ static struct cfgelem shmem_cfgelems[] = { #endif static struct cfgelem discovery_peer_cfgattrs[] = { +#ifdef DDSRT_WITH_FREERTOSTCP + STRING("Address", NULL, 1, "192.168.11.3:7400", // Not working, use XML string +#else STRING("Address", NULL, 1, NULL, +#endif MEMBEROF(ddsi_config_peer_listelem, peer), FUNCTIONS(0, uf_ipv4, ff_free, pf_string), DESCRIPTION( @@ -1829,6 +1918,16 @@ static struct cfgelem discovery_peers_group_cfgelems[] = { }; static struct cfgelem discovery_peers_cfgelems[] = { +#ifdef DDSRT_WITH_FREERTOSTCP + GROUP("Peer", NULL, discovery_peer_cfgattrs, INT_MAX, // Not working, use XML string + MEMBER(peers), + FUNCTIONS(if_peer, 0, 0, 0), + DESCRIPTION( + "

This element specifies the base port number (refer to the DDSI 2.1 " + "specification, section 9.6.1, constant PB).

" + )), + +#else GROUP("Peer", NULL, discovery_peer_cfgattrs, INT_MAX, MEMBER(peers), FUNCTIONS(if_peer, 0, 0, 0), @@ -1845,6 +1944,7 @@ static struct cfgelem discovery_peers_cfgelems[] = { ), MAXIMUM(0)), /* Group element can occur more than once, but 1 is required because of the way its processed (for now) */ +#endif END_MARKER }; @@ -1900,7 +2000,12 @@ static struct cfgelem discovery_cfgelems[] = { "and fixing the participant index has no adverse effects, it is " "recommended that the second be option be used.

" )), +#ifdef DDSRT_WITH_FREERTOSTCP + /* polling port number to dest peer */ + INT("MaxAutoParticipantIndex", NULL, 1, "2", /* 9 */ +#else INT("MaxAutoParticipantIndex", NULL, 1, "9", +#endif MEMBER(maxAutoParticipantIndex), FUNCTIONS(0, uf_natint, 0, pf_int), DESCRIPTION( diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_config.h b/src/core/ddsi/include/dds/ddsi/ddsi_config.h index 6862e1cc..4036b50a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_config.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_config.h @@ -310,8 +310,8 @@ struct ddsi_config unsigned delivery_queue_maxsamples; - uint16_t fragment_size; - uint32_t max_msg_size; + uint16_t fragment_size; // default: 1344 + uint32_t max_msg_size; /* default: 14720 how many fragment in single submsg */ uint32_t max_rexmit_msg_size; uint32_t init_transmit_extra_pct; uint32_t max_rexmit_burst_size; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_locator.h b/src/core/ddsi/include/dds/ddsi/ddsi_locator.h index 0d6d2631..584a06da 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_locator.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_locator.h @@ -23,7 +23,7 @@ struct ddsi_tran_conn; /* address field in locator maintained in network byte order, the rest in host */ typedef struct { - int32_t kind; + int32_t kind; // NN_LOCATOR_KIND_UDPv4 uint32_t port; unsigned char address[16]; } ddsi_locator_t; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h index b12de943..3cf62747 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -98,6 +98,24 @@ struct ddsi_serdata_default_unpadded { #define DDSI_SERDATA_DEFAULT_PAD(n) (n) #endif + +#if 0 +/* un-fold to easy to track in SI */ +struct ddsi_serdata_default { + struct ddsi_serdata c; + uint32_t pos; + uint32_t size; + DDSI_SERDATA_DEFAULT_DEBUG_FIELDS + struct ddsi_serdata_default_key key; + struct serdatapool *serpool; + struct ddsi_serdata_default *next; /* in pool->freelist */ + char pad[DDSI_SERDATA_DEFAULT_PAD (8 - (offsetof (struct ddsi_serdata_default_unpadded, data) % 8))]; + struct CDRHeader hdr; + char data[]; +}; +#endif + + struct ddsi_serdata_default { DDSI_SERDATA_DEFAULT_PREPAD; char pad[DDSI_SERDATA_DEFAULT_PAD (8 - (offsetof (struct ddsi_serdata_default_unpadded, data) % 8))]; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h index 2d36180e..14ea1252 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h @@ -18,7 +18,11 @@ extern "C" { typedef struct nn_udpv4mcgen_address { /* base IPv4 MC address is ipv4, host bits are bits base .. base+count-1, this machine is bit idx */ +#ifdef DDSRT_WITH_FREERTOSTCP + in_addr_t ipv4; +#else struct in_addr ipv4; +#endif uint8_t base; uint8_t count; uint8_t idx; /* must be last: then sorting will put them consecutively */ diff --git a/src/core/ddsi/include/dds/ddsi/q_log.h b/src/core/ddsi/include/dds/ddsi/q_log.h index 64d3c0f8..cbb9fb03 100644 --- a/src/core/ddsi/include/dds/ddsi/q_log.h +++ b/src/core/ddsi/include/dds/ddsi/q_log.h @@ -24,6 +24,9 @@ extern "C" { #define GVTRACE(...) DDS_CTRACE (&gv->logconfig, __VA_ARGS__) #define GVLOG(cat, ...) DDS_CLOG ((cat), &gv->logconfig, __VA_ARGS__) +#ifdef DDSRT_WITH_FREERTOSTCP +#define GVINFO(...) DDS_CLOG (DDS_LC_INFO, &gv->logconfig, __VA_ARGS__) +#endif #define GVWARNING(...) DDS_CLOG (DDS_LC_WARNING, &gv->logconfig, __VA_ARGS__) #define GVERROR(...) DDS_CLOG (DDS_LC_ERROR, &gv->logconfig, __VA_ARGS__) diff --git a/src/core/ddsi/include/dds/ddsi/q_thread.h b/src/core/ddsi/include/dds/ddsi/q_thread.h index 5d84c11d..fd382ea9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_thread.h +++ b/src/core/ddsi/include/dds/ddsi/q_thread.h @@ -132,7 +132,11 @@ DDS_EXPORT dds_return_t join_thread (struct thread_state1 *ts1); DDS_EXPORT void log_stack_traces (const struct ddsrt_log_cfg *logcfg, const struct ddsi_domaingv *gv); DDS_INLINE_EXPORT inline struct thread_state1 *lookup_thread_state (void) { +#ifdef DDSRT_WITH_FREERTOSTCP + struct thread_state1 *ts1 = (struct thread_state1 *)ddsrt_thread_tls_get(DDS_TLS_IDX_STATE, tsd_thread_state); +#else struct thread_state1 *ts1 = tsd_thread_state; +#endif if (ts1) return ts1; else diff --git a/src/core/ddsi/src/ddsi_cdrstream.c b/src/core/ddsi/src/ddsi_cdrstream.c index 084a627b..5e485c49 100644 --- a/src/core/ddsi/src/ddsi_cdrstream.c +++ b/src/core/ddsi/src/ddsi_cdrstream.c @@ -861,12 +861,12 @@ static char *dds_stream_reuse_string_bound (dds_istream_t * __restrict is, char so this check is superfluous, but perhaps rejecting such a sample is the wrong thing to do */ if (!alloc) - assert (str != NULL); + { assert (str != NULL); } else if (str == NULL) - str = dds_alloc (size); + { str = dds_alloc (size); } memcpy (str, src, length > size ? size : length); if (length > size) - str[size - 1] = '\0'; + { str[size - 1] = '\0'; } is->m_index += length; return str; } @@ -3821,7 +3821,11 @@ static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dd case DDS_OP_VAL_4BY: { const union { int32_t s; uint32_t u; float f; } x = { .u = dds_is_get4 (is) }; if (flags & DDS_OP_FLAG_FP) + #ifdef DDSRT_WITH_FREERTOSTCP + return prtf (buf, bufsize, "%f", x.f); + #else return prtf (buf, bufsize, "%g", x.f); + #endif else if (flags & DDS_OP_FLAG_SGN) return prtf (buf, bufsize, "%"PRId32, x.s); else @@ -3830,7 +3834,11 @@ static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dd case DDS_OP_VAL_8BY: { const union { int64_t s; uint64_t u; double f; } x = { .u = dds_is_get8 (is) }; if (flags & DDS_OP_FLAG_FP) + #ifdef DDSRT_WITH_FREERTOSTCP + return prtf (buf, bufsize, "%f", x.f); + #else return prtf (buf, bufsize, "%g", x.f); + #endif else if (flags & DDS_OP_FLAG_SGN) return prtf (buf, bufsize, "%"PRId64, x.s); else diff --git a/src/core/ddsi/src/ddsi_ipaddr.c b/src/core/ddsi/src/ddsi_ipaddr.c index 5d286ff3..eb086360 100644 --- a/src/core/ddsi/src/ddsi_ipaddr.c +++ b/src/core/ddsi/src/ddsi_ipaddr.c @@ -251,7 +251,11 @@ void ddsi_ipaddr_to_loc (ddsi_locator_t *dst, const struct sockaddr *src, int32_ { const struct sockaddr_in *x = (const struct sockaddr_in *) src; assert (kind == NN_LOCATOR_KIND_UDPv4 || kind == NN_LOCATOR_KIND_TCPv4); + #ifdef DDSRT_WITH_FREERTOSTCP + if (x->sin_addr == htonl (INADDR_ANY)) + #else if (x->sin_addr.s_addr == htonl (INADDR_ANY)) + #endif { dst->kind = NN_LOCATOR_KIND_INVALID; dst->port = NN_LOCATOR_PORT_INVALID; @@ -261,7 +265,11 @@ void ddsi_ipaddr_to_loc (ddsi_locator_t *dst, const struct sockaddr *src, int32_ { dst->port = (x->sin_port == 0) ? NN_LOCATOR_PORT_INVALID : ntohs (x->sin_port); memset (dst->address, 0, 12); + #ifdef DDSRT_WITH_FREERTOSTCP + memcpy (dst->address + 12, &x->sin_addr, 4); + #else memcpy (dst->address + 12, &x->sin_addr.s_addr, 4); + #endif } break; } @@ -310,7 +318,11 @@ void ddsi_ipaddr_from_loc (struct sockaddr_storage *dst, const ddsi_locator_t *s struct sockaddr_in *x = (struct sockaddr_in *) dst; x->sin_family = AF_INET; x->sin_port = (src->port == NN_LOCATOR_PORT_INVALID) ? 0 : htons ((unsigned short) src->port); + #ifdef DDSRT_WITH_FREERTOSTCP + memcpy (&x->sin_addr, src->address + 12, 4); + #else memcpy (&x->sin_addr.s_addr, src->address + 12, 4); + #endif break; } #if DDSRT_HAVE_IPV6 diff --git a/src/core/ddsi/src/ddsi_ownip.c b/src/core/ddsi/src/ddsi_ownip.c index 6e06a8fe..bbf8e97d 100644 --- a/src/core/ddsi/src/ddsi_ownip.c +++ b/src/core/ddsi/src/ddsi_ownip.c @@ -273,7 +273,11 @@ static bool gather_interfaces (struct ddsi_domaingv * const gv, size_t *n_interf ddsrt_freeifaddrs (ifa_root); assert ((*n_interfaces > 0) == (*maxq_count > 0)); if (*n_interfaces == 0) + { GVERROR ("failed to find interfaces for \"%s\"\n", gv->m_factory->m_typename); + ddsrt_free (*maxq_list); + ddsrt_free (*interfaces); + } return (*n_interfaces > 0); } diff --git a/src/core/ddsi/src/ddsi_plist.c b/src/core/ddsi/src/ddsi_plist.c index 9cabeafc..8dbff081 100644 --- a/src/core/ddsi/src/ddsi_plist.c +++ b/src/core/ddsi/src/ddsi_plist.c @@ -730,7 +730,7 @@ static dds_return_t ser_type_information (struct nn_xmsg *xmsg, nn_parameterid_t static dds_return_t valid_type_information (const void *src, size_t srcoff) { ddsi_typeinfo_t const * const * x = deser_generic_src (src, &srcoff, alignof (ddsi_typeinfo_t *)); - return *x != NULL && ddsi_typeinfo_valid (*x); + return (*x != NULL && ddsi_typeinfo_valid (*x)) ? DDS_RETCODE_OK : DDS_RETCODE_BAD_PARAMETER; } static bool equal_type_information (const void *srcx, const void *srcy, size_t srcoff) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 717e81e4..48028abd 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -1259,9 +1259,7 @@ static void cleanup_participant_sec_attributes(void *arg) if (!sc->crypto_context->crypto_key_factory->unregister_participant(sc->crypto_context->crypto_key_factory, attr->crypto_handle, &exception)) EXCEPTION_ERROR(gv, &exception, "Failed to unregister participant"); - ddsrt_avl_cfree(&pp_proxypp_treedef, &attr->proxy_participants, NULL); - ddsrt_mutex_unlock(&attr->lock); - ddsrt_free(attr); + participant_sec_attributes_free(attr); ddsrt_free(arg); } diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index eca7e147..cb8328de 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -188,7 +188,11 @@ static dds_return_t ddsi_tcp_sock_new (struct ddsi_tran_factory_tcp * const fact { case NN_LOCATOR_KIND_TCPv4: socketname.a4.sin_family = AF_INET; + #ifdef DDSRT_WITH_FREERTOSTCP + socketname.a4.sin_addr = htonl (INADDR_ANY); + #else socketname.a4.sin_addr.s_addr = htonl (INADDR_ANY); + #endif socketname.a4.sin_port = htons (port); break; #if DDSRT_HAVE_IPV6 @@ -459,8 +463,13 @@ static bool ddsi_tcp_select (struct ddsi_domaingv const * const gv, ddsrt_socket static int32_t addrfam_to_locator_kind (int af) { +#if DDSRT_HAVE_IPV6 assert (af == AF_INET || af == AF_INET6); return (af == AF_INET) ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6; +#else + assert (af == AF_INET); + return (af == AF_INET) ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_INVALID; +#endif } static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char *buf, size_t len, bool allow_spurious, ddsi_locator_t *srcloc) @@ -805,6 +814,10 @@ static dds_return_t ddsi_tcp_create_conn (ddsi_tran_conn_t *conn_out, struct dds struct ddsi_tran_factory_tcp * const fact = (struct ddsi_tran_factory_tcp *) fact_cmn; (void) qos; (void) port; + struct ddsi_domaingv const * const gv = fact->fact.gv; + struct nn_interface const * const intf = qos->m_interface ? qos->m_interface : &gv->interfaces[0]; + + fact->ddsi_tcp_conn_client.m_base.m_interf = intf; *conn_out = &fact->ddsi_tcp_conn_client.m_base; return DDS_RETCODE_OK; } @@ -1068,8 +1081,13 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener) switch (addr.a.sa_family) { case AF_INET: - if (addr.a4.sin_addr.s_addr == htonl (INADDR_ANY)) - addr.a4.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + #ifdef DDSRT_WITH_FREERTOSTCP + if (addr.a4.sin_addr == htonl (INADDR_ANY)) + { addr.a4.sin_addr = htonl (INADDR_LOOPBACK); } + #else + if (addr.a4.sin_addr.s_addr == htonl (INADDR_ANY)) + { addr.a4.sin_addr.s_addr = htonl (INADDR_LOOPBACK); } + #endif break; #if DDSRT_HAVE_IPV6 case AF_INET6: diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index be1ed3d7..6f5411bd 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -134,7 +134,9 @@ void ddsi_conn_free (ddsi_tran_conn_t conn) for (uint32_t i = 0; i < conn->m_base.gv->n_recv_threads; i++) { if (!conn->m_base.gv->recv_threads[i].ts) + { assert (!ddsrt_atomic_ld32 (&conn->m_base.gv->rtps_keepgoing)); + } else { switch (conn->m_base.gv->recv_threads[i].arg.mode) diff --git a/src/core/ddsi/src/ddsi_typelib.c b/src/core/ddsi/src/ddsi_typelib.c index ee799c7d..b3c84103 100644 --- a/src/core/ddsi/src/ddsi_typelib.c +++ b/src/core/ddsi/src/ddsi_typelib.c @@ -134,7 +134,7 @@ const ddsi_typeid_t *ddsi_typeinfo_complete_typeid (const ddsi_typeinfo_t *typei return (const ddsi_typeid_t *) &typeinfo->x.complete.typeid_with_size.type_id; } -static bool typeinfo_dependent_typeids_valid (const struct DDS_XTypes_TypeIdentifierWithDependencies *t) +static bool typeinfo_dependent_typeids_valid (const struct DDS_XTypes_TypeIdentifierWithDependencies *t, ddsi_typeid_kind_t kind) { if (t->dependent_typeid_count == -1) { @@ -149,8 +149,9 @@ static bool typeinfo_dependent_typeids_valid (const struct DDS_XTypes_TypeIdenti return false; for (uint32_t n = 0; n < t->dependent_typeids._length; n++) { - if (!ddsi_typeid_is_minimal_impl (&t->dependent_typeids._buffer[n].type_id) || - t->dependent_typeids._buffer[n].typeobject_serialized_size == 0) + if ((kind == DDSI_TYPEID_KIND_MINIMAL && !ddsi_typeid_is_minimal_impl (&t->dependent_typeids._buffer[n].type_id)) + || (kind == DDSI_TYPEID_KIND_COMPLETE && !ddsi_typeid_is_complete_impl (&t->dependent_typeids._buffer[n].type_id)) + || t->dependent_typeids._buffer[n].typeobject_serialized_size == 0) return false; } } @@ -164,8 +165,8 @@ bool ddsi_typeinfo_valid (const ddsi_typeinfo_t *typeinfo) if (ddsi_typeid_is_none (tid_min) || !ddsi_typeid_is_hash (tid_min) || ddsi_typeid_is_none (tid_compl) || !ddsi_typeid_is_hash (tid_compl)) return false; - if (!typeinfo_dependent_typeids_valid (&typeinfo->x.minimal) || - !typeinfo_dependent_typeids_valid (&typeinfo->x.complete)) + if (!typeinfo_dependent_typeids_valid (&typeinfo->x.minimal, DDSI_TYPEID_KIND_MINIMAL) || + !typeinfo_dependent_typeids_valid (&typeinfo->x.complete, DDSI_TYPEID_KIND_COMPLETE)) return false; return true; } @@ -323,18 +324,6 @@ static struct ddsi_type * ddsi_type_new (struct ddsi_domaingv *gv, const struct return type; } -static bool type_has_dep (const struct ddsi_type *type, const struct DDS_XTypes_TypeIdentifier *dep_type_id) -{ - struct ddsi_type_dep *dep = type->deps; - while (dep) - { - if (!ddsi_typeid_compare_impl (&dep->type->xt.id.x, dep_type_id)) - return true; - dep = dep->prev; - } - return false; -} - static void type_add_dep (struct ddsi_domaingv *gv, struct ddsi_type *type, const struct DDS_XTypes_TypeIdentifier *dep_type_id, const struct DDS_XTypes_TypeObject *dep_type_obj, uint32_t *n_match_upd, struct generic_proxy_endpoint ***gpe_match_upd) { struct ddsi_typeid_str tistr, tistrdep; @@ -376,11 +365,22 @@ static void type_add_deps (struct ddsi_domaingv *gv, struct ddsi_type *type, con for (uint32_t n = 0; dep_ids && n < dep_ids->_length; n++) { const struct DDS_XTypes_TypeIdentifier *dep_type_id = &dep_ids->_buffer[n].type_id; - if (ddsi_typeid_compare_impl (&type->xt.id.x, dep_type_id) && !type_has_dep (type, dep_type_id)) + if (!ddsi_typeid_compare_impl (&type->xt.id.x, dep_type_id)) + continue; + const struct DDS_XTypes_TypeObject *dep_type_obj = type_map ? ddsi_typemap_typeobj (type_map, dep_type_id) : NULL; + struct ddsi_type_dep *dep = type->deps; + while (dep) { - const struct DDS_XTypes_TypeObject *dep_type_obj = type_map ? ddsi_typemap_typeobj (type_map, dep_type_id) : NULL; - type_add_dep (gv, type, dep_type_id, dep_type_obj, n_match_upd, gpe_match_upd); + if (!ddsi_typeid_compare_impl (&dep->type->xt.id.x, dep_type_id) && dep_type_obj != NULL && ddsi_xt_type_add_typeobj (gv, &dep->type->xt, dep_type_obj) == DDS_RETCODE_OK) + { + dep->type->state = DDSI_TYPE_RESOLVED; + (void) ddsi_type_get_gpe_matches (gv, dep->type, gpe_match_upd, n_match_upd); + break; + } + dep = dep->prev; } + if (!dep) + type_add_dep (gv, type, dep_type_id, dep_type_obj, n_match_upd, gpe_match_upd); } } } @@ -648,6 +648,7 @@ uint32_t ddsi_type_get_gpe_matches (struct ddsi_domaingv *gv, const struct ddsi_ return 0; uint32_t n = 0; + thread_state_awake (lookup_thread_state (), gv); *gpe_match_upd = ddsrt_realloc (*gpe_match_upd, (*n_match_upd + ddsi_type_proxy_guid_list_count (&type->proxy_guids)) * sizeof (**gpe_match_upd)); struct ddsi_type_proxy_guid_list_iter it; for (ddsi_guid_t guid = ddsi_type_proxy_guid_list_iter_first (&type->proxy_guids, &it); !is_null_guid (&guid); guid = ddsi_type_proxy_guid_list_iter_next (&it)) @@ -664,6 +665,7 @@ uint32_t ddsi_type_get_gpe_matches (struct ddsi_domaingv *gv, const struct ddsi_ } *n_match_upd += n; ddsi_type_register_with_proxy_endpoints_locked (gv, type); + thread_state_asleep (lookup_thread_state ()); return n; } diff --git a/src/core/ddsi/src/ddsi_typelookup.c b/src/core/ddsi/src/ddsi_typelookup.c index 161d0b94..2210dcc5 100644 --- a/src/core/ddsi/src/ddsi_typelookup.c +++ b/src/core/ddsi/src/ddsi_typelookup.c @@ -172,6 +172,13 @@ void ddsi_tl_handle_request (struct ddsi_domaingv *gv, struct ddsi_serdata *d) DDS_Builtin_TypeLookup_Request req; memset (&req, 0, sizeof (req)); ddsi_serdata_to_sample (d, &req, NULL, NULL); + if (req.data._d != DDS_Builtin_TypeLookup_getTypes_HashId) + { + GVTRACE (" handle-tl-req wr "PGUIDFMT " unknown req-type %"PRIi32, PGUID (from_guid (&req.header.requestId.writer_guid)), req.data._d); + ddsi_sertype_free_sample (d->type, &req, DDS_FREE_CONTENTS); + return; + } + GVTRACE (" handle-tl-req wr "PGUIDFMT " seqnr %"PRIu64" ntypeids %"PRIu32, PGUID (from_guid (&req.header.requestId.writer_guid)), from_seqno (&req.header.requestId.sequence_number), req.data._u.getTypes.type_ids._length); ddsrt_mutex_lock (&gv->typelib_lock); @@ -221,6 +228,13 @@ void ddsi_tl_handle_reply (struct ddsi_domaingv *gv, struct ddsi_serdata *d) DDS_Builtin_TypeLookup_Reply reply; memset (&reply, 0, sizeof (reply)); ddsi_serdata_to_sample (d, &reply, NULL, NULL); + if (reply.return_data._d != DDS_Builtin_TypeLookup_getTypes_HashId) + { + GVTRACE (" handle-tl-reply wr "PGUIDFMT " unknown reply-type %"PRIi32, PGUID (from_guid (&reply.header.requestId.writer_guid)), reply.return_data._d); + ddsi_sertype_free_sample (d->type, &reply, DDS_FREE_CONTENTS); + return; + } + bool resolved = false; ddsrt_mutex_lock (&gv->typelib_lock); GVTRACE ("handle-tl-reply wr "PGUIDFMT " seqnr %"PRIu64" ntypeids %"PRIu32"\n", PGUID (from_guid (&reply.header.requestId.writer_guid)), from_seqno (&reply.header.requestId.sequence_number), reply.return_data._u.getType._u.result.types._length); diff --git a/src/core/ddsi/src/ddsi_typewrap.c b/src/core/ddsi/src/ddsi_typewrap.c index 3b87bb63..21cc7521 100644 --- a/src/core/ddsi/src/ddsi_typewrap.c +++ b/src/core/ddsi/src/ddsi_typewrap.c @@ -420,7 +420,7 @@ static void xt_sbounds_to_lbounds (struct DDS_XTypes_LBoundSeq *lb, const struct static void xt_lbounds_dup (struct DDS_XTypes_LBoundSeq *dst, const struct DDS_XTypes_LBoundSeq *src) { dst->_length = src->_length; - dst->_buffer = ddsrt_memdup (&src->_buffer, dst->_length * sizeof (*dst->_buffer)); + dst->_buffer = ddsrt_memdup (src->_buffer, dst->_length * sizeof (*dst->_buffer)); } static void DDS_XTypes_AppliedBuiltinMemberAnnotations_copy (struct DDS_XTypes_AppliedBuiltinMemberAnnotations *dst, const struct DDS_XTypes_AppliedBuiltinMemberAnnotations *src); diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 26c59e9e..2964bd5d 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -88,6 +88,19 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn_cmn, unsigned char * bu msghdr.msg_controllen = 0; #endif +#ifdef DDSRT_WITH_FREERTOSTCP +{ + if (conn->m_base.m_base.m_port == 7410) + { + GVTRACE(" @@@@@@ waitset UDP RX on port %u ... ", conn->m_base.m_base.m_port); + } + if (conn->m_base.m_base.m_port == 7411) + { + GVTRACE(" @@@@@@ uc UDP RX on port %u ... ", conn->m_base.m_base.m_port); + } +} +#endif + do { rc = ddsrt_recvmsg (conn->m_sock, &msghdr, 0, &ret); } while (rc == DDS_RETCODE_INTERRUPTED); @@ -95,7 +108,9 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn_cmn, unsigned char * bu if (ret > 0) { if (srcloc) - addr_to_loc (conn->m_base.m_factory, srcloc, &src); + { + addr_to_loc (conn->m_base.m_factory, srcloc, &src); + } if (gv->pcap_fp) { @@ -153,6 +168,13 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn_cmn, const ddsi_locato #if defined(__sun) && !defined(_XPG4_2) msg.msg_accrights = NULL; msg.msg_accrightslen = 0; +#elif defined DDSRT_WITH_FREERTOSTCP /* got whole payload sz for trans */ + msg.msg_control = NULL; + msg.msg_controllen = 0U; + for (int ii = 0; ii < niov; ii++) + { + msg.msg_controllen += iov[ii].iov_len; + } #else msg.msg_control = NULL; msg.msg_controllen = 0; @@ -163,6 +185,7 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn_cmn, const ddsi_locato DDSRT_UNUSED_ARG (flags); #endif #if MSG_NOSIGNAL && !LWIP_SOCKET +#error sendflags |= MSG_NOSIGNAL; #endif do { @@ -266,7 +289,13 @@ static dds_return_t set_dont_route (struct ddsi_domaingv const * const gv, ddsrt return rc; } +#ifdef DDSRT_WITH_FREERTOSTCP +static dds_return_t set_socket_buffer (struct ddsi_domaingv const * const gv, + ddsrt_socket_t sock, int32_t socket_option, const char *socket_option_name, + const char *name, const struct ddsi_config_socket_buf_size *config, uint32_t default_min_size) +#else static dds_return_t set_socket_buffer (struct ddsi_domaingv const * const gv, ddsrt_socket_t sock, int32_t socket_option, const char *socket_option_name, const char *name, const struct ddsi_config_socket_buf_size *config, uint32_t default_min_size) +#endif { // if (min, max)= and initbuf= then request= and result= // (def, def) < defmin defmin whatever it is @@ -275,9 +304,14 @@ static dds_return_t set_socket_buffer (struct ddsi_domaingv const * const gv, dd // (M, N=M) anything N error if < M // defmin = 1MB for receive buffer, 0B for send buffer + +#ifdef DDSRT_WITH_FREERTOSTCP + const bool always_set_size = true; +#else const bool always_set_size = // whether to call setsockopt unconditionally ((config->min.isdefault && !config->max.isdefault) || (!config->min.isdefault && !config->max.isdefault && config->max.value >= config->min.value)); +#endif const uint32_t socket_min_buf_size = // error if it ends up below this !config->min.isdefault ? config->min.value : 0; const uint32_t socket_req_buf_size = // size to request @@ -289,7 +323,13 @@ static dds_return_t set_socket_buffer (struct ddsi_domaingv const * const gv, dd socklen_t optlen = (socklen_t) sizeof (actsize); dds_return_t rc; +#ifdef DDSRT_WITH_FREERTOSTCP +#warning " *** FreeRTOS-Plus-TCP FreeRTOS_Plus_TCP runtime wrapper ..." + rc = DDS_RETCODE_OK; + actsize = socket_req_buf_size + 1U; /* stub getsockopt a different value */ +#else rc = ddsrt_getsockopt (sock, SOL_SOCKET, socket_option, &actsize, &optlen); +#endif if (rc == DDS_RETCODE_BAD_PARAMETER) { /* not all stacks support getting/setting RCVBUF */ @@ -304,6 +344,13 @@ static dds_return_t set_socket_buffer (struct ddsi_domaingv const * const gv, dd if (always_set_size || actsize < socket_req_buf_size) { + #ifdef DDSRT_WITH_FREERTOSTCP + rc = ddsrt_setsockopt (sock, SOL_SOCKET, socket_option, &socket_req_buf_size, sizeof (actsize)); + + #warning " *** FreeRTOS-Plus-TCP FreeRTOS_Plus_TCP runtime wrapper ..." + actsize = socket_req_buf_size; + + #else (void) ddsrt_setsockopt (sock, SOL_SOCKET, socket_option, &socket_req_buf_size, sizeof (actsize)); /* We don't check the return code from setsockopt, because some O/Ss tend @@ -316,11 +363,15 @@ static dds_return_t set_socket_buffer (struct ddsi_domaingv const * const gv, dd } if (actsize >= socket_req_buf_size) - GVLOG (DDS_LC_CONFIG, "socket %s buffer size set to %"PRIu32" bytes\n", name, actsize); + { + GVLOG (DDS_LC_CONFIG, "socket %s buffer size set to %"PRIu32" bytes\n", name, actsize); + } else if (actsize >= socket_min_buf_size) - GVLOG (DDS_LC_CONFIG, + { + GVLOG (DDS_LC_CONFIG, "failed to increase socket %s buffer size to %"PRIu32" bytes, continuing with %"PRIu32" bytes\n", name, socket_req_buf_size, actsize); + } else { /* If the configuration states it must be >= X, then error out if the @@ -330,9 +381,10 @@ static dds_return_t set_socket_buffer (struct ddsi_domaingv const * const gv, dd name, socket_min_buf_size, actsize); rc = DDS_RETCODE_NOT_ENOUGH_SPACE; } + #endif } - return (rc < 0) ? rc : (actsize > (uint32_t) INT32_MAX) ? INT32_MAX : (int32_t) actsize; + return (rc < 0) ? rc : ((actsize > (uint32_t) INT32_MAX) ? INT32_MAX : (int32_t) actsize); } static dds_return_t set_rcvbuf (struct ddsi_domaingv const * const gv, ddsrt_socket_t sock, const struct ddsi_config_socket_buf_size *config) @@ -374,6 +426,7 @@ static dds_return_t set_mc_options_transmit_ipv6 (struct ddsi_domaingv const * c static dds_return_t set_mc_options_transmit_ipv4_if (struct ddsi_domaingv const * const gv, struct nn_interface const * const intf, ddsrt_socket_t sock) { +#ifndef DDSRT_WITH_FREERTOSTCP #if (defined(__linux) || defined(__APPLE__)) && !LWIP_SOCKET if (gv->config.use_multicast_if_mreqn) { @@ -390,6 +443,7 @@ static dds_return_t set_mc_options_transmit_ipv4_if (struct ddsi_domaingv const } #else (void) gv; +#endif #endif return ddsrt_setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, intf->loc.address + 12, 4); } @@ -466,7 +520,11 @@ static dds_return_t ddsi_udp_create_conn (ddsi_tran_conn_t *conn_out, ddsi_tran_ { case NN_LOCATOR_KIND_UDPv4: if (bind_to_any) - socketname.a4.sin_addr.s_addr = htonl (INADDR_ANY); + #ifdef DDSRT_WITH_FREERTOSTCP + { socketname.a4.sin_addr = htonl (INADDR_ANY); } + #else + { socketname.a4.sin_addr.s_addr = htonl (INADDR_ANY); } + #endif break; #if DDSRT_HAVE_IPV6 case NN_LOCATOR_KIND_UDPv6: @@ -509,11 +567,15 @@ static dds_return_t ddsi_udp_create_conn (ddsi_tran_conn_t *conn_out, ddsi_tran_ break; } while (!ddsrt_atomic_cas32 (&fact->receive_buf_size, old, (uint32_t) rc)); } + GVLOG (DDS_LC_CONFIG, " set_rcvbuf done\n"); if (set_sndbuf (gv, sock, &gv->config.socket_sndbuf_size) < 0) goto fail_w_socket; + GVLOG (DDS_LC_CONFIG, " set_sndbuf done\n"); + if (gv->config.dontRoute && set_dont_route (gv, sock, ipv6) != DDS_RETCODE_OK) goto fail_w_socket; + GVLOG (DDS_LC_CONFIG, " set_dont_route done\n"); if ((rc = ddsrt_bind (sock, &socketname.a, ddsrt_sockaddr_get_size (&socketname.a))) != DDS_RETCODE_OK) { @@ -531,6 +593,7 @@ static dds_return_t ddsi_udp_create_conn (ddsi_tran_conn_t *conn_out, ddsi_tran_ (rc == DDS_RETCODE_PRECONDITION_NOT_MET) ? "address in use" : dds_strretcode (rc)); goto fail_w_socket; } + GVLOG (DDS_LC_CONFIG, " ddsrt_bind to port %u done \n", get_socket_port (gv, sock)); if (set_mc_xmit_options) { @@ -538,6 +601,7 @@ static dds_return_t ddsi_udp_create_conn (ddsi_tran_conn_t *conn_out, ddsi_tran_ if (rc != DDS_RETCODE_OK) goto fail_w_socket; } + GVLOG (DDS_LC_CONFIG, " set_mc_options_transmit %d done\n", set_mc_xmit_options); #ifdef DDS_HAS_NETWORK_CHANNELS if (qos->m_diffserv != 0 && fact->m_kind == NN_LOCATOR_KIND_UDPv4) @@ -571,7 +635,11 @@ static dds_return_t ddsi_udp_create_conn (ddsi_tran_conn_t *conn_out, ddsi_tran_ conn->m_base.m_disable_multiplexing_fn = ddsi_udp_disable_multiplexing; conn->m_base.m_locator_fn = ddsi_udp_conn_locator; +#ifdef DDSRT_WITH_FREERTOSTCP + GVLOG (DDS_LC_CONFIG, "ddsi_udp_create_conn %s socket %"PRIdSOCK" port %"PRIu32"\n", purpose_str, conn->m_sock, conn->m_base.m_base.m_port); +#else GVTRACE ("ddsi_udp_create_conn %s socket %"PRIdSOCK" port %"PRIu32"\n", purpose_str, conn->m_sock, conn->m_base.m_base.m_port); +#endif *conn_out = &conn->m_base; return DDS_RETCODE_OK; @@ -605,9 +673,13 @@ static int joinleave_asm_mcgroup (ddsrt_socket_t socket, int join, const ddsi_lo struct ip_mreq mreq; mreq.imr_multiaddr = mcip.a4.sin_addr; if (interf) - memcpy (&mreq.imr_interface, interf->loc.address + 12, sizeof (mreq.imr_interface)); + { memcpy (&mreq.imr_interface, interf->loc.address + 12, sizeof (mreq.imr_interface)); } else - mreq.imr_interface.s_addr = htonl (INADDR_ANY); + #ifdef DDSRT_WITH_FREERTOSTCP + { mreq.imr_interface = htonl (INADDR_ANY); } + #else + { mreq.imr_interface.s_addr = htonl (INADDR_ANY); } + #endif rc = ddsrt_setsockopt (socket, IPPROTO_IP, join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreq, sizeof (mreq)); } return (rc == DDS_RETCODE_OK) ? 0 : -1; @@ -714,15 +786,25 @@ static int ddsi_udp_is_mcaddr (const struct ddsi_tran_factory *tran, const ddsi_ switch (loc->kind) { case NN_LOCATOR_KIND_UDPv4: { +#ifdef DDSRT_WITH_FREERTOSTCP + const in_addr_t *ipv4 = (const in_addr_t *) (loc->address + 12); + DDSRT_WARNING_GNUC_OFF(sign-conversion) + return IN_MULTICAST (ntohl (*ipv4)); +#else const struct in_addr *ipv4 = (const struct in_addr *) (loc->address + 12); DDSRT_WARNING_GNUC_OFF(sign-conversion) return IN_MULTICAST (ntohl (ipv4->s_addr)); +#endif DDSRT_WARNING_GNUC_ON(sign-conversion) } case NN_LOCATOR_KIND_UDPv4MCGEN: { const nn_udpv4mcgen_address_t *mcgen = (const nn_udpv4mcgen_address_t *) loc->address; DDSRT_WARNING_GNUC_OFF(sign-conversion) + #ifdef DDSRT_WITH_FREERTOSTCP + return IN_MULTICAST (ntohl (mcgen->ipv4)); + #else return IN_MULTICAST (ntohl (mcgen->ipv4.s_addr)); + #endif DDSRT_WARNING_GNUC_ON(sign-conversion) } #if DDSRT_HAVE_IPV6 @@ -832,7 +914,11 @@ static char *ddsi_udp_locator_to_string (char *dst, size_t sizeof_dst, const dds memcpy (&mcgen, loc->address, sizeof (mcgen)); memset (&src, 0, sizeof (src)); src.sin_family = AF_INET; + #ifdef DDSRT_WITH_FREERTOSTCP + memcpy (&src.sin_addr, &mcgen.ipv4, 4); + #else memcpy (&src.sin_addr.s_addr, &mcgen.ipv4, 4); + #endif ddsrt_sockaddrtostr ((const struct sockaddr *) &src, dst, sizeof_dst); pos = strlen (dst); assert (pos <= sizeof_dst); @@ -876,9 +962,11 @@ static int ddsi_udp_locator_from_sockaddr (const struct ddsi_tran_factory *tran_ if (tran->m_kind != NN_LOCATOR_KIND_UDPv4) return -1; break; +#if DDSRT_HAVE_IPV6 case AF_INET6: if (tran->m_kind != NN_LOCATOR_KIND_UDPv6) return -1; +#endif break; } ddsi_ipaddr_to_loc (loc, sockaddr, tran->m_kind); diff --git a/src/core/ddsi/src/ddsi_wraddrset.c b/src/core/ddsi/src/ddsi_wraddrset.c index d3430d38..dcca2a15 100644 --- a/src/core/ddsi/src/ddsi_wraddrset.c +++ b/src/core/ddsi/src/ddsi_wraddrset.c @@ -691,7 +691,11 @@ static void wras_add_locator (const struct ddsi_domaingv *gv, struct addrset *ne memcpy (&l1, tmploc.c.address, sizeof (l1)); tmploc.c.kind = NN_LOCATOR_KIND_UDPv4; memset (tmploc.c.address, 0, 12); + #ifdef DDSRT_WITH_FREERTOSTCP + iph = ntohl (l1.ipv4); + #else iph = ntohl (l1.ipv4.s_addr); + #endif for (i = 0; i < nreaders; i++) { cover_info_t ci = cover_get (covered, i, locidx); diff --git a/src/core/ddsi/src/q_addrset.c b/src/core/ddsi/src/q_addrset.c index 25759c80..5e1095e1 100644 --- a/src/core/ddsi/src/q_addrset.c +++ b/src/core/ddsi/src/q_addrset.c @@ -96,6 +96,8 @@ int add_addresses_to_addrset (const struct ddsi_domaingv *gv, struct addrset *as DDSRT_WARNING_MSVC_OFF(4996); char *addrs_copy, *cursor, *a; int retval = -1; + + GVLOG (DDS_LC_CONFIG, " add addrs [%s] @@@@@@@@@@@@", addrs); addrs_copy = ddsrt_strdup (addrs); cursor = addrs_copy; while ((a = ddsrt_strsep (&cursor, ",")) != NULL) diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 2e60c34b..c293de6c 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -223,6 +223,20 @@ static struct addrset *addrset_from_locatorlists (const struct ddsi_domaingv *gv external IP address, this locator will be translated into one in the same subnet as our own local ip and selected. */ assert (gv->n_interfaces == 1); // gv->extmask: the hack is only supported if limited to a single interface + #ifdef DDSRT_WITH_FREERTOSTCP + in_addr_t tmp4 = *((in_addr_t *) (loc.address + 12)); + const in_addr_t ownip = *((in_addr_t *) (gv->interfaces[0].loc.address + 12)); + const in_addr_t extip = *((in_addr_t *) (gv->interfaces[0].extloc.address + 12)); + const in_addr_t extmask = *((in_addr_t *) (gv->extmask.address + 12)); + + if ((tmp4 & extmask) == (extip & extmask)) + { + /* translate network part of the IP address from the external + one to the internal one */ + tmp4 = (tmp4 & ~extmask) | (ownip & extmask); + memcpy (loc.address + 12, &tmp4, 4); + } + #else struct in_addr tmp4 = *((struct in_addr *) (loc.address + 12)); const struct in_addr ownip = *((struct in_addr *) (gv->interfaces[0].loc.address + 12)); const struct in_addr extip = *((struct in_addr *) (gv->interfaces[0].extloc.address + 12)); @@ -235,6 +249,8 @@ static struct addrset *addrset_from_locatorlists (const struct ddsi_domaingv *gv tmp4.s_addr = (tmp4.s_addr & ~extmask.s_addr) | (ownip.s_addr & extmask.s_addr); memcpy (loc.address + 12, &tmp4, 4); } + #endif + } addrset_from_locatorlists_add_one (gv, &loc, as, &intfs, &direct); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 1ce7f8de..d934f86c 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3329,6 +3329,7 @@ void update_proxy_endpoint_matching (const struct ddsi_domaingv *gv, struct gene const char *tp = entity_topic_name (&proxy_ep->e); ddsrt_mtime_t tnow = ddsrt_time_monotonic (); + thread_state_awake (lookup_thread_state (), gv); entidx_enum_init_topic (&it, gv->entity_index, mkind, tp, &max); while ((em = entidx_enum_next_max (&it, &max)) != NULL) { @@ -3336,6 +3337,7 @@ void update_proxy_endpoint_matching (const struct ddsi_domaingv *gv, struct gene generic_do_match_connect (&proxy_ep->e, em, tnow, false); } entidx_enum_fini (&it); + thread_state_asleep (lookup_thread_state ()); } @@ -3998,6 +4000,10 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_g } } } + else + { + wr->lease = NULL; + } return 0; } @@ -4340,7 +4346,11 @@ static void joinleave_mcast_helper (struct ddsi_domaingv *gv, ddsi_tran_conn_t c memcpy (&l1, l.address, sizeof (l1)); l.kind = NN_LOCATOR_KIND_UDPv4; memset (l.address, 0, 12); + #ifdef DDSRT_WITH_FREERTOSTCP + iph = ntohl (l1.ipv4); + #else iph = ntohl (l1.ipv4.s_addr); + #endif for (uint32_t i = 1; i < ((uint32_t)1 << l1.count); i++) { uint32_t ipn, iph1 = iph; @@ -5981,9 +5991,9 @@ static int proxy_endpoint_common_init (struct entity_common *e, struct proxy_end int ret; if (is_builtin_entityid (guid->entityid, proxypp->vendor)) - assert ((plist->qos.present & QP_TYPE_NAME) == 0); + { assert ((plist->qos.present & QP_TYPE_NAME) == 0); } else - assert ((plist->qos.present & (QP_TOPIC_NAME | QP_TYPE_NAME)) == (QP_TOPIC_NAME | QP_TYPE_NAME)); + { assert ((plist->qos.present & (QP_TOPIC_NAME | QP_TYPE_NAME)) == (QP_TOPIC_NAME | QP_TYPE_NAME)); } name = (plist->present & PP_ENTITY_NAME) ? plist->entity_name : ""; entity_common_init (e, proxypp->e.gv, guid, name, kind, tcreate, proxypp->vendor, false); diff --git a/src/core/ddsi/src/q_freelist.c b/src/core/ddsi/src/q_freelist.c index 28ed6ea1..9ce76244 100644 --- a/src/core/ddsi/src/q_freelist.c +++ b/src/core/ddsi/src/q_freelist.c @@ -120,6 +120,11 @@ void nn_freelist_init (struct nn_freelist *fl, uint32_t max, size_t linkoff) fl->count = 0; fl->max = (max == UINT32_MAX) ? max-1 : max; fl->linkoff = linkoff; + +#ifdef DDSRT_WITH_FREERTOSTCP + /* init TLS var */ + ddsrt_thread_tls_set(freelist_inner_idx, DDS_TLS_IDX_FREE, (void*)(-1)); +#endif } static void *get_next (const struct nn_freelist *fl, const void *e) @@ -160,6 +165,27 @@ void nn_freelist_fini (struct nn_freelist *fl, void (*xfree) (void *)) static ddsrt_atomic_uint32_t freelist_inner_idx_off = DDSRT_ATOMIC_UINT32_INIT(0); +#ifdef DDSRT_WITH_FREERTOSTCP +static int get_freelist_inner_idx (void) +{ + int inner_idx = -1; + + inner_idx = ddsrt_thread_tls_get(DDS_TLS_IDX_FREE, freelist_inner_idx); + + if(inner_idx == -1) + { + static const uint64_t unihashconsts[] = { + UINT64_C (16292676669999574021), + UINT64_C (10242350189706880077), + }; + uintptr_t addr; + uint64_t t = (uint64_t) ((uintptr_t) &addr) + ddsrt_atomic_ld32 (&freelist_inner_idx_off); + inner_idx = (int) (((((uint32_t) t + unihashconsts[0]) * ((uint32_t) (t >> 32) + unihashconsts[1]))) >> (64 - NN_FREELIST_NPAR_LG2)); + } + ddsrt_thread_tls_set(freelist_inner_idx, DDS_TLS_IDX_FREE, inner_idx); + return inner_idx; +} +#else static int get_freelist_inner_idx (void) { if (freelist_inner_idx == -1) @@ -174,6 +200,7 @@ static int get_freelist_inner_idx (void) } return freelist_inner_idx; } +#endif static int lock_inner (struct nn_freelist *fl) { @@ -185,7 +212,12 @@ static int lock_inner (struct nn_freelist *fl) { ddsrt_atomic_st32(&fl->cc, 0); ddsrt_atomic_inc32(&freelist_inner_idx_off); + + #ifdef DDSRT_WITH_FREERTOSTCP + ddsrt_thread_tls_set(freelist_inner_idx, DDS_TLS_IDX_FREE, (void*)(-1)); + #else freelist_inner_idx = -1; + #endif } } return k; diff --git a/src/core/ddsi/src/q_gc.c b/src/core/ddsi/src/q_gc.c index 61819126..7941ceb3 100644 --- a/src/core/ddsi/src/q_gc.c +++ b/src/core/ddsi/src/q_gc.c @@ -204,7 +204,11 @@ struct gcreq_queue *gcreq_queue_new (struct ddsi_domaingv *gv) bool gcreq_queue_start (struct gcreq_queue *q) { +#ifdef DDSRT_WITH_FREERTOSTCP + if (create_thread (&q->ts, q->gv, "dds_gc", (uint32_t (*) (void *)) gcreq_queue_thread, q) == DDS_RETCODE_OK) +#else if (create_thread (&q->ts, q->gv, "gc", (uint32_t (*) (void *)) gcreq_queue_thread, q) == DDS_RETCODE_OK) +#endif return true; else { diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 0338f7e8..f7f4725d 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -130,6 +130,13 @@ static enum make_uc_sockets_ret make_uc_sockets (struct ddsi_domaingv *gv, uint3 } ddsi_conn_locator (gv->disc_conn_uc, &gv->loc_meta_uc); ddsi_conn_locator (gv->data_conn_uc, &gv->loc_default_uc); + + #ifdef DDSRT_WITH_FREERTOSTCP + /* update portid to up */ + *pdisc = gv->disc_conn_uc->m_base.m_port; + *pdata = gv->data_conn_uc->m_base.m_port; + #endif + return MUSRET_SUCCESS; fail_data: @@ -539,6 +546,7 @@ int rtps_config_prep (struct ddsi_domaingv *gv, struct cfgst *cfgst) DDS_ILOG (DDS_LC_ERROR, gv->config.domainId, "Invalid port mapping: %s\n", message); goto err_config_late_error; } + DDS_ILOG (DDS_LC_INFO, gv->config.domainId, " @@@@@@@@@@@ port mapping: <%s> \n", message); } /* retry_on_reject_duration default is dependent on late_ack_mode and responsiveness timeout, so fix up */ @@ -1022,20 +1030,23 @@ static int setup_and_start_recv_threads (struct ddsi_domaingv *gv) it before it does anything with it. */ if ((gv->recv_threads[i].arg.rbpool = nn_rbufpool_new (&gv->logconfig, gv->config.rbuf_size, gv->config.rmsg_chunk_size)) == NULL) { - GVERROR ("rtps_init: can't allocate receive buffer pool for thread %s\n", gv->recv_threads[i].name); + GVERROR ("rtps_start: can't allocate receive buffer pool for thread %s\n", gv->recv_threads[i].name); goto fail; } + GVLOG(DDS_LC_CONFIG, "rtps_start: alloc rbpool %p for recv_thread[%d] '%s' done \n", + gv->recv_threads[i].arg.rbpool, i, gv->recv_threads[i].name); if (gv->recv_threads[i].arg.mode == RTM_MANY) { if ((gv->recv_threads[i].arg.u.many.ws = os_sockWaitsetNew ()) == NULL) { - GVERROR ("rtps_init: can't allocate sock waitset for thread %s\n", gv->recv_threads[i].name); + GVERROR ("rtps_start: can't allocate sock waitset for thread %s\n", gv->recv_threads[i].name); goto fail; } + GVLOG(DDS_LC_CONFIG, "rtps_start: allocate sock waitset for thread %s done \n", gv->recv_threads[i].name); } if (create_thread (&gv->recv_threads[i].ts, gv, gv->recv_threads[i].name, recv_thread, &gv->recv_threads[i].arg) != DDS_RETCODE_OK) { - GVERROR ("rtps_init: failed to start thread %s\n", gv->recv_threads[i].name); + GVERROR ("rtps_start: failed to start thread %s\n", gv->recv_threads[i].name); goto fail; } } @@ -1339,6 +1350,7 @@ int rtps_init (struct ddsi_domaingv *gv) gv->listener = NULL; gv->debmon = NULL; +#ifndef DDSRT_WITH_FREERTOS /* Print start time for referencing relative times in the remainder of the DDS_LOG. */ { int sec = (int) (gv->tstart.v / 1000000000); @@ -1347,6 +1359,7 @@ int rtps_init (struct ddsi_domaingv *gv) ddsrt_ctime(gv->tstart.v, str, sizeof(str)); GVLOG (DDS_LC_CONFIG, "started at %d.06%d -- %s\n", sec, usec, str); } +#endif /* Allow configuration to set "deaf_mute" in case we want to start out that way */ gv->deaf = gv->config.initial_deaf; @@ -1362,6 +1375,7 @@ int rtps_init (struct ddsi_domaingv *gv) { case DDSI_TRANS_DEFAULT: assert(0); +#ifdef DDSRT_TRANS_UDP case DDSI_TRANS_UDP: case DDSI_TRANS_UDP6: gv->config.publish_uc_locators = 1; @@ -1370,6 +1384,8 @@ int rtps_init (struct ddsi_domaingv *gv) goto err_udp_tcp_init; gv->m_factory = ddsi_factory_find (gv, gv->config.transport_selector == DDSI_TRANS_UDP ? "udp" : "udp6"); break; +#endif +#ifdef DDSRT_TRANS_TCP case DDSI_TRANS_TCP: case DDSI_TRANS_TCP6: gv->config.publish_uc_locators = (gv->config.tcp_port != -1); @@ -1381,6 +1397,8 @@ int rtps_init (struct ddsi_domaingv *gv) goto err_udp_tcp_init; gv->m_factory = ddsi_factory_find (gv, gv->config.transport_selector == DDSI_TRANS_TCP ? "tcp" : "tcp6"); break; +#endif +#ifdef DDSRT_TRANS_RAWETH case DDSI_TRANS_RAWETH: gv->config.publish_uc_locators = 1; gv->config.enable_uc_locators = 0; @@ -1390,6 +1408,8 @@ int rtps_init (struct ddsi_domaingv *gv) goto err_udp_tcp_init; gv->m_factory = ddsi_factory_find (gv, "raweth"); break; +#endif +#ifdef DDSRT_TRANS_NONE case DDSI_TRANS_NONE: gv->config.publish_uc_locators = 0; gv->config.enable_uc_locators = 0; @@ -1399,6 +1419,7 @@ int rtps_init (struct ddsi_domaingv *gv) goto err_udp_tcp_init; gv->m_factory = ddsi_factory_find (gv, "dummy"); break; +#endif } gv->m_factory->m_enable = true; @@ -1423,12 +1444,12 @@ int rtps_init (struct ddsi_domaingv *gv) { if (!gv->interfaces[i].mc_capable) { - GVWARNING ("selected interface \"%s\" is not multicast-capable: disabling multicast\n", gv->interfaces[i].name); gv->config.allowMulticast = DDSI_AMC_FALSE; /* ensure discovery can work: firstly, that the process will be reachable on a "well-known" port number, and secondly, that the local interface's IP address gets added to the discovery address set */ gv->config.participantIndex = DDSI_PARTICIPANT_INDEX_AUTO; + GVWARNING ("selected interface \"%s\" is not multicast-capable: disabling multicast\n", gv->interfaces[i].name); } else if (gv->config.allowMulticast & DDSI_AMC_DEFAULT) { @@ -1438,7 +1459,7 @@ int rtps_init (struct ddsi_domaingv *gv) if (gv->interfaces[i].mc_flaky) { gv->config.allowMulticast = DDSI_AMC_SPDP; - GVLOG (DDS_LC_CONFIG, "presumed flaky multicast, use for SPDP only\n"); + GVLOG (DDS_LC_CONFIG, "presumed flaky multicast(0x%08x), use for SPDP only\n", gv->config.allowMulticast); } else { @@ -1447,6 +1468,12 @@ int rtps_init (struct ddsi_domaingv *gv) } } } +#ifdef DDSRT_WITH_FREERTOSTCP + } + else + { + GVWARNING (" (gv->config.allowMulticast) is false! \n"); +#endif } assert ((gv->config.allowMulticast & DDSI_AMC_DEFAULT) == 0); @@ -1573,8 +1600,12 @@ int rtps_init (struct ddsi_domaingv *gv) memcpy (&gv->ppguid_base.prefix.s[2], digest, sizeof (gv->ppguid_base.prefix.s) - 2); gv->ppguid_base.prefix = nn_ntoh_guid_prefix (gv->ppguid_base.prefix); gv->ppguid_base.entityid.u = NN_ENTITYID_PARTICIPANT; + GVLOG(DDS_LC_CONFIG, " GUID prefix: "PGUIDFMT "vs [%08x %08x %08x]", + PGUID (gv->ppguid_base), + gv->ppguid_base.prefix.u[0], gv->ppguid_base.prefix.u[1], gv->ppguid_base.prefix.u[2]); } + ddsrt_mutex_init (&gv->lock); ddsrt_mutex_init (&gv->spdp_lock); gv->spdp_defrag = nn_defrag_new (&gv->logconfig, NN_DEFRAG_DROP_OLDEST, gv->config.defrag_unreliable_maxsamples); @@ -1582,6 +1613,8 @@ int rtps_init (struct ddsi_domaingv *gv) gv->m_tkmap = ddsi_tkmap_new (gv); + GVLOG (DDS_LC_CONFIG, "participantIndex %d \n", gv->config.participantIndex); + if (gv->m_factory->m_connless) { if (gv->config.participantIndex >= 0 || gv->config.participantIndex == DDSI_PARTICIPANT_INDEX_NONE) @@ -1600,6 +1633,8 @@ int rtps_init (struct ddsi_domaingv *gv) goto err_unicast_sockets; case MUSRET_ERROR: /* something bad happened; assume make_uc_sockets logged the error */ + GVERROR ("rtps_init: other failed to create unicast sockets for domain %"PRId32" participant index %d (ports %"PRIu32", %"PRIu32")\n", + gv->config.extDomainId.value, gv->config.participantIndex, port_disc_uc, port_data_uc); goto err_unicast_sockets; } } @@ -1621,8 +1656,10 @@ int rtps_init (struct ddsi_domaingv *gv) gv->config.extDomainId.value, ppid, port_disc_uc, port_data_uc); goto err_unicast_sockets; case MUSRET_PORTS_IN_USE: /* Try next one */ + GVERROR ("Failed to create unicast sockets PORTS_IN_USE \n"); break; case MUSRET_ERROR: + GVERROR ("Failed to create unicast sockets ERROR \n"); /* something bad happened; assume make_uc_sockets logged the error */ goto err_unicast_sockets; } @@ -1632,6 +1669,7 @@ int rtps_init (struct ddsi_domaingv *gv) GVERROR ("Failed to find a free participant index for domain %"PRIu32"\n", gv->config.extDomainId.value); goto err_unicast_sockets; } + GVLOG (DDS_LC_INFO,"find a participant %d index for domain %"PRIu32"\n", ppid, gv->config.extDomainId.value); gv->config.participantIndex = ppid; } else @@ -1640,11 +1678,12 @@ int rtps_init (struct ddsi_domaingv *gv) } GVLOG (DDS_LC_CONFIG, "rtps_init: uc ports: disc %"PRIu32" data %"PRIu32"\n", port_disc_uc, port_data_uc); } - GVLOG (DDS_LC_CONFIG, "rtps_init: domainid %"PRIu32" participantid %d\n", gv->config.domainId, gv->config.participantIndex); + GVLOG (DDS_LC_INFO, "rtps_init: domainid %"PRIu32" participantid %d\n", gv->config.domainId, gv->config.participantIndex); if (gv->config.pcap_file && *gv->config.pcap_file) { gv->pcap_fp = new_pcap_file (gv, gv->config.pcap_file); + GVLOG (DDS_LC_CONFIG, "rtps_init: pcap_file %s done \n", gv->config.pcap_file); if (gv->pcap_fp) { ddsrt_mutex_init (&gv->pcap_lock); @@ -2032,6 +2071,8 @@ int rtps_start (struct ddsi_domaingv *gv) return -1; } } + +#ifdef DDSRT_TRANS_TCP if (gv->config.monitor_port >= 0) { if ((gv->debmon = new_debug_monitor (gv, gv->config.monitor_port)) == NULL) @@ -2041,6 +2082,7 @@ int rtps_start (struct ddsi_domaingv *gv) return -1; } } +#endif return 0; } diff --git a/src/core/ddsi/src/q_pcap.c b/src/core/ddsi/src/q_pcap.c index 3b843f79..bb0115c1 100644 --- a/src/core/ddsi/src/q_pcap.c +++ b/src/core/ddsi/src/q_pcap.c @@ -145,8 +145,13 @@ void write_pcap_received (struct ddsi_domaingv *gv, ddsrt_wctime_t tstamp, const u.ipv4_hdr = ipv4_hdr_template; u.ipv4_hdr.totallength = ddsrt_toBE2u ((unsigned short) sz_iud); u.ipv4_hdr.ttl = 128; + #ifdef DDSRT_WITH_FREERTOSTCP + u.ipv4_hdr.srcip = ((struct sockaddr_in*) src)->sin_addr; + u.ipv4_hdr.dstip = ((struct sockaddr_in*) dst)->sin_addr; + #else u.ipv4_hdr.srcip = ((struct sockaddr_in*) src)->sin_addr.s_addr; u.ipv4_hdr.dstip = ((struct sockaddr_in*) dst)->sin_addr.s_addr; + #endif u.ipv4_hdr.checksum = calc_ipv4_checksum (u.x); (void) fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, gv->pcap_fp); udp_hdr.srcport = ((struct sockaddr_in*) src)->sin_port; @@ -178,8 +183,13 @@ void write_pcap_sent (struct ddsi_domaingv *gv, ddsrt_wctime_t tstamp, const str u.ipv4_hdr = ipv4_hdr_template; u.ipv4_hdr.totallength = ddsrt_toBE2u ((unsigned short) sz_iud); u.ipv4_hdr.ttl = 255; + #ifdef DDSRT_WITH_FREERTOSTCP + u.ipv4_hdr.srcip = ((struct sockaddr_in*) src)->sin_addr; + u.ipv4_hdr.dstip = ((struct sockaddr_in*) hdr->msg_name)->sin_addr; + #else u.ipv4_hdr.srcip = ((struct sockaddr_in*) src)->sin_addr.s_addr; u.ipv4_hdr.dstip = ((struct sockaddr_in*) hdr->msg_name)->sin_addr.s_addr; + #endif u.ipv4_hdr.checksum = calc_ipv4_checksum (u.x); (void) fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, gv->pcap_fp); udp_hdr.srcport = ((struct sockaddr_in*) src)->sin_port; diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index e4898c34..65cd2e8b 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -3177,7 +3177,7 @@ static void handle_rtps_message (struct thread_state1 * const ts1, struct ddsi_d else if (hdr->version.major != RTPS_MAJOR || (hdr->version.major == RTPS_MAJOR && hdr->version.minor < RTPS_MINOR_MINIMUM)) { if ((hdr->version.major == RTPS_MAJOR && hdr->version.minor < RTPS_MINOR_MINIMUM)) - GVTRACE ("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu\n, version mismatch: %d.%d\n", + GVWARNING ("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu\n, version mismatch: %d.%d\n", PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, hdr->version.major, hdr->version.minor); if (DDSI_SC_PEDANTIC_P (gv->config)) malformed_packet_received (gv, msg, NULL, (size_t) sz, hdr->vendorid); @@ -3197,6 +3197,12 @@ static void handle_rtps_message (struct thread_state1 * const ts1, struct ddsi_d if (res != NN_RTPS_MSG_STATE_ERROR) { handle_submsg_sequence (ts1, gv, conn, srcloc, ddsrt_time_wallclock (), ddsrt_time_elapsed (), &hdr->guid_prefix, guidprefix, msg, (size_t) sz, msg + RTPS_MESSAGE_HEADER_SIZE, rmsg, res == NN_RTPS_MSG_STATE_ENCODED); +#ifdef DDSRT_WITH_FREERTOSTCP + } + else + { + GVWARNING(" decode_rtps_messages error! \n"); +#endif } } } @@ -3229,7 +3235,7 @@ static bool do_packet (struct thread_state1 * const ts1, struct ddsi_domaingv *g buff = (unsigned char *) NN_RMSG_PAYLOAD (rmsg); hdr = (Header_t*) buff; - if (conn->m_stream) + if (conn->m_stream) /* ONLY for TCP conn */ { MsgLen_t * ml = (MsgLen_t*) (hdr + 1); @@ -3446,13 +3452,16 @@ uint32_t listen_thread (struct ddsi_tran_listener *listener) static int recv_thread_waitset_add_conn (os_sockWaitset ws, ddsi_tran_conn_t conn) { if (conn == NULL) - return 0; + { return 0; } else { struct ddsi_domaingv *gv = conn->m_base.gv; for (uint32_t i = 0; i < gv->n_recv_threads; i++) + { + /* SKIP add thread "recvUC" / gv->data_conn_uc to waitset! */ if (gv->recv_threads[i].arg.mode == RTM_SINGLE && gv->recv_threads[i].arg.u.single.conn == conn) - return 0; + { return 0; } + } return os_sockWaitsetAdd (ws, conn); } } @@ -3495,6 +3504,12 @@ uint32_t recv_thread (void *vrecv_thread_arg) os_sockWaitset waitset = recv_thread_arg->mode == RTM_MANY ? recv_thread_arg->u.many.ws : NULL; ddsrt_mtime_t next_thread_cputime = { 0 }; +#ifdef DDSRT_WITH_FREERTOS + char name[64]; + ddsrt_thread_getname (name, sizeof (name)); + DDS_WARNING("recv_thread: called up for thread[%s] \n", name); +#endif + nn_rbufpool_setowner (rbpool, ddsrt_thread_self ()); if (waitset == NULL) { @@ -3515,17 +3530,36 @@ uint32_t recv_thread (void *vrecv_thread_arg) { int rc; if ((rc = recv_thread_waitset_add_conn (waitset, gv->disc_conn_uc)) < 0) - DDS_FATAL("recv_thread: failed to add disc_conn_uc to waitset\n"); + { DDS_FATAL("recv_thread: failed to add disc_conn_uc to waitset\n"); } + #ifdef DDSRT_WITH_FREERTOSTCP + if (rc > 0) + { DDS_INFO("recv_thread: add disc_conn_uc to waitset ! \n"); } + #endif num_fixed_uc += (unsigned)rc; + if ((rc = recv_thread_waitset_add_conn (waitset, gv->data_conn_uc)) < 0) DDS_FATAL("recv_thread: failed to add data_conn_uc to waitset\n"); + #ifdef DDSRT_WITH_FREERTOSTCP + if (rc > 0) + { DDS_INFO("recv_thread: add data_conn_uc to waitset ! \n"); } + #endif num_fixed_uc += (unsigned)rc; + num_fixed += num_fixed_uc; if ((rc = recv_thread_waitset_add_conn (waitset, gv->disc_conn_mc)) < 0) DDS_FATAL("recv_thread: failed to add disc_conn_mc to waitset\n"); + #ifdef DDSRT_WITH_FREERTOSTCP + if (rc > 0) + { DDS_INFO("recv_thread: add disc_conn_mc to waitset ! \n"); } + #endif num_fixed += (unsigned)rc; + if ((rc = recv_thread_waitset_add_conn (waitset, gv->data_conn_mc)) < 0) DDS_FATAL("recv_thread: failed to add data_conn_mc to waitset\n"); + #ifdef DDSRT_WITH_FREERTOSTCP + if (rc > 0) + { DDS_INFO("recv_thread: add data_conn_mc to waitset ! \n"); } + #endif num_fixed += (unsigned)rc; // OpenDDS doesn't respect the locator lists and insists on sending to the @@ -3535,9 +3569,13 @@ uint32_t recv_thread (void *vrecv_thread_arg) // Iceoryx gets added as a pseudo-interface but there's no socket to wait // for input on if (ddsi_conn_handle (gv->xmit_conns[i]) == DDSRT_INVALID_SOCKET) - continue; + { continue; } if ((rc = recv_thread_waitset_add_conn (waitset, gv->xmit_conns[i])) < 0) - DDS_FATAL("recv_thread: failed to add transmit_conn[%d] to waitset\n", i); + DDS_FATAL("recv_thread: failed to add xmit_conn[%d] to waitset\n", i); + #ifdef DDSRT_WITH_FREERTOSTCP + if (rc > 0) + { DDS_INFO("recv_thread: add xmit_conn[%d] to waitset ! \n", i); } + #endif num_fixed += (unsigned)rc; } } @@ -3564,7 +3602,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) for (uint32_t i = 0; i < lps.nps; i++) { if (lps.ps[i].m_conn) - os_sockWaitsetAdd (waitset, lps.ps[i].m_conn); + { os_sockWaitsetAdd (waitset, lps.ps[i].m_conn); } } } @@ -3575,13 +3613,18 @@ uint32_t recv_thread (void *vrecv_thread_arg) while ((idx = os_sockWaitsetNextEvent (ctx, &conn)) >= 0) { const ddsi_guid_prefix_t *guid_prefix; - if (((unsigned)idx < num_fixed) || gv->config.many_sockets_mode != DDSI_MSM_MANY_UNICAST) - guid_prefix = NULL; + if (((unsigned)idx < num_fixed) + || gv->config.many_sockets_mode != DDSI_MSM_MANY_UNICAST) + { guid_prefix = NULL; } else - guid_prefix = &lps.ps[(unsigned)idx - num_fixed].guid_prefix; + { guid_prefix = &lps.ps[(unsigned)idx - num_fixed].guid_prefix; } + /* Process message and clean out connection if failed or closed */ - if (!do_packet (ts1, gv, conn, guid_prefix, rbpool) && !conn->m_connless) + if (!do_packet (ts1, gv, conn, guid_prefix, rbpool) + && !conn->m_connless) + { ddsi_conn_free (conn); + } } } } diff --git a/src/core/ddsi/src/q_sockwaitset_s.c b/src/core/ddsi/src/q_sockwaitset_s.c new file mode 100755 index 00000000..df1c8bc9 --- /dev/null +++ b/src/core/ddsi/src/q_sockwaitset_s.c @@ -0,0 +1,522 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/sockets.h" +#include "dds/ddsrt/sync.h" + +#include "dds/ddsi/q_sockwaitset.h" +#include "dds/ddsi/ddsi_config_impl.h" +#include "dds/ddsi/q_log.h" +#include "dds/ddsi/ddsi_tran.h" + +#define WAITSET_DELTA 8 + +#define MODE_KQUEUE 1 +#define MODE_SELECT 2 +#define MODE_WFMEVS 3 + +#if defined __APPLE__ +#define MODE_SEL MODE_KQUEUE +#elif defined WINCE +#define MODE_SEL MODE_WFMEVS +#else +#define MODE_SEL MODE_SELECT /* FreeRTOS always use select */ +#endif + + +#ifdef DDSRT_WITH_FREERTOSTCP +# warning " *** FreeRTOS-Plus-TCP debug include tree " + +#else +#if !_WIN32 && !LWIP_SOCKET + +#if ! __VXWORKS__&& !__QNXNTO__ +#include +#endif /* __VXWORKS__ __QNXNTO__ */ + +#ifndef _WRS_KERNEL +#include +#endif +#ifdef __sun +#include +#include +#include +#endif + +#endif /* !_WIN32 && !LWIP_SOCKET */ +#endif + +typedef struct os_sockWaitsetSet +{ + ddsi_tran_conn_t * conns; /* connections in set */ + ddsrt_socket_t * fds; /* file descriptors in set */ + unsigned sz; /* max number of fds in context */ + unsigned n; /* actual number of fds in context */ +} os_sockWaitsetSet; + +struct os_sockWaitsetCtx +{ + os_sockWaitsetSet set; /* set of connections and descriptors */ + unsigned index; /* cursor for enumerating */ + ddsrt_fd_set_t rdset; /* read file descriptors set */ +}; + +struct os_sockWaitset +{ + ddsrt_socket_t pipe[2]; /* pipe used for triggering */ + ddsrt_mutex_t mutex; /* concurrency guard */ + int fdmax_plus_1; /* value for first parameter of select() */ + os_sockWaitsetSet set; /* set of descriptors handled next */ + struct os_sockWaitsetCtx ctx; /* set of descriptors being handled */ +}; + +#if defined (_WIN32) +static int make_pipe (ddsrt_socket_t fd[2]) +{ + struct sockaddr_in addr; + socklen_t asize = sizeof (addr); + ddsrt_socket_t listener = socket (AF_INET, SOCK_STREAM, 0); + ddsrt_socket_t s1 = socket (AF_INET, SOCK_STREAM, 0); + ddsrt_socket_t s2 = DDSRT_INVALID_SOCKET; + + addr.sin_family = AF_INET; + #ifdef DDSRT_WITH_FREERTOSTCP + addr.sin_addr = htonl (INADDR_LOOPBACK); + #else + addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + #endif + addr.sin_port = 0; + if (bind (listener, (struct sockaddr *)&addr, sizeof (addr)) == -1) + goto fail; + if (getsockname (listener, (struct sockaddr *)&addr, &asize) == -1) + goto fail; + if (listen (listener, 1) == -1) + goto fail; + if (connect (s1, (struct sockaddr *)&addr, sizeof (addr)) == -1) + goto fail; + if ((s2 = accept (listener, 0, 0)) == INVALID_SOCKET) + goto fail; + closesocket (listener); + /* Equivalent to FD_CLOEXEC */ + SetHandleInformation ((HANDLE) s1, HANDLE_FLAG_INHERIT, 0); + SetHandleInformation ((HANDLE) s2, HANDLE_FLAG_INHERIT, 0); + fd[0] = s1; + fd[1] = s2; + return 0; + +fail: + closesocket (listener); + closesocket (s1); + closesocket (s2); + return -1; +} +#elif defined(__VXWORKS__) +static int make_pipe (int pfd[2]) +{ + char pipename[OSPL_PIPENAMESIZE]; + int pipecount = 0; + do { + snprintf ((char*)&pipename, sizeof (pipename), "/pipe/ospl%d", pipecount++); + } while ((result = pipeDevCreate ((char*)&pipename, 1, 1)) == -1 && os_getErrno() == EINVAL); + if (result == -1) + goto fail_pipedev; + if ((pfd[0] = open ((char*)&pipename, O_RDWR, 0644)) == -1) + goto fail_open0; + if ((pfd[1] = open ((char*)&pipename, O_RDWR, 0644)) == -1) + goto fail_open1; + return 0; + +fail_open1: + close (pfd[0]); +fail_open0: + pipeDevDelete (pipename, 0); +fail_pipedev: + return -1; +} +#elif !defined(LWIP_SOCKET) +static int make_pipe (int pfd[2]) +{ + return pipe (pfd); +} +#endif + +static void os_sockWaitsetNewSet (os_sockWaitsetSet * set) +{ + set->fds = ddsrt_malloc (WAITSET_DELTA * sizeof (*set->fds)); + set->conns = ddsrt_malloc (WAITSET_DELTA * sizeof (*set->conns)); + set->sz = WAITSET_DELTA; + set->n = 1; +} + +static void os_sockWaitsetFreeSet (os_sockWaitsetSet * set) +{ + ddsrt_free (set->fds); + ddsrt_free (set->conns); +} + +static void os_sockWaitsetNewCtx (os_sockWaitsetCtx ctx) +{ + os_sockWaitsetNewSet (&ctx->set); + + #ifdef DDSRT_WITH_FREERTOSTCP + ctx->rdset = DDSRT_FD_SET_CRATE(); + DDSRT_FD_ZERO (ctx->rdset); + DDS_WARNING("os_sockWaitsetNewCtx: rdset created! rdset %p \n", ctx->rdset); + #else + FD_ZERO (ctx->rdset); + #endif +} + +static void os_sockWaitsetFreeCtx (os_sockWaitsetCtx ctx) +{ + #ifdef DDSRT_WITH_FREERTOSTCP + DDSRT_FD_SET_DELETE(ctx->rdset); + #endif + os_sockWaitsetFreeSet (&ctx->set); +} + +os_sockWaitset os_sockWaitsetNew (void) +{ + int result; + os_sockWaitset ws = ddsrt_malloc (sizeof (*ws)); + + os_sockWaitsetNewSet (&ws->set); + os_sockWaitsetNewCtx (&ws->ctx); + +#if ! defined (_WIN32) + ws->fdmax_plus_1 = 0; +#else + ws->fdmax_plus_1 = FD_SETSIZE; +#endif + +#if defined(LWIP_SOCKET) + ws->pipe[0] = -1; + ws->pipe[1] = -1; + result = 0; +#elif defined(DDSRT_WITH_FREERTOSTCP) + # warning " *** FreeRTOS-Plus-TCP FreeRTOS_Plus_TCP runtime wrapper ..." + ws->pipe[0] = -1; + ws->pipe[1] = -1; + result = 0; +#else + # error " *** NO makepipe for FreeRTOS " + + result = make_pipe (ws->pipe); +#endif + if (result == -1) + { + os_sockWaitsetFreeCtx (&ws->ctx); + os_sockWaitsetFreeSet (&ws->set); + ddsrt_free (ws); + return NULL; + } + +#if !defined(LWIP_SOCKET) && !defined(DDSRT_WITH_FREERTOSTCP) + ws->set.fds[0] = ws->pipe[0]; +#else +#warning " *** FreeRTOS-Plus-TCP FreeRTOS_Plus_TCP runtime wrapper ..." + ws->set.fds[0] = 0; +#endif + ws->set.conns[0] = NULL; + +#if !defined(__VXWORKS__) && !defined(_WIN32) && !defined(LWIP_SOCKET) && !defined(DDSRT_WITH_FREERTOSTCP) && !defined(__QNXNTO__) + (void) fcntl (ws->pipe[0], F_SETFD, fcntl (ws->pipe[0], F_GETFD) | FD_CLOEXEC); + (void) fcntl (ws->pipe[1], F_SETFD, fcntl (ws->pipe[1], F_GETFD) | FD_CLOEXEC); +#endif + +#if !defined(LWIP_SOCKET) && !defined(DDSRT_WITH_FREERTOSTCP) + FD_SET (ws->set.fds[0], ws->ctx.rdset); +#endif + +#if !defined(_WIN32) && !defined(DDSRT_WITH_FREERTOSTCP) + ws->fdmax_plus_1 = ws->set.fds[0] + 1; +#endif + + ddsrt_mutex_init (&ws->mutex); + + return ws; +} + +static void os_sockWaitsetGrow (os_sockWaitsetSet * set) +{ + set->sz += WAITSET_DELTA; + set->conns = ddsrt_realloc (set->conns, set->sz * sizeof (*set->conns)); + set->fds = ddsrt_realloc (set->fds, set->sz * sizeof (*set->fds)); +} + +void os_sockWaitsetFree (os_sockWaitset ws) +{ +#if defined(__VXWORKS__) && defined(__RTP__) + char nameBuf[OSPL_PIPENAMESIZE]; + ioctl (ws->pipe[0], FIOGETNAME, &nameBuf); +#endif + +#if defined(DDSRT_WITH_FREERTOSTCP) +# warning " *** FreeRTOS-Plus-TCP runtime tree " + (void) ddsrt_close (ws->pipe[0]); + (void) ddsrt_close (ws->pipe[1]); +#else + +#if defined(_WIN32) + closesocket (ws->pipe[0]); + closesocket (ws->pipe[1]); +#elif !defined(LWIP_SOCKET) + (void) close (ws->pipe[0]); + (void) close (ws->pipe[1]); +#endif +#endif + +#if defined(__VXWORKS__) && defined(__RTP__) + pipeDevDelete ((char*) &nameBuf, 0); +#endif + os_sockWaitsetFreeSet (&ws->set); + os_sockWaitsetFreeCtx (&ws->ctx); + ddsrt_mutex_destroy (&ws->mutex); + ddsrt_free (ws); +} + +void os_sockWaitsetTrigger (os_sockWaitset ws) +{ +#if defined(LWIP_SOCKET) + (void)ws; +#elif defined (DDSRT_WITH_FREERTOSTCP) +#warning " *** FreeRTOS-Plus-TCP FreeRTOS_Plus_TCP runtime wrapper ..." + (void)ws; +#else + char buf = 0; + int n; + +#if defined (_WIN32) + n = send (ws->pipe[1], &buf, 1, 0); +#else + n = (int) write (ws->pipe[1], &buf, 1); +#endif + if (n != 1) + { + DDS_WARNING("os_sockWaitsetTrigger: write failed on trigger pipe\n"); + } +#endif +} + +int os_sockWaitsetAdd (os_sockWaitset ws, ddsi_tran_conn_t conn) +{ + ddsrt_socket_t handle = ddsi_conn_handle (conn); + os_sockWaitsetSet * set = &ws->set; + unsigned idx; + int ret; + +#if ! defined (_WIN32) && ! defined(DDSRT_WITH_FREERTOSTCP) + assert (handle >= 0); + assert (handle < FD_SETSIZE); +#endif + + ddsrt_mutex_lock (&ws->mutex); + for (idx = 0; idx < set->n; idx++) + { + if (set->conns[idx] == conn) + break; + } + if (idx < set->n) + { ret = 0; } + else + { + if (set->n == set->sz) + { os_sockWaitsetGrow (set); } +#if ! defined (_WIN32) && ! defined(DDSRT_WITH_FREERTOSTCP) + if ((int) handle >= ws->fdmax_plus_1) + ws->fdmax_plus_1 = handle + 1; +#endif + set->conns[set->n] = conn; + set->fds[set->n] = handle; + set->n++; + ret = 1; + } + ddsrt_mutex_unlock (&ws->mutex); + return ret; +} + +void os_sockWaitsetPurge (os_sockWaitset ws, unsigned index) +{ + os_sockWaitsetSet * set = &ws->set; + + ddsrt_mutex_lock (&ws->mutex); + if (index + 1 <= set->n) + { + for (unsigned i = index + 1; i < set->n; i++) + { + set->conns[i] = NULL; + set->fds[i] = 0; + } + set->n = index + 1; + } + ddsrt_mutex_unlock (&ws->mutex); +} + +void os_sockWaitsetRemove (os_sockWaitset ws, ddsi_tran_conn_t conn) +{ + os_sockWaitsetSet * set = &ws->set; + + ddsrt_mutex_lock (&ws->mutex); + for (unsigned i = 0; i < set->n; i++) + { + if (conn == set->conns[i]) + { + set->n--; + if (i != set->n) + { + set->fds[i] = set->fds[set->n]; + set->conns[i] = set->conns[set->n]; + } + break; + } + } + ddsrt_mutex_unlock (&ws->mutex); +} + +os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws) +{ + unsigned u; +#if !_WIN32 + int fdmax; +#endif + ddsrt_fd_set_t rdset = NULL; + os_sockWaitsetCtx ctx = &ws->ctx; + os_sockWaitsetSet * dst = &ctx->set; + os_sockWaitsetSet * src = &ws->set; + + ddsrt_mutex_lock (&ws->mutex); + +#ifdef DDSRT_WITH_FREERTOSTCP + fdmax = 0; /* For FreeRTOS_TCP stack, fdmax is stub for api compatible */ +#else + #if !_WIN32 + fdmax = ws->fdmax_plus_1; + #endif +#endif + + /* Copy context to working context */ + + while (dst->sz < src->sz) + { + os_sockWaitsetGrow (dst); + } + dst->n = src->n; + + for (u = 0; u < src->n; u++) + { + dst->conns[u] = src->conns[u]; + dst->fds[u] = src->fds[u]; + } + + ddsrt_mutex_unlock (&ws->mutex); + + + /* Copy file descriptors into select read set */ + rdset = ctx->rdset; +#ifdef DDSRT_WITH_FREERTOSTCP + if (rdset == NULL) + { + assert(0); + } + +#endif + + DDSRT_FD_ZERO (rdset); +#if !defined(LWIP_SOCKET) && !defined(DDSRT_WITH_FREERTOSTCP) + for (u = 0; u < dst->n; u++) + { + FD_SET (dst->fds[u], rdset); + } +#else + /* fds[0]/conns[0] not using for RTOS */ + for (u = 1; u < dst->n; u++) + { + DDSRT_WARNING_GNUC_OFF(sign-conversion) + DDSRT_FD_SET (dst->fds[u], rdset); + DDSRT_WARNING_GNUC_ON(sign-conversion) + } +#endif /* LWIP_SOCKET */ + + dds_return_t rc; + do + { + rc = ddsrt_select (fdmax, rdset, NULL, NULL, SELECT_TIMEOUT_MS); + if (rc < 0 && rc != DDS_RETCODE_INTERRUPTED && rc != DDS_RETCODE_TRY_AGAIN) + { + DDS_WARNING("os_sockWaitsetWait: select failed, retcode = %"PRId32, rc); + break; + } + } while (rc < 0); + + if (rc > 0) + { + /* set start VALID conn index + * this simply skips the trigger fd, index0 is INV. + */ + ctx->index = 1; + + /* to confirm for DDSRT_WITH_FREERTOSTCP + TODO + TODO + TODO + TODO + TODO + TODO + */ +#if ! defined(LWIP_SOCKET) && !defined(DDSRT_WITH_FREERTOSTCP) + if (FD_ISSET (dst->fds[0], rdset)) + { + char buf; + int n1; + #if defined (_WIN32) + n1 = recv (dst->fds[0], &buf, 1, 0); + #else + n1 = (int) read (dst->fds[0], &buf, 1); + #endif + if (n1 != 1) + { + DDS_WARNING("os_sockWaitsetWait: read failed on trigger pipe\n"); + assert (0); + } + } +#endif /* LWIP_SOCKET */ + return ctx; + } + + return NULL; +} + +int os_sockWaitsetNextEvent (os_sockWaitsetCtx ctx, ddsi_tran_conn_t * conn) +{ + while (ctx->index < ctx->set.n) + { + unsigned idx = ctx->index++; + ddsrt_socket_t fd = ctx->set.fds[idx]; +#if ! defined (LWIP_SOCKET) && ! defined(DDSRT_WITH_FREERTOSTCP) + assert(idx > 0); +#endif + + if (DDSRT_FD_ISSET (fd, ctx->rdset)) + { + *conn = ctx->set.conns[idx]; + + return (int) (idx - 1); + } + } + return -1; +} + + diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 6de01fa1..3205bc74 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -109,7 +109,12 @@ void thread_states_init (unsigned maxthreads) (not strictly required, but it'll get one eventually anyway, and this makes it rather more clear). */ #ifndef NDEBUG +#ifdef DDSRT_WITH_FREERTOSTCP + struct thread_state1 * const ts0 = (struct thread_state1 * const)ddsrt_thread_tls_get(DDS_TLS_IDX_STATE, tsd_thread_state); +#else struct thread_state1 * const ts0 = tsd_thread_state; +#endif + #endif struct thread_state1 * const ts1 = lookup_thread_state_real (); assert (ts0 == NULL || ts0 == ts1); @@ -124,7 +129,12 @@ bool thread_states_fini (void) struct thread_state1 *ts1 = lookup_thread_state (); assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime))); reap_thread_state (ts1, true); + + #ifdef DDSRT_WITH_FREERTOSTCP + ddsrt_thread_tls_set(tsd_thread_state, DDS_TLS_IDX_STATE, NULL); + #else tsd_thread_state = NULL; + #endif /* Some applications threads that, at some point, required a thread state, may still be around. Of those, the cleanup routine is invoked when the thread terminates. This should be rewritten @@ -215,13 +225,22 @@ static struct thread_state1 *lazy_create_thread_state (ddsrt_thread_t self) struct thread_state1 *lookup_thread_state_real (void) { +#ifdef DDSRT_WITH_FREERTOSTCP + struct thread_state1 *ts1 = (struct thread_state1 *)ddsrt_thread_tls_get(DDS_TLS_IDX_STATE, tsd_thread_state); +#else struct thread_state1 *ts1 = tsd_thread_state; +#endif + if (ts1 == NULL) { ddsrt_thread_t self = ddsrt_thread_self (); if ((ts1 = find_thread_state (self)) == NULL) ts1 = lazy_create_thread_state (self); +#ifdef DDSRT_WITH_FREERTOSTCP + ddsrt_thread_tls_set(tsd_thread_state, DDS_TLS_IDX_STATE, ts1); +#else tsd_thread_state = ts1; +#endif } assert (ts1 != NULL); return ts1; @@ -232,9 +251,19 @@ static uint32_t create_thread_wrapper (void *ptr) struct thread_state1 * const ts1 = ptr; struct ddsi_domaingv const * const gv = ddsrt_atomic_ldvoidp (&ts1->gv); if (gv) - GVTRACE ("started new thread %"PRIdTID": %s\n", ddsrt_gettid (), ts1->name); + { + #ifndef DDSRT_WITH_FREERTOSTCP + GVTRACE ("started new thread %"PRIdTID": %s \n", ddsrt_gettid (), ts1->name); + #else + GVTRACE ("started new thread %"PRIdTID": %s, thread_t 0x%lx \n", ddsrt_gettid (), ts1->name, ts1->tid.task); + #endif + } assert (ts1->state == THREAD_STATE_INIT); +#ifdef DDSRT_WITH_FREERTOSTCP + ddsrt_thread_tls_set(tsd_thread_state, DDS_TLS_IDX_STATE, ts1); +#else tsd_thread_state = ts1; +#endif ddsrt_mutex_lock (&thread_states.lock); ts1->state = THREAD_STATE_ALIVE; ddsrt_mutex_unlock (&thread_states.lock); @@ -242,7 +271,12 @@ static uint32_t create_thread_wrapper (void *ptr) ddsrt_mutex_lock (&thread_states.lock); ts1->state = THREAD_STATE_STOPPED; ddsrt_mutex_unlock (&thread_states.lock); +#ifdef DDSRT_WITH_FREERTOSTCP + ddsrt_thread_tls_set(tsd_thread_state, DDS_TLS_IDX_STATE, NULL); +#else tsd_thread_state = NULL; +#endif + return ret; } diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 3e07fb55..b1bbd0d3 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -323,18 +323,32 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_ { if (ddsrt_avl_is_empty (&wr->readers)) { +#ifdef DDSRT_WITH_FREERTOSTCP + ETRACE (wr, "heartbeat(wr "PGUIDFMT"%s) piggybacked, resched in %u usec (min-ack [none], avail-seq %"PRIu64", xmit %"PRIu64")\n", + PGUID (wr->e.guid), + *hbansreq ? "" : " final", + (hbc->tsched.v == DDS_NEVER) ? DDS_NEVER : ((hbc->tsched.v - tnow.v) / (NANOSECONDS_PER_SECOND / MICROSECONDS_PER_SECOND)), // usec +#else ETRACE (wr, "heartbeat(wr "PGUIDFMT"%s) piggybacked, resched in %g s (min-ack [none], avail-seq %"PRIu64", xmit %"PRIu64")\n", PGUID (wr->e.guid), *hbansreq ? "" : " final", (hbc->tsched.v == DDS_NEVER) ? INFINITY : (double) (hbc->tsched.v - tnow.v) / 1e9, +#endif whcst->max_seq, writer_read_seq_xmit(wr)); } else { +#ifdef DDSRT_WITH_FREERTOSTCP + ETRACE (wr, "heartbeat(wr "PGUIDFMT"%s) piggybacked, resched in %u usec (min-ack %"PRIu64"%s, avail-seq %"PRIu64", xmit %"PRIu64")\n", + PGUID (wr->e.guid), + *hbansreq ? "" : " final", + (hbc->tsched.v == DDS_NEVER) ? DDS_NEVER : ((hbc->tsched.v - tnow.v) / (NANOSECONDS_PER_SECOND / MICROSECONDS_PER_SECOND)), // usec +#else ETRACE (wr, "heartbeat(wr "PGUIDFMT"%s) piggybacked, resched in %g s (min-ack %"PRIu64"%s, avail-seq %"PRIu64", xmit %"PRIu64")\n", PGUID (wr->e.guid), *hbansreq ? "" : " final", (hbc->tsched.v == DDS_NEVER) ? INFINITY : (double) (hbc->tsched.v - tnow.v) / 1e9, +#endif root_rdmatch (wr)->min_seq, root_rdmatch (wr)->all_have_replied_to_hb ? "" : "!", whcst->max_seq, writer_read_seq_xmit(wr)); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 62af2967..0b285405 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -531,14 +531,22 @@ struct xeventq * xeventq_new (struct ddsi_domaingv *gv, size_t max_queued_rexmit dds_return_t xeventq_start (struct xeventq *evq, const char *name) { dds_return_t rc; +#ifdef DDSRT_WITH_FREERTOSTCP + char * evqname = "dds_tev"; +#else char * evqname = "tev"; +#endif assert (evq->ts == NULL); if (name) { size_t slen = strlen (name) + 5; evqname = ddsrt_malloc (slen); + #ifdef DDSRT_WITH_FREERTOSTCP + (void) snprintf (evqname, slen, "dds_tev.%s", name); + #else (void) snprintf (evqname, slen, "tev.%s", name); + #endif } evq->terminate = 0; @@ -764,20 +772,36 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, ddsrt if (ddsrt_avl_is_empty (&wr->readers)) { - GVTRACE ("heartbeat(wr "PGUIDFMT"%s) %s, resched in %g s (min-ack [none], avail-seq %"PRIu64", xmit %"PRIu64")\n", +#ifdef DDSRT_WITH_FREERTOSTCP + GVINFO ("heartbeat(wr "PGUIDFMT"%s) %s, resched in %u usec (min-ack [none], avail-seq %"PRIu64", xmit %"PRIu64")\n", + PGUID (wr->e.guid), + hbansreq ? "" : " final", + msg ? "sent" : "suppressed", + (t_next.v == DDS_NEVER) ? DDS_NEVER : ((t_next.v - tnow.v) / (NANOSECONDS_PER_SECOND / MICROSECONDS_PER_SECOND)), // usec +#else + GVINFO ("heartbeat(wr "PGUIDFMT"%s) %s, resched in %g s (min-ack [none], avail-seq %"PRIu64", xmit %"PRIu64")\n", PGUID (wr->e.guid), hbansreq ? "" : " final", msg ? "sent" : "suppressed", (t_next.v == DDS_NEVER) ? INFINITY : (double)(t_next.v - tnow.v) / 1e9, +#endif whcst.max_seq, writer_read_seq_xmit (wr)); } else { - GVTRACE ("heartbeat(wr "PGUIDFMT"%s) %s, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRIu64", xmit %"PRIu64")\n", +#ifdef DDSRT_WITH_FREERTOSTCP + GVINFO("heartbeat(wr "PGUIDFMT"%s) %s, resched in %u usec (min-ack %"PRId64"%s, avail-seq %"PRIu64", xmit %"PRIu64")\n", PGUID (wr->e.guid), hbansreq ? "" : " final", msg ? "sent" : "suppressed", - (t_next.v == DDS_NEVER) ? INFINITY : (double)(t_next.v - tnow.v) / 1e9, + (t_next.v == DDS_NEVER) ? DDS_NEVER : ((t_next.v - tnow.v) / (NANOSECONDS_PER_SECOND / MICROSECONDS_PER_SECOND)), // usec +#else + GVINFO("heartbeat(wr "PGUIDFMT"%s) %s, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRIu64", xmit %"PRIu64")\n", + PGUID (wr->e.guid), + hbansreq ? "" : " final", + msg ? "sent" : "suppressed", + (t_next.v == DDS_NEVER) ? DDS_NEVER : (double)(t_next.v - tnow.v) / 1e9, +#endif ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->min_seq, ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb ? "" : "!", whcst.max_seq, writer_read_seq_xmit (wr)); @@ -1028,10 +1052,18 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e else { ddsrt_mtime_t tnext = ddsrt_mtime_add_duration (tnow, DDS_SECS (1)); - GVTRACE ("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n", +#ifdef DDSRT_WITH_FREERTOSTCP + GVTRACE ("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %u usec)\n", + PGUID (pp->e.guid), + PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER, + (tnext.v - tnow.v) / (NANOSECONDS_PER_SECOND / MICROSECONDS_PER_SECOND) // usec + ); +#else + GVTRACE ("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %g s)\n", PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER, (double)(tnext.v - tnow.v) / 1e9); +#endif (void) resched_xevent_if_earlier (ev, tnext); } } @@ -1055,10 +1087,18 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e intv = gv->config.spdp_interval; tnext = ddsrt_mtime_add_duration (tnow, intv); - GVTRACE ("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n", + #ifdef DDSRT_WITH_FREERTOSTCP + GVTRACE ("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %u usec)\n", + PGUID (pp->e.guid), + PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER, + (tnext.v - tnow.v) / (NANOSECONDS_PER_SECOND / MICROSECONDS_PER_SECOND) // usec + ); + #else + GVTRACE ("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %g s)\n", PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER, (double)(tnext.v - tnow.v) / 1e9); + #endif (void) resched_xevent_if_earlier (ev, tnext); } } @@ -1091,7 +1131,13 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_ tnext.v = tnow.v + intv - DDS_SECS (2); else tnext.v = tnow.v + 4 * intv / 5; - GVTRACE ("resched pmd("PGUIDFMT"): %gs\n", PGUID (pp->e.guid), (double)(tnext.v - tnow.v) / 1e9); + #ifdef DDSRT_WITH_FREERTOSTCP + GVTRACE ("resched pmd("PGUIDFMT"): %u usec\n", PGUID (pp->e.guid), + (tnext.v - tnow.v) / (NANOSECONDS_PER_SECOND / MICROSECONDS_PER_SECOND) // usec + ); + #else + GVTRACE ("resched pmd("PGUIDFMT"): %g s\n", PGUID (pp->e.guid), (double)(tnext.v - tnow.v) / 1e9); + #endif } (void) resched_xevent_if_earlier (ev, tnext); @@ -1127,6 +1173,12 @@ static void handle_individual_xevent (struct thread_state1 * const ts1, struct x switch (xev->kind) { case XEVK_HEARTBEAT: + #ifdef DDSRT_WITH_FREERTOSTCP + { + static uint32_t hb_cnt = 0U; + DDS_WARNING(" handle_xevk_heartbeat %u ... ", hb_cnt++); + } + #endif handle_xevk_heartbeat (xp, xev, tnow); break; case XEVK_ACKNACK: diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index aa5bbc75..1cb12543 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -121,6 +121,7 @@ struct nn_xmsg { #ifdef IOV_MAX #if IOV_MAX > 0 && IOV_MAX < 256 +#error " you should not be here for DDSRT_WITH_FREERTOSTCP" #define NN_XMSG_MAX_MESSAGE_IOVECS IOV_MAX #endif #endif /* defined IOV_MAX */ @@ -1248,7 +1249,15 @@ static ssize_t nn_xpack_send1 (const ddsi_xlocator_t *loc, void * varg) } /* Possible number of bytes written can be larger * due to security. */ + #ifdef DDSRT_WITH_FREERTOSTCP + if (nbytes < len) + { + GVERROR (" sent len is NOT right! len %u v %u", len, nbytes); + assert (nbytes == -1 || (size_t) nbytes >= len); + } + #else assert (nbytes == -1 || (size_t) nbytes >= len); + #endif } #endif } @@ -1718,7 +1727,7 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag const uint32_t max_msg_size = rexmit ? xp->gv->config.max_rexmit_msg_size : xp->gv->config.max_msg_size; if (xpo_niov > 0 && sz > max_msg_size) { - GVTRACE (" => now niov %d sz %"PRIuSIZE" > max_msg_size %"PRIu32", nn_xpack_send niov %d sz %"PRIu32" now\n", + GVINFO (" => now niov %d sz %"PRIuSIZE" > max_msg_size %"PRIu32", nn_xpack_send niov %d sz %"PRIu32" now\n", (int) niov, sz, max_msg_size, (int) xpo_niov, xpo_sz); xp->msg_len.length = xpo_sz; xp->niov = xpo_niov; diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 01fdec45..2e357365 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -160,8 +160,10 @@ if(DDSRT_HAVE_GETADDRINFO OR DDSRT_HAVE_GETHOSTBYNAME_R) set(DDSRT_HAVE_DNS TRUE) endif() check_type_size("struct sockaddr_in6" SIZEOF_SOCKADDR_IN6) -if(SIZEOF_SOCKADDR_IN6) - set(DDSRT_HAVE_IPV6 TRUE) +if(ENABLE_IPV6) + if(SIZEOF_SOCKADDR_IN6) + set(DDSRT_HAVE_IPV6 TRUE) + endif() endif() if(WITH_FREERTOS) diff --git a/src/ddsrt/include/dds/config.h.in b/src/ddsrt/include/dds/config.h.in index 87493ab3..f33ed369 100644 --- a/src/ddsrt/include/dds/config.h.in +++ b/src/ddsrt/include/dds/config.h.in @@ -15,6 +15,17 @@ #cmakedefine DDSRT_WITH_LWIP 1 #cmakedefine DDSRT_WITH_FREERTOS 1 +/* begin: FreeRTOS_Plus_TCP IP stack */ +#cmakedefine DDSRT_WITH_FREERTOSTCP 1 + +#cmakedefine DDSRT_TRANS_UDP 1 +#cmakedefine DDSRT_TRANS_TCP 1 +#cmakedefine DDSRT_TRANS_RAWETH 1 +#cmakedefine DDSRT_TRANS_NONE 1 + +/* end: FreeRTOS_Plus_TCP IP stack */ + + #cmakedefine DDSRT_HAVE_DYNLIB 1 #cmakedefine DDSRT_HAVE_FILESYSTEM 1 #cmakedefine DDSRT_HAVE_NETSTAT 1 diff --git a/src/ddsrt/include/dds/ddsrt/iovec.h b/src/ddsrt/include/dds/ddsrt/iovec.h index cbfa3514..3e9fe845 100644 --- a/src/ddsrt/include/dds/ddsrt/iovec.h +++ b/src/ddsrt/include/dds/ddsrt/iovec.h @@ -26,6 +26,15 @@ typedef unsigned long ddsrt_msg_iovlen_t; #if DDSRT_WITH_LWIP #include + +#elif defined DDSRT_WITH_FREERTOSTCP +#warning "debug rtos tcp stack including " +/* will implement struct io_vec in freertos_plus_tcp.h wrapper header. */ + +struct iovec { + void *iov_base; + size_t iov_len; +}; #else #include #include @@ -36,6 +45,8 @@ typedef size_t ddsrt_iov_len_t; #if defined(__linux) && !LWIP_SOCKET typedef size_t ddsrt_msg_iovlen_t; +#elif defined DDSRT_WITH_FREERTOSTCP +typedef size_t ddsrt_msg_iovlen_t; #else /* POSIX says int (which macOS, FreeBSD, Solaris do) */ typedef int ddsrt_msg_iovlen_t; #endif diff --git a/src/ddsrt/include/dds/ddsrt/log.h b/src/ddsrt/include/dds/ddsrt/log.h index dabdacb8..cbe31492 100644 --- a/src/ddsrt/include/dds/ddsrt/log.h +++ b/src/ddsrt/include/dds/ddsrt/log.h @@ -24,6 +24,9 @@ #include #include +#include "dds/config.h" +#include "dds/features.h" + #include "dds/export.h" #include "dds/ddsrt/attributes.h" @@ -87,8 +90,12 @@ extern "C" { DDS_LC_CONTENT | DDS_LC_SHM) /** @}*/ +#ifdef DDSRT_WITH_FREERTOSTCP +#define DDS_LOG_MASK DDS_LC_ALL +#else #define DDS_LOG_MASK \ (DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_INFO) +#endif #define DDS_TRACE_MASK \ (~DDS_LOG_MASK) @@ -382,9 +389,15 @@ dds_log( * passed just as easily, they are rejected so that tracing is kept entirely * separate from logging, if only cosmetic. */ +#ifndef DDSRT_WITH_FREERTOSTCP #define DDS_LOG(cat, ...) \ ((dds_get_log_mask() & (cat)) ? \ dds_log((cat), __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0) +#else +#define DDS_LOG(cat, fmt, ...) \ + ((dds_get_log_mask() & (cat)) ? \ + dds_log((cat), __FILE__, __LINE__, DDS_FUNCTION, fmt, ##__VA_ARGS__) : 0) +#endif /** * @brief Write a log message with a domain id override. @@ -398,10 +411,15 @@ dds_log( * passed just as easily, they are rejected so that tracing is kept entirely * separate from logging, if only cosmetic. */ +#ifndef DDSRT_WITH_FREERTOSTCP #define DDS_ILOG(cat, domid, ...) \ ((dds_get_log_mask() & (cat)) ? \ dds_log_id((cat), (domid), __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0) - +#else +#define DDS_ILOG(cat, domid, fmt, ...) \ + ((dds_get_log_mask() & (cat)) ? \ + dds_log_id((cat), (domid), __FILE__, __LINE__, DDS_FUNCTION, fmt " \n", ##__VA_ARGS__) : 0) +#endif /** * @brief Write a log message using a specific config. * @@ -414,9 +432,15 @@ dds_log( * passed just as easily, they are rejected so that tracing is kept entirely * separate from logging, if only cosmetic. */ +#ifndef DDSRT_WITH_FREERTOSTCP #define DDS_CLOG(cat, cfg, ...) \ (((cfg)->c.mask & (cat)) ? \ dds_log_cfg((cfg), (cat), __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0) +#else +#define DDS_CLOG(cat, cfg, fmt, ...) \ + (((cfg)->c.mask & (cat)) ? \ + dds_log_cfg((cfg), (cat), __FILE__, __LINE__, DDS_FUNCTION, fmt "\n", ##__VA_ARGS__) : 0) +#endif /** Write a log message of type #DDS_LC_INFO into global log. */ #define DDS_INFO(...) \ @@ -428,8 +452,13 @@ dds_log( #define DDS_ERROR(...) \ DDS_LOG(DDS_LC_ERROR, __VA_ARGS__) /** Write a log message of type #DDS_LC_ERROR into global log and abort. */ +#ifndef DDSRT_WITH_FREERTOSTCP #define DDS_FATAL(...) \ dds_log(DDS_LC_FATAL, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) +#else +#define DDS_FATAL(fmt, ...) \ + dds_log(DDS_LC_FATAL, __FILE__, __LINE__, DDS_FUNCTION, fmt "\n", ##__VA_ARGS__) +#endif /* MSVC mishandles __VA_ARGS__ while claiming to be conforming -- and even if they have a defensible implement, they still differ from every other diff --git a/src/ddsrt/include/dds/ddsrt/process.h b/src/ddsrt/include/dds/ddsrt/process.h index c074d084..84e75197 100644 --- a/src/ddsrt/include/dds/ddsrt/process.h +++ b/src/ddsrt/include/dds/ddsrt/process.h @@ -55,6 +55,18 @@ extern "C" { DDS_EXPORT ddsrt_pid_t ddsrt_getpid(void); +/** + * @brief Return process name of the calling process. + * + * On linux maps to /proc/self/cmdline's first entry (argv[0]), + * on mac/windows maps to relevant API calls. Falls back to process-{pid} + * on failure. + * + * @returns The process name of the calling process. + */ +DDS_EXPORT char * +ddsrt_getprocessname(void); + #if defined (__cplusplus) } #endif diff --git a/src/ddsrt/include/dds/ddsrt/sockets.h b/src/ddsrt/include/dds/ddsrt/sockets.h index 65b40ed5..4a911c67 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets.h +++ b/src/ddsrt/include/dds/ddsrt/sockets.h @@ -10,10 +10,16 @@ #include "dds/ddsrt/retcode.h" #include "dds/ddsrt/time.h" #include "dds/ddsrt/misc.h" -#if _WIN32 -#include "dds/ddsrt/sockets/windows.h" + +#if defined DDSRT_WITH_FREERTOSTCP + #warning " debug rtos tcp stack including " + #include "dds/ddsrt/sockets/freertos_plus_tcp.h" #else -#include "dds/ddsrt/sockets/posix.h" + #if _WIN32 + #include "dds/ddsrt/sockets/windows.h" + #else + #include "dds/ddsrt/sockets/posix.h" + #endif #endif #if defined (__cplusplus) @@ -187,9 +193,15 @@ ddsrt_setsockreuse( DDS_EXPORT dds_return_t ddsrt_select( int32_t nfds, +#ifdef DDSRT_WITH_FREERTOSTCP + ddsrt_fd_set_t readfds, + ddsrt_fd_set_t writefds, + ddsrt_fd_set_t errorfds, +#else fd_set *readfds, fd_set *writefds, fd_set *errorfds, +#endif dds_duration_t reltime); #if _WIN32 diff --git a/src/ddsrt/include/dds/ddsrt/sockets/freertos_plus_tcp.h b/src/ddsrt/include/dds/ddsrt/sockets/freertos_plus_tcp.h new file mode 100755 index 00000000..c2c01e22 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/sockets/freertos_plus_tcp.h @@ -0,0 +1,245 @@ +/* + * INTEL CONFIDENTIAL + * + * Copyright (C) 2022 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, + * and your use of them is governed by the express license under which they + * were provided to you ("License"). Unless the License provides otherwise, + * you may not use, modify, copy, publish, distribute, disclose or transmit + * this software or the related documents without Intel's prior written permission. + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly + * stated in the License. + */ + +#ifndef DDSRT_SOCKETS_FREERTOS_PLUS_TCP_H +#define DDSRT_SOCKETS_FREERTOS_PLUS_TCP_H + +#define __need_size_t +#include + +/* This operating system-specific header file defines the SOCK_*, PF_*, + AF_*, MSG_*, SOL_*, and SO_* constants, and the `struct sockaddr', + `struct msghdr', and `struct linger' types. */ + +#include + +#include +#include +#include +#include + +#include "dds/ddsrt/iovec.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifndef ntohl +#define ntohl FreeRTOS_ntohl +#define htol FreeRTOS_htonl + +#define htos FreeRTOS_htons +#define ntohs FreeRTOS_ntohs +#endif + +#define inet_addr FreeRTOS_inet_addr +#define IN_MULTICAST(ip) (xIsIPv4Multicast(ntohl(ip))) + + +/* posix data for FreeRTOS+TCP stack */ +#define DDSRT_HAVE_SSM 0 +#define IFF_UP 0x1 +#define IFF_BROADCAST 0x2 +#define IFF_LOOPBACK 0x8 +#define IFF_POINTOPOINT 0x10 +#define IFF_MULTICAST 0x1000 + +struct msghdr +{ + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; + int msg_iovlen; + void *msg_control; + socklen_t msg_controllen; + int msg_flags; +}; + +struct timeval +{ + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; + +typedef struct msghdr ddsrt_msghdr_t; +#define DDSRT_MSGHDR_FLAGS 0 + + +/* adaption to ddsrt socket interface */ +typedef Socket_t ddsrt_socket_t; /* Socket_t ==> FreeRTOS_Socket_t* */ +// typedef SocketSelect_t fd_set; /* SocketSelect_t => struct xSOCKET_SET */ +typedef SocketSet_t ddsrt_fd_set_t; + +#define SELECT_TIMEOUT_MS 1000U /* 200U experienced value from XRCE-client */ + +/* +FD_ZERO() clears a set. +FD_SET() and FD_CLR() respectively add and remove a given file descriptor from a set. +FD_ISSET() tests to see if a file descriptor is part of the set; this is useful after select() returns. +*/ +static inline void DDSRT_FD_ZERO(ddsrt_fd_set_t set) +{ + (void)set; +} + +static ddsrt_fd_set_t DDSRT_FD_SET_CRATE(void) +{ + SocketSet_t set = FreeRTOS_CreateSocketSet(); + assert(set); + return set; +} + +static void DDSRT_FD_SET_DELETE(ddsrt_fd_set_t set) +{ + assert(set); + FreeRTOS_DeleteSocketSet(set); +} + +/* +#define DDSRT_FD_ISSET(fd, set) FreeRTOS_FD_ISSET(fd, set) +#define DDSRT_FD_SET(fd, set) FreeRTOS_FD_SET(fd, set, eSELECT_READ | eSELECT_EXCEPT) +#define DDSRT_FD_CLR(fd, set) FreeRTOS_FD_CLR(fd, set, eSELECT_ALL) +*/ + +static inline int32_t DDSRT_FD_ISSET(ddsrt_socket_t fd, ddsrt_fd_set_t set) +{ + return (int32_t)FreeRTOS_FD_ISSET(fd, set); +} + +/* for FD_SET only be used in CDDS for rdset */ +static inline void DDSRT_FD_SET(ddsrt_socket_t fd, ddsrt_fd_set_t set) +{ + FreeRTOS_FD_SET(fd, set, eSELECT_READ | eSELECT_EXCEPT); +} + +static inline void DDSRT_FD_CLR(ddsrt_socket_t fd, ddsrt_fd_set_t set) +{ + FreeRTOS_FD_CLR(fd, set, eSELECT_ALL); +} + +#ifndef sa_family_t + typedef uint8_t sa_family_t; +#endif + + struct sockaddr_storage + { + uint8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + uint32_t s2_data2[3]; + }; + +#if 1 + /* for posix compatible sa_family reference inside DDS + * we declare sockaddr a new struct but same W/ freertos_sockaddr + */ + struct sockaddr + { + uint8_t sa_len; + sa_family_t sa_family; + uint16_t sin_port; + uint32_t sin_addr; + }; +#else +#define sockaddr freertos_sockaddr +#endif + +#define sockaddr_in freertos_sockaddr +typedef uint32_t in_addr_t; /* base type for internet address */ + +/* + * Options and types related to multicast membership + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 + typedef struct ip_mreq + { + in_addr_t imr_multiaddr; /* IP multicast address of group */ + in_addr_t imr_interface; /* local IP address of interface */ + } ip_mreq; + // end multicast + +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 + +/** 255.255.255.255 */ +#define INADDR_NONE ((uint32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define INADDR_LOOPBACK ((uint32_t)0x7f000000UL) +/** 0.0.0.0 */ +#define INADDR_ANY ((uint32_t)0x00000000UL) +/** 255.255.255.255 */ +#define INADDR_BROADCAST ((uint32_t)0xffffffffUL) + +#define AF_INET FREERTOS_AF_INET +#define AF_INET6 FREERTOS_AF_INET6 + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP ipPROTOCOL_ICMP + +#define SOCK_DGRAM FREERTOS_SOCK_DGRAM +#define IPPROTO_UDP FREERTOS_IPPROTO_UDP + +#define SOCK_STREAM FREERTOS_SOCK_STREAM +#define IPPROTO_TCP FREERTOS_IPPROTO_TCP + +#define SOL_SOCKET IPPROTO_IP /* set socket level, always 0 for RTOS */ + +#define SO_REUSEADDR FREERTOS_SO_REUSE_LISTEN_SOCKET +#define SO_RCVTIMEO FREERTOS_SO_RCVTIMEO +#define SO_SNDTIMEO FREERTOS_SO_SNDTIMEO +#define SO_SNDBUF FREERTOS_SO_SNDBUF +#define SO_RCVBUF FREERTOS_SO_RCVBUF + +#define SO_OOB FREERTOS_MSG_OOB +#define SO_PEEK FREERTOS_MSG_PEEK +#define SO_DONTROUTE FREERTOS_MSG_DONTROUTE +#define SO_DONTWAIT FREERTOS_MSG_DONTWAIT + +/* + FreeRTOS_accept() has an optional timeout. The timeout defaults + to ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME, and is modified + using the FREERTOS_SO_RCVTIMEO parameter in a call to FreeRTOS_setsockopt() + + If a timeout occurs before a connection from a remote socket + is accepted then NULL is returned. +*/ +#define ACCEPT_TIMEOUT (NULL) // accpet timeout +#define INVALID_SOCKET (FREERTOS_INVALID_SOCKET) + +/* The following constants should be used for the second parameter of + `shutdown'. */ +#define SHUT_RD FREERTOS_SHUT_RD +#define SHUT_WR FREERTOS_SHUT_WR +#define SHUT_RDWR FREERTOS_SHUT_RDWR + + +#define DDSRT_INVALID_SOCKET (INVALID_SOCKET) +#define PRIdSOCK PRIxPTR + +// #define errno FreeRTOS_errno +#define DDSRT_RET_OK (0) + +#ifndef FD_SETSIZE +#define FD_SETSIZE 8 +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/src/ddsrt/include/dds/ddsrt/sockets/posix.h b/src/ddsrt/include/dds/ddsrt/sockets/posix.h index e48cc0c2..2c232415 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets/posix.h +++ b/src/ddsrt/include/dds/ddsrt/sockets/posix.h @@ -31,6 +31,13 @@ extern "C" { #endif typedef int ddsrt_socket_t; + +#ifdef DDSRT_WITH_FREERTOSTCP +typedef fd_set* ddsrt_fd_set_t; /* compatible with FreeRTOS +TCP */ +#define SELECT_TIMEOUT_MS DDS_INFINITY +#endif + + #define DDSRT_INVALID_SOCKET (-1) #define PRIdSOCK "d" diff --git a/src/ddsrt/include/dds/ddsrt/threads.h b/src/ddsrt/include/dds/ddsrt/threads.h index 6341bf7a..46ac58fb 100644 --- a/src/ddsrt/include/dds/ddsrt/threads.h +++ b/src/ddsrt/include/dds/ddsrt/threads.h @@ -49,7 +49,13 @@ extern "C" { supports Thread-local storage since version 2.0. */ /* VxWorks 7 supports __thread for both GCC and DIAB, older versions may support it as well, but that is not verified. */ + +#ifdef DDSRT_WITH_FREERTOSTCP +#define ddsrt_thread_local +#else #define ddsrt_thread_local __thread +#endif + #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) #define ddsrt_thread_local __thread #else @@ -73,6 +79,32 @@ typedef struct { uint32_t stackSize; } ddsrt_threadattr_t; + +#ifdef DDSRT_WITH_FREERTOS +#if configNUM_THREAD_LOCAL_STORAGE_POINTERS <= 0 +#error " Error, FreeRTOS THREAD_LOCAL_STORAGE support NOT enabled!" +#endif + +/* +add configNUM_THREAD_LOCAL_STORAGE_POINTERS for DDS usage + 22 taskguard and FATfs reserved 0~3 +*/ +#define DDS_TLS_IDX_LOGBUFF 4 +#define DDS_TLS_IDX_FREE 5 +#define DDS_TLS_IDX_STATE 6 +#define DDS_TLS_IDX_CTX 7 + +#define ddsrt_thread_tls_set(d, idx, s) \ + vTaskSetThreadLocalStoragePointer(NULL, idx, (void*)s) + +#define ddsrt_thread_tls_get(idx, s) \ + pvTaskGetThreadLocalStoragePointer(NULL, idx) +#else +#error +#define ddsrt_thread_tls_set(d, idx, s) (d) = (s) +#define ddsrt_thread_tls_get(idx, s) (s) +#endif + /** * @brief Initialize thread attributes to platform defaults. */ diff --git a/src/ddsrt/src/cdtors.c b/src/ddsrt/src/cdtors.c index 5ceca0a8..ad49ab2e 100644 --- a/src/ddsrt/src/cdtors.c +++ b/src/ddsrt/src/cdtors.c @@ -165,6 +165,19 @@ DDSRT_WARNING_CLANG_ON(missing-prototypes) #pragma data_seg() #endif #else /* _WIN32 */ + +#ifdef DDSRT_WITH_FREERTOSTCP +void ddsrt_ctor(void) +{ + ddsrt_init(); +} + +void ddsrt_dtor(void) +{ + ddsrt_fini(); +} + +#else void __attribute__((constructor)) ddsrt_ctor(void); void __attribute__((destructor)) ddsrt_dtor(void); @@ -177,5 +190,8 @@ void __attribute__((destructor)) ddsrt_dtor(void) { ddsrt_fini(); } + +#endif + #endif /* _WIN32 */ diff --git a/src/ddsrt/src/heap/freertos/heap.c b/src/ddsrt/src/heap/freertos/heap.c index ffb3d0fb..89d448bc 100644 --- a/src/ddsrt/src/heap/freertos/heap.c +++ b/src/ddsrt/src/heap/freertos/heap.c @@ -10,6 +10,7 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include +#include #if defined(configSUPPORT_DYNAMIC_ALLOCATION) && \ (configSUPPORT_DYNAMIC_ALLOCATION == 0) diff --git a/src/ddsrt/src/ifaddrs.c b/src/ddsrt/src/ifaddrs.c index d50a2e40..8114780d 100644 --- a/src/ddsrt/src/ifaddrs.c +++ b/src/ddsrt/src/ifaddrs.c @@ -19,7 +19,9 @@ ddsrt_freeifaddrs(ddsrt_ifaddrs_t *ifa) while (ifa != NULL) { next = ifa->next; + #ifndef DDSRT_WITH_FREERTOSTCP ddsrt_free(ifa->name); + #endif ddsrt_free(ifa->addr); ddsrt_free(ifa->netmask); ddsrt_free(ifa->broadaddr); diff --git a/src/ddsrt/src/ifaddrs/freertos_plus_tcp/ifaddrs_plus_tcp.c b/src/ddsrt/src/ifaddrs/freertos_plus_tcp/ifaddrs_plus_tcp.c new file mode 100755 index 00000000..52c17792 --- /dev/null +++ b/src/ddsrt/src/ifaddrs/freertos_plus_tcp/ifaddrs_plus_tcp.c @@ -0,0 +1,110 @@ + +#include +#include + +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/misc.h" +#include "sockets_priv.h" + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" +#include "dds/ddsrt/ifaddrs.h" +#include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/string.h" + +extern const int *const os_supp_afs; + + +static dds_return_t copyaddr(ddsrt_ifaddrs_t **ifap) +{ + dds_return_t rc = DDS_RETCODE_OK; + ddsrt_ifaddrs_t *ifa; + struct sockaddr sa = {0U}; + + assert(ifap != NULL); + + /* note: local IP shoule be got after STACK up! */ + u32 lip, netmask, bcip; + bcip = ipBROADCAST_IP_ADDRESS; + FreeRTOS_GetAddressConfiguration(&lip, &netmask, NULL, NULL); + + ifa = ddsrt_calloc(1, sizeof(*ifa)); + if(ifa == NULL) + { + rc = DDS_RETCODE_OUT_OF_RESOURCES; + goto __exit; + } + + ifa->addr = ddsrt_calloc(1, sizeof(struct sockaddr)); + ifa->netmask = ddsrt_calloc(1, sizeof(struct sockaddr)); + ifa->broadaddr = ddsrt_calloc(1, sizeof(struct sockaddr)); + if ((ifa->addr == NULL) + || (ifa->netmask == NULL) + || (ifa->broadaddr == NULL)) + { + rc = DDS_RETCODE_OUT_OF_RESOURCES; + goto __exit; + } + + sa.sa_len = sizeof(struct sockaddr); + sa.sa_family = AF_INET; + sa.sin_addr = (lip); /* storage IP, no need. FreeRTOS_htonl */ + memcpy((void*)ifa->addr, &sa, sizeof(struct sockaddr)); + + sa.sin_addr = (netmask); + memcpy((void*)ifa->netmask, &sa, sizeof(struct sockaddr)); + + sa.sin_addr = (bcip); + memcpy((void*)ifa->broadaddr, &sa, sizeof(struct sockaddr)); + + ifa->next = NULL; + ifa->type = DDSRT_IFTYPE_WIRED; + ifa->name = "eqos0"; + ifa->index = 0; + ifa->flags = IFF_UP | IFF_BROADCAST; // | IFF_MULTICAST; + +__exit: + if (rc == DDS_RETCODE_OK) + { + *ifap = ifa; + } + else + { + ddsrt_freeifaddrs(ifa); + *ifap = NULL; + } + + return rc; +} + +dds_return_t ddsrt_getifaddrs(ddsrt_ifaddrs_t **ifap, const int *afs) +{ + dds_return_t rc = DDS_RETCODE_OK; + int use_ip4 = 0; + int use_ip6 = 0; + + assert(ifap != NULL); + + if (afs == NULL) + { + afs = os_supp_afs; + } + + for (int i = 0; afs[i] != DDSRT_AF_TERM; i++) + { + if (afs[i] == AF_INET) + { + use_ip4 = 1; + } +#ifdef DDSRT_HAVE_IPV6 + else if (afs[i] == AF_INET6) + { + use_ip6 = 1; + } +#endif + } + + rc = copyaddr(ifap); + + return rc; +} diff --git a/src/ddsrt/src/log.c b/src/ddsrt/src/log.c index a291c0ca..33d3f29e 100644 --- a/src/ddsrt/src/log.c +++ b/src/ddsrt/src/log.c @@ -38,7 +38,9 @@ typedef struct { FILE *out; } log_sink_t; +#ifndef DDSRT_WITH_FREERTOS static ddsrt_thread_local log_buffer_t log_buffer; +#endif static ddsrt_once_t lock_inited = DDSRT_ONCE_INIT; static ddsrt_rwlock_t lock; @@ -50,13 +52,82 @@ struct ddsrt_log_cfg_impl { DDSRT_STATIC_ASSERT (sizeof (struct ddsrt_log_cfg_impl) <= sizeof (struct ddsrt_log_cfg)); +static const uint8_t * ddslstr[] = { + "DDS_LC_FATAL", + "DDS_LC_ERROR", + "DDS_LC_WARNING", + "DDS_LC_INFO", + "DDS_LC_CONFIG", + "DDS_LC_DISCOVERY", + "DDS_LC_DATA", + "DDS_LC_TRACE", + "DDS_LC_RADMIN", + "DDS_LC_TIMING", + "DDS_LC_TRAFFIC", + "DDS_LC_TOPIC", + "DDS_LC_TCP", + "DDS_LC_PLIST", + "DDS_LC_WHC", + "DDS_LC_THROTTLE", + "DDS_LC_RHC", + "DDS_LC_CONTENT", + "DDS_LC_SHM", + }; + static void default_sink (void *ptr, const dds_log_data_t *data) { + #ifdef DDSRT_WITH_FREERTOSTCP + + (void)ptr; + uint32_t lv; + + uint32_t i; + for (i = 0U; i < sizeof(int) * 8U; i++) + { + if (data->priority <= (1U << i)) + { break; } + } + + switch (data->priority) + { + case DDS_LC_FATAL: + case DDS_LC_ERROR: + lv = IPLOG_LEVEL_ERROR; + pr_error("[%s] %s @%s-%d", ddslstr[i], data->message, data->function, data->line); + break; + case DDS_LC_WARNING: + lv = IPLOG_LEVEL_WARN; + pr_warn("[%s] %s @%s-%d", ddslstr[i], data->message, data->function, data->line); + break; + case DDS_LC_CONFIG: + case DDS_LC_INFO: + lv = IPLOG_LEVEL_INFO; + pr_info("[%s] %s @%s-%d", ddslstr[i], data->message, data->function, data->line); + break; + case DDS_LC_TRACE: + lv = IPLOG_LEVEL_DEBUG; + pr_debug("[%s] %s @%s-%d", ddslstr[i], data->message, data->function, data->line); + break; + + case DDS_LC_DISCOVERY: + lv = IPLOG_LEVEL_DEBUG; + pr_debug("[%s] %s @%s-%d", ddslstr[i], data->message, data->function, data->line); + break; + + default: + lv = IPLOG_LEVEL_DEBUG; + pr_debug("[%s] %s @%s-%d", ddslstr[i], data->message, data->function, data->line); + break; + } + //net_log_print(lv, "[%s] %s @%s-%d", ddslstr[i], data->message, data->function, data->line); + + #else if (ptr) { (void) fwrite (data->message - data->hdrsize, 1, data->hdrsize + data->size + 1, (FILE *) ptr); fflush ((FILE *) ptr); } + #endif } #define LOG (0) @@ -64,7 +135,14 @@ static void default_sink (void *ptr, const dds_log_data_t *data) static struct ddsrt_log_cfg_impl logconfig = { .c = { + #ifdef DDSRT_WITH_FREERTOSTCP + .mask = DDS_LC_ALL + | DDS_LC_DISCOVERY | DDS_LC_TOPIC + | DDS_LC_CONFIG | DDS_LC_INFO | DDS_LC_WARNING + | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_FATAL, + #else .mask = DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_FATAL, + #endif .tracemask = 0, .domid = UINT32_MAX }, @@ -172,8 +250,19 @@ static size_t print_header (char *str, uint32_t id) { int cnt, off; char *tid, buf[MAX_TID_LEN+1] = { 0 }; + #ifdef DDSRT_WITH_FREERTOSTCP + /* + * for RTOS, printf might not support all format output, + * so add explict len other that this STDIO tricks + * printf("%.*s", 10, str) - output str with cutoff or prefix padding to 10 chars. + */ + static const char fmt_no_id[] = "%06u.%06d [] %.10s:"; + static const char fmt_with_id[] = "%06u.%06d [%"PRIu32"] %.10s:"; + // snprintf (str + off, HDR_LEN - off, fmt_no_id, sec, usec, tid); + #else static const char fmt_no_id[] = "%10u.%06d [] %*.*s:"; static const char fmt_with_id[] = "%10u.%06d [%"PRIu32"] %*.*s:"; + #endif dds_time_t time; unsigned sec; int usec; @@ -187,18 +276,44 @@ static size_t print_header (char *str, uint32_t id) if (id == UINT32_MAX) { off = MAX_ID_LEN; + #ifdef DDSRT_WITH_FREERTOSTCP + /* fix bug, HDR might overwrite log buffer set before. + HDR_LEN - off + //snprintf (str + off, HDR_LEN, "%10u.%06d [] %*.*s:", sec, usec, MAX_TID_LEN, MAX_TID_LEN, tid) + */ + cnt = snprintf (str + off, HDR_LEN - off, fmt_no_id, sec, usec, + tid); + #else cnt = snprintf (str + off, HDR_LEN, fmt_no_id, sec, usec, MAX_TID_LEN, MAX_TID_LEN, tid); + #endif } else { /* low domain ids tend to be most used from what I have seen */ off = 9; if (id >= 10) - for (uint32_t thres = 10; off > 0 && id >= thres; off--, thres *= 10); + { for (uint32_t thres = 10; off > 0 && id >= thres; off--, thres *= 10); } + + #ifdef DDSRT_WITH_FREERTOSTCP + cnt = snprintf (str + off, HDR_LEN - off, fmt_with_id, sec, usec, id, tid); + #else cnt = snprintf (str + off, HDR_LEN, fmt_with_id, sec, usec, id, MAX_TID_LEN, MAX_TID_LEN, tid); + #endif } +#ifdef DDSRT_WITH_FREERTOSTCP + /* fix CycloneDDS bug + * for RTOS printf might not support all STDIO format. "%.*s" + */ + assert (off + cnt < HDR_LEN); + for (int i = off + cnt; i < HDR_LEN; i++) + { + str[i] = ' '; /* Replace snprintf null byte by space. */ + } +#else assert (off + cnt == (HDR_LEN - 1)); str[off + cnt] = ' '; /* Replace snprintf null byte by space. */ +#endif + return (size_t) (cnt + 1); } @@ -209,6 +324,10 @@ static void vlog1 (const struct ddsrt_log_cfg_impl *cfg, uint32_t cat, uint32_t log_buffer_t *lb; dds_log_data_t data; + #ifdef DDSRT_WITH_FREERTOS + log_buffer_t log_buffer = {0}; + #endif + /* id can be used to override the id in logconfig, so that the global logging configuration can be used for reporting errors while inlcuding a domain id. This simply verifies that the id override is only ever diff --git a/src/ddsrt/src/process/freertos/process.c b/src/ddsrt/src/process/freertos/process.c index b2998885..360d499d 100644 --- a/src/ddsrt/src/process/freertos/process.c +++ b/src/ddsrt/src/process/freertos/process.c @@ -20,3 +20,8 @@ ddsrt_getpid(void) return xTaskGetCurrentTaskHandle(); } +char * +ddsrt_getprocessname(void) +{ + return pcTaskGetName(xTaskGetCurrentTaskHandle()); +} diff --git a/src/ddsrt/src/sockets.c b/src/ddsrt/src/sockets.c index 364be9a8..08bfd800 100644 --- a/src/ddsrt/src/sockets.c +++ b/src/ddsrt/src/sockets.c @@ -19,6 +19,9 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" +#ifdef DDSRT_WITH_FREERTOSTCP +# warning " *** FreeRTOS-Plus-TCP debug include tree " +#else #if !LWIP_SOCKET # if !defined(_WIN32) # include @@ -29,6 +32,7 @@ # endif /* __linux */ # endif /* _WIN32 */ #endif /* LWIP_SOCKET */ +#endif /* FreeRTOSTCP */ #if defined __APPLE__ #include @@ -119,7 +123,11 @@ ddsrt_sockaddr_isunspecified(const struct sockaddr *__restrict sa) return IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6*)sa)->sin6_addr); #endif case AF_INET: - return (((struct sockaddr_in *)sa)->sin_addr.s_addr == 0); + #ifdef DDSRT_WITH_FREERTOSTCP + return (((struct sockaddr_in *)sa)->sin_addr == 0); + #else + return (((struct sockaddr_in *)sa)->sin_addr.s_addr == 0); + #endif } return false; @@ -137,8 +145,12 @@ ddsrt_sockaddr_isloopback(const struct sockaddr *__restrict sa) &((const struct sockaddr_in6 *)sa)->sin6_addr); #endif /* DDSRT_HAVE_IPV6 */ case AF_INET: + #ifdef DDSRT_WITH_FREERTOSTCP + return (((const struct sockaddr_in *)sa)->sin_addr == htonl(INADDR_LOOPBACK)); + #else return (((const struct sockaddr_in *)sa)->sin_addr.s_addr == htonl(INADDR_LOOPBACK)); + #endif } return false; @@ -160,11 +172,19 @@ ddsrt_sockaddr_insamesubnet( switch (sa1->sa_family) { case AF_INET: { + #ifdef DDSRT_WITH_FREERTOSTCP + eq = ((((struct sockaddr_in *)sa1)->sin_addr & + ((struct sockaddr_in *)mask)->sin_addr) + == + (((struct sockaddr_in *)sa2)->sin_addr & + ((struct sockaddr_in *)mask)->sin_addr)); + #else eq = ((((struct sockaddr_in *)sa1)->sin_addr.s_addr & ((struct sockaddr_in *)mask)->sin_addr.s_addr) == (((struct sockaddr_in *)sa2)->sin_addr.s_addr & ((struct sockaddr_in *)mask)->sin_addr.s_addr)); + #endif } break; #if DDSRT_HAVE_IPV6 case AF_INET6: { @@ -196,14 +216,24 @@ ddsrt_sockaddrfromstr(int af, const char *str, void *sa) switch (af) { case AF_INET: { + #ifdef DDSRT_WITH_FREERTOSTCP + in_addr_t buf; + #else struct in_addr buf; + #endif #if DDSRT_HAVE_INET_PTON if (inet_pton(af, str, &buf) != 1) { return DDS_RETCODE_BAD_PARAMETER; } #else + #ifdef DDSRT_WITH_FREERTOSTCP + buf = inet_addr (str); + if (buf == (in_addr_t)(-1)) + #else buf.s_addr = inet_addr (str); - if (buf.s_addr == (in_addr_t)-1) { + if (buf.s_addr == (in_addr_t)(-1)) + #endif + { return DDS_RETCODE_BAD_PARAMETER; } #endif @@ -247,7 +277,11 @@ DDSRT_WARNING_GNUC_OFF(sign-conversion) AF_INET, &((struct sockaddr_in *)sa)->sin_addr, buf, (uint32_t)size); #else { + #ifdef DDSRT_WITH_FREERTOSTCP + in_addr_t x = ntohl(((struct sockaddr_in *)sa)->sin_addr); + #else in_addr_t x = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); + #endif snprintf(buf,size,"%u.%u.%u.%u",(x>>24),(x>>16)&0xff,(x>>8)&0xff,x&0xff); ptr = buf; } diff --git a/src/ddsrt/src/threads/freertos/threads.c b/src/ddsrt/src/threads/freertos/threads.c index 206d7d62..9f3be999 100644 --- a/src/ddsrt/src/threads/freertos/threads.c +++ b/src/ddsrt/src/threads/freertos/threads.c @@ -183,7 +183,11 @@ static dds_return_t thread_context_acquire(thread_context_t **ctxptr) { dds_return_t rc = DDS_RETCODE_OK; + #ifdef DDSRT_WITH_FREERTOSTCP + thread_context_t *ctx = (thread_context_t *)ddsrt_thread_tls_get(DDS_TLS_IDX_CTX, thread_context); + #else thread_context_t *ctx = thread_context; + #endif if (ctx == NULL) { /* Dynamically initialize global thread registry (exactly once). */ @@ -199,7 +203,11 @@ thread_context_acquire(thread_context_t **ctxptr) ctx->task = xTaskGetCurrentTaskHandle(); } ddsrt_mutex_unlock(&thread_registry.mutex); + #ifdef DDSRT_WITH_FREERTOSTCP + ddsrt_thread_tls_set(thread_context, DDS_TLS_IDX_CTX, ctx); + #else thread_context = ctx; + #endif } else { assert(ctx->func != NULL); assert(ctx->stat == THREAD_RUNNING); @@ -326,7 +334,11 @@ thread_start_routine(void *arg) thread because a reference to the thread's context is stored and synchronization is considerably easier if it's handled there. */ +#ifdef DDSRT_WITH_FREERTOSTCP + ddsrt_thread_tls_set(thread_context, DDS_TLS_IDX_CTX, ctx); +#else thread_context = ctx; +#endif ret = ctx->func(ctx->arg); thread_fini(ctx, ret); /* DO NOT DEREFERENCE THREAD CONTEXT ANYMORE! */ @@ -427,6 +439,10 @@ void ddsrt_thread_init(uint32_t reason) { (void)reason; +#ifdef DDSRT_WITH_FREERTOSTCP + /* init TLS var */ + ddsrt_thread_tls_set(thread_context, DDS_TLS_IDX_CTX, NULL); +#endif if (thread_context_require() != DDS_RETCODE_OK) { assert(0); } @@ -440,7 +456,12 @@ ddsrt_thread_fini(uint32_t reason) (void)reason; /* NO-OP if no context exists since thread-local storage and cleanup handler references are both stored in the thread context. */ + #ifdef DDSRT_WITH_FREERTOSTCP + ctx = (thread_context_t *)ddsrt_thread_tls_get(DDS_TLS_IDX_CTX, thread_context); + if ( ctx != NULL) { + #else if ((ctx = thread_context) != NULL) { + #endif assert(ctx->func != &non_local_thread); thread_fini(ctx, 0); } diff --git a/src/ddsrt/src/time.c b/src/ddsrt/src/time.c index 9551f0dd..64945fcc 100644 --- a/src/ddsrt/src/time.c +++ b/src/ddsrt/src/time.c @@ -38,6 +38,8 @@ void dds_sleepfor(dds_duration_t n) } #endif +#ifndef DDSRT_WITH_FREERTOS +#warning " ctime in glib, ignore it for FreeRTOS " size_t ddsrt_ctime(dds_time_t n, char *str, size_t size) { @@ -73,6 +75,7 @@ ddsrt_ctime(dds_time_t n, char *str, size_t size) return ddsrt_strlcpy(str, buf, size); } +#endif static void time_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, int64_t t) { diff --git a/src/ddsrt/src/time/freertos/time.c b/src/ddsrt/src/time/freertos/time.c index 01c367bb..e1e5d5a9 100644 --- a/src/ddsrt/src/time/freertos/time.c +++ b/src/ddsrt/src/time/freertos/time.c @@ -20,6 +20,9 @@ DDS_EXPORT extern inline TickType_t ddsrt_duration_to_ticks_ceil(dds_duration_t dds_time_t dds_time(void) { +#ifdef DDSRT_WITH_FREERTOSTCP + return get_timer_us(0U) * 1000U; +#else struct timespec ts; #if __STDC_VERSION__ >= 201112L @@ -29,6 +32,7 @@ dds_time_t dds_time(void) #endif return (ts.tv_sec * DDS_NSECS_IN_SEC) + ts.tv_nsec; +#endif } #define NSECS_PER_TICK (DDS_NSECS_IN_SEC / configTICK_RATE_HZ) diff --git a/src/idl/include/idl/processor.h b/src/idl/include/idl/processor.h index 4e23085a..b27a21eb 100644 --- a/src/idl/include/idl/processor.h +++ b/src/idl/include/idl/processor.h @@ -78,6 +78,7 @@ struct idl_pstate { struct { uint32_t flags; /**< processor options */ int default_extensibility; /**< default extensibility for aggregated types */ + bool default_nested; /**< default nestedness for aggregated types */ const idl_warning_t *disable_warnings; /**< list of warning that will be suppressed */ size_t n_disable_warnings; /**< number of items in disable_warnings */ } config; diff --git a/src/idl/src/processor.c b/src/idl/src/processor.c index 216decd3..2d5e83d0 100644 --- a/src/idl/src/processor.c +++ b/src/idl/src/processor.c @@ -156,6 +156,7 @@ idl_create_pstate( pstate->config.flags = flags; pstate->config.default_extensibility = IDL_DEFAULT_EXTENSIBILITY_UNDEFINED; + pstate->config.default_nested = false; pstate->global_scope = pstate->scope = scope; if (pstate->config.flags & IDL_FLAG_ANNOTATIONS) { @@ -476,6 +477,31 @@ static idl_retcode_t validate_bitbound(idl_pstate_t *pstate) return idl_visit(pstate, pstate->root, &visitor, NULL); } +static void +set_nestedness( + const idl_pstate_t* pstate, + void* node, + bool current_fallback) +{ + IDL_FOREACH(node, node) { + if (idl_is_module(node)) { + idl_module_t *mod = node; + if (!mod->default_nested.annotation) + mod->default_nested.value = current_fallback; + else + current_fallback = mod->default_nested.value; + + IDL_FOREACH(node, mod->definitions) { + set_nestedness(pstate, node, current_fallback); + } + } else if (idl_is_union(node) && !((idl_union_t*)node)->nested.annotation) { + ((idl_union_t*)node)->nested.value = current_fallback; + } else if (idl_is_struct(node) && !((idl_struct_t*)node)->nested.annotation) { + ((idl_struct_t*)node)->nested.value = current_fallback; + } + } +} + static idl_retcode_t set_type_extensibility(idl_pstate_t *pstate) { if (pstate->config.default_extensibility == IDL_DEFAULT_EXTENSIBILITY_UNDEFINED && idl_has_unset_extensibility_r(pstate->root)) { @@ -563,6 +589,8 @@ idl_retcode_t idl_parse(idl_pstate_t *pstate) if ((ret = idl_set_xcdr2_required(pstate->root) != IDL_RETCODE_OK)) goto err; + set_nestedness(pstate, pstate->root, pstate->config.default_nested); + if (pstate->keylists) { if ((ret = idl_validate_keylists(pstate)) != IDL_RETCODE_OK) goto err; diff --git a/src/idl/tests/annotation.c b/src/idl/tests/annotation.c index 6a9d26a7..1c6505e7 100644 --- a/src/idl/tests/annotation.c +++ b/src/idl/tests/annotation.c @@ -432,12 +432,18 @@ CU_Test(idl_annotation, default_nested) const char *str; struct { bool a; bool v; } dn[3]; struct { bool a; bool v; } n[2]; + bool pstate_default_nested; } tests[] = { - { M("m1", M("m2", S("s1")) M("m3", S("s2"))), {{0,0},{0,0},{0,0}}, {{0,0},{0,0}} }, - { DN() M("m1", M("m2", S("s1")) M("m3", S("s2"))), {{1,1},{0,1},{0,1}}, {{0,1},{0,1}} }, - { DN() M("m1", DN(NO) M("m2", S("s1")) M("m3", S("s2"))), {{1,1},{1,0},{0,1}}, {{0,0},{0,1}} }, - { DN(NO) M("m1", DN(YES) M("m2", S("s1")) M("m3", S("s2"))), {{1,0},{1,1},{0,0}}, {{0,1},{0,0}} }, - { DN(YES) M("m1", M("m2", N(NO) S("s1")) M("m3", S("s2"))), {{1,1},{0,1},{0,1}}, {{1,0},{0,1}} } + { M("m1", M("m2", S("s1")) M("m3", S("s2"))), {{0,0},{0,0},{0,0}}, {{0,0},{0,0}}, false }, + { DN() M("m1", M("m2", S("s1")) M("m3", S("s2"))), {{1,1},{0,1},{0,1}}, {{0,1},{0,1}}, false }, + { DN() M("m1", DN(NO) M("m2", S("s1")) M("m3", S("s2"))), {{1,1},{1,0},{0,1}}, {{0,0},{0,1}}, false }, + { DN(NO) M("m1", DN(YES) M("m2", S("s1")) M("m3", S("s2"))), {{1,0},{1,1},{0,0}}, {{0,1},{0,0}}, false }, + { DN(YES) M("m1", M("m2", N(NO) S("s1")) M("m3", S("s2"))), {{1,1},{0,1},{0,1}}, {{1,0},{0,1}}, false }, + { M("m1", M("m2", S("s1")) M("m3", S("s2"))), {{0,1},{0,1},{0,1}}, {{0,1},{0,1}}, true }, + { DN() M("m1", M("m2", S("s1")) M("m3", S("s2"))), {{1,1},{0,1},{0,1}}, {{0,1},{0,1}}, true }, + { DN() M("m1", DN(NO) M("m2", S("s1")) M("m3", S("s2"))), {{1,1},{1,0},{0,1}}, {{0,0},{0,1}}, true }, + { DN(NO) M("m1", DN(YES) M("m2", S("s1")) M("m3", S("s2"))), {{1,0},{1,1},{0,0}}, {{0,1},{0,0}}, true }, + { DN(YES) M("m1", M("m2", N(NO) S("s1")) M("m3", S("s2"))), {{1,1},{0,1},{0,1}}, {{1,0},{0,1}}, true }, }; static const size_t n = sizeof(tests)/sizeof(tests[0]); @@ -449,7 +455,13 @@ CU_Test(idl_annotation, default_nested) for (size_t i=0; i < n; i++) { pstate = NULL; - ret = parse_string(IDL_FLAG_ANNOTATIONS, tests[i].str, &pstate); + ret = idl_create_pstate(IDL_FLAG_ANNOTATIONS, NULL, &pstate); + if (IDL_RETCODE_OK == ret) { + pstate->config.default_extensibility = IDL_FINAL; + pstate->config.default_nested = tests[i].pstate_default_nested; + ret = idl_parse_string(pstate, tests[i].str); + } + CU_ASSERT_EQUAL(ret, IDL_RETCODE_OK); if (ret == IDL_RETCODE_OK) { m = (idl_module_t *)pstate->root; @@ -473,7 +485,8 @@ CU_Test(idl_annotation, default_nested) CU_ASSERT(!tests[i].n[1].a == !s->nested.annotation); CU_ASSERT(s->nested.value == tests[i].n[1].v); } - idl_delete_pstate(pstate); + if (pstate) + idl_delete_pstate(pstate); } } #undef M diff --git a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c index bb900f16..1f556556 100644 --- a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c +++ b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c @@ -464,7 +464,7 @@ crypto_decrypt_data( { bool result = true; EVP_CIPHER_CTX *ctx; - crypto_session_key_t session_key; + crypto_session_key_t session_key = {.data = {0} }; uint32_t key_size = crypto_get_key_size(CRYPTO_TRANSFORM_KIND(transformation_kind)); int len = 0; diff --git a/src/tools/_confgen/CMakeLists.txt b/src/tools/_confgen/CMakeLists.txt index 9df1b82a..d5ca793d 100644 --- a/src/tools/_confgen/CMakeLists.txt +++ b/src/tools/_confgen/CMakeLists.txt @@ -60,33 +60,33 @@ if (NOT ${_confgen_hash_correct}) add_custom_target( _confgen - COMMAND _confgen-exe ARGS -f defconfig -o "${generated_defconfig_src}" - COMMAND _confgen-exe ARGS -f rnc -o "${generated_cyclonedds_rnc}" - COMMAND _confgen-exe ARGS -f xsd -o "${generated_cyclonedds_xsd}" - COMMAND _confgen-exe ARGS -f md -o "${generated_options_md}" + COMMAND _confgen-exe -f defconfig -o "${generated_defconfig_src}" + COMMAND _confgen-exe -f rnc -o "${generated_cyclonedds_rnc}" + COMMAND _confgen-exe -f xsd -o "${generated_cyclonedds_xsd}" + COMMAND _confgen-exe -f md -o "${generated_options_md}" # Append hashes to defconfig.c - COMMAND ${CMAKE_COMMAND} ARGS + COMMAND ${CMAKE_COMMAND} "-DPREFIX=/*" "-DPOSTFIX=*/" -DHASH_FILES=${out_confgen_hash_files} -DAPPEND_FILES=${generated_defconfig_src} -P ${CMAKE_SOURCE_DIR}/cmake/AppendHashScript.cmake # Append hashes to rnc - COMMAND ${CMAKE_COMMAND} ARGS + COMMAND ${CMAKE_COMMAND} "-DPREFIX=#" "-DPOSTFIX=" -DHASH_FILES=${out_confgen_hash_files} -DAPPEND_FILES=${generated_cyclonedds_rnc} -P ${CMAKE_SOURCE_DIR}/cmake/AppendHashScript.cmake # Append hashes to xsd - COMMAND ${CMAKE_COMMAND} ARGS + COMMAND ${CMAKE_COMMAND} "-DPREFIX=" -DHASH_FILES=${out_confgen_hash_files} -DAPPEND_FILES=${generated_cyclonedds_xsd} -P ${CMAKE_SOURCE_DIR}/cmake/AppendHashScript.cmake # Append hashes to md - COMMAND ${CMAKE_COMMAND} ARGS + COMMAND ${CMAKE_COMMAND} "-DPREFIX=" -DHASH_FILES=${out_confgen_hash_files} diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index f5645d5f..de24ab0f 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -2125,7 +2125,7 @@ int main (int argc, char *argv[]) sigset_t sigset, osigset; ddsrt_thread_t sigtid; #endif - char netload_if[256]; + char netload_if[256] = {0}; double netload_bw = -1; double rss_init = 0.0, rss_final = 0.0; ddsrt_threadattr_init (&attr); diff --git a/src/tools/idlc/src/descriptor_type_meta.c b/src/tools/idlc/src/descriptor_type_meta.c index 338051bf..4f54ed9e 100644 --- a/src/tools/idlc/src/descriptor_type_meta.c +++ b/src/tools/idlc/src/descriptor_type_meta.c @@ -198,6 +198,12 @@ has_fully_descriptive_typeid (const idl_type_spec_t *type_spec) static idl_retcode_t get_typeid(const idl_pstate_t *pstate, struct descriptor_type_meta *dtm, const idl_type_spec_t *type_spec, bool alias_related_type, DDS_XTypes_TypeIdentifier *ti, DDS_XTypes_TypeKind kind, bool array_element); +static DDS_XTypes_CollectionElementFlag +get_sequence_element_flags(const idl_sequence_t *seq); + +static DDS_XTypes_CollectionElementFlag +get_array_element_flags(const idl_node_t *node); + static idl_retcode_t get_plain_typeid (const idl_pstate_t *pstate, struct descriptor_type_meta *dtm, const idl_type_spec_t *type_spec, bool alias_related_type, DDS_XTypes_TypeIdentifier *ti, DDS_XTypes_TypeKind kind) { @@ -220,6 +226,7 @@ get_plain_typeid (const idl_pstate_t *pstate, struct descriptor_type_meta *dtm, ti->_u.array_sdefn.element_identifier = calloc (1, sizeof (*ti->_u.array_sdefn.element_identifier)); if ((ret = get_typeid (pstate, dtm, type_spec, false, ti->_u.array_sdefn.element_identifier, kind, true)) < 0) return ret; + ti->_u.array_sdefn.header.element_flags = get_array_element_flags (type_spec); if (has_fully_descriptive_typeid_impl (type_spec, true, alias_related_type)) ti->_u.array_sdefn.header.equiv_kind = DDS_XTypes_EK_BOTH; else @@ -227,6 +234,7 @@ get_plain_typeid (const idl_pstate_t *pstate, struct descriptor_type_meta *dtm, } else { ti->_d = DDS_XTypes_TI_PLAIN_ARRAY_LARGE; ti->_u.array_ldefn.element_identifier = calloc (1, sizeof (*ti->_u.array_ldefn.element_identifier)); + ti->_u.array_ldefn.header.element_flags = get_array_element_flags (type_spec); for (; literal; literal = idl_next (literal)) { assert (literal->value.uint64 < UINT32_MAX); uint32_t val = literal->value.uint32; @@ -275,6 +283,7 @@ get_plain_typeid (const idl_pstate_t *pstate, struct descriptor_type_meta *dtm, if (!idl_is_bounded (seq) || seq->maximum <= UINT8_MAX) { ti->_d = DDS_XTypes_TI_PLAIN_SEQUENCE_SMALL; ti->_u.seq_sdefn.bound = (uint8_t) seq->maximum; + ti->_u.seq_sdefn.header.element_flags = get_sequence_element_flags (seq); ti->_u.seq_sdefn.element_identifier = calloc (1, sizeof (*ti->_u.seq_sdefn.element_identifier)); if ((ret = get_typeid (pstate, dtm, idl_type_spec (type_spec), false, ti->_u.seq_sdefn.element_identifier, kind, false)) < 0) return ret; @@ -285,6 +294,7 @@ get_plain_typeid (const idl_pstate_t *pstate, struct descriptor_type_meta *dtm, } else { ti->_d = DDS_XTypes_TI_PLAIN_SEQUENCE_LARGE; ti->_u.seq_ldefn.bound = seq->maximum; + ti->_u.seq_ldefn.header.element_flags = get_sequence_element_flags (seq); ti->_u.seq_ldefn.element_identifier = calloc (1, sizeof (*ti->_u.seq_ldefn.element_identifier)); if ((ret = get_typeid (pstate, dtm, idl_type_spec (type_spec), false, ti->_u.seq_ldefn.element_identifier, kind, false)) < 0) return ret; @@ -386,19 +396,18 @@ static DDS_XTypes_StructMemberFlag get_struct_member_flags(const idl_member_t *member) { DDS_XTypes_StructMemberFlag flags = 0u; - if (member->try_construct.annotation) { - switch (member->try_construct.value) { - case IDL_DISCARD: - flags |= DDS_XTypes_TRY_CONSTRUCT_DISCARD; - break; - case IDL_USE_DEFAULT: - flags |= DDS_XTypes_TRY_CONSTRUCT_USE_DEFAULT; - break; - case IDL_TRIM: - flags |= DDS_XTypes_TRY_CONSTRUCT_TRIM; - break; - } + switch (member->try_construct.value) { + case IDL_DISCARD: + flags |= DDS_XTypes_TRY_CONSTRUCT_DISCARD; + break; + case IDL_USE_DEFAULT: + flags |= DDS_XTypes_TRY_CONSTRUCT_USE_DEFAULT; + break; + case IDL_TRIM: + flags |= DDS_XTypes_TRY_CONSTRUCT_TRIM; + break; } + if (member->external.value) flags |= DDS_XTypes_IS_EXTERNAL; if (member->key.value) @@ -434,6 +443,10 @@ static DDS_XTypes_UnionDiscriminatorFlag get_union_discriminator_flags(const idl_switch_type_spec_t *switch_type_spec) { DDS_XTypes_UnionDiscriminatorFlag flags = 0u; + + // FIXME: support non-default try-construct + flags |= DDS_XTypes_TRY_CONSTRUCT_DISCARD; + // XTypes spec 7.2.2.4.4.4.6: In a union type, the discriminator member shall always have the 'must understand' attribute set to true flags |= DDS_XTypes_IS_MUST_UNDERSTAND; if (switch_type_spec->key.value) @@ -446,18 +459,16 @@ static DDS_XTypes_UnionMemberFlag get_union_case_flags(const idl_case_t *_case) { DDS_XTypes_UnionMemberFlag flags = 0u; - if (_case->try_construct.annotation) { - switch (_case->try_construct.value) { - case IDL_DISCARD: - flags |= DDS_XTypes_TRY_CONSTRUCT_DISCARD; - break; - case IDL_USE_DEFAULT: - flags |= DDS_XTypes_TRY_CONSTRUCT_USE_DEFAULT; - break; - case IDL_TRIM: - flags |= DDS_XTypes_TRY_CONSTRUCT_TRIM; - break; - } + switch (_case->try_construct.value) { + case IDL_DISCARD: + flags |= DDS_XTypes_TRY_CONSTRUCT_DISCARD; + break; + case IDL_USE_DEFAULT: + flags |= DDS_XTypes_TRY_CONSTRUCT_USE_DEFAULT; + break; + case IDL_TRIM: + flags |= DDS_XTypes_TRY_CONSTRUCT_TRIM; + break; } if (_case->external.value) flags |= DDS_XTypes_IS_EXTERNAL; @@ -468,10 +479,13 @@ get_union_case_flags(const idl_case_t *_case) } static DDS_XTypes_CollectionElementFlag -get_collection_element_flags(const idl_sequence_t *seq) +get_sequence_element_flags(const idl_sequence_t *seq) { DDS_XTypes_CollectionElementFlag flags = 0u; + // FIXME: support non-default try-construct + flags |= DDS_XTypes_TRY_CONSTRUCT_DISCARD; + (void) seq; // FIXME: support @external for sequence element type // if (seq->external) @@ -479,6 +493,21 @@ get_collection_element_flags(const idl_sequence_t *seq) return flags; } +static DDS_XTypes_CollectionElementFlag +get_array_element_flags(const idl_node_t *node) +{ + DDS_XTypes_CollectionElementFlag flags = 0u; + + // FIXME: support non-default try-construct + flags |= DDS_XTypes_TRY_CONSTRUCT_DISCARD; + + (void) node; + // FIXME: support @external for array element type + // if (arr->external) + // flags |= DDS_XTypes_IS_EXTERNAL; + return flags; +} + static DDS_XTypes_BitmaskTypeFlag get_bitmask_flags(const idl_bitmask_t *_bitmask) { @@ -988,7 +1017,7 @@ add_array ( if (!revisit) { dtm->stack->to_minimal->_u.minimal._u.array_type.element.common.element_flags = - dtm->stack->to_complete->_u.complete._u.array_type.element.common.element_flags = get_collection_element_flags (node); + dtm->stack->to_complete->_u.complete._u.array_type.element.common.element_flags = get_sequence_element_flags (node); if ((ret = get_complete_type_detail (type_spec, &dtm->stack->to_complete->_u.complete._u.array_type.header.detail)) < 0) return ret; @@ -1428,7 +1457,7 @@ emit_sequence( No need to include sequence_type.header.detail here, because sequences are anonymous types and there is no type name to store */ dtm->stack->to_minimal->_u.minimal._u.sequence_type.element.common.element_flags = - dtm->stack->to_complete->_u.complete._u.sequence_type.element.common.element_flags = get_collection_element_flags (node); + dtm->stack->to_complete->_u.complete._u.sequence_type.element.common.element_flags = get_sequence_element_flags (node); dtm->stack->to_minimal->_u.minimal._u.sequence_type.header.common.bound = dtm->stack->to_complete->_u.complete._u.sequence_type.header.common.bound = seq->maximum; return IDL_VISIT_REVISIT | IDL_VISIT_TYPE_SPEC; diff --git a/src/tools/idlc/src/idlc.c b/src/tools/idlc/src/idlc.c index bc25c228..3ea2edb7 100644 --- a/src/tools/idlc/src/idlc.c +++ b/src/tools/idlc/src/idlc.c @@ -59,6 +59,7 @@ static struct { int keylist; int case_sensitive; int default_extensibility; + bool default_nested; struct idlc_disable_warning_list disable_warnings; int help; int version; @@ -314,6 +315,7 @@ static idl_retcode_t idlc_parse(void) pstate->scanner.position.column = 1; pstate->config.flags |= IDL_WRITE; pstate->config.default_extensibility = config.default_extensibility; + pstate->config.default_nested = config.default_nested; pstate->config.disable_warnings = config.disable_warnings.list; pstate->config.n_disable_warnings = config.disable_warnings.count; } @@ -442,6 +444,18 @@ static int config_default_extensibility(const idlc_option_t *opt, const char *ar return 0; } +static int config_default_nested(const idlc_option_t *opt, const char *arg) +{ + (void)opt; + if (strcmp(arg, "true") == 0) + config.default_nested = true; + else if (strcmp(arg, "false") == 0) + config.default_nested = false; + else + return IDLC_BAD_ARGUMENT; + return 0; +} + static int add_disable_warning(idl_warning_t warning) { if (config.disable_warnings.count == config.disable_warnings.size) { @@ -539,6 +553,12 @@ static const idlc_option_t *compopts[] = { "Set the default extensibility that is used in case no extensibility" "is set on a type. Possible values are final, appendable and mutable. " "(default: final)" }, + &(idlc_option_t){ + IDLC_FUNCTION, { .function = &config_default_nested }, 'n', "", "", + "Set the default nestedness that is used in the absence of nestedness specifiers on a type " + "(@topic/nested), or other specifiers in its hierarchy (@default_nestedness on modules), " + "with an unset nestedness implicitly being false. Possible values for this option are: true, " + "false (default: true). " }, &(idlc_option_t){ IDLC_FUNCTION, { .function = &config_warning }, 'W', "", "", "Enable or disable warnings. Possible values are: no-implicit-extensibility, " @@ -602,6 +622,7 @@ int main(int argc, char *argv[]) config.compile = 1; config.preprocess = 1; config.default_extensibility = IDL_DEFAULT_EXTENSIBILITY_UNDEFINED; + config.default_nested = false; config.disable_warnings.list = NULL; config.disable_warnings.size = 0; config.disable_warnings.count = 0; diff --git a/src/tools/idlc/tests/type_meta.c b/src/tools/idlc/tests/type_meta.c index 48fffc55..b5df38a8 100644 --- a/src/tools/idlc/tests/type_meta.c +++ b/src/tools/idlc/tests/type_meta.c @@ -202,7 +202,7 @@ static DDS_XTypes_TypeObject *get_typeobj_union(const char *name, uint16_t flags ._d = DDS_XTypes_TK_UNION, ._u.union_type = (DDS_XTypes_CompleteUnionType) { .union_flags = flags, - .discriminator = { .common = { .member_flags = DDS_XTypes_IS_MUST_UNDERSTAND, .type_id = disc_type } }, + .discriminator = { .common = { .member_flags = DDS_XTypes_IS_MUST_UNDERSTAND | DDS_XTypes_TRY_CONSTRUCT_DISCARD, .type_id = disc_type } }, .member_seq = { ._maximum = member_cnt, ._length = member_cnt, @@ -224,9 +224,9 @@ static DDS_XTypes_TypeObject *get_typeobj1 (void) DDS_XTypes_IS_APPENDABLE, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 3, (smember_t[]) { - { 0, DDS_XTypes_IS_KEY | DDS_XTypes_IS_MUST_UNDERSTAND, { ._d = DDS_XTypes_TK_INT64 }, "f1" }, - { 1, DDS_XTypes_IS_OPTIONAL, { ._d = DDS_XTypes_TI_STRING8_SMALL, ._u.string_sdefn.bound = 0 }, "f2" }, - { 4, DDS_XTypes_IS_EXTERNAL, { ._d = DDS_XTypes_TK_CHAR8 }, "f3" } + { 0, DDS_XTypes_IS_KEY | DDS_XTypes_IS_MUST_UNDERSTAND | DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_INT64 }, "f1" }, + { 1, DDS_XTypes_IS_OPTIONAL | DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TI_STRING8_SMALL, ._u.string_sdefn.bound = 0 }, "f2" }, + { 4, DDS_XTypes_IS_EXTERNAL | DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_CHAR8 }, "f3" } }); } @@ -237,8 +237,8 @@ static DDS_XTypes_TypeObject *get_typeobj2 (void) DDS_XTypes_IS_MUTABLE, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 2, (smember_t[]) { - { 0, DDS_XTypes_IS_OPTIONAL | DDS_XTypes_IS_EXTERNAL, { ._d = DDS_XTypes_TK_UINT32 }, "f1" }, - { 1, DDS_XTypes_IS_OPTIONAL | DDS_XTypes_IS_EXTERNAL, { ._d = DDS_XTypes_TK_UINT32 }, "f2" } + { 0, DDS_XTypes_IS_OPTIONAL | DDS_XTypes_IS_EXTERNAL | DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_UINT32 }, "f1" }, + { 1, DDS_XTypes_IS_OPTIONAL | DDS_XTypes_IS_EXTERNAL | DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_UINT32 }, "f2" } }); } @@ -249,8 +249,8 @@ static DDS_XTypes_TypeObject *get_typeobj3 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_INT16 }, 2, (umember_t[]) { - { 0, 0, { ._d = DDS_XTypes_TK_INT32 }, "f1", 1, (int32_t[]) { 1 } }, - { 1, DDS_XTypes_IS_EXTERNAL | DDS_XTypes_IS_DEFAULT, { ._d = DDS_XTypes_TI_STRING8_SMALL, ._u.string_sdefn.bound = 0 }, "f2", 2, (int32_t[]) { 2, 3 } } + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_INT32 }, "f1", 1, (int32_t[]) { 1 } }, + { 1, DDS_XTypes_IS_EXTERNAL | DDS_XTypes_IS_DEFAULT | DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TI_STRING8_SMALL, ._u.string_sdefn.bound = 0 }, "f2", 2, (int32_t[]) { 2, 3 } } }); } @@ -273,14 +273,14 @@ static DDS_XTypes_TypeObject *get_typeobj4 (void) DDS_XTypes_IS_MUTABLE | DDS_XTypes_IS_NESTED, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 1, (smember_t[]) { - { 5, 0, { ._d = DDS_XTypes_TK_INT32 }, "a1" } + { 5, DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_INT32 }, "a1" } })); return get_typeobj_struct ( "t4::test_struct", DDS_XTypes_IS_MUTABLE, ti_base, 1, (smember_t[]) { - { 10, 0, { ._d = DDS_XTypes_TK_INT32 }, "f1" } + { 10, DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_INT32 }, "f1" } }); } @@ -301,7 +301,7 @@ static DDS_XTypes_TypeObject *get_typeobj5 (void) .body = { .common = { .related_flags = 0, .related_type = (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TI_PLAIN_SEQUENCE_SMALL, ._u.seq_sdefn = { - .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = 0 }, + .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD }, .bound = 0, .element_identifier = ti_long } @@ -314,7 +314,7 @@ static DDS_XTypes_TypeObject *get_typeobj5 (void) DDS_XTypes_TypeIdentifier ti_seq = { ._d = DDS_XTypes_TI_PLAIN_SEQUENCE_SMALL, ._u.seq_sdefn = { - .header = { .equiv_kind = DDS_XTypes_EK_COMPLETE, .element_flags = 0 }, + .header = { .equiv_kind = DDS_XTypes_EK_COMPLETE, .element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD }, .bound = 0 } }; @@ -326,8 +326,8 @@ static DDS_XTypes_TypeObject *get_typeobj5 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 2, (smember_t[]) { - { 0, 0, ti_seq, "f1" }, - { 1, 0, ti_alias, "f2" } + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_seq, "f1" }, + { 1, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_alias, "f2" } }); } @@ -345,7 +345,7 @@ static DDS_XTypes_TypeObject *get_typeobj6 (void) ti_f1 = (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TI_PLAIN_ARRAY_SMALL, ._u.array_sdefn = { - .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = 0 }, + .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD }, .array_bound_seq = { ._maximum = 1, ._length = 1, ._buffer = f1bound_seq, ._release = true }, .element_identifier = ti_f1_el } @@ -356,6 +356,7 @@ static DDS_XTypes_TypeObject *get_typeobj6 (void) // the other 2 fields. ti_f1._u.array_sdefn.array_bound_seq._buffer = f1bound_seq; ti_f1._u.array_sdefn.element_identifier = ti_f1_el; + ti_f1._u.array_sdefn.header.element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD; } /* f2 type identifier: string<555> f2[999][3] */ @@ -370,7 +371,7 @@ static DDS_XTypes_TypeObject *get_typeobj6 (void) ti_f2 = (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TI_PLAIN_ARRAY_LARGE, ._u.array_ldefn = { - .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = 0 }, + .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD }, .array_bound_seq = { ._maximum = 2, ._length = 2, ._buffer = f2bound_seq, ._release = true }, .element_identifier = ti_f2_el } @@ -378,6 +379,7 @@ static DDS_XTypes_TypeObject *get_typeobj6 (void) // Clang's static analyzer ... ti_f2._u.array_ldefn.array_bound_seq._buffer = f2bound_seq; ti_f2._u.array_ldefn.element_identifier = ti_f2_el; + ti_f2._u.array_ldefn.header.element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD; } /* f3 type identifier: a[3] f3 */ @@ -389,7 +391,7 @@ static DDS_XTypes_TypeObject *get_typeobj6 (void) DDS_XTypes_IS_FINAL | DDS_XTypes_IS_NESTED, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 1, (smember_t[]) { - { 0, 0, { ._d = DDS_XTypes_TK_INT32 }, "a1" } + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_INT32 }, "a1" } })); uint8_t *f3bound_seq = calloc (1, sizeof (*f3bound_seq)); @@ -397,7 +399,7 @@ static DDS_XTypes_TypeObject *get_typeobj6 (void) ti_f3 = (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TI_PLAIN_ARRAY_SMALL, ._u.array_sdefn = { - .header = { .equiv_kind = DDS_XTypes_EK_COMPLETE, .element_flags = 0 }, + .header = { .equiv_kind = DDS_XTypes_EK_COMPLETE, .element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD }, .array_bound_seq = { ._maximum = 1, ._length = 1, ._buffer = f3bound_seq, ._release = true }, .element_identifier = ti_a } @@ -405,6 +407,7 @@ static DDS_XTypes_TypeObject *get_typeobj6 (void) // Clang's static analyzer ... ti_f3._u.array_sdefn.array_bound_seq._buffer = f3bound_seq; ti_f3._u.array_sdefn.element_identifier = ti_a; + ti_f3._u.array_sdefn.header.element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD; } return get_typeobj_struct ( @@ -412,9 +415,9 @@ static DDS_XTypes_TypeObject *get_typeobj6 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 3, (smember_t[]) { - { 0, 0, ti_f1, "f1" }, - { 1, 0, ti_f2, "f2" }, - { 2, 0, ti_f3, "f3" } + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f1, "f1" }, + { 1, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f2, "f2" }, + { 2, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f3, "f3" } }); } @@ -465,8 +468,8 @@ static DDS_XTypes_TypeObject *get_typeobj7 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 2, (smember_t[]) { - { 0, 0, ti_f1, "f1" }, - { 1, 0, ti_f2, "f2" } + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f1, "f1" }, + { 1, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f2, "f2" } }); } @@ -485,7 +488,7 @@ static DDS_XTypes_TypeObject *get_typeobj8 (void) ti_f1 = (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TI_PLAIN_ARRAY_SMALL, ._u.array_sdefn = { - .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = 0 }, + .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD }, .array_bound_seq = { ._maximum = 2, ._length = 2, ._buffer = f1bound_seq, ._release = true }, .element_identifier = ti_f1_el } @@ -497,7 +500,7 @@ static DDS_XTypes_TypeObject *get_typeobj8 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 1, (smember_t[]) { - { 0, 0, ti_f1, "f1" } + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f1, "f1" } }); } @@ -529,8 +532,8 @@ static DDS_XTypes_TypeObject *get_typeobj9 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 2, (smember_t[]) { - { 0, 0, ti_f, "f1" }, - { 1, 0, ti_f, "f2" } + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f, "f1" }, + { 1, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f, "f2" } }); } @@ -562,8 +565,8 @@ static DDS_XTypes_TypeObject *get_typeobj10 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 2, (smember_t[]) { - { 0, 0, ti_f, "f1" }, - { 1, 0, ti_f, "f2" } + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f, "f1" }, + { 1, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f, "f2" } }); } @@ -574,8 +577,8 @@ static DDS_XTypes_TypeObject *get_typeobj11 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_CHAR8 }, 2, (umember_t[]) { - { 99, 0, { ._d = DDS_XTypes_TK_INT32 }, "f1", 1, (int32_t[]) { 'a' } }, - { 5, DDS_XTypes_IS_DEFAULT, { ._d = DDS_XTypes_TK_UINT16 }, "f2", 0, (int32_t[]) { 0 } } + { 99, DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_INT32 }, "f1", 1, (int32_t[]) { 'a' } }, + { 5, DDS_XTypes_IS_DEFAULT | DDS_XTypes_TRY_CONSTRUCT_DISCARD, { ._d = DDS_XTypes_TK_UINT16 }, "f2", 0, (int32_t[]) { 0 } } }); } @@ -602,7 +605,7 @@ static DDS_XTypes_TypeObject *get_typeobj12 (void) .body = { .common = { .related_flags = 0, .related_type = (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TI_PLAIN_SEQUENCE_SMALL, ._u.seq_sdefn = { - .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = 0 }, + .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD }, .bound = 0, .element_identifier = ti_long } @@ -624,7 +627,7 @@ static DDS_XTypes_TypeObject *get_typeobj12 (void) .body = { .common = { .related_flags = 0, .related_type = (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TI_PLAIN_ARRAY_SMALL, ._u.array_sdefn = { - .header = { .equiv_kind = DDS_XTypes_EK_COMPLETE, .element_flags = 0 }, + .header = { .equiv_kind = DDS_XTypes_EK_COMPLETE, .element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD }, .array_bound_seq = { ._maximum = 1, ._length = 1, ._buffer = bound_seq, ._release = true }, .element_identifier = ti_alias_seq } @@ -639,7 +642,7 @@ static DDS_XTypes_TypeObject *get_typeobj12 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 1, (smember_t[]) { - { 0, 0, ti_f1, "f1" }, + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f1, "f1" }, }); } @@ -665,7 +668,7 @@ static DDS_XTypes_TypeObject *get_typeobj13 (void) .body = { .common = { .related_flags = 0, .related_type = (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TI_PLAIN_ARRAY_SMALL, ._u.array_sdefn = { - .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = 0 }, + .header = { .equiv_kind = DDS_XTypes_EK_BOTH, .element_flags = DDS_XTypes_TRY_CONSTRUCT_DISCARD }, .array_bound_seq = { ._maximum = 1, ._length = 1, ._buffer = bound_seq, ._release = true }, .element_identifier = ti_long } @@ -694,7 +697,7 @@ static DDS_XTypes_TypeObject *get_typeobj13 (void) DDS_XTypes_IS_FINAL, (DDS_XTypes_TypeIdentifier) { ._d = DDS_XTypes_TK_NONE }, 1, (smember_t[]) { - { 0, 0, ti_f1, "f1" }, + { 0, DDS_XTypes_TRY_CONSTRUCT_DISCARD, ti_f1, "f1" }, }); }