static void testSIPSURI(void) { belle_sip_uri_t * L_uri = belle_sip_uri_parse("sips:linphone.org"); char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri)); belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri)); L_uri = belle_sip_uri_parse(l_raw_uri); belle_sip_free(l_raw_uri); CU_ASSERT_EQUAL(belle_sip_uri_is_secure(L_uri), 1); belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri)); L_uri = belle_sip_uri_parse("sip:linphone.org"); CU_ASSERT_EQUAL(belle_sip_uri_is_secure(L_uri), 0); belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri)); }
const char *sal_address_get_scheme(const SalAddress *addr){ belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr); belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr); if (uri) { if (belle_sip_uri_is_secure(uri)) return "sips"; else return "sip"; } else return NULL; }
int belle_sip_uri_get_listening_port(const belle_sip_uri_t *uri){ int port=belle_sip_uri_get_port(uri); const char *transport=belle_sip_uri_get_transport_param(uri); if (!transport) { transport=belle_sip_uri_is_secure(uri)?"tls":"udp"; } if (port==0) port=belle_sip_listening_point_get_well_known_port(transport); return port; }
static int belle_sip_dialog_init_as_uac(belle_sip_dialog_t *obj, belle_sip_request_t *req, belle_sip_response_t *resp){ const belle_sip_list_t *elem; belle_sip_header_contact_t *ct=belle_sip_message_get_header_by_type(resp,belle_sip_header_contact_t); belle_sip_header_cseq_t *cseq=belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); belle_sip_header_to_t *to=belle_sip_message_get_header_by_type(resp,belle_sip_header_to_t); belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(req,belle_sip_header_via_t); belle_sip_uri_t *requri=belle_sip_request_get_uri(req); if (!to){ belle_sip_error("No to in response."); return -1; } if (!cseq){ belle_sip_error("No cseq in request."); return -1; } if (!via){ belle_sip_error("No via in request."); return -1; } if (strcasecmp(belle_sip_header_via_get_protocol(via),"TLS")==0 && belle_sip_uri_is_secure(requri)){ obj->is_secure=TRUE; } /**12.1.2 * The route set MUST be set to the list of URIs in the Record-Route *header field from the response, taken in reverse order and preserving *all URI parameters. If no Record-Route header field is present in *the response, the route set MUST be set to the empty set. **/ obj->route_set=belle_sip_list_free_with_data(obj->route_set,belle_sip_object_unref); for(elem=belle_sip_message_get_headers((belle_sip_message_t*)resp,BELLE_SIP_RECORD_ROUTE);elem!=NULL;elem=elem->next){ obj->route_set=belle_sip_list_prepend(obj->route_set,belle_sip_object_ref(belle_sip_header_route_create( (belle_sip_header_address_t*)elem->data))); } check_route_set(obj->route_set); /*contact might be provided later*/ if (ct) obj->remote_target=(belle_sip_header_address_t*)belle_sip_object_ref(ct); obj->local_cseq=belle_sip_header_cseq_get_seq_number(cseq); /*call id is already set */ /*local_tag is already set*/ obj->remote_party=(belle_sip_header_address_t*)belle_sip_object_ref(to); /*local party is already set*/ if (strcmp(belle_sip_request_get_method(req),"INVITE")==0){ set_last_out_invite(obj,req); } return 0; }
belle_sip_hop_t* belle_sip_hop_new_from_uri(const belle_sip_uri_t *uri){ const char *host; const char *cname=NULL; const char * transport=belle_sip_uri_get_transport_param(uri); if (!transport) { transport=belle_sip_uri_is_secure(uri)?"tls":"udp"; } host=belle_sip_uri_get_maddr_param(uri); if (!host) host=belle_sip_uri_get_host(uri); else cname=belle_sip_uri_get_host(uri); return belle_sip_hop_new( transport, cname, host, belle_sip_uri_get_listening_port(uri)); }
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; }
/* * RFC 3261 SIP: Session Initiation Protocol June 2002 * 19.1.4 URI Comparison Some operations in this specification require determining whether two SIP or SIPS URIs are equivalent. In this specification, registrars need to compare bindings in Contact URIs in REGISTER requests (see Section 10.3.). SIP and SIPS URIs are compared for equality according to the following rules: */ int belle_sip_uri_equals(const belle_sip_uri_t* uri_a,const belle_sip_uri_t* uri_b) { const belle_sip_list_t * params; const char* b_param; const char* a_param; /* o A SIP and SIPS URI are never equivalent. */ if (belle_sip_uri_is_secure(uri_a)!=belle_sip_uri_is_secure(uri_b)) { return 0; } /* o Comparison of the userinfo of SIP and SIPS URIs is case- sensitive. This includes userinfo containing passwords or formatted as telephone-subscribers. Comparison of all other components of the URI is case-insensitive unless explicitly defined otherwise. */ if (uri_a->user && uri_b->user) { if (IS_EQUAL(uri_a->user,uri_b->user)) return 0; } else if (uri_a->user != uri_a->user) { return 0; } /* o The ordering of parameters and header fields is not significant in comparing SIP and SIPS URIs. o Characters other than those in the "reserved" set (see RFC 2396 [5]) are equivalent to their ""%" HEX HEX" encoding. o An IP address that is the result of a DNS lookup of a host name does not match that host name. o For two URIs to be equal, the user, password, host, and port components must match. */ if (!uri_a->host || !uri_b->host) { return 0; } else if (IS_EQUAL_CASE(uri_a->host,uri_b->host)) { return 0; } if (uri_a->port !=uri_b->port) return 0; /* A URI omitting the user component will not match a URI that includes one. A URI omitting the password component will not match a URI that includes one. A URI omitting any component with a default value will not match a URI explicitly containing that component with its default value. For instance, a URI omitting the optional port component will not match a URI explicitly declaring port 5060. The same is true for the transport-parameter, ttl-parameter, user-parameter, and method components. Defining sip:user@host to not be equivalent to sip:user@host:5060 is a change from RFC 2543. When deriving addresses from URIs, equivalent addresses are expected from equivalent URIs. The URI sip:user@host:5060 will always resolve to port 5060. The URI sip:user@host may resolve to other ports through the DNS SRV mechanisms detailed in [4]. o URI uri-parameter components are compared as follows: - Any uri-parameter appearing in both URIs must match. */ /* * - A user, ttl, or method uri-parameter appearing in only one URI never matches, even if it contains the default value. - A URI that includes an maddr parameter will not match a URI that contains no maddr parameter. * */ PARAM_CASE_CMP(uri_a,uri_b,"transport") PARAM_CASE_CMP(uri_a,uri_b,"user") PARAM_CASE_CMP(uri_a,uri_b,"ttl") PARAM_CASE_CMP(uri_a,uri_b,"method") PARAM_CASE_CMP(uri_a,uri_b,"maddr") for(params=belle_sip_parameters_get_parameters((belle_sip_parameters_t*) uri_a);params!=NULL;params=params->next) { if ((b_param=belle_sip_parameters_get_parameter((belle_sip_parameters_t*) uri_b,(const char*)params->data)) !=NULL) { if (IS_EQUAL_CASE(b_param,(const char*)params->data)) return 0; } } /* - All other uri-parameters appearing in only one URI are ignored when comparing the URIs. */ /* *fixme ignored for now*/ /* o URI header components are never ignored. Any present header component MUST be present in both URIs and match for the URIs to match. The matching rules are defined for each header field in Section 20. */ return 1; }
bool_t sal_address_is_secure(const SalAddress *addr){ belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr); belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr); if (uri) return belle_sip_uri_is_secure(uri); return FALSE; }