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 #include "sal_impl.h"
20 
21 /*create an operation */
sal_op_new(Sal * sal)22 SalOp * sal_op_new(Sal *sal){
23 	SalOp *op=ms_new0(SalOp,1);
24 	__sal_op_init(op,sal);
25 	op->type=SalOpUnknown;
26 	op->privacy=SalPrivacyNone;
27 	op->manual_refresher=FALSE;/*tells that requests with expiry (SUBSCRIBE, PUBLISH) will be automatically refreshed*/
28 	op->sdp_handling=sal->default_sdp_handling;
29 	sal_op_ref(op);
30 	return op;
31 }
32 
sal_op_kill_dialog(SalOp * op)33 void sal_op_kill_dialog(SalOp *op) {
34 	ms_warning("op [%p]: force kill of dialog [%p]", op, op->dialog);
35 	belle_sip_dialog_delete(op->dialog);
36 }
37 
sal_op_release(SalOp * op)38 void sal_op_release(SalOp *op){
39 	/*if in terminating state, keep this state because it means we are waiting for a response to be able to terminate the operation.*/
40 	if (op->state!=SalOpStateTerminating)
41 		op->state=SalOpStateTerminated;
42 	sal_op_set_user_pointer(op,NULL);/*mandatory because releasing op doesn't not mean freeing op. Make sure back pointer will not be used later*/
43 	if (op->base.release_cb)
44 		op->base.release_cb(&op->base);
45 	if (op->refresher) {
46 		belle_sip_refresher_stop(op->refresher);
47 	}
48 	op->op_released = TRUE;
49 	sal_op_unref(op);
50 }
51 
sal_op_release_impl(SalOp * op)52 void sal_op_release_impl(SalOp *op){
53 	ms_message("Destroying op [%p] of type [%s]",op,sal_op_type_to_string(op->type));
54 	if (op->pending_auth_transaction) belle_sip_object_unref(op->pending_auth_transaction);
55 	sal_remove_pending_auth(op->base.root,op);
56 	if (op->auth_info) {
57 		sal_auth_info_delete(op->auth_info);
58 	}
59 	if (op->sdp_answer) belle_sip_object_unref(op->sdp_answer);
60 	if (op->refresher) {
61 		belle_sip_object_unref(op->refresher);
62 		op->refresher=NULL;
63 	}
64 	if (op->result)
65 		sal_media_description_unref(op->result);
66 	if(op->replaces) belle_sip_object_unref(op->replaces);
67 	if(op->referred_by) belle_sip_object_unref(op->referred_by);
68 
69 	if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans);
70 	if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
71 	if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans);
72 	if (op->event) belle_sip_object_unref(op->event);
73 	sal_error_info_reset(&op->error_info);
74 	__sal_op_free(op);
75 	return ;
76 }
77 
sal_op_authenticate(SalOp * op,const SalAuthInfo * info)78 void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){
79 	if (op->type == SalOpRegister) {
80 		/*Registration authenticate is just about registering again*/
81 		sal_register_refresh(op,-1);
82 	}else {
83 		/*for sure auth info will be accessible from the provider*/
84 		sal_process_authentication(op);
85 	}
86 	return ;
87 }
88 
sal_op_cancel_authentication(SalOp * h)89 void sal_op_cancel_authentication(SalOp *h){
90 	ms_fatal("sal_op_cancel_authentication not implemented yet");
91 	return ;
92 }
93 
sal_op_get_auth_requested(SalOp * op)94 SalAuthInfo * sal_op_get_auth_requested(SalOp *op){
95 	return op->auth_info;
96 }
97 
sal_op_create_contact(SalOp * op)98 belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){
99 	belle_sip_header_contact_t* contact_header;
100 	belle_sip_uri_t* contact_uri;
101 
102 	if (sal_op_get_contact_address(op)) {
103 		contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op)));
104 	} else {
105 		contact_header= belle_sip_header_contact_new();
106 	}
107 
108 	if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) {
109 		/*no uri, just creating a new one*/
110 		contact_uri=belle_sip_uri_new();
111 		belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri);
112 	}
113 
114 	belle_sip_uri_set_user_password(contact_uri,NULL);
115 	belle_sip_uri_set_secure(contact_uri,sal_op_is_secure(op));
116 	if (op->privacy!=SalPrivacyNone){
117 		belle_sip_uri_set_user(contact_uri,NULL);
118 	}
119 	belle_sip_header_contact_set_automatic(contact_header,op->base.root->auto_contacts);
120 	if (op->base.root->uuid){
121 		if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance")==0){
122 			char *instance_id=belle_sip_strdup_printf("\"<urn:uuid:%s>\"",op->base.root->uuid);
123 			belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance",instance_id);
124 			belle_sip_free(instance_id);
125 		}
126 	}
127 	return contact_header;
128 }
129 
130 
131 
add_initial_route_set(belle_sip_request_t * request,const MSList * list)132 static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){
133 	const MSList *elem;
134 	for (elem=list;elem!=NULL;elem=elem->next){
135 		SalAddress *addr=(SalAddress*)elem->data;
136 		belle_sip_header_route_t *route;
137 		belle_sip_uri_t *uri;
138 		/*Optimization: if the initial route set only contains one URI which is the same as the request URI, ommit it*/
139 		if (elem==list && list->next==NULL){
140 			belle_sip_uri_t *requri=belle_sip_request_get_uri(request);
141 			/*skip the first route it is the same as the request uri*/
142 			if (strcmp(sal_address_get_domain(addr),belle_sip_uri_get_host(requri))==0 ){
143 				ms_message("Skipping top route of initial route-set because same as request-uri.");
144 				continue;
145 			}
146 		}
147 
148 		route=belle_sip_header_route_create((belle_sip_header_address_t*)addr);
149 		uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route);
150 		belle_sip_uri_set_lr_param(uri,1);
151 		belle_sip_message_add_header((belle_sip_message_t*)request,(belle_sip_header_t*)route);
152 	}
153 }
154 
sal_op_build_request(SalOp * op,const char * method)155 belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
156 	belle_sip_header_from_t* from_header;
157 	belle_sip_header_to_t* to_header;
158 	belle_sip_provider_t* prov=op->base.root->prov;
159 	belle_sip_request_t *req;
160 	belle_sip_uri_t* req_uri;
161 	belle_sip_uri_t* to_uri;
162 	belle_sip_header_call_id_t *call_id_header;
163 
164 	const SalAddress* to_address;
165 	const MSList *elem=sal_op_get_route_addresses(op);
166 	char token[10];
167 
168 	/* check that the op has a correct to address */
169 	to_address = sal_op_get_to_address(op);
170 	if( to_address == NULL ){
171 		ms_error("No To: address, cannot build request");
172 		return NULL;
173 	}
174 
175 	to_uri = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to_address));
176 	if( to_uri == NULL ){
177 		ms_error("To: address is invalid, cannot build request");
178 		return NULL;
179 	}
180 
181 	if (strcmp("REGISTER",method)==0 || op->privacy==SalPrivacyNone) {
182 		from_header = belle_sip_header_from_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op))
183 						,belle_sip_random_token(token,sizeof(token)));
184 	} else {
185 		from_header=belle_sip_header_from_create2("Anonymous <sip:anonymous@anonymous.invalid>",belle_sip_random_token(token,sizeof(token)));
186 	}
187 	/*make sure to preserve components like headers or port*/
188 
189 	req_uri = (belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)to_uri);
190 	belle_sip_uri_set_secure(req_uri,sal_op_is_secure(op));
191 
192 	to_header = belle_sip_header_to_create(BELLE_SIP_HEADER_ADDRESS(to_address),NULL);
193 	call_id_header = belle_sip_provider_create_call_id(prov);
194 	if (sal_op_get_call_id(op)) {
195 		belle_sip_header_call_id_set_call_id(call_id_header, sal_op_get_call_id(op));
196 	}
197 
198 	req=belle_sip_request_create(
199 					req_uri,
200 					method,
201 					call_id_header,
202 					belle_sip_header_cseq_create(20,method),
203 					from_header,
204 					to_header,
205 					belle_sip_header_via_new(),
206 					70);
207 
208 	if (op->privacy & SalPrivacyId) {
209 		belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)));
210 		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity));
211 	}
212 
213 	if (elem && strcmp(method,"REGISTER")!=0 && !op->base.root->no_initial_route){
214 		add_initial_route_set(req,elem);
215 	}
216 
217 	if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){
218 		belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new();
219 		if (op->privacy&SalPrivacyCritical)
220 			belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyCritical));
221 		if (op->privacy&SalPrivacyHeader)
222 			belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyHeader));
223 		if (op->privacy&SalPrivacyId)
224 			belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyId));
225 		if (op->privacy&SalPrivacyNone)
226 			belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyNone));
227 		if (op->privacy&SalPrivacySession)
228 			belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacySession));
229 		if (op->privacy&SalPrivacyUser)
230 			belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyUser));
231 		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(privacy_header));
232 	}
233 	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->base.root->supported);
234 	return req;
235 }
236 
sal_op_create_response_from_request(SalOp * op,belle_sip_request_t * req,int code)237 belle_sip_response_t *sal_op_create_response_from_request(SalOp *op, belle_sip_request_t *req, int code){
238 	return sal_create_response_from_request(op->base.root,req,code);
239 }
240 
241 /*ping: main purpose is to obtain its own contact address behind firewalls*/
sal_ping(SalOp * op,const char * from,const char * to)242 int sal_ping(SalOp *op, const char *from, const char *to){
243 	sal_op_set_from(op,from);
244 	sal_op_set_to(op,to);
245 	return sal_op_send_request(op,sal_op_build_request(op,"OPTIONS"));
246 }
247 
sal_op_set_replaces(SalOp * op,belle_sip_header_replaces_t * replaces)248 void sal_op_set_replaces(SalOp* op,belle_sip_header_replaces_t* replaces) {
249 	if (op->replaces){
250 		belle_sip_object_unref(op->replaces);
251 	}
252 	op->replaces=replaces;
253 	belle_sip_object_ref(op->replaces);
254 }
255 
sal_op_set_remote_ua(SalOp * op,belle_sip_message_t * message)256 void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message) {
257 	belle_sip_header_user_agent_t* user_agent=belle_sip_message_get_header_by_type(message,belle_sip_header_user_agent_t);
258 	char user_agent_string[256];
259 	if (user_agent && belle_sip_header_user_agent_get_products_as_string(user_agent,user_agent_string,sizeof(user_agent_string))>0) {
260 		if (op->base.remote_ua!=NULL){
261 			ms_free(op->base.remote_ua);
262 		}
263 		op->base.remote_ua=ms_strdup(user_agent_string);
264 	}
265 }
266 
sal_op_send_request_with_expires(SalOp * op,belle_sip_request_t * request,int expires)267 int sal_op_send_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires) {
268 	belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES);
269 
270 	if (!expires_header && expires>=0) {
271 		belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header=belle_sip_header_expires_new()));
272 	}
273 	if (expires_header) belle_sip_header_expires_set_expires(expires_header,expires);
274 	return sal_op_send_request(op,request);
275 }
276 
sal_op_resend_request(SalOp * op,belle_sip_request_t * request)277 void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) {
278 	belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CSEQ);
279 	belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
280 	sal_op_send_request(op,request);
281 }
282 
add_headers(SalOp * op,belle_sip_header_t * h,belle_sip_message_t * msg)283 static void add_headers(SalOp *op, belle_sip_header_t *h, belle_sip_message_t *msg){
284 
285 	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_contact_t)){
286 		belle_sip_header_contact_t* newct;
287 		/*special case for contact, we want to keep everything from the custom contact but set automatic mode and add our own parameters as well*/
288 		sal_op_set_contact_address(op,(SalAddress*)BELLE_SIP_HEADER_ADDRESS(h));
289 		newct = sal_op_create_contact(op);
290 		belle_sip_message_set_header(BELLE_SIP_MESSAGE(msg),BELLE_SIP_HEADER(newct));
291 		return;
292 	}
293 	/*if a header already exists in the message, replace it*/
294 	belle_sip_message_set_header(msg,h);
295 
296 }
297 
_sal_op_add_custom_headers(SalOp * op,belle_sip_message_t * msg)298 void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg){
299 	if (op->base.sent_custom_headers){
300 		belle_sip_message_t *ch=(belle_sip_message_t*)op->base.sent_custom_headers;
301 		belle_sip_list_t *l=belle_sip_message_get_all_headers(ch);
302 		belle_sip_list_t *elem;
303 		for(elem=l;elem!=NULL;elem=elem->next){
304 			add_headers(op,(belle_sip_header_t*)elem->data,msg);
305 		}
306 		belle_sip_list_free(l);
307 	}
308 }
309 
_sal_op_send_request_with_contact(SalOp * op,belle_sip_request_t * request,bool_t add_contact)310 static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request, bool_t add_contact) {
311 	belle_sip_client_transaction_t* client_transaction;
312 	belle_sip_provider_t* prov=op->base.root->prov;
313 	belle_sip_uri_t* outbound_proxy=NULL;
314 	belle_sip_header_contact_t* contact;
315 	int result =-1;
316 	belle_sip_uri_t *next_hop_uri=NULL;
317 
318 	if (add_contact && !belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t)) {
319 		contact = sal_op_create_contact(op);
320 		belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact));
321 	} /*keep existing*/
322 
323 	_sal_op_add_custom_headers(op, (belle_sip_message_t*)request);
324 
325 	if (!op->dialog || belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_NULL) {
326 		/*don't put route header if  dialog is in confirmed state*/
327 		const MSList *elem=sal_op_get_route_addresses(op);
328 		const char *transport;
329 		const char *method=belle_sip_request_get_method(request);
330 		belle_sip_listening_point_t *udplp=belle_sip_provider_get_listening_point(prov,"UDP");
331 
332 		if (elem) {
333 			outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data);
334 			next_hop_uri=outbound_proxy;
335 		}else{
336 			next_hop_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri(request));
337 		}
338 		transport=belle_sip_uri_get_transport_param(next_hop_uri);
339 		if (transport==NULL){
340 			/*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use
341 			 * the first available transport*/
342 			if (!belle_sip_uri_is_secure(next_hop_uri)){
343 				if (udplp==NULL){
344 					if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){
345 						transport="tcp";
346 					}else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){
347 						transport="tls";
348 					}
349 				}
350 				if (transport){
351 					belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport);
352 					belle_sip_uri_set_transport_param(next_hop_uri,transport);
353 				}
354 			}
355 		}else{
356 #ifdef TUNNEL_ENABLED
357 			if (udplp && BELLE_SIP_OBJECT_IS_INSTANCE_OF(udplp,belle_sip_tunnel_listening_point_t)){
358 				/* our tunnel mode only supports UDP. Force transport to be set to UDP */
359 				belle_sip_uri_set_transport_param(next_hop_uri,"udp");
360 			}
361 #endif
362 		}
363 		/*because in case of tunnel, transport can be changed*/
364 		transport=belle_sip_uri_get_transport_param(next_hop_uri);
365 
366 		if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport &&
367 			(strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){
368 			/*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/
369 			belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t);
370 			belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"alias",NULL);
371 		}
372 	}
373 
374 	client_transaction = belle_sip_provider_create_client_transaction(prov,request);
375 	belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),sal_op_ref(op));
376 	if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans);
377 	op->pending_client_trans=client_transaction; /*update pending inv for being able to cancel*/
378 	belle_sip_object_ref(op->pending_client_trans);
379 
380 	if (belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_user_agent_t)==NULL)
381 		belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(op->base.root->user_agent));
382 
383 	if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION)
384 		&& !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) {
385 		/*hmm just in case we already have authentication param in cache*/
386 		belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL,op->base.realm);
387 	}
388 	result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/);
389 
390 	/*update call id if not set yet for this OP*/
391 	if (result == 0 && !op->base.call_id) {
392 		op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_call_id_t))));
393 	}
394 
395 	return result;
396 
397 }
398 
sal_op_send_request(SalOp * op,belle_sip_request_t * request)399 int sal_op_send_request(SalOp* op, belle_sip_request_t* request)  {
400 	bool_t need_contact=FALSE;
401 	if (request==NULL) {
402 		return -1; /*sanity check*/
403 	}
404 	/*
405 	  Header field          where   proxy ACK BYE CAN INV OPT REG
406 	  ___________________________________________________________
407 	  Contact                 R            o   -   -   m   o   o
408 	 */
409 	if (strcmp(belle_sip_request_get_method(request),"INVITE")==0
410 			||strcmp(belle_sip_request_get_method(request),"REGISTER")==0
411 			||strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0
412 			||strcmp(belle_sip_request_get_method(request),"OPTIONS")==0
413 			||strcmp(belle_sip_request_get_method(request),"REFER")==0) /* Despite contact seems not mandatory, call flow example show a Contact in REFER requests*/
414 		need_contact=TRUE;
415 
416 	return _sal_op_send_request_with_contact(op, request,need_contact);
417 }
418 
sal_reason_to_sip_code(SalReason r)419 int sal_reason_to_sip_code(SalReason r){
420 	int ret=500;
421 	switch(r){
422 		case SalReasonNone:
423 			ret=200;
424 			break;
425 		case SalReasonIOError:
426 			ret=503;
427 			break;
428 		case SalReasonUnknown:
429 			ret=400;
430 			break;
431 		case SalReasonBusy:
432 			ret=486;
433 			break;
434 		case SalReasonDeclined:
435 			ret=603;
436 			break;
437 		case SalReasonDoNotDisturb:
438 			ret=600;
439 			break;
440 		case SalReasonForbidden:
441 			ret=403;
442 			break;
443 		case SalReasonUnsupportedContent:
444 			ret=415;
445 			break;
446 		case SalReasonNotFound:
447 			ret=404;
448 			break;
449 		case SalReasonRedirect:
450 			ret=302;
451 			break;
452 		case SalReasonTemporarilyUnavailable:
453 			ret=480;
454 			break;
455 		case SalReasonServiceUnavailable:
456 			ret=503;
457 			break;
458 		case SalReasonRequestPending:
459 			ret=491;
460 			break;
461 		case SalReasonUnauthorized:
462 			ret=401;
463 			break;
464 		case SalReasonNotAcceptable:
465 			ret=488; /*or maybe 606 Not Acceptable ?*/
466 			break;
467 		case SalReasonNoMatch:
468 			ret=481;
469 			break;
470 		case SalReasonRequestTimeout:
471 			ret=408;
472 			break;
473 		case SalReasonMovedPermanently:
474 			ret=301;
475 			break;
476 		case SalReasonGone:
477 			ret=410;
478 			break;
479 		case SalReasonAddressIncomplete:
480 			ret=484;
481 			break;
482 		case SalReasonNotImplemented:
483 			ret=501;
484 			break;
485 		case SalReasonServerTimeout:
486 			ret=504;
487 			break;
488 		case SalReasonBadGateway:
489 			ret=502;
490 			break;
491 		case SalReasonInternalError:
492 			ret=500;
493 			break;
494 	}
495 	return ret;
496 }
497 
_sal_reason_from_sip_code(int code)498 SalReason _sal_reason_from_sip_code(int code) {
499 	if (code>=100 && code<300) return SalReasonNone;
500 
501 	switch(code) {
502 	case 0:
503 		return SalReasonIOError;
504 	case 301:
505 		return SalReasonMovedPermanently;
506 	case 302:
507 		return SalReasonRedirect;
508 	case 401:
509 	case 407:
510 		return SalReasonUnauthorized;
511 	case 403:
512 		return SalReasonForbidden;
513 	case 404:
514 		return SalReasonNotFound;
515 	case 408:
516 		return SalReasonRequestTimeout;
517 	case 410:
518 		return SalReasonGone;
519 	case 415:
520 		return SalReasonUnsupportedContent;
521 	case 422:
522 		ms_error ("422 not implemented yet");;
523 		break;
524 	case 480:
525 		return SalReasonTemporarilyUnavailable;
526 	case 481:
527 		return SalReasonNoMatch;
528 	case 484:
529 		return SalReasonAddressIncomplete;
530 	case 486:
531 		return SalReasonBusy;
532 	case 487:
533 		return SalReasonNone;
534 	case 488:
535 		return SalReasonNotAcceptable;
536 	case 491:
537 		return SalReasonRequestPending;
538 	case 500:
539 		return SalReasonInternalError;
540 	case 501:
541 		return SalReasonNotImplemented;
542 	case 502:
543 		return SalReasonBadGateway;
544 	case 503:
545 		return SalReasonServiceUnavailable;
546 	case 504:
547 		return SalReasonServerTimeout;
548 	case 600:
549 		return SalReasonDoNotDisturb;
550 	case 603:
551 		return SalReasonDeclined;
552 	default:
553 		return SalReasonUnknown;
554 	}
555 	return SalReasonUnknown;
556 }
557 
sal_error_info_none(void)558 const SalErrorInfo *sal_error_info_none(void){
559 	static SalErrorInfo none={
560 		SalReasonNone,
561 		"Ok",
562 		200,
563 		NULL,
564 		NULL,
565 
566 	};
567 	return &none;
568 }
569 
sal_error_info_reset(SalErrorInfo * ei)570 void sal_error_info_reset(SalErrorInfo *ei){
571 	if (ei->status_string){
572 		ms_free(ei->status_string);
573 		ei->status_string=NULL;
574 	}
575 	if (ei->warnings){
576 		ms_free(ei->warnings);
577 		ei->warnings=NULL;
578 
579 	}
580 	if (ei->full_string){
581 		ms_free(ei->full_string);
582 		ei->full_string=NULL;
583 	}
584 	if (ei->protocol){
585 		ms_free(ei->protocol);
586 		ei->protocol = NULL;
587 	}
588 	ei->protocol_code=0;
589 	ei->reason=SalReasonNone;
590 	ei->sub_sei = NULL;
591 }
592 
sal_error_info_set(SalErrorInfo * ei,SalReason reason,const char * protocol,int code,const char * status_string,const char * warning)593 void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol, int code, const char *status_string, const char *warning){
594 	sal_error_info_reset(ei);
595 	if (reason==SalReasonUnknown && strcmp(protocol, "SIP") == 0 && code != 0) ei->reason=_sal_reason_from_sip_code(code);
596 	else{
597 		ei->reason=reason;
598 		if (code == 0) {
599 			code = sal_reason_to_sip_code(reason);
600 		}
601 	}
602 	ei->protocol_code=code;
603 	ei->status_string=status_string ? ms_strdup(status_string) : NULL;
604 	ei->warnings=warning ? ms_strdup(warning) : NULL;
605 	ei->protocol = protocol ? ms_strdup(protocol) : NULL;
606 	if (ei->status_string){
607 		if (ei->warnings)
608 			ei->full_string=ms_strdup_printf("%s %s",ei->status_string,ei->warnings);
609 		else ei->full_string=ms_strdup(ei->status_string);
610 	}
611 }
612 
sal_op_set_reason_error_info(SalOp * op,belle_sip_message_t * msg)613 void sal_op_set_reason_error_info(SalOp *op, belle_sip_message_t *msg){
614 	belle_sip_header_reason_t* reason_header = belle_sip_message_get_header_by_type(msg,belle_sip_header_reason_t);
615 	if (reason_header){
616 		SalErrorInfo *ei=&op->reason_error_info; // ?//
617 		const char *protocol = belle_sip_header_reason_get_protocol(reason_header);
618 		int code = belle_sip_header_reason_get_cause(reason_header);
619 		const char *text = belle_sip_header_reason_get_text(reason_header);
620 		sal_error_info_set(ei, SalReasonUnknown, protocol, code, text, NULL);
621 	}
622 }
623 
sal_op_set_error_info_from_response(SalOp * op,belle_sip_response_t * response)624 void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response){
625 	int code = belle_sip_response_get_status_code(response);
626 	const char *reason_phrase=belle_sip_response_get_reason_phrase(response);
627 	belle_sip_header_t *warning=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Warning");
628 	SalErrorInfo *ei=&op->error_info;
629 	const char *warnings;
630 
631 	warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL;
632 	sal_error_info_set(ei,SalReasonUnknown,"SIP", code,reason_phrase,warnings);
633 	sal_op_set_reason_error_info(op, BELLE_SIP_MESSAGE(response));
634 }
635 
sal_op_get_error_info(const SalOp * op)636 const SalErrorInfo *sal_op_get_error_info(const SalOp *op){
637 	return &op->error_info;
638 }
639 
sal_op_get_reason_error_info(const SalOp * op)640 const SalErrorInfo * sal_op_get_reason_error_info(const SalOp *op){
641 	return &op->reason_error_info;
642 }
643 
644 
645 
646 
unlink_op_with_dialog(SalOp * op,belle_sip_dialog_t * dialog)647 static void unlink_op_with_dialog(SalOp *op, belle_sip_dialog_t* dialog){
648 	belle_sip_dialog_set_application_data(dialog,NULL);
649 	sal_op_unref(op);
650 	belle_sip_object_unref(dialog);
651 }
652 
link_op_with_dialog(SalOp * op,belle_sip_dialog_t * dialog)653 static belle_sip_dialog_t *link_op_with_dialog(SalOp *op, belle_sip_dialog_t* dialog){
654 	belle_sip_dialog_set_application_data(dialog,sal_op_ref(op));
655 	belle_sip_object_ref(dialog);
656 	return dialog;
657 }
658 
set_or_update_dialog(SalOp * op,belle_sip_dialog_t * dialog)659 void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog) {
660 	ms_message("op [%p] : set_or_update_dialog() current=[%p] new=[%p]",op,op->dialog,dialog);
661 	sal_op_ref(op);
662 	if (op->dialog!=dialog){
663 		if (op->dialog){
664 			/*FIXME: shouldn't we delete unconfirmed dialogs ?*/
665 			unlink_op_with_dialog(op,op->dialog);
666 			op->dialog=NULL;
667 		}
668 		if (dialog) {
669 			op->dialog=link_op_with_dialog(op,dialog);
670 			belle_sip_dialog_enable_pending_trans_checking(dialog,op->base.root->pending_trans_checking);
671 		}
672 	}
673 	sal_op_unref(op);
674 }
675 /*return reffed op*/
sal_op_ref(SalOp * op)676 SalOp* sal_op_ref(SalOp* op) {
677 	op->ref++;
678 	return op;
679 }
680 /*return null, destroy op if ref count =0*/
sal_op_unref(SalOp * op)681 void* sal_op_unref(SalOp* op) {
682 	op->ref--;
683 	if (op->ref==0) {
684 		sal_op_release_impl(op);
685 	}else if (op->ref<0){
686 		ms_fatal("SalOp [%p]: too many unrefs.",op);
687 	}
688 	return NULL;
689 }
690 
sal_op_send_and_create_refresher(SalOp * op,belle_sip_request_t * req,int expires,belle_sip_refresher_listener_t listener)691 int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener ) {
692 	if (sal_op_send_request_with_expires(op,req,expires)==0) {
693 		if (op->refresher) {
694 			belle_sip_refresher_stop(op->refresher);
695 			belle_sip_object_unref(op->refresher);
696 		}
697 		if ((op->refresher = belle_sip_client_transaction_create_refresher(op->pending_client_trans))) {
698 			/*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified
699 			 * that it is terminated anymore.*/
700 			sal_op_unref(op);/*loose the reference that was given to the transaction when creating it*/
701 			/* Note that the refresher will replace our data with belle_sip_transaction_set_application_data().
702 			 Something in the design is not very good here, it makes things complicated to the belle-sip user.
703 			 Possible ideas to improve things: refresher shall not use belle_sip_transaction_set_application_data() internally, refresher should let the first transaction
704 			 notify the user as a normal transaction*/
705 			belle_sip_refresher_set_listener(op->refresher,listener,op);
706 			belle_sip_refresher_set_retry_after(op->refresher,op->base.root->refresher_retry_after);
707 			belle_sip_refresher_set_realm(op->refresher,op->base.realm);
708 			belle_sip_refresher_enable_manual_mode(op->refresher,op->manual_refresher);
709 			return 0;
710 		} else {
711 			return -1;
712 		}
713 	}
714 	return -1;
715 }
716 
sal_op_state_to_string(const SalOpState value)717 const char* sal_op_state_to_string(const SalOpState value) {
718 	switch(value) {
719 	case SalOpStateEarly: return"SalOpStateEarly";
720 	case SalOpStateActive: return "SalOpStateActive";
721 	case SalOpStateTerminating: return "SalOpStateTerminating";
722 	case SalOpStateTerminated: return "SalOpStateTerminated";
723 	default:
724 		return "Unknown";
725 	}
726 }
727 
728 /*
729  * Warning: this function takes owneship of the custom headers
730  */
sal_op_set_sent_custom_header(SalOp * op,SalCustomHeader * ch)731 void sal_op_set_sent_custom_header(SalOp *op, SalCustomHeader* ch){
732 	SalOpBase *b=(SalOpBase *)op;
733 	if (b->sent_custom_headers){
734 		sal_custom_header_free(b->sent_custom_headers);
735 		b->sent_custom_headers=NULL;
736 	}
737 	if (ch) belle_sip_object_ref((belle_sip_message_t*)ch);
738 	b->sent_custom_headers=ch;
739 }
740 
sal_op_assign_recv_headers(SalOp * op,belle_sip_message_t * incoming)741 void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming){
742 	if (incoming) belle_sip_object_ref(incoming);
743 	if (op->base.recv_custom_headers){
744 		belle_sip_object_unref(op->base.recv_custom_headers);
745 		op->base.recv_custom_headers=NULL;
746 	}
747 	if (incoming){
748 		op->base.recv_custom_headers=(SalCustomHeader*)incoming;
749 	}
750 }
751 
sal_op_get_remote_contact(const SalOp * op)752 const char *sal_op_get_remote_contact(const SalOp *op){
753 	/*
754 	 * remote contact is filled in process_response
755 	 */
756 	return op->base.remote_contact;
757 }
758 
sal_op_get_body_handler(SalOp * op,belle_sip_message_t * msg)759 SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg) {
760 	belle_sip_body_handler_t *body_handler = belle_sip_message_get_body_handler(msg);
761 	if (body_handler != NULL) {
762 		belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t);
763 		belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t);
764 		belle_sip_header_t *content_encoding = belle_sip_message_get_header(msg, "Content-Encoding");
765 		if (content_type != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_type));
766 		if (content_length != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_length));
767 		if (content_encoding != NULL) belle_sip_body_handler_add_header(body_handler, content_encoding);
768 	}
769 	return (SalBodyHandler *)body_handler;
770 }
771 
sal_op_set_privacy(SalOp * op,SalPrivacyMask privacy)772 void sal_op_set_privacy(SalOp* op,SalPrivacyMask privacy) {
773 	op->privacy=privacy;
774 }
sal_op_get_privacy(const SalOp * op)775 SalPrivacyMask sal_op_get_privacy(const SalOp* op) {
776 	return op->privacy;
777 }
778 
sal_op_is_secure(const SalOp * op)779 bool_t sal_op_is_secure(const SalOp* op) {
780 	const SalAddress* from = sal_op_get_from_address(op);
781 	const SalAddress* to = sal_op_get_to_address(op);
782 
783 	return from && to && strcasecmp("sips",sal_address_get_scheme(from))==0 && strcasecmp("sips",sal_address_get_scheme(to))==0;
784 }
785 
sal_op_set_manual_refresher_mode(SalOp * op,bool_t enabled)786 void sal_op_set_manual_refresher_mode(SalOp *op, bool_t enabled){
787 	op->manual_refresher=enabled;
788 }
789 
sal_op_get_address_family(SalOp * op)790 int sal_op_get_address_family(SalOp *op){
791 	belle_sip_transaction_t *tr=NULL;
792 	belle_sip_header_address_t *contact;
793 
794 
795 	if (op->refresher)
796 		tr=(belle_sip_transaction_t *)belle_sip_refresher_get_transaction(op->refresher);
797 
798 	if (tr==NULL)
799 		tr=(belle_sip_transaction_t *)op->pending_client_trans;
800 	if (tr==NULL)
801 		tr=(belle_sip_transaction_t *)op->pending_server_trans;
802 
803 	if (tr==NULL){
804 		ms_error("Unable to determine IP version from signaling operation.");
805 		return AF_UNSPEC;
806 	}
807 
808 
809 	if (op->refresher) {
810 		belle_sip_response_t *resp = belle_sip_transaction_get_response(tr);
811 		belle_sip_header_via_t *via = resp ?belle_sip_message_get_header_by_type(resp,belle_sip_header_via_t):NULL;
812 		if (!via){
813 			ms_error("Unable to determine IP version from signaling operation, no via header found.");
814 			return AF_UNSPEC;
815 		}
816 		return (strchr(belle_sip_header_via_get_host(via),':') != NULL) ? AF_INET6 : AF_INET;
817 	} else {
818 		belle_sip_request_t *req = belle_sip_transaction_get_request(tr);
819 		contact=(belle_sip_header_address_t*)belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t);
820 		if (!contact){
821 			ms_error("Unable to determine IP version from signaling operation, no contact header found.");
822 		}
823 		return sal_address_is_ipv6((SalAddress*)contact) ? AF_INET6 : AF_INET;
824 	}
825 }
826 
sal_op_is_idle(SalOp * op)827 bool_t sal_op_is_idle(SalOp *op){
828 	if (op->dialog){
829 		return !belle_sip_dialog_request_pending(op->dialog);
830 	}
831 	return TRUE;
832 }
833 
sal_op_stop_refreshing(SalOp * op)834 void sal_op_stop_refreshing(SalOp *op){
835 	if (op->refresher){
836 		belle_sip_refresher_stop(op->refresher);
837 	}
838 }
839 
sal_call_set_sdp_handling(SalOp * h,SalOpSDPHandling handling)840 void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling)  {
841 	if (handling != SalOpSDPNormal) ms_message("Enabling special SDP handling for SalOp[%p]!", h);
842 	h->sdp_handling = handling;
843 }
sal_op_cnx_ip_to_0000_if_sendonly_enable(SalOp * op,bool_t yesno)844 void sal_op_cnx_ip_to_0000_if_sendonly_enable(SalOp *op,bool_t yesno) {
845 	op->cnx_ip_to_0000_if_sendonly_enabled = yesno;
846 }
847 
sal_op_cnx_ip_to_0000_if_sendonly_enabled(SalOp * op)848 bool_t sal_op_cnx_ip_to_0000_if_sendonly_enabled(SalOp *op) {
849 	return op->cnx_ip_to_0000_if_sendonly_enabled;
850 }
851 
sal_op_is_forked_of(const SalOp * op1,const SalOp * op2)852 bool_t sal_op_is_forked_of(const SalOp *op1, const SalOp *op2){
853 	return op1->base.call_id && op2->base.call_id && strcmp(op1->base.call_id, op2->base.call_id) == 0;
854 }
sal_op_refresh(SalOp * op)855 int sal_op_refresh(SalOp *op) {
856 	if (op->refresher) {
857 		belle_sip_refresher_refresh(op->refresher,belle_sip_refresher_get_expires(op->refresher));
858 		return 0;
859 	}
860 	ms_warning("sal_refresh on op [%p] of type [%s] no refresher",op,sal_op_type_to_string(op->type));
861 	return -1;
862 }
863 
sal_op_set_event(SalOp * op,const char * eventname)864 void sal_op_set_event(SalOp *op, const char *eventname){
865 	belle_sip_header_event_t *header = NULL;
866 	if (op->event) belle_sip_object_unref(op->event);
867 	if (eventname){
868 		header = belle_sip_header_event_create(eventname);
869 		belle_sip_object_ref(header);
870 	}
871 	op->event = header;
872 }
873 
sal_op_get_public_address(SalOp * op,int * port)874 const char* sal_op_get_public_address(SalOp *op, int *port) {
875 	if (op && op->refresher) {
876 		return belle_sip_refresher_get_public_address(op->refresher, port);
877 	}
878 	return NULL;
879 }
880 
sal_op_get_local_address(SalOp * op,int * port)881 const char* sal_op_get_local_address(SalOp *op, int *port) {
882 	if (op && op->refresher) {
883 		return belle_sip_refresher_get_local_address(op->refresher, port);
884 	}
885 	return NULL;
886 }
887 
sal_op_get_dialog_id(const SalOp * op)888 char* sal_op_get_dialog_id(const SalOp *op) {
889 	if (op->dialog != NULL) {
890 		return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", ((SalOpBase*)op)->call_id,
891 			belle_sip_dialog_get_remote_tag(op->dialog), belle_sip_dialog_get_local_tag(op->dialog));
892 	}
893 	return NULL;
894 }
895 
896