1 /*
2 linphone
3 Copyright (C) 2012  Belledonne Communications, Grenoble, France
4 
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 */
19 
20 #include "sal_impl.h"
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 typedef struct belle_sip_certificates_chain_t _SalCertificatesChain;
27 typedef struct belle_sip_signing_key_t _SalSigningKey;
28 
29 /*
30 rfc3323
31 4.2 Expressing Privacy Preferences
32 When a Privacy header is constructed, it MUST consist of either the
33    value 'none', or one or more of the values 'user', 'header' and
34    'session' (each of which MUST appear at most once) which MAY in turn
35    be followed by the 'critical' indicator.
36  */
sal_op_set_privacy_from_message(SalOp * op,belle_sip_message_t * msg)37 void sal_op_set_privacy_from_message(SalOp* op,belle_sip_message_t* msg) {
38 	belle_sip_header_privacy_t* privacy = belle_sip_message_get_header_by_type(msg,belle_sip_header_privacy_t);
39 	if (!privacy) {
40 		sal_op_set_privacy(op,SalPrivacyNone);
41 	} else {
42 		belle_sip_list_t* privacy_list=belle_sip_header_privacy_get_privacy(privacy);
43 		sal_op_set_privacy(op,0);
44 		for (;privacy_list!=NULL;privacy_list=privacy_list->next) {
45 			char* privacy_value=(char*)privacy_list->data;
46 			if(strcmp(sal_privacy_to_string(SalPrivacyCritical),privacy_value) == 0)
47 				sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyCritical);
48 			if(strcmp(sal_privacy_to_string(SalPrivacyHeader),privacy_value) == 0)
49 							sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyHeader);
50 			if(strcmp(sal_privacy_to_string(SalPrivacyId),privacy_value) == 0)
51 							sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyId);
52 			if(strcmp(sal_privacy_to_string(SalPrivacyNone),privacy_value) == 0) {
53 				sal_op_set_privacy(op,SalPrivacyNone);
54 				break;
55 			}
56 			if(strcmp(sal_privacy_to_string(SalPrivacySession),privacy_value) == 0)
57 							sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacySession);
58 			if(strcmp(sal_privacy_to_string(SalPrivacyUser),privacy_value) == 0)
59 										sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyUser);
60 		}
61 	}
62 }
63 static void set_tls_properties(Sal *ctx);
64 
_belle_sip_log(const char * domain,belle_sip_log_level lev,const char * fmt,va_list args)65 void _belle_sip_log(const char *domain, belle_sip_log_level lev, const char *fmt, va_list args) {
66 	int ortp_level;
67 	switch(lev) {
68 		case BELLE_SIP_LOG_FATAL:
69 			ortp_level=ORTP_FATAL;
70 		break;
71 		case BELLE_SIP_LOG_ERROR:
72 			ortp_level=ORTP_ERROR;
73 		break;
74 		case BELLE_SIP_LOG_WARNING:
75 			ortp_level=ORTP_WARNING;
76 		break;
77 		case BELLE_SIP_LOG_MESSAGE:
78 			ortp_level=ORTP_MESSAGE;
79 		break;
80 		case BELLE_SIP_LOG_DEBUG:
81 		default:
82 			ortp_level=ORTP_DEBUG;
83 			break;
84 	}
85 	if (ortp_log_level_enabled("belle-sip", ortp_level)){
86 		ortp_logv("belle-sip", ortp_level,fmt,args);
87 	}
88 }
89 
sal_enable_log()90 void sal_enable_log(){
91 	sal_set_log_level(ORTP_MESSAGE);
92 }
93 
sal_disable_log()94 void sal_disable_log() {
95 	sal_set_log_level(ORTP_ERROR);
96 }
97 
sal_set_log_level(OrtpLogLevel level)98 void sal_set_log_level(OrtpLogLevel level) {
99 	belle_sip_log_level belle_sip_level;
100 	if ((level&ORTP_FATAL) != 0) {
101 		belle_sip_level = BELLE_SIP_LOG_FATAL;
102 	} else if ((level&ORTP_ERROR) != 0) {
103 		belle_sip_level = BELLE_SIP_LOG_ERROR;
104 	} else if ((level&ORTP_WARNING) != 0) {
105 		belle_sip_level = BELLE_SIP_LOG_WARNING;
106 	} else if ((level&ORTP_MESSAGE) != 0) {
107 		belle_sip_level = BELLE_SIP_LOG_MESSAGE;
108 	} else if (((level&ORTP_DEBUG) != 0) || ((level&ORTP_TRACE) != 0)) {
109 		belle_sip_level = BELLE_SIP_LOG_DEBUG;
110 	} else {
111 		//well, this should never occurs but...
112 		belle_sip_level = BELLE_SIP_LOG_MESSAGE;
113 	}
114 	belle_sip_set_log_level(belle_sip_level);
115 }
116 
sal_add_pending_auth(Sal * sal,SalOp * op)117 void sal_add_pending_auth(Sal *sal, SalOp *op){
118 	if (bctbx_list_find(sal->pending_auths,op)==NULL){
119 		sal->pending_auths=bctbx_list_append(sal->pending_auths,op);
120 		op->has_auth_pending=TRUE;
121 	}
122 }
123 
sal_remove_pending_auth(Sal * sal,SalOp * op)124 void sal_remove_pending_auth(Sal *sal, SalOp *op){
125 	if (op->has_auth_pending){
126 		op->has_auth_pending=FALSE;
127 		if (bctbx_list_find(sal->pending_auths,op)){
128 			sal->pending_auths=bctbx_list_remove(sal->pending_auths,op);
129 		}
130 	}
131 }
132 
sal_process_authentication(SalOp * op)133 void sal_process_authentication(SalOp *op) {
134 	belle_sip_request_t* initial_request=belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_auth_transaction);
135 	belle_sip_request_t* new_request;
136 	bool_t is_within_dialog=FALSE;
137 	belle_sip_list_t* auth_list=NULL;
138 	belle_sip_auth_event_t* auth_event;
139 	belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction);
140 	belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(initial_request,belle_sip_header_from_t);
141 	belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from);
142 
143 	if (strcasecmp(belle_sip_uri_get_host(from_uri),"anonymous.invalid")==0){
144 		/*prefer using the from from the SalOp*/
145 		from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)sal_op_get_from_address(op));
146 	}
147 
148 	if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_CONFIRMED) {
149 		new_request = belle_sip_dialog_create_request_from(op->dialog,initial_request);
150 		if (!new_request)
151 			new_request = belle_sip_dialog_create_queued_request_from(op->dialog,initial_request);
152 		is_within_dialog=TRUE;
153 	} else {
154 		new_request=initial_request;
155 		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_AUTHORIZATION);
156 		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_PROXY_AUTHORIZATION);
157 	}
158 	if (new_request==NULL) {
159 		ms_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",op);
160 		return;
161 	}
162 
163 	if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list,op->base.realm)) {
164 		if (is_within_dialog) {
165 			sal_op_send_request(op,new_request);
166 		} else {
167 			sal_op_resend_request(op,new_request);
168 		}
169 		sal_remove_pending_auth(op->base.root,op);
170 	}else {
171 		belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(response,belle_sip_header_from_t);
172 		char *tmp=belle_sip_object_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from)));
173 		ms_message("No auth info found for [%s]",tmp);
174 		belle_sip_free(tmp);
175 		sal_add_pending_auth(op->base.root,op);
176 
177 		if (is_within_dialog) {
178 			belle_sip_object_unref(new_request);
179 		}
180 	}
181 	/*always store auth info, for case of wrong credential*/
182 	if (op->auth_info) {
183 		sal_auth_info_delete(op->auth_info);
184 		op->auth_info=NULL;
185 	}
186 	if (auth_list){
187 		auth_event=(belle_sip_auth_event_t*)(auth_list->data);
188 		op->auth_info=sal_auth_info_create(auth_event);
189 		belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy);
190 	}
191 }
192 
process_dialog_terminated(void * sal,const belle_sip_dialog_terminated_event_t * event)193 static void process_dialog_terminated(void *sal, const belle_sip_dialog_terminated_event_t *event){
194 	belle_sip_dialog_t* dialog =  belle_sip_dialog_terminated_event_get_dialog(event);
195 	SalOp* op = belle_sip_dialog_get_application_data(dialog);
196 	if (op && op->callbacks && op->callbacks->process_dialog_terminated) {
197 		op->callbacks->process_dialog_terminated(op,event);
198 	} else {
199 		ms_error("sal process_dialog_terminated no op found for this dialog [%p], ignoring",dialog);
200 	}
201 }
202 
process_io_error(void * user_ctx,const belle_sip_io_error_event_t * event)203 static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
204 	belle_sip_client_transaction_t*client_transaction;
205 	SalOp* op;
206 	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event),belle_sip_client_transaction_t)) {
207 		client_transaction=BELLE_SIP_CLIENT_TRANSACTION(belle_sip_io_error_event_get_source(event));
208 		op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
209 		/*also reset auth count on IO error*/
210 		op->auth_requests=0;
211 		if (op->callbacks && op->callbacks->process_io_error) {
212 			op->callbacks->process_io_error(op,event);
213 		}
214 	} else {
215 		/*ms_error("sal process_io_error not implemented yet for non transaction");*/
216 		/*nop, because already handle at transaction layer*/
217 	}
218 }
219 
process_request_event(void * ud,const belle_sip_request_event_t * event)220 static void process_request_event(void *ud, const belle_sip_request_event_t *event) {
221 	Sal *sal=(Sal*)ud;
222 	SalOp* op=NULL;
223 	belle_sip_request_t* req = belle_sip_request_event_get_request(event);
224 	belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event);
225 	belle_sip_header_address_t* origin_address;
226 	belle_sip_header_address_t* address=NULL;
227 	belle_sip_header_from_t* from_header;
228 	belle_sip_header_to_t* to;
229 	belle_sip_header_diversion_t* diversion;
230 	belle_sip_response_t* resp;
231 	belle_sip_header_t *evh;
232 	const char *method=belle_sip_request_get_method(req);
233 	belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t);
234 
235 	from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t);
236 
237 	if (dialog) {
238 		op=(SalOp*)belle_sip_dialog_get_application_data(dialog);
239 
240 		if (op == NULL  && strcmp("NOTIFY",method) == 0) {
241 			/*special case for Dialog created by notify mathing subscribe*/
242 			belle_sip_transaction_t * sub_trans = belle_sip_dialog_get_last_transaction(dialog);
243 			op = (SalOp*)belle_sip_transaction_get_application_data(sub_trans);
244 		}
245 		if (op==NULL || op->state==SalOpStateTerminated){
246 			ms_warning("Receiving request for null or terminated op [%p], ignored",op);
247 			return;
248 		}
249 	}else{
250 		/*handle the case where we are receiving a request with to tag but it is not belonging to any dialog*/
251 		belle_sip_header_to_t *to = belle_sip_message_get_header_by_type(req, belle_sip_header_to_t);
252 		if ((strcmp("INVITE",method)==0 || strcmp("NOTIFY",method)==0) && (belle_sip_header_to_get_tag(to) != NULL)) {
253 			ms_warning("Receiving %s with to-tag but no know dialog here. Rejecting.", method);
254 			resp=belle_sip_response_create_from_request(req,481);
255 			belle_sip_provider_send_response(sal->prov,resp);
256 			return;
257 		/* by default (eg. when a to-tag is present), out of dialog ACK are automatically
258 		handled in lower layers (belle-sip) but in case it misses, it will be forwarded to us */
259 		} else if (strcmp("ACK",method)==0 && (belle_sip_header_to_get_tag(to) == NULL)) {
260 			ms_warning("Receiving ACK without to-tag but no know dialog here. Ignoring");
261 			return;
262 		}
263 
264 		if (strcmp("INVITE",method)==0) {
265 			op=sal_op_new(sal);
266 			op->dir=SalOpDirIncoming;
267 			sal_op_call_fill_cbs(op);
268 		}else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) {
269 			op=sal_op_new(sal);
270 			op->dir=SalOpDirIncoming;
271 			if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){
272 				sal_op_presence_fill_cbs(op);
273 			}else
274 				sal_op_subscribe_fill_cbs(op);
275 		}else if (strcmp("MESSAGE",method)==0) {
276 			op=sal_op_new(sal);
277 			op->dir=SalOpDirIncoming;
278 			sal_op_message_fill_cbs(op);
279 		}else if (strcmp("OPTIONS",method)==0) {
280 			resp=belle_sip_response_create_from_request(req,200);
281 			belle_sip_provider_send_response(sal->prov,resp);
282 			return;
283 		}else if (strcmp("INFO",method)==0) {
284 			resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/
285 			belle_sip_provider_send_response(sal->prov,resp);
286 			return;
287 		}else if (strcmp("BYE",method)==0) {
288 			resp=belle_sip_response_create_from_request(req,481);/*out of dialog BYE */
289 			belle_sip_provider_send_response(sal->prov,resp);
290 			return;
291 		}else if (strcmp("CANCEL",method)==0) {
292 			resp=belle_sip_response_create_from_request(req,481);/*out of dialog CANCEL */
293 			belle_sip_provider_send_response(sal->prov,resp);
294 			return;
295 		}else if (sal->enable_test_features && strcmp("PUBLISH",method)==0) {
296 			resp=belle_sip_response_create_from_request(req,200);/*out of dialog PUBLISH */
297 			belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_header_create("SIP-Etag","4441929FFFZQOA"));
298 			belle_sip_provider_send_response(sal->prov,resp);
299 			return;
300 		}else {
301 			ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req));
302 			resp=belle_sip_response_create_from_request(req,405);
303 			belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp)
304 										,BELLE_SIP_HEADER(belle_sip_header_allow_create("INVITE, CANCEL, ACK, BYE, SUBSCRIBE, NOTIFY, MESSAGE, OPTIONS, INFO")));
305 			belle_sip_provider_send_response(sal->prov,resp);
306 			return;
307 		}
308 	}
309 
310 	if (!op->base.from_address)  {
311 		if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header)))
312 			address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header))
313 					,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header)));
314 		else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header))))
315 			address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header))
316 					,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header)));
317 		else
318 			ms_error("Cannot not find from uri from request [%p]",req);
319 		sal_op_set_from_address(op,(SalAddress*)address);
320 		belle_sip_object_unref(address);
321 	}
322 
323 	if( remote_contact ){
324 		__sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact)));
325 	}
326 
327 	if (!op->base.to_address) {
328 		to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t);
329 		if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to)))
330 			address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to))
331 					,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to)));
332 		else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to))))
333 			address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to))
334 					,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to)));
335 		else
336 			ms_error("Cannot not find to uri from request [%p]",req);
337 
338 		sal_op_set_to_address(op,(SalAddress*)address);
339 		belle_sip_object_unref(address);
340 	}
341 
342 	if(!op->base.diversion_address){
343 		diversion=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_diversion_t);
344 		if (diversion) {
345 			if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion)))
346 				address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion))
347 						,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion)));
348 			else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion))))
349 				address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion))
350 						,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion)));
351 			else
352 				ms_warning("Cannot not find diversion header from request [%p]",req);
353 			if (address) {
354 				sal_op_set_diversion_address(op,(SalAddress*)address);
355 				belle_sip_object_unref(address);
356 			}
357 		}
358 	}
359 
360 	if (!op->base.origin) {
361 		/*set origin uri*/
362 		origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req));
363 		__sal_op_set_network_origin_address(op,(SalAddress*)origin_address);
364 		belle_sip_object_unref(origin_address);
365 	}
366 	if (!op->base.remote_ua) {
367 		sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(req));
368 	}
369 
370 	if (!op->base.call_id) {
371 		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))));
372 	}
373 	/*It is worth noting that proxies can (and
374    will) remove this header field*/
375 	sal_op_set_privacy_from_message(op,(belle_sip_message_t*)req);
376 
377 	sal_op_assign_recv_headers(op,(belle_sip_message_t*)req);
378 	if (op->callbacks && op->callbacks->process_request_event) {
379 		op->callbacks->process_request_event(op,event);
380 	} else {
381 		ms_error("sal process_request_event not implemented yet");
382 	}
383 
384 }
385 
process_response_event(void * user_ctx,const belle_sip_response_event_t * event)386 static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){
387 	belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
388 	belle_sip_response_t* response = belle_sip_response_event_get_response(event);
389 	int response_code = belle_sip_response_get_status_code(response);
390 
391 	if (!client_transaction) {
392 		ms_warning("Discarding stateless response [%i]",response_code);
393 		return;
394 	} else {
395 		SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
396 		belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
397 		belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(response, belle_sip_header_contact_t);
398 
399 		if (op->state == SalOpStateTerminated) {
400 			belle_sip_message("Op [%p] is terminated, nothing to do with this [%i]", op, response_code);
401 			return;
402 		}
403 		/*do it all the time, since we can receive provisional responses from a different instance than the final one*/
404 		sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response));
405 
406 		if(remote_contact) {
407 			__sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact)));
408 		}
409 
410 		if (!op->base.call_id) {
411 			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))));
412 		}
413 
414 		sal_op_assign_recv_headers(op,(belle_sip_message_t*)response);
415 
416 		if (op->callbacks && op->callbacks->process_response_event) {
417 			/*handle authorization*/
418 			switch (response_code) {
419 				case 200:
420 					break;
421 				case 401:
422 				case 407:
423 					if (op->state == SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) {
424 						/*only bye are completed*/
425 						belle_sip_message("Op is in state terminating, nothing else to do ");
426 					} else {
427 						if (op->pending_auth_transaction){
428 							belle_sip_object_unref(op->pending_auth_transaction);
429 							op->pending_auth_transaction=NULL;
430 						}
431 						if (++op->auth_requests > 2) {
432 							ms_warning("Auth info cannot be found for op [%s/%s] after 2 attempts, giving up",sal_op_get_from(op)
433 																												,sal_op_get_to(op));
434 							op->base.root->callbacks.auth_failure(op,op->auth_info);
435 							sal_remove_pending_auth(op->base.root,op);
436 						} else {
437 							op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction);
438 							sal_process_authentication(op);
439 							return;
440 						}
441 					}
442 					break;
443 				case 403:
444 					if (op->auth_info) op->base.root->callbacks.auth_failure(op,op->auth_info);
445 					break;
446 			}
447 			if (response_code >= 180 && response_code !=401 && response_code !=407 && response_code !=403) {
448 				/*not an auth request*/
449 				op->auth_requests=0;
450 			}
451 			op->callbacks->process_response_event(op,event);
452 		} else {
453 			ms_error("Unhandled event response [%p]",event);
454 		}
455 	}
456 }
457 
process_timeout(void * user_ctx,const belle_sip_timeout_event_t * event)458 static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
459 	belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event);
460 	SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
461 	if (op && op->callbacks && op->callbacks->process_timeout) {
462 		op->callbacks->process_timeout(op,event);
463 	} else {
464 		ms_error("Unhandled event timeout [%p]",event);
465 	}
466 }
467 
process_transaction_terminated(void * user_ctx,const belle_sip_transaction_terminated_event_t * event)468 static void process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
469 	belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event);
470 	belle_sip_server_transaction_t* server_transaction = belle_sip_transaction_terminated_event_get_server_transaction(event);
471 	belle_sip_transaction_t* trans;
472 	SalOp* op;
473 
474 	if(client_transaction)
475 		trans=BELLE_SIP_TRANSACTION(client_transaction);
476 	 else
477 		trans=BELLE_SIP_TRANSACTION(server_transaction);
478 
479 	op = (SalOp*)belle_sip_transaction_get_application_data(trans);
480 	if (op && op->callbacks && op->callbacks->process_transaction_terminated) {
481 		op->callbacks->process_transaction_terminated(op,event);
482 	} else {
483 		ms_message("Unhandled transaction terminated [%p]",trans);
484 	}
485 	if (op) {
486 		sal_op_unref(op); /*because every transaction ref op*/
487 		belle_sip_transaction_set_application_data(trans,NULL); /*no longuer reference something we do not ref to avoid futur access of a released op*/
488 	}
489 }
490 
491 
process_auth_requested(void * sal,belle_sip_auth_event_t * event)492 static void process_auth_requested(void *sal, belle_sip_auth_event_t *event) {
493 	SalAuthInfo* auth_info = sal_auth_info_create(event);
494 	((Sal*)sal)->callbacks.auth_requested(sal,auth_info);
495 	belle_sip_auth_event_set_passwd(event,(const char*)auth_info->password);
496 	belle_sip_auth_event_set_ha1(event,(const char*)auth_info->ha1);
497 	belle_sip_auth_event_set_userid(event,(const char*)auth_info->userid);
498 	belle_sip_auth_event_set_signing_key(event,(belle_sip_signing_key_t *)auth_info->key);
499 	belle_sip_auth_event_set_client_certificates_chain(event,(belle_sip_certificates_chain_t* )auth_info->certificates);
500 	sal_auth_info_delete(auth_info);
501 }
502 
sal_init(MSFactory * factory)503 Sal * sal_init(MSFactory *factory){
504 	belle_sip_listener_callbacks_t listener_callbacks;
505 	Sal * sal=ms_new0(Sal,1);
506 
507 	/*belle_sip_object_enable_marshal_check(TRUE);*/
508 	sal->auto_contacts=TRUE;
509 	sal->factory = factory;
510 	/*first create the stack, which initializes the belle-sip object's pool for this thread*/
511 	belle_sip_set_log_handler(_belle_sip_log);
512 	sal->stack = belle_sip_stack_new(NULL);
513 
514 	sal->user_agent=belle_sip_header_user_agent_new();
515 #if defined(PACKAGE_NAME) && defined(LIBLINPHONE_VERSION)
516 	belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LIBLINPHONE_VERSION);
517 #else
518 	belle_sip_header_user_agent_add_product(sal->user_agent, "Unknown");
519 #endif
520 	sal_append_stack_string_to_user_agent(sal);
521 	belle_sip_object_ref(sal->user_agent);
522 
523 	sal->prov = belle_sip_stack_create_provider(sal->stack,NULL);
524 	sal_nat_helper_enable(sal,TRUE);
525 	memset(&listener_callbacks,0,sizeof(listener_callbacks));
526 	listener_callbacks.process_dialog_terminated=process_dialog_terminated;
527 	listener_callbacks.process_io_error=process_io_error;
528 	listener_callbacks.process_request_event=process_request_event;
529 	listener_callbacks.process_response_event=process_response_event;
530 	listener_callbacks.process_timeout=process_timeout;
531 	listener_callbacks.process_transaction_terminated=process_transaction_terminated;
532 	listener_callbacks.process_auth_requested=process_auth_requested;
533 	sal->listener=belle_sip_listener_create_from_callbacks(&listener_callbacks,sal);
534 	belle_sip_provider_add_sip_listener(sal->prov,sal->listener);
535 	sal->tls_verify=TRUE;
536 	sal->tls_verify_cn=TRUE;
537 	sal->refresher_retry_after=60000; /*default value in ms*/
538 	sal->enable_sip_update=TRUE;
539 	sal->pending_trans_checking=TRUE;
540 	sal->ssl_config = NULL;
541 	return sal;
542 }
543 
sal_set_user_pointer(Sal * sal,void * user_data)544 void sal_set_user_pointer(Sal *sal, void *user_data){
545 	sal->up=user_data;
546 }
547 
sal_get_user_pointer(const Sal * sal)548 void *sal_get_user_pointer(const Sal *sal){
549 	return sal->up;
550 }
551 
unimplemented_stub(void)552 static void unimplemented_stub(void){
553 	ms_warning("Unimplemented SAL callback");
554 }
555 
sal_set_callbacks(Sal * ctx,const SalCallbacks * cbs)556 void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
557 	memcpy(&ctx->callbacks,cbs,sizeof(*cbs));
558 	if (ctx->callbacks.call_received==NULL)
559 		ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub;
560 	if (ctx->callbacks.call_ringing==NULL)
561 		ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub;
562 	if (ctx->callbacks.call_accepted==NULL)
563 		ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub;
564 	if (ctx->callbacks.call_failure==NULL)
565 		ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
566 	if (ctx->callbacks.call_terminated==NULL)
567 		ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
568 	if (ctx->callbacks.call_released==NULL)
569 		ctx->callbacks.call_released=(SalOnCallReleased)unimplemented_stub;
570 	if (ctx->callbacks.call_updating==NULL)
571 		ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub;
572 	if (ctx->callbacks.auth_failure==NULL)
573 		ctx->callbacks.auth_failure=(SalOnAuthFailure)unimplemented_stub;
574 	if (ctx->callbacks.register_success==NULL)
575 		ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub;
576 	if (ctx->callbacks.register_failure==NULL)
577 		ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
578 	if (ctx->callbacks.dtmf_received==NULL)
579 		ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
580 	if (ctx->callbacks.notify==NULL)
581 		ctx->callbacks.notify=(SalOnNotify)unimplemented_stub;
582 	if (ctx->callbacks.subscribe_received==NULL)
583 		ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
584 	if (ctx->callbacks.incoming_subscribe_closed==NULL)
585 		ctx->callbacks.incoming_subscribe_closed=(SalOnIncomingSubscribeClosed)unimplemented_stub;
586 	if (ctx->callbacks.parse_presence_requested==NULL)
587 		ctx->callbacks.parse_presence_requested=(SalOnParsePresenceRequested)unimplemented_stub;
588 	if (ctx->callbacks.convert_presence_to_xml_requested==NULL)
589 		ctx->callbacks.convert_presence_to_xml_requested=(SalOnConvertPresenceToXMLRequested)unimplemented_stub;
590 	if (ctx->callbacks.notify_presence==NULL)
591 		ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub;
592 	if (ctx->callbacks.subscribe_presence_received==NULL)
593 		ctx->callbacks.subscribe_presence_received=(SalOnSubscribePresenceReceived)unimplemented_stub;
594 	if (ctx->callbacks.message_received==NULL)
595 		ctx->callbacks.message_received=(SalOnMessageReceived)unimplemented_stub;
596 	if (ctx->callbacks.ping_reply==NULL)
597 		ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
598 	if (ctx->callbacks.auth_requested==NULL)
599 		ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
600 	if (ctx->callbacks.info_received==NULL)
601 		ctx->callbacks.info_received=(SalOnInfoReceived)unimplemented_stub;
602 	if (ctx->callbacks.on_publish_response==NULL)
603 		ctx->callbacks.on_publish_response=(SalOnPublishResponse)unimplemented_stub;
604 	if (ctx->callbacks.on_expire==NULL)
605 		ctx->callbacks.on_expire=(SalOnExpire)unimplemented_stub;
606 }
607 
608 
609 
sal_uninit(Sal * sal)610 void sal_uninit(Sal* sal){
611 	belle_sip_object_unref(sal->user_agent);
612 	belle_sip_object_unref(sal->prov);
613 	belle_sip_object_unref(sal->stack);
614 	belle_sip_object_unref(sal->listener);
615 	if (sal->supported) belle_sip_object_unref(sal->supported);
616 	bctbx_list_free_with_data(sal->supported_tags,ms_free);
617 	bctbx_list_free_with_data(sal->supported_content_types, ms_free);
618 	if (sal->uuid) ms_free(sal->uuid);
619 	if (sal->root_ca) ms_free(sal->root_ca);
620 	if (sal->root_ca_data) ms_free(sal->root_ca_data);
621 	ms_free(sal);
622 };
623 
sal_transport_available(Sal * sal,SalTransport t)624 int sal_transport_available(Sal *sal, SalTransport t){
625 	switch(t){
626 		case SalTransportUDP:
627 		case SalTransportTCP:
628 			return TRUE;
629 		case SalTransportTLS:
630 			return belle_sip_stack_tls_available(sal->stack);
631 		case SalTransportDTLS:
632 			return FALSE;
633 	}
634 	return FALSE;
635 }
636 
sal_content_encoding_available(Sal * sal,const char * content_encoding)637 bool_t sal_content_encoding_available(Sal *sal, const char *content_encoding) {
638 	return (bool_t)belle_sip_stack_content_encoding_available(sal->stack, content_encoding);
639 }
640 
sal_add_listen_port(Sal * ctx,SalAddress * addr,bool_t is_tunneled)641 static int sal_add_listen_port(Sal *ctx, SalAddress* addr, bool_t is_tunneled){
642 	int result;
643 	belle_sip_listening_point_t* lp;
644 	if (is_tunneled){
645 #ifdef TUNNEL_ENABLED
646 		if (sal_address_get_transport(addr)!=SalTransportUDP){
647 			ms_error("Tunneled mode is only available for UDP kind of transports.");
648 			return -1;
649 		}
650 		lp = belle_sip_tunnel_listening_point_new(ctx->stack, ctx->tunnel_client);
651 		if (!lp){
652 			ms_error("Could not create tunnel listening point.");
653 			return -1;
654 		}
655 #else
656 		ms_error("No tunnel support in library.");
657 		return -1;
658 #endif
659 	}else{
660 		lp = belle_sip_stack_create_listening_point(ctx->stack,
661 									sal_address_get_domain(addr),
662 									sal_address_get_port(addr),
663 									sal_transport_to_string(sal_address_get_transport(addr)));
664 	}
665 	if (lp) {
666 		belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
667 		result = belle_sip_provider_add_listening_point(ctx->prov,lp);
668 		if (sal_address_get_transport(addr)==SalTransportTLS) {
669 			set_tls_properties(ctx);
670 		}
671 	} else {
672 		return -1;
673 	}
674 	return result;
675 }
676 
sal_listen_port(Sal * ctx,const char * addr,int port,SalTransport tr,int is_tunneled)677 int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_tunneled) {
678 	SalAddress* sal_addr = sal_address_new(NULL);
679 	int result;
680 	sal_address_set_domain(sal_addr,addr);
681 	sal_address_set_port(sal_addr,port);
682 	sal_address_set_transport(sal_addr,tr);
683 	result = sal_add_listen_port(ctx, sal_addr, is_tunneled);
684 	sal_address_destroy(sal_addr);
685 	return result;
686 }
687 
remove_listening_point(belle_sip_listening_point_t * lp,belle_sip_provider_t * prov)688 static void remove_listening_point(belle_sip_listening_point_t* lp,belle_sip_provider_t* prov) {
689 	belle_sip_provider_remove_listening_point(prov,lp);
690 }
691 
sal_get_listening_port(Sal * ctx,SalTransport tr)692 int sal_get_listening_port(Sal *ctx, SalTransport tr){
693 	const char *tpn=sal_transport_to_string(tr);
694 	belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(ctx->prov, tpn);
695 	if (lp){
696 		return belle_sip_listening_point_get_port(lp);
697 	}
698 	return 0;
699 }
700 
sal_unlisten_ports(Sal * ctx)701 int sal_unlisten_ports(Sal *ctx){
702 	const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(ctx->prov);
703 	belle_sip_list_t * tmp_list = belle_sip_list_copy(lps);
704 	belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))remove_listening_point,ctx->prov);
705 	belle_sip_list_free(tmp_list);
706 	ms_message("sal_unlisten_ports done");
707 	return 0;
708 }
709 
sal_get_socket(Sal * ctx)710 ortp_socket_t sal_get_socket(Sal *ctx){
711 	ms_warning("sal_get_socket is deprecated");
712 	return -1;
713 }
714 
sal_set_user_agent(Sal * ctx,const char * user_agent)715 void sal_set_user_agent(Sal *ctx, const char *user_agent){
716 	belle_sip_header_user_agent_set_products(ctx->user_agent,NULL);
717 	belle_sip_header_user_agent_add_product(ctx->user_agent,user_agent);
718 	return ;
719 }
720 
sal_get_user_agent(Sal * ctx)721 const char* sal_get_user_agent(Sal *ctx){
722 	static char user_agent[255];
723 	belle_sip_header_user_agent_get_products_as_string(ctx->user_agent, user_agent, 254);
724 	return user_agent;
725 }
726 
sal_append_stack_string_to_user_agent(Sal * ctx)727 void sal_append_stack_string_to_user_agent(Sal *ctx) {
728 	char stack_string[64];
729 	snprintf(stack_string, sizeof(stack_string) - 1, "(belle-sip/%s)", belle_sip_version_to_string());
730 	belle_sip_header_user_agent_add_product(ctx->user_agent, stack_string);
731 }
732 
733 /*keepalive period in ms*/
sal_set_keepalive_period(Sal * ctx,unsigned int value)734 void sal_set_keepalive_period(Sal *ctx,unsigned int value){
735 	const belle_sip_list_t* iterator;
736 	belle_sip_listening_point_t* lp;
737 	ctx->keep_alive=value;
738 	for (iterator=belle_sip_provider_get_listening_points(ctx->prov);iterator!=NULL;iterator=iterator->next) {
739 		lp=(belle_sip_listening_point_t*)iterator->data;
740 		if (ctx->use_tcp_tls_keep_alive || strcasecmp(belle_sip_listening_point_get_transport(lp),"udp")==0) {
741 			belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
742 		}
743 	}
744 }
sal_set_tunnel(Sal * ctx,void * tunnelclient)745 int sal_set_tunnel(Sal *ctx, void *tunnelclient) {
746 #ifdef TUNNEL_ENABLED
747 	ctx->tunnel_client=tunnelclient;
748 	return 0;
749 #else
750 	return -1;
751 #endif
752 }
753 
754 /**
755  * returns keepalive period in ms
756  * 0 desactiaved
757  * */
sal_get_keepalive_period(Sal * ctx)758 unsigned int sal_get_keepalive_period(Sal *ctx){
759 	return ctx->keep_alive;
760 }
sal_use_session_timers(Sal * ctx,int expires)761 void sal_use_session_timers(Sal *ctx, int expires){
762 	ctx->session_expires=expires;
763 	return ;
764 }
765 
sal_use_one_matching_codec_policy(Sal * ctx,bool_t one_matching_codec)766 void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec){
767 	ctx->one_matching_codec=one_matching_codec;
768 }
769 
sal_use_rport(Sal * ctx,bool_t use_rports)770 void sal_use_rport(Sal *ctx, bool_t use_rports){
771 	belle_sip_provider_enable_rport(ctx->prov,use_rports);
772 	ms_message("Sal use rport [%s]",use_rports?"enabled":"disabled");
773 	return ;
774 }
775 
set_tls_properties(Sal * ctx)776 static void set_tls_properties(Sal *ctx){
777 	belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(ctx->prov,"TLS");
778 	if (lp){
779 		belle_sip_tls_listening_point_t *tlp=BELLE_SIP_TLS_LISTENING_POINT(lp);
780 		belle_tls_crypto_config_t *crypto_config = belle_tls_crypto_config_new();
781 		int verify_exceptions = BELLE_TLS_VERIFY_NONE;
782 		if (!ctx->tls_verify) verify_exceptions = BELLE_TLS_VERIFY_ANY_REASON;
783 		else if (!ctx->tls_verify_cn) verify_exceptions = BELLE_TLS_VERIFY_CN_MISMATCH;
784 		belle_tls_crypto_config_set_verify_exceptions(crypto_config, verify_exceptions);
785 		if (ctx->root_ca != NULL) belle_tls_crypto_config_set_root_ca(crypto_config, ctx->root_ca);
786 		if (ctx->root_ca_data != NULL) belle_tls_crypto_config_set_root_ca_data(crypto_config, ctx->root_ca_data);
787 		if (ctx->ssl_config != NULL) belle_tls_crypto_config_set_ssl_config(crypto_config, ctx->ssl_config);
788 		belle_sip_tls_listening_point_set_crypto_config(tlp, crypto_config);
789 		belle_sip_object_unref(crypto_config);
790 	}
791 }
792 
sal_set_root_ca(Sal * ctx,const char * rootCa)793 void sal_set_root_ca(Sal* ctx, const char* rootCa) {
794 	if (ctx->root_ca) {
795 		ms_free(ctx->root_ca);
796 		ctx->root_ca = NULL;
797 	}
798 	if (rootCa)
799 		ctx->root_ca = ms_strdup(rootCa);
800 	set_tls_properties(ctx);
801 	return;
802 }
803 
sal_set_root_ca_data(Sal * ctx,const char * data)804 void sal_set_root_ca_data(Sal* ctx, const char* data) {
805 	if (ctx->root_ca_data) {
806 		ms_free(ctx->root_ca_data);
807 		ctx->root_ca_data = NULL;
808 	}
809 	if (data)
810 		ctx->root_ca_data = ms_strdup(data);
811 	set_tls_properties(ctx);
812 	return;
813 }
814 
sal_verify_server_certificates(Sal * ctx,bool_t verify)815 void sal_verify_server_certificates(Sal *ctx, bool_t verify){
816 	ctx->tls_verify=verify;
817 	set_tls_properties(ctx);
818 	return ;
819 }
820 
sal_verify_server_cn(Sal * ctx,bool_t verify)821 void sal_verify_server_cn(Sal *ctx, bool_t verify){
822 	ctx->tls_verify_cn=verify;
823 	set_tls_properties(ctx);
824 	return ;
825 }
826 
sal_set_ssl_config(Sal * ctx,void * ssl_config)827 void sal_set_ssl_config(Sal *ctx, void *ssl_config) {
828 	ctx->ssl_config = ssl_config;
829 	set_tls_properties(ctx);
830 	return ;
831 }
832 
sal_use_tcp_tls_keepalive(Sal * ctx,bool_t enabled)833 void sal_use_tcp_tls_keepalive(Sal *ctx, bool_t enabled) {
834 	ctx->use_tcp_tls_keep_alive=enabled;
835 }
836 
sal_iterate(Sal * sal)837 int sal_iterate(Sal *sal){
838 	belle_sip_stack_sleep(sal->stack,0);
839 	return 0;
840 }
sal_get_pending_auths(Sal * sal)841 bctbx_list_t * sal_get_pending_auths(Sal *sal){
842 	return bctbx_list_copy(sal->pending_auths);
843 }
844 
845 /*misc*/
sal_get_default_local_ip(Sal * sal,int address_family,char * ip,size_t iplen)846 void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen){
847 	strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen);
848 	ms_error("sal_get_default_local_ip() is deprecated.");
849 }
850 
sal_get_root_ca(Sal * ctx)851 const char *sal_get_root_ca(Sal* ctx) {
852 	return ctx->root_ca;
853 }
854 
sal_reset_transports(Sal * ctx)855 int sal_reset_transports(Sal *ctx){
856 	ms_message("Reseting transports");
857 	belle_sip_provider_clean_channels(ctx->prov);
858 	return 0;
859 }
860 
sal_set_dscp(Sal * ctx,int dscp)861 void sal_set_dscp(Sal *ctx, int dscp){
862 	belle_sip_stack_set_default_dscp(ctx->stack,dscp);
863 }
864 
sal_set_send_error(Sal * sal,int value)865 void  sal_set_send_error(Sal *sal,int value) {
866 	 belle_sip_stack_set_send_error(sal->stack,value);
867 }
sal_set_recv_error(Sal * sal,int value)868 void  sal_set_recv_error(Sal *sal,int value) {
869 	 belle_sip_provider_set_recv_error(sal->prov,value);
870 }
sal_nat_helper_enable(Sal * sal,bool_t enable)871 void sal_nat_helper_enable(Sal *sal,bool_t enable) {
872 	sal->nat_helper_enabled=enable;
873 	belle_sip_provider_enable_nat_helper(sal->prov,enable);
874 	ms_message("Sal nat helper [%s]",enable?"enabled":"disabled");
875 }
sal_nat_helper_enabled(Sal * sal)876 bool_t sal_nat_helper_enabled(Sal *sal) {
877 	return sal->nat_helper_enabled;
878 }
sal_set_dns_timeout(Sal * sal,int timeout)879 void sal_set_dns_timeout(Sal* sal,int timeout) {
880 	belle_sip_stack_set_dns_timeout(sal->stack, timeout);
881 }
882 
sal_get_dns_timeout(const Sal * sal)883 int sal_get_dns_timeout(const Sal* sal)  {
884 	return belle_sip_stack_get_dns_timeout(sal->stack);
885 }
886 
sal_set_transport_timeout(Sal * sal,int timeout)887 void sal_set_transport_timeout(Sal* sal,int timeout) {
888 	belle_sip_stack_set_transport_timeout(sal->stack, timeout);
889 }
890 
sal_get_transport_timeout(const Sal * sal)891 int sal_get_transport_timeout(const Sal* sal)  {
892 	return belle_sip_stack_get_transport_timeout(sal->stack);
893 }
894 
sal_set_dns_servers(Sal * sal,const bctbx_list_t * servers)895 void sal_set_dns_servers(Sal *sal, const bctbx_list_t *servers){
896 	belle_sip_list_t *l = NULL;
897 
898 	/*we have to convert the bctbx_list_t into a belle_sip_list_t first*/
899 	for (; servers != NULL; servers = servers->next){
900 		l = belle_sip_list_append(l, servers->data);
901 	}
902 	belle_sip_stack_set_dns_servers(sal->stack, l);
903 	belle_sip_list_free(l);
904 }
905 
sal_enable_dns_srv(Sal * sal,bool_t enable)906 void sal_enable_dns_srv(Sal *sal, bool_t enable) {
907 	belle_sip_stack_enable_dns_srv(sal->stack, (unsigned char)enable);
908 }
909 
sal_dns_srv_enabled(const Sal * sal)910 bool_t sal_dns_srv_enabled(const Sal *sal) {
911 	return (bool_t)belle_sip_stack_dns_srv_enabled(sal->stack);
912 }
913 
sal_enable_dns_search(Sal * sal,bool_t enable)914 void sal_enable_dns_search(Sal *sal, bool_t enable) {
915 	belle_sip_stack_enable_dns_search(sal->stack, (unsigned char)enable);
916 }
917 
sal_dns_search_enabled(const Sal * sal)918 bool_t sal_dns_search_enabled(const Sal *sal) {
919 	return (bool_t)belle_sip_stack_dns_search_enabled(sal->stack);
920 }
921 
sal_set_dns_user_hosts_file(Sal * sal,const char * hosts_file)922 void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file) {
923 	belle_sip_stack_set_dns_user_hosts_file(sal->stack, hosts_file);
924 }
925 
sal_get_dns_user_hosts_file(const Sal * sal)926 const char * sal_get_dns_user_hosts_file(const Sal *sal) {
927 	return belle_sip_stack_get_dns_user_hosts_file(sal->stack);
928 }
929 
sal_auth_info_create(belle_sip_auth_event_t * event)930 SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) {
931 	SalAuthInfo* auth_info = sal_auth_info_new();
932 	auth_info->realm = ms_strdup(belle_sip_auth_event_get_realm(event));
933 	auth_info->username = ms_strdup(belle_sip_auth_event_get_username(event));
934 	auth_info->domain = ms_strdup(belle_sip_auth_event_get_domain(event));
935 	auth_info->mode = (SalAuthMode)belle_sip_auth_event_get_mode(event);
936 	return auth_info;
937 }
938 
sal_auth_info_get_mode(const SalAuthInfo * auth_info)939 SalAuthMode sal_auth_info_get_mode(const SalAuthInfo* auth_info) { return auth_info->mode; }
sal_auth_info_get_signing_key(const SalAuthInfo * auth_info)940 SalSigningKey *sal_auth_info_get_signing_key(const SalAuthInfo* auth_info) { return auth_info->key; }
sal_auth_info_get_certificates_chain(const SalAuthInfo * auth_info)941 SalCertificatesChain *sal_auth_info_get_certificates_chain(const SalAuthInfo* auth_info) { return auth_info->certificates; }
sal_auth_info_set_mode(SalAuthInfo * auth_info,SalAuthMode mode)942 void sal_auth_info_set_mode(SalAuthInfo* auth_info, SalAuthMode mode) { auth_info->mode = mode; }
sal_certificates_chain_delete(SalCertificatesChain * chain)943 void sal_certificates_chain_delete(SalCertificatesChain *chain) {
944 	belle_sip_object_unref((belle_sip_object_t *)chain);
945 }
sal_signing_key_delete(SalSigningKey * key)946 void sal_signing_key_delete(SalSigningKey *key) {
947 	belle_sip_object_unref((belle_sip_object_t *)key);
948 }
949 
sal_op_type_to_string(const SalOpType type)950 const char* sal_op_type_to_string(const SalOpType type) {
951 	switch(type) {
952 	case SalOpRegister: return "SalOpRegister";
953 	case SalOpCall: return "SalOpCall";
954 	case SalOpMessage: return "SalOpMessage";
955 	case SalOpPresence: return "SalOpPresence";
956 	default:
957 		return "SalOpUnknown";
958 	}
959 }
960 
sal_use_dates(Sal * ctx,bool_t enabled)961 void sal_use_dates(Sal *ctx, bool_t enabled){
962 	ctx->use_dates=enabled;
963 }
964 
sal_auth_compute_ha1(const char * userid,const char * realm,const char * password,char ha1[33])965 int sal_auth_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]) {
966 	return belle_sip_auth_helper_compute_ha1(userid, realm, password, ha1);
967 }
968 
sal_custom_header_ref(SalCustomHeader * ch)969 SalCustomHeader *sal_custom_header_ref(SalCustomHeader *ch){
970 	if (ch == NULL) return NULL;
971 	belle_sip_object_ref(ch);
972 	return ch;
973 }
974 
sal_custom_header_unref(SalCustomHeader * ch)975 void sal_custom_header_unref(SalCustomHeader *ch){
976 	if (ch == NULL) return;
977 	belle_sip_object_unref(ch);
978 }
979 
sal_custom_header_append(SalCustomHeader * ch,const char * name,const char * value)980 SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *value){
981 	belle_sip_message_t *msg=(belle_sip_message_t*)ch;
982 	belle_sip_header_t *h;
983 
984 	if (msg==NULL){
985 		msg=(belle_sip_message_t*)belle_sip_request_new();
986 		belle_sip_object_ref(msg);
987 	}
988 	h=belle_sip_header_create(name,value);
989 	if (h==NULL){
990 		belle_sip_error("Fail to parse custom header.");
991 		return (SalCustomHeader*)msg;
992 	}
993 	belle_sip_message_add_header(msg,h);
994 	return (SalCustomHeader*)msg;
995 }
996 
sal_custom_header_find(const SalCustomHeader * ch,const char * name)997 const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name){
998 	if (ch){
999 		belle_sip_header_t *h=belle_sip_message_get_header((belle_sip_message_t*)ch,name);
1000 
1001 		if (h){
1002 			return belle_sip_header_get_unparsed_value(h);
1003 		}
1004 	}
1005 	return NULL;
1006 }
1007 
sal_custom_header_remove(SalCustomHeader * ch,const char * name)1008 SalCustomHeader *sal_custom_header_remove(SalCustomHeader *ch, const char *name) {
1009 	belle_sip_message_t *msg=(belle_sip_message_t*)ch;
1010 	if (msg==NULL) return NULL;
1011 
1012 	belle_sip_message_remove_header(msg, name);
1013 	return (SalCustomHeader*)msg;
1014 }
1015 
sal_custom_header_free(SalCustomHeader * ch)1016 void sal_custom_header_free(SalCustomHeader *ch){
1017 	if (ch==NULL) return;
1018 	belle_sip_object_unref((belle_sip_message_t*)ch);
1019 }
1020 
sal_custom_header_clone(const SalCustomHeader * ch)1021 SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch){
1022 	if (ch==NULL) return NULL;
1023 	return (SalCustomHeader*)belle_sip_object_ref((belle_sip_message_t*)ch);
1024 }
1025 
sal_op_get_recv_custom_header(SalOp * op)1026 const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op){
1027 	SalOpBase *b=(SalOpBase *)op;
1028 	return b->recv_custom_headers;
1029 }
1030 
sal_custom_sdp_attribute_append(SalCustomSdpAttribute * csa,const char * name,const char * value)1031 SalCustomSdpAttribute * sal_custom_sdp_attribute_append(SalCustomSdpAttribute *csa, const char *name, const char *value) {
1032 	belle_sdp_session_description_t *desc = (belle_sdp_session_description_t *)csa;
1033 	belle_sdp_attribute_t *attr;
1034 
1035 	if (desc == NULL) {
1036 		desc = (belle_sdp_session_description_t *)belle_sdp_session_description_new();
1037 		belle_sip_object_ref(desc);
1038 	}
1039 	attr = BELLE_SDP_ATTRIBUTE(belle_sdp_raw_attribute_create(name, value));
1040 	if (attr == NULL) {
1041 		belle_sip_error("Fail to create custom SDP attribute.");
1042 		return (SalCustomSdpAttribute*)desc;
1043 	}
1044 	belle_sdp_session_description_add_attribute(desc, attr);
1045 	return (SalCustomSdpAttribute *)desc;
1046 }
1047 
sal_custom_sdp_attribute_find(const SalCustomSdpAttribute * csa,const char * name)1048 const char * sal_custom_sdp_attribute_find(const SalCustomSdpAttribute *csa, const char *name) {
1049 	if (csa) {
1050 		return belle_sdp_session_description_get_attribute_value((belle_sdp_session_description_t *)csa, name);
1051 	}
1052 	return NULL;
1053 }
1054 
sal_custom_sdp_attribute_free(SalCustomSdpAttribute * csa)1055 void sal_custom_sdp_attribute_free(SalCustomSdpAttribute *csa) {
1056 	if (csa == NULL) return;
1057 	belle_sip_object_unref((belle_sdp_session_description_t *)csa);
1058 }
1059 
sal_custom_sdp_attribute_clone(const SalCustomSdpAttribute * csa)1060 SalCustomSdpAttribute * sal_custom_sdp_attribute_clone(const SalCustomSdpAttribute *csa) {
1061 	if (csa == NULL) return NULL;
1062 	return (SalCustomSdpAttribute *)belle_sip_object_ref((belle_sdp_session_description_t *)csa);
1063 }
1064 
sal_set_uuid(Sal * sal,const char * uuid)1065 void sal_set_uuid(Sal *sal, const char *uuid){
1066 	if (sal->uuid){
1067 		ms_free(sal->uuid);
1068 		sal->uuid=NULL;
1069 	}
1070 	if (uuid)
1071 		sal->uuid=ms_strdup(uuid);
1072 }
1073 
1074 typedef struct {
1075 	unsigned int time_low;
1076 	unsigned short time_mid;
1077 	unsigned short time_hi_and_version;
1078 	unsigned char clock_seq_hi_and_reserved;
1079 	unsigned char clock_seq_low;
1080 	unsigned char node[6];
1081 } sal_uuid_t;
1082 
sal_generate_uuid(char * uuid,size_t len)1083 int sal_generate_uuid(char *uuid, size_t len) {
1084 	sal_uuid_t uuid_struct;
1085 	int i;
1086 	int written;
1087 
1088 	if (len==0) return -1;
1089 	/*create an UUID as described in RFC4122, 4.4 */
1090 	belle_sip_random_bytes((unsigned char*)&uuid_struct, sizeof(sal_uuid_t));
1091 	uuid_struct.clock_seq_hi_and_reserved&=~(1<<6);
1092 	uuid_struct.clock_seq_hi_and_reserved|=1<<7;
1093 	uuid_struct.time_hi_and_version&=~(0xf<<12);
1094 	uuid_struct.time_hi_and_version|=4<<12;
1095 
1096 	written=snprintf(uuid,len,"%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", uuid_struct.time_low, uuid_struct.time_mid,
1097 			uuid_struct.time_hi_and_version, uuid_struct.clock_seq_hi_and_reserved,
1098 			uuid_struct.clock_seq_low);
1099 	if ((written < 0) || ((size_t)written > (len +13))) {
1100 		ms_error("sal_create_uuid(): buffer is too short !");
1101 		return -1;
1102 	}
1103 	for (i = 0; i < 6; i++)
1104 		written+=snprintf(uuid+written,len-written,"%2.2x", uuid_struct.node[i]);
1105 	uuid[len-1]='\0';
1106 	return 0;
1107 }
1108 
sal_create_uuid(Sal * ctx,char * uuid,size_t len)1109 int sal_create_uuid(Sal*ctx, char *uuid, size_t len) {
1110 	if (sal_generate_uuid(uuid, len) == 0) {
1111 		sal_set_uuid(ctx, uuid);
1112 		return 0;
1113 	}
1114 	return -1;
1115 }
1116 
make_supported_header(Sal * sal)1117 static void make_supported_header(Sal *sal){
1118 	bctbx_list_t *it;
1119 	char *alltags=NULL;
1120 	size_t buflen=64;
1121 	size_t written=0;
1122 
1123 	if (sal->supported){
1124 		belle_sip_object_unref(sal->supported);
1125 		sal->supported=NULL;
1126 	}
1127 	for(it=sal->supported_tags;it!=NULL;it=it->next){
1128 		const char *tag=(const char*)it->data;
1129 		size_t taglen=strlen(tag);
1130 		if (alltags==NULL || (written+taglen+1>=buflen)) alltags=ms_realloc(alltags,(buflen=buflen*2));
1131 		written+=snprintf(alltags+written,buflen-written,it->next ? "%s, " : "%s",tag);
1132 	}
1133 	if (alltags){
1134 		sal->supported=belle_sip_header_create("Supported",alltags);
1135 		if (sal->supported){
1136 			belle_sip_object_ref(sal->supported);
1137 		}
1138 		ms_free(alltags);
1139 	}
1140 }
1141 
sal_set_supported_tags(Sal * ctx,const char * tags)1142 void sal_set_supported_tags(Sal *ctx, const char* tags){
1143 	ctx->supported_tags=bctbx_list_free_with_data(ctx->supported_tags,ms_free);
1144 	if (tags){
1145 		char *iter;
1146 		char *buffer=ms_strdup(tags);
1147 		char *tag;
1148 		char *context=NULL;
1149 		iter=buffer;
1150 		while((tag=strtok_r(iter,", ",&context))!=NULL){
1151 			iter=NULL;
1152 			ctx->supported_tags=bctbx_list_append(ctx->supported_tags,ms_strdup(tag));
1153 		}
1154 		ms_free(buffer);
1155 	}
1156 	make_supported_header(ctx);
1157 }
1158 
sal_get_supported_tags(Sal * ctx)1159 const char *sal_get_supported_tags(Sal *ctx){
1160 	if (ctx->supported){
1161 		return belle_sip_header_get_unparsed_value(ctx->supported);
1162 	}
1163 	return NULL;
1164 }
1165 
sal_add_supported_tag(Sal * ctx,const char * tag)1166 void sal_add_supported_tag(Sal *ctx, const char* tag){
1167 	bctbx_list_t *elem=bctbx_list_find_custom(ctx->supported_tags,(bctbx_compare_func)strcasecmp,tag);
1168 	if (!elem){
1169 		ctx->supported_tags=bctbx_list_append(ctx->supported_tags,ms_strdup(tag));
1170 		make_supported_header(ctx);
1171 	}
1172 
1173 }
1174 
sal_remove_supported_tag(Sal * ctx,const char * tag)1175 void sal_remove_supported_tag(Sal *ctx, const char* tag){
1176 	bctbx_list_t *elem=bctbx_list_find_custom(ctx->supported_tags,(bctbx_compare_func)strcasecmp,tag);
1177 	if (elem){
1178 		ms_free(elem->data);
1179 		ctx->supported_tags=bctbx_list_erase_link(ctx->supported_tags,elem);
1180 		make_supported_header(ctx);
1181 	}
1182 }
1183 
1184 
1185 
sal_create_response_from_request(Sal * sal,belle_sip_request_t * req,int code)1186 belle_sip_response_t* sal_create_response_from_request ( Sal* sal, belle_sip_request_t* req, int code ) {
1187 	belle_sip_response_t *resp=belle_sip_response_create_from_request(req,code);
1188 	belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(sal->user_agent));
1189 	belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal->supported);
1190 	return resp;
1191 }
1192 
sal_set_refresher_retry_after(Sal * sal,int value)1193 void sal_set_refresher_retry_after(Sal *sal,int value) {
1194 	sal->refresher_retry_after=value;
1195 }
1196 
sal_get_refresher_retry_after(const Sal * sal)1197 int sal_get_refresher_retry_after(const Sal *sal) {
1198 	return sal->refresher_retry_after;
1199 }
1200 
sal_enable_auto_contacts(Sal * ctx,bool_t enabled)1201 void sal_enable_auto_contacts(Sal *ctx, bool_t enabled){
1202 	ctx->auto_contacts=enabled;
1203 }
1204 
sal_enable_test_features(Sal * ctx,bool_t enabled)1205 void sal_enable_test_features(Sal*ctx, bool_t enabled){
1206 	ctx->enable_test_features=enabled;
1207 }
1208 
sal_use_no_initial_route(Sal * ctx,bool_t enabled)1209 void sal_use_no_initial_route(Sal *ctx, bool_t enabled){
1210 	ctx->no_initial_route=enabled;
1211 }
1212 
sal_resolve_a(Sal * sal,const char * name,int port,int family,belle_sip_resolver_callback_t cb,void * data)1213 belle_sip_resolver_context_t * sal_resolve_a(Sal* sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data){
1214 	return belle_sip_stack_resolve_a(sal->stack,name,port,family,cb,data);
1215 }
1216 
sal_resolve(Sal * sal,const char * service,const char * transport,const char * name,int port,int family,belle_sip_resolver_callback_t cb,void * data)1217 belle_sip_resolver_context_t * sal_resolve(Sal *sal, const char *service, const char *transport, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data) {
1218 	return belle_sip_stack_resolve(sal->stack, service, transport, name, port, family, cb, data);
1219 }
1220 
1221 
sal_enable_unconditional_answer(Sal * sal,int value)1222 void sal_enable_unconditional_answer(Sal *sal,int value) {
1223 	belle_sip_provider_enable_unconditional_answer(sal->prov,value);
1224 }
1225 
1226 /** Parse a file containing either a certificate chain order in PEM format or a single DER cert
1227  * @param auth_info structure where to store the result of parsing
1228  * @param path path to certificate chain file
1229  * @param format either PEM or DER
1230  */
sal_certificates_chain_parse_file(SalAuthInfo * auth_info,const char * path,SalCertificateRawFormat format)1231 void sal_certificates_chain_parse_file(SalAuthInfo* auth_info, const char* path, SalCertificateRawFormat format) {
1232 	auth_info->certificates = (SalCertificatesChain*) belle_sip_certificates_chain_parse_file(path, (belle_sip_certificate_raw_format_t)format);
1233 	if (auth_info->certificates) belle_sip_object_ref((belle_sip_object_t *) auth_info->certificates);
1234 }
1235 
1236 /**
1237  * Parse a file containing either a private or public rsa key
1238  * @param auth_info structure where to store the result of parsing
1239  * @param passwd password (optionnal)
1240  */
sal_signing_key_parse_file(SalAuthInfo * auth_info,const char * path,const char * passwd)1241 void sal_signing_key_parse_file(SalAuthInfo* auth_info, const char* path, const char *passwd) {
1242 	auth_info->key = (SalSigningKey *) belle_sip_signing_key_parse_file(path, passwd);
1243 	if (auth_info->key) belle_sip_object_ref((belle_sip_object_t *) auth_info->key);
1244 }
1245 
1246 /** Parse a buffer containing either a certificate chain order in PEM format or a single DER cert
1247  * @param auth_info structure where to store the result of parsing
1248  * @param buffer the buffer to parse
1249  * @param format either PEM or DER
1250  */
sal_certificates_chain_parse(SalAuthInfo * auth_info,const char * buffer,SalCertificateRawFormat format)1251 void sal_certificates_chain_parse(SalAuthInfo* auth_info, const char* buffer, SalCertificateRawFormat format) {
1252 	size_t len = buffer != NULL ? strlen(buffer) : 0;
1253 	auth_info->certificates = (SalCertificatesChain*) belle_sip_certificates_chain_parse(buffer, len, (belle_sip_certificate_raw_format_t)format);
1254 	if (auth_info->certificates) belle_sip_object_ref((belle_sip_object_t *) auth_info->certificates);
1255 }
1256 
1257 /**
1258  * Parse a buffer containing either a private or public rsa key
1259  * @param auth_info structure where to store the result of parsing
1260  * @param passwd password (optionnal)
1261  */
sal_signing_key_parse(SalAuthInfo * auth_info,const char * buffer,const char * passwd)1262 void sal_signing_key_parse(SalAuthInfo* auth_info, const char* buffer, const char *passwd) {
1263 	size_t len = buffer != NULL ? strlen(buffer) : 0;
1264 	auth_info->key = (SalSigningKey *) belle_sip_signing_key_parse(buffer, len, passwd);
1265 	if (auth_info->key) belle_sip_object_ref((belle_sip_object_t *) auth_info->key);
1266 }
1267 
1268 /**
1269  * Parse a directory to get a certificate with the given subject common name
1270  *
1271  */
sal_certificates_chain_parse_directory(char ** certificate_pem,char ** key_pem,char ** fingerprint,const char * path,const char * subject,SalCertificateRawFormat format,bool_t generate_certificate,bool_t generate_dtls_fingerprint)1272 void sal_certificates_chain_parse_directory(char **certificate_pem, char **key_pem, char **fingerprint, const char* path, const char *subject, SalCertificateRawFormat format, bool_t generate_certificate, bool_t generate_dtls_fingerprint) {
1273 	belle_sip_certificates_chain_t *certificate = NULL;
1274 	belle_sip_signing_key_t *key = NULL;
1275 	*certificate_pem = NULL;
1276 	*key_pem = NULL;
1277 	if (belle_sip_get_certificate_and_pkey_in_dir(path, subject, &certificate, &key, (belle_sip_certificate_raw_format_t)format) == 0) {
1278 		*certificate_pem = belle_sip_certificates_chain_get_pem(certificate);
1279 		*key_pem = belle_sip_signing_key_get_pem(key);
1280 		ms_message("Retrieve certificate with CN=%s successful\n", subject);
1281 	} else {
1282 		if (generate_certificate == TRUE) {
1283 			if ( belle_sip_generate_self_signed_certificate(path, subject, &certificate, &key) == 0) {
1284 				*certificate_pem = belle_sip_certificates_chain_get_pem(certificate);
1285 				*key_pem = belle_sip_signing_key_get_pem(key);
1286 				ms_message("Generate self-signed certificate with CN=%s successful\n", subject);
1287 			}
1288 		}
1289 	}
1290 	/* generate the fingerprint as described in RFC4572 if needed */
1291 	if ((generate_dtls_fingerprint == TRUE) && (fingerprint != NULL)) {
1292 		if (*fingerprint != NULL) {
1293 			ms_free(*fingerprint);
1294 		}
1295 		*fingerprint = belle_sip_certificates_chain_get_fingerprint(certificate);
1296 	}
1297 
1298 	/* free key and certificate */
1299 	if ( certificate != NULL ) {
1300 		belle_sip_object_unref(certificate);
1301 	}
1302 	if ( key != NULL ) {
1303 		belle_sip_object_unref(key);
1304 	}
1305 }
1306 
sal_get_random_bytes(unsigned char * ret,size_t size)1307 unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size){
1308 	return belle_sip_random_bytes(ret,size);
1309 }
1310 
sal_get_random_token(int size)1311 char *sal_get_random_token(int size){
1312 	return belle_sip_random_token(ms_malloc(size),size);
1313 }
1314 
sal_get_random(void)1315 unsigned int sal_get_random(void){
1316 	unsigned int ret=0;
1317 	belle_sip_random_bytes((unsigned char*)&ret,4);
1318 	return ret;
1319 }
1320 
sal_create_timer(Sal * sal,belle_sip_source_func_t func,void * data,unsigned int timeout_value_ms,const char * timer_name)1321 belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name) {
1322 	belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack);
1323 	return belle_sip_main_loop_create_timeout(ml, func, data, timeout_value_ms, timer_name);
1324 }
1325 
sal_cancel_timer(Sal * sal,belle_sip_source_t * timer)1326 void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer) {
1327 	belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack);
1328 	belle_sip_main_loop_remove_source(ml, timer);
1329 }
1330 
sal_begin_background_task(const char * name,void (* max_time_reached)(void *),void * data)1331 unsigned long sal_begin_background_task(const char *name, void (*max_time_reached)(void *), void *data){
1332 	return belle_sip_begin_background_task(name, max_time_reached, data);
1333 }
1334 
sal_end_background_task(unsigned long id)1335 void sal_end_background_task(unsigned long id){
1336 	belle_sip_end_background_task(id);
1337 }
1338 
1339 
sal_enable_sip_update_method(Sal * ctx,bool_t value)1340 void sal_enable_sip_update_method(Sal *ctx,bool_t value) {
1341 	ctx->enable_sip_update=value;
1342 }
1343 
sal_default_set_sdp_handling(Sal * sal,SalOpSDPHandling sdp_handling_method)1344 void sal_default_set_sdp_handling(Sal *sal, SalOpSDPHandling sdp_handling_method)  {
1345 	if (sdp_handling_method != SalOpSDPNormal ) ms_message("Enabling special SDP handling for all new SalOp in Sal[%p]!", sal);
1346 	sal->default_sdp_handling = sdp_handling_method;
1347 }
1348 
sal_pending_trans_checking_enabled(const Sal * sal)1349 bool_t sal_pending_trans_checking_enabled(const Sal *sal) {
1350 	return sal->pending_trans_checking;
1351 }
1352 
sal_enable_pending_trans_checking(Sal * sal,bool_t value)1353 int sal_enable_pending_trans_checking(Sal *sal, bool_t value) {
1354 	sal->pending_trans_checking = value;
1355 	return 0;
1356 }
sal_set_http_proxy_host(Sal * sal,const char * host)1357 void sal_set_http_proxy_host(Sal *sal, const char *host) {
1358 	belle_sip_stack_set_http_proxy_host(sal->stack, host);
1359 }
1360 
sal_set_http_proxy_port(Sal * sal,int port)1361 void sal_set_http_proxy_port(Sal *sal, int port) {
1362 	belle_sip_stack_set_http_proxy_port(sal->stack, port);
1363 }
sal_get_http_proxy_host(const Sal * sal)1364 const char *sal_get_http_proxy_host(const Sal *sal) {
1365 	return belle_sip_stack_get_http_proxy_host(sal->stack);
1366 }
1367 
sal_get_http_proxy_port(const Sal * sal)1368 int sal_get_http_proxy_port(const Sal *sal) {
1369 	return belle_sip_stack_get_http_proxy_port(sal->stack);
1370 }
1371 
sal_body_handler_find_header(const SalBodyHandler * body_handler,const char * header_name)1372 static belle_sip_header_t * sal_body_handler_find_header(const SalBodyHandler *body_handler, const char *header_name) {
1373 	belle_sip_body_handler_t *bsbh = BELLE_SIP_BODY_HANDLER(body_handler);
1374 	const belle_sip_list_t *l = belle_sip_body_handler_get_headers(bsbh);
1375 	for (; l != NULL; l = l->next) {
1376 		belle_sip_header_t *header = BELLE_SIP_HEADER(l->data);
1377 		if (strcmp(belle_sip_header_get_name(header), header_name) == 0) {
1378 			return header;
1379 		}
1380 	}
1381 	return NULL;
1382 }
1383 
sal_body_handler_new(void)1384 SalBodyHandler * sal_body_handler_new(void) {
1385 	belle_sip_memory_body_handler_t *body_handler = belle_sip_memory_body_handler_new(NULL, NULL);
1386 	return (SalBodyHandler *)BELLE_SIP_BODY_HANDLER(body_handler);
1387 }
1388 
sal_body_handler_ref(SalBodyHandler * body_handler)1389 SalBodyHandler * sal_body_handler_ref(SalBodyHandler *body_handler) {
1390 	return (SalBodyHandler *)belle_sip_object_ref(BELLE_SIP_OBJECT(body_handler));
1391 }
1392 
sal_body_handler_unref(SalBodyHandler * body_handler)1393 void sal_body_handler_unref(SalBodyHandler *body_handler) {
1394 	belle_sip_object_unref(BELLE_SIP_OBJECT(body_handler));
1395 }
1396 
sal_body_handler_get_type(const SalBodyHandler * body_handler)1397 const char * sal_body_handler_get_type(const SalBodyHandler *body_handler) {
1398 	belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type"));
1399 	if (content_type != NULL) {
1400 		return belle_sip_header_content_type_get_type(content_type);
1401 	}
1402 	return NULL;
1403 }
1404 
sal_body_handler_set_type(SalBodyHandler * body_handler,const char * type)1405 void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type) {
1406 	belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type"));
1407 	if (content_type == NULL) {
1408 		content_type = belle_sip_header_content_type_new();
1409 		belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_type));
1410 	}
1411 	belle_sip_header_content_type_set_type(content_type, type);
1412 }
1413 
sal_body_handler_get_subtype(const SalBodyHandler * body_handler)1414 const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler) {
1415 	belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type"));
1416 	if (content_type != NULL) {
1417 		return belle_sip_header_content_type_get_subtype(content_type);
1418 	}
1419 	return NULL;
1420 }
1421 
sal_body_handler_set_subtype(SalBodyHandler * body_handler,const char * subtype)1422 void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype) {
1423 	belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type"));
1424 	if (content_type == NULL) {
1425 		content_type = belle_sip_header_content_type_new();
1426 		belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_type));
1427 	}
1428 	belle_sip_header_content_type_set_subtype(content_type, subtype);
1429 }
1430 
sal_body_handler_get_encoding(const SalBodyHandler * body_handler)1431 const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler) {
1432 	belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding");
1433 	if (content_encoding != NULL) {
1434 		return belle_sip_header_get_unparsed_value(content_encoding);
1435 	}
1436 	return NULL;
1437 }
1438 
sal_body_handler_set_encoding(SalBodyHandler * body_handler,const char * encoding)1439 void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding) {
1440 	belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding");
1441 	if (content_encoding != NULL) {
1442 		belle_sip_body_handler_remove_header_from_ptr(BELLE_SIP_BODY_HANDLER(body_handler), content_encoding);
1443 	}
1444 	belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), belle_sip_header_create("Content-Encoding", encoding));
1445 }
1446 
sal_body_handler_get_data(const SalBodyHandler * body_handler)1447 void * sal_body_handler_get_data(const SalBodyHandler *body_handler) {
1448 	return belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(body_handler));
1449 }
1450 
sal_body_handler_set_data(SalBodyHandler * body_handler,void * data)1451 void sal_body_handler_set_data(SalBodyHandler *body_handler, void *data) {
1452 	belle_sip_memory_body_handler_set_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(body_handler), data);
1453 }
1454 
sal_body_handler_get_size(const SalBodyHandler * body_handler)1455 size_t sal_body_handler_get_size(const SalBodyHandler *body_handler) {
1456 	return belle_sip_body_handler_get_size(BELLE_SIP_BODY_HANDLER(body_handler));
1457 }
1458 
sal_body_handler_set_size(SalBodyHandler * body_handler,size_t size)1459 void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size) {
1460 	belle_sip_header_content_length_t *content_length = BELLE_SIP_HEADER_CONTENT_LENGTH(sal_body_handler_find_header(body_handler, "Content-Length"));
1461 	if (content_length == NULL) {
1462 		content_length = belle_sip_header_content_length_new();
1463 		belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_length));
1464 	}
1465 	belle_sip_header_content_length_set_content_length(content_length, size);
1466 	belle_sip_body_handler_set_size(BELLE_SIP_BODY_HANDLER(body_handler), size);
1467 }
1468 
sal_body_handler_is_multipart(const SalBodyHandler * body_handler)1469 bool_t sal_body_handler_is_multipart(const SalBodyHandler *body_handler) {
1470 	if (BELLE_SIP_IS_INSTANCE_OF(body_handler, belle_sip_multipart_body_handler_t)) return TRUE;
1471 	return FALSE;
1472 }
1473 
sal_body_handler_get_part(const SalBodyHandler * body_handler,int idx)1474 SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, int idx) {
1475 	const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler));
1476 	return (SalBodyHandler *)belle_sip_list_nth_data(l, idx);
1477 }
1478 
sal_body_handler_find_part_by_header(const SalBodyHandler * body_handler,const char * header_name,const char * header_value)1479 SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value) {
1480 	const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler));
1481 	for (; l != NULL; l = l->next) {
1482 		belle_sip_body_handler_t *bsbh = BELLE_SIP_BODY_HANDLER(l->data);
1483 		const belle_sip_list_t *headers = belle_sip_body_handler_get_headers(bsbh);
1484 		for (; headers != NULL; headers = headers->next) {
1485 			belle_sip_header_t *header = BELLE_SIP_HEADER(headers->data);
1486 			if ((strcmp(belle_sip_header_get_name(header), header_name) == 0) && (strcmp(belle_sip_header_get_unparsed_value(header), header_value) == 0)) {
1487 				return (SalBodyHandler *)bsbh;
1488 			}
1489 		}
1490 	}
1491 	return NULL;
1492 }
1493 
sal_body_handler_get_header(const SalBodyHandler * body_handler,const char * header_name)1494 const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name) {
1495 	belle_sip_header_t *header = sal_body_handler_find_header(body_handler, header_name);
1496 	if (header != NULL) {
1497 		return belle_sip_header_get_unparsed_value(header);
1498 	}
1499 	return NULL;
1500 }
1501 
sal_get_stack_impl(Sal * sal)1502 void *sal_get_stack_impl(Sal *sal) {
1503 	return sal->stack;
1504 }
1505 
sal_is_content_type_supported(const Sal * sal,const char * content_type)1506 bool_t sal_is_content_type_supported(const Sal *sal, const char *content_type) {
1507 	bctbx_list_t *item;
1508 	for (item = sal->supported_content_types; item != NULL; item = bctbx_list_next(item)) {
1509 		const char *item_content_type = (const char *)bctbx_list_get_data(item);
1510 		if (strcmp(item_content_type, content_type) == 0) return TRUE;
1511 	}
1512 	return FALSE;
1513 }
1514 
sal_add_content_type_support(Sal * sal,const char * content_type)1515 void sal_add_content_type_support(Sal *sal, const char *content_type) {
1516 	if ((content_type != NULL) && (sal_is_content_type_supported(sal, content_type) == FALSE)) {
1517 		sal->supported_content_types = bctbx_list_append(sal->supported_content_types, ms_strdup(content_type));
1518 	}
1519 }
1520