diff options
Diffstat (limited to 'AudioManagerUtilities/include/CAmSocketHandler.h')
-rw-r--r-- | AudioManagerUtilities/include/CAmSocketHandler.h | 632 |
1 files changed, 320 insertions, 312 deletions
diff --git a/AudioManagerUtilities/include/CAmSocketHandler.h b/AudioManagerUtilities/include/CAmSocketHandler.h index 5c3c5ba..717f792 100644 --- a/AudioManagerUtilities/include/CAmSocketHandler.h +++ b/AudioManagerUtilities/include/CAmSocketHandler.h @@ -4,6 +4,7 @@ * 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 @@ -17,7 +18,6 @@ #ifndef SOCKETHANDLER_H_ #define SOCKETHANDLER_H_ -#include "audiomanagertypes.h" #include <sys/socket.h> #include <stdint.h> #include <sys/poll.h> @@ -25,190 +25,309 @@ #include <map> #include <set> #include <signal.h> +#include <vector> +#include <functional> +#include <sys/signalfd.h> +#include <audiomanagerconfig.h> +#include "audiomanagertypes.h" + +#ifdef WITH_TIMERFD + +#include <stdio.h> +#include <string> +#include <stdexcept> +#include <unistd.h> +#include <fcntl.h> + +#endif namespace am { #define MAX_NS 1000000000L -#define MAX_TIMERHANDLE INT16_MAX -#define MAX_POLLHANDLE INT16_MAX +#define MAX_TIMERHANDLE UINT16_MAX +#define MAX_POLLHANDLE UINT16_MAX -typedef uint16_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler typedef uint16_t sh_pollHandle_t; //!<this is a handle for a filedescriptor to be used with the SocketHandler +typedef sh_pollHandle_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler /** - * prototype for poll prepared callback - */ + * prototype for poll prepared callback + */ class IAmShPollPrepare { public: virtual void Call(const sh_pollHandle_t handle, void* userData) = 0; - virtual ~IAmShPollPrepare() {}; + virtual ~IAmShPollPrepare() {} }; /** - * prototype for poll fired callback - */ + * prototype for poll fired callback + */ class IAmShPollFired { public: virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) = 0; - virtual ~ IAmShPollFired() {}; + virtual ~ IAmShPollFired() {} }; /** - * prototype for poll check callback - */ + * prototype for poll check callback + */ class IAmShPollCheck { public: virtual bool Call(const sh_pollHandle_t handle, void* userData) = 0; - virtual ~ IAmShPollCheck() {}; + virtual ~ IAmShPollCheck() {} }; /** - * prototype for dispatch callback - */ + * prototype for dispatch callback + */ class IAmShPollDispatch { public: virtual bool Call(const sh_pollHandle_t handle, void* userData) = 0; - virtual ~ IAmShPollDispatch() {}; + virtual ~ IAmShPollDispatch() {} }; /** - * prototype for the timer callback - */ + * prototype for the timer callback + */ class IAmShTimerCallBack { public: + IAmShTimerCallBack(){}; virtual void Call(const sh_timerHandle_t handle, void* userData) = 0; - virtual ~IAmShTimerCallBack() {}; + virtual ~IAmShTimerCallBack(){} }; -/** - * 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 +/**make private, not public + * template for a callback + */ +template<class TClass> class TAmShPollFired: public IAmShPollFired { +private: + TClass* mInstance; + void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); + public: - template<class TClass> class TAmShPollFired: public IAmShPollFired + 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) { - private: - TClass* mInstance; - void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); + (*mInstance.*mFunction)(pollfd, handle, userData); + } +}; - public: - TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) : - mInstance(instance), // - mFunction(function) {}; +/** + * template for a callback + */ +template<class TClass> class TAmShPollCheck: public IAmShPollCheck +{ +private: + TClass* mInstance; + bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); - virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) - { - (*mInstance.*mFunction)(pollfd, handle, userData); - }; - }; +public: + TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : + mInstance(instance), // + mFunction(function) + {} - template<class TClass> class TAmShPollCheck: public IAmShPollCheck + virtual bool Call(const sh_pollHandle_t handle, void* userData) { - private: - TClass* mInstance; - bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); + return ((*mInstance.*mFunction)(handle, userData)); + } +}; - public: - TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : - mInstance(instance), // - mFunction(function) {}; +/** + * template for a callback + */ +template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch +{ +private: + TClass* mInstance; + bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); - virtual bool Call(const sh_pollHandle_t handle, void* userData) - { - return ((*mInstance.*mFunction)(handle, userData)); - }; - }; +public: + TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : + mInstance(instance), // + mFunction(function) + {} - CAmSocketHandler(); - ~CAmSocketHandler(); + virtual bool Call(const sh_pollHandle_t handle, void* userData) + { + return ((*mInstance.*mFunction)(handle, userData)); + } +}; - 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 addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void* userData); - 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(); - void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) - { - (void) pollfd; - (void) handle; - (void) userData; - }; - bool checkerCallback(const sh_pollHandle_t handle, void* userData) - { - (void) handle; - (void) userData; - return (false); - }; +/** + * template to create the functor for a class + */ +template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack +{ +private: + TClass* mInstance; + void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData); - TAmShPollFired<CAmSocketHandler> receiverCallbackT; - TAmShPollCheck<CAmSocketHandler> checkerCallbackT; +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 TClass> 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 //!<struct that holds information about polls + { + sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor + pollfd pollfdValue; //!<the array for polling the filedescriptors + std::function<void(const sh_pollHandle_t handle, void* userData)> prepareCB; //preperation callback + std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> firedCB; //fired callback + std::function<bool(const sh_pollHandle_t handle, void* userData)> checkCB; //check callback + std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatchCB; //dispatch callback + void* userData; + + sh_poll_s() : + handle(0), pollfdValue(), prepareCB(), firedCB(), checkCB(), dispatchCB(), userData(0) + {} + }; - static CAmSocketHandler* mInstance; - int mPipe[2]; - int mDispatchDone; //this starts / stops the mainloop struct sh_timer_s //!<struct that holds information of timers { - sh_timerHandle_t handle; //!<the handle of the timer + sh_timerHandle_t handle; //!<the handle of the timer +#ifdef WITH_TIMERFD + int fd; + itimerspec countdown; //!<the countdown, this value is decreased every time the timer is up +#else timespec countdown; //!<the countdown, this value is decreased every time the timer is up - IAmShTimerCallBack* callback; //!<the callbackfunction - void * userData; //!<saves a void pointer together with the rest. +#endif + std::function<void(const sh_timerHandle_t handle, void* userData)> callback; //timer callback + void* userData; + sh_timer_s() : + handle(0) +#ifdef WITH_TIMERFD + , fd(0) +#endif + , countdown(), callback(), userData(0) + {} }; - typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists - - struct sh_poll_s //!<struct that holds information about polls + struct sh_signal_s { sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor - IAmShPollPrepare *prepareCB; //!<pointer to preperation callback - IAmShPollFired *firedCB; //!<pointer to fired callback - IAmShPollCheck *checkCB; //!< pointer to check callback - IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback - pollfd pollfdValue; //!<the array for polling the filedescriptors - void *userData; //!<userdata saved together with the callback. + std::function<void(const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData)> callback; + void* userData; + sh_signal_s() : + handle(0), callback(), userData(0) + {} + }; + + struct sh_identifier_s + { + std::set<sh_pollHandle_t> pollHandles; + uint16_t limit; + uint16_t lastUsedID; + sh_identifier_s(const uint16_t pollLimit = UINT16_MAX) : + pollHandles(), limit(pollLimit), lastUsedID(0) + {} }; - typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors - typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks + typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists + typedef std::vector<pollfd> VectorListPollfd_t; //!<vector of filedescriptors + typedef std::vector<sh_poll_s> VectorListPoll_t; //!<list for the callbacks + typedef std::vector<sh_signal_s> VectorSignalHandlers_t; //!<list for the callbacks + + typedef enum:uint8_t + { + NO_ERROR = 0u, // OK + PIPE_ERROR = 1u, // Pipe error + FD_ERROR = 2u, // Invalid file descriptor + SFD_ERROR = 4u, + } internal_codes_e; + typedef uint8_t internal_codes_t; + int mPipe[2]; + bool mDispatchDone; //this starts / stops the mainloop + + sh_identifier_s mSetPollKeys; //!A set of all used ppoll keys + VectorListPoll_t mListPoll; //!<list that holds all information for the ppoll + sh_identifier_s mSetTimerKeys; //!A set of all used timer keys + std::list<sh_timer_s> mListTimer; //!<list of all timers + std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers + sh_identifier_s mSetSignalhandlerKeys; //!A set of all used signal handler keys + VectorSignalHandlers_t mSignalHandlers; + bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated + internal_codes_t mInternalCodes; + sh_pollHandle_t mSignalFdHandle; +#ifndef WITH_TIMERFD + timespec mStartTime; //!<here the actual time is saved for timecorrection +#endif +private: bool fdIsValid(const int fd) const; + + timespec* insertTime(timespec& buffertime); +#ifdef WITH_TIMERFD + am_Error_e createTimeFD(const itimerspec & timeouts, int & fd); + +#else void timerUp(); void timerCorrection(); - timespec* insertTime(timespec& buffertime); /** - * compares countdown values - * @param a - * @param b - * @return true if b greater a - */ + * compares countdown values + * @param a + * @param b + * @return true if b greater a + */ inline static bool compareCountdown(const sh_timer_s& a, const sh_timer_s& b) { return ((a.countdown.tv_sec == b.countdown.tv_sec) ? (a.countdown.tv_nsec < b.countdown.tv_nsec) : (a.countdown.tv_sec < b.countdown.tv_sec)); } /** - * Subtracts b from a - * @param a - * @param b - * @return subtracted value - */ + * Subtracts b from a + * @param a + * @param b + * @return subtracted value + */ inline static timespec timespecSub(const timespec& a, const timespec& b) { timespec result; @@ -234,11 +353,11 @@ private: } /** - * adds timespec values - * @param a - * @param b - * @return the added values - */ + * adds timespec values + * @param a + * @param b + * @return the added values + */ inline timespec timespecAdd(const timespec& a, const timespec& b) { timespec result; @@ -253,234 +372,123 @@ private: } /** - * comapares timespec values - * @param a - * @param b - * @return - */ + * 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); + return (-1); //greater else if (a.tv_sec > b.tv_sec) - return (1); + return (1); //less else if (a.tv_nsec < b.tv_nsec) - return (-1); + return (-1); //greater else if (a.tv_nsec > b.tv_nsec) - return (1); + return (1); //equal return (0); } +#endif /** - * functor to return all fired events - * @param a - * @return - */ - inline static bool eventFired(const pollfd& a) - { - return (a.revents == 0 ? false : true); - } + * functor to prepare all fire events + * @param a + * @return + */ + inline static void prepare(sh_poll_s& row); /** - * functor to help find the items that do not need dispatching - * @param a - * @return - */ - inline static bool noDispatching(const sh_poll_s& a) - { - //remove from list of there is no checkCB - if (!a.checkCB) - return (true); - return (!a.checkCB->Call(a.handle, a.userData)); - } + * functor to return all fired events + * @param a + * @return + */ + inline static void fire(sh_poll_s& a); /** - * checks if dispatching is already finished - * @param a - * @return - */ - inline static bool dispatchingFinished(const sh_poll_s& a) - { - //remove from list of there is no dispatchCB - if (!a.dispatchCB) - return (true); - return (!a.dispatchCB->Call(a.handle, a.userData)); - } - - class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array - { - private: - mListPollfd_t& mArray; - public: - CAmShCopyPollfd(mListPollfd_t& dest) : mArray(dest) {} - void operator()(const sh_poll_s& row); - }; - - class CAmShCallFire //!< functor to call the firecallbacks - { - public: - CAmShCallFire() {}; - void operator()(sh_poll_s& row); - }; - - class CAmShCallPrep //!< functor to call the preparation callbacks - { - public: - CAmShCallPrep() {}; - void operator()(sh_poll_s& row); - }; - - class CAmShCallTimer //!<functor to call a timer - { - public: - CAmShCallTimer() {}; - void operator()(sh_timer_s& row); - }; - - class CAmShCountdownUp //!<functor that checks if a timer is up - { - private: - timespec mDiffTime; - public: - CAmShCountdownUp(const timespec& differenceTime) : mDiffTime(differenceTime) {}; - bool operator()(const sh_timer_s& row); - }; - - class CAmShCountdownZero //!<functor that checks if a timer is zero - { - public: - CAmShCountdownZero() {}; - bool operator()(const sh_timer_s& row); - }; - - class CAmShSubstractTime //!<functor to easy substract from each countdown value - { - private: - timespec param; - public: - CAmShSubstractTime(timespec param) : param(param) {} - inline void operator()(sh_timer_s& t) - { - t.countdown = timespecSub(t.countdown, param); - } - }; - - mListPollfd_t mfdPollingArray; //!<the polling array for ppoll - std::set<sh_pollHandle_t> mSetPollKeys; //!A set of all used ppoll keys - mListPoll_t mListPoll; //!<list that holds all information for the ppoll - std::set<sh_timerHandle_t> mSetTimerKeys; //!A set of all used timer keys - std::list<sh_timer_s> mListTimer; //!<list of all timers - std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers - sh_timerHandle_t mLastInsertedHandle; //!<keeps track of the last inserted timer handle - sh_pollHandle_t mLastInsertedPollHandle; //!<keeps track of the last inserted poll handle - bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated - timespec mStartTime; //!<here the actual time is saved for timecorrection - -}; - -/** - * template to create the functor for a class - */ -template<class TClass> 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)) : - mInstance(instance), // - mFunction(function) {}; + * functor to return all fired events + * @param a + * @return + */ + inline static bool eventFired(const pollfd& a); - virtual void Call(sh_timerHandle_t handle, void* userData) - { - (*mInstance.*mFunction)(handle, userData); - } -}; - -/** - * template for a callback - */ -template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare -{ -private: - TClass* mInstance; - void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData); - -public: - TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) : - mInstance(instance), // - mFunction(function) {}; + /** + * functor to help find the items that do not need dispatching + * @param a + * @return + */ + inline static bool noDispatching(const sh_poll_s& a); - virtual void Call(const sh_timerHandle_t handle, void* userData) - { - (*mInstance.*mFunction)(handle, userData); - }; -}; + /** + * checks if dispatching is already finished + * @param a + * @return + */ + inline static bool dispatchingFinished(const sh_poll_s& a); -/**make private, not public - * template for a callback - */ -template<class TClass> class TAmShPollFired: public IAmShPollFired -{ -private: - TClass* mInstance; - void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); + /** + * 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: - 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 TClass> 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) {}; + CAmSocketHandler(); + ~CAmSocketHandler(); + + /** + * install the signal fd + */ + am_Error_e listenToSignals(const std::vector<uint8_t> & listSignals); + + am_Error_e addFDPoll(const int fd, const short event, std::function<void(const sh_pollHandle_t handle, void* userData)> prepare, std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> fired, + std::function<bool(const sh_pollHandle_t handle, void* userData)> check, std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatch, void* userData, sh_pollHandle_t& handle); - virtual bool Call(const sh_pollHandle_t handle, void* userData) - { - return ((*mInstance.*mFunction)(handle, userData)); - }; + 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<void(const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData)> 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<void(const sh_timerHandle_t handle, void* userData)> 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(); }; -/** - * template for a callback - */ -template<class TClass> 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)); - }; -}; } /* namespace am */ #endif /* SOCKETHANDLER_H_ */ |