Ejemplo n.º 1
0
/*copy the content of ref object to new object, for the part they have in common in their inheritence diagram*/
void _belle_sip_object_copy(belle_sip_object_t *newobj, const belle_sip_object_t *ref){
	belle_sip_object_vptr_t *vptr;
	vptr=find_common_floor(newobj->vptr,ref->vptr);
	if (vptr==NULL){
		belle_sip_fatal("Should not happen");
	}
	while(vptr!=NULL){
		if (vptr->clone==NULL){
			belle_sip_fatal("Object of type %s cannot be cloned, it does not provide a clone() implementation.",vptr->type_name);
			return;
		}else vptr->clone(newobj,ref);
		vptr=vptr->get_parent();
	}
}
Ejemplo n.º 2
0
void belle_sip_object_pool_remove(belle_sip_object_pool_t *pool, belle_sip_object_t *obj){
	unsigned long tid=belle_sip_thread_self_id();
	if (obj->pool!=pool){
		belle_sip_fatal("Attempting to remove object from an incorrect pool: obj->pool=%p, pool=%p",obj->pool,pool);
		return;
	}
	if (tid!=pool->thread_id){
		belle_sip_fatal("It is forbidden (and unsafe()) to ref()/unref() an unowned object outside of the thread that created it.");
		return;
	}
	pool->objects=belle_sip_list_delete_link(pool->objects,obj->pool_iterator);
	obj->pool_iterator=NULL;
	obj->pool=NULL;
}
Ejemplo n.º 3
0
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){
	size_t tmp_buf_size=buff_size*2;
	char *p=(char*)belle_sip_malloc0(tmp_buf_size);
	size_t i;
	size_t initial_offset=*offset;
	belle_sip_error_code error=vptr->marshal(obj,p,buff_size,offset);
	size_t written;

	for (i=initial_offset;i<buff_size;++i){
		if (p[i]=='\0') break;
	}
	written=i-initial_offset;
	if (error==BELLE_SIP_BUFFER_OVERFLOW){
		belle_sip_error("Object of type %s commited a buffer overflow by marshalling %i bytes",
			vptr->type_name,(int)(*offset-initial_offset));
	} else if (error!=BELLE_SIP_OK){
		belle_sip_error("Object of type %s produced an error during marshalling: %i",
			vptr->type_name,error);
	}
	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*/
		belle_sip_fatal("Object of type %s marshalled %i bytes but said it marshalled %i bytes !",
			vptr->type_name,(int)written,(int)(*offset-initial_offset));
	}
	memcpy(buff+initial_offset,p+initial_offset,*offset-initial_offset);
	belle_sip_free(p);
	return error;
}
Ejemplo n.º 4
0
void belle_sip_main_loop_add_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source){
	if (source->node.next || source->node.prev){
		belle_sip_fatal("Source is already linked somewhere else.");
		return;
	}
	if (source->node.data!=source){
		belle_sip_fatal("Insane source passed to belle_sip_main_loop_add_source() !");
		return;
	}
	belle_sip_object_ref(source);
	if (source->timeout>=0){
		source->expire_ms=belle_sip_time_ms()+source->timeout;
	}
	ml->sources=belle_sip_list_append_link(ml->sources,&source->node);
	ml->nsources++;
}
Ejemplo n.º 5
0
void belle_sip_object_pool_add(belle_sip_object_pool_t *pool, belle_sip_object_t *obj){
	if (obj->pool!=NULL){
		belle_sip_fatal("It is not possible to add an object to multiple pools.");
	}
	pool->objects=belle_sip_list_prepend(pool->objects,obj);
	obj->pool_iterator=pool->objects;
	obj->pool=pool;
}
Ejemplo n.º 6
0
int _belle_sip_dialog_match(belle_sip_dialog_t *obj, const char *call_id, const char *local_tag, const char *remote_tag){
	const char *dcid;
	if (obj->state==BELLE_SIP_DIALOG_NULL) belle_sip_fatal("_belle_sip_dialog_match() must not be used for dialog in null state.");
	dcid=belle_sip_header_call_id_get_call_id(obj->call_id);
	return strcmp(dcid,call_id)==0
		&& strcmp(obj->local_tag,local_tag)==0 
		&& obj->remote_tag /* handle 180 without to tag */ && strcmp(obj->remote_tag,remote_tag)==0;
}
Ejemplo n.º 7
0
static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args){
	const char *lname="undef";
	char *msg;
	struct timeval tp;
	struct tm *lt;
#ifndef _WIN32
	struct tm tmstorage;
#endif
	time_t curtime;

	belle_sip_gettimeofday(&tp,NULL);
	curtime=tp.tv_sec;
#ifdef _WIN32
	lt = localtime(&curtime);
#else
	lt = localtime_r(&curtime,&tmstorage);
#endif

	if (__log_file==NULL) __log_file=stderr;
	switch(lev){
		case BELLE_SIP_LOG_DEBUG:
			lname="debug";
			break;
		case BELLE_SIP_LOG_MESSAGE:
			lname="message";
			break;
		case BELLE_SIP_LOG_WARNING:
			lname="warning";
			break;
		case BELLE_SIP_LOG_ERROR:
			lname="error";
			break;
		case BELLE_SIP_LOG_FATAL:
			lname="fatal";
			break;
		default:
			belle_sip_fatal("Bad level !");
	}
	msg=belle_sip_strdup_vprintf(fmt,args);
#if defined(_MSC_VER) && !defined(_WIN32_WCE)
	#ifndef _UNICODE
	OutputDebugStringA(msg);
	OutputDebugStringA("\r\n");
	#else
	{
		int len=strlen(msg);
		wchar_t *tmp=(wchar_t*)belle_sip_malloc0((len+1)*sizeof(wchar_t));
		mbstowcs(tmp,msg,len);
		OutputDebugStringW(tmp);
		OutputDebugStringW(L"\r\n");
		belle_sip_free(tmp);
	}
	#endif
#endif
	fprintf(__log_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i belle-sip-%s-%s" ENDLINE,1900+lt->tm_year,lt->tm_mon+1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec,(int)(tp.tv_usec/1000), lname,msg);
	fflush(__log_file);
	free(msg);
}
Ejemplo n.º 8
0
void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno){
	if (obj!=NULL){
		if (has_type(obj,id)==0){
			belle_sip_fatal("Bad cast to %s at %s:%i",castname,file,fileno);
			return NULL;
		}
	}
	return obj;
}
Ejemplo n.º 9
0
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){
	if (obj!=NULL){
		if (belle_sip_object_get_interface_methods(obj,ifid)==0){
			belle_sip_fatal("Bad cast to interface %s at %s:%i",castname,file,fileno);
			return NULL;
		}
	}
	return obj;
}
Ejemplo n.º 10
0
belle_sip_listening_point_t *belle_sip_stack_create_listening_point(belle_sip_stack_t *s, const char *ipaddress, int port, const char *transport){
	belle_sip_listening_point_t *lp=NULL;
	if (strcasecmp(transport,"UDP")==0) {
		lp=belle_sip_udp_listening_point_new(s,ipaddress,port);
	} else if (strcasecmp(transport,"TCP") == 0) {
		lp=belle_sip_stream_listening_point_new(s,ipaddress,port);
	}else if (strcasecmp(transport,"TLS") == 0) {
		lp=belle_sip_tls_listening_point_new(s,ipaddress,port);
	} else {
		belle_sip_fatal("Unsupported transport %s",transport);
	}
	return lp;
}
Ejemplo n.º 11
0
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END

void belle_sip_server_transaction_init(belle_sip_server_transaction_t *t, belle_sip_provider_t *prov,belle_sip_request_t *req){
	const char *branch;
	belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)req,"via"));
	branch=belle_sip_header_via_get_branch(via);
	if (branch==NULL || strncmp(branch,BELLE_SIP_BRANCH_MAGIC_COOKIE,strlen(BELLE_SIP_BRANCH_MAGIC_COOKIE))!=0){
		branch=req->rfc2543_branch;
		if (branch==NULL) belle_sip_fatal("No computed branch for RFC2543 style of message, this should never happen.");
	}
	t->base.branch_id=belle_sip_strdup(branch);
	belle_sip_transaction_init((belle_sip_transaction_t*)t,prov,req);
	belle_sip_random_token(t->to_tag,sizeof(t->to_tag));
}
Ejemplo n.º 12
0
static void nict_set_completed(belle_sip_nict_t *obj, belle_sip_response_t *resp){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
	const belle_sip_timer_config_t *cfg=belle_sip_transaction_get_timer_config(base);
	belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_COMPLETED);
	if (obj->timer_K) belle_sip_fatal("Should never happen.");

	belle_sip_client_transaction_notify_response((belle_sip_client_transaction_t*)obj,resp);

	if (!belle_sip_channel_is_reliable(base->channel)){
		obj->timer_K=belle_sip_timeout_source_new((belle_sip_source_func_t)nict_on_timer_K,obj,cfg->T4);
		belle_sip_object_set_name((belle_sip_object_t*)obj->timer_K,"timer_K");
		belle_sip_transaction_start_timer(base,obj->timer_K);
	}else belle_sip_transaction_terminate(base);
}
Ejemplo n.º 13
0
void belle_sip_object_unref(void *ptr){
	belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
	if (obj->ref==-1) belle_sip_fatal("Object with name [%s] freed twice !",obj->name);
	if (obj->ref==0 && obj->pool){
		belle_sip_object_pool_remove(obj->pool,obj);
		obj->ref=-1;
		belle_sip_object_delete(obj);
		return;
	}
	obj->ref--;
	if (obj->ref==0){
		obj->ref=-1;
		belle_sip_object_delete(obj);
	}
}
Ejemplo n.º 14
0
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END

void belle_sip_client_transaction_init(belle_sip_client_transaction_t *obj, belle_sip_provider_t *prov, belle_sip_request_t *req){
	belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)req,"via"));
	char token[BELLE_SIP_BRANCH_ID_LENGTH];

	if (!via){
		belle_sip_fatal("belle_sip_client_transaction_init(): No via in request.");
	}

	if (strcmp(belle_sip_request_get_method(req),"CANCEL")!=0){
		obj->base.branch_id=belle_sip_strdup_printf(BELLE_SIP_BRANCH_MAGIC_COOKIE ".%s",belle_sip_random_token(token,sizeof(token)));
		belle_sip_header_via_set_branch(via,obj->base.branch_id);
	}else{
		obj->base.branch_id=belle_sip_strdup(belle_sip_header_via_get_branch(via));
	}
	belle_sip_transaction_init((belle_sip_transaction_t*)obj, prov,req);
}
Ejemplo n.º 15
0
void belle_sip_object_weak_unref(void *obj, belle_sip_object_destroy_notify_t destroy_notify, void *userpointer){
	belle_sip_object_t *o=BELLE_SIP_OBJECT(obj);
	weak_ref_t *ref,*prevref=NULL,*next=NULL;

	if (o->ref==-1) return; /*too late and avoid recursions*/
	for(ref=o->weak_refs;ref!=NULL;ref=next){
		next=ref->next;
		if (ref->notify==destroy_notify && ref->userpointer==userpointer){
			if (prevref==NULL) o->weak_refs=next;
			else prevref->next=next;
			belle_sip_free(ref);
			return;
		}else{
			prevref=ref;
		}
	}
	belle_sip_fatal("Could not find weak_ref, you're a looser.");
}
Ejemplo n.º 16
0
void belle_sip_object_weak_unref(void *obj, belle_sip_object_destroy_notify_t destroy_notify, void *userpointer){
	belle_sip_object_t *o=BELLE_SIP_OBJECT(obj);
	weak_ref_t *ref,*prevref=NULL,*next=NULL;
	int found=FALSE;

	if (o->ref==-1) return; /*too late and avoid recursions*/
	for(ref=o->weak_refs;ref!=NULL;ref=next){
		next=ref->next;
		if (ref->notify==destroy_notify && ref->userpointer==userpointer){
			if (prevref==NULL) o->weak_refs=next;
			else prevref->next=next;
			belle_sip_free(ref);
			found=TRUE;
			/*do not break or return, someone could have put twice the same weak ref on the same object*/
		}else{
			prevref=ref;
		}
	}
	if (!found) belle_sip_fatal("Could not find weak_ref, you're a looser.");
}
Ejemplo n.º 17
0
void belle_sip_object_unref(void *ptr){
	belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
	if (obj->ref==-1) {
		belle_sip_error("Object [%p] freed twice !",obj);
		if (obj->vptr && obj->vptr->type_name) belle_sip_error("Object type might be [%s]",obj->vptr->type_name);
		if (obj->name) belle_sip_error("Object name might be [%s]",obj->name);
		belle_sip_fatal("Fatal object error encountered, aborting.");
		return;
	}
	if (obj->ref==0 && obj->pool){
		belle_sip_object_pool_remove(obj->pool,obj);
		obj->ref=-1;
		belle_sip_object_delete(obj);
		return;
	}
	obj->ref--;
	if (obj->ref==0){
		obj->ref=-1;
		belle_sip_object_delete(obj);
	}
}
Ejemplo n.º 18
0
const char *belle_sip_transaction_state_to_string(belle_sip_transaction_state_t state){
	switch(state){
		case BELLE_SIP_TRANSACTION_INIT:
			return "INIT";
		case BELLE_SIP_TRANSACTION_TRYING:
			return "TRYING";
		case BELLE_SIP_TRANSACTION_CALLING:
			return "CALLING";
		case BELLE_SIP_TRANSACTION_COMPLETED:
			return "COMPLETED";
		case BELLE_SIP_TRANSACTION_CONFIRMED:
			return "CONFIRMED";
		case BELLE_SIP_TRANSACTION_ACCEPTED:
			return "ACCEPTED";
		case BELLE_SIP_TRANSACTION_PROCEEDING:
			return "PROCEEDING";
		case BELLE_SIP_TRANSACTION_TERMINATED:
			return "TERMINATED";
	}
	belle_sip_fatal("Invalid transaction state.");
	return "INVALID";
}
Ejemplo n.º 19
0
void belle_sip_object_pool_clean(belle_sip_object_pool_t *pool){
	belle_sip_list_t *elem,*next;

	if (!belle_sip_object_pool_cleanable(pool)){
		belle_sip_warning("Thread pool [%p] cannot be cleaned from thread [%lu] because it was created for thread [%lu]",
				 pool,belle_sip_thread_self_id(),(unsigned long)pool->thread_id);
		return;
	}

	for(elem=pool->objects;elem!=NULL;elem=next){
		belle_sip_object_t *obj=(belle_sip_object_t*)elem->data;
		if (obj->ref==0){
			belle_sip_message("Garbage collecting unowned object of type %s",obj->vptr->type_name);
			obj->ref=-1;
			belle_sip_object_delete(obj);
			next=elem->next;
			belle_sip_free(elem);
		}else {
			belle_sip_fatal("Object %p is in unowned list but with ref count %i, bug.",obj,obj->ref);
			next=elem->next;
		}
	}
	pool->objects=NULL;
}
Ejemplo n.º 20
0
static void _send_message(belle_sip_channel_t *obj){
	char buffer[belle_sip_network_buffer_size];
	size_t len=0;
	belle_sip_error_code error=BELLE_SIP_OK;
	belle_sip_message_t *msg=obj->cur_out_message;
	belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg);
	size_t body_len=bh ? belle_sip_body_handler_get_size(bh) : 0;
	int sendret;
	size_t off;
	int ret;
	
	if (obj->ewouldblock_buffer){
		sendret=send_buffer(obj,(const char*)obj->ewouldblock_buffer+obj->ewouldblock_offset,obj->ewouldblock_size-obj->ewouldblock_offset);
		if (sendret>0){
			obj->ewouldblock_offset+=sendret;
			if (obj->ewouldblock_offset==obj->ewouldblock_size){
				free_ewouldblock_buffer(obj);
			}
			return; /*we prefer poll again to be sure we can write*/
		}else if (belle_sip_error_code_is_would_block(-sendret)) {
			/*we got an ewouldblock again. Nothing to do, we'll be called later in order to retry*/
			return;
		}else {/*error or disconnection case*/
			goto done;
		}
	}
	
	if (obj->out_state==OUTPUT_STREAM_SENDING_HEADERS){
		BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_sending,obj,msg);
		check_content_length(msg,body_len);
		error=belle_sip_object_marshal((belle_sip_object_t*)msg,buffer,sizeof(buffer)-1,&len);
		if (error!=BELLE_SIP_OK) {
			belle_sip_error("channel [%p] _send_message: marshaling failed.",obj);
			goto done;
		}
		/*send the headers and eventually the body if it fits in our buffer*/
		if (bh){
			size_t max_body_len=sizeof(buffer)-1-len;
			
			if (body_len>0 && body_len<=max_body_len){ /*if size is known and fits into our buffer, send together with headers*/
				belle_sip_body_handler_begin_transfer(bh);
				do{
					max_body_len=sizeof(buffer)-1-len;
					ret=belle_sip_body_handler_send_chunk(bh,msg,(uint8_t*)buffer+len,&max_body_len);
					len+=max_body_len;
				}while(ret==BELLE_SIP_CONTINUE);
				belle_sip_body_handler_end_transfer(bh);
			}else{
				if (body_len==0){
					belle_sip_fatal("Sending bodies whose size is not known must be done in chunked mode, which is not supported yet.");
				}
				belle_sip_body_handler_begin_transfer(bh);
				obj->out_state=OUTPUT_STREAM_SENDING_BODY;
			}
		}
		off=0;
		do{
			sendret=send_buffer(obj,buffer+off,len-off);
			if (sendret>0){
				off+=sendret;
				if (off==len){
					break;
				}
			}else if (belle_sip_error_code_is_would_block(-sendret)) {
				handle_ewouldblock(obj,buffer+off,len-off);
				return;
			}else {/*error or disconnection case*/
				goto done;
			}
		}while(1);
	}
	if (obj->out_state==OUTPUT_STREAM_SENDING_BODY){
		do{
			size_t chunk_len=sizeof(buffer)-1;
			ret=belle_sip_body_handler_send_chunk(bh,msg,(uint8_t*)buffer,&chunk_len);
			if (chunk_len!=0){
				off=0;
				do{
					sendret=send_buffer(obj,buffer+off,chunk_len-off);
					if (sendret>0){
						off+=sendret;
						if (off==chunk_len){
							break;
						}
					}else if (belle_sip_error_code_is_would_block(-sendret)) {
						handle_ewouldblock(obj,buffer+off,chunk_len-off);
						return;
					}else {/*error or disconnection case*/
						goto done;
					}
				}while(1);
			}
		}while(ret==BELLE_SIP_CONTINUE);
		belle_sip_body_handler_end_transfer(bh);
	}
	done:
		/*we get ready to send another message*/
		belle_sip_source_set_events((belle_sip_source_t*)obj,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR);
		free_ewouldblock_buffer(obj);
		obj->out_state=OUTPUT_STREAM_IDLE;
		belle_sip_object_unref(obj->cur_out_message);
		obj->cur_out_message=NULL;
}
Ejemplo n.º 21
0
static void belle_sip_source_destroy(belle_sip_source_t *obj){
	if (obj->node.next || obj->node.prev){
		belle_sip_fatal("Destroying source currently used in main loop !");
	}
	belle_sip_source_uninit(obj);
}