* fixed bug 59 & Bug 63. Removes superfluss comments in DBusWrapper, removes non...
[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 #include <iostream> //todo: remove me
31 namespace am
32 {
33
34 #define MAX_NS 1000000000L
35
36 static volatile sig_atomic_t gDispatchDone = 1; //this global is used to stop the mainloop
37
38 typedef uint16_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
39 typedef uint16_t sh_pollHandle_t; //!<this is a handle for a filedescriptor to be used with the SocketHandler
40
41 /**
42  * prototype for poll prepared callback
43  */
44 class IAmShPollPrepare
45 {
46 public:
47     virtual void Call(const sh_pollHandle_t handle, void* userData)=0;
48     virtual ~IAmShPollPrepare()
49     {
50     }
51     ;
52 };
53
54 /**
55  * prototype for poll fired callback
56  */
57 class IAmShPollFired
58 {
59 public:
60     virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)=0;
61     virtual ~ IAmShPollFired()
62     {
63     }
64     ;
65 };
66
67 /**
68  * prototype for poll check callback
69  */
70 class IAmShPollCheck
71 {
72 public:
73     virtual bool Call(const sh_pollHandle_t handle, void* userData)=0;
74     virtual ~ IAmShPollCheck()
75     {
76     }
77     ;
78 };
79
80 /**
81  * prototype for dispatch callback
82  */
83 class IAmShPollDispatch
84 {
85 public:
86     virtual bool Call(const sh_pollHandle_t handle, void* userData)=0;
87     virtual ~ IAmShPollDispatch()
88     {
89     }
90     ;
91 };
92
93 /**
94  * prototype for the timer callback
95  */
96 class IAmShTimerCallBack
97 {
98 public:
99     virtual void Call(const sh_timerHandle_t handle, void* userData)=0;
100     virtual ~IAmShTimerCallBack()
101     {
102     }
103     ;
104 };
105
106 /**
107  * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler
108  * to get called on communication of the filedescriptors.\n
109  * More information can be found here : \ref mainl
110  */
111 class CAmSocketHandler
112 {
113 public:
114     template<class TClass> class TAmShPollFired: public IAmShPollFired
115     {
116     private:
117         TClass* mInstance;
118         void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
119
120     public:
121         TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
122                 mInstance(instance), //
123                 mFunction(function) {};
124
125         virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
126         {
127             (*mInstance.*mFunction)(pollfd, handle, userData);
128         };
129     };
130
131     template<class TClass> class TAmShPollCheck: public IAmShPollCheck
132     {
133     private:
134         TClass* mInstance;
135         bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
136
137     public:
138         TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
139                 mInstance(instance), //
140                 mFunction(function) {};
141
142         virtual bool Call(const sh_pollHandle_t handle, void* userData)
143         {
144             return ((*mInstance.*mFunction)(handle, userData));
145         };
146     };
147
148     CAmSocketHandler();
149     ~CAmSocketHandler();
150
151     am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle);
152     am_Error_e removeFDPoll(const sh_pollHandle_t handle);
153     am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events);
154     am_Error_e addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void* userData);
155     am_Error_e removeTimer(const sh_timerHandle_t handle);
156     am_Error_e restartTimer(const sh_timerHandle_t handle);
157     am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec timeouts);
158     am_Error_e stopTimer(const sh_timerHandle_t handle);
159     void start_listenting();
160     void stop_listening();
161     void exit_mainloop();
162     void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
163         {
164             (void) pollfd;
165             (void) handle;
166             (void) userData;
167         };
168     bool checkerCallback(const sh_pollHandle_t handle, void* userData)
169         {
170             (void) handle;
171             (void) userData;
172             return (false);
173         };
174
175     TAmShPollFired<CAmSocketHandler> receiverCallbackT;
176     TAmShPollCheck<CAmSocketHandler> checkerCallbackT;
177
178 private:
179
180     static CAmSocketHandler* mInstance;
181     int mPipe[2];
182
183     struct sh_timer_s //!<struct that holds information of timers
184     {
185         sh_timerHandle_t handle; //!<the handle of the timer
186         timespec countdown; //!<the countdown, this value is decreased every time the timer is up
187         IAmShTimerCallBack* callback; //!<the callbackfunction
188         void * userData; //!<saves a void pointer together with the rest.
189     };
190
191     typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
192
193     struct sh_poll_s //!<struct that holds information about polls
194     {
195         sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
196         IAmShPollPrepare *prepareCB; //!<pointer to preperation callback
197         IAmShPollFired *firedCB; //!<pointer to fired callback
198         IAmShPollCheck *checkCB; //!< pointer to check callback
199         IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback
200         pollfd pollfdValue; //!<the array for polling the filedescriptors
201         void *userData; //!<userdata saved together with the callback.
202     };
203
204     typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
205     typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
206
207     bool fdIsValid(const int fd) const;
208     void timerUp();
209     void timerCorrection();
210     timespec* insertTime(timespec& buffertime);
211
212     /**
213      * compares countdown values
214      * @param a
215      * @param b
216      * @return true if b greater a
217      */
218     inline static bool compareCountdown(const sh_timer_s& a, const sh_timer_s& b)
219     {
220         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));
221     }
222
223     /**
224      * Subtracts b from a
225      * @param a
226      * @param b
227      * @return subtracted value
228      */
229     inline static timespec timespecSub(const timespec& a, const timespec& b)
230     {
231         timespec result;
232
233         if ((a.tv_sec < b.tv_sec) || ((a.tv_sec == b.tv_sec) && (a.tv_nsec <= b.tv_nsec)))
234         {
235             result.tv_sec = result.tv_nsec = 0;
236         }
237         else
238         {
239             result.tv_sec = a.tv_sec - b.tv_sec;
240             if (a.tv_nsec < b.tv_nsec)
241             {
242                 result.tv_nsec = a.tv_nsec + MAX_NS - b.tv_nsec;
243                 result.tv_sec--; /* Borrow a second. */
244             }
245             else
246             {
247                 result.tv_nsec = a.tv_nsec - b.tv_nsec;
248             }
249         }
250         return (result);
251     }
252
253     /**
254      * adds timespec values
255      * @param a
256      * @param b
257      * @return the added values
258      */
259     inline timespec timespecAdd(const timespec& a, const timespec& b)
260     {
261         timespec result;
262         result.tv_sec = a.tv_sec + b.tv_sec;
263         result.tv_nsec = a.tv_nsec + b.tv_nsec;
264         if (result.tv_nsec >= MAX_NS)
265         {
266             result.tv_sec++;
267             result.tv_nsec = result.tv_nsec - MAX_NS;
268         }
269         return (result);
270     }
271
272     /**
273      * comapares timespec values
274      * @param a
275      * @param b
276      * @return
277      */
278     inline int timespecCompare(const timespec& a, const timespec& b)
279     {
280         //less
281         if (a.tv_sec < b.tv_sec)
282             return (-1);
283         //greater
284         else if (a.tv_sec > b.tv_sec)
285             return (1);
286         //less
287         else if (a.tv_nsec < b.tv_nsec)
288             return (-1);
289         //greater
290         else if (a.tv_nsec > b.tv_nsec)
291             return (1);
292         //equal
293         else
294             return (0);
295     }
296
297     /**
298      * functor to return all fired events
299      * @param a
300      * @return
301      */
302     inline static bool eventFired(const pollfd& a)
303     {
304         return (a.revents == 0 ? false : true);
305     }
306
307     /**
308      * functor to help find the items that do not need dispatching
309      * @param a
310      * @return
311      */
312     inline static bool noDispatching(const sh_poll_s& a)
313     {
314         //remove from list of there is no checkCB
315         if (!a.checkCB)
316             return (true);
317         return (!a.checkCB->Call(a.handle, a.userData));
318     }
319
320     /**
321      * checks if dispatching is already finished
322      * @param a
323      * @return
324      */
325     inline static bool dispatchingFinished(const sh_poll_s& a)
326     {
327         //remove from list of there is no dispatchCB
328         if (!a.dispatchCB)
329             return (true);
330         return (!a.dispatchCB->Call(a.handle, a.userData));
331     }
332
333     class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array
334     {
335     private:
336         mListPollfd_t& mArray;
337     public:
338         CAmShCopyPollfd(mListPollfd_t& dest) :
339                 mArray(dest)
340         {
341         }
342         void operator()(const sh_poll_s& row)
343         {
344             pollfd temp = row.pollfdValue;
345             temp.revents = 0;
346             mArray.push_back(temp);
347         }
348     };
349
350     class CAmShCallFire //!< functor to call the firecallbacks
351     {
352     public:
353         CAmShCallFire()
354         {
355         }
356         ;
357         void operator()(sh_poll_s& row)
358         {
359             row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
360         }
361     };
362
363     class CAmShCallPrep //!< functor to call the preparation callbacks
364     {
365     public:
366         CAmShCallPrep()
367         {
368         }
369         ;
370         void operator()(sh_poll_s& row)
371         {
372             if (row.prepareCB)
373                 row.prepareCB->Call(row.handle, row.userData);
374         }
375     };
376
377     class CAmShCallTimer //!<functor to call a timer
378     {
379     public:
380         CAmShCallTimer()
381         {
382         }
383         ;
384         void operator()(sh_timer_s& row)
385         {
386             row.callback->Call(row.handle, row.userData);
387         }
388     };
389
390     class CAmShCountdownUp //!<functor that checks if a timer is up
391     {
392     private:
393         timespec mDiffTime;
394     public:
395         CAmShCountdownUp(const timespec& differenceTime) :
396                 mDiffTime(differenceTime)
397         {
398         }
399         ;
400         bool operator()(const sh_timer_s& row)
401         {
402             timespec sub = timespecSub(row.countdown, mDiffTime);
403             if (sub.tv_nsec == 0 && sub.tv_sec == 0)
404                 return (true);
405             return (false);
406         }
407     };
408
409     class CAmShCountdownZero //!<functor that checks if a timer is zero
410     {
411     public:
412         CAmShCountdownZero()
413         {
414         }
415         ;
416         bool operator()(const sh_timer_s& row)
417         {
418             if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
419                 return (true);
420             return (false);
421         }
422     };
423
424     class CAmShSubstractTime //!<functor to easy substract from each countdown value
425     {
426     private:
427         timespec param;
428     public:
429         CAmShSubstractTime(timespec param) :
430                 param(param)
431         {
432         }
433         inline void operator()(sh_timer_s& t)
434         {
435             t.countdown = timespecSub(t.countdown, param);
436         }
437     };
438
439     mListPollfd_t mfdPollingArray; //!<the polling array for ppoll
440     mListPoll_t mListPoll; //!<list that holds all information for the ppoll
441     std::list<sh_timer_s> mListTimer; //!<list of all timers
442     std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
443     sh_timerHandle_t mLastInsertedHandle; //!<keeps track of the last inserted timer handle
444     sh_pollHandle_t mLastInsertedPollHandle; //!<keeps track of the last inserted poll handle
445     bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated
446     timespec mStartTime; //!<here the actual time is saved for timecorrection
447
448 //    void debugPrintTimerList ()
449 //    {
450 //        std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
451 //        for(;it!=mListActiveTimer.end();++it)
452 //        {
453 //            std::cout<< "Handle " << it->handle << "sec " << it->countdown.tv_sec << "nsec " << it->countdown.tv_nsec<<std::endl;
454 //        }
455 //    }
456 }
457 ;
458
459 /**
460  * template to create the functor for a class
461  */
462 template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
463 {
464 private:
465     TClass* mInstance;
466     void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
467
468 public:
469     TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
470             mInstance(instance), //
471             mFunction(function)
472     {
473     }
474     ;
475
476     virtual void Call(sh_timerHandle_t handle, void* userData)
477     {
478         (*mInstance.*mFunction)(handle, userData);
479     }
480 };
481
482 /**
483  * template for a callback
484  */
485 template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
486 {
487 private:
488     TClass* mInstance;
489     void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
490
491 public:
492     TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
493             mInstance(instance), //
494             mFunction(function)
495     {
496     }
497     ;
498
499     virtual void Call(const sh_timerHandle_t handle, void* userData)
500     {
501         (*mInstance.*mFunction)(handle, userData);
502     }
503     ;
504 };
505
506 /**make private, not public
507  * template for a callback
508  */
509 template<class TClass> class TAmShPollFired: public IAmShPollFired
510 {
511 private:
512     TClass* mInstance;
513     void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
514
515 public:
516     TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
517             mInstance(instance), //
518             mFunction(function)
519     {
520     }
521     ;
522
523     virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
524     {
525         (*mInstance.*mFunction)(pollfd, handle, userData);
526     }
527     ;
528 };
529
530 /**
531  * template for a callback
532  */
533 template<class TClass> class TAmShPollCheck: public IAmShPollCheck
534 {
535 private:
536     TClass* mInstance;
537     bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
538
539 public:
540     TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
541             mInstance(instance), //
542             mFunction(function)
543     {
544     }
545     ;
546
547     virtual bool Call(const sh_pollHandle_t handle, void* userData)
548     {
549         return ((*mInstance.*mFunction)(handle, userData));
550     }
551     ;
552 };
553
554 /**
555  * template for a callback
556  */
557 template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch
558 {
559 private:
560     TClass* mInstance;
561     bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
562
563 public:
564     TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
565             mInstance(instance), //
566             mFunction(function)
567     {
568     }
569     ;
570
571     virtual bool Call(const sh_pollHandle_t handle, void* userData)
572     {
573         return ((*mInstance.*mFunction)(handle, userData));
574     }
575     ;
576 };
577 } /* namespace am */
578 #endif /* SOCKETHANDLER_H_ */