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