AudioManager  7.6.6
Native Application Runtime Environment
CAmSocketHandler.cpp
Go to the documentation of this file.
1 
25 #include <cassert>
26 #include <sys/fcntl.h>
27 #include <sys/errno.h>
28 #include <sys/poll.h>
29 #include <time.h>
30 #include <algorithm>
31 #include <features.h>
32 #include <csignal>
33 #include <unistd.h>
34 
35 #include "CAmDltWrapper.h"
36 #include "CAmSocketHandler.h"
37 
38 #ifdef WITH_TIMERFD
39 #include <sys/timerfd.h>
40 #endif
41 
42 namespace am
43 {
44 
46  mPipe(), //
47  mDispatchDone(true), //
48  mSetPollKeys(MAX_POLLHANDLE), //
49  mListPoll(), //
50  mSetTimerKeys(MAX_TIMERHANDLE),
51  mListTimer(), //
52  mListActiveTimer(), //
53  mSetSignalhandlerKeys(MAX_POLLHANDLE), //
54  mSignalHandlers(), //
55  mRecreatePollfds(true),
56  mInternalCodes(internal_codes_e::NO_ERROR),
57  mSignalFdHandle(0)
58 #ifndef WITH_TIMERFD
59 ,mStartTime() //
60 #endif
61 {
62  if (pipe(mPipe) == -1)
63  {
64  mInternalCodes = internal_codes_e::PIPE_ERROR;
65  logError("Sockethandler could not create pipe!");
66  }
67 
68  //add the pipe to the poll - nothing needs to be processed here we just need the pipe to trigger the ppoll
69  short event = 0;
70  sh_pollHandle_t handle;
71  event |= POLLIN;
72  if (addFDPoll(mPipe[0], event, NULL,
73  [](const pollfd, const sh_pollHandle_t, void*){},
74  [](const sh_pollHandle_t, void*) { return (false); },
75  NULL, NULL, handle) != E_OK)
76  {
77  mInternalCodes |= internal_codes_e::FD_ERROR;
78  }
79 }
80 
82 {
83  for (auto it : mListPoll)
84  {
85  close(it.pollfdValue.fd);
86  }
87  close(mPipe[0]);
88  close(mPipe[1]);
89 }
90 
91 //todo: maybe have some: give me more time returned?
96 {
97  mDispatchDone = false;
98  int16_t pollStatus;
99 
100 #ifndef WITH_TIMERFD
101  clock_gettime(CLOCK_MONOTONIC, &mStartTime);
102 #endif
103  timespec buffertime;
104 
105  VectorListPoll_t cloneListPoll;
106  VectorListPoll_t::iterator listmPollIt;
107  VectorListPollfd_t fdPollingArray;
108 
109  auto preparePollfd = [&](const sh_poll_s& row)
110  {
111  CAmSocketHandler::prepare((sh_poll_s&)row);
112  pollfd temp = row.pollfdValue;
113  temp.revents = 0;
114  fdPollingArray.push_back(temp);
115  };
116 
117  while (!mDispatchDone)
118  {
119  if (mRecreatePollfds)
120  {
121  fdPollingArray.clear();
122  //freeze mListPoll by copying it - otherwise we get problems when we want to manipulate it during the next lines
123  cloneListPoll = mListPoll;
124  //there was a change in the setup, so we need to recreate the fdarray from the list
125  std::for_each(cloneListPoll.begin(), cloneListPoll.end(), preparePollfd);
126  mRecreatePollfds = false;
127  }
128  else
129  {
130  //first we go through the registered filedescriptors and check if someone needs preparation:
131  std::for_each(cloneListPoll.begin(), cloneListPoll.end(), CAmSocketHandler::prepare);
132  }
133 
134 #ifndef WITH_TIMERFD
135  timerCorrection();
136 #endif
137  //block until something is on a filedescriptor
138 
139  if ((pollStatus = ppoll(&fdPollingArray[0], fdPollingArray.size(), insertTime(buffertime), NULL)) < 0)
140  {
141  if (errno == EINTR)
142  {
143  //a signal was received, that means it's time to go...
144  pollStatus = 0;
145  }
146  else
147  {
148  logError("SocketHandler::start_listenting ppoll returned with error", errno);
149  throw std::runtime_error(std::string("SocketHandler::start_listenting ppoll returned with error."));
150  }
151  }
152 
153  if (pollStatus != 0) //only check filedescriptors if there was a change
154  {
155  std::list<sh_poll_s> listPoll;
156  //todo: here could be a timer that makes sure naughty plugins return!
157  //stage 0+1, call firedCB
158  listmPollIt = cloneListPoll.begin();
159  for (auto it : fdPollingArray)
160  {
161  if (CAmSocketHandler::eventFired(it))
162  {
163  listmPollIt->pollfdValue.revents = it.revents;
164  listPoll.push_back(*listmPollIt);
165  CAmSocketHandler::fire(*listmPollIt);
166  }
167  else
168  {
169  listmPollIt->pollfdValue.revents = 0;
170  }
171  listmPollIt++;
172  }
173 
174  //stage 2, lets ask around if some dispatching is necessary, the ones who need stay on the list
175  listPoll.remove_if(CAmSocketHandler::noDispatching);
176 
177  //stage 3, the ones left need to dispatch, we do this as long as there is something to dispatch..
178  do
179  {
180  listPoll.remove_if(CAmSocketHandler::dispatchingFinished);
181  } while (!listPoll.empty());
182 
183  }
184 #ifndef WITH_TIMERFD
185  else //Timerevent
186  {
187  //this was a timer event, we need to take care about the timers
188  //find out the timedifference to starttime
189  timerUp();
190  }
191 #endif
192  }
193 }
194 
199 {
200  mDispatchDone = true;
201 #ifndef WITH_TIMERFD
202  //this is for all running timers only - we need to handle the additional offset here
203  if (!mListActiveTimer.empty())
204  {
205  timespec currentTime, correctionTime;
206  clock_gettime(CLOCK_MONOTONIC, &currentTime);
207  correctionTime = timespecSub(currentTime, mStartTime);
208  std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), [&correctionTime](sh_timer_s& t)
209  { t.countdown = timespecSub(t.countdown, correctionTime);});
210  }
211 #endif
212 }
213 
215 {
216  //end the while loop
217  stop_listening();
218 
219  //fire the ending filedescriptor
220  int p(1);
221  ssize_t result = write(mPipe[1], &p, sizeof(p));
222 }
223 
225 {
226  return ((mInternalCodes&internal_codes_e::PIPE_ERROR)>0)||((mInternalCodes&internal_codes_e::FD_ERROR)>0);
227 }
228 
229 am_Error_e CAmSocketHandler::getFDPollData(const sh_pollHandle_t handle, sh_poll_s & outPollData)
230 {
231  VectorListPoll_t::iterator iterator = mListPoll.begin();
232  for (; iterator != mListPoll.end(); ++iterator)
233  {
234  if (iterator->handle == handle)
235  {
236  outPollData = *iterator;
237  return (E_OK);
238  }
239  }
240  return (E_UNKNOWN);
241 }
242 
247 am_Error_e CAmSocketHandler::listenToSignals(const std::vector<uint8_t> & listSignals)
248 {
249  int fdErr;
250  uint8_t addedSignals = 0;
251  sigset_t sigset;
252 
253  if(0==listSignals.size())
254  {
255  logWarning("Empty signal list!");
256  return (E_NOT_POSSIBLE);
257  }
258 
259  /* Create a sigset of all the signals that we're interested in */
260  fdErr = sigemptyset(&sigset);
261  if (fdErr != 0)
262  {
263  logError("Could not create sigset!");
264  return (E_NOT_POSSIBLE);
265  }
266 
267  for(uint8_t itSignal : listSignals)
268  {
269  fdErr = sigaddset(&sigset, itSignal);
270  if (fdErr != 0)
271  logWarning("Could not add", itSignal);
272  else
273  addedSignals++;
274  }
275 
276  if(0==addedSignals)
277  {
278  logWarning("None of the signals were added!");
279  return (E_NOT_POSSIBLE);
280  }
281 
282  /* We must block the signals in order for signalfd to receive them */
283  fdErr = sigprocmask(SIG_BLOCK, &sigset, NULL);
284  if (fdErr != 0)
285  {
286  logError("Could not block signals! They must be blocked in order to receive them!");
287  return (E_NOT_POSSIBLE);
288  }
289 
290  int signalHandlerFd;
291  if(mSignalFdHandle)
292  {
293  sh_poll_s sgPollData;
294  if(E_OK!=getFDPollData(mSignalFdHandle, sgPollData))
295  {
296  removeFDPoll(mSignalFdHandle);
297  mSignalFdHandle = 0;
298  }
299  else
300  {
301  int signalHandlerFd = signalfd(sgPollData.pollfdValue.fd, &sigset, 0);
302  if (signalHandlerFd == -1)
303  {
304  logError("Could not update signal fd!");
305  return (E_NOT_POSSIBLE);
306  }
307  return E_OK;
308  }
309  }
310 
311  if(0==mSignalFdHandle)
312  {
313  /* Create the signalfd */
314  signalHandlerFd = signalfd(-1, &sigset, 0);
315  if (signalHandlerFd == -1)
316  {
317  logError("Could not open signal fd!");
318  return (E_NOT_POSSIBLE);
319  }
320 
321  auto actionPoll = [this](const pollfd pollfd, const sh_pollHandle_t, void*)
322  {
323  const VectorSignalHandlers_t & signalHandlers = mSignalHandlers;
324  /* We have a valid signal, read the info from the fd */
325  struct signalfd_siginfo info;
326  ssize_t bytes = read(pollfd.fd, &info, sizeof(info));
327  assert(bytes == sizeof(info));
328 
329  /* Notify all listeners */
330  for(auto it: signalHandlers)
331  it.callback(it.handle, info, it.userData);
332  };
333  /* We're going to add the signal fd through addFDPoll. At this point we don't have any signal listeners. */
334  am_Error_e shFdError = addFDPoll(signalHandlerFd, POLLIN | POLLERR | POLLHUP, NULL, actionPoll, [](const sh_pollHandle_t, void*)
335  { return (false);}, NULL, NULL, mSignalFdHandle);
336  return shFdError;
337  }
338 }
339 
353 am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, std::function<void(const sh_pollHandle_t handle, void* userData)> prepare,
354  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,
355  std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatch, void* userData, sh_pollHandle_t& handle)
356 {
357  if (!fdIsValid(fd))
358  return (E_NON_EXISTENT);
359 
360  //create a new handle for the poll
361  if (!nextHandle(mSetPollKeys))
362  {
363  logError("Could not create new polls, too many open!");
364  return (E_NOT_POSSIBLE);
365  }
366 
367  sh_poll_s pollData;
368  pollData.pollfdValue.fd = fd;
369  pollData.handle = mSetPollKeys.lastUsedID;
370  pollData.pollfdValue.events = event;
371  pollData.pollfdValue.revents = 0;
372  pollData.prepareCB = prepare;
373  pollData.firedCB = fired;
374  pollData.checkCB = check;
375  pollData.dispatchCB = dispatch;
376  pollData.userData = userData;
377  //add new data to the list
378  mListPoll.push_back(pollData);
379 
380  mRecreatePollfds = true;
381 
382  handle = pollData.handle;
383  return (E_OK);
384 
385 }
386 
399 am::am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void *userData, sh_pollHandle_t & handle)
400 {
401 
402  std::function<void(const sh_pollHandle_t handle, void* userData)> prepareCB; //preperation callback
403  std::function<void(const pollfd poll, const sh_pollHandle_t handle, void* userData)> firedCB; //fired callback
404  std::function<bool(const sh_pollHandle_t handle, void* userData)> checkCB; //check callback
405  std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatchCB; //check callback
406 
407  if (prepare)
408  prepareCB = std::bind(&IAmShPollPrepare::Call, prepare, std::placeholders::_1, std::placeholders::_2);
409  if (fired)
410  firedCB = std::bind(&IAmShPollFired::Call, fired, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
411  if (check)
412  checkCB = std::bind(&IAmShPollCheck::Call, check, std::placeholders::_1, std::placeholders::_2);
413  if (dispatch)
414  dispatchCB = std::bind(&IAmShPollDispatch::Call, dispatch, std::placeholders::_1, std::placeholders::_2);
415 
416  return addFDPoll(fd, event, prepareCB, firedCB, checkCB, dispatchCB, userData, handle);
417 }
418 
425 {
426  VectorListPoll_t::iterator iterator = mListPoll.begin();
427 
428  for (; iterator != mListPoll.end(); ++iterator)
429  {
430  if (iterator->handle == handle)
431  {
432  iterator = mListPoll.erase(iterator);
433  mSetPollKeys.pollHandles.erase(handle);
434  mRecreatePollfds = true;
435  return (E_OK);
436  }
437  }
438  return (E_UNKNOWN);
439 }
440 
448 am_Error_e CAmSocketHandler::addSignalHandler(std::function<void(const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData)> callback, sh_pollHandle_t& handle, void * userData)
449 {
450  if (!nextHandle(mSetSignalhandlerKeys))
451  {
452  logError("Could not create new polls, too many open!");
453  return (E_NOT_POSSIBLE);
454  }
455 
456  mSignalHandlers.emplace_back();
457  mSignalHandlers.back().callback = callback;
458  mSignalHandlers.back().handle = mSetSignalhandlerKeys.lastUsedID;
459  mSignalHandlers.back().userData = userData;
460  handle = mSetSignalhandlerKeys.lastUsedID;
461 
462  return E_OK;
463 }
464 
471 {
472  VectorSignalHandlers_t::iterator it(mSignalHandlers.begin());
473  for (; it != mSignalHandlers.end(); ++it)
474  {
475  if (it->handle == handle)
476  {
477  it = mSignalHandlers.erase(it);
478  mSetSignalhandlerKeys.pollHandles.erase(handle);
479  return (E_OK);
480  }
481  }
482  return (E_UNKNOWN);
483 }
484 
497 am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, const bool repeats)
498 {
499  assert(callback!=NULL);
500 
501  std::function<void(const sh_timerHandle_t handle, void* userData)> callbackFunc;
502  callbackFunc = std::bind(&IAmShTimerCallBack::Call, callback, std::placeholders::_1, std::placeholders::_2);
503 
504  return addTimer(timeouts, callbackFunc, handle, userData, repeats);
505 }
506 
507 am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, std::function<void(const sh_timerHandle_t handle, void* userData)> callback, sh_timerHandle_t& handle, void * userData, const bool repeats)
508 {
509  assert(!((timeouts.tv_sec == 0) && (timeouts.tv_nsec == 0)));
510 
511  mListTimer.emplace_back();
512  sh_timer_s & timerItem = mListTimer.back();
513 
514 #ifndef WITH_TIMERFD
515  //create a new handle for the timer
516  if (!nextHandle(mSetTimerKeys))
517  {
518  logError("Could not create new timers, too many open!");
519  mListTimer.pop_back();
520  return (E_NOT_POSSIBLE);
521  }
522  //create a new handle for the timer
523  handle = mSetTimerKeys.lastUsedID;
524 
525  timerItem.countdown = timeouts;
526  timerItem.callback = callback;
527  timerItem.userData = userData;
528 
529  timerItem.handle = handle;
530 
531  //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
532  timespec currentTime;
533  clock_gettime(CLOCK_MONOTONIC, &currentTime);
534  if (!mDispatchDone)//the mainloop is started
535  timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
536  mListTimer.push_back(timerItem);
537  mListActiveTimer.push_back(timerItem);
538  mListActiveTimer.sort(compareCountdown);
539  return (E_OK);
540 
541 #else
542  timerItem.countdown.it_value = timeouts;
543  if (repeats)
544  timerItem.countdown.it_interval = timeouts;
545  else
546  {
547  timespec zero;
548  zero.tv_sec = 0;
549  zero.tv_nsec = 0;
550  timerItem.countdown.it_interval = zero;
551  }
552 
553  timerItem.fd = -1;
554  timerItem.userData = userData;
555  am_Error_e err = createTimeFD(timerItem.countdown, timerItem.fd);
556  if (err != E_OK)
557  {
558  mListTimer.pop_back();
559  return err;
560  }
561 
562  static auto actionPoll = [](const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
563  {
564  uint64_t mExpirations;
565  if (read(pollfd.fd, &mExpirations, sizeof(uint64_t)) == -1)
566  {
567  //error received...try again
568  read(pollfd.fd, &mExpirations, sizeof(uint64_t));
569  }
570  };
571 
572  err = addFDPoll(timerItem.fd, POLLIN, NULL, actionPoll, [callback](const sh_pollHandle_t handle, void* userData)->bool
573  {
574  callback(handle, userData);
575  return false;
576  },
577  NULL, userData, handle);
578  if (E_OK == err)
579  {
580  timerItem.handle = handle;
581  }
582  else
583  {
584  mListTimer.pop_back();
585  }
586  return err;
587 #endif
588 
589 }
590 
597 {
598  assert(handle != 0);
599 
600  //stop the current timer
601 #ifdef WITH_TIMERFD
602  std::list<sh_timer_s>::iterator it = mListTimer.begin();
603  for (; it != mListTimer.end(); ++it)
604  {
605  if (it->handle == handle)
606  break;
607  }
608  if (it == mListTimer.end())
609  return (E_NON_EXISTENT);
610 
611  close(it->fd);
612  mListTimer.erase(it);
613  return removeFDPoll(handle);
614 #else
615  stopTimer(handle);
616  std::list<sh_timer_s>::iterator it(mListTimer.begin());
617  for (; it != mListTimer.end(); ++it)
618  {
619  if (it->handle == handle)
620  {
621  it = mListTimer.erase(it);
622  mSetTimerKeys.pollHandles.erase(handle);
623  return (E_OK);
624  }
625  }
626  return (E_UNKNOWN);
627 #endif
628 }
629 
636 am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const timespec & timeouts)
637 {
638 #ifdef WITH_TIMERFD
639  std::list<sh_timer_s>::iterator it = mListTimer.begin();
640  for (; it != mListTimer.end(); ++it)
641  {
642  if (it->handle == handle)
643  break;
644  }
645  if (it == mListTimer.end())
646  return (E_NON_EXISTENT);
647 
648  if (it->countdown.it_interval.tv_nsec != 0 || it->countdown.it_interval.tv_sec != 0)
649  it->countdown.it_interval = timeouts;
650  it->countdown.it_value = timeouts;
651 
652  if (!fdIsValid(it->fd))
653  {
654  am_Error_e err = createTimeFD(it->countdown, it->fd);
655  if (err != E_OK)
656  return err;
657  }
658  else
659  {
660  if (timerfd_settime(it->fd, 0, &it->countdown, NULL))
661  {
662  logError("Failed to set timer duration");
663  return E_NOT_POSSIBLE;
664  }
665  }
666 #else
667 
668  //update the mList ....
669  sh_timer_s timerItem;
670  std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
671  bool found(false);
672  for (; it != mListTimer.end(); ++it)
673  {
674  if (it->handle == handle)
675  {
676  it->countdown = timeouts;
677  timerItem = *it;
678  found = true;
679  break;
680  }
681  }
682  if (!found)
683  return (E_NON_EXISTENT);
684 
685  found = false;
686 
687  //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
688  timespec currentTime, timeoutsCorrected;
689  currentTime.tv_nsec=timeoutsCorrected.tv_nsec=0;
690  currentTime.tv_sec=timeoutsCorrected.tv_sec=0;
691  clock_gettime(CLOCK_MONOTONIC, &currentTime);
692  if (!mDispatchDone)//the mainloop is started
693  timeoutsCorrected = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
694 
695  for (; activeIt != mListActiveTimer.end(); ++activeIt)
696  {
697  if (activeIt->handle == handle)
698  {
699  activeIt->countdown = timeoutsCorrected;
700  found = true;
701  break;
702  }
703  }
704 
705  if (!found)
706  timerItem.countdown = timeoutsCorrected;
707  mListActiveTimer.push_back(timerItem);
708 
709  mListActiveTimer.sort(compareCountdown);
710 
711 #endif
712  return (E_OK);
713 }
714 
721 {
722 #ifdef WITH_TIMERFD
723  std::list<sh_timer_s>::iterator it = mListTimer.begin();
724  for (; it != mListTimer.end(); ++it)
725  {
726  if (it->handle == handle)
727  break;
728  }
729  if (it == mListTimer.end())
730  return (E_NON_EXISTENT);
731 
732  if (!fdIsValid(it->fd))
733  {
734  am_Error_e err = createTimeFD(it->countdown, it->fd);
735  if (err != E_OK)
736  return err;
737  }
738  else
739  {
740  if (timerfd_settime(it->fd, 0, &it->countdown, NULL))
741  {
742  logError("Failed to set timer duration");
743  return E_NOT_POSSIBLE;
744  }
745  }
746 #else
747 
748  sh_timer_s timerItem;
749  //find the original value
750  std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
751  bool found(false);
752  for (; it != mListTimer.end(); ++it)
753  {
754  if (it->handle == handle)
755  {
756  timerItem = *it;
757  found = true;
758  break;
759  }
760  }
761  if (!found)
762  return (E_NON_EXISTENT);
763 
764  found = false;
765 
766  //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
767  timespec currentTime, timeoutsCorrected;
768  clock_gettime(CLOCK_MONOTONIC, &currentTime);
769  if (!mDispatchDone)//the mainloop is started
770  {
771  timeoutsCorrected = timespecAdd(timerItem.countdown, timespecSub(currentTime, mStartTime));
772  timerItem.countdown = timeoutsCorrected;
773  }
774 
775  for (; activeIt != mListActiveTimer.end(); ++activeIt)
776  {
777  if (activeIt->handle == handle)
778  {
779  activeIt->countdown = timerItem.countdown;
780  found = true;
781  break;
782  }
783  }
784 
785  if (!found)
786  mListActiveTimer.push_back(timerItem);
787 
788  mListActiveTimer.sort(compareCountdown);
789 #endif
790  return (E_OK);
791 }
792 
799 {
800 #ifdef WITH_TIMERFD
801  std::list<sh_timer_s>::iterator it = mListTimer.begin();
802  for (; it != mListTimer.end(); ++it)
803  {
804  if (it->handle == handle)
805  break;
806  }
807  if (it == mListTimer.end())
808  return (E_NON_EXISTENT);
809 
810  itimerspec countdown = it->countdown;
811  countdown.it_value.tv_nsec = 0;
812  countdown.it_value.tv_sec = 0;
813 
814  if (timerfd_settime(it->fd, 0, &countdown, NULL))
815  {
816  logError("Failed to set timer duration");
817  return E_NOT_POSSIBLE;
818  }
819  return (E_OK);
820 #else
821  //go through the list and remove the timer with the handle
822  std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
823  for (; it != mListActiveTimer.end(); ++it)
824  {
825  if (it->handle == handle)
826  {
827  it = mListActiveTimer.erase(it);
828  return (E_OK);
829  }
830  }
831  return (E_NON_EXISTENT);
832 #endif
833 }
834 
842 {
843  VectorListPoll_t::iterator iterator = mListPoll.begin();
844 
845  for (; iterator != mListPoll.end(); ++iterator)
846  {
847  if (iterator->handle == handle)
848  {
849  iterator->pollfdValue.events = events;
850  mRecreatePollfds = true;
851  return (E_OK);
852  }
853  }
854  return (E_UNKNOWN);
855 }
856 
862 bool CAmSocketHandler::fdIsValid(const int fd) const
863 {
864  return (fcntl(fd, F_GETFL) != -1 || errno != EBADF);
865 }
866 
867 #ifndef WITH_TIMERFD
868 
871 void CAmSocketHandler::timerUp()
872 {
873  //find out the timedifference to starttime
874  static timespec currentTime, diffTime;
875  clock_gettime(CLOCK_MONOTONIC, &currentTime);
876  diffTime = timespecSub(currentTime, mStartTime);
877 
878  static auto countdownUp = [&](const sh_timer_s& row)->bool
879  {
880  timespec sub = timespecSub(row.countdown, diffTime);
881  if (sub.tv_nsec == 0 && sub.tv_sec == 0)
882  return (true);
883  return (false);
884  };
885 
886  //now we need to substract the diffTime from all timers and see if they are up
887  std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownUp);
888 
889  //copy all fired timers into a list
890  std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
891 
892  //erase all fired timers
893  std::list<sh_timer_s>::iterator it(overflowIter.base());
894  mListActiveTimer.erase(mListActiveTimer.begin(), it);
895 
896  //call the callbacks for the timers
897  std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer);
898 }
899 
903 void CAmSocketHandler::timerCorrection()
904 {
905  //get the current time and calculate the correction value
906  static timespec currentTime, correctionTime;
907  clock_gettime(CLOCK_MONOTONIC, &currentTime);
908  correctionTime = timespecSub(currentTime, mStartTime);
909  mStartTime = currentTime;
910 
911  static auto countdownZero = [](const sh_timer_s& row)->bool
912  {
913  if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
914  return (true);
915  return (false);
916  };
917 
918  static auto substractTime = [&](sh_timer_s& t)
919  {
920  t.countdown = timespecSub(t.countdown, correctionTime);
921  };
922 
923  if (!mListActiveTimer.empty())
924  {
925 
926  //subtract the correction value from all items in the list
927  std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), substractTime);
928 
929  //find the last occurrence of zero -> timer overflowed
930  std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownZero);
931 
932  //only if a timer overflowed
933  if (overflowIter != mListActiveTimer.rend())
934  {
935  //copy all timers that need to be called to a new list
936  std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
937 
938  //erase all fired timers
939  std::list<sh_timer_s>::iterator it(overflowIter.base());
940  mListActiveTimer.erase(mListActiveTimer.begin(), it);
941 
942  //call the callbacks for the timers
943  std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer);
944  }
945  }
946 }
947 #endif
948 
952 void CAmSocketHandler::prepare(am::CAmSocketHandler::sh_poll_s& row)
953 {
954  if (row.prepareCB)
955  {
956  try
957  {
958  row.prepareCB(row.handle, row.userData);
959  } catch (std::exception& e)
960  {
961  logError("Sockethandler: Exception in Preparecallback,caught", e.what());
962  }
963  }
964 }
965 
969 void CAmSocketHandler::fire(sh_poll_s& a)
970 {
971  try
972  {
973  a.firedCB(a.pollfdValue, a.handle, a.userData);
974  } catch (std::exception& e)
975  {
976  logError("Sockethandler: Exception in Preparecallback,caught", e.what());
977  }
978 }
979 
983 bool CAmSocketHandler::noDispatching(const sh_poll_s& a)
984 {
985  //remove from list of there is no checkCB
986  if (nullptr == a.checkCB)
987  return (true);
988  return (!a.checkCB(a.handle, a.userData));
989 }
990 
994 bool CAmSocketHandler::dispatchingFinished(const sh_poll_s& a)
995 {
996  //remove from list of there is no dispatchCB
997  if (nullptr == a.dispatchCB)
998  return (true);
999  return (!a.dispatchCB(a.handle, a.userData));
1000 }
1001 
1005 bool CAmSocketHandler::eventFired(const pollfd& a)
1006 {
1007  return (a.revents == 0 ? false : true);
1008 }
1009 
1015 inline timespec* CAmSocketHandler::insertTime(timespec& buffertime)
1016 {
1017 #ifndef WITH_TIMERFD
1018  if (!mListActiveTimer.empty())
1019  {
1020  buffertime = mListActiveTimer.front().countdown;
1021  return (&buffertime);
1022  }
1023  else
1024 #endif
1025  {
1026  return (NULL);
1027  }
1028 }
1029 
1030 #ifdef WITH_TIMERFD
1031 am_Error_e CAmSocketHandler::createTimeFD(const itimerspec & timeouts, int & fd)
1032 {
1033  fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
1034  if (fd <= 0)
1035  {
1036  logError("Failed to create timer");
1037  return E_NOT_POSSIBLE;
1038  }
1039 
1040  if (timerfd_settime(fd, 0, &timeouts, NULL))
1041  {
1042  logError("Failed to set timer duration");
1043  return E_NOT_POSSIBLE;
1044  }
1045  return E_OK;
1046 }
1047 #endif
1048 
1049 void CAmSocketHandler::callTimer(sh_timer_s& a)
1050 {
1051  try
1052  {
1053  a.callback(a.handle, a.userData);
1054  } catch (std::exception& e)
1055  {
1056  logError("Sockethandler: Exception in Timercallback,caught", e.what());
1057  }
1058 }
1059 
1060 bool CAmSocketHandler::nextHandle(sh_identifier_s & handle)
1061 {
1062  //create a new handle for the poll
1063  const sh_pollHandle_t lastHandle(handle.lastUsedID);
1064  do
1065  {
1066  ++handle.lastUsedID;
1067  if (handle.lastUsedID == handle.limit)
1068  {
1069  handle.lastUsedID = 1;
1070  }
1071  if (handle.lastUsedID == lastHandle)
1072  {
1073  logError("Could not create new polls, too many open!");
1074  return (false);
1075  }
1076 
1077  } while (handle.pollHandles.find(handle.lastUsedID) != handle.pollHandles.end());
1078 
1079  handle.pollHandles.insert(handle.lastUsedID);
1080 
1081  return (true);
1082 }
1083 
1084 }
1085 
void logWarning(T value, TArgs...args)
logs given values with warninglevel with the default context
A Common-API wrapper class, which loads the common-api runtime and instantiates all necessary objects...
the desired object is non existent
am_Error_e
the errors of the audiomanager.
virtual bool Call(const sh_pollHandle_t handle, void *userData)=0
prototype for poll fired callback
am_Error_e restartTimer(const sh_timerHandle_t handle)
restarts a timer with the original value
virtual bool Call(const sh_pollHandle_t handle, void *userData)=0
uint16_t sh_pollHandle_t
this is a handle for a filedescriptor to be used with the SocketHandler
SPDX license identifier: MPL-2.0.
prototype for poll check callback
am_Error_e removeFDPoll(const sh_pollHandle_t handle)
removes a filedescriptor from the poll loop
prototype for poll prepared callback
am_Error_e removeTimer(const sh_timerHandle_t handle)
removes a timer from the list of timers
am_Error_e stopTimer(const sh_timerHandle_t handle)
stops a timer
virtual void Call(const sh_pollHandle_t handle, void *userData)=0
am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec &timeouts)
restarts a timer and updates with a new interva
#define MAX_TIMERHANDLE
am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events)
updates the eventFlags of a poll
void start_listenting()
start the block listening for filedescriptors.
am_Error_e listenToSignals(const std::vector< uint8_t > &listSignals)
install the signal fd
#define MAX_POLLHANDLE
prototype for dispatch callback
virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void *userData)=0
the desired action is not possible
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)
Adds a filedescriptor to the polling loop.
SPDX license identifier: MPL-2.0.
void logError(T value, TArgs...args)
logs given values with errorlevel with the default context
prototype for the timer callback
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)
Adds a callback for any signals.
am_Error_e removeSignalHandler(const sh_pollHandle_t handle)
removes a signal handler from the list
no error - positive reply
virtual void Call(const sh_timerHandle_t handle, void *userData)=0
sh_pollHandle_t sh_timerHandle_t
this is a handle for a timer to be used with the SocketHandler
void stop_listening()
exits the loop
am_Error_e addTimer(const timespec &timeouts, IAmShTimerCallBack *callback, sh_timerHandle_t &handle, void *userData, const bool __attribute__((__unused__)) repeats=false)