4 * Created on: Dec 18, 2011
8 #include "SocketHandler.h"
10 #include <sys/fcntl.h>
11 #include <sys/errno.h>
17 //todo: implement ppoll
19 #include <iostream> //todo remove
23 SocketHandler::SocketHandler()
28 mLastInsertedHandle(1),
35 SocketHandler::~SocketHandler()
40 //todo: maybe have some: give me more time returned?
42 * start the block listening for filedescriptors. This is the mainloop.
44 void SocketHandler::start_listenting()
53 //block until something is on a filedescriptor
54 if((pollStatus=poll(&mListPollfd.front(),mListPollfd.size(),timespec2ms(mTimeout)))==-1)
56 //todo enter DLT message here;
59 if (pollStatus!=0) //only check filedescriptors if there was a change
61 //todo: here could be a timer that makes sure naughty plugins return!
63 //go through the list of fds and check if an event was set...
64 mPollfd_t::iterator iterator=mListPollfd.begin();
65 mPollfd_t::iterator iteratorEnd=mListPollfd.end();
66 for(;iterator!=iteratorEnd;++iterator)
68 //oh yes! then, fire the callback !
69 if(iterator->revents !=0)
71 //check the map for the right callback
72 mMapFdCallback_t::iterator iteratorCB=mMapFdCallback.begin();
73 iteratorCB=mMapFdCallback.find(iterator->fd);
74 if(iteratorCB!=mMapFdCallback.end())
77 iteratorCB->second->Call(iterator->fd,iterator->events);
84 //this was a timer event, we need to take care about the timers
93 void SocketHandler::stop_listening()
99 * Adds a filedescriptor to the polling loop
100 * @param fd this is a valid filedescriptor
101 * @param event the event flags
102 * @param callback the callback that shall be called if the filedescriptor poll succeeded
103 * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid
105 am_Error_e SocketHandler::addFDPoll(const int fd, const short event, TBasicPollCallback*& callback)
107 if (!fdIsValid(fd)) return E_NON_EXISTENT;
111 tempPollfd.events=event;
112 tempPollfd.revents=NULL;
114 //insert the filedescriptor into the poll array
115 mListPollfd.push_back(tempPollfd);
117 //insert the callback into the map
118 mMapFdCallback.insert(std::make_pair(fd,callback));
123 * removes a filedescriptor from the poll loop
124 * @param fd the filedescriptor to be removed
125 * @return E_OK in case of sucess, E_NON_EXISTENT or E_UNKNOWN if the fd in not registered
127 am_Error_e SocketHandler::removeFDPoll(const int fd)
129 mMapFdCallback_t::iterator iterator=mMapFdCallback.begin();
131 //find the filedescriptor
132 iterator=mMapFdCallback.find(fd);
133 if (iterator==mMapFdCallback.end()) return E_NON_EXISTENT;
136 mMapFdCallback.erase(iterator);
138 //also remove from the callBackList
139 mPollfd_t::iterator pollIterator=mListPollfd.begin();
140 for(;pollIterator!=mListPollfd.end();++pollIterator)
142 if (pollIterator->fd==fd)
144 mListPollfd.erase(pollIterator);
152 * adds a timer to the list of timers. The callback will be fired when the timer is up.
153 * This is not a high precise timer, it is very coarse. It is meant to be used for timeouts when waiting
154 * for an answer via a filedescriptor.
155 * One time timer. If you need again a timer, you need to add a new timer in the callback of the old one.
156 * @param timeouts time until the callback is fired
157 * @param callback the callback
158 * @param handle the handle that is created for the timer is returned. Can be used to remove the timer
159 * @return E_OK in case of success
161 am_Error_e SocketHandler::addTimer(const timespec timeouts,TBasicTimerCallback*& callback,timerHandle_t& handle)
163 assert(!((timeouts.tv_sec==0) && (timeouts.tv_nsec==0)));
164 assert(callback!=NULL);
168 //create a new handle for the timer
169 handle=mLastInsertedHandle++; //todo: overflow ruling !
170 timerItem.handle=handle;
171 timerItem.countdown=timeouts;
172 timerItem.timeout=timeouts;
173 timerItem.callback=callback;
175 //add timer to the list
176 mListTimer.push_back(timerItem);
178 //very important: sort the list so that the smallest value is front
179 mListTimer.sort(compareCountdown);
180 mTimeout=mListTimer.front().countdown;
185 * removes a timer from the list of timers
186 * @param handle the handle to the timer
187 * @return E_OK in case of success, E_UNKNOWN if timer was not found.
189 am_Error_e SocketHandler::removeTimer(const timerHandle_t handle)
193 //go through the list and remove the timer with the handle
194 std::list<timer_s>::iterator it=mListTimer.begin();
195 for(;it!=mListTimer.end();++it)
197 if(it->handle==handle)
199 it=mListTimer.erase(it);
200 if (!mListTimer.empty())
202 mTimeout=mListTimer.front().countdown;
216 * checks if a filedescriptor is valid
217 * @param fd the filedescriptor
218 * @return true if the fd is valid
220 bool SocketHandler::fdIsValid(const int fd) const
222 return (fcntl(fd, F_GETFL) != -1 || errno != EBADF);
226 * whenever a timer is up, this function needs to be called.
227 * Removes the fired timer, calls the callback and resets mTimeout
229 void SocketHandler::timerUp()
231 //first fire the event
232 mListTimer.front().callback->Call(mListTimer.front().handle);
234 //then remove the first timer, the one who fired
235 mListTimer.pop_front();
236 if(!mListTimer.empty())
238 //substract the old value from all timers in the list
239 std::for_each(mListTimer.begin(),mListTimer.end(),SubstractTime(mTimeout));
240 mTimeout=mListTimer.front().countdown;
252 void SocketHandler::initTimer()
254 if(!mListTimer.empty())
256 mTimeout=mListTimer.front().countdown;
266 * convert timespec to milliseconds
267 * @param time time in timespec
268 * @return time in milliseconds
270 inline int SocketHandler::timespec2ms(const timespec& time)
272 return (time.tv_nsec==-1 && time.tv_sec==-1) ? -1 : time.tv_sec*1000 + time.tv_nsec/1000000;
276 * functor to easy substract from each countdown
277 * @param t value to substract from
279 void SocketHandler::SubstractTime::operator()(timer_s& t) const
282 if((val=t.countdown.tv_nsec-param.tv_nsec)<0)
284 t.countdown.tv_nsec=1000000000 + val;
285 t.countdown.tv_sec--;
289 t.countdown.tv_nsec=val;
291 (t.countdown.tv_sec-param.tv_sec)<0 ? 0 : (t.countdown.tv_sec-=param.tv_sec);