proxy.c 58.2 KB
Newer Older
aymeric's avatar
aymeric committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
linphone
Copyright (C) 2000  Simon MORLAT (simon.morlat@linphone.org)
*/
/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
20

21 22
#include <ctype.h>

23
#include <bctoolbox/defs.h>
24
#include "linphone/core_utils.h"
25
#include "linphone/core.h"
26
#include "linphone/lpconfig.h"
27
#include "linphone/sipsetup.h"
28

29
#include "mediastreamer2/mediastream.h"
30

31
#include "core/core.h"
32
#include "enum.h"
33 34 35 36
#include "private.h"

// For migration purpose.
#include "address/address-p.h"
37
#include "c-wrapper/c-wrapper.h"
38
#include "linphone/api/c-dial-plan.h"
39

40 41 42
#include "dial-plan/dial-plan.h"
#include "dial-plan/dial-plan-p.h"

43
using namespace LinphonePrivate;
44

45
/*store current config related to server location*/
46
static void linphone_proxy_config_store_server_config(LinphoneProxyConfig* cfg) {
Simon Morlat's avatar
Simon Morlat committed
47
	if (cfg->saved_identity) linphone_address_unref(cfg->saved_identity);
48 49
	if (cfg->identity_address)
		cfg->saved_identity = linphone_address_clone(cfg->identity_address);
50
	else
51
		cfg->saved_identity = NULL;
52

Simon Morlat's avatar
Simon Morlat committed
53
	if (cfg->saved_proxy) linphone_address_unref(cfg->saved_proxy);
54 55
	if (cfg->reg_proxy)
		cfg->saved_proxy = linphone_address_new(cfg->reg_proxy);
56
	else
57
		cfg->saved_proxy = NULL;
58 59
}

60
LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b) {
61
	if (a == NULL && b == NULL)
62
		return LinphoneProxyConfigAddressEqual;
63
	else if (!a || !b)
64
		return LinphoneProxyConfigAddressDifferent;
65

66 67
	if (linphone_address_equal(a,b))
		return LinphoneProxyConfigAddressEqual;
68 69
	if (linphone_address_weak_equal(a,b)) {
		/*also check both transport and uri */
Simon Morlat's avatar
Simon Morlat committed
70
		if (linphone_address_get_secure(a) == linphone_address_get_secure(b) && linphone_address_get_transport(a) == linphone_address_get_transport(b))
71 72 73 74 75
			return LinphoneProxyConfigAddressWeakEqual;
		else
			return LinphoneProxyConfigAddressDifferent;
	}
	return LinphoneProxyConfigAddressDifferent; /*either username, domain or port ar not equals*/
76 77
}

78 79
LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* cfg) {
	LinphoneAddress *current_proxy=cfg->reg_proxy?linphone_address_new(cfg->reg_proxy):NULL;
80 81
	LinphoneProxyConfigAddressComparisonResult result_identity;
	LinphoneProxyConfigAddressComparisonResult result;
82

83
	result = linphone_proxy_config_address_equal(cfg->saved_identity,cfg->identity_address);
84
	if (result == LinphoneProxyConfigAddressDifferent) goto end;
85
	result_identity = result;
86

87
	result = linphone_proxy_config_address_equal(cfg->saved_proxy,current_proxy);
88
	if (result == LinphoneProxyConfigAddressDifferent) goto end;
89 90 91 92 93
	/** If the proxies are equal use the result of the difference between the identities,
	  * otherwise the result is weak-equal and so weak-equal must be returned even if the
	  * identities were equal.
	  */
	if (result == LinphoneProxyConfigAddressEqual) result = result_identity;
94

Simon Morlat's avatar
Simon Morlat committed
95
	end:
Simon Morlat's avatar
Simon Morlat committed
96
	if (current_proxy) linphone_address_unref(current_proxy);
97
	ms_message("linphone_proxy_config_is_server_config_changed : %i", result);
Simon Morlat's avatar
Simon Morlat committed
98
	return result;
99
}
100

smorlat's avatar
smorlat committed
101
void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
102
	bctbx_list_t *elem;
smorlat's avatar
smorlat committed
103
	int i;
104
	if (!linphone_core_ready(lc)) return;
105

106
	for(elem=lc->sip_conf.proxies,i=0;elem!=NULL;elem=bctbx_list_next(elem),i++){
smorlat's avatar
smorlat committed
107 108 109
		LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
		linphone_proxy_config_write_to_config_file(lc->config,cfg,i);
	}
110 111
	/*to ensure removed configs are erased:*/
	linphone_proxy_config_write_to_config_file(lc->config,NULL,i);
112
	lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy_config_index(lc));
smorlat's avatar
smorlat committed
113
}
aymeric's avatar
aymeric committed
114

115
static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *cfg) {
116 117 118
	const char *dial_prefix = lc ? lp_config_get_default_string(lc->config,"proxy","dial_prefix",NULL) : NULL;
	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;
119
	const char *route = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_route", NULL) : NULL; //TODO return list instead of string
120
	const char *realm = lc ? lp_config_get_default_string(lc->config, "proxy", "realm", NULL) : NULL;
121
	const char *quality_reporting_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "quality_reporting_collector", NULL) : NULL;
122 123
	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;
124
	const char *refkey = lc ? lp_config_get_default_string(lc->config, "proxy", "refkey", NULL) : NULL;
125
	const char *nat_policy_ref = lc ? lp_config_get_default_string(lc->config, "proxy", "nat_policy_ref", NULL):NULL;
126
	const char *conference_factory_uri = lc ? lp_config_get_default_string(lc->config, "proxy", "conference_factory_uri", NULL):NULL;
127
	cfg->lc = lc;
128
	cfg->expires = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_expires", 3600) : 3600;
129
	cfg->reg_sendregister = lc ? !!lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 1) : 1;
130
	cfg->dial_prefix = dial_prefix ? ms_strdup(dial_prefix) : NULL;
131
	cfg->dial_escape_plus = lc ? !!lp_config_get_default_int(lc->config, "proxy", "dial_escape_plus", 0) : 0;
132
	cfg->privacy = lc ? (LinphonePrivacyMask)lp_config_get_default_int(lc->config, "proxy", "privacy", LinphonePrivacyDefault) : (LinphonePrivacyMask)LinphonePrivacyDefault;
133 134 135
	cfg->identity_address = identity ? linphone_address_new(identity) : NULL;
	cfg->reg_identity = cfg->identity_address ? linphone_address_as_string(cfg->identity_address) : NULL;
	cfg->reg_proxy = proxy ? ms_strdup(proxy) : NULL;
136
	cfg->reg_routes = route ? bctbx_list_append(cfg->reg_routes, ms_strdup(route)) : NULL; //TODO get list directly
137
	cfg->realm = realm ? ms_strdup(realm) : NULL;
138
	cfg->quality_reporting_enabled = lc ? !!lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0;
139
	cfg->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL;
140
	cfg->quality_reporting_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_interval", 0) : 0;
141 142
	cfg->contact_params = contact_params ? ms_strdup(contact_params) : NULL;
	cfg->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL;
143
	cfg->avpf_mode = lc ? static_cast<LinphoneAVPFMode>(lp_config_get_default_int(lc->config, "proxy", "avpf", LinphoneAVPFDefault)) : LinphoneAVPFDefault;
144
	cfg->avpf_rr_interval = lc ? !!lp_config_get_default_int(lc->config, "proxy", "avpf_rr_interval", 5) : 5;
145
	cfg->publish_expires= lc ? lp_config_get_default_int(lc->config, "proxy", "publish_expires", -1) : -1;
146
	cfg->publish = lc ? !!lp_config_get_default_int(lc->config, "proxy", "publish", FALSE) : FALSE;
147 148 149 150
	cfg->lime_x3dh = lc ? !!lp_config_get_int(lc->config, "lime", "lime_x3dh", FALSE) : FALSE;
	if (!cfg->lime_x3dh) {
		cfg->lime_x3dh = lc ? !!lp_config_get_int(lc->config, "lime", "lime_v2", FALSE) : FALSE;
	}
151
	cfg->push_notification_allowed = lc ? !!lp_config_get_default_int(lc->config, "proxy", "push_notification_allowed", TRUE) : TRUE;
152
	cfg->refkey = refkey ? ms_strdup(refkey) : NULL;
153 154 155 156 157 158 159 160 161
	if (nat_policy_ref) {
		LinphoneNatPolicy *policy = linphone_config_create_nat_policy_from_section(lc->config,nat_policy_ref);
		linphone_proxy_config_set_nat_policy(cfg, policy);
		if (policy) {
			linphone_nat_policy_unref(policy);
		} else {
			ms_error("Cannot create default nat policy with ref [%s] for proxy config [%p]",nat_policy_ref,cfg);
		}
	}
162
	cfg->conference_factory_uri = conference_factory_uri ? ms_strdup(conference_factory_uri) : NULL;
aymeric's avatar
aymeric committed
163 164
}

165 166 167
LinphoneProxyConfig *linphone_proxy_config_new() {
	return linphone_core_create_proxy_config(NULL);
}
168

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
static char * append_linphone_address(LinphoneAddress *addr,char *out) {
	char *res = out;
	if (addr) {
		char *tmp;
		tmp = linphone_address_as_string(addr);
		res = ms_strcat_printf(out, "%s",tmp);
		ms_free(tmp);
	}
	return res;
};
static char * append_string(const char * string,char *out) {
	char *res = out;
	if (string) {
		res = ms_strcat_printf(out, "%s",string);
	}
	return res;
}
/*
 * return true if computed value has changed
 */
bool_t linphone_proxy_config_compute_publish_params_hash(LinphoneProxyConfig * cfg) {
	char * source = NULL;
	char hash[33];
	char saved;
	unsigned long long previous_hash[2];
194
	bctbx_list_t *routes_iterator = cfg->reg_routes;
195 196
	previous_hash[0] = cfg->previous_publish_config_hash[0];
	previous_hash[1] = cfg->previous_publish_config_hash[1];
197

198 199 200
	source = ms_strcat_printf(source, "%i",cfg->privacy);
	source=append_linphone_address(cfg->identity_address, source);
	source=append_string(cfg->reg_proxy,source);
201 202 203 204 205
	while (routes_iterator) {
		const char *route = (const char *)bctbx_list_get_data(routes_iterator);
		source=append_string(route,source);
		routes_iterator = bctbx_list_next(routes_iterator);
	}
206 207 208 209 210 211 212 213 214 215 216 217
	source=append_string(cfg->realm,source);
	source = ms_strcat_printf(source, "%i",cfg->publish_expires);
	source = ms_strcat_printf(source, "%i",cfg->publish);
	belle_sip_auth_helper_compute_ha1(source, "dummy", "dummy", hash);
	ms_free(source);
	saved = hash[16];
	hash[16] = '\0';
	cfg->previous_publish_config_hash[0] = strtoull(hash, (char **)NULL, 16);
	hash[16] = saved;
	cfg->previous_publish_config_hash[1] = strtoull(&hash[16], (char **)NULL, 16);
	return previous_hash[0] != cfg->previous_publish_config_hash[0] || previous_hash[1] != cfg->previous_publish_config_hash[1];
}
218
static void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg);
219 220 221 222 223 224 225 226 227 228

BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneProxyConfig);

BELLE_SIP_INSTANCIATE_VPTR(LinphoneProxyConfig, belle_sip_object_t,
	(belle_sip_object_destroy_t)_linphone_proxy_config_destroy,
	NULL, // clone
	NULL, // marshal
	FALSE
);

229
LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) {
230 231 232
	LinphoneProxyConfig *cfg = belle_sip_object_new(LinphoneProxyConfig);
	linphone_proxy_config_init(lc,cfg);
	return cfg;
233 234
}

235 236
void _linphone_proxy_config_release_ops(LinphoneProxyConfig *cfg){
	if (cfg->op) {
237
		cfg->op->release();
238 239
		cfg->op=NULL;
	}
240 241 242 243
	if (cfg->presence_publish_event){
		linphone_event_terminate(cfg->presence_publish_event);
		linphone_event_unref(cfg->presence_publish_event);
		cfg->presence_publish_event=NULL;
244 245 246 247
	}
}

void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){
248 249 250 251 252 253 254 255 256
	if (cfg->reg_proxy != NULL) ms_free(cfg->reg_proxy);
	if (cfg->reg_identity != NULL) ms_free(cfg->reg_identity);
	if (cfg->identity_address != NULL) linphone_address_unref(cfg->identity_address);
	if (cfg->reg_routes != NULL) bctbx_list_free_with_data(cfg->reg_routes, ms_free);
	if (cfg->quality_reporting_collector != NULL) ms_free(cfg->quality_reporting_collector);
	if (cfg->ssctx != NULL) sip_setup_context_free(cfg->ssctx);
	if (cfg->realm != NULL) ms_free(cfg->realm);
	if (cfg->type != NULL) ms_free(cfg->type);
	if (cfg->dial_prefix != NULL) ms_free(cfg->dial_prefix);
257 258
	if (cfg->contact_params) ms_free(cfg->contact_params);
	if (cfg->contact_uri_params) ms_free(cfg->contact_uri_params);
259 260 261
	if (cfg->saved_proxy != NULL) linphone_address_unref(cfg->saved_proxy);
	if (cfg->saved_identity != NULL) linphone_address_unref(cfg->saved_identity);
	if (cfg->sent_headers != NULL) sal_custom_header_free(cfg->sent_headers);
262
	if (cfg->pending_contact) linphone_address_unref(cfg->pending_contact);
263
	if (cfg->refkey) ms_free(cfg->refkey);
Ghislain MARY's avatar
Ghislain MARY committed
264 265 266
	if (cfg->nat_policy != NULL) {
		linphone_nat_policy_unref(cfg->nat_policy);
	}
267 268
	if (cfg->conference_factory_uri)
		bctbx_free(cfg->conference_factory_uri);
269 270 271
	if (cfg->ei){
		linphone_error_info_unref(cfg->ei);
	}
Ronan's avatar
Ronan committed
272

273
	if (cfg->service_route) linphone_address_unref(cfg->service_route);
Ronan's avatar
Ronan committed
274
	if (cfg->contact_address) linphone_address_unref(cfg->contact_address);
Ghislain MARY's avatar
Ghislain MARY committed
275 276
	if (cfg->contact_address_without_params)
		linphone_address_unref(cfg->contact_address_without_params);
Ronan's avatar
Ronan committed
277

278
	_linphone_proxy_config_release_ops(cfg);
279 280 281 282 283 284
}

void linphone_proxy_config_destroy(LinphoneProxyConfig *cfg) {
	belle_sip_object_unref(cfg);
}

285 286 287 288 289
void _linphone_proxy_config_release(LinphoneProxyConfig *cfg) {
	_linphone_proxy_config_release_ops(cfg);
	belle_sip_object_unref(cfg);
}

290 291 292 293 294 295 296
LinphoneProxyConfig *linphone_proxy_config_ref(LinphoneProxyConfig *cfg) {
	belle_sip_object_ref(cfg);
	return cfg;
}

void linphone_proxy_config_unref(LinphoneProxyConfig *cfg) {
	belle_sip_object_unref(cfg);
aymeric's avatar
aymeric committed
297 298
}

299 300
bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *cfg){
	return cfg->state == LinphoneRegistrationOk;
smorlat's avatar
smorlat committed
301 302
}

303
LinphoneStatus linphone_proxy_config_set_server_addr(LinphoneProxyConfig *cfg, const char *server_addr){
304 305
	LinphoneAddress *addr=NULL;
	char *modified=NULL;
306

307 308
	if (cfg->reg_proxy!=NULL) ms_free(cfg->reg_proxy);
	cfg->reg_proxy=NULL;
309

aymeric's avatar
aymeric committed
310
	if (server_addr!=NULL && strlen(server_addr)>0){
311
		if (strstr(server_addr,"sip:")==NULL && strstr(server_addr,"sips:")==NULL){
312 313 314
			modified=ms_strdup_printf("sip:%s",server_addr);
			addr=linphone_address_new(modified);
			ms_free(modified);
315
		}
316 317
		if (addr==NULL)
			addr=linphone_address_new(server_addr);
318
		if (addr){
319
			cfg->reg_proxy=linphone_address_as_string(addr);
Simon Morlat's avatar
Simon Morlat committed
320
			linphone_address_unref(addr);
aymeric's avatar
aymeric committed
321 322
		}else{
			ms_warning("Could not parse %s",server_addr);
323
			return -1;
aymeric's avatar
aymeric committed
324 325 326 327 328
		}
	}
	return 0;
}

329

330
LinphoneStatus linphone_proxy_config_set_identity_address(LinphoneProxyConfig *cfg, const LinphoneAddress *addr){
331
	if (!addr || linphone_address_get_username(addr)==NULL){
332 333
		char* as_string = addr ? linphone_address_as_string(addr) : ms_strdup("NULL");
		ms_warning("Invalid sip identity: %s", as_string);
334 335 336 337
		ms_free(as_string);
		return -1;
	}
	if (cfg->identity_address != NULL) {
Simon Morlat's avatar
Simon Morlat committed
338
		linphone_address_unref(cfg->identity_address);
339 340 341 342 343 344 345 346 347 348
	}
	cfg->identity_address=linphone_address_clone(addr);

	if (cfg->reg_identity!=NULL) {
		ms_free(cfg->reg_identity);
	}
	cfg->reg_identity= linphone_address_as_string(cfg->identity_address);
	return 0;
}

349
LinphoneStatus linphone_proxy_config_set_identity(LinphoneProxyConfig *cfg, const char *identity){
aymeric's avatar
aymeric committed
350
	if (identity!=NULL && strlen(identity)>0){
351 352
		LinphoneAddress *addr=linphone_address_new(identity);
		int ret=linphone_proxy_config_set_identity_address(cfg, addr);
Simon Morlat's avatar
Simon Morlat committed
353
		if (addr) linphone_address_unref(addr);
354
		return ret;
aymeric's avatar
aymeric committed
355
	}
356
	return -1;
smorlat's avatar
smorlat committed
357 358 359
}

const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
360
	return cfg->identity_address ? linphone_address_get_domain(cfg->identity_address) : NULL;
aymeric's avatar
aymeric committed
361 362
}

363
LinphoneStatus linphone_proxy_config_set_route(LinphoneProxyConfig *cfg, const char *route)
aymeric's avatar
aymeric committed
364
{
365
	if (cfg->reg_routes != NULL) {
366
		bctbx_list_free_with_data(cfg->reg_routes, ms_free);
367
		cfg->reg_routes = NULL;
aymeric's avatar
aymeric committed
368
	}
369
	if (route!=NULL && route[0] !='\0'){
370 371
		SalAddress *addr;
		char *tmp;
372
		/*try to prepend 'sip:' */
373
		if (strstr(route,"sip:")==NULL && strstr(route,"sips:")==NULL){
374 375 376 377
			tmp=ms_strdup_printf("sip:%s",route);
		}else tmp=ms_strdup(route);
		addr=sal_address_new(tmp);
		if (addr!=NULL){
Ghislain MARY's avatar
Ghislain MARY committed
378
			sal_address_unref(addr);
379
			cfg->reg_routes = bctbx_list_append(cfg->reg_routes, tmp);
380
			return 0;
381 382
		}else{
			ms_free(tmp);
383
			return -1;
384
		}
385 386
	} else {
		return 0;
387
	}
aymeric's avatar
aymeric committed
388 389
}

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
LinphoneStatus linphone_proxy_config_set_routes(LinphoneProxyConfig *cfg, const bctbx_list_t *routes) {
	if (cfg->reg_routes != NULL) {
		bctbx_list_free_with_data(cfg->reg_routes, ms_free);
		cfg->reg_routes = NULL;
	}
	bctbx_list_t *iterator = (bctbx_list_t *)routes;
	while (iterator != NULL) {
		char *route = (char *)bctbx_list_get_data(iterator);
		if (route != NULL && route[0] !='\0') {
			SalAddress *addr;
			char *tmp;
			/*try to prepend 'sip:' */
			if (strstr(route,"sip:") == NULL && strstr(route,"sips:") == NULL) {
				tmp = ms_strdup_printf("sip:%s",route);
			} else {
				tmp = ms_strdup(route);
			}
			addr = sal_address_new(tmp);
			if (addr != NULL) {
Ghislain MARY's avatar
Ghislain MARY committed
409
				sal_address_unref(addr);
410 411 412 413 414 415 416 417 418 419 420
				cfg->reg_routes = bctbx_list_append(cfg->reg_routes, tmp);
			} else {
				ms_free(tmp);
				return -1;
			}
		}
		iterator = bctbx_list_next(iterator);
	}
	return 0;
}

421
bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *cfg){
422
	if (cfg->reg_proxy==NULL)
aymeric's avatar
aymeric committed
423
		return FALSE;
424
	if (cfg->identity_address==NULL)
aymeric's avatar
aymeric committed
425 426 427 428
		return FALSE;
	return TRUE;
}

429
void linphone_proxy_config_enableregister(LinphoneProxyConfig *cfg, bool_t val){
430
	if (val != cfg->reg_sendregister) cfg->register_changed = TRUE;
431
	cfg->reg_sendregister=val;
aymeric's avatar
aymeric committed
432 433
}

434
void linphone_proxy_config_set_expires(LinphoneProxyConfig *cfg, int val){
435
	if (val<0) val=600;
436
	if (val != cfg->expires) cfg->register_changed = TRUE;
437
	cfg->expires=val;
aymeric's avatar
aymeric committed
438 439
}

440 441
void linphone_proxy_config_enable_publish(LinphoneProxyConfig *cfg, bool_t val){
	cfg->publish=val;
aymeric's avatar
aymeric committed
442
}
443

444
void linphone_proxy_config_pause_register(LinphoneProxyConfig *cfg){
445
	if (cfg->op) cfg->op->stopRefreshing();
446 447
}

448
void linphone_proxy_config_edit(LinphoneProxyConfig *cfg){
449
	/*store current config related to server location*/
450
	linphone_proxy_config_store_server_config(cfg);
451
	linphone_proxy_config_compute_publish_params_hash(cfg);
452

453 454
	if (cfg->publish && cfg->presence_publish_event){
		linphone_event_pause_publish(cfg->presence_publish_event);
455
	}
456
	/*Don't stop refresher*/
aymeric's avatar
aymeric committed
457 458
}

459 460 461
void linphone_proxy_config_apply(LinphoneProxyConfig *cfg,LinphoneCore *lc){
	cfg->lc=lc;
	linphone_proxy_config_done(cfg);
aymeric's avatar
aymeric committed
462
}
Simon Morlat's avatar
Simon Morlat committed
463

464
void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg){
465
	LinphoneAddress *contact_addr = NULL;
466
	const SalAddress *sal_addr = cfg->op && cfg->state == LinphoneRegistrationOk ? cfg->op->getContactAddress() : NULL;
467 468 469 470
	if (sal_addr) {
		char *buf = sal_address_as_string(sal_addr);
		contact_addr = buf ? linphone_address_new(buf) : NULL;
		ms_free(buf);
471 472 473 474
	}

	/*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/
	if (contact_addr) {
475
		if (linphone_address_get_transport(contact_addr) != LinphoneTransportUdp && lp_config_get_int(cfg->lc->config, "sip", "unregister_previous_contact", 0)) {
476 477 478 479 480 481
			if (cfg->pending_contact)
				linphone_address_unref(cfg->pending_contact);
			cfg->pending_contact=contact_addr;
		} else
			linphone_address_unref(contact_addr);
	}
482 483 484 485
	if (cfg->presence_publish_event){ /*might probably do better*/
		linphone_event_set_publish_state(cfg->presence_publish_event,LinphonePublishNone);
		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*/
		cfg->presence_publish_event=NULL;
486
	}
487

488
	if (cfg->op){
489
		cfg->op->release();
490
		cfg->op=NULL;
491 492 493
	}
}

494
static void guess_contact_for_register (LinphoneProxyConfig *cfg) {
495 496
	if (cfg->contact_address)
		linphone_address_unref(cfg->contact_address);
497
	cfg->contact_address = nullptr;
498 499 500

	if (cfg->contact_address_without_params)
		linphone_address_unref(cfg->contact_address_without_params);
501
	cfg->contact_address_without_params = nullptr;
502

503 504 505 506 507 508 509 510 511 512 513
	LinphoneAddress *proxy = linphone_address_new(cfg->reg_proxy);
	if (!proxy)
		return;
	const char *host = linphone_address_get_domain(proxy);
	if (host) {
		cfg->contact_address_without_params = linphone_address_clone(cfg->identity_address);
		linphone_address_clean(cfg->contact_address_without_params);
		linphone_address_set_port(cfg->contact_address_without_params, -1);
		linphone_address_set_domain(cfg->contact_address_without_params, nullptr);
		linphone_address_set_display_name(cfg->contact_address_without_params, nullptr);
		cfg->contact_address = linphone_address_clone(cfg->contact_address_without_params);
514
		if (cfg->contact_params) {
515
			// We want to add a list of contacts params to the linphone address
516
			linphone_address_set_params(cfg->contact_address, cfg->contact_params);
517
		}
518 519
		if (cfg->contact_uri_params)
			linphone_address_set_uri_params(cfg->contact_address, cfg->contact_uri_params);
520
	}
Simon Morlat's avatar
Simon Morlat committed
521
	linphone_address_unref(proxy);
522
}
523

524 525 526
void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj) {
	if (obj->op && (obj->state == LinphoneRegistrationOk ||
					(obj->state == LinphoneRegistrationProgress && obj->expires != 0))) {
527
		obj->op->unregister();
528 529
	}
}
530

531 532 533
static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){
	if (cfg->reg_sendregister){
		LinphoneAddress* proxy=linphone_address_new(cfg->reg_proxy);
Simon Morlat's avatar
Simon Morlat committed
534
		char* proxy_string;
535 536
		char * from = linphone_address_as_string(cfg->identity_address);
		ms_message("LinphoneProxyConfig [%p] about to register (LinphoneCore version: %s)",cfg,linphone_core_get_version());
537
		proxy_string=linphone_address_as_string_uri_only(proxy);
Simon Morlat's avatar
Simon Morlat committed
538
		linphone_address_unref(proxy);
539
		if (cfg->op)
540 541
			cfg->op->release();
		cfg->op=new SalRegisterOp(cfg->lc->sal);
542

543
		linphone_configure_op(cfg->lc, cfg->op, cfg->identity_address, cfg->sent_headers, FALSE);
544

545 546
		guess_contact_for_register(cfg);
		if (cfg->contact_address)
547 548
			cfg->op->setContactAddress(L_GET_PRIVATE_FROM_C_OBJECT(cfg->contact_address)->getInternalAddress());
		cfg->op->setUserPointer(cfg);
549

550
		if (cfg->op->sendRegister(
551 552 553
			proxy_string,
			cfg->reg_identity,
			cfg->expires,
554
			cfg->pending_contact ? L_GET_PRIVATE_FROM_C_OBJECT(cfg->pending_contact)->getInternalAddress() : NULL
555
		)==0) {
556 557 558 559
			if (cfg->pending_contact) {
				linphone_address_unref(cfg->pending_contact);
				cfg->pending_contact=NULL;
			}
560
			linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress,"Registration in progress");
561
		} else {
562
			linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,"Registration failed");
563
		}
564
		ms_free(proxy_string);
565
		ms_free(from);
566
	} else {
567
		/* unregister if registered*/
568 569
		if (cfg->state == LinphoneRegistrationProgress) {
			linphone_proxy_config_set_state(cfg,LinphoneRegistrationCleared,"Registration cleared");
570
		}
571
		_linphone_proxy_config_unregister(cfg);
aymeric's avatar
aymeric committed
572
	}
smorlat's avatar
smorlat committed
573 574
}

575 576
void linphone_proxy_config_refresh_register(LinphoneProxyConfig *cfg){
	if (cfg->reg_sendregister && cfg->op && cfg->state!=LinphoneRegistrationProgress){
577
		if (cfg->op->refreshRegister(cfg->expires) == 0) {
578
			linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress, "Refresh registration");
579
		}
580 581 582
	}
}

583 584 585 586 587 588

void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix){
	if (cfg->dial_prefix!=NULL){
		ms_free(cfg->dial_prefix);
		cfg->dial_prefix=NULL;
	}
589
	if (prefix && prefix[0]!='\0') cfg->dial_prefix=ms_strdup(prefix);
590 591 592 593 594 595 596 597 598 599 600 601 602
}

const char *linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg){
	return cfg->dial_prefix;
}

void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val){
	cfg->dial_escape_plus=val;
}

bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg){
	return cfg->dial_escape_plus;
}
603

604 605
void linphone_proxy_config_enable_quality_reporting(LinphoneProxyConfig *cfg, bool_t val){
	cfg->quality_reporting_enabled = val;
606 607
}

608
bool_t linphone_proxy_config_quality_reporting_enabled(LinphoneProxyConfig *cfg){
609
	return cfg->quality_reporting_enabled;
610 611
}

612
void linphone_proxy_config_set_quality_reporting_interval(LinphoneProxyConfig *cfg, int interval) {
613
	cfg->quality_reporting_interval = interval;
614 615 616 617 618 619
}

int linphone_proxy_config_get_quality_reporting_interval(LinphoneProxyConfig *cfg) {
	return cfg->quality_reporting_interval;
}

620
void linphone_proxy_config_set_quality_reporting_collector(LinphoneProxyConfig *cfg, const char *collector){
621 622
	if (collector!=NULL && strlen(collector)>0){
		LinphoneAddress *addr=linphone_address_new(collector);
623
		if (!addr){
624
			ms_error("Invalid SIP collector URI: %s. Quality reporting will be DISABLED.",collector);
625
		} else {
626
			if (cfg->quality_reporting_collector != NULL){
627
				ms_free(cfg->quality_reporting_collector);
628
			}
629
			cfg->quality_reporting_collector = ms_strdup(collector);
630 631 632
		}

		if (addr){
Simon Morlat's avatar
Simon Morlat committed
633
			linphone_address_unref(addr);
634 635 636 637
		}
	}
}

638 639
const char *linphone_proxy_config_get_quality_reporting_collector(const LinphoneProxyConfig *cfg){
	return cfg->quality_reporting_collector;
640 641 642
}


643
bool_t linphone_proxy_config_is_phone_number(LinphoneProxyConfig *proxy, const char *username){
644
	const char *p;
645
	if (!username) return FALSE;
646
	for(p=username;*p!='\0';++p){
647
		if (isdigit(*p) ||
648 649 650 651
			*p==' ' ||
			*p=='.' ||
			*p=='-' ||
			*p==')' ||
652 653
			*p=='(' ||
			*p=='/' ||
654
			*p=='+' ||
655 656
			(unsigned char)*p==0xca || (unsigned char)*p==0xc2 || (unsigned char)*p==0xa0 // non-breakable space (iOS uses it to format contacts phone number)
			) {
657
			continue;
658
		}
659
		return FALSE;
660 661 662 663
	}
	return TRUE;
}

664
//remove anything but [0-9] and +
665
static char *flatten_number(const char *number){
666
	char *result=reinterpret_cast<char *>(ms_malloc0(strlen(number)+1));
667 668 669
	char *w=result;
	const char *r;
	for(r=number;*r!='\0';++r){
670
		if (*r=='+' || isdigit(*r)){
671 672 673 674 675 676 677
			*w++=*r;
		}
	}
	*w++='\0';
	return result;
}

jehan's avatar
jehan committed
678
/*static char* replace_plus_with_icp(char *phone, const char* icp){
679
	return (icp && phone[0]=='+') ? ms_strdup_printf("%s%s", icp, phone+1) : ms_strdup(phone);
jehan's avatar
jehan committed
680
}*/
681

682
static char* replace_icp_with_plus(char *phone, const char *icp){
683 684
	return (strstr(phone, icp) == phone) ?  ms_strdup_printf("+%s", phone+strlen(icp)) : ms_strdup(phone);
}
685

686
bool_t linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len){
687 688
	char * normalized_phone = linphone_proxy_config_normalize_phone_number(proxy, username);
	const char * output = normalized_phone ? normalized_phone : username;
689
	memset(result, 0, result_len);
690 691 692
	memcpy(result, output, MIN(strlen(output) + 1, result_len));
	ms_free(normalized_phone);
	return output != username;
693 694
}

695 696 697
char* linphone_proxy_config_normalize_phone_number(LinphoneProxyConfig *proxy, const char *username) {
	LinphoneProxyConfig *tmpproxy = proxy ? proxy : linphone_proxy_config_new();
	char* result = NULL;
698
	DialPlan dialplan;
699 700
	char * nationnal_significant_number = NULL;
	int ccc = -1;
701

702 703
	if (linphone_proxy_config_is_phone_number(tmpproxy, username)){
		char * flatten=flatten_number(username);
704
		ms_debug("Flattened number is '%s' for '%s'",flatten, username);
705

706
		ccc = DialPlan::lookupCccFromE164(flatten);
707
		if (ccc>-1) { /*e164 like phone number*/
708
			dialplan = DialPlan::findByCcc(ccc);
709
			nationnal_significant_number = strstr(flatten, dialplan.getCountryCallingCode().c_str());
710
			if (nationnal_significant_number) {
711
				nationnal_significant_number +=strlen(dialplan.getCountryCallingCode().c_str());
712 713 714 715 716
			}
		} else if (flatten[0] =='+') {
			ms_message ("Unknown ccc for e164 like number [%s]", flatten);
			goto end;
		} else {
717 718 719 720 721
			if (tmpproxy->dial_prefix) {
				dialplan = DialPlan::findByCcc(tmpproxy->dial_prefix); //copy dial plan;
			} else {
				dialplan = DialPlan::MostCommon;
			}
722
			if (tmpproxy->dial_prefix){
723
				if (strcmp(tmpproxy->dial_prefix,dialplan.getCountryCallingCode().c_str()) != 0){
724
					//probably generic dialplan, preserving proxy dial prefix
725 726
					dialplan.setCountryCallingCode(tmpproxy->dial_prefix);
				}
727

728
				/*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)*/
729 730 731
				if (strstr(flatten, dialplan.getInternationalCallPrefix().c_str()) == flatten) {
					char *e164 = replace_icp_with_plus(flatten, dialplan.getInternationalCallPrefix().c_str());
					result = linphone_proxy_config_normalize_phone_number(tmpproxy, e164);
732 733 734
					ms_free(e164);
					goto end;
				}
735 736
			}
			nationnal_significant_number=flatten;
737
		}
738
		ms_debug("Using dial plan '%s'",dialplan.getCountry().c_str());
739

740
		/*if proxy has a dial prefix, modify phonenumber accordingly*/
741
		if (dialplan.getCountryCallingCode().c_str()[0]!='\0') {
742
			/* the number already starts with + or international prefix*/
743 744 745
			/*0. keep at most national number significant digits */
			char* nationnal_significant_number_start = nationnal_significant_number
														+ MAX(0, (int)strlen(nationnal_significant_number)
746 747
														- (int)dialplan.getNationalNumberLength());
			ms_debug("Prefix not present. Keeping at most %d digits: %s", dialplan.getNationalNumberLength(), nationnal_significant_number_start);
748 749 750 751 752

			/*1. First prepend international calling prefix or +*/
			/*2. Second add prefix*/
			/*3. Finally add user digits */
			result = ms_strdup_printf("%s%s%s"
753 754
										, tmpproxy->dial_escape_plus ? dialplan.getInternationalCallPrefix().c_str() : "+"
										, dialplan.getCountryCallingCode().c_str()
755 756
										, nationnal_significant_number_start);
			ms_debug("Prepended prefix resulted in %s", result);
757
		}
758 759

	end:
760 761 762 763 764 765
		if (result==NULL) {
			result = flatten;
		} else {
			ms_free(flatten);
		}
	}
766
	if (proxy==NULL) linphone_proxy_config_unref(tmpproxy);
767 768 769 770 771 772 773
	return result;
}

static LinphoneAddress* _linphone_core_destroy_addr_if_not_sip( LinphoneAddress* addr ){
	if( linphone_address_is_sip(addr) ) {
		return addr;
	} else {
Simon Morlat's avatar
Simon Morlat committed
774
		linphone_address_unref(addr);
775 776 777 778 779 780 781 782 783 784
		return NULL;
	}
}

LinphoneAddress* linphone_proxy_config_normalize_sip_uri(LinphoneProxyConfig *proxy, const char *username) {
	enum_lookup_res_t *enumres=NULL;
	char *enum_domain=NULL;
	char *tmpurl;
	LinphoneAddress *uri;

785
	if (!username || *username=='\0') return NULL;
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810

	if (is_enum(username,&enum_domain)){
		if (enum_lookup(enum_domain,&enumres)<0){
			ms_free(enum_domain);
			return NULL;
		}
		ms_free(enum_domain);
		tmpurl=enumres->sip_address[0];
		uri=linphone_address_new(tmpurl);
		enum_lookup_res_free(enumres);
		return _linphone_core_destroy_addr_if_not_sip(uri);
	}
	/* check if we have a "sip:" or a "sips:" */
	if ( (strstr(username,"sip:")==NULL) && (strstr(username,"sips:")==NULL) ){
		/* this doesn't look like a true sip uri */
		if (strchr(username,'@')!=NULL){
			/* seems like sip: is missing !*/
			tmpurl=ms_strdup_printf("sip:%s",username);
			uri=linphone_address_new(tmpurl);
			ms_free(tmpurl);
			if (uri){
				return _linphone_core_destroy_addr_if_not_sip(uri);
			}
		}

811
		if (proxy!=NULL && linphone_proxy_config_get_identity_address(proxy)!=NULL){
812
			/* append the proxy domain suffix but remove any custom parameters/headers */
813
			LinphoneAddress *uri=linphone_address_clone(linphone_proxy_config_get_identity_address(proxy));
814 815
			if (uri==NULL){
				return NULL;
816
			} else {
817
				linphone_address_clean(uri);
818
				linphone_address_set_display_name(uri,NULL);
819
				linphone_address_set_username(uri,username);
820
				return _linphone_core_destroy_addr_if_not_sip(uri);
821
			}
822 823 824
		} else {
			return NULL;
		}
825 826 827 828 829 830 831 832 833
	}
	uri=linphone_address_new(username);
	if (uri!=NULL){
		return _linphone_core_destroy_addr_if_not_sip(uri);
	}

	return NULL;
}

834 835 836 837 838 839 840
void linphone_proxy_config_set_etag(LinphoneProxyConfig *cfg,const char* sip_etag) {
	if (cfg->sip_etag) ms_free(cfg->sip_etag);
	if (sip_etag)
		cfg->sip_etag = ms_strdup(sip_etag);
	else
		cfg->sip_etag = NULL;
}
smorlat's avatar
smorlat committed
841 842 843
/**
 * Commits modification made to the proxy configuration.
**/
844
LinphoneStatus linphone_proxy_config_done(LinphoneProxyConfig *cfg)
smorlat's avatar
smorlat committed
845
{
846 847
	LinphoneProxyConfigAddressComparisonResult res;

848
	if (!linphone_proxy_config_check(cfg->lc,cfg))
849 850
		return -1;

851
	/*check if server address has changed*/
852
	res = linphone_proxy_config_is_server_config_changed(cfg);
853
	if (res != LinphoneProxyConfigAddressEqual) {
854
		/* server config has changed, need to unregister from previous first*/
855
		if (cfg->op) {
856
			if (res == LinphoneProxyConfigAddressDifferent) {
857
				_linphone_proxy_config_unregister(cfg);
858
			}
859
			cfg->op->setUserPointer(NULL); /*we don't want to receive status for this un register*/
860
			cfg->op->unref(); /*but we keep refresher to handle authentication if needed*/
861
			cfg->op=NULL;
862
		}
863
		if (cfg->presence_publish_event) {
864 865 866 867
			if (res == LinphoneProxyConfigAddressDifferent) {
				_linphone_proxy_config_unpublish(cfg);
			}
		}
868
		cfg->commit = TRUE;
869
	}
870

871
	if (cfg->register_changed){
872
		cfg->commit = TRUE;
873 874 875 876
		cfg->register_changed = FALSE;
	}
	if (cfg->commit){
		linphone_proxy_config_pause_register(cfg);
877
	}
878

879 880
	if (linphone_proxy_config_compute_publish_params_hash(cfg)) {
		ms_message("Publish params have changed on proxy config [%p]",cfg);
881
		if (cfg->presence_publish_event) {
882
			if (cfg->publish) {
883
				linphone_proxy_config_set_etag(cfg, linphone_event_get_custom_header(cfg->presence_publish_event, "SIP-ETag"));
884
			}
885
			/*publish is terminated*/
886
			linphone_event_terminate(cfg->presence_publish_event);
887 888 889 890
		}
		if (cfg->publish) cfg->send_publish=TRUE;
	} else {
		ms_message("Publish params have not changed on proxy config [%p]",cfg);
891
	}
892

893
	linphone_proxy_config_write_all_to_config_file(cfg->lc);
aymeric's avatar
aymeric committed
894 895 896
	return 0;
}

897 898 899 900
const char* linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg)
{
	return cfg?cfg->realm:NULL;
}
aymeric's avatar
aymeric committed
901 902 903 904 905
void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm)
{
	if (cfg->realm!=NULL) {
		ms_free(cfg->realm);
	}
906
	cfg->realm=ms_strdup(realm);
aymeric's avatar
aymeric committed
907 908
}

909
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){
910
	int err=0;
911 912
	LinphoneAddress *presentity_address = NULL;
	char* contact = NULL;
913

914
	if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){
915 916
		LinphoneContent *content;
		char *presence_body;
917
		if (proxy->presence_publish_event==NULL){
918
			proxy->presence_publish_event = linphone_proxy_config_create_publish(proxy
919 920
										 , "presence"
										 , linphone_proxy_config_get_publish_expires(proxy));
921
			linphone_event_ref(proxy->presence_publish_event);
922
		}
923
		proxy->presence_publish_event->internal = TRUE;
924

925 926 927 928
		if (linphone_presence_model_get_presentity(presence) == NULL) {
			ms_message("No presentity set for model [%p], using identity from proxy config [%p]", presence, proxy);
			linphone_presence_model_set_presentity(presence,linphone_proxy_config_get_identity_address(proxy));
		}
929

930 931 932 933 934 935 936 937
		if (!linphone_address_equal(linphone_presence_model_get_presentity(presence), linphone_proxy_config_get_identity_address(proxy))) {
			ms_message("Presentity for model [%p] differ proxy config [%p], using proxy", presence, proxy);
			presentity_address = linphone_address_clone(linphone_presence_model_get_presentity(presence)); /*saved, just in case*/
			if (linphone_presence_model_get_contact(presence)) {
				contact = bctbx_strdup(linphone_presence_model_get_contact(presence));
			}
			linphone_presence_model_set_presentity(presence,linphone_proxy_config_get_identity_address(proxy));
			linphone_presence_model_set_contact(presence,NULL); /*it will be automatically computed*/
938

939
		}
940
		if (!(presence_body = linphone_presence_model_to_xml(presence))) {
941
			ms_error("Cannot publish presence model [%p] for proxy config [%p] because of xml serialization error",presence,proxy);
942
			return -1;
943
		}
944

945
		content = linphone_content_new();
946
		linphone_content_set_buffer(content, (const uint8_t *)presence_body,strlen(presence_body));
947 948
		linphone_content_set_type(content, "application");
		linphone_content_set_subtype(content,"pidf+xml");
949
		if (proxy->sip_etag) {
950
			linphone_event_add_custom_header(proxy->presence_publish_event, "SIP-If-Match", proxy->sip_etag);
951 952 953
			ms_free(proxy->sip_etag);
			proxy->sip_etag=NULL;
		}
954
		err = linphone_event_send_publish(proxy->presence_publish_event, content);
955
		linphone_content_unref(content);
Ghislain MARY's avatar
Ghislain MARY committed
956
		ms_free(presence_body);
957 958 959 960 961 962 963 964
		if (presentity_address) {
			linphone_presence_model_set_presentity(presence,presentity_address);
			linphone_address_unref(presentity_address);
		}
		if (contact) {
			linphone_presence_model_set_contact(presence,contact);
			bctbx_free(contact);
		}
965

966
	}else proxy->send_publish=TRUE; /*otherwise do not send publish if registration is in progress, this will be done later*/
967
	return err;
aymeric's avatar
aymeric committed
968 969
}

970
void _linphone_proxy_config_unpublish(LinphoneProxyConfig *obj) {
971 972 973 974
	if (obj->presence_publish_event
		&& (linphone_event_get_publish_state(obj->presence_publish_event) == LinphonePublishOk ||
					(linphone_event_get_publish_state(obj->presence_publish_event)  == LinphonePublishProgress && obj->publish_expires != 0))) {
		linphone_event_unpublish(obj->presence_publish_event);
975
	}
976 977 978 979
	if (obj->sip_etag) {
		ms_free(obj->sip_etag);
		obj->sip_etag=NULL;
	}
980 981
}

982 983 984 985 986 987 988
const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *cfg) {
	if (cfg->reg_routes) return (const char *)bctbx_list_get_data(cfg->reg_routes);
	return NULL;
}

const bctbx_list_t* linphone_proxy_config_get_routes(const LinphoneProxyConfig *cfg) {
	return cfg->reg_routes;
989 990
}

991 992
const LinphoneAddress *linphone_proxy_config_get_identity_address(const LinphoneProxyConfig *cfg){
	return cfg->identity_address;
993 994
}

995 996
const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *cfg){
	return cfg->reg_identity;
997 998
}

999 1000
bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *cfg){
	return cfg->publish;
1001 1002
}

1003 1004
const char *linphone_proxy_config_get_server_addr(const LinphoneProxyConfig *cfg){
	return cfg->reg_proxy;
1005 1006 1007
}

/**
1008
 * @return the duration of registration.
1009
**/
1010 1011
int linphone_proxy_config_get_expires(const LinphoneProxyConfig *cfg){
	return cfg->expires;
1012 1013
}

1014 1015 1016 1017 1018 1019 1020 1021
bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *cfg){
	return cfg->reg_sendregister;
}

void linphone_proxy_config_set_contact_parameters(LinphoneProxyConfig *cfg, const char *contact_params){
	if (cfg->contact_params) {
		ms_free(cfg->contact_params);
		cfg->contact_params=NULL;
1022 1023
	}
	if (contact_params){
1024
		cfg->contact_params=ms_strdup(contact_params);
1025
	}
1026
	cfg->register_changed = TRUE;
1027 1028
}

1029 1030 1031 1032
void linphone_proxy_config_set_contact_uri_parameters(LinphoneProxyConfig *cfg, const char *contact_uri_params){
	if (cfg->contact_uri_params) {
		ms_free(cfg->contact_uri_params);
		cfg->contact_uri_params=NULL;
1033 1034
	}
	if (contact_uri_params){
1035
		cfg->contact_uri_params=ms_strdup(contact_uri_params);
1036
	}
1037
	cfg->register_changed = TRUE;
1038 1039
}

1040 1041
const char *linphone_proxy_config_get_contact_parameters(const LinphoneProxyConfig *cfg){
	return cfg->contact_params;
1042 1043
}

1044 1045
const char *linphone_proxy_config_get_contact_uri_parameters(const LinphoneProxyConfig *cfg){
	return cfg->contact_uri_params;
1046 1047
}

Matthieu Tanon's avatar
Matthieu Tanon committed
1048