chan_console.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2006 - 2008, Digium, Inc.
  5. *
  6. * Russell Bryant <russell@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. /*!
  19. * \file
  20. * \brief Cross-platform console channel driver
  21. *
  22. * \author Russell Bryant <russell@digium.com>
  23. *
  24. * \note Some of the code in this file came from chan_oss and chan_alsa.
  25. * chan_oss, Mark Spencer <markster@digium.com>
  26. * chan_oss, Luigi Rizzo
  27. * chan_alsa, Matthew Fredrickson <creslin@digium.com>
  28. *
  29. * \ingroup channel_drivers
  30. *
  31. * Portaudio http://www.portaudio.com/
  32. *
  33. * To install portaudio v19 from svn, check it out using the following command:
  34. * - svn co https://www.portaudio.com/repos/portaudio/branches/v19-devel
  35. *
  36. * \note Since this works with any audio system that libportaudio supports,
  37. * including ALSA and OSS, this may someday deprecate chan_alsa and chan_oss.
  38. * However, before that can be done, it needs to *at least* have all of the
  39. * features that these other channel drivers have. The features implemented
  40. * in at least one of the other console channel drivers that are not yet
  41. * implemented here are:
  42. *
  43. * - Set Auto-answer from the dialplan
  44. * - transfer CLI command
  45. * - boost CLI command and .conf option
  46. * - console_video support
  47. */
  48. /*! \li \ref chan_console.c uses the configuration file \ref console.conf
  49. * \addtogroup configuration_file
  50. */
  51. /*! \page console.conf console.conf
  52. * \verbinclude console.conf.sample
  53. */
  54. /*** MODULEINFO
  55. <depend>portaudio</depend>
  56. <support_level>extended</support_level>
  57. ***/
  58. #include "asterisk.h"
  59. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  60. #include <sys/signal.h> /* SIGURG */
  61. #include <portaudio.h>
  62. #include "asterisk/module.h"
  63. #include "asterisk/channel.h"
  64. #include "asterisk/pbx.h"
  65. #include "asterisk/causes.h"
  66. #include "asterisk/cli.h"
  67. #include "asterisk/musiconhold.h"
  68. #include "asterisk/callerid.h"
  69. #include "asterisk/astobj2.h"
  70. #include "asterisk/stasis_channels.h"
  71. #include "asterisk/format_cache.h"
  72. /*!
  73. * \brief The sample rate to request from PortAudio
  74. *
  75. * \todo Make this optional. If this is only going to talk to 8 kHz endpoints,
  76. * then it makes sense to use 8 kHz natively.
  77. */
  78. #define SAMPLE_RATE 16000
  79. /*!
  80. * \brief The number of samples to configure the portaudio stream for
  81. *
  82. * 320 samples (20 ms) is the most common frame size in Asterisk. So, the code
  83. * in this module reads 320 sample frames from the portaudio stream and queues
  84. * them up on the Asterisk channel. Frames of any size can be written to a
  85. * portaudio stream, but the portaudio documentation does say that for high
  86. * performance applications, the data should be written to Pa_WriteStream in
  87. * the same size as what is used to initialize the stream.
  88. */
  89. #define NUM_SAMPLES 320
  90. /*! \brief Mono Input */
  91. #define INPUT_CHANNELS 1
  92. /*! \brief Mono Output */
  93. #define OUTPUT_CHANNELS 1
  94. /*!
  95. * \brief Maximum text message length
  96. * \note This should be changed if there is a common definition somewhere
  97. * that defines the maximum length of a text message.
  98. */
  99. #define TEXT_SIZE 256
  100. /*! \brief Dance, Kirby, Dance! @{ */
  101. #define V_BEGIN " --- <(\"<) --- "
  102. #define V_END " --- (>\")> ---\n"
  103. /*! @} */
  104. static const char config_file[] = "console.conf";
  105. /*!
  106. * \brief Console pvt structure
  107. *
  108. * Currently, this is a singleton object. However, multiple instances will be
  109. * needed when this module is updated for multiple device support.
  110. */
  111. static struct console_pvt {
  112. AST_DECLARE_STRING_FIELDS(
  113. /*! Name of the device */
  114. AST_STRING_FIELD(name);
  115. AST_STRING_FIELD(input_device);
  116. AST_STRING_FIELD(output_device);
  117. /*! Default context for outgoing calls */
  118. AST_STRING_FIELD(context);
  119. /*! Default extension for outgoing calls */
  120. AST_STRING_FIELD(exten);
  121. /*! Default CallerID number */
  122. AST_STRING_FIELD(cid_num);
  123. /*! Default CallerID name */
  124. AST_STRING_FIELD(cid_name);
  125. /*! Default MOH class to listen to, if:
  126. * - No MOH class set on the channel
  127. * - Peer channel putting this device on hold did not suggest a class */
  128. AST_STRING_FIELD(mohinterpret);
  129. /*! Default language */
  130. AST_STRING_FIELD(language);
  131. /*! Default parkinglot */
  132. AST_STRING_FIELD(parkinglot);
  133. );
  134. /*! Current channel for this device */
  135. struct ast_channel *owner;
  136. /*! Current PortAudio stream for this device */
  137. PaStream *stream;
  138. /*! A frame for preparing to queue on to the channel */
  139. struct ast_frame fr;
  140. /*! Running = 1, Not running = 0 */
  141. unsigned int streamstate:1;
  142. /*! On-hook = 0, Off-hook = 1 */
  143. unsigned int hookstate:1;
  144. /*! Unmuted = 0, Muted = 1 */
  145. unsigned int muted:1;
  146. /*! Automatically answer incoming calls */
  147. unsigned int autoanswer:1;
  148. /*! Ignore context in the console dial CLI command */
  149. unsigned int overridecontext:1;
  150. /*! Set during a reload so that we know to destroy this if it is no longer
  151. * in the configuration file. */
  152. unsigned int destroy:1;
  153. /*! ID for the stream monitor thread */
  154. pthread_t thread;
  155. } globals;
  156. AST_MUTEX_DEFINE_STATIC(globals_lock);
  157. static struct ao2_container *pvts;
  158. #define NUM_PVT_BUCKETS 7
  159. static struct console_pvt *active_pvt;
  160. AST_RWLOCK_DEFINE_STATIC(active_lock);
  161. /*!
  162. * \brief Global jitterbuffer configuration
  163. *
  164. * \note Disabled by default.
  165. * \note Values shown here match the defaults shown in console.conf.sample
  166. */
  167. static struct ast_jb_conf default_jbconf = {
  168. .flags = 0,
  169. .max_size = 200,
  170. .resync_threshold = 1000,
  171. .impl = "fixed",
  172. .target_extra = 40,
  173. };
  174. static struct ast_jb_conf global_jbconf;
  175. /*! Channel Technology Callbacks @{ */
  176. static struct ast_channel *console_request(const char *type, struct ast_format_cap *cap,
  177. const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);
  178. static int console_digit_begin(struct ast_channel *c, char digit);
  179. static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration);
  180. static int console_text(struct ast_channel *c, const char *text);
  181. static int console_hangup(struct ast_channel *c);
  182. static int console_answer(struct ast_channel *c);
  183. static struct ast_frame *console_read(struct ast_channel *chan);
  184. static int console_call(struct ast_channel *c, const char *dest, int timeout);
  185. static int console_write(struct ast_channel *chan, struct ast_frame *f);
  186. static int console_indicate(struct ast_channel *chan, int cond,
  187. const void *data, size_t datalen);
  188. static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
  189. /*! @} */
  190. static struct ast_channel_tech console_tech = {
  191. .type = "Console",
  192. .description = "Console Channel Driver",
  193. .requester = console_request,
  194. .send_digit_begin = console_digit_begin,
  195. .send_digit_end = console_digit_end,
  196. .send_text = console_text,
  197. .hangup = console_hangup,
  198. .answer = console_answer,
  199. .read = console_read,
  200. .call = console_call,
  201. .write = console_write,
  202. .indicate = console_indicate,
  203. .fixup = console_fixup,
  204. };
  205. /*! \brief lock a console_pvt struct */
  206. #define console_pvt_lock(pvt) ao2_lock(pvt)
  207. /*! \brief unlock a console_pvt struct */
  208. #define console_pvt_unlock(pvt) ao2_unlock(pvt)
  209. static inline struct console_pvt *ref_pvt(struct console_pvt *pvt)
  210. {
  211. if (pvt)
  212. ao2_ref(pvt, +1);
  213. return pvt;
  214. }
  215. static inline struct console_pvt *unref_pvt(struct console_pvt *pvt)
  216. {
  217. ao2_ref(pvt, -1);
  218. return NULL;
  219. }
  220. static struct console_pvt *find_pvt(const char *name)
  221. {
  222. struct console_pvt tmp_pvt = {
  223. .name = name,
  224. };
  225. return ao2_find(pvts, &tmp_pvt, OBJ_POINTER);
  226. }
  227. /*!
  228. * \brief Stream monitor thread
  229. *
  230. * \arg data A pointer to the console_pvt structure that contains the portaudio
  231. * stream that needs to be monitored.
  232. *
  233. * This function runs in its own thread to monitor data coming in from a
  234. * portaudio stream. When enough data is available, it is queued up to
  235. * be read from the Asterisk channel.
  236. */
  237. static void *stream_monitor(void *data)
  238. {
  239. struct console_pvt *pvt = data;
  240. char buf[NUM_SAMPLES * sizeof(int16_t)];
  241. PaError res;
  242. struct ast_frame f = {
  243. .frametype = AST_FRAME_VOICE,
  244. .subclass.format = ast_format_slin16,
  245. .src = "console_stream_monitor",
  246. .data.ptr = buf,
  247. .datalen = sizeof(buf),
  248. .samples = sizeof(buf) / sizeof(int16_t),
  249. };
  250. for (;;) {
  251. pthread_testcancel();
  252. res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
  253. pthread_testcancel();
  254. if (!pvt->owner) {
  255. return NULL;
  256. }
  257. if (res == paNoError)
  258. ast_queue_frame(pvt->owner, &f);
  259. }
  260. return NULL;
  261. }
  262. static int open_stream(struct console_pvt *pvt)
  263. {
  264. int res = paInternalError;
  265. if (!strcasecmp(pvt->input_device, "default") &&
  266. !strcasecmp(pvt->output_device, "default")) {
  267. res = Pa_OpenDefaultStream(&pvt->stream, INPUT_CHANNELS, OUTPUT_CHANNELS,
  268. paInt16, SAMPLE_RATE, NUM_SAMPLES, NULL, NULL);
  269. } else {
  270. PaStreamParameters input_params = {
  271. .channelCount = 1,
  272. .sampleFormat = paInt16,
  273. .suggestedLatency = (1.0 / 50.0), /* 20 ms */
  274. .device = paNoDevice,
  275. };
  276. PaStreamParameters output_params = {
  277. .channelCount = 1,
  278. .sampleFormat = paInt16,
  279. .suggestedLatency = (1.0 / 50.0), /* 20 ms */
  280. .device = paNoDevice,
  281. };
  282. PaDeviceIndex idx, num_devices, def_input, def_output;
  283. if (!(num_devices = Pa_GetDeviceCount()))
  284. return res;
  285. def_input = Pa_GetDefaultInputDevice();
  286. def_output = Pa_GetDefaultOutputDevice();
  287. for (idx = 0;
  288. idx < num_devices && (input_params.device == paNoDevice
  289. || output_params.device == paNoDevice);
  290. idx++)
  291. {
  292. const PaDeviceInfo *dev = Pa_GetDeviceInfo(idx);
  293. if (dev->maxInputChannels) {
  294. if ( (idx == def_input && !strcasecmp(pvt->input_device, "default")) ||
  295. !strcasecmp(pvt->input_device, dev->name) )
  296. input_params.device = idx;
  297. }
  298. if (dev->maxOutputChannels) {
  299. if ( (idx == def_output && !strcasecmp(pvt->output_device, "default")) ||
  300. !strcasecmp(pvt->output_device, dev->name) )
  301. output_params.device = idx;
  302. }
  303. }
  304. if (input_params.device == paNoDevice)
  305. ast_log(LOG_ERROR, "No input device found for console device '%s'\n", pvt->name);
  306. if (output_params.device == paNoDevice)
  307. ast_log(LOG_ERROR, "No output device found for console device '%s'\n", pvt->name);
  308. res = Pa_OpenStream(&pvt->stream, &input_params, &output_params,
  309. SAMPLE_RATE, NUM_SAMPLES, paNoFlag, NULL, NULL);
  310. }
  311. return res;
  312. }
  313. static int start_stream(struct console_pvt *pvt)
  314. {
  315. PaError res;
  316. int ret_val = 0;
  317. console_pvt_lock(pvt);
  318. /* It is possible for console_hangup to be called before the
  319. * stream is started, if this is the case pvt->owner will be NULL
  320. * and start_stream should be aborted. */
  321. if (pvt->streamstate || !pvt->owner)
  322. goto return_unlock;
  323. pvt->streamstate = 1;
  324. ast_debug(1, "Starting stream\n");
  325. res = open_stream(pvt);
  326. if (res != paNoError) {
  327. ast_log(LOG_WARNING, "Failed to open stream - (%d) %s\n",
  328. res, Pa_GetErrorText(res));
  329. ret_val = -1;
  330. goto return_unlock;
  331. }
  332. res = Pa_StartStream(pvt->stream);
  333. if (res != paNoError) {
  334. ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
  335. res, Pa_GetErrorText(res));
  336. ret_val = -1;
  337. goto return_unlock;
  338. }
  339. if (ast_pthread_create_background(&pvt->thread, NULL, stream_monitor, pvt)) {
  340. ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
  341. ret_val = -1;
  342. }
  343. return_unlock:
  344. console_pvt_unlock(pvt);
  345. return ret_val;
  346. }
  347. static int stop_stream(struct console_pvt *pvt)
  348. {
  349. if (!pvt->streamstate || pvt->thread == AST_PTHREADT_NULL)
  350. return 0;
  351. pthread_cancel(pvt->thread);
  352. pthread_kill(pvt->thread, SIGURG);
  353. pthread_join(pvt->thread, NULL);
  354. console_pvt_lock(pvt);
  355. Pa_AbortStream(pvt->stream);
  356. Pa_CloseStream(pvt->stream);
  357. pvt->stream = NULL;
  358. pvt->streamstate = 0;
  359. console_pvt_unlock(pvt);
  360. return 0;
  361. }
  362. /*!
  363. * \note Called with the pvt struct locked
  364. */
  365. static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
  366. {
  367. struct ast_format_cap *caps;
  368. struct ast_channel *chan;
  369. caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
  370. if (!caps) {
  371. return NULL;
  372. }
  373. if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL,
  374. ext, ctx, assignedids, requestor, 0, "Console/%s", pvt->name))) {
  375. ao2_ref(caps, -1);
  376. return NULL;
  377. }
  378. ast_channel_stage_snapshot(chan);
  379. ast_channel_tech_set(chan, &console_tech);
  380. ast_channel_set_readformat(chan, ast_format_slin16);
  381. ast_channel_set_writeformat(chan, ast_format_slin16);
  382. ast_format_cap_append(caps, ast_format_slin16, 0);
  383. ast_channel_nativeformats_set(chan, caps);
  384. ao2_ref(caps, -1);
  385. ast_channel_tech_pvt_set(chan, ref_pvt(pvt));
  386. pvt->owner = chan;
  387. if (!ast_strlen_zero(pvt->language))
  388. ast_channel_language_set(chan, pvt->language);
  389. ast_jb_configure(chan, &global_jbconf);
  390. ast_channel_stage_snapshot_done(chan);
  391. ast_channel_unlock(chan);
  392. if (state != AST_STATE_DOWN) {
  393. if (ast_pbx_start(chan)) {
  394. ast_channel_hangupcause_set(chan, AST_CAUSE_SWITCH_CONGESTION);
  395. ast_hangup(chan);
  396. chan = NULL;
  397. } else
  398. start_stream(pvt);
  399. }
  400. return chan;
  401. }
  402. static struct ast_channel *console_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
  403. {
  404. struct ast_channel *chan = NULL;
  405. struct console_pvt *pvt;
  406. if (!(pvt = find_pvt(data))) {
  407. ast_log(LOG_ERROR, "Console device '%s' not found\n", data);
  408. return NULL;
  409. }
  410. if (!(ast_format_cap_iscompatible(cap, console_tech.capabilities))) {
  411. struct ast_str *cap_buf = ast_str_alloca(64);
  412. ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n",
  413. ast_format_cap_get_names(cap, &cap_buf));
  414. goto return_unref;
  415. }
  416. if (pvt->owner) {
  417. ast_log(LOG_NOTICE, "Console channel already active!\n");
  418. *cause = AST_CAUSE_BUSY;
  419. goto return_unref;
  420. }
  421. console_pvt_lock(pvt);
  422. chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN, assignedids, requestor);
  423. console_pvt_unlock(pvt);
  424. if (!chan)
  425. ast_log(LOG_WARNING, "Unable to create new Console channel!\n");
  426. return_unref:
  427. unref_pvt(pvt);
  428. return chan;
  429. }
  430. static int console_digit_begin(struct ast_channel *c, char digit)
  431. {
  432. ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);
  433. return -1; /* non-zero to request inband audio */
  434. }
  435. static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration)
  436. {
  437. ast_verb(1, V_BEGIN "Console Received End of Digit %c (duration %u)" V_END,
  438. digit, duration);
  439. return -1; /* non-zero to request inband audio */
  440. }
  441. static int console_text(struct ast_channel *c, const char *text)
  442. {
  443. ast_verb(1, V_BEGIN "Console Received Text '%s'" V_END, text);
  444. return 0;
  445. }
  446. static int console_hangup(struct ast_channel *c)
  447. {
  448. struct console_pvt *pvt = ast_channel_tech_pvt(c);
  449. ast_verb(1, V_BEGIN "Hangup on Console" V_END);
  450. pvt->hookstate = 0;
  451. pvt->owner = NULL;
  452. stop_stream(pvt);
  453. ast_channel_tech_pvt_set(c, unref_pvt(pvt));
  454. return 0;
  455. }
  456. static int console_answer(struct ast_channel *c)
  457. {
  458. struct console_pvt *pvt = ast_channel_tech_pvt(c);
  459. ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);
  460. ast_setstate(c, AST_STATE_UP);
  461. return start_stream(pvt);
  462. }
  463. /*
  464. * \brief Implementation of the ast_channel_tech read() callback
  465. *
  466. * Calling this function is harmless. However, if it does get called, it
  467. * is an indication that something weird happened that really shouldn't
  468. * have and is worth looking into.
  469. *
  470. * Why should this function not get called? Well, let me explain. There are
  471. * a couple of ways to pass on audio that has come from this channel. The way
  472. * that this channel driver uses is that once the audio is available, it is
  473. * wrapped in an ast_frame and queued onto the channel using ast_queue_frame().
  474. *
  475. * The other method would be signalling to the core that there is audio waiting,
  476. * and that it needs to call the channel's read() callback to get it. The way
  477. * the channel gets signalled is that one or more file descriptors are placed
  478. * in the fds array on the ast_channel which the core will poll() on. When the
  479. * fd indicates that input is available, the read() callback is called. This
  480. * is especially useful when there is a dedicated file descriptor where the
  481. * audio is read from. An example would be the socket for an RTP stream.
  482. */
  483. static struct ast_frame *console_read(struct ast_channel *chan)
  484. {
  485. ast_debug(1, "I should not be called ...\n");
  486. return &ast_null_frame;
  487. }
  488. static int console_call(struct ast_channel *c, const char *dest, int timeout)
  489. {
  490. struct console_pvt *pvt = ast_channel_tech_pvt(c);
  491. enum ast_control_frame_type ctrl;
  492. ast_verb(1, V_BEGIN "Call to device '%s' on console from '%s' <%s>" V_END,
  493. dest,
  494. S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, ""),
  495. S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, ""));
  496. console_pvt_lock(pvt);
  497. if (pvt->autoanswer) {
  498. pvt->hookstate = 1;
  499. console_pvt_unlock(pvt);
  500. ast_verb(1, V_BEGIN "Auto-answered" V_END);
  501. ctrl = AST_CONTROL_ANSWER;
  502. } else {
  503. console_pvt_unlock(pvt);
  504. ast_verb(1, V_BEGIN "Type 'console answer' to answer, or use the 'autoanswer' option "
  505. "for future calls" V_END);
  506. ctrl = AST_CONTROL_RINGING;
  507. ast_indicate(c, AST_CONTROL_RINGING);
  508. }
  509. ast_queue_control(c, ctrl);
  510. return start_stream(pvt);
  511. }
  512. static int console_write(struct ast_channel *chan, struct ast_frame *f)
  513. {
  514. struct console_pvt *pvt = ast_channel_tech_pvt(chan);
  515. Pa_WriteStream(pvt->stream, f->data.ptr, f->samples);
  516. return 0;
  517. }
  518. static int console_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
  519. {
  520. struct console_pvt *pvt = ast_channel_tech_pvt(chan);
  521. int res = 0;
  522. switch (cond) {
  523. case AST_CONTROL_BUSY:
  524. case AST_CONTROL_CONGESTION:
  525. case AST_CONTROL_RINGING:
  526. case AST_CONTROL_INCOMPLETE:
  527. case AST_CONTROL_PVT_CAUSE_CODE:
  528. case -1:
  529. res = -1; /* Ask for inband indications */
  530. break;
  531. case AST_CONTROL_PROGRESS:
  532. case AST_CONTROL_PROCEEDING:
  533. case AST_CONTROL_VIDUPDATE:
  534. case AST_CONTROL_SRCUPDATE:
  535. break;
  536. case AST_CONTROL_HOLD:
  537. ast_verb(1, V_BEGIN "Console Has Been Placed on Hold" V_END);
  538. ast_moh_start(chan, data, pvt->mohinterpret);
  539. break;
  540. case AST_CONTROL_UNHOLD:
  541. ast_verb(1, V_BEGIN "Console Has Been Retrieved from Hold" V_END);
  542. ast_moh_stop(chan);
  543. break;
  544. default:
  545. ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n",
  546. cond, ast_channel_name(chan));
  547. /* The core will play inband indications for us if appropriate */
  548. res = -1;
  549. }
  550. return res;
  551. }
  552. static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
  553. {
  554. struct console_pvt *pvt = ast_channel_tech_pvt(newchan);
  555. pvt->owner = newchan;
  556. return 0;
  557. }
  558. /*!
  559. * split a string in extension-context, returns pointers to malloc'ed
  560. * strings.
  561. * If we do not have 'overridecontext' then the last @ is considered as
  562. * a context separator, and the context is overridden.
  563. * This is usually not very necessary as you can play with the dialplan,
  564. * and it is nice not to need it because you have '@' in SIP addresses.
  565. * Return value is the buffer address.
  566. *
  567. * \note came from chan_oss
  568. */
  569. static char *ast_ext_ctx(struct console_pvt *pvt, const char *src, char **ext, char **ctx)
  570. {
  571. if (ext == NULL || ctx == NULL)
  572. return NULL; /* error */
  573. *ext = *ctx = NULL;
  574. if (src && *src != '\0')
  575. *ext = ast_strdup(src);
  576. if (*ext == NULL)
  577. return NULL;
  578. if (!pvt->overridecontext) {
  579. /* parse from the right */
  580. *ctx = strrchr(*ext, '@');
  581. if (*ctx)
  582. *(*ctx)++ = '\0';
  583. }
  584. return *ext;
  585. }
  586. static struct console_pvt *get_active_pvt(void)
  587. {
  588. struct console_pvt *pvt;
  589. ast_rwlock_rdlock(&active_lock);
  590. pvt = ref_pvt(active_pvt);
  591. ast_rwlock_unlock(&active_lock);
  592. return pvt;
  593. }
  594. static char *cli_console_autoanswer(struct ast_cli_entry *e, int cmd,
  595. struct ast_cli_args *a)
  596. {
  597. struct console_pvt *pvt;
  598. char *res = CLI_SUCCESS;
  599. switch (cmd) {
  600. case CLI_INIT:
  601. e->command = "console {set|show} autoanswer [on|off]";
  602. e->usage =
  603. "Usage: console {set|show} autoanswer [on|off]\n"
  604. " Enables or disables autoanswer feature. If used without\n"
  605. " argument, displays the current on/off status of autoanswer.\n"
  606. " The default value of autoanswer is in 'oss.conf'.\n";
  607. return NULL;
  608. case CLI_GENERATE:
  609. return NULL;
  610. }
  611. pvt = get_active_pvt();
  612. if (!pvt) {
  613. ast_cli(a->fd, "No console device is set as active.\n");
  614. return CLI_FAILURE;
  615. }
  616. if (a->argc == e->args - 1) {
  617. ast_cli(a->fd, "Auto answer is %s.\n", pvt->autoanswer ? "on" : "off");
  618. unref_pvt(pvt);
  619. return CLI_SUCCESS;
  620. }
  621. if (a->argc != e->args) {
  622. unref_pvt(pvt);
  623. return CLI_SHOWUSAGE;
  624. }
  625. if (!strcasecmp(a->argv[e->args-1], "on"))
  626. pvt->autoanswer = 1;
  627. else if (!strcasecmp(a->argv[e->args - 1], "off"))
  628. pvt->autoanswer = 0;
  629. else
  630. res = CLI_SHOWUSAGE;
  631. unref_pvt(pvt);
  632. return res;
  633. }
  634. static char *cli_console_flash(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  635. {
  636. struct console_pvt *pvt;
  637. if (cmd == CLI_INIT) {
  638. e->command = "console flash";
  639. e->usage =
  640. "Usage: console flash\n"
  641. " Flashes the call currently placed on the console.\n";
  642. return NULL;
  643. } else if (cmd == CLI_GENERATE) {
  644. return NULL;
  645. }
  646. if (a->argc != e->args) {
  647. return CLI_SHOWUSAGE;
  648. }
  649. pvt = get_active_pvt();
  650. if (!pvt) {
  651. ast_cli(a->fd, "No console device is set as active\n");
  652. return CLI_FAILURE;
  653. }
  654. if (!pvt->owner) {
  655. ast_cli(a->fd, "No call to flash\n");
  656. unref_pvt(pvt);
  657. return CLI_FAILURE;
  658. }
  659. pvt->hookstate = 0;
  660. ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
  661. unref_pvt(pvt);
  662. return CLI_SUCCESS;
  663. }
  664. static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  665. {
  666. char *s = NULL;
  667. const char *mye = NULL, *myc = NULL;
  668. struct console_pvt *pvt;
  669. if (cmd == CLI_INIT) {
  670. e->command = "console dial";
  671. e->usage =
  672. "Usage: console dial [extension[@context]]\n"
  673. " Dials a given extension (and context if specified)\n";
  674. return NULL;
  675. } else if (cmd == CLI_GENERATE) {
  676. return NULL;
  677. }
  678. if (a->argc > e->args + 1) {
  679. return CLI_SHOWUSAGE;
  680. }
  681. pvt = get_active_pvt();
  682. if (!pvt) {
  683. ast_cli(a->fd, "No console device is currently set as active\n");
  684. return CLI_FAILURE;
  685. }
  686. if (pvt->owner) { /* already in a call */
  687. int i;
  688. struct ast_frame f = { AST_FRAME_DTMF };
  689. const char *s;
  690. if (a->argc == e->args) { /* argument is mandatory here */
  691. ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
  692. unref_pvt(pvt);
  693. return CLI_FAILURE;
  694. }
  695. s = a->argv[e->args];
  696. /* send the string one char at a time */
  697. for (i = 0; i < strlen(s); i++) {
  698. f.subclass.integer = s[i];
  699. ast_queue_frame(pvt->owner, &f);
  700. }
  701. unref_pvt(pvt);
  702. return CLI_SUCCESS;
  703. }
  704. /* if we have an argument split it into extension and context */
  705. if (a->argc == e->args + 1) {
  706. char *ext = NULL, *con = NULL;
  707. s = ast_ext_ctx(pvt, a->argv[e->args], &ext, &con);
  708. ast_debug(1, "provided '%s', exten '%s' context '%s'\n",
  709. a->argv[e->args], mye, myc);
  710. mye = ext;
  711. myc = con;
  712. }
  713. /* supply default values if needed */
  714. if (ast_strlen_zero(mye))
  715. mye = pvt->exten;
  716. if (ast_strlen_zero(myc))
  717. myc = pvt->context;
  718. if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
  719. console_pvt_lock(pvt);
  720. pvt->hookstate = 1;
  721. console_new(pvt, mye, myc, AST_STATE_RINGING, NULL, NULL);
  722. console_pvt_unlock(pvt);
  723. } else
  724. ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
  725. ast_free(s);
  726. unref_pvt(pvt);
  727. return CLI_SUCCESS;
  728. }
  729. static char *cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  730. {
  731. struct console_pvt *pvt;
  732. if (cmd == CLI_INIT) {
  733. e->command = "console hangup";
  734. e->usage =
  735. "Usage: console hangup\n"
  736. " Hangs up any call currently placed on the console.\n";
  737. return NULL;
  738. } else if (cmd == CLI_GENERATE) {
  739. return NULL;
  740. }
  741. if (a->argc != e->args) {
  742. return CLI_SHOWUSAGE;
  743. }
  744. pvt = get_active_pvt();
  745. if (!pvt) {
  746. ast_cli(a->fd, "No console device is set as active\n");
  747. return CLI_FAILURE;
  748. }
  749. if (!pvt->owner && !pvt->hookstate) {
  750. ast_cli(a->fd, "No call to hang up\n");
  751. unref_pvt(pvt);
  752. return CLI_FAILURE;
  753. }
  754. pvt->hookstate = 0;
  755. if (pvt->owner)
  756. ast_queue_hangup(pvt->owner);
  757. unref_pvt(pvt);
  758. return CLI_SUCCESS;
  759. }
  760. static char *cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  761. {
  762. const char *s;
  763. struct console_pvt *pvt;
  764. char *res = CLI_SUCCESS;
  765. if (cmd == CLI_INIT) {
  766. e->command = "console {mute|unmute}";
  767. e->usage =
  768. "Usage: console {mute|unmute}\n"
  769. " Mute/unmute the microphone.\n";
  770. return NULL;
  771. } else if (cmd == CLI_GENERATE) {
  772. return NULL;
  773. }
  774. if (a->argc != e->args) {
  775. return CLI_SHOWUSAGE;
  776. }
  777. pvt = get_active_pvt();
  778. if (!pvt) {
  779. ast_cli(a->fd, "No console device is set as active\n");
  780. return CLI_FAILURE;
  781. }
  782. s = a->argv[e->args-1];
  783. if (!strcasecmp(s, "mute"))
  784. pvt->muted = 1;
  785. else if (!strcasecmp(s, "unmute"))
  786. pvt->muted = 0;
  787. else
  788. res = CLI_SHOWUSAGE;
  789. ast_verb(1, V_BEGIN "The Console is now %s" V_END,
  790. pvt->muted ? "Muted" : "Unmuted");
  791. unref_pvt(pvt);
  792. return res;
  793. }
  794. static char *cli_list_available(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  795. {
  796. PaDeviceIndex idx, num, def_input, def_output;
  797. if (cmd == CLI_INIT) {
  798. e->command = "console list available";
  799. e->usage =
  800. "Usage: console list available\n"
  801. " List all available devices.\n";
  802. return NULL;
  803. } else if (cmd == CLI_GENERATE)
  804. return NULL;
  805. if (a->argc != e->args)
  806. return CLI_SHOWUSAGE;
  807. ast_cli(a->fd, "\n"
  808. "=============================================================\n"
  809. "=== Available Devices =======================================\n"
  810. "=============================================================\n"
  811. "===\n");
  812. num = Pa_GetDeviceCount();
  813. if (!num) {
  814. ast_cli(a->fd, "(None)\n");
  815. return CLI_SUCCESS;
  816. }
  817. def_input = Pa_GetDefaultInputDevice();
  818. def_output = Pa_GetDefaultOutputDevice();
  819. for (idx = 0; idx < num; idx++) {
  820. const PaDeviceInfo *dev = Pa_GetDeviceInfo(idx);
  821. if (!dev)
  822. continue;
  823. ast_cli(a->fd, "=== ---------------------------------------------------------\n"
  824. "=== Device Name: %s\n", dev->name);
  825. if (dev->maxInputChannels)
  826. ast_cli(a->fd, "=== ---> %sInput Device\n", (idx == def_input) ? "Default " : "");
  827. if (dev->maxOutputChannels)
  828. ast_cli(a->fd, "=== ---> %sOutput Device\n", (idx == def_output) ? "Default " : "");
  829. ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n");
  830. }
  831. ast_cli(a->fd, "=============================================================\n\n");
  832. return CLI_SUCCESS;
  833. }
  834. static char *cli_list_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  835. {
  836. struct ao2_iterator i;
  837. struct console_pvt *pvt;
  838. if (cmd == CLI_INIT) {
  839. e->command = "console list devices";
  840. e->usage =
  841. "Usage: console list devices\n"
  842. " List all configured devices.\n";
  843. return NULL;
  844. } else if (cmd == CLI_GENERATE)
  845. return NULL;
  846. if (a->argc != e->args)
  847. return CLI_SHOWUSAGE;
  848. ast_cli(a->fd, "\n"
  849. "=============================================================\n"
  850. "=== Configured Devices ======================================\n"
  851. "=============================================================\n"
  852. "===\n");
  853. i = ao2_iterator_init(pvts, 0);
  854. while ((pvt = ao2_iterator_next(&i))) {
  855. console_pvt_lock(pvt);
  856. ast_cli(a->fd, "=== ---------------------------------------------------------\n"
  857. "=== Device Name: %s\n"
  858. "=== ---> Active: %s\n"
  859. "=== ---> Input Device: %s\n"
  860. "=== ---> Output Device: %s\n"
  861. "=== ---> Context: %s\n"
  862. "=== ---> Extension: %s\n"
  863. "=== ---> CallerID Num: %s\n"
  864. "=== ---> CallerID Name: %s\n"
  865. "=== ---> MOH Interpret: %s\n"
  866. "=== ---> Language: %s\n"
  867. "=== ---> Parkinglot: %s\n"
  868. "=== ---> Muted: %s\n"
  869. "=== ---> Auto-Answer: %s\n"
  870. "=== ---> Override Context: %s\n"
  871. "=== ---------------------------------------------------------\n===\n",
  872. pvt->name, (pvt == active_pvt) ? "Yes" : "No",
  873. pvt->input_device, pvt->output_device, pvt->context,
  874. pvt->exten, pvt->cid_num, pvt->cid_name, pvt->mohinterpret,
  875. pvt->language, pvt->parkinglot, pvt->muted ? "Yes" : "No", pvt->autoanswer ? "Yes" : "No",
  876. pvt->overridecontext ? "Yes" : "No");
  877. console_pvt_unlock(pvt);
  878. unref_pvt(pvt);
  879. }
  880. ao2_iterator_destroy(&i);
  881. ast_cli(a->fd, "=============================================================\n\n");
  882. return CLI_SUCCESS;
  883. }
  884. /*!
  885. * \brief answer command from the console
  886. */
  887. static char *cli_console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  888. {
  889. struct console_pvt *pvt;
  890. switch (cmd) {
  891. case CLI_INIT:
  892. e->command = "console answer";
  893. e->usage =
  894. "Usage: console answer\n"
  895. " Answers an incoming call on the console channel.\n";
  896. return NULL;
  897. case CLI_GENERATE:
  898. return NULL; /* no completion */
  899. }
  900. pvt = get_active_pvt();
  901. if (!pvt) {
  902. ast_cli(a->fd, "No console device is set as active\n");
  903. return CLI_FAILURE;
  904. }
  905. if (a->argc != e->args) {
  906. unref_pvt(pvt);
  907. return CLI_SHOWUSAGE;
  908. }
  909. if (!pvt->owner) {
  910. ast_cli(a->fd, "No one is calling us\n");
  911. unref_pvt(pvt);
  912. return CLI_FAILURE;
  913. }
  914. pvt->hookstate = 1;
  915. ast_indicate(pvt->owner, -1);
  916. ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
  917. unref_pvt(pvt);
  918. return CLI_SUCCESS;
  919. }
  920. /*!
  921. * \brief Console send text CLI command
  922. *
  923. * \note concatenate all arguments into a single string. argv is NULL-terminated
  924. * so we can use it right away
  925. */
  926. static char *cli_console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  927. {
  928. char buf[TEXT_SIZE];
  929. struct console_pvt *pvt;
  930. struct ast_frame f = {
  931. .frametype = AST_FRAME_TEXT,
  932. .data.ptr = buf,
  933. .src = "console_send_text",
  934. };
  935. int len;
  936. if (cmd == CLI_INIT) {
  937. e->command = "console send text";
  938. e->usage =
  939. "Usage: console send text <message>\n"
  940. " Sends a text message for display on the remote terminal.\n";
  941. return NULL;
  942. } else if (cmd == CLI_GENERATE) {
  943. return NULL;
  944. }
  945. pvt = get_active_pvt();
  946. if (!pvt) {
  947. ast_cli(a->fd, "No console device is set as active\n");
  948. return CLI_FAILURE;
  949. }
  950. if (a->argc < e->args + 1) {
  951. unref_pvt(pvt);
  952. return CLI_SHOWUSAGE;
  953. }
  954. if (!pvt->owner) {
  955. ast_cli(a->fd, "Not in a call\n");
  956. unref_pvt(pvt);
  957. return CLI_FAILURE;
  958. }
  959. ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
  960. if (ast_strlen_zero(buf)) {
  961. unref_pvt(pvt);
  962. return CLI_SHOWUSAGE;
  963. }
  964. len = strlen(buf);
  965. buf[len] = '\n';
  966. f.datalen = len + 1;
  967. ast_queue_frame(pvt->owner, &f);
  968. unref_pvt(pvt);
  969. return CLI_SUCCESS;
  970. }
  971. static void set_active(struct console_pvt *pvt, const char *value)
  972. {
  973. if (pvt == &globals) {
  974. ast_log(LOG_ERROR, "active is only valid as a per-device setting\n");
  975. return;
  976. }
  977. if (!ast_true(value))
  978. return;
  979. ast_rwlock_wrlock(&active_lock);
  980. if (active_pvt)
  981. unref_pvt(active_pvt);
  982. active_pvt = ref_pvt(pvt);
  983. ast_rwlock_unlock(&active_lock);
  984. }
  985. static char *cli_console_active(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  986. {
  987. struct console_pvt *pvt;
  988. switch (cmd) {
  989. case CLI_INIT:
  990. e->command = "console {set|show} active";
  991. e->usage =
  992. "Usage: console {set|show} active [<device>]\n"
  993. " Set or show the active console device for the Asterisk CLI.\n";
  994. return NULL;
  995. case CLI_GENERATE:
  996. if (a->pos == e->args) {
  997. struct ao2_iterator i;
  998. int x = 0;
  999. char *res = NULL;
  1000. i = ao2_iterator_init(pvts, 0);
  1001. while ((pvt = ao2_iterator_next(&i))) {
  1002. if (++x > a->n && !strncasecmp(pvt->name, a->word, strlen(a->word)))
  1003. res = ast_strdup(pvt->name);
  1004. unref_pvt(pvt);
  1005. if (res) {
  1006. ao2_iterator_destroy(&i);
  1007. return res;
  1008. }
  1009. }
  1010. ao2_iterator_destroy(&i);
  1011. }
  1012. return NULL;
  1013. }
  1014. if (a->argc < e->args)
  1015. return CLI_SHOWUSAGE;
  1016. if (a->argc == 3) {
  1017. pvt = get_active_pvt();
  1018. if (!pvt)
  1019. ast_cli(a->fd, "No device is currently set as the active console device.\n");
  1020. else {
  1021. console_pvt_lock(pvt);
  1022. ast_cli(a->fd, "The active console device is '%s'.\n", pvt->name);
  1023. console_pvt_unlock(pvt);
  1024. pvt = unref_pvt(pvt);
  1025. }
  1026. return CLI_SUCCESS;
  1027. }
  1028. if (!(pvt = find_pvt(a->argv[e->args - 1]))) {
  1029. ast_cli(a->fd, "Could not find a device called '%s'.\n", a->argv[e->args]);
  1030. return CLI_FAILURE;
  1031. }
  1032. set_active(pvt, "yes");
  1033. console_pvt_lock(pvt);
  1034. ast_cli(a->fd, "The active console device has been set to '%s'\n", pvt->name);
  1035. console_pvt_unlock(pvt);
  1036. unref_pvt(pvt);
  1037. return CLI_SUCCESS;
  1038. }
  1039. static struct ast_cli_entry cli_console[] = {
  1040. AST_CLI_DEFINE(cli_console_dial, "Dial an extension from the console"),
  1041. AST_CLI_DEFINE(cli_console_hangup, "Hangup a call on the console"),
  1042. AST_CLI_DEFINE(cli_console_mute, "Disable/Enable mic input"),
  1043. AST_CLI_DEFINE(cli_console_answer, "Answer an incoming console call"),
  1044. AST_CLI_DEFINE(cli_console_sendtext, "Send text to a connected party"),
  1045. AST_CLI_DEFINE(cli_console_flash, "Send a flash to the connected party"),
  1046. AST_CLI_DEFINE(cli_console_autoanswer, "Turn autoanswer on or off"),
  1047. AST_CLI_DEFINE(cli_list_available, "List available devices"),
  1048. AST_CLI_DEFINE(cli_list_devices, "List configured devices"),
  1049. AST_CLI_DEFINE(cli_console_active, "View or Set the active console device"),
  1050. };
  1051. /*!
  1052. * \brief Set default values for a pvt struct
  1053. *
  1054. * \note This function expects the pvt lock to be held.
  1055. */
  1056. static void set_pvt_defaults(struct console_pvt *pvt)
  1057. {
  1058. if (pvt == &globals) {
  1059. ast_string_field_set(pvt, mohinterpret, "default");
  1060. ast_string_field_set(pvt, context, "default");
  1061. ast_string_field_set(pvt, exten, "s");
  1062. ast_string_field_set(pvt, language, "");
  1063. ast_string_field_set(pvt, cid_num, "");
  1064. ast_string_field_set(pvt, cid_name, "");
  1065. ast_string_field_set(pvt, parkinglot, "");
  1066. pvt->overridecontext = 0;
  1067. pvt->autoanswer = 0;
  1068. } else {
  1069. ast_mutex_lock(&globals_lock);
  1070. ast_string_field_set(pvt, mohinterpret, globals.mohinterpret);
  1071. ast_string_field_set(pvt, context, globals.context);
  1072. ast_string_field_set(pvt, exten, globals.exten);
  1073. ast_string_field_set(pvt, language, globals.language);
  1074. ast_string_field_set(pvt, cid_num, globals.cid_num);
  1075. ast_string_field_set(pvt, cid_name, globals.cid_name);
  1076. ast_string_field_set(pvt, parkinglot, globals.parkinglot);
  1077. pvt->overridecontext = globals.overridecontext;
  1078. pvt->autoanswer = globals.autoanswer;
  1079. ast_mutex_unlock(&globals_lock);
  1080. }
  1081. }
  1082. static void store_callerid(struct console_pvt *pvt, const char *value)
  1083. {
  1084. char cid_name[256];
  1085. char cid_num[256];
  1086. ast_callerid_split(value, cid_name, sizeof(cid_name),
  1087. cid_num, sizeof(cid_num));
  1088. ast_string_field_set(pvt, cid_name, cid_name);
  1089. ast_string_field_set(pvt, cid_num, cid_num);
  1090. }
  1091. /*!
  1092. * \brief Store a configuration parameter in a pvt struct
  1093. *
  1094. * \note This function expects the pvt lock to be held.
  1095. */
  1096. static void store_config_core(struct console_pvt *pvt, const char *var, const char *value)
  1097. {
  1098. if (pvt == &globals && !ast_jb_read_conf(&global_jbconf, var, value))
  1099. return;
  1100. CV_START(var, value);
  1101. CV_STRFIELD("context", pvt, context);
  1102. CV_STRFIELD("extension", pvt, exten);
  1103. CV_STRFIELD("mohinterpret", pvt, mohinterpret);
  1104. CV_STRFIELD("language", pvt, language);
  1105. CV_F("callerid", store_callerid(pvt, value));
  1106. CV_BOOL("overridecontext", pvt->overridecontext);
  1107. CV_BOOL("autoanswer", pvt->autoanswer);
  1108. CV_STRFIELD("parkinglot", pvt, parkinglot);
  1109. if (pvt != &globals) {
  1110. CV_F("active", set_active(pvt, value))
  1111. CV_STRFIELD("input_device", pvt, input_device);
  1112. CV_STRFIELD("output_device", pvt, output_device);
  1113. }
  1114. ast_log(LOG_WARNING, "Unknown option '%s'\n", var);
  1115. CV_END;
  1116. }
  1117. static void pvt_destructor(void *obj)
  1118. {
  1119. struct console_pvt *pvt = obj;
  1120. ast_string_field_free_memory(pvt);
  1121. }
  1122. static int init_pvt(struct console_pvt *pvt, const char *name)
  1123. {
  1124. pvt->thread = AST_PTHREADT_NULL;
  1125. if (ast_string_field_init(pvt, 32))
  1126. return -1;
  1127. ast_string_field_set(pvt, name, S_OR(name, ""));
  1128. return 0;
  1129. }
  1130. static void build_device(struct ast_config *cfg, const char *name)
  1131. {
  1132. struct ast_variable *v;
  1133. struct console_pvt *pvt;
  1134. int new = 0;
  1135. if ((pvt = find_pvt(name))) {
  1136. console_pvt_lock(pvt);
  1137. set_pvt_defaults(pvt);
  1138. pvt->destroy = 0;
  1139. } else {
  1140. if (!(pvt = ao2_alloc(sizeof(*pvt), pvt_destructor)))
  1141. return;
  1142. init_pvt(pvt, name);
  1143. set_pvt_defaults(pvt);
  1144. new = 1;
  1145. }
  1146. for (v = ast_variable_browse(cfg, name); v; v = v->next)
  1147. store_config_core(pvt, v->name, v->value);
  1148. if (new)
  1149. ao2_link(pvts, pvt);
  1150. else
  1151. console_pvt_unlock(pvt);
  1152. unref_pvt(pvt);
  1153. }
  1154. static int pvt_mark_destroy_cb(void *obj, void *arg, int flags)
  1155. {
  1156. struct console_pvt *pvt = obj;
  1157. pvt->destroy = 1;
  1158. return 0;
  1159. }
  1160. static void destroy_pvts(void)
  1161. {
  1162. struct ao2_iterator i;
  1163. struct console_pvt *pvt;
  1164. i = ao2_iterator_init(pvts, 0);
  1165. while ((pvt = ao2_iterator_next(&i))) {
  1166. if (pvt->destroy) {
  1167. ao2_unlink(pvts, pvt);
  1168. ast_rwlock_wrlock(&active_lock);
  1169. if (active_pvt == pvt)
  1170. active_pvt = unref_pvt(pvt);
  1171. ast_rwlock_unlock(&active_lock);
  1172. }
  1173. unref_pvt(pvt);
  1174. }
  1175. ao2_iterator_destroy(&i);
  1176. }
  1177. /*!
  1178. * \brief Load the configuration
  1179. * \param reload if this was called due to a reload
  1180. * \retval 0 success
  1181. * \retval -1 failure
  1182. */
  1183. static int load_config(int reload)
  1184. {
  1185. struct ast_config *cfg;
  1186. struct ast_variable *v;
  1187. struct ast_flags config_flags = { 0 };
  1188. char *context = NULL;
  1189. /* default values */
  1190. memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
  1191. ast_mutex_lock(&globals_lock);
  1192. set_pvt_defaults(&globals);
  1193. ast_mutex_unlock(&globals_lock);
  1194. if (!(cfg = ast_config_load(config_file, config_flags))) {
  1195. ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
  1196. return -1;
  1197. } else if (cfg == CONFIG_STATUS_FILEINVALID) {
  1198. ast_log(LOG_NOTICE, "Config file %s has an invalid format\n", config_file);
  1199. return -1;
  1200. }
  1201. ao2_callback(pvts, OBJ_NODATA, pvt_mark_destroy_cb, NULL);
  1202. ast_mutex_lock(&globals_lock);
  1203. for (v = ast_variable_browse(cfg, "general"); v; v = v->next)
  1204. store_config_core(&globals, v->name, v->value);
  1205. ast_mutex_unlock(&globals_lock);
  1206. while ((context = ast_category_browse(cfg, context))) {
  1207. if (strcasecmp(context, "general"))
  1208. build_device(cfg, context);
  1209. }
  1210. ast_config_destroy(cfg);
  1211. destroy_pvts();
  1212. return 0;
  1213. }
  1214. static int pvt_hash_cb(const void *obj, const int flags)
  1215. {
  1216. const struct console_pvt *pvt = obj;
  1217. return ast_str_case_hash(pvt->name);
  1218. }
  1219. static int pvt_cmp_cb(void *obj, void *arg, int flags)
  1220. {
  1221. struct console_pvt *pvt = obj, *pvt2 = arg;
  1222. return !strcasecmp(pvt->name, pvt2->name) ? CMP_MATCH | CMP_STOP : 0;
  1223. }
  1224. static void stop_streams(void)
  1225. {
  1226. struct console_pvt *pvt;
  1227. struct ao2_iterator i;
  1228. i = ao2_iterator_init(pvts, 0);
  1229. while ((pvt = ao2_iterator_next(&i))) {
  1230. if (pvt->hookstate)
  1231. stop_stream(pvt);
  1232. unref_pvt(pvt);
  1233. }
  1234. ao2_iterator_destroy(&i);
  1235. }
  1236. static int unload_module(void)
  1237. {
  1238. ao2_ref(console_tech.capabilities, -1);
  1239. console_tech.capabilities = NULL;
  1240. ast_channel_unregister(&console_tech);
  1241. ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
  1242. stop_streams();
  1243. Pa_Terminate();
  1244. /* Will unref all the pvts so they will get destroyed, too */
  1245. ao2_ref(pvts, -1);
  1246. pvt_destructor(&globals);
  1247. return 0;
  1248. }
  1249. /*!
  1250. * \brief Load the module
  1251. *
  1252. * Module loading including tests for configuration or dependencies.
  1253. * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
  1254. * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
  1255. * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
  1256. * configuration file or other non-critical problem return
  1257. * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
  1258. */
  1259. static int load_module(void)
  1260. {
  1261. PaError res;
  1262. if (!(console_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
  1263. return AST_MODULE_LOAD_DECLINE;
  1264. }
  1265. ast_format_cap_append(console_tech.capabilities, ast_format_slin16, 0);
  1266. init_pvt(&globals, NULL);
  1267. if (!(pvts = ao2_container_alloc(NUM_PVT_BUCKETS, pvt_hash_cb, pvt_cmp_cb)))
  1268. goto return_error;
  1269. if (load_config(0))
  1270. goto return_error;
  1271. res = Pa_Initialize();
  1272. if (res != paNoError) {
  1273. ast_log(LOG_WARNING, "Failed to initialize audio system - (%d) %s\n",
  1274. res, Pa_GetErrorText(res));
  1275. goto return_error_pa_init;
  1276. }
  1277. if (ast_channel_register(&console_tech)) {
  1278. ast_log(LOG_ERROR, "Unable to register channel type 'Console'\n");
  1279. goto return_error_chan_reg;
  1280. }
  1281. if (ast_cli_register_multiple(cli_console, ARRAY_LEN(cli_console)))
  1282. goto return_error_cli_reg;
  1283. return AST_MODULE_LOAD_SUCCESS;
  1284. return_error_cli_reg:
  1285. ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
  1286. return_error_chan_reg:
  1287. ast_channel_unregister(&console_tech);
  1288. return_error_pa_init:
  1289. Pa_Terminate();
  1290. return_error:
  1291. if (pvts)
  1292. ao2_ref(pvts, -1);
  1293. pvts = NULL;
  1294. ao2_ref(console_tech.capabilities, -1);
  1295. console_tech.capabilities = NULL;
  1296. pvt_destructor(&globals);
  1297. return AST_MODULE_LOAD_DECLINE;
  1298. }
  1299. static int reload(void)
  1300. {
  1301. return load_config(1);
  1302. }
  1303. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Console Channel Driver",
  1304. .support_level = AST_MODULE_SUPPORT_EXTENDED,
  1305. .load = load_module,
  1306. .unload = unload_module,
  1307. .reload = reload,
  1308. .load_pri = AST_MODPRI_CHANNEL_DRIVER,
  1309. );