diff --git a/NEWS b/NEWS index 413970e6a..0fc65a86f 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +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) * diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 55786af3b..367551c81 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -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; -} - -/* - * 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; + return b->recv_custom_headers; } + + diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 70f3a45d4..7e2eab0ef 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -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_ */ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index cd16356d1..ae237acfa 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -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; } } diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 57e8149ee..981eed9b2 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -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; + } +} diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index 7baf559dc..f610f2d3c 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -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 (ptrice_ufrag, value, sizeof(stream->ice_ufrag)); diff --git a/coreapi/chat.c b/coreapi/chat.c index 54a15526b..5fa51c46d 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -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) { diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index fa2c891f5..1d4c22a1c 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -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; } } diff --git a/coreapi/sal.c b/coreapi/sal.c index 407d0fc2e..e8619b319 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -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); } diff --git a/include/sal/sal.h b/include/sal/sal.h index ecb6bb314..5274e02f9 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -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(); diff --git a/tester/call_tester.c b/tester/call_tester.c index bfb3dac2e..62683d2fa 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -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 = {