From 0015964665d0b3865abd48c6e41e592babf3ce55 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 12 Feb 2010 10:48:11 +0100 Subject: [PATCH] fix memory leaks, debug SDP nego --- coreapi/callbacks.c | 44 +++++++++++++++--------- coreapi/linphonecore.c | 71 +++++++++++++++++++++++++++++---------- coreapi/offeranswer.c | 49 +++++++++++++++++++-------- coreapi/private.h | 1 + coreapi/sal.c | 5 +-- coreapi/sal.h | 2 +- coreapi/sal_eXosip2.c | 19 ++++++++--- coreapi/sal_eXosip2_sdp.c | 7 ++++ mediastreamer2 | 2 +- 9 files changed, 145 insertions(+), 55 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 5b5bcad86..f6c5f034a 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -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; } } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 9dd4cd9ce..6ccac20b5 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -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 (ramime_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; } diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index 3e872c6e1..f4b914381 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -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;instreams;++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;instreams;++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;instreams;++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;instreams;++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; } diff --git a/coreapi/private.h b/coreapi/private.h index abea80b82..bcd914439 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -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); diff --git a/coreapi/sal.c b/coreapi/sal.c index d33124e8a..ae432d565 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -36,6 +36,7 @@ static void sal_media_description_destroy(SalMediaDescription *md){ for(i=0;istreams[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;instreams;++i){ - SalStreamDescription *ss=&md->streams[i]; + const SalStreamDescription *ss=&md->streams[i]; if (ss->proto==proto && ss->type==type) return ss; } return NULL; diff --git a/coreapi/sal.h b/coreapi/sal.h index 5dc91efd7..eb8042361 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -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*/ diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c index ad8e5c191..d3a6d224b 100644 --- a/coreapi/sal_eXosip2.c +++ b/coreapi/sal_eXosip2.c @@ -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; diff --git a/coreapi/sal_eXosip2_sdp.c b/coreapi/sal_eXosip2_sdp.c index 1189477d6..3dfde45d3 100644 --- a/coreapi/sal_eXosip2_sdp.c +++ b/coreapi/sal_eXosip2_sdp.c @@ -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; } diff --git a/mediastreamer2 b/mediastreamer2 index 8dae09b11..ae7dfdcae 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 8dae09b11ee8a0fe29674944b207b5e06fb0f4ed +Subproject commit ae7dfdcaea6d5fe6d4f44a6247b4ca506799e379