res_fax_spandsp.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2009-2010, Digium, Inc.
  5. *
  6. * Matthew Nicholson <mnicholson@digium.com>
  7. *
  8. * Initial T.38-gateway code
  9. * 2008, Daniel Ferenci <daniel.ferenci@nethemba.com>
  10. * Created by Nethemba s.r.o. http://www.nethemba.com
  11. * Sponsored by IPEX a.s. http://www.ipex.cz
  12. *
  13. * T.38-gateway integration into asterisk app_fax and rework
  14. * 2008, Gregory Hinton Nietsky <gregory@dnstelecom.co.za>
  15. * dns Telecom http://www.dnstelecom.co.za
  16. *
  17. * Modified to make T.38-gateway compatible with Asterisk 1.6.2
  18. * 2010, Anton Verevkin <mymail@verevkin.it>
  19. * ViaNetTV http://www.vianettv.com
  20. *
  21. * Modified to make T.38-gateway work
  22. * 2010, Klaus Darilion, IPCom GmbH, www.ipcom.at
  23. *
  24. * See http://www.asterisk.org for more information about
  25. * the Asterisk project. Please do not directly contact
  26. * any of the maintainers of this project for assistance;
  27. * the project provides a web site, mailing lists and IRC
  28. * channels for your use.
  29. *
  30. * This program is free software, distributed under the terms of
  31. * the GNU General Public License Version 2. See the LICENSE file
  32. * at the top of the source tree.
  33. */
  34. /*! \file
  35. *
  36. * \brief Spandsp T.38 and G.711 FAX Resource
  37. *
  38. * \author Matthew Nicholson <mnicholson@digium.com>
  39. * \author Gregory H. Nietsky <gregory@distrotech.co.za>
  40. *
  41. * This module registers the Spandsp FAX technology with the res_fax module.
  42. */
  43. /*** MODULEINFO
  44. <depend>spandsp</depend>
  45. <depend>res_fax</depend>
  46. <support_level>extended</support_level>
  47. ***/
  48. #include "asterisk.h"
  49. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  50. #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
  51. #include <spandsp.h>
  52. #include <spandsp/version.h>
  53. #include "asterisk/logger.h"
  54. #include "asterisk/module.h"
  55. #include "asterisk/strings.h"
  56. #include "asterisk/cli.h"
  57. #include "asterisk/utils.h"
  58. #include "asterisk/timing.h"
  59. #include "asterisk/astobj2.h"
  60. #include "asterisk/res_fax.h"
  61. #include "asterisk/channel.h"
  62. #include "asterisk/format_cache.h"
  63. #define SPANDSP_FAX_SAMPLES 160
  64. #define SPANDSP_FAX_TIMER_RATE 8000 / SPANDSP_FAX_SAMPLES /* 50 ticks per second, 20ms, 160 samples per second */
  65. #define SPANDSP_ENGAGE_UDPTL_NAT_RETRY 3
  66. static void *spandsp_fax_new(struct ast_fax_session *s, struct ast_fax_tech_token *token);
  67. static void spandsp_fax_destroy(struct ast_fax_session *s);
  68. static struct ast_frame *spandsp_fax_read(struct ast_fax_session *s);
  69. static int spandsp_fax_write(struct ast_fax_session *s, const struct ast_frame *f);
  70. static int spandsp_fax_start(struct ast_fax_session *s);
  71. static int spandsp_fax_cancel(struct ast_fax_session *s);
  72. static int spandsp_fax_switch_to_t38(struct ast_fax_session *s);
  73. static int spandsp_fax_gateway_start(struct ast_fax_session *s);
  74. static int spandsp_fax_gateway_process(struct ast_fax_session *s, const struct ast_frame *f);
  75. static void spandsp_fax_gateway_cleanup(struct ast_fax_session *s);
  76. static int spandsp_v21_detect(struct ast_fax_session *s, const struct ast_frame *f);
  77. static void spandsp_v21_cleanup(struct ast_fax_session *s);
  78. static void spandsp_v21_tone(void *data, int code, int level, int delay);
  79. static char *spandsp_fax_cli_show_capabilities(int fd);
  80. static char *spandsp_fax_cli_show_session(struct ast_fax_session *s, int fd);
  81. static void spandsp_manager_fax_session(struct mansession *s,
  82. const char *id_text, struct ast_fax_session *session);
  83. static char *spandsp_fax_cli_show_stats(int fd);
  84. static char *spandsp_fax_cli_show_settings(int fd);
  85. static struct ast_fax_tech spandsp_fax_tech = {
  86. .type = "Spandsp",
  87. .description = "Spandsp FAX Driver",
  88. #if SPANDSP_RELEASE_DATE >= 20090220
  89. /* spandsp 0.0.6 */
  90. .version = SPANDSP_RELEASE_DATETIME_STRING,
  91. #else
  92. /* spandsp 0.0.5
  93. * TODO: maybe we should determine the version better way
  94. */
  95. .version = "pre-20090220",
  96. #endif
  97. .caps = AST_FAX_TECH_AUDIO | AST_FAX_TECH_T38 | AST_FAX_TECH_SEND
  98. | AST_FAX_TECH_RECEIVE | AST_FAX_TECH_GATEWAY
  99. | AST_FAX_TECH_V21_DETECT,
  100. .new_session = spandsp_fax_new,
  101. .destroy_session = spandsp_fax_destroy,
  102. .read = spandsp_fax_read,
  103. .write = spandsp_fax_write,
  104. .start_session = spandsp_fax_start,
  105. .cancel_session = spandsp_fax_cancel,
  106. .switch_to_t38 = spandsp_fax_switch_to_t38,
  107. .cli_show_capabilities = spandsp_fax_cli_show_capabilities,
  108. .cli_show_session = spandsp_fax_cli_show_session,
  109. .manager_fax_session = spandsp_manager_fax_session,
  110. .cli_show_stats = spandsp_fax_cli_show_stats,
  111. .cli_show_settings = spandsp_fax_cli_show_settings,
  112. };
  113. struct spandsp_fax_stats {
  114. int success;
  115. int nofax;
  116. int neg_failed;
  117. int failed_to_train;
  118. int rx_protocol_error;
  119. int tx_protocol_error;
  120. int protocol_error;
  121. int retries_exceeded;
  122. int file_error;
  123. int mem_error;
  124. int call_dropped;
  125. int unknown_error;
  126. int switched;
  127. };
  128. static struct {
  129. ast_mutex_t lock;
  130. struct spandsp_fax_stats g711;
  131. struct spandsp_fax_stats t38;
  132. } spandsp_global_stats;
  133. struct spandsp_pvt {
  134. unsigned int ist38:1;
  135. unsigned int isdone:1;
  136. enum ast_t38_state ast_t38_state;
  137. fax_state_t fax_state;
  138. t38_terminal_state_t t38_state;
  139. t30_state_t *t30_state;
  140. t38_core_state_t *t38_core_state;
  141. struct spandsp_fax_stats *stats;
  142. struct spandsp_fax_gw_stats *t38stats;
  143. t38_gateway_state_t t38_gw_state;
  144. struct ast_timer *timer;
  145. AST_LIST_HEAD(frame_queue, ast_frame) read_frames;
  146. int v21_detected;
  147. modem_connect_tones_rx_state_t *tone_state;
  148. };
  149. static int spandsp_v21_new(struct spandsp_pvt *p);
  150. static void session_destroy(struct spandsp_pvt *p);
  151. static int t38_tx_packet_handler(t38_core_state_t *t38_core_state, void *data, const uint8_t *buf, int len, int count);
  152. static void t30_phase_e_handler(t30_state_t *t30_state, void *data, int completion_code);
  153. static void spandsp_log(int level, const char *msg);
  154. static int update_stats(struct spandsp_pvt *p, int completion_code);
  155. static int spandsp_modems(struct ast_fax_session_details *details);
  156. static void set_logging(logging_state_t *state, struct ast_fax_session_details *details);
  157. static void set_local_info(t30_state_t *t30_state, struct ast_fax_session_details *details);
  158. static void set_file(t30_state_t *t30_state, struct ast_fax_session_details *details);
  159. static void set_ecm(t30_state_t *t30_state, struct ast_fax_session_details *details);
  160. static void session_destroy(struct spandsp_pvt *p)
  161. {
  162. struct ast_frame *f;
  163. t30_state_t *t30_to_terminate;
  164. if (p->t30_state) {
  165. t30_to_terminate = p->t30_state;
  166. } else if (p->ist38) {
  167. #if SPANDSP_RELEASE_DATE >= 20080725
  168. t30_to_terminate = &p->t38_state.t30;
  169. #else
  170. t30_to_terminate = &p->t38_state.t30_state;
  171. #endif
  172. } else {
  173. #if SPANDSP_RELEASE_DATE >= 20080725
  174. t30_to_terminate = &p->fax_state.t30;
  175. #else
  176. t30_to_terminate = &p->fax_state.t30_state;
  177. #endif
  178. }
  179. t30_terminate(t30_to_terminate);
  180. p->isdone = 1;
  181. ast_timer_close(p->timer);
  182. p->timer = NULL;
  183. fax_release(&p->fax_state);
  184. t38_terminal_release(&p->t38_state);
  185. while ((f = AST_LIST_REMOVE_HEAD(&p->read_frames, frame_list))) {
  186. ast_frfree(f);
  187. }
  188. }
  189. /*! \brief
  190. *
  191. */
  192. static int t38_tx_packet_handler(t38_core_state_t *t38_core_state, void *data, const uint8_t *buf, int len, int count)
  193. {
  194. int res = -1;
  195. struct ast_fax_session *s = data;
  196. struct spandsp_pvt *p = s->tech_pvt;
  197. struct ast_frame fax_frame = {
  198. .frametype = AST_FRAME_MODEM,
  199. .subclass.integer = AST_MODEM_T38,
  200. .src = "res_fax_spandsp_t38",
  201. };
  202. struct ast_frame *f = &fax_frame;
  203. /* TODO: Asterisk does not provide means of resending the same packet multiple
  204. times so count is ignored at the moment */
  205. AST_FRAME_SET_BUFFER(f, buf, 0, len);
  206. if (!(f = ast_frisolate(f))) {
  207. return res;
  208. }
  209. if (s->details->caps & AST_FAX_TECH_GATEWAY) {
  210. ast_set_flag(f, AST_FAX_FRFLAG_GATEWAY);
  211. if (p->ast_t38_state == T38_STATE_NEGOTIATED) {
  212. res = ast_write(s->chan, f);
  213. } else {
  214. res = ast_queue_frame(s->chan, f);
  215. }
  216. ast_frfree(f);
  217. } else {
  218. /* no need to lock, this all runs in the same thread */
  219. AST_LIST_INSERT_TAIL(&p->read_frames, f, frame_list);
  220. res = 0;
  221. }
  222. return res;
  223. }
  224. static int update_stats(struct spandsp_pvt *p, int completion_code)
  225. {
  226. switch (completion_code) {
  227. case T30_ERR_OK:
  228. ast_atomic_fetchadd_int(&p->stats->success, 1);
  229. break;
  230. /* Link problems */
  231. case T30_ERR_CEDTONE: /*! The CED tone exceeded 5s */
  232. case T30_ERR_T0_EXPIRED: /*! Timed out waiting for initial communication */
  233. case T30_ERR_T1_EXPIRED: /*! Timed out waiting for the first message */
  234. case T30_ERR_T3_EXPIRED: /*! Timed out waiting for procedural interrupt */
  235. case T30_ERR_HDLC_CARRIER: /*! The HDLC carrier did not stop in a timely manner */
  236. case T30_ERR_CANNOT_TRAIN: /*! Failed to train with any of the compatible modems */
  237. ast_atomic_fetchadd_int(&p->stats->failed_to_train, 1);
  238. break;
  239. case T30_ERR_OPER_INT_FAIL: /*! Operator intervention failed */
  240. case T30_ERR_INCOMPATIBLE: /*! Far end is not compatible */
  241. case T30_ERR_RX_INCAPABLE: /*! Far end is not able to receive */
  242. case T30_ERR_TX_INCAPABLE: /*! Far end is not able to transmit */
  243. case T30_ERR_NORESSUPPORT: /*! Far end cannot receive at the resolution of the image */
  244. case T30_ERR_NOSIZESUPPORT: /*! Far end cannot receive at the size of image */
  245. ast_atomic_fetchadd_int(&p->stats->neg_failed, 1);
  246. break;
  247. case T30_ERR_UNEXPECTED: /*! Unexpected message received */
  248. ast_atomic_fetchadd_int(&p->stats->protocol_error, 1);
  249. break;
  250. /* Phase E status values returned to a transmitter */
  251. case T30_ERR_TX_BADDCS: /*! Received bad response to DCS or training */
  252. case T30_ERR_TX_BADPG: /*! Received a DCN from remote after sending a page */
  253. case T30_ERR_TX_ECMPHD: /*! Invalid ECM response received from receiver */
  254. case T30_ERR_TX_GOTDCN: /*! Received a DCN while waiting for a DIS */
  255. case T30_ERR_TX_INVALRSP: /*! Invalid response after sending a page */
  256. case T30_ERR_TX_NODIS: /*! Received other than DIS while waiting for DIS */
  257. case T30_ERR_TX_PHBDEAD: /*! Received no response to DCS, training or TCF */
  258. case T30_ERR_TX_PHDDEAD: /*! No response after sending a page */
  259. case T30_ERR_TX_T5EXP: /*! Timed out waiting for receiver ready (ECM mode) */
  260. ast_atomic_fetchadd_int(&p->stats->tx_protocol_error, 1);
  261. break;
  262. /* Phase E status values returned to a receiver */
  263. case T30_ERR_RX_ECMPHD: /*! Invalid ECM response received from transmitter */
  264. case T30_ERR_RX_GOTDCS: /*! DCS received while waiting for DTC */
  265. case T30_ERR_RX_INVALCMD: /*! Unexpected command after page received */
  266. case T30_ERR_RX_NOCARRIER: /*! Carrier lost during fax receive */
  267. case T30_ERR_RX_NOEOL: /*! Timed out while waiting for EOL (end Of line) */
  268. ast_atomic_fetchadd_int(&p->stats->rx_protocol_error, 1);
  269. break;
  270. case T30_ERR_RX_NOFAX: /*! Timed out while waiting for first line */
  271. ast_atomic_fetchadd_int(&p->stats->nofax, 1);
  272. break;
  273. case T30_ERR_RX_T2EXPDCN: /*! Timer T2 expired while waiting for DCN */
  274. case T30_ERR_RX_T2EXPD: /*! Timer T2 expired while waiting for phase D */
  275. case T30_ERR_RX_T2EXPFAX: /*! Timer T2 expired while waiting for fax page */
  276. case T30_ERR_RX_T2EXPMPS: /*! Timer T2 expired while waiting for next fax page */
  277. case T30_ERR_RX_T2EXPRR: /*! Timer T2 expired while waiting for RR command */
  278. case T30_ERR_RX_T2EXP: /*! Timer T2 expired while waiting for NSS, DCS or MCF */
  279. case T30_ERR_RX_DCNWHY: /*! Unexpected DCN while waiting for DCS or DIS */
  280. case T30_ERR_RX_DCNDATA: /*! Unexpected DCN while waiting for image data */
  281. case T30_ERR_RX_DCNFAX: /*! Unexpected DCN while waiting for EOM, EOP or MPS */
  282. case T30_ERR_RX_DCNPHD: /*! Unexpected DCN after EOM or MPS sequence */
  283. case T30_ERR_RX_DCNRRD: /*! Unexpected DCN after RR/RNR sequence */
  284. case T30_ERR_RX_DCNNORTN: /*! Unexpected DCN after requested retransmission */
  285. ast_atomic_fetchadd_int(&p->stats->rx_protocol_error, 1);
  286. break;
  287. /* TIFF file problems */
  288. case T30_ERR_FILEERROR: /*! TIFF/F file cannot be opened */
  289. case T30_ERR_NOPAGE: /*! TIFF/F page not found */
  290. case T30_ERR_BADTIFF: /*! TIFF/F format is not compatible */
  291. case T30_ERR_BADPAGE: /*! TIFF/F page number tag missing */
  292. case T30_ERR_BADTAG: /*! Incorrect values for TIFF/F tags */
  293. case T30_ERR_BADTIFFHDR: /*! Bad TIFF/F header - incorrect values in fields */
  294. ast_atomic_fetchadd_int(&p->stats->file_error, 1);
  295. break;
  296. case T30_ERR_NOMEM: /*! Cannot allocate memory for more pages */
  297. ast_atomic_fetchadd_int(&p->stats->mem_error, 1);
  298. break;
  299. /* General problems */
  300. case T30_ERR_RETRYDCN: /*! Disconnected after permitted retries */
  301. ast_atomic_fetchadd_int(&p->stats->retries_exceeded, 1);
  302. break;
  303. case T30_ERR_CALLDROPPED: /*! The call dropped prematurely */
  304. ast_atomic_fetchadd_int(&p->stats->call_dropped, 1);
  305. break;
  306. /* Feature negotiation issues */
  307. case T30_ERR_NOPOLL: /*! Poll not accepted */
  308. case T30_ERR_IDENT_UNACCEPTABLE: /*! Far end's ident is not acceptable */
  309. case T30_ERR_SUB_UNACCEPTABLE: /*! Far end's sub-address is not acceptable */
  310. case T30_ERR_SEP_UNACCEPTABLE: /*! Far end's selective polling address is not acceptable */
  311. case T30_ERR_PSA_UNACCEPTABLE: /*! Far end's polled sub-address is not acceptable */
  312. case T30_ERR_SID_UNACCEPTABLE: /*! Far end's sender identification is not acceptable */
  313. case T30_ERR_PWD_UNACCEPTABLE: /*! Far end's password is not acceptable */
  314. case T30_ERR_TSA_UNACCEPTABLE: /*! Far end's transmitting subscriber internet address is not acceptable */
  315. case T30_ERR_IRA_UNACCEPTABLE: /*! Far end's internet routing address is not acceptable */
  316. case T30_ERR_CIA_UNACCEPTABLE: /*! Far end's calling subscriber internet address is not acceptable */
  317. case T30_ERR_ISP_UNACCEPTABLE: /*! Far end's internet selective polling address is not acceptable */
  318. case T30_ERR_CSA_UNACCEPTABLE: /*! Far end's called subscriber internet address is not acceptable */
  319. ast_atomic_fetchadd_int(&p->stats->neg_failed, 1);
  320. break;
  321. default:
  322. ast_atomic_fetchadd_int(&p->stats->unknown_error, 1);
  323. ast_log(LOG_WARNING, "unknown FAX session result '%d' (%s)\n", completion_code, t30_completion_code_to_str(completion_code));
  324. return -1;
  325. }
  326. return 0;
  327. }
  328. /*! \brief Phase E handler callback.
  329. * \param t30_state the span t30 state
  330. * \param data this will be the ast_fax_session
  331. * \param completion_code the result of the fax session
  332. *
  333. * This function pulls stats from the spandsp stack and stores them for res_fax
  334. * to use later.
  335. */
  336. static void t30_phase_e_handler(t30_state_t *t30_state, void *data, int completion_code)
  337. {
  338. struct ast_fax_session *s = data;
  339. struct spandsp_pvt *p = s->tech_pvt;
  340. char headerinfo[T30_MAX_PAGE_HEADER_INFO + 1];
  341. const char *c;
  342. t30_stats_t stats;
  343. ast_debug(5, "FAX session '%u' entering phase E\n", s->id);
  344. p->isdone = 1;
  345. update_stats(p, completion_code);
  346. t30_get_transfer_statistics(t30_state, &stats);
  347. if (completion_code == T30_ERR_OK) {
  348. ast_string_field_set(s->details, result, "SUCCESS");
  349. } else {
  350. ast_string_field_set(s->details, result, "FAILED");
  351. ast_string_field_set(s->details, error, t30_completion_code_to_str(completion_code));
  352. }
  353. ast_string_field_set(s->details, resultstr, t30_completion_code_to_str(completion_code));
  354. ast_debug(5, "FAX session '%u' completed with result: %s (%s)\n", s->id, s->details->result, s->details->resultstr);
  355. if ((c = t30_get_tx_ident(t30_state))) {
  356. ast_string_field_set(s->details, localstationid, c);
  357. }
  358. if ((c = t30_get_rx_ident(t30_state))) {
  359. ast_string_field_set(s->details, remotestationid, c);
  360. }
  361. #if SPANDSP_RELEASE_DATE >= 20090220
  362. s->details->pages_transferred = (s->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx;
  363. #else
  364. s->details->pages_transferred = stats.pages_transferred;
  365. #endif
  366. ast_string_field_build(s->details, transfer_rate, "%d", stats.bit_rate);
  367. ast_string_field_build(s->details, resolution, "%dx%d", stats.x_resolution, stats.y_resolution);
  368. t30_get_tx_page_header_info(t30_state, headerinfo);
  369. ast_string_field_set(s->details, headerinfo, headerinfo);
  370. }
  371. /*! \brief Send spandsp log messages to asterisk.
  372. * \param level the spandsp logging level
  373. * \param msg the log message
  374. *
  375. * \note This function is a callback function called by spandsp.
  376. */
  377. static void spandsp_log(int level, const char *msg)
  378. {
  379. if (level == SPAN_LOG_ERROR) {
  380. ast_log(LOG_ERROR, "%s", msg);
  381. } else if (level == SPAN_LOG_WARNING) {
  382. ast_log(LOG_WARNING, "%s", msg);
  383. } else {
  384. ast_fax_log(LOG_DEBUG, msg);
  385. }
  386. }
  387. static void set_logging(logging_state_t *state, struct ast_fax_session_details *details)
  388. {
  389. int level = SPAN_LOG_WARNING;
  390. if (details->option.debug) {
  391. level = SPAN_LOG_DEBUG_3;
  392. }
  393. span_log_set_message_handler(state, spandsp_log);
  394. span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);
  395. }
  396. static void set_local_info(t30_state_t *t30_state, struct ast_fax_session_details *details)
  397. {
  398. if (!ast_strlen_zero(details->localstationid)) {
  399. t30_set_tx_ident(t30_state, details->localstationid);
  400. }
  401. if (!ast_strlen_zero(details->headerinfo)) {
  402. t30_set_tx_page_header_info(t30_state, details->headerinfo);
  403. }
  404. }
  405. static void set_file(t30_state_t *t30_state, struct ast_fax_session_details *details)
  406. {
  407. if (details->caps & AST_FAX_TECH_RECEIVE) {
  408. t30_set_rx_file(t30_state, AST_LIST_FIRST(&details->documents)->filename, -1);
  409. } else {
  410. /* if not AST_FAX_TECH_RECEIVE, assume AST_FAX_TECH_SEND, this
  411. * should be safe because we ensure either RECEIVE or SEND is
  412. * indicated in spandsp_fax_new() */
  413. t30_set_tx_file(t30_state, AST_LIST_FIRST(&details->documents)->filename, -1, -1);
  414. }
  415. }
  416. static void set_ecm(t30_state_t *t30_state, struct ast_fax_session_details *details)
  417. {
  418. t30_set_ecm_capability(t30_state, details->option.ecm);
  419. t30_set_supported_compressions(t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
  420. }
  421. static int spandsp_v21_new(struct spandsp_pvt *p)
  422. {
  423. /* XXX Here we use MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE even though
  424. * we don't care about CED tones. Using MODEM_CONNECT_TONES_PREAMBLE
  425. * doesn't seem to work right all the time.
  426. */
  427. p->tone_state = modem_connect_tones_rx_init(NULL, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, spandsp_v21_tone, p);
  428. if (!p->tone_state) {
  429. return -1;
  430. }
  431. return 0;
  432. }
  433. static int spandsp_modems(struct ast_fax_session_details *details)
  434. {
  435. int modems = 0;
  436. if (AST_FAX_MODEM_V17 & details->modems) {
  437. modems |= T30_SUPPORT_V17;
  438. }
  439. if (AST_FAX_MODEM_V27 & details->modems) {
  440. modems |= T30_SUPPORT_V27TER;
  441. }
  442. if (AST_FAX_MODEM_V29 & details->modems) {
  443. modems |= T30_SUPPORT_V29;
  444. }
  445. if (AST_FAX_MODEM_V34 & details->modems) {
  446. #if defined(T30_SUPPORT_V34)
  447. modems |= T30_SUPPORT_V34;
  448. #elif defined(T30_SUPPORT_V34HDX)
  449. modems |= T30_SUPPORT_V34HDX;
  450. #else
  451. ast_log(LOG_WARNING, "v34 not supported in this version of spandsp\n");
  452. #endif
  453. }
  454. return modems;
  455. }
  456. /*! \brief create an instance of the spandsp tech_pvt for a fax session */
  457. static void *spandsp_fax_new(struct ast_fax_session *s, struct ast_fax_tech_token *token)
  458. {
  459. struct spandsp_pvt *p;
  460. int caller_mode;
  461. if ((!(p = ast_calloc(1, sizeof(*p))))) {
  462. ast_log(LOG_ERROR, "Cannot initialize the spandsp private FAX technology structure.\n");
  463. goto e_return;
  464. }
  465. if (s->details->caps & AST_FAX_TECH_V21_DETECT) {
  466. if (spandsp_v21_new(p)) {
  467. ast_log(LOG_ERROR, "Cannot initialize the spandsp private v21 technology structure.\n");
  468. goto e_return;
  469. }
  470. s->state = AST_FAX_STATE_ACTIVE;
  471. return p;
  472. }
  473. if (s->details->caps & AST_FAX_TECH_GATEWAY) {
  474. s->state = AST_FAX_STATE_INITIALIZED;
  475. return p;
  476. }
  477. AST_LIST_HEAD_INIT(&p->read_frames);
  478. if (s->details->caps & AST_FAX_TECH_RECEIVE) {
  479. caller_mode = 0;
  480. } else if (s->details->caps & AST_FAX_TECH_SEND) {
  481. caller_mode = 1;
  482. } else {
  483. ast_log(LOG_ERROR, "Are we sending or receiving? The FAX requirements (capabilities: 0x%X) were not properly set.\n", s->details->caps);
  484. goto e_free;
  485. }
  486. if (!(p->timer = ast_timer_open())) {
  487. ast_log(LOG_ERROR, "Channel '%s' FAX session '%u' failed to create timing source.\n", s->channame, s->id);
  488. goto e_free;
  489. }
  490. s->fd = ast_timer_fd(p->timer);
  491. p->stats = &spandsp_global_stats.g711;
  492. if (s->details->caps & (AST_FAX_TECH_T38 | AST_FAX_TECH_AUDIO)) {
  493. if ((s->details->caps & AST_FAX_TECH_AUDIO) == 0) {
  494. /* audio mode was not requested, start in T.38 mode */
  495. p->ist38 = 1;
  496. p->stats = &spandsp_global_stats.t38;
  497. }
  498. /* init t38 stuff */
  499. t38_terminal_init(&p->t38_state, caller_mode, t38_tx_packet_handler, s);
  500. set_logging(&p->t38_state.logging, s->details);
  501. /* init audio stuff */
  502. fax_init(&p->fax_state, caller_mode);
  503. set_logging(&p->fax_state.logging, s->details);
  504. }
  505. s->state = AST_FAX_STATE_INITIALIZED;
  506. return p;
  507. e_free:
  508. ast_free(p);
  509. e_return:
  510. return NULL;
  511. }
  512. static void spandsp_v21_cleanup(struct ast_fax_session *s) {
  513. struct spandsp_pvt *p = s->tech_pvt;
  514. modem_connect_tones_rx_free(p->tone_state);
  515. }
  516. /*! \brief Destroy a spandsp fax session.
  517. */
  518. static void spandsp_fax_destroy(struct ast_fax_session *s)
  519. {
  520. struct spandsp_pvt *p = s->tech_pvt;
  521. if (s->details->caps & AST_FAX_TECH_GATEWAY) {
  522. spandsp_fax_gateway_cleanup(s);
  523. } else if (s->details->caps & AST_FAX_TECH_V21_DETECT) {
  524. spandsp_v21_cleanup(s);
  525. } else {
  526. session_destroy(p);
  527. }
  528. ast_free(p);
  529. s->tech_pvt = NULL;
  530. s->fd = -1;
  531. }
  532. /*! \brief Read a frame from the spandsp fax stack.
  533. */
  534. static struct ast_frame *spandsp_fax_read(struct ast_fax_session *s)
  535. {
  536. struct spandsp_pvt *p = s->tech_pvt;
  537. uint8_t buffer[AST_FRIENDLY_OFFSET + SPANDSP_FAX_SAMPLES * sizeof(uint16_t)];
  538. int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
  539. int samples;
  540. struct ast_frame fax_frame = {
  541. .frametype = AST_FRAME_VOICE,
  542. .src = "res_fax_spandsp_g711",
  543. .subclass.format = ast_format_slin,
  544. };
  545. struct ast_frame *f = &fax_frame;
  546. if (ast_timer_ack(p->timer, 1) < 0) {
  547. ast_log(LOG_ERROR, "Failed to acknowledge timer for FAX session '%u'\n", s->id);
  548. return NULL;
  549. }
  550. /* XXX do we need to lock here? */
  551. if (p->isdone) {
  552. s->state = AST_FAX_STATE_COMPLETE;
  553. ast_debug(5, "FAX session '%u' is complete.\n", s->id);
  554. return NULL;
  555. }
  556. if (p->ist38) {
  557. t38_terminal_send_timeout(&p->t38_state, SPANDSP_FAX_SAMPLES);
  558. if ((f = AST_LIST_REMOVE_HEAD(&p->read_frames, frame_list))) {
  559. return f;
  560. }
  561. } else {
  562. if ((samples = fax_tx(&p->fax_state, buf, SPANDSP_FAX_SAMPLES)) > 0) {
  563. f->samples = samples;
  564. AST_FRAME_SET_BUFFER(f, buffer, AST_FRIENDLY_OFFSET, samples * sizeof(int16_t));
  565. return ast_frisolate(f);
  566. }
  567. }
  568. return &ast_null_frame;
  569. }
  570. static void spandsp_v21_tone(void *data, int code, int level, int delay)
  571. {
  572. struct spandsp_pvt *p = data;
  573. if (code == MODEM_CONNECT_TONES_FAX_PREAMBLE) {
  574. p->v21_detected = 1;
  575. }
  576. }
  577. static int spandsp_v21_detect(struct ast_fax_session *s, const struct ast_frame *f) {
  578. struct spandsp_pvt *p = s->tech_pvt;
  579. int16_t *slndata;
  580. g711_state_t *decoder;
  581. if (p->v21_detected) {
  582. return 0;
  583. }
  584. /*invalid frame*/
  585. if (!f->data.ptr || !f->datalen) {
  586. return -1;
  587. }
  588. ast_debug(5, "frame={ datalen=%d, samples=%d, mallocd=%d, src=%s, flags=%u, ts=%ld, len=%ld, seqno=%d, data.ptr=%p, subclass.format=%s }\n", f->datalen, f->samples, f->mallocd, f->src, f->flags, f->ts, f->len, f->seqno, f->data.ptr, ast_format_get_name(f->subclass.format));
  589. /* slinear frame can be passed to spandsp */
  590. if (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
  591. modem_connect_tones_rx(p->tone_state, f->data.ptr, f->samples);
  592. /* alaw/ulaw frame must be converted to slinear before passing to spandsp */
  593. } else if (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL ||
  594. ast_format_cmp(f->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
  595. if (!(slndata = ast_malloc(sizeof(*slndata) * f->samples))) {
  596. return -1;
  597. }
  598. decoder = g711_init(NULL, (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL ? G711_ALAW : G711_ULAW));
  599. g711_decode(decoder, slndata, f->data.ptr, f->samples);
  600. ast_debug(5, "spandsp transcoding frame from %s to slinear for v21 detection\n", ast_format_get_name(f->subclass.format));
  601. modem_connect_tones_rx(p->tone_state, slndata, f->samples);
  602. g711_release(decoder);
  603. #if SPANDSP_RELEASE_DATE >= 20090220
  604. g711_free(decoder);
  605. #endif
  606. ast_free(slndata);
  607. /* frame in other formats cannot be passed to spandsp, it could cause segfault */
  608. } else {
  609. ast_log(LOG_WARNING, "Frame format %s not supported, v.21 detection skipped\n", ast_format_get_name(f->subclass.format));
  610. return -1;
  611. }
  612. if (p->v21_detected) {
  613. s->details->option.v21_detected = 1;
  614. ast_debug(5, "v.21 detected\n");
  615. }
  616. return 0;
  617. }
  618. /*! \brief Write a frame to the spandsp fax stack.
  619. * \param s a fax session
  620. * \param f the frame to write
  621. *
  622. * \note res_fax does not currently use the return value of this function.
  623. * Also the fax_rx() function never fails.
  624. *
  625. * \retval 0 success
  626. * \retval -1 failure
  627. */
  628. static int spandsp_fax_write(struct ast_fax_session *s, const struct ast_frame *f)
  629. {
  630. struct spandsp_pvt *p = s->tech_pvt;
  631. if (s->details->caps & AST_FAX_TECH_V21_DETECT) {
  632. return spandsp_v21_detect(s, f);
  633. }
  634. if (s->details->caps & AST_FAX_TECH_GATEWAY) {
  635. return spandsp_fax_gateway_process(s, f);
  636. }
  637. /* XXX do we need to lock here? */
  638. if (s->state == AST_FAX_STATE_COMPLETE) {
  639. ast_log(LOG_WARNING, "FAX session '%u' is in the '%s' state.\n", s->id, ast_fax_state_to_str(s->state));
  640. return -1;
  641. }
  642. if (p->ist38) {
  643. return t38_core_rx_ifp_packet(p->t38_core_state, f->data.ptr, f->datalen, f->seqno);
  644. } else {
  645. return fax_rx(&p->fax_state, f->data.ptr, f->samples);
  646. }
  647. }
  648. /*! \brief generate T.30 packets sent to the T.30 leg of gateway
  649. * \param chan T.30 channel
  650. * \param data fax session structure
  651. * \param len not used
  652. * \param samples no of samples generated
  653. * \return -1 on failure or 0 on sucess*/
  654. static int spandsp_fax_gw_t30_gen(struct ast_channel *chan, void *data, int len, int samples)
  655. {
  656. int res = -1;
  657. struct ast_fax_session *s = data;
  658. struct spandsp_pvt *p = s->tech_pvt;
  659. uint8_t buffer[AST_FRIENDLY_OFFSET + samples * sizeof(uint16_t)];
  660. struct ast_frame *f;
  661. struct ast_frame t30_frame = {
  662. .frametype = AST_FRAME_VOICE,
  663. .subclass.format = ast_format_slin,
  664. .src = "res_fax_spandsp_g711",
  665. .samples = samples,
  666. .flags = AST_FAX_FRFLAG_GATEWAY,
  667. };
  668. AST_FRAME_SET_BUFFER(&t30_frame, buffer, AST_FRIENDLY_OFFSET, t30_frame.samples * sizeof(int16_t));
  669. if (!(f = ast_frisolate(&t30_frame))) {
  670. return p->isdone ? -1 : res;
  671. }
  672. /* generate a T.30 packet */
  673. if ((f->samples = t38_gateway_tx(&p->t38_gw_state, f->data.ptr, f->samples))) {
  674. f->datalen = f->samples * sizeof(int16_t);
  675. res = ast_write(chan, f);
  676. }
  677. ast_frfree(f);
  678. return p->isdone ? -1 : res;
  679. }
  680. /*! \brief simple routine to allocate data to generator
  681. * \param chan channel
  682. * \param params generator data
  683. * \return data to use in generator call*/
  684. static void *spandsp_fax_gw_gen_alloc(struct ast_channel *chan, void *params) {
  685. ao2_ref(params, +1);
  686. return params;
  687. }
  688. static void spandsp_fax_gw_gen_release(struct ast_channel *chan, void *data) {
  689. ao2_ref(data, -1);
  690. }
  691. /*! \brief activate a spandsp gateway based on the information in the given fax session
  692. * \param s fax session
  693. * \return -1 on error 0 on sucess*/
  694. static int spandsp_fax_gateway_start(struct ast_fax_session *s) {
  695. struct spandsp_pvt *p = s->tech_pvt;
  696. struct ast_fax_t38_parameters *t38_param;
  697. int i;
  698. RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
  699. static struct ast_generator t30_gen = {
  700. .alloc = spandsp_fax_gw_gen_alloc,
  701. .release = spandsp_fax_gw_gen_release,
  702. .generate = spandsp_fax_gw_t30_gen,
  703. };
  704. #if SPANDSP_RELEASE_DATE >= 20081012
  705. /* for spandsp shaphots 0.0.6 and higher */
  706. p->t38_core_state=&p->t38_gw_state.t38x.t38;
  707. #else
  708. /* for spandsp release 0.0.5 */
  709. p->t38_core_state=&p->t38_gw_state.t38;
  710. #endif
  711. if (!t38_gateway_init(&p->t38_gw_state, t38_tx_packet_handler, s)) {
  712. return -1;
  713. }
  714. p->ist38 = 1;
  715. p->ast_t38_state = ast_channel_get_t38_state(s->chan);
  716. if (!(peer = ast_channel_bridge_peer(s->chan))) {
  717. ast_channel_unlock(s->chan);
  718. return -1;
  719. }
  720. /* we can be in T38_STATE_NEGOTIATING or T38_STATE_NEGOTIATED when the
  721. * gateway is started. We treat both states the same. */
  722. if (p->ast_t38_state == T38_STATE_NEGOTIATING) {
  723. p->ast_t38_state = T38_STATE_NEGOTIATED;
  724. }
  725. ast_activate_generator(p->ast_t38_state == T38_STATE_NEGOTIATED ? peer : s->chan, &t30_gen , s);
  726. set_logging(&p->t38_gw_state.logging, s->details);
  727. set_logging(&p->t38_core_state->logging, s->details);
  728. t38_param = (p->ast_t38_state == T38_STATE_NEGOTIATED) ? &s->details->our_t38_parameters : &s->details->their_t38_parameters;
  729. t38_set_t38_version(p->t38_core_state, t38_param->version);
  730. t38_gateway_set_ecm_capability(&p->t38_gw_state, s->details->option.ecm);
  731. t38_set_max_datagram_size(p->t38_core_state, t38_param->max_ifp);
  732. t38_set_fill_bit_removal(p->t38_core_state, t38_param->fill_bit_removal);
  733. t38_set_mmr_transcoding(p->t38_core_state, t38_param->transcoding_mmr);
  734. t38_set_jbig_transcoding(p->t38_core_state, t38_param->transcoding_jbig);
  735. t38_set_data_rate_management_method(p->t38_core_state,
  736. (t38_param->rate_management == AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF)? 1 : 2);
  737. t38_gateway_set_transmit_on_idle(&p->t38_gw_state, TRUE);
  738. t38_set_sequence_number_handling(p->t38_core_state, TRUE);
  739. t38_gateway_set_supported_modems(&p->t38_gw_state, spandsp_modems(s->details));
  740. /* engage udptl nat on other side of T38 line
  741. * (Asterisk changes media ports thus we send a few packets to reinitialize
  742. * pinholes in NATs and FWs
  743. */
  744. for (i=0; i < SPANDSP_ENGAGE_UDPTL_NAT_RETRY; i++) {
  745. #if SPANDSP_RELEASE_DATE >= 20091228
  746. t38_core_send_indicator(&p->t38_gw_state.t38x.t38, T38_IND_NO_SIGNAL);
  747. #elif SPANDSP_RELEASE_DATE >= 20081012
  748. t38_core_send_indicator(&p->t38_gw_state.t38x.t38, T38_IND_NO_SIGNAL, p->t38_gw_state.t38x.t38.indicator_tx_count);
  749. #else
  750. t38_core_send_indicator(&p->t38_gw_state.t38, T38_IND_NO_SIGNAL, p->t38_gw_state.t38.indicator_tx_count);
  751. #endif
  752. }
  753. s->state = AST_FAX_STATE_ACTIVE;
  754. return 0;
  755. }
  756. /*! \brief process a frame from the bridge
  757. * \param s fax session
  758. * \param f frame to process
  759. * \return 1 on sucess 0 on incorect packet*/
  760. static int spandsp_fax_gateway_process(struct ast_fax_session *s, const struct ast_frame *f)
  761. {
  762. struct spandsp_pvt *p = s->tech_pvt;
  763. /*invalid frame*/
  764. if (!f->data.ptr || !f->datalen) {
  765. return -1;
  766. }
  767. /* Process a IFP packet */
  768. if ((f->frametype == AST_FRAME_MODEM) && (f->subclass.integer == AST_MODEM_T38)) {
  769. return t38_core_rx_ifp_packet(p->t38_core_state, f->data.ptr, f->datalen, f->seqno);
  770. } else if ((f->frametype == AST_FRAME_VOICE) &&
  771. (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
  772. return t38_gateway_rx(&p->t38_gw_state, f->data.ptr, f->samples);
  773. }
  774. return -1;
  775. }
  776. /*! \brief gather data and clean up after gateway ends
  777. * \param s fax session*/
  778. static void spandsp_fax_gateway_cleanup(struct ast_fax_session *s)
  779. {
  780. struct spandsp_pvt *p = s->tech_pvt;
  781. t38_stats_t t38_stats;
  782. t38_gateway_get_transfer_statistics(&p->t38_gw_state, &t38_stats);
  783. s->details->option.ecm = t38_stats.error_correcting_mode ? AST_FAX_OPTFLAG_TRUE : AST_FAX_OPTFLAG_FALSE;
  784. s->details->pages_transferred = t38_stats.pages_transferred;
  785. ast_string_field_build(s->details, transfer_rate, "%d", t38_stats.bit_rate);
  786. }
  787. /*! \brief */
  788. static int spandsp_fax_start(struct ast_fax_session *s)
  789. {
  790. struct spandsp_pvt *p = s->tech_pvt;
  791. s->state = AST_FAX_STATE_OPEN;
  792. if (s->details->caps & AST_FAX_TECH_GATEWAY) {
  793. return spandsp_fax_gateway_start(s);
  794. }
  795. if (p->ist38) {
  796. #if SPANDSP_RELEASE_DATE >= 20080725
  797. /* for spandsp shaphots 0.0.6 and higher */
  798. p->t30_state = &p->t38_state.t30;
  799. p->t38_core_state = &p->t38_state.t38_fe.t38;
  800. #else
  801. /* for spandsp releases 0.0.5 */
  802. p->t30_state = &p->t38_state.t30_state;
  803. p->t38_core_state = &p->t38_state.t38;
  804. #endif
  805. } else {
  806. #if SPANDSP_RELEASE_DATE >= 20080725
  807. /* for spandsp shaphots 0.0.6 and higher */
  808. p->t30_state = &p->fax_state.t30;
  809. #else
  810. /* for spandsp release 0.0.5 */
  811. p->t30_state = &p->fax_state.t30_state;
  812. #endif
  813. }
  814. set_logging(&p->t30_state->logging, s->details);
  815. /* set some parameters */
  816. set_local_info(p->t30_state, s->details);
  817. set_file(p->t30_state, s->details);
  818. set_ecm(p->t30_state, s->details);
  819. t30_set_supported_modems(p->t30_state, spandsp_modems(s->details));
  820. /* perhaps set_transmit_on_idle() should be called */
  821. t30_set_phase_e_handler(p->t30_state, t30_phase_e_handler, s);
  822. /* set T.38 parameters */
  823. if (p->ist38) {
  824. set_logging(&p->t38_core_state->logging, s->details);
  825. t38_set_max_datagram_size(p->t38_core_state, s->details->their_t38_parameters.max_ifp);
  826. if (s->details->their_t38_parameters.fill_bit_removal) {
  827. t38_set_fill_bit_removal(p->t38_core_state, TRUE);
  828. }
  829. if (s->details->their_t38_parameters.transcoding_mmr) {
  830. t38_set_mmr_transcoding(p->t38_core_state, TRUE);
  831. }
  832. if (s->details->their_t38_parameters.transcoding_jbig) {
  833. t38_set_jbig_transcoding(p->t38_core_state, TRUE);
  834. }
  835. } else {
  836. /* have the fax stack generate silence if it has no data to send */
  837. fax_set_transmit_on_idle(&p->fax_state, 1);
  838. }
  839. /* start the timer */
  840. if (ast_timer_set_rate(p->timer, SPANDSP_FAX_TIMER_RATE)) {
  841. ast_log(LOG_ERROR, "FAX session '%u' error setting rate on timing source.\n", s->id);
  842. return -1;
  843. }
  844. s->state = AST_FAX_STATE_ACTIVE;
  845. return 0;
  846. }
  847. /*! \brief */
  848. static int spandsp_fax_cancel(struct ast_fax_session *s)
  849. {
  850. struct spandsp_pvt *p = s->tech_pvt;
  851. if (s->details->caps & AST_FAX_TECH_GATEWAY) {
  852. p->isdone = 1;
  853. return 0;
  854. }
  855. t30_terminate(p->t30_state);
  856. p->isdone = 1;
  857. return 0;
  858. }
  859. /*! \brief */
  860. static int spandsp_fax_switch_to_t38(struct ast_fax_session *s)
  861. {
  862. struct spandsp_pvt *p = s->tech_pvt;
  863. /* prevent the phase E handler from running, this is not a real termination */
  864. t30_set_phase_e_handler(p->t30_state, NULL, NULL);
  865. t30_terminate(p->t30_state);
  866. s->details->option.switch_to_t38 = 1;
  867. ast_atomic_fetchadd_int(&p->stats->switched, 1);
  868. p->ist38 = 1;
  869. p->stats = &spandsp_global_stats.t38;
  870. spandsp_fax_start(s);
  871. return 0;
  872. }
  873. /*! \brief */
  874. static char *spandsp_fax_cli_show_capabilities(int fd)
  875. {
  876. ast_cli(fd, "SEND RECEIVE T.38 G.711 GATEWAY\n\n");
  877. return CLI_SUCCESS;
  878. }
  879. /*! \brief */
  880. static char *spandsp_fax_cli_show_session(struct ast_fax_session *s, int fd)
  881. {
  882. ao2_lock(s);
  883. if (s->details->caps & AST_FAX_TECH_GATEWAY) {
  884. struct spandsp_pvt *p = s->tech_pvt;
  885. ast_cli(fd, "%-22s : %u\n", "session", s->id);
  886. ast_cli(fd, "%-22s : %s\n", "operation", "Gateway");
  887. ast_cli(fd, "%-22s : %s\n", "state", ast_fax_state_to_str(s->state));
  888. if (s->state != AST_FAX_STATE_UNINITIALIZED) {
  889. t38_stats_t stats;
  890. t38_gateway_get_transfer_statistics(&p->t38_gw_state, &stats);
  891. ast_cli(fd, "%-22s : %s\n", "ECM Mode", stats.error_correcting_mode ? "Yes" : "No");
  892. ast_cli(fd, "%-22s : %d\n", "Data Rate", stats.bit_rate);
  893. ast_cli(fd, "%-22s : %d\n", "Page Number", stats.pages_transferred + 1);
  894. }
  895. } else if (s->details->caps & AST_FAX_TECH_V21_DETECT) {
  896. ast_cli(fd, "%-22s : %u\n", "session", s->id);
  897. ast_cli(fd, "%-22s : %s\n", "operation", "V.21 Detect");
  898. ast_cli(fd, "%-22s : %s\n", "state", ast_fax_state_to_str(s->state));
  899. } else {
  900. struct spandsp_pvt *p = s->tech_pvt;
  901. ast_cli(fd, "%-22s : %u\n", "session", s->id);
  902. ast_cli(fd, "%-22s : %s\n", "operation", (s->details->caps & AST_FAX_TECH_RECEIVE) ? "Receive" : "Transmit");
  903. ast_cli(fd, "%-22s : %s\n", "state", ast_fax_state_to_str(s->state));
  904. if (s->state != AST_FAX_STATE_UNINITIALIZED) {
  905. t30_stats_t stats;
  906. t30_get_transfer_statistics(p->t30_state, &stats);
  907. ast_cli(fd, "%-22s : %s\n", "Last Status", t30_completion_code_to_str(stats.current_status));
  908. ast_cli(fd, "%-22s : %s\n", "ECM Mode", stats.error_correcting_mode ? "Yes" : "No");
  909. ast_cli(fd, "%-22s : %d\n", "Data Rate", stats.bit_rate);
  910. ast_cli(fd, "%-22s : %dx%d\n", "Image Resolution", stats.x_resolution, stats.y_resolution);
  911. #if SPANDSP_RELEASE_DATE >= 20090220
  912. ast_cli(fd, "%-22s : %d\n", "Page Number", ((s->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx) + 1);
  913. #else
  914. ast_cli(fd, "%-22s : %d\n", "Page Number", stats.pages_transferred + 1);
  915. #endif
  916. ast_cli(fd, "%-22s : %s\n", "File Name", s->details->caps & AST_FAX_TECH_RECEIVE ? p->t30_state->rx_file : p->t30_state->tx_file);
  917. ast_cli(fd, "\nData Statistics:\n");
  918. #if SPANDSP_RELEASE_DATE >= 20090220
  919. ast_cli(fd, "%-22s : %d\n", "Tx Pages", stats.pages_tx);
  920. ast_cli(fd, "%-22s : %d\n", "Rx Pages", stats.pages_rx);
  921. #else
  922. ast_cli(fd, "%-22s : %d\n", "Tx Pages", (s->details->caps & AST_FAX_TECH_SEND) ? stats.pages_transferred : 0);
  923. ast_cli(fd, "%-22s : %d\n", "Rx Pages", (s->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_transferred : 0);
  924. #endif
  925. ast_cli(fd, "%-22s : %d\n", "Longest Bad Line Run", stats.longest_bad_row_run);
  926. ast_cli(fd, "%-22s : %d\n", "Total Bad Lines", stats.bad_rows);
  927. }
  928. }
  929. ao2_unlock(s);
  930. ast_cli(fd, "\n\n");
  931. return CLI_SUCCESS;
  932. }
  933. static void spandsp_manager_fax_session(struct mansession *s,
  934. const char *id_text, struct ast_fax_session *session)
  935. {
  936. struct ast_str *message_string;
  937. struct spandsp_pvt *span_pvt = session->tech_pvt;
  938. int res;
  939. message_string = ast_str_create(128);
  940. if (!message_string) {
  941. return;
  942. }
  943. ao2_lock(session);
  944. res = ast_str_append(&message_string, 0, "SessionNumber: %u\r\n", session->id);
  945. res |= ast_str_append(&message_string, 0, "Operation: %s\r\n", ast_fax_session_operation_str(session));
  946. res |= ast_str_append(&message_string, 0, "State: %s\r\n", ast_fax_state_to_str(session->state));
  947. if (session->details->caps & AST_FAX_TECH_GATEWAY) {
  948. t38_stats_t stats;
  949. if (session->state == AST_FAX_STATE_UNINITIALIZED) {
  950. goto skip_cap_additions;
  951. }
  952. t38_gateway_get_transfer_statistics(&span_pvt->t38_gw_state, &stats);
  953. res |= ast_str_append(&message_string, 0, "ErrorCorrectionMode: %s\r\n",
  954. stats.error_correcting_mode ? "yes" : "no");
  955. res |= ast_str_append(&message_string, 0, "DataRate: %d\r\n",
  956. stats.bit_rate);
  957. res |= ast_str_append(&message_string, 0, "PageNumber: %d\r\n",
  958. stats.pages_transferred + 1);
  959. } else if (!(session->details->caps & AST_FAX_TECH_V21_DETECT)) { /* caps is SEND/RECEIVE */
  960. t30_stats_t stats;
  961. if (session->state == AST_FAX_STATE_UNINITIALIZED) {
  962. goto skip_cap_additions;
  963. }
  964. t30_get_transfer_statistics(span_pvt->t30_state, &stats);
  965. res |= ast_str_append(&message_string, 0, "ErrorCorrectionMode: %s\r\n",
  966. stats.error_correcting_mode ? "Yes" : "No");
  967. res |= ast_str_append(&message_string, 0, "DataRate: %d\r\n",
  968. stats.bit_rate);
  969. res |= ast_str_append(&message_string, 0, "ImageResolution: %dx%d\r\n",
  970. stats.x_resolution, stats.y_resolution);
  971. #if SPANDSP_RELEASE_DATE >= 20090220
  972. res |= ast_str_append(&message_string, 0, "PageNumber: %d\r\n",
  973. ((session->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx) + 1);
  974. #else
  975. res |= ast_str_append(&message_string, 0, "PageNumber: %d\r\n",
  976. stats.pages_transferred + 1);
  977. #endif
  978. res |= ast_str_append(&message_string, 0, "FileName: %s\r\n",
  979. session->details->caps & AST_FAX_TECH_RECEIVE ? span_pvt->t30_state->rx_file :
  980. span_pvt->t30_state->tx_file);
  981. #if SPANDSP_RELEASE_DATE >= 20090220
  982. res |= ast_str_append(&message_string, 0, "PagesTransmitted: %d\r\n",
  983. stats.pages_tx);
  984. res |= ast_str_append(&message_string, 0, "PagesReceived: %d\r\n",
  985. stats.pages_rx);
  986. #else
  987. res |= ast_str_append(&message_string, 0, "PagesTransmitted: %d\r\n",
  988. (session->details->caps & AST_FAX_TECH_SEND) ? stats.pages_transferred : 0);
  989. res |= ast_str_append(&message_string, 0, "PagesReceived: %d\r\n",
  990. (session->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_transferred : 0);
  991. #endif
  992. res |= ast_str_append(&message_string, 0, "TotalBadLines: %d\r\n",
  993. stats.bad_rows);
  994. }
  995. skip_cap_additions:
  996. ao2_unlock(session);
  997. if (res < 0) {
  998. /* One or more of the ast_str_append attempts failed, cancel the message */
  999. ast_free(message_string);
  1000. return;
  1001. }
  1002. astman_append(s, "Event: FAXSession\r\n"
  1003. "%s"
  1004. "%s"
  1005. "\r\n",
  1006. id_text,
  1007. ast_str_buffer(message_string));
  1008. ast_free(message_string);
  1009. }
  1010. /*! \brief */
  1011. static char *spandsp_fax_cli_show_stats(int fd)
  1012. {
  1013. ast_mutex_lock(&spandsp_global_stats.lock);
  1014. ast_cli(fd, "\n%-20.20s\n", "Spandsp G.711");
  1015. ast_cli(fd, "%-20.20s : %d\n", "Success", spandsp_global_stats.g711.success);
  1016. ast_cli(fd, "%-20.20s : %d\n", "Switched to T.38", spandsp_global_stats.g711.switched);
  1017. ast_cli(fd, "%-20.20s : %d\n", "Call Dropped", spandsp_global_stats.g711.call_dropped);
  1018. ast_cli(fd, "%-20.20s : %d\n", "No FAX", spandsp_global_stats.g711.nofax);
  1019. ast_cli(fd, "%-20.20s : %d\n", "Negotiation Failed", spandsp_global_stats.g711.neg_failed);
  1020. ast_cli(fd, "%-20.20s : %d\n", "Train Failure", spandsp_global_stats.g711.failed_to_train);
  1021. ast_cli(fd, "%-20.20s : %d\n", "Retries Exceeded", spandsp_global_stats.g711.retries_exceeded);
  1022. ast_cli(fd, "%-20.20s : %d\n", "Protocol Error", spandsp_global_stats.g711.protocol_error);
  1023. ast_cli(fd, "%-20.20s : %d\n", "TX Protocol Error", spandsp_global_stats.g711.tx_protocol_error);
  1024. ast_cli(fd, "%-20.20s : %d\n", "RX Protocol Error", spandsp_global_stats.g711.rx_protocol_error);
  1025. ast_cli(fd, "%-20.20s : %d\n", "File Error", spandsp_global_stats.g711.file_error);
  1026. ast_cli(fd, "%-20.20s : %d\n", "Memory Error", spandsp_global_stats.g711.mem_error);
  1027. ast_cli(fd, "%-20.20s : %d\n", "Unknown Error", spandsp_global_stats.g711.unknown_error);
  1028. ast_cli(fd, "\n%-20.20s\n", "Spandsp T.38");
  1029. ast_cli(fd, "%-20.20s : %d\n", "Success", spandsp_global_stats.t38.success);
  1030. ast_cli(fd, "%-20.20s : %d\n", "Call Dropped", spandsp_global_stats.t38.call_dropped);
  1031. ast_cli(fd, "%-20.20s : %d\n", "No FAX", spandsp_global_stats.t38.nofax);
  1032. ast_cli(fd, "%-20.20s : %d\n", "Negotiation Failed", spandsp_global_stats.t38.neg_failed);
  1033. ast_cli(fd, "%-20.20s : %d\n", "Train Failure", spandsp_global_stats.t38.failed_to_train);
  1034. ast_cli(fd, "%-20.20s : %d\n", "Retries Exceeded", spandsp_global_stats.t38.retries_exceeded);
  1035. ast_cli(fd, "%-20.20s : %d\n", "Protocol Error", spandsp_global_stats.t38.protocol_error);
  1036. ast_cli(fd, "%-20.20s : %d\n", "TX Protocol Error", spandsp_global_stats.t38.tx_protocol_error);
  1037. ast_cli(fd, "%-20.20s : %d\n", "RX Protocol Error", spandsp_global_stats.t38.rx_protocol_error);
  1038. ast_cli(fd, "%-20.20s : %d\n", "File Error", spandsp_global_stats.t38.file_error);
  1039. ast_cli(fd, "%-20.20s : %d\n", "Memory Error", spandsp_global_stats.t38.mem_error);
  1040. ast_cli(fd, "%-20.20s : %d\n", "Unknown Error", spandsp_global_stats.t38.unknown_error);
  1041. ast_mutex_unlock(&spandsp_global_stats.lock);
  1042. return CLI_SUCCESS;
  1043. }
  1044. /*! \brief Show res_fax_spandsp settings */
  1045. static char *spandsp_fax_cli_show_settings(int fd)
  1046. {
  1047. /* no settings at the moment */
  1048. return CLI_SUCCESS;
  1049. }
  1050. /*! \brief unload res_fax_spandsp */
  1051. static int unload_module(void)
  1052. {
  1053. ast_fax_tech_unregister(&spandsp_fax_tech);
  1054. ast_mutex_destroy(&spandsp_global_stats.lock);
  1055. return AST_MODULE_LOAD_SUCCESS;
  1056. }
  1057. /*! \brief load res_fax_spandsp */
  1058. static int load_module(void)
  1059. {
  1060. ast_mutex_init(&spandsp_global_stats.lock);
  1061. spandsp_fax_tech.module = ast_module_info->self;
  1062. if (ast_fax_tech_register(&spandsp_fax_tech) < 0) {
  1063. ast_log(LOG_ERROR, "failed to register FAX technology\n");
  1064. return AST_MODULE_LOAD_DECLINE;
  1065. }
  1066. /* prevent logging to stderr */
  1067. span_set_message_handler(NULL);
  1068. return AST_MODULE_LOAD_SUCCESS;
  1069. }
  1070. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Spandsp G.711 and T.38 FAX Technologies",
  1071. .support_level = AST_MODULE_SUPPORT_EXTENDED,
  1072. .load = load_module,
  1073. .unload = unload_module,
  1074. );