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);
267 char localip_tmp[LINPHONE_IPADDR_SIZE] = {'\0'};
268 const char *localip = NULL;
271 LinphoneAddress *contact;
273 contact=linphone_address_new(obj->reg_identity);
275 if (obj->lc->upnp != NULL && linphone_core_get_firewall_policy(obj->lc)==LinphonePolicyUseUpnp &&
276 linphone_upnp_context_get_state(obj->lc->upnp) == LinphoneUpnpStateOk) {
277 localip = linphone_upnp_context_get_external_ipaddress(obj->lc->upnp);
278 localport = linphone_upnp_context_get_external_port(obj->lc->upnp);
281 if(localip == NULL) {
282 localip = localip_tmp;
283 linphone_core_get_local_ip(obj->lc,host,localip_tmp);
285 if(localport == -1) {
286 localport = linphone_core_get_sip_port(obj->lc);
288 linphone_address_set_port_int(contact,localport);
289 linphone_address_set_domain(contact,localip);
290 linphone_address_set_display_name(contact,NULL);
292 linphone_core_get_sip_transports(obj->lc,&tr);
293 if (tr.udp_port <= 0) {
295 sal_address_set_param(contact,"transport","tcp");
296 } else if (tr.tls_port>0) {
297 sal_address_set_param(contact,"transport","tls");
300 tmp=linphone_address_as_string_uri_only(contact);
301 if (obj->contact_params)
302 ret=ms_strdup_printf("<%s;%s>",tmp,obj->contact_params);
303 else ret=ms_strdup_printf("<%s>",tmp);
304 linphone_address_destroy(contact);
307 linphone_address_destroy (proxy);
311 static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
312 if (obj->reg_sendregister){
315 sal_op_release(obj->op);
316 obj->op=sal_op_new(obj->lc->sal);
317 contact=guess_contact_for_register(obj);
318 sal_op_set_contact(obj->op,contact);
320 sal_op_set_user_pointer(obj->op,obj);
321 if (sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires)==0) {
322 linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress");
324 linphone_proxy_config_set_state(obj,LinphoneRegistrationFailed,"Registration failed");
330 * Refresh a proxy registration.
331 * This is useful if for example you resuming from suspend, thus IP address may have changed.
333 void linphone_proxy_config_refresh_register(LinphoneProxyConfig *obj){
334 if (obj->reg_sendregister && obj->op){
335 if (sal_register_refresh(obj->op,obj->expires) == 0) {
336 linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress, "Refresh registration");
343 * Sets a dialing prefix to be automatically prepended when inviting a number with
344 * linphone_core_invite();
345 * This dialing prefix shall usually be the country code of the country where the user is living.
348 void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix){
349 if (cfg->dial_prefix!=NULL){
350 ms_free(cfg->dial_prefix);
351 cfg->dial_prefix=NULL;
353 if (prefix && prefix[0]!='\0') cfg->dial_prefix=ms_strdup(prefix);
357 * Returns dialing prefix.
361 const char *linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg){
362 return cfg->dial_prefix;
366 * Sets whether liblinphone should replace "+" by international calling prefix in dialed numbers (passed to
367 * #linphone_core_invite ).
370 void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val){
371 cfg->dial_escape_plus=val;
375 * Returns whether liblinphone should replace "+" by "00" in dialed numbers (passed to
376 * #linphone_core_invite ).
379 bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg){
380 return cfg->dial_escape_plus;
383 * http://en.wikipedia.org/wiki/Telephone_numbering_plan
384 * http://en.wikipedia.org/wiki/Telephone_numbers_in_Europe
386 typedef struct dial_plan{
388 const char* iso_country_code; /* ISO 3166-1 alpha-2 code, ex: FR for France*/
389 char ccc[8]; /*country calling code*/
390 int nnl; /*maximum national number length*/
391 const char * icp; /*international call prefix, ex: 00 in europe*/
395 /* TODO: fill with information for all countries over the world*/
397 static dial_plan_t const dial_plans[]={
398 {"Afghanistan" ,"AF" , "93" , 9 , "00" },
399 {"Albania" ,"AL" , "355" , 9 , "00" },
400 {"Algeria" ,"DZ" , "213" , 9 , "00" },
401 {"American Samoa" ,"AS" , "1" , 10 , "011" },
402 {"Andorra" ,"AD" , "376" , 6 , "00" },
403 {"Angola" ,"AO" , "244" , 9 , "00" },
404 {"Anguilla" ,"AI" , "1" , 10 , "011" },
405 {"Antigua and Barbuda" ,"AG" , "1" , 10 , "011" },
406 {"Argentina" ,"AR" , "54" , 10 , "00" },
407 {"Armenia" ,"AM" , "374" , 8 , "00" },
408 {"Aruba" ,"AW" , "297" , 7 , "011" },
409 {"Australia" ,"AU" , "61" , 9 , "0011"},
410 {"Austria" ,"AT" , "43" , 10 , "00" },
411 {"Azerbaijan" ,"AZ" , "994" , 9 , "00" },
412 {"Bahamas" ,"BS" , "1" , 10 , "011" },
413 {"Bahrain" ,"BH" , "973" , 8 , "00" },
414 {"Bangladesh" ,"BD" , "880" , 10 , "00" },
415 {"Barbados" ,"BB" , "1" , 10 , "011" },
416 {"Belarus" ,"BY" , "375" , 9 , "00" },
417 {"Belgium" ,"BE" , "32" , 9 , "00" },
418 {"Belize" ,"BZ" , "501" , 7 , "00" },
419 {"Benin" ,"BJ" , "229" , 8 , "00" },
420 {"Bermuda" ,"BM" , "1" , 10 , "011" },
421 {"Bhutan" ,"BT" , "975" , 8 , "00" },
422 {"Bolivia" ,"BO" , "591" , 8 , "00" },
423 {"Bosnia and Herzegovina" ,"BA" , "387" , 8 , "00" },
424 {"Botswana" ,"BW" , "267" , 8 , "00" },
425 {"Brazil" ,"BR" , "55" , 10 , "00" },
426 {"Brunei Darussalam" ,"BN" , "673" , 7 , "00" },
427 {"Bulgaria" ,"BG" , "359" , 9 , "00" },
428 {"Burkina Faso" ,"BF" , "226" , 8 , "00" },
429 {"Burundi" ,"BI" , "257" , 8 , "011" },
430 {"Cambodia" ,"KH" , "855" , 9 , "00" },
431 {"Cameroon" ,"CM" , "237" , 8 , "00" },
432 {"Canada" ,"CA" , "1" , 10 , "011" },
433 {"Cape Verde" ,"CV" , "238" , 7 , "00" },
434 {"Cayman Islands" ,"KY" , "1" , 10 , "011" },
435 {"Central African Republic" ,"CF" , "236" , 8 , "00" },
436 {"Chad" ,"TD" , "235" , 8 , "00" },
437 {"Chile" ,"CL" , "56" , 9 , "00" },
438 {"China" ,"CN" , "86" , 11 , "00" },
439 {"Colombia" ,"CO" , "57" , 10 , "00" },
440 {"Comoros" ,"KM" , "269" , 7 , "00" },
441 {"Congo" ,"CG" , "242" , 9 , "00" },
442 {"Congo Democratic Republic" ,"CD" , "243" , 9 , "00" },
443 {"Cook Islands" ,"CK" , "682" , 5 , "00" },
444 {"Costa Rica" ,"CR" , "506" , 8 , "00" },
445 {"C�te d'Ivoire" ,"AD" , "225" , 8 , "00" },
446 {"Croatia" ,"HR" , "385" , 9 , "00" },
447 {"Cuba" ,"CU" , "53" , 8 , "119" },
448 {"Cyprus" ,"CY" , "357" , 8 , "00" },
449 {"Czech Republic" ,"CZ" , "420" , 9 , "00" },
450 {"Denmark" ,"DK" , "45" , 8 , "00" },
451 {"Djibouti" ,"DJ" , "253" , 8 , "00" },
452 {"Dominica" ,"DM" , "1" , 10 , "011" },
453 {"Dominican Republic" ,"DO" , "1" , 10 , "011" },
454 {"Ecuador" ,"EC" , "593" , 9 , "00" },
455 {"Egypt" ,"EG" , "20" , 10 , "00" },
456 {"El Salvador" ,"SV" , "503" , 8 , "00" },
457 {"Equatorial Guinea" ,"GQ" , "240" , 9 , "00" },
458 {"Eritrea" ,"ER" , "291" , 7 , "00" },
459 {"Estonia" ,"EE" , "372" , 8 , "00" },
460 {"Ethiopia" ,"ET" , "251" , 9 , "00" },
461 {"Falkland Islands" ,"FK" , "500" , 5 , "00" },
462 {"Faroe Islands" ,"FO" , "298" , 6 , "00" },
463 {"Fiji" ,"FJ" , "679" , 7 , "00" },
464 {"Finland" ,"FI" , "358" , 9 , "00" },
465 {"France" ,"FR" , "33" , 9 , "00" },
466 {"French Guiana" ,"GF" , "594" , 9 , "00" },
467 {"French Polynesia" ,"PF" , "689" , 6 , "00" },
468 {"Gabon" ,"GA" , "241" , 8 , "00" },
469 {"Gambia" ,"GM" , "220" , 7 , "00" },
470 {"Georgia" ,"GE" , "995" , 9 , "00" },
471 {"Germany" ,"DE" , "49" , 11 , "00" },
472 {"Ghana" ,"GH" , "233" , 9 , "00" },
473 {"Gibraltar" ,"GI" , "350" , 8 , "00" },
474 {"Greece" ,"GR" , "30" ,10 , "00" },
475 {"Greenland" ,"GL" , "299" , 6 , "00" },
476 {"Grenada" ,"GD" , "1" , 10 , "011" },
477 {"Guadeloupe" ,"GP" , "590" , 9 , "00" },
478 {"Guam" ,"GU" , "1" , 10 , "011" },
479 {"Guatemala" ,"GT" , "502" , 8 , "00" },
480 {"Guinea" ,"GN" , "224" , 8 , "00" },
481 {"Guinea-Bissau" ,"GW" , "245" , 7 , "00" },
482 {"Guyana" ,"GY" , "592" , 7 , "001" },
483 {"Haiti" ,"HT" , "509" , 8 , "00" },
484 {"Honduras" ,"HN" , "504" , 8 , "00" },
485 {"Hong Kong" ,"HK" , "852" , 8 , "001" },
486 {"Hungary" ,"HU" , "36" , 9 , "00" },
487 {"Iceland" ,"IS" , "354" , 9 , "00" },
488 {"India" ,"IN" , "91" , 10 , "00" },
489 {"Indonesia" ,"ID" , "62" , 10 , "001" },
490 {"Iran" ,"IR" , "98" , 10 , "00" },
491 {"Iraq" ,"IQ" , "964" , 10 , "00" },
492 {"Ireland" ,"IE" , "353" , 9 , "00" },
493 {"Israel" ,"IL" , "972" , 9 , "00" },
494 {"Italy" ,"IT" , "39" , 10 , "00" },
495 {"Jamaica" ,"JM" , "1" , 10 , "011" },
496 {"Japan" ,"JP" , "81" , 10 , "010" },
497 {"Jordan" ,"JO" , "962" , 9 , "00" },
498 {"Kazakhstan" ,"KZ" , "7" , 10 , "00" },
499 {"Kenya" ,"KE" , "254" , 9 , "000" },
500 {"Kiribati" ,"KI" , "686" , 5 , "00" },
501 {"Korea, North" ,"KP" , "850" , 12 , "99" },
502 {"Korea, South" ,"KR" , "82" , 12 , "001" },
503 {"Kuwait" ,"KW" , "965" , 8 , "00" },
504 {"Kyrgyzstan" ,"KG" , "996" , 9 , "00" },
505 {"Laos" ,"LA" , "856" , 10 , "00" },
506 {"Latvia" ,"LV" , "371" , 8 , "00" },
507 {"Lebanon" ,"LB" , "961" , 7 , "00" },
508 {"Lesotho" ,"LS" , "266" , 8 , "00" },
509 {"Liberia" ,"LR" , "231" , 8 , "00" },
510 {"Libya" ,"LY" , "218" , 8 , "00" },
511 {"Liechtenstein" ,"LI" , "423" , 7 , "00" },
512 {"Lithuania" ,"LT" , "370" , 8 , "00" },
513 {"Luxembourg" ,"LU" , "352" , 9 , "00" },
514 {"Macau" ,"MO" , "853" , 8 , "00" },
515 {"Macedonia" ,"MK" , "389" , 8 , "00" },
516 {"Madagascar" ,"MG" , "261" , 9 , "00" },
517 {"Malawi" ,"MW" , "265" , 9 , "00" },
518 {"Malaysia" ,"MY" , "60" , 9 , "00" },
519 {"Maldives" ,"MV" , "960" , 7 , "00" },
520 {"Mali" ,"ML" , "223" , 8 , "00" },
521 {"Malta" ,"MT" , "356" , 8 , "00" },
522 {"Marshall Islands" ,"MH" , "692" , 7 , "011" },
523 {"Martinique" ,"MQ" , "596" , 9 , "00" },
524 {"Mauritania" ,"MR" , "222" , 8 , "00" },
525 {"Mauritius" ,"MU" , "230" , 7 , "00" },
526 {"Mayotte Island" ,"YT" , "262" , 9 , "00" },
527 {"Mexico" ,"MX" , "52" , 10 , "00" },
528 {"Micronesia" ,"FM" , "691" , 7 , "011" },
529 {"Moldova" ,"MD" , "373" , 8 , "00" },
530 {"Monaco" ,"MC" , "377" , 8 , "00" },
531 {"Mongolia" ,"MN" , "976" , 8 , "001" },
532 {"Montenegro" ,"ME" , "382" , 8 , "00" },
533 {"Montserrat" ,"MS" , "664" , 10 , "011" },
534 {"Morocco" ,"MA" , "212" , 9 , "00" },
535 {"Mozambique" ,"MZ" , "258" , 9 , "00" },
536 {"Myanmar" ,"MM" , "95" , 8 , "00" },
537 {"Namibia" ,"NA" , "264" , 9 , "00" },
538 {"Nauru" ,"NR" , "674" , 7 , "00" },
539 {"Nepal" ,"NP" , "43" , 10 , "00" },
540 {"Netherlands" ,"NL" , "31" , 9 , "00" },
541 {"New Caledonia" ,"NC" , "687" , 6 , "00" },
542 {"New Zealand" ,"NZ" , "64" , 10 , "00" },
543 {"Nicaragua" ,"NI" , "505" , 8 , "00" },
544 {"Niger" ,"NE" , "227" , 8 , "00" },
545 {"Nigeria" ,"NG" , "234" , 10 , "009" },
546 {"Niue" ,"NU" , "683" , 4 , "00" },
547 {"Norfolk Island" ,"NF" , "672" , 5 , "00" },
548 {"Northern Mariana Islands" ,"MP" , "1" , 10 , "011" },
549 {"Norway" ,"NO" , "47" , 8 , "00" },
550 {"Oman" ,"OM" , "968" , 8 , "00" },
551 {"Pakistan" ,"PK" , "92" , 10 , "00" },
552 {"Palau" ,"PW" , "680" , 7 , "011" },
553 {"Palestine" ,"PS" , "970" , 9 , "00" },
554 {"Panama" ,"PA" , "507" , 8 , "00" },
555 {"Papua New Guinea" ,"PG" , "675" , 8 , "00" },
556 {"Paraguay" ,"PY" , "595" , 9 , "00" },
557 {"Peru" ,"PE" , "51" , 9 , "00" },
558 {"Philippines" ,"PH" , "63" , 10 , "00" },
559 {"Poland" ,"PL" , "48" , 9 , "00" },
560 {"Portugal" ,"PT" , "351" , 9 , "00" },
561 {"Puerto Rico" ,"PR" , "1" , 10 , "011" },
562 {"Qatar" ,"QA" , "974" , 8 , "00" },
563 {"R�union Island" ,"RE" , "262" , 9 , "011" },
564 {"Romania" ,"RO" , "40" , 9 , "00" },
565 {"Russian Federation" ,"RU" , "7" , 10 , "8" },
566 {"Rwanda" ,"RW" , "250" , 9 , "00" },
567 {"Saint Helena" ,"SH" , "290" , 4 , "00" },
568 {"Saint Kitts and Nevis" ,"KN" , "1" , 10 , "011" },
569 {"Saint Lucia" ,"LC" , "1" , 10 , "011" },
570 {"Saint Pierre and Miquelon" ,"PM" , "508" , 6 , "00" },
571 {"Saint Vincent and the Grenadines","VC" , "1" , 10 , "011" },
572 {"Samoa" ,"WS" , "685" , 7 , "0" },
573 {"San Marino" ,"SM" , "378" , 10 , "00" },
574 {"S�o Tom� and Pr�ncipe" ,"ST" , "239" , 7 , "00" },
575 {"Saudi Arabia" ,"SA" , "966" , 9 , "00" },
576 {"Senegal" ,"SN" , "221" , 9 , "00" },
577 {"Serbia" ,"RS" , "381" , 9 , "00" },
578 {"Seychelles" ,"SC" , "248" , 7 , "00" },
579 {"Sierra Leone" ,"SL" , "232" , 8 , "00" },
580 {"Singapore" ,"SG" , "65" , 8 , "001" },
581 {"Slovakia" ,"SK" , "421" , 9 , "00" },
582 {"Slovenia" ,"SI" , "386" , 8 , "00" },
583 {"Solomon Islands" ,"SB" , "677" , 7 , "00" },
584 {"Somalia" ,"SO" , "252" , 8 , "00" },
585 {"South Africa" ,"ZA" , "27" , 9 , "00" },
586 {"Spain" ,"ES" , "34" , 9 , "00" },
587 {"Sri Lanka" ,"LK" , "94" , 9 , "00" },
588 {"Sudan" ,"SD" , "249" , 9 , "00" },
589 {"Suriname" ,"SR" , "597" , 7 , "00" },
590 {"Swaziland" ,"SZ" , "268" , 8 , "00" },
591 {"Sweden" ,"SE" , "1" , 9 , "00" },
592 {"Switzerland" ,"XK" , "41" , 9 , "00" },
593 {"Syria" ,"SY" , "963" , 9 , "00" },
594 {"Taiwan" ,"TW" , "886" , 9 , "810" },
595 {"Tajikistan" ,"TJ" , "992" , 9 , "002" },
596 {"Tanzania" ,"TZ" , "255" , 9 , "000" },
597 {"Thailand" ,"TH" , "66" , 9 , "001" },
598 {"Togo" ,"TG" , "228" , 8 , "00" },
599 {"Tokelau" ,"TK" , "690" , 4 , "00" },
600 {"Tonga" ,"TO" , "676" , 5 , "00" },
601 {"Trinidad and Tobago" ,"TT" , "1" , 10 , "011" },
602 {"Tunisia" ,"TN" , "216" , 8 , "00" },
603 {"Turkey" ,"TR" , "90" , 10 , "00" },
604 {"Turkmenistan" ,"TM" , "993" , 8 , "00" },
605 {"Turks and Caicos Islands" ,"TC" , "1" , 7 , "0" },
606 {"Tuvalu" ,"TV" , "688" , 5 , "00" },
607 {"Uganda" ,"UG" , "256" , 9 , "000" },
608 {"Ukraine" ,"UA" , "380" , 9 , "00" },
609 {"United Arab Emirates" ,"AE" , "971" , 9 , "00" },
610 {"United Kingdom" ,"UK" , "44" , 10 , "00" },
611 {"United States" ,"US" , "1" , 10 , "011" },
612 {"Uruguay" ,"UY" , "598" , 8 , "00" },
613 {"Uzbekistan" ,"UZ" , "998" , 9 , "8" },
614 {"Vanuatu" ,"VU" , "678" , 7 , "00" },
615 {"Venezuela" ,"VE" , "58" , 10 , "00" },
616 {"Vietnam" ,"VN" , "84" , 9 , "00" },
617 {"Wallis and Futuna" ,"WF" , "681" , 5 , "00" },
618 {"Yemen" ,"YE" , "967" , 9 , "00" },
619 {"Zambia" ,"ZM" , "260" , 9 , "00" },
620 {"Zimbabwe" ,"ZW" , "263" , 9 , "00" },
621 {NULL ,NULL , "" , 0 , NULL }
623 static dial_plan_t most_common_dialplan={ "generic" ,"", "", 10, "00"};
625 int linphone_dial_plan_lookup_ccc_from_e164(const char* e164) {
626 dial_plan_t* dial_plan;
627 dial_plan_t* elected_dial_plan=NULL;
637 for (dial_plan=(dial_plan_t*)dial_plans; dial_plan->country!=NULL; dial_plan++) {
638 if (strncmp(dial_plan->ccc,&e164[1],i) == 0) {
639 elected_dial_plan=dial_plan;
643 } while ((found>1 || found==0) && i < sizeof(dial_plan->ccc));
645 return atoi(elected_dial_plan->ccc);
647 return -1; /*not found */
651 int linphone_dial_plan_lookup_ccc_from_iso(const char* iso) {
652 dial_plan_t* dial_plan;
653 for (dial_plan=(dial_plan_t*)dial_plans; dial_plan->country!=NULL; dial_plan++) {
654 if (strcmp(iso, dial_plan->iso_country_code)==0) {
655 return atoi(dial_plan->ccc);
661 static void lookup_dial_plan(const char *ccc, dial_plan_t *plan){
663 for(i=0;dial_plans[i].country!=NULL;++i){
664 if (strcmp(ccc,dial_plans[i].ccc)==0){
669 /*else return a generic "most common" dial plan*/
670 *plan=most_common_dialplan;
671 strcpy(plan->ccc,ccc);
674 static bool_t is_a_phone_number(const char *username){
676 for(p=username;*p!='\0';++p){
690 static char *flatten_number(const char *number){
691 char *result=ms_malloc0(strlen(number)+1);
694 for(r=number;*r!='\0';++r){
695 if (*r=='+' || isdigit(*r)){
703 static void replace_plus(const char *src, char *dest, size_t destlen, const char *icp){
706 if (icp && src[0]=='+' && (destlen>(i=strlen(icp))) ){
711 for(;(i<destlen-1) && *src!='\0';++i){
719 int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len){
721 if (is_a_phone_number(username)){
723 flatten=flatten_number(username);
724 ms_message("Flattened number is '%s'",flatten);
726 if (proxy->dial_prefix==NULL || proxy->dial_prefix[0]=='\0'){
727 /*no prefix configured, nothing else to do*/
728 strncpy(result,flatten,result_len);
732 dial_plan_t dialplan;
733 lookup_dial_plan(proxy->dial_prefix,&dialplan);
734 ms_message("Using dialplan '%s'",dialplan.country);
735 if (flatten[0]=='+' || strstr(flatten,dialplan.icp)==flatten){
736 /* the number has international prefix or +, so nothing to do*/
737 ms_message("Prefix already present.");
738 /*eventually replace the plus*/
739 replace_plus(flatten,result,result_len,proxy->dial_escape_plus ? dialplan.icp : NULL);
745 numlen=strlen(flatten);
746 /*keep at most national number significant digits */
747 skip=numlen-dialplan.nnl;
749 /*first prepend internation calling prefix or +*/
750 if (proxy->dial_escape_plus){
751 strncpy(result,dialplan.icp,result_len);
752 i+=strlen(dialplan.icp);
754 strncpy(result,"+",result_len);
758 if (result_len-i>strlen(dialplan.ccc)){
759 strcpy(result+i,dialplan.ccc);
760 i+=strlen(dialplan.ccc);
763 strncpy(result+i,flatten+skip,result_len-i-1);
767 }else strncpy(result,username,result_len);
772 * Commits modification made to the proxy configuration.
774 int linphone_proxy_config_done(LinphoneProxyConfig *obj)
776 if (!linphone_proxy_config_check(obj->lc,obj)) return -1;
778 linphone_proxy_config_write_all_to_config_file(obj->lc);
782 void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm)
784 if (cfg->realm!=NULL) {
788 if (realm!=NULL) cfg->realm=ms_strdup(realm);
791 int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy,
792 LinphoneOnlineStatus presence_mode){
794 SalOp *op=sal_op_new(proxy->lc->sal);
795 err=sal_publish(op,linphone_proxy_config_get_identity(proxy),
796 linphone_proxy_config_get_identity(proxy),linphone_online_status_to_sal(presence_mode));
797 if (proxy->publish_op!=NULL)
798 sal_op_release(proxy->publish_op);
799 proxy->publish_op=op;
804 * Returns the route set for this proxy configuration.
806 const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj){
807 return obj->reg_route;
811 * Returns the SIP identity that belongs to this proxy configuration.
813 * The SIP identity is a SIP address (Display Name <sip:username@@domain> )
815 const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj){
816 return obj->reg_identity;
820 * Returns TRUE if PUBLISH request is enabled for this proxy.
822 bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj){
827 * Returns the proxy's SIP address.
829 const char *linphone_proxy_config_get_addr(const LinphoneProxyConfig *obj){
830 return obj->reg_proxy;
834 * Returns the duration of registration.
836 int linphone_proxy_config_get_expires(const LinphoneProxyConfig *obj){
841 * Returns TRUE if registration to the proxy is enabled.
843 bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *obj){
844 return obj->reg_sendregister;
848 * Set optional contact parameters that will be added to the contact information sent in the registration.
849 * @param obj the proxy config object
850 * @param contact_params a string contaning the additional parameters in text form, like "myparam=something;myparam2=something_else"
852 * 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.
853 * 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>.
855 void linphone_proxy_config_set_contact_parameters(LinphoneProxyConfig *obj, const char *contact_params){
856 if (obj->contact_params) {
857 ms_free(obj->contact_params);
858 obj->contact_params=NULL;
861 obj->contact_params=ms_strdup(contact_params);
866 * Returns previously set contact parameters.
868 const char *linphone_proxy_config_get_contact_parameters(const LinphoneProxyConfig *obj){
869 return obj->contact_params;
872 struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *obj){
877 * Add a proxy configuration.
878 * This will start registration on the proxy, if registration is enabled.
880 int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
881 if (!linphone_proxy_config_check(lc,cfg)) {
884 if (ms_list_find(lc->sip_conf.proxies,cfg)!=NULL){
885 ms_warning("ProxyConfig already entered, ignored.");
888 lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)cfg);
889 linphone_proxy_config_apply(cfg,lc);
894 * Removes a proxy configuration.
896 * LinphoneCore will then automatically unregister and place the proxy configuration
897 * on a deleted list. For that reason, a removed proxy does NOT need to be freed.
899 void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
900 /* check this proxy config is in the list before doing more*/
901 if (ms_list_find(lc->sip_conf.proxies,cfg)==NULL){
902 ms_error("linphone_core_remove_proxy_config: LinphoneProxyConfig %p is not known by LinphoneCore (programming error?)",cfg);
905 lc->sip_conf.proxies=ms_list_remove(lc->sip_conf.proxies,(void *)cfg);
906 /* add to the list of destroyed proxies, so that the possible unREGISTER request can succeed authentication */
907 lc->sip_conf.deleted_proxies=ms_list_append(lc->sip_conf.deleted_proxies,(void *)cfg);
908 cfg->deletion_date=ms_time(NULL);
909 if (cfg->state==LinphoneRegistrationOk){
910 /* this will unREGISTER */
911 linphone_proxy_config_edit(cfg);
913 if (lc->default_proxy==cfg){
914 lc->default_proxy=NULL;
916 linphone_proxy_config_write_all_to_config_file(lc);
919 * Erase all proxies from config.
923 void linphone_core_clear_proxy_config(LinphoneCore *lc){
924 MSList* list=ms_list_copy(linphone_core_get_proxy_config_list((const LinphoneCore*)lc));
926 for(;list!=NULL;list=list->next){
927 linphone_core_remove_proxy_config(lc,(LinphoneProxyConfig *)list->data);
930 linphone_proxy_config_write_all_to_config_file(lc);
933 * Sets the default proxy.
935 * This default proxy must be part of the list of already entered LinphoneProxyConfig.
936 * Toggling it as default will make LinphoneCore use the identity associated with
937 * the proxy configuration in all incoming and outgoing calls.
939 void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config){
940 /* check if this proxy is in our list */
942 if (ms_list_find(lc->sip_conf.proxies,config)==NULL){
943 ms_warning("Bad proxy address: it is not in the list !");
944 lc->default_proxy=NULL;
948 lc->default_proxy=config;
949 if (linphone_core_ready(lc))
950 lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
953 void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){
954 if (index<0) linphone_core_set_default_proxy(lc,NULL);
955 else linphone_core_set_default_proxy(lc,ms_list_nth_data(lc->sip_conf.proxies,index));
959 * Returns the default proxy configuration, that is the one used to determine the current identity.
961 int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config){
963 if (config!=NULL) *config=lc->default_proxy;
964 if (lc->default_proxy!=NULL){
965 pos=ms_list_position(lc->sip_conf.proxies,ms_list_find(lc->sip_conf.proxies,(void *)lc->default_proxy));
971 * Returns an unmodifiable list of entered proxy configurations.
973 const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){
974 return lc->sip_conf.proxies;
977 void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyConfig *obj, int index)
981 sprintf(key,"proxy_%i",index);
982 lp_config_clean_section(config,key);
986 if (obj->type!=NULL){
987 lp_config_set_string(config,key,"type",obj->type);
989 if (obj->reg_proxy!=NULL){
990 lp_config_set_string(config,key,"reg_proxy",obj->reg_proxy);
992 if (obj->reg_route!=NULL){
993 lp_config_set_string(config,key,"reg_route",obj->reg_route);
995 if (obj->reg_identity!=NULL){
996 lp_config_set_string(config,key,"reg_identity",obj->reg_identity);
998 if (obj->contact_params!=NULL){
999 lp_config_set_string(config,key,"contact_parameters",obj->contact_params);
1001 lp_config_set_int(config,key,"reg_expires",obj->expires);
1002 lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister);
1003 lp_config_set_int(config,key,"publish",obj->publish);
1004 lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus);
1005 lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix);
1010 LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config, int index)
1013 const char *identity;
1015 LinphoneProxyConfig *cfg;
1018 sprintf(key,"proxy_%i",index);
1020 if (!lp_config_has_section(config,key)){
1024 cfg=linphone_proxy_config_new();
1026 identity=lp_config_get_string(config,key,"reg_identity",NULL);
1027 proxy=lp_config_get_string(config,key,"reg_proxy",NULL);
1029 linphone_proxy_config_set_identity(cfg,identity);
1030 linphone_proxy_config_set_server_addr(cfg,proxy);
1032 tmp=lp_config_get_string(config,key,"reg_route",NULL);
1033 if (tmp!=NULL) linphone_proxy_config_set_route(cfg,tmp);
1035 linphone_proxy_config_set_contact_parameters(cfg,lp_config_get_string(config,key,"contact_parameters",NULL));
1037 linphone_proxy_config_expires(cfg,lp_config_get_int(config,key,"reg_expires",LP_CONFIG_DEFAULT_INT(config,"reg_expires",600)));
1038 linphone_proxy_config_enableregister(cfg,lp_config_get_int(config,key,"reg_sendregister",0));
1040 linphone_proxy_config_enable_publish(cfg,lp_config_get_int(config,key,"publish",0));
1042 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)));
1043 linphone_proxy_config_set_dial_prefix(cfg,lp_config_get_string(config,key,"dial_prefix",LP_CONFIG_DEFAULT_STRING(config,"dial_prefix",NULL)));
1045 tmp=lp_config_get_string(config,key,"type",NULL);
1046 if (tmp!=NULL && strlen(tmp)>0)
1047 linphone_proxy_config_set_sip_setup(cfg,tmp);
1052 static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){
1053 SipSetupContext *ssc;
1054 SipSetup *ss=sip_setup_lookup(cfg->type);
1055 LinphoneCore *lc=linphone_proxy_config_get_core(cfg);
1058 ssc=sip_setup_context_new(ss,cfg);
1060 if (cfg->reg_identity==NULL){
1061 ms_error("Invalid identity for this proxy configuration.");
1064 caps=sip_setup_context_get_capabilities(ssc);
1065 if (caps & SIP_SETUP_CAP_ACCOUNT_MANAGER){
1066 if (sip_setup_context_login_account(ssc,cfg->reg_identity,NULL)!=0){
1067 if (lc->vtable.display_warning){
1068 char *tmp=ms_strdup_printf(_("Could not login as %s"),cfg->reg_identity);
1069 lc->vtable.display_warning(lc,tmp);
1075 if (caps & SIP_SETUP_CAP_PROXY_PROVIDER){
1077 if (sip_setup_context_get_proxy(ssc,NULL,proxy,sizeof(proxy))==0){
1078 linphone_proxy_config_set_server_addr(cfg,proxy);
1080 ms_error("Could not retrieve proxy uri !");
1086 SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg){
1087 if (cfg->ssctx!=NULL) return cfg->ssctx->funcs;
1088 if (cfg->type!=NULL){
1089 return sip_setup_lookup(cfg->type);
1094 void linphone_proxy_config_update(LinphoneProxyConfig *cfg){
1095 LinphoneCore *lc=cfg->lc;
1097 if (cfg->type && cfg->ssctx==NULL){
1098 linphone_proxy_config_activate_sip_setup(cfg);
1100 if ((!lc->sip_conf.register_only_when_network_is_up || lc->network_reachable) &&
1101 (!lc->sip_conf.register_only_when_upnp_is_ok || linphone_core_get_upnp_state(lc) == LinphoneUpnpStateOk))
1102 linphone_proxy_config_register(cfg);
1103 if (cfg->publish && cfg->publish_op==NULL){
1104 linphone_proxy_config_send_publish(cfg,lc->presence_mode);
1110 void linphone_proxy_config_set_sip_setup(LinphoneProxyConfig *cfg, const char *type){
1113 cfg->type=ms_strdup(type);
1114 if (linphone_proxy_config_get_addr(cfg)==NULL){
1115 /*put a placeholder so that the sip setup gets saved into the config */
1116 linphone_proxy_config_set_server_addr(cfg,"sip:undefined");
1120 SipSetupContext *linphone_proxy_config_get_sip_setup_context(LinphoneProxyConfig *cfg){
1128 LinphoneAccountCreator *linphone_account_creator_new(struct _LinphoneCore *core, const char *type){
1129 LinphoneAccountCreator *obj;
1130 LinphoneProxyConfig *cfg;
1131 SipSetup *ss=sip_setup_lookup(type);
1132 SipSetupContext *ssctx;
1136 if (!(sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_ACCOUNT_MANAGER)){
1137 ms_error("%s cannot manage accounts.",type);
1140 obj=ms_new0(LinphoneAccountCreator,1);
1141 cfg=linphone_proxy_config_new();
1142 ssctx=sip_setup_context_new(ss,cfg);
1145 set_string(&obj->domain,sip_setup_context_get_domains(ssctx)[0]);
1150 void linphone_account_creator_set_username(LinphoneAccountCreator *obj, const char *username){
1151 set_string(&obj->username,username);
1154 void linphone_account_creator_set_password(LinphoneAccountCreator *obj, const char *password){
1155 set_string(&obj->password,password);
1158 void linphone_account_creator_set_domain(LinphoneAccountCreator *obj, const char *domain){
1159 set_string(&obj->domain,domain);
1162 void linphone_account_creator_set_route(LinphoneAccountCreator *obj, const char *route) {
1163 set_string(&obj->route,route);
1166 void linphone_account_creator_set_email(LinphoneAccountCreator *obj, const char *email) {
1167 set_string(&obj->email,email);
1170 void linphone_account_creator_set_suscribe(LinphoneAccountCreator *obj, int suscribe) {
1171 obj->suscribe = suscribe;
1174 const char * linphone_account_creator_get_username(LinphoneAccountCreator *obj){
1175 return obj->username;
1178 const char * linphone_account_creator_get_domain(LinphoneAccountCreator *obj){
1182 int linphone_account_creator_test_existence(LinphoneAccountCreator *obj){
1183 SipSetupContext *ssctx=obj->ssctx;
1184 char *uri=ms_strdup_printf("%s@%s",obj->username,obj->domain);
1185 int err=sip_setup_context_account_exists(ssctx,uri);
1190 int linphone_account_creator_test_validation(LinphoneAccountCreator *obj) {
1191 SipSetupContext *ssctx=obj->ssctx;
1192 int err=sip_setup_context_account_validated(ssctx,obj->username);
1196 LinphoneProxyConfig * linphone_account_creator_validate(LinphoneAccountCreator *obj){
1197 SipSetupContext *ssctx=obj->ssctx;
1198 char *uri=ms_strdup_printf("%s@%s",obj->username,obj->domain);
1199 int err=sip_setup_context_create_account(ssctx, uri, obj->password, obj->email, obj->suscribe);
1202 obj->succeeded=TRUE;
1203 return sip_setup_context_get_proxy_config(ssctx);
1208 void linphone_account_creator_destroy(LinphoneAccountCreator *obj){
1210 ms_free(obj->username);
1212 ms_free(obj->password);
1214 ms_free(obj->domain);
1215 if (!obj->succeeded){
1216 linphone_proxy_config_destroy(sip_setup_context_get_proxy_config(obj->ssctx));
1220 void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cr, void * ud) {
1224 void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) {
1225 return cr->user_data;
1228 void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){
1229 LinphoneCore *lc=cfg->lc;
1231 if (lc && lc->vtable.registration_state_changed){
1232 lc->vtable.registration_state_changed(lc,cfg,state,message);
1236 LinphoneRegistrationState linphone_proxy_config_get_state(const LinphoneProxyConfig *cfg){
1240 const char *linphone_registration_state_to_string(LinphoneRegistrationState cs){
1242 case LinphoneRegistrationCleared:
1243 return "LinphoneRegistrationCleared";
1245 case LinphoneRegistrationNone:
1246 return "LinphoneRegistrationNone";
1248 case LinphoneRegistrationProgress:
1249 return "LinphoneRegistrationProgress";
1251 case LinphoneRegistrationOk:
1252 return "LinphoneRegistrationOk";
1254 case LinphoneRegistrationFailed:
1255 return "LinphoneRegistrationFailed";
1261 LinphoneReason linphone_proxy_config_get_error(const LinphoneProxyConfig *cfg) {
1265 void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg,LinphoneReason error) {