void belle_sip_listening_point_set_keep_alive(belle_sip_listening_point_t *lp,int ms) {
	if (ms <=0) {
		if (lp->keep_alive_timer) {
			belle_sip_main_loop_remove_source(lp->stack->ml,lp->keep_alive_timer);
			belle_sip_object_unref(lp->keep_alive_timer);
			lp->keep_alive_timer=NULL;
		}
		return;
	}

	if (!lp->keep_alive_timer) {
		lp->keep_alive_timer = belle_sip_main_loop_create_timeout(lp->stack->ml
			, keep_alive_timer_func
			, lp
			, ms
			,"keep alive") ;
	} else {
		belle_sip_source_set_timeout(lp->keep_alive_timer,ms);
	}
	return;
}
belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t,belle_sip_list_t** auth_infos,const char* realm) {
	belle_sip_request_t* initial_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t));
	belle_sip_request_t* req=belle_sip_request_clone_with_body(initial_request);
	belle_sip_header_cseq_t* cseq=belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
	belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
	if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)) != BELLE_SIP_TRANSACTION_COMPLETED
		&& belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)) != BELLE_SIP_TRANSACTION_TERMINATED) {
		belle_sip_error("Invalid state [%s] for transaction [%p], should be BELLE_SIP_TRANSACTION_COMPLETED | BELLE_SIP_TRANSACTION_TERMINATED"
					,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)))
					,t);
		belle_sip_object_unref(req);
		return NULL;
	}
	/*remove auth headers*/
	belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_AUTHORIZATION);
	belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_PROXY_AUTHORIZATION);

	/*put auth header*/
	belle_sip_provider_add_authorization(t->base.provider,req,t->base.last_response,NULL,auth_infos,realm);
	return req;
}
Exemple #3
0
static void one_get(const char *url,http_counters_t* counters, int *counter){
	belle_http_request_listener_callbacks_t cbs={0};
	belle_http_request_listener_t *l;
	belle_generic_uri_t *uri;
	belle_http_request_t *req;
	
	uri=belle_generic_uri_parse(url);
	
	req=belle_http_request_create("GET",
							    uri,
							    belle_sip_header_create("User-Agent","belle-sip/"PACKAGE_VERSION),
							    NULL);
	cbs.process_response=process_response;
	cbs.process_io_error=process_io_error;
	cbs.process_auth_requested=process_auth_requested;
	l=belle_http_request_listener_create_from_callbacks(&cbs,counters);
	belle_http_provider_send_request(prov,req,l);
	wait_for(stack,counter,1,3000);
	
	belle_sip_object_unref(l);
}
Exemple #4
0
int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact){
	belle_sip_request_t *req;
	belle_sip_uri_t* req_uri;
	belle_sip_header_t* accept_header;

	if (op->refresher){
		belle_sip_refresher_stop(op->refresher);
		belle_sip_object_unref(op->refresher);
		op->refresher=NULL;
	}

	op->type=SalOpRegister;
	sal_op_set_from(op,from);
	sal_op_set_to(op,from);
	sal_op_set_route(op,proxy);
	req = sal_op_build_request(op,"REGISTER");
	req_uri = belle_sip_request_get_uri(req);
	belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/
	if (op->base.root->use_dates){
		time_t curtime=time(NULL);
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime)));
	}
	accept_header = belle_sip_header_create("Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml");
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), accept_header);
	belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op));
	if (old_contact) {
		belle_sip_header_contact_t *contact=belle_sip_header_contact_create((const belle_sip_header_address_t *)old_contact);
		if (contact) {
			char * tmp;
			belle_sip_header_contact_set_expires(contact,0); /*remove old aor*/
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(contact));
			tmp = belle_sip_object_to_string(contact);
			ms_message("Clearing contact [%s] for op [%p]",tmp,op);
			ms_free(tmp);
		} else {
			ms_error("Cannot add old contact header to op [%p]",op);
		}
	}
	return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener);
}
Exemple #5
0
void sal_op_release_impl(SalOp *op){
	ms_message("Destroying op [%p] of type [%s]",op,sal_op_type_to_string(op->type));
	if (op->pending_auth_transaction) belle_sip_object_unref(op->pending_auth_transaction);
	if (op->auth_info) {
		sal_remove_pending_auth(op->base.root,op);
		sal_auth_info_delete(op->auth_info);
	}
	if (op->sdp_answer) belle_sip_object_unref(op->sdp_answer);
	if (op->refresher) {
		belle_sip_object_unref(op->refresher);
		op->refresher=NULL;
	}
	if (op->result)
		sal_media_description_unref(op->result);
	if(op->replaces) belle_sip_object_unref(op->replaces);
	if(op->referred_by) belle_sip_object_unref(op->referred_by);

	if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans);
	if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
	if (op->event) belle_sip_object_unref(op->event);
	__sal_op_free(op);
	return ;
}
static void test_rtcp_xr_attribute(void) {
	belle_sdp_rtcp_xr_attribute_t* lAttribute;

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == FALSE);
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == FALSE);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:rcvr-rtt=all:10"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_STRING_EQUAL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(lAttribute), "all");
	CU_ASSERT_EQUAL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_max_size(lAttribute), 10);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:stat-summary"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_PTR_NULL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(lAttribute));
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == TRUE);
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == FALSE);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:stat-summary=loss,jitt"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == TRUE);
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "loss"));
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "jitt"));
	CU_ASSERT_PTR_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "HL"));
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:voip-metrics"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == FALSE);
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == TRUE);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:rcvr-rtt=sender stat-summary=loss,dup,jitt,TTL voip-metrics"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_STRING_EQUAL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(lAttribute), "sender");
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == TRUE);
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "loss"));
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "dup"));
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "jitt"));
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "TTL"));
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == TRUE);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));
}
static void test_generate_and_parse_certificates(void) {
	belle_sip_certificates_chain_t *certificate, *parsed_certificate;
	belle_sip_signing_key_t *key, *parsed_key;
	char *pem_certificate, *pem_parsed_certificate, *pem_key, *pem_parsed_key;
	int ret = 0;
	char *belle_sip_certificate_temporary_dir = bc_tester_file(TEMPORARY_CERTIFICATE_DIR);

	/* create 2 certificates in the temporary certificate directory (TODO : set the directory in a absolute path?? where?)*/
	ret = belle_sip_generate_self_signed_certificate(belle_sip_certificate_temporary_dir, "test_certificate1", &certificate, &key);
	if (ret == BCTOOLBOX_ERROR_UNAVAILABLE_FUNCTION) {
		belle_sip_warning("Test skipped, self signed certificate generation not available.");
		return;
	}
	BC_ASSERT_EQUAL_FATAL(0, ret, int, "%d");
	belle_sip_object_unref(certificate);
	belle_sip_object_unref(key);
	ret = belle_sip_generate_self_signed_certificate(belle_sip_certificate_temporary_dir, "test_certificate2", &certificate, &key);
	BC_ASSERT_EQUAL_FATAL(0, ret, int, "%d");

	/* parse directory to get the certificate2 */
	ret = belle_sip_get_certificate_and_pkey_in_dir(belle_sip_certificate_temporary_dir, "test_certificate2", &parsed_certificate, &parsed_key, BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM);
	free(belle_sip_certificate_temporary_dir);
	BC_ASSERT_EQUAL_FATAL(0, ret, int, "%d");

	/* get pem version of generated and parsed certificate and compare them */
	pem_certificate = belle_sip_certificates_chain_get_pem(certificate);
	BC_ASSERT_TRUE_FATAL(pem_certificate!=NULL);
	pem_parsed_certificate = belle_sip_certificates_chain_get_pem(parsed_certificate);
	BC_ASSERT_TRUE_FATAL(pem_parsed_certificate!=NULL);
	BC_ASSERT_STRING_EQUAL(pem_certificate, pem_parsed_certificate);

	/* get pem version of generated and parsed key and compare them */
	pem_key = belle_sip_signing_key_get_pem(key);
	BC_ASSERT_TRUE_FATAL(pem_key!=NULL);
	pem_parsed_key = belle_sip_signing_key_get_pem(parsed_key);
	BC_ASSERT_TRUE_FATAL(pem_parsed_key!=NULL);
	BC_ASSERT_STRING_EQUAL(pem_key, pem_parsed_key);

	belle_sip_free(pem_certificate);
	belle_sip_free(pem_parsed_certificate);
	belle_sip_free(pem_key);
	belle_sip_free(pem_parsed_key);
	belle_sip_object_unref(certificate);
	belle_sip_object_unref(parsed_certificate);
	belle_sip_object_unref(key);
	belle_sip_object_unref(parsed_key);
}
static void prepare_query(CardDavRequest *request) {
	belle_http_request_listener_callbacks_t cbs = { 0 };
	belle_http_request_listener_t *l = NULL;
	belle_generic_uri_t *uri = NULL;
	belle_http_request_t *req = NULL;
	belle_sip_memory_body_handler_t *bh = NULL;
	belle_sip_stack_t *stack = NULL;
	belle_http_provider_t *http_provider = NULL;

	belle_sip_set_log_level(BELLE_SIP_LOG_MESSAGE);
	uri = belle_generic_uri_parse(request->url);
	if (!uri) {
		belle_sip_error("Could not send request, URL %s is invalid", request->url);
		return;
	}
	req = belle_http_request_create(request->method, uri, belle_sip_header_content_type_create("application", "xml; charset=utf-8"), belle_sip_header_create("Depth", request->depth), NULL);
	if (!req) {
		belle_sip_object_unref(uri);
		belle_sip_error("Could not create request");
		return;
	}
	
	bh = belle_sip_memory_body_handler_new_copy_from_buffer(request->body, strlen(request->body), NULL, NULL);
	belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(bh));
	
	cbs.process_response = process_response_from_post_xml_rpc_request;
	cbs.process_io_error = process_io_error_from_post_xml_rpc_request;
	cbs.process_auth_requested = process_auth_requested_from_post_xml_rpc_request;
	l = belle_http_request_listener_create_from_callbacks(&cbs, request);
	
	stack = belle_sip_stack_new(NULL);
	http_provider = belle_sip_stack_create_http_provider(stack, "0.0.0.0");
	
	request->request_in_progress = 1;
	belle_http_provider_send_request(http_provider, req, l);
	while (request->request_in_progress) {
		belle_sip_stack_sleep(stack, 0);
	}
}
Exemple #9
0
static int process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) {
	belle_sdp_session_description_t* sdp;
	int err=0;
	SalReason reason;
	if (extract_sdp(op,BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) {
		if (sdp){
			op->sdp_offering=FALSE;
			op->base.remote_media=sal_media_description_new();
			sdp_to_media_description(sdp,op->base.remote_media);
			/*make some sanity check about the SDP received*/
			if (!is_media_description_acceptable(op->base.remote_media)){
				err=-1;
				reason=SalReasonNotAcceptable;
			}
			belle_sip_object_unref(sdp);
		}else op->sdp_offering=TRUE; /*INVITE without SDP*/
	}else err=-1;

	if (err==-1){
		sal_call_decline(op,reason,NULL);
	}
	return err;
}
static void testRegisterRaw(void) {
	const char* raw_message = "REGISTER sip:192.168.0.20 SIP/2.0\r\n"\
							"Via: SIP/2.0/UDP 192.168.1.8:5062;rport;branch=z9hG4bK1439638806\r\n"\
							"From: <sip:[email protected]>;tag=465687829\r\n"\
							"To: <sip:[email protected]>\r\n"\
							"Call-ID: 1053183492\r\n"\
							"CSeq: 1 REGISTER\r\n"\
							"Contact: <sip:[email protected]:5062>\r\n"\
							"Max-Forwards: 70\r\n"\
							"User-Agent: Linphone/3.3.99.10 (eXosip2/3.3.0)\r\n"\
							"Expires: 3600\r\n"\
							"Content-Length: 0\r\n\r\n123456789";
	belle_sip_request_t* request;
	size_t size=0;
	size_t raw_message_size= strlen(raw_message);
	belle_sip_message_t* message = belle_sip_message_parse_raw(raw_message,raw_message_size,&size);
	CU_ASSERT_EQUAL(raw_message_size,size+9);
	request = BELLE_SIP_REQUEST(message);
	CU_ASSERT_STRING_EQUAL(belle_sip_request_get_method(request),"REGISTER");
	CU_ASSERT_PTR_NOT_NULL(belle_sip_request_get_uri(request));
	CU_ASSERT_STRING_EQUAL(&raw_message[size],"123456789");
	belle_sip_object_unref(message);
}
static void test_dictionary(void)
{
	belle_sip_dict_t* obj = belle_sip_object_new(belle_sip_dict_t);
	const char* str = "";
	int i = 5;
	int64_t i64 = 0xF2345678 << 1; // gcc doesn't like 0x1234567890 as a 64 bit literal..

	belle_sip_dict_set_int(obj, "test_i", i);
	BC_ASSERT_EQUAL(belle_sip_dict_get_int(obj,"test_i",-1),i, int, "%d");

	// return default int value
	BC_ASSERT_EQUAL(belle_sip_dict_get_int(obj,"unexistent",-1),-1, int, "%d");

	// remove existing entry
	BC_ASSERT_EQUAL(belle_sip_dict_remove(obj, "test_i"),0, int, "%d");

	// test_i should't be present anymore
	BC_ASSERT_EQUAL(belle_sip_dict_get_int(obj,"test_i",-1),-1, int, "%d");

	// remove unknown entry
	BC_ASSERT_NOT_EQUAL(belle_sip_dict_remove(obj, "unexistent"),0,int,"%d");

	belle_sip_dict_set_string(obj, "test_str", str);
	BC_ASSERT_STRING_EQUAL( (const char*)belle_sip_dict_get_string(obj, "test_str", ""),str);

	// unknown string value
	BC_ASSERT_STRING_EQUAL( (const char*)belle_sip_dict_get_string(obj, "unexistent", "toto"),"toto");

	belle_sip_dict_set_int64(obj, "test_i64", i64);
	BC_ASSERT_EQUAL(belle_sip_dict_get_int64(obj,"test_i64",-1),i64, int, "%d");

	belle_sip_dict_clear(obj);
	// test_str shouldn't exist anymore
	BC_ASSERT_STRING_EQUAL(belle_sip_dict_get_string(obj,"test_str","toto"),"toto");

	belle_sip_object_unref(obj);
}
static void http_channel_context_handle_response(belle_http_channel_context_t *ctx , belle_sip_channel_t *chan, belle_http_response_t *response){
	belle_http_request_t *req=NULL;
	belle_http_response_event_t ev={0};
	int code;
	belle_sip_header_t *connection;
	/*pop the request matching this response*/
	ctx->pending_requests=belle_sip_list_pop_front(ctx->pending_requests,(void**)&req);
	if (req==NULL){
		belle_sip_error("Receiving http response not matching any request.");
		return;
	}
	if (belle_http_request_is_cancelled(req)) {
		belle_sip_warning("Receiving http response for a cancelled request.");
		return;
	}
	connection=belle_sip_message_get_header((belle_sip_message_t *)response,"Connection");
	if (connection && strstr(belle_sip_header_get_unparsed_value(connection),"close")!=NULL)
		chan->about_to_be_closed=TRUE;

	belle_http_request_set_response(req,response);
	code=belle_http_response_get_status_code(response);
	if ((code==401 || code==407) && http_channel_context_handle_authentication(ctx,req)==0 ){
		/*nothing to do, the request has been resubmitted with authentication*/
	}else{
		/*else notify the app about the response received*/
		ev.source=(belle_sip_object_t*)ctx->provider;
		ev.request=req;
		ev.response=response;
		BELLE_HTTP_REQUEST_INVOKE_LISTENER(req,process_response,&ev);
		if( req->background_task_id ){
			belle_sip_warning("HTTP request finished: ending bg task id=[%x]", req->background_task_id);
			belle_sip_end_background_task(req->background_task_id);
			req->background_task_id = 0;
		}
	}
	belle_sip_object_unref(req);
}
Exemple #13
0
void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t* server_transaction){
	belle_sip_request_t* req = belle_sip_request_event_get_request(event);
	const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
	belle_sip_header_t* header_event=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event");
	belle_sip_header_content_type_t* content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t);
	belle_sip_response_t* resp;

	ms_message("Receiving NOTIFY request on op [%p]",op);
	if (header_event
	&& strncasecmp(belle_sip_header_get_unparsed_value(header_event),"refer",strlen("refer"))==0
	&& content_type
	&& strcmp(belle_sip_header_content_type_get_type(content_type),"message")==0
	&& strcmp(belle_sip_header_content_type_get_subtype(content_type),"sipfrag")==0
	&& body){
		belle_sip_response_t* sipfrag=BELLE_SIP_RESPONSE(belle_sip_message_parse(body));

		if (sipfrag){
			int code=belle_sip_response_get_status_code(sipfrag);
			SalReferStatus status=SalReferFailed;
			if (code<200){
				status=SalReferTrying;
			}else if (code<300){
				status=SalReferSuccess;
			}else if (code>=400){
				status=SalReferFailed;
			}
			belle_sip_object_unref(sipfrag);
			resp = sal_op_create_response_from_request(op,req,200);
			belle_sip_server_transaction_send_response(server_transaction,resp);
			op->base.root->callbacks.notify_refer(op,status);
		}
	}else{
		ms_error("Notify without sipfrag, trashing");
		resp = sal_op_create_response_from_request(op,req,501);
		belle_sip_server_transaction_send_response(server_transaction,resp);
	}
}
int sal_register(SalOp *op, const char *proxy, const char *from, int expires){
	belle_sip_request_t *req;
	belle_sip_uri_t* req_uri;
	
	if (op->refresher){
		belle_sip_refresher_stop(op->refresher);
		belle_sip_object_unref(op->refresher);
		op->refresher=NULL;
	}
	
	op->type=SalOpRegister;
	sal_op_set_from(op,from);
	sal_op_set_to(op,from);
	sal_op_set_route(op,proxy);
	req = sal_op_build_request(op,"REGISTER");
	req_uri = belle_sip_request_get_uri(req);
	belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/
	if (op->base.root->use_dates){
		time_t curtime=time(NULL);
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime)));
	}
	belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op));
	return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener);
}
Exemple #15
0
static void make_supported_header(Sal *sal){
	bctbx_list_t *it;
	char *alltags=NULL;
	size_t buflen=64;
	size_t written=0;

	if (sal->supported){
		belle_sip_object_unref(sal->supported);
		sal->supported=NULL;
	}
	for(it=sal->supported_tags;it!=NULL;it=it->next){
		const char *tag=(const char*)it->data;
		size_t taglen=strlen(tag);
		if (alltags==NULL || (written+taglen+1>=buflen)) alltags=ms_realloc(alltags,(buflen=buflen*2));
		written+=snprintf(alltags+written,buflen-written,it->next ? "%s, " : "%s",tag);
	}
	if (alltags){
		sal->supported=belle_sip_header_create("Supported",alltags);
		if (sal->supported){
			belle_sip_object_ref(sal->supported);
		}
		ms_free(alltags);
	}
}
Exemple #16
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;
}
static void destroy_endpoint(endpoint_t *endpoint) {
	reset_endpoint(endpoint);
	belle_sip_object_unref(endpoint->stack);
	belle_sip_free(endpoint);
	belle_sip_uninit_sockets();
}
Exemple #18
0
static void channel_invoke_state_listener_defered(belle_sip_channel_t *obj){
	channel_invoke_state_listener(obj);
	belle_sip_object_unref(obj);
}
Exemple #19
0
static void channel_connect_next(belle_sip_channel_t *obj){
	belle_sip_channel_connect(obj);
	belle_sip_object_unref(obj);
}
Exemple #20
0
void linphone_friend_unref(LinphoneFriend *lf) {
	belle_sip_object_unref(lf);
}
Exemple #21
0
void belle_sip_auth_event_set_client_certificates_chain(belle_sip_auth_event_t* event, belle_sip_certificates_chain_t* value) {
	if (event->cert) belle_sip_object_unref(event->cert);
	event->cert=value;
	if (event->cert) belle_sip_object_ref(event->cert);
}
Exemple #22
0
void linphone_content_unref(LinphoneContent *content) {
	belle_sip_object_unref(content);
}
Exemple #23
0
static void client_transaction_destroy(belle_sip_client_transaction_t *t ){
	if (t->preset_route) belle_sip_object_unref(t->preset_route);
	if (t->next_hop) belle_sip_object_unref(t->next_hop);
}
Exemple #24
0
static void unlink_op_with_dialog(SalOp *op, belle_sip_dialog_t* dialog){
	belle_sip_dialog_set_application_data(dialog,NULL);
	sal_op_unref(op);
	belle_sip_object_unref(dialog);
}
Exemple #25
0
static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request, bool_t add_contact) {
	belle_sip_client_transaction_t* client_transaction;
	belle_sip_provider_t* prov=op->base.root->prov;
	belle_sip_uri_t* outbound_proxy=NULL;
	belle_sip_header_contact_t* contact;
	int result =-1;
	belle_sip_uri_t *next_hop_uri=NULL;

	if (add_contact && !belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t)) {
		contact = sal_op_create_contact(op);
		belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact));
	} /*keep existing*/

	_sal_op_add_custom_headers(op, (belle_sip_message_t*)request);

	if (!op->dialog || belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_NULL) {
		/*don't put route header if  dialog is in confirmed state*/
		const MSList *elem=sal_op_get_route_addresses(op);
		const char *transport;
		const char *method=belle_sip_request_get_method(request);
		belle_sip_listening_point_t *udplp=belle_sip_provider_get_listening_point(prov,"UDP");

		if (elem) {
			outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data);
			next_hop_uri=outbound_proxy;
		}else{
			next_hop_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri(request));
		}
		transport=belle_sip_uri_get_transport_param(next_hop_uri);
		if (transport==NULL){
			/*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use
			 * the first available transport*/
			if (!belle_sip_uri_is_secure(next_hop_uri)){
				if (udplp==NULL){
					if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){
						transport="tcp";
					}else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){
						transport="tls";
					}
				}
				if (transport){
					belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport);
					belle_sip_uri_set_transport_param(next_hop_uri,transport);
				}
			}
		}else{
#ifdef TUNNEL_ENABLED
			if (udplp && BELLE_SIP_OBJECT_IS_INSTANCE_OF(udplp,belle_sip_tunnel_listening_point_t)){
				/* our tunnel mode only supports UDP. Force transport to be set to UDP */
				belle_sip_uri_set_transport_param(next_hop_uri,"udp");
			}
#endif
		}
		if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport &&
			(strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){
			/*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/
			belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t);
			belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"alias",NULL);
		}
	}

	client_transaction = belle_sip_provider_create_client_transaction(prov,request);
	belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),sal_op_ref(op));
	if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans);
	op->pending_client_trans=client_transaction; /*update pending inv for being able to cancel*/
	belle_sip_object_ref(op->pending_client_trans);

	if (belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_user_agent_t)==NULL)
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(op->base.root->user_agent));

	if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION)
		&& !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) {
		/*hmm just in case we already have authentication param in cache*/
		belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL,op->base.realm);
	}
	result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/);

	/*update call id if not set yet for this OP*/
	if (result == 0 && !op->base.call_id) {
		op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_call_id_t))));
	}

	return result;

}
Exemple #26
0
void linphone_account_creator_unref(LinphoneAccountCreator *creator) {
	belle_sip_object_unref(creator);
}
Exemple #27
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);
}
Exemple #28
0
void linphone_account_creator_cbs_unref(LinphoneAccountCreatorCbs *cbs) {
	belle_sip_object_unref(cbs);
}
Exemple #29
0
static void subscribe_process_request_event(void *op_base, const belle_sip_request_event_t *event) {
	SalOp* op = (SalOp*)op_base;
	belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
	belle_sip_request_t* req = belle_sip_request_event_get_request(event);
	belle_sip_dialog_state_t dialog_state;
	belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
	belle_sip_header_t *event_header;
	SalBody body;
	belle_sip_response_t* resp;
	const char *eventname=NULL;
	const char *method=belle_sip_request_get_method(req);
	
	belle_sip_object_ref(server_transaction);
	if (op->pending_server_trans)  belle_sip_object_unref(op->pending_server_trans);
	op->pending_server_trans=server_transaction;

	event_header=belle_sip_message_get_header((belle_sip_message_t*)req,"Event");
	sal_op_get_body(op,(belle_sip_message_t*)req,&body);
	
	if (event_header==NULL){
		ms_warning("No event header in incoming SUBSCRIBE.");
		resp=sal_op_create_response_from_request(op,req,400);
		belle_sip_server_transaction_send_response(server_transaction,resp);
		return;
	}
	if (op->event==NULL) {
		op->event=event_header;
		belle_sip_object_ref(op->event);
	}
	eventname=belle_sip_header_get_unparsed_value(event_header);
	
	if (!op->dialog) {
		if (strcmp(method,"SUBSCRIBE")==0){
			op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction));
			belle_sip_dialog_set_application_data(op->dialog,op);
			sal_op_ref(op);
			ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
		}else{ /*this is a NOTIFY*/
			handle_notify(op,req,eventname,&body);
			return;
		}
	}
	dialog_state=belle_sip_dialog_get_state(op->dialog);
	switch(dialog_state) {

	case BELLE_SIP_DIALOG_NULL: {
		op->base.root->callbacks.subscribe_received(op,eventname,body.type ? &body : NULL);
		break;
	}
	case BELLE_SIP_DIALOG_EARLY:
		ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",belle_sip_request_get_method(req),op->dialog);
		break;

	case BELLE_SIP_DIALOG_CONFIRMED:
		if (strcmp("NOTIFY",method)==0) {
			handle_notify(op,req,eventname,&body);
		} else if (strcmp("SUBSCRIBE",method)==0) {
			/*either a refresh of an unsubscribe*/
			if (expires && belle_sip_header_expires_get_expires(expires)>0) {
				resp=sal_op_create_response_from_request(op,req,200);
				belle_sip_server_transaction_send_response(server_transaction,resp);
			} else if(expires) {
				ms_message("Unsubscribe received from [%s]",sal_op_get_from(op));
				resp=sal_op_create_response_from_request(op,req,200);
				belle_sip_server_transaction_send_response(server_transaction,resp);
				op->base.root->callbacks.subscribe_closed(op);
			}
		}
		break;
		default: {
			ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
		}
	}
}
Exemple #30
0
void linphone_call_params_unref(LinphoneCallParams *cp) {
	belle_sip_object_unref(cp);
}