Exemplo n.º 1
0
static void presence_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase){
	SalOp* op = (SalOp*)user_pointer;
	switch(status_code){
		case 481: {

			ms_message("The server or remote ua lost the SUBSCRIBE dialog context. Let's restart a new one.");
			belle_sip_refresher_stop(op->refresher);
			if (op->dialog) { /*delete previous dialog if any*/
				belle_sip_dialog_set_application_data(op->dialog,NULL);
				belle_sip_object_unref(op->dialog);
				op->dialog=NULL;
			}

			if (sal_op_get_contact_address(op)) {
				/*contact is also probably not good*/
				SalAddress* contact=sal_address_clone(sal_op_get_contact_address(op));
				sal_address_set_port(contact,-1);
				sal_address_set_domain(contact,NULL);
				sal_op_set_contact_address(op,contact);
				sal_address_destroy(contact);
			}

			sal_subscribe_presence(op,NULL,NULL,-1);
		break;
		}
	}
}
Exemplo n.º 2
0
belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){
	belle_sip_header_contact_t* contact_header;
	belle_sip_uri_t* contact_uri;

	if (sal_op_get_contact_address(op)) {
		contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op)));
	} else {
		contact_header= belle_sip_header_contact_new();
	}

	if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) {
		/*no uri, just creating a new one*/
		contact_uri=belle_sip_uri_new();
		belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri);
	}

	belle_sip_uri_set_user_password(contact_uri,NULL);
	belle_sip_uri_set_secure(contact_uri,sal_op_is_secure(op));
	if (op->privacy!=SalPrivacyNone){
		belle_sip_uri_set_user(contact_uri,NULL);
	}
	belle_sip_header_contact_set_automatic(contact_header,op->base.root->auto_contacts);
	if (op->base.root->uuid){
		if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance")==0){
			char *instance_id=belle_sip_strdup_printf("\"<urn:uuid:%s>\"",op->base.root->uuid);
			belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance",instance_id);
			belle_sip_free(instance_id);
		}
	}
	return contact_header;
}
Exemplo n.º 3
0
int sal_call_notify_ringing(SalOp *op, bool_t early_media){
	int status_code =early_media?183:180;
	belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans));
	belle_sip_response_t* ringing_response = sal_op_create_response_from_request(op,req,status_code);
	belle_sip_header_t *require;
	const char *tags=NULL;

	if (early_media){
		handle_offer_answer_response(op,ringing_response);
	}
	require=belle_sip_message_get_header((belle_sip_message_t*)req,"Require");
	if (require) tags=belle_sip_header_get_unparsed_value(require);
	/* if client requires 100rel, then add necessary stuff*/
	if (tags && strstr(tags,"100rel")!=0) {
		belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("Require","100rel"));
		belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("RSeq","1"));
	}

#ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING
	if (tags && strstr(tags,"100rel")!=0)
#endif
	{
		belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op);
		belle_sip_header_contact_t* contact_header;
		if (contact && (contact_header=belle_sip_header_contact_create(contact))) {
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(ringing_response),BELLE_SIP_HEADER(contact_header));
		}
	}
	belle_sip_server_transaction_send_response(op->pending_server_trans,ringing_response);
	return 0;
}
Exemplo n.º 4
0
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){
	belle_sip_request_t* req;
	char content_type_raw[256];
	size_t content_length = msg?strlen(msg):0;
	time_t curtime=time(NULL);
	
	if (op->dialog){
		/*for SIP MESSAGE that are sent in call's dialog*/
		req=belle_sip_dialog_create_queued_request(op->dialog,"MESSAGE");
	}else{
		sal_op_message_fill_cbs(op);
		if (from)
			sal_op_set_from(op,from);
		if (to)
			sal_op_set_to(op,to);
		op->dir=SalOpDirOutgoing;

		req=sal_op_build_request(op,"MESSAGE");
		if (sal_op_get_contact_address(op)){
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op)));
		}
	}
	snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type);
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw)));
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length)));
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime)));
	belle_sip_message_set_body(BELLE_SIP_MESSAGE(req),msg,content_length);
	return sal_op_send_request(op,req);

}
Exemplo n.º 5
0
int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){
	belle_sip_request_t *req=NULL;
	if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) {
		if (from)
			sal_op_set_from(op,from);
		if (to)
			sal_op_set_to(op,to);

		sal_op_publish_fill_cbs(op);
		req=sal_op_build_request(op,"PUBLISH");
		if (sal_op_get_contact_address(op)){
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op)));
		}
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname));
		sal_op_add_body(op,BELLE_SIP_MESSAGE(req),body);
		return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener);
	} else {
		/*update status*/
		const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
		belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
		/*update body*/
		sal_op_add_body(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? body : NULL);
		return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires);
	}
}
Exemplo n.º 6
0
static void presence_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase){
	SalOp* op = (SalOp*)user_pointer;
	if (status_code >= 300) {
		ms_message("The SUBSCRIBE dialog no longer works. Let's restart a new one.");
		belle_sip_refresher_stop(op->refresher);
		if (op->dialog) { /*delete previous dialog if any*/
			set_or_update_dialog(op, NULL);
		}

		if (sal_op_get_contact_address(op)) {
			/*contact is also probably not good*/
			SalAddress* contact=sal_address_clone(sal_op_get_contact_address(op));
			sal_address_set_port(contact,-1);
			sal_address_set_domain(contact,NULL);
			sal_op_set_contact_address(op,contact);
			sal_address_destroy(contact);
		}
		/*send a new SUBSCRIBE, that will attempt to establish a new dialog*/
		sal_subscribe_presence(op,NULL,NULL,-1);
	}
}
Exemplo n.º 7
0
/*presence publish */
int sal_publish_presence(SalOp *op, const char *from, const char *to, int expires, SalPresenceModel *presence){
	belle_sip_request_t *req=NULL;
	if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) {
		if (from)
			sal_op_set_from(op,from);
		if (to)
			sal_op_set_to(op,to);

		op->type=SalOpPublish;
		req=sal_op_build_request(op,"PUBLISH");
		if (sal_op_get_contact_address(op)){
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op)));
		}
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event","presence"));
		sal_add_presence_info(op,BELLE_SIP_MESSAGE(req),presence);
		return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener);
	} else {
		/*update presence status*/
		const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
		belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
		sal_add_presence_info(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? presence : NULL);
		return belle_sip_refresher_refresh(op->refresher,expires);
	}
}
Exemplo n.º 8
0
static void process_response_event(void *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);
	int response_code = belle_sip_response_get_status_code(response);
	if (!client_transaction) {
		ms_warning("Discarding stateless response [%i]",response_code);
		return;
	} else {
		SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
		belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
		belle_sip_header_contact_t* original_contact;
		belle_sip_header_address_t* contact_address=NULL;
		belle_sip_header_via_t* via_header;
		belle_sip_uri_t* contact_uri;
		unsigned int contact_port;
		const char* received;
		int rport;
		bool_t contact_updated=FALSE;
		char* new_contact;

		if (op->state == SalOpStateTerminated) {
			belle_sip_message("Op is terminated, nothing to do with this [%i]",response_code);
			return;
		}
		if (!op->base.remote_ua) {
			sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response));
		}
		if (!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(response), belle_sip_header_call_id_t))));
		}

		sal_op_assign_recv_headers(op,(belle_sip_message_t*)response);
		
		if (op->callbacks.process_response_event) {

			if (op->base.root->nat_helper_enabled) {
				/*Fix contact if needed*/
				via_header= (belle_sip_header_via_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_VIA);
				received = belle_sip_header_via_get_received(via_header);
				rport = belle_sip_header_via_get_rport(via_header);
				if ((original_contact=belle_sip_message_get_header_by_type(request,belle_sip_header_contact_t))) {
					/*update contact with sent values in any cases*/
					contact_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(original_contact)));
					sal_op_set_contact_address(op,(const SalAddress *)contact_address);
					belle_sip_object_unref(contact_address);
				}
				if (sal_op_get_contact(op)){
					if (received!=NULL || rport>0) {
						contact_address = BELLE_SIP_HEADER_ADDRESS(sal_address_clone(sal_op_get_contact_address(op)));
						contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_address));
						if (received && strcmp(received,belle_sip_uri_get_host(contact_uri))!=0) {
							/*need to update host*/
							belle_sip_uri_set_host(contact_uri,received);
							contact_updated=TRUE;
						}
						contact_port =  belle_sip_uri_get_port(contact_uri);
						if (rport>0 && rport!=contact_port && (contact_port+rport)!=5060) {
							/*need to update port*/
							belle_sip_uri_set_port(contact_uri,rport);
							contact_updated=TRUE;
						}

						/*try to fix transport if needed (very unlikely)*/
						if (strcasecmp(belle_sip_header_via_get_transport(via_header),"UDP")!=0) {
							if (!belle_sip_uri_get_transport_param(contact_uri)
									||strcasecmp(belle_sip_uri_get_transport_param(contact_uri),belle_sip_header_via_get_transport(via_header))!=0) {
								belle_sip_uri_set_transport_param(contact_uri,belle_sip_header_via_get_transport_lowercase(via_header));
								contact_updated=TRUE;
							}
						} else {
							if (belle_sip_uri_get_transport_param(contact_uri)) {
								contact_updated=TRUE;
								belle_sip_uri_set_transport_param(contact_uri,NULL);
							}
						}
						if (contact_updated) {
							char* old_contact=belle_sip_object_to_string(BELLE_SIP_OBJECT(sal_op_get_contact_address(op)));
							new_contact=belle_sip_object_to_string(BELLE_SIP_OBJECT(contact_address));
							ms_message("Updating contact from [%s] to [%s] for [%p]",old_contact,new_contact,op);
							sal_op_set_contact_address(op,(const SalAddress *)contact_address);
							belle_sip_free(new_contact);
							belle_sip_free(old_contact);
						}
						if (contact_address)belle_sip_object_unref(contact_address);
					}
				}
			}
			
			/*handle authorization*/
			switch (response_code) {
				case 200: {
					break;
				}
				case 401:
				case 407:{
					
					/*belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);*//*remove op from trans*/
					if (op->state == SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) {
						/*only bye are completed*/
						belle_sip_message("Op is in state terminating, nothing else to do ");
					} else {
						if (op->pending_auth_transaction){
							belle_sip_object_unref(op->pending_auth_transaction);
							op->pending_auth_transaction=NULL;
						}
						op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction);
						sal_process_authentication(op);
						return;
					}
				}
			}
			op->callbacks.process_response_event(op,event);
		} else {
			ms_error("Unhandled event response [%p]",event);
		}
	}

}
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg, const char *peer_uri){
	belle_sip_request_t* req;
	char content_type_raw[256];
	size_t content_length = msg?strlen(msg):0;
	time_t curtime = time(NULL);
	uint8_t *multipartEncryptedMessage = NULL;
	int retval;
	
	if (op->dialog){
		/*for SIP MESSAGE that are sent in call's dialog*/
		req = belle_sip_dialog_create_queued_request(op->dialog,"MESSAGE");
	}else{
		sal_op_message_fill_cbs(op);
		if (from)
			sal_op_set_from(op, from);
		if (to)
			sal_op_set_to(op, to);
		op->dir = SalOpDirOutgoing;

		req = sal_op_build_request(op,"MESSAGE");
		if (req == NULL ){
			return -1;
		}
		if (sal_op_get_contact_address(op)){
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(sal_op_create_contact(op)));
		}
	}

	/* shall we try to encrypt the message?*/
	if ((strcmp(content_type, "xml/cipher") == 0) || ((strcmp(content_type, "application/cipher.vnd.gsma.rcs-ft-http+xml") == 0))) {
		/* access the zrtp cache to get keys needed to cipher the message */
		LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
		FILE *CACHEFD = fopen(lc->zrtp_secrets_cache, "rb+");
		if (CACHEFD == NULL) {
			ms_warning("Unable to access ZRTP ZID cache to encrypt message");
			/*probably not a good idea to do this:*/
			sal_error_info_set(&op->error_info, SalReasonNotAcceptable, 488, "Unable to encrypt IM", NULL);
			op->base.root->callbacks.text_delivery_update(op,SalTextDeliveryFailed);
			return -1;
		} else {
			size_t cacheSize;
			char *cacheString;
			xmlDocPtr cacheXml;
			int retval;

			cacheString=ms_load_file_content(CACHEFD, &cacheSize);
			if (!cacheString){
				ms_warning("Unable to load content of ZRTP ZID cache to encrypt message");
				return -1;
			}
			cacheString[cacheSize] = '\0';
			cacheSize += 1;
			fclose(CACHEFD);
			cacheXml = xmlParseDoc((xmlChar*)cacheString);
			ms_free(cacheString);
			retval = lime_createMultipartMessage(cacheXml, (uint8_t *)msg, (uint8_t *)peer_uri, &multipartEncryptedMessage);
			if (retval != 0) {
				ms_warning("Unable to encrypt message for %s : %s - op [%p]", peer_uri, lime_error_code_to_string(retval), op);
				xmlFreeDoc(cacheXml);
				free(multipartEncryptedMessage);
				/*probably not a good idea to do this:*/
				sal_error_info_set(&op->error_info, SalReasonNotAcceptable, 488, "Unable to encrypt IM", NULL);
				op->base.root->callbacks.text_delivery_update(op,SalTextDeliveryFailed);
				return -1;
			} else {
				/* dump updated cache to a string */
				xmlChar *xmlStringOutput;
				int xmlStringLength;
				xmlDocDumpFormatMemoryEnc(cacheXml, &xmlStringOutput, &xmlStringLength, "UTF-8", 0);
				/* write it to the cache file */
				CACHEFD = fopen(lc->zrtp_secrets_cache, "wb+");
				if (fwrite(xmlStringOutput, 1, xmlStringLength, CACHEFD)<=0){
					ms_warning("Unable to write zid cache");
				}
				xmlFree(xmlStringOutput);
				fclose(CACHEFD);
				content_length = strlen((const char *)multipartEncryptedMessage);
			}
			xmlFreeDoc(cacheXml);
		}
	}

	snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type);
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw)));
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length)));
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime)));
	belle_sip_message_set_body(BELLE_SIP_MESSAGE(req),(multipartEncryptedMessage==NULL)?msg:(const char *)multipartEncryptedMessage,content_length);
	retval = sal_op_send_request(op,req);
	free(multipartEncryptedMessage);

	return retval;
}