* [GAM-46] improvements on CAmSockthandler.
[profile/ivi/genivi/genivi-audio-manager.git] / include / shared / CAmSocketHandler.h
1 /**
2  *  Copyright (C) 2012, BMW AG
3  *
4  *  \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012
5  *
6  *  \copyright
7  *  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction,
8  *  including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9  *  subject to the following conditions:
10  *  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12  *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
13  *  THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14  *
15  *  \file CAmSocketHandler.h
16  *  For further information see http://www.genivi.org/.
17  */
18
19 #ifndef SOCKETHANDLER_H_
20 #define SOCKETHANDLER_H_
21
22 #include "audiomanagertypes.h"
23 #include <sys/socket.h>
24 #include <stdint.h>
25 #include <sys/poll.h>
26 #include <list>
27 #include <map>
28 #include <signal.h>
29
30 namespace am
31 {
32
33 static volatile sig_atomic_t gDispatchDone = 0; //this global is used to stop the mainloop
34
35 typedef uint16_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
36 typedef uint16_t sh_pollHandle_t; //!<this is a handle for a filedescriptor to be used with the SocketHandler
37
38 /**
39  * prototype for poll prepared callback
40  */
41 class IAmShPollPrepare
42 {
43 public:
44     virtual void Call(const sh_pollHandle_t handle, void* userData)=0;
45     virtual ~IAmShPollPrepare(){};
46 };
47
48 /**
49  * prototype for poll fired callback
50  */
51 class IAmShPollFired
52 {
53 public:
54     virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)=0;
55     virtual ~ IAmShPollFired(){};
56 };
57
58 /**
59  * prototype for poll check callback
60  */
61 class IAmShPollCheck
62 {
63 public:
64     virtual bool Call(const sh_pollHandle_t handle, void* userData)=0;
65     virtual ~ IAmShPollCheck(){};
66 };
67
68 /**
69  * prototype for dispatch callback
70  */
71 class IAmShPollDispatch
72 {
73 public:
74     virtual bool Call(const sh_pollHandle_t handle, void* userData)=0;
75     virtual ~ IAmShPollDispatch(){};
76 };
77
78 /**
79  * prototype for the timer callback
80  */
81 class IAmShTimerCallBack
82 {
83 public:
84     virtual void Call(const sh_timerHandle_t handle, void* userData)=0;
85     virtual ~IAmShTimerCallBack(){};
86 };
87
88 /**
89  * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler
90  * to get called on communication of the filedescriptors.\n
91  * More information can be found here : \ref mainl
92  */
93 class CAmSocketHandler
94 {
95 public:
96     CAmSocketHandler();
97     ~CAmSocketHandler();
98
99     am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle);
100     am_Error_e removeFDPoll(const sh_pollHandle_t handle);
101     am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events);
102     am_Error_e addTimer(const timespec timeouts, IAmShTimerCallBack*& callback, sh_timerHandle_t& handle, void* userData);
103     am_Error_e removeTimer(const sh_timerHandle_t handle);
104     am_Error_e restartTimer(const sh_timerHandle_t handle, const timespec timeouts);
105     am_Error_e stopTimer(const sh_timerHandle_t handle);
106     void start_listenting();
107     void stop_listening();
108 private:
109     struct sh_timer_s //!<struct that holds information of timers
110     {
111         sh_timerHandle_t handle; //!<the handle of the timer
112         timespec countdown; //!<the countdown, this value is decreased every time the timer is up
113         timespec timeout; //!<the original timer value
114         IAmShTimerCallBack* callback; //!<the callbackfunction
115         void * userData; //!<saves a void pointer together with the rest.
116     };
117
118     typedef std::reverse_iterator<sh_timer_s> rListTimerIter;
119
120     class CAmShSubstractTime //!<functor to easy substract from each countdown value
121     {
122     private:
123         timespec param;
124     public:
125         CAmShSubstractTime(timespec param) :
126                 param(param){}
127         inline void operator()(sh_timer_s& t) const;
128     };
129
130     struct sh_poll_s //!<struct that holds information about polls
131     {
132         sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
133         IAmShPollPrepare *prepareCB;
134         IAmShPollFired *firedCB;
135         IAmShPollCheck *checkCB;
136         IAmShPollDispatch *dispatchCB;
137         pollfd pollfdValue; //!<the array for polling the filedescriptors
138         void *userData; //!<userdata saved together with the callback.
139     };
140
141     typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
142     typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
143
144     class CAmShCopyPollfd
145     {
146     private:
147         mListPollfd_t& mArray;
148     public:
149         CAmShCopyPollfd(mListPollfd_t& dest) :
150                 mArray(dest){}
151         void operator()(const sh_poll_s& row)
152         {
153             pollfd temp = row.pollfdValue;
154             temp.revents = 0;
155             mArray.push_back(temp);
156         }
157     };
158
159     class CAmShMatchingFd
160     {
161     private:
162         int mFD, mEventFlag;
163     public:
164         CAmShMatchingFd(int fd, int eventFlag) :
165                 mFD(fd), //
166                 mEventFlag(eventFlag)
167         { }
168         bool operator()(const sh_poll_s& a)
169         {
170             return (((a.pollfdValue.fd == mFD) && (a.pollfdValue.events == mEventFlag)) ? true : false);
171         }
172     };
173
174     class CAmShCallFire
175     {
176     public:
177         CAmShCallFire(){};
178         void operator()(sh_poll_s& row)
179         {
180             row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
181         }
182     };
183
184     class CAmShCallPrep
185     {
186     public:
187         CAmShCallPrep(){};
188         void operator()(sh_poll_s& row)
189         {
190             if (row.prepareCB)
191                 row.prepareCB->Call(row.handle, row.userData);
192         }
193     };
194
195     class CAmShCallTimer
196     {
197     public:
198         CAmShCallTimer(){};
199         void operator()(sh_timer_s& row)
200         {
201             row.callback->Call(row.handle, row.userData);
202         }
203     };
204
205     class CAmShCountdownUp
206     {
207     public:
208         CAmShCountdownUp(){};
209         bool operator()(sh_timer_s& row)
210         {
211             if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
212                 return (true);
213             return (false);
214         }
215     };
216
217     class CAmShCountdownSame
218     {
219     private:
220         sh_timer_s mCompareValue;
221     public:
222         CAmShCountdownSame(sh_timer_s& a) :
223                 mCompareValue(a)
224         {}
225         bool operator()(const sh_timer_s& b)
226         {
227             return ((mCompareValue.countdown.tv_sec == b.countdown.tv_sec) && (mCompareValue.countdown.tv_nsec == b.countdown.tv_nsec) ? true : false);
228         }
229     };
230
231     bool fdIsValid(const int fd) const;
232     void initTimer();
233     void timerUp();
234     void timerCorrection();
235     int timespec2ms(const timespec& time);
236     timespec* insertTime(timespec& buffertime);
237
238     static bool compareCountdown(const sh_timer_s& a, const sh_timer_s& b)
239     {
240         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));
241     }
242
243     /**
244      * Subtracts b from a
245      * @param a
246      * @param b
247      * @return subtracted value
248      */
249     static timespec timespecSub(const timespec& a, const timespec& b)
250     {
251         timespec result;
252
253         if ((a.tv_sec < b.tv_sec) || ((a.tv_sec == b.tv_sec) && (a.tv_nsec <= b.tv_nsec)))
254         {
255             result.tv_sec = result.tv_nsec = 0;
256         }
257         else
258         {
259             result.tv_sec = a.tv_sec - b.tv_sec;
260             if (a.tv_nsec < b.tv_nsec)
261             {
262                 result.tv_nsec = a.tv_nsec + 1000000000L - b.tv_nsec;
263                 result.tv_sec--; /* Borrow a second. */
264             }
265             else
266             {
267                 result.tv_nsec = a.tv_nsec - b.tv_nsec;
268             }
269         }
270         return (result);
271     }
272
273     static timespec timespecAdd(const timespec& a, const timespec b)
274     {
275         timespec result;
276         result.tv_sec = a.tv_sec + b.tv_sec;
277         result.tv_nsec = a.tv_nsec + b.tv_nsec;
278         if (result.tv_nsec >= 1000000000L)
279         {
280             result.tv_sec++;
281             result.tv_nsec = result.tv_nsec - 1000000000L;
282         }
283         return (result);
284     }
285
286     static int timespecCompare(const timespec& a, const timespec& b)
287     {
288         //less
289         if (a.tv_sec < b.tv_sec)
290             return (-1);
291         //greater
292         else if (a.tv_sec > b.tv_sec)
293             return (1);
294         //less
295         else if (a.tv_nsec < b.tv_nsec)
296             return (-1);
297         //greater
298         else if (a.tv_nsec > b.tv_nsec)
299             return (1);
300         //equal
301         else
302             return (0);
303     }
304
305     inline static bool eventFired(const pollfd& a)
306     {
307         return (a.revents == 0 ? false : true);
308     }
309
310     inline static bool noDispatching(const sh_poll_s& a)
311     {
312         //remove from list of there is no checkCB
313         if (!a.checkCB)
314             return (true);
315         return (!a.checkCB->Call(a.handle, a.userData));
316     }
317
318     inline static bool dispatchingFinished(const sh_poll_s& a)
319     {
320         //remove from list of there is no dispatchCB
321         if (!a.dispatchCB)
322             return (true);
323         return (!a.dispatchCB->Call(a.handle, a.userData));
324     }
325
326     mListPollfd_t mfdPollingArray;
327     mListPoll_t mListPoll;
328     std::list<sh_timer_s> mListTimer; //!<list of all timers
329     std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
330     sh_timerHandle_t mLastInsertedHandle;
331     sh_pollHandle_t mLastInsertedPollHandle;
332     bool mRecreatePollfds;
333     timespec mStartTime;
334 }
335 ;
336
337 /**
338  * template to create the functor for a class
339  */
340 template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
341 {
342 private:
343     TClass* mInstance;
344     void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
345
346 public:
347     TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
348             mInstance(instance), //
349             mFunction(function){};
350
351     virtual void Call(sh_timerHandle_t handle, void* userData)
352     {
353         (*mInstance.*mFunction)(handle, userData);
354     }
355 };
356
357 /**
358  * template for a callback
359  */
360 template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
361 {
362 private:
363     TClass* mInstance;
364     void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
365
366 public:
367     TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
368             mInstance(instance), //
369             mFunction(function){};
370
371     virtual void Call(const sh_timerHandle_t handle, void* userData)
372     {
373         (*mInstance.*mFunction)(handle, userData);
374     };
375 };
376
377 /**
378  * template for a callback
379  */
380 template<class TClass> class TAmShPollFired: public IAmShPollFired
381 {
382 private:
383     TClass* mInstance;
384     void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
385
386 public:
387     TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
388             mInstance(instance), //
389             mFunction(function){};
390
391     virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
392     {
393         (*mInstance.*mFunction)(pollfd, handle, userData);
394     };
395 };
396
397 /**
398  * template for a callback
399  */
400 template<class TClass> class TAmShPollCheck: public IAmShPollCheck
401 {
402 private:
403     TClass* mInstance;
404     bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
405
406 public:
407     TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
408             mInstance(instance), //
409             mFunction(function){};
410
411     virtual bool Call(const sh_pollHandle_t handle, void* userData)
412     {
413         return ((*mInstance.*mFunction)(handle, userData));
414     };
415 };
416
417 /**
418  * template for a callback
419  */
420 template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch
421 {
422 private:
423     TClass* mInstance;
424     bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
425
426 public:
427     TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
428             mInstance(instance), //
429             mFunction(function){};
430
431     virtual bool Call(const sh_pollHandle_t handle, void* userData)
432     {
433         return ((*mInstance.*mFunction)(handle, userData));
434     };
435 };
436 } /* namespace am */
437 #endif /* SOCKETHANDLER_H_ */