3 Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Library General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "linphonecore.h"
25 #include "mediastreamer2/mediastream.h"
30 void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
33 if (!linphone_core_ready(lc)) return;
35 for(elem=lc->sip_conf.proxies,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
36 LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
37 linphone_proxy_config_write_to_config_file(lc->config,cfg,i);
39 /*to ensure removed configs are erased:*/
40 linphone_proxy_config_write_to_config_file(lc->config,NULL,i);
41 lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
44 static void linphone_proxy_config_init(LinphoneCore* lc,LinphoneProxyConfig *obj){
45 memset(obj,0,sizeof(LinphoneProxyConfig));
46 obj->magic=linphone_proxy_config_magic;
47 obj->expires=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"reg_expires",3600);
48 obj->dial_prefix=ms_strdup(LP_CONFIG_DEFAULT_STRING((lc?lc->config:NULL),"dial_prefix",'\0'));
49 obj->dial_escape_plus=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"dial_escape_plus",0);
58 * @deprecated, use #linphone_core_create_proxy_config instead
59 *Creates an empty proxy config.
61 LinphoneProxyConfig *linphone_proxy_config_new() {
62 return linphone_core_create_proxy_config(NULL);
64 LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) {
65 LinphoneProxyConfig *obj=NULL;
66 obj=ms_new(LinphoneProxyConfig,1);
67 linphone_proxy_config_init(lc,obj);
74 * Destroys a proxy config.
76 * @note: LinphoneProxyConfig that have been removed from LinphoneCore with
77 * linphone_core_remove_proxy_config() must not be freed.
79 void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
80 if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
81 if (obj->reg_identity!=NULL) ms_free(obj->reg_identity);
82 if (obj->reg_route!=NULL) ms_free(obj->reg_route);
83 if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx);
84 if (obj->realm!=NULL) ms_free(obj->realm);
85 if (obj->type!=NULL) ms_free(obj->type);
86 if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix);
87 if (obj->op) sal_op_release(obj->op);
88 if (obj->publish_op) sal_op_release(obj->publish_op);
92 * Returns a boolean indicating that the user is sucessfully registered on the proxy.
94 bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *obj){
95 return obj->state == LinphoneRegistrationOk;
99 * Sets the proxy address
101 * Examples of valid sip proxy address are:
102 * - IP address: sip:87.98.157.38
103 * - IP address with port: sip:87.98.157.38:5062
104 * - hostnames : sip:sip.example.net
106 int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr){
107 LinphoneAddress *addr=NULL;
110 if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
113 if (server_addr!=NULL && strlen(server_addr)>0){
114 if (strstr(server_addr,"sip:")==NULL){
115 modified=ms_strdup_printf("sip:%s",server_addr);
116 addr=linphone_address_new(modified);
120 addr=linphone_address_new(server_addr);
122 obj->reg_proxy=linphone_address_as_string(addr);
123 linphone_address_destroy(addr);
125 ms_warning("Could not parse %s",server_addr);
133 * Sets the user identity as a SIP address.
135 * This identity is normally formed with display name, username and domain, such
137 * Alice <sip:alice@example.net>
138 * The REGISTER messages will have from and to set to this identity.
141 int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity){
142 LinphoneAddress *addr;
143 if (identity!=NULL && strlen(identity)>0){
144 addr=linphone_address_new(identity);
145 if (!addr || linphone_address_get_username(addr)==NULL){
146 ms_warning("Invalid sip identity: %s",identity);
148 linphone_address_destroy(addr);
151 if (obj->reg_identity!=NULL) {
152 ms_free(obj->reg_identity);
153 obj->reg_identity=NULL;
155 obj->reg_identity=ms_strdup(identity);
159 obj->realm=ms_strdup(linphone_address_get_domain(addr));
160 linphone_address_destroy(addr);
167 const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
173 * When a route is set, all outgoing calls will go to the route's destination if this proxy
174 * is the default one (see linphone_core_set_default_proxy() ).
176 int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route)
178 if (obj->reg_route!=NULL){
179 ms_free(obj->reg_route);
185 /*try to prepend 'sip:' */
186 if (strstr(route,"sip:")==NULL){
187 tmp=ms_strdup_printf("sip:%s",route);
188 }else tmp=ms_strdup(route);
189 addr=sal_address_new(tmp);
191 sal_address_destroy(addr);
201 bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *obj){
202 if (obj->reg_proxy==NULL){
203 if (lc->vtable.display_warning)
204 lc->vtable.display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\""
205 " followed by a hostname."));
208 if (obj->reg_identity==NULL){
209 if (lc->vtable.display_warning)
210 lc->vtable.display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like "
211 "sip:username@proxydomain, such as sip:alice@example.net"));
218 * Indicates whether a REGISTER request must be sent to the proxy.
220 void linphone_proxy_config_enableregister(LinphoneProxyConfig *obj, bool_t val){
221 obj->reg_sendregister=val;
225 * Sets the registration expiration time in seconds.
227 void linphone_proxy_config_expires(LinphoneProxyConfig *obj, int val){
232 void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
236 * Starts editing a proxy configuration.
238 * Because proxy configuration must be consistent, applications MUST
239 * call linphone_proxy_config_edit() before doing any attempts to modify
240 * proxy configuration (such as identity, proxy address and so on).
241 * Once the modifications are done, then the application must call
242 * linphone_proxy_config_done() to commit the changes.
244 void linphone_proxy_config_edit(LinphoneProxyConfig *obj){
245 if (obj->reg_sendregister){
247 if (obj->state != LinphoneRegistrationNone && obj->state != LinphoneRegistrationCleared) {
248 sal_unregister(obj->op);
253 void linphone_proxy_config_apply(LinphoneProxyConfig *obj,LinphoneCore *lc)
256 linphone_proxy_config_done(obj);
259 static char *guess_contact_for_register(LinphoneProxyConfig *obj){
260 LinphoneAddress *proxy=linphone_address_new(obj->reg_proxy);
263 if (proxy==NULL) return NULL;
264 host=linphone_address_get_domain (proxy);
266 char localip[LINPHONE_IPADDR_SIZE];
269 LinphoneAddress *contact;
271 linphone_core_get_local_ip(obj->lc,host,localip);
272 contact=linphone_address_new(obj->reg_identity);
273 linphone_address_set_domain (contact,localip);
274 linphone_address_set_port_int(contact,linphone_core_get_sip_port(obj->lc));
275 linphone_address_set_display_name(contact,NULL);
277 linphone_core_get_sip_transports(obj->lc,&tr);
278 if (tr.udp_port <= 0) {
280 sal_address_set_param(contact,"transport","tcp");
281 } else if (tr.tls_port>0) {
282 sal_address_set_param(contact,"transport","tls");
285 tmp=linphone_address_as_string_uri_only(contact);
286 if (obj->contact_params)
287 ret=ms_strdup_printf("<%s;%s>",tmp,obj->contact_params);
288 else ret=ms_strdup_printf("<%s>",tmp);
289 linphone_address_destroy(contact);
292 linphone_address_destroy (proxy);
296 static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
297 if (obj->reg_sendregister){
300 sal_op_release(obj->op);
301 obj->op=sal_op_new(obj->lc->sal);
302 contact=guess_contact_for_register(obj);
303 sal_op_set_contact(obj->op,contact);
305 sal_op_set_user_pointer(obj->op,obj);
306 if (sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires)==0) {
307 linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress");
309 linphone_proxy_config_set_state(obj,LinphoneRegistrationFailed,"Registration failed");
315 * Refresh a proxy registration.
316 * This is useful if for example you resuming from suspend, thus IP address may have changed.
318 void linphone_proxy_config_refresh_register(LinphoneProxyConfig *obj){
319 if (obj->reg_sendregister && obj->op){
320 if (sal_register_refresh(obj->op,obj->expires) == 0) {
321 linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress, "Refresh registration");
328 * Sets a dialing prefix to be automatically prepended when inviting a number with
329 * linphone_core_invite();
330 * This dialing prefix shall usually be the country code of the country where the user is living.
333 void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix){
334 if (cfg->dial_prefix!=NULL){
335 ms_free(cfg->dial_prefix);
336 cfg->dial_prefix=NULL;
338 if (prefix && prefix[0]!='\0') cfg->dial_prefix=ms_strdup(prefix);
342 * Returns dialing prefix.
346 const char *linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg){
347 return cfg->dial_prefix;
351 * Sets whether liblinphone should replace "+" by international calling prefix in dialed numbers (passed to
352 * #linphone_core_invite ).
355 void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val){
356 cfg->dial_escape_plus=val;
360 * Returns whether liblinphone should replace "+" by "00" in dialed numbers (passed to
361 * #linphone_core_invite ).
364 bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg){
365 return cfg->dial_escape_plus;
368 * http://en.wikipedia.org/wiki/Telephone_numbering_plan
369 * http://en.wikipedia.org/wiki/Telephone_numbers_in_Europe
371 typedef struct dial_plan{
373 const char* iso_country_code; /* ISO 3166-1 alpha-2 code, ex: FR for France*/
374 char ccc[8]; /*country calling code*/
375 int nnl; /*maximum national number length*/
376 const char * icp; /*international call prefix, ex: 00 in europe*/
380 /* TODO: fill with information for all countries over the world*/
382 static dial_plan_t const dial_plans[]={
383 {"Afghanistan" ,"AF" , "93" , 9 , "00" },
384 {"Albania" ,"AL" , "355" , 9 , "00" },
385 {"Algeria" ,"DZ" , "213" , 9 , "00" },
386 {"American Samoa" ,"AS" , "1" , 10 , "011" },
387 {"Andorra" ,"AD" , "376" , 6 , "00" },
388 {"Angola" ,"AO" , "244" , 9 , "00" },
389 {"Anguilla" ,"AI" , "1" , 10 , "011" },
390 {"Antigua and Barbuda" ,"AG" , "1" , 10 , "011" },
391 {"Argentina" ,"AR" , "54" , 10 , "00" },
392 {"Armenia" ,"AM" , "374" , 8 , "00" },
393 {"Aruba" ,"AW" , "297" , 7 , "011" },
394 {"Australia" ,"AU" , "61" , 9 , "0011"},
395 {"Austria" ,"AT" , "43" , 10 , "00" },
396 {"Azerbaijan" ,"AZ" , "994" , 9 , "00" },
397 {"Bahamas" ,"BS" , "1" , 10 , "011" },
398 {"Bahrain" ,"BH" , "973" , 8 , "00" },
399 {"Bangladesh" ,"BD" , "880" , 10 , "00" },
400 {"Barbados" ,"BB" , "1" , 10 , "011" },
401 {"Belarus" ,"BY" , "375" , 9 , "00" },
402 {"Belgium" ,"BE" , "32" , 9 , "00" },
403 {"Belize" ,"BZ" , "501" , 7 , "00" },
404 {"Benin" ,"BJ" , "229" , 8 , "00" },
405 {"Bermuda" ,"BM" , "1" , 10 , "011" },
406 {"Bhutan" ,"BT" , "975" , 8 , "00" },
407 {"Bolivia" ,"BO" , "591" , 8 , "00" },
408 {"Bosnia and Herzegovina" ,"BA" , "387" , 8 , "00" },
409 {"Botswana" ,"BW" , "267" , 8 , "00" },
410 {"Brazil" ,"BR" , "55" , 10 , "00" },
411 {"Brunei Darussalam" ,"BN" , "673" , 7 , "00" },
412 {"Bulgaria" ,"BG" , "359" , 9 , "00" },
413 {"Burkina Faso" ,"BF" , "226" , 8 , "00" },
414 {"Burundi" ,"BI" , "257" , 8 , "011" },
415 {"Cambodia" ,"KH" , "855" , 9 , "00" },
416 {"Cameroon" ,"CM" , "237" , 8 , "00" },
417 {"Canada" ,"CA" , "1" , 10 , "011" },
418 {"Cape Verde" ,"CV" , "238" , 7 , "00" },
419 {"Cayman Islands" ,"KY" , "1" , 10 , "011" },
420 {"Central African Republic" ,"CF" , "236" , 8 , "00" },
421 {"Chad" ,"TD" , "235" , 8 , "00" },
422 {"Chile" ,"CL" , "56" , 9 , "00" },
423 {"China" ,"CN" , "86" , 11 , "00" },
424 {"Colombia" ,"CO" , "57" , 10 , "00" },
425 {"Comoros" ,"KM" , "269" , 7 , "00" },
426 {"Congo" ,"CG" , "242" , 9 , "00" },
427 {"Congo Democratic Republic" ,"CD" , "243" , 9 , "00" },
428 {"Cook Islands" ,"CK" , "682" , 5 , "00" },
429 {"Costa Rica" ,"CR" , "506" , 8 , "00" },
430 {"C�te d'Ivoire" ,"AD" , "225" , 8 , "00" },
431 {"Croatia" ,"HR" , "385" , 9 , "00" },
432 {"Cuba" ,"CU" , "53" , 8 , "119" },
433 {"Cyprus" ,"CY" , "357" , 8 , "00" },
434 {"Czech Republic" ,"CZ" , "420" , 9 , "00" },
435 {"Denmark" ,"DK" , "45" , 8 , "00" },
436 {"Djibouti" ,"DJ" , "253" , 8 , "00" },
437 {"Dominica" ,"DM" , "1" , 10 , "011" },
438 {"Dominican Republic" ,"DO" , "1" , 10 , "011" },
439 {"Ecuador" ,"EC" , "593" , 9 , "00" },
440 {"Egypt" ,"EG" , "20" , 10 , "00" },
441 {"El Salvador" ,"SV" , "503" , 8 , "00" },
442 {"Equatorial Guinea" ,"GQ" , "240" , 9 , "00" },
443 {"Eritrea" ,"ER" , "291" , 7 , "00" },
444 {"Estonia" ,"EE" , "372" , 8 , "00" },
445 {"Ethiopia" ,"ET" , "251" , 9 , "00" },
446 {"Falkland Islands" ,"FK" , "500" , 5 , "00" },
447 {"Faroe Islands" ,"FO" , "298" , 6 , "00" },
448 {"Fiji" ,"FJ" , "679" , 7 , "00" },
449 {"Finland" ,"FI" , "358" , 9 , "00" },
450 {"France" ,"FR" , "33" , 9 , "00" },
451 {"French Guiana" ,"GF" , "594" , 9 , "00" },
452 {"French Polynesia" ,"PF" , "689" , 6 , "00" },
453 {"Gabon" ,"GA" , "241" , 8 , "00" },
454 {"Gambia" ,"GM" , "220" , 7 , "00" },
455 {"Georgia" ,"GE" , "995" , 9 , "00" },
456 {"Germany" ,"DE" , "49" , 11 , "00" },
457 {"Ghana" ,"GH" , "233" , 9 , "00" },
458 {"Gibraltar" ,"GI" , "350" , 8 , "00" },
459 {"Greece" ,"GR" , "30" ,10 , "00" },
460 {"Greenland" ,"GL" , "299" , 6 , "00" },
461 {"Grenada" ,"GD" , "1" , 10 , "011" },
462 {"Guadeloupe" ,"GP" , "590" , 9 , "00" },
463 {"Guam" ,"GU" , "1" , 10 , "011" },
464 {"Guatemala" ,"GT" , "502" , 8 , "00" },
465 {"Guinea" ,"GN" , "224" , 8 , "00" },
466 {"Guinea-Bissau" ,"GW" , "245" , 7 , "00" },
467 {"Guyana" ,"GY" , "592" , 7 , "001" },
468 {"Haiti" ,"HT" , "509" , 8 , "00" },
469 {"Honduras" ,"HN" , "504" , 8 , "00" },
470 {"Hong Kong" ,"HK" , "852" , 8 , "001" },
471 {"Hungary" ,"HU" , "36" , 9 , "00" },
472 {"Iceland" ,"IS" , "354" , 9 , "00" },
473 {"India" ,"IN" , "91" , 10 , "00" },
474 {"Indonesia" ,"ID" , "62" , 10 , "001" },
475 {"Iran" ,"IR" , "98" , 10 , "00" },
476 {"Iraq" ,"IQ" , "964" , 10 , "00" },
477 {"Ireland" ,"IE" , "353" , 9 , "00" },
478 {"Israel" ,"IL" , "972" , 9 , "00" },
479 {"Italy" ,"IT" , "39" , 10 , "00" },
480 {"Jamaica" ,"JM" , "1" , 10 , "011" },
481 {"Japan" ,"JP" , "81" , 10 , "010" },
482 {"Jordan" ,"JO" , "962" , 9 , "00" },
483 {"Kazakhstan" ,"KZ" , "7" , 10 , "00" },
484 {"Kenya" ,"KE" , "254" , 9 , "000" },
485 {"Kiribati" ,"KI" , "686" , 5 , "00" },
486 {"Korea, North" ,"KP" , "850" , 12 , "99" },
487 {"Korea, South" ,"KR" , "82" , 12 , "001" },
488 {"Kuwait" ,"KW" , "965" , 8 , "00" },
489 {"Kyrgyzstan" ,"KG" , "996" , 9 , "00" },
490 {"Laos" ,"LA" , "856" , 10 , "00" },
491 {"Latvia" ,"LV" , "371" , 8 , "00" },
492 {"Lebanon" ,"LB" , "961" , 7 , "00" },
493 {"Lesotho" ,"LS" , "266" , 8 , "00" },
494 {"Liberia" ,"LR" , "231" , 8 , "00" },
495 {"Libya" ,"LY" , "218" , 8 , "00" },
496 {"Liechtenstein" ,"LI" , "423" , 7 , "00" },
497 {"Lithuania" ,"LT" , "370" , 8 , "00" },
498 {"Luxembourg" ,"LU" , "352" , 9 , "00" },
499 {"Macau" ,"MO" , "853" , 8 , "00" },
500 {"Macedonia" ,"MK" , "389" , 8 , "00" },
501 {"Madagascar" ,"MG" , "261" , 9 , "00" },
502 {"Malawi" ,"MW" , "265" , 9 , "00" },
503 {"Malaysia" ,"MY" , "60" , 9 , "00" },
504 {"Maldives" ,"MV" , "960" , 7 , "00" },
505 {"Mali" ,"ML" , "223" , 8 , "00" },
506 {"Malta" ,"MT" , "356" , 8 , "00" },
507 {"Marshall Islands" ,"MH" , "692" , 7 , "011" },
508 {"Martinique" ,"MQ" , "596" , 9 , "00" },
509 {"Mauritania" ,"MR" , "222" , 8 , "00" },
510 {"Mauritius" ,"MU" , "230" , 7 , "00" },
511 {"Mayotte Island" ,"YT" , "262" , 9 , "00" },
512 {"Mexico" ,"MX" , "52" , 10 , "00" },
513 {"Micronesia" ,"FM" , "691" , 7 , "011" },
514 {"Moldova" ,"MD" , "373" , 8 , "00" },
515 {"Monaco" ,"MC" , "377" , 8 , "00" },
516 {"Mongolia" ,"MN" , "976" , 8 , "001" },
517 {"Montenegro" ,"ME" , "382" , 8 , "00" },
518 {"Montserrat" ,"MS" , "664" , 10 , "011" },
519 {"Morocco" ,"MA" , "212" , 9 , "00" },
520 {"Mozambique" ,"MZ" , "258" , 9 , "00" },
521 {"Myanmar" ,"MM" , "95" , 8 , "00" },
522 {"Namibia" ,"NA" , "264" , 9 , "00" },
523 {"Nauru" ,"NR" , "674" , 7 , "00" },
524 {"Nepal" ,"NP" , "43" , 10 , "00" },
525 {"Netherlands" ,"NL" , "31" , 9 , "00" },
526 {"New Caledonia" ,"NC" , "687" , 6 , "00" },
527 {"New Zealand" ,"NZ" , "64" , 10 , "00" },
528 {"Nicaragua" ,"NI" , "505" , 8 , "00" },
529 {"Niger" ,"NE" , "227" , 8 , "00" },
530 {"Nigeria" ,"NG" , "234" , 10 , "009" },
531 {"Niue" ,"NU" , "683" , 4 , "00" },
532 {"Norfolk Island" ,"NF" , "672" , 5 , "00" },
533 {"Northern Mariana Islands" ,"MP" , "1" , 10 , "011" },
534 {"Norway" ,"NO" , "47" , 8 , "00" },
535 {"Oman" ,"OM" , "968" , 8 , "00" },
536 {"Pakistan" ,"PK" , "92" , 10 , "00" },
537 {"Palau" ,"PW" , "680" , 7 , "011" },
538 {"Palestine" ,"PS" , "970" , 9 , "00" },
539 {"Panama" ,"PA" , "507" , 8 , "00" },
540 {"Papua New Guinea" ,"PG" , "675" , 8 , "00" },
541 {"Paraguay" ,"PY" , "595" , 9 , "00" },
542 {"Peru" ,"PE" , "51" , 9 , "00" },
543 {"Philippines" ,"PH" , "63" , 10 , "00" },
544 {"Poland" ,"PL" , "48" , 9 , "00" },
545 {"Portugal" ,"PT" , "351" , 9 , "00" },
546 {"Puerto Rico" ,"PR" , "1" , 10 , "011" },
547 {"Qatar" ,"QA" , "974" , 8 , "00" },
548 {"R�union Island" ,"RE" , "262" , 9 , "011" },
549 {"Romania" ,"RO" , "40" , 9 , "00" },
550 {"Russian Federation" ,"RU" , "7" , 10 , "8" },
551 {"Rwanda" ,"RW" , "250" , 9 , "00" },
552 {"Saint Helena" ,"SH" , "290" , 4 , "00" },
553 {"Saint Kitts and Nevis" ,"KN" , "1" , 10 , "011" },
554 {"Saint Lucia" ,"LC" , "1" , 10 , "011" },
555 {"Saint Pierre and Miquelon" ,"PM" , "508" , 6 , "00" },
556 {"Saint Vincent and the Grenadines","VC" , "1" , 10 , "011" },
557 {"Samoa" ,"WS" , "685" , 7 , "0" },
558 {"San Marino" ,"SM" , "378" , 10 , "00" },
559 {"S�o Tom� and Pr�ncipe" ,"ST" , "239" , 7 , "00" },
560 {"Saudi Arabia" ,"SA" , "966" , 9 , "00" },
561 {"Senegal" ,"SN" , "221" , 9 , "00" },
562 {"Serbia" ,"RS" , "381" , 9 , "00" },
563 {"Seychelles" ,"SC" , "248" , 7 , "00" },
564 {"Sierra Leone" ,"SL" , "232" , 8 , "00" },
565 {"Singapore" ,"SG" , "65" , 8 , "001" },
566 {"Slovakia" ,"SK" , "421" , 9 , "00" },
567 {"Slovenia" ,"SI" , "386" , 8 , "00" },
568 {"Solomon Islands" ,"SB" , "677" , 7 , "00" },
569 {"Somalia" ,"SO" , "252" , 8 , "00" },
570 {"South Africa" ,"ZA" , "27" , 9 , "00" },
571 {"Spain" ,"ES" , "34" , 9 , "00" },
572 {"Sri Lanka" ,"LK" , "94" , 9 , "00" },
573 {"Sudan" ,"SD" , "249" , 9 , "00" },
574 {"Suriname" ,"SR" , "597" , 7 , "00" },
575 {"Swaziland" ,"SZ" , "268" , 8 , "00" },
576 {"Sweden" ,"SE" , "1" , 9 , "00" },
577 {"Switzerland" ,"XK" , "41" , 9 , "00" },
578 {"Syria" ,"SY" , "963" , 9 , "00" },
579 {"Taiwan" ,"TW" , "886" , 9 , "810" },
580 {"Tajikistan" ,"TJ" , "992" , 9 , "002" },
581 {"Tanzania" ,"TZ" , "255" , 9 , "000" },
582 {"Thailand" ,"TH" , "66" , 9 , "001" },
583 {"Togo" ,"TG" , "228" , 8 , "00" },
584 {"Tokelau" ,"TK" , "690" , 4 , "00" },
585 {"Tonga" ,"TO" , "676" , 5 , "00" },
586 {"Trinidad and Tobago" ,"TT" , "1" , 10 , "011" },
587 {"Tunisia" ,"TN" , "216" , 8 , "00" },
588 {"Turkey" ,"TR" , "90" , 10 , "00" },
589 {"Turkmenistan" ,"TM" , "993" , 8 , "00" },
590 {"Turks and Caicos Islands" ,"TC" , "1" , 7 , "0" },
591 {"Tuvalu" ,"TV" , "688" , 5 , "00" },
592 {"Uganda" ,"UG" , "256" , 9 , "000" },
593 {"Ukraine" ,"UA" , "380" , 9 , "00" },
594 {"United Arab Emirates" ,"AE" , "971" , 9 , "00" },
595 {"United Kingdom" ,"UK" , "44" , 10 , "00" },
596 {"United States" ,"US" , "1" , 10 , "011" },
597 {"Uruguay" ,"UY" , "598" , 8 , "00" },
598 {"Uzbekistan" ,"UZ" , "998" , 9 , "8" },
599 {"Vanuatu" ,"VU" , "678" , 7 , "00" },
600 {"Venezuela" ,"VE" , "58" , 10 , "00" },
601 {"Vietnam" ,"VN" , "84" , 9 , "00" },
602 {"Wallis and Futuna" ,"WF" , "681" , 5 , "00" },
603 {"Yemen" ,"YE" , "967" , 9 , "00" },
604 {"Zambia" ,"ZM" , "260" , 9 , "00" },
605 {"Zimbabwe" ,"ZW" , "263" , 9 , "00" },
606 {NULL ,NULL , "" , 0 , NULL }
608 static dial_plan_t most_common_dialplan={ "generic" ,"", "", 10, "00"};
610 int linphone_dial_plan_lookup_ccc_from_e164(const char* e164) {
611 dial_plan_t* dial_plan;
612 dial_plan_t* elected_dial_plan=NULL;
622 for (dial_plan=(dial_plan_t*)dial_plans; dial_plan->country!=NULL; dial_plan++) {
623 if (strncmp(dial_plan->ccc,&e164[1],i) == 0) {
624 elected_dial_plan=dial_plan;
628 } while ((found>1 || found==0) && i < sizeof(dial_plan->ccc));
630 return atoi(elected_dial_plan->ccc);
632 return -1; /*not found */
636 int linphone_dial_plan_lookup_ccc_from_iso(const char* iso) {
637 dial_plan_t* dial_plan;
638 for (dial_plan=(dial_plan_t*)dial_plans; dial_plan->country!=NULL; dial_plan++) {
639 if (strcmp(iso, dial_plan->iso_country_code)==0) {
640 return atoi(dial_plan->ccc);
646 static void lookup_dial_plan(const char *ccc, dial_plan_t *plan){
648 for(i=0;dial_plans[i].country!=NULL;++i){
649 if (strcmp(ccc,dial_plans[i].ccc)==0){
654 /*else return a generic "most common" dial plan*/
655 *plan=most_common_dialplan;
656 strcpy(plan->ccc,ccc);
659 static bool_t is_a_phone_number(const char *username){
661 for(p=username;*p!='\0';++p){
675 static char *flatten_number(const char *number){
676 char *result=ms_malloc0(strlen(number)+1);
679 for(r=number;*r!='\0';++r){
680 if (*r=='+' || isdigit(*r)){
688 static void replace_plus(const char *src, char *dest, size_t destlen, const char *icp){
691 if (icp && src[0]=='+' && (destlen>(i=strlen(icp))) ){
696 for(;(i<destlen-1) && *src!='\0';++i){
704 int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len){
706 if (is_a_phone_number(username)){
708 flatten=flatten_number(username);
709 ms_message("Flattened number is '%s'",flatten);
711 if (proxy->dial_prefix==NULL || proxy->dial_prefix[0]=='\0'){
712 /*no prefix configured, nothing else to do*/
713 strncpy(result,flatten,result_len);
717 dial_plan_t dialplan;
718 lookup_dial_plan(proxy->dial_prefix,&dialplan);
719 ms_message("Using dialplan '%s'",dialplan.country);
720 if (flatten[0]=='+' || strstr(flatten,dialplan.icp)==flatten){
721 /* the number has international prefix or +, so nothing to do*/
722 ms_message("Prefix already present.");
723 /*eventually replace the plus*/
724 replace_plus(flatten,result,result_len,proxy->dial_escape_plus ? dialplan.icp : NULL);
730 numlen=strlen(flatten);
731 /*keep at most national number significant digits */
732 skip=numlen-dialplan.nnl;
734 /*first prepend internation calling prefix or +*/
735 if (proxy->dial_escape_plus){
736 strncpy(result,dialplan.icp,result_len);
737 i+=strlen(dialplan.icp);
739 strncpy(result,"+",result_len);
743 if (result_len-i>strlen(dialplan.ccc)){
744 strcpy(result+i,dialplan.ccc);
745 i+=strlen(dialplan.ccc);
748 strncpy(result+i,flatten+skip,result_len-i-1);
752 }else strncpy(result,username,result_len);
757 * Commits modification made to the proxy configuration.
759 int linphone_proxy_config_done(LinphoneProxyConfig *obj)
761 if (!linphone_proxy_config_check(obj->lc,obj)) return -1;
763 linphone_proxy_config_write_all_to_config_file(obj->lc);
767 void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm)
769 if (cfg->realm!=NULL) {
773 if (realm!=NULL) cfg->realm=ms_strdup(realm);
776 int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy,
777 LinphoneOnlineStatus presence_mode){
779 SalOp *op=sal_op_new(proxy->lc->sal);
780 err=sal_publish(op,linphone_proxy_config_get_identity(proxy),
781 linphone_proxy_config_get_identity(proxy),linphone_online_status_to_sal(presence_mode));
782 if (proxy->publish_op!=NULL)
783 sal_op_release(proxy->publish_op);
784 proxy->publish_op=op;
789 * Returns the route set for this proxy configuration.
791 const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj){
792 return obj->reg_route;
796 * Returns the SIP identity that belongs to this proxy configuration.
798 * The SIP identity is a SIP address (Display Name <sip:username@@domain> )
800 const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj){
801 return obj->reg_identity;
805 * Returns TRUE if PUBLISH request is enabled for this proxy.
807 bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj){
812 * Returns the proxy's SIP address.
814 const char *linphone_proxy_config_get_addr(const LinphoneProxyConfig *obj){
815 return obj->reg_proxy;
819 * Returns the duration of registration.
821 int linphone_proxy_config_get_expires(const LinphoneProxyConfig *obj){
826 * Returns TRUE if registration to the proxy is enabled.
828 bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *obj){
829 return obj->reg_sendregister;
833 * Set optional contact parameters that will be added to the contact information sent in the registration.
834 * @param obj the proxy config object
835 * @param contact_params a string contaning the additional parameters in text form, like "myparam=something;myparam2=something_else"
837 * 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.
838 * 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>.
840 void linphone_proxy_config_set_contact_parameters(LinphoneProxyConfig *obj, const char *contact_params){
841 if (obj->contact_params) {
842 ms_free(obj->contact_params);
843 obj->contact_params=NULL;
846 obj->contact_params=ms_strdup(contact_params);
851 * Returns previously set contact parameters.
853 const char *linphone_proxy_config_get_contact_parameters(const LinphoneProxyConfig *obj){
854 return obj->contact_params;
857 struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *obj){
862 * Add a proxy configuration.
863 * This will start registration on the proxy, if registration is enabled.
865 int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
866 if (!linphone_proxy_config_check(lc,cfg)) {
869 if (ms_list_find(lc->sip_conf.proxies,cfg)!=NULL){
870 ms_warning("ProxyConfig already entered, ignored.");
873 lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)cfg);
874 linphone_proxy_config_apply(cfg,lc);
879 * Removes a proxy configuration.
881 * LinphoneCore will then automatically unregister and place the proxy configuration
882 * on a deleted list. For that reason, a removed proxy does NOT need to be freed.
884 void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
885 /* check this proxy config is in the list before doing more*/
886 if (ms_list_find(lc->sip_conf.proxies,cfg)==NULL){
887 ms_error("linphone_core_remove_proxy_config: LinphoneProxyConfig %p is not known by LinphoneCore (programming error?)",cfg);
890 lc->sip_conf.proxies=ms_list_remove(lc->sip_conf.proxies,(void *)cfg);
891 /* add to the list of destroyed proxies, so that the possible unREGISTER request can succeed authentication */
892 lc->sip_conf.deleted_proxies=ms_list_append(lc->sip_conf.deleted_proxies,(void *)cfg);
893 cfg->deletion_date=ms_time(NULL);
894 if (cfg->state==LinphoneRegistrationOk){
895 /* this will unREGISTER */
896 linphone_proxy_config_edit(cfg);
898 if (lc->default_proxy==cfg){
899 lc->default_proxy=NULL;
901 linphone_proxy_config_write_all_to_config_file(lc);
904 * Erase all proxies from config.
908 void linphone_core_clear_proxy_config(LinphoneCore *lc){
909 MSList* list=ms_list_copy(linphone_core_get_proxy_config_list((const LinphoneCore*)lc));
911 for(;list!=NULL;list=list->next){
912 linphone_core_remove_proxy_config(lc,(LinphoneProxyConfig *)list->data);
915 linphone_proxy_config_write_all_to_config_file(lc);
918 * Sets the default proxy.
920 * This default proxy must be part of the list of already entered LinphoneProxyConfig.
921 * Toggling it as default will make LinphoneCore use the identity associated with
922 * the proxy configuration in all incoming and outgoing calls.
924 void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config){
925 /* check if this proxy is in our list */
927 if (ms_list_find(lc->sip_conf.proxies,config)==NULL){
928 ms_warning("Bad proxy address: it is not in the list !");
929 lc->default_proxy=NULL;
933 lc->default_proxy=config;
934 if (linphone_core_ready(lc))
935 lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
938 void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){
939 if (index<0) linphone_core_set_default_proxy(lc,NULL);
940 else linphone_core_set_default_proxy(lc,ms_list_nth_data(lc->sip_conf.proxies,index));
944 * Returns the default proxy configuration, that is the one used to determine the current identity.
946 int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config){
948 if (config!=NULL) *config=lc->default_proxy;
949 if (lc->default_proxy!=NULL){
950 pos=ms_list_position(lc->sip_conf.proxies,ms_list_find(lc->sip_conf.proxies,(void *)lc->default_proxy));
956 * Returns an unmodifiable list of entered proxy configurations.
958 const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){
959 return lc->sip_conf.proxies;
962 void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyConfig *obj, int index)
966 sprintf(key,"proxy_%i",index);
967 lp_config_clean_section(config,key);
971 if (obj->type!=NULL){
972 lp_config_set_string(config,key,"type",obj->type);
974 if (obj->reg_proxy!=NULL){
975 lp_config_set_string(config,key,"reg_proxy",obj->reg_proxy);
977 if (obj->reg_route!=NULL){
978 lp_config_set_string(config,key,"reg_route",obj->reg_route);
980 if (obj->reg_identity!=NULL){
981 lp_config_set_string(config,key,"reg_identity",obj->reg_identity);
983 if (obj->contact_params!=NULL){
984 lp_config_set_string(config,key,"contact_parameters",obj->contact_params);
986 lp_config_set_int(config,key,"reg_expires",obj->expires);
987 lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister);
988 lp_config_set_int(config,key,"publish",obj->publish);
989 lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus);
990 lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix);
995 LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config, int index)
998 const char *identity;
1000 LinphoneProxyConfig *cfg;
1003 sprintf(key,"proxy_%i",index);
1005 if (!lp_config_has_section(config,key)){
1009 cfg=linphone_proxy_config_new();
1011 identity=lp_config_get_string(config,key,"reg_identity",NULL);
1012 proxy=lp_config_get_string(config,key,"reg_proxy",NULL);
1014 linphone_proxy_config_set_identity(cfg,identity);
1015 linphone_proxy_config_set_server_addr(cfg,proxy);
1017 tmp=lp_config_get_string(config,key,"reg_route",NULL);
1018 if (tmp!=NULL) linphone_proxy_config_set_route(cfg,tmp);
1020 linphone_proxy_config_set_contact_parameters(cfg,lp_config_get_string(config,key,"contact_parameters",NULL));
1022 linphone_proxy_config_expires(cfg,lp_config_get_int(config,key,"reg_expires",LP_CONFIG_DEFAULT_INT(config,"reg_expires",600)));
1023 linphone_proxy_config_enableregister(cfg,lp_config_get_int(config,key,"reg_sendregister",0));
1025 linphone_proxy_config_enable_publish(cfg,lp_config_get_int(config,key,"publish",0));
1027 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)));
1028 linphone_proxy_config_set_dial_prefix(cfg,lp_config_get_string(config,key,"dial_prefix",LP_CONFIG_DEFAULT_STRING(config,"dial_prefix",NULL)));
1030 tmp=lp_config_get_string(config,key,"type",NULL);
1031 if (tmp!=NULL && strlen(tmp)>0)
1032 linphone_proxy_config_set_sip_setup(cfg,tmp);
1037 static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){
1038 SipSetupContext *ssc;
1039 SipSetup *ss=sip_setup_lookup(cfg->type);
1040 LinphoneCore *lc=linphone_proxy_config_get_core(cfg);
1043 ssc=sip_setup_context_new(ss,cfg);
1045 if (cfg->reg_identity==NULL){
1046 ms_error("Invalid identity for this proxy configuration.");
1049 caps=sip_setup_context_get_capabilities(ssc);
1050 if (caps & SIP_SETUP_CAP_ACCOUNT_MANAGER){
1051 if (sip_setup_context_login_account(ssc,cfg->reg_identity,NULL)!=0){
1052 if (lc->vtable.display_warning){
1053 char *tmp=ms_strdup_printf(_("Could not login as %s"),cfg->reg_identity);
1054 lc->vtable.display_warning(lc,tmp);
1060 if (caps & SIP_SETUP_CAP_PROXY_PROVIDER){
1062 if (sip_setup_context_get_proxy(ssc,NULL,proxy,sizeof(proxy))==0){
1063 linphone_proxy_config_set_server_addr(cfg,proxy);
1065 ms_error("Could not retrieve proxy uri !");
1071 SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg){
1072 if (cfg->ssctx!=NULL) return cfg->ssctx->funcs;
1073 if (cfg->type!=NULL){
1074 return sip_setup_lookup(cfg->type);
1079 void linphone_proxy_config_update(LinphoneProxyConfig *cfg){
1080 LinphoneCore *lc=cfg->lc;
1082 if (cfg->type && cfg->ssctx==NULL){
1083 linphone_proxy_config_activate_sip_setup(cfg);
1085 if ((!lc->sip_conf.register_only_when_network_is_up || lc->network_reachable) &&
1086 (!lc->sip_conf.register_only_when_upnp_is_ok || linphone_core_get_upnp_state(lc) == LinphoneUpnpStateOk))
1087 linphone_proxy_config_register(cfg);
1088 if (cfg->publish && cfg->publish_op==NULL){
1089 linphone_proxy_config_send_publish(cfg,lc->presence_mode);
1095 void linphone_proxy_config_set_sip_setup(LinphoneProxyConfig *cfg, const char *type){
1098 cfg->type=ms_strdup(type);
1099 if (linphone_proxy_config_get_addr(cfg)==NULL){
1100 /*put a placeholder so that the sip setup gets saved into the config */
1101 linphone_proxy_config_set_server_addr(cfg,"sip:undefined");
1105 SipSetupContext *linphone_proxy_config_get_sip_setup_context(LinphoneProxyConfig *cfg){
1113 LinphoneAccountCreator *linphone_account_creator_new(struct _LinphoneCore *core, const char *type){
1114 LinphoneAccountCreator *obj;
1115 LinphoneProxyConfig *cfg;
1116 SipSetup *ss=sip_setup_lookup(type);
1117 SipSetupContext *ssctx;
1121 if (!(sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_ACCOUNT_MANAGER)){
1122 ms_error("%s cannot manage accounts.",type);
1125 obj=ms_new0(LinphoneAccountCreator,1);
1126 cfg=linphone_proxy_config_new();
1127 ssctx=sip_setup_context_new(ss,cfg);
1130 set_string(&obj->domain,sip_setup_context_get_domains(ssctx)[0]);
1135 void linphone_account_creator_set_username(LinphoneAccountCreator *obj, const char *username){
1136 set_string(&obj->username,username);
1139 void linphone_account_creator_set_password(LinphoneAccountCreator *obj, const char *password){
1140 set_string(&obj->password,password);
1143 void linphone_account_creator_set_domain(LinphoneAccountCreator *obj, const char *domain){
1144 set_string(&obj->domain,domain);
1147 void linphone_account_creator_set_route(LinphoneAccountCreator *obj, const char *route) {
1148 set_string(&obj->route,route);
1151 void linphone_account_creator_set_email(LinphoneAccountCreator *obj, const char *email) {
1152 set_string(&obj->email,email);
1155 void linphone_account_creator_set_suscribe(LinphoneAccountCreator *obj, int suscribe) {
1156 obj->suscribe = suscribe;
1159 const char * linphone_account_creator_get_username(LinphoneAccountCreator *obj){
1160 return obj->username;
1163 const char * linphone_account_creator_get_domain(LinphoneAccountCreator *obj){
1167 int linphone_account_creator_test_existence(LinphoneAccountCreator *obj){
1168 SipSetupContext *ssctx=obj->ssctx;
1169 char *uri=ms_strdup_printf("%s@%s",obj->username,obj->domain);
1170 int err=sip_setup_context_account_exists(ssctx,uri);
1175 int linphone_account_creator_test_validation(LinphoneAccountCreator *obj) {
1176 SipSetupContext *ssctx=obj->ssctx;
1177 int err=sip_setup_context_account_validated(ssctx,obj->username);
1181 LinphoneProxyConfig * linphone_account_creator_validate(LinphoneAccountCreator *obj){
1182 SipSetupContext *ssctx=obj->ssctx;
1183 char *uri=ms_strdup_printf("%s@%s",obj->username,obj->domain);
1184 int err=sip_setup_context_create_account(ssctx, uri, obj->password, obj->email, obj->suscribe);
1187 obj->succeeded=TRUE;
1188 return sip_setup_context_get_proxy_config(ssctx);
1193 void linphone_account_creator_destroy(LinphoneAccountCreator *obj){
1195 ms_free(obj->username);
1197 ms_free(obj->password);
1199 ms_free(obj->domain);
1200 if (!obj->succeeded){
1201 linphone_proxy_config_destroy(sip_setup_context_get_proxy_config(obj->ssctx));
1205 void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cr, void * ud) {
1209 void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) {
1210 return cr->user_data;
1213 void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){
1214 LinphoneCore *lc=cfg->lc;
1216 if (lc && lc->vtable.registration_state_changed){
1217 lc->vtable.registration_state_changed(lc,cfg,state,message);
1221 LinphoneRegistrationState linphone_proxy_config_get_state(const LinphoneProxyConfig *cfg){
1225 const char *linphone_registration_state_to_string(LinphoneRegistrationState cs){
1227 case LinphoneRegistrationCleared:
1228 return "LinphoneRegistrationCleared";
1230 case LinphoneRegistrationNone:
1231 return "LinphoneRegistrationNone";
1233 case LinphoneRegistrationProgress:
1234 return "LinphoneRegistrationProgress";
1236 case LinphoneRegistrationOk:
1237 return "LinphoneRegistrationOk";
1239 case LinphoneRegistrationFailed:
1240 return "LinphoneRegistrationFailed";
1246 LinphoneReason linphone_proxy_config_get_error(const LinphoneProxyConfig *cfg) {
1250 void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg,LinphoneReason error) {