* [GAM-49] worked in comments to last patches
[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     CAmSocketHandler();
115     ~CAmSocketHandler();
116
117     am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle);
118     am_Error_e removeFDPoll(const sh_pollHandle_t handle);
119     am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events);
120     am_Error_e addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void* userData);
121     am_Error_e removeTimer(const sh_timerHandle_t handle);
122     am_Error_e restartTimer(const sh_timerHandle_t handle);
123     am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec timeouts);
124     am_Error_e stopTimer(const sh_timerHandle_t handle);
125     void start_listenting();
126     void stop_listening();
127 private:
128     struct sh_timer_s //!<struct that holds information of timers
129     {
130         sh_timerHandle_t handle; //!<the handle of the timer
131         timespec countdown; //!<the countdown, this value is decreased every time the timer is up
132         IAmShTimerCallBack* callback; //!<the callbackfunction
133         void * userData; //!<saves a void pointer together with the rest.
134     };
135
136     typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
137
138     struct sh_poll_s //!<struct that holds information about polls
139     {
140         sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
141         IAmShPollPrepare *prepareCB; //!<pointer to preperation callback
142         IAmShPollFired *firedCB; //!<pointer to fired callback
143         IAmShPollCheck *checkCB; //!< pointer to check callback
144         IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback
145         pollfd pollfdValue; //!<the array for polling the filedescriptors
146         void *userData; //!<userdata saved together with the callback.
147     };
148
149     typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
150     typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
151
152     bool fdIsValid(const int fd) const;
153     void timerUp();
154     void timerCorrection();
155     timespec* insertTime(timespec& buffertime);
156
157     /**
158      * compares countdown values
159      * @param a
160      * @param b
161      * @return true if b greater a
162      */
163     inline static bool compareCountdown(const sh_timer_s& a, const sh_timer_s& b)
164     {
165         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));
166     }
167
168     /**
169      * Subtracts b from a
170      * @param a
171      * @param b
172      * @return subtracted value
173      */
174     inline static timespec timespecSub(const timespec& a, const timespec& b)
175     {
176         timespec result;
177
178         if ((a.tv_sec < b.tv_sec) || ((a.tv_sec == b.tv_sec) && (a.tv_nsec <= b.tv_nsec)))
179         {
180             result.tv_sec = result.tv_nsec = 0;
181         }
182         else
183         {
184             result.tv_sec = a.tv_sec - b.tv_sec;
185             if (a.tv_nsec < b.tv_nsec)
186             {
187                 result.tv_nsec = a.tv_nsec + MAX_NS - b.tv_nsec;
188                 result.tv_sec--; /* Borrow a second. */
189             }
190             else
191             {
192                 result.tv_nsec = a.tv_nsec - b.tv_nsec;
193             }
194         }
195         return (result);
196     }
197
198     /**
199      * adds timespec values
200      * @param a
201      * @param b
202      * @return the added values
203      */
204     inline timespec timespecAdd(const timespec& a, const timespec& b)
205     {
206         timespec result;
207         result.tv_sec = a.tv_sec + b.tv_sec;
208         result.tv_nsec = a.tv_nsec + b.tv_nsec;
209         if (result.tv_nsec >= MAX_NS)
210         {
211             result.tv_sec++;
212             result.tv_nsec = result.tv_nsec - MAX_NS;
213         }
214         return (result);
215     }
216
217     /**
218      * comapares timespec values
219      * @param a
220      * @param b
221      * @return
222      */
223     inline int timespecCompare(const timespec& a, const timespec& b)
224     {
225         //less
226         if (a.tv_sec < b.tv_sec)
227             return (-1);
228         //greater
229         else if (a.tv_sec > b.tv_sec)
230             return (1);
231         //less
232         else if (a.tv_nsec < b.tv_nsec)
233             return (-1);
234         //greater
235         else if (a.tv_nsec > b.tv_nsec)
236             return (1);
237         //equal
238         else
239             return (0);
240     }
241
242     /**
243      * functor to return all fired events
244      * @param a
245      * @return
246      */
247     inline static bool eventFired(const pollfd& a)
248     {
249         return (a.revents == 0 ? false : true);
250     }
251
252     /**
253      * functor to help find the items that do not need dispatching
254      * @param a
255      * @return
256      */
257     inline static bool noDispatching(const sh_poll_s& a)
258     {
259         //remove from list of there is no checkCB
260         if (!a.checkCB)
261             return (true);
262         return (!a.checkCB->Call(a.handle, a.userData));
263     }
264
265     /**
266      * checks if dispatching is already finished
267      * @param a
268      * @return
269      */
270     inline static bool dispatchingFinished(const sh_poll_s& a)
271     {
272         //remove from list of there is no dispatchCB
273         if (!a.dispatchCB)
274             return (true);
275         return (!a.dispatchCB->Call(a.handle, a.userData));
276     }
277
278     class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array
279     {
280     private:
281         mListPollfd_t& mArray;
282     public:
283         CAmShCopyPollfd(mListPollfd_t& dest) :
284                 mArray(dest)
285         {
286         }
287         void operator()(const sh_poll_s& row)
288         {
289             pollfd temp = row.pollfdValue;
290             temp.revents = 0;
291             mArray.push_back(temp);
292         }
293     };
294
295     class CAmShCallFire //!< functor to call the firecallbacks
296     {
297     public:
298         CAmShCallFire()
299         {
300         }
301         ;
302         void operator()(sh_poll_s& row)
303         {
304             row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
305         }
306     };
307
308     class CAmShCallPrep //!< functor to call the preparation callbacks
309     {
310     public:
311         CAmShCallPrep()
312         {
313         }
314         ;
315         void operator()(sh_poll_s& row)
316         {
317             if (row.prepareCB)
318                 row.prepareCB->Call(row.handle, row.userData);
319         }
320     };
321
322     class CAmShCallTimer //!<functor to call a timer
323     {
324     public:
325         CAmShCallTimer()
326         {
327         }
328         ;
329         void operator()(sh_timer_s& row)
330         {
331             row.callback->Call(row.handle, row.userData);
332         }
333     };
334
335     class CAmShCountdownUp //!<functor that checks if a timer is up
336     {
337     private:
338         timespec mDiffTime;
339     public:
340         CAmShCountdownUp(const timespec& differenceTime) :
341                 mDiffTime(differenceTime)
342         {
343         }
344         ;
345         bool operator()(const sh_timer_s& row)
346         {
347             timespec sub = timespecSub(row.countdown, mDiffTime);
348             if (sub.tv_nsec == 0 && sub.tv_sec == 0)
349                 return (true);
350             return (false);
351         }
352     };
353
354     class CAmShCountdownZero //!<functor that checks if a timer is zero
355     {
356     public:
357         CAmShCountdownZero()
358         {
359         }
360         ;
361         bool operator()(const sh_timer_s& row)
362         {
363             if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
364                 return (true);
365             return (false);
366         }
367     };
368
369     class CAmShSubstractTime //!<functor to easy substract from each countdown value
370     {
371     private:
372         timespec param;
373     public:
374         CAmShSubstractTime(timespec param) :
375                 param(param)
376         {
377         }
378         inline void operator()(sh_timer_s& t)
379         {
380             t.countdown = timespecSub(t.countdown, param);
381         }
382     };
383
384     mListPollfd_t mfdPollingArray; //!<the polling array for ppoll
385     mListPoll_t mListPoll; //!<list that holds all information for the ppoll
386     std::list<sh_timer_s> mListTimer; //!<list of all timers
387     std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
388     sh_timerHandle_t mLastInsertedHandle; //!<keeps track of the last inserted timer handle
389     sh_pollHandle_t mLastInsertedPollHandle; //!<keeps track of the last inserted poll handle
390     bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated
391     timespec mStartTime; //!<here the actual time is saved for timecorrection
392
393 //    void debugPrintTimerList ()
394 //    {
395 //        std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
396 //        for(;it!=mListActiveTimer.end();++it)
397 //        {
398 //            std::cout<< "Handle " << it->handle << "sec " << it->countdown.tv_sec << "nsec " << it->countdown.tv_nsec<<std::endl;
399 //        }
400 //    }
401 }
402 ;
403
404 /**
405  * template to create the functor for a class
406  */
407 template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
408 {
409 private:
410     TClass* mInstance;
411     void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
412
413 public:
414     TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
415             mInstance(instance), //
416             mFunction(function)
417     {
418     }
419     ;
420
421     virtual void Call(sh_timerHandle_t handle, void* userData)
422     {
423         (*mInstance.*mFunction)(handle, userData);
424     }
425 };
426
427 /**
428  * template for a callback
429  */
430 template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
431 {
432 private:
433     TClass* mInstance;
434     void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
435
436 public:
437     TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
438             mInstance(instance), //
439             mFunction(function)
440     {
441     }
442     ;
443
444     virtual void Call(const sh_timerHandle_t handle, void* userData)
445     {
446         (*mInstance.*mFunction)(handle, userData);
447     }
448     ;
449 };
450
451 /**make private, not public
452  * template for a callback
453  */
454 template<class TClass> class TAmShPollFired: public IAmShPollFired
455 {
456 private:
457     TClass* mInstance;
458     void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
459
460 public:
461     TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
462             mInstance(instance), //
463             mFunction(function)
464     {
465     }
466     ;
467
468     virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
469     {
470         (*mInstance.*mFunction)(pollfd, handle, userData);
471     }
472     ;
473 };
474
475 /**
476  * template for a callback
477  */
478 template<class TClass> class TAmShPollCheck: public IAmShPollCheck
479 {
480 private:
481     TClass* mInstance;
482     bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
483
484 public:
485     TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
486             mInstance(instance), //
487             mFunction(function)
488     {
489     }
490     ;
491
492     virtual bool Call(const sh_pollHandle_t handle, void* userData)
493     {
494         return ((*mInstance.*mFunction)(handle, userData));
495     }
496     ;
497 };
498
499 /**
500  * template for a callback
501  */
502 template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch
503 {
504 private:
505     TClass* mInstance;
506     bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
507
508 public:
509     TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
510             mInstance(instance), //
511             mFunction(function)
512     {
513     }
514     ;
515
516     virtual bool Call(const sh_pollHandle_t handle, void* userData)
517     {
518         return ((*mInstance.*mFunction)(handle, userData));
519     }
520     ;
521 };
522 } /* namespace am */
523 #endif /* SOCKETHANDLER_H_ */