3 Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr)
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "linphonecore.h"
23 #include "mediastreamer2/mediastream.h"
24 #include <eXosip2/eXosip.h>
25 #include <osipparser2/osip_message.h>
26 #include <osipparser2/osip_parser.h>
28 static int linphone_answer_sdp(LinphoneCore *lc, eXosip_event_t *ev, sdp_message_t *sdp);
30 static bool_t linphone_call_matches_event(LinphoneCall *call, eXosip_event_t *ev){
31 return call->cid==ev->cid;
34 static 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: call=%p, call->cid=%i, ev->cid=%i",
37 lc->call,lc->call?lc->call->cid:-1,ev->cid);
39 eXosip_call_terminate(ev->cid,ev->did);
43 lc->call->cid=ev->cid;
44 lc->call->did=ev->did;
45 lc->call->tid=ev->tid;
48 static void linphone_connect_incoming(LinphoneCore *lc){
50 lc->vtable.display_status(lc,_("Connected."));
51 lc->call->state=LCStateAVRunning;
52 if (lc->ringstream!=NULL){
53 ring_stop(lc->ringstream);
56 if (lc->audiostream->ticker!=NULL){
57 /*case where we accepted early media */
58 linphone_core_stop_media_streams(lc);
59 linphone_core_init_media_streams(lc);
61 linphone_core_start_media_streams(lc,lc->call);
64 int linphone_call_accepted(LinphoneCore *lc, eXosip_event_t *ev)
66 LinphoneCall *call=lc->call;
68 const char *sdpanswer=NULL;
69 osip_message_t *msg=NULL;
72 ms_warning("No call to accept.");
75 linphone_call_proceeding(lc,ev);
76 if (!linphone_call_matches_event(lc->call,ev)) return 0;
77 call->auth_pending=FALSE;
78 if (call->state==LCStateAVRunning){
79 return 0; /*already accepted*/
81 linphone_call_init_media_params(call);
82 sdp=eXosip_get_sdp_info(ev->response);
83 if (!lc->sip_conf.sdp_200_ack){
85 sdp_context_read_answer(call->sdpctx,sdp);
87 /*we receive a 200OK with an sdp offer*/
88 err=linphone_answer_sdp(lc,ev,sdp);
89 if (err==0) sdpanswer=call->sdpctx->answerstr;
92 gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
93 linphone_connect_incoming(lc);
95 /*send the ack once streams are started*/
96 eXosip_call_build_ack(ev->did,&msg);
97 if (sdpanswer!=NULL) linphone_set_sdp(msg,sdpanswer);
98 eXosip_call_send_ack(ev->did,msg);
101 ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
102 linphone_core_terminate_call(lc,NULL);
104 sdp_message_free(sdp);
109 int linphone_call_terminated(LinphoneCore *lc, eXosip_event_t *ev)
111 /*stop ringing if necessary*/
113 if (lc->call->cid!=ev->cid){
114 /* this is not current call */
115 ms_message("call %i terminated, this was not current call.",ev->cid);
120 ms_message("Current call terminated...");
121 if (lc->ringstream!=NULL) {
122 ring_stop(lc->ringstream);
125 linphone_core_stop_media_streams(lc);
127 lc->vtable.display_status(lc,_("Call terminated."));
128 gstate_new_state(lc, GSTATE_CALL_END, NULL);
129 if (lc->vtable.bye_recv!=NULL){
131 osip_from_to_str(ev->request->from,&from);
132 lc->vtable.bye_recv(lc,from);
136 linphone_call_destroy(lc->call);
143 int linphone_call_released(LinphoneCore *lc, int cid){
144 LinphoneCall *call=lc->call;
145 if (call!=NULL && call->cid==cid){
147 linphone_call_destroy(lc->call);
149 lc->vtable.display_status(lc,_("Could not reach destination."));
150 gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
155 int linphone_call_failure(LinphoneCore *lc, eXosip_event_t *ev)
157 const char *reason="";
158 char *msg486=_("User is busy.");
159 char *msg480=_("User is temporarily unavailable.");
160 char *msg487=_("Request Cancelled.");
161 /*char *retrymsg=_("%s. Retry after %i minute(s).");*/
162 char *msg600=_("User does not want to be disturbed.");
163 char *msg603=_("Call declined.");
166 LinphoneCall *call=lc->call;
169 /*check that the faillure is related to this call, not an old one*/
170 if (!linphone_call_matches_event(call,ev)) {
171 ms_warning("Failure reported for an old call.");
177 code=osip_message_get_status_code(ev->response);
178 reason=osip_message_get_reason_phrase(ev->response);
187 linphone_process_authentication(lc,ev);
191 lc->vtable.display_status(lc,_("Bad request"));
194 lc->vtable.display_status(lc,_("User cannot be found at given address."));
197 lc->vtable.display_status(lc,_("Remote user cannot support any of proposed codecs."));
200 /*ignore: eXosip_automatic_action will do the job of retrying with a greater Session-Expires*/
207 msg_header_getbyname(msg,"retry-after",0,&retry);
210 umsg=g_malloc(strlen(tmpmsg)+strlen(retrymsg)+13);
211 sprintf(umsg,retrymsg,tmpmsg,atoi(retry->hvalue)/60);
212 lc->vtable.display_message(lc,umsg);
215 lc->vtable.display_message(lc,tmpmsg);
217 case 487: /*request terminated*/
218 lc->vtable.display_status(lc,msg487);
221 lc->vtable.display_message(lc,msg600);
224 lc->vtable.display_status(lc,msg603);
226 case -110: /* time out, call leg is lost */
227 lc->vtable.display_status(lc,_("Timeout."));
230 lc->vtable.display_status(lc,_("Remote host was found but refused connection."));
236 lc->vtable.display_status(lc,reason);
238 else ms_warning("failure_cb unknown code=%i\n",code);
240 if (lc->ringstream!=NULL) {
241 ring_stop(lc->ringstream);
244 linphone_core_stop_media_streams(lc);
246 linphone_call_destroy(call);
247 gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
253 extern sdp_handler_t linphone_sdphandler;
255 static int linphone_answer_sdp(LinphoneCore *lc, eXosip_event_t *ev, sdp_message_t *sdp){
257 sdp_context_t *ctx=NULL;
259 ctx=lc->call->sdpctx;
260 /* get the result of the negociation */
261 sdp_context_get_answer(ctx,sdp);
262 status=sdp_context_get_status(ctx);
265 linphone_core_init_media_streams(lc);
268 if (status==-1) status=415;
273 int linphone_inc_new_call(LinphoneCore *lc, eXosip_event_t *ev)
275 sdp_message_t *sdp=NULL;
276 osip_from_t *from_url=ev->request->from;
282 osip_from_to_str(ev->request->from,&from);
283 osip_to_to_str(ev->request->to,&to);
285 /* first check if we can answer successfully to this invite */
286 if (lc->presence_mode!=LINPHONE_STATUS_ONLINE){
287 ms_message("Not present !! presence mode : %d\n",lc->presence_mode);
289 if (lc->presence_mode==LINPHONE_STATUS_BUSY)
290 eXosip_call_send_answer(ev->tid,486,NULL);
291 else if (lc->presence_mode==LINPHONE_STATUS_AWAY
292 ||lc->presence_mode==LINPHONE_STATUS_BERIGHTBACK
293 ||lc->presence_mode==LINPHONE_STATUS_ONTHEPHONE
294 ||lc->presence_mode==LINPHONE_STATUS_OUTTOLUNCH
295 ||lc->presence_mode==LINPHONE_STATUS_OFFLINE)
296 eXosip_call_send_answer(ev->tid,480,NULL);
297 else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB)
298 eXosip_call_send_answer(ev->tid,480,NULL);
299 else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED)
302 eXosip_call_build_answer(ev->tid,302,&msg);
303 osip_message_set_contact(msg,lc->alt_contact);
304 eXosip_call_send_answer(ev->tid,302,msg);
306 else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_ALT_SERVICE)
309 eXosip_call_build_answer(ev->tid,380,&msg);
310 osip_message_set_contact(msg,lc->alt_contact);
311 eXosip_call_send_answer(ev->tid,380,msg);
314 eXosip_call_send_answer(ev->tid,486,NULL);
318 if (lc->call!=NULL){/*busy*/
320 eXosip_call_send_answer(ev->tid,486,NULL);
324 lc->call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),ev);
326 sdp=eXosip_get_sdp_info(ev->request);
328 ms_message("No sdp body in invite, 200-ack scheme");
331 err=linphone_answer_sdp(lc,ev,sdp);
335 if (from_2char_without_params(from_url,&tmp)!=0){
336 tmp=ms_strdup("Unknown user");
338 gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp);
339 barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you."));
341 lc->vtable.display_status(lc,barmesg);
344 if (lc->sound_conf.ring_sndcard!=NULL){
345 ms_message("Starting local ring...");
346 lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
348 linphone_call_set_state(lc->call,LCStateRinging);
350 eXosip_call_send_answer(ev->tid,180,NULL);
353 lc->vtable.inv_recv(lc,tmp);
357 ms_error("Error during sdp negociation. ");
359 eXosip_call_send_answer(ev->tid,415,NULL);
361 linphone_call_destroy(lc->call);
367 if (sdp) sdp_message_free(sdp);
371 void linphone_handle_ack(LinphoneCore *lc, eXosip_event_t *ev){
372 sdp_message_t *sdp=eXosip_get_sdp_info(ev->ack);
374 sdp_context_read_answer(lc->call->sdpctx,sdp);
375 linphone_connect_incoming(lc);
376 sdp_message_free(sdp);
380 void linphone_handle_reinvite(LinphoneCore *lc, eXosip_event_t *ev){
381 sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
383 LinphoneCall *call=lc->call;
387 ms_warning("No sdp in reinvite !");
389 eXosip_call_send_answer(ev->tid,603,NULL);
394 /* get the result of the negociation */
395 linphone_call_init_media_params(call);
396 answer=sdp_context_get_answer(ctx,sdp);
397 status=sdp_context_get_status(ctx);
399 osip_message_t *msg=NULL;
400 linphone_core_stop_media_streams(lc);
401 linphone_core_init_media_streams(lc);
403 if (eXosip_call_build_answer(ev->tid,200,&msg)<0){
404 ms_warning("Reinvite for closed call ?");
406 linphone_core_stop_media_streams(lc);
407 sdp_message_free(sdp);
410 answer=call->sdpctx->answerstr; /* takes the sdp already computed*/
411 linphone_set_sdp(msg,answer);
412 eXosip_call_send_answer(ev->tid,200,msg);
414 linphone_core_start_media_streams(lc,call);
417 eXosip_call_send_answer(ev->tid,status,NULL);
420 sdp_message_free(sdp);
423 void linphone_do_automatic_redirect(LinphoneCore *lc, const char *contact){
424 char *msg=ortp_strdup_printf(_("Redirected to %s..."),contact);
425 lc->vtable.display_status(lc,msg);
427 if (lc->call!=NULL) linphone_call_destroy(lc->call);
429 linphone_core_invite(lc,contact);
432 void linphone_call_redirected(LinphoneCore *lc, eXosip_event_t *ev){
433 int code=osip_message_get_status_code(ev->response);
436 osip_message_get_contact(ev->response,0,&ct);
437 if (ct) osip_contact_to_str(ct,&contact);
440 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);
441 if (lc->call!=NULL) linphone_call_destroy(lc->call);
445 linphone_do_automatic_redirect(lc,contact);
448 if (contact) osip_free(contact);
452 /* these are the SdpHandler callbacks: we are called in to be aware of the content
453 of the SDP messages exchanged */
455 int linphone_set_audio_offer(sdp_context_t *ctx)
457 LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
458 LinphoneCore *lc=call->core;
461 sdp_payload_t payload;
464 elem=lc->codecs_conf.audio_codecs;
466 codec=(PayloadType*) elem->data;
467 if (linphone_core_check_payload_type_usability(lc,codec) &&
468 linphone_core_payload_type_enabled(lc,codec)){
469 sdp_payload_init(&payload);
470 payload.a_rtpmap=ortp_strdup_printf("%s/%i/1",codec->mime_type,codec->clock_rate);
471 payload.pt=rtp_profile_get_payload_number_from_rtpmap(lc->local_profile,payload.a_rtpmap);
472 payload.localport=call->audio_params.natd_port > 0 ?
473 call->audio_params.natd_port : lc->rtp_conf.audio_rtp_port;
474 sdp_context_add_audio_payload(ctx,&payload);
475 ms_free(payload.a_rtpmap);
477 elem=ms_list_next(elem);
479 /* add telephone-event payload*/
480 sdp_payload_init(&payload);
481 payload.pt=rtp_profile_get_payload_number_from_mime(lc->local_profile,"telephone-event");
482 payload.a_rtpmap="telephone-event/8000";
483 payload.a_fmtp="0-11";
484 if (lc->dw_audio_bw>0) payload.b_as_bandwidth=lc->dw_audio_bw;
485 if (lc->down_ptime>0) {
486 payload.a_ptime=lc->down_ptime;
487 ms_message("ptime [%i]",payload.a_ptime);
489 sdp_context_add_audio_payload(ctx,&payload);
493 static int find_payload_type_number(RtpProfile *prof, PayloadType *pt){
497 it=rtp_profile_get_payload(prof,i);
498 if (it!=NULL && strcasecmp(pt->mime_type,it->mime_type)==0
499 && (pt->clock_rate==it->clock_rate || pt->clock_rate<=0) ){
500 if ( (pt->recv_fmtp && it->recv_fmtp && strcasecmp(pt->recv_fmtp,it->recv_fmtp)==0) ||
501 (pt->recv_fmtp==NULL && it->recv_fmtp==NULL) ){
507 if (candidate==-1) ms_fatal("Should not happen.");
511 static int find_payload_type_number_best_match(RtpProfile *prof, const char *rtpmap, const char *fmtp){
512 int localpt=rtp_profile_get_payload_number_from_rtpmap(prof,rtpmap);
515 if (localpt<0) return -1;
516 pt=rtp_profile_get_payload(prof,localpt);
517 if (strcasecmp(pt->mime_type,"H264")==0){
518 /*hack for H264: need to answer with same packetization-mode*/
520 memset(&tmp,0,sizeof(tmp));
521 tmp.mime_type="H264";
522 tmp.clock_rate=pt->clock_rate;
523 if (fmtp && fmtp_get_value(fmtp,"packetization-mode",value,sizeof(value))){
524 tmp.recv_fmtp=(atoi(value)==1) ? "packetization-mode=1" : NULL;
526 localpt=find_payload_type_number(prof,&tmp);
531 int linphone_set_video_offer(sdp_context_t *ctx)
533 LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
534 LinphoneCore *lc=call->core;
537 bool_t firsttime=TRUE;
539 if (!linphone_core_video_enabled(lc)) return -1;
541 for(elem=lc->codecs_conf.video_codecs;elem!=NULL;elem=ms_list_next(elem)){
542 codec=(PayloadType*) elem->data;
543 if (linphone_core_check_payload_type_usability(lc,codec) &&
544 linphone_core_payload_type_enabled(lc,codec)){
545 sdp_payload_t payload;
546 sdp_payload_init(&payload);
548 payload.a_rtpmap=ortp_strdup_printf("%s/%i",codec->mime_type,codec->clock_rate);
549 payload.localport=call->video_params.natd_port>0 ?
550 call->video_params.natd_port : lc->rtp_conf.video_rtp_port;
551 payload.pt=find_payload_type_number(lc->local_profile,codec);
552 payload.a_fmtp=codec->recv_fmtp;
555 if (lc->dw_video_bw>0)
556 payload.b_as_bandwidth=lc->dw_video_bw;
558 sdp_context_add_video_payload(ctx,&payload);
559 ms_free(payload.a_rtpmap);
568 SupportedAndValid /* valid= the presence of this codec is enough to make a call */
571 SupportLevel linphone_payload_is_supported(LinphoneCore *lc, sdp_payload_t *payload,RtpProfile *local_profile,RtpProfile *dialog_profile, bool_t answering, PayloadType **local_payload_type)
575 if (payload->a_rtpmap!=NULL){
576 localpt=find_payload_type_number_best_match(local_profile,payload->a_rtpmap,payload->a_fmtp);
579 ms_warning("payload has no rtpmap.");
582 if (localpt>=0 && localpt <128 ){
583 /* this payload is understood, but does the user want to use it ?? */
584 PayloadType *rtppayload;
585 rtppayload=rtp_profile_get_payload(local_profile,localpt);
586 if (rtppayload==NULL) {
587 ms_warning("strange error !!");
590 *local_payload_type=rtppayload;
591 if (strcmp(rtppayload->mime_type,"telephone-event")!=0){
592 if (answering && !linphone_core_check_payload_type_usability(lc,rtppayload) ){
593 ms_warning("payload %s is not usable",rtppayload->mime_type);
596 if ( !linphone_core_payload_type_enabled(lc,rtppayload)) {
597 ms_warning("payload %s is not enabled.",rtppayload->mime_type);
600 ret=SupportedAndValid;
602 if (dialog_profile!=NULL){
604 /* this payload is supported in our local rtp profile, so add it to the dialog rtp
606 rtppayload=payload_type_clone(rtppayload);
607 if (rtp_profile_get_payload(dialog_profile,payload->pt)!=NULL){
608 ms_error("Payload %s type already entered, should not happen !",rtppayload->mime_type);
610 rtp_profile_set_payload(dialog_profile,payload->pt,rtppayload);
611 /* add to the rtp payload type some other parameters (bandwidth) */
612 if (rtppayload->type==PAYLOAD_VIDEO){
619 if (payload->b_as_bandwidth!=0){
620 ms_message("Remote bandwidth constraint: %i",payload->b_as_bandwidth);
621 /*obey to remote bandwidth constraint AND our own upbandwidth constraint*/
622 rtppayload->normal_bitrate=1000*get_min_bandwidth(
623 payload->b_as_bandwidth, ubw);
625 /*limit to upload bandwidth if exist, else no limit*/
626 if (ubw>0) rtppayload->normal_bitrate=1000*ubw;
628 if (rtppayload->type!=PAYLOAD_VIDEO){
629 rtppayload->normal_bitrate=-1; /*allow speex to use maximum bitrate*/
633 if (payload->a_fmtp!=NULL){
634 payload_type_set_send_fmtp(rtppayload,payload->a_fmtp);
636 payload->a_fmtp=rtppayload->recv_fmtp;
637 if (payload->a_ptime>0){
639 snprintf(tmp,sizeof(tmp),"ptime=%i",payload->a_ptime);
640 payload_type_append_send_fmtp(rtppayload,tmp);
641 ms_message("%s attribute added to fmtp",tmp);
649 int linphone_accept_audio_offer(sdp_context_t *ctx,sdp_payload_t *payload)
651 RtpProfile *remote_profile;
652 StreamParams *params;
653 SupportLevel supported;
654 LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
655 LinphoneCore *lc=call->core;
656 PayloadType *lpt=NULL;
658 params=&call->audio_params;
659 remote_profile=call->profile;
660 /* see if this codec is supported in our local rtp profile*/
661 supported=linphone_payload_is_supported(lc,payload,lc->local_profile,remote_profile,TRUE,&lpt);
662 if (supported==Unsupported) {
663 ms_message("Refusing audio codec %i (%s)",payload->pt,payload->a_rtpmap);
666 if (lc->sip_conf.only_one_codec && params->initialized){
667 ms_message("Only one codec has to be accepted.");
670 if (supported==SupportedAndValid) {
671 if (params->initialized==0){
672 /* this is the first codec we accept, it is going to be used*/
673 params->localport=lc->rtp_conf.audio_rtp_port;
674 payload->localport=params->natd_port>0 ?
675 params->natd_port : lc->rtp_conf.audio_rtp_port;
676 params->line=payload->line;
677 params->pt=payload->pt; /* remember the first payload accepted */
678 if (payload->relay_host!=NULL){
679 strncpy(params->remoteaddr,payload->relay_host,sizeof(params->remoteaddr)-1);
680 params->remoteport=payload->relay_port;
681 params->remotertcpport=payload->relay_port;
682 params->relay_session_id=payload->relay_session_id;
684 strncpy(params->remoteaddr,payload->c_addr,sizeof(params->remoteaddr)-1);
685 params->remoteport=payload->remoteport;
686 params->remotertcpport=payload->remoteport+1;
688 params->initialized=1;
689 /* we can now update the allocated bandwidth for audio, and then video*/
690 linphone_core_update_allocated_audio_bandwidth_in_call(lc,lpt);
691 /* give our download bandwidth constraint*/
692 payload->b_as_bandwidth=(lc->dw_audio_bw>0) ? lc->dw_audio_bw : 0;
694 /* refuse all other audio lines*/
695 if(params->line!=payload->line) {
696 ms_message("Only one audio line can be accepted.");
697 #if !defined(_WIN32_WCE)
699 #endif /*_WIN32_WCE*/
707 int linphone_accept_video_offer(sdp_context_t *ctx,sdp_payload_t *payload)
709 LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
710 LinphoneCore *lc=call->core;
711 RtpProfile *remote_profile;
712 StreamParams *params;
713 SupportLevel supported;
714 PayloadType *lpt=NULL;
716 if (!linphone_core_video_enabled(lc)) return -1;
718 if (payload->remoteport==0) {
719 ms_message("Video stream refused by remote.");
723 params=&call->video_params;
724 remote_profile=call->profile;
725 /* see if this codec is supported in our local rtp profile*/
726 supported=linphone_payload_is_supported(lc,payload,lc->local_profile,remote_profile,TRUE,&lpt);
727 if (supported==Unsupported) {
728 ms_message("Refusing video codec %i (%s)",payload->pt,payload->a_rtpmap);
731 if (lc->sip_conf.only_one_codec && params->initialized){
734 if (supported==SupportedAndValid){
735 if (params->initialized==0){
736 /* this is the first codec we may accept*/
737 params->localport=lc->rtp_conf.video_rtp_port;
738 payload->localport=params->natd_port>0 ? params->natd_port : lc->rtp_conf.video_rtp_port;
739 params->line=payload->line;
740 params->pt=payload->pt; /* remember the first payload accepted */
741 if (payload->relay_host!=NULL){
742 strncpy(params->remoteaddr,payload->relay_host,sizeof(params->remoteaddr)-1);
743 params->remoteport=payload->relay_port;
744 params->remotertcpport=payload->relay_port;
745 params->relay_session_id=payload->relay_session_id;
747 strncpy(params->remoteaddr,payload->c_addr,sizeof(params->remoteaddr)-1);
748 params->remoteport=payload->remoteport;
749 params->remotertcpport=params->remoteport+1;
751 params->initialized=1;
752 payload->b_as_bandwidth=(lc->dw_video_bw>0) ? lc->dw_video_bw : 0;
754 /* refuse all other video lines*/
755 if(params->line!=payload->line) return -1;
761 int linphone_read_audio_answer(sdp_context_t *ctx,sdp_payload_t *payload)
763 LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
764 LinphoneCore *lc=call->core;
765 StreamParams *params;
766 SupportLevel supported;
767 PayloadType *lpt=NULL;
769 /* paranoid check: see if this codec is supported in our local rtp profile*/
770 supported=linphone_payload_is_supported(lc, payload,lc->local_profile,call->profile,FALSE,&lpt);
771 if (supported==Unsupported) {
772 ms_warning("This remote sip phone did not answer properly to my sdp offer: rtpmap=%s",payload->a_rtpmap);
775 if (supported==SupportedAndValid){
776 params=&call->audio_params;
777 if (params->initialized==0){
778 /* this is the first codec we accept, this is the one that is going to be used (at least for sending
780 params->localport=lc->rtp_conf.audio_rtp_port;
781 params->line=payload->line;
782 params->pt=payload->pt; /* remember the first payload accepted */
783 if (payload->relay_host!=NULL){
784 strncpy(params->remoteaddr,payload->relay_host,sizeof(params->remoteaddr)-1);
785 params->remoteport=payload->relay_port;
786 params->remotertcpport=payload->relay_port;
787 params->relay_session_id=payload->relay_session_id;
789 strncpy(params->remoteaddr,payload->c_addr,sizeof(params->remoteaddr)-1);
790 params->remoteport=payload->remoteport;
791 params->remotertcpport=payload->remoteport+1;
793 params->initialized=1;
794 /* we can now update the allocated bandwidth for audio, and then video*/
795 linphone_core_update_allocated_audio_bandwidth_in_call(lc,lpt);
801 int linphone_read_video_answer(sdp_context_t *ctx,sdp_payload_t *payload)
803 LinphoneCall *call=(LinphoneCall*)sdp_context_get_user_pointer(ctx);
804 LinphoneCore *lc=call->core;
805 StreamParams *params;
806 SupportLevel supported;
807 PayloadType *lpt=NULL;
809 /* paranoid check: see if this codec is supported in our local rtp profile*/
810 supported=linphone_payload_is_supported(lc, payload,lc->local_profile,call->profile,FALSE,&lpt);
811 if (supported==Unsupported) {
812 ms_warning("This remote sip phone did not answer properly to my sdp offer: rtpmap=%s",payload->a_rtpmap);
815 if (supported==SupportedAndValid){
816 params=&call->video_params;
817 if (params->initialized==0){
818 /* this is the first codec we may accept*/
819 params->localport=lc->rtp_conf.video_rtp_port;
820 params->line=payload->line;
821 params->pt=payload->pt; /* remember the first payload accepted */
822 if (payload->relay_host!=NULL){
823 strncpy(params->remoteaddr,payload->relay_host,sizeof(params->remoteaddr)-1);
824 params->remoteport=payload->relay_port;
825 params->remotertcpport=payload->relay_port;
826 params->relay_session_id=payload->relay_session_id;
828 strncpy(params->remoteaddr,payload->c_addr,sizeof(params->remoteaddr)-1);
829 params->remoteport=payload->remoteport;
830 params->remotertcpport=payload->remoteport+1;
832 params->initialized=1;
838 void linphone_call_ringing(LinphoneCore *lc, eXosip_event_t *ev){
839 sdp_message_t *sdp=eXosip_get_sdp_info(ev->response);
840 LinphoneCall *call=lc->call;
842 lc->vtable.display_status(lc,_("Remote ringing."));
843 linphone_call_proceeding(lc,ev);
844 if (call==NULL) return;
846 if (lc->ringstream!=NULL) return; /*already ringing !*/
847 if (lc->sound_conf.play_sndcard!=NULL){
848 ms_message("Remote ringing...");
849 lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,lc->sound_conf.play_sndcard);
852 /*accept early media */
853 StreamParams *audio_params;
855 ms_error("No call ?");
858 if (lc->audiostream->ticker!=NULL){
859 /*streams already started */
860 ms_message("Early media already started.");
863 audio_params=&call->audio_params;
864 sdp_context_read_answer(lc->call->sdpctx,sdp);
866 lc->vtable.display_status(lc,_("Early media."));
867 gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
868 if (lc->ringstream!=NULL){
869 ring_stop(lc->ringstream);
872 ms_message("Doing early media...");
873 linphone_core_start_media_streams(lc,call);
875 call->state=LCStateRinging;
878 sdp_message_free(sdp);
882 static void linphone_process_media_control_xml(LinphoneCore *lc, eXosip_event_t *ev){
883 osip_body_t *body=NULL;
884 osip_message_get_body(ev->request,0,&body);
885 if (body && body->body!=NULL &&
886 strstr(body->body,"picture_fast_update")){
887 osip_message_t *ans=NULL;
888 ms_message("Receiving VFU request !");
891 video_stream_send_vfu(lc->videostream);
893 eXosip_call_build_answer(ev->tid,200,&ans);
895 eXosip_call_send_answer(ev->tid,200,ans);
899 static void linphone_process_dtmf_relay(LinphoneCore *lc, eXosip_event_t *ev){
900 osip_body_t *body=NULL;
901 osip_message_get_body(ev->request,0,&body);
902 if (body && body->body!=NULL){
903 osip_message_t *ans=NULL;
904 const char *name=strstr(body->body,"Signal");
905 if (name==NULL) name=strstr(body->body,"signal");
907 ms_warning("Could not extract the dtmf name from the SIP INFO.");
910 name+=strlen("signal");
911 if (sscanf(name," = %1s",tmp)==1){
912 ms_message("Receiving dtmf %s via SIP INFO.",tmp);
913 if (lc->vtable.dtmf_received != NULL)
914 lc->vtable.dtmf_received(lc, tmp[0]);
918 eXosip_call_build_answer(ev->tid,200,&ans);
920 eXosip_call_send_answer(ev->tid,200,ans);
924 void linphone_call_message_new(LinphoneCore *lc, eXosip_event_t *ev){
925 osip_message_t *ans=NULL;
927 if (MSG_IS_INFO(ev->request)){
928 osip_content_type_t *ct;
929 ct=osip_message_get_content_type(ev->request);
930 if (ct && ct->subtype){
931 if (strcmp(ct->subtype,"media_control+xml")==0)
932 linphone_process_media_control_xml(lc,ev);
933 else if (strcmp(ct->subtype,"dtmf-relay")==0)
934 linphone_process_dtmf_relay(lc,ev);
936 ms_message("Unhandled SIP INFO.");
937 /*send an "Not implemented" answer*/
938 eXosip_call_build_answer(ev->tid,501,&ans);
940 eXosip_call_send_answer(ev->tid,501,ans);
943 /*empty SIP INFO, probably to test we are alive. Send an empty answer*/
944 eXosip_call_build_answer(ev->tid,200,&ans);
946 eXosip_call_send_answer(ev->tid,200,ans);
949 }else ms_warning("linphone_call_message_new: No request ?");
952 void linphone_registration_faillure(LinphoneCore *lc, eXosip_event_t *ev){
955 const char *reason=NULL;
956 osip_uri_t *requri=osip_message_get_uri(ev->request);
958 LinphoneProxyConfig *cfg;
961 status_code=osip_message_get_status_code(ev->response);
962 reason=osip_message_get_reason_phrase(ev->response);
967 linphone_process_authentication(lc,ev);
970 cfg=linphone_core_get_proxy_config_from_rid(lc,ev->rid);
971 /* if contact is up to date, process the failure, otherwise resend a new register with
972 updated contact first, just in case the faillure is due to incorrect contact */
973 if (linphone_proxy_config_register_again_with_updated_contact(cfg,ev->request,ev->response))
974 return; /*we are retrying with an updated contact*/
975 linphone_proxy_config_process_authentication_failure(lc,status_code,ev);
976 osip_uri_to_str(requri,&ru);
977 msg=ortp_strdup_printf(_("Registration on %s failed: %s"),ru,(reason!=NULL) ? reason : _("no response timeout"));
978 lc->vtable.display_status(lc,msg);
979 gstate_new_state(lc, GSTATE_REG_FAILED, msg);
985 void linphone_registration_success(LinphoneCore *lc,eXosip_event_t *ev){
986 LinphoneProxyConfig *cfg;
987 osip_uri_t *requri=osip_message_get_uri(ev->request);
990 osip_header_t *h=NULL;
992 cfg=linphone_core_get_proxy_config_from_rid(lc,ev->rid);
993 ms_return_if_fail(cfg!=NULL);
995 osip_message_get_expires(ev->request,0,&h);
996 if (h!=NULL && atoi(h->hvalue)!=0){
997 cfg->registered=TRUE;
998 linphone_proxy_config_register_again_with_updated_contact(cfg,ev->request,ev->response);
999 }else cfg->registered=FALSE;
1001 gstate_new_state(lc, GSTATE_REG_OK, NULL);
1003 osip_uri_to_str(requri,&ru);
1004 if (cfg->registered) msg=ms_strdup_printf(_("Registration on %s successful."),ru);
1005 else msg=ms_strdup_printf(_("Unregistration on %s done."),ru);
1006 lc->vtable.display_status(lc,msg);
1011 static bool_t comes_from_local_if(osip_message_t *msg){
1012 osip_via_t *via=NULL;
1013 osip_message_get_via(msg,0,&via);
1016 host=osip_via_get_host(via);
1017 if (strcmp(host,"127.0.0.1")==0 || strcmp(host,"::1")==0){
1018 osip_generic_param_t *param=NULL;
1019 osip_via_param_get_byname(via,"received",¶m);
1020 if (param==NULL) return TRUE;
1021 if (param->gvalue &&
1022 (strcmp(param->gvalue,"127.0.0.1")==0 || strcmp(param->gvalue,"::1")==0)){
1030 static void linphone_inc_update(LinphoneCore *lc, eXosip_event_t *ev){
1031 osip_message_t *msg=NULL;
1032 ms_message("Processing incoming UPDATE");
1034 eXosip_message_build_answer(ev->tid,200,&msg);
1036 eXosip_message_send_answer(ev->tid,200,msg);
1040 static void linphone_other_request(LinphoneCore *lc, eXosip_event_t *ev){
1041 ms_message("in linphone_other_request");
1042 if (ev->request==NULL) return;
1043 if (strcmp(ev->request->sip_method,"MESSAGE")==0){
1044 linphone_core_text_received(lc,ev);
1045 eXosip_message_send_answer(ev->tid,200,NULL);
1046 }else if (strcmp(ev->request->sip_method,"OPTIONS")==0){
1047 osip_message_t *options=NULL;
1048 eXosip_options_build_answer(ev->tid,200,&options);
1049 osip_message_set_allow(options,"INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, SUBSCRIBE, NOTIFY, INFO");
1050 osip_message_set_accept(options,"application/sdp");
1051 eXosip_options_send_answer(ev->tid,200,options);
1052 }else if (strcmp(ev->request->sip_method,"WAKEUP")==0
1053 && comes_from_local_if(ev->request)) {
1054 eXosip_message_send_answer(ev->tid,200,NULL);
1055 ms_message("Receiving WAKEUP request !");
1056 if (lc->vtable.show)
1057 lc->vtable.show(lc);
1058 }else if (strncmp(ev->request->sip_method, "REFER", 5) == 0){
1059 ms_message("Receiving REFER request !");
1060 if (comes_from_local_if(ev->request)) {
1061 osip_header_t *h=NULL;
1062 osip_message_header_get_byname(ev->request,"Refer-To",0,&h);
1063 eXosip_message_send_answer(ev->tid,200,NULL);
1065 if (lc->vtable.refer_received)
1066 lc->vtable.refer_received(lc,h->hvalue);
1069 }else ms_warning("Ignored REFER not coming from this local loopback interface.");
1070 }else if (strncmp(ev->request->sip_method, "UPDATE", 6) == 0){
1071 linphone_inc_update(lc,ev);
1075 osip_message_to_str(ev->request,&tmp,&msglen);
1077 ms_message("Unsupported request received:\n%s",tmp);
1080 /*answer with a 501 Not implemented*/
1081 eXosip_message_send_answer(ev->tid,501,NULL);
1085 void linphone_core_process_event(LinphoneCore *lc,eXosip_event_t *ev)
1088 case EXOSIP_CALL_ANSWERED:
1089 ms_message("CALL_ANSWERED\n");
1090 linphone_call_accepted(lc,ev);
1091 linphone_authentication_ok(lc,ev);
1093 case EXOSIP_CALL_CLOSED:
1094 case EXOSIP_CALL_CANCELLED:
1095 ms_message("CALL_CLOSED or CANCELLED\n");
1096 linphone_call_terminated(lc,ev);
1098 case EXOSIP_CALL_TIMEOUT:
1099 case EXOSIP_CALL_NOANSWER:
1100 ms_message("CALL_TIMEOUT or NOANSWER\n");
1101 linphone_call_failure(lc,ev);
1103 case EXOSIP_CALL_REQUESTFAILURE:
1104 case EXOSIP_CALL_GLOBALFAILURE:
1105 case EXOSIP_CALL_SERVERFAILURE:
1106 ms_message("CALL_REQUESTFAILURE or GLOBALFAILURE or SERVERFAILURE\n");
1107 linphone_call_failure(lc,ev);
1109 case EXOSIP_CALL_INVITE:
1110 ms_message("CALL_NEW\n");
1111 /* CALL_NEW is used twice in qos mode :
1112 * when you receive invite (textinfo = "With QoS" or "Without QoS")
1113 * and when you receive update (textinfo = "New Call") */
1114 linphone_inc_new_call(lc,ev);
1116 case EXOSIP_CALL_REINVITE:
1117 linphone_handle_reinvite(lc,ev);
1119 case EXOSIP_CALL_ACK:
1120 ms_message("CALL_ACK");
1121 linphone_handle_ack(lc,ev);
1123 case EXOSIP_CALL_REDIRECTED:
1124 ms_message("CALL_REDIRECTED");
1125 linphone_call_redirected(lc,ev);
1127 case EXOSIP_CALL_PROCEEDING:
1128 ms_message("CALL_PROCEEDING");
1129 linphone_call_proceeding(lc,ev);
1131 case EXOSIP_CALL_RINGING:
1132 ms_message("CALL_RINGING");
1133 linphone_call_ringing(lc,ev);
1135 case EXOSIP_CALL_MESSAGE_NEW:
1136 ms_message("EXOSIP_CALL_MESSAGE_NEW");
1137 linphone_call_message_new(lc,ev);
1139 case EXOSIP_CALL_MESSAGE_REQUESTFAILURE:
1140 if (ev->did<0 && ev->response &&
1141 (ev->response->status_code==407 || ev->response->status_code==401)){
1142 eXosip_default_action(ev);
1145 case EXOSIP_IN_SUBSCRIPTION_NEW:
1146 ms_message("CALL_SUBSCRIPTION_NEW or UPDATE");
1147 linphone_subscription_new(lc,ev);
1149 case EXOSIP_SUBSCRIPTION_UPDATE:
1151 case EXOSIP_SUBSCRIPTION_NOTIFY:
1152 ms_message("CALL_SUBSCRIPTION_NOTIFY");
1153 linphone_notify_recv(lc,ev);
1155 case EXOSIP_SUBSCRIPTION_ANSWERED:
1156 ms_message("EXOSIP_SUBSCRIPTION_ANSWERED, ev->sid=%i\n",ev->sid);
1157 linphone_subscription_answered(lc,ev);
1159 case EXOSIP_SUBSCRIPTION_CLOSED:
1160 ms_message("EXOSIP_SUBSCRIPTION_CLOSED\n");
1161 linphone_subscription_closed(lc,ev);
1163 case EXOSIP_CALL_RELEASED:
1164 ms_message("CALL_RELEASED\n");
1165 linphone_call_released(lc, ev->cid);
1167 case EXOSIP_REGISTRATION_FAILURE:
1168 ms_message("REGISTRATION_FAILURE\n");
1169 linphone_registration_faillure(lc,ev);
1171 case EXOSIP_REGISTRATION_SUCCESS:
1172 linphone_authentication_ok(lc,ev);
1173 linphone_registration_success(lc,ev);
1175 case EXOSIP_MESSAGE_NEW:
1176 linphone_other_request(lc,ev);
1178 case EXOSIP_MESSAGE_REQUESTFAILURE:
1179 if (ev->response && (ev->response->status_code == 407 || ev->response->status_code == 401)){
1180 /*the user is expected to have registered to the proxy, thus password is known*/
1181 eXosip_default_action(ev);
1185 ms_message("Unhandled exosip event !");
1188 eXosip_event_free(ev);