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_internal.h"
20 
21 static void _belle_sip_object_pool_remove_from_stack(belle_sip_object_pool_t *pool);
22 
23 static int _belle_sip_object_marshal_check_enabled = FALSE;
24 
has_type(belle_sip_object_t * obj,belle_sip_type_id_t id)25 static int has_type(belle_sip_object_t *obj, belle_sip_type_id_t id){
26 	belle_sip_object_vptr_t *vptr=obj->vptr;
27 
28 	while(vptr!=NULL){
29 		if (vptr->id==id) return TRUE;
30 		vptr=vptr->get_parent();
31 	}
32 	return FALSE;
33 }
34 
_belle_sip_object_is_instance_of(belle_sip_object_t * obj,belle_sip_type_id_t id)35 int _belle_sip_object_is_instance_of(belle_sip_object_t * obj,belle_sip_type_id_t id) {
36 	return has_type(obj,id);
37 }
38 
belle_sip_object_enable_marshal_check(int enable)39 void belle_sip_object_enable_marshal_check(int enable) {
40 	_belle_sip_object_marshal_check_enabled = (enable) ? TRUE : FALSE;
41 }
42 
43 
44 static belle_sip_list_t *all_objects=NULL;
45 static int belle_sip_leak_detector_enabled=FALSE;
46 static int belle_sip_leak_detector_inhibited=FALSE;
47 
add_new_object(belle_sip_object_t * obj)48 static void add_new_object(belle_sip_object_t *obj){
49 	if (belle_sip_leak_detector_enabled && !belle_sip_leak_detector_inhibited){
50 		all_objects=belle_sip_list_prepend(all_objects,obj);
51 	}
52 }
53 
remove_free_object(belle_sip_object_t * obj)54 static void remove_free_object(belle_sip_object_t *obj){
55 	if (belle_sip_leak_detector_enabled && !belle_sip_leak_detector_inhibited){
56 		belle_sip_list_t* it;
57 		it=belle_sip_list_find(all_objects,obj);
58 		if (it)
59 			all_objects = belle_sip_list_delete_link(all_objects,it); /*it may fail if the leak detector was inhibitted at the time the object was created*/
60 	}
61 }
62 
belle_sip_object_inhibit_leak_detector(int yes)63 void belle_sip_object_inhibit_leak_detector(int yes){
64 	belle_sip_leak_detector_inhibited=yes ? TRUE : FALSE;
65 }
66 
belle_sip_object_enable_leak_detector(int enable)67 void belle_sip_object_enable_leak_detector(int enable){
68 	belle_sip_leak_detector_enabled=enable;
69 }
70 
belle_sip_object_get_object_count(void)71 int belle_sip_object_get_object_count(void){
72 	return (int)belle_sip_list_size(all_objects);
73 }
74 
belle_sip_object_flush_active_objects(void)75 void belle_sip_object_flush_active_objects(void){
76 	//do not free objects so that they are still detected as leaked by valgrind and such
77 	all_objects = belle_sip_list_free(all_objects);
78 }
79 
belle_sip_object_dump_active_objects(void)80 void belle_sip_object_dump_active_objects(void){
81 	belle_sip_list_t *elem;
82 
83 	if (all_objects){
84 		belle_sip_warning("List of leaked objects:");
85 		for(elem=all_objects;elem!=NULL;elem=elem->next){
86 			belle_sip_object_t *obj=(belle_sip_object_t*)elem->data;
87 			char* content= belle_sip_object_to_string(obj);
88 			belle_sip_warning("%s(%p) ref=%i, content [%10s...]",obj->vptr->type_name,obj,obj->ref,content);
89 			belle_sip_free(content);
90 		}
91 	}else belle_sip_warning("No objects leaked.");
92 }
93 
_belle_sip_object_new(size_t objsize,belle_sip_object_vptr_t * vptr)94 belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr){
95 	belle_sip_object_t *obj=(belle_sip_object_t *)belle_sip_malloc0(vptr->size);
96 
97 	obj->ref=vptr->initially_unowned ? 0 : 1;
98 	obj->vptr=vptr;
99 	if (obj->ref==0){
100 		belle_sip_object_pool_t *pool=belle_sip_object_pool_get_current();
101 		if (pool) belle_sip_object_pool_add(pool,obj);
102 	}
103 	add_new_object(obj);
104 	return obj;
105 }
106 
belle_sip_object_is_initially_unowned(const belle_sip_object_t * obj)107 int belle_sip_object_is_initially_unowned(const belle_sip_object_t *obj){
108 	return obj->vptr->initially_unowned;
109 }
110 
belle_sip_object_ref(void * obj)111 belle_sip_object_t * belle_sip_object_ref(void *obj){
112 	belle_sip_object_t *o=BELLE_SIP_OBJECT(obj);
113 	if (o->ref==0 && o->pool){
114 		belle_sip_object_pool_remove(o->pool,obj);
115 	}
116 	o->ref++;
117 	return obj;
118 }
119 
belle_sip_object_unref(void * ptr)120 void belle_sip_object_unref(void *ptr){
121 	belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
122 	if (obj->ref <= -1) {
123 		belle_sip_error("Object [%p] freed twice or corrupted !",obj);
124 		if (obj->vptr && obj->vptr->type_name) belle_sip_error("Object type might be [%s]",obj->vptr->type_name);
125 		if (obj->name) belle_sip_error("Object name might be [%s]",obj->name);
126 		belle_sip_fatal("Fatal object error encountered, aborting.");
127 		return;
128 	}
129 	if (obj->vptr->initially_unowned && obj->ref==0){
130 		if (obj->pool)
131 			belle_sip_object_pool_remove(obj->pool,obj);
132 		obj->ref=-1;
133 		belle_sip_object_delete(obj);
134 		return;
135 	}
136 	obj->ref--;
137 	if (obj->ref == 0){
138 		obj->ref = -1;
139 		belle_sip_object_delete(obj);
140 	}
141 }
142 
weak_ref_new(belle_sip_object_destroy_notify_t destroy_notify,void * userpointer)143 static weak_ref_t *weak_ref_new(belle_sip_object_destroy_notify_t destroy_notify, void *userpointer){
144 	weak_ref_t *r=belle_sip_new(weak_ref_t);
145 	r->next=NULL;
146 	r->notify=destroy_notify;
147 	r->userpointer=userpointer;
148 	return r;
149 }
150 
belle_sip_object_weak_ref(void * obj,belle_sip_object_destroy_notify_t destroy_notify,void * userpointer)151 belle_sip_object_t *belle_sip_object_weak_ref(void *obj, belle_sip_object_destroy_notify_t destroy_notify, void *userpointer){
152 	belle_sip_object_t *o=BELLE_SIP_OBJECT(obj);
153 	weak_ref_t *old=o->weak_refs;
154 	o->weak_refs=weak_ref_new(destroy_notify,userpointer);
155 	o->weak_refs->next=old;
156 	return o;
157 }
158 
belle_sip_object_weak_unref(void * obj,belle_sip_object_destroy_notify_t destroy_notify,void * userpointer)159 void belle_sip_object_weak_unref(void *obj, belle_sip_object_destroy_notify_t destroy_notify, void *userpointer){
160 	belle_sip_object_t *o=BELLE_SIP_OBJECT(obj);
161 	weak_ref_t *ref,*prevref=NULL,*next=NULL;
162 	int found=FALSE;
163 
164 	if (o->ref==-1) return; /*too late and avoid recursions*/
165 	for(ref=o->weak_refs;ref!=NULL;ref=next){
166 		next=ref->next;
167 		if (ref->notify==destroy_notify && ref->userpointer==userpointer){
168 			if (prevref==NULL) o->weak_refs=next;
169 			else prevref->next=next;
170 			belle_sip_free(ref);
171 			found=TRUE;
172 			/*do not break or return, someone could have put twice the same weak ref on the same object*/
173 		}else{
174 			prevref=ref;
175 		}
176 	}
177 	if (!found) belle_sip_fatal("Could not find weak_ref, you're a looser.");
178 }
179 
belle_sip_object_loose_weak_refs(belle_sip_object_t * obj)180 static void belle_sip_object_loose_weak_refs(belle_sip_object_t *obj){
181 	weak_ref_t *ref,*next;
182 	for(ref=obj->weak_refs;ref!=NULL;ref=next){
183 		next=ref->next;
184 		ref->notify(ref->userpointer,obj);
185 		belle_sip_free(ref);
186 	}
187 	obj->weak_refs=NULL;
188 }
189 
_belle_sip_object_uninit(belle_sip_object_t * obj)190 static void _belle_sip_object_uninit(belle_sip_object_t *obj){
191 	if (obj->name)
192 		belle_sip_free(obj->name);
193 }
194 
_belle_sip_object_clone(belle_sip_object_t * obj,const belle_sip_object_t * orig)195 static void _belle_sip_object_clone(belle_sip_object_t *obj, const belle_sip_object_t *orig){
196 	if (orig->name!=NULL) obj->name=belle_sip_strdup(orig->name);
197 }
198 
_belle_object_marshal(belle_sip_object_t * obj,char * buff,size_t buff_size,size_t * offset)199 static belle_sip_error_code _belle_object_marshal(belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset) {
200 	return belle_sip_snprintf(buff,buff_size,offset,"{%s::%s %p}",obj->vptr->type_name,obj->name ? obj->name : "(no name)",obj);
201 }
202 
no_parent(void)203 static belle_sip_object_vptr_t *no_parent(void){
204 	return NULL;
205 }
206 
207 belle_sip_object_vptr_t belle_sip_object_t_vptr={
208 	BELLE_SIP_TYPE_ID(belle_sip_object_t),
209 	sizeof(belle_sip_object_t),
210 	"belle_sip_object_t",
211 	FALSE,
212 	no_parent, /*no parent, it's god*/
213 	NULL,
214 	_belle_sip_object_uninit,
215 	_belle_sip_object_clone,
216 	_belle_object_marshal,
217 	BELLE_SIP_DEFAULT_BUFSIZE_HINT
218 };
219 
belle_sip_object_t_vptr_get(void)220 belle_sip_object_vptr_t *belle_sip_object_t_vptr_get(void){
221 	return &belle_sip_object_t_vptr;
222 }
223 
belle_sip_object_delete(void * ptr)224 void belle_sip_object_delete(void *ptr){
225 	belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
226 	belle_sip_object_vptr_t *vptr;
227 
228 	belle_sip_object_loose_weak_refs(obj);
229 	remove_free_object(obj);
230 	vptr=obj->vptr;
231 	while(vptr!=NULL){
232 		if (vptr->destroy) vptr->destroy(obj);
233 		vptr=vptr->get_parent();
234 	}
235 	belle_sip_object_data_clear(obj);
236 	belle_sip_free(obj);
237 }
238 
find_common_floor(belle_sip_object_vptr_t * vptr1,belle_sip_object_vptr_t * vptr2)239 static belle_sip_object_vptr_t *find_common_floor(belle_sip_object_vptr_t *vptr1, belle_sip_object_vptr_t *vptr2){
240 	belle_sip_object_vptr_t *it1,*it2;
241 	for (it1=vptr1;it1!=NULL;it1=it1->get_parent()){
242 		if (it1==vptr2)
243 			return vptr2;
244 	}
245 	for(it2=vptr2;it2!=NULL;it2=it2->get_parent()){
246 		if (vptr1==it2)
247 			return vptr1;
248 	}
249 	return find_common_floor(vptr1->get_parent(),vptr2);
250 }
251 
252 /*copy the content of ref object to new object, for the part they have in common in their inheritence diagram*/
_belle_sip_object_copy(belle_sip_object_t * newobj,const belle_sip_object_t * ref)253 void _belle_sip_object_copy(belle_sip_object_t *newobj, const belle_sip_object_t *ref){
254 	belle_sip_object_vptr_t *vptr;
255 	vptr=find_common_floor(newobj->vptr,ref->vptr);
256 	if (vptr==NULL){
257 		belle_sip_fatal("Should not happen");
258 	}
259 	while(vptr!=NULL){
260 		if (vptr->clone==NULL){
261 			belle_sip_fatal("Object of type %s cannot be cloned, it does not provide a clone() implementation.",vptr->type_name);
262 			return;
263 		}else vptr->clone(newobj,ref);
264 		vptr=vptr->get_parent();
265 	}
266 }
267 
belle_sip_object_clone(const belle_sip_object_t * obj)268 belle_sip_object_t *belle_sip_object_clone(const belle_sip_object_t *obj){
269 	belle_sip_object_t *newobj;
270 
271 	newobj=belle_sip_malloc0(obj->vptr->size);
272 	newobj->ref=obj->vptr->initially_unowned ? 0 : 1;
273 	newobj->vptr=obj->vptr;
274 	_belle_sip_object_copy(newobj,obj);
275 	if (newobj->ref==0){
276 		belle_sip_object_pool_t *pool=belle_sip_object_pool_get_current();
277 		if (pool) belle_sip_object_pool_add(pool,newobj);
278 	}
279 	add_new_object(newobj);
280 	return newobj;
281 }
282 
belle_sip_object_clone_and_ref(const belle_sip_object_t * obj)283 belle_sip_object_t *belle_sip_object_clone_and_ref(const belle_sip_object_t *obj) {
284 	return belle_sip_object_ref(belle_sip_object_clone(obj));
285 }
286 
287 
288 struct belle_sip_object_data{
289 	char* name;
290 	void* data;
291 	belle_sip_data_destroy destroy_func;
292 };
293 
belle_sip_object_data_find(const void * a,const void * b)294 static int belle_sip_object_data_find(const void* a, const void* b)
295 {
296 	struct belle_sip_object_data* da = (struct belle_sip_object_data*)a;
297 	return strcmp(da->name, (const char*)b);
298 }
299 
belle_sip_object_data_destroy(void * data)300 static void belle_sip_object_data_destroy(void* data)
301 {
302 	struct belle_sip_object_data* da = (struct belle_sip_object_data*)data;
303 	if (da->destroy_func) da->destroy_func(da->data);
304 	belle_sip_free(da->name);
305 	belle_sip_free(da);
306 }
307 
belle_sip_object_data_set(belle_sip_object_t * obj,const char * name,void * data,belle_sip_data_destroy destroy_func)308 int belle_sip_object_data_set( belle_sip_object_t *obj, const char* name, void* data, belle_sip_data_destroy destroy_func )
309 {
310 	int ret = 0;
311 	belle_sip_list_t*  list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
312 	struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL;
313 
314 	if( entry == NULL){
315 		entry = belle_sip_malloc0(sizeof( struct belle_sip_object_data));
316 		obj->data_store = belle_sip_list_append(obj->data_store, entry);
317 	}
318 	else {
319 		// clean previous data
320 		if( entry->destroy_func ) entry->destroy_func(entry->data);
321 		belle_sip_free(entry->name);
322 		ret = 1;
323 	}
324 
325 	if( entry ){
326 		entry->data = data;
327 		entry->name = belle_sip_strdup(name);
328 		entry->destroy_func = destroy_func;
329 	} else {
330 		ret = -1;
331 	}
332 	return ret;
333 }
334 
belle_sip_object_data_get(belle_sip_object_t * obj,const char * name)335 void* belle_sip_object_data_get( belle_sip_object_t *obj, const char* name )
336 {
337 	belle_sip_list_t  *list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
338 	struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL;
339 
340 	return entry? entry->data : NULL;
341 }
342 
belle_sip_object_data_remove(belle_sip_object_t * obj,const char * name)343 int belle_sip_object_data_remove( belle_sip_object_t *obj, const char* name)
344 {
345 	belle_sip_list_t  *list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
346 	struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL;
347 	if( entry ){
348 		belle_sip_free(entry->name);
349 		if( entry->destroy_func ) entry->destroy_func(entry->data);
350 		belle_sip_free(entry);
351 	}
352 	if( list_entry ) obj->data_store = belle_sip_list_remove_link(obj->data_store, list_entry);
353 	return !(list_entry!= NULL);
354 }
355 
belle_sip_object_data_exists(const belle_sip_object_t * obj,const char * name)356 int belle_sip_object_data_exists( const belle_sip_object_t *obj, const char* name )
357 {
358 	return (belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name) != NULL);
359 }
360 
361 
belle_sip_object_data_grab(belle_sip_object_t * obj,const char * name)362 void* belle_sip_object_data_grab( belle_sip_object_t* obj, const char* name)
363 {
364 	belle_sip_list_t  *list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
365 	struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL;
366 	void* data =NULL;
367 
368 	if( entry ){
369 		belle_sip_free(entry->name);
370 		data = entry->data;
371 	}
372 	obj->data_store = belle_sip_list_remove_link(obj->data_store, list_entry);
373 	belle_sip_free(entry);
374 
375 	return data;
376 }
377 
belle_sip_object_data_clear(belle_sip_object_t * obj)378 void belle_sip_object_data_clear( belle_sip_object_t* obj )
379 {
380 	belle_sip_list_for_each(obj->data_store, belle_sip_object_data_destroy);
381 	obj->data_store = belle_sip_list_free(obj->data_store);
382 }
383 
belle_sip_object_data_clone(const belle_sip_object_t * src,belle_sip_object_t * dst,belle_sip_data_clone clone_func)384 void belle_sip_object_data_clone( const belle_sip_object_t* src, belle_sip_object_t* dst, belle_sip_data_clone clone_func)
385 {
386 	belle_sip_object_data_clear(dst);
387 	belle_sip_object_data_merge(src, dst, clone_func);
388 }
389 
belle_sip_object_data_merge(const belle_sip_object_t * src,belle_sip_object_t * dst,belle_sip_data_clone clone_func)390 void belle_sip_object_data_merge( const belle_sip_object_t* src, belle_sip_object_t* dst, belle_sip_data_clone clone_func)
391 {
392 	belle_sip_list_t *list = src->data_store;
393 	struct belle_sip_object_data* it = NULL;
394 	void* cloned_data = NULL;
395 
396 	while( list ){
397 		it = list->data;
398 		if( it ){
399 			cloned_data = (clone_func)? clone_func( it->name, it->data ) : it->data;
400 			belle_sip_object_data_set(dst, it->name, cloned_data, it->destroy_func);
401 		}
402 		list = list->next;
403 	}
404 }
405 
406 
407 struct belle_sip_object_foreach_data {
408 	void (*apply_func)(const char*, void*, void*);
409 	void* userdata;
410 };
411 
belle_sip_object_for_each_cb(void * data,void * pvdata)412 static void belle_sip_object_for_each_cb(void* data, void* pvdata)
413 {
414 	struct belle_sip_object_data*         it = (struct belle_sip_object_data*)data;
415 	struct belle_sip_object_foreach_data* fd = (struct belle_sip_object_foreach_data*)pvdata;
416 
417 	if( it && fd->apply_func ){
418 		fd->apply_func(it->name, it->data, fd->userdata);
419 	}
420 }
421 
belle_sip_object_data_foreach(const belle_sip_object_t * obj,void (* apply_func)(const char * key,void * data,void * userdata),void * userdata)422 void belle_sip_object_data_foreach( const belle_sip_object_t* obj, void (*apply_func)(const char* key, void* data, void* userdata), void* userdata)
423 {
424 	struct belle_sip_object_foreach_data fd = { apply_func, userdata };
425 	belle_sip_list_for_each2(obj->data_store, belle_sip_object_for_each_cb, &fd);
426 }
427 
428 
belle_sip_object_cast(belle_sip_object_t * obj,belle_sip_type_id_t id,const char * castname,const char * file,int fileno)429 void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno){
430 	if (obj!=NULL){
431 		if (has_type(obj,id)==0){
432 			belle_sip_fatal("Bad cast to %s at %s:%i",castname,file,fileno);
433 			return NULL;
434 		}
435 	}
436 	return obj;
437 }
438 
belle_sip_object_get_interface_methods(belle_sip_object_t * obj,belle_sip_interface_id_t ifid)439 void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid){
440 	if (obj!=NULL){
441 		belle_sip_object_vptr_t *vptr;
442 		for (vptr=obj->vptr;vptr!=NULL;vptr=vptr->get_parent()){
443 			belle_sip_interface_desc_t **ifaces=vptr->interfaces;
444 			if (ifaces!=NULL){
445 				for(;*ifaces!=0;++ifaces){
446 					if ((*ifaces)->id==ifid){
447 						return *ifaces;
448 					}
449 				}
450 			}
451 		}
452 	}
453 	return NULL;
454 }
455 
belle_sip_object_implements(belle_sip_object_t * obj,belle_sip_interface_id_t id)456 int belle_sip_object_implements(belle_sip_object_t *obj, belle_sip_interface_id_t id){
457 	return belle_sip_object_get_interface_methods(obj,id)!=NULL;
458 }
459 
belle_sip_object_interface_cast(belle_sip_object_t * obj,belle_sip_interface_id_t ifid,const char * castname,const char * file,int fileno)460 void *belle_sip_object_interface_cast(belle_sip_object_t *obj, belle_sip_interface_id_t ifid, const char *castname, const char *file, int fileno){
461 	if (obj!=NULL){
462 		if (belle_sip_object_get_interface_methods(obj,ifid)==0){
463 			belle_sip_fatal("Bad cast to interface %s at %s:%i",castname,file,fileno);
464 			return NULL;
465 		}
466 	}
467 	return obj;
468 }
469 
belle_sip_object_set_name(belle_sip_object_t * object,const char * name)470 void belle_sip_object_set_name(belle_sip_object_t* object,const char* name) {
471 	if (object->name) {
472 		belle_sip_free(object->name);
473 		object->name=NULL;
474 	}
475 	if (name)
476 		object->name=belle_sip_strdup(name);
477 }
478 
belle_sip_object_get_name(belle_sip_object_t * object)479 const char* belle_sip_object_get_name(belle_sip_object_t* object) {
480 	return object->name;
481 }
482 
checked_marshal(belle_sip_object_vptr_t * vptr,belle_sip_object_t * obj,char * buff,size_t buff_size,size_t * offset)483 static belle_sip_error_code checked_marshal(belle_sip_object_vptr_t *vptr, belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset){
484 	size_t tmp_buf_size=buff_size*2;
485 	char *p=(char*)belle_sip_malloc0(tmp_buf_size);
486 	size_t i;
487 	size_t initial_offset=*offset;
488 	belle_sip_error_code error=vptr->marshal(obj,p,buff_size,offset);
489 	size_t written;
490 
491 	for (i=initial_offset;i<buff_size;++i){
492 		if (p[i]=='\0') break;
493 	}
494 	written=i-initial_offset;
495 	if (error==BELLE_SIP_OK){
496 		if (written!=(*offset-initial_offset) && written!=(buff_size-initial_offset-1)){ /*this is because snprintf won't allow you to write a non null character at the end of the buffer*/
497 			belle_sip_fatal("Object of type %s marshalled %i bytes but said it marshalled %i bytes !",
498 				vptr->type_name,(int)written,(int)(*offset-initial_offset));
499 		}
500 		memcpy(buff+initial_offset,p+initial_offset,*offset-initial_offset);
501 	}else if (error==BELLE_SIP_BUFFER_OVERFLOW){
502 		/* Case where the object aborted the marshalling because of not enough room.
503 		 * Should this happen, it is not allowed to write past buffer end anyway */
504 		if (written > buff_size){
505 			belle_sip_fatal("Object of type %s commited a buffer overflow by marshalling %i bytes",
506 				vptr->type_name,(int)(*offset-initial_offset));
507 		}
508 	}else{
509 		belle_sip_error("Object of type %s produced an error during marshalling: %i",
510 			vptr->type_name,error);
511 	}
512 	belle_sip_free(p);
513 	return error;
514 }
515 
belle_sip_object_marshal(belle_sip_object_t * obj,char * buff,size_t buff_size,size_t * offset)516 belle_sip_error_code belle_sip_object_marshal(belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset) {
517 	belle_sip_object_vptr_t *vptr=obj->vptr;
518 	while (vptr != NULL) {
519 		if (vptr->marshal != NULL) {
520 			if (_belle_sip_object_marshal_check_enabled == TRUE)
521 				return checked_marshal(vptr,obj,buff,buff_size,offset);
522 			else
523 				return vptr->marshal(obj,buff,buff_size,offset);
524 		} else {
525 			vptr=vptr->get_parent();
526 		}
527 	}
528 	return BELLE_SIP_NOT_IMPLEMENTED; /*no implementation found*/
529 }
530 
531 
belle_sip_object_to_alloc_string(belle_sip_object_t * obj,int size_hint)532 static char * belle_sip_object_to_alloc_string(belle_sip_object_t *obj, int size_hint){
533 	char *buf=belle_sip_malloc(size_hint);
534 	size_t offset=0;
535 	belle_sip_error_code error = belle_sip_object_marshal(obj,buf,size_hint-1,&offset);
536 	obj->vptr->tostring_bufsize_hint=size_hint;
537 	if (error==BELLE_SIP_BUFFER_OVERFLOW){
538 		belle_sip_message("belle_sip_object_to_alloc_string(): hint buffer was too short while doing to_string() for %s, retrying", obj->vptr->type_name);
539 		belle_sip_free(buf);
540 		return belle_sip_object_to_alloc_string(obj,2*size_hint);
541 	}
542 	buf=belle_sip_realloc(buf,offset+1);
543 	buf[offset]='\0';
544 	return buf;
545 }
546 
get_hint_size(int size)547 static int get_hint_size(int size){
548 	if (size<128)
549 		return 128;
550 	return size;
551 }
552 
belle_sip_object_to_string(void * _obj)553 char* belle_sip_object_to_string(void* _obj) {
554 	belle_sip_object_t *obj=BELLE_SIP_OBJECT(_obj);
555 	if (obj->vptr->tostring_bufsize_hint!=0){
556 		return belle_sip_object_to_alloc_string(obj,obj->vptr->tostring_bufsize_hint);
557 	}else{
558 		char buff[BELLE_SIP_MAX_TO_STRING_SIZE];
559 		size_t offset=0;
560 		belle_sip_error_code error = belle_sip_object_marshal(obj,buff,sizeof(buff)-1,&offset);
561 		if (error==BELLE_SIP_BUFFER_OVERFLOW){
562 			belle_sip_message("belle_sip_object_to_string(): temporary buffer is too short while doing to_string() for %s, retrying", obj->vptr->type_name);
563 			return belle_sip_object_to_alloc_string(obj,get_hint_size(2*(int)offset));
564 		}
565 		buff[offset]='\0';
566 		obj->vptr->tostring_bufsize_hint=get_hint_size(2*(int)offset);
567 		return belle_sip_strdup(buff);
568 	}
569 }
570 
_belle_sip_object_describe_type(belle_sip_object_vptr_t * vptr)571 char * _belle_sip_object_describe_type(belle_sip_object_vptr_t *vptr){
572 	const int maxbufsize=2048;
573 	char *ret=belle_sip_malloc(maxbufsize);
574 	belle_sip_object_vptr_t *it;
575 	size_t pos=0;
576 	belle_sip_list_t *l=NULL,*elem;
577 	belle_sip_snprintf(ret,maxbufsize,&pos,"Ownership:\n");
578 	belle_sip_snprintf(ret,maxbufsize,&pos,"\t%s is created initially %s\n",vptr->type_name,
579 				  vptr->initially_unowned ? "unowned" : "owned");
580 	belle_sip_snprintf(ret,maxbufsize,&pos,"\nInheritance diagram:\n");
581 	for(it=vptr;it!=NULL;it=it->get_parent()){
582 		l=belle_sip_list_prepend(l,it);
583 	}
584 	for(elem=l;elem!=NULL;elem=elem->next){
585 		it=(belle_sip_object_vptr_t*)elem->data;
586 		belle_sip_snprintf(ret,maxbufsize,&pos,"\t%s\n",it->type_name);
587 		if (elem->next)
588 			belle_sip_snprintf(ret,maxbufsize,&pos,"\t        |\n");
589 	}
590 	belle_sip_list_free(l);
591 	belle_sip_snprintf(ret,maxbufsize,&pos,"\nImplemented interfaces:\n");
592 	for(it=vptr;it!=NULL;it=it->get_parent()){
593 		belle_sip_interface_desc_t **desc=it->interfaces;
594 		if (desc!=NULL){
595 			for(;*desc!=NULL;desc++){
596 				belle_sip_snprintf(ret,maxbufsize,&pos,"\t* %s\n",(*desc)->ifname);
597 			}
598 		}
599 	}
600 	return ret;
601 }
602 
belle_sip_object_describe(void * obj)603 char *belle_sip_object_describe(void *obj){
604 	belle_sip_object_t *o=BELLE_SIP_OBJECT(obj);
605 	return _belle_sip_object_describe_type(o->vptr);
606 }
607 
608 #if !defined(_WIN32)
609 
610 #include <dlfcn.h>
611 
belle_sip_object_describe_type_from_name(const char * name)612 char *belle_sip_object_describe_type_from_name(const char *name){
613 	char *vptr_name;
614 	void *handle;
615 	void *symbol;
616 	belle_sip_object_get_vptr_t vptr_getter;
617 
618 	handle=dlopen(NULL,RTLD_LAZY);
619 	if (handle==NULL){
620 		belle_sip_error("belle_sip_object_describe_type_from_name: dlopen() failed: %s",dlerror());
621 		return NULL;
622 	}
623 	vptr_name=belle_sip_strdup_printf("%s_vptr_get",name);
624 	symbol=dlsym(handle,vptr_name);
625 	belle_sip_free(vptr_name);
626 	dlclose(handle);
627 	if (symbol==NULL){
628 		belle_sip_error("belle_sip_object_describe_type_from_name: could not find vptr for type %s",name);
629 		return NULL;
630 	}
631 	vptr_getter=(belle_sip_object_get_vptr_t)symbol;
632 	return _belle_sip_object_describe_type(vptr_getter());
633 }
634 
635 #else
636 
belle_sip_object_describe_type_from_name(const char * name)637 char *belle_sip_object_describe_type_from_name(const char *name){
638 	return belle_sip_strdup_printf("Sorry belle_sip_object_describe_type_from_name() is not implemented on this platform.");
639 }
640 
641 #endif
642 
643 struct belle_sip_object_pool{
644 	belle_sip_object_t base;
645 	belle_sip_list_t *objects;
646 	unsigned long thread_id;
647 };
648 
belle_sip_object_pool_destroy(belle_sip_object_pool_t * pool)649 static void belle_sip_object_pool_destroy(belle_sip_object_pool_t *pool){
650 	belle_sip_object_pool_clean(pool);
651 	_belle_sip_object_pool_remove_from_stack(pool);
652 }
653 
654 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_object_pool_t);
655 BELLE_SIP_INSTANCIATE_VPTR(belle_sip_object_pool_t,belle_sip_object_t,belle_sip_object_pool_destroy,NULL,NULL,FALSE);
656 
belle_sip_object_pool_new(void)657 belle_sip_object_pool_t *belle_sip_object_pool_new(void){
658 	belle_sip_object_pool_t *pool=belle_sip_object_new(belle_sip_object_pool_t);
659 	pool->thread_id=belle_sip_thread_self_id();
660 	return pool;
661 }
662 
belle_sip_object_pool_add(belle_sip_object_pool_t * pool,belle_sip_object_t * obj)663 void belle_sip_object_pool_add(belle_sip_object_pool_t *pool, belle_sip_object_t *obj){
664 	if (obj->pool!=NULL){
665 		belle_sip_fatal("It is not possible to add an object to multiple pools.");
666 	}
667 	pool->objects=belle_sip_list_prepend(pool->objects,obj);
668 	obj->pool_iterator=pool->objects;
669 	obj->pool=pool;
670 }
671 
belle_sip_object_pool_remove(belle_sip_object_pool_t * pool,belle_sip_object_t * obj)672 void belle_sip_object_pool_remove(belle_sip_object_pool_t *pool, belle_sip_object_t *obj){
673 	unsigned long tid=belle_sip_thread_self_id();
674 	if (obj->pool!=pool){
675 		belle_sip_fatal("Attempting to remove object from an incorrect pool: obj->pool=%p, pool=%p",obj->pool,pool);
676 		return;
677 	}
678 	if (tid!=pool->thread_id){
679 		belle_sip_fatal("It is forbidden (and unsafe()) to ref()/unref() an unowned object outside of the thread that created it.");
680 		return;
681 	}
682 	pool->objects=belle_sip_list_delete_link(pool->objects,obj->pool_iterator);
683 	obj->pool_iterator=NULL;
684 	obj->pool=NULL;
685 }
686 
belle_sip_object_pool_cleanable(belle_sip_object_pool_t * pool)687 int belle_sip_object_pool_cleanable(belle_sip_object_pool_t *pool){
688 	return pool->thread_id!=0 && belle_sip_thread_self_id()==pool->thread_id;
689 }
690 
belle_sip_object_pool_clean(belle_sip_object_pool_t * pool)691 void belle_sip_object_pool_clean(belle_sip_object_pool_t *pool){
692 	belle_sip_list_t *elem,*next;
693 
694 	if (!belle_sip_object_pool_cleanable(pool)){
695 		belle_sip_warning("Thread pool [%p] cannot be cleaned from thread [%lu] because it was created for thread [%lu]",
696 				 pool,belle_sip_thread_self_id(),(unsigned long)pool->thread_id);
697 		return;
698 	}
699 
700 	for(elem=pool->objects;elem!=NULL;elem=next){
701 		belle_sip_object_t *obj=(belle_sip_object_t*)elem->data;
702 		if (obj->ref==0){
703 			belle_sip_message("Garbage collecting unowned object of type %s",obj->vptr->type_name);
704 			obj->ref=-1;
705 			belle_sip_object_delete(obj);
706 			next=elem->next;
707 			belle_sip_free(elem);
708 		}else {
709 			belle_sip_fatal("Object %p is in unowned list but with ref count %i, bug.",obj,obj->ref);
710 			next=elem->next;
711 		}
712 	}
713 	pool->objects=NULL;
714 }
715 
belle_sip_object_pool_detach_from_thread(belle_sip_object_pool_t * pool)716 static void belle_sip_object_pool_detach_from_thread(belle_sip_object_pool_t *pool){
717 	belle_sip_object_pool_clean(pool);
718 	pool->thread_id=(unsigned long)0;
719 }
720 
cleanup_pool_stack(void * data)721 static void cleanup_pool_stack(void *data){
722 	belle_sip_list_t **pool_stack=(belle_sip_list_t**)data;
723 	if (*pool_stack){
724 		/*
725 		 * We would expect the pool_stack to be empty when the thread terminates.
726 		 * Otherwise that means the management of object pool is not properly done by the application.
727 		 * Since the object pools might be still referenced by the application, we can't destroy them.
728 		 * Instead, we mark them as detached, so that when the thread that will attempt to destroy them will do it,
729 		 * we'll accept (since anyway these object pool are no longer needed.
730 		 */
731 		belle_sip_warning("There were still [%u] object pools for thread [%lu] while the thread exited. ",
732 			(unsigned int)belle_sip_list_size(*pool_stack),belle_sip_thread_self_id());
733 		belle_sip_list_free_with_data(*pool_stack,(void (*)(void*)) belle_sip_object_pool_detach_from_thread);
734 	}
735 	*pool_stack=NULL;
736 	belle_sip_free(pool_stack);
737 }
738 
get_current_pool_stack(int * first_time)739 static belle_sip_list_t** get_current_pool_stack(int *first_time){
740 	static belle_sip_thread_key_t pools_key;
741 	static int pools_key_created=0;
742 	belle_sip_list_t **pool_stack;
743 
744 	if (first_time) *first_time=0;
745 
746 	if (!pools_key_created){
747 		pools_key_created=1;
748 		if (belle_sip_thread_key_create(&pools_key, cleanup_pool_stack)!=0){
749 			return NULL;
750 		}
751 	}
752 	pool_stack=(belle_sip_list_t**)belle_sip_thread_getspecific(pools_key);
753 	if (pool_stack==NULL){
754 		pool_stack=belle_sip_new(belle_sip_list_t*);
755 		*pool_stack=NULL;
756 		belle_sip_thread_setspecific(pools_key,pool_stack);
757 		if (first_time) *first_time=1;
758 	}
759 	return pool_stack;
760 }
761 
_belle_sip_object_pool_remove_from_stack(belle_sip_object_pool_t * pool)762 static void _belle_sip_object_pool_remove_from_stack(belle_sip_object_pool_t *pool){
763 	belle_sip_list_t **pools=get_current_pool_stack(NULL);
764 	unsigned long tid=belle_sip_thread_self_id();
765 
766 	if (tid!=pool->thread_id){
767 		belle_sip_fatal("It is forbidden to destroy a pool outside the thread that created it.");
768 		return;
769 	}
770 
771 	if (pools==NULL) {
772 		belle_sip_fatal("Not possible to pop a pool.");
773 		return;
774 	}
775 	if (*pools==NULL){
776 		belle_sip_fatal("There is no current pool in stack.");
777 		return;
778 	}
779 	*pools=belle_sip_list_remove(*pools,pool);
780 }
781 
belle_sip_object_pool_push(void)782 belle_sip_object_pool_t * belle_sip_object_pool_push(void){
783 	belle_sip_list_t **pools=get_current_pool_stack(NULL);
784 	belle_sip_object_pool_t *pool;
785 	if (pools==NULL) {
786 		belle_sip_error("Not possible to create a pool.");
787 		return NULL;
788 	}
789 	pool=belle_sip_object_pool_new();
790 	*pools=belle_sip_list_prepend(*pools,pool);
791 	return pool;
792 }
793 
794 
795 
belle_sip_object_pool_get_current(void)796 belle_sip_object_pool_t *belle_sip_object_pool_get_current(void){
797 	int first_time;
798 	belle_sip_list_t **pools=get_current_pool_stack(&first_time);
799 	if (pools==NULL) return NULL;
800 	if (*pools==NULL ){
801 		if (first_time) {
802 			belle_sip_warning("There is no object pool created in thread [%lu]. "
803 			"Use belle_sip_object_pool_push() to create one. Unowned objects not unref'd will be leaked.",
804 			belle_sip_thread_self_id());
805 		}
806 		return NULL;
807 	}
808 	return (belle_sip_object_pool_t*)(*pools)->data;
809 }
810 
811 
812