--- /dev/null
+.build/
+*-
+*~
--- /dev/null
+---
+# .readthedocs.yml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+# Required
+version: 2
+
+formats:
+ - htmlzip
+
+build:
+ image: latest
+
+python:
+ version: 3.7
+ install:
+ - requirements: docs/requirements-docs.txt
+
+sphinx:
+ configuration: docs/conf.py
+
#==================================================================================
-# Copyright (c) 2019 Nokia
-# Copyright (c) 2018-2019 AT&T Intellectual Property.
+# Copyright (c) 2020 AT&T Intellectual Property.
#
-# Licensed under the Apache License, Version 2.0 (the "License");
+# Licensed under the Apache License, Version 2.0 (the "License"),
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# This CMake definition supports several -D command line options:
#
# -DDEBUG=n Enable debugging level n
-# -DDEV_PKG=1 Development package configuration
-# -DBUILD_DOC=1 Man pages generated
-# -DPRESERVE_PTYPE=1 Do not change the processor type when naming deb packages
# -DGPROF=1 Enable profiling compile time flags
-# -DMAN_PREFIX=<path> Supply a path where man pages are installed (default: /usr/share/man)
+#
+# Building the binaries in this project should be as easy as running the
+# following command in this directory:
+# rm -fr .build
+# make .build
+# cd .build
+# cmake .. [-DGPROF=1] [-DDEBUG=1]
+# make test [install] ARGS=-V
+#
project( ricxfcpp )
-cmake_minimum_required( VERSION 3.5 )
+cmake_minimum_required( VERSION 3.14 )
-set( major_version "0" ) # should be automatically populated from git tag later, but until CI process sets a tag we use this
-set( minor_version "1" )
-set( patch_level "2" )
+set( major_version "1" ) # until CI supports auto tagging; must hard set
+set( minor_version "0" )
+set( patch_level "0" )
set( install_root "${CMAKE_INSTALL_PREFIX}" )
-set( install_inc "include/ricxfcpp" )
-if( MAN_PREFIX )
- set( install_man ${MAN_PREFIX} ) # is there a cmake var for this -- can't find one
-else()
- set( install_man "/usr/share/man" ) # this needs to be fixed so it's not hard coded
-endif()
+set( install_inc "/usr/local/include" )
# Must use GNUInstallDirs to install libraries into correct
# locations on all platforms.
endif()
set( install_lib "${CMAKE_INSTALL_LIBDIR}" )
-message( "+++ ricxfcpp library install target directory: ${install_lib}" )
-
-# ---------------- extract some things from git ------------------------------
-
-# commit id for the version string
-execute_process(
- COMMAND bash -c "git rev-parse --short HEAD|awk '{printf\"%s\", $0}'"
- OUTPUT_VARIABLE git_id
-)
-
-# version information for library names and version string
-execute_process(
- COMMAND bash -c "git describe --tags --abbrev=0 HEAD 2>/dev/null | awk -v tag=0.0.4095 ' { tag=$1 } END{ print tag suffix }'|sed 's/\\./;/g' "
- OUTPUT_VARIABLE mmp_version_str
- ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
-)
-message( "+++ mmp version from tag: '${mmp_version_str}'" )
-
-# extra indicator to show that the build was based on modified file(s) and not the true commit
-# (no hope of reproducing the exact library for debugging). Used only for the internal version
-# string.
-execute_process(
- COMMAND bash -c "git diff --shortstat|awk -v fmt=%s -v r=-rotten '{ s=r } END { printf( fmt, s ) }'"
- OUTPUT_VARIABLE spoiled_str
-)
-
-# uncomment these lines once CI starts adding a tag on merge
-#set( mmp_version ${mmp_version_str} )
-#list( GET mmp_version 0 major_version )
-#list( GET mmp_version 1 minor_version )
-#list( GET mmp_version 2 patch_level )
if( DEBUG ) # if set, we'll set debugging on in the compile
set( debugging ${DEBUG} )
unset( DEBUG CACHE ) # we don't want this to persist
+# ---------------- extract some things from git ------------------------------
+
+# commit id for the version string
+execute_process(
+ COMMAND bash -c "git rev-parse --short HEAD|awk '{printf\"%s\", $0}'"
+ OUTPUT_VARIABLE git_id
+)
+
# define constants used in the version string, debugging, etc.
add_definitions(
-DGIT_ID=${git_id}
-DDEBUG=${debugging}
)
-# ---------------- suss out pkg gen tools so we don't fail generating packages that the system cannot support --------------
-
-# deb packages use underbars, and package manager(s) seem to flip the *_64 processor type
-# to the old (non-standard) amd64 string, so we do it here for consistency. Set -DPRESERVE_PTYPE=1
-# to prevent the flip. RPM packages will always be given the system generated processor type string.
-#
-if( ${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" )
- if( NOT PRESERVE_PTYPE )
- set( deb_sys_name "amd64" )
- else()
- set( deb_sys_name ${CMAKE_SYSTEM_PROCESSOR} )
- endif()
-else()
- set( deb_sys_name ${CMAKE_SYSTEM_PROCESSOR} )
-endif()
-unset( PRESERVE_PTYPE CACHE ) # we don't want this to persist
-
-set( rpm_sys_name ${CMAKE_SYSTEM_PROCESSOR} )
-
-if( DEV_PKG )
- set( deb_pkg_name "ricxfcpp-dev" )
- set( rpm_pkg_name "ricxfcpp-devel" )
-else()
- set( deb_pkg_name "ricxfcpp" )
- set( rpm_pkg_name "ricxfcpp" )
-endif()
-
-set( pkg_label "ricxfcpp${spoiled_str}-${major_version}.${minor_version}.${patch_level}-${sys_name}" )
-set( rpm_pkg_label "${rpm_pkg_name}${spoiled_str}-${major_version}.${minor_version}.${patch_level}-${rpm_sys_name}" )
-set( deb_pkg_label "${deb_pkg_name}${spoiled_str}_${major_version}.${minor_version}.${patch_level}_${deb_sys_name}" )
-message( "+++ pkg name: ${deb_pkg_label}.deb" )
-
-set( gen_rpm 0 )
-find_program( rpm NAMES rpmbuild ) # rpm package gen requires this to be installed
-if( "${rpm}" MATCHES "rpm-NOTFOUND" ) # cannot build rpm
- set( pkg_list "DEB" )
- message( "### make package will generate only deb package; cannot find support to generate rpm packages" )
-else()
- message( "+++ pkg name: ${rpm_pkg_label}.rpm" ) # debugging if we think we can gen rpm too
- set( pkg_list "DEB;RPM" )
- set( gen_rpm 1 )
- message( "+++ make package will generate both deb and rpm packages" )
-endif()
-
-
-
-# this gets us round a chicken/egg problem. include files don't exist until make is run
-# but Cmake insists on having these exist when we add them to include directories to
-# enable code to find them after we build them.
-#
-include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/src/messaging" )
-
-
# Compiler flags
#
set( CMAKE_POSITION_INDEPENDENT_CODE ON )
-set( CMAKE_C_FLAGS "-g " )
-set( CMAKE_CPP_FLAGS "-g " )
if( GPROF ) # if set, we'll set profiling flag on compiles
message( "+++ profiling is on" )
set( CMAKE_C_FLAGS "-pg " )
set( CMAKE_CPP_FLAGS "-pg " )
else()
+ set( CMAKE_C_FLAGS "-g " )
+ set( CMAKE_CPP_FLAGS "-g " )
message( "+++ profiling is off" )
endif()
-unset( GPROF CACHE ) # we don't want this to persist
-
-# Include modules
-add_subdirectory( src/messaging )
-add_subdirectory( src/xapp )
-#add_subdirectory( doc ) # this will auto skip if {X}fm is not available
-
+unset( GPROF CACHE ) # ensure this does not persist
-# shared and static libraries are built from the same object files.
-#
-add_library( ricxfcpp_shared SHARED "$<TARGET_OBJECTS:message_objects>;$<TARGET_OBJECTS:xapp_objects>" )
-set_target_properties( ricxfcpp_shared
- PROPERTIES
- OUTPUT_NAME "ricxfcpp"
- SOVERSION ${major_version}
- VERSION ${major_version}.${minor_version}.${patch_level}
-)
-target_include_directories( ricxfcpp_shared PUBLIC "src/messenger" "src/xapp" )
+# each binary is built from a subset
+add_subdirectory( src/ts_xapp )
-# we only build/export the static archive (.a) if generating a dev package
-if( DEV_PKG )
- add_library( ricxfcpp_static STATIC "$<TARGET_OBJECTS:message_objects>;$<TARGET_OBJECTS:xapp_objects>" )
- set_target_properties( ricxfcpp_static
- PROPERTIES
- OUTPUT_NAME "ricxfcpp"
- SOVERSION ${major_version}
- VERSION ${major_version}.${minor_version}.${patch_level}
- )
- target_include_directories( ricxfcpp_static PUBLIC "src/messenger" "src/xapp" )
-endif()
# -------- unit testing -------------------------------------------------------
enable_testing()
COMMAND bash ../test/unit_test.sh -q
WORKING_DIRECTORY ../test
)
-
-
-# ------------- packaging -----------------------------------------------------
-
-# Define what should be installed, and where they should go. For dev package we install
-# only the RMr headers, man pages and archive (.a) files. The run-time package gets just
-# the library (.so) files and nothing more.
-#
-if( DEV_PKG )
- set( target_list "ricxfcpp_static" )
-else()
- set( target_list "ricxfcpp_shared" )
-endif()
-
-install( TARGETS ${target_list} EXPORT LibraryConfig
- LIBRARY DESTINATION ${install_lib}
- ARCHIVE DESTINATION ${install_lib}
- PUBLIC_HEADER DESTINATION ${install_inc}
-)
-
-unset( DEV_PKG CACHE ) # prevent from being a hidden setting if user redoes things
-
-IF( EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake" )
- include( InstallRequiredSystemLibraries )
-
- set( CPACK_DEBIAN_PACKAGE_NAME ${deb_pkg_name} )
- set( CPACK_RPM_PACKAGE_NAME ${rpm_pkg_name} )
-
- set( CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/local;/usr/local/bin;/usr/local/include;/usr/local/share;/usr/local/lib" )
-
- set( CPACK_set_DESTDIR "on" )
- set( CPACK_PACKAGING_INSTALL_PREFIX "${install_root}" )
- set( CPACK_GENERATOR "${pkg_list}" )
-
- set( CPACK_PACKAGE_DESCRIPTION "C++ framework for RIC xAPPs based on RMR." )
- set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "RIC xAPP C++ framework library" )
- set( CPACK_PACKAGE_VENDOR "None" )
- set( CPACK_PACKAGE_CONTACT "None" )
- set( CPACK_PACKAGE_VERSION_MAJOR "${major_version}" )
- set( CPACK_PACKAGE_VERSION_MINOR "${minor_version}" )
- set( CPACK_PACKAGE_VERSION_PATCH "${patch_level}" )
- set( CPACK_PACKAGE "${pkg_label}" ) # generic name for old versions of cpack
- set( CPACK_DEBIAN_FILE_NAME "${deb_pkg_label}.deb" )
- set( CPACK_RPM_FILE_NAME "${rpm_pkg_label}.rpm" )
-
- # Future: define dependencies on RMR and other libs
-
- set( CPACK_DEBIAN_PACKAGE_PRIORITY "optional" )
- set( CPACK_DEBIAN_PACKAGE_SECTION "ric" )
- set( CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR} )
- set( CPACK_RPM_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR} )
-
- # this seems ingnored if included
- #set( CPACK_COMPONENTS_ALL Libraries ApplicationData )
-
- INCLUDE( CPack )
-ENDIF()
# Author: E. Scott Daniels
# --------------------------------------------------------------------------------------
-# nexus seems to use ports rather than adding release, prod, staging to the url :(
# the builder has: git, wget, cmake, gcc/g++, make, python2/3. v7 dropped nng support
#
-FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu18-c-go:7-u18.04 as buildenv
+FROM nexus3.o-ran-sc.org:10004/o-ran-sc/bldr-ubuntu18-c-go:8-u18.04 as buildenv
# spaces to save things in the build image to copy to final image
RUN mkdir -p /playpen/assets /playpen/src /playpen/bin
#
-# build and install the application
+# build and install the application(s)
#
-COPY examples/* /playpen/src/
-RUN cd /playpen/src && make && make install
-
+COPY . /playpen/src/
+RUN cd /playpen/src && \
+ rm -fr .build &&\
+ mkdir .build && \
+ cd .build && \
+ cmake .. && \
+ make install
# non-programme things that we need to push to final image
#
COPY --from=buildenv /playpen/assets/* /data
# if needed, set RMR vars
-#ENV RMR_RTG_SVC=rm-host:port
-#ENV RMR_VCTL_FILE=/tmp/rmr.v
ENV RMR_SEED_RT=/data/bootstrap.rt
+#ENV RMR_RTG_SVC=rm-host:port
+ENV RMR_VCTL_FILE=/tmp/rmr.v
+RUN echo "2" >/tmp/rmr.v
-#CMD [ "ts_xapp_start.sh" ]
CMD [ "/usr/local/bin/ts_xapp" ]
+++ /dev/null
-#!/usr/bin/env ksh
-
-# Mnemonic: rmr_build.sh
-# Abstract: This will pull RMR from the repo, build and install. This
-# is en lieu of using wget to fetch the RMR package from some
-# repo and installing it. The package method is preferred
-# but if that breaks this can be used in place of it.
-
-rmr_ver=${1:-3.6.2}
-
-# assume that we're in the proper directory
-set -e
-git clone "https://gerrit.o-ran-sc.org/r/ric-plt/lib/rmr"
-
-cd rmr
-git checkout $ver
-mkdir .build
-cd .build
-cmake .. -DDEV_PKG=1 -DPACK_EXTERNALS=1
-make install
-cmake .. -DDEV_PKG=0
-make install
-
--- /dev/null
+# this is used by CI jobs to apply a tag when it builds the image
+---
+tag: '1.0.0'
--- /dev/null
+/_build
+/out
--- /dev/null
+from docs_conf.conf import *
+linkcheck_ignore = [
+ 'http://localhost.*',
+ 'http://127.0.0.1.*',
+ 'https://gerrit.o-ran-sc.org.*'
+]
--- /dev/null
+---
+project_cfg: oran
+project: ric-app-ts
--- /dev/null
+
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+
+Traffic Steering xAPP
+=====================
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Documents:
+
+ user-guide.rst
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Misc:
+
+ rel-notes.rst
+
+* :ref:`search`
--- /dev/null
+
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+
+.. CAUTION: this document is generated from source in doc/src/rtd.
+.. To make changes edit the source and recompile the document.
+.. Do NOT make changes directly to .rst or .md files.
+
+Traffic Steering xAPP
+=====================
+
+2020 April 28 Version 1.0.0
+----------------------------
+
+ Initial release.
+
--- /dev/null
+sphinx
+sphinx-rtd-theme
+sphinxcontrib-httpdomain
+recommonmark
+lfdocs-conf
--- /dev/null
+
+
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+..
+.. CAUTION: this document is generated from source in doc/src/*
+.. To make changes edit the source and recompile the document.
+.. Do NOT make changes directly to .rst or .md files.
+
+
+============
+User's Guide
+============
+---------------------
+Traffic Steering xAPP
+---------------------
+
+Introduction
+============
+
+Some text about the traffic steering xAPP will eventually be added here.
+++ /dev/null
-
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-
-This directory contains the source for the RMR messaging portion of the
-framework. Specifially:
-
- message.*
- provides a message class from which the user can extract/set information
- (type, subscription ID, payload, etc.) and provides instance funcitons
- for sending and replying to the message. User programmes will interact
- directly with this.
-
- msg_component.*
- This is a small type def that allows some of the getter functions in message
- to return a smart pointer to memory which cannot directly be released (e.g
- the payload). This allows the user programme to declare a variable of type
- Msg_component (which is really a smart pointer with a custom deleter) rather
- than having to understand the needed smart pointer construct for these things.
-
- messenger.*
- This class provides the direct "wrapper" on top of RMR. It supports
- high level operations such as Listen and callback management.
-
- callback.*
- This provides the callback support to messenger (listen) functions.
-
- default_cb.*
- This module contains any default callback functions which are provided
- by the framework (e.g. health check processing).
-
-
-
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: callback.cpp
- Abstract: Function defs for the callback managment object
- Date: 9 March 2020
- Author: E. Scott Daniels
-*/
-
-#include <cstdlib>
-
-#include <rmr/rmr.h>
-
-#include "message.hpp"
-//class Messenger;
-
-
-/*
- Builder.
-*/
-Callback::Callback( user_callback ufun, void* data ) { // builder
- user_fun = ufun;
- udata = data;
-}
-
-/*
- there is nothing to be done from a destruction perspective, so no
- destruction function needed at the moment.
-*/
-
-/*
- Drive_cb will invoke the callback and pass along the stuff passed here.
-*/
-void Callback::Drive_cb( Message& m ) {
- if( user_fun != NULL ) {
- user_fun( m, m.Get_mtype(), m.Get_subid(), m.Get_len(), m.Get_payload(), udata );
- }
-}
-
-
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: callback.hpp
- Abstract: class description for a callback managment object.
- Date: 9 March 2020
- Author: E. Scott Daniels
-*/
-
-
-#ifndef _CALLBACK_HPP
-#define _CALLBACK_HPP
-
-#include <memory>
-
-class Messenger;
-class Message;
-#include "message.hpp"
-
-typedef void(*user_callback)( Message& m, int mtype, int subid, int payload_len, Msg_component payload, void* usr_data );
-
-class Callback {
-
- private:
- user_callback user_fun;
- void* udata; // user data
-
- public:
- Callback( user_callback, void* data ); // builder
- void Drive_cb( Message& m ); // invoker
-};
-
-
-#endif
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: default_cb.cpp
- Abstract: This is a set of static functions that are used as
- the default Messenger callbacks.
-
- Date: 11 Mar 2020
- Author: E. Scott Daniels
-*/
-
-#include <string.h>
-#include <unistd.h>
-
-#include <rmr/rmr.h>
-#include <rmr/RIC_message_types.h>
-
-
-#include <cstdlib>
-
-#include "messenger.hpp"
-
-/*
- This is the default health check function that we provide (user
- may override it). It will respond to health check messages by
- sending an OK back to the source.
-
- The mr paramter is obviously ignored, but to add this as a callback
- the function sig must match.
-*/
-void Health_ck_cb( Message& mbuf, int mtype, int sid, int len, Msg_component payload, void* data ) {
- unsigned char response[128];
-
- snprintf( (char* ) response, sizeof( response ), "OK\n" );
- mbuf.Send_response( RIC_HEALTH_CHECK_RESP, sid, strlen( (char *) response )+1, response );
-}
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: default_cb.hpp
- Abstract: Headers/prototypes for the default callbacks. The
- default callbacks are those which we install when
- the messenger is created and handles things that
- the application might not want to (e.g. health check).
-
- Date: 11 March 2020
- Author: E. Scott Daniels
-*/
-
-#ifndef _DEF_CB_H
-#define _DEF_CB_H
-
-
-void Health_ck_cb( Message& mbuf, int mtype, int sid, int len, Msg_component payload, void* data );
-
-
-#endif
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: message.cpp
- Abstract: A message wrapper. This should completely hide the
- underlying transport (RMR) message structure from
- the user application. For the most part, the getters
- are used by the framwork; it is unlikely that other
- than adding/extracting the MEID, the user app will
- be completely unaware of information that is not
- presented in the callback parms.
-
- Date: 12 March 2020
- Author: E. Scott Daniels
-*/
-
-#include <string.h>
-#include <unistd.h>
-
-#include <rmr/rmr.h>
-
-#include <iostream>
-
-#include "message.hpp"
-
-// --------------- private ------------------------------------------------
-
-// --------------- builders/operators -------------------------------------
-
-/*
- Create a new message wrapper for an existing RMR msg buffer.
-*/
-Message::Message( rmr_mbuf_t* mbuf, void* mrc ) {
- this->mrc = mrc; // the message router context for sends
- this->mbuf = mbuf;
-}
-
-Message::Message( void* mrc, int payload_len ) {
- this->mrc = mrc;
- this->mbuf = rmr_alloc_msg( mrc, payload_len );
-}
-
-/*
- Copy builder. Given a source object instance (soi), create a copy.
- Creating a copy should be avoided as it can be SLOW!
-*/
-Message::Message( const Message& soi ) {
- int payload_size;
-
- mrc = soi.mrc;
- payload_size = rmr_payload_size( soi.mbuf ); // rmr can handle a nil pointer
- mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
-}
-
-/*
- Assignment operator. Simiolar to the copycat, but "this" object exists and
- may have data that needs to be released prior to making a copy of the soi.
-*/
-Message& Message::operator=( const Message& soi ) {
- int payload_size;
-
- if( this != &soi ) { // cannot do self assignment
- if( mbuf != NULL ) {
- rmr_free_msg( mbuf ); // release the old one so we don't leak
- }
-
- payload_size = rmr_payload_size( soi.mbuf ); // rmr can handle a nil pointer
- mrc = soi.mrc;
- mbuf = rmr_realloc_payload( soi.mbuf, payload_size, RMR_COPY, RMR_CLONE );
- }
-
- return *this;
-}
-
-/*
- Move builder. Given a source object instance (soi), move the information from
- the soi ensuring that the destriction of the soi doesn't trash things from
- under us.
-*/
-Message::Message( Message&& soi ) {
- mrc = soi.mrc;
- mbuf = soi.mbuf;
-
- soi.mrc = NULL; // prevent closing of RMR stuff on soi destroy
- soi.mbuf = NULL;
-}
-
-/*
- Move Assignment operator. Move the message data to the existing object
- ensure the object reference is cleaned up, and ensuring that the source
- object references are removed.
-*/
-Message& Message::operator=( Message&& soi ) {
- if( this != &soi ) { // cannot do self assignment
- if( mbuf != NULL ) {
- rmr_free_msg( mbuf ); // release the old one so we don't leak
- }
-
- mrc = soi.mrc;
- mbuf = soi.mbuf;
-
- soi.mrc = NULL;
- soi.mbuf = NULL;
- }
-
- return *this;
-}
-
-
-/*
- Destroyer.
-*/
-Message::~Message() {
- if( mbuf != NULL ) {
- rmr_free_msg( mbuf );
- }
-
- mbuf = NULL;
-}
-
-
-// --- getters/setters -----------------------------------------------------
-/*
- Copy the payload bytes, and return a smart pointer (unique) to it.
- If the application needs to update the payload in place for a return
- to sender call, or just to access the payload in a more efficent manner
- (without the copy), the Get_payload() function should be considered.
-
- This function will return a NULL pointer if malloc fails.
-*/
-//char* Message::Copy_payload( ){
-std::unique_ptr<unsigned char> Message::Copy_payload( ){
- unsigned char* new_payload = NULL;
-
- if( mbuf != NULL ) {
- new_payload = (unsigned char *) malloc( sizeof( unsigned char ) * mbuf->len );
- memcpy( new_payload, mbuf->payload, mbuf->len );
- }
-
- return std::unique_ptr<unsigned char>( new_payload );
-}
-
-/*
- Makes a copy of the MEID and returns a smart pointer to it.
-*/
-std::unique_ptr<unsigned char> Message::Get_meid(){
- unsigned char* m = NULL;
-
- m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID );
- rmr_get_meid( mbuf, m );
-
- return std::unique_ptr<unsigned char>( m );
-}
-
-/*
- Return the total size of the payload (the amount that can be written to
- as opposed to the portion of the payload which is currently in use.
- If mbuf isn't valid (nil, or message has a broken header) the return
- will be -1.
-*/
-int Message::Get_available_size(){
- return rmr_payload_size( mbuf ); // rmr can handle a nil pointer
-}
-
-int Message::Get_mtype(){
- int rval = INVALID_MTYPE;
-
- if( mbuf != NULL ) {
- rval = mbuf->mtype;
- }
-
- return rval;
-}
-
-/*
- Makes a copy of the source field and returns a smart pointer to it.
-*/
-std::unique_ptr<unsigned char> Message::Get_src(){
- unsigned char* m = NULL;
-
- m = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_SRC );
- memset( m, 0, sizeof( unsigned char ) * RMR_MAX_SRC );
-
- if( m != NULL ) {
- rmr_get_src( mbuf, m );
- }
-
- return std::unique_ptr<unsigned char>( m );
-}
-
-int Message::Get_state( ){
- int state = INVALID_STATUS;
-
- if( mbuf != NULL ) {
- state = mbuf->state;
- }
-
- return state;
-}
-
-int Message::Get_subid(){
- int rval = INVALID_SUBID;
-
- if( mbuf != NULL ) {
- rval =mbuf->sub_id;
- }
-
- return rval;
-}
-
-/*
- Return the amount of the payload (bytes) which is used. See
- Get_available_size() to get the total usable space in the payload.
-*/
-int Message::Get_len(){
- int rval = 0;
-
- if( mbuf != NULL ) {
- rval = mbuf->len;
- }
-
- return rval;
-}
-
-/*
- This returns a smart (unique) pointer to the payload portion of the
- message. This provides the user application with the means to
- update the payload in place to avoid multiple copies. The
- user programme is responsible to determing the usable payload
- length by calling Message:Get_available_size(), and ensuring that
- writing beyond the indicated size does not happen.
-*/
-Msg_component Message::Get_payload(){
- if( mbuf != NULL ) {
- return std::unique_ptr<unsigned char, unfreeable>( mbuf->payload );
- }
-
- return NULL;
-}
-
-void Message::Set_meid( std::shared_ptr<unsigned char> new_meid ) {
- if( mbuf != NULL ) {
- rmr_str2meid( mbuf, (unsigned char *) new_meid.get() );
- }
-}
-
-void Message::Set_mtype( int new_type ){
- if( mbuf != NULL ) {
- mbuf->mtype = new_type;
- }
-}
-
-void Message::Set_len( int new_len ){
- if( mbuf != NULL && new_len >= 0 ) {
- mbuf->len = new_len;
- }
-}
-
-void Message::Set_subid( int new_subid ){
- if( mbuf != NULL ) {
- mbuf->sub_id = new_subid;
- }
-}
-
-
-// -------------- send functions ---------------------------------
-
-/*
- This assumes that the contents of the mbuf were set by either a send attempt that
- failed with a retry and thus is ready to be processed by RMR.
- Exposed to the user, but not expected to be frequently used.
-*/
-bool Message::Send( ) {
- bool state = false;
-
- if( mbuf != NULL ) {
- mbuf = rmr_send_msg( mrc, mbuf ); // send and pick up new mbuf
- state = mbuf->state == RMR_OK; // overall state for caller
- }
-
- return state;
-}
-
-/*
- Similar to Send(), this assumes that the message is already set up and this is a retry.
- Exposed to the user, but not expected to be frequently used.
-*/
-bool Message::Reply( ) {
- bool state = false;
-
- if( mbuf != NULL ) {
- mbuf = rmr_rts_msg( mrc, mbuf ); // send and pick up new mbuf
- state = mbuf->state == RMR_OK; // state for caller based on send
- }
-
- return state;
-}
-
-/*
- Send workhorse.
- This will setup the message (type etc.) ensure the message payload space is
- large enough and copy in the payload (if a new payload is given), then will
- either send or rts the message based on the stype parm.
-
- If payload is nil, then we assume the user updated the payload in place and
- no copy is needed.
-
- This is public, but most users should use Send_msg or Send_response functions.
-*/
-bool Message::Send( int mtype, int subid, int payload_len, unsigned char* payload, int stype ) {
- bool state = false;
-
- if( mbuf != NULL ) {
- if( mtype != NO_CHANGE ) {
- mbuf->mtype = mtype;
- }
- if( subid != NO_CHANGE ) {
- mbuf->sub_id = subid;
- }
-
- if( payload_len != NO_CHANGE ) {
- mbuf->len = payload_len;
- }
-
- if( payload != NULL ) { // if we have a payload, ensure msg has room, realloc if needed, then copy
- mbuf = rmr_realloc_payload( mbuf, payload_len, RMR_NO_COPY, RMR_NO_CLONE ); // ensure message is large enough
- if( mbuf == NULL ) {
- return false;
- }
-
- memcpy( mbuf->payload, payload, mbuf->len );
- }
-
- if( stype == RESPONSE ) {
- mbuf = rmr_rts_msg( mrc, mbuf );
- } else {
- mbuf = rmr_send_msg( mrc, mbuf );
- }
-
- state = mbuf->state == RMR_OK;
- }
-
- return state;
-}
-
-/*
- Send a response to the endpoint that sent the original message.
-
- Response can be null and the assumption will be that the message payload
- was updated in place and no additional copy is needed before sending the message.
-
- The second form of the call allows for a stack allocated buffer (e.g. char foo[120]) to
- be passed as the payload.
-*/
-bool Message::Send_response( int mtype, int subid, int response_len, std::shared_ptr<unsigned char> response ) {
- return Send( mtype, subid, response_len, response.get(), RESPONSE );
-}
-
-bool Message::Send_response( int mtype, int subid, int response_len, unsigned char* response ) {
- return Send( mtype, subid, response_len, response, RESPONSE );
-}
-
-/*
- These allow a response message to be sent without changing the mtype/subid.
-*/
-bool Message::Send_response( int response_len, std::shared_ptr<unsigned char> response ) {
- return Send( NO_CHANGE, NO_CHANGE, response_len, response.get(), RESPONSE );
-}
-
-bool Message::Send_response( int response_len, unsigned char* response ) {
- return Send( NO_CHANGE, NO_CHANGE, response_len, response, RESPONSE );
-}
-
-
-/*
- Send a message based on message type routing.
-
- Payload can be null and the assumption will be that the message payload
- was updated in place and no additional copy is needed before sending the message.
-
- Return is a new mbuf suitable for sending another message, or the original buffer with
- a bad state sent if there was a failure.
-*/
-bool Message::Send_msg( int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload ) {
- return Send( mtype, subid, payload_len, payload.get(), MESSAGE );
-}
-
-bool Message::Send_msg( int mtype, int subid, int payload_len, unsigned char* payload ) {
- return Send( mtype, subid, payload_len, payload, MESSAGE );
-}
-
-/*
- Similar send functions that allow the message type/subid to remain unchanged
-*/
-bool Message::Send_msg( int payload_len, std::shared_ptr<unsigned char> payload ) {
- return Send( NO_CHANGE, NO_CHANGE, payload_len, payload.get(), MESSAGE );
-}
-
-bool Message::Send_msg( int payload_len, unsigned char* payload ) {
- return Send( NO_CHANGE, NO_CHANGE, payload_len, payload, MESSAGE );
-}
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: message.hpp
- Abstract: Headers for the message class.
- This class provides an interface to the user application
- when information from the message is needed.
-
- Date: 10 March 2020
- Author: E. Scott Daniels
-*/
-
-#ifndef _MESSAGE_HPP
-#define _MESSAGE_HPP
-
-
-#include <iostream>
-#include <string>
-
-#include <rmr/rmr.h>
-
-#include "msg_component.hpp"
-#include "callback.hpp"
-#include "default_cb.hpp"
-
-#ifndef RMR_NO_CLONE
- #define RMR_NO_CLONE 0
- #define RMR_NO_COPY 0
- #define RMR_CLONE 1
- #define RMR_COPY 1
-#endif
-
-
-// ------------------------------------------------------------------------
-
-class Message {
- private:
- rmr_mbuf_t* mbuf; // the underlying RMR message buffer
- void* mrc; // message router context
- std::shared_ptr<char> psp; // shared pointer to the payload to give out
-
- public:
- static const int NO_CHANGE = -99; // indicates no change to a send/reply parameter
- static const int INVALID_MTYPE = -1;
- static const int INVALID_STATUS = -1;
- static const int INVALID_SUBID = -2;
- static const int NO_SUBID = -1; // not all messages have a subid
-
- static const int RESPONSE = 0; // send types
- static const int MESSAGE = 1;
-
- Message( rmr_mbuf_t* mbuf, void* mrc ); // builders
- Message( void* mrc, int payload_len );
- Message( const Message& soi ); // copy cat
- Message& operator=( const Message& soi ); // copy operator
- Message( Message&& soi ); // mover
- Message& operator=( Message&& soi ); // move operator
- ~Message(); // destroyer
-
- std::unique_ptr<unsigned char> Copy_payload( ); // copy the payload; deletable smart pointer
-
- std::unique_ptr<unsigned char> Get_meid(); // returns a copy of the meid bytes
- int Get_available_size();
- int Get_len();
- int Get_mtype();
- Msg_component Get_payload();
- std::unique_ptr<unsigned char> Get_src();
- int Get_state( );
- int Get_subid();
-
- void Set_meid( std::shared_ptr<unsigned char> new_meid );
- void Set_mtype( int new_type );
- void Set_subid( int new_subid );
- void Set_len( int new_len );
-
- bool Reply( );
- bool Send( );
- bool Send( int mtype, int subid, int payload_len, unsigned char* payload, int stype );
-
- bool Send_msg( int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> payload );
- bool Send_msg( int mtype, int subid, int payload_len, unsigned char* payload );
- bool Send_msg( int payload_len, std::shared_ptr<unsigned char> payload );
- bool Send_msg( int payload_len, unsigned char* payload );
-
- bool Send_response( int mtype, int subid, int payload_len, std::shared_ptr<unsigned char> response );
- bool Send_response( int mtype, int subid, int payload_len, unsigned char* response );
- bool Send_response( int payload_len, std::shared_ptr<unsigned char> response );
- bool Send_response( int payload_len, unsigned char* response );
-};
-
-
-#endif
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: messenger.cpp
- Abstract: Message Router Messenger.
-
- Date: 10 March 2020
- Author: E. Scott Daniels
-*/
-
-#include <string.h>
-#include <unistd.h>
-
-#include <rmr/rmr.h>
-#include <rmr/RIC_message_types.h>
-
-
-#include <iostream>
-#include <string>
-#include <map>
-#include <memory>
-#include <mutex>
-
-#include "callback.hpp"
-#include "default_cb.hpp" // default callback prototypes
-#include "message.hpp"
-#include "messenger.hpp"
-
-
-// --------------- private -----------------------------------------------------
-
-
-// ---------------- C++ buggerd up way of maintining class constants ----------
-const int Messenger::MAX_PAYLOAD = (1024*64);
-const int Messenger::DEFAULT_CALLBACK = -1;
-
-// --------------- builders -----------------------------------------------
-/*
- If wait4table is true, then the construction of the object does not
- complete until the underlying transport has a new copy of the route
- table.
-
- If port is nil, then the default port is used (4560).
-*/
-Messenger::Messenger( char* port, bool wait4table ) {
- if( port == NULL ) {
- port = (char *) "4560";
- }
-
- gate = new std::mutex();
- listen_port = strdup( port );
- mrc = rmr_init( listen_port, Messenger::MAX_PAYLOAD, 0 );
-
- if( wait4table ) {
- this->Wait_for_cts( 0 );
- }
-
- Add_msg_cb( RIC_HEALTH_CHECK_REQ, Health_ck_cb, NULL ); // add our default call backs
-
- ok_2_run = true;
-}
-
-/*
- Move support. We DO allow the instance to be moved as only one copy
- remains following the move.
- Given a source object instance (soi) we move the information to
- the new object, and then DELETE what was moved so that when the
- user frees the soi, it doesn't destroy what we snarfed.
-*/
-Messenger::Messenger( Messenger&& soi ) {
- mrc = soi.mrc;
- listen_port = soi.listen_port;
- ok_2_run = soi.ok_2_run;
- gate = soi.gate;
- cb_hash = soi.cb_hash; // this seems dodgy
-
- soi.gate = NULL;
- soi.listen_port = NULL;
- soi.mrc = NULL;
-}
-
-/*
- Move operator. Given a source object instance, movee it's contents
- to this insance. We must first clean up this instance.
-*/
-Messenger& Messenger::operator=( Messenger&& soi ) {
- if( this != &soi ) { // cannot move onto ourself
- if( mrc != NULL ) {
- rmr_close( mrc );
- }
- if( listen_port != NULL ) {
- free( listen_port );
- }
-
- mrc = soi.mrc;
- listen_port = soi.listen_port;
- ok_2_run = soi.ok_2_run;
- gate = soi.gate;
- cb_hash = soi.cb_hash; // this seems dodgy
-
- soi.gate = NULL;
- soi.listen_port = NULL;
- soi.mrc = NULL;
- }
-
- return *this;
-}
-
-/*
- Destroyer.
-*/
-Messenger::~Messenger() {
- if( mrc != NULL ) {
- rmr_close( mrc );
- }
-
- if( listen_port != NULL ) {
- free( listen_port );
- }
-}
-
-/*
- Allow user to register a callback function invoked when a specific type of
- message is received. The user may pass an optional data pointer which
- will be passed to the function when it is called. The function signature
- must be:
- void fun( Messenger* mr, rmr_mbuf_t* mbuf, void* data );
-
- The user can also invoke this function to set the "default" callback by
- passing Messenger::DEFAULT_CALLBACK as the mtype. If no other callback
- is defined for a message type, the default callback function is invoked.
- If a default is not provided, a non-matching message is silently dropped.
-*/
-void Messenger::Add_msg_cb( int mtype, user_callback fun_name, void* data ) {
- Callback* cb;
-
- cb = new Callback( fun_name, data );
- cb_hash[mtype] = cb;
-
- callbacks = true;
-}
-
-/*
- Message allocation for user to send. User must destroy the message when
- finished, but may keep the message for as long as is necessary
- and reuse it over and over.
-*/
-//Message* Messenger::Alloc_msg( int payload_size ) {
-std::unique_ptr<Message> Messenger::Alloc_msg( int payload_size ) {
- return std::unique_ptr<Message>( new Message( mrc, payload_size ) );
-}
-
-void Messenger::Listen( ) {
- int count = 0;
- rmr_mbuf_t* mbuf = NULL;
- std::map<int,Callback*>::iterator mi; // map iterator; silly indirect way to point at the value
- Callback* dcb = NULL; // default callback so we don't search
- Callback* sel_cb; // callback selected to invoke
- std::unique_ptr<Message>m;
-
- if( mrc == NULL ) {
- return;
- }
-
- mi = cb_hash.find( DEFAULT_CALLBACK );
- if( mi != cb_hash.end() ) {
- dcb = mi->second; // oddly named second field is the address of the callback block
- }
-
- while( ok_2_run ) {
- mbuf = rmr_torcv_msg( mrc, mbuf, 2000 ); // come up for air every 2 sec to check ok2run
- if( mbuf != NULL ) {
- if( mbuf->state == RMR_OK ) {
- m = std::unique_ptr<Message>( new Message( mbuf, mrc ) ); // auto delteted when scope terminates
-
- sel_cb = dcb; // start with default
- if( callbacks && ((mi = cb_hash.find( mbuf->mtype )) != cb_hash.end()) ) {
- sel_cb = mi->second; // override with user callback
- }
- if( sel_cb != NULL ) {
- sel_cb->Drive_cb( *m ); // drive the selected one
- mbuf = NULL; // not safe to use after given to cb
- }
- } else {
- if( mbuf->state != RMR_ERR_TIMEOUT ) {
- fprintf( stderr, "<LISTENER> got bad status: %d\n", mbuf->state );
- }
- }
- }
- }
-}
-
-/*
- Wait for the next message, up to a max timout, and return the message received.
-*/
-std::unique_ptr<Message> Messenger::Receive( int timeout ) {
- rmr_mbuf_t* mbuf = NULL;
- std::unique_ptr<Message> m = NULL;
-
- if( mrc != NULL ) {
- mbuf = rmr_torcv_msg( mrc, mbuf, timeout ); // future: do we want to reuse the mbuf here?
- if( mbuf != NULL ) {
- m = std::unique_ptr<Message>( new Message( mbuf, mrc ) );
- }
- }
-
- return m;
-}
-
-/*
- Called to gracefully stop all listeners.
-*/
-void Messenger::Stop( ) {
- ok_2_run = false;
-}
-
-/*
- RMR messages must be released by RMR as there might be transport
- buffers that have to be dealt with. Every callback is expected to
- call this function when finished with the message.
-void Messenger::Release_mbuf( void* vmbuf ) {
- rmr_free_msg( (rmr_mbuf_t *) vmbuf );
-}
-*/
-
-/*
- Wait for clear to send.
- Until RMR loads a route table, all sends will fail with a
- "no endpoint" state. This function allows the user application
- to block until RMR has a viable route table. It does not guarentee
- that every message that the user app will try to send has an entry.
-
- The use of this function by the user application allows for the
- parallel initialisation of the application while waiting for the
- route table service to generate a table for the application. The
- initialisation function may be callsed with "no wait" and this
- function invoked when the application has completed initialisation
- and is ready to start sending messages.
-
- The max wait parameter is the maximum number of seconds to block.
- If RMR never reports ready false is returned. A true return
- incidcates all is ready. If max_wait is 0, then this will only
- return when RMR is ready to send.
-*/
-bool Messenger::Wait_for_cts( int max_wait ) {
- bool block_4ever;
- bool state = false;
-
- block_4ever = max_wait == 0;
- while( block_4ever || max_wait > 0 ) {
- if( rmr_ready( mrc ) ) {
- state = true;
- break;
- }
-
- sleep( 1 );
- max_wait--;
- }
-
- return state;
-}
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-
-/*
- Mnemonic: messenger.hpp
- Abstract: Headers for the messenger class
-
- Date: 10 March 2020
- Author: E. Scott Daniels
-*/
-
-#ifndef _messenger_hpp
-#define _messenger_hpp
-
-
-#include <iostream>
-#include <string>
-#include <map>
-#include <memory>
-#include <mutex>
-
-#include <rmr/rmr.h>
-
-#include "message.hpp"
-
-#ifndef RMR_FALSE
- #define RMR_FALSE 0
- #define RMR_TRUE 1
-#endif
-
-class Messenger {
-
- private:
- std::map<int,Callback*> cb_hash; // callback functions associated with message types
- std::mutex* gate; // overall mutex should we need searialisation
- bool ok_2_run;
- bool callbacks = false; // true if callbacks are defined
- void* mrc; // message router context
- char* listen_port; // port we ask msg router to listen on
-
- // copy and assignment are PRIVATE so that they fail if xapp tries; messenger cannot be copied!
- Messenger( const Messenger& soi );
- Messenger& operator=( const Messenger& soi );
-
- public:
- // -- constants which need an instance; that happens as a global in the .cpp file (wtf C++)
- static const int MAX_PAYLOAD; // max message size we'll handle
- static const int DEFAULT_CALLBACK; // parm for add callback to set default
-
- Messenger( char* port, bool wait4table ); // builder
- Messenger( Messenger&& soi ); // move construction
- Messenger& operator=( Messenger&& soi ); // move operator
- ~Messenger(); // destroyer
-
- void Add_msg_cb( int mtype, user_callback fun_name, void* data );
- std::unique_ptr<Message> Alloc_msg( int payload_size ); // message allocation
- void Listen( ); // lisen driver
- std::unique_ptr<Message> Receive( int timeout ); // receive 1 message
- void Stop( ); // force to stop
- //void Release_mbuf( void* vmbuf );
- bool Wait_for_cts( int max_wait );
-};
-
-#endif
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: msg_component.hpp
- Abstract: Defines a message component type which is needed in order
- to use smart pointers (unique) to point at bytes in the
- RMR message (which are not directly allocated and cannot
- be freed/deleted outside of RMR (require a special destruction
- call in the smart pointer).
-
- Date: 17 March 2020
- Author: E. Scott Daniels
-*/
-
-#ifndef _MSG_COMPONENT_HPP
-#define _MSG_COMPONENT_HPP
-
-#include <memory>
-
-// -------------- smart pointer support --------------------------------
-/*
- Pointers to a lot of things in the RMR message aren't directly
- allocated and thus cannot be directly freed. To return a smart
- pointer to these we have to ensure that no attempt to free/delete
- the reference is made. This struct defines a type with a function
- pointer (operator) that is 'registered' as the delete function for
- such a smart pointer, and does _nothing_ when called.
-*/
-typedef struct {
- void operator()( unsigned char * p ){}
-} unfreeable;
-
-/*
- A 'generic' smart pointer to a component in the message which cannot
- be directly freed (e.g. the payload, meid, etc).
-*/
-using Msg_component = std::unique_ptr<unsigned char, unfreeable>;
-
-#endif
-# vim: sw=4 ts=4 noet:
-#
#==================================================================================
-# Copyright (c) 2020 Nokia
-# Copyright (c) 2020 AT&T Intellectual Property.
+# Copyright (c) 2020 AT&T Intellectual Property.
#
-# Licensed under the Apache License, Version 2.0 (the "License");
+# Licensed under the Apache License, Version 2.0 (the "License"),
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#==================================================================================
#
+add_executable( ts_xapp ts_xapp.cpp )
+target_link_libraries( ts_xapp ricxfcpp;rmr_si;sdl;pthread )
-# For clarity: this generates object, not a lib as the CM command implies.
-#
-add_library( message_objects OBJECT
- callback.cpp
- default_cb.cpp
- message.cpp
- messenger.cpp
+install(
+ TARGETS ts_xapp
+ DESTINATION ${install_bin}
)
-target_include_directories (message_objects PUBLIC
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
- $<INSTALL_INTERFACE:include>
- PRIVATE src)
-
-# header files should go into .../include/xfcpp/
-if( DEV_PKG )
- install( FILES
- callback.hpp
- default_cb.hpp
- message.hpp
- messenger.hpp
- msg_component.hpp
- DESTINATION ${install_inc}
- )
-endif()
-
-# vim: sw=4 ts=4 noet:
-#
+# vim: ts=4 sw=4 noet:
+
#==================================================================================
-# Copyright (c) 2020 Nokia
-# Copyright (c) 2020 AT&T Intellectual Property.
+# Copyright (c) 2020 Nokia
+# Copyright (c) 2020 AT&T Intellectual Property.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# See the License for the specific language governing permissions and
# limitations under the License.
#==================================================================================
-#
+# simple makefile to build the examples. This assumes that the xapp framework
+# library has been installed or the LD_LIBRARY_PATH and C_INCLUDE_PATH environent
+# variables are set to reference the needed files.
-# For clarity: this generates object, not a lib as the CM command implies.
-#
-add_library( xapp_objects OBJECT
- xapp.cpp
-)
+%.o:: %.cpp %.hpp
+ g++ -g ${prereq%% *} -c
-target_include_directories (xapp_objects PUBLIC
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
- $<INSTALL_INTERFACE:include>
- PRIVATE src)
+% :: %.cpp
+ g++ $< -g -o $@ -lricxfcpp -lrmr_si -lpthread -lm -lsdl
-# header files should go into .../include/xfcpp/
-if( DEV_PKG )
- install( FILES
- xapp.hpp
- DESTINATION ${install_inc}
- )
-endif()
+all:: ts_xapp
+install::
+ cp ts_xapp /usr/local/bin/
fprintf(stderr, "cb 2");
send_payload = msg->Get_payload(); // direct access to payload
- snprintf( (char *) send_payload.get(), 2048, "{\"UEPredictionSet\" : [\"222\", \"333\", \"444\"]}", i );
+ snprintf( (char *) send_payload.get(), 2048, "{\"UEPredictionSet\" : [\"222\", \"333\", \"444\"]}" );
fprintf(stderr, "cb 3");
// payload updated in place, nothing to copy from, so payload parm is nil
if ( ! msg->Send_msg( mtype, Message::NO_SUBID, strlen( (char *) send_payload.get() )+1, NULL )) {
- fprintf( stderr, "<SNDR> send failed: %d\n", i );
+ fprintf( stderr, "<SNDR> send failed: %d\n", msg->Get_state() );
}
fprintf(stderr, "cb 4");
int delay = 1000000; // mu-sec delay; default 1s
- char* port = (char *) "4555";
+ char* port = (char *) "4560";
int ai;
+++ /dev/null
-
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-
-This directory contains the source for the overall Xapp class.
-Specifially:
-
- xapp.*
- Is the class that the user creates in their application. It provides, by
- extension, the RMR messaging functions.
-
-
-
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: xapp.cpp
- Abstract: The main xapp class.
- This class actually extends the messenger class as most of what
- would be done here is just passing through to the messenger.
-
- Date: 13 March 2020
- Author: E. Scott Daniels
-*/
-
-#include <string.h>
-#include <unistd.h>
-
-#include <rmr/rmr.h>
-#include <rmr/RIC_message_types.h>
-
-
-#include <iostream>
-#include <thread>
-
-#include <messenger.hpp>
-#include "xapp.hpp"
-
-// --------------- private -----------------------------------------------------
-
-
-
-// --------------- builders -----------------------------------------------
-
-/*
- If wait4table is true, then the construction of the object does not
- complete until the underlying transport has a new copy of the route
- table.
-
- If port is nil, then the default port is used (4560).
-*/
-Xapp::Xapp( char* port, bool wait4table ) : Messenger( port, wait4table ) {
- // nothing to do; all handled in Messenger constructor
-}
-
-/*
- Destroyer.
-*/
-Xapp::~Xapp() {
- // nothing to destroy; superclass destruction is magically invoked.
-}
-
-/*
- Start n threads, each running a listener which will drive callbacks.
-
- The final listener is started in the main thread; in otherwords this
- function won't return unless that listener crashes.
-*/
-void Xapp::Run( int nthreads ) {
- int i;
- std::thread** tinfo; // each thread we'll start
-
- tinfo = new std::thread* [nthreads-1];
-
- for( i = 0; i < nthreads - 1; i++ ) { // thread for each n-1; last runs here
- tinfo[i] = new std::thread( &Xapp::Listen, this );
- }
-
- this->Listen(); // will return only when halted
-
- for( i = 0; i < nthreads - 1; i++ ) { // wait for others to stop
- tinfo[i]->join();
- }
-
- delete tinfo;
-}
-
-/*
- Halt the xapp. This will drive the messenger's stop function to prevent any
- active listeners from running, and will shut things down.
-*/
-void Xapp::Halt() {
- this->Stop(); // messenger shut off
-}
-
+++ /dev/null
-// vi: ts=4 sw=4 noet:
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: xapp.hpp
- Abstract: Headers for the xapp class. This class extends the messenger class
- as most of the function of this class would be just passing through
- calls to the messenger object.
-
- Date: 13 March 2020
- Author: E. Scott Daniels
-*/
-
-#ifndef _xapp_hpp
-#define _xapp_hpp
-
-
-#include <iostream>
-#include <string>
-#include <mutex>
-#include <map>
-
-#include <rmr/rmr.h>
-
-#include "callback.hpp"
-#include "messenger.hpp"
-
-class Xapp : public Messenger {
-
- private:
- std::string name;
-
- // copy and assignment are PRIVATE because we cant "clone" the listen environment
- Xapp( const Xapp& soi );
- Xapp& operator=( const Xapp& soi );
-
- public:
- Xapp( char* listen_port, bool wait4rt ); // builder
- Xapp( );
- ~Xapp(); // destroyer
-
- void Run( int nthreads ); // message listen driver
- void Halt( ); // force to stop
-};
-
-#endif
+++ /dev/null
-// vim: ts=4 sw=4 noet :
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: rmr_em.c
- Abstract: RMR emulation for testing
-
- Date: 20 March
- Author: E. Scott Daniels
-*/
-
-#include <unistd.h>
-#include <string.h>
-#include <malloc.h>
-
-
-/*
- CAUTION: this is a copy of what is in RMR and it is needed as some of the framework
- functions access the 'public' fields like state and mtype.
-*/
-typedef struct {
- int state; // state of processing
- int mtype; // message type
- int len; // length of data in the payload (send or received)
- unsigned char* payload; // transported data
- unsigned char* xaction; // pointer to fixed length transaction id bytes
- int sub_id; // subscription id
- int tp_state; // transport state (errno) valid only if state != RMR_OK, and even then may not be valid
-
- // these things are off limits to the user application
- void* tp_buf; // underlying transport allocated pointer (e.g. nng message)
- void* header; // internal message header (whole buffer: header+payload)
- unsigned char* id; // if we need an ID in the message separate from the xaction id
- int flags; // various MFL_ (private) flags as needed
- int alloc_len; // the length of the allocated space (hdr+payload)
-
- void* ring; // ring this buffer should be queued back to
- int rts_fd; // SI fd for return to sender
-
- int cookie; // cookie to detect user misuse of free'd msg
-} rmr_mbuf_t;
-
-typedef struct {
- char meid[32];
- char src[32];
-} header_t;
-
-
-void* rmr_init( char* port, int flags ) {
- return malloc( sizeof( char ) * 100 );
-}
-
-rmr_mbuf_t* rmr_alloc_msg( void* mrc, int payload_len ) {
- rmr_mbuf_t* mbuf;
- char* p; // the tp buffer; also the payload
- header_t* h;
- int len;
-
- len = (sizeof( char ) * payload_len) + sizeof( header_t );
- p = (char *) malloc( len );
- if( p == NULL ) {
- return NULL;
- }
- h = (header_t *) p;
- memset( p, 0, len );
-
- mbuf = (rmr_mbuf_t *) malloc( sizeof( rmr_mbuf_t ) );
- if( mbuf == NULL ) {
- free( p );
- return NULL;
- }
- memset( mbuf, 0, sizeof( rmr_mbuf_t ) );
-
- mbuf->tp_buf = p;
- mbuf->payload = (char *)p + sizeof( header_t );
-
-
- mbuf->len = 0;
- mbuf->alloc_len = payload_len;
- mbuf->payload = (void *) p;
- strncpy( h->src, "host:ip", 8 );
- strncpy( h->meid, "EniMeini", 9 );
-
- return mbuf;
-}
-
-void rmr_free_msg( rmr_mbuf_t* mbuf ) {
- if( mbuf ) {
- if( mbuf->tp_buf ) {
- free( mbuf->tp_buf );
- }
- free( mbuf );
- }
-}
-
-char* rmr_get_meid( rmr_mbuf_t* mbuf, char* m ) {
- header_t* h;
-
- if( mbuf != NULL ) {
- if( m == NULL ) {
- m = (char *) malloc( sizeof( char ) * 32 );
- }
- h = (header_t *) mbuf->tp_buf;
- memcpy( m, h->meid, 32 );
- }
-
- return m;
-}
-
-int rmr_payload_size( rmr_mbuf_t* mbuf ) {
-
- if( mbuf != NULL ) {
- return mbuf->alloc_len;
- }
-
- return 0;
-}
-
-char *rmr_get_src( rmr_mbuf_t* mbuf, char *m ) {
- header_t* h;
-
- if( mbuf != NULL ) {
- if( m == NULL ) {
- m = (char *) malloc( sizeof( char ) * 32 );
- }
- h = (header_t *) mbuf->tp_buf;
- memcpy( m, h->src, 32 );
- }
-
- return m;
-}
-
-int rmr_str2meid( rmr_mbuf_t* mbuf, unsigned char* s ) {
- header_t* h;
-
- if( mbuf != NULL ) {
- if( s == NULL ) {
- return 1;
- }
-
- if( strlen( s ) > 31 ) {
- return 1;
- }
-
- h = (header_t *) mbuf->tp_buf;
- strncpy( h->meid, s, 32 );
- return 0;
- }
-
- return 1;
-}
-
-rmr_mbuf_t* rmr_send_msg( void* mrc, rmr_mbuf_t* mbuf ) {
-
- if( mbuf != NULL ) {
- mbuf->state = 0;
- }
-
- return mbuf;
-}
-
-rmr_mbuf_t* rmr_rts_msg( void* mrc, rmr_mbuf_t* mbuf ) {
-
- if( mbuf != NULL ) {
- mbuf->state = 0;
- }
-
- return mbuf;
-}
-
-rmr_mbuf_t* rmr_realloc_payload( rmr_mbuf_t* mbuf, int payload_len, int copy, int clone ) { // ensure message is large enough
- rmr_mbuf_t* nmb;
- unsigned char* payload;
-
- if( mbuf == NULL ) {
- return NULL;
- }
-
- nmb = rmr_alloc_msg( NULL, payload_len );
- if( copy ) {
- memcpy( nmb->payload, mbuf->payload, mbuf->len );
- nmb->len = mbuf->len;
- } else {
- nmb->len = 0;
- }
- nmb->state = mbuf->state;
-
- if( ! clone ) {
- free( mbuf );
- }
- return nmb;
-}
-
-void rmr_close( void* mrc ) {
- return;
-}
-
-rmr_mbuf_t* rmr_torcv_msg( void* mrc, rmr_mbuf_t* mbuf, int timeout ) {
- static int max2receive = 500;
- static int mtype = 0;
-
- if( mbuf == NULL ) {
- mbuf = rmr_alloc_msg( NULL, 2048 );
- }
-
- if( max2receive <= 0 ) {
- mbuf->state = 12;
- mbuf->len = 0;
- mbuf->mtype = -1;
- mbuf->sub_id = -1;
- }
-
- max2receive--;
-
- mbuf->state = 0;
- mbuf->len = 80;
- mbuf->mtype = mtype;
- mbuf->sub_id = -1;
-
- mtype++;
- if( mtype > 100 ) {
- mtype = 0;
- }
-
- return mbuf;
-}
-
-int rmr_ready( void* mrc ) {
- static int state = 0;
-
- if( ! state ) {
- state = 1;
- return 0;
- }
-
- return 1;
-}
-
+++ /dev/null
-// vim: ts=4 sw=4 noet :
-/*
-==================================================================================
- Copyright (c) 2020 Nokia
- Copyright (c) 2020 AT&T Intellectual Property.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================================
-*/
-
-/*
- Mnemonic: Unit_test.cpp
- Abstract: This is the unit test driver for the C++ xAPP framework. It
- operates by including all of the modules directly (in order
- to build them with the necessary coverage flags), then
- drives all that it can. The RMR emulation module provides
- emulated RMR functions which simulate the creation, sending
- and receiving of messages etc.
-
- Date: 20 March 2020
- Author: E. Scott Daniels
-*/
-
-#include <memory>
-
-
-#include "../src/messaging/callback.hpp"
-#include "../src/messaging/default_cb.hpp"
-#include "../src/messaging/message.hpp"
-#include "../src/messaging/messenger.hpp"
-#include "../src/messaging/msg_component.hpp"
-#include "../src/xapp/xapp.hpp"
-
-#include "../src/messaging/callback.cpp"
-#include "../src/messaging/default_cb.cpp"
-#include "../src/messaging/message.cpp"
-#include "../src/messaging/messenger.cpp"
-#include "../src/xapp/xapp.cpp"
-
-/*
- callback error counts are global for ease. They track the number of times each callback
- was invoked with the expected message type(s) and any times they were not.
-*/
-int err_cb1 = 0;
-int err_cb2 = 0;
-int err_cbd = 0;
-
-int good_cb1 = 0;
-int good_cb2 = 0;
-int good_cbd = 0;
-
-/*
- callback functions to register; driven as we "receive" messages (the RMR emulation package
- will generate a message every time the receive function is called).
-*/
-void cb1( Message& mbuf, int mtype, int subid, int len, Msg_component payload, void* data ) {
- if( mtype != 1 ) { // should only be driven for type 1 messages
- err_cb1++;
- } else {
- good_cb1++;
- }
-}
-void cb2( Message& mbuf, int mtype, int subid, int len, Msg_component payload, void* data ) {
- if( mtype != 2 ) { // should only be driven for type 2 messages
- err_cb2++;
- } else {
- good_cb2++;
- }
-}
-void cbd( Message& mbuf, int mtype, int subid, int len, Msg_component payload, void* data ) {
- if( mtype > 0 && mtype < 3 ) { // should only be driven for types that arent 1 or 2
- if( err_cbd < 10 ) {
- fprintf( stderr, "<FAIL> cbd: bad message type: %d\n", mtype );
- }
- err_cbd++;
- } else {
- good_cbd++;
- }
-}
-
-/*
- The Xapp Run() function only returns when Xapp is asked to stop, and that
- isn't supported from inside any of the callbacks. This funciton is
- started in a thread and after a few seconds it will drive the halt
- function in the Xapp instance to stop the run function and allow the
- unit test to finish.
-*/
-void killer( std::shared_ptr<Xapp> x ) {
- fprintf( stderr, "<INFO> killer is waiting in the shadows\n" );
- sleep( 2 );
- fprintf( stderr, "<INFO> killer is on the loose\n" );
- x->Halt();
-}
-
-int main( int argc, char** argv ) {
- std::thread* tinfo; // we'll start a thread that will shut things down after a few seconds
- std::unique_ptr<Message> msg;
- std::shared_ptr<Xapp> x;
- Msg_component payload;
- std::unique_ptr<unsigned char> ucs;
- unsigned char* new_payload;
- std::shared_ptr<unsigned char> new_p_ref; // reference to payload to pass to send functions
- char* port = (char *) "4560";
- int ai = 1; // arg processing index
- int nthreads = 2; // ensure the for loop is executed in setup
- int i;
- int len;
- int errors = 0;
- char wbuf[256];
-
- ai = 1;
- while( ai < argc ) { // very simple flag processing (no bounds/error checking)
- if( argv[ai][0] != '-' ) {
- break;
- }
-
- switch( argv[ai][1] ) { // we only support -x so -xy must be -x -y
- case 'p':
- port = argv[ai+1];
- ai++;
- break;
-
- case 't':
- nthreads = atoi( argv[ai+1] );
- ai++;
- break;
- }
-
- ai++;
- }
-
- x = std::shared_ptr<Xapp>( new Xapp( port, true ) );
- x->Add_msg_cb( 1, cb1, NULL );
- x->Add_msg_cb( 2, cb2, NULL );
- x->Add_msg_cb( -1, cbd, NULL );
-
- msg = x->Alloc_msg( 2048 );
- payload = msg->Get_payload();
- msg->Set_len( 128 );
- msg->Set_mtype( 100 );
- msg->Set_subid( -10 );
-
- ucs = msg->Copy_payload( );
- if( ucs == NULL ) {
- fprintf( stderr, "<FAIL> expected pointer to copy payload but got nil\n" );
- errors++;
- }
-
- ucs = msg->Get_meid();
- if( ucs == NULL ) {
- fprintf( stderr, "<FAIL> expected pointer to meid copy but got nil\n" );
- errors++;
- }
-
- ucs = msg->Get_src();
- if( ucs == NULL ) {
- fprintf( stderr, "<FAIL> expected pointer to src copy but got nil\n" );
- errors++;
- }
-
- i = msg->Get_available_size();
- if( i != 2048 ) {
- fprintf( stderr, "<FAIL> len expected payload avail size of 2048 but got %d\n", i );
- errors++;
- }
-
- i = msg->Get_mtype();
- if( i != 100 ) {
- fprintf( stderr, "<FAIL> expected mtype of 100 but got %d\n", i );
- errors++;
- }
-
- i = msg->Get_state( );
- if( i != 0 ) {
- fprintf( stderr, "<FAIL> expected state of 0 but got %d\n", i );
- errors++;
- }
-
- i = msg->Get_subid();
- if( i != -10 ) {
- fprintf( stderr, "<FAIL> expected subid of -10 but got %d\n", i );
- errors++;
- }
-
- i = msg->Get_len();
- if( i != 128 ) {
- fprintf( stderr, "<FAIL> len expected 128 but got %d\n", i );
- errors++;
- }
-
- msg->Send(); // generic send as is functions
- msg->Reply();
-
- new_payload = (unsigned char *) malloc( sizeof( unsigned char ) * 2048 ); // a large payload
- memset( new_payload, 0 , sizeof( unsigned char ) * 2048 );
- new_p_ref = std::shared_ptr<unsigned char>( new_payload ); // reference it for send calls
-
- msg->Set_meid( new_p_ref );
-
- msg->Send_msg( 255, new_p_ref ); // send without changing the message type/subid from above
- msg->Send_msg( 255, new_payload ); // drive the alternate prototype
- msg->Send_msg( 100, 1, 128, new_p_ref ); // send using just 128 bytes of payload
- msg->Send_msg( 100, 1, 128, new_payload ); // drive with alternate prototype
-
- msg->Set_len( 128 );
- msg->Set_mtype( 100 );
- msg->Set_subid( -10 );
-
- msg->Send_response( 100, new_p_ref ); // send a response (rts) with establisehd message type etc
- msg->Send_response( 100, new_payload );
- msg->Send_response( 100, 10, 100, new_p_ref );
- msg->Send_response( 100, 10, 100, new_payload );
-
-
- msg = NULL; // should drive the message destroyer for coverage
-
- msg = x->Receive( 2000 );
- if( msg == NULL ) {
- fprintf( stderr, "<FAIL> expected message from receive but got nil\n" );
- errors++;
- }
-
- tinfo = new std::thread; // start killer thread to terminate things so that run doesn't hang forever
- tinfo = new std::thread( killer, x );
-
- x->Run( nthreads );
- x->Halt(); // drive for coverage
-
- if( err_cb1 + err_cb2 + err_cbd > 0 ) {
- fprintf( stderr, "<FAIL> one or more callbacks reported an error: [%d] [%d] [%d]\n", err_cb1, err_cb2, err_cbd );
- fprintf( stderr, "<INFO> callback good values: [%d] [%d] [%d]\n", good_cb1, good_cb2, good_cbd );
- errors++;
- }
-
- // ----- specific move/copy coverage drivers ---------------------------
-
- Messenger m1( (char *) "1234", false ); // messenger class does NOT permit copies, so no need to test
- Messenger m2( (char *) "9999", false );
- m1 = std::move( m2 ); // drives move operator= function
- Messenger m3 = std::move( m1 ); // drives move constructor function
-
- std::unique_ptr<Message> msg2 = x->Alloc_msg( 2048 );
- std::unique_ptr<Message> msg3 = x->Alloc_msg( 4096 );
-
- snprintf( wbuf, sizeof( wbuf ), "Stand up and cheer!!" );
- msg3->Set_len( strlen( wbuf ) );
- strcpy( (char *) (msg3->Get_payload()).get(), wbuf ); // populate the payload to vet copy later
- fprintf( stderr, "<DBUG> set string (%s) \n", (char *) (msg3->Get_payload()).get() );
-
- Message msg4 = *(msg3.get()); // drive copy builder; msg4 should have a 4096 byte payload
- fprintf( stderr, "<DBUG> copy string (%s) \n", (char *) (msg4.Get_payload()).get() ); // and payload should be coppied
- if( msg4.Get_available_size() != 4096 ) {
- errors++;
- fprintf( stderr, "<FAIL> message copy builder payload size smells: expected 4096, got %d\n", msg4.Get_available_size() );
- }
- if( strcmp( (char *) msg4.Get_payload().get(), wbuf ) != 0 ) {
- errors++;
- fprintf( stderr, "<FAIL> message copy builder payload of copy not the expected string\n" );
- }
-
- snprintf( wbuf, sizeof( wbuf ), "Rambling Wreck; GT!" ); // different string into msg 2 to ensure copy replaced msg3 string
- strcpy( (char *) (msg2->Get_payload()).get(), wbuf ); // populate the msg2 payload to vet copy
- msg2->Set_len( strlen( wbuf ) );
- *msg3 = *msg2; // drive the copy operator= function
- if( msg3->Get_available_size() != 2048 ) {
- errors++;
- fprintf( stderr, "<FAIL> message copy operator payload size smells: expected 2048, got %d\n", msg3->Get_available_size() );
- }
- if( strcmp( (char *) msg3->Get_payload().get(), wbuf ) != 0 ) {
- errors++;
- fprintf( stderr, "<FAIL> message copy builder payload of copy not the expected string\n" );
- }
-
- Message msg5 = std::move( *(msg3.get()) ); // drive move constructor
- if( msg5.Get_available_size() != 2048 ) {
- errors++;
- fprintf( stderr, "<FAIL> message copy operator payload size smells: expected 2048, got %d\n", msg5.Get_available_size() );
- }
- if( strcmp( (char *) msg5.Get_payload().get(), wbuf ) != 0 ) {
- errors++;
- fprintf( stderr, "<FAIL> message copy builder payload of copy not the expected string\n" );
- }
-
- msg5.Set_len( 2 ); // bogus len for vetting later
- msg5 = std::move( *(msg3.get()) );
- if( msg5.Get_len() == 21 ) {
- errors++;
- fprintf( stderr, "<FAIL> message move operator payload len smells: expected 21, got %d\n", msg5.Get_len() );
- }
-
- return errors > 0;
-}
while [[ $1 == "-"* ]]
do
case $1 in
- -q) spew="head -40";;
+ -q) spew="head -40";; # how much to dump on build error
-v) spew="cat";;
esac
shift
done
+if [[ ! -f unit_test.cpp ]]
+then
+ echo "[PASS] no unit test source exists"
+ exit 0
+fi
+
make nuke >/dev/null
make unit_test >/tmp/PID$$.log 2>&1
abort_if_error $? "unable to make"
-spew="cat"
+spew="cat" # after we build, dump everything on error
./unit_test >/tmp/PID$$.log 2>&1
abort_if_error $? "unit test failed"
--- /dev/null
+# This work is licensed under a Creative Commons Attribution 4.0 International License.
+# SPDX-License-Identifier: CC-BY-4.0
+# Copyright (C) 2020 AT&T Intellectual Property
+# documentation only
+
+# this file is needed to control the read the docs verification mechanism in jenkins
+
+[tox]
+minversion = 2.0
+envlist =
+ docs,
+ docs-linkcheck,
+skipsdist = true
+
+[testenv:docs]
+basepython = python3
+deps =
+ sphinx
+ sphinx-rtd-theme
+ sphinxcontrib-httpdomain
+ recommonmark
+ lfdocs-conf
+
+commands =
+ sphinx-build -W -b html -n -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/html
+ echo "Generated docs available in {toxinidir}/docs/_build/html"
+whitelist_externals = echo
+
+[testenv:docs-linkcheck]
+basepython = python3
+deps = sphinx
+ sphinx-rtd-theme
+ sphinxcontrib-httpdomain
+ recommonmark
+ lfdocs-conf
+commands = sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/linkcheck
+