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.
20 #include "sal_eXosip2.h"
22 #include "offeranswer.h"
24 void sal_get_default_local_ip(Sal *sal, int address_family,char *ip, size_t iplen){
25 if (eXosip_guess_localip(address_family,ip,iplen)<0){
26 /*default to something */
27 strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen);
28 ms_error("Could not find default routable ip address !");
32 static SalOp * sal_find_register(Sal *sal, int rid){
35 for(elem=sal->registers;elem!=NULL;elem=elem->next){
36 op=(SalOp*)elem->data;
37 if (op->rid==rid) return op;
42 static void sal_add_register(Sal *sal, SalOp *op){
43 sal->registers=ms_list_append(sal->registers,op);
46 static void sal_remove_register(Sal *sal, int rid){
49 for(elem=sal->registers;elem!=NULL;elem=elem->next){
50 op=(SalOp*)elem->data;
52 sal->registers=ms_list_remove_link(sal->registers,elem);
58 SalOp * sal_op_new(Sal *sal){
59 SalOp *op=ms_new(SalOp,1);
60 __sal_op_init(op,sal);
61 op->cid=op->did=op->tid=op->rid=op->nid=op->sid-1;
62 op->supports_session_timers=FALSE;
63 op->sdp_offering=TRUE;
64 op->pending_auth=NULL;
70 void sal_op_release(SalOp *op){
72 sdp_message_free(op->sdp_answer);
74 eXosip_event_free(op->pending_auth);
76 sal_remove_register(op->base.root,op->rid);
79 eXosip_call_set_reference(op->cid,NULL);
84 static void _osip_trace_func(char *fi, int li, osip_trace_level_t level, char *chfr, va_list ap){
85 int ortp_level=ORTP_DEBUG;
91 ortp_level=ORTP_MESSAGE;
94 ortp_level=ORTP_WARNING;
98 ortp_level=ORTP_ERROR;
101 ortp_level=ORTP_FATAL;
103 case END_TRACE_LEVEL:
106 if (ortp_log_level_enabled(level)){
107 int len=strlen(chfr);
108 char *chfrdup=ortp_strdup(chfr);
109 /*need to remove endline*/
111 if (chfrdup[len-1]=='\n')
113 if (chfrdup[len-2]=='\r')
116 ortp_logv(ortp_level,chfrdup,ap);
123 static bool_t firsttime=TRUE;
125 osip_trace_initialize_func (OSIP_INFO4,&_osip_trace_func);
129 return ms_new0(Sal,1);
132 void sal_uninit(Sal* sal){
137 void sal_set_user_pointer(Sal *sal, void *user_data){
141 void *sal_get_user_pointer(const Sal *sal){
145 void sal_masquerade(Sal *ctx, const char *ip){
146 eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,ip);
149 static void unimplemented_stub(){
150 ms_warning("Unimplemented SAL callback");
153 void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
154 memcpy(&ctx->callbacks,cbs,sizeof(*cbs));
155 if (ctx->callbacks.call_received==NULL)
156 ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub;
157 if (ctx->callbacks.call_ringing==NULL)
158 ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub;
159 if (ctx->callbacks.call_accepted==NULL)
160 ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub;
161 if (ctx->callbacks.call_failure==NULL)
162 ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
163 if (ctx->callbacks.call_terminated==NULL)
164 ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
165 if (ctx->callbacks.call_updated==NULL)
166 ctx->callbacks.call_updated=(SalOnCallUpdated)unimplemented_stub;
167 if (ctx->callbacks.auth_requested==NULL)
168 ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
169 if (ctx->callbacks.auth_success==NULL)
170 ctx->callbacks.auth_success=(SalOnAuthSuccess)unimplemented_stub;
171 if (ctx->callbacks.register_success==NULL)
172 ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub;
173 if (ctx->callbacks.register_failure==NULL)
174 ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
175 if (ctx->callbacks.dtmf_received==NULL)
176 ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
177 if (ctx->callbacks.presence_changed==NULL)
178 ctx->callbacks.presence_changed=(SalOnPresenceChanged)unimplemented_stub;
179 if (ctx->callbacks.subscribe_received==NULL)
180 ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
181 if (ctx->callbacks.text_received==NULL)
182 ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
183 if (ctx->callbacks.internal_message==NULL)
184 ctx->callbacks.internal_message=(SalOnInternalMsg)unimplemented_stub;
187 int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure){
190 int proto=IPPROTO_UDP;
192 if (ctx->running) eXosip_quit();
195 eXosip_set_option(13,&err); /*13=EXOSIP_OPT_SRV_WITH_NAPTR, as it is an enum value, we can't use it unless we are sure of the
196 version of eXosip, which is not the case*/
197 /*see if it looks like an IPv6 address*/
198 ipv6=strchr(addr,':')!=NULL;
199 eXosip_enable_ipv6(ipv6);
201 if (tr!=SalTransportDatagram || is_secure){
202 ms_fatal("SIP over TCP or TLS or DTLS is not supported yet.");
206 err=eXosip_listen_addr(proto, addr, port, ipv6 ? PF_INET6 : PF_INET, 0);
210 void sal_set_user_agent(Sal *ctx, const char *user_agent){
211 eXosip_set_user_agent(user_agent);
214 void sal_use_session_timers(Sal *ctx, int expires){
215 ctx->session_expires=expires;
219 static void set_sdp(osip_message_t *sip,sdp_message_t *msg){
223 sdp_message_to_str(msg,&sdp);
225 snprintf(clen,sizeof(clen),"%i",sdplen);
226 osip_message_set_body(sip,sdp,sdplen);
227 osip_message_set_content_type(sip,"application/sdp");
228 osip_message_set_content_length(sip,clen);
232 static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *desc){
233 sdp_message_t *msg=media_description_to_sdp(desc);
235 ms_error("Fail to print sdp message !");
239 sdp_message_free(msg);
242 static void sdp_process(SalOp *h){
244 sal_media_description_unref(h->result);
246 h->result=sal_media_description_new();
247 if (h->sdp_offering){
248 offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result);
251 offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result);
252 h->sdp_answer=media_description_to_sdp(h->result);
253 strcpy(h->result->addr,h->base.remote_media->addr);
254 for(i=0;i<h->result->nstreams;++i){
255 if (h->result->streams[i].port>0){
256 strcpy(h->result->streams[i].addr,h->base.remote_media->streams[i].addr);
257 h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
258 h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
259 h->result->streams[i].port=h->base.remote_media->streams[i].port;
266 int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc){
268 sal_media_description_ref(desc);
269 if (h->base.local_media)
270 sal_media_description_unref(h->base.local_media);
271 h->base.local_media=desc;
275 int sal_call(SalOp *h, const char *from, const char *to){
277 osip_message_t *invite=NULL;
278 sal_op_set_from(h,from);
280 err=eXosip_call_build_initial_invite(&invite,to,from,h->base.route,"Phone call");
282 ms_error("Could not create call.");
286 osip_message_set_contact(invite,h->base.contact);
287 if (h->base.root->session_expires!=0){
288 osip_message_set_header(invite, "Session-expires", "200");
289 osip_message_set_supported(invite, "timer");
291 if (h->base.local_media){
292 h->sdp_offering=TRUE;
293 set_sdp_from_desc(invite,h->base.local_media);
294 }else h->sdp_offering=FALSE;
296 err=eXosip_call_send_initial_invite(invite);
300 ms_error("Fail to send invite !");
303 eXosip_call_set_reference(h->cid,h);
308 int sal_call_notify_ringing(SalOp *h){
310 eXosip_call_send_answer(h->tid,180,NULL);
315 int sal_call_accept(SalOp * h){
317 const char *contact=sal_op_get_contact(h);
319 int err=eXosip_call_build_answer(h->tid,200,&msg);
320 if (err<0 || msg==NULL){
321 ms_error("Fail to build answer for call: err=%i",err);
324 if (h->base.root->session_expires!=0){
325 if (h->supports_session_timers) osip_message_set_supported(msg, "timer");
328 if (contact) osip_message_set_contact(msg,contact);
330 if (h->base.local_media){
331 /*this is the case where we received an invite without SDP*/
332 if (h->sdp_offering) {
333 set_sdp_from_desc(msg,h->base.local_media);
336 set_sdp(msg,h->sdp_answer);
339 ms_error("You are accepting a call but not defined any media capabilities !");
341 eXosip_call_send_answer(h->tid,200,msg);
345 int sal_call_decline(SalOp *h, SalReason reason, const char *redirect){
346 if (reason==SalReasonBusy){
348 eXosip_call_send_answer(h->tid,486,NULL);
351 else if (reason==SalReasonTemporarilyUnavailable){
353 eXosip_call_send_answer(h->tid,480,NULL);
355 }else if (reason==SalReasonDoNotDisturb){
357 eXosip_call_send_answer(h->tid,600,NULL);
359 }else if (reason==SalReasonMedia){
361 eXosip_call_send_answer(h->tid,415,NULL);
363 }else if (redirect!=NULL && reason==SalReasonRedirect){
366 if (strstr(redirect,"sip:")!=0) code=302;
369 eXosip_call_build_answer(h->tid,code,&msg);
370 osip_message_set_contact(msg,redirect);
371 eXosip_call_send_answer(h->tid,code,msg);
373 }else sal_call_terminate(h);
377 SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
378 if (h->base.local_media && h->base.remote_media && !h->result){
384 int sal_refer(SalOp *h, const char *refer_to){
385 osip_message_t *msg=NULL;
388 eXosip_call_build_refer(h->did,refer_to, &msg);
389 if (msg) err=eXosip_call_send_request(h->did, msg);
395 int sal_call_send_dtmf(SalOp *h, char dtmf){
396 osip_message_t *msg=NULL;
401 eXosip_call_build_info(h->did,&msg);
403 snprintf(dtmf_body, sizeof(dtmf_body), "Signal=%c\r\nDuration=250\r\n", dtmf);
404 osip_message_set_body(msg,dtmf_body,strlen(dtmf_body));
405 osip_message_set_content_type(msg,"application/dtmf-relay");
406 snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(dtmf_body));
407 osip_message_set_content_length(msg,clen);
408 eXosip_call_send_request(h->did,msg);
414 int sal_call_terminate(SalOp *h){
416 eXosip_call_terminate(h->cid,h->did);
417 eXosip_call_set_reference(h->cid,NULL);
422 void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){
423 if (h->pending_auth){
425 if (info->userid==NULL || info->userid[0]=='\0') userid=info->username;
426 else userid=info->userid;
428 eXosip_add_authentication_info (info->username,userid,
429 info->password, NULL,info->realm);
430 eXosip_default_action(h->pending_auth);
432 eXosip_event_free(h->pending_auth);
433 h->pending_auth=NULL;
437 static void inc_new_call(Sal *sal, eXosip_event_t *ev){
438 SalOp *op=sal_op_new(sal);
439 osip_from_t *from,*to;
441 sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
443 op->base.remote_media=sal_media_description_new();
444 sdp_to_media_description(sdp,op->base.remote_media);
445 sdp_message_free(sdp);
446 }else op->sdp_offering=TRUE;
448 from=osip_message_get_from(ev->request);
449 to=osip_message_get_to(ev->request);
450 osip_from_to_str(from,&tmp);
451 sal_op_set_from(op,tmp);
453 osip_from_to_str(to,&tmp);
454 sal_op_set_to(op,tmp);
461 eXosip_call_set_reference(op->cid,op);
462 sal->callbacks.call_received(op);
465 static void handle_reinvite(Sal *sal, eXosip_event_t *ev){
466 SalOp *op=(SalOp*)ev->external_reference;
468 osip_message_t *msg=NULL;
471 ms_warning("Reinvite for non-existing operation !");
476 sdp=eXosip_get_sdp_info(ev->request);
477 if (op->base.remote_media){
478 sal_media_description_unref(op->base.remote_media);
479 op->base.remote_media=NULL;
482 eXosip_call_build_answer(ev->tid,200,&msg);
484 if (msg==NULL) return;
485 if (op->base.root->session_expires!=0){
486 if (op->supports_session_timers) osip_message_set_supported(msg, "timer");
489 op->sdp_offering=FALSE;
490 op->base.remote_media=sal_media_description_new();
491 sdp_to_media_description(sdp,op->base.remote_media);
492 sdp_message_free(sdp);
494 set_sdp(msg,op->sdp_answer);
496 op->sdp_offering=TRUE;
497 set_sdp_from_desc(msg,op->base.local_media);
500 eXosip_call_send_answer(ev->tid,200,msg);
504 static void handle_ack(Sal *sal, eXosip_event_t *ev){
505 SalOp *op=(SalOp*)ev->external_reference;
509 ms_warning("ack for non-existing call !");
512 sdp=eXosip_get_sdp_info(ev->ack);
514 op->base.remote_media=sal_media_description_new();
515 sdp_to_media_description(sdp,op->base.remote_media);
517 sdp_message_free(sdp);
520 sal->callbacks.call_updated(op);
523 sal->callbacks.call_ack(op);
527 static int call_proceeding(Sal *sal, eXosip_event_t *ev){
528 SalOp *op=(SalOp*)ev->external_reference;
530 ms_warning("This call has been canceled.");
532 eXosip_call_terminate(ev->cid,ev->did);
541 static void call_ringing(Sal *sal, eXosip_event_t *ev){
544 if (call_proceeding(sal, ev)==-1) return;
545 op=(SalOp*)ev->external_reference;
546 sdp=eXosip_get_sdp_info(ev->response);
548 op->base.remote_media=sal_media_description_new();
549 sdp_to_media_description(sdp,op->base.remote_media);
550 sdp_message_free(sdp);
551 if (op->base.local_media) sdp_process(op);
553 sal->callbacks.call_ringing(op);
556 static void call_accepted(Sal *sal, eXosip_event_t *ev){
558 osip_message_t *msg=NULL;
560 op=(SalOp*)ev->external_reference;
562 ms_error("A closed call is accepted ?");
565 sdp=eXosip_get_sdp_info(ev->response);
567 op->base.remote_media=sal_media_description_new();
568 sdp_to_media_description(sdp,op->base.remote_media);
569 sdp_message_free(sdp);
570 if (op->base.local_media) sdp_process(op);
572 eXosip_call_build_ack(ev->did,&msg);
574 set_sdp(msg,op->sdp_answer);
575 eXosip_call_send_ack(ev->did,msg);
576 sal->callbacks.call_accepted(op);
579 static void call_terminated(Sal *sal, eXosip_event_t *ev){
582 op=(SalOp*)ev->external_reference;
584 ms_warning("Call terminated for already closed call ?");
587 osip_from_to_str(ev->request->from,&from);
588 eXosip_call_set_reference(ev->cid,NULL);
590 sal->callbacks.call_terminated(op,from);
594 static void call_released(Sal *sal, eXosip_event_t *ev){
596 op=(SalOp*)ev->external_reference;
600 eXosip_call_set_reference(ev->cid,NULL);
601 /*sal->callbacks.call_terminated(op);*/
604 static int get_auth_data(eXosip_event_t *ev, const char **realm, const char **username){
605 const char *prx_realm=NULL,*www_realm=NULL;
606 osip_proxy_authenticate_t *prx_auth;
607 osip_www_authenticate_t *www_auth;
608 osip_message_t *resp=ev->response;
610 *username=osip_uri_get_username(resp->from->url);
611 prx_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->proxy_authenticates,0);
612 www_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->www_authenticates,0);
614 prx_realm=osip_proxy_authenticate_get_realm(prx_auth);
616 www_realm=osip_www_authenticate_get_realm(www_auth);
620 }else if (www_realm){
628 static bool_t process_authentication(Sal *sal, eXosip_event_t *ev){
630 const char *username,*realm;
631 op=(SalOp*)ev->external_reference;
633 ms_warning("No operation associated with this authentication !");
636 if (get_auth_data(ev,&realm,&username)==0){
637 if (op->pending_auth!=NULL)
638 eXosip_event_free(op->pending_auth);
640 sal->callbacks.auth_requested(op,realm,username);
646 static void authentication_ok(Sal *sal, eXosip_event_t *ev){
648 const char *username,*realm;
649 op=(SalOp*)ev->external_reference;
651 ms_warning("No operation associated with this authentication_ok!");
654 if (get_auth_data(ev,&realm,&username)==0){
655 sal->callbacks.auth_success(op,realm,username);
659 static bool_t call_failure(Sal *sal, eXosip_event_t *ev){
662 const char *reason=NULL;
663 SalError error=SalErrorUnknown;
664 SalReason sr=SalReasonUnknown;
666 op=(SalOp*)ev->external_reference;
669 ms_warning("Call failure reported for a closed call, ignored.");
674 code=osip_message_get_status_code(ev->response);
675 reason=osip_message_get_reason_phrase(ev->response);
681 return process_authentication(sal,ev);
684 error=SalErrorUnknown;
687 error=SalErrorFailure;
688 sr=SalReasonNotFound;
691 error=SalErrorFailure;
695 eXosip_default_action(ev);
699 error=SalErrorFailure;
700 sr=SalReasonTemporarilyUnavailable;
702 error=SalErrorFailure;
708 error=SalErrorFailure;
709 sr=SalReasonDoNotDisturb;
712 error=SalErrorFailure;
713 sr=SalReasonDeclined;
717 error=SalErrorFailure;
719 }else error=SalErrorNoResponse;
721 if (code!=487) sal->callbacks.call_failure(op,error,sr,reason);
726 static void process_media_control_xml(Sal *sal, eXosip_event_t *ev){
727 SalOp *op=(SalOp*)ev->external_reference;
728 osip_body_t *body=NULL;
731 ms_warning("media control xml received without operation context!");
735 osip_message_get_body(ev->request,0,&body);
736 if (body && body->body!=NULL &&
737 strstr(body->body,"picture_fast_update")){
738 osip_message_t *ans=NULL;
739 ms_message("Receiving VFU request !");
740 if (sal->callbacks.vfu_request){
741 sal->callbacks.vfu_request(op);
742 eXosip_call_build_answer(ev->tid,200,&ans);
744 eXosip_call_send_answer(ev->tid,200,ans);
749 static void process_dtmf_relay(Sal *sal, eXosip_event_t *ev){
750 SalOp *op=(SalOp*)ev->external_reference;
751 osip_body_t *body=NULL;
754 ms_warning("media dtmf relay received without operation context!");
758 osip_message_get_body(ev->request,0,&body);
759 if (body && body->body!=NULL){
760 osip_message_t *ans=NULL;
761 const char *name=strstr(body->body,"Signal");
762 if (name==NULL) name=strstr(body->body,"signal");
764 ms_warning("Could not extract the dtmf name from the SIP INFO.");
767 name+=strlen("signal");
768 if (sscanf(name," = %1s",tmp)==1){
769 ms_message("Receiving dtmf %s via SIP INFO.",tmp);
770 if (sal->callbacks.dtmf_received != NULL)
771 sal->callbacks.dtmf_received(op, tmp[0]);
774 eXosip_call_build_answer(ev->tid,200,&ans);
776 eXosip_call_send_answer(ev->tid,200,ans);
780 static void call_message_new(Sal *sal, eXosip_event_t *ev){
781 osip_message_t *ans=NULL;
783 if (MSG_IS_INFO(ev->request)){
784 osip_content_type_t *ct;
785 ct=osip_message_get_content_type(ev->request);
786 if (ct && ct->subtype){
787 if (strcmp(ct->subtype,"media_control+xml")==0)
788 process_media_control_xml(sal,ev);
789 else if (strcmp(ct->subtype,"dtmf-relay")==0)
790 process_dtmf_relay(sal,ev);
792 ms_message("Unhandled SIP INFO.");
793 /*send an "Not implemented" answer*/
795 eXosip_call_build_answer(ev->tid,501,&ans);
797 eXosip_call_send_answer(ev->tid,501,ans);
801 /*empty SIP INFO, probably to test we are alive. Send an empty answer*/
803 eXosip_call_build_answer(ev->tid,200,&ans);
805 eXosip_call_send_answer(ev->tid,200,ans);
809 }else ms_warning("call_message_new: No request ?");
812 static void inc_update(Sal *sal, eXosip_event_t *ev){
813 osip_message_t *msg=NULL;
814 ms_message("Processing incoming UPDATE");
816 eXosip_message_build_answer(ev->tid,200,&msg);
818 eXosip_message_send_answer(ev->tid,200,msg);
822 static bool_t comes_from_local_if(osip_message_t *msg){
823 osip_via_t *via=NULL;
824 osip_message_get_via(msg,0,&via);
827 host=osip_via_get_host(via);
828 if (strcmp(host,"127.0.0.1")==0 || strcmp(host,"::1")==0){
829 osip_generic_param_t *param=NULL;
830 osip_via_param_get_byname(via,"received",¶m);
831 if (param==NULL) return TRUE;
833 (strcmp(param->gvalue,"127.0.0.1")==0 || strcmp(param->gvalue,"::1")==0)){
841 static void text_received(Sal *sal, eXosip_event_t *ev){
842 osip_body_t *body=NULL;
843 char *from=NULL,*msg;
845 osip_message_get_body(ev->request,0,&body);
847 ms_error("Could not get text message from SIP body");
851 osip_from_to_str(ev->request->from,&from);
852 sal->callbacks.text_received(sal,from,msg);
856 static void other_request(Sal *sal, eXosip_event_t *ev){
857 ms_message("in other_request");
858 if (ev->request==NULL) return;
859 if (strcmp(ev->request->sip_method,"MESSAGE")==0){
860 text_received(sal,ev);
861 eXosip_message_send_answer(ev->tid,200,NULL);
862 }else if (strcmp(ev->request->sip_method,"OPTIONS")==0){
863 osip_message_t *options=NULL;
864 eXosip_options_build_answer(ev->tid,200,&options);
865 osip_message_set_allow(options,"INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, SUBSCRIBE, NOTIFY, INFO");
866 osip_message_set_accept(options,"application/sdp");
867 eXosip_options_send_answer(ev->tid,200,options);
868 }else if (strcmp(ev->request->sip_method,"WAKEUP")==0
869 && comes_from_local_if(ev->request)) {
870 eXosip_message_send_answer(ev->tid,200,NULL);
871 ms_message("Receiving WAKEUP request !");
872 sal->callbacks.internal_message(sal,"WAKEUP");
873 }else if (strncmp(ev->request->sip_method, "REFER", 5) == 0){
874 ms_message("Receiving REFER request !");
875 if (comes_from_local_if(ev->request)) {
876 osip_header_t *h=NULL;
877 osip_message_header_get_byname(ev->request,"Refer-To",0,&h);
878 eXosip_message_send_answer(ev->tid,200,NULL);
880 sal->callbacks.refer_received(sal,NULL,h->hvalue);
882 }else ms_warning("Ignored REFER not coming from this local loopback interface.");
883 }else if (strncmp(ev->request->sip_method, "UPDATE", 6) == 0){
888 osip_message_to_str(ev->request,&tmp,&msglen);
890 ms_message("Unsupported request received:\n%s",tmp);
893 /*answer with a 501 Not implemented*/
894 eXosip_message_send_answer(ev->tid,501,NULL);
898 static void update_contact(SalOp *op, const char *received, const char *rport){
899 SalAddress *addr=sal_address_new(sal_op_get_contact(op));
901 sal_address_set_domain(addr,received);
902 sal_address_set_port(addr,rport);
903 tmp=sal_address_as_string(addr);
904 sal_op_set_contact(op,tmp);
908 static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *orig_request, osip_message_t *last_answer){
910 const char *rport,*received;
911 osip_via_t *via=NULL;
912 osip_generic_param_t *param=NULL;
913 osip_contact_t *ctt=NULL;
914 osip_message_get_via(last_answer,0,&via);
915 if (!via) return FALSE;
916 osip_via_param_get_byname(via,"rport",¶m);
917 if (param) rport=param->gvalue;
920 osip_via_param_get_byname(via,"received",¶m);
921 if (param) received=param->gvalue;
923 osip_message_get_contact(orig_request,0,&ctt);
924 if (strcmp(ctt->url->host,received)==0){
925 /*ip address matches, check ports*/
926 const char *contact_port=ctt->url->port;
927 const char *via_rport=rport;
928 if (via_rport==NULL || strlen(via_rport)>0)
930 if (contact_port==NULL || strlen(contact_port)>0)
932 if (strcmp(contact_port,via_rport)==0){
933 ms_message("Register has up to date contact, doing nothing.");
935 }else ms_message("ports do not match, need to update the register (%s <> %s)", contact_port,via_rport);
939 eXosip_register_build_register(op->rid,op->expires,&msg);
942 ms_warning("Fail to create a contact updated register.");
945 osip_message_get_contact(msg,0,&ctt);
946 if (ctt->url->host!=NULL){
947 osip_free(ctt->url->host);
949 ctt->url->host=osip_strdup(received);
950 if (ctt->url->port!=NULL){
951 osip_free(ctt->url->port);
953 ctt->url->port=osip_strdup(rport);
954 eXosip_register_send_register(op->rid,msg);
956 update_contact(op,received,rport);
957 ms_message("Resending new register with updated contact %s:%s",received,rport);
961 static void registration_success(Sal *sal, eXosip_event_t *ev){
962 SalOp *op=sal_find_register(sal,ev->rid);
963 osip_header_t *h=NULL;
966 ms_error("Receiving register response for unknown operation");
969 osip_message_get_expires(ev->request,0,&h);
970 if (h!=NULL && atoi(h->hvalue)!=0){
972 if (!register_again_with_updated_contact(op,ev->request,ev->response)){
973 sal->callbacks.register_success(op,registered);
975 }else registered=FALSE;
978 static bool_t registration_failure(Sal *sal, eXosip_event_t *ev){
980 const char *reason=NULL;
981 SalOp *op=sal_find_register(sal,ev->rid);
982 SalReason sr=SalReasonUnknown;
983 SalError se=SalErrorUnknown;
986 ms_error("Receiving register failure for unknown operation");
990 status_code=osip_message_get_status_code(ev->response);
991 reason=osip_message_get_reason_phrase(ev->response);
996 return process_authentication(sal,ev);
999 /* if contact is up to date, process the failure, otherwise resend a new register with
1000 updated contact first, just in case the faillure is due to incorrect contact */
1001 if (register_again_with_updated_contact(op,ev->request,ev->response))
1002 return TRUE; /*we are retrying with an updated contact*/
1003 if (status_code==403){
1005 sr=SalReasonForbidden;
1006 }else if (status_code==0){
1007 se=SalErrorNoResponse;
1009 sal->callbacks.register_failure(op,se,sr,reason);
1014 static bool_t process_event(Sal *sal, eXosip_event_t *ev){
1016 case EXOSIP_CALL_ANSWERED:
1017 ms_message("CALL_ANSWERED\n");
1018 call_accepted(sal,ev);
1019 authentication_ok(sal,ev);
1021 case EXOSIP_CALL_CLOSED:
1022 case EXOSIP_CALL_CANCELLED:
1023 ms_message("CALL_CLOSED or CANCELLED\n");
1024 call_terminated(sal,ev);
1026 case EXOSIP_CALL_TIMEOUT:
1027 case EXOSIP_CALL_NOANSWER:
1028 ms_message("CALL_TIMEOUT or NOANSWER\n");
1029 return call_failure(sal,ev);
1031 case EXOSIP_CALL_REQUESTFAILURE:
1032 case EXOSIP_CALL_GLOBALFAILURE:
1033 case EXOSIP_CALL_SERVERFAILURE:
1034 ms_message("CALL_REQUESTFAILURE or GLOBALFAILURE or SERVERFAILURE\n");
1035 return call_failure(sal,ev);
1037 case EXOSIP_CALL_INVITE:
1038 ms_message("CALL_NEW\n");
1039 inc_new_call(sal,ev);
1041 case EXOSIP_CALL_REINVITE:
1042 handle_reinvite(sal,ev);
1044 case EXOSIP_CALL_ACK:
1045 ms_message("CALL_ACK");
1048 case EXOSIP_CALL_REDIRECTED:
1049 ms_message("CALL_REDIRECTED");
1050 eXosip_default_action(ev);
1052 case EXOSIP_CALL_PROCEEDING:
1053 ms_message("CALL_PROCEEDING");
1054 call_proceeding(sal,ev);
1056 case EXOSIP_CALL_RINGING:
1057 ms_message("CALL_RINGING");
1058 call_ringing(sal,ev);
1060 case EXOSIP_CALL_MESSAGE_NEW:
1061 ms_message("EXOSIP_CALL_MESSAGE_NEW");
1062 call_message_new(sal,ev);
1064 case EXOSIP_CALL_MESSAGE_REQUESTFAILURE:
1065 if (ev->did<0 && ev->response &&
1066 (ev->response->status_code==407 || ev->response->status_code==401)){
1067 return process_authentication(sal,ev);
1070 case EXOSIP_IN_SUBSCRIPTION_NEW:
1071 ms_message("CALL_SUBSCRIPTION_NEW ");
1072 sal_exosip_subscription_recv(sal,ev);
1074 case EXOSIP_SUBSCRIPTION_UPDATE:
1075 ms_message("CALL_SUBSCRIPTION_UPDATE");
1077 case EXOSIP_SUBSCRIPTION_NOTIFY:
1078 ms_message("CALL_SUBSCRIPTION_NOTIFY");
1079 sal_exosip_notify_recv(sal,ev);
1081 case EXOSIP_SUBSCRIPTION_ANSWERED:
1082 ms_message("EXOSIP_SUBSCRIPTION_ANSWERED, ev->sid=%i\n",ev->sid);
1083 sal_exosip_subscription_answered(sal,ev);
1085 case EXOSIP_SUBSCRIPTION_CLOSED:
1086 ms_message("EXOSIP_SUBSCRIPTION_CLOSED\n");
1087 sal_exosip_subscription_closed(sal,ev);
1089 case EXOSIP_CALL_RELEASED:
1090 ms_message("CALL_RELEASED\n");
1091 call_released(sal, ev);
1093 case EXOSIP_REGISTRATION_FAILURE:
1094 ms_message("REGISTRATION_FAILURE\n");
1095 return registration_failure(sal,ev);
1097 case EXOSIP_REGISTRATION_SUCCESS:
1098 authentication_ok(sal,ev);
1099 registration_success(sal,ev);
1101 case EXOSIP_MESSAGE_NEW:
1102 other_request(sal,ev);
1104 case EXOSIP_MESSAGE_REQUESTFAILURE:
1105 if (ev->response && (ev->response->status_code == 407 || ev->response->status_code == 401)){
1106 return process_authentication(sal,ev);
1110 ms_message("Unhandled exosip event !");
1116 int sal_iterate(Sal *sal){
1119 while((ev=eXosip_event_wait(0,0))!=NULL){
1120 if (process_event(sal,ev))
1121 eXosip_event_free(ev);
1124 eXosip_automatic_refresh();
1130 int sal_register(SalOp *h, const char *proxy, const char *from, int expires){
1131 osip_message_t *msg;
1134 h->rid=eXosip_register_build_initial_register(from,proxy,sal_op_get_contact(h),expires,&msg);
1135 sal_add_register(h->base.root,h);
1138 eXosip_register_build_register(h->rid,expires,&msg);
1140 eXosip_register_send_register(h->rid,msg);
1148 SalAddress * sal_address_new(const char *uri){
1150 osip_from_init(&from);
1151 if (osip_from_parse(from,uri)!=0){
1152 osip_from_free(from);
1155 return (SalAddress*)from;
1158 SalAddress * sal_address_clone(const SalAddress *addr){
1159 osip_from_t *ret=NULL;
1160 osip_from_clone((osip_from_t*)addr,&ret);
1161 return (SalAddress*)ret;
1164 #define null_if_empty(s) (((s)!=NULL && (s)[0]!='\0') ? (s) : NULL )
1166 const char *sal_address_get_scheme(const SalAddress *addr){
1167 const osip_from_t *u=(const osip_from_t*)addr;
1168 return null_if_empty(u->url->scheme);
1171 const char *sal_address_get_display_name(const SalAddress* addr){
1172 const osip_from_t *u=(const osip_from_t*)addr;
1173 return null_if_empty(u->displayname);
1176 const char *sal_address_get_username(const SalAddress *addr){
1177 const osip_from_t *u=(const osip_from_t*)addr;
1178 return null_if_empty(u->url->username);
1181 const char *sal_address_get_domain(const SalAddress *addr){
1182 const osip_from_t *u=(const osip_from_t*)addr;
1183 return null_if_empty(u->url->host);
1186 void sal_address_set_display_name(SalAddress *addr, const char *display_name){
1187 osip_from_t *u=(osip_from_t*)addr;
1188 if (u->displayname!=NULL){
1189 osip_free(u->displayname);
1190 u->displayname=NULL;
1192 if (display_name!=NULL)
1193 u->displayname=osip_strdup(display_name);
1196 void sal_address_set_username(SalAddress *addr, const char *username){
1197 osip_from_t *uri=(osip_from_t*)addr;
1198 if (uri->url->username!=NULL){
1199 osip_free(uri->url->username);
1200 uri->url->username=NULL;
1203 uri->url->username=osip_strdup(username);
1206 void sal_address_set_domain(SalAddress *addr, const char *host){
1207 osip_from_t *uri=(osip_from_t*)addr;
1208 if (uri->url->host!=NULL){
1209 osip_free(uri->url->host);
1210 uri->url->host=NULL;
1213 uri->url->host=osip_strdup(host);
1216 void sal_address_set_port(SalAddress *addr, const char *port){
1217 osip_from_t *uri=(osip_from_t*)addr;
1218 if (uri->url->port!=NULL){
1219 osip_free(uri->url->port);
1220 uri->url->port=NULL;
1223 uri->url->port=osip_strdup(port);
1226 void sal_address_set_port_int(SalAddress *uri, int port){
1229 /*this is the default, special case to leave the port field blank*/
1230 sal_address_set_port(uri,NULL);
1233 snprintf(tmp,sizeof(tmp),"%i",port);
1234 sal_address_set_port(uri,tmp);
1237 void sal_address_clean(SalAddress *addr){
1238 osip_generic_param_freelist(& ((osip_from_t*)addr)->gen_params);
1241 char *sal_address_as_string(const SalAddress *u){
1243 osip_from_to_str((osip_from_t*)u,&tmp);
1249 char *sal_address_as_string_uri_only(const SalAddress *u){
1250 char *tmp=NULL,*ret;
1251 osip_uri_to_str(((osip_from_t*)u)->url,&tmp);
1257 void sal_address_destroy(SalAddress *u){
1258 osip_from_free((osip_from_t*)u);