void belle_sip_listening_point_set_keep_alive(belle_sip_listening_point_t *lp,int ms) { if (ms <=0) { if (lp->keep_alive_timer) { belle_sip_main_loop_remove_source(lp->stack->ml,lp->keep_alive_timer); belle_sip_object_unref(lp->keep_alive_timer); lp->keep_alive_timer=NULL; } return; } if (!lp->keep_alive_timer) { lp->keep_alive_timer = belle_sip_main_loop_create_timeout(lp->stack->ml , keep_alive_timer_func , lp , ms ,"keep alive") ; } else { belle_sip_source_set_timeout(lp->keep_alive_timer,ms); } return; }
belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t,belle_sip_list_t** auth_infos,const char* realm) { belle_sip_request_t* initial_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t)); belle_sip_request_t* req=belle_sip_request_clone_with_body(initial_request); belle_sip_header_cseq_t* cseq=belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1); if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)) != BELLE_SIP_TRANSACTION_COMPLETED && belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)) != BELLE_SIP_TRANSACTION_TERMINATED) { belle_sip_error("Invalid state [%s] for transaction [%p], should be BELLE_SIP_TRANSACTION_COMPLETED | BELLE_SIP_TRANSACTION_TERMINATED" ,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t))) ,t); belle_sip_object_unref(req); return NULL; } /*remove auth headers*/ belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_AUTHORIZATION); belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_PROXY_AUTHORIZATION); /*put auth header*/ belle_sip_provider_add_authorization(t->base.provider,req,t->base.last_response,NULL,auth_infos,realm); return req; }
static void one_get(const char *url,http_counters_t* counters, int *counter){ belle_http_request_listener_callbacks_t cbs={0}; belle_http_request_listener_t *l; belle_generic_uri_t *uri; belle_http_request_t *req; uri=belle_generic_uri_parse(url); req=belle_http_request_create("GET", uri, belle_sip_header_create("User-Agent","belle-sip/"PACKAGE_VERSION), NULL); cbs.process_response=process_response; cbs.process_io_error=process_io_error; cbs.process_auth_requested=process_auth_requested; l=belle_http_request_listener_create_from_callbacks(&cbs,counters); belle_http_provider_send_request(prov,req,l); wait_for(stack,counter,1,3000); belle_sip_object_unref(l); }
int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact){ belle_sip_request_t *req; belle_sip_uri_t* req_uri; belle_sip_header_t* accept_header; if (op->refresher){ belle_sip_refresher_stop(op->refresher); belle_sip_object_unref(op->refresher); op->refresher=NULL; } op->type=SalOpRegister; sal_op_set_from(op,from); sal_op_set_to(op,from); sal_op_set_route(op,proxy); req = sal_op_build_request(op,"REGISTER"); req_uri = belle_sip_request_get_uri(req); belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/ if (op->base.root->use_dates){ time_t curtime=time(NULL); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); } accept_header = belle_sip_header_create("Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), accept_header); belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op)); if (old_contact) { belle_sip_header_contact_t *contact=belle_sip_header_contact_create((const belle_sip_header_address_t *)old_contact); if (contact) { char * tmp; belle_sip_header_contact_set_expires(contact,0); /*remove old aor*/ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(contact)); tmp = belle_sip_object_to_string(contact); ms_message("Clearing contact [%s] for op [%p]",tmp,op); ms_free(tmp); } else { ms_error("Cannot add old contact header to op [%p]",op); } } return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener); }
void sal_op_release_impl(SalOp *op){ ms_message("Destroying op [%p] of type [%s]",op,sal_op_type_to_string(op->type)); if (op->pending_auth_transaction) belle_sip_object_unref(op->pending_auth_transaction); if (op->auth_info) { sal_remove_pending_auth(op->base.root,op); sal_auth_info_delete(op->auth_info); } if (op->sdp_answer) belle_sip_object_unref(op->sdp_answer); if (op->refresher) { 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); if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans); if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); if (op->event) belle_sip_object_unref(op->event); __sal_op_free(op); return ; }
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)); }
static void test_generate_and_parse_certificates(void) { belle_sip_certificates_chain_t *certificate, *parsed_certificate; belle_sip_signing_key_t *key, *parsed_key; char *pem_certificate, *pem_parsed_certificate, *pem_key, *pem_parsed_key; int ret = 0; char *belle_sip_certificate_temporary_dir = bc_tester_file(TEMPORARY_CERTIFICATE_DIR); /* create 2 certificates in the temporary certificate directory (TODO : set the directory in a absolute path?? where?)*/ ret = belle_sip_generate_self_signed_certificate(belle_sip_certificate_temporary_dir, "test_certificate1", &certificate, &key); if (ret == BCTOOLBOX_ERROR_UNAVAILABLE_FUNCTION) { belle_sip_warning("Test skipped, self signed certificate generation not available."); return; } BC_ASSERT_EQUAL_FATAL(0, ret, int, "%d"); belle_sip_object_unref(certificate); belle_sip_object_unref(key); ret = belle_sip_generate_self_signed_certificate(belle_sip_certificate_temporary_dir, "test_certificate2", &certificate, &key); BC_ASSERT_EQUAL_FATAL(0, ret, int, "%d"); /* parse directory to get the certificate2 */ ret = belle_sip_get_certificate_and_pkey_in_dir(belle_sip_certificate_temporary_dir, "test_certificate2", &parsed_certificate, &parsed_key, BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM); free(belle_sip_certificate_temporary_dir); BC_ASSERT_EQUAL_FATAL(0, ret, int, "%d"); /* get pem version of generated and parsed certificate and compare them */ pem_certificate = belle_sip_certificates_chain_get_pem(certificate); BC_ASSERT_TRUE_FATAL(pem_certificate!=NULL); pem_parsed_certificate = belle_sip_certificates_chain_get_pem(parsed_certificate); BC_ASSERT_TRUE_FATAL(pem_parsed_certificate!=NULL); BC_ASSERT_STRING_EQUAL(pem_certificate, pem_parsed_certificate); /* get pem version of generated and parsed key and compare them */ pem_key = belle_sip_signing_key_get_pem(key); BC_ASSERT_TRUE_FATAL(pem_key!=NULL); pem_parsed_key = belle_sip_signing_key_get_pem(parsed_key); BC_ASSERT_TRUE_FATAL(pem_parsed_key!=NULL); BC_ASSERT_STRING_EQUAL(pem_key, pem_parsed_key); belle_sip_free(pem_certificate); belle_sip_free(pem_parsed_certificate); belle_sip_free(pem_key); belle_sip_free(pem_parsed_key); belle_sip_object_unref(certificate); belle_sip_object_unref(parsed_certificate); belle_sip_object_unref(key); belle_sip_object_unref(parsed_key); }
static void prepare_query(CardDavRequest *request) { belle_http_request_listener_callbacks_t cbs = { 0 }; belle_http_request_listener_t *l = NULL; belle_generic_uri_t *uri = NULL; belle_http_request_t *req = NULL; belle_sip_memory_body_handler_t *bh = NULL; belle_sip_stack_t *stack = NULL; belle_http_provider_t *http_provider = NULL; belle_sip_set_log_level(BELLE_SIP_LOG_MESSAGE); uri = belle_generic_uri_parse(request->url); if (!uri) { belle_sip_error("Could not send request, URL %s is invalid", request->url); return; } req = belle_http_request_create(request->method, uri, belle_sip_header_content_type_create("application", "xml; charset=utf-8"), belle_sip_header_create("Depth", request->depth), NULL); if (!req) { belle_sip_object_unref(uri); belle_sip_error("Could not create request"); return; } bh = belle_sip_memory_body_handler_new_copy_from_buffer(request->body, strlen(request->body), NULL, NULL); belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(bh)); cbs.process_response = process_response_from_post_xml_rpc_request; cbs.process_io_error = process_io_error_from_post_xml_rpc_request; cbs.process_auth_requested = process_auth_requested_from_post_xml_rpc_request; l = belle_http_request_listener_create_from_callbacks(&cbs, request); stack = belle_sip_stack_new(NULL); http_provider = belle_sip_stack_create_http_provider(stack, "0.0.0.0"); request->request_in_progress = 1; belle_http_provider_send_request(http_provider, req, l); while (request->request_in_progress) { belle_sip_stack_sleep(stack, 0); } }
static int process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { belle_sdp_session_description_t* sdp; int err=0; SalReason reason; if (extract_sdp(op,BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) { if (sdp){ op->sdp_offering=FALSE; op->base.remote_media=sal_media_description_new(); sdp_to_media_description(sdp,op->base.remote_media); /*make some sanity check about the SDP received*/ if (!is_media_description_acceptable(op->base.remote_media)){ err=-1; reason=SalReasonNotAcceptable; } belle_sip_object_unref(sdp); }else op->sdp_offering=TRUE; /*INVITE without SDP*/ }else err=-1; if (err==-1){ sal_call_decline(op,reason,NULL); } return err; }
static void testRegisterRaw(void) { const char* raw_message = "REGISTER sip:192.168.0.20 SIP/2.0\r\n"\ "Via: SIP/2.0/UDP 192.168.1.8:5062;rport;branch=z9hG4bK1439638806\r\n"\ "From: <sip:[email protected]>;tag=465687829\r\n"\ "To: <sip:[email protected]>\r\n"\ "Call-ID: 1053183492\r\n"\ "CSeq: 1 REGISTER\r\n"\ "Contact: <sip:[email protected]:5062>\r\n"\ "Max-Forwards: 70\r\n"\ "User-Agent: Linphone/3.3.99.10 (eXosip2/3.3.0)\r\n"\ "Expires: 3600\r\n"\ "Content-Length: 0\r\n\r\n123456789"; belle_sip_request_t* request; size_t size=0; size_t raw_message_size= strlen(raw_message); belle_sip_message_t* message = belle_sip_message_parse_raw(raw_message,raw_message_size,&size); CU_ASSERT_EQUAL(raw_message_size,size+9); request = BELLE_SIP_REQUEST(message); CU_ASSERT_STRING_EQUAL(belle_sip_request_get_method(request),"REGISTER"); CU_ASSERT_PTR_NOT_NULL(belle_sip_request_get_uri(request)); CU_ASSERT_STRING_EQUAL(&raw_message[size],"123456789"); belle_sip_object_unref(message); }
static void test_dictionary(void) { belle_sip_dict_t* obj = belle_sip_object_new(belle_sip_dict_t); const char* str = ""; int i = 5; int64_t i64 = 0xF2345678 << 1; // gcc doesn't like 0x1234567890 as a 64 bit literal.. belle_sip_dict_set_int(obj, "test_i", i); BC_ASSERT_EQUAL(belle_sip_dict_get_int(obj,"test_i",-1),i, int, "%d"); // return default int value BC_ASSERT_EQUAL(belle_sip_dict_get_int(obj,"unexistent",-1),-1, int, "%d"); // remove existing entry BC_ASSERT_EQUAL(belle_sip_dict_remove(obj, "test_i"),0, int, "%d"); // test_i should't be present anymore BC_ASSERT_EQUAL(belle_sip_dict_get_int(obj,"test_i",-1),-1, int, "%d"); // remove unknown entry BC_ASSERT_NOT_EQUAL(belle_sip_dict_remove(obj, "unexistent"),0,int,"%d"); belle_sip_dict_set_string(obj, "test_str", str); BC_ASSERT_STRING_EQUAL( (const char*)belle_sip_dict_get_string(obj, "test_str", ""),str); // unknown string value BC_ASSERT_STRING_EQUAL( (const char*)belle_sip_dict_get_string(obj, "unexistent", "toto"),"toto"); belle_sip_dict_set_int64(obj, "test_i64", i64); BC_ASSERT_EQUAL(belle_sip_dict_get_int64(obj,"test_i64",-1),i64, int, "%d"); belle_sip_dict_clear(obj); // test_str shouldn't exist anymore BC_ASSERT_STRING_EQUAL(belle_sip_dict_get_string(obj,"test_str","toto"),"toto"); belle_sip_object_unref(obj); }
static void http_channel_context_handle_response(belle_http_channel_context_t *ctx , belle_sip_channel_t *chan, belle_http_response_t *response){ belle_http_request_t *req=NULL; belle_http_response_event_t ev={0}; int code; belle_sip_header_t *connection; /*pop the request matching this response*/ ctx->pending_requests=belle_sip_list_pop_front(ctx->pending_requests,(void**)&req); if (req==NULL){ belle_sip_error("Receiving http response not matching any request."); return; } if (belle_http_request_is_cancelled(req)) { belle_sip_warning("Receiving http response for a cancelled request."); return; } connection=belle_sip_message_get_header((belle_sip_message_t *)response,"Connection"); if (connection && strstr(belle_sip_header_get_unparsed_value(connection),"close")!=NULL) chan->about_to_be_closed=TRUE; belle_http_request_set_response(req,response); code=belle_http_response_get_status_code(response); if ((code==401 || code==407) && http_channel_context_handle_authentication(ctx,req)==0 ){ /*nothing to do, the request has been resubmitted with authentication*/ }else{ /*else notify the app about the response received*/ ev.source=(belle_sip_object_t*)ctx->provider; ev.request=req; ev.response=response; BELLE_HTTP_REQUEST_INVOKE_LISTENER(req,process_response,&ev); if( req->background_task_id ){ belle_sip_warning("HTTP request finished: ending bg task id=[%x]", req->background_task_id); belle_sip_end_background_task(req->background_task_id); req->background_task_id = 0; } } belle_sip_object_unref(req); }
void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t* server_transaction){ belle_sip_request_t* req = belle_sip_request_event_get_request(event); const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); belle_sip_header_t* header_event=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"); belle_sip_header_content_type_t* content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t); belle_sip_response_t* resp; ms_message("Receiving NOTIFY request on op [%p]",op); if (header_event && strncasecmp(belle_sip_header_get_unparsed_value(header_event),"refer",strlen("refer"))==0 && content_type && strcmp(belle_sip_header_content_type_get_type(content_type),"message")==0 && strcmp(belle_sip_header_content_type_get_subtype(content_type),"sipfrag")==0 && body){ belle_sip_response_t* sipfrag=BELLE_SIP_RESPONSE(belle_sip_message_parse(body)); if (sipfrag){ int code=belle_sip_response_get_status_code(sipfrag); SalReferStatus status=SalReferFailed; if (code<200){ status=SalReferTrying; }else if (code<300){ status=SalReferSuccess; }else if (code>=400){ status=SalReferFailed; } belle_sip_object_unref(sipfrag); resp = sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); op->base.root->callbacks.notify_refer(op,status); } }else{ ms_error("Notify without sipfrag, trashing"); resp = sal_op_create_response_from_request(op,req,501); belle_sip_server_transaction_send_response(server_transaction,resp); } }
int sal_register(SalOp *op, const char *proxy, const char *from, int expires){ belle_sip_request_t *req; belle_sip_uri_t* req_uri; if (op->refresher){ belle_sip_refresher_stop(op->refresher); belle_sip_object_unref(op->refresher); op->refresher=NULL; } op->type=SalOpRegister; sal_op_set_from(op,from); sal_op_set_to(op,from); sal_op_set_route(op,proxy); req = sal_op_build_request(op,"REGISTER"); req_uri = belle_sip_request_get_uri(req); belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/ if (op->base.root->use_dates){ time_t curtime=time(NULL); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); } belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op)); return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener); }
static void make_supported_header(Sal *sal){ bctbx_list_t *it; char *alltags=NULL; size_t buflen=64; size_t written=0; if (sal->supported){ belle_sip_object_unref(sal->supported); sal->supported=NULL; } for(it=sal->supported_tags;it!=NULL;it=it->next){ const char *tag=(const char*)it->data; size_t taglen=strlen(tag); if (alltags==NULL || (written+taglen+1>=buflen)) alltags=ms_realloc(alltags,(buflen=buflen*2)); written+=snprintf(alltags+written,buflen-written,it->next ? "%s, " : "%s",tag); } if (alltags){ sal->supported=belle_sip_header_create("Supported",alltags); if (sal->supported){ belle_sip_object_ref(sal->supported); } ms_free(alltags); } }
static void _send_message(belle_sip_channel_t *obj){ char buffer[belle_sip_network_buffer_size]; size_t len=0; belle_sip_error_code error=BELLE_SIP_OK; belle_sip_message_t *msg=obj->cur_out_message; belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg); size_t body_len=bh ? belle_sip_body_handler_get_size(bh) : 0; int sendret; size_t off; int ret; if (obj->ewouldblock_buffer){ sendret=send_buffer(obj,(const char*)obj->ewouldblock_buffer+obj->ewouldblock_offset,obj->ewouldblock_size-obj->ewouldblock_offset); if (sendret>0){ obj->ewouldblock_offset+=sendret; if (obj->ewouldblock_offset==obj->ewouldblock_size){ free_ewouldblock_buffer(obj); } return; /*we prefer poll again to be sure we can write*/ }else if (belle_sip_error_code_is_would_block(-sendret)) { /*we got an ewouldblock again. Nothing to do, we'll be called later in order to retry*/ return; }else {/*error or disconnection case*/ goto done; } } if (obj->out_state==OUTPUT_STREAM_SENDING_HEADERS){ BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_sending,obj,msg); check_content_length(msg,body_len); error=belle_sip_object_marshal((belle_sip_object_t*)msg,buffer,sizeof(buffer)-1,&len); if (error!=BELLE_SIP_OK) { belle_sip_error("channel [%p] _send_message: marshaling failed.",obj); goto done; } /*send the headers and eventually the body if it fits in our buffer*/ if (bh){ size_t max_body_len=sizeof(buffer)-1-len; if (body_len>0 && body_len<=max_body_len){ /*if size is known and fits into our buffer, send together with headers*/ belle_sip_body_handler_begin_transfer(bh); do{ max_body_len=sizeof(buffer)-1-len; ret=belle_sip_body_handler_send_chunk(bh,msg,(uint8_t*)buffer+len,&max_body_len); len+=max_body_len; }while(ret==BELLE_SIP_CONTINUE); belle_sip_body_handler_end_transfer(bh); }else{ if (body_len==0){ belle_sip_fatal("Sending bodies whose size is not known must be done in chunked mode, which is not supported yet."); } belle_sip_body_handler_begin_transfer(bh); obj->out_state=OUTPUT_STREAM_SENDING_BODY; } } off=0; do{ sendret=send_buffer(obj,buffer+off,len-off); if (sendret>0){ off+=sendret; if (off==len){ break; } }else if (belle_sip_error_code_is_would_block(-sendret)) { handle_ewouldblock(obj,buffer+off,len-off); return; }else {/*error or disconnection case*/ goto done; } }while(1); } if (obj->out_state==OUTPUT_STREAM_SENDING_BODY){ do{ size_t chunk_len=sizeof(buffer)-1; ret=belle_sip_body_handler_send_chunk(bh,msg,(uint8_t*)buffer,&chunk_len); if (chunk_len!=0){ off=0; do{ sendret=send_buffer(obj,buffer+off,chunk_len-off); if (sendret>0){ off+=sendret; if (off==chunk_len){ break; } }else if (belle_sip_error_code_is_would_block(-sendret)) { handle_ewouldblock(obj,buffer+off,chunk_len-off); return; }else {/*error or disconnection case*/ goto done; } }while(1); } }while(ret==BELLE_SIP_CONTINUE); belle_sip_body_handler_end_transfer(bh); } done: /*we get ready to send another message*/ belle_sip_source_set_events((belle_sip_source_t*)obj,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR); free_ewouldblock_buffer(obj); obj->out_state=OUTPUT_STREAM_IDLE; belle_sip_object_unref(obj->cur_out_message); obj->cur_out_message=NULL; }
static void destroy_endpoint(endpoint_t *endpoint) { reset_endpoint(endpoint); belle_sip_object_unref(endpoint->stack); belle_sip_free(endpoint); belle_sip_uninit_sockets(); }
static void channel_invoke_state_listener_defered(belle_sip_channel_t *obj){ channel_invoke_state_listener(obj); belle_sip_object_unref(obj); }
static void channel_connect_next(belle_sip_channel_t *obj){ belle_sip_channel_connect(obj); belle_sip_object_unref(obj); }
void linphone_friend_unref(LinphoneFriend *lf) { belle_sip_object_unref(lf); }
void belle_sip_auth_event_set_client_certificates_chain(belle_sip_auth_event_t* event, belle_sip_certificates_chain_t* value) { if (event->cert) belle_sip_object_unref(event->cert); event->cert=value; if (event->cert) belle_sip_object_ref(event->cert); }
void linphone_content_unref(LinphoneContent *content) { belle_sip_object_unref(content); }
static void client_transaction_destroy(belle_sip_client_transaction_t *t ){ if (t->preset_route) belle_sip_object_unref(t->preset_route); if (t->next_hop) belle_sip_object_unref(t->next_hop); }
static void unlink_op_with_dialog(SalOp *op, belle_sip_dialog_t* dialog){ belle_sip_dialog_set_application_data(dialog,NULL); sal_op_unref(op); belle_sip_object_unref(dialog); }
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; belle_sip_provider_t* prov=op->base.root->prov; belle_sip_uri_t* outbound_proxy=NULL; belle_sip_header_contact_t* contact; int result =-1; belle_sip_uri_t *next_hop_uri=NULL; if (add_contact && !belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t)) { contact = sal_op_create_contact(op); belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact)); } /*keep existing*/ _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); const char *transport; const char *method=belle_sip_request_get_method(request); belle_sip_listening_point_t *udplp=belle_sip_provider_get_listening_point(prov,"UDP"); if (elem) { outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data); next_hop_uri=outbound_proxy; }else{ next_hop_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri(request)); } transport=belle_sip_uri_get_transport_param(next_hop_uri); if (transport==NULL){ /*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use * the first available transport*/ if (!belle_sip_uri_is_secure(next_hop_uri)){ if (udplp==NULL){ if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){ transport="tcp"; }else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){ transport="tls"; } } if (transport){ belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport); belle_sip_uri_set_transport_param(next_hop_uri,transport); } } }else{ #ifdef TUNNEL_ENABLED if (udplp && BELLE_SIP_OBJECT_IS_INSTANCE_OF(udplp,belle_sip_tunnel_listening_point_t)){ /* our tunnel mode only supports UDP. Force transport to be set to UDP */ belle_sip_uri_set_transport_param(next_hop_uri,"udp"); } #endif } if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport && (strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){ /*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/ belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t); belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"alias",NULL); } } client_transaction = belle_sip_provider_create_client_transaction(prov,request); belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),sal_op_ref(op)); if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans); op->pending_client_trans=client_transaction; /*update pending inv for being able to cancel*/ belle_sip_object_ref(op->pending_client_trans); if (belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_user_agent_t)==NULL) belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(op->base.root->user_agent)); if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION) && !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) { /*hmm just in case we already have authentication param in cache*/ belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL,op->base.realm); } result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/); /*update call id if not set yet for this OP*/ if (result == 0 && !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(request), belle_sip_header_call_id_t)))); } return result; }
void linphone_account_creator_unref(LinphoneAccountCreator *creator) { belle_sip_object_unref(creator); }
static void stream_description_to_sdp ( belle_sdp_session_description_t *session_desc, const SalMediaDescription *md, const SalStreamDescription *stream ) { belle_sdp_mime_parameter_t* mime_param; belle_sdp_media_description_t* media_desc; int j; MSList* pt_it; PayloadType* pt; char buffer[1024]; char* dir=NULL; const char *rtp_addr; const char *rtcp_addr; int rtp_port; int rtcp_port; bool_t different_rtp_and_rtcp_addr; rtp_addr=stream->rtp_addr; rtcp_addr=stream->rtcp_addr; rtp_port=stream->rtp_port; rtcp_port=stream->rtcp_port; media_desc = belle_sdp_media_description_create ( sal_stream_description_get_type_as_string(stream) ,stream->rtp_port ,1 ,sal_media_proto_to_string ( stream->proto ) ,NULL ); if (stream->payloads) { for ( pt_it=stream->payloads; pt_it!=NULL; pt_it=pt_it->next ) { pt= ( PayloadType* ) pt_it->data; mime_param= belle_sdp_mime_parameter_create ( pt->mime_type , payload_type_get_number ( pt ) , pt->clock_rate ,stream->type==SalAudio?1:-1 ); belle_sdp_mime_parameter_set_parameters ( mime_param,pt->recv_fmtp ); if ( stream->ptime>0 ) { belle_sdp_mime_parameter_set_ptime ( mime_param,stream->ptime ); } belle_sdp_media_description_append_values_from_mime_parameter ( media_desc,mime_param ); belle_sip_object_unref ( mime_param ); } } else { /* to comply with SDP we cannot have an empty payload type number list */ /* as it happens only when mline is declined with a zero port, it does not matter to put whatever codec*/ belle_sip_list_t* format = belle_sip_list_append(NULL,0); belle_sdp_media_set_media_formats(belle_sdp_media_description_get_media(media_desc),format); } /*only add a c= line within the stream description if address are differents*/ if (rtp_addr[0]!='\0' && strcmp(rtp_addr,md->addr)!=0){ bool_t inet6; if (strchr(rtp_addr,':')!=NULL){ inet6=TRUE; }else inet6=FALSE; belle_sdp_media_description_set_connection(media_desc,belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr)); } if ( stream->bandwidth>0 ) belle_sdp_media_description_set_bandwidth ( media_desc,"AS",stream->bandwidth ); if ( stream->proto == SalProtoRtpSavp ) { /* add crypto lines */ for ( j=0; j<SAL_CRYPTO_ALGO_MAX; j++ ) { switch ( stream->crypto[j].algo ) { case AES_128_SHA1_80: snprintf ( buffer, sizeof ( buffer ), "%d %s inline:%s", stream->crypto[j].tag, "AES_CM_128_HMAC_SHA1_80", stream->crypto[j].master_key ); belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( "crypto",buffer ) ); break; case AES_128_SHA1_32: snprintf ( buffer, sizeof ( buffer ), "%d %s inline:%s", stream->crypto[j].tag, "AES_CM_128_HMAC_SHA1_32", stream->crypto[j].master_key ); belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( "crypto",buffer ) ); break; case AES_128_NO_AUTH: ms_warning ( "Unsupported crypto suite: AES_128_NO_AUTH" ); break; case NO_CIPHER_SHA1_80: ms_warning ( "Unsupported crypto suite: NO_CIPHER_SHA1_80" ); break; default: j = SAL_CRYPTO_ALGO_MAX; /* no break */ } } } switch ( stream->dir ) { case SalStreamSendRecv: /*dir="sendrecv";*/ dir=NULL; break; case SalStreamRecvOnly: dir="recvonly"; break; case SalStreamSendOnly: dir="sendonly"; break; case SalStreamInactive: dir="inactive"; break; } if ( dir ) belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( dir,NULL ) ); if (rtp_port != 0) { different_rtp_and_rtcp_addr = (rtcp_addr[0] != '\0') && (strcmp(rtp_addr, rtcp_addr) != 0); if ((rtcp_port != (rtp_port + 1)) || (different_rtp_and_rtcp_addr == TRUE)) { if (different_rtp_and_rtcp_addr == TRUE) { snprintf(buffer, sizeof(buffer), "%u IN IP4 %s", rtcp_port, rtcp_addr); } else { snprintf(buffer, sizeof(buffer), "%u",rtcp_port); } belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("rtcp",buffer)); } } if (stream->ice_completed == TRUE) { belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("nortpproxy","yes")); } if (stream->ice_mismatch == TRUE) { belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-mismatch",NULL)); } else { if (rtp_port != 0) { if (stream->ice_pwd[0] != '\0') belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-pwd",stream->ice_pwd)); if (stream->ice_ufrag[0] != '\0') belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-ufrag",stream->ice_ufrag)); add_ice_candidates(media_desc,stream); add_ice_remote_candidates(media_desc,stream); } } if (stream->rtcp_xr.enabled == TRUE) { char sastr[1024] = {0}; char mastr[1024] = {0}; size_t saoff = 0; size_t maoff = 0; const belle_sdp_attribute_t *session_attribute = belle_sdp_session_description_get_attribute(session_desc, "rtcp-xr"); belle_sdp_attribute_t *media_attribute; if (session_attribute != NULL) { belle_sip_object_marshal((belle_sip_object_t*)session_attribute, sastr, sizeof(sastr), &saoff); } media_attribute = create_rtcp_xr_attribute(&stream->rtcp_xr); if (media_attribute != NULL) { belle_sip_object_marshal((belle_sip_object_t*)media_attribute, mastr, sizeof(mastr), &maoff); } if (strcmp(sastr, mastr) != 0) { belle_sdp_media_description_add_attribute(media_desc, media_attribute); } else { belle_sip_object_unref((belle_sip_object_t*)media_attribute); } } belle_sdp_session_description_add_media_description(session_desc, media_desc); }
void linphone_account_creator_cbs_unref(LinphoneAccountCreatorCbs *cbs) { belle_sip_object_unref(cbs); }
static void subscribe_process_request_event(void *op_base, const belle_sip_request_event_t *event) { SalOp* op = (SalOp*)op_base; belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_dialog_state_t dialog_state; belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); belle_sip_header_t *event_header; SalBody body; belle_sip_response_t* resp; const char *eventname=NULL; const char *method=belle_sip_request_get_method(req); belle_sip_object_ref(server_transaction); if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); op->pending_server_trans=server_transaction; event_header=belle_sip_message_get_header((belle_sip_message_t*)req,"Event"); sal_op_get_body(op,(belle_sip_message_t*)req,&body); if (event_header==NULL){ ms_warning("No event header in incoming SUBSCRIBE."); resp=sal_op_create_response_from_request(op,req,400); belle_sip_server_transaction_send_response(server_transaction,resp); return; } if (op->event==NULL) { op->event=event_header; belle_sip_object_ref(op->event); } eventname=belle_sip_header_get_unparsed_value(event_header); if (!op->dialog) { if (strcmp(method,"SUBSCRIBE")==0){ op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction)); belle_sip_dialog_set_application_data(op->dialog,op); sal_op_ref(op); ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); }else{ /*this is a NOTIFY*/ handle_notify(op,req,eventname,&body); return; } } dialog_state=belle_sip_dialog_get_state(op->dialog); switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: { op->base.root->callbacks.subscribe_received(op,eventname,body.type ? &body : NULL); break; } case BELLE_SIP_DIALOG_EARLY: ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",belle_sip_request_get_method(req),op->dialog); break; case BELLE_SIP_DIALOG_CONFIRMED: if (strcmp("NOTIFY",method)==0) { handle_notify(op,req,eventname,&body); } else if (strcmp("SUBSCRIBE",method)==0) { /*either a refresh of an unsubscribe*/ if (expires && belle_sip_header_expires_get_expires(expires)>0) { resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); } else if(expires) { ms_message("Unsubscribe received from [%s]",sal_op_get_from(op)); resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); op->base.root->callbacks.subscribe_closed(op); } } break; default: { ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); } } }
void linphone_call_params_unref(LinphoneCallParams *cp) { belle_sip_object_unref(cp); }