config_global.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * Mark Michelson <mmichelson@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. #include "asterisk.h"
  19. #include <pjsip.h>
  20. #include <pjlib.h>
  21. #include "asterisk/res_pjsip.h"
  22. #include "include/res_pjsip_private.h"
  23. #include "asterisk/pbx.h"
  24. #include "asterisk/sorcery.h"
  25. #include "asterisk/taskprocessor.h"
  26. #include "asterisk/ast_version.h"
  27. #include "asterisk/res_pjsip_cli.h"
  28. #define DEFAULT_MAX_FORWARDS 70
  29. #define DEFAULT_KEEPALIVE_INTERVAL 90
  30. #define DEFAULT_USERAGENT_PREFIX "Asterisk PBX"
  31. #define DEFAULT_OUTBOUND_ENDPOINT "default_outbound_endpoint"
  32. #define DEFAULT_DEBUG "no"
  33. #define DEFAULT_ENDPOINT_IDENTIFIER_ORDER "ip,username,anonymous"
  34. #define DEFAULT_MAX_INITIAL_QUALIFY_TIME 0
  35. #define DEFAULT_FROM_USER "asterisk"
  36. #define DEFAULT_REALM "asterisk"
  37. #define DEFAULT_REGCONTEXT ""
  38. #define DEFAULT_CONTACT_EXPIRATION_CHECK_INTERVAL 30
  39. #define DEFAULT_DISABLE_MULTI_DOMAIN 0
  40. #define DEFAULT_VOICEMAIL_EXTENSION ""
  41. #define DEFAULT_UNIDENTIFIED_REQUEST_COUNT 5
  42. #define DEFAULT_UNIDENTIFIED_REQUEST_PERIOD 5
  43. #define DEFAULT_UNIDENTIFIED_REQUEST_PRUNE_INTERVAL 30
  44. #define DEFAULT_MWI_TPS_QUEUE_HIGH AST_TASKPROCESSOR_HIGH_WATER_LEVEL
  45. #define DEFAULT_MWI_TPS_QUEUE_LOW -1
  46. #define DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED 0
  47. #define DEFAULT_IGNORE_URI_USER_OPTIONS 0
  48. #define DEFAULT_USE_CALLERID_CONTACT 0
  49. #define DEFAULT_SEND_CONTACT_STATUS_ON_UPDATE_REGISTRATION 1
  50. /*!
  51. * \brief Cached global config object
  52. *
  53. * \details
  54. * Cached so we don't have to keep asking sorcery for the config.
  55. * We could ask for it hundreds of times a second if not more.
  56. */
  57. static AO2_GLOBAL_OBJ_STATIC(global_cfg);
  58. static char default_useragent[256];
  59. struct global_config {
  60. SORCERY_OBJECT(details);
  61. AST_DECLARE_STRING_FIELDS(
  62. AST_STRING_FIELD(useragent);
  63. AST_STRING_FIELD(regcontext);
  64. AST_STRING_FIELD(default_outbound_endpoint);
  65. /*! Debug logging yes|no|host */
  66. AST_STRING_FIELD(debug);
  67. /*! Order by which endpoint identifiers are checked (comma separated list) */
  68. AST_STRING_FIELD(endpoint_identifier_order);
  69. /*! User name to place in From header if there is no better option */
  70. AST_STRING_FIELD(default_from_user);
  71. /*! Default voicemail extension */
  72. AST_STRING_FIELD(default_voicemail_extension);
  73. /*! Realm to use in challenges before an endpoint is identified */
  74. AST_STRING_FIELD(default_realm);
  75. );
  76. /*! Value to put in Max-Forwards header */
  77. unsigned int max_forwards;
  78. /*! The interval at which to send keep alive messages to active connection-oriented transports */
  79. unsigned int keep_alive_interval;
  80. /*! The maximum time for all contacts to be qualified at startup */
  81. unsigned int max_initial_qualify_time;
  82. /*! The interval at which to check for expired contacts */
  83. unsigned int contact_expiration_check_interval;
  84. /*! Nonzero to disable multi domain support */
  85. unsigned int disable_multi_domain;
  86. /*! The maximum number of unidentified requests per source IP address before a security event is logged */
  87. unsigned int unidentified_request_count;
  88. /*! The period during which unidentified requests are accumulated */
  89. unsigned int unidentified_request_period;
  90. /*! Interval at which expired unidentifed requests will be pruned */
  91. unsigned int unidentified_request_prune_interval;
  92. struct {
  93. /*! Taskprocessor high water alert trigger level */
  94. unsigned int tps_queue_high;
  95. /*! Taskprocessor low water clear alert level. */
  96. int tps_queue_low;
  97. /*! Nonzero to disable sending unsolicited mwi to all endpoints on startup */
  98. unsigned int disable_initial_unsolicited;
  99. } mwi;
  100. /*! Nonzero if URI user field options are ignored. */
  101. unsigned int ignore_uri_user_options;
  102. /*! Nonzero if CALLERID(num) is to be used as the default contact username instead of default_from_user */
  103. unsigned int use_callerid_contact;
  104. /*! Nonzero if need to send AMI ContactStatus event when a contact is updated */
  105. unsigned int send_contact_status_on_update_registration;
  106. };
  107. static void global_destructor(void *obj)
  108. {
  109. struct global_config *cfg = obj;
  110. ast_string_field_free_memory(cfg);
  111. }
  112. static void *global_alloc(const char *name)
  113. {
  114. struct global_config *cfg;
  115. cfg = ast_sorcery_generic_alloc(sizeof(*cfg), global_destructor);
  116. if (!cfg || ast_string_field_init(cfg, 100)) {
  117. ao2_cleanup(cfg);
  118. return NULL;
  119. }
  120. return cfg;
  121. }
  122. /*
  123. * There is ever only one global section, so we can use a single global
  124. * value here to track the regcontext through reloads.
  125. */
  126. static char *previous_regcontext = NULL;
  127. static int check_regcontext(const struct global_config *cfg)
  128. {
  129. char *current = NULL;
  130. if (previous_regcontext && !strcmp(previous_regcontext, cfg->regcontext)) {
  131. /* Nothing changed so nothing to do */
  132. return 0;
  133. }
  134. if (!ast_strlen_zero(cfg->regcontext)) {
  135. current = ast_strdup(cfg->regcontext);
  136. if (!current) {
  137. return -1;
  138. }
  139. if (ast_sip_persistent_endpoint_add_to_regcontext(cfg->regcontext)) {
  140. ast_free(current);
  141. return -1;
  142. }
  143. }
  144. if (!ast_strlen_zero(previous_regcontext)) {
  145. ast_context_destroy_by_name(previous_regcontext, "PJSIP");
  146. ast_free(previous_regcontext);
  147. previous_regcontext = NULL;
  148. }
  149. if (current) {
  150. previous_regcontext = current;
  151. }
  152. return 0;
  153. }
  154. static int global_apply(const struct ast_sorcery *sorcery, void *obj)
  155. {
  156. struct global_config *cfg = obj;
  157. char max_forwards[10];
  158. if (ast_strlen_zero(cfg->debug)) {
  159. ast_log(LOG_ERROR,
  160. "Global option 'debug' can't be empty. Set it to a valid value or remove the entry to accept 'no' as the default\n");
  161. return -1;
  162. }
  163. if (ast_strlen_zero(cfg->default_from_user)) {
  164. ast_log(LOG_ERROR,
  165. "Global option 'default_from_user' can't be empty. Set it to a valid value or remove the entry to accept 'asterisk' as the default\n");
  166. return -1;
  167. }
  168. snprintf(max_forwards, sizeof(max_forwards), "%u", cfg->max_forwards);
  169. ast_sip_add_global_request_header("Max-Forwards", max_forwards, 1);
  170. ast_sip_add_global_request_header("User-Agent", cfg->useragent, 1);
  171. ast_sip_add_global_response_header("Server", cfg->useragent, 1);
  172. if (check_regcontext(cfg)) {
  173. return -1;
  174. }
  175. ao2_t_global_obj_replace_unref(global_cfg, cfg, "Applying global settings");
  176. return 0;
  177. }
  178. static struct global_config *get_global_cfg(void)
  179. {
  180. return ao2_global_obj_ref(global_cfg);
  181. }
  182. char *ast_sip_global_default_outbound_endpoint(void)
  183. {
  184. char *str;
  185. struct global_config *cfg;
  186. cfg = get_global_cfg();
  187. if (!cfg) {
  188. return ast_strdup(DEFAULT_OUTBOUND_ENDPOINT);
  189. }
  190. str = ast_strdup(cfg->default_outbound_endpoint);
  191. ao2_ref(cfg, -1);
  192. return str;
  193. }
  194. char *ast_sip_get_debug(void)
  195. {
  196. char *res;
  197. struct global_config *cfg;
  198. cfg = get_global_cfg();
  199. if (!cfg) {
  200. return ast_strdup(DEFAULT_DEBUG);
  201. }
  202. res = ast_strdup(cfg->debug);
  203. ao2_ref(cfg, -1);
  204. return res;
  205. }
  206. char *ast_sip_get_regcontext(void)
  207. {
  208. char *res;
  209. struct global_config *cfg;
  210. cfg = get_global_cfg();
  211. if (!cfg) {
  212. return ast_strdup(DEFAULT_REGCONTEXT);
  213. }
  214. res = ast_strdup(cfg->regcontext);
  215. ao2_ref(cfg, -1);
  216. return res;
  217. }
  218. char *ast_sip_get_default_voicemail_extension(void)
  219. {
  220. char *res;
  221. struct global_config *cfg;
  222. cfg = get_global_cfg();
  223. if (!cfg) {
  224. return ast_strdup(DEFAULT_VOICEMAIL_EXTENSION);
  225. }
  226. res = ast_strdup(cfg->default_voicemail_extension);
  227. ao2_ref(cfg, -1);
  228. return res;
  229. }
  230. char *ast_sip_get_endpoint_identifier_order(void)
  231. {
  232. char *res;
  233. struct global_config *cfg;
  234. cfg = get_global_cfg();
  235. if (!cfg) {
  236. return ast_strdup(DEFAULT_ENDPOINT_IDENTIFIER_ORDER);
  237. }
  238. res = ast_strdup(cfg->endpoint_identifier_order);
  239. ao2_ref(cfg, -1);
  240. return res;
  241. }
  242. unsigned int ast_sip_get_keep_alive_interval(void)
  243. {
  244. unsigned int interval;
  245. struct global_config *cfg;
  246. cfg = get_global_cfg();
  247. if (!cfg) {
  248. return DEFAULT_KEEPALIVE_INTERVAL;
  249. }
  250. interval = cfg->keep_alive_interval;
  251. ao2_ref(cfg, -1);
  252. return interval;
  253. }
  254. unsigned int ast_sip_get_contact_expiration_check_interval(void)
  255. {
  256. unsigned int interval;
  257. struct global_config *cfg;
  258. cfg = get_global_cfg();
  259. if (!cfg) {
  260. return DEFAULT_CONTACT_EXPIRATION_CHECK_INTERVAL;
  261. }
  262. interval = cfg->contact_expiration_check_interval;
  263. ao2_ref(cfg, -1);
  264. return interval;
  265. }
  266. unsigned int ast_sip_get_disable_multi_domain(void)
  267. {
  268. unsigned int disable_multi_domain;
  269. struct global_config *cfg;
  270. cfg = get_global_cfg();
  271. if (!cfg) {
  272. return DEFAULT_DISABLE_MULTI_DOMAIN;
  273. }
  274. disable_multi_domain = cfg->disable_multi_domain;
  275. ao2_ref(cfg, -1);
  276. return disable_multi_domain;
  277. }
  278. unsigned int ast_sip_get_max_initial_qualify_time(void)
  279. {
  280. unsigned int time;
  281. struct global_config *cfg;
  282. cfg = get_global_cfg();
  283. if (!cfg) {
  284. return DEFAULT_MAX_INITIAL_QUALIFY_TIME;
  285. }
  286. time = cfg->max_initial_qualify_time;
  287. ao2_ref(cfg, -1);
  288. return time;
  289. }
  290. void ast_sip_get_unidentified_request_thresholds(unsigned int *count, unsigned int *period,
  291. unsigned int *prune_interval)
  292. {
  293. struct global_config *cfg;
  294. cfg = get_global_cfg();
  295. if (!cfg) {
  296. *count = DEFAULT_UNIDENTIFIED_REQUEST_COUNT;
  297. *period = DEFAULT_UNIDENTIFIED_REQUEST_PERIOD;
  298. *prune_interval = DEFAULT_UNIDENTIFIED_REQUEST_PRUNE_INTERVAL;
  299. return;
  300. }
  301. *count = cfg->unidentified_request_count;
  302. *period = cfg->unidentified_request_period;
  303. *prune_interval = cfg->unidentified_request_prune_interval;
  304. ao2_ref(cfg, -1);
  305. return;
  306. }
  307. void ast_sip_get_default_realm(char *realm, size_t size)
  308. {
  309. struct global_config *cfg;
  310. cfg = get_global_cfg();
  311. if (!cfg) {
  312. ast_copy_string(realm, DEFAULT_REALM, size);
  313. } else {
  314. ast_copy_string(realm, cfg->default_realm, size);
  315. ao2_ref(cfg, -1);
  316. }
  317. }
  318. void ast_sip_get_default_from_user(char *from_user, size_t size)
  319. {
  320. struct global_config *cfg;
  321. cfg = get_global_cfg();
  322. if (!cfg) {
  323. ast_copy_string(from_user, DEFAULT_FROM_USER, size);
  324. } else {
  325. ast_copy_string(from_user, cfg->default_from_user, size);
  326. ao2_ref(cfg, -1);
  327. }
  328. }
  329. unsigned int ast_sip_get_mwi_tps_queue_high(void)
  330. {
  331. unsigned int tps_queue_high;
  332. struct global_config *cfg;
  333. cfg = get_global_cfg();
  334. if (!cfg) {
  335. return DEFAULT_MWI_TPS_QUEUE_HIGH;
  336. }
  337. tps_queue_high = cfg->mwi.tps_queue_high;
  338. ao2_ref(cfg, -1);
  339. return tps_queue_high;
  340. }
  341. int ast_sip_get_mwi_tps_queue_low(void)
  342. {
  343. int tps_queue_low;
  344. struct global_config *cfg;
  345. cfg = get_global_cfg();
  346. if (!cfg) {
  347. return DEFAULT_MWI_TPS_QUEUE_LOW;
  348. }
  349. tps_queue_low = cfg->mwi.tps_queue_low;
  350. ao2_ref(cfg, -1);
  351. return tps_queue_low;
  352. }
  353. unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void)
  354. {
  355. unsigned int disable_initial_unsolicited;
  356. struct global_config *cfg;
  357. cfg = get_global_cfg();
  358. if (!cfg) {
  359. return DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED;
  360. }
  361. disable_initial_unsolicited = cfg->mwi.disable_initial_unsolicited;
  362. ao2_ref(cfg, -1);
  363. return disable_initial_unsolicited;
  364. }
  365. unsigned int ast_sip_get_ignore_uri_user_options(void)
  366. {
  367. unsigned int ignore_uri_user_options;
  368. struct global_config *cfg;
  369. cfg = get_global_cfg();
  370. if (!cfg) {
  371. return DEFAULT_IGNORE_URI_USER_OPTIONS;
  372. }
  373. ignore_uri_user_options = cfg->ignore_uri_user_options;
  374. ao2_ref(cfg, -1);
  375. return ignore_uri_user_options;
  376. }
  377. unsigned int ast_sip_get_use_callerid_contact(void)
  378. {
  379. unsigned int use_callerid_contact;
  380. struct global_config *cfg;
  381. cfg = get_global_cfg();
  382. if (!cfg) {
  383. return DEFAULT_USE_CALLERID_CONTACT;
  384. }
  385. use_callerid_contact = cfg->use_callerid_contact;
  386. ao2_ref(cfg, -1);
  387. return use_callerid_contact;
  388. }
  389. unsigned int ast_sip_get_send_contact_status_on_update_registration(void)
  390. {
  391. unsigned int send_contact_status_on_update_registration;
  392. struct global_config *cfg;
  393. cfg = get_global_cfg();
  394. if (!cfg) {
  395. return DEFAULT_SEND_CONTACT_STATUS_ON_UPDATE_REGISTRATION;
  396. }
  397. send_contact_status_on_update_registration = cfg->send_contact_status_on_update_registration;
  398. ao2_ref(cfg, -1);
  399. return send_contact_status_on_update_registration;
  400. }
  401. /*!
  402. * \internal
  403. * \brief Observer to set default global object if none exist.
  404. *
  405. * \param name Module name owning the sorcery instance.
  406. * \param sorcery Instance being observed.
  407. * \param object_type Name of object being observed.
  408. * \param reloaded Non-zero if the object is being reloaded.
  409. *
  410. * \return Nothing
  411. */
  412. static void global_loaded_observer(const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)
  413. {
  414. struct ao2_container *globals;
  415. struct global_config *cfg;
  416. if (strcmp(object_type, "global")) {
  417. /* Not interested */
  418. return;
  419. }
  420. globals = ast_sorcery_retrieve_by_fields(sorcery, "global",
  421. AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
  422. if (globals) {
  423. int count;
  424. count = ao2_container_count(globals);
  425. ao2_ref(globals, -1);
  426. if (1 < count) {
  427. ast_log(LOG_ERROR,
  428. "At most one pjsip.conf type=global object can be defined. You have %d defined.\n",
  429. count);
  430. return;
  431. }
  432. if (count) {
  433. return;
  434. }
  435. }
  436. ast_debug(1, "No pjsip.conf type=global object exists so applying defaults.\n");
  437. cfg = ast_sorcery_alloc(sorcery, "global", NULL);
  438. if (!cfg) {
  439. return;
  440. }
  441. global_apply(sorcery, cfg);
  442. ao2_ref(cfg, -1);
  443. }
  444. static const struct ast_sorcery_instance_observer observer_callbacks_global = {
  445. .object_type_loaded = global_loaded_observer,
  446. };
  447. int sip_cli_print_global(struct ast_sip_cli_context *context)
  448. {
  449. struct global_config *cfg = get_global_cfg();
  450. if (!cfg) {
  451. cfg = ast_sorcery_alloc(ast_sip_get_sorcery(), "global", NULL);
  452. if (!cfg) {
  453. return -1;
  454. }
  455. }
  456. ast_str_append(&context->output_buffer, 0, "\nGlobal Settings:\n\n");
  457. ast_sip_cli_print_sorcery_objectset(cfg, context, 0);
  458. ao2_ref(cfg, -1);
  459. return 0;
  460. }
  461. int ast_sip_destroy_sorcery_global(void)
  462. {
  463. struct ast_sorcery *sorcery = ast_sip_get_sorcery();
  464. ast_sorcery_instance_observer_remove(sorcery, &observer_callbacks_global);
  465. if (previous_regcontext) {
  466. ast_context_destroy_by_name(previous_regcontext, "PJSIP");
  467. ast_free(previous_regcontext);
  468. }
  469. ao2_t_global_obj_release(global_cfg, "Module is unloading");
  470. return 0;
  471. }
  472. int ast_sip_initialize_sorcery_global(void)
  473. {
  474. struct ast_sorcery *sorcery = ast_sip_get_sorcery();
  475. snprintf(default_useragent, sizeof(default_useragent), "%s %s",
  476. DEFAULT_USERAGENT_PREFIX, ast_get_version());
  477. ast_sorcery_apply_default(sorcery, "global", "config", "pjsip.conf,criteria=type=global,single_object=yes,explicit_name=global");
  478. if (ast_sorcery_object_register(sorcery, "global", global_alloc, NULL, global_apply)) {
  479. return -1;
  480. }
  481. ast_sorcery_object_field_register(sorcery, "global", "type", "", OPT_NOOP_T, 0, 0);
  482. ast_sorcery_object_field_register(sorcery, "global", "max_forwards",
  483. __stringify(DEFAULT_MAX_FORWARDS),
  484. OPT_UINT_T, 0, FLDSET(struct global_config, max_forwards));
  485. ast_sorcery_object_field_register(sorcery, "global", "user_agent", default_useragent,
  486. OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, useragent));
  487. ast_sorcery_object_field_register(sorcery, "global", "default_outbound_endpoint",
  488. DEFAULT_OUTBOUND_ENDPOINT,
  489. OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, default_outbound_endpoint));
  490. ast_sorcery_object_field_register(sorcery, "global", "debug", DEFAULT_DEBUG,
  491. OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, debug));
  492. ast_sorcery_object_field_register(sorcery, "global", "endpoint_identifier_order",
  493. DEFAULT_ENDPOINT_IDENTIFIER_ORDER,
  494. OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, endpoint_identifier_order));
  495. ast_sorcery_object_field_register(sorcery, "global", "keep_alive_interval",
  496. __stringify(DEFAULT_KEEPALIVE_INTERVAL),
  497. OPT_UINT_T, 0, FLDSET(struct global_config, keep_alive_interval));
  498. ast_sorcery_object_field_register(sorcery, "global", "max_initial_qualify_time",
  499. __stringify(DEFAULT_MAX_INITIAL_QUALIFY_TIME),
  500. OPT_UINT_T, 0, FLDSET(struct global_config, max_initial_qualify_time));
  501. ast_sorcery_object_field_register(sorcery, "global", "default_from_user", DEFAULT_FROM_USER,
  502. OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, default_from_user));
  503. ast_sorcery_object_field_register(sorcery, "global", "default_voicemail_extension",
  504. DEFAULT_VOICEMAIL_EXTENSION, OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config,
  505. default_voicemail_extension));
  506. ast_sorcery_object_field_register(sorcery, "global", "regcontext", DEFAULT_REGCONTEXT,
  507. OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, regcontext));
  508. ast_sorcery_object_field_register(sorcery, "global", "contact_expiration_check_interval",
  509. __stringify(DEFAULT_CONTACT_EXPIRATION_CHECK_INTERVAL),
  510. OPT_UINT_T, 0, FLDSET(struct global_config, contact_expiration_check_interval));
  511. ast_sorcery_object_field_register(sorcery, "global", "disable_multi_domain",
  512. DEFAULT_DISABLE_MULTI_DOMAIN ? "yes" : "no",
  513. OPT_BOOL_T, 1, FLDSET(struct global_config, disable_multi_domain));
  514. ast_sorcery_object_field_register(sorcery, "global", "unidentified_request_count",
  515. __stringify(DEFAULT_UNIDENTIFIED_REQUEST_COUNT),
  516. OPT_UINT_T, 0, FLDSET(struct global_config, unidentified_request_count));
  517. ast_sorcery_object_field_register(sorcery, "global", "unidentified_request_period",
  518. __stringify(DEFAULT_UNIDENTIFIED_REQUEST_PERIOD),
  519. OPT_UINT_T, 0, FLDSET(struct global_config, unidentified_request_period));
  520. ast_sorcery_object_field_register(sorcery, "global", "unidentified_request_prune_interval",
  521. __stringify(DEFAULT_UNIDENTIFIED_REQUEST_PRUNE_INTERVAL),
  522. OPT_UINT_T, 0, FLDSET(struct global_config, unidentified_request_prune_interval));
  523. ast_sorcery_object_field_register(sorcery, "global", "default_realm", DEFAULT_REALM,
  524. OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, default_realm));
  525. ast_sorcery_object_field_register(sorcery, "global", "mwi_tps_queue_high",
  526. __stringify(DEFAULT_MWI_TPS_QUEUE_HIGH),
  527. OPT_UINT_T, 0, FLDSET(struct global_config, mwi.tps_queue_high));
  528. ast_sorcery_object_field_register(sorcery, "global", "mwi_tps_queue_low",
  529. __stringify(DEFAULT_MWI_TPS_QUEUE_LOW),
  530. OPT_INT_T, 0, FLDSET(struct global_config, mwi.tps_queue_low));
  531. ast_sorcery_object_field_register(sorcery, "global", "mwi_disable_initial_unsolicited",
  532. DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED ? "yes" : "no",
  533. OPT_BOOL_T, 1, FLDSET(struct global_config, mwi.disable_initial_unsolicited));
  534. ast_sorcery_object_field_register(sorcery, "global", "ignore_uri_user_options",
  535. DEFAULT_IGNORE_URI_USER_OPTIONS ? "yes" : "no",
  536. OPT_BOOL_T, 1, FLDSET(struct global_config, ignore_uri_user_options));
  537. ast_sorcery_object_field_register(sorcery, "global", "use_callerid_contact",
  538. DEFAULT_USE_CALLERID_CONTACT ? "yes" : "no",
  539. OPT_YESNO_T, 1, FLDSET(struct global_config, use_callerid_contact));
  540. ast_sorcery_object_field_register(sorcery, "global", "send_contact_status_on_update_registration",
  541. DEFAULT_SEND_CONTACT_STATUS_ON_UPDATE_REGISTRATION ? "yes" : "no",
  542. OPT_YESNO_T, 1, FLDSET(struct global_config, send_contact_status_on_update_registration));
  543. if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) {
  544. return -1;
  545. }
  546. return 0;
  547. }