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