fix memory leaks, debug SDP nego

This commit is contained in:
Simon Morlat 2010-02-12 10:48:11 +01:00
parent 8a03d2340a
commit 0015964665
9 changed files with 145 additions and 55 deletions

View file

@ -77,6 +77,8 @@ static void call_received(SalOp *h){
lc->call=call;
sal_call_set_local_media_description(h,call->localdesc);
call->resultdesc=sal_call_get_final_media_description(h);
if (call->resultdesc)
sal_media_description_ref(call->resultdesc);
if (call->resultdesc && sal_media_description_empty(call->resultdesc)){
sal_call_decline(h,SalReasonMedia,NULL);
linphone_call_destroy(call);
@ -101,7 +103,7 @@ static void call_received(SalOp *h){
}
linphone_call_set_state(call,LCStateRinging);
sal_call_notify_ringing(h);
linphone_core_init_media_streams(lc,lc->call);
if (lc->vtable.inv_recv) lc->vtable.inv_recv(lc,tmp);
ms_free(barmesg);
ms_free(tmp);
@ -140,6 +142,7 @@ static void call_ringing(SalOp *h){
}
ms_message("Doing early media...");
linphone_core_start_media_streams(lc,call);
call->media_pending=TRUE;
}
call->state=LCStateRinging;
}
@ -166,6 +169,10 @@ static void call_accepted(SalOp *op){
if (call->resultdesc)
sal_media_description_unref(call->resultdesc);
call->resultdesc=sal_call_get_final_media_description(op);
if (call->resultdesc){
sal_media_description_ref(call->resultdesc);
call->media_pending=FALSE;
}
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
linphone_connect_incoming(lc,call);
@ -187,21 +194,26 @@ static void call_ack(SalOp *op){
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);
if (call->media_pending){
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_ref(call->resultdesc);
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);
}
call->media_pending=FALSE;
}
}

View file

@ -137,7 +137,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
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);
sal_op_set_user_pointer(call->op,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,
@ -693,6 +693,37 @@ static bool_t get_codec(LpConfig *config, char* type, int index, PayloadType **r
return TRUE;
}
static const char *codec_pref_order[]={
"speex",
"gsm",
"pcmu",
"pcma",
"H264",
"MP4V-ES",
"theora",
"H263-1998",
"H263",
NULL,
};
static int find_codec_rank(const char *mime){
int i;
for(i=0;codec_pref_order[i]!=NULL;++i){
if (strcasecmp(codec_pref_order[i],mime)==0)
break;
}
return i;
}
static int codec_compare(const PayloadType *a, const PayloadType *b){
int ra,rb;
ra=find_codec_rank(a->mime_type);
rb=find_codec_rank(b->mime_type);
if (ra==rb) return 0;
if (ra>rb) return 1;
if (ra<rb) return -1;
}
static MSList *add_missing_codecs(SalStreamType mtype, MSList *l){
int i;
for(i=0;i<127;++i){
@ -709,11 +740,7 @@ static MSList *add_missing_codecs(SalStreamType mtype, MSList *l){
payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED);
ms_message("Adding new codec %s/%i with fmtp %s",
pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : "");
if (strcasecmp(pt->mime_type,"speex")==0 ||
strcasecmp(pt->mime_type,"MP4V-ES")==0 ||
strcasecmp(pt->mime_type,"H264")==0)
l=ms_list_prepend(l,pt);
else l=ms_list_append(l,pt);
l=ms_list_insert_sorted(l,pt,(int (*)(const void *, const void *))codec_compare);
}
}
}
@ -1733,7 +1760,7 @@ int linphone_core_invite(LinphoneCore *lc, const char *url)
int err=0;
char *route=NULL;
const char *from=NULL;
const char *contact=NULL;
char *contact=NULL;
LinphoneProxyConfig *proxy=NULL;
LinphoneAddress *parsed_url2=NULL;
LinphoneAddress *real_parsed_url=NULL;
@ -1775,13 +1802,16 @@ int linphone_core_invite(LinphoneCore *lc, const char *url)
except when the user choosed to override the ipaddress */
if (linphone_core_get_firewall_policy(lc)!=LINPHONE_POLICY_USE_NAT_ADDRESS)
contact=get_fixed_contact(lc,call->localip,dest_proxy);
if (contact)
if (contact){
sal_op_set_contact(call->op, contact);
ms_free(contact);
}
lc->call=call;
linphone_core_init_media_streams(lc,lc->call);
if (!lc->sip_conf.sdp_200_ack){
call->media_pending=TRUE;
sal_call_set_local_media_description(call->op,call->localdesc);
}
err=sal_call(call->op,from,real_url);
@ -1798,10 +1828,8 @@ int linphone_core_invite(LinphoneCore *lc, const char *url)
lc->call=NULL;
}else gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, url);
goto end;
end:
if (real_url!=NULL) ms_free(real_url);
if (route!=NULL) ms_free(route);
if (real_url!=NULL) ms_free(real_url);
if (route!=NULL) ms_free(route);
return (err<0) ? -1 : 0;
}
@ -1947,9 +1975,9 @@ static void post_configure_audio_streams(LinphoneCore *lc){
}
}
static RtpProfile *make_profile(LinphoneCore *lc, SalStreamDescription *desc, int *used_pt){
static RtpProfile *make_profile(LinphoneCore *lc, const SalStreamDescription *desc, int *used_pt){
int bw;
MSList *elem;
const MSList *elem;
RtpProfile *prof=rtp_profile_new("Call profile");
bool_t first=TRUE;
if (desc->type==SalAudio){
@ -1988,7 +2016,7 @@ void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call){
cname=linphone_address_as_string_uri_only(me);
{
SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
SalProtoRtpAvp,SalAudio);
if (stream){
call->audio_profile=make_profile(lc,stream,&used_pt);
@ -2032,7 +2060,7 @@ void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call){
}
#ifdef VIDEO_ENABLED
{
SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
SalProtoRtpAvp,SalVideo);
/* shutdown preview */
if (lc->previewstream!=NULL) {
@ -2091,10 +2119,12 @@ void linphone_core_stop_media_streams(LinphoneCore *lc, LinphoneCall *call){
}
#endif
if (call->audio_profile){
rtp_profile_clear_all(call->audio_profile);
rtp_profile_destroy(call->audio_profile);
call->audio_profile=NULL;
}
if (call->video_profile){
rtp_profile_clear_all(call->video_profile);
rtp_profile_destroy(call->video_profile);
call->video_profile=NULL;
}
@ -2150,7 +2180,7 @@ int linphone_core_accept_call(LinphoneCore *lc, const char *url)
if (call->resultdesc){
sal_media_description_ref(call->resultdesc);
linphone_core_start_media_streams(lc, call);
}
}else call->media_pending=TRUE;
ms_message("call answered.");
return 0;
}
@ -3160,6 +3190,10 @@ void sip_config_uninit(LinphoneCore *lc)
}
}
ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy);
ms_list_free(config->proxies);
config->proxies=NULL;
linphone_proxy_config_write_to_config_file(lc->config,NULL,i); /*mark the end */
for(elem=lc->auth_info,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
@ -3167,6 +3201,9 @@ void sip_config_uninit(LinphoneCore *lc)
linphone_auth_info_write_config(lc->config,ai,i);
}
linphone_auth_info_write_config(lc->config,NULL,i); /* mark the end */
ms_list_for_each(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy);
ms_list_free(lc->auth_info);
lc->auth_info=NULL;
sal_uninit(lc->sal);
lc->sal=NULL;
}

View file

@ -71,11 +71,9 @@ static MSList *match_payloads(const MSList *local, const MSList *remote){
}
static bool_t only_telephone_event(const MSList *l){
for(;l!=NULL;l=l->next){
PayloadType *p=(PayloadType*)l->data;
if (strcasecmp(p->mime_type,"telephone-event")!=0){
return FALSE;
}
PayloadType *p=(PayloadType*)l->data;
if (strcasecmp(p->mime_type,"telephone-event")!=0){
return FALSE;
}
return TRUE;
}
@ -83,11 +81,15 @@ static bool_t only_telephone_event(const MSList *l){
static void initiate_outgoing(const SalStreamDescription *local_offer,
const SalStreamDescription *remote_answer,
SalStreamDescription *result){
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads);
if (remote_answer->port!=0)
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads);
if (result->payloads && !only_telephone_event(result->payloads)){
strcpy(result->addr,remote_answer->addr);
result->port=remote_answer->port;
result->bandwidth=remote_answer->bandwidth;
result->ptime=remote_answer->ptime;
result->proto=local_offer->proto;
result->type=local_offer->type;
}else{
result->port=0;
}
@ -99,9 +101,12 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
SalStreamDescription *result){
result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads);
if (result->payloads && !only_telephone_event(result->payloads)){
strcpy(result->addr,local_cap->addr);
result->port=local_cap->port;
result->bandwidth=local_cap->bandwidth;
result->ptime=local_cap->ptime;
result->proto=local_cap->proto;
result->type=local_cap->type;
}else{
result->port=0;
}
@ -114,11 +119,19 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
const SalMediaDescription *remote_answer,
SalMediaDescription *result){
int i;
for(i=0;i<local_offer->nstreams;++i){
initiate_outgoing(&local_offer->streams[i],&remote_answer->streams[i],&result->streams[i]);
int i,j;
const SalStreamDescription *ls,*rs;
for(i=0,j=0;i<local_offer->nstreams;++i){
ms_message("Processing for stream %i",i);
ls=&local_offer->streams[i];
rs=sal_media_description_find_stream(remote_answer,ls->proto,ls->type);
if (rs) {
initiate_outgoing(ls,rs,&result->streams[j]);
++j;
}
else ms_warning("No matching stream for %i",i);
}
result->nstreams=local_offer->nstreams;
result->nstreams=j;
strcpy(result->addr,remote_answer->addr);
return 0;
}
@ -131,11 +144,19 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
const SalMediaDescription *remote_offer,
SalMediaDescription *result){
int i;
for(i=0;i<local_capabilities->nstreams;++i){
initiate_incoming(&local_capabilities->streams[i],&remote_offer->streams[i],&result->streams[i]);
int i,j;
const SalStreamDescription *ls,*rs;
for(i=0,j=0;i<remote_offer->nstreams;++i){
rs=&remote_offer->streams[i];
ms_message("Processing for stream %i",i);
ls=sal_media_description_find_stream(local_capabilities,rs->proto,rs->type);
if (ls){
initiate_incoming(ls,rs,&result->streams[j]);
++j;
}
}
result->nstreams=local_capabilities->nstreams;
result->nstreams=j;
strcpy(result->addr,local_capabilities->addr);
return 0;
}

View file

@ -75,6 +75,7 @@ typedef struct _LinphoneCall
time_t start_time; /*time at which the call was initiated*/
time_t media_start_time; /*time at which it was accepted, media streams established*/
LCState state;
bool_t media_pending;
} LinphoneCall;
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to);

View file

@ -36,6 +36,7 @@ static void sal_media_description_destroy(SalMediaDescription *md){
for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;i++){
ms_list_for_each(md->streams[i].payloads,(void (*)(void *))payload_type_destroy);
ms_list_free(md->streams[i].payloads);
md->streams[i].payloads=NULL;
}
ms_free(md);
}
@ -51,11 +52,11 @@ void sal_media_description_unref(SalMediaDescription *md){
}
}
SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
const SalStreamDescription *sal_media_description_find_stream(const SalMediaDescription *md,
SalMediaProto proto, SalStreamType type){
int i;
for(i=0;i<md->nstreams;++i){
SalStreamDescription *ss=&md->streams[i];
const SalStreamDescription *ss=&md->streams[i];
if (ss->proto==proto && ss->type==type) return ss;
}
return NULL;

View file

@ -114,7 +114,7 @@ SalMediaDescription *sal_media_description_new();
void sal_media_description_ref(SalMediaDescription *md);
void sal_media_description_unref(SalMediaDescription *md);
bool_t sal_media_description_empty(SalMediaDescription *md);
SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
const SalStreamDescription *sal_media_description_find_stream(const SalMediaDescription *md,
SalMediaProto proto, SalStreamType type);
/*this structure must be at the first byte of the SalOp structure defined by implementors*/

View file

@ -92,6 +92,7 @@ SalOp * sal_op_new(Sal *sal){
SalOp *op=ms_new(SalOp,1);
__sal_op_init(op,sal);
op->cid=op->did=op->tid=op->rid=op->nid=op->sid=-1;
op->result=NULL;
op->supports_session_timers=FALSE;
op->sdp_offering=TRUE;
op->pending_auth=NULL;
@ -109,11 +110,14 @@ void sal_op_release(SalOp *op){
sal_remove_register(op->base.root,op->rid);
}
if (op->cid!=-1){
ms_message("Cleaning cid %i",op->cid);
eXosip_call_set_reference(op->cid,NULL);
}
if (op->pending_auth){
sal_remove_pending_auth(op->base.root,op);
}
if (op->result)
sal_media_description_unref(op->result);
__sal_op_free(op);
}
@ -280,6 +284,7 @@ static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *de
}
static void sdp_process(SalOp *h){
ms_message("Doing SDP offer/answer process");
if (h->result){
sal_media_description_unref(h->result);
}
@ -323,8 +328,10 @@ int sal_call(SalOp *h, const char *from, const char *to){
ms_error("Could not create call.");
return -1;
}
if (h->base.contact)
if (h->base.contact){
osip_list_special_free(&invite->contacts,(void (*)(void*))osip_contact_free);
osip_message_set_contact(invite,h->base.contact);
}
if (h->base.root->session_expires!=0){
osip_message_set_header(invite, "Session-expires", "200");
osip_message_set_supported(invite, "timer");
@ -472,6 +479,7 @@ void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){
eXosip_unlock();
eXosip_clear_authentication_info();
eXosip_event_free(h->pending_auth);
sal_remove_pending_auth(sal_op_get_sal(h),h);
h->pending_auth=NULL;
}
}
@ -482,6 +490,7 @@ static void inc_new_call(Sal *sal, eXosip_event_t *ev){
char *tmp;
sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
if (sdp){
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
sdp_message_free(sdp);
@ -635,12 +644,14 @@ static void call_terminated(Sal *sal, eXosip_event_t *ev){
static void call_released(Sal *sal, eXosip_event_t *ev){
SalOp *op;
char *from;
op=(SalOp*)ev->external_reference;
if (op==NULL){
return;
}
eXosip_call_set_reference(ev->cid,NULL);
/*sal->callbacks.call_terminated(op);*/
op->cid=-1;
if (op->did==-1)
sal->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,NULL);
}
static int get_auth_data(eXosip_event_t *ev, const char **realm, const char **username){
@ -1160,7 +1171,7 @@ static bool_t process_event(Sal *sal, eXosip_event_t *ev){
}
break;
default:
ms_message("Unhandled exosip event !");
ms_message("Unhandled exosip event ! %i");
break;
}
return TRUE;

View file

@ -252,6 +252,9 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
addr = sdp_message_c_addr_get (msg, i, 0);
if (addr != NULL)
strncpy(stream->addr,addr,sizeof(stream->addr));
if (port)
stream->port=atoi(port);
stream->ptime=_sdp_message_get_a_ptime(msg,i);
if (strcasecmp("audio", mtype) == 0){
stream->type=SalAudio;
@ -273,7 +276,11 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
/* get the fmtp, if any */
fmtp=sdp_message_a_attr_value_get_with_pt(msg, i, ptn,"fmtp");
payload_type_set_send_fmtp(pt,fmtp);
stream->payloads=ms_list_append(stream->payloads,pt);
ms_message("Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate,
pt->send_fmtp ? pt->send_fmtp : "");
}
}
desc->nstreams=i;
return 0;
}

@ -1 +1 @@
Subproject commit 8dae09b11ee8a0fe29674944b207b5e06fb0f4ed
Subproject commit ae7dfdcaea6d5fe6d4f44a6247b4ca506799e379