Exemplo n.º 1
0
static void http_provider_uninit(belle_http_provider_t *obj){
	belle_sip_message("http provider destroyed.");
	belle_sip_free(obj->bind_ip);
	belle_sip_list_for_each(obj->tcp_channels,(void (*)(void*))belle_sip_channel_force_close);
	belle_sip_list_free_with_data(obj->tcp_channels,belle_sip_object_unref);
	belle_sip_list_for_each(obj->tls_channels,(void (*)(void*))belle_sip_channel_force_close);
	belle_sip_list_free_with_data(obj->tls_channels,belle_sip_object_unref);
	belle_sip_object_unref(obj->verify_ctx);
}
Exemplo n.º 2
0
void sal_process_authentication(SalOp *op) {
	belle_sip_request_t* request=belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_auth_transaction);
	bool_t is_within_dialog=FALSE;
	belle_sip_list_t* auth_list=NULL;
	belle_sip_auth_event_t* auth_event;
	belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction);
	
	sal_add_pending_auth(op->base.root,op);
	
	if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_CONFIRMED) {
		request = belle_sip_dialog_create_request_from(op->dialog,(const belle_sip_request_t *)request);
		is_within_dialog=TRUE;
	} else {
		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION);
		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION);
	}
	if (belle_sip_provider_add_authorization(op->base.root->prov,request,response,&auth_list)) {
		if (is_within_dialog) {
			sal_op_send_request(op,request);
		} else {
			sal_op_resend_request(op,request);
		}
		sal_remove_pending_auth(op->base.root,op);
	}else {
		ms_message("No auth info found for [%s]",sal_op_get_from(op));
		if (is_within_dialog) {
			belle_sip_object_unref(request);
		}
		if (op->auth_info) sal_auth_info_delete(op->auth_info);
		auth_event=(belle_sip_auth_event_t*)(auth_list->data);
		op->auth_info=sal_auth_info_create(auth_event);
		belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy);
	}

}
Exemplo n.º 3
0
static void sdp_parse_payload_types(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) {
	PayloadType *pt;
	PayloadTypeAvpfParams avpf_params;
	belle_sip_list_t* mime_param_it=NULL;
	belle_sdp_mime_parameter_t* mime_param;
	belle_sip_list_t* mime_params=belle_sdp_media_description_build_mime_parameters ( media_desc );
	memset(&avpf_params, 0, sizeof(avpf_params));
	for ( mime_param_it=mime_params
						; mime_param_it!=NULL
			; mime_param_it=mime_param_it->next ) {
		mime_param=BELLE_SDP_MIME_PARAMETER ( mime_param_it->data );

		pt=payload_type_new();
		payload_type_set_number ( pt,belle_sdp_mime_parameter_get_media_format ( mime_param ) );
		pt->clock_rate=belle_sdp_mime_parameter_get_rate ( mime_param );
		pt->mime_type=ms_strdup ( belle_sdp_mime_parameter_get_type ( mime_param ) );
		pt->channels=belle_sdp_mime_parameter_get_channel_count ( mime_param );
		payload_type_set_send_fmtp ( pt,belle_sdp_mime_parameter_get_parameters ( mime_param ) );
		payload_type_set_avpf_params(pt, avpf_params);
		stream->payloads=ms_list_append ( stream->payloads,pt );
		stream->ptime=belle_sdp_mime_parameter_get_ptime ( mime_param );
		ms_message ( "Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate,
						pt->send_fmtp ? pt->send_fmtp : "" );
	}
	if ( mime_params ) belle_sip_list_free_with_data ( mime_params,belle_sip_object_unref );
}
Exemplo n.º 4
0
static void belle_sip_dialog_uninit(belle_sip_dialog_t *obj){
	if (obj->route_set)
		belle_sip_list_free_with_data(obj->route_set,belle_sip_object_unref);
	if (obj->remote_target)
		belle_sip_object_unref(obj->remote_target);
	if (obj->call_id)
		belle_sip_object_unref(obj->call_id);
	if (obj->local_party)
		belle_sip_object_unref(obj->local_party);
	if (obj->remote_party)
		belle_sip_object_unref(obj->remote_party);
	if (obj->local_tag)
		belle_sip_free(obj->local_tag);
	if (obj->remote_tag)
		belle_sip_free(obj->remote_tag);
	if (obj->last_out_invite)
		belle_sip_object_unref(obj->last_out_invite);
	if (obj->last_out_ack)
		belle_sip_object_unref(obj->last_out_ack);
	if (obj->last_transaction)
		belle_sip_object_unref(obj->last_transaction);
	if(obj->privacy)
		belle_sip_object_unref(obj->privacy);
/*	if(obj->preferred_identity)
			belle_sip_object_unref(obj->preferred_identity);*/
}
Exemplo n.º 5
0
void sal_process_authentication(SalOp *op) {
	belle_sip_request_t* initial_request=belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_auth_transaction);
	belle_sip_request_t* new_request;
	bool_t is_within_dialog=FALSE;
	belle_sip_list_t* auth_list=NULL;
	belle_sip_auth_event_t* auth_event;
	belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction);
	belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(initial_request,belle_sip_header_from_t);
	belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from);

	if (strcasecmp(belle_sip_uri_get_host(from_uri),"anonymous.invalid")==0){
		/*prefer using the from from the SalOp*/
		from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)sal_op_get_from_address(op));
	}

	if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_CONFIRMED) {
		new_request = belle_sip_dialog_create_request_from(op->dialog,initial_request);
		if (!new_request)
			new_request = belle_sip_dialog_create_queued_request_from(op->dialog,initial_request);
		is_within_dialog=TRUE;
	} else {
		new_request=initial_request;
		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_AUTHORIZATION);
		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_PROXY_AUTHORIZATION);
	}
	if (new_request==NULL) {
		ms_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",op);
		return;
	}

	if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list,op->base.realm)) {
		if (is_within_dialog) {
			sal_op_send_request(op,new_request);
		} else {
			sal_op_resend_request(op,new_request);
		}
		sal_remove_pending_auth(op->base.root,op);
	}else {
		belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(response,belle_sip_header_from_t);
		char *tmp=belle_sip_object_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from)));
		ms_message("No auth info found for [%s]",tmp);
		belle_sip_free(tmp);
		sal_add_pending_auth(op->base.root,op);

		if (is_within_dialog) {
			belle_sip_object_unref(new_request);
		}
	}
	/*always store auth info, for case of wrong credential*/
	if (op->auth_info) {
		sal_auth_info_delete(op->auth_info);
		op->auth_info=NULL;
	}
	if (auth_list){
		auth_event=(belle_sip_auth_event_t*)(auth_list->data);
		op->auth_info=sal_auth_info_create(auth_event);
		belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy);
	}
}
Exemplo n.º 6
0
static void _linphone_xml_rpc_request_destroy(LinphoneXmlRpcRequest *request) {
    belle_sip_list_free_with_data(request->arg_list, (void (*)(void*))free_arg);
    if ((request->response.type == LinphoneXmlRpcArgString) && (request->response.data.s != NULL)) {
        belle_sip_free(request->response.data.s);
    }
    if (request->content) belle_sip_free(request->content);
    belle_sip_free(request->method);
    linphone_xml_rpc_request_cbs_unref(request->callbacks);
}
Exemplo n.º 7
0
static void notify_incoming_messages(belle_sip_channel_t *obj){
	belle_sip_list_t *elem,*l_it;
	belle_sip_list_t *listeners=belle_sip_list_copy_with_data(obj->listeners,(void *(*)(void*))belle_sip_object_ref);
	
	for(l_it=listeners;l_it!=NULL;l_it=l_it->next){
		belle_sip_channel_listener_t *listener=(belle_sip_channel_listener_t*)l_it->data;
		for(elem=obj->incoming_messages;elem!=NULL;elem=elem->next){
			belle_sip_message_t *msg=(belle_sip_message_t*)elem->data;
			BELLE_SIP_INTERFACE_METHODS_TYPE(belle_sip_channel_listener_t) *methods;
			methods=BELLE_SIP_INTERFACE_GET_METHODS(listener,belle_sip_channel_listener_t);
			if (methods->on_message)
				methods->on_message(listener,obj,msg);
		}
	}
	belle_sip_list_free_with_data(listeners,belle_sip_object_unref);
	belle_sip_list_free_with_data(obj->incoming_messages,belle_sip_object_unref);
	obj->incoming_messages=NULL;
}
Exemplo n.º 8
0
static void destroy(belle_sip_refresher_t *refresher){
	belle_sip_refresher_stop(refresher);
	belle_sip_provider_remove_internal_sip_listener(refresher->transaction->base.provider,BELLE_SIP_LISTENER(refresher));
	belle_sip_object_unref(refresher->transaction);
	refresher->transaction=NULL;
	if (refresher->realm) belle_sip_free(refresher->realm);
	if (refresher->auth_events) refresher->auth_events=belle_sip_list_free_with_data(refresher->auth_events,(void (*)(void*))belle_sip_auth_event_destroy);
	if (refresher->first_acknoleged_request) belle_sip_object_unref(refresher->first_acknoleged_request);
	if (refresher->dialog) belle_sip_object_unref(refresher->dialog);
}
Exemplo n.º 9
0
void belle_sip_dialog_delete(belle_sip_dialog_t *obj){
	int dropped_transactions;
	
	belle_sip_dialog_stop_200Ok_retrans(obj); /*if any*/
	set_state(obj,BELLE_SIP_DIALOG_TERMINATED);
	dropped_transactions=belle_sip_list_size(obj->queued_ct);
	if (dropped_transactions>0) belle_sip_warning("dialog [%p]: leaves %i queued transaction aborted.",obj,dropped_transactions);
	belle_sip_list_for_each(obj->queued_ct,(void(*)(void*))belle_sip_transaction_terminate);
	obj->queued_ct=belle_sip_list_free_with_data(obj->queued_ct,belle_sip_object_unref);
	belle_sip_provider_remove_dialog(obj->provider,obj);
}
Exemplo n.º 10
0
static int belle_sip_dialog_init_as_uac(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(resp,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 (!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.2
	 *  The route set MUST be set to the list of URIs in the Record-Route
   	 *header field from the response, taken in reverse order and preserving
   	 *all URI parameters.  If no Record-Route header field is present in
   	 *the response, 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*)resp,BELLE_SIP_RECORD_ROUTE);elem!=NULL;elem=elem->next){
		obj->route_set=belle_sip_list_prepend(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);
	/*contact might be provided later*/
	if (ct)
		obj->remote_target=(belle_sip_header_address_t*)belle_sip_object_ref(ct);

	obj->local_cseq=belle_sip_header_cseq_get_seq_number(cseq);
	/*call id is already set */
	/*local_tag is already set*/
	obj->remote_party=(belle_sip_header_address_t*)belle_sip_object_ref(to);
	/*local party is already set*/
	if (strcmp(belle_sip_request_get_method(req),"INVITE")==0){
		set_last_out_invite(obj,req);
	}
	return 0;
}
Exemplo n.º 11
0
void belle_sip_listening_point_clean_channels(belle_sip_listening_point_t *lp){
	int existing_channels;
	belle_sip_list_t* iterator;
	
	if ((existing_channels=belle_sip_list_size(lp->channels)) > 0) {
		belle_sip_message("Listening point destroying [%i] channels",existing_channels);
	}
	for (iterator=lp->channels;iterator!=NULL;iterator=iterator->next) {
		belle_sip_channel_t *chan=(belle_sip_channel_t*)iterator->data;
		belle_sip_channel_force_close(chan);
	}
	lp->channels=belle_sip_list_free_with_data(lp->channels,(void (*)(void*))belle_sip_object_unref);
}
static void reset_endpoint(endpoint_t *endpoint) {
	endpoint->resolver_ctx = 0;
	endpoint->resolve_done = 0;
	endpoint->resolve_ko = 0;
	if (endpoint->ai_list != NULL) {
		belle_sip_freeaddrinfo(endpoint->ai_list);
		endpoint->ai_list = NULL;
	}
	if (endpoint->srv_list != NULL) {
		belle_sip_list_free_with_data(endpoint->srv_list, belle_sip_object_unref);
		endpoint->srv_list = NULL;
	}
}
Exemplo n.º 13
0
void belle_http_provider_cancel_request(belle_http_provider_t *obj, belle_http_request_t *req){
	belle_sip_list_t *outgoing_messages;

	belle_http_request_cancel(req);
	if (req->channel){
		// Keep the list of the outgoing messages of the channel...
		outgoing_messages = belle_sip_list_copy_with_data(req->channel->outgoing_messages,(void* (*)(void*))belle_sip_object_ref);
		provider_remove_channel(obj, req->channel);
		// ... close the channel...
		belle_sip_channel_force_close(req->channel);
		// ... and reenqueue the previously queued outgoing messages into a new channel
		belle_sip_list_for_each2(outgoing_messages,(void (*)(void*,void*))reenqueue_request,obj);
		belle_sip_list_free_with_data(outgoing_messages,belle_sip_object_unref);
	}
}
Exemplo n.º 14
0
void sal_process_authentication(SalOp *op) {
	belle_sip_request_t* initial_request=belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_auth_transaction);
	belle_sip_request_t* new_request;
	bool_t is_within_dialog=FALSE;
	belle_sip_list_t* auth_list=NULL;
	belle_sip_auth_event_t* auth_event;
	belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction);
	

	if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_CONFIRMED) {
		new_request = belle_sip_dialog_create_request_from(op->dialog,initial_request);
		if (!new_request)
			new_request = belle_sip_dialog_create_queued_request_from(op->dialog,initial_request);
		is_within_dialog=TRUE;
	} else {
		new_request=initial_request;
		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_AUTHORIZATION);
		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_PROXY_AUTHORIZATION);
	}
	if (new_request==NULL) {
		ms_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",op);
		return;
	}
	
	if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,&auth_list)) {
		if (is_within_dialog) {
			sal_op_send_request(op,new_request);
		} else {
			sal_op_resend_request(op,new_request);
		}
		sal_remove_pending_auth(op->base.root,op);
	}else {
		ms_message("No auth info found for [%s]",sal_op_get_from(op));
		sal_add_pending_auth(op->base.root,op);

		if (is_within_dialog) {
			belle_sip_object_unref(new_request);
		}
	}
	/*always store auth info, for case of wrong credential*/
	if (op->auth_info) sal_auth_info_delete(op->auth_info);
	if (auth_list){
		auth_event=(belle_sip_auth_event_t*)(auth_list->data);
		op->auth_info=sal_auth_info_create(auth_event);
		belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy);
	}
}
Exemplo n.º 15
0
static void cleanup_pool_stack(void *data){
	belle_sip_list_t **pool_stack=(belle_sip_list_t**)data;
	if (*pool_stack){
		/*
		 * We would expect the pool_stack to be empty when the thread terminates.
		 * Otherwise that means the management of object pool is not properly done by the application.
		 * Since the object pools might be still referenced by the application, we can't destroy them.
		 * Instead, we mark them as detached, so that when the thread that will attempt to destroy them will do it,
		 * we'll accept (since anyway these object pool are no longer needed.
		 */
		belle_sip_warning("There were still [%i] object pools for thread [%lu] while the thread exited. ",
				 belle_sip_list_size(*pool_stack),belle_sip_thread_self_id());
		belle_sip_list_free_with_data(*pool_stack,(void (*)(void*)) belle_sip_object_pool_detach_from_thread);
	}
	*pool_stack=NULL;
	belle_sip_free(pool_stack);
}
Exemplo n.º 16
0
static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
	if (obj->peer_list) freeaddrinfo(obj->peer_list);
	if (obj->peer_cname) belle_sip_free(obj->peer_cname);
	belle_sip_free(obj->peer_name);
	if (obj->local_ip) belle_sip_free(obj->local_ip);
	obj->listeners=for_each_weak_unref_free(obj->listeners,(belle_sip_object_destroy_notify_t)channel_remove_listener,obj);
	if (obj->resolver_ctx>0) belle_sip_resolver_context_cancel(obj->resolver_ctx);
	if (obj->inactivity_timer){
		belle_sip_main_loop_remove_source(obj->stack->ml,obj->inactivity_timer);
		belle_sip_object_unref(obj->inactivity_timer);
	}
	if (obj->public_ip) belle_sip_free(obj->public_ip);
	if (obj->outgoing_messages) belle_sip_list_free_with_data(obj->outgoing_messages,belle_sip_object_unref);
	channel_end_send_background_task(obj);
	channel_end_recv_background_task(obj);
	/*normally this should do nothing because it sould have been terminated already,
		however leaving a background task open is so dangerous that we have to be paranoid*/
	belle_sip_message("Channel [%p] destroyed",obj);
}
Exemplo n.º 17
0
int sdp_to_media_description ( belle_sdp_session_description_t  *session_desc, SalMediaDescription *desc ) {
	/*
	typedef struct SalMediaDescription{
		int refcount;
		char addr[64];
		char username[64];
		int nstreams;
		int bandwidth;
		unsigned int session_ver;
		unsigned int session_id;
		SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
	} SalMediaDescription;
	 */
	belle_sdp_connection_t* cnx;
	belle_sip_list_t* media_desc_it;
	belle_sdp_media_description_t* media_desc;
	const char *mtype,*proto;
	SalStreamDescription *stream;
	belle_sdp_media_t* media;
	belle_sip_list_t* mime_params=NULL;
	belle_sip_list_t* mime_param_it=NULL;
	belle_sdp_mime_parameter_t* mime_param;
	PayloadType *pt;
	belle_sip_list_t* attribute_it;
	const belle_sdp_attribute_t* attribute;
	int valid_count = 0;
	char tmp[256], tmp2[256];
	int nb=0;
	SalStreamDir stream_dir=SalStreamSendRecv;
	const char* value;
	
	desc->n_active_streams = 0;
	desc->n_total_streams = 0;

	if ( ( cnx=belle_sdp_session_description_get_connection ( session_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
		strncpy ( desc->addr,belle_sdp_connection_get_address ( cnx ),sizeof ( desc->addr ) );
	}
	if ( belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ) >0 ) {
		desc->bandwidth=belle_sdp_session_description_get_bandwidth ( session_desc,"AS" );
	}
	/*in some very rare case, session attribute may set stream dir*/
	if ( belle_sdp_session_description_get_attribute ( session_desc,"sendrecv" ) ) {
		stream_dir=SalStreamSendRecv;
	} else if ( belle_sdp_session_description_get_attribute ( session_desc,"sendonly" ) ) {
		stream_dir=SalStreamSendOnly;
	} else if ( belle_sdp_session_description_get_attribute ( session_desc,"recvonly" ) ) {
		stream_dir=SalStreamRecvOnly;
	} else if ( belle_sdp_session_description_get_attribute ( session_desc,"inactive" ) ) {
		stream_dir=SalStreamInactive;
	}

	/* Get ICE remote ufrag and remote pwd, and ice_lite flag */
	value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag");
	if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag));
	
	value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-pwd");
	if (value) strncpy(desc->ice_pwd, value, sizeof(desc->ice_pwd));
	
	value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-lite");
	if (value) desc->ice_lite = TRUE;
	
	for ( media_desc_it=belle_sdp_session_description_get_media_descriptions ( session_desc )
						; media_desc_it!=NULL
			; media_desc_it=media_desc_it->next ) {
		int nb_ice_candidates=0;
		media_desc=BELLE_SDP_MEDIA_DESCRIPTION ( media_desc_it->data );
		stream=&desc->streams[desc->n_total_streams];
		media=belle_sdp_media_description_get_media ( media_desc );

		memset ( stream,0,sizeof ( *stream ) );

		proto = belle_sdp_media_get_protocol ( media );
		stream->proto=SalProtoUnknown;
		if ( proto ) {
			if ( strcasecmp ( proto,"RTP/AVP" ) ==0 )
				stream->proto=SalProtoRtpAvp;
			else if ( strcasecmp ( proto,"RTP/SAVP" ) ==0 ) {
				stream->proto=SalProtoRtpSavp;
			}
		}
		if ( ( cnx=belle_sdp_media_description_get_connection ( media_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
			strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ),sizeof ( stream->rtp_addr ) );
		}

		stream->rtp_port=belle_sdp_media_get_media_port ( media );

		if ( stream->rtp_port > 0 )
			desc->n_active_streams++;

		mtype = belle_sdp_media_get_media_type ( media );
		if ( strcasecmp ( "audio", mtype ) == 0 ) {
			stream->type=SalAudio;
		} else if ( strcasecmp ( "video", mtype ) == 0 ) {
			stream->type=SalVideo;
		} else {
			stream->type=SalOther;
			strncpy ( stream->typeother,mtype,sizeof ( stream->typeother )-1 );
		}

		if ( belle_sdp_media_description_get_bandwidth ( media_desc,"AS" ) >0 ) {
			stream->bandwidth=belle_sdp_media_description_get_bandwidth ( media_desc,"AS" );
		}


		if ( belle_sdp_media_description_get_attribute ( media_desc,"sendrecv" ) ) {
			stream->dir=SalStreamSendRecv;
		} else if ( belle_sdp_media_description_get_attribute ( media_desc,"sendonly" ) ) {
			stream->dir=SalStreamSendOnly;
		} else if ( belle_sdp_media_description_get_attribute ( media_desc,"recvonly" ) ) {
			stream->dir=SalStreamRecvOnly;
		} else if ( belle_sdp_media_description_get_attribute ( media_desc,"inactive" ) ) {
			stream->dir=SalStreamInactive;
		} else {
			stream->dir=stream_dir; /*takes default value if not present*/
		}

		/* for each payload type */
		mime_params=belle_sdp_media_description_build_mime_parameters ( media_desc );
		for ( mime_param_it=mime_params
							; mime_param_it!=NULL
				; mime_param_it=mime_param_it->next ) {
			mime_param=BELLE_SDP_MIME_PARAMETER ( mime_param_it->data )

					   pt=payload_type_new();
			payload_type_set_number ( pt,belle_sdp_mime_parameter_get_media_format ( mime_param ) );
			pt->clock_rate=belle_sdp_mime_parameter_get_rate ( mime_param );
			pt->mime_type=ms_strdup ( belle_sdp_mime_parameter_get_type ( mime_param ) );
			pt->channels=belle_sdp_mime_parameter_get_channel_count ( mime_param );
			payload_type_set_send_fmtp ( pt,belle_sdp_mime_parameter_get_parameters ( mime_param ) );
			stream->payloads=ms_list_append ( stream->payloads,pt );
			stream->ptime=belle_sdp_mime_parameter_get_ptime ( mime_param );
			ms_message ( "Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate,
						 pt->send_fmtp ? pt->send_fmtp : "" );
		}
		if ( mime_params ) belle_sip_list_free_with_data ( mime_params,belle_sip_object_unref );
		
		
		/* Get media specific RTCP attribute */
		stream->rtcp_port = stream->rtp_port + 1;
		snprintf(stream->rtcp_addr, sizeof(stream->rtcp_addr), "%s", stream->rtp_addr);
		attribute=belle_sdp_media_description_get_attribute(media_desc,"rtcp");
		if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
			char tmp[256];
			int nb = sscanf(value, "%d IN IP4 %s", &stream->rtcp_port, tmp);
			if (nb == 1) {
				/* SDP rtcp attribute only contains the port */
			} else if (nb == 2) {
				strncpy(stream->rtcp_addr, tmp, sizeof(stream->rtcp_addr));
			} else {
				ms_warning("sdp has a strange a=rtcp line (%s) nb=%i", value, nb);
			}
		}
		
		/* read crypto lines if any */
		if ( stream->proto == SalProtoRtpSavp ) {
			valid_count=0;
			memset ( &stream->crypto, 0, sizeof ( stream->crypto ) );
			for ( attribute_it=belle_sdp_media_description_get_attributes ( media_desc )
							   ; valid_count < SAL_CRYPTO_ALGO_MAX && attribute_it!=NULL;
					attribute_it=attribute_it->next ) {
				attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data );

				if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) {
					nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s",
								  &stream->crypto[valid_count].tag,
								  tmp,
								  tmp2 );
					ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
								 stream->crypto[valid_count].tag,
								 tmp,
								 tmp2 );
					if ( nb == 3 ) {
						if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_80",tmp ) == 0 )
							stream->crypto[valid_count].algo = AES_128_SHA1_80;
						else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",tmp ) == 0 )
							stream->crypto[valid_count].algo = AES_128_SHA1_32;
						else {
							ms_warning ( "Failed to parse crypto-algo: '%s'", tmp );
							stream->crypto[valid_count].algo = 0;
						}
						if ( stream->crypto[valid_count].algo ) {
							strncpy ( stream->crypto[valid_count].master_key, tmp2, 41 );
							stream->crypto[valid_count].master_key[40] = '\0';
							ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
										 stream->crypto[valid_count].tag,
										 tmp,
										 stream->crypto[valid_count].master_key );
							valid_count++;
						}
					} else {
						ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb );
					}
				}
			}
			ms_message ( "Found: %d valid crypto lines", valid_count );
		}
		
		/* Get ICE candidate attributes if any */
		for (attribute_it = belle_sdp_media_description_get_attributes(media_desc); attribute_it != NULL; attribute_it=attribute_it->next) {
			const char *att_name;
			attribute=(belle_sdp_attribute_t*)attribute_it->data;
			att_name=belle_sdp_attribute_get_name(attribute);
			value=belle_sdp_attribute_get_value(attribute);
			if ((keywordcmp("candidate", att_name) == 0) && (value != NULL)) {
				SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates];
				int nb = sscanf(value, "%s %u UDP %u %s %d typ %s raddr %s rport %d",
					candidate->foundation, &candidate->componentID, &candidate->priority, candidate->addr, &candidate->port,
					candidate->type, candidate->raddr, &candidate->rport);
				if ((nb == 6) || (nb == 8)) nb_ice_candidates++;
				else memset(candidate, 0, sizeof(*candidate));
			} else if ((keywordcmp("remote-candidates", att_name) == 0) && (value != NULL)) {
				SalIceRemoteCandidate candidate;
				unsigned int componentID;
				int offset;
				const char *ptr = value;
				const char *endptr=value+strlen(ptr);
				while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) {
					if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) {
						SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1];
						strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr));
						remote_candidate->port = candidate.port;
					}
					ptr += offset;
					if (ptr<endptr){
						if (ptr[offset] == ' ') ptr += 1;
					}else break;
				}
			} else if ((keywordcmp("ice-ufrag", att_name) == 0) && (value != NULL)) {
				strncpy(stream->ice_ufrag, value, sizeof(stream->ice_ufrag));
			} else if ((keywordcmp("ice-pwd", att_name) == 0) && (value != NULL)) {
				strncpy(stream->ice_pwd, value, sizeof(stream->ice_pwd));
			} else if (keywordcmp("ice-mismatch", att_name) == 0) {
				stream->ice_mismatch = TRUE;
			}
		}
		desc->n_total_streams++;
	}
	return 0;
}
Exemplo n.º 18
0
static void belle_sip_body_handler_destroy(belle_sip_body_handler_t *obj){
	belle_sip_list_free_with_data(obj->headers,belle_sip_object_unref);
	belle_sip_free(obj->headerStringBuffer);
}
Exemplo n.º 19
0
static void belle_sip_multipart_body_handler_destroy(belle_sip_multipart_body_handler_t *obj){
	belle_sip_list_free_with_data(obj->parts,belle_sip_object_unref);
	if (obj->buffer != NULL) belle_sip_free(obj->buffer);
	if (obj->boundary != NULL) belle_sip_free(obj->boundary);
}
Exemplo n.º 20
0
static void process_response_event(belle_sip_listener_t *user_ctx, const belle_sip_response_event_t *event){
	belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
	belle_sip_response_t* response = belle_sip_response_event_get_response(event);
	belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
	int response_code = belle_sip_response_get_status_code(response);
	belle_sip_refresher_t* refresher=(belle_sip_refresher_t*)user_ctx;
	belle_sip_header_contact_t *contact;


	if (refresher && (client_transaction !=refresher->transaction))
		return; /*not for me*/

	set_or_update_dialog(refresher,belle_sip_response_event_get_dialog(event));
	/*success case:*/
	if (response_code>=200 && response_code<300){
		refresher->auth_failures=0;
		refresher->number_of_retry=0;
		/*great, success*/
		if (strcmp(belle_sip_request_get_method(request),"PUBLISH")==0) {
			/*search for etag*/
			belle_sip_header_t* etag=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"SIP-ETag");
			if (etag) {
				belle_sip_header_t* sip_if_match = belle_sip_header_create("SIP-If-Match",belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(etag)));
				/*update request for next refresh*/
				belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),"SIP-If-Match");
				belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),sip_if_match);
			} else if (refresher->target_expires > 0){
				belle_sip_warning("Refresher [%p] received 200ok to a publish without etag",refresher);
			}
		}
		/*update expire if needed*/
		set_expires_from_trans(refresher);

		if (refresher->target_expires<=0) {
			belle_sip_refresher_stop(refresher); /*doesn't not make sense to refresh if expire =0;*/
		} else {
			/*remove all contact with expire = 0 from request if any, because no need to refresh them*/
			const belle_sip_list_t * contact_list= belle_sip_message_get_headers(BELLE_SIP_MESSAGE(request),BELLE_SIP_CONTACT);
			belle_sip_list_t *iterator, *head;
			if (contact_list) {
				for (iterator=head=belle_sip_list_copy(contact_list);iterator!=NULL;iterator=iterator->next) {
					belle_sip_header_contact_t *contact_for_expire = (belle_sip_header_contact_t *)(iterator->data);
					if (belle_sip_header_contact_get_expires(contact_for_expire) == 0) {
						belle_sip_message_remove_header_from_ptr(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact_for_expire));
					}
				}
				belle_sip_list_free(head);
			}
		}

		if (refresher->state==started) {
			if (!refresher->first_acknoleged_request)
				belle_sip_object_ref(refresher->first_acknoleged_request = request);
			if (is_contact_address_acurate(refresher,request)) {
				schedule_timer(refresher); /*re-arm timer*/
			} else {
				belle_sip_message("belle_sip_refresher_start(): refresher [%p] is resubmitting request because contact sent was not correct in original request.",refresher);
				belle_sip_refresher_refresh(refresher,refresher->target_expires);
				return;
			}
		}
		else belle_sip_message("Refresher [%p] not scheduling next refresh, because it was stopped",refresher);
	}else{/*special error cases*/
		switch (response_code) {
		case 301:
		case 302:
			contact=belle_sip_message_get_header_by_type(response,belle_sip_header_contact_t);
			if (contact){
				belle_sip_uri_t *uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact));
				if (uri && belle_sip_refresher_refresh_internal(refresher,refresher->target_expires,TRUE,&refresher->auth_events,uri)==0)
					return;
			}
			break;
		case 401:
		case 407:
			refresher->auth_failures++;
			if (refresher->auth_failures>1){
				/*avoid looping with 407 or 401 */
				belle_sip_warning("Authentication is failing constantly, %s",(refresher->target_expires>0)? "will retry later":"giving up.");
				if (refresher->target_expires>0) retry_later(refresher);
				refresher->auth_failures=0; /*reset auth failure*/
				break;
			}
			if (refresher->auth_events) {
				refresher->auth_events=belle_sip_list_free_with_data(refresher->auth_events,(void (*)(void*))belle_sip_auth_event_destroy);
			}
			if (belle_sip_refresher_refresh_internal(refresher,refresher->target_expires,TRUE,&refresher->auth_events,NULL)==0)
				return; /*ok, keep 401 internal*/
			break; /*Else notify user of registration failure*/
		case 403:
			/*In case of 403, we will retry later, just in case*/
			if (refresher->target_expires>0) retry_later(refresher);
			break;
		case 412:
			if (strcmp(belle_sip_request_get_method(request),"PUBLISH")==0) {
				belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),"SIP-If-Match");
				if (refresher->target_expires>0) {
					retry_later_on_io_error(refresher);
					return; /*do not notify this kind of error*/
				}
			} else {
				if (refresher->target_expires>0) retry_later(refresher);
			}
			break;
		case 423:{
			belle_sip_header_extension_t *min_expires=BELLE_SIP_HEADER_EXTENSION(belle_sip_message_get_header((belle_sip_message_t*)response,"Min-Expires"));
			if (min_expires){
				const char *value=belle_sip_header_extension_get_value(min_expires);
				if (value){
					int new_expires=atoi(value);
					if (new_expires>0 && refresher->state==started){
						refresher->target_expires=new_expires;
						belle_sip_refresher_refresh(refresher,refresher->target_expires);
						return;
					}
				}
			}else belle_sip_warning("Receiving 423 but no min-expires header.");
			break;
		}
		case 491: {
			if (refresher->target_expires>0) {
				retry_later_on_io_error(refresher);
				return; /*do not notify this kind of error*/
			}
		}
		case 505:
		case 501:
			/*irrecoverable errors, probably no need to retry later*/
			break;
		
		default:
			/*for all other errors, retry later*/
			if (refresher->target_expires>0) retry_later(refresher);
			break;
		}
	}
	if (refresher->listener) refresher->listener(refresher,refresher->user_data,response_code, belle_sip_response_get_reason_phrase(response));

}
Exemplo n.º 21
0
static void belle_http_channel_context_uninit(belle_http_channel_context_t *obj){
	belle_sip_list_free_with_data(obj->pending_requests,belle_sip_object_unref);
}
Exemplo n.º 22
0
static void test_mime_parameter(void) {
	const char* l_src = "m=audio 7078 RTP/AVP 111 110 0 8 9 3 18 101\r\n"\
						"a=rtpmap:111 speex/16000\r\n"\
						"a=fmtp:111 vbr=on\r\n"\
						"a=rtpmap:110 speex/8000\r\n"\
						"a=fmtp:110 vbr=on\r\n"\
						"a=rtpmap:8 PCMA/8000\r\n"\
						"a=rtpmap:101 telephone-event/8000\r\n"\
						"a=fmtp:101 0-11\r\n"\
						"a=ptime:40\r\n";

	belle_sdp_mime_parameter_t* l_param;
	belle_sdp_mime_parameter_t*  lTmp;
	belle_sdp_media_t* l_media;
	belle_sip_list_t* mime_parameter_list;
	belle_sip_list_t* mime_parameter_list_iterator;
	belle_sdp_media_description_t* l_media_description_tmp = belle_sdp_media_description_parse(l_src);

	belle_sdp_media_description_t* l_media_description = belle_sdp_media_description_parse(belle_sip_object_to_string(l_media_description_tmp));
	belle_sip_object_unref(l_media_description_tmp);

	mime_parameter_list = belle_sdp_media_description_build_mime_parameters(l_media_description);
	mime_parameter_list_iterator = mime_parameter_list;
	CU_ASSERT_PTR_NOT_NULL(mime_parameter_list);
	belle_sip_object_unref(BELLE_SIP_OBJECT(l_media_description));

	l_media_description = belle_sdp_media_description_new();
	belle_sdp_media_description_set_media(l_media_description,l_media=belle_sdp_media_parse("m=audio 7078 RTP/AVP 0"));

	belle_sdp_media_set_media_formats(l_media,belle_sip_list_free(belle_sdp_media_get_media_formats(l_media))); /*to remove 0*/


	for (;mime_parameter_list_iterator!=NULL;mime_parameter_list_iterator=mime_parameter_list_iterator->next) {
		belle_sdp_media_description_append_values_from_mime_parameter(l_media_description,(belle_sdp_mime_parameter_t*)mime_parameter_list_iterator->data);
	}
	belle_sip_list_free_with_data(mime_parameter_list, (void (*)(void*))belle_sip_object_unref);

	/*marshal/unmarshal again*/
	l_media_description_tmp = l_media_description;
	l_media_description= belle_sdp_media_description_parse(belle_sip_object_to_string(l_media_description));
	belle_sip_object_unref(l_media_description_tmp);
	/*belle_sip_message("%s",belle_sip_object_to_string(l_media_description));*/
	{
		belle_sip_list_t* attributes=belle_sdp_media_description_get_attributes(l_media_description);
#ifdef	BELLE_SDP_FORCE_RTP_MAP
		CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(attributes,(belle_sip_compare_func)compare_attribute,"8 PCMA/8000"));
		CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(attributes,(belle_sip_compare_func)compare_attribute,"18 G729/8000"));
#else
		CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(attributes,(belle_sip_compare_func)compare_attribute,"8 PCMA/8000"));
		CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(attributes,(belle_sip_compare_func)compare_attribute,"18 G729/8000"));
#endif
	}
	mime_parameter_list = belle_sdp_media_description_build_mime_parameters(l_media_description);
	belle_sip_object_unref(l_media_description);
	lTmp = find_mime_parameter(mime_parameter_list,111);
	l_param = BELLE_SDP_MIME_PARAMETER(belle_sip_object_clone(BELLE_SIP_OBJECT(lTmp)));

	CU_ASSERT_PTR_NOT_NULL(l_param);
	check_mime_param(l_param,16000,1,40,-1,111,"speex","vbr=on");
	belle_sip_object_unref(l_param);

	l_param = find_mime_parameter(mime_parameter_list,110);
	CU_ASSERT_PTR_NOT_NULL(l_param);
	check_mime_param(l_param,8000,1,40,-1,110,"speex","vbr=on");

	l_param = find_mime_parameter(mime_parameter_list,3);
	CU_ASSERT_PTR_NOT_NULL(l_param);
	check_mime_param(l_param,8000,1,40,-1,3,"GSM",NULL);


	l_param = find_mime_parameter(mime_parameter_list,0);
	CU_ASSERT_PTR_NOT_NULL(l_param);
	check_mime_param(l_param,8000,1,40,-1,0,"PCMU",NULL);


	l_param = find_mime_parameter(mime_parameter_list,8);
	CU_ASSERT_PTR_NOT_NULL(l_param);
	check_mime_param(l_param,8000,1,40,-1,8,"PCMA",NULL);


	l_param = find_mime_parameter(mime_parameter_list,9);
	CU_ASSERT_PTR_NOT_NULL(l_param);
	check_mime_param(l_param,8000,1,40,-1,9,"G722",NULL);


	l_param = find_mime_parameter(mime_parameter_list,101);
	CU_ASSERT_PTR_NOT_NULL(l_param);
	check_mime_param(l_param,8000,1,40,-1,101,"telephone-event","0-11");

	belle_sip_list_free_with_data(mime_parameter_list, (void (*)(void*))belle_sip_object_unref);
}
Exemplo n.º 23
0
belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff, size_t buff_size, size_t *offset) {
	const belle_sip_list_t* list;
	belle_sip_error_code error=BELLE_SIP_OK;

	error=belle_sip_snprintf(buff,buff_size,offset,"%s:",uri->secure?"sips":"sip");
	if (error!=BELLE_SIP_OK) return error;

	if (uri->user && uri->user[0]!='\0') {
		char* escaped_username=belle_sip_uri_to_escaped_username(uri->user);
		error=belle_sip_snprintf(buff,buff_size,offset,"%s",escaped_username);
		belle_sip_free(escaped_username);
		if (error!=BELLE_SIP_OK) return error;

		if (uri->user_password) {
			char* escaped_password=belle_sip_uri_to_escaped_userpasswd(uri->user_password);
			error=belle_sip_snprintf(buff,buff_size,offset,":%s",escaped_password);
			belle_sip_free(escaped_password);
			if (error!=BELLE_SIP_OK) return error;
		}
		error=belle_sip_snprintf(buff,buff_size,offset,"@");
		if (error!=BELLE_SIP_OK) return error;

	}

	if (uri->host) {
		if (strchr(uri->host,':')) { /*ipv6*/
			error=belle_sip_snprintf(buff,buff_size,offset,"[%s]",uri->host);
		} else {
			error=belle_sip_snprintf(buff,buff_size,offset,"%s",uri->host);
		}
		if (error!=BELLE_SIP_OK) return error;
	} else {
		belle_sip_warning("no host found in this uri");
	}

	if (uri->port!=0) {
		error=belle_sip_snprintf(buff,buff_size,offset,":%i",uri->port);
		if (error!=BELLE_SIP_OK) return error;
	}

	{
		belle_sip_parameters_t *encparams = belle_sip_parameters_new();
		belle_sip_list_for_each2(uri->params.param_list, (void (*)(void *, void *))encode_params, &encparams->param_list);
		error=belle_sip_parameters_marshal(encparams,buff,buff_size,offset);
		belle_sip_parameters_destroy(encparams);
		if (error!=BELLE_SIP_OK) return error;
	}

	{
		belle_sip_list_t * encheaders = NULL;
		belle_sip_list_for_each2(uri->header_list->param_list, (void (*)(void *, void *))encode_headers, &encheaders);

		for(list=encheaders;list!=NULL;list=list->next){
			belle_sip_param_pair_t* container = list->data;
			if (list == encheaders) {
				//first case
				error=belle_sip_snprintf(buff,buff_size,offset,"?%s=%s",container->name,container->value?container->value:"");
			} else {
				//subsequent headers
				error=belle_sip_snprintf(buff,buff_size,offset,"&%s=%s",container->name,container->value?container->value:"");
			}
			if (error!=BELLE_SIP_OK) break;
		}
		belle_sip_list_free_with_data(encheaders,(void (*)(void*))belle_sip_param_pair_destroy);
	}

	return error;
}