1 /*
2 belle-sip - SIP (RFC3261) library.
3 Copyright (C) 2010 Belledonne Communications SARL
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "belle-sip/belle-sip.h"
20 #include "belle_sip_internal.h"
21 #include "bctoolbox/map.h"
22 #include <limits.h>
23
24 #ifndef _WIN32
25 #include <unistd.h>
26 #include <poll.h>
27 typedef struct pollfd belle_sip_pollfd_t;
28
belle_sip_poll(belle_sip_pollfd_t * pfd,int count,int duration)29 static int belle_sip_poll(belle_sip_pollfd_t *pfd, int count, int duration){
30 int err;
31 err=poll(pfd,count,duration);
32 if (err==-1 && errno!=EINTR)
33 belle_sip_error("poll() error: %s",strerror(errno));
34 return err;
35 }
36
37 /*
38 Poll() based implementation of event loop.
39 */
40
belle_sip_event_to_poll(unsigned int events)41 static int belle_sip_event_to_poll(unsigned int events){
42 int ret=0;
43 if (events & BELLE_SIP_EVENT_READ)
44 ret|=POLLIN;
45 if (events & BELLE_SIP_EVENT_WRITE)
46 ret|=POLLOUT;
47 if (events & BELLE_SIP_EVENT_ERROR)
48 ret|=POLLERR;
49 return ret;
50 }
51
belle_sip_poll_to_event(belle_sip_pollfd_t * pfd)52 static unsigned int belle_sip_poll_to_event(belle_sip_pollfd_t * pfd){
53 unsigned int ret=0;
54 short events=pfd->revents;
55 if (events & POLLIN)
56 ret|=BELLE_SIP_EVENT_READ;
57 if (events & POLLOUT)
58 ret|=BELLE_SIP_EVENT_WRITE;
59 if (events & POLLERR)
60 ret|=BELLE_SIP_EVENT_ERROR;
61 return ret;
62 }
63
belle_sip_source_to_poll(belle_sip_source_t * s,belle_sip_pollfd_t * pfd,int i)64 static void belle_sip_source_to_poll(belle_sip_source_t *s, belle_sip_pollfd_t *pfd, int i){
65 pfd[i].fd=s->fd;
66 pfd[i].events=belle_sip_event_to_poll(s->events);
67 pfd[i].revents=0;
68 s->index=i;
69 }
70
belle_sip_source_get_revents(belle_sip_source_t * s,belle_sip_pollfd_t * pfd)71 static unsigned int belle_sip_source_get_revents(belle_sip_source_t *s,belle_sip_pollfd_t *pfd){
72 return belle_sip_poll_to_event(&pfd[s->index]);
73 }
74
75 #else
76
77
78 #include <malloc.h>
79
80
81 typedef HANDLE belle_sip_pollfd_t;
82
belle_sip_source_to_poll(belle_sip_source_t * s,belle_sip_pollfd_t * pfd,int i)83 static void belle_sip_source_to_poll(belle_sip_source_t *s, belle_sip_pollfd_t *pfd,int i){
84 s->index=i;
85 pfd[i]=s->fd;
86
87 /*special treatments for windows sockets*/
88 if (s->sock!=(belle_sip_socket_t)-1){
89 int err;
90 long events=0;
91
92 if (s->events & BELLE_SIP_EVENT_READ)
93 events|=FD_READ|FD_ACCEPT;
94 if (s->events & BELLE_SIP_EVENT_WRITE)
95 events|=FD_WRITE|FD_CONNECT;
96 if (events!=s->armed_events){
97 s->armed_events=events;
98 err=WSAEventSelect(s->sock,s->fd,events);
99 if (err!=0) belle_sip_error("WSAEventSelect() failed: %s",belle_sip_get_socket_error_string());
100 }
101 }
102 }
103
belle_sip_source_get_revents(belle_sip_source_t * s,belle_sip_pollfd_t * pfd)104 static unsigned int belle_sip_source_get_revents(belle_sip_source_t *s,belle_sip_pollfd_t *pfd){
105 WSANETWORKEVENTS revents={0};
106 int err;
107 unsigned int ret=0;
108
109 if (WaitForSingleObjectEx(s->fd,0,FALSE)==WAIT_OBJECT_0){
110 if (s->sock!=(belle_sip_socket_t)-1){
111 /*special treatments for windows sockets*/
112 err=WSAEnumNetworkEvents(s->sock,s->fd,&revents);
113 if (err!=0){
114 belle_sip_error("WSAEnumNetworkEvents() failed: %s socket=%x",belle_sip_get_socket_error_string(),(unsigned int)s->sock);
115 return 0;
116 }
117 if (revents.lNetworkEvents & FD_READ || revents.lNetworkEvents & FD_ACCEPT){
118 ret|=BELLE_SIP_EVENT_READ;
119 }
120 if (revents.lNetworkEvents & FD_WRITE || revents.lNetworkEvents & FD_CONNECT){
121 ret|=BELLE_SIP_EVENT_WRITE;
122 }
123 s->armed_events=0;
124 }else{
125 ret=BELLE_SIP_EVENT_READ;
126 ResetEvent(s->fd);
127 }
128 }
129 return ret;
130 }
131
belle_sip_poll(belle_sip_pollfd_t * pfd,int count,int duration)132 static int belle_sip_poll(belle_sip_pollfd_t *pfd, int count, int duration){
133 DWORD ret;
134
135 if (count == 0) {
136 belle_sip_sleep(duration);
137 return 0;
138 }
139
140 ret=WaitForMultipleObjectsEx(count,pfd,FALSE,duration,FALSE);
141 if (ret==WAIT_FAILED){
142 belle_sip_error("WaitForMultipleObjectsEx() failed.");
143 return -1;
144 }
145 if (ret==WAIT_TIMEOUT){
146 return 0;
147 }
148 return ret-WAIT_OBJECT_0;
149 }
150
151 #endif
152
belle_sip_source_destroy(belle_sip_source_t * obj)153 static void belle_sip_source_destroy(belle_sip_source_t *obj){
154 if (obj->node.next || obj->node.prev){
155 belle_sip_fatal("Destroying source currently used in main loop !");
156 }
157 belle_sip_source_uninit(obj);
158 }
159
belle_sip_source_init(belle_sip_source_t * s,belle_sip_source_func_t func,void * data,belle_sip_fd_t fd,unsigned int events,unsigned int timeout_value_ms)160 static void belle_sip_source_init(belle_sip_source_t *s, belle_sip_source_func_t func, void *data, belle_sip_fd_t fd, unsigned int events, unsigned int timeout_value_ms){
161 static unsigned long global_id=1;
162 s->node.data=s;
163 if (s->id==0) s->id=global_id++;
164 s->fd=fd;
165 s->events=events;
166 s->timeout=timeout_value_ms;
167 s->data=data;
168 s->notify=func;
169 s->sock=(belle_sip_socket_t)-1;
170 }
171
belle_sip_source_uninit(belle_sip_source_t * obj)172 void belle_sip_source_uninit(belle_sip_source_t *obj){
173 #ifdef _WIN32
174 if (obj->sock!=(belle_sip_socket_t)-1){
175 WSACloseEvent(obj->fd);
176 obj->fd=(WSAEVENT)-1;
177 }
178 #endif
179 obj->fd=(belle_sip_fd_t)-1;
180 obj->sock=(belle_sip_socket_t)-1;
181 /* if (obj->it) {
182 bctbx_iterator_delete(obj->it);
183 obj->it=NULL;
184 }*/
185 }
186
belle_sip_source_set_notify(belle_sip_source_t * s,belle_sip_source_func_t func)187 void belle_sip_source_set_notify(belle_sip_source_t *s, belle_sip_source_func_t func) {
188 s->notify = func;
189 }
190
belle_sip_socket_source_init(belle_sip_source_t * s,belle_sip_source_func_t func,void * data,belle_sip_socket_t sock,unsigned int events,unsigned int timeout_value_ms)191 void belle_sip_socket_source_init(belle_sip_source_t *s, belle_sip_source_func_t func, void *data, belle_sip_socket_t sock, unsigned int events, unsigned int timeout_value_ms){
192 #ifdef _WIN32
193 /*on windows, the fd to poll is not the socket */
194 belle_sip_fd_t fd=(belle_sip_fd_t)-1;
195 if (sock!=(belle_sip_socket_t)-1)
196 fd=WSACreateEvent();
197 else
198 fd=(WSAEVENT)-1;
199 belle_sip_source_init(s,func,data,fd,events,timeout_value_ms);
200
201 #else
202 belle_sip_source_init(s,func,data,sock,events,timeout_value_ms);
203 #endif
204 s->sock=sock;
205 if (sock!=(belle_sip_socket_t)-1)
206 belle_sip_socket_set_nonblocking(sock);
207 }
208
belle_sip_fd_source_init(belle_sip_source_t * s,belle_sip_source_func_t func,void * data,belle_sip_fd_t fd,unsigned int events,unsigned int timeout_value_ms)209 void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t func, void *data, belle_sip_fd_t fd, unsigned int events, unsigned int timeout_value_ms){
210 belle_sip_source_init(s,func,data,fd,events,timeout_value_ms);
211 }
212
213 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_source_t);
214 BELLE_SIP_INSTANCIATE_VPTR(belle_sip_source_t,belle_sip_object_t,belle_sip_source_destroy,NULL,NULL,FALSE);
215
belle_sip_socket_source_new(belle_sip_source_func_t func,void * data,belle_sip_socket_t sock,unsigned int events,unsigned int timeout_value_ms)216 belle_sip_source_t * belle_sip_socket_source_new(belle_sip_source_func_t func, void *data, belle_sip_socket_t sock, unsigned int events, unsigned int timeout_value_ms){
217 belle_sip_source_t *s=belle_sip_object_new(belle_sip_source_t);
218 belle_sip_socket_source_init(s,func,data,sock,events,timeout_value_ms);
219 return s;
220 }
221
belle_sip_fd_source_new(belle_sip_source_func_t func,void * data,belle_sip_fd_t fd,unsigned int events,unsigned int timeout_value_ms)222 belle_sip_source_t * belle_sip_fd_source_new(belle_sip_source_func_t func, void *data, belle_sip_fd_t fd, unsigned int events, unsigned int timeout_value_ms){
223 belle_sip_source_t *s=belle_sip_object_new(belle_sip_source_t);
224 belle_sip_fd_source_init(s,func,data,fd,events,timeout_value_ms);
225 return s;
226 }
227
belle_sip_timeout_source_new(belle_sip_source_func_t func,void * data,unsigned int timeout_value_ms)228 belle_sip_source_t * belle_sip_timeout_source_new(belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms){
229 return belle_sip_socket_source_new(func,data,(belle_sip_socket_t)-1,0,timeout_value_ms);
230 }
231
belle_sip_source_get_id(const belle_sip_source_t * s)232 unsigned long belle_sip_source_get_id(const belle_sip_source_t *s){
233 return s->id;
234 }
belle_sip_source_get_user_data(const belle_sip_source_t * s)235 void * belle_sip_source_get_user_data(const belle_sip_source_t *s) {
236 return s->data;
237 }
belle_sip_source_set_user_data(belle_sip_source_t * s,void * user_data)238 void belle_sip_source_set_user_data(belle_sip_source_t *s, void *user_data) {
239 s->data = user_data;
240 }
belle_sip_source_set_events(belle_sip_source_t * source,int event_mask)241 int belle_sip_source_set_events(belle_sip_source_t* source, int event_mask) {
242 source->events = event_mask;
243 return 0;
244 }
245
belle_sip_source_get_socket(const belle_sip_source_t * source)246 belle_sip_socket_t belle_sip_source_get_socket(const belle_sip_source_t* source) {
247 return source->sock;
248 }
249
250
251 struct belle_sip_main_loop{
252 belle_sip_object_t base;
253 belle_sip_list_t *fd_sources;
254 bctbx_map_t *timer_sources;
255 belle_sip_object_pool_t *pool;
256 int nsources;
257 int run;
258 int in_loop;
259 bctbx_mutex_t timer_sources_mutex;
260 };
261
belle_sip_main_loop_remove_source(belle_sip_main_loop_t * ml,belle_sip_source_t * source)262 void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source){
263 bool_t elem_removed = FALSE;
264 if (source->node.next || source->node.prev || &source->node==ml->fd_sources) {
265 ml->fd_sources=belle_sip_list_remove_link(ml->fd_sources,&source->node);
266 belle_sip_object_unref(source);
267 elem_removed = TRUE;
268 }
269 if (source->it) {
270 bctbx_mutex_lock(&ml->timer_sources_mutex);
271 bctbx_map_erase(ml->timer_sources, source->it);
272 bctbx_iterator_delete(source->it);
273 bctbx_mutex_unlock(&ml->timer_sources_mutex);
274
275 source->it=NULL;
276 belle_sip_object_unref(source);
277 elem_removed = TRUE;
278 }
279 if (elem_removed) {
280 source->cancelled=TRUE;
281 ml->nsources--;
282 if (source->on_remove)
283 source->on_remove(source);
284
285 }
286 }
287
288
belle_sip_main_loop_destroy(belle_sip_main_loop_t * ml)289 static void belle_sip_main_loop_destroy(belle_sip_main_loop_t *ml){
290 while (ml->fd_sources){
291 belle_sip_main_loop_remove_source(ml,(belle_sip_source_t*)ml->fd_sources->data);
292 }
293 if (belle_sip_object_pool_cleanable(ml->pool)){
294 belle_sip_object_unref(ml->pool);
295 }
296 bctbx_mmap_ullong_delete(ml->timer_sources);
297 bctbx_mutex_destroy(&ml->timer_sources_mutex);
298 }
299
300 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_main_loop_t);
301 BELLE_SIP_INSTANCIATE_VPTR(belle_sip_main_loop_t,belle_sip_object_t,belle_sip_main_loop_destroy,NULL,NULL,FALSE);
302
belle_sip_main_loop_new(void)303 belle_sip_main_loop_t *belle_sip_main_loop_new(void){
304 belle_sip_main_loop_t*m=belle_sip_object_new(belle_sip_main_loop_t);
305 m->pool=belle_sip_object_pool_push();
306 m->timer_sources = bctbx_mmap_ullong_new();
307 bctbx_mutex_init(&m->timer_sources_mutex,NULL);
308 return m;
309 }
310
belle_sip_main_loop_add_source(belle_sip_main_loop_t * ml,belle_sip_source_t * source)311 void belle_sip_main_loop_add_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source){
312 if (source->node.next || source->node.prev){
313 belle_sip_fatal("Source is already linked somewhere else.");
314 return;
315 }
316 if (source->node.data!=source){
317 belle_sip_fatal("Insane source passed to belle_sip_main_loop_add_source() !");
318 return;
319 }
320
321 source->ml=ml;
322
323 if (source->timeout>=0){
324 belle_sip_object_ref(source);
325 source->expire_ms=belle_sip_time_ms()+source->timeout;
326 bctbx_mutex_lock(&ml->timer_sources_mutex);
327 source->it = bctbx_map_insert_and_delete_with_returned_it(ml->timer_sources
328 , (bctbx_pair_t*)bctbx_pair_ullong_new(source->expire_ms, source));
329 bctbx_mutex_unlock(&ml->timer_sources_mutex);
330
331 }
332 source->cancelled=FALSE;
333 if (source->fd != (belle_sip_fd_t)-1 ) {
334 belle_sip_object_ref(source);
335 ml->fd_sources=belle_sip_list_prepend_link(ml->fd_sources,&source->node);
336 }
337
338 ml->nsources++;
339 }
340
belle_sip_main_loop_create_timeout_with_remove_cb(belle_sip_main_loop_t * ml,belle_sip_source_func_t func,void * data,unsigned int timeout_value_ms,const char * timer_name,belle_sip_source_remove_callback_t remove_func)341 belle_sip_source_t* belle_sip_main_loop_create_timeout_with_remove_cb( belle_sip_main_loop_t *ml
342 , belle_sip_source_func_t func
343 , void *data
344 , unsigned int timeout_value_ms
345 , const char* timer_name
346 , belle_sip_source_remove_callback_t remove_func) {
347 belle_sip_source_t * s=belle_sip_timeout_source_new(func,data,timeout_value_ms);
348 belle_sip_object_set_name((belle_sip_object_t*)s,timer_name);
349 if (remove_func) {
350 belle_sip_source_set_remove_cb(s, remove_func);
351 }
352 belle_sip_main_loop_add_source(ml,s);
353 return s;
354 }
belle_sip_main_loop_create_timeout(belle_sip_main_loop_t * ml,belle_sip_source_func_t func,void * data,unsigned int timeout_value_ms,const char * timer_name)355 belle_sip_source_t* belle_sip_main_loop_create_timeout(belle_sip_main_loop_t *ml
356 , belle_sip_source_func_t func
357 , void *data
358 , unsigned int timeout_value_ms
359 ,const char* timer_name) {
360 return belle_sip_main_loop_create_timeout_with_remove_cb(ml, func, data, timeout_value_ms,timer_name,NULL);
361
362 }
363
belle_sip_main_loop_add_timeout(belle_sip_main_loop_t * ml,belle_sip_source_func_t func,void * data,unsigned int timeout_value_ms)364 unsigned long belle_sip_main_loop_add_timeout(belle_sip_main_loop_t *ml, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms){
365 belle_sip_source_t * s=belle_sip_main_loop_create_timeout(ml,func,data,timeout_value_ms,"Timer");
366 belle_sip_object_unref(s);
367 return s->id;
368 }
369
belle_sip_main_loop_do_later(belle_sip_main_loop_t * ml,belle_sip_callback_t func,void * data)370 void belle_sip_main_loop_do_later(belle_sip_main_loop_t *ml, belle_sip_callback_t func, void *data){
371 belle_sip_source_t * s=belle_sip_main_loop_create_timeout(ml,(belle_sip_source_func_t)func,data,0,"defered task");
372 s->oneshot=TRUE;
373 belle_sip_object_unref(s);
374 }
375
376
belle_sip_source_set_timeout(belle_sip_source_t * s,unsigned int value_ms)377 void belle_sip_source_set_timeout(belle_sip_source_t *s, unsigned int value_ms){
378 if (!s->expired){
379 belle_sip_main_loop_t *ml = s->ml;
380 s->expire_ms=belle_sip_time_ms()+value_ms;
381 if (s->it){
382 /*this timeout is already sorted in the timer_sources map, we need to move it to its new place*/
383 bctbx_mutex_lock(&ml->timer_sources_mutex);
384 bctbx_map_erase(ml->timer_sources, s->it);
385 bctbx_iterator_delete(s->it);
386 s->it = bctbx_map_insert_and_delete_with_returned_it(ml->timer_sources,
387 (bctbx_pair_t*)bctbx_pair_ullong_new(s->expire_ms, s));
388 bctbx_mutex_unlock(&ml->timer_sources_mutex);
389 }
390 }
391 s->timeout=value_ms;
392 }
393
belle_sip_source_set_remove_cb(belle_sip_source_t * s,belle_sip_source_remove_callback_t func)394 void belle_sip_source_set_remove_cb(belle_sip_source_t *s, belle_sip_source_remove_callback_t func) {
395 s->on_remove=func;
396 }
397
belle_sip_source_get_timeout(const belle_sip_source_t * s)398 unsigned int belle_sip_source_get_timeout(const belle_sip_source_t *s){
399 return s->timeout;
400 }
401
belle_sip_source_cancel(belle_sip_source_t * s)402 void belle_sip_source_cancel(belle_sip_source_t *s){
403 s->cancelled=TRUE;
404 if (s->it) {
405 bctbx_mutex_lock(&s->ml->timer_sources_mutex);
406 bctbx_map_erase(s->ml->timer_sources, s->it);
407 bctbx_iterator_delete(s->it);
408 /*put on front*/
409 s->it = bctbx_map_insert_and_delete_with_returned_it(s->ml->timer_sources, (bctbx_pair_t*)bctbx_pair_ullong_new(0, s));
410
411 bctbx_mutex_unlock(&s->ml->timer_sources_mutex);
412 }
413 }
414
match_source_id(const void * s,const void * pid)415 static int match_source_id(const void *s, const void *pid){
416 if ( ((belle_sip_source_t*)s)->id==(unsigned long)(intptr_t)pid){
417 return 0;
418 }
419 return -1;
420 }
421
belle_sip_main_loop_find_source(belle_sip_main_loop_t * ml,unsigned long id)422 belle_sip_source_t *belle_sip_main_loop_find_source(belle_sip_main_loop_t *ml, unsigned long id){
423 bctbx_iterator_t *it;
424 belle_sip_source_t *ret=NULL;
425 belle_sip_list_t *elem=belle_sip_list_find_custom(ml->fd_sources,match_source_id,(const void*)(intptr_t)id);
426 if (elem!=NULL) {
427 ret = (belle_sip_source_t*)elem->data;
428 } else if ((it = bctbx_map_find_custom(ml->timer_sources, match_source_id, (const void*)(intptr_t)id))) {
429 ret = (belle_sip_source_t*)bctbx_pair_get_second(bctbx_iterator_get_pair(it));
430 bctbx_iterator_delete(it);
431 } /*else
432 ret = NULL;*/
433
434 return ret;
435
436 }
437
belle_sip_main_loop_cancel_source(belle_sip_main_loop_t * ml,unsigned long id)438 void belle_sip_main_loop_cancel_source(belle_sip_main_loop_t *ml, unsigned long id){
439 belle_sip_source_t *s=belle_sip_main_loop_find_source(ml,id);
440 if (s) belle_sip_source_cancel(s);
441 }
442
belle_sip_main_loop_iterate(belle_sip_main_loop_t * ml)443 static void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
444 size_t pfd_size = ml->nsources * sizeof(belle_sip_pollfd_t);
445 belle_sip_pollfd_t *pfd=(belle_sip_pollfd_t*)belle_sip_malloc0(pfd_size);
446 int i=0;
447 belle_sip_source_t *s;
448 belle_sip_list_t *elem,*next;
449 int duration=-1;
450 int ret;
451 uint64_t cur;
452 belle_sip_list_t *to_be_notified=NULL;
453 int can_clean=belle_sip_object_pool_cleanable(ml->pool); /*iterate might not be called by the thread that created the main loop*/
454 belle_sip_object_pool_t *tmp_pool=NULL;
455 bctbx_iterator_t *it,*end;
456
457 if (!can_clean){
458 /*Push a temporary pool for the time of the iterate loop*/
459 tmp_pool=belle_sip_object_pool_push();
460 }
461
462 /*Step 1: prepare the pollfd table and get the next timeout value */
463 for(elem=ml->fd_sources;elem!=NULL;elem=next) {
464 next=elem->next;
465 s=(belle_sip_source_t*)elem->data;
466 if (!s->cancelled){
467 if (s->fd!=(belle_sip_fd_t)-1){
468 belle_sip_source_to_poll(s,pfd,i);
469 ++i;
470 }
471 }
472 }
473 /*all source with timeout are in ml->timer_sources*/
474 if (bctbx_map_size(ml->timer_sources) >0) {
475 int64_t diff;
476 uint64_t next_wakeup_time;
477 it = bctbx_map_begin(ml->timer_sources);
478 /*use first because in case of canceled timer, key ==0 , key != s->expire_ms */
479 next_wakeup_time = bctbx_pair_ullong_get_first((const bctbx_pair_ullong_t *)bctbx_iterator_get_pair(it));
480 /* compute the amount of time to wait for shortest timeout*/
481 cur=belle_sip_time_ms();
482 diff=next_wakeup_time-cur;
483 if (diff>0)
484 duration=MIN((unsigned int)diff,INT_MAX);
485 else
486 duration=0;
487 bctbx_iterator_delete(it);
488 it = NULL;
489 }
490
491 /* do the poll */
492 ret=belle_sip_poll(pfd,i,duration);
493 if (ret==-1){
494 goto end;
495 }
496
497 /* Step 2: examine poll results and determine the list of source to be notified */
498 cur=belle_sip_time_ms();
499 for(elem=ml->fd_sources;elem!=NULL;elem=elem->next){
500 unsigned revents=0;
501 s=(belle_sip_source_t*)elem->data;
502 if (!s->cancelled){
503 if (s->fd!=(belle_sip_fd_t)-1){
504 if (s->notify_required) { /*for testing purpose to force channel to read*/
505 revents=BELLE_SIP_EVENT_READ;
506 s->notify_required=0; /*reset*/
507 } else {
508 revents=belle_sip_source_get_revents(s,pfd);
509 }
510 s->revents=revents;
511 } else {
512 belle_sip_error("Source [%p] does not contains any fd !",s);
513 }
514 if (revents!=0){
515 to_be_notified=belle_sip_list_append(to_be_notified,belle_sip_object_ref(s));
516 }
517 }else to_be_notified=belle_sip_list_append(to_be_notified,belle_sip_object_ref(s));
518 }
519
520 /* Step 3: find timeouted sources */
521
522 bctbx_mutex_lock(&ml->timer_sources_mutex); /*iterator chain might be alterated by element insertion*/
523 it = bctbx_map_begin(ml->timer_sources);
524 end = bctbx_map_end(ml->timer_sources);
525 while (!bctbx_iterator_equals(it,end)) {
526 /*use first because in case of canceled timer, key != s->expire_ms*/
527 uint64_t expire = bctbx_pair_ullong_get_first((const bctbx_pair_ullong_t *)bctbx_iterator_get_pair(it));
528 s = (belle_sip_source_t*)bctbx_pair_get_second(bctbx_iterator_get_pair(it));
529 if (expire > cur) {
530 /* no need to continue looping because map is ordered*/
531 break;
532 } else {
533 if (s->revents==0) {
534 s->expired=TRUE;
535 to_be_notified=belle_sip_list_append(to_be_notified,belle_sip_object_ref(s));
536 } /*else already in to_be_notified by Step 2*/
537
538 s->revents|=BELLE_SIP_EVENT_TIMEOUT;
539 it=bctbx_iterator_get_next(it);
540 }
541 }
542 bctbx_iterator_delete(it);
543 bctbx_iterator_delete(end);
544 bctbx_mutex_unlock(&ml->timer_sources_mutex);
545
546 /* Step 4: notify those to be notified */
547 for(elem=to_be_notified;elem!=NULL;){
548 s=(belle_sip_source_t*)elem->data;
549 next=elem->next;
550 if (!s->cancelled){
551
552 if (s->timeout > 0 && belle_sip_log_level_enabled(BELLE_SIP_LOG_DEBUG)) {
553 /*to avoid too many traces*/
554 char *objdesc=belle_sip_object_to_string((belle_sip_object_t*)s);
555 belle_sip_debug("source %s notified revents=%u, timeout=%i",objdesc,revents,s->timeout);
556 belle_sip_free(objdesc);
557 }
558
559 ret=s->notify(s->data,s->revents);
560 if (ret==BELLE_SIP_STOP || s->oneshot){
561 /*this source needs to be removed*/
562 belle_sip_main_loop_remove_source(ml,s);
563 } else {
564 if (s->expired && s->it) {
565 bctbx_mutex_lock(&ml->timer_sources_mutex);
566 bctbx_map_erase(ml->timer_sources, s->it);
567 bctbx_iterator_delete(s->it);
568 bctbx_mutex_unlock(&ml->timer_sources_mutex);
569 s->it=NULL;
570 belle_sip_object_unref(s);
571 }
572 if (!s->it && s->timeout >= 0){
573 /*timeout needs to be started again */
574 if (ret==BELLE_SIP_CONTINUE_WITHOUT_CATCHUP){
575 s->expire_ms=cur+s->timeout;
576 }else{
577 s->expire_ms+=s->timeout;
578 }
579 s->expired=FALSE;
580 bctbx_mutex_lock(&ml->timer_sources_mutex);
581 s->it = bctbx_map_insert_and_delete_with_returned_it(ml->timer_sources,
582 (bctbx_pair_t*)bctbx_pair_ullong_new(s->expire_ms, s));
583 bctbx_mutex_unlock(&ml->timer_sources_mutex);
584 belle_sip_object_ref(s);
585 }
586 }
587 } else {
588 belle_sip_main_loop_remove_source(ml,s);
589 }
590 s->revents=0;
591 belle_sip_object_unref(s);
592 belle_sip_free(elem); /*free just the element*/
593 elem=next;
594 }
595
596 if (can_clean) belle_sip_object_pool_clean(ml->pool);
597 else if (tmp_pool) {
598 belle_sip_object_unref(tmp_pool);
599 tmp_pool=NULL;
600 }
601 end:
602
603 belle_sip_free(pfd);
604 }
605
belle_sip_main_loop_run(belle_sip_main_loop_t * ml)606 void belle_sip_main_loop_run(belle_sip_main_loop_t *ml){
607 if (ml->in_loop){
608 belle_sip_warning("belle_sip_main_loop_run(): reentrancy detected, doing nothing");
609 return;
610 }
611 ml->run = TRUE;
612 ml->in_loop = TRUE;
613 while(ml->run){
614 belle_sip_main_loop_iterate(ml);
615 }
616 ml->in_loop = FALSE;
617 }
618
belle_sip_main_loop_quit(belle_sip_main_loop_t * ml)619 int belle_sip_main_loop_quit(belle_sip_main_loop_t *ml){
620 ml->run=0;
621 return BELLE_SIP_STOP;
622 }
623
belle_sip_main_loop_sleep(belle_sip_main_loop_t * ml,int milliseconds)624 void belle_sip_main_loop_sleep(belle_sip_main_loop_t *ml, int milliseconds){
625 belle_sip_source_t * s=belle_sip_main_loop_create_timeout(ml,(belle_sip_source_func_t)belle_sip_main_loop_quit,ml,milliseconds,"Main loop sleep timer");
626 belle_sip_main_loop_run(ml);
627 belle_sip_main_loop_remove_source(ml,s);
628 belle_sip_object_unref(s);
629 }
630
631