/*constructor for channels creating an outgoing connection * bindip local ip address to bind on, typically 0.0.0.0 or ::0 * locaport locaport to use for binding, can be set to 0 if port doesn't matter * peer_cname canonical name of remote host, used for TLS verification * peername peer's hostname, either ip address or DNS name * pee_port peer's port to connect to. */ void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack,const char *bindip,int localport,const char *peer_cname, const char *peername, int peer_port){ /*to initialize our base class:*/ belle_sip_channel_set_socket(obj,-1,NULL); /*then initialize members*/ obj->ai_family=AF_INET; obj->peer_cname=peer_cname ? belle_sip_strdup(peer_cname) : NULL; obj->peer_name=belle_sip_strdup(peername); obj->peer_port=peer_port; obj->stack=stack; if (bindip){ if (strcmp(bindip,"::0")!=0 && strcmp(bindip,"0.0.0.0")!=0) obj->local_ip=belle_sip_strdup(bindip); if (strchr(bindip,':')!=NULL) obj->ai_family=AF_INET6; } obj->local_port=localport; obj->simulated_recv_return=1;/*not set*/ if (peername){ /*check if we are given a real dns name or just an ip address*/ struct addrinfo *ai=belle_sip_ip_address_to_addrinfo(AF_UNSPEC,peername,peer_port); if (ai) freeaddrinfo(ai); else obj->has_name=TRUE; } belle_sip_channel_input_stream_reset(&obj->input_stream); update_inactivity_timer(obj,FALSE); }
belle_sip_hop_t* belle_sip_hop_new(const char* transport, const char *cname, const char* host,int port) { belle_sip_hop_t* hop = belle_sip_object_new(belle_sip_hop_t); if (transport) hop->transport=belle_sip_strdup(transport); if (host) hop->host=belle_sip_strdup(host); if (cname) hop->cname=belle_sip_strdup(cname); hop->port=port; return hop; }
static void belle_sip_hop_clone(belle_sip_hop_t *hop, const belle_sip_hop_t *orig){ if (orig->host) hop->host=belle_sip_strdup(orig->host); if (orig->cname) hop->cname=belle_sip_strdup(orig->cname); if (orig->transport) hop->transport=belle_sip_strdup(orig->transport); }
static void set_to_tag(belle_sip_dialog_t *obj, belle_sip_header_to_t *to){ const char *to_tag=belle_sip_header_to_get_tag(to); if (obj->is_server){ if (to_tag && !obj->local_tag) obj->local_tag=belle_sip_strdup(to_tag); }else{ if (to_tag && !obj->remote_tag) obj->remote_tag=belle_sip_strdup(to_tag); } }
belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t){ belle_sip_dialog_t *obj; belle_sip_header_from_t *from; const char *from_tag; belle_sip_header_to_t *to; const char *to_tag=NULL; from=belle_sip_message_get_header_by_type(t->request,belle_sip_header_from_t); if (from==NULL){ belle_sip_error("belle_sip_dialog_new(): no from!"); return NULL; } from_tag=belle_sip_header_from_get_tag(from); if (from_tag==NULL){ belle_sip_error("belle_sip_dialog_new(): no from tag!"); return NULL; } if (t->last_response) { to=belle_sip_message_get_header_by_type(t->last_response,belle_sip_header_to_t); if (to==NULL){ belle_sip_error("belle_sip_dialog_new(): no to!"); return NULL; } to_tag=belle_sip_header_to_get_tag(to); } obj=belle_sip_object_new(belle_sip_dialog_t); obj->terminate_on_bye=1; obj->provider=t->provider; if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_server_transaction_t)){ obj->remote_tag=belle_sip_strdup(from_tag); obj->local_tag=to_tag?belle_sip_strdup(to_tag):NULL; /*might be null at dialog creation*/ obj->remote_party=(belle_sip_header_address_t*)belle_sip_object_ref(from); obj->is_server=TRUE; }else{ const belle_sip_list_t *predefined_routes=NULL; obj->local_tag=belle_sip_strdup(from_tag); obj->remote_tag=to_tag?belle_sip_strdup(to_tag):NULL; /*might be null at dialog creation*/ obj->local_party=(belle_sip_header_address_t*)belle_sip_object_ref(from); obj->is_server=FALSE; for(predefined_routes=belle_sip_message_get_headers((belle_sip_message_t*)t->request,BELLE_SIP_ROUTE); predefined_routes!=NULL;predefined_routes=predefined_routes->next){ obj->route_set=belle_sip_list_append(obj->route_set,belle_sip_object_ref(predefined_routes->data)); } } belle_sip_message("New %s dialog [%p] , local tag [%s], remote tag [%s]" ,obj->is_server?"server":"client" ,obj ,obj->local_tag?obj->local_tag:"" ,obj->remote_tag?obj->remote_tag:""); set_state(obj,BELLE_SIP_DIALOG_NULL); return obj; }
static void belle_sip_uri_clone(belle_sip_uri_t* uri, const belle_sip_uri_t *orig){ uri->secure=orig->secure; uri->user=orig->user?belle_sip_strdup(orig->user):NULL; uri->user_password=orig->user_password?belle_sip_strdup(orig->user_password):NULL; uri->host=orig->host?belle_sip_strdup(orig->host):NULL; uri->port=orig->port; if (orig->header_list){ uri->header_list=(belle_sip_parameters_t*)belle_sip_object_clone(BELLE_SIP_OBJECT(orig->header_list)); belle_sip_object_ref(uri->header_list); } }
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END belle_sip_multipart_body_handler_t *belle_sip_multipart_body_handler_new(belle_sip_body_handler_progress_callback_t progress_cb, void *data, belle_sip_body_handler_t *first_part, const char *boundary){ belle_sip_multipart_body_handler_t *obj=belle_sip_object_new(belle_sip_multipart_body_handler_t); belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,progress_cb,data); if (boundary != NULL) { obj->boundary = belle_sip_strdup(boundary); } else { obj->boundary = belle_sip_strdup(BELLESIP_MULTIPART_BOUNDARY); } obj->base.expected_size = strlen(obj->boundary) + 8; /* body's length will be part length(including boundary) + multipart end. 8 is for "\r\n--" and "--\r\n" */ if (first_part) belle_sip_multipart_body_handler_add_part(obj,first_part); return obj; }
static void* test_object_data_string_clone(const char*name, void* data){ clone_called++; if( strcmp(name, "test_str") == 0) return belle_sip_strdup(data); else return data; }
static LinphoneNatPolicy * _linphone_nat_policy_new_with_ref(LinphoneCore *lc, const char *ref) { LinphoneNatPolicy *policy = belle_sip_object_new(LinphoneNatPolicy); belle_sip_object_ref(policy); policy->lc = lc; policy->ref = belle_sip_strdup(ref); return policy; }
belle_sip_request_t* try_register_user_at_domain(belle_sip_stack_t * stack ,belle_sip_provider_t *prov ,const char *transport ,int use_transaction ,const char* username ,const char* domain ,const char* outbound_proxy ,int success_expected) { belle_sip_request_t *req,*copy; char identity[256]; char uri[256]; int i; char *outbound=NULL; number_of_challenge=0; if (transport) snprintf(uri,sizeof(uri),"sip:%s;transport=%s",domain,transport); else snprintf(uri,sizeof(uri),"sip:%s",domain); if (transport && strcasecmp("tls",transport)==0 && belle_sip_provider_get_listening_point(prov,"tls")==NULL){ belle_sip_error("No TLS support, test skipped."); return NULL; } if (outbound_proxy){ if (strstr(outbound_proxy,"sip:")==NULL && strstr(outbound_proxy,"sips:")==NULL){ outbound=belle_sip_strdup_printf("sip:%s",outbound_proxy); }else outbound=belle_sip_strdup(outbound_proxy); } snprintf(identity,sizeof(identity),"Tester <sip:%s@%s>",username,domain); req=belle_sip_request_create( belle_sip_uri_parse(uri), "REGISTER", belle_sip_provider_create_call_id(prov), belle_sip_header_cseq_create(20,"REGISTER"), belle_sip_header_from_create2(identity,BELLE_SIP_RANDOM_TAG), belle_sip_header_to_create2(identity,NULL), belle_sip_header_via_new(), 70); is_register_ok=0; io_error_count=0; using_transaction=0; belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(600))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_contact_new())); copy=(belle_sip_request_t*)belle_sip_object_ref(belle_sip_object_clone((belle_sip_object_t*)req)); belle_sip_provider_add_sip_listener(prov,l=BELLE_SIP_LISTENER(listener)); if (use_transaction){ belle_sip_client_transaction_t *t=belle_sip_provider_create_client_transaction(prov,req); belle_sip_client_transaction_send_request_to(t,outbound?belle_sip_uri_parse(outbound):NULL); }else belle_sip_provider_send_request(prov,req); for(i=0;!is_register_ok && i<2 && io_error_count==0;i++) belle_sip_stack_sleep(stack,5000); CU_ASSERT_EQUAL(is_register_ok,success_expected); if (success_expected) CU_ASSERT_EQUAL(using_transaction,use_transaction); belle_sip_provider_remove_sip_listener(prov,l); if (outbound) belle_sip_free(outbound); return copy; }
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_http_provider_t *belle_http_provider_new(belle_sip_stack_t *s, const char *bind_ip){ belle_http_provider_t *p=belle_sip_object_new(belle_http_provider_t); p->stack=s; p->bind_ip=belle_sip_strdup(bind_ip); p->ai_family=strchr(p->bind_ip,':') ? AF_INET6 : AF_INET; p->verify_ctx=belle_tls_verify_policy_new(); return p; }
void belle_sip_object_set_name(belle_sip_object_t* object,const char* name) { if (object->name) { belle_sip_free(object->name); object->name=NULL; } if (name) object->name=belle_sip_strdup(name); }
static LinphoneXmlRpcRequest * _linphone_xml_rpc_request_new(const char *method, LinphoneXmlRpcArgType return_type) { LinphoneXmlRpcRequest *request = belle_sip_object_new(LinphoneXmlRpcRequest); request->callbacks = linphone_xml_rpc_request_cbs_new(); request->status = LinphoneXmlRpcStatusPending; request->response.type = return_type; request->method = belle_sip_strdup(method); return request; }
void sal_set_uuid(Sal *sal, const char *uuid){ if (sal->uuid){ belle_sip_free(sal->uuid); sal->uuid=NULL; } if (uuid) sal->uuid=belle_sip_strdup(uuid); }
void belle_sip_refresher_set_realm(belle_sip_refresher_t* refresher, const char* realm) { if (refresher->realm){ belle_sip_free(refresher->realm); refresher->realm = NULL; } if (realm!=NULL){ refresher->realm=belle_sip_strdup(realm); } }
void linphone_content_set_name(LinphoneContent *content, const char *name) { if (content->name != NULL) { belle_sip_free(content->name); content->name = NULL; } if (name != NULL) { content->name = belle_sip_strdup(name); } }
void linphone_nat_policy_set_stun_server_username(LinphoneNatPolicy *policy, const char *username) { char *new_username = NULL; if (username != NULL) new_username = belle_sip_strdup(username); if (policy->stun_server_username != NULL) { belle_sip_free(policy->stun_server_username); policy->stun_server_username = NULL; } if (new_username != NULL) policy->stun_server_username = new_username; }
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END belle_sip_file_body_handler_t *belle_sip_file_body_handler_new(const char *filepath, belle_sip_body_handler_progress_callback_t progress_cb, void *data) { struct stat statbuf; belle_sip_file_body_handler_t *obj = belle_sip_object_new(belle_sip_file_body_handler_t); belle_sip_body_handler_init((belle_sip_body_handler_t*)obj, progress_cb, data); obj->filepath = belle_sip_strdup(filepath); if (stat(obj->filepath, &statbuf) == 0) { obj->base.expected_size = statbuf.st_size; } return obj; }
int belle_tls_verify_policy_set_root_ca(belle_tls_verify_policy_t *obj, const char *path){ if (obj->root_ca){ belle_sip_free(obj->root_ca); obj->root_ca=NULL; } if (path){ obj->root_ca=belle_sip_strdup(path); belle_sip_message("Root ca path set to %s",obj->root_ca); } else { belle_sip_message("Root ca path disabled"); } return 0; }
void linphone_nat_policy_set_stun_server(LinphoneNatPolicy *policy, const char *stun_server) { char *new_stun_server = NULL; if (stun_server != NULL) new_stun_server = belle_sip_strdup(stun_server); if (policy->stun_server != NULL) { belle_sip_free(policy->stun_server); policy->stun_server = NULL; } if (new_stun_server != NULL) { policy->stun_server = new_stun_server; linphone_nat_policy_resolve_stun_server(policy); } }
int belle_sip_tls_listening_point_set_root_ca(belle_sip_tls_listening_point_t *lp, const char *path){ if (lp->root_ca){ belle_sip_free(lp->root_ca); lp->root_ca=NULL; } if (path){ lp->root_ca=belle_sip_strdup(path); belle_sip_message("Root ca path set to %s",lp->root_ca); } else { belle_sip_message("Root ca path disabled"); } return 0; }
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END void belle_sip_server_transaction_init(belle_sip_server_transaction_t *t, belle_sip_provider_t *prov,belle_sip_request_t *req){ const char *branch; belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)req,"via")); branch=belle_sip_header_via_get_branch(via); if (branch==NULL || strncmp(branch,BELLE_SIP_BRANCH_MAGIC_COOKIE,strlen(BELLE_SIP_BRANCH_MAGIC_COOKIE))!=0){ branch=req->rfc2543_branch; if (branch==NULL) belle_sip_fatal("No computed branch for RFC2543 style of message, this should never happen."); } t->base.branch_id=belle_sip_strdup(branch); belle_sip_transaction_init((belle_sip_transaction_t*)t,prov,req); belle_sip_random_token(t->to_tag,sizeof(t->to_tag)); }
belle_http_request_t *belle_http_request_create(const char *method, belle_generic_uri_t *url, ...){ va_list vl; belle_http_request_t *obj=belle_http_request_new(); belle_sip_header_t *header; obj->method=belle_sip_strdup(method); obj->req_uri=(belle_generic_uri_t*)belle_sip_object_ref(url); va_start(vl,url); while((header=va_arg(vl,belle_sip_header_t*))!=NULL){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(obj),header); } va_end(vl); return obj; }
char* belle_sip_object_to_string(void* _obj) { belle_sip_object_t *obj=BELLE_SIP_OBJECT(_obj); if (obj->vptr->tostring_bufsize_hint!=0){ return belle_sip_object_to_alloc_string(obj,obj->vptr->tostring_bufsize_hint); }else{ char buff[BELLE_SIP_MAX_TO_STRING_SIZE]; size_t offset=0; belle_sip_error_code error = belle_sip_object_marshal(obj,buff,sizeof(buff),&offset); if (error==BELLE_SIP_BUFFER_OVERFLOW){ belle_sip_message("belle_sip_object_to_string(): temporary buffer is too short while doing to_string() for %s, retrying", obj->vptr->type_name); return belle_sip_object_to_alloc_string(obj,get_hint_size(2*offset)); } buff[offset]='\0'; obj->vptr->tostring_bufsize_hint=get_hint_size(2*offset); return belle_sip_strdup(buff); } }
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END void belle_sip_client_transaction_init(belle_sip_client_transaction_t *obj, belle_sip_provider_t *prov, belle_sip_request_t *req){ belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)req,"via")); char token[BELLE_SIP_BRANCH_ID_LENGTH]; if (!via){ belle_sip_fatal("belle_sip_client_transaction_init(): No via in request."); } if (strcmp(belle_sip_request_get_method(req),"CANCEL")!=0){ obj->base.branch_id=belle_sip_strdup_printf(BELLE_SIP_BRANCH_MAGIC_COOKIE ".%s",belle_sip_random_token(token,sizeof(token))); belle_sip_header_via_set_branch(via,obj->base.branch_id); }else{ obj->base.branch_id=belle_sip_strdup(belle_sip_header_via_get_branch(via)); } belle_sip_transaction_init((belle_sip_transaction_t*)obj, prov,req); }
static void split_request_url(belle_http_request_t *req){ belle_generic_uri_t *uri=belle_http_request_get_uri(req); belle_generic_uri_t *new_uri; char *host_value; const char *path; if (belle_generic_uri_get_host(uri)==NULL && req->orig_uri!=NULL) return;/*already processed request uri*/ path=belle_generic_uri_get_path(uri); if (path==NULL) path="/"; new_uri=belle_generic_uri_new(); belle_generic_uri_set_path(new_uri,path); belle_generic_uri_set_query(new_uri, belle_generic_uri_get_query(uri)); if (belle_generic_uri_get_port(uri)>0) host_value=belle_sip_strdup_printf("%s:%i",belle_generic_uri_get_host(uri),belle_generic_uri_get_port(uri)); else host_value=belle_sip_strdup(belle_generic_uri_get_host(uri)); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Host",host_value)); belle_sip_free(host_value); SET_OBJECT_PROPERTY(req,orig_uri,uri); belle_http_request_set_uri(req,new_uri); }
void belle_sip_channel_set_public_ip_port(belle_sip_channel_t *obj, const char *public_ip, int port){ if (obj->public_ip){ int ip_changed=0; int port_changed=0; if (public_ip && strcmp(obj->public_ip,public_ip)!=0){ ip_changed=1; } if (port!=obj->public_port){ port_changed=1; } if (ip_changed || port_changed){ belle_sip_warning("channel [%p]: public ip is changed from [%s:%i] to [%s:%i]",obj,obj->public_ip,obj->public_port,public_ip,port); } belle_sip_free(obj->public_ip); obj->public_ip=NULL; }else if (public_ip){ belle_sip_message("channel [%p]: discovered public ip and port are [%s:%i]",obj,public_ip,port); } if (public_ip){ obj->public_ip=belle_sip_strdup(public_ip); } obj->public_port=port; }
void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t slen){ char name[NI_MAXHOST]; char serv[NI_MAXSERV]; if (obj->local_ip==NULL){ struct sockaddr_storage saddr; socklen_t slen2=sizeof(saddr); int err; belle_sip_address_remove_v4_mapping(addr,(struct sockaddr*) &saddr,&slen2); err=getnameinfo((struct sockaddr*)&saddr,slen,name,sizeof(name),serv,sizeof(serv),NI_NUMERICHOST|NI_NUMERICSERV); if (err!=0){ belle_sip_error("belle_sip_channel_set_ready(): getnameinfo() failed: %s",gai_strerror(err)); }else{ obj->local_ip=belle_sip_strdup(name); obj->local_port=atoi(serv); belle_sip_message("Channel has local address %s:%s",name,serv); } } channel_set_state(obj,BELLE_SIP_CHANNEL_READY); channel_process_queue(obj); channel_end_send_background_task(obj); }
static void parse_valid_xml_rpc_response(LinphoneXmlRpcRequest *request, const char *response_body) { xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new(); xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); request->status = LinphoneXmlRpcStatusFailed; xml_ctx->doc = xmlReadDoc((const unsigned char*)response_body, 0, NULL, 0); if (xml_ctx->doc != NULL) { const char *response_str = NULL; if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end; switch (request->response.type) { case LinphoneXmlRpcArgInt: response_str = linphone_get_xml_text_content(xml_ctx, "/methodResponse/params/param/value/int"); if (response_str != NULL) { request->response.data.i = atoi(response_str); request->status = LinphoneXmlRpcStatusOk; } break; case LinphoneXmlRpcArgString: response_str = linphone_get_xml_text_content(xml_ctx, "/methodResponse/params/param/value/string"); if (response_str != NULL) { request->response.data.s = belle_sip_strdup(response_str); request->status = LinphoneXmlRpcStatusOk; } break; default: break; } if (response_str) linphone_free_xml_text_content(response_str); } else { ms_warning("Wrongly formatted XML-RPC response: %s", xml_ctx->errorBuffer); } end: linphone_xmlparsing_context_destroy(xml_ctx); if (request->callbacks->response != NULL) { request->callbacks->response(request); } }