app_chanisavail.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include <sys/ioctl.h>
  30. #include "asterisk/lock.h"
  31. #include "asterisk/file.h"
  32. #include "asterisk/channel.h"
  33. #include "asterisk/pbx.h"
  34. #include "asterisk/module.h"
  35. #include "asterisk/app.h"
  36. #include "asterisk/devicestate.h"
  37. static char *app = "ChanIsAvail";
  38. static char *synopsis = "Check channel availability";
  39. static char *descrip =
  40. " ChanIsAvail(Technology/resource[&Technology2/resource2...][,options]): \n"
  41. "This application will check to see if any of the specified channels are\n"
  42. "available.\n"
  43. " Options:\n"
  44. " s - Consider the channel unavailable if the channel is in use at all.\n"
  45. " t - Simply checks if specified channels exist in the channel list\n"
  46. " (implies option s).\n"
  47. "Note that the AVAILSTATUS variable is used for both device state\n"
  48. "and cause code. It is therefore possible for it to give a value that may\n"
  49. "indicate a device is available when it is not. It is suggested that the\n"
  50. "AVAILORIGCHAN variable is used instead to see whether a device is available\n"
  51. "or not.\n"
  52. "This application sets the following channel variable upon completion:\n"
  53. " AVAILCHAN - the name of the available channel, if one exists\n"
  54. " AVAILORIGCHAN - the canonical channel name that was used to create the channel\n"
  55. " AVAILSTATUS - the status code for the available channel\n";
  56. static int chanavail_exec(struct ast_channel *chan, void *data)
  57. {
  58. int res=-1, inuse=-1, option_state=0, string_compare=0;
  59. int status;
  60. char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur;
  61. struct ast_channel *tempchan;
  62. AST_DECLARE_APP_ARGS(args,
  63. AST_APP_ARG(reqchans);
  64. AST_APP_ARG(options);
  65. );
  66. if (ast_strlen_zero(data)) {
  67. ast_log(LOG_WARNING, "ChanIsAvail requires an argument (DAHDI/1&DAHDI/2)\n");
  68. return -1;
  69. }
  70. info = ast_strdupa(data);
  71. AST_STANDARD_APP_ARGS(args, info);
  72. if (args.options) {
  73. if (strchr(args.options, 's'))
  74. option_state = 1;
  75. if (strchr(args.options, 't'))
  76. string_compare = 1;
  77. }
  78. peers = args.reqchans;
  79. if (peers) {
  80. cur = peers;
  81. do {
  82. /* remember where to start next time */
  83. rest = strchr(cur, '&');
  84. if (rest) {
  85. *rest = 0;
  86. rest++;
  87. }
  88. tech = cur;
  89. number = strchr(tech, '/');
  90. if (!number) {
  91. ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
  92. return -1;
  93. }
  94. *number = '\0';
  95. number++;
  96. if (string_compare) {
  97. /* ast_parse_device_state checks for "SIP/1234" as a channel name.
  98. ast_device_state will ask the SIP driver for the channel state. */
  99. snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
  100. status = inuse = ast_parse_device_state(trychan);
  101. } else if (option_state) {
  102. /* If the pbx says in use then don't bother trying further.
  103. This is to permit testing if someone's on a call, even if the
  104. channel can permit more calls (ie callwaiting, sip calls, etc). */
  105. snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
  106. status = inuse = ast_device_state(trychan);
  107. }
  108. if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
  109. pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
  110. /* Store the originally used channel too */
  111. snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
  112. pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp);
  113. snprintf(tmp, sizeof(tmp), "%d", status);
  114. pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
  115. ast_hangup(tempchan);
  116. tempchan = NULL;
  117. res = 1;
  118. break;
  119. } else {
  120. snprintf(tmp, sizeof(tmp), "%d", status);
  121. pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
  122. }
  123. cur = rest;
  124. } while (cur);
  125. }
  126. if (res < 1) {
  127. pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
  128. pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", "");
  129. }
  130. return 0;
  131. }
  132. static int unload_module(void)
  133. {
  134. return ast_unregister_application(app);
  135. }
  136. static int load_module(void)
  137. {
  138. return ast_register_application(app, chanavail_exec, synopsis, descrip);
  139. }
  140. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Check channel availability");