func_channel.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2006, Digium, Inc.
  5. *
  6. * See http://www.asterisk.org for more information about
  7. * the Asterisk project. Please do not directly contact
  8. * any of the maintainers of this project for assistance;
  9. * the project provides a web site, mailing lists and IRC
  10. * channels for your use.
  11. *
  12. * This program is free software, distributed under the terms of
  13. * the GNU General Public License Version 2. See the LICENSE file
  14. * at the top of the source tree.
  15. */
  16. /*! \file
  17. *
  18. * \brief Channel info dialplan functions
  19. *
  20. * \author Kevin P. Fleming <kpfleming@digium.com>
  21. * \author Ben Winslow
  22. *
  23. * \ingroup functions
  24. */
  25. /*** MODULEINFO
  26. <support_level>core</support_level>
  27. ***/
  28. #include "asterisk.h"
  29. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  30. #include <regex.h>
  31. #include <ctype.h>
  32. #include "asterisk/module.h"
  33. #include "asterisk/channel.h"
  34. #include "asterisk/pbx.h"
  35. #include "asterisk/utils.h"
  36. #include "asterisk/app.h"
  37. #include "asterisk/indications.h"
  38. #include "asterisk/stringfields.h"
  39. #include "asterisk/global_datastores.h"
  40. /*** DOCUMENTATION
  41. <function name="CHANNELS" language="en_US">
  42. <synopsis>
  43. Gets the list of channels, optionally filtering by a regular expression.
  44. </synopsis>
  45. <syntax>
  46. <parameter name="regular_expression" />
  47. </syntax>
  48. <description>
  49. <para>Gets the list of channels, optionally filtering by a <replaceable>regular_expression</replaceable>. If
  50. no argument is provided, all known channels are returned. The
  51. <replaceable>regular_expression</replaceable> must correspond to
  52. the POSIX.2 specification, as shown in <emphasis>regex(7)</emphasis>. The list returned
  53. will be space-delimited.</para>
  54. </description>
  55. </function>
  56. <function name="MASTER_CHANNEL" language="en_US">
  57. <synopsis>
  58. Gets or sets variables on the master channel
  59. </synopsis>
  60. <description>
  61. <para>Allows access to the channel which created the current channel, if any. If the channel is already
  62. a master channel, then accesses local channel variables.</para>
  63. </description>
  64. </function>
  65. <function name="CHANNEL" language="en_US">
  66. <synopsis>
  67. Gets/sets various pieces of information about the channel.
  68. </synopsis>
  69. <syntax>
  70. <parameter name="item" required="true">
  71. <para>Standard items (provided by all channel technologies) are:</para>
  72. <enumlist>
  73. <enum name="audioreadformat">
  74. <para>R/O format currently being read.</para>
  75. </enum>
  76. <enum name="audionativeformat">
  77. <para>R/O format used natively for audio.</para>
  78. </enum>
  79. <enum name="audiowriteformat">
  80. <para>R/O format currently being written.</para>
  81. </enum>
  82. <enum name="callgroup">
  83. <para>R/W call groups for call pickup.</para>
  84. </enum>
  85. <enum name="pickupgroup">
  86. <para>R/W call groups for call pickup.</para>
  87. </enum>
  88. <enum name="channeltype">
  89. <para>R/O technology used for channel.</para>
  90. </enum>
  91. <enum name="checkhangup">
  92. <para>R/O Whether the channel is hanging up (1/0)</para>
  93. </enum>
  94. <enum name="language">
  95. <para>R/W language for sounds played.</para>
  96. </enum>
  97. <enum name="musicclass">
  98. <para>R/W class (from musiconhold.conf) for hold music.</para>
  99. </enum>
  100. <enum name="name">
  101. <para>The name of the channel</para>
  102. </enum>
  103. <enum name="parkinglot">
  104. <para>R/W parkinglot for parking.</para>
  105. </enum>
  106. <enum name="rxgain">
  107. <para>R/W set rxgain level on channel drivers that support it.</para>
  108. </enum>
  109. <enum name="secure_bridge_signaling">
  110. <para>Whether or not channels bridged to this channel require secure signaling</para>
  111. </enum>
  112. <enum name="secure_bridge_media">
  113. <para>Whether or not channels bridged to this channel require secure media</para>
  114. </enum>
  115. <enum name="state">
  116. <para>R/O state for channel</para>
  117. </enum>
  118. <enum name="tonezone">
  119. <para>R/W zone for indications played</para>
  120. </enum>
  121. <enum name="transfercapability">
  122. <para>R/W ISDN Transfer Capability, one of:</para>
  123. <enumlist>
  124. <enum name="SPEECH" />
  125. <enum name="DIGITAL" />
  126. <enum name="RESTRICTED_DIGITAL" />
  127. <enum name="3K1AUDIO" />
  128. <enum name="DIGITAL_W_TONES" />
  129. <enum name="VIDEO" />
  130. </enumlist>
  131. </enum>
  132. <enum name="txgain">
  133. <para>R/W set txgain level on channel drivers that support it.</para>
  134. </enum>
  135. <enum name="videonativeformat">
  136. <para>R/O format used natively for video</para>
  137. </enum>
  138. <enum name="trace">
  139. <para>R/W whether or not context tracing is enabled, only available
  140. <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
  141. </enum>
  142. </enumlist>
  143. <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
  144. <enumlist>
  145. <enum name="peerip">
  146. <para>R/O Get the IP address of the peer.</para>
  147. </enum>
  148. <enum name="recvip">
  149. <para>R/O Get the source IP address of the peer.</para>
  150. </enum>
  151. <enum name="from">
  152. <para>R/O Get the URI from the From: header.</para>
  153. </enum>
  154. <enum name="uri">
  155. <para>R/O Get the URI from the Contact: header.</para>
  156. </enum>
  157. <enum name="useragent">
  158. <para>R/O Get the useragent.</para>
  159. </enum>
  160. <enum name="peername">
  161. <para>R/O Get the name of the peer.</para>
  162. </enum>
  163. <enum name="t38passthrough">
  164. <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
  165. otherwise <literal>0</literal></para>
  166. </enum>
  167. <enum name="rtpqos">
  168. <para>R/O Get QOS information about the RTP stream</para>
  169. <para> This option takes two additional arguments:</para>
  170. <para> Argument 1:</para>
  171. <para> <literal>audio</literal> Get data about the audio stream</para>
  172. <para> <literal>video</literal> Get data about the video stream</para>
  173. <para> <literal>text</literal> Get data about the text stream</para>
  174. <para> Argument 2:</para>
  175. <para> <literal>local_ssrc</literal> Local SSRC (stream ID)</para>
  176. <para> <literal>local_lostpackets</literal> Local lost packets</para>
  177. <para> <literal>local_jitter</literal> Local calculated jitter</para>
  178. <para> <literal>local_maxjitter</literal> Local calculated jitter (maximum)</para>
  179. <para> <literal>local_minjitter</literal> Local calculated jitter (minimum)</para>
  180. <para> <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
  181. <para> <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
  182. <para> <literal>local_count</literal> Number of received packets</para>
  183. <para> <literal>remote_ssrc</literal> Remote SSRC (stream ID)</para>
  184. <para> <literal>remote_lostpackets</literal>Remote lost packets</para>
  185. <para> <literal>remote_jitter</literal> Remote reported jitter</para>
  186. <para> <literal>remote_maxjitter</literal> Remote calculated jitter (maximum)</para>
  187. <para> <literal>remote_minjitter</literal> Remote calculated jitter (minimum)</para>
  188. <para> <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
  189. <para> <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
  190. <para> <literal>remote_count</literal> Number of transmitted packets</para>
  191. <para> <literal>rtt</literal> Round trip time</para>
  192. <para> <literal>maxrtt</literal> Round trip time (maximum)</para>
  193. <para> <literal>minrtt</literal> Round trip time (minimum)</para>
  194. <para> <literal>normdevrtt</literal> Round trip time (normal deviation)</para>
  195. <para> <literal>stdevrtt</literal> Round trip time (standard deviation)</para>
  196. <para> <literal>all</literal> All statistics (in a form suited to logging,
  197. but not for parsing)</para>
  198. </enum>
  199. <enum name="rtpdest">
  200. <para>R/O Get remote RTP destination information.</para>
  201. <para> This option takes one additional argument:</para>
  202. <para> Argument 1:</para>
  203. <para> <literal>audio</literal> Get audio destination</para>
  204. <para> <literal>video</literal> Get video destination</para>
  205. <para> <literal>text</literal> Get text destination</para>
  206. </enum>
  207. </enumlist>
  208. <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
  209. <enumlist>
  210. <enum name="peerip">
  211. <para>R/O Get the peer's ip address.</para>
  212. </enum>
  213. <enum name="peername">
  214. <para>R/O Get the peer's username.</para>
  215. </enum>
  216. </enumlist>
  217. <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
  218. <enumlist>
  219. <enum name="dahdi_channel">
  220. <para>R/O DAHDI channel related to this channel.</para>
  221. </enum>
  222. <enum name="dahdi_span">
  223. <para>R/O DAHDI span related to this channel.</para>
  224. </enum>
  225. <enum name="dahdi_type">
  226. <para>R/O DAHDI channel type, one of:</para>
  227. <enumlist>
  228. <enum name="analog" />
  229. <enum name="mfc/r2" />
  230. <enum name="pri" />
  231. <enum name="pseudo" />
  232. <enum name="ss7" />
  233. </enumlist>
  234. </enum>
  235. <enum name="keypad_digits">
  236. <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
  237. </enum>
  238. <enum name="reversecharge">
  239. <para>R/O PRI Reverse Charging Indication, one of:</para>
  240. <enumlist>
  241. <enum name="-1"> <para>None</para></enum>
  242. <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
  243. </enumlist>
  244. </enum>
  245. <enum name="no_media_path">
  246. <para>R/O PRI Nonzero if the channel has no B channel.
  247. The channel is either on hold or a call waiting call.</para>
  248. </enum>
  249. <enum name="buffers">
  250. <para>W/O Change the channel's buffer policy (for the current call only)</para>
  251. <para>This option takes two arguments:</para>
  252. <para> Number of buffers,</para>
  253. <para> Buffer policy being one of:</para>
  254. <para> <literal>full</literal></para>
  255. <para> <literal>immediate</literal></para>
  256. <para> <literal>half</literal></para>
  257. </enum>
  258. <enum name="echocan_mode">
  259. <para>W/O Change the configuration of the active echo
  260. canceller on the channel (if any), for the current call
  261. only.</para>
  262. <para>Possible values are:</para>
  263. <para> <literal>on</literal> Normal mode (the echo canceller is actually reinitalized)</para>
  264. <para> <literal>off</literal> Disabled</para>
  265. <para> <literal>fax</literal> FAX/data mode (NLP disabled if possible, otherwise
  266. completely disabled)</para>
  267. <para> <literal>voice</literal> Voice mode (returns from FAX mode, reverting the changes that were made)</para>
  268. </enum>
  269. </enumlist>
  270. <para><emphasis>chan_ooh323</emphasis> provides the following additional options:</para>
  271. <enumlist>
  272. <enum name="faxdetect">
  273. <para>Fax Detect [R/W]</para>
  274. <para>Returns 0 or 1</para>
  275. <para>Write yes or no</para>
  276. </enum>
  277. <enum name="t38support">
  278. <para>t38support [R/W]</para>
  279. <para>Returns 0 or 1</para>
  280. <para>Write yes or no</para>
  281. </enum>
  282. <enum name="h323id">
  283. <para>Returns h323id [R]</para>
  284. </enum>
  285. </enumlist>
  286. </parameter>
  287. </syntax>
  288. <description>
  289. <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
  290. be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
  291. requested that is not available on the current channel will return an empty string.</para>
  292. </description>
  293. </function>
  294. ***/
  295. #define locked_copy_string(chan, dest, source, len) \
  296. do { \
  297. ast_channel_lock(chan); \
  298. ast_copy_string(dest, source, len); \
  299. ast_channel_unlock(chan); \
  300. } while (0)
  301. #define locked_string_field_set(chan, field, source) \
  302. do { \
  303. ast_channel_lock(chan); \
  304. ast_string_field_set(chan, field, source); \
  305. ast_channel_unlock(chan); \
  306. } while (0)
  307. static const char * const transfercapability_table[0x20] = {
  308. "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
  309. "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
  310. "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
  311. "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
  312. static int func_channel_read(struct ast_channel *chan, const char *function,
  313. char *data, char *buf, size_t len)
  314. {
  315. int ret = 0;
  316. char tmp[512];
  317. struct ast_format_cap *tmpcap;
  318. if (!strcasecmp(data, "audionativeformat")) {
  319. if ((tmpcap = ast_format_cap_get_type(chan->nativeformats, AST_FORMAT_TYPE_AUDIO))) {
  320. ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
  321. tmpcap = ast_format_cap_destroy(tmpcap);
  322. }
  323. } else if (!strcasecmp(data, "videonativeformat")) {
  324. if ((tmpcap = ast_format_cap_get_type(chan->nativeformats, AST_FORMAT_TYPE_VIDEO))) {
  325. ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
  326. tmpcap = ast_format_cap_destroy(tmpcap);
  327. }
  328. } else if (!strcasecmp(data, "audioreadformat")) {
  329. ast_copy_string(buf, ast_getformatname(&chan->readformat), len);
  330. } else if (!strcasecmp(data, "audiowriteformat")) {
  331. ast_copy_string(buf, ast_getformatname(&chan->writeformat), len);
  332. #ifdef CHANNEL_TRACE
  333. } else if (!strcasecmp(data, "trace")) {
  334. ast_channel_lock(chan);
  335. ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
  336. ast_channel_unlock(chan);
  337. #endif
  338. } else if (!strcasecmp(data, "tonezone") && chan->zone)
  339. locked_copy_string(chan, buf, chan->zone->country, len);
  340. else if (!strcasecmp(data, "language"))
  341. locked_copy_string(chan, buf, chan->language, len);
  342. else if (!strcasecmp(data, "musicclass"))
  343. locked_copy_string(chan, buf, chan->musicclass, len);
  344. else if (!strcasecmp(data, "name")) {
  345. locked_copy_string(chan, buf, chan->name, len);
  346. } else if (!strcasecmp(data, "parkinglot"))
  347. locked_copy_string(chan, buf, chan->parkinglot, len);
  348. else if (!strcasecmp(data, "state"))
  349. locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
  350. else if (!strcasecmp(data, "channeltype"))
  351. locked_copy_string(chan, buf, chan->tech->type, len);
  352. else if (!strcasecmp(data, "accountcode"))
  353. locked_copy_string(chan, buf, chan->accountcode, len);
  354. else if (!strcasecmp(data, "checkhangup")) {
  355. ast_channel_lock(chan);
  356. ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
  357. ast_channel_unlock(chan);
  358. } else if (!strcasecmp(data, "peeraccount"))
  359. locked_copy_string(chan, buf, chan->peeraccount, len);
  360. else if (!strcasecmp(data, "hangupsource"))
  361. locked_copy_string(chan, buf, chan->hangupsource, len);
  362. else if (!strcasecmp(data, "appname") && chan->appl)
  363. locked_copy_string(chan, buf, chan->appl, len);
  364. else if (!strcasecmp(data, "appdata") && chan->data)
  365. locked_copy_string(chan, buf, chan->data, len);
  366. else if (!strcasecmp(data, "exten") && chan->data)
  367. locked_copy_string(chan, buf, chan->exten, len);
  368. else if (!strcasecmp(data, "context") && chan->data)
  369. locked_copy_string(chan, buf, chan->context, len);
  370. else if (!strcasecmp(data, "userfield") && chan->data)
  371. locked_copy_string(chan, buf, chan->userfield, len);
  372. else if (!strcasecmp(data, "channame") && chan->data)
  373. locked_copy_string(chan, buf, chan->name, len);
  374. else if (!strcasecmp(data, "linkedid")) {
  375. ast_channel_lock(chan);
  376. if (ast_strlen_zero(chan->linkedid)) {
  377. /* fall back on the channel's uniqueid if linkedid is unset */
  378. ast_copy_string(buf, chan->uniqueid, len);
  379. }
  380. else {
  381. ast_copy_string(buf, chan->linkedid, len);
  382. }
  383. ast_channel_unlock(chan);
  384. } else if (!strcasecmp(data, "peer")) {
  385. struct ast_channel *p;
  386. ast_channel_lock(chan);
  387. p = ast_bridged_channel(chan);
  388. if (p || chan->tech || chan->cdr) /* dummy channel? if so, we hid the peer name in the language */
  389. ast_copy_string(buf, (p ? p->name : ""), len);
  390. else {
  391. /* a dummy channel can still pass along bridged peer info via
  392. the BRIDGEPEER variable */
  393. const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
  394. if (!ast_strlen_zero(pname))
  395. ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
  396. else
  397. buf[0] = 0;
  398. }
  399. ast_channel_unlock(chan);
  400. } else if (!strcasecmp(data, "uniqueid")) {
  401. locked_copy_string(chan, buf, chan->uniqueid, len);
  402. } else if (!strcasecmp(data, "transfercapability")) {
  403. locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len);
  404. } else if (!strcasecmp(data, "callgroup")) {
  405. char groupbuf[256];
  406. locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len);
  407. } else if (!strcasecmp(data, "pickupgroup")) {
  408. char groupbuf[256];
  409. locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->pickupgroup), len);
  410. } else if (!strcasecmp(data, "amaflags")) {
  411. char amabuf[256];
  412. snprintf(amabuf,sizeof(amabuf), "%d", chan->amaflags);
  413. locked_copy_string(chan, buf, amabuf, len);
  414. } else if (!strncasecmp(data, "secure_bridge_", 14)) {
  415. struct ast_datastore *ds;
  416. ast_channel_lock(chan);
  417. if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
  418. struct ast_secure_call_store *encrypt = ds->data;
  419. if (!strcasecmp(data, "secure_bridge_signaling")) {
  420. snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
  421. } else if (!strcasecmp(data, "secure_bridge_media")) {
  422. snprintf(buf, len, "%s", encrypt->media ? "1" : "");
  423. }
  424. }
  425. ast_channel_unlock(chan);
  426. } else if (!chan->tech || !chan->tech->func_channel_read || chan->tech->func_channel_read(chan, function, data, buf, len)) {
  427. ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
  428. ret = -1;
  429. }
  430. return ret;
  431. }
  432. static int func_channel_write_real(struct ast_channel *chan, const char *function,
  433. char *data, const char *value)
  434. {
  435. int ret = 0;
  436. signed char gainset;
  437. if (!strcasecmp(data, "language"))
  438. locked_string_field_set(chan, language, value);
  439. else if (!strcasecmp(data, "parkinglot"))
  440. locked_string_field_set(chan, parkinglot, value);
  441. else if (!strcasecmp(data, "musicclass"))
  442. locked_string_field_set(chan, musicclass, value);
  443. else if (!strcasecmp(data, "accountcode"))
  444. locked_string_field_set(chan, accountcode, value);
  445. else if (!strcasecmp(data, "userfield"))
  446. locked_string_field_set(chan, userfield, value);
  447. else if (!strcasecmp(data, "amaflags")) {
  448. ast_channel_lock(chan);
  449. if(isdigit(*value)) {
  450. sscanf(value, "%30d", &chan->amaflags);
  451. } else if (!strcasecmp(value,"OMIT")){
  452. chan->amaflags = 1;
  453. } else if (!strcasecmp(value,"BILLING")){
  454. chan->amaflags = 2;
  455. } else if (!strcasecmp(value,"DOCUMENTATION")){
  456. chan->amaflags = 3;
  457. }
  458. ast_channel_unlock(chan);
  459. } else if (!strcasecmp(data, "peeraccount"))
  460. locked_string_field_set(chan, peeraccount, value);
  461. else if (!strcasecmp(data, "hangupsource"))
  462. /* XXX - should we be forcing this here? */
  463. ast_set_hangupsource(chan, value, 0);
  464. #ifdef CHANNEL_TRACE
  465. else if (!strcasecmp(data, "trace")) {
  466. ast_channel_lock(chan);
  467. if (ast_true(value))
  468. ret = ast_channel_trace_enable(chan);
  469. else if (ast_false(value))
  470. ret = ast_channel_trace_disable(chan);
  471. else {
  472. ret = -1;
  473. ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
  474. }
  475. ast_channel_unlock(chan);
  476. }
  477. #endif
  478. else if (!strcasecmp(data, "tonezone")) {
  479. struct ast_tone_zone *new_zone;
  480. if (!(new_zone = ast_get_indication_zone(value))) {
  481. ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
  482. ret = -1;
  483. } else {
  484. ast_channel_lock(chan);
  485. if (chan->zone) {
  486. chan->zone = ast_tone_zone_unref(chan->zone);
  487. }
  488. chan->zone = ast_tone_zone_ref(new_zone);
  489. ast_channel_unlock(chan);
  490. new_zone = ast_tone_zone_unref(new_zone);
  491. }
  492. } else if (!strcasecmp(data, "callgroup")) {
  493. chan->callgroup = ast_get_group(value);
  494. } else if (!strcasecmp(data, "pickupgroup")) {
  495. chan->pickupgroup = ast_get_group(value);
  496. } else if (!strcasecmp(data, "txgain")) {
  497. sscanf(value, "%4hhd", &gainset);
  498. ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
  499. } else if (!strcasecmp(data, "rxgain")) {
  500. sscanf(value, "%4hhd", &gainset);
  501. ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
  502. } else if (!strcasecmp(data, "transfercapability")) {
  503. unsigned short i;
  504. for (i = 0; i < 0x20; i++) {
  505. if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
  506. chan->transfercapability = i;
  507. break;
  508. }
  509. }
  510. } else if (!strncasecmp(data, "secure_bridge_", 14)) {
  511. struct ast_datastore *ds;
  512. struct ast_secure_call_store *store;
  513. if (!chan || !value) {
  514. return -1;
  515. }
  516. ast_channel_lock(chan);
  517. if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
  518. if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
  519. ast_channel_unlock(chan);
  520. return -1;
  521. }
  522. if (!(store = ast_calloc(1, sizeof(*store)))) {
  523. ast_channel_unlock(chan);
  524. ast_free(ds);
  525. return -1;
  526. }
  527. ds->data = store;
  528. ast_channel_datastore_add(chan, ds);
  529. } else {
  530. store = ds->data;
  531. }
  532. ast_channel_unlock(chan);
  533. if (!strcasecmp(data, "secure_bridge_signaling")) {
  534. store->signaling = ast_true(value) ? 1 : 0;
  535. } else if (!strcasecmp(data, "secure_bridge_media")) {
  536. store->media = ast_true(value) ? 1 : 0;
  537. }
  538. } else if (!chan->tech->func_channel_write
  539. || chan->tech->func_channel_write(chan, function, data, value)) {
  540. ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
  541. data);
  542. ret = -1;
  543. }
  544. return ret;
  545. }
  546. static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
  547. {
  548. int res;
  549. ast_chan_write_info_t write_info = {
  550. .version = AST_CHAN_WRITE_INFO_T_VERSION,
  551. .write_fn = func_channel_write_real,
  552. .chan = chan,
  553. .function = function,
  554. .data = data,
  555. .value = value,
  556. };
  557. res = func_channel_write_real(chan, function, data, value);
  558. ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
  559. return res;
  560. }
  561. static struct ast_custom_function channel_function = {
  562. .name = "CHANNEL",
  563. .read = func_channel_read,
  564. .write = func_channel_write,
  565. };
  566. static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
  567. {
  568. struct ast_channel *c = NULL;
  569. regex_t re;
  570. int res;
  571. size_t buflen = 0;
  572. struct ast_channel_iterator *iter;
  573. buf[0] = '\0';
  574. if (!ast_strlen_zero(data)) {
  575. if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
  576. regerror(res, &re, buf, maxlen);
  577. ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
  578. return -1;
  579. }
  580. }
  581. if (!(iter = ast_channel_iterator_all_new())) {
  582. if (!ast_strlen_zero(data)) {
  583. regfree(&re);
  584. }
  585. return -1;
  586. }
  587. while ((c = ast_channel_iterator_next(iter))) {
  588. ast_channel_lock(c);
  589. if (ast_strlen_zero(data) || regexec(&re, c->name, 0, NULL, 0) == 0) {
  590. size_t namelen = strlen(c->name);
  591. if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
  592. if (!ast_strlen_zero(buf)) {
  593. strcat(buf, " ");
  594. buflen++;
  595. }
  596. strcat(buf, c->name);
  597. buflen += namelen;
  598. } else {
  599. ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n");
  600. }
  601. }
  602. ast_channel_unlock(c);
  603. c = ast_channel_unref(c);
  604. }
  605. ast_channel_iterator_destroy(iter);
  606. if (!ast_strlen_zero(data)) {
  607. regfree(&re);
  608. }
  609. return 0;
  610. }
  611. static struct ast_custom_function channels_function = {
  612. .name = "CHANNELS",
  613. .read = func_channels_read,
  614. };
  615. static int func_mchan_read(struct ast_channel *chan, const char *function,
  616. char *data, struct ast_str **buf, ssize_t len)
  617. {
  618. struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid);
  619. char *template = ast_alloca(4 + strlen(data));
  620. sprintf(template, "${%s}", data); /* SAFE */
  621. ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
  622. if (mchan) {
  623. ast_channel_unref(mchan);
  624. }
  625. return 0;
  626. }
  627. static int func_mchan_write(struct ast_channel *chan, const char *function,
  628. char *data, const char *value)
  629. {
  630. struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid);
  631. pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
  632. if (mchan) {
  633. ast_channel_unref(mchan);
  634. }
  635. return 0;
  636. }
  637. static struct ast_custom_function mchan_function = {
  638. .name = "MASTER_CHANNEL",
  639. .read2 = func_mchan_read,
  640. .write = func_mchan_write,
  641. };
  642. static int unload_module(void)
  643. {
  644. int res = 0;
  645. res |= ast_custom_function_unregister(&channel_function);
  646. res |= ast_custom_function_unregister(&channels_function);
  647. res |= ast_custom_function_unregister(&mchan_function);
  648. return res;
  649. }
  650. static int load_module(void)
  651. {
  652. int res = 0;
  653. res |= ast_custom_function_register(&channel_function);
  654. res |= ast_custom_function_register(&channels_function);
  655. res |= ast_custom_function_register(&mchan_function);
  656. return res;
  657. }
  658. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");