int belle_sip_object_data_set( belle_sip_object_t *obj, const char* name, void* data, belle_sip_data_destroy destroy_func ) { int ret = 0; struct _belle_sip_list* list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name); struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL; if( entry == NULL){ entry = belle_sip_malloc0(sizeof( struct belle_sip_object_data)); obj->data_store = belle_sip_list_append(obj->data_store, entry); } else { // clean previous data if( entry->destroy_func ) entry->destroy_func(entry->data); belle_sip_free(entry->name); ret = 1; } if( entry ){ entry->data = data; entry->name = belle_sip_strdup(name); entry->destroy_func = destroy_func; } else { ret = -1; } return ret; }
belle_sip_list_t *belle_sip_list_delete_custom(belle_sip_list_t *list, belle_sip_compare_func compare_func, const void *user_data){ belle_sip_list_t *elem=belle_sip_list_find_custom(list,compare_func,user_data); if (elem!=NULL){ list=belle_sip_list_delete_link(list,elem); } return list; }
void* belle_sip_object_data_get( belle_sip_object_t *obj, const char* name ) { struct _belle_sip_list* list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name); struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL; return entry? entry->data : NULL; }
belle_sip_source_t *belle_sip_main_loop_find_source(belle_sip_main_loop_t *ml, unsigned long id){ belle_sip_list_t *elem=belle_sip_list_find_custom(ml->sources,match_source_id,(const void*)id); if (elem!=NULL){ return (belle_sip_source_t*)elem->data; } return NULL; }
belle_sip_header_contact_t* belle_sip_refresher_get_contact(const belle_sip_refresher_t* refresher) { belle_sip_transaction_t* transaction = BELLE_SIP_TRANSACTION(refresher->transaction); belle_sip_request_t*request=belle_sip_transaction_get_request(transaction); belle_sip_response_t*response=transaction->last_response; const belle_sip_list_t* contact_header_list; belle_sip_header_contact_t* unfixed_local_contact; belle_sip_header_contact_t* fixed_local_contact; char* tmp_string; char* tmp_string2; if (!response) return NULL; /*we assume, there is only one contact in request*/ unfixed_local_contact= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t); fixed_local_contact= BELLE_SIP_HEADER_CONTACT(belle_sip_object_clone(BELLE_SIP_OBJECT(unfixed_local_contact))); /*first fix contact using received/rport*/ belle_sip_response_fix_contact(response,fixed_local_contact); contact_header_list = belle_sip_message_get_headers(BELLE_SIP_MESSAGE(response),BELLE_SIP_CONTACT); if (contact_header_list) { contact_header_list = belle_sip_list_find_custom((belle_sip_list_t*)contact_header_list ,(belle_sip_compare_func)belle_sip_header_contact_not_equals , (const void*)fixed_local_contact); if (!contact_header_list) { /*reset header list*/ contact_header_list = belle_sip_message_get_headers(BELLE_SIP_MESSAGE(response),BELLE_SIP_CONTACT); contact_header_list = belle_sip_list_find_custom((belle_sip_list_t*)contact_header_list ,(belle_sip_compare_func)belle_sip_header_contact_not_equals ,unfixed_local_contact); } if (!contact_header_list) { tmp_string=belle_sip_object_to_string(BELLE_SIP_OBJECT(fixed_local_contact)); tmp_string2=belle_sip_object_to_string(BELLE_SIP_OBJECT(unfixed_local_contact)); belle_sip_message("No matching contact neither for [%s] nor [%s]", tmp_string, tmp_string2); belle_sip_object_unref(fixed_local_contact); belle_sip_free(tmp_string); belle_sip_free(tmp_string2); return NULL; } else { belle_sip_object_unref(fixed_local_contact); return BELLE_SIP_HEADER_CONTACT(contact_header_list->data); } } else { return NULL; } }
int belle_sip_object_data_remove( belle_sip_object_t *obj, const char* name) { struct _belle_sip_list* list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name); struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL; if( entry ){ belle_sip_free(entry->name); if( entry->destroy_func ) entry->destroy_func(entry->data); belle_sip_free(entry); } if( list_entry ) obj->data_store = belle_sip_list_remove_link(obj->data_store, list_entry); return !(list_entry!= NULL); }
void* belle_sip_object_data_grab( belle_sip_object_t* obj, const char* name) { struct _belle_sip_list* list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name); struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL; void* data =NULL; if( entry ){ belle_sip_free(entry->name); data = entry->data; } obj->data_store = belle_sip_list_remove_link(obj->data_store, list_entry); belle_sip_free(entry); return data; }
static void test_rtcp_xr_attribute(void) { belle_sdp_rtcp_xr_attribute_t* lAttribute; lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr")); CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr"); CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == FALSE); CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == FALSE); belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute)); lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:rcvr-rtt=all:10")); CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr"); CU_ASSERT_STRING_EQUAL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(lAttribute), "all"); CU_ASSERT_EQUAL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_max_size(lAttribute), 10); belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute)); lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:stat-summary")); CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr"); CU_ASSERT_PTR_NULL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(lAttribute)); CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == TRUE); CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == FALSE); belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute)); lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:stat-summary=loss,jitt")); CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr"); CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == TRUE); CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "loss")); CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "jitt")); CU_ASSERT_PTR_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "HL")); belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute)); lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:voip-metrics")); CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr"); CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == FALSE); CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == TRUE); belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute)); lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:rcvr-rtt=sender stat-summary=loss,dup,jitt,TTL voip-metrics")); CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr"); CU_ASSERT_STRING_EQUAL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(lAttribute), "sender"); CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == TRUE); CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "loss")); CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "dup")); CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "jitt")); CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "TTL")); CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == TRUE); belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute)); }
int belle_sip_object_data_exists( const belle_sip_object_t *obj, const char* name ) { return (belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name) != NULL); }
static void test_mime_parameter(void) { const char* l_src = "m=audio 7078 RTP/AVP 111 110 0 8 9 3 18 101\r\n"\ "a=rtpmap:111 speex/16000\r\n"\ "a=fmtp:111 vbr=on\r\n"\ "a=rtpmap:110 speex/8000\r\n"\ "a=fmtp:110 vbr=on\r\n"\ "a=rtpmap:8 PCMA/8000\r\n"\ "a=rtpmap:101 telephone-event/8000\r\n"\ "a=fmtp:101 0-11\r\n"\ "a=ptime:40\r\n"; belle_sdp_mime_parameter_t* l_param; belle_sdp_mime_parameter_t* lTmp; belle_sdp_media_t* l_media; belle_sip_list_t* mime_parameter_list; belle_sip_list_t* mime_parameter_list_iterator; belle_sdp_media_description_t* l_media_description_tmp = belle_sdp_media_description_parse(l_src); belle_sdp_media_description_t* l_media_description = belle_sdp_media_description_parse(belle_sip_object_to_string(l_media_description_tmp)); belle_sip_object_unref(l_media_description_tmp); mime_parameter_list = belle_sdp_media_description_build_mime_parameters(l_media_description); mime_parameter_list_iterator = mime_parameter_list; CU_ASSERT_PTR_NOT_NULL(mime_parameter_list); belle_sip_object_unref(BELLE_SIP_OBJECT(l_media_description)); l_media_description = belle_sdp_media_description_new(); belle_sdp_media_description_set_media(l_media_description,l_media=belle_sdp_media_parse("m=audio 7078 RTP/AVP 0")); belle_sdp_media_set_media_formats(l_media,belle_sip_list_free(belle_sdp_media_get_media_formats(l_media))); /*to remove 0*/ for (;mime_parameter_list_iterator!=NULL;mime_parameter_list_iterator=mime_parameter_list_iterator->next) { belle_sdp_media_description_append_values_from_mime_parameter(l_media_description,(belle_sdp_mime_parameter_t*)mime_parameter_list_iterator->data); } belle_sip_list_free_with_data(mime_parameter_list, (void (*)(void*))belle_sip_object_unref); /*marshal/unmarshal again*/ l_media_description_tmp = l_media_description; l_media_description= belle_sdp_media_description_parse(belle_sip_object_to_string(l_media_description)); belle_sip_object_unref(l_media_description_tmp); /*belle_sip_message("%s",belle_sip_object_to_string(l_media_description));*/ { belle_sip_list_t* attributes=belle_sdp_media_description_get_attributes(l_media_description); #ifdef BELLE_SDP_FORCE_RTP_MAP CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(attributes,(belle_sip_compare_func)compare_attribute,"8 PCMA/8000")); CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(attributes,(belle_sip_compare_func)compare_attribute,"18 G729/8000")); #else CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(attributes,(belle_sip_compare_func)compare_attribute,"8 PCMA/8000")); CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(attributes,(belle_sip_compare_func)compare_attribute,"18 G729/8000")); #endif } mime_parameter_list = belle_sdp_media_description_build_mime_parameters(l_media_description); belle_sip_object_unref(l_media_description); lTmp = find_mime_parameter(mime_parameter_list,111); l_param = BELLE_SDP_MIME_PARAMETER(belle_sip_object_clone(BELLE_SIP_OBJECT(lTmp))); CU_ASSERT_PTR_NOT_NULL(l_param); check_mime_param(l_param,16000,1,40,-1,111,"speex","vbr=on"); belle_sip_object_unref(l_param); l_param = find_mime_parameter(mime_parameter_list,110); CU_ASSERT_PTR_NOT_NULL(l_param); check_mime_param(l_param,8000,1,40,-1,110,"speex","vbr=on"); l_param = find_mime_parameter(mime_parameter_list,3); CU_ASSERT_PTR_NOT_NULL(l_param); check_mime_param(l_param,8000,1,40,-1,3,"GSM",NULL); l_param = find_mime_parameter(mime_parameter_list,0); CU_ASSERT_PTR_NOT_NULL(l_param); check_mime_param(l_param,8000,1,40,-1,0,"PCMU",NULL); l_param = find_mime_parameter(mime_parameter_list,8); CU_ASSERT_PTR_NOT_NULL(l_param); check_mime_param(l_param,8000,1,40,-1,8,"PCMA",NULL); l_param = find_mime_parameter(mime_parameter_list,9); CU_ASSERT_PTR_NOT_NULL(l_param); check_mime_param(l_param,8000,1,40,-1,9,"G722",NULL); l_param = find_mime_parameter(mime_parameter_list,101); CU_ASSERT_PTR_NOT_NULL(l_param); check_mime_param(l_param,8000,1,40,-1,101,"telephone-event","0-11"); belle_sip_list_free_with_data(mime_parameter_list, (void (*)(void*))belle_sip_object_unref); }
static int belle_sip_refresher_refresh_internal(belle_sip_refresher_t* refresher, int expires, int auth_mandatory, belle_sip_list_t** auth_infos, belle_sip_uri_t *requri) { belle_sip_request_t*old_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(refresher->transaction)); belle_sip_response_t*old_response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(refresher->transaction)); belle_sip_dialog_t* dialog = refresher->dialog; belle_sip_client_transaction_t* client_transaction; belle_sip_request_t* request; belle_sip_header_expires_t* expires_header; belle_sip_uri_t* preset_route=refresher->transaction->preset_route; belle_sip_provider_t* prov=refresher->transaction->base.provider; belle_sip_header_contact_t* contact; /*first remove timer if any*/ if (expires >=0) { refresher->target_expires=expires; } else { /*-1 keep last value*/ } if (!dialog) { const belle_sip_transaction_state_t state=belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction)); /*create new request*/ if (belle_sip_transaction_state_is_transient(state)) { /*operation pending, cannot update authorization headers*/ belle_sip_header_cseq_t* cseq; belle_sip_message("Refresher [%p] already has transaction [%p] in state [%s]" ,refresher ,refresher->transaction ,belle_sip_transaction_state_to_string(state)); if (strcmp(belle_sip_request_get_method(old_request),"PUBLISH")==0) { belle_sip_message("Refresher [%p] new publish is delayed to end of ongoing transaction" ,refresher); refresher->publish_pending = TRUE; return 0; } else { request=belle_sip_request_clone_with_body(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(refresher->transaction))); cseq=belle_sip_message_get_header_by_type(request,belle_sip_header_cseq_t); belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1); } } else { request=belle_sip_client_transaction_create_authenticated_request(refresher->transaction,auth_infos,refresher->realm); } if (requri){ /*case where we are redirected*/ belle_sip_request_set_uri(request,requri); /*remove auth headers, they are not valid for new destination*/ belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION); belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION); } } else { switch (belle_sip_dialog_get_state(dialog)) { case BELLE_SIP_DIALOG_CONFIRMED: { if (belle_sip_dialog_request_pending(dialog)){ belle_sip_message("Cannot refresh now, there is a pending request in the dialog."); return -1; } request=belle_sip_dialog_create_request_from(dialog,old_request); if (strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0) { belle_sip_header_content_type_t *content_type; /*put expire header*/ if (!(expires_header = belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t))) { expires_header = belle_sip_header_expires_new(); belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header)); } if ((content_type = belle_sip_message_get_header_by_type(request, belle_sip_header_content_type_t)) && strcasecmp("application", belle_sip_header_content_type_get_type(content_type)) == 0 && strcasecmp("resource-lists+xml", belle_sip_header_content_type_get_subtype(content_type)) == 0) { /*rfc5367 3.2. Subsequent SUBSCRIBE Requests ... At this point, there are no semantics associated with resource-list bodies in subsequent SUBSCRIBE requests (although future extensions can define them). Therefore, UACs SHOULD NOT include resource-list bodies in subsequent SUBSCRIBE requests to a resource list server. */ belle_sip_message("Removing body, content type and content length for refresher [%p]",refresher); belle_sip_message_set_body(BELLE_SIP_MESSAGE(request), NULL, 0); belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CONTENT_TYPE); belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CONTENT_LENGTH); } } belle_sip_provider_add_authorization(prov,request,old_response,NULL,auth_infos,refresher->realm); break; } case BELLE_SIP_DIALOG_TERMINATED: { if (refresher->first_acknoleged_request) { char tmp[11]; belle_sip_message("Dialog [%p] is in state terminated, recreating a new one for refresher [%p]",dialog,refresher); request = refresher->first_acknoleged_request; belle_sip_header_cseq_set_seq_number(belle_sip_message_get_header_by_type(request,belle_sip_header_cseq_t) ,20); belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(belle_sip_message_get_header_by_type(request,belle_sip_header_to_t)),"tag"); belle_sip_header_call_id_set_call_id( belle_sip_message_get_header_by_type(request,belle_sip_header_call_id_t) , belle_sip_random_token(tmp,sizeof(tmp))); break; } /*else nop, error case*/ } default: { belle_sip_error("Unexpected dialog state [%s] for dialog [%p], cannot refresh [%s]" ,belle_sip_dialog_state_to_string(belle_sip_dialog_get_state(dialog)) ,dialog ,belle_sip_request_get_method(old_request)); return -1; } } } if (auth_mandatory && auth_infos && belle_sip_list_find_custom(*auth_infos, unfilled_auth_info, NULL)) { belle_sip_message("Auth info not found for this refresh operation on [%p]",refresher); if (request) belle_sip_object_unref(request); return -1; } refresher->on_io_error=0; /*reset this flag*/ /*update expires in any cases*/ expires_header = belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t); if (expires_header) belle_sip_header_expires_set_expires(expires_header,refresher->target_expires); contact=belle_sip_message_get_header_by_type(request,belle_sip_header_contact_t); if (contact && belle_sip_header_contact_get_expires(contact)>=0) belle_sip_header_contact_set_expires(contact,refresher->target_expires); /*update the Date header if it exists*/ { belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(request,belle_sip_header_date_t); if (date){ time_t curtime=time(NULL); belle_sip_header_date_set_time(date,&curtime); } } client_transaction = belle_sip_provider_create_client_transaction(prov,request); client_transaction->base.is_internal=1; belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),refresher); if (request == refresher->first_acknoleged_request) { /*request is now ref by transaction so no need to keepo it*/ belle_sip_object_unref(refresher->first_acknoleged_request); refresher->first_acknoleged_request = NULL; } switch (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction))) { case BELLE_SIP_TRANSACTION_INIT: case BELLE_SIP_TRANSACTION_CALLING: case BELLE_SIP_TRANSACTION_TRYING: /*very early state, we can assume nobody will answer, stop retransmiting*/ belle_sip_transaction_terminate(BELLE_SIP_TRANSACTION(refresher->transaction)); break; default: /*we preserve the transaction "as is"*/ break; } /*update reference transaction for next refresh*/ belle_sip_object_unref(refresher->transaction); refresher->transaction=client_transaction; belle_sip_object_ref(refresher->transaction); if (belle_sip_client_transaction_send_request_to(client_transaction,requri?requri:preset_route)) { /*send imediatly to requri in case of redirect*/ belle_sip_error("Cannot send refresh method [%s] for refresher [%p]" ,belle_sip_request_get_method(request) ,refresher); return -1; } if (expires==0) belle_sip_refresher_stop_internal(refresher,0); /*unregister transaction must be preserved*/ return 0; }