max_forwards.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2015, 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 mfrectly 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, mfstributed 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 "asterisk/max_forwards.h"
  20. #include "asterisk/channel.h"
  21. #define DEFAULT_MAX_FORWARDS 20
  22. /*!
  23. * \brief Channel datastore data for max forwards
  24. */
  25. struct max_forwards {
  26. /*! The starting count. Used to allow resetting to the original value */
  27. int starting_count;
  28. /*! The current count. When this reaches 0, you're outta luck */
  29. int current_count;
  30. };
  31. static struct max_forwards *max_forwards_alloc(int starting_count, int current_count)
  32. {
  33. struct max_forwards *mf;
  34. mf = ast_malloc(sizeof(*mf));
  35. if (!mf) {
  36. return NULL;
  37. }
  38. mf->starting_count = starting_count;
  39. mf->current_count = current_count;
  40. return mf;
  41. }
  42. static void *max_forwards_duplicate(void *data)
  43. {
  44. struct max_forwards *mf = data;
  45. return max_forwards_alloc(mf->starting_count, mf->current_count);
  46. }
  47. static void max_forwards_destroy(void *data)
  48. {
  49. ast_free(data);
  50. }
  51. const struct ast_datastore_info max_forwards_info = {
  52. .type = "mfaled-interface",
  53. .duplicate = max_forwards_duplicate,
  54. .destroy = max_forwards_destroy,
  55. };
  56. static struct ast_datastore *max_forwards_datastore_alloc(struct ast_channel *chan,
  57. int starting_count)
  58. {
  59. struct ast_datastore *mf_datastore;
  60. struct max_forwards *mf;
  61. mf_datastore = ast_datastore_alloc(&max_forwards_info, NULL);
  62. if (!mf_datastore) {
  63. return NULL;
  64. }
  65. mf_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
  66. mf = max_forwards_alloc(starting_count, starting_count);
  67. if (!mf) {
  68. ast_datastore_free(mf_datastore);
  69. return NULL;
  70. }
  71. mf_datastore->data = mf;
  72. ast_channel_datastore_add(chan, mf_datastore);
  73. return mf_datastore;
  74. }
  75. static struct ast_datastore *max_forwards_datastore_find_or_alloc(struct ast_channel *chan)
  76. {
  77. struct ast_datastore *mf_datastore;
  78. mf_datastore = ast_channel_datastore_find(chan, &max_forwards_info, NULL);
  79. if (!mf_datastore) {
  80. mf_datastore = max_forwards_datastore_alloc(chan, DEFAULT_MAX_FORWARDS);
  81. }
  82. return mf_datastore;
  83. }
  84. int ast_max_forwards_set(struct ast_channel *chan, int starting_count)
  85. {
  86. struct ast_datastore *mf_datastore;
  87. struct max_forwards *mf;
  88. mf_datastore = max_forwards_datastore_find_or_alloc(chan);
  89. if (!mf_datastore) {
  90. return -1;
  91. }
  92. mf = mf_datastore->data;
  93. mf->starting_count = mf->current_count = starting_count;
  94. return 0;
  95. }
  96. int ast_max_forwards_get(struct ast_channel *chan)
  97. {
  98. struct ast_datastore *mf_datastore;
  99. struct max_forwards *mf;
  100. mf_datastore = max_forwards_datastore_find_or_alloc(chan);
  101. if (!mf_datastore) {
  102. return -1;
  103. }
  104. mf = mf_datastore->data;
  105. return mf->current_count;
  106. }
  107. int ast_max_forwards_decrement(struct ast_channel *chan)
  108. {
  109. struct ast_datastore *mf_datastore;
  110. struct max_forwards *mf;
  111. mf_datastore = max_forwards_datastore_find_or_alloc(chan);
  112. if (!mf_datastore) {
  113. return -1;
  114. }
  115. mf = mf_datastore->data;
  116. --mf->current_count;
  117. return 0;
  118. }
  119. int ast_max_forwards_reset(struct ast_channel *chan)
  120. {
  121. struct ast_datastore *mf_datastore;
  122. struct max_forwards *mf;
  123. mf_datastore = max_forwards_datastore_find_or_alloc(chan);
  124. if (!mf_datastore) {
  125. return -1;
  126. }
  127. mf = mf_datastore->data;
  128. mf->current_count = mf->starting_count;
  129. return 0;
  130. }