app_fax.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Simple fax applications
  5. *
  6. * 2007-2008, Dmitry Andrianov <asterisk@dima.spb.ru>
  7. *
  8. * Code based on original implementation by Steve Underwood <steveu@coppice.org>
  9. *
  10. * This program is free software, distributed under the terms of
  11. * the GNU General Public License
  12. *
  13. */
  14. /*** MODULEINFO
  15. <defaultenabled>no</defaultenabled>
  16. <depend>spandsp</depend>
  17. <conflict>res_fax</conflict>
  18. <support_level>extended</support_level>
  19. ***/
  20. #include "asterisk.h"
  21. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <inttypes.h>
  26. #include <pthread.h>
  27. #include <errno.h>
  28. #include <tiffio.h>
  29. #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
  30. #include <spandsp.h>
  31. #include <spandsp/version.h>
  32. #include "asterisk/lock.h"
  33. #include "asterisk/file.h"
  34. #include "asterisk/logger.h"
  35. #include "asterisk/channel.h"
  36. #include "asterisk/pbx.h"
  37. #include "asterisk/app.h"
  38. #include "asterisk/dsp.h"
  39. #include "asterisk/module.h"
  40. #include "asterisk/stasis.h"
  41. #include "asterisk/stasis_channels.h"
  42. #include "asterisk/format_cache.h"
  43. /*** DOCUMENTATION
  44. <application name="SendFAX" language="en_US" module="app_fax">
  45. <synopsis>
  46. Send a Fax
  47. </synopsis>
  48. <syntax>
  49. <parameter name="filename" required="true">
  50. <para>Filename of TIFF file to fax</para>
  51. </parameter>
  52. <parameter name="a" required="false">
  53. <para>Makes the application behave as the answering machine</para>
  54. <para>(Default behavior is as calling machine)</para>
  55. </parameter>
  56. </syntax>
  57. <description>
  58. <para>Send a given TIFF file to the channel as a FAX.</para>
  59. <para>This application sets the following channel variables:</para>
  60. <variablelist>
  61. <variable name="LOCALSTATIONID">
  62. <para>To identify itself to the remote end</para>
  63. </variable>
  64. <variable name="LOCALHEADERINFO">
  65. <para>To generate a header line on each page</para>
  66. </variable>
  67. <variable name="FAXSTATUS">
  68. <value name="SUCCESS"/>
  69. <value name="FAILED"/>
  70. </variable>
  71. <variable name="FAXERROR">
  72. <para>Cause of failure</para>
  73. </variable>
  74. <variable name="REMOTESTATIONID">
  75. <para>The CSID of the remote side</para>
  76. </variable>
  77. <variable name="FAXPAGES">
  78. <para>Number of pages sent</para>
  79. </variable>
  80. <variable name="FAXBITRATE">
  81. <para>Transmission rate</para>
  82. </variable>
  83. <variable name="FAXRESOLUTION">
  84. <para>Resolution of sent fax</para>
  85. </variable>
  86. </variablelist>
  87. </description>
  88. </application>
  89. <application name="ReceiveFAX" language="en_US" module="app_fax">
  90. <synopsis>
  91. Receive a Fax
  92. </synopsis>
  93. <syntax>
  94. <parameter name="filename" required="true">
  95. <para>Filename of TIFF file save incoming fax</para>
  96. </parameter>
  97. <parameter name="c" required="false">
  98. <para>Makes the application behave as the calling machine</para>
  99. <para>(Default behavior is as answering machine)</para>
  100. </parameter>
  101. </syntax>
  102. <description>
  103. <para>Receives a FAX from the channel into the given filename
  104. overwriting the file if it already exists.</para>
  105. <para>File created will be in TIFF format.</para>
  106. <para>This application sets the following channel variables:</para>
  107. <variablelist>
  108. <variable name="LOCALSTATIONID">
  109. <para>To identify itself to the remote end</para>
  110. </variable>
  111. <variable name="LOCALHEADERINFO">
  112. <para>To generate a header line on each page</para>
  113. </variable>
  114. <variable name="FAXSTATUS">
  115. <value name="SUCCESS"/>
  116. <value name="FAILED"/>
  117. </variable>
  118. <variable name="FAXERROR">
  119. <para>Cause of failure</para>
  120. </variable>
  121. <variable name="REMOTESTATIONID">
  122. <para>The CSID of the remote side</para>
  123. </variable>
  124. <variable name="FAXPAGES">
  125. <para>Number of pages sent</para>
  126. </variable>
  127. <variable name="FAXBITRATE">
  128. <para>Transmission rate</para>
  129. </variable>
  130. <variable name="FAXRESOLUTION">
  131. <para>Resolution of sent fax</para>
  132. </variable>
  133. </variablelist>
  134. </description>
  135. </application>
  136. ***/
  137. static const char app_sndfax_name[] = "SendFAX";
  138. static const char app_rcvfax_name[] = "ReceiveFAX";
  139. #define MAX_SAMPLES 240
  140. /* Watchdog. I have seen situations when remote fax disconnects (because of poor line
  141. quality) while SpanDSP continues staying in T30_STATE_IV_CTC state forever.
  142. To avoid this, we terminate when we see that T30 state does not change for 5 minutes.
  143. We also terminate application when more than 30 minutes passed regardless of
  144. state changes. This is just a precaution measure - no fax should take that long */
  145. #define WATCHDOG_TOTAL_TIMEOUT 30 * 60
  146. #define WATCHDOG_STATE_TIMEOUT 5 * 60
  147. typedef struct {
  148. struct ast_channel *chan;
  149. enum ast_t38_state t38state; /* T38 state of the channel */
  150. int direction; /* Fax direction: 0 - receiving, 1 - sending */
  151. int caller_mode;
  152. char *file_name;
  153. struct ast_control_t38_parameters t38parameters;
  154. volatile int finished;
  155. } fax_session;
  156. static void span_message(int level, const char *msg)
  157. {
  158. if (level == SPAN_LOG_ERROR) {
  159. ast_log(LOG_ERROR, "%s", msg);
  160. } else if (level == SPAN_LOG_WARNING) {
  161. ast_log(LOG_WARNING, "%s", msg);
  162. } else {
  163. ast_debug(1, "%s", msg);
  164. }
  165. }
  166. static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
  167. {
  168. struct ast_channel *chan = (struct ast_channel *) user_data;
  169. struct ast_frame outf = {
  170. .frametype = AST_FRAME_MODEM,
  171. .subclass.integer = AST_MODEM_T38,
  172. .src = __FUNCTION__,
  173. };
  174. /* TODO: Asterisk does not provide means of resending the same packet multiple
  175. times so count is ignored at the moment */
  176. AST_FRAME_SET_BUFFER(&outf, buf, 0, len);
  177. if (ast_write(chan, &outf) < 0) {
  178. ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
  179. return -1;
  180. }
  181. return 0;
  182. }
  183. static void phase_e_handler(t30_state_t *f, void *user_data, int result)
  184. {
  185. RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
  186. RAII_VAR(struct ast_json *, json_filenames, NULL, ast_json_unref);
  187. RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
  188. const char *local_ident;
  189. const char *far_ident;
  190. char buf[20];
  191. fax_session *s = (fax_session *) user_data;
  192. t30_stats_t stat;
  193. int pages_transferred;
  194. ast_debug(1, "Fax phase E handler. result=%d\n", result);
  195. t30_get_transfer_statistics(f, &stat);
  196. s = (fax_session *) user_data;
  197. if (result != T30_ERR_OK) {
  198. s->finished = -1;
  199. /* FAXSTATUS is already set to FAILED */
  200. pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result));
  201. ast_log(LOG_WARNING, "Error transmitting fax. result=%d: %s.\n", result, t30_completion_code_to_str(result));
  202. return;
  203. }
  204. s->finished = 1;
  205. local_ident = S_OR(t30_get_tx_ident(f), "");
  206. far_ident = S_OR(t30_get_rx_ident(f), "");
  207. pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS");
  208. pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL);
  209. pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident);
  210. #if SPANDSP_RELEASE_DATE >= 20090220
  211. pages_transferred = (s->direction) ? stat.pages_tx : stat.pages_rx;
  212. #else
  213. pages_transferred = stat.pages_transferred;
  214. #endif
  215. snprintf(buf, sizeof(buf), "%d", pages_transferred);
  216. pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf);
  217. snprintf(buf, sizeof(buf), "%d", stat.y_resolution);
  218. pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf);
  219. snprintf(buf, sizeof(buf), "%d", stat.bit_rate);
  220. pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf);
  221. ast_debug(1, "Fax transmitted successfully.\n");
  222. ast_debug(1, " Remote station ID: %s\n", far_ident);
  223. ast_debug(1, " Pages transferred: %d\n", pages_transferred);
  224. ast_debug(1, " Image resolution: %d x %d\n", stat.x_resolution, stat.y_resolution);
  225. ast_debug(1, " Transfer Rate: %d\n", stat.bit_rate);
  226. json_filenames = ast_json_pack("[s]", s->file_name);
  227. if (!json_filenames) {
  228. return;
  229. }
  230. ast_json_ref(json_filenames);
  231. json_object = ast_json_pack("{s: s, s: s, s: s, s: i, s: i, s: i, s: o}",
  232. "type", s->direction ? "send" : "receive",
  233. "remote_station_id", AST_JSON_UTF8_VALIDATE(far_ident),
  234. "local_station_id", AST_JSON_UTF8_VALIDATE(local_ident),
  235. "fax_pages", pages_transferred,
  236. "fax_resolution", stat.y_resolution,
  237. "fax_bitrate", stat.bit_rate,
  238. "filenames", json_filenames);
  239. message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(s->chan), ast_channel_fax_type(), json_object);
  240. if (!message) {
  241. return;
  242. }
  243. stasis_publish(ast_channel_topic(s->chan), message);
  244. }
  245. /* === Helper functions to configure fax === */
  246. /* Setup SPAN logging according to Asterisk debug level */
  247. static int set_logging(logging_state_t *state)
  248. {
  249. int level = SPAN_LOG_WARNING + option_debug;
  250. span_log_set_message_handler(state, span_message);
  251. span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);
  252. return 0;
  253. }
  254. static void set_local_info(t30_state_t *state, fax_session *s)
  255. {
  256. const char *x;
  257. x = pbx_builtin_getvar_helper(s->chan, "LOCALSTATIONID");
  258. if (!ast_strlen_zero(x))
  259. t30_set_tx_ident(state, x);
  260. x = pbx_builtin_getvar_helper(s->chan, "LOCALHEADERINFO");
  261. if (!ast_strlen_zero(x))
  262. t30_set_tx_page_header_info(state, x);
  263. }
  264. static void set_file(t30_state_t *state, fax_session *s)
  265. {
  266. if (s->direction)
  267. t30_set_tx_file(state, s->file_name, -1, -1);
  268. else
  269. t30_set_rx_file(state, s->file_name, -1);
  270. }
  271. static void set_ecm(t30_state_t *state, int ecm)
  272. {
  273. t30_set_ecm_capability(state, ecm);
  274. t30_set_supported_compressions(state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
  275. }
  276. /* === Generator === */
  277. /* This function is only needed to return passed params so
  278. generator_activate will save it to channel's generatordata */
  279. static void *fax_generator_alloc(struct ast_channel *chan, void *params)
  280. {
  281. return params;
  282. }
  283. static int fax_generator_generate(struct ast_channel *chan, void *data, int len, int samples)
  284. {
  285. fax_state_t *fax = (fax_state_t*) data;
  286. uint8_t buffer[AST_FRIENDLY_OFFSET + MAX_SAMPLES * sizeof(uint16_t)];
  287. int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
  288. struct ast_frame outf = {
  289. .frametype = AST_FRAME_VOICE,
  290. .subclass.format = ast_format_slin,
  291. .src = __FUNCTION__,
  292. };
  293. if (samples > MAX_SAMPLES) {
  294. ast_log(LOG_WARNING, "Only generating %d samples, where %d requested\n", MAX_SAMPLES, samples);
  295. samples = MAX_SAMPLES;
  296. }
  297. if ((len = fax_tx(fax, buf, samples)) > 0) {
  298. outf.samples = len;
  299. AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET, len * sizeof(int16_t));
  300. if (ast_write(chan, &outf) < 0) {
  301. ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
  302. return -1;
  303. }
  304. }
  305. return 0;
  306. }
  307. static struct ast_generator generator = {
  308. .alloc = fax_generator_alloc,
  309. .generate = fax_generator_generate,
  310. };
  311. /* === Transmission === */
  312. static int transmit_audio(fax_session *s)
  313. {
  314. int res = -1;
  315. struct ast_format *original_read_fmt;
  316. struct ast_format *original_write_fmt = NULL;
  317. fax_state_t fax;
  318. t30_state_t *t30state;
  319. struct ast_frame *inf = NULL;
  320. int last_state = 0;
  321. struct timeval now, start, state_change;
  322. enum ast_t38_state t38_state;
  323. struct ast_control_t38_parameters t38_parameters = { .version = 0,
  324. .max_ifp = 800,
  325. .rate = AST_T38_RATE_14400,
  326. .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
  327. .fill_bit_removal = 1,
  328. /*
  329. * spandsp has API calls to support MMR and JBIG transcoding, but they aren't
  330. * implemented quite yet... so don't offer them to the remote endpoint
  331. * .transcoding_mmr = 1,
  332. * .transcoding_jbig = 1,
  333. */
  334. };
  335. /* if in called party mode, try to use T.38 */
  336. if (s->caller_mode == FALSE) {
  337. /* check if we are already in T.38 mode (unlikely), or if we can request
  338. * a switch... if so, request it now and wait for the result, rather
  339. * than starting an audio FAX session that will have to be cancelled
  340. */
  341. if ((t38_state = ast_channel_get_t38_state(s->chan)) == T38_STATE_NEGOTIATED) {
  342. return 1;
  343. } else if ((t38_state != T38_STATE_UNAVAILABLE) &&
  344. (t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE,
  345. (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0))) {
  346. /* wait up to five seconds for negotiation to complete */
  347. unsigned int timeout = 5000;
  348. int ms;
  349. ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(s->chan));
  350. while (timeout > 0) {
  351. ms = ast_waitfor(s->chan, 1000);
  352. if (ms < 0) {
  353. ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(s->chan));
  354. return -1;
  355. }
  356. if (!ms) {
  357. /* nothing happened */
  358. if (timeout > 0) {
  359. timeout -= 1000;
  360. continue;
  361. } else {
  362. ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(s->chan));
  363. break;
  364. }
  365. }
  366. if (!(inf = ast_read(s->chan))) {
  367. return -1;
  368. }
  369. if ((inf->frametype == AST_FRAME_CONTROL) &&
  370. (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
  371. (inf->datalen == sizeof(t38_parameters))) {
  372. struct ast_control_t38_parameters *parameters = inf->data.ptr;
  373. switch (parameters->request_response) {
  374. case AST_T38_NEGOTIATED:
  375. ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(s->chan));
  376. res = 1;
  377. break;
  378. case AST_T38_REFUSED:
  379. ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(s->chan));
  380. break;
  381. default:
  382. ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(s->chan));
  383. break;
  384. }
  385. ast_frfree(inf);
  386. if (res == 1) {
  387. return 1;
  388. } else {
  389. break;
  390. }
  391. }
  392. ast_frfree(inf);
  393. }
  394. }
  395. }
  396. #if SPANDSP_RELEASE_DATE >= 20080725
  397. /* for spandsp shaphots 0.0.6 and higher */
  398. t30state = &fax.t30;
  399. #else
  400. /* for spandsp release 0.0.5 */
  401. t30state = &fax.t30_state;
  402. #endif
  403. original_read_fmt = ao2_bump(ast_channel_readformat(s->chan));
  404. res = ast_set_read_format(s->chan, ast_format_slin);
  405. if (res < 0) {
  406. ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
  407. goto done;
  408. }
  409. original_write_fmt = ao2_bump(ast_channel_writeformat(s->chan));
  410. res = ast_set_write_format(s->chan, ast_format_slin);
  411. if (res < 0) {
  412. ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
  413. goto done;
  414. }
  415. /* Initialize T30 terminal */
  416. fax_init(&fax, s->caller_mode);
  417. /* Setup logging */
  418. set_logging(&fax.logging);
  419. set_logging(&t30state->logging);
  420. /* Configure terminal */
  421. set_local_info(t30state, s);
  422. set_file(t30state, s);
  423. set_ecm(t30state, TRUE);
  424. fax_set_transmit_on_idle(&fax, TRUE);
  425. t30_set_phase_e_handler(t30state, phase_e_handler, s);
  426. start = state_change = ast_tvnow();
  427. ast_activate_generator(s->chan, &generator, &fax);
  428. while (!s->finished) {
  429. inf = NULL;
  430. if ((res = ast_waitfor(s->chan, 25)) < 0) {
  431. ast_debug(1, "Error waiting for a frame\n");
  432. break;
  433. }
  434. /* Watchdog */
  435. now = ast_tvnow();
  436. if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
  437. ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
  438. res = -1;
  439. break;
  440. }
  441. if (!res) {
  442. /* There was timeout waiting for a frame. Loop around and wait again */
  443. continue;
  444. }
  445. /* There is a frame available. Get it */
  446. res = 0;
  447. if (!(inf = ast_read(s->chan))) {
  448. ast_debug(1, "Channel hangup\n");
  449. res = -1;
  450. break;
  451. }
  452. ast_debug(10, "frame %d/%s, len=%d\n", inf->frametype, ast_format_get_name(inf->subclass.format), inf->datalen);
  453. /* Check the frame type. Format also must be checked because there is a chance
  454. that a frame in old format was already queued before we set channel format
  455. to slinear so it will still be received by ast_read */
  456. if (inf->frametype == AST_FRAME_VOICE &&
  457. (ast_format_cmp(inf->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
  458. if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {
  459. /* I know fax_rx never returns errors. The check here is for good style only */
  460. ast_log(LOG_WARNING, "fax_rx returned error\n");
  461. res = -1;
  462. break;
  463. }
  464. if (last_state != t30state->state) {
  465. state_change = ast_tvnow();
  466. last_state = t30state->state;
  467. }
  468. } else if ((inf->frametype == AST_FRAME_CONTROL) &&
  469. (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS)) {
  470. struct ast_control_t38_parameters *parameters = inf->data.ptr;
  471. if (parameters->request_response == AST_T38_NEGOTIATED) {
  472. /* T38 switchover completed */
  473. s->t38parameters = *parameters;
  474. ast_debug(1, "T38 negotiated, finishing audio loop\n");
  475. res = 1;
  476. break;
  477. } else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
  478. t38_parameters.request_response = AST_T38_NEGOTIATED;
  479. ast_debug(1, "T38 request received, accepting\n");
  480. /* Complete T38 switchover */
  481. ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
  482. /* Do not break audio loop, wait until channel driver finally acks switchover
  483. * with AST_T38_NEGOTIATED
  484. */
  485. }
  486. }
  487. ast_frfree(inf);
  488. inf = NULL;
  489. }
  490. ast_debug(1, "Loop finished, res=%d\n", res);
  491. if (inf)
  492. ast_frfree(inf);
  493. ast_deactivate_generator(s->chan);
  494. /* If we are switching to T38, remove phase E handler. Otherwise it will be executed
  495. by t30_terminate, display diagnostics and set status variables although no transmittion
  496. has taken place yet. */
  497. if (res > 0) {
  498. t30_set_phase_e_handler(t30state, NULL, NULL);
  499. }
  500. t30_terminate(t30state);
  501. fax_release(&fax);
  502. done:
  503. if (original_write_fmt) {
  504. if (ast_set_write_format(s->chan, original_write_fmt) < 0)
  505. ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", ast_channel_name(s->chan));
  506. ao2_ref(original_write_fmt, -1);
  507. }
  508. if (original_read_fmt) {
  509. if (ast_set_read_format(s->chan, original_read_fmt) < 0)
  510. ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(s->chan));
  511. ao2_ref(original_read_fmt, -1);
  512. }
  513. return res;
  514. }
  515. static int transmit_t38(fax_session *s)
  516. {
  517. int res = 0;
  518. t38_terminal_state_t t38;
  519. struct ast_frame *inf = NULL;
  520. int last_state = 0;
  521. struct timeval now, start, state_change, last_frame;
  522. t30_state_t *t30state;
  523. t38_core_state_t *t38state;
  524. #if SPANDSP_RELEASE_DATE >= 20080725
  525. /* for spandsp shaphots 0.0.6 and higher */
  526. t30state = &t38.t30;
  527. t38state = &t38.t38_fe.t38;
  528. #else
  529. /* for spandsp releases 0.0.5 */
  530. t30state = &t38.t30_state;
  531. t38state = &t38.t38;
  532. #endif
  533. /* Initialize terminal */
  534. memset(&t38, 0, sizeof(t38));
  535. if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
  536. ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
  537. res = -1;
  538. goto disable_t38;
  539. }
  540. t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);
  541. if (s->t38parameters.fill_bit_removal) {
  542. t38_set_fill_bit_removal(t38state, TRUE);
  543. }
  544. if (s->t38parameters.transcoding_mmr) {
  545. t38_set_mmr_transcoding(t38state, TRUE);
  546. }
  547. if (s->t38parameters.transcoding_jbig) {
  548. t38_set_jbig_transcoding(t38state, TRUE);
  549. }
  550. /* Setup logging */
  551. set_logging(&t38.logging);
  552. set_logging(&t30state->logging);
  553. set_logging(&t38state->logging);
  554. /* Configure terminal */
  555. set_local_info(t30state, s);
  556. set_file(t30state, s);
  557. set_ecm(t30state, TRUE);
  558. t30_set_phase_e_handler(t30state, phase_e_handler, s);
  559. now = start = state_change = ast_tvnow();
  560. while (!s->finished) {
  561. inf = NULL;
  562. if ((res = ast_waitfor(s->chan, 25)) < 0) {
  563. ast_debug(1, "Error waiting for a frame\n");
  564. break;
  565. }
  566. last_frame = now;
  567. /* Watchdog */
  568. now = ast_tvnow();
  569. if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
  570. ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
  571. res = -1;
  572. break;
  573. }
  574. t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
  575. if (!res) {
  576. /* There was timeout waiting for a frame. Loop around and wait again */
  577. continue;
  578. }
  579. /* There is a frame available. Get it */
  580. res = 0;
  581. if (!(inf = ast_read(s->chan))) {
  582. ast_debug(1, "Channel hangup\n");
  583. res = -1;
  584. break;
  585. }
  586. ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass.integer, inf->datalen);
  587. if (inf->frametype == AST_FRAME_MODEM && inf->subclass.integer == AST_MODEM_T38) {
  588. t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno);
  589. if (last_state != t30state->state) {
  590. state_change = ast_tvnow();
  591. last_state = t30state->state;
  592. }
  593. } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
  594. struct ast_control_t38_parameters *parameters = inf->data.ptr;
  595. if (parameters->request_response == AST_T38_TERMINATED) {
  596. ast_debug(1, "T38 down, finishing\n");
  597. break;
  598. }
  599. }
  600. ast_frfree(inf);
  601. inf = NULL;
  602. }
  603. ast_debug(1, "Loop finished, res=%d\n", res);
  604. if (inf)
  605. ast_frfree(inf);
  606. t30_terminate(t30state);
  607. t38_terminal_release(&t38);
  608. disable_t38:
  609. /* if we are not the caller, it's our job to shut down the T.38
  610. * session when the FAX transmisson is complete.
  611. */
  612. if ((s->caller_mode == FALSE) &&
  613. (ast_channel_get_t38_state(s->chan) == T38_STATE_NEGOTIATED)) {
  614. struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
  615. if (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) {
  616. /* wait up to five seconds for negotiation to complete */
  617. unsigned int timeout = 5000;
  618. int ms;
  619. ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(s->chan));
  620. while (timeout > 0) {
  621. ms = ast_waitfor(s->chan, 1000);
  622. if (ms < 0) {
  623. ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(s->chan));
  624. return -1;
  625. }
  626. if (!ms) {
  627. /* nothing happened */
  628. if (timeout > 0) {
  629. timeout -= 1000;
  630. continue;
  631. } else {
  632. ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", ast_channel_name(s->chan));
  633. break;
  634. }
  635. }
  636. if (!(inf = ast_read(s->chan))) {
  637. return -1;
  638. }
  639. if ((inf->frametype == AST_FRAME_CONTROL) &&
  640. (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
  641. (inf->datalen == sizeof(t38_parameters))) {
  642. struct ast_control_t38_parameters *parameters = inf->data.ptr;
  643. switch (parameters->request_response) {
  644. case AST_T38_TERMINATED:
  645. ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(s->chan));
  646. break;
  647. case AST_T38_REFUSED:
  648. ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(s->chan));
  649. break;
  650. default:
  651. ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(s->chan));
  652. break;
  653. }
  654. ast_frfree(inf);
  655. break;
  656. }
  657. ast_frfree(inf);
  658. }
  659. }
  660. }
  661. return res;
  662. }
  663. static int transmit(fax_session *s)
  664. {
  665. int res = 0;
  666. /* Clear all channel variables which to be set by the application.
  667. Pre-set status to error so in case of any problems we can just leave */
  668. pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED");
  669. pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems");
  670. pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);
  671. pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
  672. pbx_builtin_setvar_helper(s->chan, "FAXPAGES", "0");
  673. pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
  674. pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL);
  675. if (ast_channel_state(s->chan) != AST_STATE_UP) {
  676. /* Shouldn't need this, but checking to see if channel is already answered
  677. * Theoretically asterisk should already have answered before running the app */
  678. res = ast_answer(s->chan);
  679. if (res) {
  680. ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(s->chan));
  681. return res;
  682. }
  683. }
  684. s->t38state = ast_channel_get_t38_state(s->chan);
  685. if (s->t38state != T38_STATE_NEGOTIATED) {
  686. /* T38 is not negotiated on the channel yet. First start regular transmission. If it switches to T38, follow */
  687. pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio");
  688. res = transmit_audio(s);
  689. if (res > 0) {
  690. /* transmit_audio reports switchover to T38. Update t38state */
  691. s->t38state = ast_channel_get_t38_state(s->chan);
  692. if (s->t38state != T38_STATE_NEGOTIATED) {
  693. ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");
  694. }
  695. }
  696. }
  697. if (s->t38state == T38_STATE_NEGOTIATED) {
  698. pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38");
  699. res = transmit_t38(s);
  700. }
  701. if (res) {
  702. ast_log(LOG_WARNING, "Transmission error\n");
  703. res = -1;
  704. } else if (s->finished < 0) {
  705. ast_log(LOG_WARNING, "Transmission failed\n");
  706. } else if (s->finished > 0) {
  707. ast_debug(1, "Transmission finished Ok\n");
  708. }
  709. return res;
  710. }
  711. /* === Application functions === */
  712. static int sndfax_exec(struct ast_channel *chan, const char *data)
  713. {
  714. int res = 0;
  715. char *parse;
  716. fax_session session = { 0, };
  717. char restore_digit_detect = 0;
  718. AST_DECLARE_APP_ARGS(args,
  719. AST_APP_ARG(file_name);
  720. AST_APP_ARG(options);
  721. );
  722. if (chan == NULL) {
  723. ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
  724. return -1;
  725. }
  726. /* The next few lines of code parse out the filename and header from the input string */
  727. if (ast_strlen_zero(data)) {
  728. /* No data implies no filename or anything is present */
  729. ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");
  730. return -1;
  731. }
  732. parse = ast_strdupa(data);
  733. AST_STANDARD_APP_ARGS(args, parse);
  734. session.caller_mode = TRUE;
  735. if (args.options) {
  736. if (strchr(args.options, 'a'))
  737. session.caller_mode = FALSE;
  738. }
  739. /* Done parsing */
  740. session.direction = 1;
  741. session.file_name = args.file_name;
  742. session.chan = chan;
  743. session.finished = 0;
  744. /* get current digit detection mode, then disable digit detection if enabled */
  745. {
  746. int dummy = sizeof(restore_digit_detect);
  747. ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
  748. }
  749. if (restore_digit_detect) {
  750. char new_digit_detect = 0;
  751. ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
  752. }
  753. /* disable FAX tone detection if enabled */
  754. {
  755. char new_fax_detect = 0;
  756. ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
  757. }
  758. res = transmit(&session);
  759. if (restore_digit_detect) {
  760. ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
  761. }
  762. return res;
  763. }
  764. static int rcvfax_exec(struct ast_channel *chan, const char *data)
  765. {
  766. int res = 0;
  767. char *parse;
  768. fax_session session;
  769. char restore_digit_detect = 0;
  770. AST_DECLARE_APP_ARGS(args,
  771. AST_APP_ARG(file_name);
  772. AST_APP_ARG(options);
  773. );
  774. if (chan == NULL) {
  775. ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
  776. return -1;
  777. }
  778. /* The next few lines of code parse out the filename and header from the input string */
  779. if (ast_strlen_zero(data)) {
  780. /* No data implies no filename or anything is present */
  781. ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");
  782. return -1;
  783. }
  784. parse = ast_strdupa(data);
  785. AST_STANDARD_APP_ARGS(args, parse);
  786. session.caller_mode = FALSE;
  787. if (args.options) {
  788. if (strchr(args.options, 'c'))
  789. session.caller_mode = TRUE;
  790. }
  791. /* Done parsing */
  792. session.direction = 0;
  793. session.file_name = args.file_name;
  794. session.chan = chan;
  795. session.finished = 0;
  796. /* get current digit detection mode, then disable digit detection if enabled */
  797. {
  798. int dummy = sizeof(restore_digit_detect);
  799. ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
  800. }
  801. if (restore_digit_detect) {
  802. char new_digit_detect = 0;
  803. ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
  804. }
  805. /* disable FAX tone detection if enabled */
  806. {
  807. char new_fax_detect = 0;
  808. ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
  809. }
  810. res = transmit(&session);
  811. if (restore_digit_detect) {
  812. ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
  813. }
  814. return res;
  815. }
  816. static int unload_module(void)
  817. {
  818. int res;
  819. res = ast_unregister_application(app_sndfax_name);
  820. res |= ast_unregister_application(app_rcvfax_name);
  821. return res;
  822. }
  823. static int load_module(void)
  824. {
  825. int res ;
  826. res = ast_register_application_xml(app_sndfax_name, sndfax_exec);
  827. res |= ast_register_application_xml(app_rcvfax_name, rcvfax_exec);
  828. /* The default SPAN message handler prints to stderr. It is something we do not want */
  829. span_set_message_handler(NULL);
  830. return res;
  831. }
  832. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Simple FAX Application",
  833. .support_level = AST_MODULE_SUPPORT_EXTENDED,
  834. .load = load_module,
  835. .unload = unload_module,
  836. );