Exemplo n.º 1
0
void belle_sip_multipart_body_handler_add_part(belle_sip_multipart_body_handler_t *obj, belle_sip_body_handler_t *part){
	obj->base.expected_size+=part->expected_size+strlen(obj->boundary) + 4; /* add the separator length to the body length as each part start with a separator. 4 is for "--" and "\r\n" */
	if (part->headers != NULL) { /* there is a declared header for this part, add its length to the expected total length */
		size_t headerStringBufferSize = DEFAULT_HEADER_STRING_SIZE;
		size_t offset = 0;
		belle_sip_list_t *headerList = part->headers;
		part->headerStringBuffer = (char *)belle_sip_malloc(DEFAULT_HEADER_STRING_SIZE);

		while (headerList != NULL) {
			size_t offsetBackup=offset; /* we must backup the offset as it will be messed up by the marshal function in case of failure */
			belle_sip_error_code returnCode = belle_sip_object_marshal(headerList->data, part->headerStringBuffer, headerStringBufferSize-5, &offset); /* -5 to leave room for carriage returns */
			if (returnCode == BELLE_SIP_BUFFER_OVERFLOW) { /* increase buffer size */
				offset=offsetBackup; /* restore the offset, no data were written to the buffer */
				headerStringBufferSize+=DEFAULT_HEADER_STRING_SIZE;
				part->headerStringBuffer = (char *)belle_sip_realloc(part->headerStringBuffer, headerStringBufferSize);
			} else if (returnCode == BELLE_SIP_OK) { /* add the carriage return chars */
				part->headerStringBuffer[offset++]='\r';
				part->headerStringBuffer[offset++]='\n';
				headerList = belle_sip_list_next(headerList);
			}
		}
		part->headerStringBuffer[offset++]='\r';
		part->headerStringBuffer[offset++]='\n';
		obj->base.expected_size += offset;
		part->headerStringBuffer[offset++]='\0'; /* null terminate the buffer in order to be able to get it length later using strlen */
	}
	obj->parts=belle_sip_list_append(obj->parts,belle_sip_object_ref(part));
}
Exemplo n.º 2
0
belle_sip_list_t* belle_sip_list_insert_sorted(belle_sip_list_t* list, void *data, int (*compare_func)(const void *, const void*)){
	belle_sip_list_t* it,*previt=NULL;
	belle_sip_list_t* nelem;
	belle_sip_list_t* ret=list;
	if (list==NULL) return belle_sip_list_append(list,data);
	else{
		nelem=belle_sip_list_new(data);
		for(it=list;it!=NULL;it=it->next){
			previt=it;
			if (compare_func(data,it->data)<=0){
				nelem->prev=it->prev;
				nelem->next=it;
				if (it->prev!=NULL)
					it->prev->next=nelem;
				else{
					ret=nelem;
				}
				it->prev=nelem;
				return ret;
			}
		}
		previt->next=nelem;
		nelem->prev=previt;
	}
	return ret;
}
Exemplo n.º 3
0
static void encode_headers(belle_sip_param_pair_t* container, belle_sip_list_t** newlist) {
	char *escapedName = belle_sip_uri_to_escaped_header(container->name);
	char *escapedValue = container->value? belle_sip_uri_to_escaped_header(container->value) : NULL;
	*newlist = belle_sip_list_append(*newlist, belle_sip_param_pair_new(escapedName, escapedValue));
	if (escapedName) free(escapedName);
	if (escapedValue) free(escapedValue);
}
Exemplo n.º 4
0
int belle_sip_object_data_set( belle_sip_object_t *obj, const char* name, void* data, belle_sip_data_destroy destroy_func )
{
	int ret = 0;
	struct _belle_sip_list*  list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
	struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL;

	if( entry == NULL){
		entry = belle_sip_malloc0(sizeof( struct belle_sip_object_data));
		obj->data_store = belle_sip_list_append(obj->data_store, entry);
	}
	else {
		// clean previous data
		if( entry->destroy_func ) entry->destroy_func(entry->data);
		belle_sip_free(entry->name);
		ret = 1;
	}

	if( entry ){
		entry->data = data;
		entry->name = belle_sip_strdup(name);
		entry->destroy_func = destroy_func;
	} else {
		ret = -1;
	}
	return ret;
}
Exemplo n.º 5
0
static void belle_sip_channel_message_ready(belle_sip_channel_t *obj){
	belle_sip_message_t *msg=obj->input_stream.msg;
	belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg);
	if (bh) belle_sip_body_handler_end_transfer(bh);
	if (belle_sip_message_is_response(msg)) belle_sip_channel_learn_public_ip_port(obj,BELLE_SIP_RESPONSE(msg));
	obj->incoming_messages=belle_sip_list_append(obj->incoming_messages,msg);
	belle_sip_channel_input_stream_reset(&obj->input_stream);
}
Exemplo n.º 6
0
belle_sip_list_t* belle_sip_list_copy(const belle_sip_list_t* list){
	belle_sip_list_t* copy=NULL;
	const belle_sip_list_t* iter;
	for(iter=list;iter!=NULL;iter=belle_sip_list_next(iter)){
		copy=belle_sip_list_append(copy,iter->data);
	}
	return copy;
}
Exemplo n.º 7
0
belle_sip_list_t* belle_sip_list_copy_with_data(const belle_sip_list_t* list, void* (*copyfunc)(void*)){
	belle_sip_list_t* copy=NULL;
	const belle_sip_list_t* iter;
	for(iter=list;iter!=NULL;iter=belle_sip_list_next(iter)){
		copy=belle_sip_list_append(copy,copyfunc(iter->data));
	}
	return copy;
}
Exemplo n.º 8
0
void sal_set_dns_servers(Sal *sal, const bctbx_list_t *servers){
	belle_sip_list_t *l = NULL;

	/*we have to convert the bctbx_list_t into a belle_sip_list_t first*/
	for (; servers != NULL; servers = servers->next){
		l = belle_sip_list_append(l, servers->data);
	}
	belle_sip_stack_set_dns_servers(sal->stack, l);
	belle_sip_list_free(l);
}
Exemplo n.º 9
0
belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t){
	belle_sip_dialog_t *obj;
	belle_sip_header_from_t *from;
	const char *from_tag;
	belle_sip_header_to_t *to;
	const char *to_tag=NULL;

	from=belle_sip_message_get_header_by_type(t->request,belle_sip_header_from_t);
	if (from==NULL){
		belle_sip_error("belle_sip_dialog_new(): no from!");
		return NULL;
	}
	from_tag=belle_sip_header_from_get_tag(from);
	if (from_tag==NULL){
		belle_sip_error("belle_sip_dialog_new(): no from tag!");
		return NULL;
	}

	if (t->last_response) {
		to=belle_sip_message_get_header_by_type(t->last_response,belle_sip_header_to_t);
		if (to==NULL){
			belle_sip_error("belle_sip_dialog_new(): no to!");
			return NULL;
		}
		to_tag=belle_sip_header_to_get_tag(to);
	}
	obj=belle_sip_object_new(belle_sip_dialog_t);
	obj->terminate_on_bye=1;
	obj->provider=t->provider;
	
	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_server_transaction_t)){
		obj->remote_tag=belle_sip_strdup(from_tag);
		obj->local_tag=to_tag?belle_sip_strdup(to_tag):NULL; /*might be null at dialog creation*/
		obj->remote_party=(belle_sip_header_address_t*)belle_sip_object_ref(from);
		obj->is_server=TRUE;
	}else{
		const belle_sip_list_t *predefined_routes=NULL;
		obj->local_tag=belle_sip_strdup(from_tag);
		obj->remote_tag=to_tag?belle_sip_strdup(to_tag):NULL; /*might be null at dialog creation*/
		obj->local_party=(belle_sip_header_address_t*)belle_sip_object_ref(from);
		obj->is_server=FALSE;
		for(predefined_routes=belle_sip_message_get_headers((belle_sip_message_t*)t->request,BELLE_SIP_ROUTE);
			predefined_routes!=NULL;predefined_routes=predefined_routes->next){
			obj->route_set=belle_sip_list_append(obj->route_set,belle_sip_object_ref(predefined_routes->data));	
		}
	}
	belle_sip_message("New %s dialog [%p] , local tag [%s], remote tag [%s]"
			,obj->is_server?"server":"client"
			,obj
			,obj->local_tag?obj->local_tag:""
			,obj->remote_tag?obj->remote_tag:"");
	set_state(obj,BELLE_SIP_DIALOG_NULL);
	return obj;
}
Exemplo n.º 10
0
void belle_sip_listening_point_add_channel(belle_sip_listening_point_t *lp, belle_sip_channel_t *chan){
	chan->lp=lp;
	belle_sip_channel_add_listener(chan,lp->channel_listener); /*add channel listener*/
	/*channel is already owned, no ref needed - REVISIT: channel should be initally unowned probably.*/
	
	/* The channel with names must be treated with higher priority by the get_channel() method so queued on front.
	 * This is to prevent the UDP listening point to dispatch incoming messages to channels that were created by inbound connection
	 * where name cannot be determined. When this arrives, there can be 2 channels for the same destination IP and strange problems can occur
	 * where requests are sent through name qualified channel and response received through name unqualified channel.
	 */
	if (chan->has_name)
		lp->channels=belle_sip_list_prepend(lp->channels,chan);
	else
		lp->channels=belle_sip_list_append(lp->channels,chan);
}
Exemplo n.º 11
0
static int belle_sip_dialog_init_as_uas(belle_sip_dialog_t *obj, belle_sip_request_t *req, belle_sip_response_t *resp){
	const belle_sip_list_t *elem;
	belle_sip_header_contact_t *ct=belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t);
	belle_sip_header_cseq_t *cseq=belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
	belle_sip_header_to_t *to=belle_sip_message_get_header_by_type(resp,belle_sip_header_to_t);
	belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(req,belle_sip_header_via_t);
	belle_sip_uri_t *requri=belle_sip_request_get_uri(req);

	if (!ct){
		belle_sip_error("No contact in request.");
		return -1;
	}
	if (!to){
		belle_sip_error("No to in response.");
		return -1;
	}
	if (!cseq){
		belle_sip_error("No cseq in request.");
		return -1;
	}
	if (!via){
		belle_sip_error("No via in request.");
		return -1;
	}
	if (strcasecmp(belle_sip_header_via_get_protocol(via),"TLS")==0
	    && belle_sip_uri_is_secure(requri)){
		obj->is_secure=TRUE;
	}
	/* 12.1.1
	*The route set MUST be set to the list of URIs in the Record-Route
	* header field from the request, taken in order and preserving all URI
	* parameters.  If no Record-Route header field is present in the
	*request, the route set MUST be set to the empty set.
	*/
	obj->route_set=belle_sip_list_free_with_data(obj->route_set,belle_sip_object_unref);
	for(elem=belle_sip_message_get_headers((belle_sip_message_t*)req,BELLE_SIP_RECORD_ROUTE);elem!=NULL;elem=elem->next){
		obj->route_set=belle_sip_list_append(obj->route_set,belle_sip_object_ref(belle_sip_header_route_create(
		                                     (belle_sip_header_address_t*)elem->data)));
	}
	check_route_set(obj->route_set);
	obj->remote_target=(belle_sip_header_address_t*)belle_sip_object_ref(ct);
	obj->remote_cseq=belle_sip_header_cseq_get_seq_number(cseq);
	/*call id already set */
	/*remote party already set */
	obj->local_party=(belle_sip_header_address_t*)belle_sip_object_ref(to);

	return 0;
}
Exemplo n.º 12
0
belle_sip_list_t* belle_sip_list_insert(belle_sip_list_t* list, belle_sip_list_t* before, void *data){
	belle_sip_list_t* elem;
	if (list==NULL || before==NULL) return belle_sip_list_append(list,data);
	for(elem=list;elem!=NULL;elem=belle_sip_list_next(elem)){
		if (elem==before){
			if (elem->prev==NULL)
				return belle_sip_list_prepend(list,data);
			else{
				belle_sip_list_t* nelem=belle_sip_list_new(data);
				nelem->prev=elem->prev;
				nelem->next=elem;
				elem->prev->next=nelem;
				elem->prev=nelem;
			}
		}
	}
	return list;
}
Exemplo n.º 13
0
static int keep_alive_timer_func(void *user_data, unsigned int events) {
	belle_sip_listening_point_t* lp=(belle_sip_listening_point_t*)user_data;
	belle_sip_list_t* iterator;
	belle_sip_channel_t* channel;
	belle_sip_list_t *to_be_closed=NULL;

	for (iterator=lp->channels;iterator!=NULL;iterator=iterator->next) {
		channel=(belle_sip_channel_t*)iterator->data;
		if (channel->state == BELLE_SIP_CHANNEL_READY && send_keep_alive(channel)==-1) { /*only send keep alive if ready*/
			to_be_closed=belle_sip_list_append(to_be_closed,channel);
		}
	}
	for (iterator=to_be_closed;iterator!=NULL;iterator=iterator->next){
		channel=(belle_sip_channel_t*)iterator->data;
		channel_set_state(channel,BELLE_SIP_CHANNEL_ERROR);
		belle_sip_channel_close(channel);
	}
	belle_sip_list_free(to_be_closed);
	return BELLE_SIP_CONTINUE_WITHOUT_CATCHUP;
}
Exemplo n.º 14
0
static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
	belle_http_channel_context_t *ctx=BELLE_HTTP_CHANNEL_CONTEXT(obj);
	ctx->pending_requests=belle_sip_list_append(ctx->pending_requests,belle_sip_object_ref(msg));
}
Exemplo n.º 15
0
static void _linphone_xml_rpc_request_add_int_arg(LinphoneXmlRpcRequest *request, int value) {
    LinphoneXmlRpcArg *arg = belle_sip_malloc0(sizeof(LinphoneXmlRpcArg));
    arg->type = LinphoneXmlRpcArgInt;
    arg->data.i = value;
    request->arg_list = belle_sip_list_append(request->arg_list, arg);
}
Exemplo n.º 16
0
static void stream_description_to_sdp ( belle_sdp_session_description_t *session_desc, const SalMediaDescription *md, const SalStreamDescription *stream ) {
	belle_sdp_mime_parameter_t* mime_param;
	belle_sdp_media_description_t* media_desc;
	int j;
	MSList* pt_it;
	PayloadType* pt;
	char buffer[1024];
	char* dir=NULL;
	const char *rtp_addr;
	const char *rtcp_addr;
	int rtp_port;
	int rtcp_port;
	bool_t different_rtp_and_rtcp_addr;
	
	rtp_addr=stream->rtp_addr;
	rtcp_addr=stream->rtcp_addr;
	rtp_port=stream->rtp_port;
	rtcp_port=stream->rtcp_port;
	
	media_desc = belle_sdp_media_description_create ( sal_stream_description_get_type_as_string(stream)
				 ,stream->rtp_port
				 ,1
				 ,sal_media_proto_to_string ( stream->proto )
				 ,NULL );
	if (stream->payloads) {
		for ( pt_it=stream->payloads; pt_it!=NULL; pt_it=pt_it->next ) {
			pt= ( PayloadType* ) pt_it->data;
			mime_param= belle_sdp_mime_parameter_create ( pt->mime_type
					, payload_type_get_number ( pt )
					, pt->clock_rate
					,stream->type==SalAudio?1:-1 );
			belle_sdp_mime_parameter_set_parameters ( mime_param,pt->recv_fmtp );
			if ( stream->ptime>0 ) {
				belle_sdp_mime_parameter_set_ptime ( mime_param,stream->ptime );
			}
			belle_sdp_media_description_append_values_from_mime_parameter ( media_desc,mime_param );
			belle_sip_object_unref ( mime_param );
		}
	} else {
		/* to comply with SDP we cannot have an empty payload type number list */
		/* as it happens only when mline is declined with a zero port, it does not matter to put whatever codec*/
		belle_sip_list_t* format = belle_sip_list_append(NULL,0);
		belle_sdp_media_set_media_formats(belle_sdp_media_description_get_media(media_desc),format);
	}
	/*only add a c= line within the stream description if address are differents*/
	if (rtp_addr[0]!='\0' && strcmp(rtp_addr,md->addr)!=0){
		bool_t inet6;
		if (strchr(rtp_addr,':')!=NULL){
			inet6=TRUE;
		}else inet6=FALSE;
		belle_sdp_media_description_set_connection(media_desc,belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr));
	}
	
	if ( stream->bandwidth>0 )
		belle_sdp_media_description_set_bandwidth ( media_desc,"AS",stream->bandwidth );

	if ( stream->proto == SalProtoRtpSavp ) {
		/* add crypto lines */
		for ( j=0; j<SAL_CRYPTO_ALGO_MAX; j++ ) {

			switch ( stream->crypto[j].algo ) {
				case AES_128_SHA1_80:
					snprintf ( buffer, sizeof ( buffer ), "%d %s inline:%s",
							   stream->crypto[j].tag, "AES_CM_128_HMAC_SHA1_80", stream->crypto[j].master_key );
					belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( "crypto",buffer ) );
					break;
				case AES_128_SHA1_32:
					snprintf ( buffer, sizeof ( buffer ), "%d %s inline:%s",
							   stream->crypto[j].tag, "AES_CM_128_HMAC_SHA1_32", stream->crypto[j].master_key );
					belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( "crypto",buffer ) );
					break;
				case AES_128_NO_AUTH:
					ms_warning ( "Unsupported crypto suite: AES_128_NO_AUTH" );
					break;
				case NO_CIPHER_SHA1_80:
					ms_warning ( "Unsupported crypto suite: NO_CIPHER_SHA1_80" );
					break;
				default:
					j = SAL_CRYPTO_ALGO_MAX;
					/* no break */
			}
		}
	}
	switch ( stream->dir ) {
		case SalStreamSendRecv:
			/*dir="sendrecv";*/
			dir=NULL;
			break;
		case SalStreamRecvOnly:
			dir="recvonly";
			break;
		case SalStreamSendOnly:
			dir="sendonly";
			break;
		case SalStreamInactive:
			dir="inactive";
			break;
	}
	if ( dir ) belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( dir,NULL ) );
	
	if (rtp_port != 0) {
		different_rtp_and_rtcp_addr = (rtcp_addr[0] != '\0') && (strcmp(rtp_addr, rtcp_addr) != 0);
		if ((rtcp_port != (rtp_port + 1)) || (different_rtp_and_rtcp_addr == TRUE)) {
			if (different_rtp_and_rtcp_addr == TRUE) {
				snprintf(buffer, sizeof(buffer), "%u IN IP4 %s", rtcp_port, rtcp_addr);
			} else {
				snprintf(buffer, sizeof(buffer), "%u",rtcp_port);
			}
			belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("rtcp",buffer));
		}
	}
	if (stream->ice_completed == TRUE) {
		belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("nortpproxy","yes"));
	}
	if (stream->ice_mismatch == TRUE) {
		belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-mismatch",NULL));
	} else {
		if (rtp_port != 0) {
			if (stream->ice_pwd[0] != '\0') 
				belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-pwd",stream->ice_pwd));
			if (stream->ice_ufrag[0] != '\0')
				belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-ufrag",stream->ice_ufrag));
			add_ice_candidates(media_desc,stream);
			add_ice_remote_candidates(media_desc,stream);
		}
	}

	if (stream->rtcp_xr.enabled == TRUE) {
		char sastr[1024] = {0};
		char mastr[1024] = {0};
		size_t saoff = 0;
		size_t maoff = 0;
		const belle_sdp_attribute_t *session_attribute = belle_sdp_session_description_get_attribute(session_desc, "rtcp-xr");
		belle_sdp_attribute_t *media_attribute;
		if (session_attribute != NULL) {
			belle_sip_object_marshal((belle_sip_object_t*)session_attribute, sastr, sizeof(sastr), &saoff);
		}
		media_attribute = create_rtcp_xr_attribute(&stream->rtcp_xr);
		if (media_attribute != NULL) {
			belle_sip_object_marshal((belle_sip_object_t*)media_attribute, mastr, sizeof(mastr), &maoff);
		}
		if (strcmp(sastr, mastr) != 0) {
			belle_sdp_media_description_add_attribute(media_desc, media_attribute);
		} else {
			belle_sip_object_unref((belle_sip_object_t*)media_attribute);
		}
	}

	belle_sdp_session_description_add_media_description(session_desc, media_desc);
}
Exemplo n.º 17
0
void belle_sip_channel_add_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
	obj->listeners=belle_sip_list_append(obj->listeners,
	                belle_sip_object_weak_ref(l,
	                (belle_sip_object_destroy_notify_t)channel_remove_listener,obj));
}
Exemplo n.º 18
0
static void _linphone_xml_rpc_request_add_string_arg(LinphoneXmlRpcRequest *request, const char *value) {
    LinphoneXmlRpcArg *arg = belle_sip_malloc0(sizeof(LinphoneXmlRpcArg));
    arg->type = LinphoneXmlRpcArgString;
    arg->data.s = belle_sip_strdup(value);
    request->arg_list = belle_sip_list_append(request->arg_list, arg);
}
Exemplo n.º 19
0
static void channel_push_outgoing(belle_sip_channel_t *obj, belle_sip_message_t *msg){
	obj->outgoing_messages=belle_sip_list_append(obj->outgoing_messages,msg);
}
Exemplo n.º 20
0
void belle_sip_body_handler_add_header(belle_sip_body_handler_t *obj, belle_sip_header_t *header) {
	if (header != NULL) {
		obj->headers=belle_sip_list_append(obj->headers,belle_sip_object_ref(header));
	}
}
Exemplo n.º 21
0
void belle_sip_dialog_queue_client_transaction(belle_sip_dialog_t *dialog, belle_sip_client_transaction_t *tr){
	dialog->queued_ct=belle_sip_list_append(dialog->queued_ct, belle_sip_object_ref(tr));
}
Exemplo n.º 22
0
void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
	size_t pfd_size = ml->nsources * sizeof(belle_sip_pollfd_t);
	belle_sip_pollfd_t *pfd=(belle_sip_pollfd_t*)belle_sip_malloc0(pfd_size);
	int i=0;
	belle_sip_source_t *s;
	belle_sip_list_t *elem,*next;
	uint64_t min_time_ms=(uint64_t)-1;
	int duration=-1;
	int ret;
	uint64_t cur;
	belle_sip_list_t *to_be_notified=NULL;
	int can_clean=belle_sip_object_pool_cleanable(ml->pool); /*iterate might not be called by the thread that created the main loop*/ 
	belle_sip_object_pool_t *tmp_pool=NULL;
	
	if (!can_clean){
		/*Push a temporary pool for the time of the iterate loop*/
		tmp_pool=belle_sip_object_pool_push();
	}
	
	/*Step 1: prepare the pollfd table and get the next timeout value */
	for(elem=ml->sources;elem!=NULL;elem=next){
		next=elem->next;
		s=(belle_sip_source_t*)elem->data;
		if (!s->cancelled){
			if (s->fd!=(belle_sip_fd_t)-1){
				belle_sip_source_to_poll(s,pfd,i);
				++i;
			}
			if (s->timeout>=0){
				if (min_time_ms>s->expire_ms){
					min_time_ms=s->expire_ms;
				}
			}
		}
	}
	
	if (min_time_ms!=(uint64_t)-1 ){
		int64_t diff;
		/* compute the amount of time to wait for shortest timeout*/
		cur=belle_sip_time_ms();
		diff=min_time_ms-cur;
		if (diff>0)
			duration=(int)diff;
		else 
			duration=0;
	}
	/* do the poll */
	ret=belle_sip_poll(pfd,i,duration);
	if (ret==-1){
		goto end;
	}
	
	/* Step 2: examine poll results and determine the list of source to be notified */
	cur=belle_sip_time_ms();
	for(elem=ml->sources;elem!=NULL;elem=elem->next){
		unsigned revents=0;
		s=(belle_sip_source_t*)elem->data;

		if (!s->cancelled){
			if (s->fd!=(belle_sip_fd_t)-1){
				if (s->notify_required) { /*for testing purpose to force channel to read*/
					revents=BELLE_SIP_EVENT_READ;
					s->notify_required=0; /*reset*/
				} else {
					revents=belle_sip_source_get_revents(s,pfd);
				}
				s->revents=revents;
			}
			if (revents!=0 || (s->timeout>=0 && cur>=s->expire_ms)){
				to_be_notified=belle_sip_list_append(to_be_notified,belle_sip_object_ref(s));
				s->expired=TRUE;
				if (s->revents==0)
					s->revents=BELLE_SIP_EVENT_TIMEOUT;
			}
		}else to_be_notified=belle_sip_list_append(to_be_notified,belle_sip_object_ref(s));
	}
	
	/* Step 3: notify those to be notified */
	for(elem=to_be_notified;elem!=NULL;){
		s=(belle_sip_source_t*)elem->data;
		next=elem->next;
		if (!s->cancelled){
			char *objdesc=belle_sip_object_to_string((belle_sip_object_t*)s);
			if (s->timeout>0)/*to avoid too many traces*/ belle_sip_debug("source %s notified revents=%u, timeout=%i",objdesc,revents,s->timeout);
			belle_sip_free(objdesc);
			ret=s->notify(s->data,s->revents);
			if (ret==BELLE_SIP_STOP || s->oneshot){
				/*this source needs to be removed*/
				belle_sip_main_loop_remove_source(ml,s);
			}else if (s->revents==BELLE_SIP_EVENT_TIMEOUT){
				/*timeout needs to be started again */
				s->expire_ms+=s->timeout;
				s->expired=FALSE;
			}
		}else belle_sip_main_loop_remove_source(ml,s);
		belle_sip_object_unref(s);
		belle_sip_free(elem); /*free just the element*/
		elem=next;
	}
	
	if (can_clean) belle_sip_object_pool_clean(ml->pool);
	else if (tmp_pool) belle_sip_object_unref(tmp_pool);
end:
	belle_sip_free(pfd);
}
Exemplo n.º 23
0
static void stream_description_to_sdp ( belle_sdp_session_description_t *session_desc, const SalMediaDescription *md, const SalStreamDescription *stream ) {
	belle_sdp_mime_parameter_t* mime_param;
	belle_sdp_media_description_t* media_desc;
	int j;
	MSList* pt_it;
	PayloadType* pt;
	char buffer[1024];
	char* dir=NULL;
	const char *rtp_addr;
	const char *rtcp_addr;
	int rtp_port;
	int rtcp_port;
	bool_t different_rtp_and_rtcp_addr;

	rtp_addr=stream->rtp_addr;
	rtcp_addr=stream->rtcp_addr;
	rtp_port=stream->rtp_port;
	rtcp_port=stream->rtcp_port;

	media_desc = belle_sdp_media_description_create ( sal_stream_description_get_type_as_string(stream)
				 ,stream->rtp_port
				 ,1
				 ,sal_media_proto_to_string ( stream->proto )
				 ,NULL );
	if (stream->payloads) {
		for ( pt_it=stream->payloads; pt_it!=NULL; pt_it=pt_it->next ) {
			pt= ( PayloadType* ) pt_it->data;
			mime_param= belle_sdp_mime_parameter_create ( pt->mime_type
					, payload_type_get_number ( pt )
					, pt->clock_rate
					, pt->channels>0 ? pt->channels : -1 );
			belle_sdp_mime_parameter_set_parameters ( mime_param,pt->recv_fmtp );
			if ( stream->ptime>0 ) {
				belle_sdp_mime_parameter_set_ptime ( mime_param,stream->ptime );
			}
			belle_sdp_media_description_append_values_from_mime_parameter ( media_desc,mime_param );
			belle_sip_object_unref ( mime_param );
		}
	} else {
		/* to comply with SDP we cannot have an empty payload type number list */
		/* as it happens only when mline is declined with a zero port, it does not matter to put whatever codec*/
		belle_sip_list_t* format = belle_sip_list_append(NULL,0);
		belle_sdp_media_set_media_formats(belle_sdp_media_description_get_media(media_desc),format);
	}
	/*only add a c= line within the stream description if address are differents*/
	if (rtp_addr[0]!='\0' && strcmp(rtp_addr,md->addr)!=0){
		bool_t inet6;
		belle_sdp_connection_t *connection;
		if (strchr(rtp_addr,':')!=NULL){
			inet6=TRUE;
		}else inet6=FALSE;
		connection = belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr);
		if (ms_is_multicast(rtp_addr)) {
			/*remove session cline in case of multicast*/
			belle_sdp_session_description_set_connection(session_desc,NULL);
			if (inet6 == FALSE)
				belle_sdp_connection_set_ttl(connection,stream->ttl);
		}
		belle_sdp_media_description_set_connection(media_desc,connection);
	}

	if ( stream->bandwidth>0 )
		belle_sdp_media_description_set_bandwidth ( media_desc,"AS",stream->bandwidth );

	if ((stream->proto == SalProtoRtpSavpf) || (stream->proto == SalProtoRtpSavp)) {
		/* add crypto lines */
		for ( j=0; j<SAL_CRYPTO_ALGO_MAX; j++ ) {
			MSCryptoSuiteNameParams desc;
			if (ms_crypto_suite_to_name_params(stream->crypto[j].algo,&desc)==0){
				if (desc.params)
					snprintf ( buffer, sizeof ( buffer )-1, "%d %s inline:%s %s", stream->crypto[j].tag, desc.name, stream->crypto[j].master_key,desc.params);
				else 
					snprintf ( buffer, sizeof ( buffer )-1, "%d %s inline:%s", stream->crypto[j].tag, desc.name, stream->crypto[j].master_key );
				
				belle_sdp_media_description_add_attribute( media_desc,belle_sdp_attribute_create ("crypto", buffer));
			}else break;
		}
	}

	/* insert DTLS session attribute if needed */
	if ((stream->proto == SalProtoUdpTlsRtpSavpf) || (stream->proto == SalProtoUdpTlsRtpSavp)) {
		char* ssrc_attribute = ms_strdup_printf("%u cname:%s",htonl(stream->rtp_ssrc),stream->rtcp_cname);
		if ((stream->dtls_role != SalDtlsRoleInvalid) && (strlen(stream->dtls_fingerprint)>0)) {
			switch(stream->dtls_role) {
				case SalDtlsRoleIsClient:
					belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","active"));
					break;
				case SalDtlsRoleIsServer:
					belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","passive"));
					break;
				case SalDtlsRoleUnset:
				default:
					belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","actpass"));
					break;
			}
			belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("fingerprint",stream->dtls_fingerprint));
		}
		belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("ssrc",ssrc_attribute)); /* truc de Jehan a virer? */
		ms_free(ssrc_attribute);
	}

	switch ( stream->dir ) {
		case SalStreamSendRecv:
			/*dir="sendrecv";*/
			dir=NULL;
			break;
		case SalStreamRecvOnly:
			dir="recvonly";
			break;
		case SalStreamSendOnly:
			dir="sendonly";
			break;
		case SalStreamInactive:
			dir="inactive";
			break;
	}
	if ( dir ) belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( dir,NULL ) );
	
	if (rtp_port != 0) {
		different_rtp_and_rtcp_addr = (rtcp_addr[0] != '\0') && (strcmp(rtp_addr, rtcp_addr) != 0);
		if ((rtcp_port != (rtp_port + 1)) || (different_rtp_and_rtcp_addr == TRUE)) {
			if (different_rtp_and_rtcp_addr == TRUE) {
				snprintf(buffer, sizeof(buffer), "%u IN IP4 %s", rtcp_port, rtcp_addr);
			} else {
				snprintf(buffer, sizeof(buffer), "%u",rtcp_port);
			}
			belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("rtcp",buffer));
		}
	}
	if (stream->ice_completed == TRUE) {
		belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("nortpproxy","yes"));
	}
	if (stream->ice_mismatch == TRUE) {
		belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-mismatch",NULL));
	} else {
		if (rtp_port != 0) {
			if (stream->ice_pwd[0] != '\0') 
				belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-pwd",stream->ice_pwd));
			if (stream->ice_ufrag[0] != '\0')
				belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-ufrag",stream->ice_ufrag));
			add_ice_candidates(media_desc,stream);
			add_ice_remote_candidates(media_desc,stream);
		}
	}

	if ((rtp_port != 0) && ((stream->proto == SalProtoRtpAvpf) || (stream->proto == SalProtoRtpSavpf))) {
		add_rtcp_fb_attributes(media_desc, md, stream);
	}

	if ((rtp_port != 0) && (stream->rtcp_xr.enabled == TRUE)) {
		char sastr[1024] = {0};
		char mastr[1024] = {0};
		size_t saoff = 0;
		size_t maoff = 0;
		const belle_sdp_attribute_t *session_attribute = belle_sdp_session_description_get_attribute(session_desc, "rtcp-xr");
		belle_sdp_attribute_t *media_attribute;
		if (session_attribute != NULL) {
			belle_sip_object_marshal((belle_sip_object_t*)session_attribute, sastr, sizeof(sastr), &saoff);
		}
		media_attribute = create_rtcp_xr_attribute(&stream->rtcp_xr);
		if (media_attribute != NULL) {
			belle_sip_object_marshal((belle_sip_object_t*)media_attribute, mastr, sizeof(mastr), &maoff);
		}
		if (strcmp(sastr, mastr) != 0) {
			belle_sdp_media_description_add_attribute(media_desc, media_attribute);
		} else {
			belle_sip_object_unref((belle_sip_object_t*)media_attribute);
		}
	}
	/*
	 * rfc5576
	 * 4.1.  The "ssrc" Media Attribute
	 * <ssrc-id> is the synchronization source (SSRC) ID of the
	 * source being described, interpreted as a 32-bit unsigned integer in
	 * network byte order and represented in decimal.*/


	belle_sdp_session_description_add_media_description(session_desc, media_desc);
}