Improve handling of values supplied to FAXOPT(ecm).
[asterisk/asterisk.git] / res / res_fax.c
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         <conflict>app_fax</conflict>
22 ***/
23
24 /*! \file
25  *
26  * \brief Generic FAX Resource for FAX technology resource modules
27  *
28  * \author Dwayne M. Hubbard <dhubbard@digium.com>
29  * \author Kevin P. Fleming <kpfleming@digium.com>
30  * 
31  * A generic FAX resource module that provides SendFAX and ReceiveFAX applications.
32  * This module requires FAX technology modules, like res_fax_spandsp, to register with it
33  * so it can use the technology modules to perform the actual FAX transmissions.
34  * \ingroup applications
35  */
36
37 #include "asterisk.h"
38
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40
41 #include "asterisk/io.h"
42 #include "asterisk/file.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/module.h"
45 #include "asterisk/app.h"
46 #include "asterisk/lock.h"
47 #include "asterisk/options.h"
48 #include "asterisk/strings.h"
49 #include "asterisk/cli.h"
50 #include "asterisk/utils.h"
51 #include "asterisk/config.h"
52 #include "asterisk/astobj2.h"
53 #include "asterisk/file.h"
54 #include "asterisk/channel.h"
55 #include "asterisk/pbx.h"
56 #include "asterisk/manager.h"
57 #include "asterisk/dsp.h"
58 #include "asterisk/res_fax.h"
59
60 static const char app_receivefax[] = "ReceiveFAX";
61 static const char synopsis_receivefax[] = "Receive a FAX and save as a TIFF/F file.";
62 static const char descrip_receivefax[] = "ReceiveFAX(filename[,options]):\n"
63  " The ReceiveFAX() application receives a FAX as a TIFF/F file with specified filename.\n"
64  " The application arguments are:\n"
65  "    'd' - enables FAX debugging\n"
66  "    'f' - allow audio fallback FAX transfer on T.38 capable channels\n"
67  "    's' - send progress Manager events (overrides statusevents setting in res_fax.conf)\n"
68  "\n"
69  " Use the FAXOPT function to specify session arguments prior to calling ReceiveFAX()\n"
70  " and use FAXOPT after ReceiveFAX completes to query result status for the session.\n"
71  " The ReceiveFAX() is provided by res_fax, which is a FAX technology agnostic module\n"
72  " that utilizes FAX technology resource modules to complete a FAX transmission.\n";
73
74 static const char app_sendfax[] = "SendFAX";
75 static const char synopsis_sendfax[] = "Sends a specified TIFF/F file as a FAX.";
76 static const char descrip_sendfax[] = "SendFAX(filename[,options]):\n"
77  " The SendFAX() application sends the specified TIFF/F file as a FAX.\n"
78  " The application arguments are:\n"
79  "    'd' - enables FAX debugging\n"
80  "    'f' - allow audio fallback FAX transfer on T.38 capable channels\n"
81  "    's' - send progress Manager events (overrides statusevents setting in res_fax.conf)\n"
82  "\n"
83  " Use the FAXOPT function to specify session arguments prior to calling SendFAX()\n"
84  " and use FAXOPT after SendFAX completes to query result status for the session.\n"
85  " The SendFAX() application is provided by res_fax, which is a FAX technology agnostic module\n"
86  " that utilizes FAX technology resource modules to complete a FAX transmission.\n";
87
88 struct debug_info_history {
89         unsigned int consec_frames;
90         unsigned int consec_ms;
91         unsigned char silence;
92 };
93
94 struct ast_fax_debug_info {
95         struct timeval base_tv;
96         struct debug_info_history c2s, s2c;
97         struct ast_dsp *dsp;
98 };
99
100 /*! \brief maximum buckets for res_fax ao2 containers */
101 #define FAX_MAXBUCKETS 10
102
103 #define RES_FAX_TIMEOUT 10000
104
105 /*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */
106 static struct {
107         /*! The number of active FAX sessions */
108         int active_sessions;
109         /*! active sessions are astobj2 objects */
110         struct ao2_container *container;
111         /*! Total number of Tx FAX attempts */
112         int fax_tx_attempts;
113         /*! Total number of Rx FAX attempts */
114         int fax_rx_attempts;
115         /*! Number of successful FAX transmissions */
116         int fax_complete;
117         /*! Number of failed FAX transmissions */
118         int fax_failures;
119         /*! the next unique session name */
120         int nextsessionname;
121 } faxregistry;
122
123 /*! \brief registered FAX technology modules are put into this list */
124 struct fax_module {
125         const struct ast_fax_tech *tech;
126         AST_RWLIST_ENTRY(fax_module) list;
127 };
128 static AST_RWLIST_HEAD_STATIC(faxmodules, fax_module);
129
130 #define RES_FAX_MINRATE 2400
131 #define RES_FAX_MAXRATE 14400
132 #define RES_FAX_STATUSEVENTS 0
133 #define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)
134
135 static struct {
136         enum ast_fax_modems modems;
137         uint32_t statusevents:1;
138         unsigned int minrate;   
139         unsigned int maxrate;
140 } general_options;
141
142 static const char *config = "res_fax.conf";
143
144 static int global_fax_debug = 0;
145
146 enum {
147         OPT_CALLEDMODE = (1 << 0),
148         OPT_CALLERMODE = (1 << 1),
149         OPT_DEBUG      = (1 << 2),
150         OPT_STATUS     = (1 << 3),
151         OPT_ALLOWAUDIO = (1 << 5),
152 };
153
154 AST_APP_OPTIONS(fax_exec_options, BEGIN_OPTIONS
155         AST_APP_OPTION('a', OPT_CALLEDMODE),
156         AST_APP_OPTION('c', OPT_CALLERMODE),
157         AST_APP_OPTION('d', OPT_DEBUG),
158         AST_APP_OPTION('f', OPT_ALLOWAUDIO),
159         AST_APP_OPTION('s', OPT_STATUS),
160 END_OPTIONS);
161
162 struct manager_event_info {
163         char context[AST_MAX_CONTEXT];
164         char exten[AST_MAX_EXTENSION];
165         char cid[128];
166 };
167
168 static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
169 {       
170         struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
171         int dspsilence;
172         unsigned int last_consec_frames, last_consec_ms;
173         unsigned char wassil;
174         struct timeval diff;
175
176         diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
177
178         ast_dsp_reset(s->debug_info->dsp);
179         ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
180
181         wassil = history->silence;
182         history->silence = (dspsilence != 0) ? 1 : 0;
183         if (history->silence != wassil) {
184                 last_consec_frames = history->consec_frames;
185                 last_consec_ms = history->consec_ms;
186                 history->consec_frames = 0;
187                 history->consec_ms = 0;
188
189                 if ((last_consec_frames != 0)) {
190                         ast_verb(6, "Channel '%s' fax session '%d', [ %.3ld.%.6ld ], %s sent %d frames (%d ms) of %s.\n",
191                                  s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
192                                  (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
193                                  (wassil) ? "silence" : "energy");
194                 }
195         }
196
197         history->consec_frames++;
198         history->consec_ms += (frame->samples / 8);
199 }
200
201 static void destroy_callback(void *data) 
202 {
203         if (data) {
204                 ao2_ref(data, -1);
205         }
206 }
207
208 static const struct ast_datastore_info fax_datastore = {
209         .type = "res_fax",
210         .destroy = destroy_callback,
211 };
212
213 /*! \brief returns a reference counted pointer to a fax datastore, if it exists */
214 static struct ast_fax_session_details *find_details(struct ast_channel *chan)
215 {
216         struct ast_fax_session_details *details;
217         struct ast_datastore *datastore;
218
219         ast_channel_lock(chan); 
220         if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
221                 ast_channel_unlock(chan);       
222                 return NULL;
223         }
224         if (!(details = datastore->data)) {
225                 ast_log(LOG_WARNING, "Huh?  channel '%s' has a FAX datastore without data!\n", chan->name);
226                 ast_channel_unlock(chan);
227                 return NULL;
228         }
229         ao2_ref(details, 1);    
230         ast_channel_unlock(chan);       
231
232         return details;
233 }
234
235 /*! \brief destroy a FAX session details structure */
236 static void destroy_session_details(void *details)
237 {
238         struct ast_fax_session_details *d = details;
239         struct ast_fax_document *doc;
240         
241         while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
242                 ast_free(doc);
243         }
244         ast_string_field_free_memory(d);        
245 }
246
247 /*! \brief create a FAX session details structure */
248 static struct ast_fax_session_details *session_details_new(void)
249 {
250         struct ast_fax_session_details *d;
251
252         if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
253                 return NULL;
254         }
255         
256         if (ast_string_field_init(d, 512)) {
257                 ao2_ref(d, -1);
258                 return NULL;
259         }
260
261         AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
262
263         /* These options need to be set to the configured default and may be overridden by
264          * SendFAX, ReceiveFAX, or FAXOPT */
265         d->option.ecm = AST_FAX_OPTFLAG_DEFAULT;
266         d->option.statusevents = general_options.statusevents;
267         d->modems = general_options.modems;
268         d->minrate = general_options.minrate;
269         d->maxrate = general_options.maxrate;
270
271         return d;
272 }
273
274 /*! \brief returns a reference counted details structure from the channel's fax datastore.  If the datastore
275  * does not exist it will be created */ 
276 static struct ast_fax_session_details *find_or_create_details(struct ast_channel *chan)
277 {
278         struct ast_fax_session_details *details;
279         struct ast_datastore *datastore;
280
281         if ((details = find_details(chan))) {
282                 return details;
283         }
284         /* channel does not have one so we must create one */
285         if (!(details = session_details_new())) {
286                 ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", chan->name);
287                 return NULL;
288         }
289         if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
290                 ao2_ref(details, -1);
291                 ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", chan->name);
292                 return NULL;
293         }
294         /* add the datastore to the channel and increment the refcount */
295         datastore->data = details;
296         ao2_ref(details, 1);
297         ast_channel_lock(chan);
298         ast_channel_datastore_add(chan, datastore);
299         ast_channel_unlock(chan);
300         return details;
301 }
302
303 unsigned int ast_fax_maxrate(void)
304 {
305         return general_options.maxrate;
306 }
307
308 unsigned int ast_fax_minrate(void)
309 {
310         return general_options.minrate;
311 }
312
313 static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
314 {               
315         char *m[5], *tok, *v = (char *)value;
316         int i = 0, j;
317
318         if (!(tok = strchr(v, ','))) {
319                 m[i++] = v;
320                 m[i] = NULL;
321         } else {
322                 tok = strtok(v, ", ");
323                 while (tok && (i < 5)) {
324                         m[i++] = tok;
325                         tok = strtok(NULL, ", ");
326                 }
327                 m[i] = NULL;
328         }
329
330         *bits = 0;
331         for (j = 0; j < i; j++) {
332                 if (!strcasecmp(m[j], "v17")) {
333                         *bits |= AST_FAX_MODEM_V17;
334                 } else if (!strcasecmp(m[j], "v27")) {
335                         *bits |= AST_FAX_MODEM_V27;
336                 } else if (!strcasecmp(m[j], "v29")) {
337                         *bits |= AST_FAX_MODEM_V29;
338                 } else if (!strcasecmp(m[j], "v34")) {
339                         *bits |= AST_FAX_MODEM_V34;
340                 } else {
341                         ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
342                 }
343         }
344         return 0;
345 }
346
347 static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
348 {
349         int count = 0;
350
351         if (bits & AST_FAX_MODEM_V17) {
352                 strcat(tbuf, "V17");
353                 count++;
354         }
355         if (bits & AST_FAX_MODEM_V27) {
356                 if (count) {
357                         strcat(tbuf, ",");
358                 }
359                 strcat(tbuf, "V27");
360                 count++;
361         }
362         if (bits & AST_FAX_MODEM_V29) {
363                 if (count) {
364                         strcat(tbuf, ",");
365                 }
366                 strcat(tbuf, "V29");
367                 count++;
368         }
369         if (bits & AST_FAX_MODEM_V34) {
370                 if (count) {
371                         strcat(tbuf, ",");
372                 }
373                 strcat(tbuf, "V34");
374                 count++;
375         }
376
377         return 0;
378 }
379
380 /*! \brief register a FAX technology module */
381 int ast_fax_tech_register(struct ast_fax_tech *tech)
382 {
383         struct fax_module *fax;
384
385         if (!(fax = ast_calloc(1, sizeof(*fax)))) {
386                 return -1;
387         }
388         fax->tech = tech;
389         AST_RWLIST_WRLOCK(&faxmodules);
390         AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
391         AST_RWLIST_UNLOCK(&faxmodules);
392         ast_module_ref(ast_module_info->self);
393
394         ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
395
396         return 0;
397 }
398
399 /*! \brief unregister a FAX technology module */
400 void ast_fax_tech_unregister(struct ast_fax_tech *tech)
401 {
402         struct fax_module *fax;
403
404         ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
405
406         AST_RWLIST_WRLOCK(&faxmodules);
407         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&faxmodules, fax, list) {
408                 if (fax->tech != tech) {
409                         continue;
410                 }
411                 AST_RWLIST_REMOVE_CURRENT(list);
412                 ast_module_unref(ast_module_info->self);
413                 ast_free(fax);
414                 ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
415                 break;  
416         }
417         AST_RWLIST_TRAVERSE_SAFE_END;
418         AST_RWLIST_UNLOCK(&faxmodules);
419 }
420
421 /*! \brief convert a ast_fax_state to a string */
422 const char *ast_fax_state_to_str(enum ast_fax_state state)
423 {
424         switch (state) {
425         case AST_FAX_STATE_UNINITIALIZED:
426                 return "Uninitialized";
427         case AST_FAX_STATE_INITIALIZED:
428                 return "Initialized";
429         case AST_FAX_STATE_OPEN:
430                 return "Open";
431         case AST_FAX_STATE_ACTIVE:
432                 return "Active";
433         case AST_FAX_STATE_COMPLETE:
434                 return "Complete";
435         default:
436                 ast_log(LOG_WARNING, "unhandled FAX state: %d\n", state);
437                 return "Unknown";
438         }
439 }
440
441 /*! \brief convert a rate string to a rate */
442 static int fax_rate_str_to_int(const char *ratestr)
443 {
444         int rate;
445
446         if (sscanf(ratestr, "%d", &rate) != 1) {
447                 ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
448                 return -1;
449         }
450         switch (rate) {
451         case 2400:
452         case 4800:
453         case 7200:
454         case 9600:
455         case 12000:
456         case 14400:
457         case 28800:
458         case 33600:
459                 return rate;
460         default:
461                 ast_log(LOG_WARNING, "ignoring invalid rate '%s'.  Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
462                 return -1;
463         }
464 }
465
466 /*! \brief destroy a FAX session structure */
467 static void destroy_session(void *session)
468 {
469         struct ast_fax_session *s = session;
470
471         if (s->tech) {
472                 if (s->tech_pvt) {
473                         s->tech->destroy_session(s);
474                 }
475                 ast_module_unref(s->tech->module);
476         }
477
478         if (s->details) {
479                 ao2_ref(s->details, -1);
480         }
481         
482         if (s->debug_info) {
483                 ast_dsp_free(s->debug_info->dsp);
484                 ast_free(s->debug_info);
485         }
486
487         if (s->smoother) {
488                 ast_smoother_free(s->smoother);
489         }
490
491         ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
492
493         ast_free(s->channame);
494 }
495
496 /*! \brief create a FAX session */
497 static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *details, struct ast_channel *chan)
498 {
499         struct ast_fax_session *s;
500         struct fax_module *faxmod;
501
502         if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
503                 return NULL;
504         }
505
506         ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
507
508         if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
509                 if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
510                         ao2_ref(s, -1);
511                         return NULL;
512                 }
513                 if (!(s->debug_info->dsp = ast_dsp_new())) {
514                         ast_free(s->debug_info);
515                         s->debug_info = NULL;
516                         ao2_ref(s, -1);
517                         return NULL;
518                 }
519                 ast_dsp_set_threshold(s->debug_info->dsp, 128);
520         }       
521
522         if (!(s->channame = ast_strdup(chan->name))) {
523                 ao2_ref(s, -1);
524                 return NULL;
525         }
526         s->chan = chan;
527         s->details = details;
528         ao2_ref(s->details, 1);
529         s->state = AST_FAX_STATE_UNINITIALIZED;
530
531         details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
532
533         /* locate a FAX technology module that can handle said requirements */
534         AST_RWLIST_RDLOCK(&faxmodules);
535         AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
536                 if ((faxmod->tech->caps & details->caps) != details->caps) {
537                         continue;
538                 }
539                 ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
540                 ast_module_ref(faxmod->tech->module);
541                 s->tech = faxmod->tech;
542                 break;
543         }
544         AST_RWLIST_UNLOCK(&faxmodules);
545
546         if (!faxmod) {
547                 ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (0x%X)\n", details->caps);
548                 ao2_ref(s, -1);
549                 return NULL;
550         }
551         if (!(s->tech_pvt = s->tech->new_session(s, NULL))) {
552                 ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
553                 ao2_ref(s, -1);
554                 ast_module_unref(faxmod->tech->module);
555                 return NULL;
556         }
557         /* link the session to the session container */
558         if (!(ao2_link(faxregistry.container, s))) {
559                 ast_log(LOG_ERROR, "failed to add FAX session '%d' to container.\n", s->id);
560                 ao2_ref(s, -1);
561                 ast_module_unref(faxmod->tech->module);
562                 return NULL;
563         }
564         ast_debug(4, "channel '%s' using FAX session '%d'\n", s->channame, s->id);
565
566         return s;
567 }
568
569 static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
570 {
571         pbx_substitute_variables_helper(chan, "${CONTEXT}", info->context, sizeof(info->context));
572         pbx_substitute_variables_helper(chan, "${EXTEN}", info->exten, sizeof(info->exten));
573         pbx_substitute_variables_helper(chan, "${CALLERID(num)}", info->cid, sizeof(info->cid));
574 }
575
576 /*! \brief send a FAX status manager event */
577 static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
578 {
579         ast_channel_lock(chan);
580         pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", status);
581         if (details->option.statusevents) {
582                 struct manager_event_info info;
583
584                 get_manager_event_info(chan, &info);
585                 manager_event(EVENT_FLAG_CALL,
586                               (details->caps & AST_FAX_TECH_RECEIVE) ? "ReceiveFAXStatus" : "SendFAXStatus",
587                               "Status: %s\r\n"
588                               "Channel: %s\r\n"
589                               "Context: %s\r\n"
590                               "Exten: %s\r\n"
591                               "CallerID: %s\r\n"
592                               "LocalStationID: %s\r\n"
593                               "FileName: %s\r\n",
594                               status,
595                               chan->name,
596                               info.context,
597                               info.exten,
598                               info.cid,
599                               details->localstationid,
600                               AST_LIST_FIRST(&details->documents)->filename);
601         }
602         ast_channel_unlock(chan);
603
604         return 0;
605 }
606
607 #define GENERIC_FAX_EXEC_ERROR(fax, chan, reason)       \
608         do {    \
609                 ast_log(LOG_ERROR, "channel '%s' FAX session '%d' failure, reason: '%s'\n", chan->name, fax->id, reason); \
610                 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", reason); \
611                 if (ast_strlen_zero(fax->details->result)) ast_string_field_set(fax->details, result, "FAILED"); \
612                 res = ms = -1; \
613         } while (0)
614
615 static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
616 {
617         dst->version = src->version;
618         dst->max_ifp = src->max_ifp;
619         dst->rate = src->rate;
620         dst->rate_management = src->rate_management;
621         dst->fill_bit_removal = src->fill_bit_removal;
622         dst->transcoding_mmr = src->transcoding_mmr;
623         dst->transcoding_jbig = src->transcoding_jbig;
624 }
625
626 static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
627 {
628         dst->version = src->version;
629         dst->max_ifp = src->max_ifp;
630         dst->rate = src->rate;
631         dst->rate_management = src->rate_management;
632         dst->fill_bit_removal = src->fill_bit_removal;
633         dst->transcoding_mmr = src->transcoding_mmr;
634         dst->transcoding_jbig = src->transcoding_jbig;
635 }
636
637 /*! \brief this is the generic FAX session handling function */
638 static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_details *details)
639 {
640         int ms;
641         int timeout = RES_FAX_TIMEOUT;
642         int res = 0, chancount;
643         unsigned int expected_frametype = -1;
644         union ast_frame_subclass expected_framesubclass = { .integer = -1 };
645         char tbuf[10];
646         unsigned int t38negotiated = 0;
647         enum ast_t38_state t38_state;
648         struct ast_control_t38_parameters t38_parameters;
649         int send_cng = -1;
650         unsigned int disable_t38 = 0;
651         const char *tempvar;
652         struct ast_fax_session *fax = NULL;
653         struct ast_frame *frame = NULL;
654         struct ast_channel *c = chan;
655         unsigned int orig_write_format = 0, orig_read_format = 0;
656         unsigned int request_t38 = 0;
657
658         details->our_t38_parameters.version = 0;
659         details->our_t38_parameters.max_ifp = 400;
660         details->our_t38_parameters.rate = AST_T38_RATE_14400;
661         details->our_t38_parameters.rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF;
662
663         chancount = 1;
664
665         /* generate 3 seconds of CED if we are in receive mode */
666         if (details->caps & AST_FAX_TECH_RECEIVE) {
667                 ms = 3000;
668                 if (ast_tonepair_start(chan, 2100, 0, ms, 0)) {
669                         ast_log(LOG_ERROR, "error generating CED tone on %s\n", chan->name);
670                         return -1;
671                 }
672
673                 do {
674                         ms = ast_waitfor(chan, ms);
675                         if (ms < 0) {
676                                 ast_log(LOG_ERROR, "error while generating CED tone on %s\n", chan->name);
677                                 ast_tonepair_stop(chan);
678                                 return -1;
679                         }
680
681                         if (ms == 0) { /* all done, nothing happened */
682                                 break;
683                         }
684
685                         if (!(frame = ast_read(chan))) {
686                                 ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", chan->name);
687                                 ast_tonepair_stop(chan);
688                                 return -1;
689                         }
690
691                         if ((frame->frametype == AST_FRAME_CONTROL) &&
692                                         (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
693                                         (frame->datalen == sizeof(t38_parameters))) {
694                                 struct ast_control_t38_parameters *parameters = frame->data.ptr;
695
696                                 switch (parameters->request_response) {
697                                 case AST_T38_REQUEST_NEGOTIATE:
698                                         /* the other end has requested a switch to T.38, so reply that we are willing, if we can
699                                          * do T.38 as well
700                                          */
701                                         t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
702                                         t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
703                                         ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
704                                         break;
705                                 case AST_T38_NEGOTIATED:
706                                         ast_log(LOG_NOTICE, "Negotiated T.38 for receive on %s\n", chan->name);
707                                         t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
708                                         details->caps &= ~AST_FAX_TECH_AUDIO;
709                                         report_fax_status(chan, details, "T.38 Negotiated");
710                                         t38negotiated = 1;
711                                         ms = 0;
712                                         break;
713                                 default:
714                                         break;
715                                 }
716                         }
717                         ast_frfree(frame);
718                 } while (ms > 0);
719                 ast_tonepair_stop(chan);
720         }
721
722         switch ((t38_state = ast_channel_get_t38_state(chan))) {
723         case T38_STATE_UNKNOWN:
724                 if (details->caps & AST_FAX_TECH_SEND) {
725                         if (details->option.allow_audio) {
726                                 details->caps |= AST_FAX_TECH_AUDIO;
727                         } else {
728                                 /* we are going to send CNG to attempt to stimulate the receiver
729                                  * into switching to T.38, since audio mode is not allowed
730                                  */
731                                 send_cng = 0;
732                         }
733                 } else {
734                         /* we *always* request a switch to T.38 if allowed; if audio is also
735                          * allowed, then we will allow the switch to happen later if needed
736                          */
737                         if (details->option.allow_audio) {
738                                 details->caps |= AST_FAX_TECH_AUDIO;
739                         }
740                         request_t38 = 1;
741                 }
742                 details->caps |= AST_FAX_TECH_T38;
743                 break;
744         case T38_STATE_UNAVAILABLE:
745                 details->caps |= AST_FAX_TECH_AUDIO;
746                 break;
747         default:
748                 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name);
749                 return -1;
750         }
751
752         if (request_t38) {
753                 /* wait up to five seconds for negotiation to complete */
754                 timeout = 5000;
755
756                 /* set parameters based on the session's parameters */
757                 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
758                 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
759                 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
760                         res = -1;
761                         goto t38done;
762                 }
763
764                 ast_log(LOG_NOTICE, "Negotiating T.38 for %s on %s\n", (details->caps & AST_FAX_TECH_SEND) ? "send" : "receive", chan->name);
765         } else if (!details->option.allow_audio) {
766                 /* wait up to sixty seconds for negotiation to complete */
767                 timeout = 60000;
768
769                 ast_log(LOG_NOTICE, "Waiting for T.38 negotiation for %s on %s\n", (details->caps & AST_FAX_TECH_SEND) ? "send" : "receive", chan->name);
770         }
771
772         if (request_t38 || !details->option.allow_audio) {
773                 struct ast_silence_generator *silence_gen = NULL;
774
775                 if (send_cng != -1) {
776                         silence_gen = ast_channel_start_silence_generator(chan);
777                 }
778
779                 while (timeout > 0) {
780                         if (send_cng > 3000) {
781                                 ast_channel_stop_silence_generator(chan, silence_gen);
782                                 silence_gen = NULL;
783                                 ast_tonepair_start(chan, 1100, 0, 500, 0);
784                                 send_cng = 0;
785                         } else if (!chan->generator && (send_cng != -1)) {
786                                 /* The CNG tone is done so restart silence generation. */
787                                 silence_gen = ast_channel_start_silence_generator(chan);
788                         }
789                         /* this timeout *MUST* be 500ms, in order to keep the spacing
790                          * of CNG tones correct when this loop is sending them
791                          */
792                         ms = ast_waitfor(chan, 500);
793                         if (ms < 0) {
794                                 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name);
795                                 res = -1;
796                                 break;
797                         }
798                         if (send_cng != -1) {
799                                 send_cng += 500 - ms;
800                         }
801                         if (!ms) {
802                                 /* nothing happened */
803                                 if (timeout > 0) {
804                                         timeout -= 500;
805                                         continue;
806                                 } else {
807                                         ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
808                                         res = -1;
809                                         break;
810                                 }
811                         }
812                         if (!(frame = ast_read(chan))) {
813                                 if (silence_gen) {
814                                         ast_channel_stop_silence_generator(chan, silence_gen);
815                                         silence_gen = NULL;
816                                 }
817                                 return -1;
818                         }
819                         if ((frame->frametype == AST_FRAME_CONTROL) &&
820                             (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
821                             (frame->datalen == sizeof(t38_parameters))) {
822                                 struct ast_control_t38_parameters *parameters = frame->data.ptr;
823                                 int stop = 1;
824                                 
825                                 switch (parameters->request_response) {
826                                 case AST_T38_REQUEST_NEGOTIATE:
827                                         t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
828                                         t38_parameters.request_response = AST_T38_NEGOTIATED;
829                                         ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
830                                         stop = 0;
831                                         break;
832                                 case AST_T38_NEGOTIATED:
833                                         ast_log(LOG_NOTICE, "Negotiated T.38 for %s on %s\n", (details->caps & AST_FAX_TECH_SEND) ? "send" : "receive", chan->name);
834                                         t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
835                                         details->caps &= ~AST_FAX_TECH_AUDIO;
836                                         t38negotiated = 1;
837                                         disable_t38 = 1;
838                                         break;
839                                 case AST_T38_REFUSED:
840                                         ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
841                                         res = -1;
842                                         break;
843                                 default:
844                                         ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
845                                         res = -1;
846                                         break;
847                                 }
848                                 if (stop) {
849                                         ast_frfree(frame);
850                                         break;
851                                 }
852                         }
853                         ast_frfree(frame);
854                 }
855
856                 if (silence_gen) {
857                         ast_channel_stop_silence_generator(chan, silence_gen);
858                         silence_gen = NULL;
859                 }
860         }
861
862 t38done:
863         /* if any failures occurred during T.38 negotiation, handle them here */
864         if (res) {
865                 /* if audio is allowed, then drop the T.38 session requirement
866                  * and proceed, otherwise the request has failed
867                  */
868                 if (details->option.allow_audio) {
869                         details->caps &= ~AST_FAX_TECH_T38;
870                         res = 0;
871                 } else {
872                         ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name);
873                         return -1;
874                 }
875         }
876
877         /* create the FAX session */
878         if (!(fax = fax_session_new(details, chan))) {
879                 ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
880                 report_fax_status(chan, details, "No Available Resource");
881                 chancount = -1;
882                 goto disable_t38;
883         }
884
885         ast_channel_lock(chan);
886         /* update session details */    
887         if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
888                 ast_string_field_set(details, headerinfo, tempvar);
889         }
890         if (ast_strlen_zero(details->localstationid)) {
891                 tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
892                 ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
893         }
894         ast_channel_unlock(chan);
895
896         report_fax_status(chan, details, "Allocating Resources");
897
898         if (details->caps & AST_FAX_TECH_AUDIO) {
899                 expected_frametype = AST_FRAME_VOICE;;
900                 expected_framesubclass.codec = AST_FORMAT_SLINEAR;
901                 orig_write_format = chan->writeformat;
902                 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
903                         ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", chan->name);
904                         ao2_lock(faxregistry.container);
905                         ao2_unlink(faxregistry.container, fax);
906                         ao2_unlock(faxregistry.container);
907                         ao2_ref(fax, -1);
908                         ast_channel_unlock(chan);
909                         return -1;
910                 }
911                 orig_read_format = chan->readformat;
912                 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
913                         ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", chan->name);
914                         ao2_lock(faxregistry.container);
915                         ao2_unlink(faxregistry.container, fax);
916                         ao2_unlock(faxregistry.container);
917                         ao2_ref(fax, -1);
918                         ast_channel_unlock(chan);
919                         return -1;
920                 }
921                 if (fax->smoother) {
922                         ast_smoother_free(fax->smoother);
923                         fax->smoother = NULL;
924                 }
925                 if (!(fax->smoother = ast_smoother_new(320))) {
926                         ast_log(LOG_WARNING, "Channel '%s' FAX session '%d' failed to obtain a smoother.\n", chan->name, fax->id);
927                 }
928         } else {
929                 expected_frametype = AST_FRAME_MODEM;
930                 expected_framesubclass.codec = AST_MODEM_T38;
931         }
932
933         if (fax->debug_info) {
934                 fax->debug_info->base_tv = ast_tvnow();
935         }
936         if (fax->tech->start_session(fax) < 0) {
937                 GENERIC_FAX_EXEC_ERROR(fax, chan, "failed to start FAX session");
938         }
939
940         pbx_builtin_setvar_helper(chan, "FAXSTATUS", NULL);
941         pbx_builtin_setvar_helper(chan, "FAXERROR", NULL);
942         report_fax_status(chan, details, "FAX Transmission In Progress");
943
944         ast_debug(5, "channel %s will wait on FAX fd %d\n", chan->name, fax->fd);
945
946         /* handle frames for the session */
947         ms = 1000;
948         while ((ms > -1) && (timeout > 0)) {
949                 struct ast_channel *ready_chan;
950                 int ofd, exception;
951
952                 ms = 1000;
953                 errno = 0;
954                 ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
955                 if (ready_chan) {
956                         if (!(frame = ast_read(chan))) {
957                                 /* the channel is probably gone, so lets stop polling on it and let the
958                                  * FAX session complete before we exit the application.  if needed,
959                                  * send the FAX stack silence so the modems can finish their session without
960                                  * any problems */
961                                 ast_log(LOG_NOTICE, "Channel '%s' did not return a frame; probably hung up.\n", chan->name);
962                                 c = NULL;
963                                 chancount = 0;
964                                 timeout -= (1000 - ms);
965                                 fax->tech->cancel_session(fax);
966                                 if (fax->tech->generate_silence) {
967                                         fax->tech->generate_silence(fax);
968                                 }
969                                 continue;
970                         }
971
972                         if ((frame->frametype == AST_FRAME_CONTROL) &&
973                             (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
974                             (frame->datalen == sizeof(t38_parameters))) {
975                                 unsigned int was_t38 = t38negotiated;
976                                 struct ast_control_t38_parameters *parameters = frame->data.ptr;
977                                 
978                                 switch (parameters->request_response) {
979                                 case AST_T38_REQUEST_NEGOTIATE:
980                                         /* the other end has requested a switch to T.38, so reply that we are willing, if we can
981                                          * do T.38 as well
982                                          */
983                                         t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
984                                         t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
985                                         ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
986                                         break;
987                                 case AST_T38_NEGOTIATED:
988                                         t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
989                                         t38negotiated = 1;
990                                         break;
991                                 default:
992                                         break;
993                                 }
994                                 if (t38negotiated && !was_t38) {
995                                         fax->tech->switch_to_t38(fax);
996                                         details->caps &= ~AST_FAX_TECH_AUDIO;
997                                         expected_frametype = AST_FRAME_MODEM;
998                                         expected_framesubclass.codec = AST_MODEM_T38;
999                                         if (fax->smoother) {
1000                                                 ast_smoother_free(fax->smoother);
1001                                                 fax->smoother = NULL;
1002                                         }
1003                                         
1004                                         report_fax_status(chan, details, "T.38 Negotiated");
1005                                         
1006                                         ast_verb(3, "Channel '%s' switched to T.38 FAX session '%d'.\n", chan->name, fax->id);
1007                                 }
1008                         } else if ((frame->frametype == expected_frametype) &&
1009                                    (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) {
1010                                 struct ast_frame *f;
1011                                 
1012                                 if (fax->smoother) {
1013                                         /* push the frame into a smoother */
1014                                         if (ast_smoother_feed(fax->smoother, frame) < 0) {
1015                                                 GENERIC_FAX_EXEC_ERROR(fax, chan, "Failed to feed the smoother");
1016                                         }
1017                                         while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
1018                                                 if (fax->debug_info) {
1019                                                         debug_check_frame_for_silence(fax, 1, f);
1020                                                 }
1021                                                 /* write the frame to the FAX stack */
1022                                                 fax->tech->write(fax, f);
1023                                                 fax->frames_received++;
1024                                                 if (f != frame) {
1025                                                         ast_frfree(f);
1026                                                 }
1027                                         }
1028                                 } else {
1029                                         /* write the frame to the FAX stack */
1030                                         fax->tech->write(fax, frame);
1031                                         fax->frames_received++;
1032                                 }
1033                                 timeout = RES_FAX_TIMEOUT;
1034                         }
1035                         ast_frfree(frame);
1036                 } else if (ofd == fax->fd) {
1037                         /* read a frame from the FAX stack and send it out the channel.
1038                          * the FAX stack will return a NULL if the FAX session has already completed */
1039                         if (!(frame = fax->tech->read(fax))) {
1040                                 break;
1041                         }
1042
1043                         if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
1044                                 debug_check_frame_for_silence(fax, 0, frame);
1045                         }
1046
1047                         ast_write(chan, frame);
1048                         fax->frames_sent++;
1049                         ast_frfree(frame);
1050                         timeout = RES_FAX_TIMEOUT;
1051                 } else {
1052                         if (ms && (ofd < 0)) {
1053                                 if ((errno == 0) || (errno == EINTR)) {
1054                                         timeout -= (1000 - ms);
1055                                         continue;
1056                                 } else {
1057                                         ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name);
1058                                         res = ms;
1059                                         break;
1060                                 }
1061                         } else {
1062                                 /* nothing happened */
1063                                 if (timeout > 0) {
1064                                         timeout -= 1000;
1065                                         continue;
1066                                 } else {
1067                                         ast_log(LOG_WARNING, "channel '%s' timed-out during the FAX transmission.\n", chan->name);
1068                                         GENERIC_FAX_EXEC_ERROR(fax, chan, "fax session timed-out");
1069                                         break;
1070                                 }
1071                         }
1072                 }
1073         }
1074         ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, ms: %d, res: %d }\n", chan->name, timeout, ms, res);
1075
1076         pbx_builtin_setvar_helper(chan, "FAXSTATUS", details->result);
1077         pbx_builtin_setvar_helper(chan, "FAXERROR", details->error);
1078         pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", details->resultstr);
1079         pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", details->remotestationid);
1080         pbx_builtin_setvar_helper(chan, "FAXBITRATE", details->transfer_rate);
1081         pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", details->resolution);
1082
1083         snprintf(tbuf, sizeof(tbuf), "%d", details->pages_transferred);
1084         pbx_builtin_setvar_helper(chan, "FAXPAGES", tbuf);
1085
1086         ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
1087         if (!strcasecmp(details->result, "FAILED")) {
1088                 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1089         }
1090
1091         if (fax) {
1092                 ao2_lock(faxregistry.container);
1093                 ao2_unlink(faxregistry.container, fax);
1094                 ao2_unlock(faxregistry.container);
1095                 ao2_ref(fax, -1);
1096         }
1097
1098         /* if the channel is still alive, and we changed its read/write formats,
1099          * restore them now
1100          */
1101         if (chancount) {
1102                 if (orig_read_format) {
1103                         ast_set_read_format(chan, orig_read_format);
1104                 }
1105                 if (orig_write_format) {
1106                         ast_set_write_format(chan, orig_write_format);
1107                 }
1108         }
1109
1110 disable_t38:
1111         if (disable_t38 &&
1112             (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED)) {
1113                 struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
1114
1115                 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) {
1116                         /* wait up to five seconds for negotiation to complete */
1117                         unsigned int timeout = 5000;
1118                         int ms;
1119                         
1120                         ast_debug(1, "Shutting down T.38 on %s\n", chan->name);
1121                         while (timeout > 0) {
1122                                 ms = ast_waitfor(chan, 1000);
1123                                 if (ms < 0) {
1124                                         ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name);
1125                                         return -1;
1126                                 }
1127                                 if (!ms) {
1128                                         /* nothing happened */
1129                                         if (timeout > 0) {
1130                                                 timeout -= 1000;
1131                                                 continue;
1132                                         } else {
1133                                                 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", chan->name);
1134                                                 break;
1135                                         }
1136                                 }
1137                                 if (!(frame = ast_read(chan))) {
1138                                         return -1;
1139                                 }
1140                                 if ((frame->frametype == AST_FRAME_CONTROL) &&
1141                                     (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1142                                     (frame->datalen == sizeof(t38_parameters))) {
1143                                         struct ast_control_t38_parameters *parameters = frame->data.ptr;
1144                                         
1145                                         switch (parameters->request_response) {
1146                                         case AST_T38_TERMINATED:
1147                                                 ast_debug(1, "Shut down T.38 on %s\n", chan->name);
1148                                                 break;
1149                                         case AST_T38_REFUSED:
1150                                                 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", chan->name);
1151                                                 break;
1152                                         default:
1153                                                 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", chan->name);
1154                                                 break;
1155                                         }
1156                                         ast_frfree(frame);
1157                                         break;
1158                                 }
1159                                 ast_frfree(frame);
1160                         }
1161                 }
1162         }
1163
1164         /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
1165         return chancount;
1166 }
1167
1168 /*! \brief initiate a receive FAX session */
1169 static int receivefax_exec(struct ast_channel *chan, const char *data)
1170 {
1171         char *parse;
1172         int channel_alive;
1173         struct ast_fax_session_details *details;
1174         struct ast_fax_document *doc;
1175         AST_DECLARE_APP_ARGS(args,
1176                 AST_APP_ARG(filename);
1177                 AST_APP_ARG(options);
1178         );
1179         struct ast_flags opts = { 0, };
1180         struct manager_event_info info;
1181
1182         if (ast_strlen_zero(data)) {
1183                 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1184                 return -1;
1185         }
1186         parse = ast_strdupa(data);
1187         AST_STANDARD_APP_ARGS(args, parse);
1188         
1189         /* initialize output channel variables */
1190         pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
1191         pbx_builtin_setvar_helper(chan, "FAXERROR", "Application Problems");
1192         pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Invalid application arguments.");
1193         pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
1194         pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
1195         pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
1196         pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
1197
1198         if (!ast_strlen_zero(args.options) &&
1199             ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
1200                 return -1;
1201         }
1202         if (ast_strlen_zero(args.filename)) {
1203                 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1204                 return -1;
1205         }
1206
1207         /* check for unsupported FAX application options */
1208         if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
1209                 ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
1210                 return -1;
1211         }
1212         
1213         /* make sure the channel is up */
1214         if (chan->_state != AST_STATE_UP) {
1215                 if (ast_answer(chan)) {
1216                         ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
1217                         return -1;
1218                 }
1219         }
1220
1221         ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
1222
1223         pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
1224         pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
1225
1226         /* Get a FAX session details structure from the channel's FAX datastore and create one if
1227          * it does not already exist. */
1228         if (!(details = find_or_create_details(chan))) {
1229                 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1230                 return -1;
1231         }
1232
1233         if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
1234                 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1235                 ao2_ref(details, -1);
1236                 return -1;
1237         }
1238
1239         strcpy(doc->filename, args.filename);
1240         AST_LIST_INSERT_TAIL(&details->documents, doc, next);
1241
1242         ast_verb(3, "Channel '%s' receiving FAX '%s'\n", chan->name, args.filename);
1243
1244         details->caps = AST_FAX_TECH_RECEIVE;
1245
1246         /* check for debug */
1247         if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
1248                 details->option.debug = AST_FAX_OPTFLAG_TRUE;
1249         }
1250
1251         /* check for request for status events */
1252         if (ast_test_flag(&opts, OPT_STATUS)) {
1253                 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
1254         }
1255
1256         if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) ||
1257             ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
1258                 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
1259         }
1260
1261         if ((channel_alive = generic_fax_exec(chan, details)) < 0) {
1262                 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1263         }
1264         
1265         /* send out the AMI completion event */
1266         ast_channel_lock(chan);
1267
1268         get_manager_event_info(chan, &info);
1269         manager_event(EVENT_FLAG_CALL,
1270                       "ReceiveFAX", 
1271                       "Channel: %s\r\n"
1272                       "Context: %s\r\n"
1273                       "Exten: %s\r\n"
1274                       "CallerID: %s\r\n"
1275                       "RemoteStationID: %s\r\n"
1276                       "LocalStationID: %s\r\n"
1277                       "PagesTransferred: %s\r\n"
1278                       "Resolution: %s\r\n"
1279                       "TransferRate: %s\r\n"
1280                       "FileName: %s\r\n",
1281                       chan->name,
1282                       info.context,
1283                       info.exten,
1284                       info.cid,
1285                       pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"),
1286                       pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"),
1287                       pbx_builtin_getvar_helper(chan, "FAXPAGES"),
1288                       pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"),
1289                       pbx_builtin_getvar_helper(chan, "FAXBITRATE"),
1290                       args.filename);
1291         ast_channel_unlock(chan);
1292
1293         ao2_ref(details, -1);
1294
1295         /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
1296         return (!channel_alive) ? -1 : 0;
1297 }
1298
1299 /*! \brief initiate a send FAX session */
1300 static int sendfax_exec(struct ast_channel *chan, const char *data)
1301 {
1302         char *parse;
1303         int channel_alive;
1304         struct ast_fax_session_details *details;
1305         struct ast_fax_document *doc;
1306         AST_DECLARE_APP_ARGS(args,
1307                 AST_APP_ARG(filename);
1308                 AST_APP_ARG(options);
1309         );
1310         struct ast_flags opts = { 0, };
1311         struct manager_event_info info;
1312
1313         if (ast_strlen_zero(data)) {
1314                 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_sendfax);
1315                 return -1;
1316         }
1317         parse = ast_strdupa(data);
1318         AST_STANDARD_APP_ARGS(args, parse);
1319
1320         /* initialize output channel variables */
1321         pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
1322         pbx_builtin_setvar_helper(chan, "FAXERROR", "Application Problems");
1323         pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Invalid application arguments.");
1324         pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
1325         pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
1326         pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
1327         pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
1328
1329         if (!ast_strlen_zero(args.options) &&
1330             ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
1331                 return -1;
1332         }
1333         if (ast_strlen_zero(args.filename)) {
1334                 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_sendfax);
1335                 return -1;
1336         }
1337         
1338         /* check for unsupported FAX application options */
1339         if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
1340                 ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
1341                 return -1;
1342         }
1343
1344         if (access(args.filename, (F_OK | R_OK)) < 0) {
1345                 ast_log(LOG_ERROR, "access failure.  Verify '%s' exists and check permissions.\n", args.filename);
1346                 return -1;
1347         }
1348         
1349         /* make sure the channel is up */
1350         if (chan->_state != AST_STATE_UP) {
1351                 if (ast_answer(chan)) {
1352                         ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
1353                         return -1;
1354                 }
1355         }
1356
1357         ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
1358         
1359         pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
1360         pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
1361
1362         /* Get a requirement structure and set it.  This structure is used
1363          * to tell the FAX technology module about the higher level FAX session */
1364         if (!(details = find_or_create_details(chan))) {
1365                 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1366                 return -1;
1367         }
1368
1369         if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
1370                 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1371                 ao2_ref(details, -1);
1372                 return -1;
1373         }
1374
1375         strcpy(doc->filename, args.filename);
1376         AST_LIST_INSERT_TAIL(&details->documents, doc, next);
1377
1378         ast_verb(3, "Channel '%s' sending FAX '%s'\n", chan->name, args.filename);
1379         
1380         details->caps = AST_FAX_TECH_SEND;
1381
1382         /* check for debug */
1383         if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
1384                 details->option.debug = AST_FAX_OPTFLAG_TRUE;
1385         }
1386
1387         /* check for request for status events */
1388         if (ast_test_flag(&opts, OPT_STATUS)) {
1389                 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
1390         }
1391
1392         if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) ||
1393             ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
1394                 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
1395         }
1396
1397         if ((channel_alive = generic_fax_exec(chan, details)) < 0) {
1398                 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1399         }
1400         
1401         /* send out the AMI completion event */
1402         ast_channel_lock(chan);
1403         get_manager_event_info(chan, &info);
1404         manager_event(EVENT_FLAG_CALL,
1405                       "SendFAX", 
1406                       "Channel: %s\r\n"
1407                       "Context: %s\r\n"
1408                       "Exten: %s\r\n"
1409                       "CallerID: %s\r\n"
1410                       "RemoteStationID: %s\r\n"
1411                       "LocalStationID: %s\r\n"
1412                       "PagesTransferred: %s\r\n"
1413                       "Resolution: %s\r\n"
1414                       "TransferRate: %s\r\n"
1415                       "FileName: %s\r\n",
1416                       chan->name,
1417                       info.context,
1418                       info.exten,
1419                       info.cid,
1420                       pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"),
1421                       pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"),
1422                       pbx_builtin_getvar_helper(chan, "FAXPAGES"),
1423                       pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"),
1424                       pbx_builtin_getvar_helper(chan, "FAXBITRATE"),
1425                       args.filename);
1426         ast_channel_unlock(chan);
1427
1428         ao2_ref(details, -1);
1429
1430         /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
1431         return (!channel_alive) ? -1 : 0;
1432 }
1433
1434 /*! \brief hash callback for ao2 */
1435 static int session_hash_cb(const void *obj, const int flags)
1436 {
1437         const struct ast_fax_session *s = obj;
1438
1439         return s->id;
1440 }
1441
1442 /*! \brief compare callback for ao2 */
1443 static int session_cmp_cb(void *obj, void *arg, int flags)
1444 {
1445         struct ast_fax_session *lhs = obj, *rhs = arg;
1446
1447         return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
1448 }
1449
1450 /*! \brief FAX session tab completion */
1451 static char *fax_session_tab_complete(struct ast_cli_args *a) 
1452 {
1453         int tklen;
1454         int wordnum = 0;
1455         char *name = NULL;
1456         struct ao2_iterator i;
1457         struct ast_fax_session *s;
1458         char tbuf[5];
1459
1460         if (a->pos != 3) {
1461                 return NULL;
1462         }
1463
1464         tklen = strlen(a->word);
1465         i = ao2_iterator_init(faxregistry.container, 0);
1466         while ((s = ao2_iterator_next(&i))) {
1467                 snprintf(tbuf, sizeof(tbuf), "%d", s->id);
1468                 if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
1469                         name = ast_strdup(tbuf);
1470                         ao2_ref(s, -1);
1471                         break;
1472                 }
1473                 ao2_ref(s, -1);
1474         }
1475         if (ao2_iterator_destroy != NULL) {
1476                 ao2_iterator_destroy(&i);
1477         }
1478         return name;
1479 }
1480
1481 /*! \brief enable FAX debugging */
1482 static char *cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1483 {
1484         int flag;
1485         const char *what;
1486
1487         switch (cmd) {
1488         case CLI_INIT:
1489                 e->command = "fax set debug {on|off}";
1490                 e->usage = 
1491                         "Usage: fax set debug { on | off }\n"
1492                         "       Enable/Disable FAX debugging on new FAX sessions.  The basic FAX debugging will result in\n"
1493                         "       additional events sent to manager sessions with 'call' class permissions.  When\n"
1494                         "       verbosity is greater than '5' events will be displayed to the console and audio versus\n"
1495                         "       energy analysis will be performed and displayed to the console.\n";
1496                 return NULL;
1497         case CLI_GENERATE:
1498                 return NULL;
1499         }
1500
1501         what = a->argv[e->args-1];      /* guaranteed to exist */
1502         if (!strcasecmp(what, "on")) {
1503                 flag = 1;
1504         } else if (!strcasecmp(what, "off")) {
1505                 flag = 0;
1506         } else {
1507                 return CLI_SHOWUSAGE;
1508         }
1509
1510         global_fax_debug = flag;
1511         ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
1512
1513         return CLI_SUCCESS;
1514 }
1515
1516 /*! \brief display registered FAX capabilities */
1517 static char *cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1518 {
1519         struct fax_module *fax;
1520         unsigned int num_modules = 0;
1521         
1522         switch (cmd) {
1523         case CLI_INIT:
1524                 e->command = "fax show capabilities";
1525                 e->usage = 
1526                         "Usage: fax show capabilities\n"
1527                         "       Shows the capabilities of the registered FAX technology modules\n";
1528                 return NULL;
1529         case CLI_GENERATE:
1530                 return NULL;
1531         }
1532
1533         ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
1534         AST_RWLIST_RDLOCK(&faxmodules);
1535         AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
1536                 ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
1537                 fax->tech->cli_show_capabilities(a->fd);
1538                 num_modules++;
1539         }
1540         AST_RWLIST_UNLOCK(&faxmodules);
1541         ast_cli(a->fd, "%d registered modules\n\n", num_modules);
1542
1543         return CLI_SUCCESS;
1544 }
1545
1546 /*! \brief display details of a specified FAX session */
1547 static char *cli_fax_show_session(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1548 {
1549         struct ast_fax_session *s, tmp;
1550
1551         switch (cmd) {
1552         case CLI_INIT:
1553                 e->command = "fax show session";
1554                 e->usage =
1555                         "Usage: fax show session <session number>\n"
1556                         "       Shows status of the named FAX session\n";
1557                 return NULL;
1558         case CLI_GENERATE:
1559                 return fax_session_tab_complete(a);
1560         }
1561
1562         if (a->argc != 4) {
1563                 return CLI_SHOWUSAGE;
1564         }
1565
1566         if (sscanf(a->argv[3], "%d", &tmp.id) != 1) {
1567                 ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
1568                 return RESULT_SUCCESS;
1569         }
1570
1571         ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
1572         s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
1573         if (s) {
1574                 s->tech->cli_show_session(s, a->fd);
1575                 ao2_ref(s, -1);
1576         }
1577         ast_cli(a->fd, "\n\n");
1578
1579         return CLI_SUCCESS;
1580 }
1581         
1582 /*! \brief display fax stats */
1583 static char *cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1584 {
1585         struct fax_module *fax;
1586         
1587         switch (cmd) {
1588         case CLI_INIT:
1589                 e->command = "fax show stats";
1590                 e->usage =
1591                         "Usage: fax show stats\n"
1592                         "       Shows a statistical summary of FAX transmissions\n";
1593                 return NULL;
1594         case CLI_GENERATE:
1595                 return NULL;
1596         }
1597
1598         ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
1599         ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
1600         ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
1601         ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
1602         ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
1603         ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
1604         AST_RWLIST_RDLOCK(&faxmodules);
1605         AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
1606                 fax->tech->cli_show_stats(a->fd);
1607         }
1608         AST_RWLIST_UNLOCK(&faxmodules);
1609         ast_cli(a->fd, "\n\n");
1610
1611         return CLI_SUCCESS;
1612 }
1613
1614 /*! \brief display fax sessions */
1615 static char *cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1616 {
1617         struct ast_fax_session *s;
1618         struct ao2_iterator i;
1619         int session_count;
1620
1621         switch (cmd) {
1622         case CLI_INIT:
1623                 e->command = "fax show sessions";
1624                 e->usage =
1625                         "Usage: fax show sessions\n"
1626                         "       Shows the current FAX sessions\n";
1627                 return NULL;
1628         case CLI_GENERATE:
1629                 return NULL;
1630         }
1631
1632         ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
1633         ast_cli(a->fd, "%-20.20s %-10.10s %-10.10s %-10.10s %-15.15s %-30.30s\n",
1634                 "Channel", "ID", "Type", "Operation", "State", "File");
1635         i = ao2_iterator_init(faxregistry.container, 0);
1636         while ((s = ao2_iterator_next(&i))) {
1637                 ao2_lock(s);
1638                 ast_cli(a->fd, "%-20.20s %-10d %-10.10s %-10.10s %-15.15s %-30.30s\n",
1639                         s->channame, s->id, s->tech->type, (s->details->caps & AST_FAX_TECH_SEND) ? "send" : "receive",
1640                         ast_fax_state_to_str(s->state), AST_LIST_FIRST(&s->details->documents)->filename);
1641                 ao2_unlock(s);
1642                 ao2_ref(s, -1);
1643         }
1644         if (ao2_iterator_destroy != NULL) {
1645                 ao2_iterator_destroy(&i);
1646         }
1647         session_count = ao2_container_count(faxregistry.container);
1648         ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
1649
1650         return CLI_SUCCESS;
1651 }
1652
1653 static struct ast_cli_entry fax_cli[] = {
1654         AST_CLI_DEFINE(cli_fax_set_debug, "Enable/Disable FAX debugging on new FAX sessions"),
1655         AST_CLI_DEFINE(cli_fax_show_capabilities, "Show the capabilities of the registered FAX technology modules"),
1656         AST_CLI_DEFINE(cli_fax_show_session, "Show the status of the named FAX sessions"),
1657         AST_CLI_DEFINE(cli_fax_show_sessions, "Show the current FAX sessions"),
1658         AST_CLI_DEFINE(cli_fax_show_stats, "Summarize FAX session history"),
1659 };
1660
1661 /*! \brief configure res_fax */
1662 static int set_config(const char *config_file)
1663 {
1664         struct ast_config *cfg;
1665         struct ast_variable *v;
1666         struct ast_flags config_flags = { 0 };
1667
1668         /* set defaults */      
1669         general_options.minrate = RES_FAX_MINRATE;
1670         general_options.maxrate = RES_FAX_MAXRATE;      
1671         general_options.statusevents = RES_FAX_STATUSEVENTS;
1672         general_options.modems = RES_FAX_MODEM;
1673
1674         /* read configuration */
1675         if (!(cfg = ast_config_load2(config_file, "res_fax", config_flags))) {
1676                 ast_log(LOG_NOTICE, "Configuration file '%s' not found, using default options.\n", config_file);
1677                 return 0;
1678         }
1679         if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
1680                 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
1681                 cfg = ast_config_load2(config_file, "res_fax", config_flags);
1682         }
1683
1684         /* create configuration */
1685         for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
1686                 int rate;
1687
1688                 if (!strcasecmp(v->name, "minrate")) {
1689                         ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
1690                         if ((rate = fax_rate_str_to_int(v->value)) == -1) {
1691                                 ast_config_destroy(cfg);
1692                                 return -1;
1693                         }
1694                         general_options.minrate = rate;
1695                 } else if (!strcasecmp(v->name, "maxrate")) {
1696                         ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
1697                         if ((rate = fax_rate_str_to_int(v->value)) == -1) {
1698                                 ast_config_destroy(cfg);
1699                                 return -1;
1700                         }
1701                         general_options.maxrate = rate;
1702                 } else if (!strcasecmp(v->name, "statusevents")) {
1703                         ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
1704                         general_options.statusevents = ast_true(v->value);
1705                 } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
1706                         general_options.modems = 0;
1707                         update_modem_bits(&general_options.modems, v->value);
1708                 }
1709         }
1710
1711         ast_config_destroy(cfg);
1712
1713         return 0;
1714 }
1715
1716 /*! \brief FAXOPT read function returns the contents of a FAX option */
1717 static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1718 {
1719         struct ast_fax_session_details *details = find_details(chan);
1720         int res = 0;
1721
1722         if (!details) {
1723                 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
1724                 return -1;
1725         }
1726         if (!strcasecmp(data, "ecm")) {
1727                 ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
1728         } else if (!strcasecmp(data, "error")) {
1729                 ast_copy_string(buf, details->error, len);
1730         } else if (!strcasecmp(data, "filename")) {
1731                 ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
1732         } else if (!strcasecmp(data, "headerinfo")) {
1733                 ast_copy_string(buf, details->headerinfo, len);
1734         } else if (!strcasecmp(data, "localstationid")) {
1735                 ast_copy_string(buf, details->localstationid, len);
1736         } else if (!strcasecmp(data, "maxrate")) {
1737                 snprintf(buf, len, "%d", details->maxrate);
1738         } else if (!strcasecmp(data, "minrate")) {
1739                 snprintf(buf, len, "%d", details->minrate);
1740         } else if (!strcasecmp(data, "pages")) {
1741                 snprintf(buf, len, "%d", details->pages_transferred);
1742         } else if (!strcasecmp(data, "rate")) {
1743                 ast_copy_string(buf, details->transfer_rate, len);
1744         } else if (!strcasecmp(data, "remotestationid")) {
1745                 ast_copy_string(buf, details->remotestationid, len);
1746         } else if (!strcasecmp(data, "resolution")) {
1747                 ast_copy_string(buf, details->resolution, len);
1748         } else if (!strcasecmp(data, "sessionid")) {
1749                 snprintf(buf, len, "%d", details->id);
1750         } else if (!strcasecmp(data, "status")) {
1751                 ast_copy_string(buf, details->result, len);
1752         } else if (!strcasecmp(data, "statusstr")) {
1753                 ast_copy_string(buf, details->resultstr, len);
1754         } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
1755                 ast_fax_modem_to_str(details->modems, buf, len);
1756         } else {
1757                 ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", chan->name, data);
1758                 res = -1;
1759         }
1760         ao2_ref(details, -1);
1761
1762         return res;
1763 }
1764
1765 /*! \brief FAXOPT write function modifies the contents of a FAX option */
1766 static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1767 {
1768         int res = 0;
1769         struct ast_fax_session_details *details;
1770
1771         if (!(details = find_or_create_details(chan))) {
1772                 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);
1773                 return -1;
1774         }
1775         ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", chan->name, data, value);
1776
1777         if (!strcasecmp(data, "ecm")) {
1778                 const char *val = ast_skip_blanks(value);
1779                 if (ast_true(val)) {
1780                         details->option.ecm = AST_FAX_OPTFLAG_TRUE;
1781                 } else if (ast_false(val)) {
1782                         details->option.ecm = AST_FAX_OPTFLAG_FALSE;
1783                 } else {
1784                         ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
1785                 }
1786         } else if (!strcasecmp(data, "headerinfo")) {
1787                 ast_string_field_set(details, headerinfo, value);
1788         } else if (!strcasecmp(data, "localstationid")) {
1789                 ast_string_field_set(details, localstationid, value);
1790         } else if (!strcasecmp(data, "maxrate")) {
1791                 details->maxrate = fax_rate_str_to_int(value);
1792         } else if (!strcasecmp(data, "minrate")) {
1793                 details->minrate = fax_rate_str_to_int(value);
1794         } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
1795                 update_modem_bits(&details->modems, value);
1796         } else {
1797                 ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", chan->name, data, value);
1798                 res = -1;
1799         }
1800
1801         ao2_ref(details, -1);
1802
1803         return res;
1804 }
1805
1806 /*! \brief FAXOPT dialplan function */
1807 struct ast_custom_function acf_faxopt = {
1808         .name = "FAXOPT",
1809         .synopsis = "Set options for use with the SendFAX and ReceiveFAX functions, or read options after a FAX transmission completes",
1810         .syntax = 
1811 "FAXOPT(<option>)\n"
1812 "  To write an option:\n"
1813 "     exten => blah,n,Set(FAXOPT(minrate)=4800)\n"
1814 "  To read an option:\n"
1815 "     exten => blah,n,NoOp(result: ${FAXOPT(status)})",
1816         .desc =
1817 "The following table outlines the <options> that can be used with FAXOPT\n\n"
1818 "  OPTION             TYPE     DESCRIPTION\n"
1819 "  ------             ----     -----------\n"
1820 "  ecm                 RW      Specify Error Correction Mode (ECM) with 'yes', disable with 'no'.\n"
1821 "  error               RO      Read the FAX transmission error upon failure.\n"
1822 "  filename            RO      Read the filename of the FAX transmission.\n"
1823 "  headerinfo          RW      Specify or read the FAX header.\n"
1824 "  localstationid      RW      Specify or read the local station identification\n"
1825 "  maxrate             RW      Specify or read the maximum transfer rate before transmission\n"
1826 "  minrate             RW      Specify or read the minimum transfer rate before transmission\n"
1827 "  modem               RW      Specify or read the FAX modem\n"
1828 "  pages               RO      Read the number of pages transferred\n"
1829 "  rate                RO      Read the negotiated transmission rate\n"
1830 "  remotestationid     RO      Read the remote station identification after the transmission\n"
1831 "  resolution          RO      Read the negotiated image resolution after the transmission\n"
1832 "  sessionid           RO      Read the session ID of the FAX transmission\n"
1833 "  status              RO      Read the result status of the FAX transmission\n"
1834 "  statusstr           RO      Read a verbose result status of the FAX transmission\n"
1835 "\n  RO : Read Only\n  RW : Read/Write\n  WO : Write Only\n"
1836 "",
1837         .read = acf_faxopt_read,
1838         .write = acf_faxopt_write,
1839 };
1840
1841 /*! \brief unload res_fax */
1842 static int unload_module(void)
1843 {
1844         ast_cli_unregister_multiple(fax_cli, ARRAY_LEN(fax_cli));
1845         
1846         if (ast_custom_function_unregister(&acf_faxopt) < 0) {
1847                 ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
1848         }
1849
1850         if (ast_unregister_application(app_sendfax) < 0) {
1851                 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
1852         }
1853
1854         if (ast_unregister_application(app_receivefax) < 0) {
1855                 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
1856         }
1857
1858         ao2_ref(faxregistry.container, -1);
1859
1860         return 0;
1861 }
1862
1863 /*! \brief load res_fax */
1864 static int load_module(void)
1865 {
1866         int res;
1867
1868         /* initialize the registry */
1869         faxregistry.active_sessions = 0;
1870         if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) {
1871                 return AST_MODULE_LOAD_DECLINE;
1872         }
1873         
1874         if (set_config(config) < 0) {
1875                 ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
1876                 ao2_ref(faxregistry.container, -1);
1877                 return AST_MODULE_LOAD_DECLINE;
1878         }
1879
1880         /* register CLI operations and applications */
1881         if (ast_register_application(app_sendfax, sendfax_exec, synopsis_sendfax, descrip_sendfax) < 0) {
1882                 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
1883                 ao2_ref(faxregistry.container, -1);
1884                 return AST_MODULE_LOAD_DECLINE;
1885         }
1886         if (ast_register_application(app_receivefax, receivefax_exec, synopsis_receivefax, descrip_receivefax) < 0) {
1887                 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
1888                 ast_unregister_application(app_sendfax);
1889                 ao2_ref(faxregistry.container, -1);
1890                 return AST_MODULE_LOAD_DECLINE;
1891         }
1892         ast_cli_register_multiple(fax_cli, ARRAY_LEN(fax_cli));
1893         res = ast_custom_function_register(&acf_faxopt);        
1894
1895         return res;
1896 }
1897
1898
1899 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Generic FAX Applications",
1900                 .load = load_module,
1901                 .unload = unload_module,
1902                );