[Top][All Lists]
[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");
- [Linphone-developers] Alternate sdp negotiation support,
Stephen Brooks <=