Commit 00c3f621 authored by Simon Morlat's avatar Simon Morlat
Browse files

add custom header test

fix memory leaks
fix invalid reads
parent 18d21119
linphone-3.7...??
* multiple SIP transports simualtaneously now allowed
* IP dual stack: can use IPv6 and IPv4 simultaneously
* fully asynchronous behavior: no more lengthly DNS or connections
linphone-3.xxx --
* fix bug in zRTP support (upgrade required)
*
......
......@@ -193,6 +193,8 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev
if (!op->base.call_id) {
op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_call_id_t))));
}
sal_op_assign_recv_headers(op,(belle_sip_message_t*)req);
if (op->callbacks.process_request_event) {
op->callbacks.process_request_event(op,event);
} else {
......@@ -702,6 +704,7 @@ SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name,
if (msg==NULL){
msg=(belle_sip_message_t*)belle_sip_request_new();
belle_sip_object_ref(msg);
}
h=BELLE_SIP_HEADER(belle_sip_header_extension_parse(tmp));
ms_free(tmp);
......@@ -714,19 +717,15 @@ SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name,
}
const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name){
belle_sip_header_t *h=belle_sip_message_get_header((belle_sip_message_t*)ch,name);
if (h){
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_extension_t)){
return belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(h));
}else{
char *tmp=belle_sip_object_to_string((belle_sip_object_t*)h);
char *p=tmp+strlen(belle_sip_header_get_name(h))+1+1; /*header name + : + ' '*/
char *ret=belle_sip_strdup(p);
belle_sip_free(tmp);
/*TODO: fix memory leak here*/
return ret;
if (ch){
belle_sip_header_t *h=belle_sip_message_get_header((belle_sip_message_t*)ch,name);
if (h){
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_extension_t)){
return belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(h));
}else{
return belle_sip_header_get_unparsed_value(h);
}
}
}
return NULL;
......@@ -740,22 +739,11 @@ SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch){
return (SalCustomHeader*)belle_sip_object_ref((belle_sip_message_t*)ch);
}
const SalCustomHeader *sal_op_get_custom_header(SalOp *op){
const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op){
SalOpBase *b=(SalOpBase *)op;
return b->custom_headers;
return b->recv_custom_headers;
}
/*
* Warning: this function takes owneship of the custom headers
*/
void sal_op_set_custom_header(SalOp *op, SalCustomHeader* ch){
SalOpBase *b=(SalOpBase *)op;
if (b->custom_headers){
sal_custom_header_free(b->custom_headers);
b->custom_headers=NULL;
}
if (ch) belle_sip_object_ref((belle_sip_message_t*)ch);
b->custom_headers=ch;
}
......@@ -128,5 +128,6 @@ void sal_add_pending_auth(Sal *sal, SalOp *op);
void sal_add_presence_info(belle_sip_message_t *notify, SalPresenceStatus online_status);
void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming);
#endif /* SAL_IMPL_H_ */
......@@ -102,7 +102,11 @@ static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* ses
}
}
static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription *desc){
return set_sdp(msg,media_description_to_sdp(desc));
int err;
belle_sdp_session_description_t *sdp=media_description_to_sdp(desc);
err=set_sdp(msg,sdp);
belle_sip_object_unref(sdp);
return err;
}
static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
......@@ -261,6 +265,7 @@ static void call_response_event(void *op_base, const belle_sip_response_event_t
}
if (op->sdp_answer){
set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer);
belle_sip_object_unref(op->sdp_answer);
op->sdp_answer=NULL;
}
belle_sip_dialog_send_ack(op->dialog,ack);
......@@ -571,6 +576,7 @@ static void handle_offer_answer_response(SalOp* op, belle_sip_response_t* respon
if (op->sdp_answer==NULL) sdp_process(op);
if (op->sdp_answer){
set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer);
belle_sip_object_unref(op->sdp_answer);
op->sdp_answer=NULL;
}
}
......
......@@ -30,7 +30,9 @@ SalOp * sal_op_new(Sal *sal){
void sal_op_release(SalOp *op){
op->state=SalOpStateTerminated;
sal_op_set_user_pointer(op,NULL);/*mandatory because releasing op doesn not mean freeing op. Make sure back pointer will not be used later*/
if (op->refresher) belle_sip_refresher_stop(op->refresher);
if (op->refresher) {
belle_sip_refresher_stop(op->refresher);
}
sal_op_unref(op);
}
void sal_op_release_impl(SalOp *op){
......@@ -42,6 +44,8 @@ void sal_op_release_impl(SalOp *op){
belle_sip_object_unref(op->refresher);
op->refresher=NULL;
}
if (op->result)
sal_media_description_unref(op->result);
if(op->replaces) belle_sip_object_unref(op->replaces);
if(op->referred_by) belle_sip_object_unref(op->referred_by);
......@@ -146,6 +150,19 @@ void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) {
sal_op_send_request(op,request);
}
static void add_headers(belle_sip_header_t *h, belle_sip_message_t *msg){
if (belle_sip_message_get_header(msg,belle_sip_header_get_name(h))==NULL)
belle_sip_message_add_header(msg,h);
}
static void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg){
if (op->base.sent_custom_headers){
belle_sip_message_t *ch=(belle_sip_message_t*)op->base.sent_custom_headers;
belle_sip_list_t *l=belle_sip_message_get_all_headers(ch);
belle_sip_list_for_each2(l,(void (*)(void *, void *))add_headers,msg);
belle_sip_list_free(l);
}
}
static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request,bool_t add_contact) {
belle_sip_client_transaction_t* client_transaction;
......@@ -153,6 +170,8 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
belle_sip_uri_t* outbound_proxy=NULL;
belle_sip_header_contact_t* contact;
_sal_op_add_custom_headers(op, (belle_sip_message_t*)request);
if (!op->dialog || belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_NULL) {
/*don't put route header if dialog is in confirmed state*/
const MSList *elem=sal_op_get_route_addresses(op);
......@@ -316,10 +335,9 @@ void* sal_op_unref(SalOp* op) {
}
return NULL;
}
int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener ) {
if (sal_op_send_request_with_expires(op,req,expires)) {
return -1;
} else {
if (sal_op_send_request_with_expires(op,req,expires)==0) {
if (op->refresher) {
belle_sip_refresher_stop(op->refresher);
belle_sip_object_unref(op->refresher);
......@@ -332,6 +350,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp
return -1;
}
}
return -1;
}
const char* sal_op_state_to_string(const SalOpSate_t value) {
......@@ -344,3 +363,27 @@ const char* sal_op_state_to_string(const SalOpSate_t value) {
return "Unknon";
}
}
/*
* Warning: this function takes owneship of the custom headers
*/
void sal_op_set_sent_custom_header(SalOp *op, SalCustomHeader* ch){
SalOpBase *b=(SalOpBase *)op;
if (b->sent_custom_headers){
sal_custom_header_free(b->sent_custom_headers);
b->sent_custom_headers=NULL;
}
if (ch) belle_sip_object_ref((belle_sip_message_t*)ch);
b->sent_custom_headers=ch;
}
void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming){
if (incoming) belle_sip_object_ref(incoming);
if (op->base.recv_custom_headers){
belle_sip_object_unref(op->base.recv_custom_headers);
op->base.recv_custom_headers=NULL;
}
if (incoming){
op->base.recv_custom_headers=(SalCustomHeader*)incoming;
}
}
......@@ -457,6 +457,7 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S
unsigned int componentID;
int offset;
const char *ptr = value;
const char *endptr=value+strlen(ptr);
while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) {
if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) {
SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1];
......@@ -464,7 +465,9 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S
remote_candidate->port = candidate.port;
}
ptr += offset;
if (ptr[offset] == ' ') ptr += 1;
if (ptr<endptr){
if (ptr[offset] == ' ') ptr += 1;
}else break;
}
} else if ((keywordcmp("ice-ufrag", att_name) == 0) && (value != NULL)) {
strncpy(stream->ice_ufrag, value, sizeof(stream->ice_ufrag));
......
......@@ -97,7 +97,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
linphone_transfer_routes_to_op(routes,op);
sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/
if (msg->custom_headers){
sal_op_set_custom_header(op,msg->custom_headers);
sal_op_set_sent_custom_header(op,msg->custom_headers);
msg->custom_headers=NULL; /*transfered to the SalOp*/
}
}
......@@ -186,7 +186,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
msg->time=sal_msg->time;
msg->state=LinphoneChatMessageStateDelivered;
msg->is_read=FALSE;
ch=sal_op_get_custom_header(op);
ch=sal_op_get_recv_custom_header(op);
if (ch) msg->custom_headers=sal_custom_header_clone(ch);
if (sal_msg->url) {
......
......@@ -478,8 +478,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
linphone_core_get_local_ip(lc,NULL,call->localip);
linphone_call_init_common(call,from,to);
_linphone_call_params_copy(&call->params,params);
sal_op_set_custom_header(call->op,call->params.custom_headers);
call->params.custom_headers=NULL;
sal_op_set_sent_custom_header(call->op,call->params.custom_headers);
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
call->ice_session = ice_session_new();
......@@ -828,7 +827,7 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
cp->low_bandwidth=TRUE;
}
}
cp->custom_headers=(SalCustomHeader*)sal_op_get_custom_header(call->op);
cp->custom_headers=(SalCustomHeader*)sal_op_get_recv_custom_header(call->op);
return cp;
}
}
......
......@@ -461,8 +461,10 @@ void __sal_op_free(SalOp *op){
ms_list_for_each(b->route_addresses,(void (*)(void*)) sal_address_destroy);
b->route_addresses=ms_list_free(b->route_addresses);
}
if (b->custom_headers)
sal_custom_header_free(b->custom_headers);
if (b->recv_custom_headers)
sal_custom_header_free(b->recv_custom_headers);
if (b->sent_custom_headers)
sal_custom_header_free(b->sent_custom_headers);
ms_free(op);
}
......
......@@ -249,7 +249,8 @@ typedef struct SalOpBase{
const char* call_id;
char *remote_contact;
SalAddress* service_route; /*as defined by rfc3608, might be a list*/
SalCustomHeader *custom_headers;
SalCustomHeader *sent_custom_headers;
SalCustomHeader *recv_custom_headers;
} SalOpBase;
......@@ -520,8 +521,10 @@ SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name,
const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name);
void sal_custom_header_free(SalCustomHeader *ch);
SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch);
const SalCustomHeader *sal_op_get_custom_header(SalOp *op);
void sal_op_set_custom_header(SalOp *op, SalCustomHeader* ch);
const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op);
void sal_op_set_sent_custom_header(SalOp *op, SalCustomHeader* ch);
void sal_enable_logs();
void sal_disable_logs();
......
......@@ -92,14 +92,18 @@ static void linphone_call_cb(LinphoneCall *call,void * user_data) {
counters->number_of_IframeDecoded++;
}
bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr) {
bool_t call_with_params(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr, const LinphoneCallParams *params) {
int retry=0;
stats initial_caller=caller_mgr->stat;
stats initial_callee=callee_mgr->stat;
CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity));
if (!params){
CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity));
}else{
CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address_with_params(caller_mgr->lc,callee_mgr->identity,params));
}
/*linphone_core_invite(caller_mgr->lc,"pauline");*/
......@@ -141,6 +145,10 @@ bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr) {
}
bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr){
return call_with_params(caller_mgr,callee_mgr,NULL);
}
static void simple_call(void) {
LinphoneCoreManager* marie = linphone_core_manager_new(liblinphone_tester_file_prefix, "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(liblinphone_tester_file_prefix, "pauline_rc");
......@@ -190,6 +198,7 @@ static void simple_call(void) {
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void simple_call_compatibility_mode(void) {
char route[256];
LinphoneCoreManager* marie = linphone_core_manager_new(liblinphone_tester_file_prefix, "marie_rc");
......@@ -417,6 +426,41 @@ static void call_with_ice(void) {
linphone_core_manager_destroy(pauline);
}
static void call_with_custom_headers(void) {
LinphoneCoreManager* marie = linphone_core_manager_new(liblinphone_tester_file_prefix, "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(liblinphone_tester_file_prefix, "pauline_rc");
LinphoneCall *c1,*c2;
LinphoneCallParams *params;
const LinphoneCallParams *remote_params;
const char *hvalue;
params=linphone_core_create_default_call_parameters(marie->lc);
linphone_call_params_add_custom_header(params,"Weather","bad");
linphone_call_params_add_custom_header(params,"Working","yes");
CU_ASSERT_TRUE(call_with_params(pauline,marie,params));
linphone_call_params_destroy(params);
c1=linphone_core_get_current_call(marie->lc);
c2=linphone_core_get_current_call(pauline->lc);
CU_ASSERT_PTR_NOT_NULL(c1);
CU_ASSERT_PTR_NOT_NULL(c2);
remote_params=linphone_call_get_remote_params(c1);
hvalue=linphone_call_params_get_custom_header(remote_params,"Weather");
CU_ASSERT_PTR_NOT_NULL(hvalue);
CU_ASSERT_TRUE(strcmp(hvalue,"bad")==0);
/*just to sleep*/
linphone_core_terminate_all_calls(pauline->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void call_paused_resumed(void) {
LinphoneCoreManager* marie = linphone_core_manager_new(liblinphone_tester_file_prefix, "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(liblinphone_tester_file_prefix, "pauline_rc");
......@@ -773,6 +817,7 @@ test_t call_tests[] = {
{ "Simple call transfer", simple_call_transfer },
{ "Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call },
{ "Call with ICE", call_with_ice },
{ "Call with custom headers",call_with_custom_headers}
};
test_suite_t call_test_suite = {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment