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