Wed Jan 8 2020 09:49:50

Asterisk developer's documentation


res_fax.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2008-2009, Digium, Inc.
5  *
6  * Dwayne M. Hubbard <dhubbard@digium.com>
7  * Kevin P. Fleming <kpfleming@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19 
20 /*** MODULEINFO
21  <support_level>core</support_level>
22  <conflict>app_fax</conflict>
23 ***/
24 
25 /*! \file
26  *
27  * \brief Generic FAX Resource for FAX technology resource modules
28  *
29  * \author Dwayne M. Hubbard <dhubbard@digium.com>
30  * \author Kevin P. Fleming <kpfleming@digium.com>
31  *
32  * A generic FAX resource module that provides SendFAX and ReceiveFAX applications.
33  * This module requires FAX technology modules, like res_fax_spandsp, to register with it
34  * so it can use the technology modules to perform the actual FAX transmissions.
35  * \ingroup applications
36  */
37 
38 #include "asterisk.h"
39 
40 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 425405 $")
41 
42 #include "asterisk/io.h"
43 #include "asterisk/file.h"
44 #include "asterisk/logger.h"
45 #include "asterisk/module.h"
46 #include "asterisk/app.h"
47 #include "asterisk/lock.h"
48 #include "asterisk/options.h"
49 #include "asterisk/strings.h"
50 #include "asterisk/cli.h"
51 #include "asterisk/utils.h"
52 #include "asterisk/config.h"
53 #include "asterisk/astobj2.h"
54 #include "asterisk/res_fax.h"
55 #include "asterisk/file.h"
56 #include "asterisk/channel.h"
57 #include "asterisk/pbx.h"
58 #include "asterisk/manager.h"
59 #include "asterisk/dsp.h"
60 #include "asterisk/indications.h"
61 #include "asterisk/ast_version.h"
62 
63 /*** DOCUMENTATION
64  <application name="ReceiveFAX" language="en_US" module="res_fax">
65  <synopsis>
66  Receive a FAX and save as a TIFF/F file.
67  </synopsis>
68  <syntax>
69  <parameter name="filename" required="true" />
70  <parameter name="options">
71  <optionlist>
72  <option name="d">
73  <para>Enable FAX debugging.</para>
74  </option>
75  <option name="f">
76  <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
77  </option>
78  <option name="s">
79  <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
80  </option>
81  </optionlist>
82  </parameter>
83  </syntax>
84  <description>
85  <para>This application is provided by res_fax, which is a FAX technology agnostic module
86  that utilizes FAX technology resource modules to complete a FAX transmission.</para>
87  <para>Session arguments can be set by the FAXOPT function and to check results of the ReceiveFax() application.</para>
88  </description>
89  <see-also>
90  <ref type="function">FAXOPT</ref>
91  </see-also>
92  </application>
93  <application name="SendFAX" language="en_US" module="res_fax">
94  <synopsis>
95  Sends a specified TIFF/F file as a FAX.
96  </synopsis>
97  <syntax>
98  <parameter name="filename" required="true" argsep="&amp;">
99  <argument name="filename2" multiple="true">
100  <para>TIFF file to send as a FAX.</para>
101  </argument>
102  </parameter>
103  <parameter name="options">
104  <optionlist>
105  <option name="d">
106  <para>Enable FAX debugging.</para>
107  </option>
108  <option name="f">
109  <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
110  </option>
111  <option name="s">
112  <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
113  </option>
114  <option name="z">
115  <para>Initiate a T.38 reinvite on the channel if the remote end does not.</para>
116  </option>
117  </optionlist>
118  </parameter>
119  </syntax>
120  <description>
121  <para>This application is provided by res_fax, which is a FAX technology agnostic module
122  that utilizes FAX technology resource modules to complete a FAX transmission.</para>
123  <para>Session arguments can be set by the FAXOPT function and to check results of the SendFax() application.</para>
124  </description>
125  <see-also>
126  <ref type="function">FAXOPT</ref>
127  </see-also>
128  </application>
129  <function name="FAXOPT" language="en_US" module="res_fax">
130  <synopsis>
131  Gets/sets various pieces of information about a fax session.
132  </synopsis>
133  <syntax>
134  <parameter name="item" required="true">
135  <enumlist>
136  <enum name="ecm">
137  <para>R/W Error Correction Mode (ECM) enable with 'yes', disable with 'no'.</para>
138  </enum>
139  <enum name="error">
140  <para>R/O FAX transmission error code upon failure.</para>
141  </enum>
142  <enum name="filename">
143  <para>R/O Filename of the first file of the FAX transmission.</para>
144  </enum>
145  <enum name="filenames">
146  <para>R/O Filenames of all of the files in the FAX transmission (comma separated).</para>
147  </enum>
148  <enum name="headerinfo">
149  <para>R/W FAX header information.</para>
150  </enum>
151  <enum name="localstationid">
152  <para>R/W Local Station Identification.</para>
153  </enum>
154  <enum name="minrate">
155  <para>R/W Minimum transfer rate set before transmission.</para>
156  </enum>
157  <enum name="maxrate">
158  <para>R/W Maximum transfer rate set before transmission.</para>
159  </enum>
160  <enum name="modem">
161  <para>R/W Modem type (v17/v27/v29).</para>
162  </enum>
163  <enum name="pages">
164  <para>R/O Number of pages transferred.</para>
165  </enum>
166  <enum name="rate">
167  <para>R/O Negotiated transmission rate.</para>
168  </enum>
169  <enum name="remotestationid">
170  <para>R/O Remote Station Identification after transmission.</para>
171  </enum>
172  <enum name="resolution">
173  <para>R/O Negotiated image resolution after transmission.</para>
174  </enum>
175  <enum name="sessionid">
176  <para>R/O Session ID of the FAX transmission.</para>
177  </enum>
178  <enum name="status">
179  <para>R/O Result Status of the FAX transmission.</para>
180  </enum>
181  <enum name="statusstr">
182  <para>R/O Verbose Result Status of the FAX transmission.</para>
183  </enum>
184  </enumlist>
185  </parameter>
186  </syntax>
187  <description>
188  <para>FAXOPT can be used to override the settings for a FAX session listed in <filename>res_fax.conf</filename>,
189  it can also be used to retreive information about a FAX session that has finished eg. pages/status.</para>
190  </description>
191  <see-also>
192  <ref type="application">ReceiveFax</ref>
193  <ref type="application">SendFax</ref>
194  </see-also>
195  </function>
196 ***/
197 
198 static const char app_receivefax[] = "ReceiveFAX";
199 static const char app_sendfax[] = "SendFAX";
200 
202  unsigned int consec_frames;
203  unsigned int consec_ms;
204  unsigned char silence;
205 };
206 
208  struct timeval base_tv;
209  struct debug_info_history c2s, s2c;
210  struct ast_dsp *dsp;
211 };
212 
213 static int fax_logger_level = -1;
214 
215 /*! \brief maximum buckets for res_fax ao2 containers */
216 #define FAX_MAXBUCKETS 10
217 
218 #define RES_FAX_TIMEOUT 10000
219 
220 /*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */
221 static struct {
222  /*! The number of active FAX sessions */
224  /*! The number of reserved FAX sessions */
226  /*! active sessions are astobj2 objects */
228  /*! Total number of Tx FAX attempts */
230  /*! Total number of Rx FAX attempts */
232  /*! Number of successful FAX transmissions */
234  /*! Number of failed FAX transmissions */
236  /*! the next unique session name */
238 } faxregistry;
239 
240 /*! \brief registered FAX technology modules are put into this list */
241 struct fax_module {
242  const struct ast_fax_tech *tech;
244 };
246 
247 #define RES_FAX_MINRATE 4800
248 #define RES_FAX_MAXRATE 14400
249 #define RES_FAX_STATUSEVENTS 0
250 #define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)
251 
252 struct fax_options {
253  enum ast_fax_modems modems;
254  uint32_t statusevents:1;
255  uint32_t ecm:1;
256  unsigned int minrate;
257  unsigned int maxrate;
258 };
259 
261 
262 static const struct fax_options default_options = {
264  .maxrate = RES_FAX_MAXRATE,
265  .statusevents = RES_FAX_STATUSEVENTS,
266  .modems = RES_FAX_MODEM,
267  .ecm = AST_FAX_OPTFLAG_TRUE,
268 };
269 
271 
272 static void get_general_options(struct fax_options* options);
273 static void set_general_options(const struct fax_options* options);
274 
275 static const char *config = "res_fax.conf";
276 
277 static int global_fax_debug = 0;
278 
279 enum {
280  OPT_CALLEDMODE = (1 << 0),
281  OPT_CALLERMODE = (1 << 1),
282  OPT_DEBUG = (1 << 2),
283  OPT_STATUS = (1 << 3),
284  OPT_ALLOWAUDIO = (1 << 5),
285  OPT_REQUEST_T38 = (1 << 6),
286 };
287 
296 
300  char cid[128];
301 };
302 
303 static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
304 {
305  struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
306  int dspsilence;
307  unsigned int last_consec_frames, last_consec_ms;
308  unsigned char wassil;
309  struct timeval diff;
310 
311  diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
312 
314  ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
315 
316  wassil = history->silence;
317  history->silence = (dspsilence != 0) ? 1 : 0;
318  if (history->silence != wassil) {
319  last_consec_frames = history->consec_frames;
320  last_consec_ms = history->consec_ms;
321  history->consec_frames = 0;
322  history->consec_ms = 0;
323 
324  if ((last_consec_frames != 0)) {
325  ast_verb(6, "Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
326  s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
327  (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
328  (wassil) ? "silence" : "energy");
329  }
330  }
331 
332  history->consec_frames++;
333  history->consec_ms += (frame->samples / 8);
334 }
335 
336 static void destroy_callback(void *data)
337 {
338  if (data) {
339  ao2_ref(data, -1);
340  }
341 }
342 
343 static const struct ast_datastore_info fax_datastore = {
344  .type = "res_fax",
345  .destroy = destroy_callback,
346 };
347 
348 /*! \brief returns a reference counted pointer to a fax datastore, if it exists */
350 {
351  struct ast_fax_session_details *details;
352  struct ast_datastore *datastore;
353 
354  ast_channel_lock(chan);
355  if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
356  ast_channel_unlock(chan);
357  return NULL;
358  }
359  if (!(details = datastore->data)) {
360  ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", chan->name);
361  ast_channel_unlock(chan);
362  return NULL;
363  }
364  ao2_ref(details, 1);
365  ast_channel_unlock(chan);
366 
367  return details;
368 }
369 
370 /*! \brief destroy a FAX session details structure */
371 static void destroy_session_details(void *details)
372 {
373  struct ast_fax_session_details *d = details;
374  struct ast_fax_document *doc;
375 
376  while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
377  ast_free(doc);
378  }
380 }
381 
382 /*! \brief create a FAX session details structure */
384 {
385  struct ast_fax_session_details *d;
386  struct fax_options options;
387 
388  if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
389  return NULL;
390  }
391 
392  if (ast_string_field_init(d, 512)) {
393  ao2_ref(d, -1);
394  return NULL;
395  }
396 
397  get_general_options(&options);
398 
400 
401  /* These options need to be set to the configured default and may be overridden by
402  * SendFAX, ReceiveFAX, or FAXOPT */
406  d->option.ecm = options.ecm;
407  d->option.statusevents = options.statusevents;
408  d->modems = options.modems;
409  d->minrate = options.minrate;
410  d->maxrate = options.maxrate;
411 
412  return d;
413 }
414 
415 /*! \brief returns a reference counted details structure from the channel's fax datastore. If the datastore
416  * does not exist it will be created */
418 {
419  struct ast_fax_session_details *details;
420  struct ast_datastore *datastore;
421 
422  if ((details = find_details(chan))) {
423  return details;
424  }
425  /* channel does not have one so we must create one */
426  if (!(details = session_details_new())) {
427  ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", chan->name);
428  return NULL;
429  }
430  if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
431  ao2_ref(details, -1);
432  ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", chan->name);
433  return NULL;
434  }
435  /* add the datastore to the channel and increment the refcount */
436  datastore->data = details;
437  ao2_ref(details, 1);
438  ast_channel_lock(chan);
439  ast_channel_datastore_add(chan, datastore);
440  ast_channel_unlock(chan);
441  return details;
442 }
443 
444 unsigned int ast_fax_maxrate(void)
445 {
446  struct fax_options options;
447  get_general_options(&options);
448 
449  return options.maxrate;
450 }
451 
452 unsigned int ast_fax_minrate(void)
453 {
454  struct fax_options options;
455  get_general_options(&options);
456 
457  return options.minrate;
458 }
459 
460 static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
461 {
462  char *m[5], *tok, *v = (char *)value;
463  int i = 0, j;
464 
465  if (!strchr(v, ',')) {
466  m[i++] = v;
467  m[i] = NULL;
468  } else {
469  tok = strtok(v, ", ");
470  while (tok && i < ARRAY_LEN(m) - 1) {
471  m[i++] = tok;
472  tok = strtok(NULL, ", ");
473  }
474  m[i] = NULL;
475  }
476 
477  *bits = 0;
478  for (j = 0; j < i; j++) {
479  if (!strcasecmp(m[j], "v17")) {
480  *bits |= AST_FAX_MODEM_V17;
481  } else if (!strcasecmp(m[j], "v27")) {
482  *bits |= AST_FAX_MODEM_V27;
483  } else if (!strcasecmp(m[j], "v29")) {
484  *bits |= AST_FAX_MODEM_V29;
485  } else if (!strcasecmp(m[j], "v34")) {
486  *bits |= AST_FAX_MODEM_V34;
487  } else {
488  ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
489  }
490  }
491  return 0;
492 }
493 
494 static char *ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
495 {
496  char *out = buf;
497  size_t size = bufsize;
498  int first = 1;
499 
500  if (caps & AST_FAX_TECH_SEND) {
501  if (!first) {
502  ast_build_string(&buf, &size, ",");
503  }
504  ast_build_string(&buf, &size, "SEND");
505  first = 0;
506  }
507  if (caps & AST_FAX_TECH_RECEIVE) {
508  if (!first) {
509  ast_build_string(&buf, &size, ",");
510  }
511  ast_build_string(&buf, &size, "RECEIVE");
512  first = 0;
513  }
514  if (caps & AST_FAX_TECH_AUDIO) {
515  if (!first) {
516  ast_build_string(&buf, &size, ",");
517  }
518  ast_build_string(&buf, &size, "AUDIO");
519  first = 0;
520  }
521  if (caps & AST_FAX_TECH_T38) {
522  if (!first) {
523  ast_build_string(&buf, &size, ",");
524  }
525  ast_build_string(&buf, &size, "T38");
526  first = 0;
527  }
528  if (caps & AST_FAX_TECH_MULTI_DOC) {
529  if (!first) {
530  ast_build_string(&buf, &size, ",");
531  }
532  ast_build_string(&buf, &size, "MULTI_DOC");
533  first = 0;
534  }
535 
536  return out;
537 }
538 
539 static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
540 {
541  int count = 0;
542 
543  if (bits & AST_FAX_MODEM_V17) {
544  strcat(tbuf, "V17");
545  count++;
546  }
547  if (bits & AST_FAX_MODEM_V27) {
548  if (count) {
549  strcat(tbuf, ",");
550  }
551  strcat(tbuf, "V27");
552  count++;
553  }
554  if (bits & AST_FAX_MODEM_V29) {
555  if (count) {
556  strcat(tbuf, ",");
557  }
558  strcat(tbuf, "V29");
559  count++;
560  }
561  if (bits & AST_FAX_MODEM_V34) {
562  if (count) {
563  strcat(tbuf, ",");
564  }
565  strcat(tbuf, "V34");
566  count++;
567  }
568 
569  return 0;
570 }
571 
572 static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
573 {
574  switch (rate) {
575  case 2400:
576  if (!(modems & (AST_FAX_MODEM_V34))) {
577  return 1;
578  }
579  break;
580  case 4800:
581  if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) {
582  return 1;
583  }
584  break;
585  case 7200:
586  if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
587  return 1;
588  }
589  break;
590  case 9600:
592  return 1;
593  }
594  break;
595  case 12000:
596  case 14400:
597  if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
598  return 1;
599  }
600  break;
601  case 28800:
602  case 33600:
603  if (!(modems & AST_FAX_MODEM_V34)) {
604  return 1;
605  }
606  break;
607  default:
608  /* this should never happen */
609  return 1;
610  }
611 
612  return 0;
613 }
614 
615 /*! \brief register a FAX technology module */
617 {
618  struct fax_module *fax;
619 
620  if (!(fax = ast_calloc(1, sizeof(*fax)))) {
621  return -1;
622  }
623  fax->tech = tech;
624  AST_RWLIST_WRLOCK(&faxmodules);
625  AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
626  AST_RWLIST_UNLOCK(&faxmodules);
628 
629  ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
630 
631  return 0;
632 }
633 
634 /*! \brief unregister a FAX technology module */
636 {
637  struct fax_module *fax;
638 
639  ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
640 
641  AST_RWLIST_WRLOCK(&faxmodules);
642  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&faxmodules, fax, list) {
643  if (fax->tech != tech) {
644  continue;
645  }
648  ast_free(fax);
649  ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
650  break;
651  }
653  AST_RWLIST_UNLOCK(&faxmodules);
654 }
655 
656 /*! \brief convert a ast_fax_state to a string */
658 {
659  switch (state) {
661  return "Uninitialized";
663  return "Initialized";
664  case AST_FAX_STATE_OPEN:
665  return "Open";
667  return "Active";
669  return "Complete";
671  return "Reserved";
673  return "Inactive";
674  default:
675  ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state);
676  return "Unknown";
677  }
678 }
679 
680 void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
681 {
682  if (fax_logger_level != -1) {
683  ast_log_dynamic_level(fax_logger_level, "%s", msg);
684  } else {
685  ast_log(level, file, line, function, "%s", msg);
686  }
687 }
688 
689 /*! \brief convert a rate string to a rate */
690 static unsigned int fax_rate_str_to_int(const char *ratestr)
691 {
692  int rate;
693 
694  if (sscanf(ratestr, "%d", &rate) != 1) {
695  ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
696  return 0;
697  }
698  switch (rate) {
699  case 2400:
700  case 4800:
701  case 7200:
702  case 9600:
703  case 12000:
704  case 14400:
705  case 28800:
706  case 33600:
707  return rate;
708  default:
709  ast_log(LOG_WARNING, "ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
710  return 0;
711  }
712 }
713 
714 static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
715 {
716  if (token) {
717  s->tech->release_token(token);
718  }
719 
720  if (s->state == AST_FAX_STATE_RESERVED) {
721  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
723  }
724 }
725 
726 /*! \brief destroy a FAX session structure */
727 static void destroy_session(void *session)
728 {
729  struct ast_fax_session *s = session;
730 
731  if (s->tech) {
732  fax_session_release(s, NULL);
733  if (s->tech_pvt) {
734  s->tech->destroy_session(s);
735  }
737  }
738 
739  if (s->details) {
740  ao2_ref(s->details, -1);
741  }
742 
743  if (s->debug_info) {
745  ast_free(s->debug_info);
746  }
747 
748  if (s->smoother) {
750  }
751 
752  if (s->state != AST_FAX_STATE_INACTIVE) {
753  ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
754  }
755 
756  ast_free(s->channame);
758 }
759 
760 static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
761 {
762  struct ast_fax_session *s;
763  struct fax_module *faxmod;
764  char caps[128] = "";
765 
766  if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
767  return NULL;
768  }
769 
771 
772  /* locate a FAX technology module that can handle said requirements
773  * Note: the requirements have not yet been finalized as T.38
774  * negotiation has not yet occured. */
775  AST_RWLIST_RDLOCK(&faxmodules);
776  AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
777  if ((faxmod->tech->caps & details->caps) != details->caps) {
778  continue;
779  }
780  ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
781  ast_module_ref(faxmod->tech->module);
782  s->tech = faxmod->tech;
783  break;
784  }
785  AST_RWLIST_UNLOCK(&faxmodules);
786 
787  if (!faxmod) {
788  ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->caps, caps, sizeof(caps)));
789  ao2_ref(s, -1);
790  return NULL;
791  }
792 
793  if (!s->tech->reserve_session) {
794  ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
795  return s;
796  }
797 
798  if (!(*token = s->tech->reserve_session(s))) {
799  ao2_ref(s, -1);
800  return NULL;
801  }
802 
804  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
805 
806  return s;
807 }
808 
809 /*! \brief create a FAX session */
810 static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *details, struct ast_channel *chan, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
811 {
812  struct ast_fax_session *s = NULL;
813  struct fax_module *faxmod;
814  char caps[128] = "";
815 
816  if (reserved) {
817  s = reserved;
818  ao2_ref(reserved, +1);
819 
820  if (s->state == AST_FAX_STATE_RESERVED) {
821  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
823  }
824  }
825 
826  if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
827  return NULL;
828  }
829 
830  ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
832 
833  if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
834  if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
835  fax_session_release(s, token);
836  ao2_ref(s, -1);
837  return NULL;
838  }
839  if (!(s->debug_info->dsp = ast_dsp_new())) {
840  ast_free(s->debug_info);
841  s->debug_info = NULL;
842  fax_session_release(s, token);
843  ao2_ref(s, -1);
844  return NULL;
845  }
847  }
848 
849  if (!(s->channame = ast_strdup(chan->name))) {
850  fax_session_release(s, token);
851  ao2_ref(s, -1);
852  return NULL;
853  }
854 
855  if (!(s->chan_uniqueid = ast_strdup(chan->uniqueid))) {
856  fax_session_release(s, token);
857  ao2_ref(s, -1);
858  return NULL;
859  }
860 
861  s->chan = chan;
862  s->details = details;
863  ao2_ref(s->details, 1);
864 
865  details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
866 
867  if (!token) {
868  /* locate a FAX technology module that can handle said requirements */
869  AST_RWLIST_RDLOCK(&faxmodules);
870  AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
871  if ((faxmod->tech->caps & details->caps) != details->caps) {
872  continue;
873  }
874  ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
875  ast_module_ref(faxmod->tech->module);
876  if (reserved) {
877  /* Balance module ref from reserved session */
878  ast_module_unref(reserved->tech->module);
879  }
880  s->tech = faxmod->tech;
881  break;
882  }
883  AST_RWLIST_UNLOCK(&faxmodules);
884 
885  if (!faxmod) {
886  ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->caps, caps, sizeof(caps)));
887  ao2_ref(s, -1);
888  return NULL;
889  }
890  }
891 
892  if (!(s->tech_pvt = s->tech->new_session(s, token))) {
893  ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
894  ao2_ref(s, -1);
895  return NULL;
896  }
897  /* link the session to the session container */
898  if (!(ao2_link(faxregistry.container, s))) {
899  ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id);
900  ao2_ref(s, -1);
901  return NULL;
902  }
903  ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id);
904 
905  return s;
906 }
907 
908 static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
909 {
910  pbx_substitute_variables_helper(chan, "${CONTEXT}", info->context, sizeof(info->context));
911  pbx_substitute_variables_helper(chan, "${EXTEN}", info->exten, sizeof(info->exten));
912  pbx_substitute_variables_helper(chan, "${CALLERID(num)}", info->cid, sizeof(info->cid));
913 }
914 
915 
916 /* \brief Generate a string of filenames using the given prefix and separator.
917  * \param details the fax session details
918  * \param prefix the prefix to each filename
919  * \param separator the separator between filenames
920  *
921  * This function generates a string of filenames from the given details
922  * structure and using the given prefix and separator.
923  *
924  * \retval NULL there was an error generating the string
925  * \return the string generated string
926  */
927 static char *generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
928 {
929  char *filenames, *c;
930  size_t size = 0;
931  int first = 1;
932  struct ast_fax_document *doc;
933 
934  /* don't process empty lists */
935  if (AST_LIST_EMPTY(&details->documents)) {
936  return NULL;
937  }
938 
939  /* Calculate the total length of all of the file names */
940  AST_LIST_TRAVERSE(&details->documents, doc, next) {
941  size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
942  }
943  size += 1; /* add space for the terminating null */
944 
945  if (!(filenames = ast_malloc(size))) {
946  return NULL;
947  }
948  c = filenames;
949 
950  ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
951  AST_LIST_TRAVERSE(&details->documents, doc, next) {
952  if (first) {
953  first = 0;
954  continue;
955  }
956 
957  ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
958  }
959 
960  return filenames;
961 }
962 
963 /*! \brief send a FAX status manager event */
964 static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
965 {
966  char *filenames = generate_filenames_string(details, "FileName: ", "\r\n");
967  if (!filenames) {
968  return 1;
969  }
970 
971  ast_channel_lock(chan);
972  if (details->option.statusevents) {
973  struct manager_event_info info;
974 
975  get_manager_event_info(chan, &info);
977  (details->caps & AST_FAX_TECH_RECEIVE) ? "ReceiveFAXStatus" : "SendFAXStatus",
978  "Status: %s\r\n"
979  "Channel: %s\r\n"
980  "Context: %s\r\n"
981  "Exten: %s\r\n"
982  "CallerID: %s\r\n"
983  "LocalStationID: %s\r\n"
984  "%s\r\n",
985  status,
986  chan->name,
987  info.context,
988  info.exten,
989  info.cid,
990  details->localstationid,
991  filenames);
992  }
993  ast_channel_unlock(chan);
994  ast_free(filenames);
995 
996  return 0;
997 }
998 
999 /*! \brief Set fax related channel variables. */
1000 static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
1001 {
1002  char buf[10];
1003  pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
1004  pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
1005  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
1006  pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL));
1007  pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", S_OR(details->localstationid, NULL));
1008  pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
1009  pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
1010 
1011  snprintf(buf, sizeof(buf), "%u", details->pages_transferred);
1012  pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
1013 }
1014 
1015 #define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason) \
1016  do { \
1017  if (ast_strlen_zero(fax->details->result)) \
1018  ast_string_field_set(fax->details, result, "FAILED"); \
1019  if (ast_strlen_zero(fax->details->resultstr)) \
1020  ast_string_field_set(fax->details, resultstr, reason); \
1021  if (ast_strlen_zero(fax->details->error)) \
1022  ast_string_field_set(fax->details, error, errorstr); \
1023  set_channel_variables(chan, fax->details); \
1024  } while (0)
1025 
1026 #define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) \
1027  do { \
1028  GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
1029  } while (0)
1030 
1031 #define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) \
1032  do { \
1033  ast_log(LOG_ERROR, "channel '%s' FAX session '%u' failure, reason: '%s' (%s)\n", chan->name, fax->id, reason, errorstr); \
1034  GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
1035  } while (0)
1036 
1038 {
1039  dst->version = src->version;
1040  dst->max_ifp = src->max_ifp;
1041  dst->rate = src->rate;
1042  dst->rate_management = src->rate_management;
1043  dst->fill_bit_removal = src->fill_bit_removal;
1044  dst->transcoding_mmr = src->transcoding_mmr;
1045  dst->transcoding_jbig = src->transcoding_jbig;
1046 }
1047 
1049 {
1050  dst->version = src->version;
1051  dst->max_ifp = src->max_ifp;
1052  dst->rate = src->rate;
1053  dst->rate_management = src->rate_management;
1054  dst->fill_bit_removal = src->fill_bit_removal;
1055  dst->transcoding_mmr = src->transcoding_mmr;
1056  dst->transcoding_jbig = src->transcoding_jbig;
1057 }
1058 
1059 static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
1060 {
1061  switch (ast_channel_get_t38_state(chan)) {
1062  case T38_STATE_UNKNOWN:
1063  details->caps |= AST_FAX_TECH_T38;
1064  break;
1065  case T38_STATE_UNAVAILABLE:
1066  details->caps |= AST_FAX_TECH_AUDIO;
1067  break;
1068  case T38_STATE_NEGOTIATING: {
1069  /* the other end already sent us a T.38 reinvite, so we need to prod the channel
1070  * driver into resending their parameters to us if it supports doing so... if
1071  * not, we can't proceed, because we can't create a proper reply without them.
1072  * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
1073  * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
1074  * that gets called after this one completes
1075  */
1077  if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
1078  ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name);
1079  return -1;
1080  }
1081  details->caps |= AST_FAX_TECH_T38;
1082  break;
1083  }
1084  default:
1085  ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name);
1086  return -1;
1087  }
1088 
1089  return 0;
1090 }
1091 
1092 static int disable_t38(struct ast_channel *chan)
1093 {
1094  int timeout_ms;
1095  struct ast_frame *frame = NULL;
1097  struct timeval start;
1098  int ms;
1099 
1100  ast_debug(1, "Shutting down T.38 on %s\n", chan->name);
1101  if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
1102  ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
1103  return -1;
1104  }
1105 
1106  /* wait up to five seconds for negotiation to complete */
1107  timeout_ms = 5000;
1108  start = ast_tvnow();
1109  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1110  ms = ast_waitfor(chan, ms);
1111 
1112  if (ms == 0) {
1113  break;
1114  }
1115  if (ms < 0) {
1116  ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
1117  return -1;
1118  }
1119 
1120  if (!(frame = ast_read(chan))) {
1121  return -1;
1122  }
1123  if ((frame->frametype == AST_FRAME_CONTROL) &&
1125  (frame->datalen == sizeof(t38_parameters))) {
1126  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1127 
1128  switch (parameters->request_response) {
1129  case AST_T38_TERMINATED:
1130  ast_debug(1, "Shut down T.38 on %s\n", chan->name);
1131  break;
1132  case AST_T38_REFUSED:
1133  ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", chan->name);
1134  ast_frfree(frame);
1135  return -1;
1136  default:
1137  ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", chan->name);
1138  ast_frfree(frame);
1139  return -1;
1140  }
1141  ast_frfree(frame);
1142  break;
1143  }
1144  ast_frfree(frame);
1145  }
1146 
1147  if (ms == 0) { /* all done, nothing happened */
1148  ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", chan->name);
1149  }
1150 
1151  return 0;
1152 }
1153 
1155  .version = 0,
1156  .max_ifp = 400,
1157  .rate = AST_T38_RATE_14400,
1158  .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
1159 };
1160 
1161 /*! \brief this is the generic FAX session handling function */
1162 static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
1163 {
1164  int ms;
1165  int timeout = RES_FAX_TIMEOUT;
1166  int chancount;
1167  unsigned int expected_frametype = -1;
1168  union ast_frame_subclass expected_framesubclass = { .integer = -1 };
1169  unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
1170  struct ast_control_t38_parameters t38_parameters;
1171  const char *tempvar;
1172  struct ast_fax_session *fax = NULL;
1173  struct ast_frame *frame = NULL;
1174  struct ast_channel *c = chan;
1175  unsigned int orig_write_format = 0, orig_read_format = 0;
1176  int remaining_time;
1177  struct timeval start;
1178 
1179  chancount = 1;
1180 
1181  /* create the FAX session */
1182  if (!(fax = fax_session_new(details, chan, reserved, token))) {
1183  ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
1184  report_fax_status(chan, details, "No Available Resource");
1185  return -1;
1186  }
1187 
1188  ast_channel_lock(chan);
1189  /* update session details */
1190  if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
1191  ast_string_field_set(details, headerinfo, tempvar);
1192  }
1193  if (ast_strlen_zero(details->localstationid)) {
1194  tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
1195  ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
1196  }
1197  ast_channel_unlock(chan);
1198 
1199  report_fax_status(chan, details, "Allocating Resources");
1200 
1201  if (details->caps & AST_FAX_TECH_AUDIO) {
1202  expected_frametype = AST_FRAME_VOICE;;
1203  expected_framesubclass.codec = AST_FORMAT_SLINEAR;
1204  orig_write_format = chan->writeformat;
1205  if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
1206  ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", chan->name);
1207  ao2_lock(faxregistry.container);
1208  ao2_unlink(faxregistry.container, fax);
1209  ao2_unlock(faxregistry.container);
1210  ao2_ref(fax, -1);
1211  ast_channel_unlock(chan);
1212  return -1;
1213  }
1214  orig_read_format = chan->readformat;
1215  if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
1216  ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", chan->name);
1217  ao2_lock(faxregistry.container);
1218  ao2_unlink(faxregistry.container, fax);
1219  ao2_unlock(faxregistry.container);
1220  ao2_ref(fax, -1);
1221  ast_channel_unlock(chan);
1222  return -1;
1223  }
1224  if (fax->smoother) {
1226  fax->smoother = NULL;
1227  }
1228  if (!(fax->smoother = ast_smoother_new(320))) {
1229  ast_log(LOG_WARNING, "Channel '%s' FAX session '%u' failed to obtain a smoother.\n", chan->name, fax->id);
1230  }
1231  } else {
1232  expected_frametype = AST_FRAME_MODEM;
1233  expected_framesubclass.codec = AST_MODEM_T38;
1234  }
1235 
1236  if (fax->debug_info) {
1237  fax->debug_info->base_tv = ast_tvnow();
1238  }
1239 
1240  /* reset our result fields just in case the fax tech driver wants to
1241  * set custom error messages */
1242  ast_string_field_set(details, result, "");
1243  ast_string_field_set(details, resultstr, "");
1244  ast_string_field_set(details, error, "");
1245  set_channel_variables(chan, details);
1246 
1247  if (fax->tech->start_session(fax) < 0) {
1248  GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
1249  }
1250 
1251  report_fax_status(chan, details, "FAX Transmission In Progress");
1252 
1253  ast_debug(5, "channel %s will wait on FAX fd %d\n", chan->name, fax->fd);
1254 
1255  /* handle frames for the session */
1256  remaining_time = timeout;
1257  start = ast_tvnow();
1258  while (remaining_time > 0) {
1259  struct ast_channel *ready_chan;
1260  int ofd, exception;
1261 
1262  ms = 1000;
1263  errno = 0;
1264  ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
1265  if (ready_chan) {
1266  if (!(frame = ast_read(chan))) {
1267  /* the channel is probably gone, so lets stop polling on it and let the
1268  * FAX session complete before we exit the application. if needed,
1269  * send the FAX stack silence so the modems can finish their session without
1270  * any problems */
1271  ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", chan->name);
1272  GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
1273  c = NULL;
1274  chancount = 0;
1275  remaining_time = ast_remaining_ms(start, timeout);
1276  fax->tech->cancel_session(fax);
1277  if (fax->tech->generate_silence) {
1278  fax->tech->generate_silence(fax);
1279  }
1280  continue;
1281  }
1282 
1283  if ((frame->frametype == AST_FRAME_CONTROL) &&
1285  (frame->datalen == sizeof(t38_parameters))) {
1286  unsigned int was_t38 = t38negotiated;
1287  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1288 
1289  switch (parameters->request_response) {
1291  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1292  * do T.38 as well
1293  */
1294  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1295  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1296  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1297  break;
1298  case AST_T38_NEGOTIATED:
1299  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1300  t38negotiated = 1;
1301  break;
1302  default:
1303  break;
1304  }
1305  if (t38negotiated && !was_t38) {
1306  fax->tech->switch_to_t38(fax);
1307  details->caps &= ~AST_FAX_TECH_AUDIO;
1308  expected_frametype = AST_FRAME_MODEM;
1309  expected_framesubclass.codec = AST_MODEM_T38;
1310  if (fax->smoother) {
1312  fax->smoother = NULL;
1313  }
1314 
1315  report_fax_status(chan, details, "T.38 Negotiated");
1316 
1317  ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", chan->name, fax->id);
1318  }
1319  } else if ((frame->frametype == expected_frametype) &&
1320  (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) {
1321  struct ast_frame *f;
1322 
1323  if (fax->smoother) {
1324  /* push the frame into a smoother */
1325  if (ast_smoother_feed(fax->smoother, frame) < 0) {
1326  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
1327  }
1328  while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
1329  if (fax->debug_info) {
1330  debug_check_frame_for_silence(fax, 1, f);
1331  }
1332  /* write the frame to the FAX stack */
1333  fax->tech->write(fax, f);
1334  fax->frames_received++;
1335  if (f != frame) {
1336  ast_frfree(f);
1337  }
1338  }
1339  } else {
1340  /* write the frame to the FAX stack */
1341  fax->tech->write(fax, frame);
1342  fax->frames_received++;
1343  }
1344  start = ast_tvnow();
1345  }
1346  ast_frfree(frame);
1347  } else if (ofd == fax->fd) {
1348  /* read a frame from the FAX stack and send it out the channel.
1349  * the FAX stack will return a NULL if the FAX session has already completed */
1350  if (!(frame = fax->tech->read(fax))) {
1351  break;
1352  }
1353 
1354  if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
1355  debug_check_frame_for_silence(fax, 0, frame);
1356  }
1357 
1358  ast_write(chan, frame);
1359  fax->frames_sent++;
1360  ast_frfree(frame);
1361  start = ast_tvnow();
1362  } else {
1363  if (ms && (ofd < 0)) {
1364  if ((errno == 0) || (errno == EINTR)) {
1365  remaining_time = ast_remaining_ms(start, timeout);
1366  if (remaining_time <= 0)
1367  GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1368  continue;
1369  } else {
1370  ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name);
1371  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
1372  break;
1373  }
1374  } else {
1375  /* nothing happened */
1376  remaining_time = ast_remaining_ms(start, timeout);
1377  if (remaining_time <= 0) {
1378  GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1379  break;
1380  }
1381  }
1382  }
1383  }
1384  ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", chan->name, timeout, remaining_time);
1385 
1386  set_channel_variables(chan, details);
1387 
1388  if (!strcasecmp(details->result, "FAILED")) {
1389  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1390  } else {
1391  ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
1392  }
1393 
1394  if (fax) {
1395  ao2_lock(faxregistry.container);
1396  ao2_unlink(faxregistry.container, fax);
1397  ao2_unlock(faxregistry.container);
1398  ao2_ref(fax, -1);
1399  }
1400 
1401  /* if the channel is still alive, and we changed its read/write formats,
1402  * restore them now
1403  */
1404  if (chancount) {
1405  if (orig_read_format) {
1406  ast_set_read_format(chan, orig_read_format);
1407  }
1408  if (orig_write_format) {
1409  ast_set_write_format(chan, orig_write_format);
1410  }
1411  }
1412 
1413  /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
1414  return chancount;
1415 }
1416 
1417 static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
1418 {
1419  int timeout_ms;
1420  struct ast_frame *frame = NULL;
1421  struct ast_control_t38_parameters t38_parameters;
1422  struct timeval start;
1423  int ms;
1424 
1426 
1427  /* don't send any audio if we've already received a T.38 reinvite */
1429  /* generate 3 seconds of CED */
1430  if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
1431  ast_log(LOG_ERROR, "error generating CED tone on %s\n", chan->name);
1432  return -1;
1433  }
1434 
1435  timeout_ms = 3000;
1436  start = ast_tvnow();
1437  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1438  ms = ast_waitfor(chan, ms);
1439 
1440  if (ms < 0) {
1441  ast_log(LOG_ERROR, "error while generating CED tone on %s\n", chan->name);
1442  ast_playtones_stop(chan);
1443  return -1;
1444  }
1445 
1446  if (ms == 0) { /* all done, nothing happened */
1447  break;
1448  }
1449 
1450  if (!(frame = ast_read(chan))) {
1451  ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", chan->name);
1452  ast_playtones_stop(chan);
1453  return -1;
1454  }
1455 
1456  if ((frame->frametype == AST_FRAME_CONTROL) &&
1458  (frame->datalen == sizeof(t38_parameters))) {
1459  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1460 
1461  switch (parameters->request_response) {
1463  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1464  * do T.38 as well
1465  */
1466  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1467  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1468  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1469  ast_playtones_stop(chan);
1470  break;
1471  case AST_T38_NEGOTIATED:
1472  ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
1473  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1474  details->caps &= ~AST_FAX_TECH_AUDIO;
1475  report_fax_status(chan, details, "T.38 Negotiated");
1476  break;
1477  default:
1478  break;
1479  }
1480  }
1481  ast_frfree(frame);
1482  }
1483 
1484  ast_playtones_stop(chan);
1485  }
1486 
1487  /* if T.38 was negotiated, we are done initializing */
1489  return 0;
1490  }
1491 
1492  /* request T.38 */
1493  ast_debug(1, "Negotiating T.38 for receive on %s\n", chan->name);
1494 
1495  /* wait up to five seconds for negotiation to complete */
1496  timeout_ms = 5000;
1497 
1498  /* set parameters based on the session's parameters */
1499  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1501  if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1502  return -1;
1503  }
1504 
1505  start = ast_tvnow();
1506  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1507  int break_loop = 0;
1508 
1509  ms = ast_waitfor(chan, ms);
1510  if (ms < 0) {
1511  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1512  return -1;
1513  }
1514  if (ms == 0) { /* all done, nothing happened */
1515  ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
1516  details->caps &= ~AST_FAX_TECH_T38;
1517  break;
1518  }
1519 
1520  if (!(frame = ast_read(chan))) {
1521  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1522  return -1;
1523  }
1524 
1525  if ((frame->frametype == AST_FRAME_CONTROL) &&
1527  (frame->datalen == sizeof(t38_parameters))) {
1528  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1529 
1530  switch (parameters->request_response) {
1532  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1533  t38_parameters.request_response = AST_T38_NEGOTIATED;
1534  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1535  break;
1536  case AST_T38_NEGOTIATED:
1537  ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
1538  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1539  details->caps &= ~AST_FAX_TECH_AUDIO;
1540  report_fax_status(chan, details, "T.38 Negotiated");
1541  break_loop = 1;
1542  break;
1543  case AST_T38_REFUSED:
1544  ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
1545  details->caps &= ~AST_FAX_TECH_T38;
1546  break_loop = 1;
1547  break;
1548  default:
1549  ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
1550  details->caps &= ~AST_FAX_TECH_T38;
1551  break_loop = 1;
1552  break;
1553  }
1554  }
1555  ast_frfree(frame);
1556  if (break_loop) {
1557  break;
1558  }
1559  }
1560 
1561  /* if T.38 was negotiated, we are done initializing */
1563  return 0;
1564  }
1565 
1566  /* if we made it here, then T.38 failed, check the 'f' flag */
1567  if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
1568  ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name);
1569  return -1;
1570  }
1571 
1572  /* ok, audio fallback is allowed */
1573  details->caps |= AST_FAX_TECH_AUDIO;
1574 
1575  return 0;
1576 }
1577 
1578 /*! \brief initiate a receive FAX session */
1579 static int receivefax_exec(struct ast_channel *chan, const char *data)
1580 {
1581  char *parse, modems[128] = "";
1582  int channel_alive;
1583  struct ast_fax_session_details *details;
1584  struct ast_fax_session *s;
1585  struct ast_fax_tech_token *token = NULL;
1586  struct ast_fax_document *doc;
1589  AST_APP_ARG(options);
1590  );
1591  struct ast_flags opts = { 0, };
1592  struct manager_event_info info;
1593 
1594  /* initialize output channel variables */
1595  pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
1596  pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
1597  pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
1598  pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
1599  pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
1600 
1601  /* if we ran receivefax then we attempted to receive a fax, even if we
1602  * never start a fax session */
1603  ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
1604 
1605  /* Get a FAX session details structure from the channel's FAX datastore and create one if
1606  * it does not already exist. */
1607  if (!(details = find_or_create_details(chan))) {
1608  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1609  pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
1610  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
1611  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1612  return -1;
1613  }
1614 
1615  ast_string_field_set(details, result, "FAILED");
1616  ast_string_field_set(details, resultstr, "error starting fax session");
1617  ast_string_field_set(details, error, "INIT_ERROR");
1618  set_channel_variables(chan, details);
1619 
1620  if (details->maxrate < details->minrate) {
1621  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1622  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1623  ast_string_field_set(details, resultstr, "maxrate is less than minrate");
1624  set_channel_variables(chan, details);
1625  ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
1626  ao2_ref(details, -1);
1627  return -1;
1628  }
1629 
1630  if (check_modem_rate(details->modems, details->minrate)) {
1631  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1632  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
1633  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
1634  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1635  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
1636  set_channel_variables(chan, details);
1637  ao2_ref(details, -1);
1638  return -1;
1639  }
1640 
1641  if (check_modem_rate(details->modems, details->maxrate)) {
1642  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1643  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
1644  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
1645  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1646  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
1647  set_channel_variables(chan, details);
1648  ao2_ref(details, -1);
1649  return -1;
1650  }
1651 
1652  if (ast_strlen_zero(data)) {
1653  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1654  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1655  ast_string_field_set(details, resultstr, "invalid arguments");
1656  set_channel_variables(chan, details);
1657  ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1658  ao2_ref(details, -1);
1659  return -1;
1660  }
1661  parse = ast_strdupa(data);
1662  AST_STANDARD_APP_ARGS(args, parse);
1663 
1664  if (!ast_strlen_zero(args.options) &&
1665  ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
1666  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1667  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1668  ast_string_field_set(details, resultstr, "invalid arguments");
1669  set_channel_variables(chan, details);
1670  ao2_ref(details, -1);
1671  return -1;
1672  }
1673  if (ast_strlen_zero(args.filename)) {
1674  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1675  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1676  ast_string_field_set(details, resultstr, "invalid arguments");
1677  set_channel_variables(chan, details);
1678  ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1679  ao2_ref(details, -1);
1680  return -1;
1681  }
1682 
1683  /* check for unsupported FAX application options */
1684  if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
1685  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1686  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1687  ast_string_field_set(details, resultstr, "invalid arguments");
1688  set_channel_variables(chan, details);
1689  ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
1690  ao2_ref(details, -1);
1691  return -1;
1692  }
1693 
1694  pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
1695  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
1696 
1697  if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
1698  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1699  ast_string_field_set(details, error, "MEMORY_ERROR");
1700  ast_string_field_set(details, resultstr, "error allocating memory");
1701  set_channel_variables(chan, details);
1702  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1703  ao2_ref(details, -1);
1704  return -1;
1705  }
1706 
1707  strcpy(doc->filename, args.filename);
1708  AST_LIST_INSERT_TAIL(&details->documents, doc, next);
1709 
1710  ast_verb(3, "Channel '%s' receiving FAX '%s'\n", chan->name, args.filename);
1711 
1712  details->caps = AST_FAX_TECH_RECEIVE;
1714 
1715  /* check for debug */
1716  if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
1717  details->option.debug = AST_FAX_OPTFLAG_TRUE;
1718  }
1719 
1720  /* check for request for status events */
1721  if (ast_test_flag(&opts, OPT_STATUS)) {
1723  }
1724 
1726  ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
1728  }
1729 
1730  if (!(s = fax_session_reserve(details, &token))) {
1731  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1732  ast_string_field_set(details, resultstr, "error reserving fax session");
1733  set_channel_variables(chan, details);
1734  ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
1735  ao2_ref(details, -1);
1736  return -1;
1737  }
1738 
1739  /* make sure the channel is up */
1740  if (chan->_state != AST_STATE_UP) {
1741  if (ast_answer(chan)) {
1742  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1743  ast_string_field_set(details, resultstr, "error answering channel");
1744  set_channel_variables(chan, details);
1745  ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
1746  fax_session_release(s, token);
1747  ao2_ref(s, -1);
1748  ao2_ref(details, -1);
1749  return -1;
1750  }
1751  }
1752 
1753  if (set_fax_t38_caps(chan, details)) {
1754  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1755  ast_string_field_set(details, error, "T38_NEG_ERROR");
1756  ast_string_field_set(details, resultstr, "error negotiating T.38");
1757  set_channel_variables(chan, details);
1758  fax_session_release(s, token);
1759  ao2_ref(s, -1);
1760  ao2_ref(details, -1);
1761  return -1;
1762  }
1763 
1764  if (details->caps & AST_FAX_TECH_T38) {
1765  if (receivefax_t38_init(chan, details)) {
1766  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1767  ast_string_field_set(details, error, "T38_NEG_ERROR");
1768  ast_string_field_set(details, resultstr, "error negotiating T.38");
1769  set_channel_variables(chan, details);
1770  fax_session_release(s, token);
1771  ao2_ref(s, -1);
1772  ao2_ref(details, -1);
1773  ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
1774  return -1;
1775  }
1776  }
1777 
1778  if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
1779  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1780  }
1781 
1783  if (disable_t38(chan)) {
1784  ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
1785  }
1786  }
1787 
1788  /* send out the AMI completion event */
1789  ast_channel_lock(chan);
1790 
1791  get_manager_event_info(chan, &info);
1793  "ReceiveFAX",
1794  "Channel: %s\r\n"
1795  "Context: %s\r\n"
1796  "Exten: %s\r\n"
1797  "CallerID: %s\r\n"
1798  "RemoteStationID: %s\r\n"
1799  "LocalStationID: %s\r\n"
1800  "PagesTransferred: %s\r\n"
1801  "Resolution: %s\r\n"
1802  "TransferRate: %s\r\n"
1803  "FileName: %s\r\n",
1804  chan->name,
1805  info.context,
1806  info.exten,
1807  info.cid,
1808  S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
1809  S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
1810  S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
1811  S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
1812  S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
1813  args.filename);
1814  ast_channel_unlock(chan);
1815 
1816  ao2_ref(s, -1);
1817  ao2_ref(details, -1);
1818 
1819  /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
1820  return (!channel_alive) ? -1 : 0;
1821 }
1822 
1823 static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
1824 {
1825  int timeout_ms;
1826  struct ast_frame *frame = NULL;
1827  struct ast_control_t38_parameters t38_parameters;
1828  struct timeval start;
1829  int ms;
1830 
1832 
1833  /* send CNG tone while listening for the receiver to initiate a switch
1834  * to T.38 mode; if they do, stop sending the CNG tone and proceed with
1835  * the switch.
1836  *
1837  * 10500 is enough time for 3 CNG tones
1838  */
1839  timeout_ms = 10500;
1840 
1841  /* don't send any audio if we've already received a T.38 reinvite */
1843  if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
1844  ast_log(LOG_ERROR, "error generating CNG tone on %s\n", chan->name);
1845  return -1;
1846  }
1847  }
1848 
1849  start = ast_tvnow();
1850  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1851  int break_loop = 0;
1852  ms = ast_waitfor(chan, ms);
1853 
1854  if (ms < 0) {
1855  ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", chan->name);
1856  ast_playtones_stop(chan);
1857  return -1;
1858  }
1859 
1860  if (ms == 0) { /* all done, nothing happened */
1861  break;
1862  }
1863 
1864  if (!(frame = ast_read(chan))) {
1865  ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", chan->name);
1866  ast_playtones_stop(chan);
1867  return -1;
1868  }
1869 
1870  if ((frame->frametype == AST_FRAME_CONTROL) &&
1872  (frame->datalen == sizeof(t38_parameters))) {
1873  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1874 
1875  switch (parameters->request_response) {
1877  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1878  * do T.38 as well
1879  */
1880  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1881  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1882  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1883  ast_playtones_stop(chan);
1884  break;
1885  case AST_T38_NEGOTIATED:
1886  ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
1887  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1888  details->caps &= ~AST_FAX_TECH_AUDIO;
1889  report_fax_status(chan, details, "T.38 Negotiated");
1890  break_loop = 1;
1891  break;
1892  default:
1893  break;
1894  }
1895  }
1896  ast_frfree(frame);
1897  if (break_loop) {
1898  break;
1899  }
1900  }
1901 
1902  ast_playtones_stop(chan);
1903 
1905  return 0;
1906  }
1907 
1908  /* T.38 negotiation did not happen, initiate a switch if requested */
1909  if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
1910  ast_debug(1, "Negotiating T.38 for send on %s\n", chan->name);
1911 
1912  /* wait up to five seconds for negotiation to complete */
1913  timeout_ms = 5000;
1914 
1915  /* set parameters based on the session's parameters */
1916  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1918  if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1919  return -1;
1920  }
1921 
1922  start = ast_tvnow();
1923  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1924  int break_loop = 0;
1925 
1926  ms = ast_waitfor(chan, ms);
1927  if (ms < 0) {
1928  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1929  return -1;
1930  }
1931  if (ms == 0) { /* all done, nothing happened */
1932  ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
1933  details->caps &= ~AST_FAX_TECH_T38;
1934  break;
1935  }
1936 
1937  if (!(frame = ast_read(chan))) {
1938  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1939  return -1;
1940  }
1941 
1942  if ((frame->frametype == AST_FRAME_CONTROL) &&
1944  (frame->datalen == sizeof(t38_parameters))) {
1945  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1946 
1947  switch (parameters->request_response) {
1949  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1950  t38_parameters.request_response = AST_T38_NEGOTIATED;
1951  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1952  break;
1953  case AST_T38_NEGOTIATED:
1954  ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
1955  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1956  details->caps &= ~AST_FAX_TECH_AUDIO;
1957  report_fax_status(chan, details, "T.38 Negotiated");
1958  break_loop = 1;
1959  break;
1960  case AST_T38_REFUSED:
1961  ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
1962  details->caps &= ~AST_FAX_TECH_T38;
1963  break_loop = 1;
1964  break;
1965  default:
1966  ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
1967  details->caps &= ~AST_FAX_TECH_T38;
1968  break_loop = 1;
1969  break;
1970  }
1971  }
1972  ast_frfree(frame);
1973  if (break_loop) {
1974  break;
1975  }
1976  }
1977 
1978  /* if T.38 was negotiated, we are done initializing */
1980  return 0;
1981  }
1982 
1983  /* send one more CNG tone to get audio going again for some
1984  * carriers if we are going to fall back to audio mode */
1985  if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
1986  if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
1987  ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", chan->name);
1988  return -1;
1989  }
1990 
1991  timeout_ms = 3500;
1992  start = ast_tvnow();
1993  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1994  int break_loop = 0;
1995 
1996  ms = ast_waitfor(chan, ms);
1997  if (ms < 0) {
1998  ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", chan->name);
1999  ast_playtones_stop(chan);
2000  return -1;
2001  }
2002  if (ms == 0) { /* all done, nothing happened */
2003  break;
2004  }
2005 
2006  if (!(frame = ast_read(chan))) {
2007  ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", chan->name);
2008  ast_playtones_stop(chan);
2009  return -1;
2010  }
2011 
2012  if ((frame->frametype == AST_FRAME_CONTROL) &&
2014  (frame->datalen == sizeof(t38_parameters))) {
2015  struct ast_control_t38_parameters *parameters = frame->data.ptr;
2016 
2017  switch (parameters->request_response) {
2019  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2020  * do T.38 as well
2021  */
2022  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2023  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2024  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2025  ast_playtones_stop(chan);
2026  break;
2027  case AST_T38_NEGOTIATED:
2028  ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
2029  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2030  details->caps &= ~AST_FAX_TECH_AUDIO;
2031  report_fax_status(chan, details, "T.38 Negotiated");
2032  break_loop = 1;
2033  break;
2034  default:
2035  break;
2036  }
2037  }
2038  ast_frfree(frame);
2039  if (break_loop) {
2040  break;
2041  }
2042  }
2043 
2044  ast_playtones_stop(chan);
2045 
2046  /* if T.38 was negotiated, we are done initializing */
2048  return 0;
2049  }
2050  }
2051  }
2052 
2053  /* if we made it here, then T.38 failed, check the 'f' flag */
2054  if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
2055  ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name);
2056  return -1;
2057  }
2058 
2059  /* ok, audio fallback is allowed */
2060  details->caps |= AST_FAX_TECH_AUDIO;
2061 
2062  return 0;
2063 }
2064 
2065 
2066 /*! \brief initiate a send FAX session */
2067 static int sendfax_exec(struct ast_channel *chan, const char *data)
2068 {
2069  char *parse, *filenames, *c, modems[128] = "";
2070  int channel_alive, file_count;
2071  struct ast_fax_session_details *details;
2072  struct ast_fax_session *s;
2073  struct ast_fax_tech_token *token = NULL;
2074  struct ast_fax_document *doc;
2076  AST_APP_ARG(filenames);
2077  AST_APP_ARG(options);
2078  );
2079  struct ast_flags opts = { 0, };
2080  struct manager_event_info info;
2081 
2082  /* initialize output channel variables */
2083  pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2084  pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2085  pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2086  pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2087  pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2088 
2089  /* if we ran sendfax then we attempted to send a fax, even if we never
2090  * start a fax session */
2091  ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
2092 
2093  /* Get a requirement structure and set it. This structure is used
2094  * to tell the FAX technology module about the higher level FAX session */
2095  if (!(details = find_or_create_details(chan))) {
2096  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2097  pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2098  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2099  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2100  return -1;
2101  }
2102 
2103  ast_string_field_set(details, result, "FAILED");
2104  ast_string_field_set(details, resultstr, "error starting fax session");
2105  ast_string_field_set(details, error, "INIT_ERROR");
2106  set_channel_variables(chan, details);
2107 
2108  if (details->maxrate < details->minrate) {
2109  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2110  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2111  ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2112  set_channel_variables(chan, details);
2113  ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2114  ao2_ref(details, -1);
2115  return -1;
2116  }
2117 
2118  if (check_modem_rate(details->modems, details->minrate)) {
2119  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2120  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2121  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2122  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2123  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2124  set_channel_variables(chan, details);
2125  ao2_ref(details, -1);
2126  return -1;
2127  }
2128 
2129  if (check_modem_rate(details->modems, details->maxrate)) {
2130  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2131  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2132  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2133  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2134  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2135  set_channel_variables(chan, details);
2136  ao2_ref(details, -1);
2137  return -1;
2138  }
2139 
2140  if (ast_strlen_zero(data)) {
2141  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2142  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2143  ast_string_field_set(details, resultstr, "invalid arguments");
2144  set_channel_variables(chan, details);
2145  ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
2146  ao2_ref(details, -1);
2147  return -1;
2148  }
2149  parse = ast_strdupa(data);
2150  AST_STANDARD_APP_ARGS(args, parse);
2151 
2152 
2153  if (!ast_strlen_zero(args.options) &&
2154  ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2155  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2156  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2157  ast_string_field_set(details, resultstr, "invalid arguments");
2158  set_channel_variables(chan, details);
2159  ao2_ref(details, -1);
2160  return -1;
2161  }
2162  if (ast_strlen_zero(args.filenames)) {
2163  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2164  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2165  ast_string_field_set(details, resultstr, "invalid arguments");
2166  set_channel_variables(chan, details);
2167  ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
2168  ao2_ref(details, -1);
2169  return -1;
2170  }
2171 
2172  /* check for unsupported FAX application options */
2173  if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
2174  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2175  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2176  ast_string_field_set(details, resultstr, "invalid arguments");
2177  set_channel_variables(chan, details);
2178  ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
2179  ao2_ref(details, -1);
2180  return -1;
2181  }
2182 
2183  file_count = 0;
2184  filenames = args.filenames;
2185  while ((c = strsep(&filenames, "&"))) {
2186  if (access(c, (F_OK | R_OK)) < 0) {
2187  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2188  ast_string_field_set(details, error, "FILE_ERROR");
2189  ast_string_field_set(details, resultstr, "error reading file");
2190  set_channel_variables(chan, details);
2191  ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames);
2192  ao2_ref(details, -1);
2193  return -1;
2194  }
2195 
2196  if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
2197  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2198  ast_string_field_set(details, error, "MEMORY_ERROR");
2199  ast_string_field_set(details, resultstr, "error allocating memory");
2200  set_channel_variables(chan, details);
2201  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2202  ao2_ref(details, -1);
2203  return -1;
2204  }
2205 
2206  strcpy(doc->filename, c);
2207  AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2208  file_count++;
2209  }
2210 
2211  if (file_count > 1) {
2212  details->caps |= AST_FAX_TECH_MULTI_DOC;
2213  }
2214 
2215  ast_verb(3, "Channel '%s' sending FAX:\n", chan->name);
2216  AST_LIST_TRAVERSE(&details->documents, doc, next) {
2217  ast_verb(3, " %s\n", doc->filename);
2218  }
2219 
2220  details->caps = AST_FAX_TECH_SEND;
2221 
2222  /* check for debug */
2223  if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2224  details->option.debug = AST_FAX_OPTFLAG_TRUE;
2225  }
2226 
2227  /* check for request for status events */
2228  if (ast_test_flag(&opts, OPT_STATUS)) {
2230  }
2231 
2233  ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
2235  }
2236 
2237  if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
2239  }
2240 
2241  if (!(s = fax_session_reserve(details, &token))) {
2242  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2243  ast_string_field_set(details, resultstr, "error reserving fax session");
2244  set_channel_variables(chan, details);
2245  ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2246  ao2_ref(details, -1);
2247  return -1;
2248  }
2249 
2250  /* make sure the channel is up */
2251  if (chan->_state != AST_STATE_UP) {
2252  if (ast_answer(chan)) {
2253  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2254  ast_string_field_set(details, resultstr, "error answering channel");
2255  set_channel_variables(chan, details);
2256  ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
2257  fax_session_release(s, token);
2258  ao2_ref(s, -1);
2259  ao2_ref(details, -1);
2260  return -1;
2261  }
2262  }
2263 
2264  if (set_fax_t38_caps(chan, details)) {
2265  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2266  ast_string_field_set(details, error, "T38_NEG_ERROR");
2267  ast_string_field_set(details, resultstr, "error negotiating T.38");
2268  set_channel_variables(chan, details);
2269  fax_session_release(s, token);
2270  ao2_ref(s, -1);
2271  ao2_ref(details, -1);
2272  return -1;
2273  }
2274 
2275  if (details->caps & AST_FAX_TECH_T38) {
2276  if (sendfax_t38_init(chan, details)) {
2277  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2278  ast_string_field_set(details, error, "T38_NEG_ERROR");
2279  ast_string_field_set(details, resultstr, "error negotiating T.38");
2280  set_channel_variables(chan, details);
2281  fax_session_release(s, token);
2282  ao2_ref(s, -1);
2283  ao2_ref(details, -1);
2284  ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
2285  return -1;
2286  }
2287  } else {
2288  details->option.send_cng = 1;
2289  }
2290 
2291  if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2292  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2293  }
2294 
2296  if (disable_t38(chan)) {
2297  ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
2298  }
2299  }
2300 
2301  if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
2302  ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
2303  ao2_ref(s, -1);
2304  ao2_ref(details, -1);
2305  return (!channel_alive) ? -1 : 0;
2306  }
2307 
2308  /* send out the AMI completion event */
2309  ast_channel_lock(chan);
2310  get_manager_event_info(chan, &info);
2312  "SendFAX",
2313  "Channel: %s\r\n"
2314  "Context: %s\r\n"
2315  "Exten: %s\r\n"
2316  "CallerID: %s\r\n"
2317  "RemoteStationID: %s\r\n"
2318  "LocalStationID: %s\r\n"
2319  "PagesTransferred: %s\r\n"
2320  "Resolution: %s\r\n"
2321  "TransferRate: %s\r\n"
2322  "%s\r\n",
2323  chan->name,
2324  info.context,
2325  info.exten,
2326  info.cid,
2327  S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
2328  S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
2329  S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
2330  S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
2331  S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
2332  filenames);
2333  ast_channel_unlock(chan);
2334 
2335  ast_free(filenames);
2336 
2337  ao2_ref(s, -1);
2338  ao2_ref(details, -1);
2339 
2340  /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2341  return (!channel_alive) ? -1 : 0;
2342 }
2343 
2344 /*! \brief hash callback for ao2 */
2345 static int session_hash_cb(const void *obj, const int flags)
2346 {
2347  const struct ast_fax_session *s = obj;
2348 
2349  return s->id;
2350 }
2351 
2352 /*! \brief compare callback for ao2 */
2353 static int session_cmp_cb(void *obj, void *arg, int flags)
2354 {
2355  struct ast_fax_session *lhs = obj, *rhs = arg;
2356 
2357  return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
2358 }
2359 
2360 /*! \brief fax session tab completion */
2362 {
2363  int tklen;
2364  int wordnum = 0;
2365  char *name = NULL;
2366  struct ao2_iterator i;
2367  struct ast_fax_session *s;
2368  char tbuf[5];
2369 
2370  if (a->pos != 3) {
2371  return NULL;
2372  }
2373 
2374  tklen = strlen(a->word);
2375  i = ao2_iterator_init(faxregistry.container, 0);
2376  while ((s = ao2_iterator_next(&i))) {
2377  snprintf(tbuf, sizeof(tbuf), "%u", s->id);
2378  if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
2379  name = ast_strdup(tbuf);
2380  ao2_ref(s, -1);
2381  break;
2382  }
2383  ao2_ref(s, -1);
2384  }
2386  return name;
2387 }
2388 
2389 static char *cli_fax_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2390 {
2391  struct fax_module *fax;
2392 
2393  switch(cmd) {
2394  case CLI_INIT:
2395  e->command = "fax show version";
2396  e->usage =
2397  "Usage: fax show version\n"
2398  " Show versions of FAX For Asterisk components.\n";
2399  return NULL;
2400  case CLI_GENERATE:
2401  return NULL;
2402  }
2403 
2404  if (a->argc != 3) {
2405  return CLI_SHOWUSAGE;
2406  }
2407 
2408  ast_cli(a->fd, "FAX For Asterisk Components:\n");
2409  ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
2410  AST_RWLIST_RDLOCK(&faxmodules);
2411  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2412  ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
2413  }
2414  AST_RWLIST_UNLOCK(&faxmodules);
2415  ast_cli(a->fd, "\n");
2416 
2417  return CLI_SUCCESS;
2418 }
2419 
2420 /*! \brief enable FAX debugging */
2421 static char *cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2422 {
2423  int flag;
2424  const char *what;
2425 
2426  switch (cmd) {
2427  case CLI_INIT:
2428  e->command = "fax set debug {on|off}";
2429  e->usage =
2430  "Usage: fax set debug { on | off }\n"
2431  " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n"
2432  " additional events sent to manager sessions with 'call' class permissions. When\n"
2433  " verbosity is greater than '5' events will be displayed to the console and audio versus\n"
2434  " energy analysis will be performed and displayed to the console.\n";
2435  return NULL;
2436  case CLI_GENERATE:
2437  return NULL;
2438  }
2439 
2440  what = a->argv[e->args-1]; /* guaranteed to exist */
2441  if (!strcasecmp(what, "on")) {
2442  flag = 1;
2443  } else if (!strcasecmp(what, "off")) {
2444  flag = 0;
2445  } else {
2446  return CLI_SHOWUSAGE;
2447  }
2448 
2449  global_fax_debug = flag;
2450  ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
2451 
2452  return CLI_SUCCESS;
2453 }
2454 
2455 /*! \brief display registered FAX capabilities */
2456 static char *cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2457 {
2458  struct fax_module *fax;
2459  unsigned int num_modules = 0;
2460 
2461  switch (cmd) {
2462  case CLI_INIT:
2463  e->command = "fax show capabilities";
2464  e->usage =
2465  "Usage: fax show capabilities\n"
2466  " Shows the capabilities of the registered FAX technology modules\n";
2467  return NULL;
2468  case CLI_GENERATE:
2469  return NULL;
2470  }
2471 
2472  ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
2473  AST_RWLIST_RDLOCK(&faxmodules);
2474  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2475  ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
2476  fax->tech->cli_show_capabilities(a->fd);
2477  num_modules++;
2478  }
2479  AST_RWLIST_UNLOCK(&faxmodules);
2480  ast_cli(a->fd, "%u registered modules\n\n", num_modules);
2481 
2482  return CLI_SUCCESS;
2483 }
2484 
2485 /*! \brief display global defaults and settings */
2486 static char *cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2487 {
2488  struct fax_module *fax;
2489  char modems[128] = "";
2490  struct fax_options options;
2491 
2492  switch (cmd) {
2493  case CLI_INIT:
2494  e->command = "fax show settings";
2495  e->usage =
2496  "Usage: fax show settings\n"
2497  " Show the global settings and defaults of both the FAX core and technology modules\n";
2498  return NULL;
2499  case CLI_GENERATE:
2500  return NULL;
2501  }
2502 
2503  get_general_options(&options);
2504 
2505  ast_cli(a->fd, "FAX For Asterisk Settings:\n");
2506  ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
2507  ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off");
2508  ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate);
2509  ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate);
2510  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
2511  ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
2512  ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
2513  AST_RWLIST_RDLOCK(&faxmodules);
2514  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2515  ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
2516  fax->tech->cli_show_settings(a->fd);
2517  }
2518  AST_RWLIST_UNLOCK(&faxmodules);
2519 
2520  return CLI_SUCCESS;
2521 }
2522 
2523 /*! \brief display details of a specified fax session */
2524 static char *cli_fax_show_session(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2525 {
2526  struct ast_fax_session *s, tmp;
2527 
2528  switch (cmd) {
2529  case CLI_INIT:
2530  e->command = "fax show session";
2531  e->usage =
2532  "Usage: fax show session <session number>\n"
2533  " Shows status of the named FAX session\n";
2534  return NULL;
2535  case CLI_GENERATE:
2536  return fax_session_tab_complete(a);
2537  }
2538 
2539  if (a->argc != 4) {
2540  return CLI_SHOWUSAGE;
2541  }
2542 
2543  if (sscanf(a->argv[3], "%u", &tmp.id) != 1) {
2544  ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
2545  return RESULT_SUCCESS;
2546  }
2547 
2548  ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
2549  s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
2550  if (s) {
2551  s->tech->cli_show_session(s, a->fd);
2552  ao2_ref(s, -1);
2553  }
2554  ast_cli(a->fd, "\n\n");
2555 
2556  return CLI_SUCCESS;
2557 }
2558 
2559 /*! \brief display fax stats */
2560 static char *cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2561 {
2562  struct fax_module *fax;
2563 
2564  switch (cmd) {
2565  case CLI_INIT:
2566  e->command = "fax show stats";
2567  e->usage =
2568  "Usage: fax show stats\n"
2569  " Shows a statistical summary of FAX transmissions\n";
2570  return NULL;
2571  case CLI_GENERATE:
2572  return NULL;
2573  }
2574 
2575  ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
2576  ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
2577  ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
2578  ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
2579  ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
2580  ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
2581  ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
2582  AST_RWLIST_RDLOCK(&faxmodules);
2583  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2584  fax->tech->cli_show_stats(a->fd);
2585  }
2586  AST_RWLIST_UNLOCK(&faxmodules);
2587  ast_cli(a->fd, "\n\n");
2588 
2589  return CLI_SUCCESS;
2590 }
2591 
2592 /*! \brief display fax sessions */
2593 static char *cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2594 {
2595  struct ast_fax_session *s;
2596  struct ao2_iterator i;
2597  int session_count;
2598  char *filenames;
2599 
2600  switch (cmd) {
2601  case CLI_INIT:
2602  e->command = "fax show sessions";
2603  e->usage =
2604  "Usage: fax show sessions\n"
2605  " Shows the current FAX sessions\n";
2606  return NULL;
2607  case CLI_GENERATE:
2608  return NULL;
2609  }
2610 
2611  ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
2612  ast_cli(a->fd, "%-20.20s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
2613  "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
2614  i = ao2_iterator_init(faxregistry.container, 0);
2615  while ((s = ao2_iterator_next(&i))) {
2616  ao2_lock(s);
2617 
2618  if (!(filenames = generate_filenames_string(s->details, "", ", "))) {
2619  ast_log(LOG_ERROR, "Error printing filenames for 'fax show sessions' command\n");
2620  ao2_unlock(s);
2621  ao2_ref(s, -1);
2623  return CLI_FAILURE;
2624  }
2625 
2626  ast_cli(a->fd, "%-20.20s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
2627  s->channame, s->tech->type, s->id,
2628  (s->details->caps & AST_FAX_TECH_AUDIO) ? "G.711" : "T.38",
2629  (s->details->caps & AST_FAX_TECH_SEND) ? "send" : "receive",
2630  ast_fax_state_to_str(s->state), filenames);
2631 
2632  ast_free(filenames);
2633  ao2_unlock(s);
2634  ao2_ref(s, -1);
2635  }
2637  session_count = ao2_container_count(faxregistry.container);
2638  ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
2639 
2640  return CLI_SUCCESS;
2641 }
2642 
2643 static struct ast_cli_entry fax_cli[] = {
2644  AST_CLI_DEFINE(cli_fax_show_version, "Show versions of FAX For Asterisk components"),
2645  AST_CLI_DEFINE(cli_fax_set_debug, "Enable/Disable FAX debugging on new FAX sessions"),
2646  AST_CLI_DEFINE(cli_fax_show_capabilities, "Show the capabilities of the registered FAX technology modules"),
2647  AST_CLI_DEFINE(cli_fax_show_settings, "Show the global settings and defaults of both the FAX core and technology modules"),
2648  AST_CLI_DEFINE(cli_fax_show_session, "Show the status of the named FAX sessions"),
2649  AST_CLI_DEFINE(cli_fax_show_sessions, "Show the current FAX sessions"),
2650  AST_CLI_DEFINE(cli_fax_show_stats, "Summarize FAX session history"),
2651 };
2652 
2653 static void set_general_options(const struct fax_options *options)
2654 {
2656  general_options = *options;
2658 }
2659 
2660 static void get_general_options(struct fax_options *options)
2661 {
2663  *options = general_options;
2665 }
2666 
2667 /*! \brief configure res_fax */
2668 static int set_config(int reload)
2669 {
2670  struct ast_config *cfg;
2671  struct ast_variable *v;
2672  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2673  char modems[128] = "";
2674  struct fax_options options;
2675  int res = 0;
2676 
2677  options = default_options;
2678 
2679  /* When we're not reloading, we have to be certain to set the general options
2680  * to the defaults in case config loading goes wrong at some point. On a reload,
2681  * the general options need to stay the same as what they were prior to the
2682  * reload rather than being reset to the defaults.
2683  */
2684  if (!reload) {
2685  set_general_options(&options);
2686  }
2687 
2688  /* read configuration */
2689  if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
2690  ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
2691  config, reload ? "not changing" : "using default");
2692  return 0;
2693  }
2694 
2695  if (cfg == CONFIG_STATUS_FILEINVALID) {
2696  ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
2697  config, reload ? "not changing" : "using default");
2698  return 0;
2699  }
2700 
2701  if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2702  return 0;
2703  }
2704 
2705  if (reload) {
2706  options = default_options;
2707  }
2708 
2709  /* create configuration */
2710  for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
2711  int rate;
2712 
2713  if (!strcasecmp(v->name, "minrate")) {
2714  ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
2715  if ((rate = fax_rate_str_to_int(v->value)) == 0) {
2716  res = -1;
2717  goto end;
2718  }
2719  options.minrate = rate;
2720  } else if (!strcasecmp(v->name, "maxrate")) {
2721  ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
2722  if ((rate = fax_rate_str_to_int(v->value)) == 0) {
2723  res = -1;
2724  goto end;
2725  }
2726  options.maxrate = rate;
2727  } else if (!strcasecmp(v->name, "statusevents")) {
2728  ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
2729  options.statusevents = ast_true(v->value);
2730  } else if (!strcasecmp(v->name, "ecm")) {
2731  ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
2732  options.ecm = ast_true(v->value);
2733  } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
2734  options.modems = 0;
2735  update_modem_bits(&options.modems, v->value);
2736  }
2737  }
2738 
2739  if (options.maxrate < options.minrate) {
2740  ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
2741  res = -1;
2742  goto end;
2743  }
2744 
2745  if (options.minrate == 2400 && (options.modems & AST_FAX_MODEM_V27) && !(options.modems & (AST_FAX_MODEM_V34))) {
2746  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
2747  ast_log(LOG_WARNING, "'modems' setting '%s' is no longer accepted with 'minrate' setting %u\n", modems, options.minrate);
2748  ast_log(LOG_WARNING, "'minrate' has been reset to 4800, please update res_fax.conf.\n");
2749  options.minrate = 4800;
2750  }
2751 
2752  if (check_modem_rate(options.modems, options.minrate)) {
2753  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
2754  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
2755  res = -1;
2756  goto end;
2757  }
2758 
2759  if (check_modem_rate(options.modems, options.maxrate)) {
2760  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
2761  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
2762  res = -1;
2763  goto end;
2764  }
2765 
2766  set_general_options(&options);
2767 
2768 end:
2769  ast_config_destroy(cfg);
2770  return res;
2771 }
2772 
2773 /*! \brief FAXOPT read function returns the contents of a FAX option */
2774 static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2775 {
2776  struct ast_fax_session_details *details = find_details(chan);
2777  int res = 0;
2778  char *filenames;
2779 
2780  if (!details) {
2781  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
2782  return -1;
2783  }
2784  if (!strcasecmp(data, "ecm")) {
2785  ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
2786  } else if (!strcasecmp(data, "error")) {
2787  ast_copy_string(buf, details->error, len);
2788  } else if (!strcasecmp(data, "filename")) {
2789  if (AST_LIST_EMPTY(&details->documents)) {
2790  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
2791  res = -1;
2792  } else {
2793  ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
2794  }
2795  } else if (!strcasecmp(data, "filenames")) {
2796  if (AST_LIST_EMPTY(&details->documents)) {
2797  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
2798  res = -1;
2799  } else if ((filenames = generate_filenames_string(details, "", ","))) {
2800  ast_copy_string(buf, filenames, len);
2801  ast_free(filenames);
2802  } else {
2803  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", chan->name, data);
2804  res = -1;
2805  }
2806  } else if (!strcasecmp(data, "headerinfo")) {
2807  ast_copy_string(buf, details->headerinfo, len);
2808  } else if (!strcasecmp(data, "localstationid")) {
2809  ast_copy_string(buf, details->localstationid, len);
2810  } else if (!strcasecmp(data, "maxrate")) {
2811  snprintf(buf, len, "%u", details->maxrate);
2812  } else if (!strcasecmp(data, "minrate")) {
2813  snprintf(buf, len, "%u", details->minrate);
2814  } else if (!strcasecmp(data, "pages")) {
2815  snprintf(buf, len, "%u", details->pages_transferred);
2816  } else if (!strcasecmp(data, "rate")) {
2817  ast_copy_string(buf, details->transfer_rate, len);
2818  } else if (!strcasecmp(data, "remotestationid")) {
2819  ast_copy_string(buf, details->remotestationid, len);
2820  } else if (!strcasecmp(data, "resolution")) {
2821  ast_copy_string(buf, details->resolution, len);
2822  } else if (!strcasecmp(data, "sessionid")) {
2823  snprintf(buf, len, "%u", details->id);
2824  } else if (!strcasecmp(data, "status")) {
2825  ast_copy_string(buf, details->result, len);
2826  } else if (!strcasecmp(data, "statusstr")) {
2827  ast_copy_string(buf, details->resultstr, len);
2828  } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
2829  ast_fax_modem_to_str(details->modems, buf, len);
2830  } else {
2831  ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", chan->name, data);
2832  res = -1;
2833  }
2834  ao2_ref(details, -1);
2835 
2836  return res;
2837 }
2838 
2839 /*! \brief FAXOPT write function modifies the contents of a FAX option */
2840 static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
2841 {
2842  int res = 0;
2843  struct ast_fax_session_details *details;
2844 
2845  if (!(details = find_or_create_details(chan))) {
2846  ast_log(LOG_WARNING, "channel '%s' can't set FAXOPT(%s) to '%s' because it failed to create a datastore.\n", chan->name, data, value);
2847  return -1;
2848  }
2849  ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", chan->name, data, value);
2850 
2851  if (!strcasecmp(data, "ecm")) {
2852  const char *val = ast_skip_blanks(value);
2853  if (ast_true(val)) {
2854  details->option.ecm = AST_FAX_OPTFLAG_TRUE;
2855  } else if (ast_false(val)) {
2856  details->option.ecm = AST_FAX_OPTFLAG_FALSE;
2857  } else {
2858  ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
2859  }
2860  } else if (!strcasecmp(data, "headerinfo")) {
2861  ast_string_field_set(details, headerinfo, value);
2862  } else if (!strcasecmp(data, "localstationid")) {
2863  ast_string_field_set(details, localstationid, value);
2864  } else if (!strcasecmp(data, "maxrate")) {
2865  details->maxrate = fax_rate_str_to_int(value);
2866  if (!details->maxrate) {
2867  details->maxrate = ast_fax_maxrate();
2868  }
2869  } else if (!strcasecmp(data, "minrate")) {
2870  details->minrate = fax_rate_str_to_int(value);
2871  if (!details->minrate) {
2872  details->minrate = ast_fax_minrate();
2873  }
2874  } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
2875  update_modem_bits(&details->modems, value);
2876  } else {
2877  ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", chan->name, data, value);
2878  res = -1;
2879  }
2880 
2881  ao2_ref(details, -1);
2882 
2883  return res;
2884 }
2885 
2886 /*! \brief FAXOPT dialplan function */
2888  .name = "FAXOPT",
2889  .read = acf_faxopt_read,
2890  .write = acf_faxopt_write,
2891 };
2892 
2893 /*! \brief unload res_fax */
2894 static int unload_module(void)
2895 {
2897 
2899  ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
2900  }
2901 
2902  if (ast_unregister_application(app_sendfax) < 0) {
2903  ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
2904  }
2905 
2906  if (ast_unregister_application(app_receivefax) < 0) {
2907  ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
2908  }
2909 
2910  if (fax_logger_level != -1) {
2912  }
2913 
2914  ao2_ref(faxregistry.container, -1);
2915 
2916  return 0;
2917 }
2918 
2919 /*! \brief load res_fax */
2920 static int load_module(void)
2921 {
2922  int res;
2923 
2924  /* initialize the registry */
2925  faxregistry.active_sessions = 0;
2926  faxregistry.reserved_sessions = 0;
2928  return AST_MODULE_LOAD_DECLINE;
2929  }
2930 
2931  if (set_config(0) < 0) {
2932  ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
2933  ao2_ref(faxregistry.container, -1);
2934  return AST_MODULE_LOAD_DECLINE;
2935  }
2936 
2937  /* register CLI operations and applications */
2938  if (ast_register_application_xml(app_sendfax, sendfax_exec) < 0) {
2939  ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
2940  ao2_ref(faxregistry.container, -1);
2941  return AST_MODULE_LOAD_DECLINE;
2942  }
2943  if (ast_register_application_xml(app_receivefax, receivefax_exec) < 0) {
2944  ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
2945  ast_unregister_application(app_sendfax);
2946  ao2_ref(faxregistry.container, -1);
2947  return AST_MODULE_LOAD_DECLINE;
2948  }
2951  fax_logger_level = ast_logger_register_level("FAX");
2952 
2953  return res;
2954 }
2955 
2956 static int reload_module(void)
2957 {
2958  set_config(1);
2959  return 0;
2960 }
2961 
2962 
2964  .load = load_module,
2965  .unload = unload_module,
2966  .reload = reload_module,
2967  .load_pri = AST_MODPRI_APP_DEPEND,
2968  );
#define RES_FAX_MINRATE
Definition: res_fax.c:247
static int receivefax_exec(struct ast_channel *chan, const char *data)
initiate a receive FAX session
Definition: res_fax.c:1579
const char * type
Definition: datastore.h:32
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: pbx.c:4676
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2417
const ast_string_field result
Definition: res_fax.h:137
struct ast_fax_tech * tech
Definition: res_fax.c:242
int fax_complete
Definition: res_fax.c:233
union ast_frame_subclass subclass
Definition: frame.h:146
#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason)
Definition: res_fax.c:1031
Tone Indication Support.
#define ast_rwlock_rdlock(a)
Definition: lock.h:201
struct ast_smoother * ast_smoother_new(int bytes)
Definition: frame.c:183
#define ast_channel_lock(chan)
Definition: channel.h:2466
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
Main Channel structure associated with a channel.
Definition: channel.h:742
static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1417
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
static struct ast_control_t38_parameters our_t38_parameters
Definition: res_fax.c:1154
void ast_smoother_free(struct ast_smoother *s)
Definition: frame.c:294
int fax_tx_attempts
Definition: res_fax.c:229
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
int active_sessions
Definition: res_fax.c:223
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
void ast_fax_tech_unregister(struct ast_fax_tech *tech)
unregister a fax technology
Definition: res_fax.c:635
#define AST_RWLOCK_DEFINE_STATIC(rwlock)
Definition: lock.h:549
static void destroy_session_details(void *details)
destroy a FAX session details structure
Definition: res_fax.c:371
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
Definition: app.h:712
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
uint32_t ecm
Definition: res_fax.c:255
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
#define RES_FAX_MAXRATE
Definition: res_fax.c:248
char * strsep(char **str, const char *delims)
int(*const start_session)(struct ast_fax_session *)
Definition: res_fax.h:232
int(*const switch_to_t38)(struct ast_fax_session *)
Definition: res_fax.h:238
unsigned int consec_frames
Definition: res_fax.c:202
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
unsigned int version
Definition: frame.h:413
const ast_string_field uniqueid
Definition: channel.h:787
String manipulation functions.
unsigned long frames_sent
Definition: res_fax.h:188
int fax_rx_attempts
Definition: res_fax.c:231
const ast_string_field headerinfo
Definition: res_fax.h:137
#define ast_strdup(a)
Definition: astmm.h:109
Definition: ast_expr2.c:325
format_t writeformat
Definition: channel.h:854
unsigned long frames_received
Definition: res_fax.h:186
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Definition: res_fax.c:690
Asterisk version information.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
char cid[128]
Definition: res_fax.c:300
static struct fax_options default_options
Definition: res_fax.c:262
unsigned int id
Definition: res_fax.h:180
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: frame.c:244
#define ast_test_flag(p, flag)
Definition: utils.h:63
void(*const release_token)(struct ast_fax_tech_token *)
Definition: res_fax.h:222
static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
Definition: res_fax.c:908
static const char app_sendfax[]
Definition: res_fax.c:199
static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
this is the generic FAX session handling function
Definition: res_fax.c:1162
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1650
void * ptr
Definition: frame.h:160
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Definition: version.c:14
Convenient Signal Processing routines.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
int(*const cancel_session)(struct ast_fax_session *)
Definition: res_fax.h:234
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
enum ast_fax_modems modems
Definition: res_fax.c:253
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
static ast_rwlock_t options_lock
Definition: res_fax.c:270
static char * ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
Definition: res_fax.c:494
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
struct ast_dsp * ast_dsp_new(void)
Definition: dsp.c:1607
const char *const type
Definition: res_fax.h:210
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static void destroy_session(void *session)
destroy a FAX session structure
Definition: res_fax.c:727
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
const ast_string_field transfer_rate
Definition: res_fax.h:137
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:1037
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:1048
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct ast_smoother * smoother
Definition: res_fax.h:204
enum ast_control_t38 request_response
Definition: frame.h:412
#define EVENT_FLAG_CALL
Definition: manager.h:72
Definition: cli.h:146
#define AST_MODEM_T38
Definition: frame.h:216
static int session_hash_cb(const void *obj, const int flags)
hash callback for ao2
Definition: res_fax.c:2345
Structure for a data store type.
Definition: datastore.h:31
Configuration File Parser.
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4447
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
enum ast_control_t38_rate rate
Definition: res_fax.h:90
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
static int session_cmp_cb(void *obj, void *arg, int flags)
compare callback for ao2
Definition: res_fax.c:2353
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
#define END_OPTIONS
Definition: app.h:663
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
const char *const description
Definition: res_fax.h:212
unsigned int maxrate
Definition: res_fax.c:257
format_t codec
Definition: frame.h:137
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:411
static struct ast_fax_session_details * session_details_new(void)
create a FAX session details structure
Definition: res_fax.c:383
unsigned int minrate
Definition: res_fax.c:256
char context[AST_MAX_CONTEXT]
Definition: res_fax.c:298
struct ast_channel * chan
Definition: res_fax.h:200
int value
Definition: syslog.c:39
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define ast_rwlock_unlock(a)
Definition: lock.h:200
void *(*const new_session)(struct ast_fax_session *, struct ast_fax_tech_token *)
Definition: res_fax.h:224
struct ao2_container * container
The asterisk data main content structure.
Definition: data.c:177
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: config.c:2499
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:3188
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
Utility functions.
int args
This gets set in ast_cli_register()
Definition: cli.h:179
static int load_module(void)
load res_fax
Definition: res_fax.c:2920
unsigned int id
Definition: res_fax.h:112
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
static char * cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display fax sessions
Definition: res_fax.c:2593
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:1670
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:202
char exten[AST_MAX_EXTENSION]
Definition: res_fax.c:299
struct ast_fax_tech_token *(*const reserve_session)(struct ast_fax_session *)
Definition: res_fax.h:220
static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
Definition: res_fax.c:460
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
FAXOPT write function modifies the contents of a FAX option.
Definition: res_fax.c:2840
#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason)
Definition: res_fax.c:1015
unsigned int transcoding_mmr
Definition: frame.h:418
const char * value
Definition: config.h:79
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:168
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: utils.c:1521
struct ast_module * self
Definition: module.h:227
static char * cli_fax_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_fax.c:2389
General Asterisk PBX channel definitions.
static char * cli_fax_show_session(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display details of a specified fax session
Definition: res_fax.c:2524
enum ast_fax_capabilities caps
Definition: res_fax.h:216
char *(*const cli_show_session)(struct ast_fax_session *, int)
Definition: res_fax.h:242
static int disable_t38(struct ast_channel *chan)
Definition: res_fax.c:1092
const int fd
Definition: cli.h:153
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
Definition: dsp.c:390
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const int n
Definition: cli.h:159
Data structure associated with a custom dialplan function.
Definition: pbx.h:95
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition: res_fax.c:572
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
int datalen
Definition: frame.h:148
static const char app_receivefax[]
Definition: res_fax.c:198
#define ao2_ref(o, delta)
Definition: astobj2.h:472
struct ast_fax_session_details * details
Definition: res_fax.h:184
enum ast_control_t38_rate rate
Definition: frame.h:415
char filename[0]
Definition: res_fax.h:99
#define ao2_lock(a)
Definition: astobj2.h:488
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:565
static struct ast_fax_session * fax_session_new(struct ast_fax_session_details *details, struct ast_channel *chan, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
create a FAX session
Definition: res_fax.c:810
const char * name
Definition: config.h:77
char * channame
Definition: res_fax.h:196
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:105
static int sendfax_exec(struct ast_channel *chan, const char *data)
initiate a send FAX session
Definition: res_fax.c:2067
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct ast_module * module
Definition: res_fax.h:218
uint32_t statusevents
Definition: res_fax.c:254
const ast_string_field remotestationid
Definition: res_fax.h:137
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:1627
Core PBX routines and definitions.
unsigned int ast_fax_minrate(void)
get the minimum supported fax rate
Definition: res_fax.c:452
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
unsigned int max_ifp
Definition: frame.h:414
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set threshold value for silence.
Definition: dsp.c:1655
const char *const * argv
Definition: cli.h:155
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
Definition: dsp.c:1725
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static int reload(void)
Definition: app_amd.c:497
unsigned int transcoding_mmr
Definition: res_fax.h:93
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
unsigned int transcoding_jbig
Definition: res_fax.h:94
static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1059
ast_fax_modems
fax modem capabilities
Definition: res_fax.h:48
char *(*const cli_show_settings)(int)
Definition: res_fax.h:246
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
void(*const destroy_session)(struct ast_fax_session *)
Definition: res_fax.h:226
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
union ast_fax_session_details::@203 option
unsigned int pages_transferred
Definition: res_fax.h:139
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Definition: res_fax.c:714
unsigned int ast_fax_maxrate(void)
get the maxiumum supported fax rate
Definition: res_fax.c:444
static struct @350 args
#define CLI_SHOWUSAGE
Definition: cli.h:44
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:1615
unsigned int fill_bit_removal
Definition: frame.h:417
unsigned int max_ifp
Definition: res_fax.h:89
static struct ast_datastore_info fax_datastore
Definition: res_fax.c:343
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1000
struct ast_fax_documents documents
Definition: res_fax.h:114
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
used to register a FAX technology module with res_fax
Definition: res_fax.h:208
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:97
struct sla_ringing_trunk * first
Definition: app_meetme.c:965
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define LOG_NOTICE
Definition: logger.h:133
#define FAX_MAXBUCKETS
maximum buckets for res_fax ao2 containers
Definition: res_fax.c:216
unsigned int minrate
Definition: res_fax.h:164
struct ast_fax_tech * tech
Definition: res_fax.h:190
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
int reserved_sessions
Definition: res_fax.c:225
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define CLI_FAILURE
Definition: cli.h:45
int errno
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static const char name[]
#define AST_MAX_CONTEXT
Definition: channel.h:136
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
const char *const version
Definition: res_fax.h:214
char *(*const cli_show_capabilities)(int)
Definition: res_fax.h:240
#define RES_FAX_STATUSEVENTS
Definition: res_fax.c:249
static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
FAXOPT read function returns the contents of a FAX option.
Definition: res_fax.c:2774
static int reload_module(void)
Definition: res_fax.c:2956
static char * cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
enable FAX debugging
Definition: res_fax.c:2421
ast_fax_capabilities
capabilities for res_fax to locate a fax technology module
Definition: res_fax.h:34
ast_fax_state
current state of a fax session
Definition: res_fax.h:60
static struct ast_format f[]
Definition: format_g726.c:181
enum ast_fax_modems modems
Definition: res_fax.h:110
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
const char * word
Definition: cli.h:157
enum ast_fax_state state
Definition: res_fax.h:194
unsigned int consec_ms
Definition: res_fax.c:203
void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
Log message at FAX or recommended level.
Definition: res_fax.c:680
static int fax_logger_level
Definition: res_fax.c:213
static int unload_module(void)
unload res_fax
Definition: res_fax.c:2894
static int global_fax_debug
Definition: res_fax.c:277
static int session_count
Definition: http.c:75
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int(*const write)(struct ast_fax_session *, const struct ast_frame *)
Definition: res_fax.h:230
Structure used to handle boolean flags.
Definition: utils.h:200
static const char * config
Definition: res_fax.c:275
Support for logging to various files, console and syslog Configuration in file logger.conf.
static void destroy_callback(void *data)
Definition: res_fax.c:336
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:414
struct ast_dsp * dsp
Definition: res_fax.c:210
const char * usage
Definition: cli.h:171
unsigned int transcoding_jbig
Definition: frame.h:419
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
char *(*const cli_show_stats)(int)
Definition: res_fax.h:244
#define ast_rwlock_wrlock(a)
Definition: lock.h:202
unsigned int version
Definition: res_fax.h:88
static struct ast_app_option fax_exec_options[128]
Definition: res_fax.c:295
static struct ast_fax_session * fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
Definition: res_fax.c:760
#define CLI_SUCCESS
Definition: cli.h:43
registered FAX technology modules are put into this list
Definition: res_fax.c:241
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Return non-zero if this is silence. Updates &quot;totalsilence&quot; with the total number of seconds of silenc...
Definition: dsp.c:1355
void * data
Definition: datastore.h:56
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:666
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
static int set_config(int reload)
configure res_fax
Definition: res_fax.c:2668
static int chancount
Definition: channel.c:102
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
Standard Command Line Interface.
format_t readformat
Definition: channel.h:853
#define ast_calloc(a, b)
Definition: astmm.h:82
struct ast_fax_document * next
Definition: res_fax.h:98
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
static struct ast_fax_session_details * find_details(struct ast_channel *chan)
returns a reference counted pointer to a fax datastore, if it exists
Definition: res_fax.c:349
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is &quot;false&quot;...
Definition: utils.c:1550
static void set_general_options(const struct fax_options *options)
Definition: res_fax.c:2653
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
const int pos
Definition: cli.h:158
static struct fax_options general_options
Definition: res_fax.c:260
static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
send a FAX status manager event
Definition: res_fax.c:964
int fax_failures
Definition: res_fax.c:235
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
enum ast_control_t38_rate_management rate_management
Definition: frame.h:416
The data required to handle a fax session.
Definition: res_fax.h:178
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static char * fax_session_tab_complete(struct ast_cli_args *a)
fax session tab completion
Definition: res_fax.c:2361
struct timeval base_tv
Definition: res_fax.c:208
static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
Definition: res_fax.c:303
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert an ast_fax_state to a string
Definition: res_fax.c:657
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_control_t38_rate_management rate_management
Definition: res_fax.h:91
static char * cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display global defaults and settings
Definition: res_fax.c:2486
enum ast_fax_capabilities caps
Definition: res_fax.h:108
char * chan_uniqueid
Definition: res_fax.h:198
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:319
void * tech_pvt
Definition: res_fax.h:192
Options provided by main asterisk program.
const char * name
Definition: pbx.h:96
#define RES_FAX_TIMEOUT
Definition: res_fax.c:218
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: utils.c:1601
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:539
const ast_string_field resultstr
Definition: res_fax.h:137
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
enum ast_frame_type frametype
Definition: frame.h:144
struct ast_variable * next
Definition: config.h:82
struct ast_frame *(*const read)(struct ast_fax_session *)
Definition: res_fax.h:228
const ast_string_field localstationid
Definition: res_fax.h:137
unsigned int maxrate
Definition: res_fax.h:166
unsigned char silence
Definition: res_fax.c:204
static char * cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display fax stats
Definition: res_fax.c:2560
#define ast_frfree(fr)
Definition: frame.h:583
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
const ast_string_field error
Definition: res_fax.h:137
int nextsessionname
Definition: res_fax.c:237
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
#define RESULT_SUCCESS
Definition: cli.h:39
static struct ast_cli_entry fax_cli[]
Definition: res_fax.c:2643
#define ast_malloc(a)
Definition: astmm.h:91
Asterisk module definitions.
struct debug_info_history c2s s2c
Definition: res_fax.c:209
unsigned int fill_bit_removal
Definition: res_fax.h:92
static char * cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display registered FAX capabilities
Definition: res_fax.c:2456
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:170
#define RES_FAX_MODEM
Definition: res_fax.c:250
union ast_frame::@172 data
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:417
static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1823
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
#define ao2_unlink(arg1, arg2)
Definition: astobj2.h:817
const ast_string_field resolution
Definition: res_fax.h:137
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
int(*const generate_silence)(struct ast_fax_session *)
Definition: res_fax.h:236
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
Definition: res_fax.c:2887
#define BEGIN_OPTIONS
Definition: app.h:662
jack_status_t status
Definition: app_jack.c:143
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int samples
Definition: frame.h:150
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
Definition: app.h:721
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
int ast_fax_tech_register(struct ast_fax_tech *tech)
register a fax technology
Definition: res_fax.c:616
static char * generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
Definition: res_fax.c:927
#define ast_smoother_feed(s, f)
Definition: frame.h:686
static char prefix[MAX_PREFIX]
Definition: http.c:107
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:2660