linphone-developers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Linphone-developers] Alternate sdp negotiation support


From: Stephen Brooks
Subject: [Linphone-developers] Alternate sdp negotiation support
Date: Mon, 27 Nov 2006 09:33:15 +0000
User-agent: Thunderbird 1.5.0.8 (X11/20061117)

Hi,

Please find attached a patch to add the alternate sdp negotiation process (aka third party call control or delayed media) for incoming calls against linphone 1.3.4. In the linphone TODO this should satisfy "support for incoming invites without SDP"

Prior to this if linphone received an incoming call INVITE with no sdp offer you would see the logs give the error "No sdp body !" and linphone would decline the call with a SIP "603 Decline" message.

RFC 3621 Section 13.2.1 page 79 details the appropriate response. In a nutshell if there's no sdp offer in the INVITE from the caller then the recipient must respond with an offer in its 200 OK (typically when the recipient answers) and the caller then sends the sdp answer in its ACK and the media session can then be established.

This was developed using the very useful SIPp utility and in particular it's 3rd Party Call Control (3pcc) test scenario. This has been successfully used informally via Cisco Call Manager 5.1

http://sipp.sourceforge.net/doc1.1/reference.html#3PCC
In the referenced diagram the three SIPp instances ran on my desktop as B to call my test unit as A

        B client
        ./sipp -mp 6002 -sn 3pcc-B -p 5062 -m 1 -trace_msg -trace_err

        B controller
./sipp -mp 6006 -sn 3pcc-C-B <B ip>:5062 -p 5064 -m 1 -3pcc <B ip>:5080 -trace_msg -trace_err

        A controller
./sipp -mp 6010 -sn 3pcc-C-A <A ip>:5060 -p 5066 -m 1 -3pcc <B ip>:5080 -trace_msg -trace_err

        A client
        Patched linphonec

        Hope this is of use :)

Regards,
--
Stephen Brooks <address@hidden>      Digital Depot, Thomas Street
Senior Software Engineer                            Dublin 8, Ireland
Lincor Solutions Ltd.                          Ph: +353 (0) 1 4893683
--- linphone-1.3.4/coreapi/linphonecore.c.fix   2006-11-27 08:30:06.000000000 
+0000
+++ linphone-1.3.4/coreapi/linphonecore.c       2006-11-27 08:54:37.000000000 
+0000
@@ -1414,25 +1414,36 @@
 int linphone_core_accept_call(LinphoneCore *lc, const char *url)
 {
        char *sdpmesg;
+       char local_sdp_port[10];
        
        if (lc->call==NULL){
                return -1;
        }
-       
-       
+
        /*stop ringing */
        if (lc->ringstream!=NULL) {
                ring_stop(lc->ringstream);
                lc->ringstream=NULL;
        }
-       /* sends a 200 OK */
-       sdpmesg=lc->call->sdpctx->answerstr;    /* takes the sdp already 
computed*/
-       eXosip_lock();
-       
eXosip_answer_call_with_body(lc->call->did,200,"application/sdp",sdpmesg);
-       eXosip_unlock();
-       lc->vtable.display_status(lc,connected);
-       
-       linphone_core_start_media_streams(lc, lc->call);
+
+       if (lc->call->sdpctx->negoc_status == 0) {
+               /* sends a 200 OK, sdp offer will be added */
+               snprintf(local_sdp_port, sizeof(local_sdp_port), "%d", 
lp_config_get_int(lc->config,"rtp","audio_rtp_port",7078));
+               eXosip_lock();
+               eXosip_answer_call(lc->call->did,200,local_sdp_port);
+               eXosip_unlock();
+       }
+       else {
+               /* sends a 200 OK */
+               sdpmesg=lc->call->sdpctx->answerstr;    /* takes the sdp 
already computed*/
+               eXosip_lock();
+               
eXosip_answer_call_with_body(lc->call->did,200,"application/sdp",sdpmesg);
+               eXosip_unlock();
+               lc->vtable.display_status(lc,connected);
+               
+               linphone_core_start_media_streams(lc, lc->call);
+       }
+
        return 0;
 }
 
--- linphone-1.3.4/coreapi/exevents.c.fix       2006-11-27 08:30:26.000000000 
+0000
+++ linphone-1.3.4/coreapi/exevents.c   2006-11-27 08:56:32.000000000 +0000
@@ -196,9 +196,39 @@
 
 extern sdp_handler_t linphone_sdphandler;
 
+void start_local_ring(LinphoneCore *lc, int did)
+{
+       eXosip_lock();
+       eXosip_answer_call(did,180,NULL);
+       eXosip_unlock();
+       /* play the ring */
+       if (try_open_dsp(lc)>0){
+               g_message("Starting local ring...");
+               lc->ringstream=ring_start(lc->sound_conf.local_ring,
+                               
2,snd_card_manager_get_card(snd_card_manager,lc->sound_conf.ring_sndcard));
+       }else g_warning("Could not start local ring !");
+}
+
+void set_state_ringing(LinphoneCore *lc, osip_from_t *from_url)
+{
+       linphone_call_set_state(lc->call,LCStateRinging);
+       {
+               char *barmesg,*tmp;
+
+               if (from_2char_without_params(from_url,&tmp)==0){
+                       barmesg=g_strdup_printf("%s %s",tmp,contacted);
+                       lc->vtable.show(lc);
+                       lc->vtable.display_status(lc,barmesg);
+                       lc->vtable.inv_recv(lc,tmp);
+                       g_free(barmesg);
+                       osip_free(tmp);
+               }
+       }
+}
+
 int linphone_inc_new_call(LinphoneCore *lc, eXosip_event_t *ev)
 {
-       char *barmesg,*answer;
+       char *answer;
        int status=200;
        sdp_context_t *ctx=NULL;
        osip_from_t *from_url=NULL;
@@ -208,7 +238,7 @@
        char *sdp_body=ev->sdp_body;
 #ifdef VINCENT_MAURY_RSVP
        char *textinfo=ev->textinfo;
- #endif
+#endif
        
        osip_from_init(&from_url);
        osip_from_parse(from_url,from);
@@ -257,102 +287,120 @@
                eXosip_unlock();
                goto end;
        }
-       if (strlen(sdp_body)==0){
-               g_warning("No sdp body !");
-               eXosip_lock();
-               eXosip_answer_call(did,603,NULL);
-               eXosip_unlock();
-               goto end;
+       if (strlen(sdp_body)==0) {
+               g_warning("No sdp body !  Using alternate sdp negociation.");
+               // initialise call session
+               
lc->call=linphone_call_new_incoming(lc,from,ev->local_uri,cid,did);
+               // sending progress messages and start ringing
+               start_local_ring(lc,did);
+               set_state_ringing(lc,from_url);
        }
+       else {
 #ifdef VINCENT_MAURY_RSVP
-       /* make the negotiation only once at the first invite received */
-       if (strcmp(textinfo,"New Call")!=0)
-       {
-               
+               /* make the negotiation only once at the first invite received 
*/
+               if (strcmp(textinfo,"New Call")!=0)
+               {
+                       
+                       
lc->call=linphone_call_new_incoming(lc,from,ev->local_uri,cid,did);
+                       ctx=lc->call->sdpctx;
+                       /* get the result of the negociation */
+                       answer=sdp_context_get_answer(ctx,sdp_body);
+                       status=sdp_context_get_status(ctx);
+               }
+#else
                
lc->call=linphone_call_new_incoming(lc,from,ev->local_uri,cid,did);
                ctx=lc->call->sdpctx;
                /* get the result of the negociation */
                answer=sdp_context_get_answer(ctx,sdp_body);
                status=sdp_context_get_status(ctx);
-       }
-#else
-       lc->call=linphone_call_new_incoming(lc,from,ev->local_uri,cid,did);
-       ctx=lc->call->sdpctx;
-       /* get the result of the negociation */
-       answer=sdp_context_get_answer(ctx,sdp_body);
-       status=sdp_context_get_status(ctx);
 
 #endif
-       switch(status)
-       {
-               case 200:
-                       /* vérification de la qos */
+               switch(status)
+               {
+                       case 200:
+                               /* vérification de la qos */
 #ifdef VINCENT_MAURY_RSVP
-                       if (strcmp(textinfo,"With QoS")==0 && !lc->rsvp_enable)
-                               /* caller has QoS, we don't */
-                               lc->vtable.display_yes_no(lc,strdup(textinfo));
-                       else if (strcmp(textinfo,"Without QoS")==0 && 
lc->rsvp_enable)
-                               /* caller doesn't have QoS, we do ! */
-                               lc->vtable.display_yes_no(lc,strdup(textinfo));
-                       else if (strcmp(textinfo,"With QoS")==0 && 
lc->rsvp_enable)
-                       {
-                               /* we agree on With QoS */
-                               eXosip_lock();
-                               
eXosip_answer_call_with_body(did,183,"application/sdp",answer);
-                               eXosip_unlock();
-                       }
-                       else if (strcmp(textinfo,"Without QoS")==0 && 
!lc->rsvp_enable ||
-                                       strcmp(textinfo,"New Call")==0)
-                       {
-                               /* we agree on Without QoS */
-                               eXosip_lock();
-                               eXosip_answer_call(did,180,NULL);
-                               eXosip_unlock();
-                               /* play the ring */
-                               if (try_open_dsp(lc)>0){
-                                       g_message("Starting local ring...");
-                                       
lc->ringstream=ring_start(lc->sound_conf.local_ring,
-                                                       
2,snd_card_manager_get_card(snd_card_manager,lc->sound_conf.ring_sndcard));
+                               if (strcmp(textinfo,"With QoS")==0 && 
!lc->rsvp_enable)
+                                       /* caller has QoS, we don't */
+                                       
lc->vtable.display_yes_no(lc,strdup(textinfo));
+                               else if (strcmp(textinfo,"Without QoS")==0 && 
lc->rsvp_enable)
+                                       /* caller doesn't have QoS, we do ! */
+                                       
lc->vtable.display_yes_no(lc,strdup(textinfo));
+                               else if (strcmp(textinfo,"With QoS")==0 && 
lc->rsvp_enable)
+                               {
+                                       /* we agree on With QoS */
+                                       eXosip_lock();
+                                       
eXosip_answer_call_with_body(did,183,"application/sdp",answer);
+                                       eXosip_unlock();
                                }
-                       }
-#else
-                       eXosip_lock();
-                       eXosip_answer_call(did,180,NULL);
-                       eXosip_unlock();
-                       /* play the ring */
-                       if (try_open_dsp(lc)>0){
-                               g_message("Starting local ring...");
-                               
lc->ringstream=ring_start(lc->sound_conf.local_ring,
-                                               
2,snd_card_manager_get_card(snd_card_manager,lc->sound_conf.ring_sndcard));
-                       }else g_warning("Could not start local ring !");
-#endif
-                       linphone_call_set_state(lc->call,LCStateRinging);
-                       {
-                               char *tmp;
-                               if 
(from_2char_without_params(from_url,&tmp)==0){
-                                       barmesg=g_strdup_printf("%s 
%s",tmp,contacted);
-                                       lc->vtable.show(lc);
-                                       lc->vtable.display_status(lc,barmesg);
-                                       lc->vtable.inv_recv(lc,tmp);
-                                       g_free(barmesg);
-                                       osip_free(tmp);
+                               else if (strcmp(textinfo,"Without QoS")==0 && 
!lc->rsvp_enable ||
+                                               strcmp(textinfo,"New Call")==0)
+                               {
+                                       /* we agree on Without QoS */
+                                       eXosip_lock();
+                                       eXosip_answer_call(did,180,NULL);
+                                       eXosip_unlock();
+                                       /* play the ring */
+                                       if (try_open_dsp(lc)>0){
+                                               g_message("Starting local 
ring...");
+                                               
lc->ringstream=ring_start(lc->sound_conf.local_ring,
+                                                               
2,snd_card_manager_get_card(snd_card_manager,lc->sound_conf.ring_sndcard));
+                                       }
                                }
-                       }
-               break;
-               default:        
-                       if (status==-1) status=415;
-                       g_warning("Error during sdp negociation. status : 
%d\n",status);
-                       eXosip_lock();
-                       eXosip_answer_call(did,status,NULL);
-                       eXosip_unlock();
-                       linphone_call_destroy(lc->call);
-                       lc->call=NULL;
+#else                          
+                               start_local_ring(lc,did);
+#endif
+                               set_state_ringing(lc,from_url);
+                       break;
+                       default:        
+                               if (status==-1) status=415;
+                               g_warning("Error during sdp negociation. status 
: %d\n",status);
+                               eXosip_lock();
+                               eXosip_answer_call(did,status,NULL);
+                               eXosip_unlock();
+                               linphone_call_destroy(lc->call);
+                               lc->call=NULL;
+               }
        }
        end:
                osip_from_free(from_url);
        return 0;
 }
 
+void linphone_inc_ack_call(LinphoneCore *lc, eXosip_event_t *ev) {
+       char *answer;
+       int status=200;
+       sdp_context_t *ctx=NULL;
+       int cid=ev->cid;
+       int did=ev->did;
+       char *from=ev->remote_uri;
+       char *sdp_body=ev->sdp_body;
+       osip_from_t *me;
+
+       if (lc->call->sdpctx->negoc_status == 0 && strlen(sdp_body) > 0) {
+               g_message("Alternative sdp negociation answer received");
+               me=linphone_core_get_primary_contact_parsed(lc);
+               ctx=lc->call->sdpctx;
+               /* get the result of the negociation */
+               answer=sdp_context_get_answer(ctx,sdp_body);
+               status=sdp_context_get_status(ctx);
+               switch(status) {
+                       case 200:
+                               lc->vtable.display_status(lc,connected);
+                               linphone_core_start_media_streams(lc, lc->call);
+                               break;
+                       default:
+                               if (status==-1) status=415;
+                               g_warning("Error during sdp negociation. status 
: %d\n",status);
+                               eXosip_lock();
+                               eXosip_answer_call(did,status,NULL);
+                               eXosip_unlock();
+                               linphone_call_destroy(lc->call);
+                               lc->call=NULL;
+               }
+       }
+}
+
 void linphone_do_automatic_redirect(LinphoneCore *lc, const char *contact){
        char *msg=g_strdup_printf(_("Redirected to %s..."),contact);
        lc->vtable.display_status(lc,msg);
@@ -730,6 +778,7 @@
                        break;
                case EXOSIP_CALL_ACK:
                        g_message("CALL_ACK\n");
+                       linphone_inc_ack_call(lc,ev);
                        break;
                case EXOSIP_CALL_REDIRECTED:
                        g_message("CALL_REDIRECTED\n");

reply via email to

[Prev in Thread] Current Thread [Next in Thread]