source: mediastreamer2/linphone/coreapi/exevents.c @ 342:ed7317483afe

Last change on this file since 342:ed7317483afe was 342:ed7317483afe, checked in by smorlat <smorlat@…>, 4 years ago

fix crash and improve authentication failure processing

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@345 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 33.6 KB
Line 
1/*
2linphone
3Copyright (C) 2000  Simon MORLAT (simon.morlat@free.fr)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20#include "exevents.h"
21#include "linphonecore.h"
22#include "private.h"
23#include "mediastreamer2/mediastream.h"
24#include <eXosip2/eXosip.h>
25#include <osipparser2/osip_message.h>
26#include <osipparser2/osip_parser.h>
27
28static int linphone_answer_sdp(LinphoneCore *lc, eXosip_event_t *ev, sdp_message_t *sdp);
29
30static bool_t linphone_call_matches_event(LinphoneCall *call, eXosip_event_t *ev){
31        return call->cid==ev->cid;
32}
33
34static void linphone_call_proceeding(LinphoneCore *lc, eXosip_event_t *ev){
35        if (lc->call==NULL || (lc->call->cid!=-1 && !linphone_call_matches_event(lc->call,ev)) ) {
36                ms_warning("This call has been canceled.");
37                eXosip_lock();
38                eXosip_call_terminate(ev->cid,ev->did);
39                eXosip_unlock();
40                return;
41        }
42        lc->call->cid=ev->cid;
43        lc->call->did=ev->did;
44        lc->call->tid=ev->tid;
45}
46
47static void linphone_connect_incoming(LinphoneCore *lc){
48        lc->vtable.show(lc);
49        lc->vtable.display_status(lc,_("Connected."));
50        lc->call->state=LCStateAVRunning;
51        if (lc->ringstream!=NULL){
52                ring_stop(lc->ringstream);
53                lc->ringstream=NULL;
54        }
55        if (lc->audiostream->ticker!=NULL){
56                /*case where we accepted early media */
57                linphone_core_stop_media_streams(lc);
58                linphone_core_init_media_streams(lc);
59        }
60        linphone_core_start_media_streams(lc,lc->call);
61}
62
63int linphone_call_accepted(LinphoneCore *lc, eXosip_event_t *ev)
64{
65        LinphoneCall *call=lc->call;
66        sdp_message_t *sdp;
67        const char *sdpanswer=NULL;
68        osip_message_t *msg=NULL;
69        int err;
70        if (call==NULL){
71                ms_warning("No call to accept.");
72                return 0;
73        }
74        linphone_call_proceeding(lc,ev);
75        if (!linphone_call_matches_event(lc->call,ev)) return 0;
76        call->auth_pending=FALSE;
77        if (call->state==LCStateAVRunning){
78                return 0; /*already accepted*/
79        }
80        linphone_call_init_media_params(call);
81        sdp=eXosip_get_sdp_info(ev->response);
82        if (!lc->sip_conf.sdp_200_ack){
83                err=0;
84                sdp_context_read_answer(call->sdpctx,sdp);
85        }else{
86                /*we receive a 200OK with an sdp offer*/
87                err=linphone_answer_sdp(lc,ev,sdp);
88                if (err==0) sdpanswer=call->sdpctx->answerstr;
89        }
90        if (err==0){
91                gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
92                linphone_connect_incoming(lc);
93        }
94        /*send the ack once streams are started*/
95        eXosip_call_build_ack(ev->did,&msg);
96        if (sdpanswer!=NULL) linphone_set_sdp(msg,sdpanswer);
97        eXosip_call_send_ack(ev->did,msg);
98        if (err!=0){
99                /*send a bye*/
100                ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
101                linphone_core_terminate_call(lc,NULL);
102        }
103        sdp_message_free(sdp);
104        return 0;
105}
106
107
108int linphone_call_terminated(LinphoneCore *lc, eXosip_event_t *ev)
109{
110        /*stop ringing if necessary*/
111        if (lc->call!=NULL){
112                if (lc->call->cid!=ev->cid){
113                        /* this is not current call */
114                        ms_message("call %i terminated, this was not current call.",ev->cid);
115                        return 0;
116                }
117        }
118       
119        ms_message("Current call terminated...");
120        if (lc->ringstream!=NULL) {
121                ring_stop(lc->ringstream);
122                lc->ringstream=NULL;
123        }
124        linphone_core_stop_media_streams(lc);
125        lc->vtable.show(lc);
126        lc->vtable.display_status(lc,_("Call terminated."));
127        gstate_new_state(lc, GSTATE_CALL_END, NULL);
128        if (lc->vtable.bye_recv!=NULL){
129                char *from;
130                osip_from_to_str(ev->request->from,&from);
131                lc->vtable.bye_recv(lc,from);
132                osip_free(from);
133        }
134        if (lc->call!=NULL){
135                linphone_call_destroy(lc->call);
136                lc->call=NULL;
137        }
138        return 0;
139}
140
141
142int linphone_call_released(LinphoneCore *lc, int cid){
143        LinphoneCall *call=lc->call;
144        if (call!=NULL && call->cid==cid){
145               
146                linphone_call_destroy(lc->call);
147                lc->call=NULL;
148                lc->vtable.display_status(lc,_("Could not reach destination."));
149                gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
150        }
151        return 0;
152}
153
154int linphone_call_failure(LinphoneCore *lc, eXosip_event_t *ev)
155{
156        const char *reason="";
157        char *msg486=_("User is busy.");
158        char *msg480=_("User is temporarily unavailable.");
159        char *msg487=_("Request Cancelled.");
160        /*char *retrymsg=_("%s. Retry after %i minute(s).");*/
161        char *msg600=_("User does not want to be disturbed.");
162        char *msg603=_("Call declined.");
163        char* tmpmsg=msg486;
164        int code;
165        LinphoneCall *call=lc->call;
166
167        if (call){
168                /*check that the faillure is related to this call, not an old one*/
169                if (!linphone_call_matches_event(call,ev)) {
170                        ms_warning("Failure reported for an old call.");
171                        return 0;
172                }
173        }
174
175        if (ev->response){
176                code=osip_message_get_status_code(ev->response);
177                reason=osip_message_get_reason_phrase(ev->response);
178        }else code=-110;
179        lc->vtable.show(lc);
180       
181        switch(code)
182        {
183                case 401:
184                case 407:
185                        if (lc->call!=NULL)
186                                linphone_process_authentication(lc,ev);
187                        return 0;
188                        break;
189                case 400:
190                        lc->vtable.display_status(lc,_("Bad request"));
191                break;
192                case 404:
193                        lc->vtable.display_status(lc,_("User cannot be found at given address."));
194                break;
195                case 415:
196                        lc->vtable.display_status(lc,_("Remote user cannot support any of proposed codecs."));
197                break;
198                case 480:
199                        tmpmsg=msg480;
200                case 486:
201                        /*
202                        msg_header_getbyname(msg,"retry-after",0,&retry);
203                        if (retry!=NULL)
204                        {
205                                umsg=g_malloc(strlen(tmpmsg)+strlen(retrymsg)+13);
206                                sprintf(umsg,retrymsg,tmpmsg,atoi(retry->hvalue)/60);
207                                lc->vtable.display_message(lc,umsg);
208                                ms_free(umsg);
209                        }*/             
210                        lc->vtable.display_message(lc,tmpmsg);
211                break;
212                case 487:
213                        lc->vtable.display_status(lc,msg487);
214                break; 
215                case 600:
216                        lc->vtable.display_message(lc,msg600);
217                break;
218                case 603:
219                        lc->vtable.display_status(lc,msg603);
220                break;
221                case -110/* time out, call leg is lost */
222                        lc->vtable.display_status(lc,_("Timeout."));
223                break;
224                case -111:
225                        lc->vtable.display_status(lc,_("Remote host was found but refused connection."));
226                break;
227               
228                default:
229                        if (code>0)
230                        {
231                                lc->vtable.display_status(lc,reason);
232                        }
233                        else ms_warning("failure_cb unknown code=%i\n",code);   
234        }
235        if (lc->ringstream!=NULL) {
236                ring_stop(lc->ringstream);
237                lc->ringstream=NULL;
238        }
239        linphone_core_stop_media_streams(lc);
240        if (call!=NULL) {
241                linphone_call_destroy(call);
242                gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
243                lc->call=NULL;
244        }
245        return 0;
246}
247
248extern sdp_handler_t linphone_sdphandler;
249
250static int linphone_answer_sdp(LinphoneCore *lc, eXosip_event_t *ev, sdp_message_t *sdp){
251        int status=200;
252        sdp_context_t *ctx=NULL;
253       
254        ctx=lc->call->sdpctx;
255        /* get the result of the negociation */
256        sdp_context_get_answer(ctx,sdp);
257        status=sdp_context_get_status(ctx);
258
259        if (status==200){
260                linphone_core_init_media_streams(lc);
261                return 0;
262        }else{
263                if (status==-1) status=415;
264        }
265        return -1;
266}
267
268int linphone_inc_new_call(LinphoneCore *lc, eXosip_event_t *ev)
269{
270        sdp_message_t *sdp=NULL;
271        osip_from_t *from_url=ev->request->from;
272        char *barmesg;
273        char *from;
274        char *to;
275        int err;
276
277        osip_from_to_str(ev->request->from,&from);
278        osip_to_to_str(ev->request->to,&to);   
279       
280        /* first check if we can answer successfully to this invite */
281        if (lc->presence_mode!=LINPHONE_STATUS_ONLINE){
282                ms_message("Not present !! presence mode : %d\n",lc->presence_mode);
283                eXosip_lock();
284                if (lc->presence_mode==LINPHONE_STATUS_BUSY)
285                        eXosip_call_send_answer(ev->tid,486,NULL);
286                else if (lc->presence_mode==LINPHONE_STATUS_AWAY
287                         ||lc->presence_mode==LINPHONE_STATUS_BERIGHTBACK
288                         ||lc->presence_mode==LINPHONE_STATUS_ONTHEPHONE
289                         ||lc->presence_mode==LINPHONE_STATUS_OUTTOLUNCH
290                         ||lc->presence_mode==LINPHONE_STATUS_OFFLINE)
291                  eXosip_call_send_answer(ev->tid,480,NULL);
292                else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB)
293                  eXosip_call_send_answer(ev->tid,480,NULL);
294                else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED)
295                  {
296                        osip_message_t *msg;
297                        eXosip_call_build_answer(ev->tid,302,&msg);
298                        osip_message_set_contact(msg,lc->alt_contact);
299                        eXosip_call_send_answer(ev->tid,302,msg);
300                  }
301                else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_ALT_SERVICE)
302                  {
303                        osip_message_t *msg;
304                        eXosip_call_build_answer(ev->tid,380,&msg);
305                        osip_message_set_contact(msg,lc->alt_contact);
306                        eXosip_call_send_answer(ev->tid,380,msg);
307                  }
308                else
309                  eXosip_call_send_answer(ev->tid,486,NULL);
310                eXosip_unlock();
311                goto end;
312        }
313        if (lc->call!=NULL){/*busy*/
314                eXosip_lock();
315                eXosip_call_send_answer(ev->tid,486,NULL);
316                eXosip_unlock();
317                goto end;
318        }
319        lc->call=linphone_call_new_incoming(lc,from,to,ev->cid,ev->did,ev->tid);
320        sdp=eXosip_get_sdp_info(ev->request);
321        if (sdp==NULL){
322                ms_message("No sdp body in invite, 200-ack scheme");
323                err=0;
324        }else{
325                err=linphone_answer_sdp(lc,ev,sdp);
326        }
327        if (!err){
328                char *tmp;
329                if (from_2char_without_params(from_url,&tmp)!=0){
330                        tmp=ms_strdup("Unknown user");
331                }
332                gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp);
333                barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you."));
334                lc->vtable.show(lc);
335                lc->vtable.display_status(lc,barmesg);
336                lc->vtable.inv_recv(lc,tmp);
337                ms_free(barmesg);
338                osip_free(tmp);
339               
340                linphone_call_set_state(lc->call,LCStateRinging);
341                eXosip_lock();
342                eXosip_call_send_answer(ev->tid,180,NULL);
343                eXosip_unlock();
344                /* play the ring */
345                if (lc->sound_conf.ring_sndcard!=NULL){
346                        ms_message("Starting local ring...");
347                        lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
348                }
349        }else{
350                ms_error("Error during sdp negociation. ");
351                eXosip_lock();
352                eXosip_call_send_answer(ev->tid,415,NULL);
353                eXosip_unlock();
354                linphone_call_destroy(lc->call);
355                lc->call=NULL;
356        }
357        end:
358        osip_free(from);
359        osip_free(to);
360        if (sdp) sdp_message_free(sdp);
361        return 0;
362}
363
364void linphone_handle_ack(LinphoneCore *lc, eXosip_event_t *ev){
365        sdp_message_t *sdp=eXosip_get_sdp_info(ev->ack);
366        if (sdp){
367                sdp_context_read_answer(lc->call->sdpctx,sdp);
368                linphone_connect_incoming(lc);
369                sdp_message_free(sdp);
370        }
371}
372
373void linphone_handle_reinvite(LinphoneCore *lc, eXosip_event_t *ev){
374        sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
375        sdp_context_t *ctx;
376        LinphoneCall *call=lc->call;
377        char *answer;
378        int status;
379        if (sdp==NULL){
380                ms_warning("No sdp in reinvite !");
381                eXosip_lock();
382                eXosip_call_send_answer(ev->tid,603,NULL);
383                eXosip_unlock();
384                return;
385        }
386        ctx=call->sdpctx;
387        /* get the result of the negociation */
388        linphone_call_init_media_params(call);
389        answer=sdp_context_get_answer(ctx,sdp);
390        status=sdp_context_get_status(ctx);
391        if (status==200){
392                osip_message_t *msg=NULL;
393                linphone_core_stop_media_streams(lc);
394                linphone_core_init_media_streams(lc);
395                eXosip_lock();
396                if (eXosip_call_build_answer(ev->tid,200,&msg)<0){
397                        ms_warning("Reinvite for closed call ?");
398                        eXosip_unlock();
399                        linphone_core_stop_media_streams(lc);
400                        sdp_message_free(sdp);
401                        return ;
402                }
403                answer=call->sdpctx->answerstr; /* takes the sdp already computed*/
404                linphone_set_sdp(msg,answer);
405                eXosip_call_send_answer(ev->tid,200,msg);
406                eXosip_unlock();
407                linphone_core_start_media_streams(lc,call);
408        }else{
409                eXosip_lock();
410                eXosip_call_send_answer(ev->tid,status,NULL);
411                eXosip_unlock();
412        }
413        sdp_message_free(sdp);
414}
415
416void linphone_do_automatic_redirect(LinphoneCore *lc, const char *contact){
417        char *msg=ortp_strdup_printf(_("Redirected to %s..."),contact);
418        lc->vtable.display_status(lc,msg);
419        ms_free(msg);
420        if (lc->call!=NULL) linphone_call_destroy(lc->call);
421        lc->call=NULL;
422        linphone_core_invite(lc,contact);
423}
424
425void linphone_call_redirected(LinphoneCore *lc, eXosip_event_t *ev){
426        int code=osip_message_get_status_code(ev->response);
427        char *contact=NULL;
428        osip_contact_t *ct;
429        osip_message_get_contact(ev->response,0,&ct);
430        if (ct) osip_contact_to_str(ct,&contact);
431        switch(code){
432                case 380:
433                        lc->vtable.display_url(lc,_("User is not reachable at the moment but he invites you\nto contact him using the following alternate resource:"),contact);
434                        if (lc->call!=NULL) linphone_call_destroy(lc->call);
435                        lc->call=NULL;
436                        break;
437                case 302:
438                        linphone_do_automatic_redirect(lc,contact);
439                        break;
440        }
441        if (contact) osip_free(contact);
442}
443
444
445/* these are the SdpHandler callbacks: we are called in to be aware of the content
446of the SDP messages exchanged */
447
448int linphone_set_audio_offer(sdp_context_t *ctx)
449{
450        LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
451        LinphoneCore *lc=call->core;
452        PayloadType *codec;
453        MSList *elem;
454        sdp_payload_t payload;
455       
456       
457        elem=lc->codecs_conf.audio_codecs;
458        while(elem!=NULL){
459                codec=(PayloadType*) elem->data;
460                if (linphone_core_check_payload_type_usability(lc,codec) && payload_type_enabled(codec)){
461                        sdp_payload_init(&payload);
462                        payload.a_rtpmap=ortp_strdup_printf("%s/%i/1",codec->mime_type,codec->clock_rate);
463                        payload.pt=rtp_profile_get_payload_number_from_rtpmap(lc->local_profile,payload.a_rtpmap);
464                        payload.localport=call->audio_params.natd_port > 0 ? 
465                                                call->audio_params.natd_port : lc->rtp_conf.audio_rtp_port;
466                        if (strcasecmp(codec->mime_type,"iLBC")==0){
467                                /* prefer the 30 ms mode */
468                                payload.a_fmtp="ptime=30";
469                        }
470                        sdp_context_add_audio_payload(ctx,&payload);
471                        ms_free(payload.a_rtpmap);
472                }
473                elem=ms_list_next(elem);
474        }
475        /* add telephone-event payload*/
476        sdp_payload_init(&payload);
477        payload.pt=rtp_profile_get_payload_number_from_mime(lc->local_profile,"telephone-event");
478        payload.a_rtpmap="telephone-event/8000";
479        payload.a_fmtp="0-11";
480        if (lc->dw_audio_bw>0) payload.b_as_bandwidth=lc->dw_audio_bw;
481        sdp_context_add_audio_payload(ctx,&payload);
482        return 0;
483}
484
485static int find_payload_type_number(RtpProfile *prof, PayloadType *pt){
486        int candidate=-1,i;
487        PayloadType *it;
488        for(i=0;i<127;++i){
489                it=rtp_profile_get_payload(prof,i);
490                if (it!=NULL && strcasecmp(pt->mime_type,it->mime_type)==0 
491                        && (pt->clock_rate==it->clock_rate || pt->clock_rate<=0) ){
492                        if ( (pt->recv_fmtp && it->recv_fmtp && strcasecmp(pt->recv_fmtp,it->recv_fmtp)==0) ||
493                                (pt->recv_fmtp==NULL && it->recv_fmtp==NULL) ){
494                                /*exact match*/
495                                return i;
496                        }else candidate=i;
497                }
498        }
499        if (candidate==-1) ms_fatal("Should not happen.");
500        return candidate;
501}
502
503static int find_payload_type_number_best_match(RtpProfile *prof, const char *rtpmap, const char *fmtp){
504        int localpt=rtp_profile_get_payload_number_from_rtpmap(prof,rtpmap);
505        PayloadType *pt;
506        char value[10];
507        if (localpt<0) return -1;
508        pt=rtp_profile_get_payload(prof,localpt);
509        if (strcasecmp(pt->mime_type,"H264")==0){
510                /*hack for H264: need to answer with same packetization-mode*/
511                PayloadType tmp;
512                memset(&tmp,0,sizeof(tmp));
513                tmp.mime_type="H264";
514                tmp.clock_rate=pt->clock_rate;
515                if (fmtp && fmtp_get_value(fmtp,"packetization-mode",value,sizeof(value))){
516                        tmp.recv_fmtp=(atoi(value)==1) ? "packetization-mode=1" : NULL;
517                }
518                localpt=find_payload_type_number(prof,&tmp);
519        }
520        return localpt;
521}
522
523int linphone_set_video_offer(sdp_context_t *ctx)
524{
525        LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
526        LinphoneCore *lc=call->core;
527        PayloadType *codec;
528        MSList *elem;
529        bool_t firsttime=TRUE; 
530
531        if (!linphone_core_video_enabled(lc)) return -1;
532
533        for(elem=lc->codecs_conf.video_codecs;elem!=NULL;elem=ms_list_next(elem)){
534                codec=(PayloadType*) elem->data;
535                if (linphone_core_check_payload_type_usability(lc,codec) && payload_type_enabled(codec)){
536                        sdp_payload_t payload;
537                        sdp_payload_init(&payload);
538                        payload.line=1;
539                        payload.a_rtpmap=ortp_strdup_printf("%s/%i",codec->mime_type,codec->clock_rate);
540                        payload.localport=call->video_params.natd_port>0 ? 
541                                        call->video_params.natd_port : lc->rtp_conf.video_rtp_port;
542                        payload.pt=find_payload_type_number(lc->local_profile,codec);
543                        payload.a_fmtp=codec->recv_fmtp;
544                        if(firsttime){
545                                firsttime=FALSE;
546                                if (lc->dw_video_bw>0)
547                                        payload.b_as_bandwidth=lc->dw_video_bw;
548                        }
549                        sdp_context_add_video_payload(ctx,&payload);
550                        ms_free(payload.a_rtpmap);
551                }
552        }
553        return 0;
554}
555
556typedef enum {
557        Unsupported,
558        Supported,
559        SupportedAndValid  /* valid= the presence of this codec is enough to make a call */
560}SupportLevel;
561
562SupportLevel linphone_payload_is_supported(LinphoneCore *lc, sdp_payload_t *payload,RtpProfile *local_profile,RtpProfile *dialog_profile, bool_t answering, PayloadType **local_payload_type)
563{
564        int localpt;
565        SupportLevel ret;
566        if (payload->a_rtpmap!=NULL){
567                localpt=find_payload_type_number_best_match(local_profile,payload->a_rtpmap,payload->a_fmtp);
568        }else{
569                localpt=payload->pt;
570                ms_warning("payload has no rtpmap.");
571        }
572       
573        if (localpt>=0 && localpt <128 ){
574                /* this payload is understood, but does the user want to use it ?? */
575                PayloadType *rtppayload;
576                rtppayload=rtp_profile_get_payload(local_profile,localpt);
577                if (rtppayload==NULL) {
578                        ms_warning("strange error !!");
579                        return Unsupported;
580                }
581                *local_payload_type=rtppayload;
582                if (strcmp(rtppayload->mime_type,"telephone-event")!=0){
583                        if (answering && !linphone_core_check_payload_type_usability(lc,rtppayload) ){
584                                ms_warning("payload %s is not usable",rtppayload->mime_type);
585                                return Unsupported;
586                        }
587                        if ( !payload_type_enabled(rtppayload)) {
588                                ms_warning("payload %s is not enabled.",rtppayload->mime_type);
589                                return Unsupported;
590                        }
591                        ret=SupportedAndValid;
592                }else ret=Supported;
593                if (dialog_profile!=NULL){
594                        int dbw,ubw;
595                        /* this payload is supported in our local rtp profile, so add it to the dialog rtp
596                        profile */
597                        rtppayload=payload_type_clone(rtppayload);
598                        if (rtp_profile_get_payload(dialog_profile,payload->pt)!=NULL){
599                                ms_error("Payload %s type already entered, should not happen !",rtppayload->mime_type);
600                        }
601                        rtp_profile_set_payload(dialog_profile,payload->pt,rtppayload);
602                        /* add to the rtp payload type some other parameters (bandwidth) */
603                        if (rtppayload->type==PAYLOAD_VIDEO){
604                                dbw=lc->dw_video_bw;
605                                ubw=lc->up_video_bw;
606                        }else{ 
607                                dbw=lc->dw_audio_bw;
608                                ubw=lc->up_audio_bw;
609                        }
610                        if (payload->b_as_bandwidth!=0){
611                                ms_message("Remote bandwidth constraint: %i",payload->b_as_bandwidth);
612                                /*obey to remote bandwidth constraint AND our own upbandwidth constraint*/
613                                rtppayload->normal_bitrate=1000*get_min_bandwidth(
614                                        payload->b_as_bandwidth, ubw);
615                        }else{
616                                /*limit to upload bandwidth if exist, else no limit*/
617                                if (ubw>0) rtppayload->normal_bitrate=1000*ubw;
618                                else {
619                                        if (rtppayload->type!=PAYLOAD_VIDEO){
620                                                rtppayload->normal_bitrate=-1; /*allow speex to use maximum bitrate*/
621                                        }
622                                }
623                        }
624                        if (payload->a_fmtp!=NULL){
625                                payload_type_set_send_fmtp(rtppayload,payload->a_fmtp);
626                        }
627                        payload->a_fmtp=rtppayload->recv_fmtp;
628                        if (payload->a_ptime>0){
629                                char tmp[30];
630                                snprintf(tmp,sizeof(tmp),"ptime=%i",payload->a_ptime);
631                                payload_type_append_send_fmtp(rtppayload,tmp);
632                                ms_message("%s attribute added to fmtp",tmp);
633                        }
634                }
635                return ret;
636        }
637        return Unsupported;
638}
639
640int linphone_accept_audio_offer(sdp_context_t *ctx,sdp_payload_t *payload)
641{
642        RtpProfile *remote_profile;
643        StreamParams *params;
644        SupportLevel supported;
645        LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
646        LinphoneCore *lc=call->core;
647        PayloadType *lpt=NULL;
648
649        params=&call->audio_params;
650        remote_profile=call->profile;
651        /* see if this codec is supported in our local rtp profile*/
652        supported=linphone_payload_is_supported(lc,payload,lc->local_profile,remote_profile,TRUE,&lpt);
653        if (supported==Unsupported) {
654                ms_message("Refusing audio codec %i (%s)",payload->pt,payload->a_rtpmap);
655                return -1;
656        }
657        if (lc->sip_conf.only_one_codec && params->initialized){
658                ms_message("Only one codec has to be accepted.");
659                return -1;
660        }
661        if (supported==SupportedAndValid) {             
662                if (params->initialized==0){
663                        /* this is the first codec we accept, it is going to be used*/
664                        params->localport=lc->rtp_conf.audio_rtp_port;
665                        payload->localport=params->natd_port>0 ? 
666                                params->natd_port : lc->rtp_conf.audio_rtp_port;
667                        params->line=payload->line;
668                        params->pt=payload->pt; /* remember the first payload accepted */
669                        if (payload->relay_host!=NULL){
670                                strncpy(params->remoteaddr,payload->relay_host,sizeof(params->remoteaddr)-1);
671                                params->remoteport=payload->relay_port;
672                                params->remotertcpport=payload->relay_port;
673                                params->relay_session_id=payload->relay_session_id;
674                        }else{
675                                strncpy(params->remoteaddr,payload->c_addr,sizeof(params->remoteaddr)-1);
676                                params->remoteport=payload->remoteport;
677                                params->remotertcpport=payload->remoteport+1;
678                        }
679                        params->initialized=1;
680                        /* we can now update the allocated bandwidth for audio, and then video*/
681                        linphone_core_update_allocated_audio_bandwidth_in_call(lc,lpt);
682                        /* give our download bandwidth constraint*/
683                        payload->b_as_bandwidth=(lc->dw_audio_bw>0) ? lc->dw_audio_bw : 0;
684                }else{
685                        /* refuse all other audio lines*/
686                        if(params->line!=payload->line) {
687                                ms_message("Only one audio line can be accepted.");
688                                abort();
689                                return -1;
690                        }
691                }
692        }
693        return 0;
694}
695
696int linphone_accept_video_offer(sdp_context_t *ctx,sdp_payload_t *payload)
697{
698        LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
699        LinphoneCore *lc=call->core;
700        RtpProfile *remote_profile;
701        StreamParams *params;
702        SupportLevel supported;
703        PayloadType *lpt=NULL;
704
705        if (!linphone_core_video_enabled(lc)) return -1;
706
707        params=&call->video_params;
708        remote_profile=call->profile;
709        /* see if this codec is supported in our local rtp profile*/
710        supported=linphone_payload_is_supported(lc,payload,lc->local_profile,remote_profile,TRUE,&lpt);
711        if (supported==Unsupported) {
712                ms_message("Refusing video codec %i (%s)",payload->pt,payload->a_rtpmap);
713                return -1;
714        }
715        if (lc->sip_conf.only_one_codec && params->initialized){
716                return -1;
717        }
718        if (supported==SupportedAndValid){
719                if (params->initialized==0){
720                        /* this is the first codec we may accept*/
721                        params->localport=lc->rtp_conf.video_rtp_port;
722                        payload->localport=params->natd_port>0 ? params->natd_port : lc->rtp_conf.video_rtp_port;
723                        params->line=payload->line;
724                        params->pt=payload->pt; /* remember the first payload accepted */
725                        if (payload->relay_host!=NULL){
726                                strncpy(params->remoteaddr,payload->relay_host,sizeof(params->remoteaddr)-1);
727                                params->remoteport=payload->relay_port;
728                                params->remotertcpport=payload->relay_port;
729                                params->relay_session_id=payload->relay_session_id;
730                        }else{
731                                strncpy(params->remoteaddr,payload->c_addr,sizeof(params->remoteaddr)-1);
732                                params->remoteport=payload->remoteport;
733                                params->remotertcpport=params->remoteport+1;
734                        }
735                        params->initialized=1;
736                        payload->b_as_bandwidth=(lc->dw_video_bw>0) ? lc->dw_video_bw : 0;
737                }else{
738                        /* refuse all other video lines*/
739                        if(params->line!=payload->line) return -1;
740                }
741        }
742        return 0;
743}
744
745int linphone_read_audio_answer(sdp_context_t *ctx,sdp_payload_t *payload)
746{
747        LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
748        LinphoneCore *lc=call->core;
749        StreamParams *params;
750        SupportLevel supported;
751        PayloadType *lpt=NULL;
752       
753        /* paranoid check: see if this codec is supported in our local rtp profile*/
754        supported=linphone_payload_is_supported(lc, payload,lc->local_profile,call->profile,FALSE,&lpt);
755        if (supported==Unsupported) {
756                ms_warning("This remote sip phone did not answer properly to my sdp offer: rtpmap=%s",payload->a_rtpmap);
757                return 0;
758        }
759        if (supported==SupportedAndValid){
760                params=&call->audio_params;
761                if (params->initialized==0){
762                        /* this is the first codec we accept, this is the one that is going to be used (at least for sending
763                        data.*/
764                        params->localport=lc->rtp_conf.audio_rtp_port;
765                        params->line=payload->line;
766                        params->pt=payload->pt; /* remember the first payload accepted */
767                        if (payload->relay_host!=NULL){
768                                strncpy(params->remoteaddr,payload->relay_host,sizeof(params->remoteaddr)-1);
769                                params->remoteport=payload->relay_port;
770                                params->remotertcpport=payload->relay_port;
771                                params->relay_session_id=payload->relay_session_id;
772                        }else{
773                                strncpy(params->remoteaddr,payload->c_addr,sizeof(params->remoteaddr)-1);
774                                params->remoteport=payload->remoteport;
775                                params->remotertcpport=payload->remoteport+1;
776                        }
777                        params->initialized=1;
778                        /* we can now update the allocated bandwidth for audio, and then video*/
779                        linphone_core_update_allocated_audio_bandwidth_in_call(lc,lpt);
780                }
781        }
782        return 0;
783}
784
785int linphone_read_video_answer(sdp_context_t *ctx,sdp_payload_t *payload)
786{
787        LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
788        LinphoneCore *lc=call->core;
789        StreamParams *params;
790        SupportLevel supported;
791        PayloadType *lpt=NULL;
792       
793        /* paranoid check: see if this codec is supported in our local rtp profile*/
794        supported=linphone_payload_is_supported(lc, payload,lc->local_profile,call->profile,FALSE,&lpt);
795        if (supported==Unsupported) {
796                ms_warning("This remote sip phone did not answer properly to my sdp offer: rtpmap=%s",payload->a_rtpmap);
797                return 0;
798        }
799        if (supported==SupportedAndValid){
800                params=&call->video_params;
801                if (params->initialized==0){
802                        /* this is the first codec we may accept*/
803                        params->localport=lc->rtp_conf.video_rtp_port;
804                        params->line=payload->line;
805                        params->pt=payload->pt; /* remember the first payload accepted */
806                        if (payload->relay_host!=NULL){
807                                strncpy(params->remoteaddr,payload->relay_host,sizeof(params->remoteaddr)-1);
808                                params->remoteport=payload->relay_port;
809                                params->remotertcpport=payload->relay_port;
810                                params->relay_session_id=payload->relay_session_id;
811                        }else{
812                                strncpy(params->remoteaddr,payload->c_addr,sizeof(params->remoteaddr)-1);
813                                params->remoteport=payload->remoteport;
814                                params->remotertcpport=payload->remoteport+1;
815                        }
816                        params->initialized=1;
817                }
818        }
819        return 0;
820}
821
822void linphone_call_ringing(LinphoneCore *lc, eXosip_event_t *ev){
823        sdp_message_t *sdp=eXosip_get_sdp_info(ev->response);
824        LinphoneCall *call=lc->call;
825       
826        linphone_call_proceeding(lc,ev);
827        if (call==NULL) return;
828        if (sdp==NULL){
829                if (lc->ringstream!=NULL) return;       /*already ringing !*/
830                if (lc->sound_conf.play_sndcard!=NULL){
831                        ms_message("Remote ringing...");
832                        lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,lc->sound_conf.play_sndcard);
833                }
834        }else{
835                /*accept early media */
836                StreamParams *audio_params;
837                if (call==NULL){
838                        ms_error("No call ?");
839                        goto end;
840                }
841                if (lc->audiostream->ticker!=NULL){
842                        /*streams already started */
843                        ms_message("Early media already started.");
844                        goto end;
845                }
846                audio_params=&call->audio_params;
847                sdp_context_read_answer(lc->call->sdpctx,sdp);
848                lc->vtable.show(lc);
849                lc->vtable.display_status(lc,_("Early media."));
850                gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
851                if (lc->ringstream!=NULL){
852                        ring_stop(lc->ringstream);
853                        lc->ringstream=NULL;
854                }
855                ms_message("Doing early media...");
856                linphone_core_start_media_streams(lc,call);
857        }
858        call->state=LCStateRinging;
859        goto end;
860        end:
861                sdp_message_free(sdp);
862
863}
864
865void linphone_call_message_new(LinphoneCore *lc, eXosip_event_t *ev){
866#ifdef VIDEO_ENABLED
867        if (ev->request){
868                if (MSG_IS_INFO(ev->request)){
869                        osip_content_type_t *ct;
870                        ct=osip_message_get_content_type(ev->request);
871                        if (ct && ct->subtype &&
872                                strcmp(ct->subtype,"media_control+xml")==0){
873                                osip_body_t *body=NULL;
874                                osip_message_get_body(ev->request,0,&body);
875                                if (body && body->body!=NULL &&
876                                        strstr(body->body,"picture_fast_update")){
877                                        osip_message_t *ans=NULL;
878                                        ms_message("Receiving VFU request !");
879                                        if (lc->videostream)
880                                                video_stream_send_vfu(lc->videostream);
881                                        eXosip_call_build_answer(ev->tid,200,&ans);
882                                        if (ans)
883                                                eXosip_call_send_answer(ev->tid,200,ans);
884                                }
885                        }       
886                }
887        }else ms_warning("linphone_call_message_new: No request ?");
888#endif
889}
890
891void linphone_registration_faillure(LinphoneCore *lc, eXosip_event_t *ev){
892        int status_code=0;
893        char *msg;
894        const char *reason=NULL;
895        osip_uri_t *requri=osip_message_get_uri(ev->request);
896        char *ru;
897       
898        osip_uri_to_str(requri,&ru);
899
900        if (ev->response){
901                status_code=osip_message_get_status_code(ev->response);
902                reason=osip_message_get_reason_phrase(ev->response);
903        }
904        switch(status_code){
905                case 401:
906                case 407:
907                        linphone_process_authentication(lc,ev);
908                        break;
909                case 403:
910                        linphone_proxy_config_process_authentication_failure(lc,ev);
911                default:
912                        msg=ortp_strdup_printf(_("Registration on %s failed: %s"),ru,(reason!=NULL) ? reason : _("no response timeout"));
913                        lc->vtable.display_status(lc,msg);
914                        gstate_new_state(lc, GSTATE_REG_FAILED, msg);
915                        ms_free(msg);
916        }
917        osip_free(ru);
918}
919
920void linphone_registration_success(LinphoneCore *lc,eXosip_event_t *ev){
921        LinphoneProxyConfig *cfg;
922        osip_uri_t *requri=osip_message_get_uri(ev->request);
923        char *msg;
924        char *ru;
925        osip_header_t *h=NULL;
926        osip_uri_to_str(requri,&ru);
927        msg=ms_strdup_printf(_("Registration on %s successful."),ru);
928        lc->vtable.display_status(lc,msg);
929        ms_free(msg);
930        osip_free(ru);
931        cfg=linphone_core_get_proxy_config_from_rid(lc,ev->rid);
932        ms_return_if_fail(cfg!=NULL);
933        gstate_new_state(lc, GSTATE_REG_OK, NULL);
934        osip_message_get_expires(ev->request,0,&h);
935        if (h!=NULL && atoi(h->hvalue)!=0){
936                cfg->registered=TRUE;
937                linphone_proxy_config_register_again_with_updated_contact(cfg,ev->request,ev->response);
938        }else cfg->registered=FALSE;
939}
940
941static bool_t comes_from_local_if(osip_message_t *msg){
942        osip_via_t *via=NULL;
943        osip_message_get_via(msg,0,&via);
944        if (via){
945                const char *host;
946                host=osip_via_get_host(via);
947                if (strcmp(host,"127.0.0.1")==0 || strcmp(host,"::1")==0){
948                        osip_generic_param_t *param=NULL;
949                        osip_via_param_get_byname(via,"received",&param);
950                        if (param==NULL) return TRUE;
951                        if (param->gvalue && 
952                                (strcmp(param->gvalue,"127.0.0.1")==0 || strcmp(param->gvalue,"::1")==0)){
953                                return TRUE;
954                        }
955                }
956        }
957        return FALSE;
958}
959
960static void linphone_other_request(LinphoneCore *lc, eXosip_event_t *ev){
961        ms_message("in linphone_other_request");
962        if (ev->request==NULL) return;
963        if (strcmp(ev->request->sip_method,"MESSAGE")==0){
964                linphone_core_text_received(lc,ev);
965                eXosip_message_send_answer(ev->tid,200,NULL);
966        }else if (strcmp(ev->request->sip_method,"OPTIONS")==0){
967#if 1
968                osip_message_t *options=NULL;
969                eXosip_options_build_answer(ev->tid,200,&options);
970                osip_message_set_allow(options,"INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, SUBSCRIBE, NOTIFY, INFO");
971                osip_message_set_accept(options,"application/sdp");
972                eXosip_options_send_answer(ev->tid,200,options);
973#else
974                ms_warning("Not answering to this options request.");
975#endif
976        }else if (strcmp(ev->request->sip_method,"WAKEUP")==0
977                && comes_from_local_if(ev->request)) {
978                eXosip_message_send_answer(ev->tid,200,NULL);
979                ms_message("Receiving WAKEUP request !");
980                if (lc->vtable.show)
981                        lc->vtable.show(lc);
982        }else {
983                char *tmp=NULL;
984                size_t msglen=0;
985                osip_message_to_str(ev->request,&tmp,&msglen);
986                if (tmp){
987                        ms_message("Unsupported request received:\n%s",tmp);
988                        osip_free(tmp);
989                }
990                /*answer with a 501 Not implemented*/
991                eXosip_message_send_answer(ev->tid,501,NULL);
992        }
993}
994
995void linphone_core_process_event(LinphoneCore *lc,eXosip_event_t *ev)
996{
997        switch(ev->type){
998                case EXOSIP_CALL_ANSWERED:
999                        ms_message("CALL_ANSWERED\n");
1000                        linphone_call_accepted(lc,ev);
1001                        linphone_authentication_ok(lc,ev);
1002                        break;
1003                case EXOSIP_CALL_CLOSED:
1004                case EXOSIP_CALL_CANCELLED:
1005                        ms_message("CALL_CLOSED or CANCELLED\n");
1006                        linphone_call_terminated(lc,ev);
1007                        break;
1008                case EXOSIP_CALL_TIMEOUT:
1009                case EXOSIP_CALL_NOANSWER:
1010                        ms_message("CALL_TIMEOUT or NOANSWER\n");
1011                        linphone_call_failure(lc,ev);
1012                        break;
1013                case EXOSIP_CALL_REQUESTFAILURE:
1014                case EXOSIP_CALL_GLOBALFAILURE:
1015                case EXOSIP_CALL_SERVERFAILURE:
1016                        ms_message("CALL_REQUESTFAILURE or GLOBALFAILURE or SERVERFAILURE\n");
1017                        linphone_call_failure(lc,ev);
1018                        break;
1019                case EXOSIP_CALL_INVITE:
1020                        ms_message("CALL_NEW\n");
1021                        /* CALL_NEW is used twice in qos mode :
1022                         * when you receive invite (textinfo = "With QoS" or "Without QoS")
1023                         * and when you receive update (textinfo = "New Call") */
1024                        linphone_inc_new_call(lc,ev);
1025                        break;
1026                case EXOSIP_CALL_REINVITE:
1027                        linphone_handle_reinvite(lc,ev);
1028                        break;
1029                case EXOSIP_CALL_ACK:
1030                        ms_message("CALL_ACK");
1031                        linphone_handle_ack(lc,ev);
1032                        break;
1033                case EXOSIP_CALL_REDIRECTED:
1034                        ms_message("CALL_REDIRECTED");
1035                        linphone_call_redirected(lc,ev);
1036                        break;
1037                case EXOSIP_CALL_PROCEEDING:
1038                        ms_message("CALL_PROCEEDING");
1039                        linphone_call_proceeding(lc,ev);
1040                        break;
1041                case EXOSIP_CALL_RINGING:
1042                        ms_message("CALL_RINGING");
1043                        linphone_call_ringing(lc,ev);
1044                        break;
1045                case EXOSIP_CALL_MESSAGE_NEW:
1046                        ms_message("EXOSIP_CALL_MESSAGE_NEW");
1047                        linphone_call_message_new(lc,ev);
1048                        break;
1049                case EXOSIP_CALL_MESSAGE_REQUESTFAILURE:
1050                        if (ev->did<0 && ev->response && 
1051                                (ev->response->status_code==407 || ev->response->status_code==401)){
1052                                 eXosip_default_action(ev);
1053                        }
1054                        break;
1055                case EXOSIP_IN_SUBSCRIPTION_NEW:
1056                        ms_message("CALL_SUBSCRIPTION_NEW or UPDATE");
1057                        linphone_subscription_new(lc,ev);
1058                        break;
1059                case EXOSIP_SUBSCRIPTION_UPDATE:
1060                        break;
1061                case EXOSIP_SUBSCRIPTION_NOTIFY:
1062                        ms_message("CALL_SUBSCRIPTION_NOTIFY");
1063                        linphone_notify_recv(lc,ev);
1064                        break;
1065                case EXOSIP_SUBSCRIPTION_ANSWERED:
1066                        ms_message("EXOSIP_SUBSCRIPTION_ANSWERED, ev->sid=%i\n",ev->sid);
1067                        linphone_subscription_answered(lc,ev);
1068                        break;
1069                case EXOSIP_SUBSCRIPTION_CLOSED:
1070                        ms_message("EXOSIP_SUBSCRIPTION_CLOSED\n");
1071                        linphone_subscription_closed(lc,ev);
1072                        break;
1073                case EXOSIP_CALL_RELEASED:
1074                        ms_message("CALL_RELEASED\n");
1075                        linphone_call_released(lc, ev->cid);
1076                        break;
1077                case EXOSIP_REGISTRATION_FAILURE:
1078                        ms_message("REGISTRATION_FAILURE\n");
1079                        linphone_registration_faillure(lc,ev);
1080                        break;
1081                case EXOSIP_REGISTRATION_SUCCESS:
1082                        linphone_authentication_ok(lc,ev);
1083                        linphone_registration_success(lc,ev);
1084                        break;
1085                case EXOSIP_MESSAGE_NEW:
1086                        linphone_other_request(lc,ev);
1087                        break;
1088                case EXOSIP_MESSAGE_REQUESTFAILURE:
1089                        if (ev->response && (ev->response->status_code == 407 || ev->response->status_code == 401)){
1090                                /*the user is expected to have registered to the proxy, thus password is known*/
1091                                eXosip_default_action(ev);
1092                        }
1093                        break;
1094                default:
1095                        ms_message("Unhandled exosip event !");
1096                        break;
1097        }
1098        eXosip_event_free(ev);
1099}
Note: See TracBrowser for help on using the repository browser.