#include "linphonecore.h"
#include "private.h"
+static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){
+ if (lc->vtable.show)
+ lc->vtable.show(lc);
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,_("Connected."));
+ call->state=LCStateAVRunning;
+ if (lc->ringstream!=NULL){
+ ring_stop(lc->ringstream);
+ lc->ringstream=NULL;
+ }
+ linphone_core_start_media_streams(lc,call);
+}
+
static void call_received(SalOp *h){
+ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
+ char *barmesg;
+ int err;
+ LinphoneCall *call;
+ const char *from,*to;
+ char *tmp;
+ LinphoneAddress *from_parsed;
+
+ /* first check if we can answer successfully to this invite */
+ if (lc->presence_mode!=LINPHONE_STATUS_ONLINE){
+ ms_message("Not present !! presence mode : %d\n",lc->presence_mode);
+ if (lc->presence_mode==LINPHONE_STATUS_BUSY)
+ sal_call_decline(h,SalReasonBusy,NULL);
+ else if (lc->presence_mode==LINPHONE_STATUS_AWAY
+ ||lc->presence_mode==LINPHONE_STATUS_BERIGHTBACK
+ ||lc->presence_mode==LINPHONE_STATUS_ONTHEPHONE
+ ||lc->presence_mode==LINPHONE_STATUS_OUTTOLUNCH
+ ||lc->presence_mode==LINPHONE_STATUS_OFFLINE)
+ sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
+ else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB)
+ sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
+ else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED)
+ sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
+ else
+ sal_call_decline(h,SalReasonBusy,NULL);
+ sal_op_release(op);
+ return;
+ }
+ if (lc->call!=NULL){/*busy*/
+ sal_call_decline(h,SalReasonBusy,NULL);
+ sal_op_release(op);
+ return;
+ }
+ from=sal_op_get_from(op);
+ to=sal_op_get_to(op);
+
+ call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),op);
+ lc->call=call;
+ sal_call_set_local_media_description(op,call->localdesc);
+ call->resultdesc=sal_call_get_final_media_description(op);
+ if (call->resultdesc && sal_media_description_empty(call->resultdesc){
+ sal_call_decline(op,SalReasonMedia,NULL);
+ linphone_call_destroy(call);
+ lc->call=NULL;
+ return;
+ }
+
+ from_parsed=linphone_address_new(sal_op_get_from(op));
+ linphone_address_clean(from_parsed);
+ tmp=linphone_address_as_string(from_parsed);
+ linphone_address_destroy(from_parsed);
+ gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp);
+ barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you."));
+ if (lc->vtable.show) lc->vtable.show(lc);
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,barmesg);
+
+ /* play the ring */
+ if (lc->sound_conf.ring_sndcard!=NULL){
+ ms_message("Starting local ring...");
+ lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
+ }
+ linphone_call_set_state(call,LCStateRinging);
+ sal_call_notify_ringing(op);
+
+ if (lc->vtable.inv_recv) lc->vtable.inv_recv(lc,tmp);
+ ms_free(barmesg);
+ ms_free(tmp);
}
static void call_ringing(SalOp *h){
+ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
+ LinphoneCall *call=lc->call;
+ SalMediaDescription *md;
+ if (call==NULL) return;
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,_("Remote ringing."));
+ md=sal_call_get_final_media_description(h);
+ if (md==NULL){
+ if (lc->ringstream!=NULL) return; /*already ringing !*/
+ if (lc->sound_conf.play_sndcard!=NULL){
+ ms_message("Remote ringing...");
+ lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,lc->sound_conf.play_sndcard);
+ }
+ }else{
+ /*accept early media */
+ if (lc->audiostream->ticker!=NULL){
+ /*streams already started */
+ ms_message("Early media already started.");
+ return;
+ }
+ sal_media_description_ref(md);
+ call->resultdesc=md;
+ if (lc->vtable.show) lc->vtable.show(lc);
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,_("Early media."));
+ gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
+ if (lc->ringstream!=NULL){
+ ring_stop(lc->ringstream);
+ lc->ringstream=NULL;
+ }
+ ms_message("Doing early media...");
+ linphone_core_start_media_streams(lc,call);
+ }
+ call->state=LCStateRinging;
}
-static void call_accepted(SalOp *h){
+static void call_accepted(SalOp *op){
+ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
+ LinphoneCall *call=lc->call;
+ if (call==NULL){
+ ms_warning("No call to accept.");
+ return 0;
+ }
+ if (sal_op_get_user_pointer(op)!=lc->call){
+ ms_warning("call_accepted: ignoring.");
+ return;
+ }
+ if (call->state==LCStateAVRunning){
+ return 0; /*already accepted*/
+ }
+ if (lc->audiostream->ticker!=NULL){
+ /*case where we accepted early media */
+ linphone_core_stop_media_streams(lc,call);
+ linphone_core_init_media_streams(lc,call);
+ }
+ if (call->resultdesc)
+ sal_media_description_unref(call->resultdesc);
+ call->resultdesc=sal_call_get_final_media_description(op);
+ if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
+ gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
+ linphone_connect_incoming(lc,call);
+ }else{
+ /*send a bye*/
+ ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
+ linphone_core_terminate_call(lc,NULL);
+ }
}
static void call_ack(SalOp *h){
+ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
+ LinphoneCall *call=lc->call;
+ if (call==NULL){
+ ms_warning("No call to be ACK'd");
+ return ;
+ }
+ if (sal_op_get_user_pointer(op)!=lc->call){
+ ms_warning("call_ack: ignoring.");
+ return;
+ }
+ if (lc->audiostream->ticker!=NULL){
+ /*case where we accepted early media */
+ linphone_core_stop_media_streams(lc,call);
+ linphone_core_init_media_streams(lc,call);
+ }
+ if (call->resultdesc)
+ sal_media_description_unref(call->resultdesc);
+ call->resultdesc=sal_call_get_final_media_description(op);
+ if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
+ gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL);
+ linphone_connect_incoming(lc,call);
+ }else{
+ /*send a bye*/
+ ms_error("Incompatible SDP response received in ACK, need to abort the call");
+ linphone_core_terminate_call(lc,NULL);
+ }
}
static void call_updated(SalOp *){
+ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
+ linphone_core_stop_media_streams(lc,call);
+ linphone_core_init_media_streams(lc,call);
+ if (call->resultdesc)
+ sal_media_description_unref(call->resultdesc);
+ call->resultdesc=sal_call_get_final_media_description(op);
+ if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
+ linphone_connect_incoming(lc,call);
+ }
}
-static void call_terminated(SalOp *h){
+static void call_terminated(SalOp *h, const char *from){
+ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
+ if (sal_op_get_user_pointer(op)!=lc->call){
+ ms_warning("call_terminated: ignoring.");
+ return;
+ }
+ ms_message("Current call terminated...");
+ if (lc->ringstream!=NULL) {
+ ring_stop(lc->ringstream);
+ lc->ringstream=NULL;
+ }
+ linphone_core_stop_media_streams(lc,lc->call);
+ lc->vtable.show(lc);
+ lc->vtable.display_status(lc,_("Call terminated."));
+ gstate_new_state(lc, GSTATE_CALL_END, NULL);
+ if (lc->vtable.bye_recv!=NULL){
+ LinphoneAddress *addr=linphone_address_new(from);
+ char *tmp;
+ linphone_address_clean(addr);
+ tmp=linphone_address_as_string(from);
+ lc->vtable.bye_recv(lc,tmp);
+ ms_free(tmp);
+ linphone_address_destroy(addr);
+ }
+ linphone_call_destroy(lc->call);
+ lc->call=NULL;
}
-static void call_failure(SalOp *h, SalError error, SalReason reason, const char *details){
+static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details){
+ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
+ const char *reason="";
+ char *msg486=_("User is busy.");
+ char *msg480=_("User is temporarily unavailable.");
+ /*char *retrymsg=_("%s. Retry after %i minute(s).");*/
+ char *msg600=_("User does not want to be disturbed.");
+ char *msg603=_("Call declined.");
+ char* tmpmsg=msg486;
+ int code;
+ LinphoneCall *call=lc->call;
+ if (sal_op_get_user_pointer(op)!=lc->call){
+ ms_warning("call_failure: ignoring.");
+ return;
+ }
+ if (lc->vtable.show) lc->vtable.show(lc);
+
+ if (error==SalErrorNoResponse){
+ if (lc->vtale.display_status)
+ lc->vtable.display_status(lc,_("No response."));
+ }else if (error==SalErrorProtocol){
+ if (lc->vtale.display_status)
+ lc->vtable.display_status(lc, details ? details : _("Error."));
+ }else if (error==SalErrorFailure){
+ switch(sr){
+ case SalReasonDeclined:
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,msg603);
+ break;
+ case SalReasonBusy:
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,msg486);
+ break;
+ case SalReasonRedirect:
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,_("Redirected"));
+ break;
+ case SalReasonTemporarilyUnavailable:
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,msg480);
+ break;
+ case SalReasonNotFound:
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,msg404);
+ break;
+ case SalReasonDoNotDisturb:
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,msg600);
+ break;
+ case SalReasonMedia:
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,_("No common codecs"));
+ break;
+ default:
+ if (lc->vtable.display_status)
+ lc->vtable.display_status(lc,_("Call failed."));
+ }
+ }
+ if (lc->ringstream!=NULL) {
+ ring_stop(lc->ringstream);
+ lc->ringstream=NULL;
+ }
+ linphone_core_stop_media_streams(lc);
+ if (call!=NULL) {
+ linphone_call_destroy(call);
+ gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
+ lc->call=NULL;
+ }
}
static void auth_requested(SalOp *h, const char *realm, const char *username){
+ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
+ LinphoneAuthInfo *ai=linphone_core_find_auth_info(lc);
}
static void auth_success(SalOp *h, const char *realm, const char *username){
linphone_core_notify_all_friends(call->core,LINPHONE_STATUS_ONTHEPHONE);
if (linphone_core_get_firewall_policy(call->core)==LINPHONE_POLICY_USE_STUN)
linphone_core_run_stun_tests(call->core,call);
- call->profile=rtp_profile_new("Call RTP profile");
}
static void discover_mtu(LinphoneCore *lc, const char *remote){
LinphoneCall *call=ms_new0(LinphoneCall,1);
call->dir=LinphoneCallOutgoing;
call->op=sal_op_new(lc->sal);
+ sal_op_set_user_pointer(call->op,lc->call);
call->core=lc;
linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip);
call->localdesc=create_local_media_description (lc,call->localip,
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
call->dir=LinphoneCallIncoming;
+ sal_op_set_user_pointer(op,call);
call->op=op;
call->core=lc;
linphone_core_notify_all_friends(obj->core,obj->core->prev_mode);
linphone_call_log_completed(obj->log,obj);
linphone_core_update_allocated_audio_bandwidth(obj->core);
- if (obj->profile!=NULL) rtp_profile_destroy(obj->profile);
if (obj->op!=NULL) sal_op_release(obj->op);
if (obj->resultdesc!=NULL) sal_media_description_unref(obj->resultdesc);
if (obj->localdesc!=NULL) sal_media_description_unref(obj->localdesc);
lc->rpc_enable = 0;
#endif
lc->sal=sal_init();
+ sal_set_user_pointer(lc->sal,lc);
if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
sal_use_session_timers(lc->sal,200);
}
ms_free(msg);
return;
}
- apply_user_agent(lc->sal);
+ apply_user_agent(lc);
}
/**
if (last_check==0 || (curtime-last_check)>=5){
sal_get_default_local_ip(lc->sal,
lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,
- ,result,LINPHONE_IPADDR_SIZE);
+ result,LINPHONE_IPADDR_SIZE);
if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){
last_status=TRUE;
ms_message("Network is up, registering now (%s)",result);
* other liblinphone methods. In not the case make sure all liblinphone calls are
* serialized with a mutex.
**/
-void linphone_core_iterate(LinphoneCore *lc)
-{
- eXosip_event_t *ev;
- bool_t disconnected=FALSE;
+void linphone_core_iterate(LinphoneCore *lc){
int disconnect_timeout = linphone_core_get_nortp_timeout(lc);
time_t curtime=time(NULL);
int elapsed;
bool_t one_second_elapsed=FALSE;
+ bool_t disconnected=FALSE;
if (curtime-lc->prevtime>=1){
lc->prevtime=curtime;
bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAddress **real_parsed_url, char **route){
enum_lookup_res_t *enumres=NULL;
- osip_to_t *parsed_url=NULL;
+ LinphoneAddress *parsed_url=NULL;
char *enum_domain=NULL;
LinphoneProxyConfig *proxy;
char *tmpurl;
if (real_parsed_url!=NULL) *real_parsed_url=parsed_url;
else linphone_address_destroy(parsed_url);
if (tmproute) *route=ms_strdup(tmproute);
- else *route=guess_route_if_any(lc,*real_parsed_url);
+
return TRUE;
}
/* else we could not do anything with url given by user, so display an error */
if (err<0){
ms_warning("Could not initiate call.");
lc->vtable.display_status(lc,_("could not call"));
+ linphone_core_stop_media_streams(lc,call);
linphone_call_destroy(call);
lc->call=NULL;
- linphone_core_stop_media_streams(lc);
}else gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, url);
goto end;
char *real_url=NULL;
LinphoneAddress *real_parsed_url=NULL;
LinphoneCall *call;
- osip_message_t *msg=NULL;
char *route;
if (!linphone_core_interpret_url(lc,url,&real_parsed_url, &route)){
/* bad url */
}
lc->call=NULL;
real_url=linphone_address_as_string (real_parsed_url);
- eXosip_call_build_refer(call->did, real_url, &msg);
+ sal_refer(call->op,real_url);
ms_free(real_url);
- eXosip_lock();
- eXosip_call_send_request(call->did, msg);
- eXosip_unlock();
return 0;
}
return FALSE;
}
-#ifdef VINCENT_MAURY_RSVP
-/* on=1 for RPC_ENABLE=1...*/
-int linphone_core_set_rpc_mode(LinphoneCore *lc, int on)
-{
- if (on==1)
- printf("RPC_ENABLE set on\n");
- else
- printf("RPC_ENABLE set off\n");
- lc->rpc_enable = (on==1);
- /* need to tell eXosip the new setting */
- if (eXosip_set_rpc_mode (lc->rpc_enable)!=0)
- return -1;
- return 0;
-}
-
-/* on=1 for RSVP_ENABLE=1...*/
-int linphone_core_set_rsvp_mode(LinphoneCore *lc, int on)
-{
- if (on==1)
- printf("RSVP_ENABLE set on\n");
- else
- printf("RSVP_ENABLE set off\n");
- lc->rsvp_enable = (on==1);
- /* need to tell eXosip the new setting */
- if (eXosip_set_rsvp_mode (lc->rsvp_enable)!=0)
- return -1;
- return 0;
-}
-
-/* answer : 1 for yes, 0 for no */
-int linphone_core_change_qos(LinphoneCore *lc, int answer)
-{
- char *sdpmesg;
- if (lc->call==NULL){
- return -1;
- }
-
- if (lc->rsvp_enable && answer==1)
- {
- /* answer is yes, local setting is with qos, so
- * the user chose to continue with no qos ! */
- /* so switch in normal mode : ring and 180 */
- lc->rsvp_enable = 0; /* no more rsvp */
- eXosip_set_rsvp_mode (lc->rsvp_enable);
- /* send 180 */
- eXosip_lock();
- eXosip_answer_call(lc->call->did,180,NULL);
- eXosip_unlock();
- /* play the ring */
- ms_message("Starting local ring...");
- lc->ringstream=ring_start(lc->sound_conf.local_ring,
- 2000,ms_snd_card_manager_get_card(ms_snd_card_manager_get(),lc->sound_conf.ring_sndcard));
- }
- else if (!lc->rsvp_enable && answer==1)
- {
- /* switch to QoS mode on : answer 183 session progress */
- lc->rsvp_enable = 1;
- eXosip_set_rsvp_mode (lc->rsvp_enable);
- /* take the sdp already computed, see osipuacb.c */
- sdpmesg=lc->call->sdpctx->answerstr;
- eXosip_lock();
- eXosip_answer_call_with_body(lc->call->did,183,"application/sdp",sdpmesg);
- eXosip_unlock();
- }
- else
- {
- /* decline offer (603) */
- linphone_core_terminate_call(lc, NULL);
- }
- return 0;
-}
-#endif
-
void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call){
SalMediaDescription *md=call->localdesc;
lc->audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc));
rtp_session_set_transports(lc->audiostream->session,lc->a_rtp,lc->a_rtcp);
#ifdef VIDEO_ENABLED
- if (lc->video_conf.display || lc->video_conf.capture && md->streams[1].port>0)
+ if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].port>0)
lc->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc));
#else
lc->videostream=NULL;
}
}
+static RtpProfile *make_profile(LinphoneCore *lc, SalStreamDescription *desc, int *used_pt){
+ int bw;
+ MSList *elem;
+ RtpProfile *prof=rtp_profile_new("Call profile");
+ bool_t first=TRUE;
+ if (desc->type==SalAudio){
+ bw=get_min_bandwidth(lc->up_audio_bw,desc->bandwidth);
+ }
+ else bw=get_min_bandwidth(lc->up_video_bw,desc->bandwidth);
+ for(elem=desc->payloads;elem!=NULL;elem=elem->next){
+ PayloadType *pt=(PayloadType*)elem->data;
+ if (bw>0) pt->normal_bitrate=bw*1000;
+ else if (desc->type==SalAudio){
+ pt->normal_bitrate=-1;
+ }
+ if (first) {
+ *used_pt=payload_type_get_number(pt);
+ first=FALSE;
+ }
+ if (desc->ptime>0){
+ char tmp[40];
+ snprintf(tmp,sizeof(tmp),"ptime=%i",desc->ptime);
+ payload_type_append_send_fmtp(pt,tmp);
+ }
+ rtp_profile_set_payload(prof,payload_type_get_number(pt),pt);
+ }
+ return prof;
+}
+
void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call){
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
const char *tool="linphone-" LINPHONE_VERSION;
char *cname;
+ int used_pt=-1;
/* adjust rtp jitter compensation. It must be at least the latency of the sound card */
int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp);
if (call->media_start_time==0) call->media_start_time=time(NULL);
- cname=ortp_strdup_printf("%s@%s",me->url->username,me->url->host);
+ cname=linphone_address_as_string_uri_only(me);
{
- StreamParams *audio_params=&call->audio_params;
- if (!lc->use_files){
- MSSndCard *playcard=lc->sound_conf.play_sndcard;
- MSSndCard *captcard=lc->sound_conf.capt_sndcard;
- if (playcard==NULL) {
- ms_warning("No card defined for playback !");
- goto end;
- }
- if (captcard==NULL) {
- ms_warning("No card defined for capture !");
- goto end;
+ SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
+ SalProtoRtpAvp,SalAudio);
+ if (stream){
+ call->audio_profile=make_profile(lc,stream,&used_pt);
+ if (!lc->use_files){
+ MSSndCard *playcard=lc->sound_conf.play_sndcard;
+ MSSndCard *captcard=lc->sound_conf.capt_sndcard;
+ if (playcard==NULL) {
+ ms_warning("No card defined for playback !");
+ goto end;
+ }
+ if (captcard==NULL) {
+ ms_warning("No card defined for capture !");
+ goto end;
+ }
+ audio_stream_start_now(
+ lc->audiostream,
+ call->audio_profile,
+ stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr,
+ stream->port,
+ stream->port+1,
+ used_pt,
+ jitt_comp,
+ playcard,
+ captcard,
+ linphone_core_echo_cancellation_enabled(lc));
+ }else{
+ audio_stream_start_with_files(
+ lc->audiostream,
+ call->audio_profile,
+ stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr,
+ stream->port,
+ stream->port+1,
+ used_pt,
+ 100,
+ lc->play_file,
+ lc->rec_file);
}
- if (audio_params->relay_session_id!=NULL)
- audio_stream_set_relay_session_id(lc->audiostream,audio_params->relay_session_id);
- audio_stream_start_now(
- lc->audiostream,
- call->profile,
- audio_params->remoteaddr,
- audio_params->remoteport,
- audio_params->remotertcpport,
- audio_params->pt,
- jitt_comp,
- playcard,
- captcard,
- linphone_core_echo_cancellation_enabled(lc));
- }else{
- audio_stream_start_with_files(
- lc->audiostream,
- call->profile,
- audio_params->remoteaddr,
- audio_params->remoteport,
- audio_params->remotertcpport,
- audio_params->pt,
- 100,
- lc->play_file,
- lc->rec_file);
- }
- post_configure_audio_streams(lc);
- audio_stream_set_rtcp_information(lc->audiostream, cname, tool);
+ post_configure_audio_streams(lc);
+ audio_stream_set_rtcp_information(lc->audiostream, cname, tool);
+ }else ms_warning("No audio stream defined ?");
}
#ifdef VIDEO_ENABLED
{
+ SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
+ SalProtoRtpAvp,SalVideo);
/* shutdown preview */
if (lc->previewstream!=NULL) {
video_preview_stop(lc->previewstream);
lc->previewstream=NULL;
}
- if (lc->video_conf.display || lc->video_conf.capture) {
- StreamParams *video_params=&call->video_params;
-
- if (video_params->remoteport>0){
- if (video_params->relay_session_id!=NULL)
- video_stream_set_relay_session_id(lc->videostream,video_params->relay_session_id);
- video_stream_set_sent_video_size(lc->videostream,linphone_core_get_preferred_video_size(lc));
- video_stream_enable_self_view(lc->videostream,lc->video_conf.selfview);
- if (lc->video_conf.display && lc->video_conf.capture)
- video_stream_start(lc->videostream,
- call->profile, video_params->remoteaddr, video_params->remoteport,
- video_params->remotertcpport,
- video_params->pt, jitt_comp, lc->video_conf.device);
- else if (lc->video_conf.display)
- video_stream_recv_only_start(lc->videostream,
- call->profile, video_params->remoteaddr, video_params->remoteport,
- video_params->pt, jitt_comp);
- else if (lc->video_conf.capture)
- video_stream_send_only_start(lc->videostream,
- call->profile, video_params->remoteaddr, video_params->remoteport,
- video_params->remotertcpport,
- video_params->pt, jitt_comp, lc->video_conf.device);
- video_stream_set_rtcp_information(lc->videostream, cname,tool);
- }
+ if (stream && (lc->video_conf.display || lc->video_conf.capture)) {
+ const char *addr=stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr;
+ call->video_profile=make_profile(lc,stream,&used_pt);
+ video_stream_set_sent_video_size(lc->videostream,linphone_core_get_preferred_video_size(lc));
+ video_stream_enable_self_view(lc->videostream,lc->video_conf.selfview);
+ if (lc->video_conf.display && lc->video_conf.capture)
+ video_stream_start(lc->videostream,
+ call->video_profile, addr, stream->port,
+ stream->port+1,
+ used_pt, jitt_comp, lc->video_conf.device);
+ else if (lc->video_conf.display)
+ video_stream_recv_only_start(lc->videostream,
+ call->video_profile, addr, stream->port,
+ used_pt, jitt_comp);
+ else if (lc->video_conf.capture)
+ video_stream_send_only_start(lc->videostream,
+ call->video_profile, addr, stream->port,
+ stream->port+1,
+ used_pt, jitt_comp, lc->video_conf.device);
+ video_stream_set_rtcp_information(lc->videostream, cname,tool);
}
}
#endif
goto end;
end:
- ms_free(cname);
- linphone_address_destroy(me);
- lc->call->state=LCStateAVRunning;
+ ms_free(cname);
+ linphone_address_destroy(me);
+ lc->call->state=LCStateAVRunning;
}
-void linphone_core_stop_media_streams(LinphoneCore *lc){
+void linphone_core_stop_media_streams(LinphoneCore *lc, LinphoneCall *call){
if (lc->audiostream!=NULL) {
audio_stream_stop(lc->audiostream);
lc->audiostream=NULL;
}
}
#endif
+ if (call->audio_profile){
+ rtp_profile_destroy(call->audio_profile);
+ call->audio_profile=NULL;
+ }
+ if (call->video_profile){
+ rtp_profile_destroy(call->video_profile);
+ call->video_profile=NULL;
+ }
}
/**
**/
int linphone_core_accept_call(LinphoneCore *lc, const char *url)
{
- char *sdpmesg;
- osip_message_t *msg=NULL;
LinphoneCall *call=lc->call;
- int err;
- bool_t offering=FALSE;
-
+ const char *contact=NULL;
+
if (call==NULL){
return -1;
}
- if (lc->call->state==LCStateAVRunning){
+ if (call->state==LCStateAVRunning){
/*call already accepted*/
return -1;
}
ms_message("ring stopped");
lc->ringstream=NULL;
}
- /* sends a 200 OK */
- err=eXosip_call_build_answer(call->tid,200,&msg);
- if (err<0 || msg==NULL){
- ms_error("Fail to build answer for call: err=%i",err);
- return -1;
- }
- if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
- if (call->supports_session_timers) osip_message_set_supported(msg, "timer");
- }
+
/*try to be best-effort in giving real local or routable contact address,
except when the user choosed to override the ipaddress */
if (linphone_core_get_firewall_policy(lc)!=LINPHONE_POLICY_USE_NAT_ADDRESS)
- fix_contact(lc,msg,call->localip,NULL);
- /*if a sdp answer is computed, send it, else send an offer */
- sdpmesg=call->sdpctx->answerstr;
- if (sdpmesg==NULL){
- offering=TRUE;
- ms_message("generating sdp offer");
- sdpmesg=sdp_context_get_offer(call->sdpctx);
-
- if (sdpmesg==NULL){
- ms_error("fail to generate sdp offer !");
- return -1;
- }
- linphone_set_sdp(msg,sdpmesg);
- linphone_core_init_media_streams(lc);
- }else{
- linphone_set_sdp(msg,sdpmesg);
- }
- eXosip_lock();
- eXosip_call_send_answer(call->tid,200,msg);
- eXosip_unlock();
+ contact=get_fixed_contact(lc,call->localip,NULL);
+ if (contact)
+ sal_op_set_contact(call->op,contact);
+
+ sal_call_accept(call->op);
lc->vtable.display_status(lc,_("Connected."));
gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL);
-
- if (!offering) linphone_core_start_media_streams(lc, lc->call);
+ call->resultdesc=sal_call_get_final_media_description(call->op);
+ if (call->resultdesc){
+ sal_media_description_ref(call->resultdesc);
+ linphone_core_start_media_streams(lc, call);
+ }
ms_message("call answered.");
return 0;
}
return -1;
}
lc->call=NULL;
-
- eXosip_lock();
- eXosip_call_terminate(call->cid,call->did);
- eXosip_unlock();
+ sal_call_terminate(call->op);
/*stop ringing*/
if (lc->ringstream!=NULL) {
ring_stop(lc->ringstream);
lc->ringstream=NULL;
}
- linphone_core_stop_media_streams(lc);
+ linphone_core_stop_media_streams(lc,call);
lc->vtable.display_status(lc,_("Call ended") );
gstate_new_state(lc, GSTATE_CALL_END, NULL);
linphone_call_destroy(call);
const char *contact,
LinphoneOnlineStatus presence_mode)
{
- int contactok=-1;
if (minutes_away>0) lc->minutes_away=minutes_away;
- if (contact!=NULL) {
- osip_from_t *url;
- osip_from_init(&url);
- contactok=osip_from_parse(url,contact);
- if (contactok>=0) {
- ms_message("contact url is correct.");
- }
- osip_from_free(url);
-
- }
- if (contactok>=0){
- if (lc->alt_contact!=NULL) ms_free(lc->alt_contact);
- lc->alt_contact=ms_strdup(contact);
+
+ if (lc->alt_contact!=NULL) {
+ ms_free(lc->alt_contact);
+ lc->alt_contact=NULL;
}
+ if (contact) lc->alt_contact=ms_strdup(contact);
if (lc->presence_mode!=presence_mode){
linphone_core_notify_all_friends(lc,presence_mode);
/*
}
lc->prev_mode=lc->presence_mode;
lc->presence_mode=presence_mode;
-
}
LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc){
* @param dtmf The dtmf name specified as a char, such as '0', '#' etc...
*
**/
-void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf)
+void linphone_core_send_dtmf(LinphoneCore *lc, char dtmf)
{
/*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/
if (linphone_core_get_use_rfc2833_for_dtmf(lc)!=0 || linphone_core_get_use_info_for_dtmf(lc)==0)
ms_error("we cannot send RFC2833 dtmf when we are not in communication");
}
}
- if (linphone_core_get_use_info_for_dtmf(lc)!=0)
- {
- char dtmf_body[1000];
- char clen[10];
- osip_message_t *msg=NULL;
+ if (linphone_core_get_use_info_for_dtmf(lc)!=0){
/* Out of Band DTMF (use INFO method) */
LinphoneCall *call=lc->call;
if (call==NULL){
return;
}
- eXosip_call_build_info(call->did,&msg);
- snprintf(dtmf_body, 999, "Signal=%c\r\nDuration=250\r\n", dtmf);
- osip_message_set_body(msg,dtmf_body,strlen(dtmf_body));
- osip_message_set_content_type(msg,"application/dtmf-relay");
- snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(dtmf_body));
- osip_message_set_content_length(msg,clen);
-
- eXosip_lock();
- eXosip_call_send_request(call->did,msg);
- eXosip_unlock();
+ sal_call_send_dtmf(call->op,dtmf);
}
}
if (err!=0){
wmsg=ortp_strdup_printf(_("Invalid nat address '%s' : %s"),
addr, gai_strerror(err));
- ms_warning(wmsg); // what is this for ?
+ ms_warning("%s",wmsg); // what is this for ?
lc->vtable.display_warning(lc, wmsg);
ms_free(wmsg);
ms_free(tmp);
if (lc->net_conf.firewall_policy==LINPHONE_POLICY_USE_NAT_ADDRESS){
if (tmp!=NULL){
if (!lc->net_conf.nat_sdp_only){
- eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,tmp);
- /* the following does not work in all cases */
- /*
- eXosip_masquerade_contact(tmp,lc->sip_conf.sip_port);
- */
+ sal_masquerade(lc->sal,tmp);
}
ms_free(tmp);
}
else{
- eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,NULL);
- eXosip_masquerade_contact("",0);
+ sal_masquerade(lc->sal,NULL);
}
}
else {
- eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,NULL);
- eXosip_masquerade_contact("",0);
+ sal_masquerade(lc->sal,NULL);
}
}
linphone_proxy_config_edit(cfg); /* to unregister */
}
- if (exosip_running)
- {
+ if (lc->sal){
int i;
- for (i=0;i<20;i++)
- {
- eXosip_event_t *ev;
- while((ev=eXosip_event_wait(0,0))!=NULL){
- linphone_core_process_event(lc,ev);
- }
- eXosip_automatic_action();
+ for (i=0;i<20;i++){
+ sal_iterate(lc->sal);
#ifndef WIN32
- usleep(100000);
+ usleep(100000);
#else
- Sleep(100);
+ Sleep(100);
#endif
- }
- }
+ }
+ }
linphone_proxy_config_write_to_config_file(lc->config,NULL,i); /*mark the end */
linphone_auth_info_write_config(lc->config,ai,i);
}
linphone_auth_info_write_config(lc->config,NULL,i); /* mark the end */
+ sal_uninit(lc->sal);
+ lc->sal=NULL;
}
void rtp_config_uninit(LinphoneCore *lc)
linphone_core_free_payload_types();
ortp_exit();
- eXosip_quit();
exosip_running=FALSE;
gstate_new_state(lc, GSTATE_POWER_OFF, NULL);
}
ms_free(sal);
}
+void sal_set_user_pointer(Sal *sal, void *user_data){
+ sal->up=user_data;
+}
+
+void *sal_get_user_pointer(const Sal *sal){
+ return sal->up;
+}
+
+void sal_masquerade(Sal *ctx, const char *ip){
+ eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,ip);
+}
+
static void unimplemented_stub(){
ms_warning("Unimplemented SAL callback");
}
return 0;
}
+int sal_call_notify_ringing(SalOp *h){
+ eXosip_lock();
+ eXosip_call_send_answer(h->tid,180,NULL);
+ eXosip_unlock();
+ return 0;
+}
+
int sal_call_accept(SalOp * h){
osip_message_t *msg;
+ const char *contact=sal_op_get_contact(h);
/* sends a 200 OK */
int err=eXosip_call_build_answer(h->tid,200,&msg);
if (err<0 || msg==NULL){
if (h->base.root->session_expires!=0){
if (h->supports_session_timers) osip_message_set_supported(msg, "timer");
}
+
+ if (contact) osip_message_set_contact(msg,contact);
if (h->base.local_media){
/*this is the case where we received an invite without SDP*/
return 0;
}
-const SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
+int sal_call_decline(SalOp *h, SalReason reason, const char *redirect){
+ if (reason==SalReasonBusy){
+ eXosip_lock();
+ eXosip_call_send_answer(h->tid,486,NULL);
+ eXosip_unlock();
+ }
+ else if (reason==SalReasonTemporarilyUnavailable){
+ eXosip_lock();
+ eXosip_call_send_answer(h->tid,480,NULL);
+ eXosip_unlock();
+ }else if (reason==SalReasonDoNotDisturb){
+ eXosip_lock();
+ eXosip_call_send_answer(h->tid,600,NULL);
+ eXosip_unlock();
+ }else if (reason==SalReasonMedia){
+ eXosip_lock();
+ eXosip_call_send_answer(h->tid,415,NULL);
+ eXosip_unlock();
+ }else if (redirect!=NULL && reason==SalReasonRedirect){
+ osip_message_t *msg;
+ int code;
+ if (strstr(redirect,"sip:")!=0) code=302;
+ else code=380;
+ eXosip_lock();
+ eXosip_call_build_answer(h->tid,code,&msg);
+ osip_message_set_contact(msg,redirect);
+ eXosip_call_send_answer(h->tid,code,msg);
+ eXosip_unlock();
+ }else sal_call_terminate(h);
+ return 0;
+}
+
+SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
if (h->base.local_media && h->base.remote_media && !h->result){
sdp_process(h);
}
return h->result;
}
+int sal_refer(SalOp *h, const char *refer_to){
+ osip_message_t *msg=NULL;
+ int err=0;
+ eXosip_lock();
+ eXosip_call_build_refer(h->did,refer_to, &msg);
+ if (msg) err=eXosip_call_send_request(h->did, msg);
+ else err=-1;
+ eXosip_unlock();
+ return err;
+}
+
+int sal_call_send_dtmf(SalOp *h, char dtmf){
+ osip_message_t *msg=NULL;
+ char dtmf_body[128];
+ char clen[10];
+
+ eXosip_lock();
+ eXosip_call_build_info(h->did,&msg);
+ if (msg){
+ snprintf(dtmf_body, sizeof(dtmf_body), "Signal=%c\r\nDuration=250\r\n", dtmf);
+ osip_message_set_body(msg,dtmf_body,strlen(dtmf_body));
+ osip_message_set_content_type(msg,"application/dtmf-relay");
+ snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(dtmf_body));
+ osip_message_set_content_length(msg,clen);
+ eXosip_call_send_request(h->did,msg);
+ }
+ eXosip_unlock();
+ return 0;
+}
+
int sal_call_terminate(SalOp *h){
eXosip_lock();
eXosip_call_terminate(h->cid,h->did);
- eXosip_unlock();
eXosip_call_set_reference(h->cid,NULL);
+ eXosip_unlock();
return 0;
}
static void call_terminated(Sal *sal, eXosip_event_t *ev){
SalOp *op;
+ char *from;
op=(SalOp*)ev->external_reference;
if (op==NULL){
ms_warning("Call terminated for already closed call ?");
return;
}
+ osip_from_to_str(ev->request->from,&from);
eXosip_call_set_reference(ev->cid,NULL);
- sal->callbacks.call_terminated(op);
+ op->cid=-1;
+ sal->callbacks.call_terminated(op,from);
+ osip_free(from);
}
static void call_released(Sal *sal, eXosip_event_t *ev){
return;
}
eXosip_call_set_reference(ev->cid,NULL);
- sal->callbacks.call_terminated(op);
+ /*sal->callbacks.call_terminated(op);*/
}
static int get_auth_data(eXosip_event_t *ev, const char **realm, const char **username){
sr=SalReasonNotFound;
break;
case 415:
- error=SalErrorMedia;
+ error=SalErrorFailure;
+ sr=SalReasonMedia;
break;
case 422:
eXosip_default_action(ev);
if (process_event(sal,ev))
eXosip_event_free(ev);
}
- if (sal->automatic_action==0) {
- eXosip_lock();
- eXosip_automatic_refresh();
- eXosip_unlock();
- }
+ eXosip_lock();
+ eXosip_automatic_refresh();
+ eXosip_unlock();
}
return 0;
}