autoservice.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2005, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@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. /*! \file
  19. *
  20. * \brief Automatic channel service routines
  21. *
  22. */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <sys/time.h>
  27. #include <signal.h>
  28. #include <errno.h>
  29. #include <unistd.h>
  30. #include <math.h> /* For PI */
  31. #include "asterisk.h"
  32. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  33. #include "asterisk/pbx.h"
  34. #include "asterisk/frame.h"
  35. #include "asterisk/sched.h"
  36. #include "asterisk/options.h"
  37. #include "asterisk/channel.h"
  38. #include "asterisk/logger.h"
  39. #include "asterisk/file.h"
  40. #include "asterisk/translate.h"
  41. #include "asterisk/manager.h"
  42. #include "asterisk/chanvars.h"
  43. #include "asterisk/linkedlists.h"
  44. #include "asterisk/indications.h"
  45. #include "asterisk/lock.h"
  46. #include "asterisk/utils.h"
  47. #define MAX_AUTOMONS 256
  48. AST_MUTEX_DEFINE_STATIC(autolock);
  49. struct asent {
  50. struct ast_channel *chan;
  51. struct asent *next;
  52. };
  53. static struct asent *aslist = NULL;
  54. static pthread_t asthread = AST_PTHREADT_NULL;
  55. static void *autoservice_run(void *ign)
  56. {
  57. struct ast_channel *mons[MAX_AUTOMONS];
  58. int x;
  59. int ms;
  60. struct ast_channel *chan;
  61. struct asent *as;
  62. struct ast_frame *f;
  63. for(;;) {
  64. x = 0;
  65. ast_mutex_lock(&autolock);
  66. as = aslist;
  67. while(as) {
  68. if (!as->chan->_softhangup) {
  69. if (x < MAX_AUTOMONS)
  70. mons[x++] = as->chan;
  71. else
  72. ast_log(LOG_WARNING, "Exceeded maximum number of automatic monitoring events. Fix autoservice.c\n");
  73. }
  74. as = as->next;
  75. }
  76. ast_mutex_unlock(&autolock);
  77. /* if (!aslist)
  78. break; */
  79. ms = 500;
  80. chan = ast_waitfor_n(mons, x, &ms);
  81. if (chan) {
  82. /* Read and ignore anything that occurs */
  83. f = ast_read(chan);
  84. if (f)
  85. ast_frfree(f);
  86. }
  87. }
  88. asthread = AST_PTHREADT_NULL;
  89. return NULL;
  90. }
  91. int ast_autoservice_start(struct ast_channel *chan)
  92. {
  93. int res = -1;
  94. struct asent *as;
  95. int needstart;
  96. ast_mutex_lock(&autolock);
  97. needstart = (asthread == AST_PTHREADT_NULL) ? 1 : 0 /* aslist ? 0 : 1 */;
  98. as = aslist;
  99. while(as) {
  100. if (as->chan == chan)
  101. break;
  102. as = as->next;
  103. }
  104. if (!as) {
  105. as = malloc(sizeof(struct asent));
  106. if (as) {
  107. memset(as, 0, sizeof(struct asent));
  108. as->chan = chan;
  109. as->next = aslist;
  110. aslist = as;
  111. res = 0;
  112. if (needstart) {
  113. if (ast_pthread_create(&asthread, NULL, autoservice_run, NULL)) {
  114. ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
  115. free(aslist);
  116. aslist = NULL;
  117. res = -1;
  118. } else
  119. pthread_kill(asthread, SIGURG);
  120. }
  121. }
  122. }
  123. ast_mutex_unlock(&autolock);
  124. return res;
  125. }
  126. int ast_autoservice_stop(struct ast_channel *chan)
  127. {
  128. int res = -1;
  129. struct asent *as, *prev;
  130. ast_mutex_lock(&autolock);
  131. as = aslist;
  132. prev = NULL;
  133. while(as) {
  134. if (as->chan == chan)
  135. break;
  136. prev = as;
  137. as = as->next;
  138. }
  139. if (as) {
  140. if (prev)
  141. prev->next = as->next;
  142. else
  143. aslist = as->next;
  144. free(as);
  145. if (!chan->_softhangup)
  146. res = 0;
  147. }
  148. if (asthread != AST_PTHREADT_NULL)
  149. pthread_kill(asthread, SIGURG);
  150. ast_mutex_unlock(&autolock);
  151. /* Wait for it to un-block */
  152. while(ast_test_flag(chan, AST_FLAG_BLOCKING))
  153. usleep(1000);
  154. return res;
  155. }