app_chanisavail.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. ***/
  30. #include "asterisk.h"
  31. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  32. #include <sys/ioctl.h>
  33. #include "asterisk/lock.h"
  34. #include "asterisk/file.h"
  35. #include "asterisk/channel.h"
  36. #include "asterisk/pbx.h"
  37. #include "asterisk/module.h"
  38. #include "asterisk/app.h"
  39. #include "asterisk/devicestate.h"
  40. static const char app[] = "ChanIsAvail";
  41. /*** DOCUMENTATION
  42. <application name="ChanIsAvail" language="en_US">
  43. <synopsis>
  44. Check channel availability
  45. </synopsis>
  46. <syntax>
  47. <parameter name="Technology/Resource" required="true" argsep="&amp;">
  48. <argument name="Technology2/Resource2" multiple="true">
  49. <para>Optional extra devices to check</para>
  50. <para>If you need more then one enter them as
  51. Technology2/Resource2&amp;Technology3/Resourse3&amp;.....</para>
  52. </argument>
  53. <para>Specification of the device(s) to check. These must be in the format of
  54. <literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
  55. represents a particular channel driver, and <replaceable>Resource</replaceable>
  56. represents a resource available to that particular channel driver.</para>
  57. </parameter>
  58. <parameter name="options" required="false">
  59. <optionlist>
  60. <option name="a">
  61. <para>Check for all available channels, not only the first one</para>
  62. </option>
  63. <option name="s">
  64. <para>Consider the channel unavailable if the channel is in use at all</para>
  65. </option>
  66. <option name="t" implies="s">
  67. <para>Simply checks if specified channels exist in the channel list</para>
  68. </option>
  69. </optionlist>
  70. </parameter>
  71. </syntax>
  72. <description>
  73. <para>This application will check to see if any of the specified channels are available.</para>
  74. <para>This application sets the following channel variables:</para>
  75. <variablelist>
  76. <variable name="AVAILCHAN">
  77. <para>The name of the available channel, if one exists</para>
  78. </variable>
  79. <variable name="AVAILORIGCHAN">
  80. <para>The canonical channel name that was used to create the channel</para>
  81. </variable>
  82. <variable name="AVAILSTATUS">
  83. <para>The device state for the device</para>
  84. </variable>
  85. <variable name="AVAILCAUSECODE">
  86. <para>The cause code returned when requesting the channel</para>
  87. </variable>
  88. </variablelist>
  89. </description>
  90. </application>
  91. ***/
  92. static int chanavail_exec(struct ast_channel *chan, const char *data)
  93. {
  94. int inuse=-1, option_state=0, string_compare=0, option_all_avail=0;
  95. int status;
  96. char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur;
  97. struct ast_str *tmp_availchan = ast_str_alloca(2048);
  98. struct ast_str *tmp_availorig = ast_str_alloca(2048);
  99. struct ast_str *tmp_availstat = ast_str_alloca(2048);
  100. struct ast_str *tmp_availcause = ast_str_alloca(2048);
  101. struct ast_channel *tempchan;
  102. AST_DECLARE_APP_ARGS(args,
  103. AST_APP_ARG(reqchans);
  104. AST_APP_ARG(options);
  105. );
  106. if (ast_strlen_zero(data)) {
  107. ast_log(LOG_WARNING, "ChanIsAvail requires an argument (DAHDI/1&DAHDI/2)\n");
  108. return -1;
  109. }
  110. info = ast_strdupa(data);
  111. AST_STANDARD_APP_ARGS(args, info);
  112. if (args.options) {
  113. if (strchr(args.options, 'a')) {
  114. option_all_avail = 1;
  115. }
  116. if (strchr(args.options, 's')) {
  117. option_state = 1;
  118. }
  119. if (strchr(args.options, 't')) {
  120. string_compare = 1;
  121. }
  122. }
  123. peers = args.reqchans;
  124. if (peers) {
  125. cur = peers;
  126. do {
  127. /* remember where to start next time */
  128. rest = strchr(cur, '&');
  129. if (rest) {
  130. *rest = 0;
  131. rest++;
  132. }
  133. tech = cur;
  134. number = strchr(tech, '/');
  135. if (!number) {
  136. ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
  137. return -1;
  138. }
  139. *number = '\0';
  140. number++;
  141. status = AST_DEVICE_UNKNOWN;
  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, ast_channel_nativeformats(chan), NULL, chan, number, &status))) {
  157. ast_str_append(&tmp_availchan, 0, "%s%s", ast_str_strlen(tmp_availchan) ? "&" : "", ast_channel_name(tempchan));
  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_EXTENDED(ASTERISK_GPL_KEY, "Check channel availability");