]> sjero.net Git - linphone/blob - coreapi/sal_eXosip2.c
fix authentication that wasn't marked as "working".
[linphone] / coreapi / sal_eXosip2.c
1 /*
2 linphone
3 Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19
20 #include "sal_eXosip2.h"
21
22 #include "offeranswer.h"
23
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 !");
29         }
30 }
31
32 static SalOp * sal_find_register(Sal *sal, int rid){
33         const MSList *elem;
34         SalOp *op;
35         for(elem=sal->registers;elem!=NULL;elem=elem->next){
36                 op=(SalOp*)elem->data;
37                 if (op->rid==rid) return op;
38         }
39         return NULL;
40 }
41
42 static void sal_add_register(Sal *sal, SalOp *op){
43         sal->registers=ms_list_append(sal->registers,op);
44 }
45
46 static void sal_remove_register(Sal *sal, int rid){
47         MSList *elem;
48         SalOp *op;
49         for(elem=sal->registers;elem!=NULL;elem=elem->next){
50                 op=(SalOp*)elem->data;
51                 if (op->rid==rid) {
52                         sal->registers=ms_list_remove_link(sal->registers,elem);
53                         return;
54                 }
55         }
56 }
57
58 static void sal_add_pending_auth(Sal *sal, SalOp *op){
59         sal->pending_auths=ms_list_append(sal->pending_auths,op);
60 }
61
62
63 static void sal_remove_pending_auth(Sal *sal, SalOp *op){
64         sal->pending_auths=ms_list_remove(sal->pending_auths,op);
65 }
66
67 void sal_exosip_fix_route(SalOp *op){
68         if (sal_op_get_route(op)!=NULL){
69                 osip_route_t *rt=NULL;
70                 osip_uri_param_t *lr_param=NULL;
71                 
72                 osip_route_init(&rt);
73                 if (osip_route_parse(rt,sal_op_get_route(op))<0){
74                         ms_warning("Bad route  %s!",sal_op_get_route(op));
75                         sal_op_set_route(op,NULL);
76                 }else{
77                         /* check if the lr parameter is set , if not add it */
78                         osip_uri_uparam_get_byname(rt->url, "lr", &lr_param);
79                         if (lr_param==NULL){
80                                 char *tmproute;
81                                 osip_uri_uparam_add(rt->url,osip_strdup("lr"),NULL);
82                                 osip_route_to_str(rt,&tmproute);
83                                 sal_op_set_route(op,tmproute);
84                                 osip_free(tmproute);
85                         }
86                 }
87                 osip_route_free(rt);
88         }
89 }
90
91 SalOp * sal_op_new(Sal *sal){
92         SalOp *op=ms_new(SalOp,1);
93         __sal_op_init(op,sal);
94         op->cid=op->did=op->tid=op->rid=op->nid=op->sid=-1;
95         op->result=NULL;
96         op->supports_session_timers=FALSE;
97         op->sdp_offering=TRUE;
98         op->pending_auth=NULL;
99         op->sdp_answer=NULL;
100         op->reinvite=FALSE;
101         return op;
102 }
103
104 void sal_op_release(SalOp *op){
105         if (op->sdp_answer)
106                 sdp_message_free(op->sdp_answer);
107         if (op->pending_auth)
108                 eXosip_event_free(op->pending_auth);
109         if (op->rid!=-1){
110                 sal_remove_register(op->base.root,op->rid);
111         }
112         if (op->cid!=-1){
113                 ms_message("Cleaning cid %i",op->cid);
114                 eXosip_call_set_reference(op->cid,NULL);
115         }
116         if (op->pending_auth){
117                 sal_remove_pending_auth(op->base.root,op);
118         }
119         if (op->result)
120                 sal_media_description_unref(op->result);
121         __sal_op_free(op);
122 }
123
124 static void _osip_trace_func(char *fi, int li, osip_trace_level_t level, char *chfr, va_list ap){
125         int ortp_level=ORTP_DEBUG;
126         switch(level){
127                 case OSIP_INFO1:
128                 case OSIP_INFO2:
129                 case OSIP_INFO3:
130                 case OSIP_INFO4:
131                         ortp_level=ORTP_MESSAGE;
132                         break;
133                 case OSIP_WARNING:
134                         ortp_level=ORTP_WARNING;
135                         break;
136                 case OSIP_ERROR:
137                 case OSIP_BUG:
138                         ortp_level=ORTP_ERROR;
139                         break;
140                 case OSIP_FATAL:
141                         ortp_level=ORTP_FATAL;
142                         break;
143                 case END_TRACE_LEVEL:
144                         break;
145         }
146         if (ortp_log_level_enabled(level)){
147                 int len=strlen(chfr);
148                 char *chfrdup=ortp_strdup(chfr);
149                 /*need to remove endline*/
150                 if (len>1){
151                         if (chfrdup[len-1]=='\n')
152                                 chfrdup[len-1]='\0';
153                         if (chfrdup[len-2]=='\r')
154                                 chfrdup[len-2]='\0';
155                 }
156                 ortp_logv(ortp_level,chfrdup,ap);
157                 ortp_free(chfrdup);
158         }
159 }
160
161
162 Sal * sal_init(){
163         static bool_t firsttime=TRUE;
164         if (firsttime){
165                 osip_trace_initialize_func (OSIP_INFO4,&_osip_trace_func);
166                 firsttime=FALSE;
167         }
168         eXosip_init();
169         return ms_new0(Sal,1);
170 }
171
172 void sal_uninit(Sal* sal){
173         eXosip_quit();
174         ms_free(sal);
175 }
176
177 void sal_set_user_pointer(Sal *sal, void *user_data){
178         sal->up=user_data;
179 }
180
181 void *sal_get_user_pointer(const Sal *sal){
182         return sal->up;
183 }
184
185 void sal_masquerade(Sal *ctx, const char *ip){
186         eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,ip);
187 }
188
189 static void unimplemented_stub(){
190         ms_warning("Unimplemented SAL callback");
191 }
192
193 void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
194         memcpy(&ctx->callbacks,cbs,sizeof(*cbs));
195         if (ctx->callbacks.call_received==NULL) 
196                 ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub;
197         if (ctx->callbacks.call_ringing==NULL) 
198                 ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub;
199         if (ctx->callbacks.call_accepted==NULL) 
200                 ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub;
201         if (ctx->callbacks.call_failure==NULL) 
202                 ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
203         if (ctx->callbacks.call_terminated==NULL) 
204                 ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
205         if (ctx->callbacks.call_updated==NULL) 
206                 ctx->callbacks.call_updated=(SalOnCallUpdated)unimplemented_stub;
207         if (ctx->callbacks.auth_requested==NULL) 
208                 ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
209         if (ctx->callbacks.auth_success==NULL) 
210                 ctx->callbacks.auth_success=(SalOnAuthSuccess)unimplemented_stub;
211         if (ctx->callbacks.register_success==NULL) 
212                 ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub;
213         if (ctx->callbacks.register_failure==NULL) 
214                 ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
215         if (ctx->callbacks.dtmf_received==NULL) 
216                 ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
217         if (ctx->callbacks.notify==NULL)
218                 ctx->callbacks.notify=(SalOnNotify)unimplemented_stub;
219         if (ctx->callbacks.subscribe_received==NULL)
220                 ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
221         if (ctx->callbacks.text_received==NULL)
222                 ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
223         if (ctx->callbacks.internal_message==NULL)
224                 ctx->callbacks.internal_message=(SalOnInternalMsg)unimplemented_stub;
225 }
226
227 int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure){
228         int err;
229         bool_t ipv6;
230         int proto=IPPROTO_UDP;
231         
232         if (ctx->running) eXosip_quit();
233         eXosip_init();
234         err=0;
235         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
236                                         version of eXosip, which is not the case*/
237         /*see if it looks like an IPv6 address*/
238         ipv6=strchr(addr,':')!=NULL;
239         eXosip_enable_ipv6(ipv6);
240
241         if (tr!=SalTransportDatagram || is_secure){
242                 ms_fatal("SIP over TCP or TLS or DTLS is not supported yet.");
243                 return -1;
244         }
245         
246         err=eXosip_listen_addr(proto, addr, port, ipv6 ?  PF_INET6 : PF_INET, 0);
247         return err;
248 }
249
250 void sal_set_user_agent(Sal *ctx, const char *user_agent){
251         eXosip_set_user_agent(user_agent);
252 }
253
254 void sal_use_session_timers(Sal *ctx, int expires){
255         ctx->session_expires=expires;
256 }
257
258 MSList *sal_get_pending_auths(Sal *sal){
259         return ms_list_copy(sal->pending_auths);
260 }
261
262
263 static void set_sdp(osip_message_t *sip,sdp_message_t *msg){
264         int sdplen;
265         char clen[10];
266         char *sdp=NULL;
267         sdp_message_to_str(msg,&sdp);
268         sdplen=strlen(sdp);
269         snprintf(clen,sizeof(clen),"%i",sdplen);
270         osip_message_set_body(sip,sdp,sdplen);
271         osip_message_set_content_type(sip,"application/sdp");
272         osip_message_set_content_length(sip,clen);
273         osip_free(sdp);
274 }
275
276 static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *desc){
277         sdp_message_t *msg=media_description_to_sdp(desc);
278         if (msg==NULL) {
279                 ms_error("Fail to print sdp message !");
280                 return;
281         }
282         set_sdp(sip,msg);
283         sdp_message_free(msg);
284 }
285
286 static void sdp_process(SalOp *h){
287         ms_message("Doing SDP offer/answer process");
288         if (h->result){
289                 sal_media_description_unref(h->result);
290         }
291         h->result=sal_media_description_new();
292         if (h->sdp_offering){   
293                 offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result);
294         }else{
295                 int i;
296                 offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result);
297                 h->sdp_answer=media_description_to_sdp(h->result);
298                 strcpy(h->result->addr,h->base.remote_media->addr);
299                 for(i=0;i<h->result->nstreams;++i){
300                         if (h->result->streams[i].port>0){
301                                 strcpy(h->result->streams[i].addr,h->base.remote_media->streams[i].addr);
302                                 h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
303                                 h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
304                                 h->result->streams[i].port=h->base.remote_media->streams[i].port;
305                         }
306                 }
307         }
308         
309 }
310
311 int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc){
312         if (desc)
313                 sal_media_description_ref(desc);
314         if (h->base.local_media)
315                 sal_media_description_unref(h->base.local_media);
316         h->base.local_media=desc;
317         return 0;
318 }
319
320 int sal_call(SalOp *h, const char *from, const char *to){
321         int err;
322         osip_message_t *invite=NULL;
323         sal_op_set_from(h,from);
324         sal_op_set_to(h,to);
325         sal_exosip_fix_route(h);
326         err=eXosip_call_build_initial_invite(&invite,to,from,sal_op_get_route(h),"Phone call");
327         if (err!=0){
328                 ms_error("Could not create call.");
329                 return -1;
330         }
331         if (h->base.contact){
332                 osip_list_special_free(&invite->contacts,(void (*)(void*))osip_contact_free);
333                 osip_message_set_contact(invite,h->base.contact);
334         }
335         if (h->base.root->session_expires!=0){
336                 osip_message_set_header(invite, "Session-expires", "200");
337                 osip_message_set_supported(invite, "timer");
338         }
339         if (h->base.local_media){
340                 h->sdp_offering=TRUE;
341                 set_sdp_from_desc(invite,h->base.local_media);
342         }else h->sdp_offering=FALSE;
343         eXosip_lock();
344         err=eXosip_call_send_initial_invite(invite);
345         eXosip_unlock();
346         h->cid=err;
347         if (err<0){
348                 ms_error("Fail to send invite !");
349                 return -1;
350         }else{
351                 eXosip_call_set_reference(h->cid,h);
352         }
353         return 0;
354 }
355
356 int sal_call_notify_ringing(SalOp *h){
357         eXosip_lock();
358         eXosip_call_send_answer(h->tid,180,NULL);
359         eXosip_unlock();
360         return 0;
361 }
362
363 int sal_call_accept(SalOp * h){
364         osip_message_t *msg;
365         const char *contact=sal_op_get_contact(h);
366         /* sends a 200 OK */
367         int err=eXosip_call_build_answer(h->tid,200,&msg);
368         if (err<0 || msg==NULL){
369                 ms_error("Fail to build answer for call: err=%i",err);
370                 return -1;
371         }
372         if (h->base.root->session_expires!=0){
373                 if (h->supports_session_timers) osip_message_set_supported(msg, "timer");
374         }
375
376         if (contact) {
377                 osip_list_special_free(&msg->contacts,(void (*)(void*))osip_contact_free);
378                 osip_message_set_contact(msg,contact);
379         }
380         
381         if (h->base.local_media){
382                 /*this is the case where we received an invite without SDP*/
383                 if (h->sdp_offering) {
384                         set_sdp_from_desc(msg,h->base.local_media);
385                 }else{
386                         if (h->sdp_answer)
387                                 set_sdp(msg,h->sdp_answer);
388                 }
389         }else{
390                 ms_error("You are accepting a call but not defined any media capabilities !");
391         }
392         eXosip_call_send_answer(h->tid,200,msg);
393         return 0;
394 }
395
396 int sal_call_decline(SalOp *h, SalReason reason, const char *redirect){
397         if (reason==SalReasonBusy){
398                 eXosip_lock();
399                 eXosip_call_send_answer(h->tid,486,NULL);
400                 eXosip_unlock();
401         }
402         else if (reason==SalReasonTemporarilyUnavailable){
403                 eXosip_lock();
404                 eXosip_call_send_answer(h->tid,480,NULL);
405                 eXosip_unlock();
406         }else if (reason==SalReasonDoNotDisturb){
407                 eXosip_lock();
408                 eXosip_call_send_answer(h->tid,600,NULL);
409                 eXosip_unlock();
410         }else if (reason==SalReasonMedia){
411                 eXosip_lock();
412                 eXosip_call_send_answer(h->tid,415,NULL);
413                 eXosip_unlock();
414         }else if (redirect!=NULL && reason==SalReasonRedirect){
415                 osip_message_t *msg;
416                 int code;
417                 if (strstr(redirect,"sip:")!=0) code=302;
418                 else code=380;
419                 eXosip_lock();
420                 eXosip_call_build_answer(h->tid,code,&msg);
421                 osip_message_set_contact(msg,redirect);
422                 eXosip_call_send_answer(h->tid,code,msg);
423                 eXosip_unlock();
424         }else sal_call_terminate(h);
425         return 0;
426 }
427
428 SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
429         if (h->base.local_media && h->base.remote_media && !h->result){
430                 sdp_process(h);
431         }
432         return h->result;
433 }
434
435 int sal_refer(SalOp *h, const char *refer_to){
436         osip_message_t *msg=NULL;
437         int err=0;
438         eXosip_lock();
439         eXosip_call_build_refer(h->did,refer_to, &msg);
440         if (msg) err=eXosip_call_send_request(h->did, msg);
441         else err=-1;
442         eXosip_unlock();
443         return err;
444 }
445
446 int sal_call_send_dtmf(SalOp *h, char dtmf){
447         osip_message_t *msg=NULL;
448         char dtmf_body[128];
449         char clen[10];
450
451         eXosip_lock();
452         eXosip_call_build_info(h->did,&msg);
453         if (msg){
454                 snprintf(dtmf_body, sizeof(dtmf_body), "Signal=%c\r\nDuration=250\r\n", dtmf);
455                 osip_message_set_body(msg,dtmf_body,strlen(dtmf_body));
456                 osip_message_set_content_type(msg,"application/dtmf-relay");
457                 snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(dtmf_body));
458                 osip_message_set_content_length(msg,clen);              
459                 eXosip_call_send_request(h->did,msg);
460         }
461         eXosip_unlock();
462         return 0;
463 }
464
465 int sal_call_terminate(SalOp *h){
466         eXosip_lock();
467         eXosip_call_terminate(h->cid,h->did);
468         eXosip_call_set_reference(h->cid,NULL);
469         eXosip_unlock();
470         return 0;
471 }
472
473 void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){
474         if (h->pending_auth){
475                 const char *userid;
476                 if (info->userid==NULL || info->userid[0]=='\0') userid=info->username;
477                 else userid=info->userid;
478                 ms_message("Authentication info for %s %s added to eXosip", info->username,info->realm);
479                 eXosip_add_authentication_info (info->username,userid,
480                                       info->password, NULL,info->realm);
481                 eXosip_lock();
482                 eXosip_default_action(h->pending_auth);
483                 eXosip_unlock();
484                 ms_message("eXosip_default_action() done");
485                 eXosip_clear_authentication_info();
486                 eXosip_event_free(h->pending_auth);
487                 sal_remove_pending_auth(sal_op_get_sal(h),h);
488                 h->pending_auth=NULL;
489         }
490 }
491
492 static void inc_new_call(Sal *sal, eXosip_event_t *ev){
493         SalOp *op=sal_op_new(sal);
494         osip_from_t *from,*to;
495         char *tmp;
496         sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
497         if (sdp){
498                 op->sdp_offering=FALSE;
499                 op->base.remote_media=sal_media_description_new();
500                 sdp_to_media_description(sdp,op->base.remote_media);
501                 sdp_message_free(sdp);
502         }else op->sdp_offering=TRUE;
503
504         from=osip_message_get_from(ev->request);
505         to=osip_message_get_to(ev->request);
506         osip_from_to_str(from,&tmp);
507         sal_op_set_from(op,tmp);
508         osip_free(tmp);
509         osip_from_to_str(to,&tmp);
510         sal_op_set_to(op,tmp);
511         osip_free(tmp);
512         
513         op->tid=ev->tid;
514         op->cid=ev->cid;
515         op->did=ev->did;
516         
517         eXosip_call_set_reference(op->cid,op);
518         sal->callbacks.call_received(op);
519 }
520
521 static void handle_reinvite(Sal *sal,  eXosip_event_t *ev){
522         SalOp *op=(SalOp*)ev->external_reference;
523         sdp_message_t *sdp;
524         osip_message_t *msg=NULL;
525
526         if (op==NULL) {
527                 ms_warning("Reinvite for non-existing operation !");
528                 return;
529         }
530         op->reinvite=TRUE;
531         op->tid=ev->tid;
532         sdp=eXosip_get_sdp_info(ev->request);
533         if (op->base.remote_media){
534                 sal_media_description_unref(op->base.remote_media);
535                 op->base.remote_media=NULL;
536         }
537         eXosip_lock();
538         eXosip_call_build_answer(ev->tid,200,&msg);
539         eXosip_unlock();
540         if (msg==NULL) return;
541         if (op->base.root->session_expires!=0){
542                 if (op->supports_session_timers) osip_message_set_supported(msg, "timer");
543         }
544         if (op->base.contact){
545                 osip_list_special_free(&msg->contacts,(void (*)(void*))osip_contact_free);
546                 osip_message_set_contact(msg,op->base.contact);
547         }
548         if (sdp){
549                 op->sdp_offering=FALSE;
550                 op->base.remote_media=sal_media_description_new();
551                 sdp_to_media_description(sdp,op->base.remote_media);
552                 sdp_message_free(sdp);
553                 sdp_process(op);
554                 set_sdp(msg,op->sdp_answer);
555         }else {
556                 op->sdp_offering=TRUE;
557                 set_sdp_from_desc(msg,op->base.local_media);
558         }
559         eXosip_lock();
560         eXosip_call_send_answer(ev->tid,200,msg);
561         eXosip_unlock();
562 }
563
564 static void handle_ack(Sal *sal,  eXosip_event_t *ev){
565         SalOp *op=(SalOp*)ev->external_reference;
566         sdp_message_t *sdp;
567
568         if (op==NULL) {
569                 ms_warning("ack for non-existing call !");
570                 return;
571         }
572         sdp=eXosip_get_sdp_info(ev->ack);
573         if (sdp){
574                 op->base.remote_media=sal_media_description_new();
575                 sdp_to_media_description(sdp,op->base.remote_media);
576                 sdp_process(op);
577                 sdp_message_free(sdp);
578         }
579         if (op->reinvite){
580                 sal->callbacks.call_updated(op);
581                 op->reinvite=FALSE;
582         }else{
583                 sal->callbacks.call_ack(op);
584         }
585 }
586
587 static int call_proceeding(Sal *sal, eXosip_event_t *ev){
588         SalOp *op=(SalOp*)ev->external_reference;
589         if (op==NULL) {
590                 ms_warning("This call has been canceled.");
591                 eXosip_lock();
592                 eXosip_call_terminate(ev->cid,ev->did);
593                 eXosip_unlock();
594                 return -1;
595         }
596         op->did=ev->did;
597         op->tid=ev->tid;
598         return 0;
599 }
600
601 static void call_ringing(Sal *sal, eXosip_event_t *ev){
602         sdp_message_t *sdp;
603         SalOp *op;
604         if (call_proceeding(sal, ev)==-1) return;
605         op=(SalOp*)ev->external_reference;
606         sdp=eXosip_get_sdp_info(ev->response);
607         if (sdp){
608                 op->base.remote_media=sal_media_description_new();
609                 sdp_to_media_description(sdp,op->base.remote_media);
610                 sdp_message_free(sdp);
611                 if (op->base.local_media) sdp_process(op);
612         }
613         sal->callbacks.call_ringing(op);
614 }
615
616 static void call_accepted(Sal *sal, eXosip_event_t *ev){
617         sdp_message_t *sdp;
618         osip_message_t *msg=NULL;
619         SalOp *op;
620         op=(SalOp*)ev->external_reference;
621         if (op==NULL){
622                 ms_error("A closed call is accepted ?");
623                 return;
624         }
625         sdp=eXosip_get_sdp_info(ev->response);
626         if (sdp){
627                 op->base.remote_media=sal_media_description_new();
628                 sdp_to_media_description(sdp,op->base.remote_media);
629                 sdp_message_free(sdp);
630                 if (op->base.local_media) sdp_process(op);
631         }
632         eXosip_call_build_ack(ev->did,&msg);
633         if (op->sdp_answer)
634                         set_sdp(msg,op->sdp_answer);
635         eXosip_call_send_ack(ev->did,msg);
636         sal->callbacks.call_accepted(op);
637 }
638
639 static void call_terminated(Sal *sal, eXosip_event_t *ev){
640         SalOp *op;
641         char *from;
642         op=(SalOp*)ev->external_reference;
643         if (op==NULL){
644                 ms_warning("Call terminated for already closed call ?");
645                 return;
646         }
647         osip_from_to_str(ev->request->from,&from);
648         eXosip_call_set_reference(ev->cid,NULL);
649         op->cid=-1;
650         sal->callbacks.call_terminated(op,from);
651         osip_free(from);
652 }
653
654 static void call_released(Sal *sal, eXosip_event_t *ev){
655         SalOp *op;
656         op=(SalOp*)ev->external_reference;
657         if (op==NULL){
658                 return;
659         }
660         op->cid=-1;
661         if (op->did==-1) 
662                 sal->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,NULL);
663 }
664
665 static int get_auth_data_from_response(osip_message_t *resp, const char **realm, const char **username){
666         const char *prx_realm=NULL,*www_realm=NULL;
667         osip_proxy_authenticate_t *prx_auth;
668         osip_www_authenticate_t *www_auth;
669         
670         *username=osip_uri_get_username(resp->from->url);
671         prx_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->proxy_authenticates,0);
672         www_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->www_authenticates,0);
673         if (prx_auth!=NULL)
674                 prx_realm=osip_proxy_authenticate_get_realm(prx_auth);
675         if (www_auth!=NULL)
676                 www_realm=osip_www_authenticate_get_realm(www_auth);
677
678         if (prx_realm){
679                 *realm=prx_realm;
680         }else if (www_realm){
681                 *realm=www_realm;
682         }else{
683                 return -1;
684         }
685         return 0;
686 }
687
688 static int get_auth_data_from_request(osip_message_t *msg, const char **realm, const char **username){
689         osip_authorization_t *auth=NULL;
690         osip_proxy_authorization_t *prx_auth=NULL;
691         
692         *username=osip_uri_get_username(msg->from->url);
693         osip_message_get_authorization(msg, 0, &auth);
694         if (auth){
695                 *realm=osip_authorization_get_realm(auth);
696                 return 0;
697         }
698         osip_message_get_proxy_authorization(msg,0,&prx_auth);
699         if (prx_auth){
700                 *realm=osip_proxy_authorization_get_realm(prx_auth);
701                 return 0;
702         }
703         return -1;
704 }
705
706 static int get_auth_data(eXosip_event_t *ev, const char **realm, const char **username){
707         if (ev->response && get_auth_data_from_response(ev->response,realm,username)==0) return 0;
708         if (ev->request && get_auth_data_from_request(ev->request,realm,username)==0) return 0;
709         return -1;
710 }
711
712 int sal_op_get_auth_requested(SalOp *op, const char **realm, const char **username){
713         if (op->pending_auth){
714                 return get_auth_data(op->pending_auth,realm,username);
715         }
716         return -1;
717 }
718
719 static SalOp *find_op(Sal *sal, eXosip_event_t *ev){
720         if (ev->external_reference)
721                 return (SalOp*)ev->external_reference;
722         if (ev->rid>0){
723                 return sal_find_register(sal,ev->rid);
724         }
725         return NULL;
726 }
727
728 static bool_t process_authentication(Sal *sal, eXosip_event_t *ev){
729         SalOp *op;
730         const char *username,*realm;
731         op=find_op(sal,ev);
732         if (op==NULL){
733                 ms_warning("No operation associated with this authentication !");
734                 return TRUE;
735         }
736         if (get_auth_data(ev,&realm,&username)==0){
737                 if (op->pending_auth!=NULL)
738                         eXosip_event_free(op->pending_auth);
739                 op->pending_auth=ev;
740                 sal_add_pending_auth (sal,op);
741                 sal->callbacks.auth_requested(op,realm,username);
742                 return FALSE;
743         }
744         return TRUE;
745 }
746
747 static void authentication_ok(Sal *sal, eXosip_event_t *ev){
748         SalOp *op;
749         const char *username,*realm;
750         op=find_op(sal,ev);
751         if (op==NULL){
752                 ms_warning("No operation associated with this authentication_ok!");
753                 return ;
754         }
755         if (get_auth_data(ev,&realm,&username)==0){
756                 sal->callbacks.auth_success(op,realm,username);
757         }
758 }
759
760 static bool_t call_failure(Sal *sal, eXosip_event_t *ev){
761         SalOp *op;
762         int code=0;
763         const char *reason=NULL;
764         SalError error=SalErrorUnknown;
765         SalReason sr=SalReasonUnknown;
766         
767         op=(SalOp*)ev->external_reference;
768
769         if (op==NULL) {
770                 ms_warning("Call failure reported for a closed call, ignored.");
771                 return TRUE;
772         }
773
774         if (ev->response){
775                 code=osip_message_get_status_code(ev->response);
776                 reason=osip_message_get_reason_phrase(ev->response);
777         }
778         switch(code)
779         {
780                 case 401:
781                 case 407:
782                         return process_authentication(sal,ev);
783                         break;
784                 case 400:
785                         error=SalErrorUnknown;
786                 break;
787                 case 404:
788                         error=SalErrorFailure;
789                         sr=SalReasonNotFound;
790                 break;
791                 case 415:
792                         error=SalErrorFailure;
793                         sr=SalReasonMedia;
794                 break;
795                 case 422:
796                         eXosip_default_action(ev);
797                         return TRUE;
798                 break;
799                 case 480:
800                         error=SalErrorFailure;
801                         sr=SalReasonTemporarilyUnavailable;
802                 case 486:
803                         error=SalErrorFailure;
804                         sr=SalReasonBusy;
805                 break;
806                 case 487:
807                 break;
808                 case 600:
809                         error=SalErrorFailure;
810                         sr=SalReasonDoNotDisturb;
811                 break;
812                 case 603:
813                         error=SalErrorFailure;
814                         sr=SalReasonDeclined;
815                 break;
816                 default:
817                         if (code>0){
818                                 error=SalErrorFailure;
819                                 sr=SalReasonUnknown;
820                         }else error=SalErrorNoResponse;
821         }
822         if (code!=487) sal->callbacks.call_failure(op,error,sr,reason);
823         return TRUE;
824 }
825
826
827 static void process_media_control_xml(Sal *sal, eXosip_event_t *ev){
828         SalOp *op=(SalOp*)ev->external_reference;
829         osip_body_t *body=NULL;
830
831         if (op==NULL){
832                 ms_warning("media control xml received without operation context!");
833                 return ;
834         }
835         
836         osip_message_get_body(ev->request,0,&body);
837         if (body && body->body!=NULL &&
838                 strstr(body->body,"picture_fast_update")){
839                 osip_message_t *ans=NULL;
840                 ms_message("Receiving VFU request !");
841                 if (sal->callbacks.vfu_request){
842                         sal->callbacks.vfu_request(op);
843                         eXosip_call_build_answer(ev->tid,200,&ans);
844                         if (ans)
845                                 eXosip_call_send_answer(ev->tid,200,ans);
846                 }
847         }
848 }
849
850 static void process_dtmf_relay(Sal *sal, eXosip_event_t *ev){
851         SalOp *op=(SalOp*)ev->external_reference;
852         osip_body_t *body=NULL;
853
854         if (op==NULL){
855                 ms_warning("media dtmf relay received without operation context!");
856                 return ;
857         }
858         
859         osip_message_get_body(ev->request,0,&body);
860         if (body && body->body!=NULL){
861                 osip_message_t *ans=NULL;
862                 const char *name=strstr(body->body,"Signal");
863                 if (name==NULL) name=strstr(body->body,"signal");
864                 if (name==NULL) {
865                         ms_warning("Could not extract the dtmf name from the SIP INFO.");
866                 }else{
867                         char tmp[2];
868                         name+=strlen("signal");
869                         if (sscanf(name," = %1s",tmp)==1){
870                                 ms_message("Receiving dtmf %s via SIP INFO.",tmp);
871                                 if (sal->callbacks.dtmf_received != NULL)
872                                         sal->callbacks.dtmf_received(op, tmp[0]);
873                         }
874                 }
875                 eXosip_call_build_answer(ev->tid,200,&ans);
876                 if (ans)
877                         eXosip_call_send_answer(ev->tid,200,ans);
878         }
879 }
880
881 static void call_message_new(Sal *sal, eXosip_event_t *ev){
882         osip_message_t *ans=NULL;
883         if (ev->request){
884                 if (MSG_IS_INFO(ev->request)){
885                         osip_content_type_t *ct;
886                         ct=osip_message_get_content_type(ev->request);
887                         if (ct && ct->subtype){
888                                 if (strcmp(ct->subtype,"media_control+xml")==0)
889                                         process_media_control_xml(sal,ev);
890                                 else if (strcmp(ct->subtype,"dtmf-relay")==0)
891                                         process_dtmf_relay(sal,ev);
892                                 else {
893                                         ms_message("Unhandled SIP INFO.");
894                                         /*send an "Not implemented" answer*/
895                                         eXosip_lock();
896                                         eXosip_call_build_answer(ev->tid,501,&ans);
897                                         if (ans)
898                                                 eXosip_call_send_answer(ev->tid,501,ans);
899                                         eXosip_unlock();
900                                 }
901                         }else{
902                                 /*empty SIP INFO, probably to test we are alive. Send an empty answer*/
903                                 eXosip_lock();
904                                 eXosip_call_build_answer(ev->tid,200,&ans);
905                                 if (ans)
906                                         eXosip_call_send_answer(ev->tid,200,ans);
907                                 eXosip_unlock();
908                         }
909                 }
910         }else ms_warning("call_message_new: No request ?");
911 }
912
913 static void inc_update(Sal *sal, eXosip_event_t *ev){
914         osip_message_t *msg=NULL;
915         ms_message("Processing incoming UPDATE");
916         eXosip_lock();
917         eXosip_message_build_answer(ev->tid,200,&msg);
918         if (msg!=NULL)
919                 eXosip_message_send_answer(ev->tid,200,msg);
920         eXosip_unlock();
921 }
922
923 static bool_t comes_from_local_if(osip_message_t *msg){
924         osip_via_t *via=NULL;
925         osip_message_get_via(msg,0,&via);
926         if (via){
927                 const char *host;
928                 host=osip_via_get_host(via);
929                 if (strcmp(host,"127.0.0.1")==0 || strcmp(host,"::1")==0){
930                         osip_generic_param_t *param=NULL;
931                         osip_via_param_get_byname(via,"received",&param);
932                         if (param==NULL) return TRUE;
933                         if (param->gvalue &&
934                                 (strcmp(param->gvalue,"127.0.0.1")==0 || strcmp(param->gvalue,"::1")==0)){
935                                 return TRUE;
936                         }
937                 }
938         }
939         return FALSE;
940 }
941
942 static void text_received(Sal *sal, eXosip_event_t *ev){
943         osip_body_t *body=NULL;
944         char *from=NULL,*msg;
945         
946         osip_message_get_body(ev->request,0,&body);
947         if (body==NULL){
948                 ms_error("Could not get text message from SIP body");
949                 return;
950         }
951         msg=body->body;
952         osip_from_to_str(ev->request->from,&from);
953         sal->callbacks.text_received(sal,from,msg);
954         osip_free(from);
955 }
956
957 static void other_request(Sal *sal, eXosip_event_t *ev){
958         ms_message("in other_request");
959         if (ev->request==NULL) return;
960         if (strcmp(ev->request->sip_method,"MESSAGE")==0){
961                 text_received(sal,ev);
962                 eXosip_message_send_answer(ev->tid,200,NULL);
963         }else if (strcmp(ev->request->sip_method,"OPTIONS")==0){
964                 osip_message_t *options=NULL;
965                 eXosip_options_build_answer(ev->tid,200,&options);
966                 osip_message_set_allow(options,"INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, SUBSCRIBE, NOTIFY, INFO");
967                 osip_message_set_accept(options,"application/sdp");
968                 eXosip_options_send_answer(ev->tid,200,options);
969         }else if (strcmp(ev->request->sip_method,"WAKEUP")==0
970                 && comes_from_local_if(ev->request)) {
971                 eXosip_message_send_answer(ev->tid,200,NULL);
972                 ms_message("Receiving WAKEUP request !");
973                 sal->callbacks.internal_message(sal,"WAKEUP");
974         }else if (strncmp(ev->request->sip_method, "REFER", 5) == 0){
975                 ms_message("Receiving REFER request !");
976                 if (comes_from_local_if(ev->request)) {
977                         osip_header_t *h=NULL;
978                         osip_message_header_get_byname(ev->request,"Refer-To",0,&h);
979                         eXosip_message_send_answer(ev->tid,200,NULL);
980                         if (h){
981                                 sal->callbacks.refer_received(sal,NULL,h->hvalue);
982                         }
983                 }else ms_warning("Ignored REFER not coming from this local loopback interface.");
984         }else if (strncmp(ev->request->sip_method, "UPDATE", 6) == 0){
985                 inc_update(sal,ev);
986     }else {
987                 char *tmp=NULL;
988                 size_t msglen=0;
989                 osip_message_to_str(ev->request,&tmp,&msglen);
990                 if (tmp){
991                         ms_message("Unsupported request received:\n%s",tmp);
992                         osip_free(tmp);
993                 }
994                 /*answer with a 501 Not implemented*/
995                 eXosip_message_send_answer(ev->tid,501,NULL);
996         }
997 }
998
999 static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *orig_request, osip_message_t *last_answer){
1000         osip_message_t *msg;
1001         const char *rport,*received;
1002         osip_via_t *via=NULL;
1003         osip_generic_param_t *param=NULL;
1004         osip_contact_t *ctt=NULL;
1005         char *tmp;
1006         
1007         osip_message_get_via(last_answer,0,&via);
1008         if (!via) return FALSE;
1009         osip_via_param_get_byname(via,"rport",&param);
1010         if (param) rport=param->gvalue;
1011         else return FALSE;
1012         param=NULL;
1013         osip_via_param_get_byname(via,"received",&param);
1014         if (param) received=param->gvalue;
1015         else return FALSE;
1016         osip_message_get_contact(orig_request,0,&ctt);
1017         if (strcmp(ctt->url->host,received)==0){
1018                 /*ip address matches, check ports*/
1019                 const char *contact_port=ctt->url->port;
1020                 const char *via_rport=rport;
1021                 if (via_rport==NULL || strlen(via_rport)>0)
1022                         via_rport="5060";
1023                 if (contact_port==NULL || strlen(contact_port)>0)
1024                         contact_port="5060";
1025                 if (strcmp(contact_port,via_rport)==0){
1026                         ms_message("Register has up to date contact, doing nothing.");
1027                         return FALSE;
1028                 }else ms_message("ports do not match, need to update the register (%s <> %s)", contact_port,via_rport);
1029         }
1030         eXosip_lock();
1031         msg=NULL;
1032         eXosip_register_build_register(op->rid,op->expires,&msg);
1033         if (msg==NULL){
1034                 eXosip_unlock();
1035                 ms_warning("Fail to create a contact updated register.");
1036                 return FALSE;
1037         }
1038         osip_message_get_contact(msg,0,&ctt);
1039         if (ctt->url->host!=NULL){
1040                 osip_free(ctt->url->host);
1041         }
1042         ctt->url->host=osip_strdup(received);
1043         if (ctt->url->port!=NULL){
1044                 osip_free(ctt->url->port);
1045         }
1046         ctt->url->port=osip_strdup(rport);
1047         eXosip_register_send_register(op->rid,msg);
1048         eXosip_unlock();
1049         osip_contact_to_str(ctt,&tmp);
1050         sal_op_set_contact(op,tmp);
1051         ms_message("Resending new register with updated contact %s",tmp);
1052         ms_free(tmp);
1053         return TRUE;
1054 }
1055
1056 static void registration_success(Sal *sal, eXosip_event_t *ev){
1057         SalOp *op=sal_find_register(sal,ev->rid);
1058         osip_header_t *h=NULL;
1059         bool_t registered;
1060         if (op==NULL){
1061                 ms_error("Receiving register response for unknown operation");
1062                 return;
1063         }
1064         osip_message_get_expires(ev->request,0,&h);
1065         if (h!=NULL && atoi(h->hvalue)!=0){
1066                 registered=TRUE;
1067                 if (!register_again_with_updated_contact(op,ev->request,ev->response)){
1068                         sal->callbacks.register_success(op,registered);
1069                 }
1070         }else registered=FALSE;
1071 }
1072
1073 static bool_t registration_failure(Sal *sal, eXosip_event_t *ev){
1074         int status_code=0;
1075         const char *reason=NULL;
1076         SalOp *op=sal_find_register(sal,ev->rid);
1077         SalReason sr=SalReasonUnknown;
1078         SalError se=SalErrorUnknown;
1079         
1080         if (op==NULL){
1081                 ms_error("Receiving register failure for unknown operation");
1082                 return TRUE;
1083         }
1084         if (ev->response){
1085                 status_code=osip_message_get_status_code(ev->response);
1086                 reason=osip_message_get_reason_phrase(ev->response);
1087         }else return TRUE;
1088         switch(status_code){
1089                 case 401:
1090                 case 407:
1091                         return process_authentication(sal,ev);
1092                         break;
1093                 default:
1094                         /* if contact is up to date, process the failure, otherwise resend a new register with
1095                                 updated contact first, just in case the faillure is due to incorrect contact */
1096                         if (register_again_with_updated_contact(op,ev->request,ev->response))
1097                                 return TRUE; /*we are retrying with an updated contact*/
1098                         if (status_code==403){
1099                                 se=SalErrorFailure;
1100                                 sr=SalReasonForbidden;
1101                         }else if (status_code==0){
1102                                 se=SalErrorNoResponse;
1103                         }
1104                         sal->callbacks.register_failure(op,se,sr,reason);
1105         }
1106         return TRUE;
1107 }
1108
1109 static bool_t process_event(Sal *sal, eXosip_event_t *ev){
1110         switch(ev->type){
1111                 case EXOSIP_CALL_ANSWERED:
1112                         ms_message("CALL_ANSWERED\n");
1113                         call_accepted(sal,ev);
1114                         authentication_ok(sal,ev);
1115                         break;
1116                 case EXOSIP_CALL_CLOSED:
1117                 case EXOSIP_CALL_CANCELLED:
1118                         ms_message("CALL_CLOSED or CANCELLED\n");
1119                         call_terminated(sal,ev);
1120                         break;
1121                 case EXOSIP_CALL_TIMEOUT:
1122                 case EXOSIP_CALL_NOANSWER:
1123                         ms_message("CALL_TIMEOUT or NOANSWER\n");
1124                         return call_failure(sal,ev);
1125                         break;
1126                 case EXOSIP_CALL_REQUESTFAILURE:
1127                 case EXOSIP_CALL_GLOBALFAILURE:
1128                 case EXOSIP_CALL_SERVERFAILURE:
1129                         ms_message("CALL_REQUESTFAILURE or GLOBALFAILURE or SERVERFAILURE\n");
1130                         return call_failure(sal,ev);
1131                         break;
1132                 case EXOSIP_CALL_INVITE:
1133                         ms_message("CALL_NEW\n");
1134                         inc_new_call(sal,ev);
1135                         break;
1136                 case EXOSIP_CALL_REINVITE:
1137                         handle_reinvite(sal,ev);
1138                         break;
1139                 case EXOSIP_CALL_ACK:
1140                         ms_message("CALL_ACK");
1141                         handle_ack(sal,ev);
1142                         break;
1143                 case EXOSIP_CALL_REDIRECTED:
1144                         ms_message("CALL_REDIRECTED");
1145                         eXosip_default_action(ev);
1146                         break;
1147                 case EXOSIP_CALL_PROCEEDING:
1148                         ms_message("CALL_PROCEEDING");
1149                         call_proceeding(sal,ev);
1150                         break;
1151                 case EXOSIP_CALL_RINGING:
1152                         ms_message("CALL_RINGING");
1153                         call_ringing(sal,ev);
1154                         break;
1155                 case EXOSIP_CALL_MESSAGE_NEW:
1156                         ms_message("EXOSIP_CALL_MESSAGE_NEW");
1157                         call_message_new(sal,ev);
1158                         break;
1159                 case EXOSIP_CALL_MESSAGE_REQUESTFAILURE:
1160                         if (ev->did<0 && ev->response &&
1161                                 (ev->response->status_code==407 || ev->response->status_code==401)){
1162                                  return process_authentication(sal,ev);
1163                         }
1164                         break;
1165                 case EXOSIP_IN_SUBSCRIPTION_NEW:
1166                         ms_message("CALL_SUBSCRIPTION_NEW ");
1167                         sal_exosip_subscription_recv(sal,ev);
1168                         break;
1169                 case EXOSIP_SUBSCRIPTION_UPDATE:
1170                         ms_message("CALL_SUBSCRIPTION_UPDATE");
1171                         break;
1172                 case EXOSIP_SUBSCRIPTION_NOTIFY:
1173                         ms_message("CALL_SUBSCRIPTION_NOTIFY");
1174                         sal_exosip_notify_recv(sal,ev);
1175                         break;
1176                 case EXOSIP_SUBSCRIPTION_ANSWERED:
1177                         ms_message("EXOSIP_SUBSCRIPTION_ANSWERED, ev->sid=%i\n",ev->sid);
1178                         sal_exosip_subscription_answered(sal,ev);
1179                         break;
1180                 case EXOSIP_SUBSCRIPTION_CLOSED:
1181                         ms_message("EXOSIP_SUBSCRIPTION_CLOSED\n");
1182                         sal_exosip_subscription_closed(sal,ev);
1183                         break;
1184                 case EXOSIP_CALL_RELEASED:
1185                         ms_message("CALL_RELEASED\n");
1186                         call_released(sal, ev);
1187                         break;
1188                 case EXOSIP_REGISTRATION_FAILURE:
1189                         ms_message("REGISTRATION_FAILURE\n");
1190                         return registration_failure(sal,ev);
1191                         break;
1192                 case EXOSIP_REGISTRATION_SUCCESS:
1193                         authentication_ok(sal,ev);
1194                         registration_success(sal,ev);
1195                         break;
1196                 case EXOSIP_MESSAGE_NEW:
1197                         other_request(sal,ev);
1198                         break;
1199                 case EXOSIP_MESSAGE_REQUESTFAILURE:
1200                         if (ev->response && (ev->response->status_code == 407 || ev->response->status_code == 401)){
1201                                 return process_authentication(sal,ev);
1202                         }
1203                         break;
1204                 default:
1205                         ms_message("Unhandled exosip event ! %i");
1206                         break;
1207         }
1208         return TRUE;
1209 }
1210
1211 int sal_iterate(Sal *sal){
1212         eXosip_event_t *ev;
1213         while((ev=eXosip_event_wait(0,0))!=NULL){
1214                 if (process_event(sal,ev))
1215                         eXosip_event_free(ev);
1216         }
1217         eXosip_lock();
1218         eXosip_automatic_refresh();
1219         eXosip_unlock();
1220         return 0;
1221 }
1222
1223 int sal_register(SalOp *h, const char *proxy, const char *from, int expires){
1224         osip_message_t *msg;
1225         sal_op_set_route(h,proxy);
1226         if (h->rid==-1){
1227                 eXosip_lock();
1228                 h->rid=eXosip_register_build_initial_register(from,proxy,sal_op_get_contact(h),expires,&msg);
1229                 sal_add_register(h->base.root,h);
1230         }else{
1231                 eXosip_lock();
1232                 eXosip_register_build_register(h->rid,expires,&msg);    
1233         }
1234         eXosip_register_send_register(h->rid,msg);
1235         eXosip_unlock();
1236         h->expires=expires;
1237         return 0;
1238 }
1239
1240 int sal_unregister(SalOp *h){
1241         osip_message_t *msg=NULL;
1242         eXosip_lock();
1243         eXosip_register_build_register(h->rid,0,&msg);
1244         if (msg) eXosip_register_send_register(h->rid,msg);
1245         else ms_warning("Could not build unREGISTER !");
1246         eXosip_unlock();
1247         return 0;
1248 }
1249
1250
1251
1252 SalAddress * sal_address_new(const char *uri){
1253         osip_from_t *from;
1254         osip_from_init(&from);
1255         if (osip_from_parse(from,uri)!=0){
1256                 osip_from_free(from);
1257                 return NULL;
1258         }
1259         return (SalAddress*)from;
1260 }
1261
1262 SalAddress * sal_address_clone(const SalAddress *addr){
1263         osip_from_t *ret=NULL;
1264         osip_from_clone((osip_from_t*)addr,&ret);
1265         return (SalAddress*)ret;
1266 }
1267
1268 #define null_if_empty(s) (((s)!=NULL && (s)[0]!='\0') ? (s) : NULL )
1269
1270 const char *sal_address_get_scheme(const SalAddress *addr){
1271         const osip_from_t *u=(const osip_from_t*)addr;
1272         return null_if_empty(u->url->scheme);
1273 }
1274
1275 const char *sal_address_get_display_name(const SalAddress* addr){
1276         const osip_from_t *u=(const osip_from_t*)addr;
1277         return null_if_empty(u->displayname);
1278 }
1279
1280 const char *sal_address_get_username(const SalAddress *addr){
1281         const osip_from_t *u=(const osip_from_t*)addr;
1282         return null_if_empty(u->url->username);
1283 }
1284
1285 const char *sal_address_get_domain(const SalAddress *addr){
1286         const osip_from_t *u=(const osip_from_t*)addr;
1287         return null_if_empty(u->url->host);
1288 }
1289
1290 void sal_address_set_display_name(SalAddress *addr, const char *display_name){
1291         osip_from_t *u=(osip_from_t*)addr;
1292         if (u->displayname!=NULL){
1293                 osip_free(u->displayname);
1294                 u->displayname=NULL;
1295         }
1296         if (display_name!=NULL)
1297                 u->displayname=osip_strdup(display_name);
1298 }
1299
1300 void sal_address_set_username(SalAddress *addr, const char *username){
1301         osip_from_t *uri=(osip_from_t*)addr;
1302         if (uri->url->username!=NULL){
1303                 osip_free(uri->url->username);
1304                 uri->url->username=NULL;
1305         }
1306         if (username)
1307                 uri->url->username=osip_strdup(username);
1308 }
1309
1310 void sal_address_set_domain(SalAddress *addr, const char *host){
1311         osip_from_t *uri=(osip_from_t*)addr;
1312         if (uri->url->host!=NULL){
1313                 osip_free(uri->url->host);
1314                 uri->url->host=NULL;
1315         }
1316         if (host)
1317                 uri->url->host=osip_strdup(host);
1318 }
1319
1320 void sal_address_set_port(SalAddress *addr, const char *port){
1321         osip_from_t *uri=(osip_from_t*)addr;
1322         if (uri->url->port!=NULL){
1323                 osip_free(uri->url->port);
1324                 uri->url->port=NULL;
1325         }
1326         if (port)
1327                 uri->url->port=osip_strdup(port);
1328 }
1329
1330 void sal_address_set_port_int(SalAddress *uri, int port){
1331         char tmp[12];
1332         if (port==5060){
1333                 /*this is the default, special case to leave the port field blank*/
1334                 sal_address_set_port(uri,NULL);
1335                 return;
1336         }
1337         snprintf(tmp,sizeof(tmp),"%i",port);
1338         sal_address_set_port(uri,tmp);
1339 }
1340
1341 void sal_address_clean(SalAddress *addr){
1342         osip_generic_param_freelist(& ((osip_from_t*)addr)->gen_params);
1343 }
1344
1345 char *sal_address_as_string(const SalAddress *u){
1346         char *tmp,*ret;
1347         osip_from_to_str((osip_from_t*)u,&tmp);
1348         ret=ms_strdup(tmp);
1349         osip_free(tmp);
1350         return ret;
1351 }
1352
1353 char *sal_address_as_string_uri_only(const SalAddress *u){
1354         char *tmp=NULL,*ret;
1355         osip_uri_to_str(((osip_from_t*)u)->url,&tmp);
1356         ret=ms_strdup(tmp);
1357         osip_free(tmp);
1358         return ret;
1359 }
1360
1361 void sal_address_destroy(SalAddress *u){
1362         osip_from_free((osip_from_t*)u);
1363 }
1364