sal_impl.c 23 KB
Newer Older
jehan's avatar
jehan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
linphone
Copyright (C) 2012  Belledonne Communications, Grenoble, France

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
19 20


jehan's avatar
jehan committed
21
#include "sal_impl.h"
Yann Diorcet's avatar
Yann Diorcet committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

void _belle_sip_log(belle_sip_log_level lev, const char *fmt, va_list args) {
	int ortp_level;
	switch(lev) {
		case BELLE_SIP_LOG_FATAL:
			ortp_level=ORTP_FATAL;
		break;
		case BELLE_SIP_LOG_ERROR:
			ortp_level=ORTP_ERROR;
		break;
		case BELLE_SIP_LOG_WARNING:
			ortp_level=ORTP_WARNING;
		break;
		case BELLE_SIP_LOG_MESSAGE:
			ortp_level=ORTP_MESSAGE;
		break;
		case BELLE_SIP_LOG_DEBUG:
jehan's avatar
jehan committed
39
		default:
jehan's avatar
jehan committed
40
			ortp_level=ORTP_DEBUG;
jehan's avatar
jehan committed
41
			break;
Yann Diorcet's avatar
Yann Diorcet committed
42 43 44 45 46 47
	}
	if (ortp_log_level_enabled(ortp_level)){
		ortp_logv(ortp_level,fmt,args);
	}
}

jehan's avatar
jehan committed
48 49 50 51 52 53
void sal_enable_logs(){
	belle_sip_set_log_level(BELLE_SIP_LOG_MESSAGE);
}
void sal_disable_logs() {
	belle_sip_set_log_level(BELLE_SIP_LOG_ERROR);
}
jehan's avatar
jehan committed
54 55 56 57 58 59 60 61
static void sal_add_pending_auth(Sal *sal, SalOp *op){
	sal->pending_auths=ms_list_append(sal->pending_auths,op);
}

 void sal_remove_pending_auth(Sal *sal, SalOp *op){
	sal->pending_auths=ms_list_remove(sal->pending_auths,op);
}

jehan's avatar
jehan committed
62
void sal_process_authentication(SalOp *op, belle_sip_response_t *response) {
jehan's avatar
jehan committed
63 64
	belle_sip_request_t* request;
	bool_t is_within_dialog=FALSE;
65 66
	belle_sip_list_t* auth_list=NULL;
	belle_sip_auth_event_t* auth_event;
jehan's avatar
jehan committed
67 68 69 70 71 72 73 74 75
	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 *)op->request);
		is_within_dialog=TRUE;
	} else {
		request=op->request;
		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);

	}
76
	if (belle_sip_provider_add_authorization(op->base.root->prov,request,response,&auth_list)) {
jehan's avatar
jehan committed
77 78
		if (is_within_dialog) {
			sal_op_send_request(op,request);
79 80
		} else {
			sal_op_resend_request(op,request);
jehan's avatar
jehan committed
81
		}
jehan's avatar
jehan committed
82 83
	}else {
		ms_message("No auth info found for [%s]",sal_op_get_from(op));
jehan's avatar
jehan committed
84 85 86
		if (is_within_dialog) {
			belle_sip_object_unref(request);
		}
87 88 89 90 91 92
		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_new();
		op->auth_info->realm = ms_strdup(belle_sip_auth_event_get_realm(auth_event)) ;
		op->auth_info->username = ms_strdup(belle_sip_auth_event_get_username(auth_event)) ;
		belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy);
jehan's avatar
jehan committed
93
		sal_add_pending_auth(op->base.root,op);
jehan's avatar
jehan committed
94 95 96
	}

}
jehan's avatar
jehan committed
97 98 99
static void process_dialog_terminated(void *sal, const belle_sip_dialog_terminated_event_t *event){
	belle_sip_dialog_t* dialog =  belle_sip_dialog_terminated_get_dialog(event);
	SalOp* op = belle_sip_dialog_get_application_data(dialog);
100
	if (op && op->callbacks.process_dialog_terminated) {
jehan's avatar
jehan committed
101 102
		op->callbacks.process_dialog_terminated(op,event);
	} else {
103
		ms_error("sal process_dialog_terminated no op found for this dialog [%p], ignoring",dialog);
jehan's avatar
jehan committed
104
	}
jehan's avatar
jehan committed
105 106
}
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
jehan's avatar
jehan committed
107 108 109 110 111 112 113 114 115
	belle_sip_client_transaction_t*client_transaction;
	SalOp* op;
	if (belle_sip_object_is_instance_of(BELLE_SIP_OBJECT(belle_sip_io_error_event_get_source(event)),BELLE_SIP_TYPE_ID(belle_sip_client_transaction_t))) {
		client_transaction=BELLE_SIP_CLIENT_TRANSACTION(belle_sip_io_error_event_get_source(event));
		op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
		if (op->callbacks.process_io_error) {
				op->callbacks.process_io_error(op,event);
		}
	} else {
116
		ms_error("sal process_io_error not implemented yet for non transaction");
jehan's avatar
jehan committed
117
	}
jehan's avatar
jehan committed
118
}
jehan's avatar
jehan committed
119
static void process_request_event(void *sal, const belle_sip_request_event_t *event) {
jehan's avatar
jehan committed
120
	SalOp* op=NULL;
jehan's avatar
jehan committed
121 122 123 124
	belle_sip_request_t* req = belle_sip_request_event_get_request(event);
	belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event);
	belle_sip_header_address_t* origin_address;
	belle_sip_header_address_t* address;
jehan's avatar
jehan committed
125
	belle_sip_header_from_t* from_header;
jehan's avatar
jehan committed
126
	belle_sip_header_to_t* to;
jehan's avatar
jehan committed
127
	belle_sip_response_t* resp;
128

jehan's avatar
jehan committed
129 130
	from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t);

jehan's avatar
jehan committed
131 132 133 134
	if (dialog) {
		op=(SalOp*)belle_sip_dialog_get_application_data(dialog);
	} else if (strcmp("INVITE",belle_sip_request_get_method(req))==0) {
		op=sal_op_new((Sal*)sal);
jehan's avatar
jehan committed
135
		op->dir=SalOpDirIncoming;
jehan's avatar
jehan committed
136
		sal_op_call_fill_cbs(op);
jehan's avatar
jehan committed
137 138 139 140
	} else if (strcmp("SUBSCRIBE",belle_sip_request_get_method(req))==0) {
		op=sal_op_new((Sal*)sal);
		op->dir=SalOpDirIncoming;
		sal_op_presence_fill_cbs(op);
jehan's avatar
jehan committed
141
	} else if (strcmp("MESSAGE",belle_sip_request_get_method(req))==0) {
142 143 144 145
		op=sal_op_new((Sal*)sal);
		op->dir=SalOpDirIncoming;
		sal_op_message_fill_cbs(op);

jehan's avatar
jehan committed
146
	} else if (strcmp("OPTIONS",belle_sip_request_get_method(req))==0) {
147 148 149 150
		resp=belle_sip_response_create_from_request(req,200);
		belle_sip_provider_send_response(((Sal*)sal)->prov,resp);
		return;
	}else {
jehan's avatar
jehan committed
151
		ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req));
152
		resp=belle_sip_response_create_from_request(req,501);
jehan's avatar
jehan committed
153
		belle_sip_provider_send_response(((Sal*)sal)->prov,resp);
jehan's avatar
jehan committed
154
		return;
jehan's avatar
jehan committed
155 156 157
	}

	if (!op->base.from_address)  {
jehan's avatar
jehan committed
158 159
		address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header))
														,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header)));
jehan's avatar
jehan committed
160 161 162
		sal_op_set_from_address(op,(SalAddress*)address);
		belle_sip_object_unref(address);
	}
jehan's avatar
jehan committed
163 164


jehan's avatar
jehan committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
	if (!op->base.to_address) {
		to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t);
		address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to))
												,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to)));
		sal_op_set_to_address(op,(SalAddress*)address);
		belle_sip_object_unref(address);
	}

	if (!op->base.origin) {
		/*set origin uri*/
		origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req));
		__sal_op_set_network_origin_address(op,(SalAddress*)origin_address);
		belle_sip_object_unref(origin_address);
	}
	if (!op->base.remote_ua) {
		sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(req));
	}

jehan's avatar
jehan committed
183 184 185
	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(req), belle_sip_header_call_id_t))));
	}
jehan's avatar
jehan committed
186 187 188 189 190 191
	if (op->callbacks.process_request_event) {
		op->callbacks.process_request_event(op,event);
	} else {
		ms_error("sal process_request_event not implemented yet");
	}

jehan's avatar
jehan committed
192 193 194 195 196
}

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);
jehan's avatar
jehan committed
197
	int response_code = belle_sip_response_get_status_code(response);
198 199
	if (!client_transaction) {
		ms_warning("Discarding state less response [%i]",response_code);
jehan's avatar
jehan committed
200
		return;
201 202 203 204 205 206 207 208 209 210 211 212
	} 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;
Sylvain Berfini's avatar
Sylvain Berfini committed
213 214
		belle_sip_request_t* old_request=NULL;
		belle_sip_response_t* old_response=NULL;
215 216 217 218 219 220 221 222


		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));
jehan's avatar
jehan committed
223
		}
jehan's avatar
jehan committed
224 225 226
		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))));
		}
227 228
		if (op->callbacks.process_response_event) {

jehan's avatar
jehan committed
229 230 231 232 233
			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);
234 235 236 237 238
				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);
jehan's avatar
jehan committed
239
				}
240

jehan's avatar
jehan committed
241 242 243 244 245 246 247 248
				if (received!=NULL || rport>0) {
					if (sal_op_get_contact(op)){
						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);
249 250
						contact_updated=TRUE;
					}
jehan's avatar
jehan committed
251 252 253 254
					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);
255 256
						contact_updated=TRUE;
					}
jehan's avatar
jehan committed
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

					/*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) {
272
						char* old_contact=belle_sip_object_to_string(BELLE_SIP_OBJECT(sal_op_get_contact_address(op)));
jehan's avatar
jehan committed
273
						new_contact=belle_sip_object_to_string(BELLE_SIP_OBJECT(contact_address));
274 275
						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);
jehan's avatar
jehan committed
276
						belle_sip_free(new_contact);
277
						belle_sip_free(old_contact);
jehan's avatar
jehan committed
278 279
					}
					if (contact_address)belle_sip_object_unref(contact_address);
280
				}
jehan's avatar
jehan committed
281
			}
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
			/*update request/response
			 * maybe only the transaction should be kept*/
			old_request=op->request;
			op->request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
			belle_sip_object_ref(op->request);
			if (old_request) belle_sip_object_unref(old_request);

			old_response=op->response;
			op->response=response; /*kept for use at authorization time*/
			belle_sip_object_ref(op->response);
			if (old_response) belle_sip_object_unref(old_response);

			/*handle authozation*/
			switch (response_code) {
			case 200: {
				sal_remove_pending_auth(op->base.root,op);/*just in case*/
				break;
			}
			case 401:
			case 407:{
302
				/*belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);*//*remove op from trans*/
303 304 305
				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 ");
306 307 308 309 310
					return;
				} else {
					sal_process_authentication(op,response);
					return;
				}
jehan's avatar
jehan committed
311
			}
jehan's avatar
jehan committed
312
			}
jehan's avatar
jehan committed
313

314 315 316 317 318
			op->callbacks.process_response_event(op,event);

		} else {
			ms_error("Unhandled event response [%p]",event);
		}
jehan's avatar
jehan committed
319 320 321 322
	}

}
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
323
	belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event);
jehan's avatar
jehan committed
324
	SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
325
	if (op && op->callbacks.process_timeout) {
jehan's avatar
jehan committed
326
		op->callbacks.process_timeout(op,event);
327
	} else {
jehan's avatar
jehan committed
328 329 330 331
		ms_error("Unhandled event timeout [%p]",event);
	}
}
static void process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
332 333
	belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event);
	belle_sip_server_transaction_t* server_transaction = belle_sip_transaction_terminated_event_get_server_transaction(event);
334
	belle_sip_transaction_t* trans;
Sylvain Berfini's avatar
Sylvain Berfini committed
335 336
	SalOp* op;

337 338 339 340 341
	if(client_transaction)
		trans=BELLE_SIP_TRANSACTION(client_transaction);
	 else
		 trans=BELLE_SIP_TRANSACTION(server_transaction);

Sylvain Berfini's avatar
Sylvain Berfini committed
342
	op = (SalOp*)belle_sip_transaction_get_application_data(trans);
343 344 345 346
	if (op && op->callbacks.process_transaction_terminated) {
		op->callbacks.process_transaction_terminated(op,event);
	} else {
		ms_error("Unhandled transaction terminated [%p]",trans);
jehan's avatar
jehan committed
347
	}
348
	if (op) sal_op_unref(op); /*no longuer need to ref op*/
jehan's avatar
jehan committed
349
}
jehan's avatar
jehan committed
350 351 352 353 354 355 356 357 358 359 360
static void process_auth_requested(void *sal, belle_sip_auth_event_t *auth_event) {
	SalAuthInfo auth_info;
	memset(&auth_info,0,sizeof(SalAuthInfo));
	auth_info.username=(char*)belle_sip_auth_event_get_username(auth_event);
	auth_info.realm=(char*)belle_sip_auth_event_get_realm(auth_event);
	((Sal*)sal)->callbacks.auth_requested(sal,&auth_info);
	belle_sip_auth_event_set_passwd(auth_event,(const char*)auth_info.password);
	belle_sip_auth_event_set_ha1(auth_event,(const char*)auth_info.ha1);
	belle_sip_auth_event_set_userid(auth_event,(const char*)auth_info.userid);
	return;
}
jehan's avatar
jehan committed
361
Sal * sal_init(){
jehan's avatar
jehan committed
362
	char stack_string[64];
jehan's avatar
jehan committed
363
	belle_sip_listener_t* listener;
jehan's avatar
jehan committed
364
	Sal * sal=ms_new0(Sal,1);
jehan's avatar
jehan committed
365
	sal->nat_helper_enabled=TRUE;
jehan's avatar
jehan committed
366 367
	snprintf(stack_string,sizeof(stack_string)-1,"(belle-sip/%s)",belle_sip_version_to_string());
	sal->user_agent=belle_sip_header_user_agent_new();
jehan's avatar
jehan committed
368
#if defined(PACKAGE_NAME) && defined(LINPHONE_VERSION)
jehan's avatar
jehan committed
369
	belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LINPHONE_VERSION);
jehan's avatar
jehan committed
370 371
#endif

jehan's avatar
jehan committed
372 373
	belle_sip_header_user_agent_add_product(sal->user_agent,stack_string);
	belle_sip_object_ref(sal->user_agent);
Yann Diorcet's avatar
Yann Diorcet committed
374
	belle_sip_set_log_handler(_belle_sip_log);
jehan's avatar
jehan committed
375 376 377 378 379 380 381 382
	sal->stack = belle_sip_stack_new(NULL);
	sal->prov = belle_sip_stack_create_provider(sal->stack,NULL);
	sal->listener_callbacks.process_dialog_terminated=process_dialog_terminated;
	sal->listener_callbacks.process_io_error=process_io_error;
	sal->listener_callbacks.process_request_event=process_request_event;
	sal->listener_callbacks.process_response_event=process_response_event;
	sal->listener_callbacks.process_timeout=process_timeout;
	sal->listener_callbacks.process_transaction_terminated=process_transaction_terminated;
jehan's avatar
jehan committed
383
	sal->listener_callbacks.process_auth_requested=process_auth_requested;
jehan's avatar
jehan committed
384
	belle_sip_provider_add_sip_listener(sal->prov,listener=belle_sip_listener_create_from_callbacks(&sal->listener_callbacks,sal));
jehan's avatar
jehan committed
385
	/* belle_sip_callbacks_t is unowned, why ?belle_sip_object_unref(listener);*/
jehan's avatar
jehan committed
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
	return sal;
}
void sal_set_user_pointer(Sal *sal, void *user_data){
	sal->up=user_data;
}

void *sal_get_user_pointer(const Sal *sal){
	return sal->up;
}

static void unimplemented_stub(){
	ms_warning("Unimplemented SAL callback");
}

void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
	memcpy(&ctx->callbacks,cbs,sizeof(*cbs));
	if (ctx->callbacks.call_received==NULL)
		ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub;
	if (ctx->callbacks.call_ringing==NULL)
		ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub;
	if (ctx->callbacks.call_accepted==NULL)
		ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub;
	if (ctx->callbacks.call_failure==NULL)
		ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
	if (ctx->callbacks.call_terminated==NULL)
		ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
	if (ctx->callbacks.call_released==NULL)
		ctx->callbacks.call_released=(SalOnCallReleased)unimplemented_stub;
	if (ctx->callbacks.call_updating==NULL)
		ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub;
	if (ctx->callbacks.auth_requested_legacy==NULL)
		ctx->callbacks.auth_requested_legacy=(SalOnAuthRequestedLegacy)unimplemented_stub;
	if (ctx->callbacks.auth_success==NULL)
		ctx->callbacks.auth_success=(SalOnAuthSuccess)unimplemented_stub;
	if (ctx->callbacks.register_success==NULL)
		ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub;
	if (ctx->callbacks.register_failure==NULL)
		ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
	if (ctx->callbacks.dtmf_received==NULL)
		ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
	if (ctx->callbacks.notify==NULL)
		ctx->callbacks.notify=(SalOnNotify)unimplemented_stub;
	if (ctx->callbacks.notify_presence==NULL)
		ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub;
	if (ctx->callbacks.subscribe_received==NULL)
		ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
	if (ctx->callbacks.text_received==NULL)
		ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
	if (ctx->callbacks.ping_reply==NULL)
		ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
	if (ctx->callbacks.auth_requested==NULL)
		ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
}



void sal_uninit(Sal* sal){
jehan's avatar
jehan committed
443
	belle_sip_object_unref(sal->user_agent);
jehan's avatar
jehan committed
444 445 446 447 448 449
	belle_sip_object_unref(sal->prov);
	belle_sip_object_unref(sal->stack);
	ms_free(sal);
	return ;
};

jehan's avatar
jehan committed
450
int sal_add_listen_port(Sal *ctx, SalAddress* addr){
jehan's avatar
jehan committed
451
	int result;
jehan's avatar
jehan committed
452 453 454 455
	belle_sip_listening_point_t* lp = belle_sip_stack_create_listening_point(ctx->stack
																			,sal_address_get_domain(addr)
																			,sal_address_get_port_int(addr)
																			,sal_transport_to_string(sal_address_get_transport(addr)));
jehan's avatar
jehan committed
456
	if (lp) {
jehan's avatar
jehan committed
457
		belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
jehan's avatar
jehan committed
458 459 460 461 462 463
		result = belle_sip_provider_add_listening_point(ctx->prov,lp);
	} else {
		return -1;
	}
	return result;
}
jehan's avatar
jehan committed
464 465 466 467 468 469 470 471 472 473
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure) {
	SalAddress* sal_addr = sal_address_new(NULL);
	int result;
	sal_address_set_domain(sal_addr,addr);
	sal_address_set_port_int(sal_addr,port);
	sal_address_set_transport(sal_addr,tr);
	result = sal_add_listen_port(ctx,sal_addr);
	sal_address_destroy(sal_addr);
	return result;
}
jehan's avatar
jehan committed
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
static void remove_listening_point(belle_sip_listening_point_t* lp,belle_sip_provider_t* prov) {
	belle_sip_provider_remove_listening_point(prov,lp);
}
int sal_unlisten_ports(Sal *ctx){
	const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(ctx->prov);
	belle_sip_list_t * tmp_list = belle_sip_list_copy(lps);
	belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))remove_listening_point,ctx->prov);
	belle_sip_list_free(tmp_list);

	ms_message("sal_unlisten_ports done");
	return 0;
}
ortp_socket_t sal_get_socket(Sal *ctx){
	ms_fatal("sal_get_socket not implemented yet");
	return -1;
}
void sal_set_user_agent(Sal *ctx, const char *user_agent){
jehan's avatar
jehan committed
491 492
	belle_sip_header_user_agent_set_products(ctx->user_agent,NULL);
	belle_sip_header_user_agent_add_product(ctx->user_agent,user_agent);
jehan's avatar
jehan committed
493 494 495 496
	return ;
}
/*keepalive period in ms*/
void sal_set_keepalive_period(Sal *ctx,unsigned int value){
jehan's avatar
jehan committed
497
	const belle_sip_list_t* iterator;
jehan's avatar
jehan committed
498
	belle_sip_listening_point_t* lp;
jehan's avatar
jehan committed
499 500
	ctx->keep_alive=value;
	for (iterator=belle_sip_provider_get_listening_points(ctx->prov);iterator!=NULL;iterator=iterator->next) {
jehan's avatar
jehan committed
501 502 503 504
		lp=(belle_sip_listening_point_t*)iterator->data;
		if (ctx->use_tcp_tls_keep_alive || strcasecmp(belle_sip_listening_point_get_transport(lp),"udp")==0) {
			belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
		}
jehan's avatar
jehan committed
505
	}
jehan's avatar
jehan committed
506 507 508 509 510 511 512
	return ;
}
/**
 * returns keepalive period in ms
 * 0 desactiaved
 * */
unsigned int sal_get_keepalive_period(Sal *ctx){
jehan's avatar
jehan committed
513
	return ctx->keep_alive;
jehan's avatar
jehan committed
514 515
}
void sal_use_session_timers(Sal *ctx, int expires){
jehan's avatar
jehan committed
516
	ctx->session_expires=expires;
jehan's avatar
jehan committed
517 518 519 520 521 522 523 524 525 526 527
	return ;
}
void sal_use_double_registrations(Sal *ctx, bool_t enabled){
	ms_error("sal_use_double_registrations not implemented yet");
	return ;
}
void sal_reuse_authorization(Sal *ctx, bool_t enabled){
	ms_error("sal_reuse_authorization not implemented yet");
	return ;
}
void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec){
jehan's avatar
jehan committed
528
	ctx->one_matching_codec=one_matching_codec;
jehan's avatar
jehan committed
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
}
void sal_use_rport(Sal *ctx, bool_t use_rports){
	ms_error("sal_use_rport not implemented yet");
	return ;
}
void sal_use_101(Sal *ctx, bool_t use_101){
	ms_error("sal_use_101 not implemented yet");
	return ;
}
void sal_set_root_ca(Sal* ctx, const char* rootCa){
	ms_error("sal_set_root_ca not implemented yet");
	return ;
}
void sal_verify_server_certificates(Sal *ctx, bool_t verify){
	ms_error("sal_verify_server_certificates not implemented yet");
	return ;
}
546 547 548 549 550 551
void sal_verify_server_cn(Sal *ctx, bool_t verify){
	ms_error("sal_verify_server_cn not implemented yet");
	return ;
}

void sal_use_tcp_tls_keepalive(Sal *ctx, bool_t enabled) {
jehan's avatar
jehan committed
552
	ctx->use_tcp_tls_keep_alive=enabled;
553
}
jehan's avatar
jehan committed
554 555 556 557 558 559 560 561 562 563 564 565 566 567

int sal_iterate(Sal *sal){
	belle_sip_stack_sleep(sal->stack,0);
	return 0;
}
MSList * sal_get_pending_auths(Sal *sal){
	return ms_list_copy(sal->pending_auths);
}

#define payload_type_set_number(pt,n)	(pt)->user_data=(void*)((long)n);
#define payload_type_get_number(pt)		((int)(long)(pt)->user_data)

/*misc*/
void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen){
jehan's avatar
jehan committed
568 569
	strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen);
	ms_error("Could not find default routable ip address !");
jehan's avatar
jehan committed
570
}
571 572 573 574 575 576

const char *sal_get_root_ca(Sal* ctx) {
	ms_fatal("sal_get_root_ca not implemented yet");
	return  NULL;
}
int sal_reset_transports(Sal *ctx){
jehan's avatar
jehan committed
577 578 579
	ms_message("reseting transport");
	belle_sip_provider_clean_channels(ctx->prov);
	return 0;
580 581 582 583
}
void sal_set_dscp(Sal *ctx, int dscp){
	ms_warning("sal_set_dscp not implemented");
}
584 585 586
void  sal_set_send_error(Sal *sal,int value) {
	 belle_sip_stack_set_send_error(sal->stack,value);
}
jehan's avatar
jehan committed
587 588 589
void  sal_set_recv_error(Sal *sal,int value) {
	 belle_sip_provider_set_recv_error(sal->prov,value);
}
jehan's avatar
jehan committed
590 591 592 593 594 595 596
void sal_nat_helper_enable(Sal *sal,bool_t enable) {
	sal->nat_helper_enabled=enable;
	ms_message("Sal nat helper [%s]",enable?"enabled":"disabled");
}
bool_t sal_nat_helper_enabled(Sal *sal) {
	return sal->nat_helper_enabled;
}
jehan's avatar
jehan committed
597 598 599 600 601 602
void sal_set_dns_timeout(Sal* sal,int timeout) {
	belle_sip_stack_set_dns_timeout(sal->stack, timeout);
}
int sal_get_dns_timeout(const Sal* sal)  {
	return belle_sip_stack_get_dns_timeout(sal->stack);
}