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
	cfg->push_notification_allowed = lc ? !!lp_config_get_default_int(lc->config, "proxy", "push_notification_allowed", TRUE) : TRUE;
148
	cfg->refkey = refkey ? ms_strdup(refkey) : NULL;
149 150 151 152 153 154 155 156 157
	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);
		}
	}
158
	linphone_proxy_config_set_conference_factory_uri(cfg, conference_factory_uri ? ms_strdup(conference_factory_uri) : NULL);
aymeric's avatar
aymeric committed
159 160
}

161 162 163
LinphoneProxyConfig *linphone_proxy_config_new() {
	return linphone_core_create_proxy_config(NULL);
}
164

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
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];
190
	bctbx_list_t *routes_iterator = cfg->reg_routes;
191 192
	previous_hash[0] = cfg->previous_publish_config_hash[0];
	previous_hash[1] = cfg->previous_publish_config_hash[1];
193

194 195 196
	source = ms_strcat_printf(source, "%i",cfg->privacy);
	source=append_linphone_address(cfg->identity_address, source);
	source=append_string(cfg->reg_proxy,source);
197 198 199 200 201
	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);
	}
202 203 204 205 206 207 208 209 210 211 212 213
	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];
}
214
static void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg);
215 216 217 218 219 220 221 222 223 224

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
);

225
LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) {
226 227 228
	LinphoneProxyConfig *cfg = belle_sip_object_new(LinphoneProxyConfig);
	linphone_proxy_config_init(lc,cfg);
	return cfg;
229 230
}

231 232
void _linphone_proxy_config_release_ops(LinphoneProxyConfig *cfg){
	if (cfg->op) {
233
		cfg->op->release();
234 235
		cfg->op=NULL;
	}
236 237 238 239
	if (cfg->presence_publish_event){
		linphone_event_terminate(cfg->presence_publish_event);
		linphone_event_unref(cfg->presence_publish_event);
		cfg->presence_publish_event=NULL;
240 241 242 243
	}
}

void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){
244 245 246 247 248 249 250 251 252
	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);
253 254
	if (cfg->contact_params) ms_free(cfg->contact_params);
	if (cfg->contact_uri_params) ms_free(cfg->contact_uri_params);
255 256 257
	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);
258
	if (cfg->pending_contact) linphone_address_unref(cfg->pending_contact);
259
	if (cfg->refkey) ms_free(cfg->refkey);
Ghislain MARY's avatar
Ghislain MARY committed
260 261 262
	if (cfg->nat_policy != NULL) {
		linphone_nat_policy_unref(cfg->nat_policy);
	}
263 264
	if (cfg->conference_factory_uri)
		bctbx_free(cfg->conference_factory_uri);
265 266 267
	if (cfg->ei){
		linphone_error_info_unref(cfg->ei);
	}
Ronan's avatar
Ronan committed
268

269
	if (cfg->service_route) linphone_address_unref(cfg->service_route);
Ronan's avatar
Ronan committed
270
	if (cfg->contact_address) linphone_address_unref(cfg->contact_address);
Ghislain MARY's avatar
Ghislain MARY committed
271 272
	if (cfg->contact_address_without_params)
		linphone_address_unref(cfg->contact_address_without_params);
Ronan's avatar
Ronan committed
273

274
	_linphone_proxy_config_release_ops(cfg);
275 276 277 278 279 280
}

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

281 282 283 284 285
void _linphone_proxy_config_release(LinphoneProxyConfig *cfg) {
	_linphone_proxy_config_release_ops(cfg);
	belle_sip_object_unref(cfg);
}

286 287 288 289 290 291 292
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
293 294
}

295 296
bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *cfg){
	return cfg->state == LinphoneRegistrationOk;
smorlat's avatar
smorlat committed
297 298
}

299
LinphoneStatus linphone_proxy_config_set_server_addr(LinphoneProxyConfig *cfg, const char *server_addr){
300 301
	LinphoneAddress *addr=NULL;
	char *modified=NULL;
302

303 304
	if (cfg->reg_proxy!=NULL) ms_free(cfg->reg_proxy);
	cfg->reg_proxy=NULL;
305

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

325

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

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

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

359
LinphoneStatus linphone_proxy_config_set_route(LinphoneProxyConfig *cfg, const char *route)
aymeric's avatar
aymeric committed
360
{
361
	if (cfg->reg_routes != NULL) {
362
		bctbx_list_free_with_data(cfg->reg_routes, ms_free);
363
		cfg->reg_routes = NULL;
aymeric's avatar
aymeric committed
364
	}
365
	if (route!=NULL && route[0] !='\0'){
366 367
		SalAddress *addr;
		char *tmp;
368
		/*try to prepend 'sip:' */
369
		if (strstr(route,"sip:")==NULL && strstr(route,"sips:")==NULL){
370 371 372 373
			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
374
			sal_address_unref(addr);
375
			cfg->reg_routes = bctbx_list_append(cfg->reg_routes, tmp);
376
			return 0;
377 378
		}else{
			ms_free(tmp);
379
			return -1;
380
		}
381 382
	} else {
		return 0;
383
	}
aymeric's avatar
aymeric committed
384 385
}

386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
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
405
				sal_address_unref(addr);
406 407 408 409 410 411 412 413 414 415 416
				cfg->reg_routes = bctbx_list_append(cfg->reg_routes, tmp);
			} else {
				ms_free(tmp);
				return -1;
			}
		}
		iterator = bctbx_list_next(iterator);
	}
	return 0;
}

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

425
void linphone_proxy_config_enableregister(LinphoneProxyConfig *cfg, bool_t val){
426
	if (val != cfg->reg_sendregister) cfg->register_changed = TRUE;
427
	cfg->reg_sendregister=val;
aymeric's avatar
aymeric committed
428 429
}

430
void linphone_proxy_config_set_expires(LinphoneProxyConfig *cfg, int val){
431
	if (val<0) val=600;
432
	if (val != cfg->expires) cfg->register_changed = TRUE;
433
	cfg->expires=val;
aymeric's avatar
aymeric committed
434 435
}

436 437
void linphone_proxy_config_enable_publish(LinphoneProxyConfig *cfg, bool_t val){
	cfg->publish=val;
aymeric's avatar
aymeric committed
438
}
439

440
void linphone_proxy_config_pause_register(LinphoneProxyConfig *cfg){
441
	if (cfg->op) cfg->op->stopRefreshing();
442 443
}

444
void linphone_proxy_config_edit(LinphoneProxyConfig *cfg){
445
	/*store current config related to server location*/
446
	linphone_proxy_config_store_server_config(cfg);
447
	linphone_proxy_config_compute_publish_params_hash(cfg);
448

449 450
	if (cfg->publish && cfg->presence_publish_event){
		linphone_event_pause_publish(cfg->presence_publish_event);
451
	}
452
	/*Don't stop refresher*/
aymeric's avatar
aymeric committed
453 454
}

455 456 457
void linphone_proxy_config_apply(LinphoneProxyConfig *cfg,LinphoneCore *lc){
	cfg->lc=lc;
	linphone_proxy_config_done(cfg);
aymeric's avatar
aymeric committed
458
}
Simon Morlat's avatar
Simon Morlat committed
459

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

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

484
	if (cfg->op){
485
		cfg->op->release();
486
		cfg->op=NULL;
487 488 489
	}
}

490 491
static LinphoneAddress *guess_contact_for_register (LinphoneProxyConfig *cfg) {
	LinphoneAddress *result = nullptr;
492 493
	LinphoneAddress *proxy = linphone_address_new(cfg->reg_proxy);
	if (!proxy)
494
		return nullptr;
495 496
	const char *host = linphone_address_get_domain(proxy);
	if (host) {
497
		result = linphone_address_clone(cfg->identity_address);
498
		if (cfg->contact_params) {
499
			// We want to add a list of contacts params to the linphone address
500
			linphone_address_set_params(result, cfg->contact_params);
501
		}
502
		if (cfg->contact_uri_params)
503
			linphone_address_set_uri_params(result, cfg->contact_uri_params);
504
	}
Simon Morlat's avatar
Simon Morlat committed
505
	linphone_address_unref(proxy);
506
	return result;
507
}
508

509 510 511
void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj) {
	if (obj->op && (obj->state == LinphoneRegistrationOk ||
					(obj->state == LinphoneRegistrationProgress && obj->expires != 0))) {
512
		obj->op->unregister();
513 514
	}
}
515

516 517 518
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
519
		char* proxy_string;
520 521
		char * from = linphone_address_as_string(cfg->identity_address);
		ms_message("LinphoneProxyConfig [%p] about to register (LinphoneCore version: %s)",cfg,linphone_core_get_version());
522
		proxy_string=linphone_address_as_string_uri_only(proxy);
Simon Morlat's avatar
Simon Morlat committed
523
		linphone_address_unref(proxy);
524
		if (cfg->op)
525 526
			cfg->op->release();
		cfg->op=new SalRegisterOp(cfg->lc->sal);
527

528
		linphone_configure_op(cfg->lc, cfg->op, cfg->identity_address, cfg->sent_headers, FALSE);
529

530 531 532 533 534 535 536 537
		LinphoneAddress *contactAddress = guess_contact_for_register(cfg);
		if (contactAddress) {
			cfg->op->setContactAddress(L_GET_PRIVATE_FROM_C_OBJECT(contactAddress)->getInternalAddress());
			if (!cfg->contact_address) {
				cfg->contact_address = linphone_address_clone(contactAddress);
			}
			linphone_address_unref(contactAddress);
		}
538
		cfg->op->setUserPointer(cfg);
539

540
		if (cfg->op->sendRegister(
541 542 543
			proxy_string,
			cfg->reg_identity,
			cfg->expires,
544
			cfg->pending_contact ? L_GET_PRIVATE_FROM_C_OBJECT(cfg->pending_contact)->getInternalAddress() : NULL
545
		)==0) {
546 547 548 549
			if (cfg->pending_contact) {
				linphone_address_unref(cfg->pending_contact);
				cfg->pending_contact=NULL;
			}
550
			linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress,"Registration in progress");
551
		} else {
552
			linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,"Registration failed");
553
		}
554
		ms_free(proxy_string);
555
		ms_free(from);
556
	} else {
557
		/* unregister if registered*/
558 559
		if (cfg->state == LinphoneRegistrationProgress) {
			linphone_proxy_config_set_state(cfg,LinphoneRegistrationCleared,"Registration cleared");
560
		}
561
		_linphone_proxy_config_unregister(cfg);
aymeric's avatar
aymeric committed
562
	}
smorlat's avatar
smorlat committed
563 564
}

565 566
void linphone_proxy_config_refresh_register(LinphoneProxyConfig *cfg){
	if (cfg->reg_sendregister && cfg->op && cfg->state!=LinphoneRegistrationProgress){
567
		if (cfg->op->refreshRegister(cfg->expires) == 0) {
568
			linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress, "Refresh registration");
569
		}
570 571 572
	}
}

573 574 575 576 577 578

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;
	}
579
	if (prefix && prefix[0]!='\0') cfg->dial_prefix=ms_strdup(prefix);
580 581 582 583 584 585 586 587 588 589 590 591 592
}

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;
}
593

594 595
void linphone_proxy_config_enable_quality_reporting(LinphoneProxyConfig *cfg, bool_t val){
	cfg->quality_reporting_enabled = val;
596 597
}

598
bool_t linphone_proxy_config_quality_reporting_enabled(LinphoneProxyConfig *cfg){
599
	return cfg->quality_reporting_enabled;
600 601
}

602
void linphone_proxy_config_set_quality_reporting_interval(LinphoneProxyConfig *cfg, int interval) {
603
	cfg->quality_reporting_interval = interval;
604 605 606 607 608 609
}

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

610
void linphone_proxy_config_set_quality_reporting_collector(LinphoneProxyConfig *cfg, const char *collector){
611 612
	if (collector!=NULL && strlen(collector)>0){
		LinphoneAddress *addr=linphone_address_new(collector);
613
		if (!addr){
614
			ms_error("Invalid SIP collector URI: %s. Quality reporting will be DISABLED.",collector);
615
		} else {
616
			if (cfg->quality_reporting_collector != NULL){
617
				ms_free(cfg->quality_reporting_collector);
618
			}
619
			cfg->quality_reporting_collector = ms_strdup(collector);
620 621 622
		}

		if (addr){
Simon Morlat's avatar
Simon Morlat committed
623
			linphone_address_unref(addr);
624 625 626 627
		}
	}
}

628 629
const char *linphone_proxy_config_get_quality_reporting_collector(const LinphoneProxyConfig *cfg){
	return cfg->quality_reporting_collector;
630 631 632
}


633
bool_t linphone_proxy_config_is_phone_number(LinphoneProxyConfig *proxy, const char *username){
634
	const char *p;
635
	if (!username) return FALSE;
636
	for(p=username;*p!='\0';++p){
637
		if (isdigit(*p) ||
638 639 640 641
			*p==' ' ||
			*p=='.' ||
			*p=='-' ||
			*p==')' ||
642 643
			*p=='(' ||
			*p=='/' ||
644
			*p=='+' ||
645 646
			(unsigned char)*p==0xca || (unsigned char)*p==0xc2 || (unsigned char)*p==0xa0 // non-breakable space (iOS uses it to format contacts phone number)
			) {
647
			continue;
648
		}
649
		return FALSE;
650 651 652 653
	}
	return TRUE;
}

654
//remove anything but [0-9] and +
655
static char *flatten_number(const char *number){
656
	char *result=reinterpret_cast<char *>(ms_malloc0(strlen(number)+1));
657 658 659
	char *w=result;
	const char *r;
	for(r=number;*r!='\0';++r){
660
		if (*r=='+' || isdigit(*r)){
661 662 663 664 665 666 667
			*w++=*r;
		}
	}
	*w++='\0';
	return result;
}

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

672
static char* replace_icp_with_plus(char *phone, const char *icp){
673 674
	return (strstr(phone, icp) == phone) ?  ms_strdup_printf("+%s", phone+strlen(icp)) : ms_strdup(phone);
}
675

676
bool_t linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len){
677 678
	char * normalized_phone = linphone_proxy_config_normalize_phone_number(proxy, username);
	const char * output = normalized_phone ? normalized_phone : username;
679
	memset(result, 0, result_len);
680 681 682
	memcpy(result, output, MIN(strlen(output) + 1, result_len));
	ms_free(normalized_phone);
	return output != username;
683 684
}

685 686 687
char* linphone_proxy_config_normalize_phone_number(LinphoneProxyConfig *proxy, const char *username) {
	LinphoneProxyConfig *tmpproxy = proxy ? proxy : linphone_proxy_config_new();
	char* result = NULL;
688
	DialPlan dialplan;
689 690
	char * nationnal_significant_number = NULL;
	int ccc = -1;
691

692 693
	if (linphone_proxy_config_is_phone_number(tmpproxy, username)){
		char * flatten=flatten_number(username);
694
		ms_debug("Flattened number is '%s' for '%s'",flatten, username);
695

696
		ccc = DialPlan::lookupCccFromE164(flatten);
697
		if (ccc>-1) { /*e164 like phone number*/
698
			dialplan = DialPlan::findByCcc(ccc);
699
			nationnal_significant_number = strstr(flatten, dialplan.getCountryCallingCode().c_str());
700
			if (nationnal_significant_number) {
701
				nationnal_significant_number +=strlen(dialplan.getCountryCallingCode().c_str());
702 703 704 705 706
			}
		} else if (flatten[0] =='+') {
			ms_message ("Unknown ccc for e164 like number [%s]", flatten);
			goto end;
		} else {
707 708 709 710 711
			if (tmpproxy->dial_prefix) {
				dialplan = DialPlan::findByCcc(tmpproxy->dial_prefix); //copy dial plan;
			} else {
				dialplan = DialPlan::MostCommon;
			}
712
			if (tmpproxy->dial_prefix){
713
				if (strcmp(tmpproxy->dial_prefix,dialplan.getCountryCallingCode().c_str()) != 0){
714
					//probably generic dialplan, preserving proxy dial prefix
715 716
					dialplan.setCountryCallingCode(tmpproxy->dial_prefix);
				}
717

718
				/*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)*/
719 720 721
				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);
722 723 724
					ms_free(e164);
					goto end;
				}
725 726
			}
			nationnal_significant_number=flatten;
727
		}
728
		ms_debug("Using dial plan '%s'",dialplan.getCountry().c_str());
729

730
		/*if proxy has a dial prefix, modify phonenumber accordingly*/
731
		if (dialplan.getCountryCallingCode().c_str()[0]!='\0') {
732
			/* the number already starts with + or international prefix*/
733 734 735
			/*0. keep at most national number significant digits */
			char* nationnal_significant_number_start = nationnal_significant_number
														+ MAX(0, (int)strlen(nationnal_significant_number)
736 737
														- (int)dialplan.getNationalNumberLength());
			ms_debug("Prefix not present. Keeping at most %d digits: %s", dialplan.getNationalNumberLength(), nationnal_significant_number_start);
738 739 740 741 742

			/*1. First prepend international calling prefix or +*/
			/*2. Second add prefix*/
			/*3. Finally add user digits */
			result = ms_strdup_printf("%s%s%s"
743 744
										, tmpproxy->dial_escape_plus ? dialplan.getInternationalCallPrefix().c_str() : "+"
										, dialplan.getCountryCallingCode().c_str()
745 746
										, nationnal_significant_number_start);
			ms_debug("Prepended prefix resulted in %s", result);
747
		}
748 749

	end:
750 751 752 753 754 755
		if (result==NULL) {
			result = flatten;
		} else {
			ms_free(flatten);
		}
	}
756
	if (proxy==NULL) linphone_proxy_config_unref(tmpproxy);
757 758 759 760 761 762 763
	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
764
		linphone_address_unref(addr);
765 766 767 768 769 770 771 772 773 774
		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;

775
	if (!username || *username=='\0') return NULL;
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800

	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);
			}
		}

801
		if (proxy!=NULL && linphone_proxy_config_get_identity_address(proxy)!=NULL){
802
			/* append the proxy domain suffix but remove any custom parameters/headers */
803
			LinphoneAddress *uri=linphone_address_clone(linphone_proxy_config_get_identity_address(proxy));
804 805
			if (uri==NULL){
				return NULL;
806
			} else {
807
				linphone_address_clean(uri);
808
				linphone_address_set_display_name(uri,NULL);
809
				linphone_address_set_username(uri,username);
810
				return _linphone_core_destroy_addr_if_not_sip(uri);
811
			}
812 813 814
		} else {
			return NULL;
		}
815 816 817 818 819 820 821 822 823
	}
	uri=linphone_address_new(username);
	if (uri!=NULL){
		return _linphone_core_destroy_addr_if_not_sip(uri);
	}

	return NULL;
}

824 825 826 827 828 829 830
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
831 832 833
/**
 * Commits modification made to the proxy configuration.
**/
834
LinphoneStatus linphone_proxy_config_done(LinphoneProxyConfig *cfg)
smorlat's avatar
smorlat committed
835
{
836 837
	LinphoneProxyConfigAddressComparisonResult res;

838
	if (!linphone_proxy_config_check(cfg->lc,cfg))
839 840
		return -1;

841
	/*check if server address has changed*/
842
	res = linphone_proxy_config_is_server_config_changed(cfg);
843
	if (res != LinphoneProxyConfigAddressEqual) {
844
		/* server config has changed, need to unregister from previous first*/
845
		if (cfg->op) {
846
			if (res == LinphoneProxyConfigAddressDifferent) {
847
				_linphone_proxy_config_unregister(cfg);
848
			}
849
			cfg->op->setUserPointer(NULL); /*we don't want to receive status for this un register*/
850
			cfg->op->unref(); /*but we keep refresher to handle authentication if needed*/
851
			cfg->op=NULL;
852
		}
853
		if (cfg->presence_publish_event) {
854 855 856 857
			if (res == LinphoneProxyConfigAddressDifferent) {
				_linphone_proxy_config_unpublish(cfg);
			}
		}
858
		cfg->commit = TRUE;
859
	}
860

861
	if (cfg->register_changed){
862
		cfg->commit = TRUE;
863 864 865 866
		cfg->register_changed = FALSE;
	}
	if (cfg->commit){
		linphone_proxy_config_pause_register(cfg);
867
	}
868

869 870
	if (linphone_proxy_config_compute_publish_params_hash(cfg)) {
		ms_message("Publish params have changed on proxy config [%p]",cfg);
871
		if (cfg->presence_publish_event) {
872
			if (cfg->publish) {
873
				linphone_proxy_config_set_etag(cfg, linphone_event_get_custom_header(cfg->presence_publish_event, "SIP-ETag"));
874
			}
875
			/*publish is terminated*/
876
			linphone_event_terminate(cfg->presence_publish_event);
877 878 879 880
		}
		if (cfg->publish) cfg->send_publish=TRUE;
	} else {
		ms_message("Publish params have not changed on proxy config [%p]",cfg);
881
	}
882

883
	linphone_proxy_config_write_all_to_config_file(cfg->lc);
aymeric's avatar
aymeric committed
884 885 886
	return 0;
}

887 888 889 890
const char* linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg)
{
	return cfg?cfg->realm:NULL;
}
aymeric's avatar
aymeric committed
891 892 893 894 895
void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm)
{
	if (cfg->realm!=NULL) {
		ms_free(cfg->realm);
	}
896
	cfg->realm=ms_strdup(realm);
aymeric's avatar
aymeric committed
897 898
}

899
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){
900
	int err=0;
901 902
	LinphoneAddress *presentity_address = NULL;
	char* contact = NULL;
903

904
	if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){
905 906
		LinphoneContent *content;
		char *presence_body;
907
		if (proxy->presence_publish_event==NULL){
908
			proxy->presence_publish_event = linphone_proxy_config_create_publish(proxy
909 910
										 , "presence"
										 , linphone_proxy_config_get_publish_expires(proxy));
911
			linphone_event_ref(proxy->presence_publish_event);
912
		}
913
		proxy->presence_publish_event->internal = TRUE;
914

915 916 917 918
		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));
		}
919

920 921 922 923 924 925 926 927
		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*/
928

929
		}
930
		if (!(presence_body = linphone_presence_model_to_xml(presence))) {
931
			ms_error("Cannot publish presence model [%p] for proxy config [%p] because of xml serialization error",presence,proxy);
932
			return -1;
933
		}
934

935
		content = linphone_content_new();
936
		linphone_content_set_buffer(content, (const uint8_t *)presence_body,strlen(presence_body));
937 938
		linphone_content_set_type(content, "application");
		linphone_content_set_subtype(content,"pidf+xml");
939
		if (proxy->sip_etag) {
940
			linphone_event_add_custom_header(proxy->presence_publish_event, "SIP-If-Match", proxy->sip_etag);
941 942 943
			ms_free(proxy->sip_etag);
			proxy->sip_etag=NULL;
		}
944
		err = linphone_event_send_publish(proxy->presence_publish_event, content);
945
		linphone_content_unref(content);
Ghislain MARY's avatar
Ghislain MARY committed
946
		ms_free(presence_body);
947 948 949 950 951 952 953 954
		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);
		}
955

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

960
void _linphone_proxy_config_unpublish(LinphoneProxyConfig *obj) {
961 962 963 964
	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);
965
	}
966 967 968 969
	if (obj->sip_etag) {
		ms_free(obj->sip_etag);
		obj->sip_etag=NULL;
	}
970 971
}

972 973 974 975 976 977 978
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;
979 980
}

981 982
const LinphoneAddress *linphone_proxy_config_get_identity_address(const LinphoneProxyConfig *cfg){
	return cfg->identity_address;
983 984
}

985 986
const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *cfg){
	return cfg->reg_identity;
987 988
}

989 990
bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *cfg){
	return cfg->publish;
991 992
}

993 994
const char *linphone_proxy_config_get_server_addr(const LinphoneProxyConfig *cfg){
	return cfg->reg_proxy;
995 996 997
}

/**
998
 * @return the duration of registration.
999
**/
1000 1001
int linphone_proxy_config_get_expires(const LinphoneProxyConfig *cfg){
	return cfg->expires;
1002 1003
}

1004 1005 1006 1007 1008 1009 1010 1011
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;
1012 1013
	}
	if (contact_params){
1014
		cfg->contact_params=ms_strdup(contact_params);
1015
	}
1016
	cfg->register_changed = TRUE;
1017 1018
}

1019 1020 1021 1022
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;
1023 1024
	}
	if (contact_uri_params){
1025
		cfg->contact_uri_params=ms_strdup(contact_uri_params);
1026
	}
1027
	cfg->register_changed = TRUE;
1028 1029
}

1030 1031
const char *linphone_proxy_config_get_contact_parameters(const LinphoneProxyConfig *cfg){
	return cfg->contact_params;
1032 1033
}

1034 1035
const char *linphone_proxy_config_get_contact_uri_parameters(const LinphoneProxyConfig *cfg){
	return cfg->contact_uri_params;
1036 1037
}

1038 1039
struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *cfg){
	return cfg->lc;
1040
}
smorlat's avatar
smorlat committed
1041

1042 1043 1044
const char *linphone_proxy_config_get_custom_header(LinphoneProxyConfig *cfg, const char *header_name){
	const SalCustomHeader *ch;
	if (!cfg->op) return NULL;
1045
	ch = cfg->op->getRecvCustomHeaders();
1046 1047 1048 1049 1050