app_chanisavail.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2005, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@digium.com>
  7. * James Golovich <james@gnuinter.net>
  8. *
  9. * See http://www.asterisk.org for more information about
  10. * the Asterisk project. Please do not directly contact
  11. * any of the maintainers of this project for assistance;
  12. * the project provides a web site, mailing lists and IRC
  13. * channels for your use.
  14. *
  15. * This program is free software, distributed under the terms of
  16. * the GNU General Public License Version 2. See the LICENSE file
  17. * at the top of the source tree.
  18. */
  19. /*! \file
  20. *
  21. * \brief Check if Channel is Available
  22. *
  23. * \author Mark Spencer <markster@digium.com>
  24. * \author James Golovich <james@gnuinter.net>
  25. * \ingroup applications
  26. */
  27. /*** MODULEINFO
  28. <support_level>extended</support_level>
  29. <defaultenabled>no</defaultenabled>
  30. ***/
  31. #include "asterisk.h"
  32. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  33. #include <sys/ioctl.h>
  34. #include "asterisk/lock.h"
  35. #include "asterisk/file.h"
  36. #include "asterisk/channel.h"
  37. #include "asterisk/pbx.h"
  38. #include "asterisk/module.h"
  39. #include "asterisk/app.h"
  40. #include "asterisk/devicestate.h"
  41. static const char app[] = "ChanIsAvail";
  42. /*** DOCUMENTATION
  43. <application name="ChanIsAvail" language="en_US">
  44. <synopsis>
  45. Check channel availability
  46. </synopsis>
  47. <syntax>
  48. <parameter name="Technology/Resource" required="true" argsep="&amp;">
  49. <argument name="Technology2/Resource2" multiple="true">
  50. <para>Optional extra devices to check</para>
  51. <para>If you need more then one enter them as
  52. Technology2/Resource2&amp;Technology3/Resourse3&amp;.....</para>
  53. </argument>
  54. <para>Specification of the device(s) to check. These must be in the format of
  55. <literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
  56. represents a particular channel driver, and <replaceable>Resource</replaceable>
  57. represents a resource available to that particular channel driver.</para>
  58. </parameter>
  59. <parameter name="options" required="false">
  60. <optionlist>
  61. <option name="a">
  62. <para>Check for all available channels, not only the first one</para>
  63. </option>
  64. <option name="s">
  65. <para>Consider the channel unavailable if the channel is in use at all</para>
  66. </option>
  67. <option name="t" implies="s">
  68. <para>Simply checks if specified channels exist in the channel list</para>
  69. </option>
  70. </optionlist>
  71. </parameter>
  72. </syntax>
  73. <description>
  74. <para>This application will check to see if any of the specified channels are available.</para>
  75. <para>This application sets the following channel variables:</para>
  76. <variablelist>
  77. <variable name="AVAILCHAN">
  78. <para>The name of the available channel, if one exists</para>
  79. </variable>
  80. <variable name="AVAILORIGCHAN">
  81. <para>The canonical channel name that was used to create the channel</para>
  82. </variable>
  83. <variable name="AVAILSTATUS">
  84. <para>The device state for the device</para>
  85. </variable>
  86. <variable name="AVAILCAUSECODE">
  87. <para>The cause code returned when requesting the channel</para>
  88. </variable>
  89. </variablelist>
  90. </description>
  91. </application>
  92. ***/
  93. static int chanavail_exec(struct ast_channel *chan, const char *data)
  94. {
  95. int inuse=-1, option_state=0, string_compare=0, option_all_avail=0;
  96. int status;
  97. char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur;
  98. struct ast_str *tmp_availchan = ast_str_alloca(2048);
  99. struct ast_str *tmp_availorig = ast_str_alloca(2048);
  100. struct ast_str *tmp_availstat = ast_str_alloca(2048);
  101. struct ast_str *tmp_availcause = ast_str_alloca(2048);
  102. struct ast_channel *tempchan;
  103. AST_DECLARE_APP_ARGS(args,
  104. AST_APP_ARG(reqchans);
  105. AST_APP_ARG(options);
  106. );
  107. if (ast_strlen_zero(data)) {
  108. ast_log(LOG_WARNING, "ChanIsAvail requires an argument (DAHDI/1&DAHDI/2)\n");
  109. return -1;
  110. }
  111. info = ast_strdupa(data);
  112. AST_STANDARD_APP_ARGS(args, info);
  113. if (args.options) {
  114. if (strchr(args.options, 'a')) {
  115. option_all_avail = 1;
  116. }
  117. if (strchr(args.options, 's')) {
  118. option_state = 1;
  119. }
  120. if (strchr(args.options, 't')) {
  121. string_compare = 1;
  122. }
  123. }
  124. peers = args.reqchans;
  125. if (peers) {
  126. cur = peers;
  127. do {
  128. /* remember where to start next time */
  129. rest = strchr(cur, '&');
  130. if (rest) {
  131. *rest = 0;
  132. rest++;
  133. }
  134. tech = cur;
  135. number = strchr(tech, '/');
  136. if (!number) {
  137. ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
  138. return -1;
  139. }
  140. *number = '\0';
  141. number++;
  142. if (string_compare) {
  143. /* ast_parse_device_state checks for "SIP/1234" as a channel name.
  144. ast_device_state will ask the SIP driver for the channel state. */
  145. snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
  146. status = inuse = ast_parse_device_state(trychan);
  147. } else if (option_state) {
  148. /* If the pbx says in use then don't bother trying further.
  149. This is to permit testing if someone's on a call, even if the
  150. channel can permit more calls (ie callwaiting, sip calls, etc). */
  151. snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
  152. status = inuse = ast_device_state(trychan);
  153. }
  154. snprintf(tmp, sizeof(tmp), "%d", status);
  155. ast_str_append(&tmp_availstat, 0, "%s%s", ast_str_strlen(tmp_availstat) ? "&" : "", tmp);
  156. if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, chan, number, &status))) {
  157. ast_str_append(&tmp_availchan, 0, "%s%s", ast_str_strlen(tmp_availchan) ? "&" : "", tempchan->name);
  158. snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
  159. ast_str_append(&tmp_availorig, 0, "%s%s", ast_str_strlen(tmp_availorig) ? "&" : "", tmp);
  160. snprintf(tmp, sizeof(tmp), "%d", status);
  161. ast_str_append(&tmp_availcause, 0, "%s%s", ast_str_strlen(tmp_availcause) ? "&" : "", tmp);
  162. ast_hangup(tempchan);
  163. tempchan = NULL;
  164. if (!option_all_avail) {
  165. break;
  166. }
  167. }
  168. cur = rest;
  169. } while (cur);
  170. }
  171. pbx_builtin_setvar_helper(chan, "AVAILCHAN", ast_str_buffer(tmp_availchan));
  172. /* Store the originally used channel too */
  173. pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", ast_str_buffer(tmp_availorig));
  174. pbx_builtin_setvar_helper(chan, "AVAILSTATUS", ast_str_buffer(tmp_availstat));
  175. pbx_builtin_setvar_helper(chan, "AVAILCAUSECODE", ast_str_buffer(tmp_availcause));
  176. return 0;
  177. }
  178. static int unload_module(void)
  179. {
  180. return ast_unregister_application(app);
  181. }
  182. static int load_module(void)
  183. {
  184. return ast_register_application_xml(app, chanavail_exec) ?
  185. AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
  186. }
  187. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Check channel availability");