From 82ec76a4e1c1b63c028955303d954c430b9a5954 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 24 Jul 2014 16:19:19 +0200 Subject: [PATCH] Reuse previous nonce if outbound proxy realm is set to avoid reauthentication --- coreapi/authentication.c | 23 ++++++++++---------- coreapi/bellesip_sal/sal_impl.c | 2 +- coreapi/bellesip_sal/sal_op_impl.c | 11 +++++----- coreapi/bellesip_sal/sal_op_presence.c | 15 ++++++------- coreapi/linphonecall.c | 3 ++- coreapi/linphonecore.c | 1 + coreapi/linphonecore.h | 14 +++++++++++++ coreapi/private.h | 1 + coreapi/proxy.c | 29 ++++++++++++++++++-------- coreapi/sal.c | 11 ++++++++++ include/sal/sal.h | 2 ++ 11 files changed, 77 insertions(+), 35 deletions(-) diff --git a/coreapi/authentication.c b/coreapi/authentication.c index d763f8902..59b3ea1b5 100644 --- a/coreapi/authentication.c +++ b/coreapi/authentication.c @@ -21,7 +21,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - + #include "linphonecore.h" #include "private.h" #include "lpconfig.h" @@ -143,7 +143,7 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in char key[50]; sprintf(key,"auth_info_%i",pos); lp_config_clean_section(config,key); - + if (obj==NULL || lp_config_get_int(config, "sip", "store_auth_info", 1) == 0){ return; } @@ -176,12 +176,12 @@ LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int char key[50]; const char *username,*userid,*passwd,*ha1,*realm,*domain; LinphoneAuthInfo *ret; - + sprintf(key,"auth_info_%i",pos); if (!lp_config_has_section(config,key)){ return NULL; } - + username=lp_config_get_string(config,key,"username",NULL); userid=lp_config_get_string(config,key,"userid",NULL); passwd=lp_config_get_string(config,key,"passwd",NULL); @@ -221,7 +221,7 @@ static int realm_match(const char *realm1, const char *realm2){ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *username, const char *realm, const char *domain){ MSList *elem; const LinphoneAuthInfo *ret=NULL; - + for (elem=lc->auth_info;elem!=NULL;elem=elem->next) { LinphoneAuthInfo *pinfo = (LinphoneAuthInfo*)elem->data; if (username && pinfo->username && strcmp(username,pinfo->username)==0) { @@ -240,7 +240,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user } } else if (domain && pinfo->domain && strcmp(domain,pinfo->domain)==0) { return pinfo; - } else if (!domain) { + } else if (!domain) { return pinfo; } } @@ -249,7 +249,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user } /** - * Find authentication info matching realm, username, domain criterias. + * Find authentication info matching realm, username, domain criteria. * First of all, (realm,username) pair are searched. If multiple results (which should not happen because realm are supposed to be unique), then domain is added to the search. * @param lc the LinphoneCore * @param realm the authentication 'realm' (optional) @@ -264,7 +264,7 @@ const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const cha if (ai==NULL && domain){ ai=find_auth_info(lc,username,realm,domain); } - } + } if (ai == NULL && domain != NULL) { ai=find_auth_info(lc,username,NULL,domain); } @@ -292,8 +292,8 @@ LinphoneAuthInfo * linphone_core_create_auth_info(LinphoneCore *lc, const char * /** * Adds authentication information to the LinphoneCore. - * - * This information will be used during all SIP transacations that require authentication. + * + * This information will be used during all SIP transactions that require authentication. **/ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){ LinphoneAuthInfo *ai; @@ -301,7 +301,7 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info) MSList *l; int restarted_op_count=0; bool_t updating=FALSE; - + if (info->ha1==NULL && info->passwd==NULL){ ms_error("linphone_core_add_auth_info(): info supplied with empty password or ha1."); return; @@ -371,7 +371,6 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in r=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain); if (r){ lc->auth_info=ms_list_remove(lc->auth_info,r); - /*printf("len=%i newlen=%i\n",len,newlen);*/ linphone_auth_info_destroy(r); write_auth_infos(lc); } diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 9693226dd..ab7714fa9 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -137,7 +137,7 @@ void sal_process_authentication(SalOp *op) { return; } - if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list)) { + if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list,op->base.realm)) { if (is_within_dialog) { sal_op_send_request(op,new_request); } else { diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 649a4e240..e548cec43 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -137,7 +137,7 @@ static void add_initial_route_set(belle_sip_request_t *request, const MSList *li continue; } } - + route=belle_sip_header_route_create((belle_sip_header_address_t*)addr); uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route); belle_sip_uri_set_lr_param(uri,1); @@ -180,11 +180,11 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity)); } - + if (elem && strcmp(method,"REGISTER")!=0 && !op->base.root->no_initial_route){ add_initial_route_set(req,elem); } - + if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){ belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new(); if (op->privacy&SalPrivacyCritical) @@ -332,7 +332,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req 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); + 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*/); @@ -608,7 +608,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp belle_sip_object_unref(op->refresher); } if ((op->refresher = belle_sip_client_transaction_create_refresher(op->pending_client_trans))) { - /*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified + /*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified * that it is terminated anymore.*/ sal_op_unref(op);/*loose the reference that was given to the transaction when creating it*/ /* Note that the refresher will replace our data with belle_sip_transaction_set_application_data(). @@ -617,6 +617,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp notify the user as a normal transaction*/ belle_sip_refresher_set_listener(op->refresher,listener,op); belle_sip_refresher_set_retry_after(op->refresher,op->base.root->refresher_retry_after); + belle_sip_refresher_set_realm(op->refresher,op->base.realm); belle_sip_refresher_enable_manual_mode(op->refresher,op->manual_refresher); return 0; } else { diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c index e1ab054aa..23db49e6f 100644 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ b/coreapi/bellesip_sal/sal_op_presence.c @@ -35,7 +35,7 @@ void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceMo belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_TYPE); belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_LENGTH); belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),NULL,0); - + if (content){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) ,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","pidf+xml"))); @@ -95,7 +95,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); int code = belle_sip_response_get_status_code(response); belle_sip_header_expires_t* expires; - + sal_op_set_error_info_from_response(op,response); if (code>=300) { @@ -127,6 +127,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even if (expires>0){ op->refresher=belle_sip_client_transaction_create_refresher(client_transaction); belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener,op); + belle_sip_refresher_set_realm(op->refresher,op->base.realm); } } break; @@ -164,7 +165,7 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req return NULL; if (belle_sip_header_content_length_get_content_length(content_length) == 0) return NULL; - + if (body==NULL) return NULL; op->base.root->callbacks.parse_presence_requested(op, @@ -181,7 +182,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){ belle_sip_server_transaction_t* server_transaction=op->pending_server_trans; belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); SalSubscribeStatus sub_state; - + if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { SalPresenceModel *presence_model = NULL; const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); @@ -194,7 +195,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){ presence_model = process_presence_notification(op, req); if (presence_model != NULL || body==NULL) { /* Presence notification body parsed successfully. */ - + resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */ op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL); } else if (body){ @@ -214,7 +215,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); belle_sip_response_t* resp; 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; @@ -256,7 +257,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques } } break; - default: + default: ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); break; } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 15df7990b..edfd973d2 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -724,6 +724,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro from_str=linphone_address_as_string_uri_only(from); sal_op_set_route(call->ping_op,sal_op_get_network_origin(op)); sal_op_set_user_pointer(call->ping_op,call); + sal_op_set_realm(call->ping_op,linphone_proxy_config_get_realm(linphone_core_lookup_known_proxy(call->core, to))); sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from),from_str); ms_free(from_str); } @@ -1313,7 +1314,7 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){ * Note that the snapshot is asynchronous, an application shall not assume that the file is created when the function returns. * @param call a LinphoneCall * @param file a path where to write the jpeg content. - * @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported). + * @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported). **/ int linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file){ #ifdef VIDEO_ENABLED diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c9b2dd4f0..35d91976d 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2824,6 +2824,7 @@ void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *d sal_op_set_to_address(op,dest); sal_op_set_from(op,identity); sal_op_set_sent_custom_header(op,headers); + sal_op_set_realm(op,linphone_proxy_config_get_realm(proxy)); if (with_contact && proxy && proxy->op){ const SalAddress *contact; if ((contact=sal_op_get_contact_address(proxy->op))){ diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 6e0d88807..518ad7c4d 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -917,6 +917,20 @@ LINPHONE_PUBLIC bool_t linphone_proxy_config_is_registered(const LinphoneProxyCo **/ LINPHONE_PUBLIC const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg); +/** + * Get the realm of the given proxy config. + * @param[in] cfg #LinphoneProxyConfig object. + * @returns The realm of the proxy config. +**/ +LINPHONE_PUBLIC const char *linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg); +/** + * Set the realm of the given proxy config. + * @param[in] cfg #LinphoneProxyConfig object. + * @param[in] realm New realm value. + * @returns The realm of the proxy config. +**/ +LINPHONE_PUBLIC void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char * realm); + LINPHONE_PUBLIC const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj); LINPHONE_PUBLIC const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj); LINPHONE_PUBLIC bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj); diff --git a/coreapi/private.h b/coreapi/private.h index 32e013c94..f1f6fdf38 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -423,6 +423,7 @@ struct _LinphoneProxyConfig char *reg_identity; char *reg_route; char *quality_reporting_collector; + char *domain; char *realm; char *contact_params; char *contact_uri_params; diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 409ddb4a3..619c98814 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -94,6 +94,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob const char *identity = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_identity", NULL) : NULL; const char *proxy = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_proxy", NULL) : NULL; const char *route = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_route", NULL) : NULL; + const char *realm = lc ? lp_config_get_default_string(lc->config, "proxy", "realm", NULL) : NULL; const char *quality_reporting_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "quality_reporting_collector", NULL) : NULL; const char *contact_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_parameters", NULL) : NULL; const char *contact_uri_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_uri_parameters", NULL) : NULL; @@ -108,6 +109,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob obj->reg_identity = identity ? ms_strdup(identity) : NULL; obj->reg_proxy = proxy ? ms_strdup(proxy) : NULL; obj->reg_route = route ? ms_strdup(route) : NULL; + obj->realm = realm ? ms_strdup(realm) : NULL; obj->quality_reporting_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0; obj->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL; obj->quality_reporting_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_interval", 0) : 0; @@ -150,6 +152,7 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){ if (obj->reg_route!=NULL) ms_free(obj->reg_route); if (obj->quality_reporting_collector!=NULL) ms_free(obj->quality_reporting_collector); if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx); + if (obj->domain!=NULL) ms_free(obj->domain); if (obj->realm!=NULL) ms_free(obj->realm); if (obj->type!=NULL) ms_free(obj->type); if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix); @@ -228,10 +231,10 @@ int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *ide obj->reg_identity=NULL; } obj->reg_identity=ms_strdup(identity); - if (obj->realm){ - ms_free(obj->realm); + if (obj->domain){ + ms_free(obj->domain); } - obj->realm=ms_strdup(linphone_address_get_domain(addr)); + obj->domain=ms_strdup(linphone_address_get_domain(addr)); linphone_address_destroy(addr); return 0; } @@ -240,7 +243,7 @@ int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *ide } const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){ - return cfg->realm; + return cfg->domain; } /** @@ -310,7 +313,7 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){ /** * Prevent a proxy config from refreshing its registration. - * This is useful to let registrations to expire naturally (or) when the application wants to keep control on when + * This is useful to let registrations to expire naturally (or) when the application wants to keep control on when * refreshes are sent. * However, linphone_core_set_network_reachable(lc,TRUE) will always request the proxy configs to refresh their registrations. * The refreshing operations can be resumed with linphone_proxy_config_refresh_register(). @@ -422,6 +425,7 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ linphone_address_destroy(contact); } sal_op_set_user_pointer(obj->op,obj); + sal_op_set_realm(obj->op, obj->realm); if (sal_register(obj->op,proxy_string,obj->reg_identity,obj->expires)==0) { linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress"); } else { @@ -946,13 +950,16 @@ int linphone_proxy_config_done(LinphoneProxyConfig *obj) return 0; } +const char* linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg) +{ + return cfg?cfg->realm:NULL; +} void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm) { if (cfg->realm!=NULL) { ms_free(cfg->realm); - cfg->realm=NULL; } - if (realm!=NULL) cfg->realm=ms_strdup(realm); + cfg->realm=ms_strdup(realm); } int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){ @@ -964,6 +971,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese sal_op_set_route(proxy->publish_op,proxy->reg_proxy); sal_op_set_from(proxy->publish_op,linphone_proxy_config_get_identity(proxy)); sal_op_set_to(proxy->publish_op,linphone_proxy_config_get_identity(proxy)); + sal_op_set_realm(proxy->publish_op,linphone_proxy_config_get_realm(proxy)); if (lp_config_get_int(proxy->lc->config,"sip","publish_msg_with_contact",0)){ SalAddress *addr=sal_address_new(linphone_proxy_config_get_identity(proxy)); sal_op_set_contact_address(proxy->publish_op,addr); @@ -1205,6 +1213,9 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC if (obj->reg_identity!=NULL){ lp_config_set_string(config,key,"reg_identity",obj->reg_identity); } + if (obj->realm!=NULL){ + lp_config_set_string(config,key,"realm",obj->realm); + } if (obj->contact_params!=NULL){ lp_config_set_string(config,key,"contact_parameters",obj->contact_params); } @@ -1259,10 +1270,10 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc CONFIGURE_STRING_VALUE(cfg,config,key,server_addr,"reg_proxy") CONFIGURE_STRING_VALUE(cfg,config,key,route,"reg_route") + CONFIGURE_STRING_VALUE(cfg,config,key,realm,"realm") + CONFIGURE_BOOL_VALUE(cfg,config,key,quality_reporting,"quality_reporting_enabled") - CONFIGURE_STRING_VALUE(cfg,config,key,quality_reporting_collector,"quality_reporting_collector") - CONFIGURE_INT_VALUE(cfg,config,key,quality_reporting_interval,"quality_reporting_interval") CONFIGURE_STRING_VALUE(cfg,config,key,contact_parameters,"contact_parameters") diff --git a/coreapi/sal.c b/coreapi/sal.c index 24da751b6..8a48c79d0 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -386,6 +386,13 @@ void sal_op_add_route_address(SalOp *op, const SalAddress *address){ sal_op_set_route_address(op,address); } } +void sal_op_set_realm(SalOp *op, const char *realm){ + SalOpBase* op_base = (SalOpBase*)op; + if (op_base->realm != NULL){ + ms_free(op_base->realm); + } + op_base->realm = ms_strdup(realm); +} void sal_op_set_from(SalOp *op, const char *from){ SET_PARAM(op,from); } @@ -511,6 +518,10 @@ void __sal_op_free(SalOp *op){ ms_free(b->route); b->route=NULL; } + if (b->realm) { + ms_free(b->realm); + b->realm=NULL; + } if (b->contact_address) { sal_address_destroy(b->contact_address); } diff --git a/include/sal/sal.h b/include/sal/sal.h index 5533182ed..ffca87c5f 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -285,6 +285,7 @@ typedef struct SalOpBase{ SalMediaDescription *remote_media; void *user_pointer; const char* call_id; + char* realm; SalAddress* service_route; /*as defined by rfc3608, might be a list*/ SalCustomHeader *sent_custom_headers; SalCustomHeader *recv_custom_headers; @@ -560,6 +561,7 @@ void sal_op_set_contact_address(SalOp *op, const SalAddress* address); void sal_op_set_route(SalOp *op, const char *route); void sal_op_set_route_address(SalOp *op, const SalAddress* address); void sal_op_add_route_address(SalOp *op, const SalAddress* address); +void sal_op_set_realm(SalOp *op, const char *realm); void sal_op_set_from(SalOp *op, const char *from); void sal_op_set_from_address(SalOp *op, const SalAddress *from); void sal_op_set_to(SalOp *op, const char *to);