proxy.c 50.3 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
20
21
/*
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.
 */
 
#include "linphonecore.h"
smorlat's avatar
smorlat committed
22
#include "sipsetup.h"
aymeric's avatar
aymeric committed
23
24
#include "lpconfig.h"
#include "private.h"
25
#include "mediastreamer2/mediastream.h"
aymeric's avatar
aymeric committed
26

27
28
29
#include <ctype.h>


smorlat's avatar
smorlat committed
30
31
32
void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
	MSList *elem;
	int i;
33
34
	if (!linphone_core_ready(lc)) return;
	
smorlat's avatar
smorlat committed
35
36
37
38
	for(elem=lc->sip_conf.proxies,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
		LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
		linphone_proxy_config_write_to_config_file(lc->config,cfg,i);
	}
39
40
41
	/*to ensure removed configs are erased:*/
	linphone_proxy_config_write_to_config_file(lc->config,NULL,i);
	lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
smorlat's avatar
smorlat committed
42
}
aymeric's avatar
aymeric committed
43

jehan's avatar
jehan committed
44
static void linphone_proxy_config_init(LinphoneCore* lc,LinphoneProxyConfig *obj){
aymeric's avatar
aymeric committed
45
	memset(obj,0,sizeof(LinphoneProxyConfig));
46
	obj->magic=linphone_proxy_config_magic;
47
48
49
	obj->expires=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"reg_expires",3600);
	obj->dial_prefix=ms_strdup(LP_CONFIG_DEFAULT_STRING((lc?lc->config:NULL),"dial_prefix",'\0'));
	obj->dial_escape_plus=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"dial_escape_plus",0);
jehan's avatar
jehan committed
50
	obj->privacy=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"privacy",LinphonePrivacyDefault);
aymeric's avatar
aymeric committed
51
52
}

smorlat's avatar
smorlat committed
53
54
55
56
57
58
/**
 * @addtogroup proxies
 * @{
**/

/**
jehan's avatar
jehan committed
59
60
 * @deprecated, use #linphone_core_create_proxy_config instead
 *Creates an empty proxy config.
smorlat's avatar
smorlat committed
61
**/
jehan's avatar
jehan committed
62
63
64
65
LinphoneProxyConfig *linphone_proxy_config_new() {
	return linphone_core_create_proxy_config(NULL);
}
LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) {
aymeric's avatar
aymeric committed
66
67
	LinphoneProxyConfig *obj=NULL;
	obj=ms_new(LinphoneProxyConfig,1);
jehan's avatar
jehan committed
68
	linphone_proxy_config_init(lc,obj);
aymeric's avatar
aymeric committed
69
70
71
	return obj;
}

jehan's avatar
jehan committed
72
73


smorlat's avatar
smorlat committed
74
75
76
77
78
79
/**
 * Destroys a proxy config.
 * 
 * @note: LinphoneProxyConfig that have been removed from LinphoneCore with
 * linphone_core_remove_proxy_config() must not be freed.
**/
aymeric's avatar
aymeric committed
80
81
82
83
void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
	if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
	if (obj->reg_identity!=NULL) ms_free(obj->reg_identity);
	if (obj->reg_route!=NULL) ms_free(obj->reg_route);
smorlat's avatar
smorlat committed
84
	if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx);
smorlat's avatar
smorlat committed
85
	if (obj->realm!=NULL) ms_free(obj->realm);
smorlat's avatar
smorlat committed
86
	if (obj->type!=NULL) ms_free(obj->type);
87
	if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix);
88
	if (obj->op) sal_op_release(obj->op);
Simon Morlat's avatar
Simon Morlat committed
89
	if (obj->publish_op) sal_op_release(obj->publish_op);
90
	if (obj->contact_params) ms_free(obj->contact_params);
Simon Morlat's avatar
Simon Morlat committed
91
	ms_free(obj);
aymeric's avatar
aymeric committed
92
93
}

smorlat's avatar
smorlat committed
94
95
/**
 * Returns a boolean indicating that the user is sucessfully registered on the proxy.
96
 * @deprecated Use linphone_proxy_config_get_state() instead.
smorlat's avatar
smorlat committed
97
**/
smorlat's avatar
smorlat committed
98
bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *obj){
99
	return obj->state == LinphoneRegistrationOk;
smorlat's avatar
smorlat committed
100
101
}

smorlat's avatar
smorlat committed
102
103
104
105
106
107
108
109
/**
 * Sets the proxy address
 *
 * Examples of valid sip proxy address are:
 * - IP address: sip:87.98.157.38
 * - IP address with port: sip:87.98.157.38:5062
 * - hostnames : sip:sip.example.net
**/
aymeric's avatar
aymeric committed
110
int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr){
111
112
	LinphoneAddress *addr=NULL;
	char *modified=NULL;
113
	
aymeric's avatar
aymeric committed
114
115
	if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
	obj->reg_proxy=NULL;
116
	
aymeric's avatar
aymeric committed
117
	if (server_addr!=NULL && strlen(server_addr)>0){
118
		if (strstr(server_addr,"sip:")==NULL && strstr(server_addr,"sips:")==NULL){
119
120
121
			modified=ms_strdup_printf("sip:%s",server_addr);
			addr=linphone_address_new(modified);
			ms_free(modified);
122
		}
123
124
		if (addr==NULL)
			addr=linphone_address_new(server_addr);
125
		if (addr){
126
			obj->reg_proxy=linphone_address_as_string(addr);
127
			linphone_address_destroy(addr);
aymeric's avatar
aymeric committed
128
129
		}else{
			ms_warning("Could not parse %s",server_addr);
130
			return -1;
aymeric's avatar
aymeric committed
131
132
133
134
135
		}
	}
	return 0;
}

smorlat's avatar
smorlat committed
136
137
138
139
140
141
142
143
144
/**
 * Sets the user identity as a SIP address.
 *
 * This identity is normally formed with display name, username and domain, such 
 * as:
 * Alice <sip:alice@example.net>
 * The REGISTER messages will have from and to set to this identity.
 *
**/
145
146
int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity){
	LinphoneAddress *addr;
aymeric's avatar
aymeric committed
147
	if (identity!=NULL && strlen(identity)>0){
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
		addr=linphone_address_new(identity);
		if (!addr || linphone_address_get_username(addr)==NULL){
			ms_warning("Invalid sip identity: %s",identity);
			if (addr)
				linphone_address_destroy(addr);
			return -1;
		}else{
			if (obj->reg_identity!=NULL) {
				ms_free(obj->reg_identity);
				obj->reg_identity=NULL;
			}
			obj->reg_identity=ms_strdup(identity);
			if (obj->realm){
				ms_free(obj->realm);
			}
			obj->realm=ms_strdup(linphone_address_get_domain(addr));
			linphone_address_destroy(addr);
			return 0;
aymeric's avatar
aymeric committed
166
167
		}
	}
168
	return -1;
smorlat's avatar
smorlat committed
169
170
171
172
}

const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
	return cfg->realm;
aymeric's avatar
aymeric committed
173
174
}

smorlat's avatar
smorlat committed
175
176
177
178
179
/**
 * Sets a SIP route.
 * When a route is set, all outgoing calls will go to the route's destination if this proxy
 * is the default one (see linphone_core_set_default_proxy() ).
**/
180
int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route)
aymeric's avatar
aymeric committed
181
{
182
183
	if (obj->reg_route!=NULL){
		ms_free(obj->reg_route);
aymeric's avatar
aymeric committed
184
185
		obj->reg_route=NULL;
	}
186
	if (route!=NULL && route[0] !='\0'){
187
188
		SalAddress *addr;
		char *tmp;
Simon Morlat's avatar
Simon Morlat committed
189
		/*try to prepend 'sip:' */
190
		if (strstr(route,"sip:")==NULL && strstr(route,"sips:")==NULL){
191
192
193
194
195
196
197
198
199
200
			tmp=ms_strdup_printf("sip:%s",route);
		}else tmp=ms_strdup(route);
		addr=sal_address_new(tmp);
		if (addr!=NULL){
			sal_address_destroy(addr);
		}else{
			ms_free(tmp);
			tmp=NULL;
		}
		obj->reg_route=tmp;
Simon Morlat's avatar
Simon Morlat committed
201
	}
202
	return 0;
aymeric's avatar
aymeric committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
}

bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *obj){
	if (obj->reg_proxy==NULL){
		if (lc->vtable.display_warning)
			lc->vtable.display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\""
						" followed by a hostname."));
		return FALSE;
	}
	if (obj->reg_identity==NULL){
		if (lc->vtable.display_warning)
			lc->vtable.display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like "
					"sip:username@proxydomain, such as sip:alice@example.net"));
		return FALSE;
	}
	return TRUE;
}

smorlat's avatar
smorlat committed
221
222
223
/**
 * Indicates whether a REGISTER request must be sent to the proxy.
**/
aymeric's avatar
aymeric committed
224
225
226
227
void linphone_proxy_config_enableregister(LinphoneProxyConfig *obj, bool_t val){
	obj->reg_sendregister=val;
}

smorlat's avatar
smorlat committed
228
229
230
/**
 * Sets the registration expiration time in seconds.
**/
231
void linphone_proxy_config_set_expires(LinphoneProxyConfig *obj, int val){
232
	if (val<0) val=600;
aymeric's avatar
aymeric committed
233
234
235
236
237
238
	obj->expires=val;
}

void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
	obj->publish=val;
}
smorlat's avatar
smorlat committed
239
240
241
242
243
244
245
246
247
/**
 * Starts editing a proxy configuration.
 *
 * Because proxy configuration must be consistent, applications MUST
 * call linphone_proxy_config_edit() before doing any attempts to modify
 * proxy configuration (such as identity, proxy address and so on).
 * Once the modifications are done, then the application must call
 * linphone_proxy_config_done() to commit the changes.
**/
aymeric's avatar
aymeric committed
248
void linphone_proxy_config_edit(LinphoneProxyConfig *obj){
Simon Morlat's avatar
Simon Morlat committed
249
250
251
252
253
254
	if (obj->publish && obj->publish_op){
		/*unpublish*/
		sal_publish_presence(obj->publish_op,NULL,NULL,0,(SalPresenceModel *)NULL);
		sal_op_release(obj->publish_op);
		obj->publish_op=NULL;
	}
aymeric's avatar
aymeric committed
255
256
	if (obj->reg_sendregister){
		/* unregister */
257
258
		if (obj->state == LinphoneRegistrationOk
				|| obj->state == LinphoneRegistrationProgress) {
259
			sal_unregister(obj->op);
aymeric's avatar
aymeric committed
260
261
262
263
		}
	}
}

Simon Morlat's avatar
Simon Morlat committed
264
void linphone_proxy_config_apply(LinphoneProxyConfig *obj,LinphoneCore *lc){
aymeric's avatar
aymeric committed
265
266
267
	obj->lc=lc;
	linphone_proxy_config_done(obj);
}
Simon Morlat's avatar
Simon Morlat committed
268

269
270
271
272
273
274
275
276
277
278
279
void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig *obj){
	if (obj->publish_op){
		sal_op_release(obj->publish_op);
		obj->publish_op=NULL;
	}
	if (obj->op){
		sal_op_release(obj->op);
		obj->op=NULL;
	}
}

280
281
282
283
LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *obj){
	LinphoneAddress *ret=NULL;
	LinphoneAddress *proxy=linphone_address_new(obj->reg_proxy);

284
285
286
287
	const char *host;
	if (proxy==NULL) return NULL;
	host=linphone_address_get_domain (proxy);
	if (host!=NULL){
288
289
		int localport = -1;
		const char *localip = NULL;
290
		char *tmp;
291
292
		char *tmp2;
		LinphoneAddress *identity;
Ghislain MARY's avatar
Ghislain MARY committed
293
		LinphoneAddress *contact;
294

295
296
297
298
299
300
301
302
303
304
305
306
307
308
		if (obj->contact_params) {
			// We want to add a list of contacts params to the linphone address
			// We remove the display name in the identity (if present) to prevent a failure in the parsing of the address due to the quotes
			identity = linphone_address_new(obj->reg_identity);
			if (identity) {
				tmp2 = linphone_address_as_string_uri_only(identity);
				tmp = ms_strdup_printf("%s;%s", tmp2, obj->contact_params);
				linphone_address_destroy(identity);
				ms_free(tmp2);
			} else {
				tmp = ms_strdup_printf("%s;%s", obj->reg_identity, obj->contact_params);
			}
		}
		else {
309
			tmp = strdup(obj->reg_identity);
310
		}
311
		
Ghislain MARY's avatar
Ghislain MARY committed
312
		contact = linphone_address_new(tmp);
313
		if (!contact) {
jehan's avatar
jehan committed
314
			ms_error("No valid contact_params for [%s]",linphone_address_get_domain(proxy));
315
316
317
			return NULL;
		}

318
319
320
#ifdef BUILD_UPNP
		if (obj->lc->upnp != NULL && linphone_core_get_firewall_policy(obj->lc)==LinphonePolicyUseUpnp &&
			linphone_upnp_context_get_state(obj->lc->upnp) == LinphoneUpnpStateOk) {
321
			LCSipTransports tr;
322
323
			localip = linphone_upnp_context_get_external_ipaddress(obj->lc->upnp);
			localport = linphone_upnp_context_get_external_port(obj->lc->upnp);
324
325
326
327
328
329
330
331
332
			linphone_core_get_sip_transports(obj->lc,&tr);
			if (tr.udp_port <= 0) {
				if (tr.tcp_port>0) {
					sal_address_set_param(contact,"transport","tcp");
				} else if (tr.tls_port>0) {
					sal_address_set_param(contact,"transport","tls");
				}
			}

333
		}
334
#endif //BUILD_UPNP
335

jehan's avatar
jehan committed
336

337
		linphone_address_set_port(contact,localport);
338
339
340
341
		linphone_address_set_domain(contact,localip);
		linphone_address_set_display_name(contact,NULL);

		ret=contact;
Simon Morlat's avatar
Simon Morlat committed
342

343
		linphone_address_destroy (proxy);
344
		ms_free(tmp);
345
346
347
	}
	return ret;
}
348
349


smorlat's avatar
smorlat committed
350
static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
aymeric's avatar
aymeric committed
351
	if (obj->reg_sendregister){
Simon Morlat's avatar
Simon Morlat committed
352
353
		LinphoneAddress* proxy=linphone_address_new(obj->reg_proxy);
		char* proxy_string;
354
#ifndef USE_BELLESIP
355
		char *contact;
356
357
358
#else
		LinphoneAddress *contact;
#endif
jehan's avatar
jehan committed
359
360
		proxy_string=linphone_address_as_string_uri_only(proxy);
		linphone_address_destroy(proxy);
361
362
363
		if (obj->op)
			sal_op_release(obj->op);
		obj->op=sal_op_new(obj->lc->sal);
jehan's avatar
jehan committed
364
365
		if ((contact=guess_contact_for_register(obj))) {
			sal_op_set_contact(obj->op,contact);
366
#ifndef USE_BELLESIP
jehan's avatar
jehan committed
367
			ms_free(contact);
368
#else
Simon Morlat's avatar
Simon Morlat committed
369
			linphone_address_destroy(contact);
370
#endif
jehan's avatar
jehan committed
371
		}
Simon Morlat's avatar
Simon Morlat committed
372
		sal_op_set_user_pointer(obj->op,obj);
jehan's avatar
jehan committed
373
		if (sal_register(obj->op,proxy_string,obj->reg_identity,obj->expires)==0) {
374
			linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress");
375
		} else {
376
			linphone_proxy_config_set_state(obj,LinphoneRegistrationFailed,"Registration failed");
377
		}
jehan's avatar
jehan committed
378
		ms_free(proxy_string);
aymeric's avatar
aymeric committed
379
	}
smorlat's avatar
smorlat committed
380
381
}

382
383
384
385
386
387
/**
 * Refresh a proxy registration.
 * This is useful if for example you resuming from suspend, thus IP address may have changed.
**/
void linphone_proxy_config_refresh_register(LinphoneProxyConfig *obj){
	if (obj->reg_sendregister && obj->op){
388
389
390
		if (sal_register_refresh(obj->op,obj->expires) == 0) {
			linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress, "Refresh registration");
		}
391
392
393
	}
}

394
395
396

/**
 * Sets a dialing prefix to be automatically prepended when inviting a number with 
397
398
 * linphone_core_invite();
 * This dialing prefix shall usually be the country code of the country where the user is living.
399
400
401
402
403
404
405
 *
**/
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;
	}
406
	if (prefix && prefix[0]!='\0') cfg->dial_prefix=ms_strdup(prefix);
407
408
409
410
411
412
413
414
415
416
417
418
}

/**
 * Returns dialing prefix.
 *
 * 
**/
const char *linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg){
	return cfg->dial_prefix;
}

/**
419
 * Sets whether liblinphone should replace "+" by international calling prefix in dialed numbers (passed to
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
 * #linphone_core_invite ).
 *
**/
void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val){
	cfg->dial_escape_plus=val;
}

/**
 * Returns whether liblinphone should replace "+" by "00" in dialed numbers (passed to
 * #linphone_core_invite ).
 *
**/
bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg){
	return cfg->dial_escape_plus;
}
435
436
437
438
439
440
/*
 * http://en.wikipedia.org/wiki/Telephone_numbering_plan
 * http://en.wikipedia.org/wiki/Telephone_numbers_in_Europe
 */
typedef struct dial_plan{
	const char *country;
441
	const char* iso_country_code; /* ISO 3166-1 alpha-2 code, ex: FR for France*/
442
443
444
	char  ccc[8]; /*country calling code*/
	int nnl; /*maximum national number length*/
	const char * icp; /*international call prefix, ex: 00 in europe*/
445
	
446
447
448
}dial_plan_t;

/* TODO: fill with information for all countries over the world*/
449

450
static dial_plan_t const dial_plans[]={
jehan's avatar
jehan committed
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
	{"Afghanistan"                  ,"AF"		, "93"      , 9		, "00"  },
	{"Albania"                      ,"AL"		, "355"     , 9		, "00"  },
	{"Algeria"                      ,"DZ"		, "213"     , 9		, "00"  },
	{"American Samoa"               ,"AS"		, "1"       , 10	, "011"	},
	{"Andorra"                      ,"AD"		, "376"     , 6		, "00"  },
	{"Angola"                       ,"AO"		, "244"     , 9		, "00"  },
	{"Anguilla"                     ,"AI"		, "1"       , 10	, "011" },
	{"Antigua and Barbuda"          ,"AG"		, "1"       , 10	, "011"	},
	{"Argentina"                    ,"AR"		, "54"      , 10	, "00"  },
	{"Armenia"                      ,"AM"		, "374"     , 8		, "00"  },
	{"Aruba"                        ,"AW"		, "297"     , 7		, "011"	},
	{"Australia"                    ,"AU"		, "61"      , 9	    , "0011"},
	{"Austria"                      ,"AT"		, "43"      , 10	, "00"  },
	{"Azerbaijan"                   ,"AZ"       , "994"     , 9		, "00"  },
	{"Bahamas"                      ,"BS"		, "1"       , 10    , "011"	},
	{"Bahrain"                      ,"BH"		, "973"     , 8     , "00"  },
	{"Bangladesh"                   ,"BD"		, "880"     , 10    , "00"  },
	{"Barbados"                     ,"BB"		, "1"       , 10    , "011"	},
469
	{"Belarus"                      ,"BY"		, "375"     , 9     , "00"  },
jehan's avatar
jehan committed
470
471
472
473
474
475
476
477
	{"Belgium"                      ,"BE"		, "32"      , 9     , "00"  },
	{"Belize"                       ,"BZ"		, "501"     , 7     , "00"  },
	{"Benin"                        ,"BJ"		, "229"     , 8     , "00"	},
	{"Bermuda"                      ,"BM"		, "1"       , 10    , "011" },
	{"Bhutan"                       ,"BT"		, "975"     , 8     , "00"  },
	{"Bolivia"                      ,"BO"		, "591"     , 8     , "00"	},
	{"Bosnia and Herzegovina"       ,"BA"		, "387"     , 8     , "00"  },
	{"Botswana"                     ,"BW"		, "267"     , 8     , "00"  },
478
	{"Brazil"                       ,"BR"		, "55"      , 10	, "00"  },
jehan's avatar
jehan committed
479
480
481
482
	{"Brunei Darussalam"            ,"BN"		, "673"     , 7		, "00"	},
	{"Bulgaria"                     ,"BG"		, "359"     , 9		, "00"  },
	{"Burkina Faso"                 ,"BF"		, "226"     , 8		, "00"  },
	{"Burundi"                      ,"BI"		, "257"     , 8     , "011" },
483
	{"Cambodia"                     ,"KH"		, "855"     , 9		, "00"  },
jehan's avatar
jehan committed
484
485
486
487
488
489
490
491
	{"Cameroon"                     ,"CM"		, "237"     , 8		, "00"  },
	{"Canada"                       ,"CA"		, "1"       , 10	, "011" },
	{"Cape Verde"                   ,"CV"		, "238"     , 7		, "00"	},
	{"Cayman Islands"               ,"KY"		, "1"       , 10	, "011" },
	{"Central African Republic"     ,"CF"		, "236"     , 8     , "00"  },
	{"Chad"                         ,"TD"		, "235"     , 8		, "00"	},
	{"Chile"                        ,"CL"		, "56"      , 9	    , "00"  },
	{"China"                        ,"CN"		, "86"      , 11	, "00"  },
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
	{"Colombia"                     ,"CO"       , "57"      , 10	, "00"  },
	{"Comoros"                      ,"KM"		, "269"     , 7     , "00"	},
	{"Congo"                        ,"CG"		, "242"     , 9		, "00"	},
	{"Congo Democratic Republic"	,"CD"		, "243"     , 9		, "00"  },
	{"Cook Islands"                 ,"CK"		, "682"     , 5		, "00"  },
	{"Costa Rica"                   ,"CR"		, "506"     , 8     , "00"	},
	{"C�te d'Ivoire"	            ,"AD"		, "225"     , 8     , "00"  },
	{"Croatia"                      ,"HR"		, "385"     , 9		, "00"  },
	{"Cuba"                         ,"CU"		, "53"      , 8     , "119" },
	{"Cyprus"                       ,"CY"		, "357"     , 8     , "00"	},
	{"Czech Republic"               ,"CZ"		, "420"     , 9     , "00"  },
	{"Denmark"                      ,"DK"		, "45"      , 8		, "00"  },
	{"Djibouti"                     ,"DJ"		, "253"     , 8		, "00"	},
	{"Dominica"                     ,"DM"		, "1"       , 10	, "011" },
	{"Dominican Republic"	        ,"DO"		, "1"       , 10	, "011" },
	{"Ecuador"                      ,"EC"       , "593"     , 9		, "00"  },
	{"Egypt"                        ,"EG"		, "20"      , 10	, "00"	},
	{"El Salvador"                  ,"SV"		, "503"     , 8		, "00"	},
	{"Equatorial Guinea"            ,"GQ"		, "240"     , 9		, "00"  },
	{"Eritrea"                      ,"ER"		, "291"     , 7		, "00"  },
	{"Estonia"                      ,"EE"		, "372"     , 8     , "00"	},
	{"Ethiopia"                     ,"ET"		, "251"     , 9     , "00"  },
	{"Falkland Islands"	            ,"FK"		, "500"     , 5		, "00"  },
	{"Faroe Islands"	            ,"FO"		, "298"     , 6     , "00"  },
	{"Fiji"                         ,"FJ"		, "679"     , 7     , "00"	},
	{"Finland"                      ,"FI"		, "358"     , 9     , "00"  },
	{"France"                       ,"FR"		, "33"      , 9		, "00"	},
	{"French Guiana"				,"GF"		, "594"     , 9		, "00"	},
	{"French Polynesia"             ,"PF"		, "689"     , 6	    , "00"  },
	{"Gabon"                        ,"GA"		, "241"     , 8     , "00"  },
	{"Gambia"                       ,"GM"       , "220"     , 7		, "00"  },
	{"Georgia"                      ,"GE"		, "995"     , 9     , "00"	},
	{"Germany"                      ,"DE"		, "49"      , 11	, "00"	},
	{"Ghana"                        ,"GH"		, "233"     , 9		, "00"  },
	{"Gibraltar"                    ,"GI"		, "350"     , 8		, "00"  },
	{"Greece"                       ,"GR"		, "30"      ,10     , "00"	},
	{"Greenland"                    ,"GL"		, "299"     , 6		, "00"  },
	{"Grenada"                      ,"GD"		, "1"       , 10	, "011" },
	{"Guadeloupe"                   ,"GP"		, "590"     , 9     , "00"  },
	{"Guam"                         ,"GU"		, "1"       , 10	, "011"	},
	{"Guatemala"                    ,"GT"		, "502"     , 8     , "00"  },
	{"Guinea"                       ,"GN"		, "224"     , 8		, "00"  },
	{"Guinea-Bissau"				,"GW"		, "245"     , 7		, "00"	},
	{"Guyana"                       ,"GY"		, "592"     , 7	    , "001" },
	{"Haiti"                        ,"HT"		, "509"     , 8     , "00"  },
	{"Honduras"                     ,"HN"       , "504"     , 8		, "00"  },
	{"Hong Kong"                    ,"HK"		, "852"     , 8     , "001"	},
	{"Hungary"                      ,"HU"		, "36"      , 9     , "00"  },
	{"Iceland"                      ,"IS"		, "354"     , 9     , "00"  },
	{"India"                        ,"IN"		, "91"      , 10    , "00"  },
	{"Indonesia"                    ,"ID"		, "62"      , 10	, "001"	},
	{"Iran"                         ,"IR"		, "98"      , 10	, "00"	},
	{"Iraq"                         ,"IQ"		, "964"     , 10	, "00"  },
	{"Ireland"                      ,"IE"		, "353"     , 9		, "00"  },
	{"Israel"                       ,"IL"		, "972"     , 9     , "00"	},
	{"Italy"                        ,"IT"		, "39"      , 10	, "00"  },
	{"Jamaica"                      ,"JM"		, "1"       , 10	, "011" },
	{"Japan"                        ,"JP"		, "81"      , 10	, "010" },
	{"Jordan"                       ,"JO"		, "962"     , 9     , "00"	},
	{"Kazakhstan"                   ,"KZ"		, "7"       , 10    , "00"  },
	{"Kenya"                        ,"KE"		, "254"     , 9		, "000" },
	{"Kiribati"                     ,"KI"		, "686"     , 5		, "00"	},
	{"Korea, North"                 ,"KP"		, "850"     , 12	, "99"  },
	{"Korea, South"                 ,"KR"       , "82"      , 12	, "001" },
	{"Kuwait"                       ,"KW"		, "965"     , 8     , "00"	},
	{"Kyrgyzstan"                   ,"KG"		, "996"     , 9     , "00"  },
	{"Laos"                         ,"LA"		, "856"     , 10    , "00"  },
	{"Latvia"                       ,"LV"		, "371"     , 8     , "00"	},
	{"Lebanon"                      ,"LB"		, "961"     , 7     , "00"	},
	{"Lesotho"                      ,"LS"		, "266"     , 8		, "00"	},
	{"Liberia"                      ,"LR"		, "231"     , 8		, "00"  },
	{"Libya"                        ,"LY"		, "218"     , 8		, "00"  },
	{"Liechtenstein"                ,"LI"		, "423"     , 7     , "00"	},
	{"Lithuania"                    ,"LT"		, "370"     , 8		, "00"  },
	{"Luxembourg"                   ,"LU"		, "352"     , 9		, "00"  },
	{"Macau"                        ,"MO"		, "853"     , 8     , "00"  },
	{"Macedonia"                    ,"MK"		, "389"     , 8     , "00"	},
	{"Madagascar"                   ,"MG"		, "261"     , 9     , "00"  },
	{"Malawi"                       ,"MW"		, "265"     , 9		, "00"  },
	{"Malaysia"                     ,"MY"		, "60"      , 9		, "00"	},
	{"Maldives"                     ,"MV"		, "960"     , 7	    , "00"  },
	{"Mali"                         ,"ML"		, "223"     , 8     , "00"  },
	{"Malta"                        ,"MT"       , "356"     , 8		, "00"  },
	{"Marshall Islands"				,"MH"		, "692"     , 7     , "011"	},
	{"Martinique"                   ,"MQ"		, "596"     , 9     , "00"  },
	{"Mauritania"                   ,"MR"		, "222"     , 8     , "00"  },
	{"Mauritius"                    ,"MU"		, "230"     , 7     , "00"	},
	{"Mayotte Island"               ,"YT"		, "262"     , 9     , "00"	},
	{"Mexico"                       ,"MX"		, "52"      , 10	, "00"	},
	{"Micronesia"                   ,"FM"		, "691"     , 7		, "011" },
	{"Moldova"                      ,"MD"		, "373"     , 8		, "00"  },
	{"Monaco"                       ,"MC"		, "377"     , 8     , "00"	},
	{"Mongolia"                     ,"MN"		, "976"     , 8     , "001" },
	{"Montenegro"                   ,"ME"		, "382"     , 8		, "00"  },
	{"Montserrat"                   ,"MS"		, "664"     , 10	, "011" },
	{"Morocco"                      ,"MA"		, "212"     , 9     , "00"	},
	{"Mozambique"                   ,"MZ"		, "258"     , 9     , "00"  },
	{"Myanmar"                      ,"MM"		, "95"      , 8		, "00"  },
	{"Namibia"                      ,"NA"		, "264"     , 9		, "00"	},
	{"Nauru"                        ,"NR"		, "674"     , 7	    , "00"  },
	{"Nepal"                        ,"NP"		, "43"      , 10	, "00"  },
	{"Netherlands"                  ,"NL"       , "31"      , 9		, "00"  },
	{"New Caledonia"				,"NC"		, "687"     , 6     , "00"	},
	{"New Zealand"                  ,"NZ"		, "64"      , 10	, "00"  },
	{"Nicaragua"                    ,"NI"		, "505"     , 8     , "00"  },
	{"Niger"                        ,"NE"		, "227"     , 8     , "00"	},
	{"Nigeria"                      ,"NG"		, "234"     , 10	, "009"	},
	{"Niue"                         ,"NU"		, "683"     , 4		, "00"	},
	{"Norfolk Island"	            ,"NF"		, "672"     , 5		, "00"  },
	{"Northern Mariana Islands"	    ,"MP"		, "1"       , 10	, "011" },
	{"Norway"                       ,"NO"		, "47"      , 8     , "00"	},
	{"Oman"                         ,"OM"		, "968"     , 8		, "00"  },
	{"Pakistan"                     ,"PK"		, "92"      , 10	, "00"  },
	{"Palau"                        ,"PW"		, "680"     , 7     , "011" },
	{"Palestine"                    ,"PS"		, "970"     , 9     , "00"	},
	{"Panama"                       ,"PA"		, "507"     , 8     , "00"  },
	{"Papua New Guinea"	            ,"PG"		, "675"     , 8		, "00"  },
	{"Paraguay"                     ,"PY"		, "595"     , 9		, "00"	},
	{"Peru"                         ,"PE"		, "51"      , 9	    , "00"  },
	{"Philippines"                  ,"PH"		, "63"      , 10	, "00"  },
	{"Poland"                       ,"PL"       , "48"      , 9		, "00"  },
	{"Portugal"                     ,"PT"		, "351"     , 9     , "00"	},
	{"Puerto Rico"                  ,"PR"		, "1"       , 10	, "011" },
	{"Qatar"                        ,"QA"		, "974"     , 8     , "00"  },
	{"R�union Island"				,"RE"		, "262"     , 9     , "011"	},
	{"Romania"                      ,"RO"		, "40"      , 9     , "00"	},
	{"Russian Federation"           ,"RU"		, "7"       , 10	, "8"	},
	{"Rwanda"                       ,"RW"		, "250"     , 9		, "00"  },
	{"Saint Helena"                 ,"SH"		, "290"     , 4		, "00"  },
	{"Saint Kitts and Nevis"		,"KN"		, "1"       , 10	, "011"	},
	{"Saint Lucia"                  ,"LC"		, "1"       , 10	, "011" },
	{"Saint Pierre and Miquelon"    ,"PM"		, "508"     , 6		, "00"  },
	{"Saint Vincent and the Grenadines","VC"	, "1"       , 10	, "011" },
	{"Samoa"                        ,"WS"		, "685"     , 7     , "0"	},
	{"San Marino"                   ,"SM"		, "378"     , 10	, "00"  },
	{"S�o Tom� and Pr�ncipe"        ,"ST"		, "239"     , 7		, "00"  },
	{"Saudi Arabia"                 ,"SA"		, "966"     , 9		, "00"	},
	{"Senegal"                      ,"SN"		, "221"     , 9	    , "00"  },
	{"Serbia"                       ,"RS"		, "381"     , 9     , "00"  },
	{"Seychelles"                   ,"SC"       , "248"     , 7		, "00"  },
	{"Sierra Leone"                 ,"SL"		, "232"     , 8     , "00"	},
	{"Singapore"                    ,"SG"		, "65"      , 8     , "001" },
	{"Slovakia"                     ,"SK"		, "421"     , 9     , "00"  },
	{"Slovenia"                     ,"SI"		, "386"     , 8     , "00"	},
	{"Solomon Islands"              ,"SB"		, "677"     , 7     , "00"	},
	{"Somalia"                      ,"SO"		, "252"     , 8		, "00"	},
	{"South Africa"                 ,"ZA"		, "27"      , 9		, "00"  },
	{"Spain"                        ,"ES"		, "34"      , 9		, "00"  },
	{"Sri Lanka"                    ,"LK"		, "94"      , 9     , "00"	},
	{"Sudan"                        ,"SD"		, "249"     , 9		, "00"  },
	{"Suriname"                     ,"SR"		, "597"     , 7		, "00"  },
	{"Swaziland"                    ,"SZ"		, "268"     , 8     , "00"  },
	{"Sweden"                       ,"SE"		, "1"       , 9     , "00"	},
	{"Switzerland"                  ,"XK"		, "41"      , 9		, "00"	},
	{"Syria"                        ,"SY"		, "963"     , 9		, "00"  },
	{"Taiwan"                       ,"TW"		, "886"     , 9		, "810"	},
	{"Tajikistan"                   ,"TJ"		, "992"     , 9	    , "002" },
	{"Tanzania"                     ,"TZ"		, "255"     , 9     , "000" },
	{"Thailand"                     ,"TH"       , "66"      , 9		, "001" },
	{"Togo"                         ,"TG"		, "228"     , 8     , "00"	},
	{"Tokelau"                      ,"TK"		, "690"     , 4     , "00"  },
	{"Tonga"                        ,"TO"		, "676"     , 5     , "00"  },
	{"Trinidad and Tobago"			,"TT"		, "1"       , 10    , "011"	},
	{"Tunisia"                      ,"TN"		, "216"     , 8     , "00"	},
	{"Turkey"                       ,"TR"		, "90"      , 10	, "00"	},
	{"Turkmenistan"                 ,"TM"		, "993"     , 8		, "00"  },
	{"Turks and Caicos Islands"	    ,"TC"		, "1"       , 7		, "0"   },
	{"Tuvalu"                       ,"TV"		, "688"     , 5     , "00"	},
	{"Uganda"                       ,"UG"		, "256"     , 9     , "000" },
	{"Ukraine"                      ,"UA"		, "380"     , 9		, "00"  },
	{"United Arab Emirates"	        ,"AE"		, "971"     , 9     , "00"  },
	{"United Kingdom"               ,"UK"		, "44"      , 10	, "00"	},
	{"United States"                ,"US"		, "1"       , 10	, "011" },
	{"Uruguay"                      ,"UY"		, "598"     , 8		, "00"  },
	{"Uzbekistan"                   ,"UZ"		, "998"     , 9		, "8"	},
	{"Vanuatu"                      ,"VU"		, "678"     , 7	    , "00"  },
	{"Venezuela"                    ,"VE"		, "58"      , 10	, "00"  },
	{"Vietnam"                      ,"VN"		, "84"      , 9     , "00"  },
	{"Wallis and Futuna"	        ,"WF"		, "681"     , 5		, "00"  },
	{"Yemen"                        ,"YE"		, "967"     , 9     , "00"  },
	{"Zambia"                       ,"ZM"		, "260"     , 9     , "00"	},
	{"Zimbabwe"                     ,"ZW"		, "263"     , 9     , "00"  },
jehan's avatar
jehan committed
674
	{NULL                           ,NULL       ,  ""       , 0     , NULL	}
675
};
676
677
static dial_plan_t most_common_dialplan={ "generic" ,"", "", 10, "00"};

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
int linphone_dial_plan_lookup_ccc_from_e164(const char* e164) {
	dial_plan_t* dial_plan;
	dial_plan_t* elected_dial_plan=NULL;
	unsigned int found;
	unsigned int i=0;
	if (e164[1]=='1') {
		/*USA case*/
		return 1;
	}
	do {
		found=0;
		i++;
		for (dial_plan=(dial_plan_t*)dial_plans; dial_plan->country!=NULL; dial_plan++) {
			if (strncmp(dial_plan->ccc,&e164[1],i) == 0) {
				elected_dial_plan=dial_plan;
				found++;
			}
		}
696
	} while ((found>1 || found==0) && i < sizeof(dial_plan->ccc));
697
698
699
700
701
702
703
	if (found==1) {
		return atoi(elected_dial_plan->ccc);
	} else {
		return -1; /*not found */
	}

}
704
705
706
707
708
709
710
711
712
int linphone_dial_plan_lookup_ccc_from_iso(const char* iso) {
	dial_plan_t* dial_plan;
	for (dial_plan=(dial_plan_t*)dial_plans; dial_plan->country!=NULL; dial_plan++) {
		if (strcmp(iso, dial_plan->iso_country_code)==0) {
			return atoi(dial_plan->ccc);
		}
	}
	return -1;
}
713
714
715
716
717
718
719
720
721
722
723
724
725

static void lookup_dial_plan(const char *ccc, dial_plan_t *plan){
	int i;
	for(i=0;dial_plans[i].country!=NULL;++i){
		if (strcmp(ccc,dial_plans[i].ccc)==0){
			*plan=dial_plans[i];
			return;
		}
	}
	/*else return a generic "most common" dial plan*/
	*plan=most_common_dialplan;
	strcpy(plan->ccc,ccc);
}
726
727
728
729
730
731

static bool_t is_a_phone_number(const char *username){
	const char *p;
	for(p=username;*p!='\0';++p){
		if (isdigit(*p) || 
		    *p==' ' ||
732
		    *p=='.' ||
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
		    *p=='-' ||
		    *p==')' ||
			*p=='(' ||
			*p=='/' ||
			*p=='+') continue;
		else return FALSE;
	}
	return TRUE;
}

static char *flatten_number(const char *number){
	char *result=ms_malloc0(strlen(number)+1);
	char *w=result;
	const char *r;
	for(r=number;*r!='\0';++r){
		if (*r=='+' || isdigit(*r)){
			*w++=*r;
		}
	}
	*w++='\0';
	return result;
}

756
static void replace_plus(const char *src, char *dest, size_t destlen, const char *icp){
757
758
	int i=0;
	
759
	if (icp && src[0]=='+' && (destlen>(i=strlen(icp))) ){
760
		src++;
761
		strcpy(dest,icp);
762
763
	}
	
Simon Morlat's avatar
Simon Morlat committed
764
	for(;(i<destlen-1) && *src!='\0';++i){
765
766
767
768
769
770
771
772
773
774
		dest[i]=*src;
		src++;
	}
	dest[i]='\0';
}


int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len){
	int numlen;
	if (is_a_phone_number(username)){
775
		char *flatten;
776
777
		flatten=flatten_number(username);
		ms_message("Flattened number is '%s'",flatten);
778
779
780
781
		
		if (proxy->dial_prefix==NULL || proxy->dial_prefix[0]=='\0'){
			/*no prefix configured, nothing else to do*/
			strncpy(result,flatten,result_len);
782
783
			ms_free(flatten);
			return 0;
784
785
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
811
812
813
814
815
816
817
		}else{
			dial_plan_t dialplan;
			lookup_dial_plan(proxy->dial_prefix,&dialplan);
			ms_message("Using dialplan '%s'",dialplan.country);
			if (flatten[0]=='+' || strstr(flatten,dialplan.icp)==flatten){
				/* the number has international prefix or +, so nothing to do*/
				ms_message("Prefix already present.");
				/*eventually replace the plus*/
				replace_plus(flatten,result,result_len,proxy->dial_escape_plus ? dialplan.icp : NULL);
				ms_free(flatten);
				return 0;
			}else{
				int i=0;
				int skip;
				numlen=strlen(flatten);
				/*keep at most national number significant digits */
				skip=numlen-dialplan.nnl;
				if (skip<0) skip=0;
				/*first prepend internation calling prefix or +*/
				if (proxy->dial_escape_plus){
					strncpy(result,dialplan.icp,result_len);
					i+=strlen(dialplan.icp);
				}else{
					strncpy(result,"+",result_len);
					i+=1;
				}
				/*add prefix*/
				if (result_len-i>strlen(dialplan.ccc)){
					strcpy(result+i,dialplan.ccc);
					i+=strlen(dialplan.ccc);
				}
				/*add user digits */
				strncpy(result+i,flatten+skip,result_len-i-1);
				ms_free(flatten);
818
819
820
821
822
823
			}
		}
	}else strncpy(result,username,result_len);
	return 0;
}

smorlat's avatar
smorlat committed
824
825
826
/**
 * Commits modification made to the proxy configuration.
**/
smorlat's avatar
smorlat committed
827
828
829
int linphone_proxy_config_done(LinphoneProxyConfig *obj)
{
	if (!linphone_proxy_config_check(obj->lc,obj)) return -1;
smorlat's avatar
smorlat committed
830
	obj->commit=TRUE;
smorlat's avatar
smorlat committed
831
	linphone_proxy_config_write_all_to_config_file(obj->lc);
aymeric's avatar
aymeric committed
832
833
834
835
836
837
838
839
840
841
842
843
	return 0;
}

void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm)
{
	if (cfg->realm!=NULL) {
		ms_free(cfg->realm);
		cfg->realm=NULL;
	}
	if (realm!=NULL) cfg->realm=ms_strdup(realm);
}

844
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){
845
	int err=0;
Simon Morlat's avatar
Simon Morlat committed
846
	
847
848
849
850
851
852
853
	if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){
		if (proxy->publish_op==NULL){
			proxy->publish_op=sal_op_new(proxy->lc->sal);
			sal_op_set_route(proxy->publish_op,proxy->reg_proxy);
			sal_op_set_from(proxy->publish_op,linphone_proxy_config_get_identity(proxy));
			sal_op_set_to(proxy->publish_op,linphone_proxy_config_get_identity(proxy));
			if (lp_config_get_int(proxy->lc->config,"sip","publish_msg_with_contact",0)){
854
				SalAddress *addr=sal_address_new(linphone_proxy_config_get_identity(proxy));
855
856
857
858
859
860
				sal_op_set_contact(proxy->publish_op,addr);
				sal_address_unref(addr);
			}
		}
		err=sal_publish_presence(proxy->publish_op,NULL,NULL,proxy->expires,(SalPresenceModel *)presence);
	}else proxy->send_publish=TRUE; /*otherwise do not send publish if registration is in progress, this will be done later*/
861
	return err;
aymeric's avatar
aymeric committed
862
863
}

864
865
866
867
868
869
870
871
872
873
/**
 * Returns the route set for this proxy configuration.
**/
const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj){
	return obj->reg_route;
}

/**
 * Returns the SIP identity that belongs to this proxy configuration.
 *
874
 * The SIP identity is a SIP address (Display Name <sip:username@@domain> )
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
**/
const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj){
	return obj->reg_identity;
}

/**
 * Returns TRUE if PUBLISH request is enabled for this proxy.
**/
bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj){
	return obj->publish;
}

/**
 * Returns the proxy's SIP address.
**/
const char *linphone_proxy_config_get_addr(const LinphoneProxyConfig *obj){
	return obj->reg_proxy;
}

/**
 * Returns the duration of registration.
**/
int linphone_proxy_config_get_expires(const LinphoneProxyConfig *obj){
	return obj->expires;
}

/**
 * Returns TRUE if registration to the proxy is enabled.
**/
bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *obj){
	return obj->reg_sendregister;
}

908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
/**
 * Set optional contact parameters that will be added to the contact information sent in the registration.
 * @param obj the proxy config object
 * @param contact_params a string contaning the additional parameters in text form, like "myparam=something;myparam2=something_else"
 *
 * The main use case for this function is provide the proxy additional information regarding the user agent, like for example unique identifier or apple push id.
 * As an example, the contact address in the SIP register sent will look like <sip:joe@15.128.128.93:50421;apple-push-id=43143-DFE23F-2323-FA2232>.
**/
void linphone_proxy_config_set_contact_parameters(LinphoneProxyConfig *obj, const char *contact_params){
	if (obj->contact_params) {
		ms_free(obj->contact_params);
		obj->contact_params=NULL;
	}
	if (contact_params){
		obj->contact_params=ms_strdup(contact_params);
	}
}

/**
 * Returns previously set contact parameters.
**/
const char *linphone_proxy_config_get_contact_parameters(const LinphoneProxyConfig *obj){
	return obj->contact_params;
}

933
934
935
struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *obj){
	return obj->lc;
}
smorlat's avatar
smorlat committed
936
937
938
939
940

/**
 * Add a proxy configuration.
 * This will start registration on the proxy, if registration is enabled.
**/
aymeric's avatar
aymeric committed
941
int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
942
943
944
	if (!linphone_proxy_config_check(lc,cfg)) {
		return -1;
	}
945
946
947
948
	if (ms_list_find(lc->sip_conf.proxies,cfg)!=NULL){
		ms_warning("ProxyConfig already entered, ignored.");
		return 0;
	}
aymeric's avatar
aymeric committed
949
950
951
952
953
	lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)cfg);
	linphone_proxy_config_apply(cfg,lc);
	return 0;
}

smorlat's avatar
smorlat committed
954
955
956
957
958
959
/**
 * Removes a proxy configuration.
 *
 * LinphoneCore will then automatically unregister and place the proxy configuration
 * on a deleted list. For that reason, a removed proxy does NOT need to be freed.
**/
aymeric's avatar
aymeric committed
960
void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
961
962
963
964
965
	/* check this proxy config is in the list before doing more*/
	if (ms_list_find(lc->sip_conf.proxies,cfg)==NULL){
		ms_error("linphone_core_remove_proxy_config: LinphoneProxyConfig %p is not known by LinphoneCore (programming error?)",cfg);
		return;
	}
aymeric's avatar
aymeric committed
966
967
968
	lc->sip_conf.proxies=ms_list_remove(lc->sip_conf.proxies,(void *)cfg);
	/* add to the list of destroyed proxies, so that the possible unREGISTER request can succeed authentication */
	lc->sip_conf.deleted_proxies=ms_list_append(lc->sip_conf.deleted_proxies,(void *)cfg);
969
	cfg->deletion_date=ms_time(NULL);
970
971
972
973
	if (cfg->state==LinphoneRegistrationOk){
		/* this will unREGISTER */
		linphone_proxy_config_edit(cfg);
	}
aymeric's avatar
aymeric committed
974
975
976
	if (lc->default_proxy==cfg){
		lc->default_proxy=NULL;
	}
977
	linphone_proxy_config_write_all_to_config_file(lc);
aymeric's avatar
aymeric committed
978
}
smorlat's avatar
smorlat committed
979
980
981
982
983
984
/**
 * Erase all proxies from config.
 *
 * @ingroup proxy
**/
void linphone_core_clear_proxy_config(LinphoneCore *lc){
smorlat's avatar
smorlat committed
985
	MSList* list=ms_list_copy(linphone_core_get_proxy_config_list((const LinphoneCore*)lc));
986
	MSList* copy=list;
smorlat's avatar
smorlat committed
987
	for(;list!=NULL;list=list->next){
smorlat's avatar
smorlat committed
988
989
		linphone_core_remove_proxy_config(lc,(LinphoneProxyConfig *)list->data);
	}
990
	ms_list_free(copy);
991
	linphone_proxy_config_write_all_to_config_file(lc);
smorlat's avatar
smorlat committed
992
}
smorlat's avatar
smorlat committed
993
994
995
996
997
998
999
/**
 * Sets the default proxy.
 *
 * This default proxy must be part of the list of already entered LinphoneProxyConfig.
 * Toggling it as default will make LinphoneCore use the identity associated with
 * the proxy configuration in all incoming and outgoing calls.
**/
aymeric's avatar
aymeric committed
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config){
	/* check if this proxy is in our list */
	if (config!=NULL){
		if (ms_list_find(lc->sip_conf.proxies,config)==NULL){
			ms_warning("Bad proxy address: it is not in the list !");
			lc->default_proxy=NULL;
			return ;
		}
	}
	lc->default_proxy=config;
1010
1011
	if (linphone_core_ready(lc))
		lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
smorlat's avatar
smorlat committed
1012
}	
aymeric's avatar
aymeric committed
1013
1014
1015
1016
1017
1018

void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){
	if (index<0) linphone_core_set_default_proxy(lc,NULL);
	else linphone_core_set_default_proxy(lc,ms_list_nth_data(lc->sip_conf.proxies,index));
}

smorlat's avatar
smorlat committed
1019
1020
1021
/**
 * Returns the default proxy configuration, that is the one used to determine the current identity.
**/
aymeric's avatar
aymeric committed
1022
1023
1024
1025
1026
1027
1028
1029
1030
int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config){
	int pos=-1;
	if (config!=NULL) *config=lc->default_proxy;
	if (lc->default_proxy!=NULL){
		pos=ms_list_position(lc->sip_conf.proxies,ms_list_find(lc->sip_conf.proxies,(void *)lc->default_proxy));
	}
	return pos;
}

smorlat's avatar
smorlat committed
1031
1032
1033
/**
 * Returns an unmodifiable list of entered proxy configurations.
**/
aymeric's avatar
aymeric committed
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){
	return lc->sip_conf.proxies;
}

void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyConfig *obj, int index)
{
	char key[50];

	sprintf(key,"proxy_%i",index);
	lp_config_clean_section(config,key);
	if (obj==NULL){
		return;
	}
smorlat's avatar
smorlat committed
1047
1048
1049
	if (obj->type!=NULL){
		lp_config_set_string(config,key,"type",obj->type);
	}
aymeric's avatar
aymeric committed
1050
1051
1052
1053
1054
1055
1056
1057
1058
	if (obj->reg_proxy!=NULL){
		lp_config_set_string(config,key,"reg_proxy",obj->reg_proxy);
	}
	if (obj->reg_route!=NULL){
		lp_config_set_string(config,key,"reg_route",obj->reg_route);
	}
	if (obj->reg_identity!=NULL){
		lp_config_set_string(config,key,"reg_identity",obj->reg_identity);
	}
Simon Morlat's avatar
Simon Morlat committed
1059
	if (obj->contact_params!=NULL){
1060
		lp_config_set_string(config,key,"contact_parameters",obj->contact_params);
Simon Morlat's avatar
Simon Morlat committed
1061
	}
aymeric's avatar
aymeric committed
1062
1063
1064
	lp_config_set_int(config,key,"reg_expires",obj->expires);
	lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister);
	lp_config_set_int(config,key,"publish",obj->publish);
1065
1066
	lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus);
	lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix);
jehan's avatar
jehan committed
1067
	lp_config_set_int(config,key,"privacy",obj->privacy);
aymeric's avatar
aymeric committed
1068
1069
}

smorlat's avatar
smorlat committed
1070
1071


aymeric's avatar
aymeric committed
1072
1073
1074
LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config, int index)
{
	const char *tmp;
smorlat's avatar
smorlat committed
1075
1076
	const char *identity;
	const char *proxy;
aymeric's avatar
aymeric committed
1077
1078
1079
1080
1081
1082
1083
1084
	LinphoneProxyConfig *cfg;
	char key[50];
	
	sprintf(key,"proxy_%i",index);

	if (!lp_config_has_section(config,key)){
		return NULL;
	}
smorlat's avatar
smorlat committed
1085
1086
1087
1088

	cfg=linphone_proxy_config_new();

	identity=lp_config_get_string(config,key,"reg_identity",NULL);	
smorlat's avatar
smorlat committed
1089
	proxy=lp_config_get_string(config,key,"reg_proxy",NULL);
smorlat's avatar
smorlat committed
1090
1091
1092
	
	linphone_proxy_config_set_identity(cfg,identity);
	linphone_proxy_config_set_server_addr(cfg,proxy);
smorlat's avatar
smorlat committed
1093
	
aymeric's avatar
aymeric committed
1094
1095
	tmp=lp_config_get_string(config,key,"reg_route",NULL);
	if (tmp!=NULL) linphone_proxy_config_set_route(cfg,tmp);
smorlat's avatar
smorlat committed
1096

Simon Morlat's avatar
Simon Morlat committed
1097
1098
	linphone_proxy_config_set_contact_parameters(cfg,lp_config_get_string(config,key,"contact_parameters",NULL));
	
1099
	linphone_proxy_config_expires(cfg,lp_config_get_int(config,key,"reg_expires",LP_CONFIG_DEFAULT_INT(config,"reg_expires",600)));
aymeric's avatar
aymeric committed
1100
1101
1102
	linphone_proxy_config_enableregister(cfg,lp_config_get_int(config,key,"reg_sendregister",0));
	
	linphone_proxy_config_enable_publish(cfg,lp_config_get_int(config,key,"publish",0));
1103

1104
1105
	linphone_proxy_config_set_dial_escape_plus(cfg,lp_config_get_int(config,key,"dial_escape_plus",LP_CONFIG_DEFAULT_INT(config,"dial_escape_plus",0)));
	linphone_proxy_config_set_dial_prefix(cfg,lp_config_get_string(config,key,"dial_prefix",LP_CONFIG_DEFAULT_STRING(config,"dial_prefix",NULL)));
aymeric's avatar
aymeric committed
1106
	
smorlat's avatar
smorlat committed
1107
1108
	tmp=lp_config_get_string(config,key,"type",NULL);
	if (tmp!=NULL && strlen(tmp)>0) 
smorlat's avatar
smorlat committed
1109
		linphone_proxy_config_set_sip_setup(cfg,tmp);
smorlat's avatar
smorlat committed
1110

jehan's avatar
jehan committed
1111
1112
	linphone_proxy_config_set_privacy(cfg,lp_config_get_int(config,key,"privacy",LP_CONFIG_DEFAULT_INT(config,"privacy",LinphonePrivacyDefault)));

aymeric's avatar
aymeric committed
1113
1114
	return cfg;
}
smorlat's avatar
smorlat committed
1115

smorlat's avatar
smorlat committed
1116
static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){
smorlat's avatar
smorlat committed
1117
	SipSetupContext *ssc;
smorlat's avatar
smorlat committed
1118
	SipSetup *ss=sip_setup_lookup(cfg->type);
smorlat's avatar
smorlat committed
1119
1120
	LinphoneCore *lc=linphone_proxy_config_get_core(cfg);
	unsigned int caps;
smorlat's avatar
smorlat committed
1121
	if (!ss) return ;
smorlat's avatar
smorlat committed
1122
	ssc=sip_setup_context_new(ss,cfg);
smorlat's avatar
smorlat committed
1123
	cfg->ssctx=ssc;
smorlat's avatar
smorlat committed
1124
1125
1126
1127
	if (cfg->reg_identity==NULL){
		ms_error("Invalid identity for this proxy configuration.");
		return;
	}
smorlat's avatar
smorlat committed
1128
1129
1130
1131
1132
1133
1134
	caps=sip_setup_context_get_capabilities(ssc);
	if (caps & SIP_SETUP_CAP_ACCOUNT_MANAGER){
		if (sip_setup_context_login_account(ssc,cfg->reg_identity,NULL)!=0){
			if (lc->vtable.display_warning){
				char *tmp=ms_strdup_printf(_("Could not login as %s"),cfg->reg_identity);
				lc->vtable.display_warning(lc,tmp);
				ms_free(tmp);
1135
			}
smorlat's avatar
smorlat committed
1136
			return;
smorlat's avatar
smorlat committed
1137
1138
		}
	}
smorlat's avatar
smorlat committed
1139
1140
1141
1142
1143
1144
1145
1146
1147
	if (caps & SIP_SETUP_CAP_PROXY_PROVIDER){
		char proxy[256];
		if (sip_setup_context_get_proxy(ssc,NULL,proxy,sizeof(proxy))==0){
			linphone_proxy_config_set_server_addr(cfg,proxy);
		}else{
			ms_error("Could not retrieve proxy uri !");
		}
	}
	
smorlat's avatar
smorlat committed
1148
1149
}

1150
1151
1152
1153
1154
1155
1156
1157
SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg){
	if (cfg->ssctx!=NULL) return cfg->ssctx->funcs;
	if (cfg->type!=NULL){
		return sip_setup_lookup(cfg->type);
	}
	return NULL;
}

1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
static bool_t can_register(LinphoneProxyConfig *cfg){
	LinphoneCore *lc=cfg->lc;
#ifdef BUILD_UPNP
	if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp){
		if(lc->sip_conf.register_only_when_upnp_is_ok && 
			(lc->upnp == NULL || !linphone_upnp_context_is_ready_for_register(lc->upnp))) {
			return FALSE;
		}
	}
#endif //BUILD_UPNP
	if (lc->sip_conf.register_only_when_network_is_up){
		LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc);
		if (tunnel && linphone_tunnel_enabled(tunnel)){
			return linphone_tunnel_connected(tunnel);
		}else{
			return lc->network_reachable;
		}
	}
	return TRUE;
}

smorlat's avatar
smorlat committed
1179
void linphone_proxy_config_update(LinphoneProxyConfig *cfg){
1180
	LinphoneCore *lc=cfg->lc;
smorlat's avatar
smorlat committed
1181
1182
1183
1184
	if (cfg->commit){
		if (cfg->type && cfg->ssctx==NULL){
			linphone_proxy_config_activate_sip_setup(cfg);
		}
1185
1186
1187
		if (can_register(cfg)){
			linphone_proxy_config_register(cfg);
			cfg->commit=FALSE;
1188
			if (cfg->publish) cfg->send_publish=TRUE;
Simon Morlat's avatar
Simon Morlat committed
1189
		}
smorlat's avatar
smorlat committed
1190
	}
1191
	if (cfg->send_publish && (cfg->state==LinphoneRegistrationOk || cfg->state==LinphoneRegistrationCleared)){
1192
		linphone_proxy_config_send_publish(cfg,lc->presence_model);
1193
		cfg->send_publish=FALSE;
Simon Morlat's avatar
Simon Morlat committed
1194
	}
smorlat's avatar
smorlat committed
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
}

void linphone_proxy_config_set_sip_setup(LinphoneProxyConfig *cfg, const char *type){
	if (cfg->type)
		ms_free(cfg->type);
	cfg->type=ms_strdup(type);
	if (linphone_proxy_config_get_addr(cfg)==NULL){
		/*put a placeholder so that the sip setup gets saved into the config */
		linphone_proxy_config_set_server_addr(cfg,"sip:undefined");
	}
}

smorlat's avatar
smorlat committed
1207
1208
1209
1210
SipSetupContext *linphone_proxy_config_get_sip_setup_context(LinphoneProxyConfig *cfg){
	return cfg->ssctx;
}

smorlat's avatar
smorlat committed
1211
1212
1213
1214
/**
 * @}
**/

1215
1216
1217
1218
1219
1220
1221
1222
1223
LinphoneAccountCreator *linphone_account_creator_new(struct _LinphoneCore *core, const char *type){
	LinphoneAccountCreator *obj;
	LinphoneProxyConfig *cfg;
	SipSetup *ss=sip_setup_lookup(type);
	SipSetupContext *ssctx;
	if (!ss){
		return NULL;
	}
	if (!(sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_ACCOUNT_MANAGER)){
1224
		ms_error("%s cannot manage accounts.",type);
1225
1226
1227
1228
1229
1230
1231
		return NULL;
	}
	obj=ms_new0(LinphoneAccountCreator,1);
	cfg=linphone_proxy_config_new();
	ssctx=sip_setup_context_new(ss,cfg);
	obj->lc=core;
	obj->ssctx=ssctx;
smorlat's avatar
smorlat committed
1232
	set_string(&obj->domain,sip_setup_context_get_domains(ssctx)[0]);
1233
1234
1235
1236
	cfg->lc=core;
	return obj;
}

smorlat's avatar
smorlat committed
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
void linphone_account_creator_set_username(LinphoneAccountCreator *obj, const char *username){
	set_string(&obj->username,username);
}

void linphone_account_creator_set_password(LinphoneAccountCreator *obj, const char *password){
	set_string(&obj->password,password);
}

void linphone_account_creator_set_domain(LinphoneAccountCreator *obj, const char *domain){
	set_string(&obj->domain,domain);
}

Sylvain Berfini's avatar
Wizard    
Sylvain Berfini committed
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
void linphone_account_creator_set_route(LinphoneAccountCreator *obj, const char *route) {
	set_string(&obj->route,route);
}

void linphone_account_creator_set_email(LinphoneAccountCreator *obj, const char *email) {
	set_string(&obj->email,email);
}

void linphone_account_creator_set_suscribe(LinphoneAccountCreator *obj, int suscribe) {
	obj->suscribe = suscribe;
}

smorlat's avatar
smorlat committed
1261
1262
1263
1264
1265
1266
1267
1268
const char * linphone_account_creator_get_username(LinphoneAccountCreator *obj){
	return obj->username;
}

const char * linphone_account_creator_get_domain(LinphoneAccountCreator *obj){
	return obj->domain;
}

1269
int linphone_account_creator_test_existence(LinphoneAccountCreator *obj){
smorlat's avatar
smorlat committed
1270
1271
1272
1273
1274
1275
1276
	SipSetupContext *ssctx=obj->ssctx;
	char *uri=ms_strdup_printf("%s@%s",obj->username,obj->domain);
	int err=sip_setup_context_account_exists(ssctx,uri);
	ms_free(uri);
	return err;
}

Sylvain Berfini's avatar
Wizard    
Sylvain Berfini committed
1277
1278
1279
1280
1281
1282
int linphone_account_creator_test_validation(LinphoneAccountCreator *obj) {
	SipSetupContext *ssctx=obj->ssctx;
	int err=sip_setup_context_account_validated(ssctx,obj->username);
	return err;
}

smorlat's avatar
smorlat committed
1283
1284
1285
LinphoneProxyConfig * linphone_account_creator_validate(LinphoneAccountCreator *obj){
	SipSetupContext *ssctx=obj->ssctx;
	char *uri=ms_strdup_printf("%s@%s",obj->username,obj->domain);
Sylvain Berfini's avatar
Wizard    
Sylvain Berfini committed
1286
	int err=sip_setup_context_create_account(ssctx, uri, obj->password, obj->email, obj->suscribe);
smorlat's avatar
smorlat committed
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
	ms_free(uri);
	if (err==0) {
		obj->succeeded=TRUE;
		return sip_setup_context_get_proxy_config(ssctx);
	}
	return NULL;
}

void linphone_account_creator_destroy(LinphoneAccountCreator *obj){
	if (obj->username)
		ms_free(obj->username);
	if (obj->password)
		ms_free(obj->password);
	if (obj->domain)
		ms_free(obj->domain);
	if (!obj->succeeded){
		linphone_proxy_config_destroy(sip_setup_context_get_proxy_config(obj->ssctx));
	}
}

jehan's avatar
jehan committed
1307
1308
1309
1310
1311
1312
1313
1314
void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cr, void * ud) {
	cr->user_data=ud;
}

void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) {
	return cr->user_data;
}

1315
1316
void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState