1 /*
2 linphone
3 Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
4 */
5 /*
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #include "linphone/core.h"
22 #include "linphone/core_utils.h"
23 #include "linphone/sipsetup.h"
24 #include "linphone/lpconfig.h"
25 #include "private.h"
26 #include "mediastreamer2/mediastream.h"
27 #include "enum.h"
28 #include <ctype.h>
29
30 /*store current config related to server location*/
linphone_proxy_config_store_server_config(LinphoneProxyConfig * cfg)31 static void linphone_proxy_config_store_server_config(LinphoneProxyConfig* cfg) {
32 if (cfg->saved_identity) linphone_address_unref(cfg->saved_identity);
33 if (cfg->identity_address)
34 cfg->saved_identity = linphone_address_clone(cfg->identity_address);
35 else
36 cfg->saved_identity = NULL;
37
38 if (cfg->saved_proxy) linphone_address_unref(cfg->saved_proxy);
39 if (cfg->reg_proxy)
40 cfg->saved_proxy = linphone_address_new(cfg->reg_proxy);
41 else
42 cfg->saved_proxy = NULL;
43 }
44
linphone_proxy_config_address_equal(const LinphoneAddress * a,const LinphoneAddress * b)45 LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b) {
46 if (a == NULL && b == NULL)
47 return LinphoneProxyConfigAddressEqual;
48 else if (!a || !b)
49 return LinphoneProxyConfigAddressDifferent;
50
51 if (linphone_address_equal(a,b))
52 return LinphoneProxyConfigAddressEqual;
53 if (linphone_address_weak_equal(a,b)) {
54 /*also check both transport and uri */
55 if (linphone_address_get_secure(a) == linphone_address_get_secure(b) && linphone_address_get_transport(a) == linphone_address_get_transport(b))
56 return LinphoneProxyConfigAddressWeakEqual;
57 else
58 return LinphoneProxyConfigAddressDifferent;
59 }
60 return LinphoneProxyConfigAddressDifferent; /*either username, domain or port ar not equals*/
61 }
62
linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig * cfg)63 LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* cfg) {
64 LinphoneAddress *current_proxy=cfg->reg_proxy?linphone_address_new(cfg->reg_proxy):NULL;
65 LinphoneProxyConfigAddressComparisonResult result_identity;
66 LinphoneProxyConfigAddressComparisonResult result;
67
68 result = linphone_proxy_config_address_equal(cfg->saved_identity,cfg->identity_address);
69 if (result == LinphoneProxyConfigAddressDifferent) goto end;
70 result_identity = result;
71
72 result = linphone_proxy_config_address_equal(cfg->saved_proxy,current_proxy);
73 if (result == LinphoneProxyConfigAddressDifferent) goto end;
74 /** If the proxies are equal use the result of the difference between the identities,
75 * otherwise the result is weak-equal and so weak-equal must be returned even if the
76 * identities were equal.
77 */
78 if (result == LinphoneProxyConfigAddressEqual) result = result_identity;
79
80 end:
81 if (current_proxy) linphone_address_unref(current_proxy);
82 ms_message("linphone_proxy_config_is_server_config_changed : %i", result);
83 return result;
84 }
85
linphone_proxy_config_write_all_to_config_file(LinphoneCore * lc)86 void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
87 bctbx_list_t *elem;
88 int i;
89 if (!linphone_core_ready(lc)) return;
90
91 for(elem=lc->sip_conf.proxies,i=0;elem!=NULL;elem=bctbx_list_next(elem),i++){
92 LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
93 linphone_proxy_config_write_to_config_file(lc->config,cfg,i);
94 }
95 /*to ensure removed configs are erased:*/
96 linphone_proxy_config_write_to_config_file(lc->config,NULL,i);
97 lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy_config_index(lc));
98 }
99
linphone_proxy_config_init(LinphoneCore * lc,LinphoneProxyConfig * cfg)100 static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *cfg) {
101 const char *dial_prefix = lc ? lp_config_get_default_string(lc->config,"proxy","dial_prefix",NULL) : NULL;
102 const char *identity = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_identity", NULL) : NULL;
103 const char *proxy = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_proxy", NULL) : NULL;
104 const char *route = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_route", NULL) : NULL;
105 const char *realm = lc ? lp_config_get_default_string(lc->config, "proxy", "realm", NULL) : NULL;
106 const char *quality_reporting_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "quality_reporting_collector", NULL) : NULL;
107 const char *contact_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_parameters", NULL) : NULL;
108 const char *contact_uri_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_uri_parameters", NULL) : NULL;
109 const char *refkey = lc ? lp_config_get_default_string(lc->config, "proxy", "refkey", NULL) : NULL;
110 const char *nat_policy_ref = lc ? lp_config_get_default_string(lc->config, "proxy", "nat_policy_ref", NULL):NULL;
111 cfg->lc = lc;
112 cfg->expires = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_expires", 3600) : 3600;
113 cfg->reg_sendregister = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 1) : 1;
114 cfg->dial_prefix = dial_prefix ? ms_strdup(dial_prefix) : NULL;
115 cfg->dial_escape_plus = lc ? lp_config_get_default_int(lc->config, "proxy", "dial_escape_plus", 0) : 0;
116 cfg->privacy = lc ? lp_config_get_default_int(lc->config, "proxy", "privacy", LinphonePrivacyDefault) : LinphonePrivacyDefault;
117 cfg->identity_address = identity ? linphone_address_new(identity) : NULL;
118 cfg->reg_identity = cfg->identity_address ? linphone_address_as_string(cfg->identity_address) : NULL;
119 cfg->reg_proxy = proxy ? ms_strdup(proxy) : NULL;
120 cfg->reg_route = route ? ms_strdup(route) : NULL;
121 cfg->realm = realm ? ms_strdup(realm) : NULL;
122 cfg->quality_reporting_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0;
123 cfg->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL;
124 cfg->quality_reporting_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_interval", 0) : 0;
125 cfg->contact_params = contact_params ? ms_strdup(contact_params) : NULL;
126 cfg->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL;
127 cfg->avpf_mode = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf", LinphoneAVPFDefault) : LinphoneAVPFDefault;
128 cfg->avpf_rr_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf_rr_interval", 5) : 5;
129 cfg->publish_expires= lc ? lp_config_get_default_int(lc->config, "proxy", "publish_expires", -1) : -1;
130 cfg->publish = lc ? lp_config_get_default_int(lc->config, "proxy", "publish", FALSE) : FALSE;
131 cfg->refkey = refkey ? ms_strdup(refkey) : NULL;
132 if (nat_policy_ref) {
133 LinphoneNatPolicy *policy = linphone_config_create_nat_policy_from_section(lc->config,nat_policy_ref);
134 linphone_proxy_config_set_nat_policy(cfg, policy);
135 if (policy) {
136 linphone_nat_policy_unref(policy);
137 } else {
138 ms_error("Cannot create default nat policy with ref [%s] for proxy config [%p]",nat_policy_ref,cfg);
139 }
140 }
141 }
142
linphone_proxy_config_new()143 LinphoneProxyConfig *linphone_proxy_config_new() {
144 return linphone_core_create_proxy_config(NULL);
145 }
146
append_linphone_address(LinphoneAddress * addr,char * out)147 static char * append_linphone_address(LinphoneAddress *addr,char *out) {
148 char *res = out;
149 if (addr) {
150 char *tmp;
151 tmp = linphone_address_as_string(addr);
152 res = ms_strcat_printf(out, "%s",tmp);
153 ms_free(tmp);
154 }
155 return res;
156 };
append_string(const char * string,char * out)157 static char * append_string(const char * string,char *out) {
158 char *res = out;
159 if (string) {
160 res = ms_strcat_printf(out, "%s",string);
161 }
162 return res;
163 }
164 /*
165 * return true if computed value has changed
166 */
linphone_proxy_config_compute_publish_params_hash(LinphoneProxyConfig * cfg)167 bool_t linphone_proxy_config_compute_publish_params_hash(LinphoneProxyConfig * cfg) {
168 char * source = NULL;
169 char hash[33];
170 char saved;
171 unsigned long long previous_hash[2];
172 previous_hash[0] = cfg->previous_publish_config_hash[0];
173 previous_hash[1] = cfg->previous_publish_config_hash[1];
174
175 source = ms_strcat_printf(source, "%i",cfg->privacy);
176 source=append_linphone_address(cfg->identity_address, source);
177 source=append_string(cfg->reg_proxy,source);
178 source=append_string(cfg->reg_route,source);
179 source=append_string(cfg->realm,source);
180 source = ms_strcat_printf(source, "%i",cfg->publish_expires);
181 source = ms_strcat_printf(source, "%i",cfg->publish);
182 belle_sip_auth_helper_compute_ha1(source, "dummy", "dummy", hash);
183 ms_free(source);
184 saved = hash[16];
185 hash[16] = '\0';
186 cfg->previous_publish_config_hash[0] = strtoull(hash, (char **)NULL, 16);
187 hash[16] = saved;
188 cfg->previous_publish_config_hash[1] = strtoull(&hash[16], (char **)NULL, 16);
189 return previous_hash[0] != cfg->previous_publish_config_hash[0] || previous_hash[1] != cfg->previous_publish_config_hash[1];
190 }
191 static void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg);
192
193 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneProxyConfig);
194
195 BELLE_SIP_INSTANCIATE_VPTR(LinphoneProxyConfig, belle_sip_object_t,
196 (belle_sip_object_destroy_t)_linphone_proxy_config_destroy,
197 NULL, // clone
198 NULL, // marshal
199 FALSE
200 );
201
linphone_core_create_proxy_config(LinphoneCore * lc)202 LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) {
203 LinphoneProxyConfig *cfg = belle_sip_object_new(LinphoneProxyConfig);
204 linphone_proxy_config_init(lc,cfg);
205 return cfg;
206 }
207
_linphone_proxy_config_release_ops(LinphoneProxyConfig * cfg)208 void _linphone_proxy_config_release_ops(LinphoneProxyConfig *cfg){
209 if (cfg->op) {
210 sal_op_release(cfg->op);
211 cfg->op=NULL;
212 }
213 if (cfg->presence_publish_event){
214 linphone_event_terminate(cfg->presence_publish_event);
215 linphone_event_unref(cfg->presence_publish_event);
216 cfg->presence_publish_event=NULL;
217 }
218 }
219
_linphone_proxy_config_destroy(LinphoneProxyConfig * cfg)220 void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){
221 if (cfg->reg_proxy!=NULL) ms_free(cfg->reg_proxy);
222 if (cfg->reg_identity!=NULL) ms_free(cfg->reg_identity);
223 if (cfg->identity_address!=NULL) linphone_address_unref(cfg->identity_address);
224 if (cfg->reg_route!=NULL) ms_free(cfg->reg_route);
225 if (cfg->quality_reporting_collector!=NULL) ms_free(cfg->quality_reporting_collector);
226 if (cfg->ssctx!=NULL) sip_setup_context_free(cfg->ssctx);
227 if (cfg->realm!=NULL) ms_free(cfg->realm);
228 if (cfg->type!=NULL) ms_free(cfg->type);
229 if (cfg->dial_prefix!=NULL) ms_free(cfg->dial_prefix);
230 if (cfg->contact_params) ms_free(cfg->contact_params);
231 if (cfg->contact_uri_params) ms_free(cfg->contact_uri_params);
232 if (cfg->saved_proxy!=NULL) linphone_address_unref(cfg->saved_proxy);
233 if (cfg->saved_identity!=NULL) linphone_address_unref(cfg->saved_identity);
234 if (cfg->sent_headers!=NULL) sal_custom_header_free(cfg->sent_headers);
235 if (cfg->pending_contact) linphone_address_unref(cfg->pending_contact);
236 if (cfg->refkey) ms_free(cfg->refkey);
237 if (cfg->nat_policy != NULL) {
238 linphone_nat_policy_unref(cfg->nat_policy);
239 }
240 if (cfg->ei){
241 linphone_error_info_unref(cfg->ei);
242 }
243 _linphone_proxy_config_release_ops(cfg);
244 }
245
linphone_proxy_config_destroy(LinphoneProxyConfig * cfg)246 void linphone_proxy_config_destroy(LinphoneProxyConfig *cfg) {
247 belle_sip_object_unref(cfg);
248 }
249
_linphone_proxy_config_release(LinphoneProxyConfig * cfg)250 void _linphone_proxy_config_release(LinphoneProxyConfig *cfg) {
251 _linphone_proxy_config_release_ops(cfg);
252 belle_sip_object_unref(cfg);
253 }
254
linphone_proxy_config_ref(LinphoneProxyConfig * cfg)255 LinphoneProxyConfig *linphone_proxy_config_ref(LinphoneProxyConfig *cfg) {
256 belle_sip_object_ref(cfg);
257 return cfg;
258 }
259
linphone_proxy_config_unref(LinphoneProxyConfig * cfg)260 void linphone_proxy_config_unref(LinphoneProxyConfig *cfg) {
261 belle_sip_object_unref(cfg);
262 }
263
linphone_proxy_config_is_registered(const LinphoneProxyConfig * cfg)264 bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *cfg){
265 return cfg->state == LinphoneRegistrationOk;
266 }
267
linphone_proxy_config_set_server_addr(LinphoneProxyConfig * cfg,const char * server_addr)268 LinphoneStatus linphone_proxy_config_set_server_addr(LinphoneProxyConfig *cfg, const char *server_addr){
269 LinphoneAddress *addr=NULL;
270 char *modified=NULL;
271
272 if (cfg->reg_proxy!=NULL) ms_free(cfg->reg_proxy);
273 cfg->reg_proxy=NULL;
274
275 if (server_addr!=NULL && strlen(server_addr)>0){
276 if (strstr(server_addr,"sip:")==NULL && strstr(server_addr,"sips:")==NULL){
277 modified=ms_strdup_printf("sip:%s",server_addr);
278 addr=linphone_address_new(modified);
279 ms_free(modified);
280 }
281 if (addr==NULL)
282 addr=linphone_address_new(server_addr);
283 if (addr){
284 cfg->reg_proxy=linphone_address_as_string(addr);
285 linphone_address_unref(addr);
286 }else{
287 ms_warning("Could not parse %s",server_addr);
288 return -1;
289 }
290 }
291 return 0;
292 }
293
294
linphone_proxy_config_set_identity_address(LinphoneProxyConfig * cfg,const LinphoneAddress * addr)295 LinphoneStatus linphone_proxy_config_set_identity_address(LinphoneProxyConfig *cfg, const LinphoneAddress *addr){
296 if (!addr || linphone_address_get_username(addr)==NULL){
297 char* as_string = addr ? linphone_address_as_string(addr) : ms_strdup("NULL");
298 ms_warning("Invalid sip identity: %s", as_string);
299 ms_free(as_string);
300 return -1;
301 }
302 if (cfg->identity_address != NULL) {
303 linphone_address_unref(cfg->identity_address);
304 }
305 cfg->identity_address=linphone_address_clone(addr);
306
307 if (cfg->reg_identity!=NULL) {
308 ms_free(cfg->reg_identity);
309 }
310 cfg->reg_identity= linphone_address_as_string(cfg->identity_address);
311 return 0;
312 }
313
linphone_proxy_config_set_identity(LinphoneProxyConfig * cfg,const char * identity)314 LinphoneStatus linphone_proxy_config_set_identity(LinphoneProxyConfig *cfg, const char *identity){
315 if (identity!=NULL && strlen(identity)>0){
316 LinphoneAddress *addr=linphone_address_new(identity);
317 int ret=linphone_proxy_config_set_identity_address(cfg, addr);
318 if (addr) linphone_address_unref(addr);
319 return ret;
320 }
321 return -1;
322 }
323
linphone_proxy_config_get_domain(const LinphoneProxyConfig * cfg)324 const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
325 return cfg->identity_address ? linphone_address_get_domain(cfg->identity_address) : NULL;
326 }
327
linphone_proxy_config_set_route(LinphoneProxyConfig * cfg,const char * route)328 LinphoneStatus linphone_proxy_config_set_route(LinphoneProxyConfig *cfg, const char *route)
329 {
330 if (cfg->reg_route!=NULL){
331 ms_free(cfg->reg_route);
332 cfg->reg_route=NULL;
333 }
334 if (route!=NULL && route[0] !='\0'){
335 SalAddress *addr;
336 char *tmp;
337 /*try to prepend 'sip:' */
338 if (strstr(route,"sip:")==NULL && strstr(route,"sips:")==NULL){
339 tmp=ms_strdup_printf("sip:%s",route);
340 }else tmp=ms_strdup(route);
341 addr=sal_address_new(tmp);
342 if (addr!=NULL){
343 sal_address_destroy(addr);
344 cfg->reg_route=tmp;
345 return 0;
346 }else{
347 ms_free(tmp);
348 return -1;
349 }
350 } else {
351 return 0;
352 }
353 }
354
linphone_proxy_config_check(LinphoneCore * lc,LinphoneProxyConfig * cfg)355 bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *cfg){
356 if (cfg->reg_proxy==NULL){
357 if (lc)
358 linphone_core_notify_display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\""
359 " followed by a hostname."));
360 return FALSE;
361 }
362 if (cfg->identity_address==NULL){
363 if (lc)
364 linphone_core_notify_display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like "
365 "sip:username@proxydomain, such as sip:alice@example.net"));
366 return FALSE;
367 }
368 return TRUE;
369 }
370
linphone_proxy_config_enableregister(LinphoneProxyConfig * cfg,bool_t val)371 void linphone_proxy_config_enableregister(LinphoneProxyConfig *cfg, bool_t val){
372 if (val != cfg->reg_sendregister) cfg->register_changed = TRUE;
373 cfg->reg_sendregister=val;
374 }
375
linphone_proxy_config_set_expires(LinphoneProxyConfig * cfg,int val)376 void linphone_proxy_config_set_expires(LinphoneProxyConfig *cfg, int val){
377 if (val<0) val=600;
378 if (val != cfg->expires) cfg->register_changed = TRUE;
379 cfg->expires=val;
380 }
381
linphone_proxy_config_enable_publish(LinphoneProxyConfig * cfg,bool_t val)382 void linphone_proxy_config_enable_publish(LinphoneProxyConfig *cfg, bool_t val){
383 cfg->publish=val;
384 }
385
linphone_proxy_config_pause_register(LinphoneProxyConfig * cfg)386 void linphone_proxy_config_pause_register(LinphoneProxyConfig *cfg){
387 if (cfg->op) sal_op_stop_refreshing(cfg->op);
388 }
389
linphone_proxy_config_edit(LinphoneProxyConfig * cfg)390 void linphone_proxy_config_edit(LinphoneProxyConfig *cfg){
391 /*store current config related to server location*/
392 linphone_proxy_config_store_server_config(cfg);
393 linphone_proxy_config_compute_publish_params_hash(cfg);
394
395 if (cfg->publish && cfg->presence_publish_event){
396 linphone_event_pause_publish(cfg->presence_publish_event);
397 }
398 /*Don't stop refresher*/
399 }
400
linphone_proxy_config_apply(LinphoneProxyConfig * cfg,LinphoneCore * lc)401 void linphone_proxy_config_apply(LinphoneProxyConfig *cfg,LinphoneCore *lc){
402 cfg->lc=lc;
403 linphone_proxy_config_done(cfg);
404 }
405
linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg)406 void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg){
407 LinphoneAddress *contact_addr=NULL;
408 if ( cfg->op
409 && cfg->state == LinphoneRegistrationOk
410 && (contact_addr = (LinphoneAddress*)sal_op_get_contact_address(cfg->op))
411 && linphone_address_get_transport(contact_addr) != LinphoneTransportUdp /*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/) {
412 /*need to save current contact in order to reset is later*/
413 linphone_address_ref(contact_addr);
414 if (cfg->pending_contact)
415 linphone_address_unref(cfg->pending_contact);
416 cfg->pending_contact=contact_addr;
417
418 }
419 if (cfg->presence_publish_event){ /*might probably do better*/
420 linphone_event_terminate(cfg->presence_publish_event);
421 if (cfg->presence_publish_event) {
422 linphone_event_unref(cfg->presence_publish_event); /*probably useless as cfg->long_term_event is already unref in linphone_proxy_config_notify_publish_state_changed. To be check with Ghislain*/
423 cfg->presence_publish_event=NULL;
424 }
425
426 }
427 if (cfg->op){
428 sal_op_release(cfg->op);
429 cfg->op=NULL;
430 }
431 }
432
guess_contact_for_register(LinphoneProxyConfig * cfg)433 LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *cfg){
434 LinphoneAddress *ret=NULL;
435 LinphoneAddress *proxy=linphone_address_new(cfg->reg_proxy);
436 const char *host;
437
438 if (proxy==NULL) return NULL;
439 host=linphone_address_get_domain(proxy);
440 if (host!=NULL){
441 int localport = -1;
442 const char *localip = NULL;
443 LinphoneAddress *contact=linphone_address_clone(cfg->identity_address);
444
445 linphone_address_clean(contact);
446
447 if (cfg->contact_params) {
448 // We want to add a list of contacts params to the linphone address
449 sal_address_set_params(contact,cfg->contact_params);
450 }
451 if (cfg->contact_uri_params){
452 sal_address_set_uri_params(contact,cfg->contact_uri_params);
453 }
454 #ifdef BUILD_UPNP
455 if (cfg->lc->upnp != NULL && linphone_core_get_firewall_policy(cfg->lc)==LinphonePolicyUseUpnp &&
456 linphone_upnp_context_get_state(cfg->lc->upnp) == LinphoneUpnpStateOk) {
457 localip = linphone_upnp_context_get_external_ipaddress(cfg->lc->upnp);
458 localport = linphone_upnp_context_get_external_port(cfg->lc->upnp);
459 }
460 #endif //BUILD_UPNP
461 linphone_address_set_port(contact,localport);
462 linphone_address_set_domain(contact,localip);
463 linphone_address_set_display_name(contact,NULL);
464
465 ret=contact;
466 }
467 linphone_address_unref(proxy);
468 return ret;
469 }
470
_linphone_proxy_config_unregister(LinphoneProxyConfig * obj)471 void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj) {
472 if (obj->op && (obj->state == LinphoneRegistrationOk ||
473 (obj->state == LinphoneRegistrationProgress && obj->expires != 0))) {
474 sal_unregister(obj->op);
475 }
476 }
477
linphone_proxy_config_register(LinphoneProxyConfig * cfg)478 static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){
479 if (cfg->reg_sendregister){
480 LinphoneAddress* proxy=linphone_address_new(cfg->reg_proxy);
481 char* proxy_string;
482 char * from = linphone_address_as_string(cfg->identity_address);
483 LinphoneAddress *contact;
484 ms_message("LinphoneProxyConfig [%p] about to register (LinphoneCore version: %s)",cfg,linphone_core_get_version());
485 proxy_string=linphone_address_as_string_uri_only(proxy);
486 linphone_address_unref(proxy);
487 if (cfg->op)
488 sal_op_release(cfg->op);
489 cfg->op=sal_op_new(cfg->lc->sal);
490
491 linphone_configure_op(cfg->lc, cfg->op, cfg->identity_address, cfg->sent_headers, FALSE);
492
493 if ((contact=guess_contact_for_register(cfg))) {
494 sal_op_set_contact_address(cfg->op,contact);
495 linphone_address_unref(contact);
496 }
497
498 sal_op_set_user_pointer(cfg->op,cfg);
499
500
501 if (sal_register(cfg->op,proxy_string, cfg->reg_identity, cfg->expires, cfg->pending_contact)==0) {
502 if (cfg->pending_contact) {
503 linphone_address_unref(cfg->pending_contact);
504 cfg->pending_contact=NULL;
505 }
506 linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress,"Registration in progress");
507 } else {
508 linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,"Registration failed");
509 }
510 ms_free(proxy_string);
511 ms_free(from);
512 } else {
513 /* unregister if registered*/
514 if (cfg->state == LinphoneRegistrationProgress) {
515 linphone_proxy_config_set_state(cfg,LinphoneRegistrationCleared,"Registration cleared");
516 }
517 _linphone_proxy_config_unregister(cfg);
518 }
519 }
520
linphone_proxy_config_refresh_register(LinphoneProxyConfig * cfg)521 void linphone_proxy_config_refresh_register(LinphoneProxyConfig *cfg){
522 if (cfg->reg_sendregister && cfg->op && cfg->state!=LinphoneRegistrationProgress){
523 if (sal_register_refresh(cfg->op,cfg->expires) == 0) {
524 linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress, "Refresh registration");
525 }
526 }
527 }
528
529
linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig * cfg,const char * prefix)530 void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix){
531 if (cfg->dial_prefix!=NULL){
532 ms_free(cfg->dial_prefix);
533 cfg->dial_prefix=NULL;
534 }
535 if (prefix && prefix[0]!='\0') cfg->dial_prefix=ms_strdup(prefix);
536 }
537
linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig * cfg)538 const char *linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg){
539 return cfg->dial_prefix;
540 }
541
linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig * cfg,bool_t val)542 void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val){
543 cfg->dial_escape_plus=val;
544 }
545
linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig * cfg)546 bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg){
547 return cfg->dial_escape_plus;
548 }
549
linphone_proxy_config_enable_quality_reporting(LinphoneProxyConfig * cfg,bool_t val)550 void linphone_proxy_config_enable_quality_reporting(LinphoneProxyConfig *cfg, bool_t val){
551 cfg->quality_reporting_enabled = val;
552 }
553
linphone_proxy_config_quality_reporting_enabled(LinphoneProxyConfig * cfg)554 bool_t linphone_proxy_config_quality_reporting_enabled(LinphoneProxyConfig *cfg){
555 return cfg->quality_reporting_enabled;
556 }
557
linphone_proxy_config_set_quality_reporting_interval(LinphoneProxyConfig * cfg,int interval)558 void linphone_proxy_config_set_quality_reporting_interval(LinphoneProxyConfig *cfg, int interval) {
559 cfg->quality_reporting_interval = interval;
560 }
561
linphone_proxy_config_get_quality_reporting_interval(LinphoneProxyConfig * cfg)562 int linphone_proxy_config_get_quality_reporting_interval(LinphoneProxyConfig *cfg) {
563 return cfg->quality_reporting_interval;
564 }
565
linphone_proxy_config_set_quality_reporting_collector(LinphoneProxyConfig * cfg,const char * collector)566 void linphone_proxy_config_set_quality_reporting_collector(LinphoneProxyConfig *cfg, const char *collector){
567 if (collector!=NULL && strlen(collector)>0){
568 LinphoneAddress *addr=linphone_address_new(collector);
569 if (!addr){
570 ms_error("Invalid SIP collector URI: %s. Quality reporting will be DISABLED.",collector);
571 } else {
572 if (cfg->quality_reporting_collector != NULL){
573 ms_free(cfg->quality_reporting_collector);
574 }
575 cfg->quality_reporting_collector = ms_strdup(collector);
576 }
577
578 if (addr){
579 linphone_address_unref(addr);
580 }
581 }
582 }
583
linphone_proxy_config_get_quality_reporting_collector(const LinphoneProxyConfig * cfg)584 const char *linphone_proxy_config_get_quality_reporting_collector(const LinphoneProxyConfig *cfg){
585 return cfg->quality_reporting_collector;
586 }
587
588
linphone_proxy_config_is_phone_number(LinphoneProxyConfig * proxy,const char * username)589 bool_t linphone_proxy_config_is_phone_number(LinphoneProxyConfig *proxy, const char *username){
590 const char *p;
591 if (!username) return FALSE;
592 for(p=username;*p!='\0';++p){
593 if (isdigit(*p) ||
594 *p==' ' ||
595 *p=='.' ||
596 *p=='-' ||
597 *p==')' ||
598 *p=='(' ||
599 *p=='/' ||
600 *p=='+' ||
601 (unsigned char)*p==0xca || (unsigned char)*p==0xc2 || (unsigned char)*p==0xa0 // non-breakable space (iOS uses it to format contacts phone number)
602 ) {
603 continue;
604 }
605 return FALSE;
606 }
607 return TRUE;
608 }
609
610 //remove anything but [0-9] and +
flatten_number(const char * number)611 static char *flatten_number(const char *number){
612 char *result=ms_malloc0(strlen(number)+1);
613 char *w=result;
614 const char *r;
615 for(r=number;*r!='\0';++r){
616 if (*r=='+' || isdigit(*r)){
617 *w++=*r;
618 }
619 }
620 *w++='\0';
621 return result;
622 }
623
624 /*static char* replace_plus_with_icp(char *phone, const char* icp){
625 return (icp && phone[0]=='+') ? ms_strdup_printf("%s%s", icp, phone+1) : ms_strdup(phone);
626 }*/
627
replace_icp_with_plus(char * phone,const char * icp)628 static char* replace_icp_with_plus(char *phone, const char *icp){
629 return (strstr(phone, icp) == phone) ? ms_strdup_printf("+%s", phone+strlen(icp)) : ms_strdup(phone);
630 }
631
linphone_proxy_config_normalize_number(LinphoneProxyConfig * proxy,const char * username,char * result,size_t result_len)632 bool_t linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len){
633 char * normalized_phone = linphone_proxy_config_normalize_phone_number(proxy, username);
634 const char * output = normalized_phone ? normalized_phone : username;
635 memset(result, 0, result_len);
636 memcpy(result, output, MIN(strlen(output) + 1, result_len));
637 ms_free(normalized_phone);
638 return output != username;
639 }
640
linphone_proxy_config_normalize_phone_number(LinphoneProxyConfig * proxy,const char * username)641 char* linphone_proxy_config_normalize_phone_number(LinphoneProxyConfig *proxy, const char *username) {
642 LinphoneProxyConfig *tmpproxy = proxy ? proxy : linphone_proxy_config_new();
643 char* result = NULL;
644 LinphoneDialPlan dialplan = {0};
645 char * nationnal_significant_number = NULL;
646 int ccc = -1;
647
648 if (linphone_proxy_config_is_phone_number(tmpproxy, username)){
649 char * flatten=flatten_number(username);
650 ms_debug("Flattened number is '%s' for '%s'",flatten, username);
651
652 ccc = linphone_dial_plan_lookup_ccc_from_e164(flatten);
653 if (ccc>-1) { /*e164 like phone number*/
654 dialplan = *linphone_dial_plan_by_ccc_as_int(ccc);
655 nationnal_significant_number = strstr(flatten, dialplan.ccc);
656 if (nationnal_significant_number) {
657 nationnal_significant_number +=strlen(dialplan.ccc);
658 }
659 } else if (flatten[0] =='+') {
660 ms_message ("Unknown ccc for e164 like number [%s]", flatten);
661 goto end;
662 } else {
663 dialplan = *linphone_dial_plan_by_ccc(tmpproxy->dial_prefix); //copy dial plan;
664 if (tmpproxy->dial_prefix){
665 if (strcmp(tmpproxy->dial_prefix,dialplan.ccc) != 0){
666 //probably generic dialplan, preserving proxy dial prefix
667 strncpy(dialplan.ccc,tmpproxy->dial_prefix,sizeof(dialplan.ccc));
668 }
669 /*it does not make sens to try replace icp with + if we are not sure from the country we are (I.E tmpproxy->dial_prefix==NULL)*/
670 if (strstr(flatten,dialplan.icp)==flatten) {
671 char *e164 = replace_icp_with_plus(flatten,dialplan.icp);
672 result = linphone_proxy_config_normalize_phone_number(tmpproxy,e164);
673 ms_free(e164);
674 goto end;
675 }
676
677 }
678 nationnal_significant_number=flatten;
679 }
680 ms_debug("Using dial plan '%s'",dialplan.country);
681
682 /*if proxy has a dial prefix, modify phonenumber accordingly*/
683 if (dialplan.ccc[0]!='\0') {
684 /* the number already starts with + or international prefix*/
685 /*0. keep at most national number significant digits */
686 char* nationnal_significant_number_start = nationnal_significant_number
687 + MAX(0, (int)strlen(nationnal_significant_number)
688 - (int)dialplan.nnl);
689 ms_debug("Prefix not present. Keeping at most %d digits: %s", dialplan.nnl, nationnal_significant_number_start);
690
691 /*1. First prepend international calling prefix or +*/
692 /*2. Second add prefix*/
693 /*3. Finally add user digits */
694 result = ms_strdup_printf("%s%s%s"
695 , tmpproxy->dial_escape_plus ? dialplan.icp : "+"
696 , dialplan.ccc
697 , nationnal_significant_number_start);
698 ms_debug("Prepended prefix resulted in %s", result);
699 }
700
701 end:
702 if (result==NULL) {
703 result = flatten;
704 } else {
705 ms_free(flatten);
706 }
707 }
708 if (proxy==NULL) linphone_proxy_config_unref(tmpproxy);
709 return result;
710 }
711
_linphone_core_destroy_addr_if_not_sip(LinphoneAddress * addr)712 static LinphoneAddress* _linphone_core_destroy_addr_if_not_sip( LinphoneAddress* addr ){
713 if( linphone_address_is_sip(addr) ) {
714 return addr;
715 } else {
716 linphone_address_unref(addr);
717 return NULL;
718 }
719 }
720
linphone_proxy_config_normalize_sip_uri(LinphoneProxyConfig * proxy,const char * username)721 LinphoneAddress* linphone_proxy_config_normalize_sip_uri(LinphoneProxyConfig *proxy, const char *username) {
722 enum_lookup_res_t *enumres=NULL;
723 char *enum_domain=NULL;
724 char *tmpurl;
725 LinphoneAddress *uri;
726
727 if (!username || *username=='\0') return NULL;
728
729 if (is_enum(username,&enum_domain)){
730 if (proxy) {
731 linphone_core_notify_display_status(proxy->lc,_("Looking for telephone number destination..."));
732 }
733 if (enum_lookup(enum_domain,&enumres)<0){
734 if (proxy) {
735 linphone_core_notify_display_status(proxy->lc,_("Could not resolve this number."));
736 }
737 ms_free(enum_domain);
738 return NULL;
739 }
740 ms_free(enum_domain);
741 tmpurl=enumres->sip_address[0];
742 uri=linphone_address_new(tmpurl);
743 enum_lookup_res_free(enumres);
744 return _linphone_core_destroy_addr_if_not_sip(uri);
745 }
746 /* check if we have a "sip:" or a "sips:" */
747 if ( (strstr(username,"sip:")==NULL) && (strstr(username,"sips:")==NULL) ){
748 /* this doesn't look like a true sip uri */
749 if (strchr(username,'@')!=NULL){
750 /* seems like sip: is missing !*/
751 tmpurl=ms_strdup_printf("sip:%s",username);
752 uri=linphone_address_new(tmpurl);
753 ms_free(tmpurl);
754 if (uri){
755 return _linphone_core_destroy_addr_if_not_sip(uri);
756 }
757 }
758
759 if (proxy!=NULL && linphone_proxy_config_get_identity_address(proxy)!=NULL){
760 /* append the proxy domain suffix but remove any custom parameters/headers */
761 LinphoneAddress *uri=linphone_address_clone(linphone_proxy_config_get_identity_address(proxy));
762 if (uri==NULL){
763 return NULL;
764 } else {
765 linphone_address_clean(uri);
766 linphone_address_set_display_name(uri,NULL);
767 linphone_address_set_username(uri,username);
768 return _linphone_core_destroy_addr_if_not_sip(uri);
769 }
770 } else {
771 return NULL;
772 }
773 }
774 uri=linphone_address_new(username);
775 if (uri!=NULL){
776 return _linphone_core_destroy_addr_if_not_sip(uri);
777 }
778
779 return NULL;
780 }
781
782 /**
783 * Commits modification made to the proxy configuration.
784 **/
linphone_proxy_config_done(LinphoneProxyConfig * cfg)785 LinphoneStatus linphone_proxy_config_done(LinphoneProxyConfig *cfg)
786 {
787 LinphoneProxyConfigAddressComparisonResult res;
788
789 if (!linphone_proxy_config_check(cfg->lc,cfg))
790 return -1;
791
792 /*check if server address has changed*/
793 res = linphone_proxy_config_is_server_config_changed(cfg);
794 if (res != LinphoneProxyConfigAddressEqual) {
795 /* server config has changed, need to unregister from previous first*/
796 if (cfg->op) {
797 if (res == LinphoneProxyConfigAddressDifferent) {
798 _linphone_proxy_config_unregister(cfg);
799 }
800 sal_op_set_user_pointer(cfg->op,NULL); /*we don't want to receive status for this un register*/
801 sal_op_unref(cfg->op); /*but we keep refresher to handle authentication if needed*/
802 cfg->op=NULL;
803 }
804 if (cfg->presence_publish_event) {
805 if (res == LinphoneProxyConfigAddressDifferent) {
806 _linphone_proxy_config_unpublish(cfg);
807 }
808 }
809 cfg->commit = TRUE;
810 }
811 if (cfg->register_changed){
812 cfg->commit = TRUE;
813 cfg->register_changed = FALSE;
814 }
815 if (cfg->commit){
816 linphone_proxy_config_pause_register(cfg);
817 }
818
819 if (linphone_proxy_config_compute_publish_params_hash(cfg)) {
820 ms_message("Publish params have changed on proxy config [%p]",cfg);
821 if (cfg->presence_publish_event) {
822 if (cfg->publish) {
823 const char * sip_etag = linphone_event_get_custom_header(cfg->presence_publish_event, "SIP-ETag");
824 if (sip_etag) {
825 if (cfg->sip_etag) ms_free(cfg->sip_etag);
826 cfg->sip_etag = ms_strdup(sip_etag);
827 }
828 }
829 /*publish is terminated*/
830 linphone_event_terminate(cfg->presence_publish_event);
831 }
832 if (cfg->publish) cfg->send_publish=TRUE;
833 } else {
834 ms_message("Publish params have not changed on proxy config [%p]",cfg);
835 }
836
837 linphone_proxy_config_write_all_to_config_file(cfg->lc);
838 return 0;
839 }
840
linphone_proxy_config_get_realm(const LinphoneProxyConfig * cfg)841 const char* linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg)
842 {
843 return cfg?cfg->realm:NULL;
844 }
linphone_proxy_config_set_realm(LinphoneProxyConfig * cfg,const char * realm)845 void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm)
846 {
847 if (cfg->realm!=NULL) {
848 ms_free(cfg->realm);
849 }
850 cfg->realm=ms_strdup(realm);
851 }
852
linphone_proxy_config_send_publish(LinphoneProxyConfig * proxy,LinphonePresenceModel * presence)853 int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){
854 int err=0;
855 LinphoneAddress *presentity_address = NULL;
856 char* contact = NULL;
857
858 if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){
859 LinphoneContent *content;
860 char *presence_body;
861 if (proxy->presence_publish_event==NULL){
862 proxy->presence_publish_event = linphone_proxy_config_create_publish(proxy
863 , "presence"
864 , linphone_proxy_config_get_publish_expires(proxy));
865 linphone_event_ref(proxy->presence_publish_event);
866 }
867 proxy->presence_publish_event->internal = TRUE;
868
869 if (linphone_presence_model_get_presentity(presence) == NULL) {
870 ms_message("No presentity set for model [%p], using identity from proxy config [%p]", presence, proxy);
871 linphone_presence_model_set_presentity(presence,linphone_proxy_config_get_identity_address(proxy));
872 }
873
874 if (!linphone_address_equal(linphone_presence_model_get_presentity(presence), linphone_proxy_config_get_identity_address(proxy))) {
875 ms_message("Presentity for model [%p] differ proxy config [%p], using proxy", presence, proxy);
876 presentity_address = linphone_address_clone(linphone_presence_model_get_presentity(presence)); /*saved, just in case*/
877 if (linphone_presence_model_get_contact(presence)) {
878 contact = bctbx_strdup(linphone_presence_model_get_contact(presence));
879 }
880 linphone_presence_model_set_presentity(presence,linphone_proxy_config_get_identity_address(proxy));
881 linphone_presence_model_set_contact(presence,NULL); /*it will be automatically computed*/
882
883 }
884 if (!(presence_body = linphone_presence_model_to_xml(presence))) {
885 ms_error("Cannot publish presence model [%p] for proxy config [%p] because of xml serialization error",presence,proxy);
886 return -1;
887 }
888
889 content = linphone_content_new();
890 linphone_content_set_buffer(content,presence_body,strlen(presence_body));
891 linphone_content_set_type(content, "application");
892 linphone_content_set_subtype(content,"pidf+xml");
893 if (proxy->sip_etag) {
894 linphone_event_add_custom_header(proxy->presence_publish_event, "SIP-If-Match", proxy->sip_etag);
895 ms_free(proxy->sip_etag);
896 proxy->sip_etag=NULL;
897 }
898 err = linphone_event_send_publish(proxy->presence_publish_event, content);
899 linphone_content_unref(content);
900 ms_free(presence_body);
901 if (presentity_address) {
902 linphone_presence_model_set_presentity(presence,presentity_address);
903 linphone_address_unref(presentity_address);
904 }
905 if (contact) {
906 linphone_presence_model_set_contact(presence,contact);
907 bctbx_free(contact);
908 }
909
910 }else proxy->send_publish=TRUE; /*otherwise do not send publish if registration is in progress, this will be done later*/
911 return err;
912 }
913
_linphone_proxy_config_unpublish(LinphoneProxyConfig * obj)914 void _linphone_proxy_config_unpublish(LinphoneProxyConfig *obj) {
915 if (obj->presence_publish_event
916 && (linphone_event_get_publish_state(obj->presence_publish_event) == LinphonePublishOk ||
917 (linphone_event_get_publish_state(obj->presence_publish_event) == LinphonePublishProgress && obj->publish_expires != 0))) {
918 linphone_event_unpublish(obj->presence_publish_event);
919 }
920 if (obj->sip_etag) {
921 ms_free(obj->sip_etag);
922 obj->sip_etag=NULL;
923 }
924 }
925
linphone_proxy_config_get_route(const LinphoneProxyConfig * cfg)926 const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *cfg){
927 return cfg->reg_route;
928 }
929
linphone_proxy_config_get_identity_address(const LinphoneProxyConfig * cfg)930 const LinphoneAddress *linphone_proxy_config_get_identity_address(const LinphoneProxyConfig *cfg){
931 return cfg->identity_address;
932 }
933
linphone_proxy_config_get_identity(const LinphoneProxyConfig * cfg)934 const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *cfg){
935 return cfg->reg_identity;
936 }
937
linphone_proxy_config_publish_enabled(const LinphoneProxyConfig * cfg)938 bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *cfg){
939 return cfg->publish;
940 }
941
linphone_proxy_config_get_server_addr(const LinphoneProxyConfig * cfg)942 const char *linphone_proxy_config_get_server_addr(const LinphoneProxyConfig *cfg){
943 return cfg->reg_proxy;
944 }
945
946 /**
947 * @return the duration of registration.
948 **/
linphone_proxy_config_get_expires(const LinphoneProxyConfig * cfg)949 int linphone_proxy_config_get_expires(const LinphoneProxyConfig *cfg){
950 return cfg->expires;
951 }
952
linphone_proxy_config_register_enabled(const LinphoneProxyConfig * cfg)953 bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *cfg){
954 return cfg->reg_sendregister;
955 }
956
linphone_proxy_config_set_contact_parameters(LinphoneProxyConfig * cfg,const char * contact_params)957 void linphone_proxy_config_set_contact_parameters(LinphoneProxyConfig *cfg, const char *contact_params){
958 if (cfg->contact_params) {
959 ms_free(cfg->contact_params);
960 cfg->contact_params=NULL;
961 }
962 if (contact_params){
963 cfg->contact_params=ms_strdup(contact_params);
964 }
965 cfg->register_changed = TRUE;
966 }
967
linphone_proxy_config_set_contact_uri_parameters(LinphoneProxyConfig * cfg,const char * contact_uri_params)968 void linphone_proxy_config_set_contact_uri_parameters(LinphoneProxyConfig *cfg, const char *contact_uri_params){
969 if (cfg->contact_uri_params) {
970 ms_free(cfg->contact_uri_params);
971 cfg->contact_uri_params=NULL;
972 }
973 if (contact_uri_params){
974 cfg->contact_uri_params=ms_strdup(contact_uri_params);
975 }
976 cfg->register_changed = TRUE;
977 }
978
linphone_proxy_config_get_contact_parameters(const LinphoneProxyConfig * cfg)979 const char *linphone_proxy_config_get_contact_parameters(const LinphoneProxyConfig *cfg){
980 return cfg->contact_params;
981 }
982
linphone_proxy_config_get_contact_uri_parameters(const LinphoneProxyConfig * cfg)983 const char *linphone_proxy_config_get_contact_uri_parameters(const LinphoneProxyConfig *cfg){
984 return cfg->contact_uri_params;
985 }
986
linphone_proxy_config_get_core(const LinphoneProxyConfig * cfg)987 struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *cfg){
988 return cfg->lc;
989 }
990
linphone_proxy_config_get_custom_header(LinphoneProxyConfig * cfg,const char * header_name)991 const char *linphone_proxy_config_get_custom_header(LinphoneProxyConfig *cfg, const char *header_name){
992 const SalCustomHeader *ch;
993 if (!cfg->op) return NULL;
994 ch = sal_op_get_recv_custom_header(cfg->op);
995 return sal_custom_header_find(ch, header_name);
996 }
997
linphone_proxy_config_set_custom_header(LinphoneProxyConfig * cfg,const char * header_name,const char * header_value)998 void linphone_proxy_config_set_custom_header(LinphoneProxyConfig *cfg, const char *header_name, const char *header_value){
999 cfg->sent_headers=sal_custom_header_append(cfg->sent_headers, header_name, header_value);
1000 cfg->register_changed = TRUE;
1001 }
1002
linphone_core_add_proxy_config(LinphoneCore * lc,LinphoneProxyConfig * cfg)1003 LinphoneStatus linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
1004 if (!linphone_proxy_config_check(lc,cfg)) {
1005 return -1;
1006 }
1007 if (bctbx_list_find(lc->sip_conf.proxies,cfg)!=NULL){
1008 ms_warning("ProxyConfig already entered, ignored.");
1009 return 0;
1010 }
1011 lc->sip_conf.proxies=bctbx_list_append(lc->sip_conf.proxies,(void *)linphone_proxy_config_ref(cfg));
1012 linphone_proxy_config_apply(cfg,lc);
1013 return 0;
1014 }
1015
linphone_core_remove_proxy_config(LinphoneCore * lc,LinphoneProxyConfig * cfg)1016 void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
1017 /* check this proxy config is in the list before doing more*/
1018 if (bctbx_list_find(lc->sip_conf.proxies,cfg)==NULL){
1019 ms_error("linphone_core_remove_proxy_config: LinphoneProxyConfig [%p] is not known by LinphoneCore (programming error?)",cfg);
1020 return;
1021 }
1022 lc->sip_conf.proxies=bctbx_list_remove(lc->sip_conf.proxies,cfg);
1023 /* add to the list of destroyed proxies, so that the possible unREGISTER request can succeed authentication */
1024 lc->sip_conf.deleted_proxies=bctbx_list_append(lc->sip_conf.deleted_proxies,cfg);
1025
1026 if (lc->default_proxy==cfg){
1027 lc->default_proxy=NULL;
1028 }
1029
1030 cfg->deletion_date=ms_time(NULL);
1031 if (cfg->state==LinphoneRegistrationOk){
1032 /* UNREGISTER */
1033 linphone_proxy_config_edit(cfg);
1034 linphone_proxy_config_enable_register(cfg,FALSE);
1035 linphone_proxy_config_done(cfg);
1036 linphone_proxy_config_update(cfg);
1037 } else if (cfg->state != LinphoneRegistrationNone) {
1038 linphone_proxy_config_set_state(cfg, LinphoneRegistrationNone,"Registration disabled");
1039 }
1040 linphone_proxy_config_write_all_to_config_file(lc);
1041 }
1042
linphone_core_clear_proxy_config(LinphoneCore * lc)1043 void linphone_core_clear_proxy_config(LinphoneCore *lc){
1044 bctbx_list_t* list=bctbx_list_copy(linphone_core_get_proxy_config_list((const LinphoneCore*)lc));
1045 bctbx_list_t* copy=list;
1046 for(;list!=NULL;list=list->next){
1047 linphone_core_remove_proxy_config(lc,(LinphoneProxyConfig *)list->data);
1048 }
1049 bctbx_list_free(copy);
1050 linphone_proxy_config_write_all_to_config_file(lc);
1051 }
1052
linphone_core_get_default_proxy_config_index(LinphoneCore * lc)1053 int linphone_core_get_default_proxy_config_index(LinphoneCore *lc) {
1054 int pos = -1;
1055 if (lc->default_proxy != NULL) {
1056 pos = bctbx_list_position(lc->sip_conf.proxies, bctbx_list_find(lc->sip_conf.proxies, (void *)lc->default_proxy));
1057 }
1058 return pos;
1059 }
1060
linphone_core_set_default_proxy_config(LinphoneCore * lc,LinphoneProxyConfig * config)1061 void linphone_core_set_default_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config){
1062 /* check if this proxy is in our list */
1063 if (config!=NULL){
1064 if (bctbx_list_find(lc->sip_conf.proxies,config)==NULL){
1065 ms_warning("Bad proxy address: it is not in the list !");
1066 lc->default_proxy=NULL;
1067 return ;
1068 }
1069 }
1070 lc->default_proxy=config;
1071 if (linphone_core_ready(lc))
1072 lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy_config_index(lc));
1073 }
1074
linphone_core_set_default_proxy_index(LinphoneCore * lc,int index)1075 void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){
1076 if (index<0) linphone_core_set_default_proxy(lc,NULL);
1077 else linphone_core_set_default_proxy(lc,bctbx_list_nth_data(lc->sip_conf.proxies,index));
1078 }
1079
linphone_core_get_default_proxy(LinphoneCore * lc,LinphoneProxyConfig ** config)1080 int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config){
1081 if (config!=NULL) *config=lc->default_proxy;
1082 return linphone_core_get_default_proxy_config_index(lc);
1083 }
1084
linphone_core_get_default_proxy_config(LinphoneCore * lc)1085 LinphoneProxyConfig * linphone_core_get_default_proxy_config(LinphoneCore *lc) {
1086 return lc->default_proxy;
1087 }
1088
linphone_core_get_proxy_config_list(const LinphoneCore * lc)1089 const bctbx_list_t *linphone_core_get_proxy_config_list(const LinphoneCore *lc){
1090 return lc->sip_conf.proxies;
1091 }
1092
linphone_proxy_config_write_to_config_file(LpConfig * config,LinphoneProxyConfig * cfg,int index)1093 void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyConfig *cfg, int index)
1094 {
1095 char key[50];
1096
1097 sprintf(key,"proxy_%i",index);
1098 lp_config_clean_section(config,key);
1099 if (cfg==NULL){
1100 return;
1101 }
1102 if (cfg->type!=NULL){
1103 lp_config_set_string(config,key,"type",cfg->type);
1104 }
1105 if (cfg->reg_proxy!=NULL){
1106 lp_config_set_string(config,key,"reg_proxy",cfg->reg_proxy);
1107 }
1108 if (cfg->reg_route!=NULL){
1109 lp_config_set_string(config,key,"reg_route",cfg->reg_route);
1110 }
1111 if (cfg->reg_identity!=NULL){
1112 lp_config_set_string(config,key,"reg_identity",cfg->reg_identity);
1113 }
1114 if (cfg->realm!=NULL){
1115 lp_config_set_string(config,key,"realm",cfg->realm);
1116 }
1117 if (cfg->contact_params!=NULL){
1118 lp_config_set_string(config,key,"contact_parameters",cfg->contact_params);
1119 }
1120 if (cfg->contact_uri_params!=NULL){
1121 lp_config_set_string(config,key,"contact_uri_parameters",cfg->contact_uri_params);
1122 }
1123 if (cfg->quality_reporting_collector!=NULL){
1124 lp_config_set_string(config,key,"quality_reporting_collector",cfg->quality_reporting_collector);
1125 }
1126 lp_config_set_int(config,key,"quality_reporting_enabled",cfg->quality_reporting_enabled);
1127 lp_config_set_int(config,key,"quality_reporting_interval",cfg->quality_reporting_interval);
1128 lp_config_set_int(config,key,"reg_expires",cfg->expires);
1129 lp_config_set_int(config,key,"reg_sendregister",cfg->reg_sendregister);
1130 lp_config_set_int(config,key,"publish",cfg->publish);
1131 lp_config_set_int(config, key, "avpf", cfg->avpf_mode);
1132 lp_config_set_int(config, key, "avpf_rr_interval", cfg->avpf_rr_interval);
1133 lp_config_set_int(config,key,"dial_escape_plus",cfg->dial_escape_plus);
1134 lp_config_set_string(config,key,"dial_prefix",cfg->dial_prefix);
1135 lp_config_set_int(config,key,"privacy",cfg->privacy);
1136 if (cfg->refkey) lp_config_set_string(config,key,"refkey",cfg->refkey);
1137 lp_config_set_int(config, key, "publish_expires", cfg->publish_expires);
1138
1139 if (cfg->nat_policy != NULL) {
1140 lp_config_set_string(config, key, "nat_policy_ref", cfg->nat_policy->ref);
1141 linphone_nat_policy_save_to_config(cfg->nat_policy);
1142 }
1143 }
1144
1145
1146 #define CONFIGURE_STRING_VALUE(cfg,config,key,param,param_name) \
1147 {\
1148 char* default_value = linphone_proxy_config_get_##param(cfg)?ms_strdup(linphone_proxy_config_get_##param(cfg)):NULL;\
1149 linphone_proxy_config_set_##param(cfg,lp_config_get_string(config,key,param_name,default_value)); \
1150 if ( default_value) ms_free(default_value); \
1151 }
1152
1153 #define CONFIGURE_BOOL_VALUE(cfg,config,key,param,param_name) \
1154 linphone_proxy_config_enable_##param(cfg,lp_config_get_int(config,key,param_name,linphone_proxy_config_##param##_enabled(cfg)));
1155
1156 #define CONFIGURE_INT_VALUE(cfg,config,key,param,param_name) \
1157 linphone_proxy_config_set_##param(cfg,lp_config_get_int(config,key,param_name,linphone_proxy_config_get_##param(cfg)));
1158
linphone_proxy_config_new_from_config_file(LinphoneCore * lc,int index)1159 LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc, int index)
1160 {
1161 const char *tmp;
1162 LinphoneProxyConfig *cfg;
1163 char key[50];
1164 LpConfig *config=lc->config;
1165 const char *nat_policy_ref;
1166
1167 sprintf(key,"proxy_%i",index);
1168
1169 if (!lp_config_has_section(config,key)){
1170 return NULL;
1171 }
1172
1173 cfg=linphone_core_create_proxy_config(lc);
1174
1175 CONFIGURE_STRING_VALUE(cfg,config,key,identity,"reg_identity")
1176 CONFIGURE_STRING_VALUE(cfg,config,key,server_addr,"reg_proxy")
1177 CONFIGURE_STRING_VALUE(cfg,config,key,route,"reg_route")
1178
1179 CONFIGURE_STRING_VALUE(cfg,config,key,realm,"realm")
1180
1181 CONFIGURE_BOOL_VALUE(cfg,config,key,quality_reporting,"quality_reporting_enabled")
1182 CONFIGURE_STRING_VALUE(cfg,config,key,quality_reporting_collector,"quality_reporting_collector")
1183 CONFIGURE_INT_VALUE(cfg,config,key,quality_reporting_interval,"quality_reporting_interval")
1184
1185 CONFIGURE_STRING_VALUE(cfg,config,key,contact_parameters,"contact_parameters")
1186 CONFIGURE_STRING_VALUE(cfg,config,key,contact_uri_parameters,"contact_uri_parameters")
1187
1188 CONFIGURE_INT_VALUE(cfg,config,key,expires,"reg_expires")
1189 CONFIGURE_BOOL_VALUE(cfg,config,key,register,"reg_sendregister")
1190 CONFIGURE_BOOL_VALUE(cfg,config,key,publish,"publish")
1191 CONFIGURE_INT_VALUE(cfg,config,key,avpf_mode,"avpf")
1192 CONFIGURE_INT_VALUE(cfg,config,key,avpf_rr_interval,"avpf_rr_interval")
1193 CONFIGURE_INT_VALUE(cfg,config,key,dial_escape_plus,"dial_escape_plus")
1194 CONFIGURE_STRING_VALUE(cfg,config,key,dial_prefix,"dial_prefix")
1195
1196 tmp=lp_config_get_string(config,key,"type",NULL);
1197 if (tmp!=NULL && strlen(tmp)>0)
1198 linphone_proxy_config_set_sip_setup(cfg,tmp);
1199 CONFIGURE_INT_VALUE(cfg,config,key,privacy,"privacy")
1200
1201 CONFIGURE_STRING_VALUE(cfg,config,key,ref_key,"refkey")
1202 CONFIGURE_INT_VALUE(cfg,config,key,publish_expires,"publish_expires")
1203
1204 nat_policy_ref = lp_config_get_string(config, key, "nat_policy_ref", NULL);
1205 if (nat_policy_ref != NULL) {
1206 cfg->nat_policy = linphone_core_create_nat_policy_from_config(lc, nat_policy_ref);
1207 }
1208
1209 return cfg;
1210 }
1211
linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig * cfg)1212 static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){
1213 SipSetupContext *ssc;
1214 SipSetup *ss=sip_setup_lookup(cfg->type);
1215 LinphoneCore *lc=linphone_proxy_config_get_core(cfg);
1216 unsigned int caps;
1217 if (!ss) return ;
1218 ssc=sip_setup_context_new(ss,cfg);
1219 cfg->ssctx=ssc;
1220 if (cfg->reg_identity==NULL){
1221 ms_error("Invalid identity for this proxy configuration.");
1222 return;
1223 }
1224 caps=sip_setup_context_get_capabilities(ssc);
1225 if (caps & SIP_SETUP_CAP_ACCOUNT_MANAGER){
1226 if (sip_setup_context_login_account(ssc,cfg->reg_identity,NULL,NULL)!=0){
1227 {
1228 char *tmp=ms_strdup_printf(_("Could not login as %s"),cfg->reg_identity);
1229 linphone_core_notify_display_warning(lc,tmp);
1230 ms_free(tmp);
1231 }
1232 return;
1233 }
1234 }
1235 if (caps & SIP_SETUP_CAP_PROXY_PROVIDER){
1236 char proxy[256];
1237 if (sip_setup_context_get_proxy(ssc,NULL,proxy,sizeof(proxy))==0){
1238 linphone_proxy_config_set_server_addr(cfg,proxy);
1239 }else{
1240 ms_error("Could not retrieve proxy uri !");
1241 }
1242 }
1243
1244 }
1245
linphone_proxy_config_get_sip_setup(LinphoneProxyConfig * cfg)1246 SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg){
1247 if (cfg->ssctx!=NULL) return cfg->ssctx->funcs;
1248 if (cfg->type!=NULL){
1249 return sip_setup_lookup(cfg->type);
1250 }
1251 return NULL;
1252 }
1253
can_register(LinphoneProxyConfig * cfg)1254 static bool_t can_register(LinphoneProxyConfig *cfg){
1255 LinphoneCore *lc=cfg->lc;
1256 #ifdef BUILD_UPNP
1257 if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp){
1258 if(lc->sip_conf.register_only_when_upnp_is_ok &&
1259 (lc->upnp == NULL || !linphone_upnp_context_is_ready_for_register(lc->upnp))) {
1260 return FALSE;
1261 }
1262 }
1263 #endif //BUILD_UPNP
1264 if (lc->sip_conf.register_only_when_network_is_up){
1265 return lc->sip_network_reachable;
1266 }
1267 return TRUE;
1268 }
1269
linphone_proxy_config_update(LinphoneProxyConfig * cfg)1270 void linphone_proxy_config_update(LinphoneProxyConfig *cfg){
1271 LinphoneCore *lc=cfg->lc;
1272 if (cfg->commit){
1273 if (cfg->type && cfg->ssctx==NULL){
1274 linphone_proxy_config_activate_sip_setup(cfg);
1275 }
1276 if (can_register(cfg)){
1277 linphone_proxy_config_register(cfg);
1278 cfg->commit=FALSE;
1279 }
1280 }
1281 if (cfg->send_publish && (cfg->state==LinphoneRegistrationOk || cfg->state==LinphoneRegistrationCleared)){
1282 linphone_proxy_config_send_publish(cfg,lc->presence_model);
1283 cfg->send_publish=FALSE;
1284 }
1285 }
1286
linphone_proxy_config_set_sip_setup(LinphoneProxyConfig * cfg,const char * type)1287 void linphone_proxy_config_set_sip_setup(LinphoneProxyConfig *cfg, const char *type){
1288 if (cfg->type)
1289 ms_free(cfg->type);
1290 cfg->type=ms_strdup(type);
1291 if (linphone_proxy_config_get_addr(cfg)==NULL){
1292 /*put a placeholder so that the sip setup gets saved into the config */
1293 linphone_proxy_config_set_server_addr(cfg,"sip:undefined");
1294 }
1295 }
1296
linphone_proxy_config_get_sip_setup_context(LinphoneProxyConfig * cfg)1297 SipSetupContext *linphone_proxy_config_get_sip_setup_context(LinphoneProxyConfig *cfg){
1298 return cfg->ssctx;
1299 }
1300
linphone_proxy_config_set_user_data(LinphoneProxyConfig * cfg,void * ud)1301 void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cfg, void *ud) {
1302 cfg->user_data = ud;
1303 }
1304
linphone_proxy_config_get_user_data(const LinphoneProxyConfig * cfg)1305 void * linphone_proxy_config_get_user_data(const LinphoneProxyConfig *cfg) {
1306 return cfg->user_data;
1307 }
1308
linphone_proxy_config_set_state(LinphoneProxyConfig * cfg,LinphoneRegistrationState state,const char * message)1309 void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){
1310 LinphoneCore *lc=cfg->lc;
1311
1312 if (state==LinphoneRegistrationProgress) {
1313 char *msg=ortp_strdup_printf(_("Refreshing on %s..."), linphone_proxy_config_get_identity(cfg));
1314 linphone_core_notify_display_status(lc,msg);
1315 ms_free(msg);
1316
1317 }
1318
1319 if (cfg->state!=state || state==LinphoneRegistrationOk) { /*allow multiple notification of LinphoneRegistrationOk for refreshing*/
1320 ms_message("Proxy config [%p] for identity [%s] moving from state [%s] to [%s] on core [%p]" ,
1321 cfg,
1322 linphone_proxy_config_get_identity(cfg),
1323 linphone_registration_state_to_string(cfg->state),
1324 linphone_registration_state_to_string(state),
1325 cfg->lc);
1326 if (linphone_core_should_subscribe_friends_only_when_registered(lc) && cfg->state!=state && state == LinphoneRegistrationOk){
1327 ms_message("Updating friends for identity [%s] on core [%p]",cfg->reg_identity,cfg->lc);
1328 /* state must be updated before calling linphone_core_update_friends_subscriptions*/
1329 cfg->state=state;
1330 linphone_core_update_friends_subscriptions(lc);
1331 } else {
1332 /*at this point state must be updated*/
1333 cfg->state=state;
1334 }
1335
1336 if (lc){
1337 linphone_core_notify_registration_state_changed(lc,cfg,state,message);
1338 linphone_core_repair_calls(lc);
1339 }
1340 } else {
1341 /*state already reported*/
1342 }
1343 }
1344
linphone_proxy_config_get_state(const LinphoneProxyConfig * cfg)1345 LinphoneRegistrationState linphone_proxy_config_get_state(const LinphoneProxyConfig *cfg){
1346 return cfg->state;
1347 }
1348
linphone_registration_state_to_string(LinphoneRegistrationState cs)1349 const char *linphone_registration_state_to_string(LinphoneRegistrationState cs){
1350 switch(cs){
1351 case LinphoneRegistrationCleared:
1352 return "LinphoneRegistrationCleared";
1353 break;
1354 case LinphoneRegistrationNone:
1355 return "LinphoneRegistrationNone";
1356 break;
1357 case LinphoneRegistrationProgress:
1358 return "LinphoneRegistrationProgress";
1359 break;
1360 case LinphoneRegistrationOk:
1361 return "LinphoneRegistrationOk";
1362 break;
1363 case LinphoneRegistrationFailed:
1364 return "LinphoneRegistrationFailed";
1365 break;
1366 }
1367 return NULL;
1368 }
1369
linphone_proxy_config_get_error(const LinphoneProxyConfig * cfg)1370 LinphoneReason linphone_proxy_config_get_error(const LinphoneProxyConfig *cfg) {
1371 return linphone_error_info_get_reason(linphone_proxy_config_get_error_info(cfg));
1372 }
1373
linphone_proxy_config_get_error_info(const LinphoneProxyConfig * cfg)1374 const LinphoneErrorInfo *linphone_proxy_config_get_error_info(const LinphoneProxyConfig *cfg){
1375 if (!cfg->ei) ((LinphoneProxyConfig*)cfg)->ei = linphone_error_info_new();
1376 linphone_error_info_from_sal_op(cfg->ei, cfg->op);
1377 return cfg->ei;
1378 }
1379
linphone_proxy_config_get_service_route(const LinphoneProxyConfig * cfg)1380 const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg) {
1381 return cfg->op?(const LinphoneAddress*) sal_op_get_service_route(cfg->op):NULL;
1382 }
linphone_proxy_config_get_transport(const LinphoneProxyConfig * cfg)1383 const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg) {
1384 const char* addr=NULL;
1385 const char* ret="udp"; /*default value*/
1386 SalAddress* route_addr=NULL;
1387 if (linphone_proxy_config_get_service_route(cfg)) {
1388 route_addr=(SalAddress*)linphone_proxy_config_get_service_route(cfg);
1389 } else if (linphone_proxy_config_get_route(cfg)) {
1390 addr=linphone_proxy_config_get_route(cfg);
1391 } else if(linphone_proxy_config_get_addr(cfg)) {
1392 addr=linphone_proxy_config_get_addr(cfg);
1393 } else {
1394 ms_error("Cannot guess transport for proxy with identity [%s]", cfg->reg_identity);
1395 return NULL;
1396 }
1397
1398 if (route_addr || (route_addr=sal_address_new(addr))) {
1399 ret=sal_transport_to_string(sal_address_get_transport(route_addr));
1400 if (!linphone_proxy_config_get_service_route(cfg)) {
1401 sal_address_destroy(route_addr);
1402 }
1403 }
1404
1405 return ret;
1406 }
linphone_proxy_config_set_privacy(LinphoneProxyConfig * params,LinphonePrivacyMask privacy)1407 void linphone_proxy_config_set_privacy(LinphoneProxyConfig *params, LinphonePrivacyMask privacy) {
1408 params->privacy=privacy;
1409 }
linphone_proxy_config_get_privacy(const LinphoneProxyConfig * params)1410 LinphonePrivacyMask linphone_proxy_config_get_privacy(const LinphoneProxyConfig *params) {
1411 return params->privacy;
1412 }
linphone_proxy_config_set_publish_expires(LinphoneProxyConfig * cfg,int expires)1413 void linphone_proxy_config_set_publish_expires(LinphoneProxyConfig *cfg, int expires) {
1414 cfg->publish_expires=expires;
1415 }
linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig * cfg)1416 int linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig *cfg) {
1417 if (cfg->publish_expires<0) {
1418 return cfg->expires; /*default value is same as register*/
1419 } else {
1420 return cfg->publish_expires;
1421 }
1422 }
1423
linphone_proxy_config_enable_avpf(LinphoneProxyConfig * cfg,bool_t enable)1424 void linphone_proxy_config_enable_avpf(LinphoneProxyConfig *cfg, bool_t enable) {
1425 cfg->avpf_mode=enable ? LinphoneAVPFEnabled : LinphoneAVPFDisabled;
1426 }
1427
linphone_proxy_config_avpf_enabled(LinphoneProxyConfig * cfg)1428 bool_t linphone_proxy_config_avpf_enabled(LinphoneProxyConfig *cfg) {
1429 if (cfg->avpf_mode==LinphoneAVPFDefault && cfg->lc){
1430 return linphone_core_get_avpf_mode(cfg->lc)==LinphoneAVPFEnabled;
1431 }
1432 return cfg->avpf_mode == LinphoneAVPFEnabled;
1433 }
1434
linphone_proxy_config_get_avpf_mode(const LinphoneProxyConfig * cfg)1435 LinphoneAVPFMode linphone_proxy_config_get_avpf_mode(const LinphoneProxyConfig *cfg){
1436 return cfg->avpf_mode;
1437 }
1438
linphone_proxy_config_set_avpf_mode(LinphoneProxyConfig * cfg,LinphoneAVPFMode mode)1439 void linphone_proxy_config_set_avpf_mode(LinphoneProxyConfig *cfg, LinphoneAVPFMode mode){
1440 cfg->avpf_mode=mode;
1441 }
1442
linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyConfig * cfg,uint8_t interval)1443 void linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyConfig *cfg, uint8_t interval) {
1444 if (interval > 5) interval = 5;
1445 cfg->avpf_rr_interval = interval;
1446 }
1447
linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig * cfg)1448 uint8_t linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig *cfg) {
1449 return cfg->avpf_rr_interval;
1450 }
1451
linphone_proxy_config_get_contact(const LinphoneProxyConfig * cfg)1452 const LinphoneAddress* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg) {
1453 return sal_op_get_contact_address(cfg->op);
1454 }
1455
linphone_proxy_config_find_auth_info(const LinphoneProxyConfig * cfg)1456 const struct _LinphoneAuthInfo* linphone_proxy_config_find_auth_info(const LinphoneProxyConfig *cfg) {
1457 const char* username = cfg->identity_address ? linphone_address_get_username(cfg->identity_address) : NULL;
1458 const char* domain = cfg->identity_address ? linphone_address_get_domain(cfg->identity_address) : NULL;
1459 return _linphone_core_find_auth_info(cfg->lc, cfg->realm, username, domain, TRUE);
1460 }
1461
linphone_proxy_config_get_ref_key(const LinphoneProxyConfig * cfg)1462 const char * linphone_proxy_config_get_ref_key(const LinphoneProxyConfig *cfg) {
1463 return cfg->refkey;
1464 }
1465
linphone_proxy_config_set_ref_key(LinphoneProxyConfig * cfg,const char * refkey)1466 void linphone_proxy_config_set_ref_key(LinphoneProxyConfig *cfg, const char *refkey) {
1467 if (cfg->refkey!=NULL){
1468 ms_free(cfg->refkey);
1469 cfg->refkey=NULL;
1470 }
1471 if (refkey) cfg->refkey=ms_strdup(refkey);
1472 }
1473
linphone_proxy_config_get_nat_policy(const LinphoneProxyConfig * cfg)1474 LinphoneNatPolicy * linphone_proxy_config_get_nat_policy(const LinphoneProxyConfig *cfg) {
1475 return cfg->nat_policy;
1476 }
1477
linphone_proxy_config_set_nat_policy(LinphoneProxyConfig * cfg,LinphoneNatPolicy * policy)1478 void linphone_proxy_config_set_nat_policy(LinphoneProxyConfig *cfg, LinphoneNatPolicy *policy) {
1479 if (policy != NULL) {
1480 policy = linphone_nat_policy_ref(policy); /* Prevent object destruction if the same policy is used */
1481 policy->lc = cfg->lc;
1482 }
1483 if (cfg->nat_policy != NULL) linphone_nat_policy_unref(cfg->nat_policy);
1484 cfg->nat_policy = policy;
1485 }
1486
linphone_proxy_config_notify_publish_state_changed(LinphoneProxyConfig * cfg,LinphonePublishState state)1487 void linphone_proxy_config_notify_publish_state_changed(LinphoneProxyConfig *cfg, LinphonePublishState state) {
1488 if ((cfg->presence_publish_event != NULL) && ((state == LinphonePublishCleared) || (state == LinphonePublishError))) {
1489 linphone_event_unref(cfg->presence_publish_event);
1490 cfg->presence_publish_event = NULL;
1491 }
1492 }
1493