/** * SPDX license identifier: MPL-2.0 * * Copyright (C) 2012, BMW AG * * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 * \author Aleksandar Donchev, aleksander.donchev@partner.bmw.de BMW 2017 * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * \file CAmSocketHandler.h * For further information see http://www.genivi.org/. */ #ifndef SOCKETHANDLER_H_ #define SOCKETHANDLER_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include "audiomanagertypes.h" #ifdef WITH_TIMERFD #include #include #include #include #include #endif namespace am { #define MAX_NS 1000000000L #define MAX_TIMERHANDLE UINT16_MAX #define MAX_POLLHANDLE UINT16_MAX typedef uint16_t sh_pollHandle_t; //! class TAmShPollFired: public IAmShPollFired { private: TClass* mInstance; void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); public: TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) : mInstance(instance), // mFunction(function) {} virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) { (*mInstance.*mFunction)(pollfd, handle, userData); } }; /** * template for a callback */ template class TAmShPollCheck: public IAmShPollCheck { private: TClass* mInstance; bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); public: TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : mInstance(instance), // mFunction(function) {} virtual bool Call(const sh_pollHandle_t handle, void* userData) { return ((*mInstance.*mFunction)(handle, userData)); } }; /** * template for a callback */ template class TAmShPollDispatch: public IAmShPollDispatch { private: TClass* mInstance; bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); public: TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : mInstance(instance), // mFunction(function) {} virtual bool Call(const sh_pollHandle_t handle, void* userData) { return ((*mInstance.*mFunction)(handle, userData)); } }; /** * template to create the functor for a class */ template class TAmShTimerCallBack: public IAmShTimerCallBack { private: TClass* mInstance; void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData); public: TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) : IAmShTimerCallBack(), mInstance(instance), // mFunction(function) {} virtual void Call(sh_timerHandle_t handle, void* userData) { (*mInstance.*mFunction)(handle, userData); } }; /** * template for a callback */ template class TAmShPollPrepare: public IAmShPollPrepare { private: TClass* mInstance; void (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); public: TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : mInstance(instance), // mFunction(function) {} virtual void Call(const sh_pollHandle_t handle, void* userData) { (*mInstance.*mFunction)(handle, userData); } }; /** * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler * to get called on communication of the filedescriptors.\n * More information can be found here : \ref mainl */ class CAmSocketHandler { struct sh_poll_s //! prepareCB; //preperation callback std::function firedCB; //fired callback std::function checkCB; //check callback std::function dispatchCB; //dispatch callback void* userData; sh_poll_s() : isValid(true), handle(0), pollfdValue(), prepareCB(), firedCB(), checkCB(), dispatchCB(), userData(0) {} }; struct sh_timer_s //! callback; //timer callback void* userData; sh_timer_s() : handle(0) #ifdef WITH_TIMERFD , fd(-1) #endif , countdown(), callback(), userData(0) {} }; struct sh_signal_s { sh_pollHandle_t handle; //! callback; void* userData; sh_signal_s() : handle(0), callback(), userData(0) {} }; struct sh_identifier_s { std::set pollHandles; uint16_t limit; uint16_t lastUsedID; sh_identifier_s(const uint16_t pollLimit = UINT16_MAX) : pollHandles(), limit(pollLimit), lastUsedID(0) {} }; typedef std::reverse_iterator rListTimerIter; //! VectorListPollfd_t; //! VectorListPoll_t; //! VectorSignalHandlers_t; //! mListTimer; //! mListActiveTimer; //! mListRemovedTimers; #endif sh_identifier_s mSetSignalhandlerKeys; //!A set of all used signal handler keys VectorSignalHandlers_t mSignalHandlers; bool mRecreatePollfds; //!= MAX_NS) { result.tv_sec++; result.tv_nsec = result.tv_nsec - MAX_NS; } return (result); } /** * comapares timespec values * @param a * @param b * @return */ inline int timespecCompare(const timespec& a, const timespec& b) { //less if (a.tv_sec < b.tv_sec) return (-1); //greater else if (a.tv_sec > b.tv_sec) return (1); //less else if (a.tv_nsec < b.tv_nsec) return (-1); //greater else if (a.tv_nsec > b.tv_nsec) return (1); //equal return (0); } #endif /** * functor to prepare all fire events * @param a * @return */ inline static void prepare(sh_poll_s& row); /** * functor to return all fired events * @param a * @return */ inline static void fire(const sh_poll_s* a); /** * functor to help find the items that do not need dispatching * @param a * @return */ inline static bool noDispatching(const sh_poll_s* a); /** * checks if dispatching is already finished * @param a * @return */ inline static bool dispatchingFinished(const sh_poll_s* a); /** * timer fire callback * @param a * @return */ inline static void callTimer(sh_timer_s& a); /** * next handle id * @param std::set handles * @return handle */ bool nextHandle(sh_identifier_s & handle); am_Error_e getFDPollData(const sh_pollHandle_t handle, sh_poll_s & outPollData); public: CAmSocketHandler(); ~CAmSocketHandler(); /** * install the signal fd */ am_Error_e listenToSignals(const std::vector & listSignals); am_Error_e addFDPoll(const int fd, const short event, std::function prepare, std::function fired, std::function check, std::function dispatch, void* userData, sh_pollHandle_t& handle); am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle); am_Error_e removeFDPoll(const sh_pollHandle_t handle); am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events); am_Error_e addSignalHandler(std::function callback, sh_pollHandle_t& handle, void * userData); am_Error_e removeSignalHandler(const sh_pollHandle_t handle); am_Error_e addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, #ifndef WITH_TIMERFD const bool __attribute__((__unused__)) repeats = false #else const bool repeats = false #endif ); am_Error_e addTimer(const timespec & timeouts, std::function callback, sh_timerHandle_t& handle, void* userData, #ifndef WITH_TIMERFD const bool __attribute__((__unused__)) repeats = false #else const bool repeats = false #endif ); am_Error_e removeTimer(const sh_timerHandle_t handle); am_Error_e restartTimer(const sh_timerHandle_t handle); am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec & timeouts); am_Error_e stopTimer(const sh_timerHandle_t handle); void start_listenting(); void stop_listening(); void exit_mainloop(); bool fatalErrorOccurred(); }; } /* namespace am */ #endif /* SOCKETHANDLER_H_ */