3 Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr)
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "sal_eXosip2.h"
25 #include "offeranswer.h"
28 // Necessary to make it linked
29 static void for_linker() { eXosip_transport_hook_register(NULL); }
31 static bool_t call_failure(Sal *sal, eXosip_event_t *ev);
33 static void text_received(Sal *sal, eXosip_event_t *ev);
35 static void masquerade_via(osip_message_t *msg, const char *ip, const char *port);
36 static bool_t fix_message_contact(SalOp *op, osip_message_t *request,osip_message_t *last_answer, bool_t expire_last_contact);
37 static void update_contact_from_response(SalOp *op, osip_message_t *response);
39 void _osip_list_set_empty(osip_list_t *l, void (*freefunc)(void*)){
41 while(!osip_list_eol(l,0)) {
42 data=osip_list_get(l,0);
43 osip_list_remove(l,0);
44 if (data) freefunc(data);
48 void sal_get_default_local_ip(Sal *sal, int address_family,char *ip, size_t iplen){
49 if (eXosip_guess_localip(address_family,ip,iplen)<0){
50 /*default to something */
51 strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen);
52 ms_error("Could not find default routable ip address !");
57 static SalOp * sal_find_call(Sal *sal, int cid){
60 for(elem=sal->calls;elem!=NULL;elem=elem->next){
61 op=(SalOp*)elem->data;
62 if (op->cid==cid) return op;
67 static void sal_add_call(Sal *sal, SalOp *op){
68 sal->calls=ms_list_append(sal->calls,op);
71 static void sal_remove_call(Sal *sal, SalOp *op){
72 sal->calls=ms_list_remove(sal->calls, op);
75 static SalOp * sal_find_register(Sal *sal, int rid){
78 for(elem=sal->registers;elem!=NULL;elem=elem->next){
79 op=(SalOp*)elem->data;
80 if (op->rid==rid) return op;
85 static void sal_add_register(Sal *sal, SalOp *op){
86 sal->registers=ms_list_append(sal->registers,op);
89 static void sal_remove_register(Sal *sal, int rid){
92 for(elem=sal->registers;elem!=NULL;elem=elem->next){
93 op=(SalOp*)elem->data;
95 sal->registers=ms_list_remove_link(sal->registers,elem);
101 static SalOp * sal_find_other(Sal *sal, osip_message_t *response){
104 osip_call_id_t *callid=osip_message_get_call_id(response);
106 ms_error("There is no call-id in this response !");
109 for(elem=sal->other_transactions;elem!=NULL;elem=elem->next){
110 op=(SalOp*)elem->data;
111 if (osip_call_id_match(callid,op->call_id)==0) return op;
116 void sal_add_other(Sal *sal, SalOp *op, osip_message_t *request){
117 osip_call_id_t *callid=osip_message_get_call_id(request);
119 ms_error("There is no call id in the request !");
122 osip_call_id_clone(callid,&op->call_id);
123 sal->other_transactions=ms_list_append(sal->other_transactions,op);
126 static void sal_remove_other(Sal *sal, SalOp *op){
127 sal->other_transactions=ms_list_remove(sal->other_transactions,op);
131 static void sal_add_pending_auth(Sal *sal, SalOp *op){
132 sal->pending_auths=ms_list_append(sal->pending_auths,op);
136 static void sal_remove_pending_auth(Sal *sal, SalOp *op){
137 sal->pending_auths=ms_list_remove(sal->pending_auths,op);
140 void sal_exosip_fix_route(SalOp *op){
141 if (sal_op_get_route(op)!=NULL){
142 osip_route_t *rt=NULL;
143 osip_uri_param_t *lr_param=NULL;
145 osip_route_init(&rt);
146 if (osip_route_parse(rt,sal_op_get_route(op))<0){
147 ms_warning("Bad route %s!",sal_op_get_route(op));
148 sal_op_set_route(op,NULL);
150 /* check if the lr parameter is set , if not add it */
151 osip_uri_uparam_get_byname(rt->url, "lr", &lr_param);
154 osip_uri_uparam_add(rt->url,osip_strdup("lr"),NULL);
155 osip_route_to_str(rt,&tmproute);
156 sal_op_set_route(op,tmproute);
164 SalOp * sal_op_new(Sal *sal){
165 SalOp *op=ms_new0(SalOp,1);
166 __sal_op_init(op,sal);
167 op->cid=op->did=op->tid=op->rid=op->nid=op->sid=-1;
169 op->supports_session_timers=FALSE;
170 op->sdp_offering=TRUE;
171 op->pending_auth=NULL;
176 op->referred_by=NULL;
177 op->masquerade_via=FALSE;
178 op->auto_answer_asked=FALSE;
180 op->terminated=FALSE;
184 bool_t sal_call_autoanswer_asked(SalOp *op)
186 return op->auto_answer_asked;
189 void sal_op_release(SalOp *op){
191 sdp_message_free(op->sdp_answer);
192 if (op->pending_auth)
193 eXosip_event_free(op->pending_auth);
195 sal_remove_register(op->base.root,op->rid);
196 eXosip_register_remove(op->rid);
199 ms_message("Cleaning cid %i",op->cid);
200 sal_remove_call(op->base.root,op);
203 sal_remove_out_subscribe(op->base.root,op);
206 sal_remove_in_subscribe(op->base.root,op);
208 osip_call_id_free(op->call_id);
211 if (op->pending_auth){
212 sal_remove_pending_auth(op->base.root,op);
215 sal_media_description_unref(op->result);
217 sal_remove_other(op->base.root,op);
218 osip_call_id_free(op->call_id);
221 ms_free(op->replaces);
223 if (op->referred_by){
224 ms_free(op->referred_by);
227 sal_auth_info_delete(op->auth_info);
232 static void _osip_trace_func(char *fi, int li, osip_trace_level_t level, char *chfr, va_list ap){
233 int ortp_level=ORTP_DEBUG;
239 ortp_level=ORTP_MESSAGE;
242 ortp_level=ORTP_WARNING;
246 ortp_level=ORTP_ERROR;
249 ortp_level=ORTP_FATAL;
251 case END_TRACE_LEVEL:
254 if (ortp_log_level_enabled(level)){
255 int len=strlen(chfr);
256 char *chfrdup=ortp_strdup(chfr);
257 /*need to remove endline*/
259 if (chfrdup[len-1]=='\n')
261 if (chfrdup[len-2]=='\r')
264 ortp_logv(ortp_level,chfrdup,ap);
271 static bool_t firsttime=TRUE;
274 osip_trace_initialize_func (OSIP_INFO4,&_osip_trace_func);
279 sal->keepalive_period=30;
280 sal->double_reg=TRUE;
281 sal->use_rports=TRUE;
283 sal->reuse_authorization=FALSE;
285 sal->verify_server_certs=TRUE;
286 sal->expire_old_contact=FALSE;
290 void sal_uninit(Sal* sal){
293 ms_free(sal->rootCa);
297 void sal_set_user_pointer(Sal *sal, void *user_data){
301 void *sal_get_user_pointer(const Sal *sal){
305 static void unimplemented_stub(){
306 ms_warning("Unimplemented SAL callback");
309 void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
310 memcpy(&ctx->callbacks,cbs,sizeof(*cbs));
311 if (ctx->callbacks.call_received==NULL)
312 ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub;
313 if (ctx->callbacks.call_ringing==NULL)
314 ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub;
315 if (ctx->callbacks.call_accepted==NULL)
316 ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub;
317 if (ctx->callbacks.call_failure==NULL)
318 ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
319 if (ctx->callbacks.call_terminated==NULL)
320 ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
321 if (ctx->callbacks.call_released==NULL)
322 ctx->callbacks.call_released=(SalOnCallReleased)unimplemented_stub;
323 if (ctx->callbacks.call_updating==NULL)
324 ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub;
325 if (ctx->callbacks.auth_requested==NULL)
326 ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
327 if (ctx->callbacks.auth_success==NULL)
328 ctx->callbacks.auth_success=(SalOnAuthSuccess)unimplemented_stub;
329 if (ctx->callbacks.register_success==NULL)
330 ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub;
331 if (ctx->callbacks.register_failure==NULL)
332 ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
333 if (ctx->callbacks.dtmf_received==NULL)
334 ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
335 if (ctx->callbacks.notify==NULL)
336 ctx->callbacks.notify=(SalOnNotify)unimplemented_stub;
337 if (ctx->callbacks.notify_presence==NULL)
338 ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub;
339 if (ctx->callbacks.subscribe_received==NULL)
340 ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
341 if (ctx->callbacks.text_received==NULL)
342 ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
343 if (ctx->callbacks.ping_reply==NULL)
344 ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
347 int sal_unlisten_ports(Sal *ctx){
356 int sal_reset_transports(Sal *ctx){
357 #ifdef HAVE_EXOSIP_RESET_TRANSPORTS
359 ms_message("Exosip transports reset.");
360 eXosip_reset_transports();
364 ms_warning("sal_reset_transports() not implemented in this version.");
370 static void set_tls_options(Sal *ctx){
372 eXosip_tls_ctx_t tlsCtx;
373 memset(&tlsCtx, 0, sizeof(tlsCtx));
374 snprintf(tlsCtx.root_ca_cert, sizeof(tlsCtx.client.cert), "%s", ctx->rootCa);
375 eXosip_set_tls_ctx(&tlsCtx);
377 #ifdef HAVE_EXOSIP_TLS_VERIFY_CERTIFICATE
378 eXosip_tls_verify_certificate(ctx->verify_server_certs);
382 int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure){
385 int proto=IPPROTO_UDP;
386 int keepalive = ctx->keepalive_period;
389 case SalTransportUDP:
391 eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE, &keepalive);
393 case SalTransportTCP:
394 case SalTransportTLS:
397 eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE,&keepalive);
398 set_tls_options(ctx);
401 ms_warning("unexpected proto, using datagram");
403 /*see if it looks like an IPv6 address*/
404 int use_rports = ctx->use_rports; // Copy char to int to avoid bad alignment
405 eXosip_set_option(EXOSIP_OPT_USE_RPORT,&use_rports);
406 int dont_use_101 = !ctx->use_101; // Copy char to int to avoid bad alignment
407 eXosip_set_option(EXOSIP_OPT_DONT_SEND_101,&dont_use_101);
409 ipv6=strchr(addr,':')!=NULL;
410 eXosip_enable_ipv6(ipv6);
412 if (is_secure && tr == SalTransportUDP){
413 ms_fatal("SIP over DTLS is not supported yet.");
416 err=eXosip_listen_addr(proto, addr, port, ipv6 ? PF_INET6 : PF_INET, is_secure);
421 ortp_socket_t sal_get_socket(Sal *ctx){
422 #ifdef HAVE_EXOSIP_GET_SOCKET
423 return eXosip_get_socket(IPPROTO_UDP);
425 ms_warning("Sorry, eXosip does not have eXosip_get_socket() method");
430 void sal_set_user_agent(Sal *ctx, const char *user_agent){
431 eXosip_set_user_agent(user_agent);
434 void sal_use_session_timers(Sal *ctx, int expires){
435 ctx->session_expires=expires;
438 void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec){
439 ctx->one_matching_codec=one_matching_codec;
442 MSList *sal_get_pending_auths(Sal *sal){
443 return ms_list_copy(sal->pending_auths);
446 void sal_use_double_registrations(Sal *ctx, bool_t enabled){
447 ctx->double_reg=enabled;
450 void sal_expire_old_registration_contacts(Sal *ctx, bool_t enabled){
451 ctx->expire_old_contact=enabled;
454 void sal_use_rport(Sal *ctx, bool_t use_rports){
455 ctx->use_rports=use_rports;
457 void sal_use_101(Sal *ctx, bool_t use_101){
458 ctx->use_101=use_101;
461 void sal_set_root_ca(Sal* ctx, const char* rootCa) {
463 ms_free(ctx->rootCa);
464 ctx->rootCa = ms_strdup(rootCa);
467 void sal_verify_server_certificates(Sal *ctx, bool_t verify){
468 ctx->verify_server_certs=verify;
469 #ifdef HAVE_EXOSIP_TLS_VERIFY_CERTIFICATE
470 eXosip_tls_verify_certificate(verify);
474 static int extract_received_rport(osip_message_t *msg, const char **received, int *rportval,SalTransport* transport){
475 osip_via_t *via=NULL;
476 osip_generic_param_t *param=NULL;
477 const char *rport=NULL;
481 osip_message_get_via(msg,0,&via);
483 ms_warning("extract_received_rport(): no via.");
487 *transport = sal_transport_parse(via->protocol);
489 if (via->port && via->port[0]!='\0')
490 *rportval=atoi(via->port);
492 osip_via_param_get_byname(via,"rport",¶m);
495 if (rport && rport[0]!='\0') *rportval=atoi(rport);
499 osip_via_param_get_byname(via,"received",¶m);
500 if (param) *received=param->gvalue;
502 if (rport==NULL && *received==NULL){
503 ms_warning("extract_received_rport(): no rport and no received parameters.");
509 static void set_sdp(osip_message_t *sip,sdp_message_t *msg){
513 sdp_message_to_str(msg,&sdp);
515 snprintf(clen,sizeof(clen),"%i",sdplen);
516 osip_message_set_body(sip,sdp,sdplen);
517 osip_message_set_content_type(sip,"application/sdp");
518 osip_message_set_content_length(sip,clen);
522 static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *desc){
523 sdp_message_t *msg=media_description_to_sdp(desc);
525 ms_error("Fail to print sdp message !");
529 sdp_message_free(msg);
532 static void sdp_process(SalOp *h){
533 ms_message("Doing SDP offer/answer process of type %s",h->sdp_offering ? "outgoing" : "incoming");
535 sal_media_description_unref(h->result);
537 h->result=sal_media_description_new();
538 if (h->sdp_offering){
539 offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result);
543 sdp_message_free(h->sdp_answer);
545 offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec);
546 h->sdp_answer=media_description_to_sdp(h->result);
547 /*once we have generated the SDP answer, we modify the result description for processing by the upper layer.
548 It should contains media parameters constraint from the remote offer, not our response*/
549 strcpy(h->result->addr,h->base.remote_media->addr);
550 h->result->bandwidth=h->base.remote_media->bandwidth;
552 for(i=0;i<h->result->nstreams;++i){
553 if (h->result->streams[i].rtp_port>0){
554 strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
555 strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
556 h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
557 h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
558 h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
559 h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;
561 if (h->result->streams[i].proto == SalProtoRtpSavp) {
562 h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
570 int sal_call_is_offerer(const SalOp *h){
571 return h->sdp_offering;
574 int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc){
576 sal_media_description_ref(desc);
577 if (h->base.local_media)
578 sal_media_description_unref(h->base.local_media);
579 h->base.local_media=desc;
580 if (h->base.remote_media){
581 /*case of an incoming call where we modify the local capabilities between the time
582 * the call is ringing and it is accepted (for example if you want to accept without video*/
583 /*reset the sdp answer so that it is computed again*/
585 sdp_message_free(h->sdp_answer);
592 int sal_call(SalOp *h, const char *from, const char *to){
595 osip_message_t *invite=NULL;
596 sal_op_set_from(h,from);
598 sal_exosip_fix_route(h);
600 h->terminated = FALSE;
602 route = sal_op_get_route(h);
603 err=eXosip_call_build_initial_invite(&invite,to,from,route,"Phone call");
605 ms_error("Could not create call. Error %d (from=%s to=%s route=%s)",
606 err, from, to, route);
609 osip_message_set_allow(invite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
610 if (h->base.contact){
611 _osip_list_set_empty(&invite->contacts,(void (*)(void*))osip_contact_free);
612 osip_message_set_contact(invite,h->base.contact);
614 if (h->base.root->session_expires!=0){
615 osip_message_set_header(invite, "Session-expires", "200");
616 osip_message_set_supported(invite, "timer");
618 if (h->base.local_media){
619 h->sdp_offering=TRUE;
620 set_sdp_from_desc(invite,h->base.local_media);
621 }else h->sdp_offering=FALSE;
623 osip_message_set_header(invite,"Replaces",h->replaces);
625 osip_message_set_header(invite,"Referred-By",h->referred_by);
629 err=eXosip_call_send_initial_invite(invite);
633 ms_error("Fail to send invite ! Error code %d", err);
636 sal_add_call(h->base.root,h);
641 int sal_call_notify_ringing(SalOp *h, bool_t early_media){
644 /*if early media send also 180 and 183 */
648 eXosip_call_build_answer(h->tid,183,&msg);
652 set_sdp(msg,h->sdp_answer);
653 sdp_message_free(h->sdp_answer);
656 eXosip_call_send_answer(h->tid,183,msg);
661 eXosip_call_send_answer(h->tid,180,NULL);
667 int sal_call_accept(SalOp * h){
669 const char *contact=sal_op_get_contact(h);
671 int err=eXosip_call_build_answer(h->tid,200,&msg);
672 if (err<0 || msg==NULL){
673 ms_error("Fail to build answer for call: err=%i",err);
676 if (h->base.root->session_expires!=0){
677 if (h->supports_session_timers) osip_message_set_supported(msg, "timer");
681 _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free);
682 osip_message_set_contact(msg,contact);
685 if (h->base.local_media){
686 /*this is the case where we received an invite without SDP*/
687 if (h->sdp_offering) {
688 set_sdp_from_desc(msg,h->base.local_media);
690 if (h->sdp_answer==NULL) sdp_process(h);
692 set_sdp(msg,h->sdp_answer);
693 sdp_message_free(h->sdp_answer);
698 ms_error("You are accepting a call but not defined any media capabilities !");
700 eXosip_call_send_answer(h->tid,200,msg);
704 int sal_call_decline(SalOp *h, SalReason reason, const char *redirect){
705 if (reason==SalReasonBusy){
707 eXosip_call_send_answer(h->tid,486,NULL);
710 else if (reason==SalReasonTemporarilyUnavailable){
712 eXosip_call_send_answer(h->tid,480,NULL);
714 }else if (reason==SalReasonDoNotDisturb){
716 eXosip_call_send_answer(h->tid,600,NULL);
718 }else if (reason==SalReasonMedia){
720 eXosip_call_send_answer(h->tid,415,NULL);
722 }else if (redirect!=NULL && reason==SalReasonRedirect){
725 if (strstr(redirect,"sip:")!=0) code=302;
728 eXosip_call_build_answer(h->tid,code,&msg);
729 osip_message_set_contact(msg,redirect);
730 eXosip_call_send_answer(h->tid,code,msg);
732 }else sal_call_terminate(h);
736 SalMediaDescription * sal_call_get_remote_media_description(SalOp *h){
737 return h->base.remote_media;
740 SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
741 if (h->base.local_media && h->base.remote_media && !h->result){
747 int sal_call_set_referer(SalOp *h, SalOp *refered_call){
748 if (refered_call->replaces)
749 h->replaces=ms_strdup(refered_call->replaces);
750 if (refered_call->referred_by)
751 h->referred_by=ms_strdup(refered_call->referred_by);
755 static int send_notify_for_refer(int did, const char *sipfrag){
758 eXosip_call_build_notify(did,EXOSIP_SUBCRSTATE_ACTIVE,&msg);
761 ms_warning("Could not build NOTIFY for refer.");
764 osip_message_set_content_type(msg,"message/sipfrag");
765 osip_message_set_header(msg,"Event","refer");
766 osip_message_set_body(msg,sipfrag,strlen(sipfrag));
767 eXosip_call_send_request(did,msg);
772 /* currently only support to notify trying and 200Ok*/
773 int sal_call_notify_refer_state(SalOp *h, SalOp *newcall){
776 send_notify_for_refer(h->did,"SIP/2.0 100 Trying\r\n");
778 else if (newcall->cid!=-1){
779 if (newcall->did==-1){
780 /* not yet established*/
781 if (!newcall->terminated){
783 send_notify_for_refer(h->did,"SIP/2.0 100 Trying\r\n");
786 if (!newcall->terminated){
787 if (send_notify_for_refer(h->did,"SIP/2.0 200 Ok\r\n")==-1){
788 /* we need previous notify transaction to complete, so buffer the request for later*/
789 h->sipfrag_pending="SIP/2.0 200 Ok\r\n";
797 int sal_ping(SalOp *op, const char *from, const char *to){
798 osip_message_t *options=NULL;
800 sal_op_set_from(op,from);
801 sal_op_set_to(op,to);
802 sal_exosip_fix_route(op);
804 eXosip_options_build_request (&options, sal_op_get_to(op),
805 sal_op_get_from(op),sal_op_get_route(op));
807 if (op->base.root->session_expires!=0){
808 osip_message_set_header(options, "Session-expires", "200");
809 osip_message_set_supported(options, "timer");
811 sal_add_other(sal_op_get_sal(op),op,options);
812 return eXosip_options_send_request(options);
817 int sal_call_refer(SalOp *h, const char *refer_to){
818 osip_message_t *msg=NULL;
821 eXosip_call_build_refer(h->did,refer_to, &msg);
822 if (msg) err=eXosip_call_send_request(h->did, msg);
828 int sal_call_refer_with_replaces(SalOp *h, SalOp *other_call_h){
829 osip_message_t *msg=NULL;
830 char referto[256]={0};
833 if (eXosip_call_get_referto(other_call_h->did,referto,sizeof(referto)-1)!=0){
834 ms_error("eXosip_call_get_referto() failed for did=%i",other_call_h->did);
838 eXosip_call_build_refer(h->did,referto, &msg);
839 osip_message_set_header(msg,"Referred-By",h->base.from);
840 if (msg) err=eXosip_call_send_request(h->did, msg);
846 SalOp *sal_call_get_replaces(SalOp *h){
847 if (h!=NULL && h->replaces!=NULL){
850 cid=eXosip_call_find_by_replaces(h->replaces);
853 SalOp *ret=sal_find_call(h->base.root,cid);
860 int sal_call_send_dtmf(SalOp *h, char dtmf){
861 osip_message_t *msg=NULL;
866 eXosip_call_build_info(h->did,&msg);
868 snprintf(dtmf_body, sizeof(dtmf_body), "Signal=%c\r\nDuration=250\r\n", dtmf);
869 osip_message_set_body(msg,dtmf_body,strlen(dtmf_body));
870 osip_message_set_content_type(msg,"application/dtmf-relay");
871 snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(dtmf_body));
872 osip_message_set_content_length(msg,clen);
873 eXosip_call_send_request(h->did,msg);
879 static void push_auth_to_exosip(const SalAuthInfo *info){
881 if (info->userid==NULL || info->userid[0]=='\0') userid=info->username;
882 else userid=info->userid;
883 ms_message("Authentication info for username [%s], id[%s], realm [%s] added to eXosip", info->username,userid, info->realm);
884 eXosip_add_authentication_info (info->username,userid,
885 info->password, NULL,info->realm);
888 * Just for symmetry ;-)
890 static void pop_auth_from_exosip() {
891 eXosip_clear_authentication_info();
894 int sal_call_terminate(SalOp *h){
896 if (h == NULL) return -1;
897 if (h->auth_info) push_auth_to_exosip(h->auth_info);
899 err=eXosip_call_terminate(h->cid,h->did);
901 if (!h->base.root->reuse_authorization) pop_auth_from_exosip();
903 ms_warning("Exosip could not terminate the call: cid=%i did=%i", h->cid,h->did);
909 void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){
910 if (h->terminated) return;
911 if (h->pending_auth){
912 push_auth_to_exosip(info);
914 /*FIXME exosip does not take into account this update register message*/
916 if (fix_message_contact(h, h->pending_auth->request,h->pending_auth->response)) {
920 update_contact_from_response(h,h->pending_auth->response);
922 eXosip_default_action(h->pending_auth);
924 ms_message("eXosip_default_action() done");
925 if (!h->base.root->reuse_authorization) pop_auth_from_exosip();
927 if (h->auth_info) sal_auth_info_delete(h->auth_info); /*if already exist*/
928 h->auth_info=sal_auth_info_clone(info); /*store auth info for subsequent request*/
931 void sal_op_cancel_authentication(SalOp *h) {
933 sal_op_get_sal(h)->callbacks.register_failure(h,SalErrorFailure, SalReasonForbidden,_("Authentication failure"));
934 } else if (h->cid >0) {
935 sal_op_get_sal(h)->callbacks.call_failure(h,SalErrorFailure, SalReasonForbidden,_("Authentication failure"),0);
937 ms_warning("Auth failure not handled");
941 static void set_network_origin(SalOp *op, osip_message_t *req){
942 const char *received=NULL;
945 SalTransport transport;
946 if (extract_received_rport(req,&received,&rport,&transport)!=0){
947 osip_via_t *via=NULL;
949 osip_message_get_via(req,0,&via);
950 received=osip_via_get_host(via);
951 tmp=osip_via_get_port(via);
952 if (tmp) rport=atoi(tmp);
954 if (transport != SalTransportUDP) {
955 snprintf(origin,sizeof(origin)-1,"sip:%s:%i",received,rport);
957 snprintf(origin,sizeof(origin)-1,"sip:%s:%i;transport=%s",received,rport,sal_transport_to_string(transport));
959 __sal_op_set_network_origin(op,origin);
962 static void set_remote_ua(SalOp* op, osip_message_t *req){
963 if (op->base.remote_ua==NULL){
964 osip_header_t *h=NULL;
965 osip_message_get_user_agent(req,0,&h);
967 op->base.remote_ua=ms_strdup(h->hvalue);
972 static void set_replaces(SalOp *op, osip_message_t *req){
973 osip_header_t *h=NULL;
976 ms_free(op->replaces);
979 osip_message_header_get_byname(req,"replaces",0,&h);
981 if (h->hvalue && h->hvalue[0]!='\0'){
982 op->replaces=ms_strdup(h->hvalue);
987 static SalOp *find_op(Sal *sal, eXosip_event_t *ev){
989 return sal_find_call(sal,ev->cid);
992 return sal_find_register(sal,ev->rid);
995 return sal_find_out_subscribe(sal,ev->sid);
998 return sal_find_in_subscribe(sal,ev->nid);
1000 if (ev->response) return sal_find_other(sal,ev->response);
1004 static void inc_new_call(Sal *sal, eXosip_event_t *ev){
1005 SalOp *op=sal_op_new(sal);
1006 osip_from_t *from,*to;
1007 osip_call_info_t *call_info;
1009 sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
1011 set_network_origin(op,ev->request);
1012 set_remote_ua(op,ev->request);
1013 set_replaces(op,ev->request);
1016 op->sdp_offering=FALSE;
1017 op->base.remote_media=sal_media_description_new();
1018 sdp_to_media_description(sdp,op->base.remote_media);
1019 sdp_message_free(sdp);
1020 }else op->sdp_offering=TRUE;
1022 from=osip_message_get_from(ev->request);
1023 to=osip_message_get_to(ev->request);
1024 osip_from_to_str(from,&tmp);
1025 sal_op_set_from(op,tmp);
1027 osip_from_to_str(to,&tmp);
1028 sal_op_set_to(op,tmp);
1031 osip_message_get_call_info(ev->request,0,&call_info);
1034 osip_call_info_to_str(call_info,&tmp);
1035 if( strstr(tmp,"answer-after=") != NULL)
1037 op->auto_answer_asked=TRUE;
1038 ms_message("The caller asked to automatically answer the call(Emergency?)\n");
1047 sal_add_call(op->base.root,op);
1048 sal->callbacks.call_received(op);
1051 static void handle_reinvite(Sal *sal, eXosip_event_t *ev){
1052 SalOp *op=find_op(sal,ev);
1056 ms_warning("Reinvite for non-existing operation !");
1061 sdp=eXosip_get_sdp_info(ev->request);
1062 if (op->base.remote_media){
1063 sal_media_description_unref(op->base.remote_media);
1064 op->base.remote_media=NULL;
1067 sal_media_description_unref(op->result);
1071 op->sdp_offering=FALSE;
1072 op->base.remote_media=sal_media_description_new();
1073 sdp_to_media_description(sdp,op->base.remote_media);
1074 sdp_message_free(sdp);
1077 op->sdp_offering=TRUE;
1079 sal->callbacks.call_updating(op);
1082 static void handle_ack(Sal *sal, eXosip_event_t *ev){
1083 SalOp *op=find_op(sal,ev);
1087 ms_warning("ack for non-existing call !");
1090 if (op->terminated) {
1091 ms_warning("ack for terminated call, ignoring");
1095 if (op->sdp_offering){
1096 sdp=eXosip_get_sdp_info(ev->ack);
1098 if (op->base.remote_media)
1099 sal_media_description_unref(op->base.remote_media);
1100 op->base.remote_media=sal_media_description_new();
1101 sdp_to_media_description(sdp,op->base.remote_media);
1103 sdp_message_free(sdp);
1109 sal->callbacks.call_ack(op);
1112 static void update_contact_from_response(SalOp *op, osip_message_t *response){
1113 const char *received;
1115 SalTransport transport;
1116 if (extract_received_rport(response,&received,&rport,&transport)==0){
1117 const char *contact=sal_op_get_contact(op);
1119 /*no contact given yet, use from instead*/
1120 contact=sal_op_get_from(op);
1123 SalAddress *addr=sal_address_new(contact);
1125 sal_address_set_domain(addr,received);
1126 sal_address_set_port_int(addr,rport);
1127 if (transport!=SalTransportUDP)
1128 sal_address_set_transport(addr,transport);
1129 tmp=sal_address_as_string(addr);
1130 ms_message("Contact address updated to %s",tmp);
1131 sal_op_set_contact(op,tmp);
1132 sal_address_destroy(addr);
1138 static int call_proceeding(Sal *sal, eXosip_event_t *ev){
1139 SalOp *op=find_op(sal,ev);
1141 if (op==NULL || op->terminated==TRUE) {
1142 ms_warning("This call has been canceled.");
1144 eXosip_call_terminate(ev->cid,ev->did);
1152 /* update contact if received and rport are set by the server
1153 note: will only be used by remote for next INVITE, if any...*/
1154 update_contact_from_response(op,ev->response);
1158 static void call_ringing(Sal *sal, eXosip_event_t *ev){
1160 SalOp *op=find_op(sal,ev);
1161 if (call_proceeding(sal, ev)==-1) return;
1163 set_remote_ua(op,ev->response);
1164 sdp=eXosip_get_sdp_info(ev->response);
1166 op->base.remote_media=sal_media_description_new();
1167 sdp_to_media_description(sdp,op->base.remote_media);
1168 sdp_message_free(sdp);
1169 if (op->base.local_media) sdp_process(op);
1171 sal->callbacks.call_ringing(op);
1174 static void call_accepted(Sal *sal, eXosip_event_t *ev){
1176 osip_message_t *msg=NULL;
1177 SalOp *op=find_op(sal,ev);
1178 const char *contact;
1180 if (op==NULL || op->terminated==TRUE) {
1181 ms_warning("This call has been already terminated.");
1183 eXosip_call_terminate(ev->cid,ev->did);
1189 set_remote_ua(op,ev->response);
1191 sdp=eXosip_get_sdp_info(ev->response);
1193 op->base.remote_media=sal_media_description_new();
1194 sdp_to_media_description(sdp,op->base.remote_media);
1195 sdp_message_free(sdp);
1196 if (op->base.local_media) sdp_process(op);
1198 eXosip_call_build_ack(ev->did,&msg);
1200 ms_warning("This call has been already terminated.");
1202 eXosip_call_terminate(ev->cid,ev->did);
1206 contact=sal_op_get_contact(op);
1208 _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free);
1209 osip_message_set_contact(msg,contact);
1211 if (op->sdp_answer){
1212 set_sdp(msg,op->sdp_answer);
1213 sdp_message_free(op->sdp_answer);
1214 op->sdp_answer=NULL;
1216 eXosip_call_send_ack(ev->did,msg);
1217 sal->callbacks.call_accepted(op);
1220 static void call_terminated(Sal *sal, eXosip_event_t *ev){
1222 SalOp *op=find_op(sal,ev);
1224 ms_warning("Call terminated for already closed call ?");
1228 osip_from_to_str(ev->request->from,&from);
1230 sal->callbacks.call_terminated(op,from!=NULL ? from : sal_op_get_from(op));
1231 if (from) osip_free(from);
1232 op->terminated=TRUE;
1235 static void call_released(Sal *sal, eXosip_event_t *ev){
1236 SalOp *op=find_op(sal,ev);
1238 ms_warning("No op associated to this call_released()");
1241 if (!op->terminated){
1242 /* no response received so far */
1243 call_failure(sal,ev);
1245 sal->callbacks.call_released(op);
1248 static int get_auth_data_from_response(osip_message_t *resp, const char **realm, const char **username){
1249 const char *prx_realm=NULL,*www_realm=NULL;
1250 osip_proxy_authenticate_t *prx_auth;
1251 osip_www_authenticate_t *www_auth;
1253 *username=osip_uri_get_username(resp->from->url);
1254 prx_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->proxy_authenticates,0);
1255 www_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->www_authenticates,0);
1257 prx_realm=osip_proxy_authenticate_get_realm(prx_auth);
1259 www_realm=osip_www_authenticate_get_realm(www_auth);
1263 }else if (www_realm){
1271 static int get_auth_data_from_request(osip_message_t *msg, const char **realm, const char **username){
1272 osip_authorization_t *auth=NULL;
1273 osip_proxy_authorization_t *prx_auth=NULL;
1275 *username=osip_uri_get_username(msg->from->url);
1276 osip_message_get_authorization(msg, 0, &auth);
1278 *realm=osip_authorization_get_realm(auth);
1281 osip_message_get_proxy_authorization(msg,0,&prx_auth);
1283 *realm=osip_proxy_authorization_get_realm(prx_auth);
1289 static int get_auth_data(eXosip_event_t *ev, const char **realm, const char **username){
1290 if (ev->response && get_auth_data_from_response(ev->response,realm,username)==0) return 0;
1291 if (ev->request && get_auth_data_from_request(ev->request,realm,username)==0) return 0;
1295 int sal_op_get_auth_requested(SalOp *op, const char **realm, const char **username){
1296 if (op->pending_auth){
1297 return get_auth_data(op->pending_auth,realm,username);
1302 static bool_t process_authentication(Sal *sal, eXosip_event_t *ev){
1304 const char *username,*realm;
1307 ms_warning("No operation associated with this authentication !");
1310 if (get_auth_data(ev,&realm,&username)==0){
1311 if (op->pending_auth!=NULL){
1312 eXosip_event_free(op->pending_auth);
1313 op->pending_auth=ev;
1315 op->pending_auth=ev;
1316 sal_add_pending_auth(sal,op);
1319 sal->callbacks.auth_requested(op,realm,username);
1325 static void authentication_ok(Sal *sal, eXosip_event_t *ev){
1327 const char *username,*realm;
1330 ms_warning("No operation associated with this authentication_ok!");
1333 if (op->pending_auth){
1334 eXosip_event_free(op->pending_auth);
1335 sal_remove_pending_auth(sal,op);
1336 op->pending_auth=NULL;
1338 if (get_auth_data(ev,&realm,&username)==0){
1339 sal->callbacks.auth_success(op,realm,username);
1343 static bool_t call_failure(Sal *sal, eXosip_event_t *ev){
1346 char* computedReason=NULL;
1347 const char *reason=NULL;
1348 SalError error=SalErrorUnknown;
1349 SalReason sr=SalReasonUnknown;
1352 op=(SalOp*)find_op(sal,ev);
1355 ms_warning("Call failure reported for a closed call, ignored.");
1360 code=osip_message_get_status_code(ev->response);
1361 reason=osip_message_get_reason_phrase(ev->response);
1362 osip_header_t *h=NULL;
1363 if (!osip_message_header_get_byname( ev->response
1367 computedReason = ms_strdup_printf("%s %s",reason,osip_header_get_value(h));
1368 reason = computedReason;
1376 return process_authentication(sal,ev);
1379 error=SalErrorUnknown;
1382 error=SalErrorFailure;
1383 sr=SalReasonNotFound;
1386 error=SalErrorFailure;
1390 eXosip_default_action(ev);
1394 error=SalErrorFailure;
1395 sr=SalReasonTemporarilyUnavailable;
1397 error=SalErrorFailure;
1403 error=SalErrorFailure;
1404 sr=SalReasonDoNotDisturb;
1407 error=SalErrorFailure;
1408 sr=SalReasonDeclined;
1412 error=SalErrorFailure;
1413 sr=SalReasonUnknown;
1414 }else error=SalErrorNoResponse;
1416 op->terminated=TRUE;
1417 sal->callbacks.call_failure(op,error,sr,reason,code);
1418 if (computedReason != NULL){
1419 ms_free(computedReason);
1424 /* Request remote side to send us VFU */
1425 void sal_call_send_vfu_request(SalOp *h){
1426 osip_message_t *msg=NULL;
1428 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1432 " <picture_fast_update></picture_fast_update>"
1440 eXosip_call_build_info(h->did,&msg);
1442 osip_message_set_body(msg,info_body,strlen(info_body));
1443 osip_message_set_content_type(msg,"application/media_control+xml");
1444 snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(info_body));
1445 osip_message_set_content_length(msg,clen);
1446 eXosip_call_send_request(h->did,msg);
1447 ms_message("Sending VFU request !");
1452 static void process_media_control_xml(Sal *sal, eXosip_event_t *ev){
1453 SalOp *op=find_op(sal,ev);
1454 osip_body_t *body=NULL;
1457 ms_warning("media control xml received without operation context!");
1461 osip_message_get_body(ev->request,0,&body);
1462 if (body && body->body!=NULL &&
1463 strstr(body->body,"picture_fast_update")){
1464 osip_message_t *ans=NULL;
1465 ms_message("Receiving VFU request !");
1466 if (sal->callbacks.vfu_request){
1467 sal->callbacks.vfu_request(op);
1468 eXosip_call_build_answer(ev->tid,200,&ans);
1470 eXosip_call_send_answer(ev->tid,200,ans);
1474 /*in all other cases we must say it is not implemented.*/
1476 osip_message_t *ans=NULL;
1478 eXosip_call_build_answer(ev->tid,501,&ans);
1480 eXosip_call_send_answer(ev->tid,501,ans);
1485 static void process_dtmf_relay(Sal *sal, eXosip_event_t *ev){
1486 SalOp *op=find_op(sal,ev);
1487 osip_body_t *body=NULL;
1490 ms_warning("media dtmf relay received without operation context!");
1494 osip_message_get_body(ev->request,0,&body);
1495 if (body && body->body!=NULL){
1496 osip_message_t *ans=NULL;
1497 const char *name=strstr(body->body,"Signal");
1498 if (name==NULL) name=strstr(body->body,"signal");
1500 ms_warning("Could not extract the dtmf name from the SIP INFO.");
1503 name+=strlen("signal");
1504 if (sscanf(name," = %1s",tmp)==1){
1505 ms_message("Receiving dtmf %s via SIP INFO.",tmp);
1506 if (sal->callbacks.dtmf_received != NULL)
1507 sal->callbacks.dtmf_received(op, tmp[0]);
1511 eXosip_call_build_answer(ev->tid,200,&ans);
1513 eXosip_call_send_answer(ev->tid,200,ans);
1518 static void fill_options_answer(osip_message_t *options){
1519 osip_message_set_allow(options,"INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, SUBSCRIBE, NOTIFY, INFO");
1520 osip_message_set_accept(options,"application/sdp");
1523 static void process_refer(Sal *sal, SalOp *op, eXosip_event_t *ev){
1524 osip_header_t *h=NULL;
1525 osip_message_t *ans=NULL;
1526 ms_message("Receiving REFER request !");
1527 osip_message_header_get_byname(ev->request,"Refer-To",0,&h);
1530 osip_from_t *from=NULL;
1532 osip_from_init(&from);
1534 if (osip_from_parse(from,h->hvalue)==0){
1536 osip_uri_header_t *uh=NULL;
1537 osip_header_t *referred_by=NULL;
1538 osip_uri_header_get_byname(&from->url->url_headers,(char*)"Replaces",&uh);
1539 if (uh!=NULL && uh->gvalue && uh->gvalue[0]!='\0'){
1540 ms_message("Found replaces in Refer-To");
1542 ms_free(op->replaces);
1544 op->replaces=ms_strdup(uh->gvalue);
1546 osip_message_header_get_byname(ev->request,"Referred-By",0,&referred_by);
1547 if (referred_by && referred_by->hvalue && referred_by->hvalue[0]!='\0'){
1548 if (op->referred_by)
1549 ms_free(op->referred_by);
1550 op->referred_by=ms_strdup(referred_by->hvalue);
1553 osip_uri_header_freelist(&from->url->url_headers);
1554 osip_from_to_str(from,&tmp);
1555 sal->callbacks.refer_received(sal,op,tmp);
1557 osip_from_free(from);
1560 eXosip_call_build_answer(ev->tid,202,&ans);
1562 eXosip_call_send_answer(ev->tid,202,ans);
1567 ms_warning("cannot do anything with the refer without destination\n");
1571 static void process_notify(Sal *sal, eXosip_event_t *ev){
1572 osip_header_t *h=NULL;
1574 SalOp *op=find_op(sal,ev);
1575 osip_message_t *ans=NULL;
1577 ms_message("Receiving NOTIFY request !");
1578 osip_from_to_str(ev->request->from,&from);
1579 osip_message_header_get_byname(ev->request,"Event",0,&h);
1581 osip_body_t *body=NULL;
1582 //osip_content_type_t *ct=NULL;
1583 osip_message_get_body(ev->request,0,&body);
1584 //ct=osip_message_get_content_type(ev->request);
1585 if (h->hvalue && strcasecmp(h->hvalue,"refer")==0){
1586 /*special handling of refer events*/
1587 if (body && body->body){
1588 osip_message_t *msg;
1589 osip_message_init(&msg);
1590 if (osip_message_parse_sipfrag(msg,body->body,strlen(body->body))==0){
1591 int code=osip_message_get_status_code(msg);
1593 sal->callbacks.notify_refer(op,SalReferTrying);
1594 }else if (code==200){
1595 sal->callbacks.notify_refer(op,SalReferSuccess);
1596 }else if (code>=400){
1597 sal->callbacks.notify_refer(op,SalReferFailed);
1600 osip_message_free(msg);
1603 /*generic handling*/
1604 sal->callbacks.notify(op,from,h->hvalue);
1607 /*answer that we received the notify*/
1609 eXosip_call_build_answer(ev->tid,200,&ans);
1611 eXosip_call_send_answer(ev->tid,200,ans);
1616 static void call_message_new(Sal *sal, eXosip_event_t *ev){
1617 osip_message_t *ans=NULL;
1619 if (MSG_IS_INFO(ev->request)){
1620 osip_content_type_t *ct;
1621 ct=osip_message_get_content_type(ev->request);
1622 if (ct && ct->subtype){
1623 if (strcmp(ct->subtype,"media_control+xml")==0)
1624 process_media_control_xml(sal,ev);
1625 else if (strcmp(ct->subtype,"dtmf-relay")==0)
1626 process_dtmf_relay(sal,ev);
1628 ms_message("Unhandled SIP INFO.");
1629 /*send an "Not implemented" answer*/
1631 eXosip_call_build_answer(ev->tid,501,&ans);
1633 eXosip_call_send_answer(ev->tid,501,ans);
1637 /*empty SIP INFO, probably to test we are alive. Send an empty answer*/
1639 eXosip_call_build_answer(ev->tid,200,&ans);
1641 eXosip_call_send_answer(ev->tid,200,ans);
1644 }else if(MSG_IS_MESSAGE(ev->request)){
1645 /* SIP messages could be received into call */
1646 text_received(sal, ev);
1648 eXosip_call_build_answer(ev->tid,200,&ans);
1650 eXosip_call_send_answer(ev->tid,200,ans);
1652 }else if(MSG_IS_REFER(ev->request)){
1653 SalOp *op=find_op(sal,ev);
1655 ms_message("Receiving REFER request !");
1656 process_refer(sal,op,ev);
1657 }else if(MSG_IS_NOTIFY(ev->request)){
1658 process_notify(sal,ev);
1659 }else if (MSG_IS_OPTIONS(ev->request)){
1661 eXosip_call_build_answer(ev->tid,200,&ans);
1663 fill_options_answer(ans);
1664 eXosip_call_send_answer(ev->tid,200,ans);
1668 }else ms_warning("call_message_new: No request ?");
1671 static void inc_update(Sal *sal, eXosip_event_t *ev){
1672 osip_message_t *msg=NULL;
1673 ms_message("Processing incoming UPDATE");
1675 eXosip_message_build_answer(ev->tid,200,&msg);
1677 eXosip_message_send_answer(ev->tid,200,msg);
1681 static bool_t comes_from_local_if(osip_message_t *msg){
1682 osip_via_t *via=NULL;
1683 osip_message_get_via(msg,0,&via);
1686 host=osip_via_get_host(via);
1687 if (strcmp(host,"127.0.0.1")==0 || strcmp(host,"::1")==0){
1688 osip_generic_param_t *param=NULL;
1689 osip_via_param_get_byname(via,"received",¶m);
1690 if (param==NULL) return TRUE;
1691 if (param->gvalue &&
1692 (strcmp(param->gvalue,"127.0.0.1")==0 || strcmp(param->gvalue,"::1")==0)){
1700 static void text_received(Sal *sal, eXosip_event_t *ev){
1701 osip_body_t *body=NULL;
1702 char *from=NULL,*msg;
1704 osip_message_get_body(ev->request,0,&body);
1706 ms_error("Could not get text message from SIP body");
1710 osip_from_to_str(ev->request->from,&from);
1711 sal->callbacks.text_received(sal,from,msg);
1717 static void other_request(Sal *sal, eXosip_event_t *ev){
1718 ms_message("in other_request");
1719 if (ev->request==NULL) return;
1720 if (strcmp(ev->request->sip_method,"MESSAGE")==0){
1721 text_received(sal,ev);
1722 eXosip_message_send_answer(ev->tid,200,NULL);
1723 }else if (strcmp(ev->request->sip_method,"OPTIONS")==0){
1724 osip_message_t *options=NULL;
1725 eXosip_options_build_answer(ev->tid,200,&options);
1726 fill_options_answer(options);
1727 eXosip_options_send_answer(ev->tid,200,options);
1728 }else if (strncmp(ev->request->sip_method, "REFER", 5) == 0){
1729 ms_message("Receiving REFER request !");
1730 if (comes_from_local_if(ev->request)) {
1731 process_refer(sal,NULL,ev);
1732 }else ms_warning("Ignored REFER not coming from this local loopback interface.");
1733 }else if (strncmp(ev->request->sip_method, "UPDATE", 6) == 0){
1738 osip_message_to_str(ev->request,&tmp,&msglen);
1740 ms_message("Unsupported request received:\n%s",tmp);
1743 /*answer with a 501 Not implemented*/
1744 eXosip_message_send_answer(ev->tid,501,NULL);
1748 static void masquerade_via(osip_message_t *msg, const char *ip, const char *port){
1749 osip_via_t *via=NULL;
1750 osip_message_get_via(msg,0,&via);
1752 osip_free(via->port);
1753 via->port=osip_strdup(port);
1754 osip_free(via->host);
1755 via->host=osip_strdup(ip);
1760 static bool_t fix_message_contact(SalOp *op, osip_message_t *request,osip_message_t *last_answer, bool_t expire_last_contact) {
1761 osip_contact_t *ctt=NULL;
1762 const char *received;
1764 SalTransport transport;
1767 if (extract_received_rport(last_answer,&received,&rport,&transport)==-1) return FALSE;
1768 osip_message_get_contact(request,0,&ctt);
1770 ms_warning("fix_message_contact(): no contact to update");
1773 if (expire_last_contact){
1774 osip_contact_t *oldct=NULL,*prevct;
1775 osip_generic_param_t *param=NULL;
1776 osip_contact_clone(ctt,&oldct);
1777 while ((prevct=(osip_contact_t*)osip_list_get(&request->contacts,1))!=NULL){
1778 osip_contact_free(prevct);
1779 osip_list_remove(&request->contacts,1);
1781 osip_list_add(&request->contacts,oldct,1);
1782 osip_contact_param_get_byname(oldct,"expires",¶m);
1784 if (param->gvalue) osip_free(param->gvalue);
1785 param->gvalue=osip_strdup("0");
1787 osip_contact_param_add(oldct,osip_strdup("expires"),osip_strdup("0"));
1790 if (ctt->url->host!=NULL){
1791 osip_free(ctt->url->host);
1793 ctt->url->host=osip_strdup(received);
1794 if (ctt->url->port!=NULL){
1795 osip_free(ctt->url->port);
1797 snprintf(port,sizeof(port),"%i",rport);
1798 ctt->url->port=osip_strdup(port);
1799 if (op->masquerade_via) masquerade_via(request,received,port);
1801 if (transport != SalTransportUDP) {
1802 sal_address_set_param((SalAddress *)ctt, "transport", sal_transport_to_string(transport));
1807 static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *orig_request, osip_message_t *last_answer){
1808 osip_contact_t *ctt=NULL;
1809 SalAddress* ori_contact_address=NULL;
1810 const char *received;
1812 SalTransport transport;
1814 osip_message_t *msg=NULL;
1815 Sal* sal=op->base.root;
1817 bool_t found_valid_contact=FALSE;
1818 bool_t from_request=FALSE;
1820 if (sal->double_reg==FALSE ) return FALSE;
1822 if (extract_received_rport(last_answer,&received,&rport,&transport)==-1) return FALSE;
1825 osip_message_get_contact(last_answer,i,&ctt);
1826 if (!from_request && ctt==NULL) {
1827 osip_message_get_contact(orig_request,0,&ctt);
1831 osip_contact_to_str(ctt,&tmp);
1832 ori_contact_address = sal_address_new(tmp);
1834 /*check if contact is up to date*/
1835 if (strcmp(sal_address_get_domain(ori_contact_address),received) ==0
1836 && sal_address_get_port_int(ori_contact_address) == rport
1837 && sal_address_get_transport(ori_contact_address) == transport) {
1839 ms_message("Register response has up to date contact, doing nothing.");
1841 ms_warning("Register response does not have up to date contact, but last request had."
1842 "Stupid registrar detected, giving up.");
1844 found_valid_contact=TRUE;
1847 sal_address_destroy(ori_contact_address);
1850 }while(!found_valid_contact);
1851 if (!found_valid_contact)
1852 ms_message("Contact do not match, resending register.");
1856 eXosip_register_build_register(op->rid,op->expires,&msg);
1859 ms_warning("Fail to create a contact updated register.");
1862 if (fix_message_contact(op,msg,last_answer,op->base.root->expire_old_contact)) {
1863 eXosip_register_send_register(op->rid,msg);
1865 ms_message("Resending new register with updated contact");
1866 update_contact_from_response(op,last_answer);
1869 ms_warning("Fail to send updated register.");
1877 static void registration_success(Sal *sal, eXosip_event_t *ev){
1878 SalOp *op=sal_find_register(sal,ev->rid);
1879 osip_header_t *h=NULL;
1882 ms_error("Receiving register response for unknown operation");
1885 osip_message_get_expires(ev->request,0,&h);
1886 if (h!=NULL && atoi(h->hvalue)!=0){
1888 if (!register_again_with_updated_contact(op,ev->request,ev->response)){
1889 sal->callbacks.register_success(op,registered);
1892 sal->callbacks.register_success(op,FALSE);
1896 static bool_t registration_failure(Sal *sal, eXosip_event_t *ev){
1898 const char *reason=NULL;
1899 SalOp *op=sal_find_register(sal,ev->rid);
1900 SalReason sr=SalReasonUnknown;
1901 SalError se=SalErrorUnknown;
1904 ms_error("Receiving register failure for unknown operation");
1908 status_code=osip_message_get_status_code(ev->response);
1909 reason=osip_message_get_reason_phrase(ev->response);
1911 switch(status_code){
1914 return process_authentication(sal,ev);
1916 case 423: /*interval too brief*/
1917 {/*retry with greater interval */
1918 osip_header_t *h=NULL;
1919 osip_message_t *msg=NULL;
1920 osip_message_header_get_byname(ev->response,"min-expires",0,&h);
1921 if (h && h->hvalue && h->hvalue[0]!='\0'){
1922 int val=atoi(h->hvalue);
1923 if (val>op->expires)
1925 }else op->expires*=2;
1927 eXosip_register_build_register(op->rid,op->expires,&msg);
1928 eXosip_register_send_register(op->rid,msg);
1932 case 606: /*Not acceptable, workaround for proxies that don't like private addresses
1933 in vias, such as ekiga.net
1934 On the opposite, freephonie.net bugs when via are masqueraded.
1936 op->masquerade_via=TRUE;
1938 /* if contact is up to date, process the failure, otherwise resend a new register with
1939 updated contact first, just in case the faillure is due to incorrect contact */
1940 if (ev->response && register_again_with_updated_contact(op,ev->request,ev->response))
1941 return TRUE; /*we are retrying with an updated contact*/
1942 if (status_code==403){
1944 sr=SalReasonForbidden;
1945 }else if (status_code==0){
1946 se=SalErrorNoResponse;
1948 sal->callbacks.register_failure(op,se,sr,reason);
1953 static void other_request_reply(Sal *sal,eXosip_event_t *ev){
1954 SalOp *op=find_op(sal,ev);
1955 LinphoneChatMessage* chat_msg;
1956 ms_message("Processing reponse status [%i] for method [%s]",ev->response->status_code,osip_message_get_method(ev->request));
1958 ms_warning("other_request_reply(): Receiving response to unknown request.");
1962 update_contact_from_response(op,ev->response);
1963 if (ev->request && strcmp(osip_message_get_method(ev->request),"OPTIONS")==0)
1964 sal->callbacks.ping_reply(op);
1965 else if (ev->request && strcmp(osip_message_get_method(ev->request),"MESSAGE")==0) {
1966 /*out of call message acknolegment*/
1967 chat_msg=(LinphoneChatMessage* )op->base.user_pointer;
1969 chat_msg->cb(chat_msg
1970 ,(ev->response->status_code==200?LinphoneChatMessageStateDelivered:LinphoneChatMessageStateNotDelivered)
1973 linphone_chat_message_destroy(chat_msg);
1978 static void process_in_call_reply(Sal *sal, eXosip_event_t *ev){
1979 SalOp *op=find_op(sal,ev);
1981 if (ev->request && strcmp(osip_message_get_method(ev->request),"NOTIFY")==0){
1982 if (op->sipfrag_pending){
1983 send_notify_for_refer(op->did,op->sipfrag_pending);
1984 op->sipfrag_pending=NULL;
1990 static bool_t process_event(Sal *sal, eXosip_event_t *ev){
1991 ms_message("linphone process event get a message %d\n",ev->type);
1993 case EXOSIP_CALL_ANSWERED:
1994 ms_message("CALL_ANSWERED\n");
1995 call_accepted(sal,ev);
1996 authentication_ok(sal,ev);
1998 case EXOSIP_CALL_CLOSED:
1999 case EXOSIP_CALL_CANCELLED:
2000 ms_message("CALL_CLOSED or CANCELLED\n");
2001 call_terminated(sal,ev);
2003 case EXOSIP_CALL_TIMEOUT:
2004 case EXOSIP_CALL_NOANSWER:
2005 ms_message("CALL_TIMEOUT or NOANSWER\n");
2006 return call_failure(sal,ev);
2008 case EXOSIP_CALL_REQUESTFAILURE:
2009 case EXOSIP_CALL_GLOBALFAILURE:
2010 case EXOSIP_CALL_SERVERFAILURE:
2011 ms_message("CALL_REQUESTFAILURE or GLOBALFAILURE or SERVERFAILURE\n");
2012 return call_failure(sal,ev);
2014 case EXOSIP_CALL_RELEASED:
2015 ms_message("CALL_RELEASED\n");
2016 call_released(sal, ev);
2018 case EXOSIP_CALL_INVITE:
2019 ms_message("CALL_NEW\n");
2020 inc_new_call(sal,ev);
2022 case EXOSIP_CALL_REINVITE:
2023 handle_reinvite(sal,ev);
2025 case EXOSIP_CALL_ACK:
2026 ms_message("CALL_ACK");
2029 case EXOSIP_CALL_REDIRECTED:
2030 ms_message("CALL_REDIRECTED");
2031 eXosip_default_action(ev);
2033 case EXOSIP_CALL_PROCEEDING:
2034 ms_message("CALL_PROCEEDING");
2035 call_proceeding(sal,ev);
2037 case EXOSIP_CALL_RINGING:
2038 ms_message("CALL_RINGING");
2039 call_ringing(sal,ev);
2040 authentication_ok(sal,ev);
2042 case EXOSIP_CALL_MESSAGE_NEW:
2043 ms_message("EXOSIP_CALL_MESSAGE_NEW");
2044 call_message_new(sal,ev);
2046 case EXOSIP_CALL_MESSAGE_REQUESTFAILURE:
2048 (ev->response->status_code==407 || ev->response->status_code==401)){
2049 return process_authentication(sal,ev);
2052 case EXOSIP_CALL_MESSAGE_ANSWERED:
2053 ms_message("EXOSIP_CALL_MESSAGE_ANSWERED ");
2054 process_in_call_reply(sal,ev);
2056 case EXOSIP_IN_SUBSCRIPTION_NEW:
2057 ms_message("CALL_IN_SUBSCRIPTION_NEW ");
2058 sal_exosip_subscription_recv(sal,ev);
2060 case EXOSIP_IN_SUBSCRIPTION_RELEASED:
2061 ms_message("CALL_SUBSCRIPTION_NEW ");
2062 sal_exosip_in_subscription_closed(sal,ev);
2064 case EXOSIP_SUBSCRIPTION_UPDATE:
2065 ms_message("CALL_SUBSCRIPTION_UPDATE");
2067 case EXOSIP_SUBSCRIPTION_NOTIFY:
2068 ms_message("CALL_SUBSCRIPTION_NOTIFY");
2069 sal_exosip_notify_recv(sal,ev);
2071 case EXOSIP_SUBSCRIPTION_ANSWERED:
2072 ms_message("EXOSIP_SUBSCRIPTION_ANSWERED, ev->sid=%i, ev->did=%i\n",ev->sid,ev->did);
2073 sal_exosip_subscription_answered(sal,ev);
2075 case EXOSIP_SUBSCRIPTION_CLOSED:
2076 ms_message("EXOSIP_SUBSCRIPTION_CLOSED\n");
2077 sal_exosip_subscription_closed(sal,ev);
2079 case EXOSIP_SUBSCRIPTION_REQUESTFAILURE: /**< announce a request failure */
2080 if (ev->response && (ev->response->status_code == 407 || ev->response->status_code == 401)){
2081 return process_authentication(sal,ev);
2083 case EXOSIP_SUBSCRIPTION_SERVERFAILURE:
2084 case EXOSIP_SUBSCRIPTION_GLOBALFAILURE:
2085 sal_exosip_subscription_closed(sal,ev);
2087 case EXOSIP_REGISTRATION_FAILURE:
2088 ms_message("REGISTRATION_FAILURE\n");
2089 return registration_failure(sal,ev);
2091 case EXOSIP_REGISTRATION_SUCCESS:
2092 authentication_ok(sal,ev);
2093 registration_success(sal,ev);
2095 case EXOSIP_MESSAGE_NEW:
2096 other_request(sal,ev);
2098 case EXOSIP_MESSAGE_PROCEEDING:
2099 case EXOSIP_MESSAGE_ANSWERED:
2100 case EXOSIP_MESSAGE_REDIRECTED:
2101 case EXOSIP_MESSAGE_SERVERFAILURE:
2102 case EXOSIP_MESSAGE_GLOBALFAILURE:
2103 other_request_reply(sal,ev);
2105 case EXOSIP_MESSAGE_REQUESTFAILURE:
2106 case EXOSIP_NOTIFICATION_REQUESTFAILURE:
2108 switch (ev->response->status_code) {
2111 return process_authentication(sal,ev);
2113 eXosip_automatic_action ();
2118 other_request_reply(sal,ev);
2121 ms_message("Unhandled exosip event ! %i",ev->type);
2127 int sal_iterate(Sal *sal){
2129 while((ev=eXosip_event_wait(0,0))!=NULL){
2130 if (process_event(sal,ev))
2131 eXosip_event_free(ev);
2133 #ifdef HAVE_EXOSIP_TRYLOCK
2134 if (eXosip_trylock()==0){
2135 eXosip_automatic_refresh();
2138 ms_warning("eXosip_trylock busy.");
2142 eXosip_automatic_refresh();
2148 static void register_set_contact(osip_message_t *msg, const char *contact){
2149 osip_uri_param_t *param = NULL;
2150 osip_contact_t *ct=NULL;
2152 /*we get the line parameter choosed by exosip, and add it to our own contact*/
2153 osip_message_get_contact(msg,0,&ct);
2155 osip_uri_uparam_get_byname(ct->url, "line", ¶m);
2156 if (param && param->gvalue)
2157 line=osip_strdup(param->gvalue);
2159 _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free);
2160 osip_message_set_contact(msg,contact);
2161 osip_message_get_contact(msg,0,&ct);
2162 osip_uri_uparam_add(ct->url,osip_strdup("line"),line);
2165 static void sal_register_add_route(osip_message_t *msg, const char *proxy){
2167 snprintf(tmp,sizeof(tmp)-1,"<%s;lr>",proxy);
2169 osip_list_special_free(&msg->routes,(void (*)(void*))osip_route_free);
2170 osip_message_set_route(msg,tmp);
2173 int sal_register(SalOp *h, const char *proxy, const char *from, int expires){
2174 osip_message_t *msg;
2175 const char *contact=sal_op_get_contact(h);
2177 sal_op_set_route(h,proxy);
2179 SalAddress *from_parsed=sal_address_new(from);
2181 if (from_parsed==NULL) {
2182 ms_warning("sal_register() bad from %s",from);
2185 snprintf(domain,sizeof(domain),"sip:%s",sal_address_get_domain(from_parsed));
2186 sal_address_destroy(from_parsed);
2188 h->rid=eXosip_register_build_initial_register(from,domain,NULL,expires,&msg);
2190 if (contact) register_set_contact(msg,contact);
2191 sal_register_add_route(msg,proxy);
2192 sal_add_register(h->base.root,h);
2194 ms_error("Could not build initial register.");
2200 eXosip_register_build_register(h->rid,expires,&msg);
2201 sal_register_add_route(msg,proxy);
2204 eXosip_register_send_register(h->rid,msg);
2207 return (msg != NULL) ? 0 : -1;
2210 int sal_register_refresh(SalOp *op, int expires){
2211 osip_message_t *msg=NULL;
2212 const char *contact=sal_op_get_contact(op);
2215 ms_error("Unexistant registration context, not possible to refresh.");
2219 eXosip_register_build_register(op->rid,expires,&msg);
2221 if (contact) register_set_contact(msg,contact);
2222 sal_register_add_route(msg,sal_op_get_route(op));
2223 eXosip_register_send_register(op->rid,msg);
2224 }else ms_error("Could not build REGISTER refresh message.");
2226 return (msg != NULL) ? 0 : -1;
2230 int sal_unregister(SalOp *h){
2231 osip_message_t *msg=NULL;
2233 eXosip_register_build_register(h->rid,0,&msg);
2234 if (msg) eXosip_register_send_register(h->rid,msg);
2235 else ms_warning("Could not build unREGISTER !");
2240 SalAddress * sal_address_new(const char *uri){
2242 osip_from_init(&from);
2244 // Remove front spaces
2245 while (uri[0]==' ') {
2249 if (osip_from_parse(from,uri)!=0){
2250 osip_from_free(from);
2253 if (from->displayname!=NULL && from->displayname[0]=='"'){
2254 char *unquoted=osip_strdup_without_quote(from->displayname);
2255 osip_free(from->displayname);
2256 from->displayname=unquoted;
2258 return (SalAddress*)from;
2261 SalAddress * sal_address_clone(const SalAddress *addr){
2262 osip_from_t *ret=NULL;
2263 osip_from_clone((osip_from_t*)addr,&ret);
2264 return (SalAddress*)ret;
2267 #define null_if_empty(s) (((s)!=NULL && (s)[0]!='\0') ? (s) : NULL )
2269 const char *sal_address_get_scheme(const SalAddress *addr){
2270 const osip_from_t *u=(const osip_from_t*)addr;
2271 return null_if_empty(u->url->scheme);
2274 const char *sal_address_get_display_name(const SalAddress* addr){
2275 const osip_from_t *u=(const osip_from_t*)addr;
2276 return null_if_empty(u->displayname);
2279 const char *sal_address_get_username(const SalAddress *addr){
2280 const osip_from_t *u=(const osip_from_t*)addr;
2281 return null_if_empty(u->url->username);
2284 const char *sal_address_get_domain(const SalAddress *addr){
2285 const osip_from_t *u=(const osip_from_t*)addr;
2286 return null_if_empty(u->url->host);
2289 void sal_address_set_display_name(SalAddress *addr, const char *display_name){
2290 osip_from_t *u=(osip_from_t*)addr;
2291 if (u->displayname!=NULL){
2292 osip_free(u->displayname);
2293 u->displayname=NULL;
2295 if (display_name!=NULL && display_name[0]!='\0'){
2296 u->displayname=osip_strdup(display_name);
2300 void sal_address_set_username(SalAddress *addr, const char *username){
2301 osip_from_t *uri=(osip_from_t*)addr;
2302 if (uri->url->username!=NULL){
2303 osip_free(uri->url->username);
2304 uri->url->username=NULL;
2307 uri->url->username=osip_strdup(username);
2310 void sal_address_set_domain(SalAddress *addr, const char *host){
2311 osip_from_t *uri=(osip_from_t*)addr;
2312 if (uri->url->host!=NULL){
2313 osip_free(uri->url->host);
2314 uri->url->host=NULL;
2317 uri->url->host=osip_strdup(host);
2320 void sal_address_set_port(SalAddress *addr, const char *port){
2321 osip_from_t *uri=(osip_from_t*)addr;
2322 if (uri->url->port!=NULL){
2323 osip_free(uri->url->port);
2324 uri->url->port=NULL;
2327 uri->url->port=osip_strdup(port);
2330 void sal_address_set_port_int(SalAddress *uri, int port){
2333 /*this is the default, special case to leave the port field blank*/
2334 sal_address_set_port(uri,NULL);
2337 snprintf(tmp,sizeof(tmp),"%i",port);
2338 sal_address_set_port(uri,tmp);
2341 void sal_address_clean(SalAddress *addr){
2342 osip_generic_param_freelist(& ((osip_from_t*)addr)->gen_params);
2343 osip_uri_param_freelist(& ((osip_from_t*)addr)->url->url_params);
2346 char *sal_address_as_string(const SalAddress *u){
2348 osip_from_t *from=(osip_from_t *)u;
2349 char *old_displayname=NULL;
2350 /* hack to force use of quotes around the displayname*/
2351 if (from->displayname!=NULL
2352 && from->displayname[0]!='"'){
2353 old_displayname=from->displayname;
2354 from->displayname=osip_enquote(from->displayname);
2356 osip_from_to_str(from,&tmp);
2357 if (old_displayname!=NULL){
2358 ms_free(from->displayname);
2359 from->displayname=old_displayname;
2366 char *sal_address_as_string_uri_only(const SalAddress *u){
2367 char *tmp=NULL,*ret;
2368 osip_uri_to_str(((osip_from_t*)u)->url,&tmp);
2373 void sal_address_set_param(SalAddress *u,const char* name,const char* value) {
2374 osip_uri_param_t *param=NULL;
2375 osip_uri_uparam_get_byname(((osip_from_t*)u)->url,(char*)name,¶m);
2377 osip_uri_uparam_add (((osip_from_t*)u)->url,ms_strdup(name),value ? ms_strdup(value) : NULL);
2379 osip_free(param->gvalue);
2380 param->gvalue=value ? osip_strdup(value) : NULL;
2385 void sal_address_destroy(SalAddress *u){
2386 osip_from_free((osip_from_t*)u);
2389 void sal_set_keepalive_period(Sal *ctx,unsigned int value) {
2390 ctx->keepalive_period=value;
2391 eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE, &value);
2393 unsigned int sal_get_keepalive_period(Sal *ctx) {
2394 return ctx->keepalive_period;
2397 const char * sal_address_get_port(const SalAddress *addr) {
2398 const osip_from_t *u=(const osip_from_t*)addr;
2399 return null_if_empty(u->url->port);
2402 int sal_address_get_port_int(const SalAddress *uri) {
2403 const char* port = sal_address_get_port(uri);
2410 SalTransport sal_address_get_transport(const SalAddress* addr) {
2411 const osip_from_t *u=(const osip_from_t*)addr;
2412 osip_uri_param_t *transport_param=NULL;
2413 osip_uri_uparam_get_byname(u->url,"transport",&transport_param);
2414 if (transport_param == NULL){
2415 return SalTransportUDP;
2417 return sal_transport_parse(transport_param->gvalue);
2420 void sal_address_set_transport(SalAddress* addr,SalTransport transport) {
2421 sal_address_set_param(addr, "transport", sal_transport_to_string(transport));
2424 /* sends a reinvite. Local media description may have changed by application since call establishment*/
2425 int sal_call_update(SalOp *h, const char *subject){
2427 osip_message_t *reinvite=NULL;
2430 if(eXosip_call_build_request(h->did,"INVITE",&reinvite) != 0 || reinvite==NULL){
2435 osip_message_set_subject(reinvite,subject);
2436 osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
2437 if (h->base.contact){
2438 _osip_list_set_empty(&reinvite->contacts,(void (*)(void*))osip_contact_free);
2439 osip_message_set_contact(reinvite,h->base.contact);
2441 if (h->base.root->session_expires!=0){
2442 osip_message_set_header(reinvite, "Session-expires", "200");
2443 osip_message_set_supported(reinvite, "timer");
2445 if (h->base.local_media){
2446 h->sdp_offering=TRUE;
2447 set_sdp_from_desc(reinvite,h->base.local_media);
2448 }else h->sdp_offering=FALSE;
2450 err = eXosip_call_send_request(h->did, reinvite);
2454 void sal_reuse_authorization(Sal *ctx, bool_t value) {
2455 ctx->reuse_authorization=value;