Asterisk - The Open Source Telephony Project GIT-master-f36a736
res_fax.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2008-2009, Digium, Inc.
5 *
6 * Dwayne M. Hubbard <dhubbard@digium.com>
7 * Kevin P. Fleming <kpfleming@digium.com>
8 * Matthew Nicholson <mnicholson@digium.com>
9 *
10 * Initial T.38-gateway code
11 * 2008, Daniel Ferenci <daniel.ferenci@nethemba.com>
12 * Created by Nethemba s.r.o. http://www.nethemba.com
13 * Sponsored by IPEX a.s. http://www.ipex.cz
14 *
15 * T.38-gateway integration into asterisk app_fax and rework
16 * 2008-2011, Gregory Hinton Nietsky <gregory@distrotech.co.za>
17 * dns Telecom http://www.dnstelecom.co.za
18 *
19 * Modified to make T.38-gateway compatible with Asterisk 1.6.2
20 * 2010, Anton Verevkin <mymail@verevkin.it>
21 * ViaNetTV http://www.vianettv.com
22 *
23 * Modified to make T.38-gateway work
24 * 2010, Klaus Darilion, IPCom GmbH, www.ipcom.at
25 *
26 * See http://www.asterisk.org for more information about
27 * the Asterisk project. Please do not directly contact
28 * any of the maintainers of this project for assistance;
29 * the project provides a web site, mailing lists and IRC
30 * channels for your use.
31 *
32 * This program is free software, distributed under the terms of
33 * the GNU General Public License Version 2. See the LICENSE file
34 * at the top of the source tree.
35 */
36
37/*** MODULEINFO
38 <support_level>core</support_level>
39***/
40
41/*! \file
42 *
43 * \brief Generic FAX Resource for FAX technology resource modules
44 *
45 * \author Dwayne M. Hubbard <dhubbard@digium.com>
46 * \author Kevin P. Fleming <kpfleming@digium.com>
47 * \author Matthew Nicholson <mnicholson@digium.com>
48 * \author Gregory H. Nietsky <gregory@distrotech.co.za>
49 *
50 * A generic FAX resource module that provides SendFAX and ReceiveFAX applications.
51 * This module requires FAX technology modules, like res_fax_spandsp, to register with it
52 * so it can use the technology modules to perform the actual FAX transmissions.
53 * \ingroup applications
54 */
55
56/*! \li \ref res_fax.c uses the configuration file \ref res_fax.conf
57 * \addtogroup configuration_file Configuration Files
58 */
59
60/*!
61 * \page res_fax.conf res_fax.conf
62 * \verbinclude res_fax.conf.sample
63 */
64
65#include "asterisk.h"
66
67#include "asterisk/io.h"
68#include "asterisk/file.h"
69#include "asterisk/logger.h"
70#include "asterisk/module.h"
71#include "asterisk/app.h"
72#include "asterisk/lock.h"
73#include "asterisk/options.h"
74#include "asterisk/strings.h"
75#include "asterisk/cli.h"
76#include "asterisk/utils.h"
77#include "asterisk/config.h"
78#include "asterisk/astobj2.h"
79#include "asterisk/res_fax.h"
80#include "asterisk/file.h"
81#include "asterisk/channel.h"
82#include "asterisk/pbx.h"
83#include "asterisk/dsp.h"
86#include "asterisk/translate.h"
87#include "asterisk/stasis.h"
89#include "asterisk/smoother.h"
91
92/*** DOCUMENTATION
93 <application name="ReceiveFAX" language="en_US" module="res_fax">
94 <synopsis>
95 Receive a FAX and save as a TIFF/F file.
96 </synopsis>
97 <syntax>
98 <parameter name="filename" required="true" />
99 <parameter name="options">
100 <optionlist>
101 <option name="d">
102 <para>Enable FAX debugging.</para>
103 </option>
104 <option name="f">
105 <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
106 </option>
107 <option name="F">
108 <para>Force usage of audio mode on T.38 capable channels.</para>
109 </option>
110 <option name="s">
111 <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
112 </option>
113 </optionlist>
114 </parameter>
115 </syntax>
116 <description>
117 <para>This application is provided by res_fax, which is a FAX technology agnostic module
118 that utilizes FAX technology resource modules to complete a FAX transmission.</para>
119 <para>Session arguments can be set by the FAXOPT function and to check results of the ReceiveFAX() application.</para>
120 </description>
121 <see-also>
122 <ref type="function">FAXOPT</ref>
123 </see-also>
124 </application>
125 <application name="SendFAX" language="en_US" module="res_fax">
126 <synopsis>
127 Sends a specified TIFF/F file as a FAX.
128 </synopsis>
129 <syntax>
130 <parameter name="filename" required="true" argsep="&amp;">
131 <argument name="filename2" multiple="true">
132 <para>TIFF file to send as a FAX.</para>
133 </argument>
134 </parameter>
135 <parameter name="options">
136 <optionlist>
137 <option name="d">
138 <para>Enable FAX debugging.</para>
139 </option>
140 <option name="f">
141 <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
142 </option>
143 <option name="F">
144 <para>Force usage of audio mode on T.38 capable channels.</para>
145 </option>
146 <option name="s">
147 <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
148 </option>
149 <option name="z">
150 <para>Initiate a T.38 reinvite on the channel if the remote end does not.</para>
151 </option>
152 </optionlist>
153 </parameter>
154 </syntax>
155 <description>
156 <para>This application is provided by res_fax, which is a FAX technology agnostic module
157 that utilizes FAX technology resource modules to complete a FAX transmission.</para>
158 <para>Session arguments can be set by the FAXOPT function and to check results of the SendFAX() application.</para>
159 </description>
160 <see-also>
161 <ref type="function">FAXOPT</ref>
162 </see-also>
163 </application>
164 <function name="FAXOPT" language="en_US" module="res_fax">
165 <synopsis>
166 Gets/sets various pieces of information about a fax session.
167 </synopsis>
168 <syntax>
169 <parameter name="item" required="true">
170 <enumlist>
171 <enum name="ecm">
172 <para>R/W Error Correction Mode (ECM) enable with 'yes', disable with 'no'.</para>
173 </enum>
174 <enum name="error">
175 <para>R/O FAX transmission error code upon failure.</para>
176 </enum>
177 <enum name="filename">
178 <para>R/O Filename of the first file of the FAX transmission.</para>
179 </enum>
180 <enum name="filenames">
181 <para>R/O Filenames of all of the files in the FAX transmission (comma separated).</para>
182 </enum>
183 <enum name="headerinfo">
184 <para>R/W FAX header information.</para>
185 </enum>
186 <enum name="localstationid">
187 <para>R/W Local Station Identification.</para>
188 </enum>
189 <enum name="minrate">
190 <para>R/W Minimum transfer rate set before transmission.</para>
191 </enum>
192 <enum name="maxrate">
193 <para>R/W Maximum transfer rate set before transmission.</para>
194 </enum>
195 <enum name="modem">
196 <para>R/W Modem type (v17/v27/v29).</para>
197 </enum>
198 <enum name="gateway">
199 <para>R/W T38 fax gateway, with optional fax activity timeout in seconds (yes[,timeout]/no)</para>
200 </enum>
201 <enum name="faxdetect">
202 <para>R/W Enable FAX detect with optional timeout in seconds (yes,t38,cng[,timeout]/no)</para>
203 </enum>
204 <enum name="pages">
205 <para>R/O Number of pages transferred.</para>
206 </enum>
207 <enum name="rate">
208 <para>R/O Negotiated transmission rate.</para>
209 </enum>
210 <enum name="remotestationid">
211 <para>R/O Remote Station Identification after transmission.</para>
212 </enum>
213 <enum name="resolution">
214 <para>R/O Negotiated image resolution after transmission.</para>
215 </enum>
216 <enum name="sessionid">
217 <para>R/O Session ID of the FAX transmission.</para>
218 </enum>
219 <enum name="status">
220 <para>R/O Result Status of the FAX transmission.</para>
221 </enum>
222 <enum name="statusstr">
223 <para>R/O Verbose Result Status of the FAX transmission.</para>
224 </enum>
225 <enum name="t38timeout">
226 <para>R/W The timeout used for T.38 negotiation.</para>
227 </enum>
228 <enum name="negotiate_both">
229 <para>R/W Upon v21 detection allow gateway to send negotiation requests to both T.38 endpoints, and do not wait on the "other" side to initiate (yes|no)</para>
230 </enum>
231 </enumlist>
232 </parameter>
233 </syntax>
234 <description>
235 <para>FAXOPT can be used to override the settings for a FAX session listed in <filename>res_fax.conf</filename>,
236 it can also be used to retrieve information about a FAX session that has finished eg. pages/status.</para>
237 </description>
238 <see-also>
239 <ref type="application">ReceiveFAX</ref>
240 <ref type="application">SendFAX</ref>
241 </see-also>
242 </function>
243 <manager name="FAXSessions" language="en_US">
244 <synopsis>
245 Lists active FAX sessions
246 </synopsis>
247 <syntax>
248 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
249 </syntax>
250 <description>
251 <para>Will generate a series of FAXSession events with information about each FAXSession. Closes with
252 a FAXSessionsComplete event which includes a count of the included FAX sessions. This action works in
253 the same manner as the CLI command 'fax show sessions'</para>
254 </description>
255 </manager>
256 <managerEvent language="en_US" name="FAXSessionsEntry">
257 <managerEventInstance class="EVENT_FLAG_REPORTING">
258 <synopsis>A single list item for the FAXSessions AMI command</synopsis>
259 <syntax>
260 <parameter name="ActionID" required="false"/>
261 <parameter name="Channel">
262 <para>Name of the channel responsible for the FAX session</para>
263 </parameter>
264 <parameter name="Technology">
265 <para>The FAX technology that the FAX session is using</para>
266 </parameter>
267 <parameter name="SessionNumber">
268 <para>The numerical identifier for this particular session</para>
269 </parameter>
270 <parameter name="SessionType">
271 <para>FAX session passthru/relay type</para>
272 <enumlist>
273 <enum name="G.711" />
274 <enum name="T.38" />
275 </enumlist>
276 </parameter>
277 <parameter name="Operation">
278 <para>FAX session operation type</para>
279 <enumlist>
280 <enum name="gateway" />
281 <enum name="V.21" />
282 <enum name="send" />
283 <enum name="receive" />
284 <enum name="none" />
285 </enumlist>
286 </parameter>
287 <parameter name="State">
288 <para>Current state of the FAX session</para>
289 <enumlist>
290 <enum name="Uninitialized" />
291 <enum name="Initialized" />
292 <enum name="Open" />
293 <enum name="Active" />
294 <enum name="Complete" />
295 <enum name="Reserved" />
296 <enum name="Inactive" />
297 <enum name="Unknown" />
298 </enumlist>
299 </parameter>
300 <parameter name="Files">
301 <para>File or list of files associated with this FAX session</para>
302 </parameter>
303 </syntax>
304 </managerEventInstance>
305 </managerEvent>
306 <managerEvent language="en_US" name="FAXSessionsComplete">
307 <managerEventInstance class="EVENT_FLAG_CALL">
308 <synopsis>Raised when all FAXSession events are completed for a FAXSessions command</synopsis>
309 <syntax>
310 <parameter name="ActionID" required="false"/>
311 <parameter name="Total">
312 <para>Count of FAXSession events sent in response to FAXSessions action</para>
313 </parameter>
314 </syntax>
315 </managerEventInstance>
316 </managerEvent>
317 <manager name="FAXSession" language="en_US">
318 <synopsis>
319 Responds with a detailed description of a single FAX session
320 </synopsis>
321 <syntax>
322 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
323 <parameter name="SessionNumber" required="true">
324 <para>The session ID of the fax the user is interested in.</para>
325 </parameter>
326 </syntax>
327 <description>
328 <para>Provides details about a specific FAX session. The response will include a common subset of
329 the output from the CLI command 'fax show session &lt;session_number&gt;' for each technology. If the
330 FAX technolgy used by this session does not include a handler for FAXSession, then this action
331 will fail.</para>
332 </description>
333 </manager>
334 <managerEvent language="en_US" name="FAXSession">
335 <managerEventInstance class="EVENT_FLAG_REPORTING">
336 <synopsis>Raised in response to FAXSession manager command</synopsis>
337 <syntax>
338 <parameter name="ActionID" required="false"/>
339 <parameter name="SessionNumber">
340 <para>The numerical identifier for this particular session</para>
341 </parameter>
342 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FAXSessionsEntry']/managerEventInstance/syntax/parameter[@name='Operation'])" />
343 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FAXSessionsEntry']/managerEventInstance/syntax/parameter[@name='State'])" />
344 <parameter name="ErrorCorrectionMode" required="false">
345 <para>Whether error correcting mode is enabled for the FAX session. This field is not
346 included when operation is 'V.21 Detect' or if operation is 'gateway' and state is
347 'Uninitialized'
348 </para>
349 <enumlist>
350 <enum name="yes" />
351 <enum name="no" />
352 </enumlist>
353 </parameter>
354 <parameter name="DataRate" required="false">
355 <para>Bit rate of the FAX. This field is not included when operation is 'V.21 Detect' or
356 if operation is 'gateway' and state is 'Uninitialized'.</para>
357 </parameter>
358 <parameter name="ImageResolution" required="false">
359 <para>Resolution of each page of the FAX. Will be in the format of X_RESxY_RES. This field
360 is not included if the operation is anything other than Receive/Transmit.</para>
361 </parameter>
362 <parameter name="PageNumber" required="false">
363 <para>Current number of pages transferred during this FAX session. May change as the FAX
364 progresses. This field is not included when operation is 'V.21 Detect' or if operation is
365 'gateway' and state is 'Uninitialized'.</para>
366 </parameter>
367 <parameter name="FileName" required="false">
368 <para>Filename of the image being sent/received for this FAX session. This field is not
369 included if Operation isn't 'send' or 'receive'.</para>
370 </parameter>
371 <parameter name="PagesTransmitted" required="false">
372 <para>Total number of pages sent during this session. This field is not included if
373 Operation isn't 'send' or 'receive'. Will always be 0 for 'receive'.</para>
374 </parameter>
375 <parameter name="PagesReceived" required="false">
376 <para>Total number of pages received during this session. This field is not included if
377 Operation is not 'send' or 'receive'. Will be 0 for 'send'.</para>
378 </parameter>
379 <parameter name="TotalBadLines" required="false">
380 <para>Total number of bad lines sent/received during this session. This field is not
381 included if Operation is not 'send' or 'received'.</para>
382 </parameter>
383 </syntax>
384 </managerEventInstance>
385 </managerEvent>
386 <manager name="FAXStats" language="en_US">
387 <synopsis>
388 Responds with fax statistics
389 </synopsis>
390 <syntax>
391 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
392 </syntax>
393 <description>
394 <para>Provides FAX statistics including the number of active sessions, reserved sessions, completed
395 sessions, failed sessions, and the number of receive/transmit attempts. This command provides all
396 of the non-technology specific information provided by the CLI command 'fax show stats'</para>
397 </description>
398 </manager>
399 <managerEvent language="en_US" name="FAXStats">
400 <managerEventInstance class="EVENT_FLAG_REPORTING">
401 <synopsis>Raised in response to FAXStats manager command</synopsis>
402 <syntax>
403 <parameter name="ActionID" required="false"/>
404 <parameter name="CurrentSessions" required="true">
405 <para>Number of active FAX sessions</para>
406 </parameter>
407 <parameter name="ReservedSessions" required="true">
408 <para>Number of reserved FAX sessions</para>
409 </parameter>
410 <parameter name="TransmitAttempts" required="true">
411 <para>Total FAX sessions for which Asterisk is/was the transmitter</para>
412 </parameter>
413 <parameter name="ReceiveAttempts" required="true">
414 <para>Total FAX sessions for which Asterisk is/was the recipient</para>
415 </parameter>
416 <parameter name="CompletedFAXes" required="true">
417 <para>Total FAX sessions which have been completed successfully</para>
418 </parameter>
419 <parameter name="FailedFAXes" required="true">
420 <para>Total FAX sessions which failed to complete successfully</para>
421 </parameter>
422 </syntax>
423 </managerEventInstance>
424 </managerEvent>
425***/
426
427static const char app_receivefax[] = "ReceiveFAX";
428static const char app_sendfax[] = "SendFAX";
429
431 unsigned int consec_frames;
432 unsigned int consec_ms;
433 unsigned char silence;
434};
435
437 struct timeval base_tv;
439 struct ast_dsp *dsp;
440};
441
442/*! \brief used for gateway framehook */
444 /*! \brief FAX Session */
448 /*! \brief reserved fax session token */
449 struct ast_fax_tech_token *token;
450 /*! \brief the start of our timeout counter */
451 struct timeval timeout_start;
452 /*! \brief framehook used in gateway mode */
454 /*! \brief bridged */
455 int bridged:1;
456 /*! \brief 1 if a v21 preamble has been detected */
458 /*! \brief a flag to track the state of our negotiation */
460 /*! \brief original audio formats */
465};
466
467/*! \brief used for fax detect framehook */
469 /*! \brief the start of our timeout counter */
470 struct timeval timeout_start;
471 /*! \brief DSP Processor */
472 struct ast_dsp *dsp;
473 /*! \brief original audio formats */
475 /*! \brief fax session details */
477 /*! \brief mode */
478 int flags;
479};
480
481/*! \brief FAX Detect flags */
482#define FAX_DETECT_MODE_CNG (1 << 0)
483#define FAX_DETECT_MODE_T38 (1 << 1)
484#define FAX_DETECT_MODE_BOTH (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)
485
486static int fax_logger_level = -1;
487
488/*! \brief maximum buckets for res_fax ao2 containers */
489#define FAX_MAXBUCKETS 10
490
491#define RES_FAX_TIMEOUT 10000
492#define FAX_GATEWAY_TIMEOUT RES_FAX_TIMEOUT
493
494/*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */
495static struct {
496 /*! The number of active FAX sessions */
498 /*! The number of reserved FAX sessions */
500 /*! active sessions are astobj2 objects */
502 /*! Total number of Tx FAX attempts */
504 /*! Total number of Rx FAX attempts */
506 /*! Number of successful FAX transmissions */
508 /*! Number of failed FAX transmissions */
510 /*! the next unique session name */
513
514/*! \brief registered FAX technology modules are put into this list */
516 const struct ast_fax_tech *tech;
518};
520
521#define RES_FAX_MINRATE 4800
522#define RES_FAX_MAXRATE 14400
523#define RES_FAX_STATUSEVENTS 0
524#define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27TER | AST_FAX_MODEM_V29)
525#define RES_FAX_T38TIMEOUT 5000
526
529 uint32_t statusevents:1;
530 uint32_t ecm:1;
531 unsigned int minrate;
532 unsigned int maxrate;
533 unsigned int t38timeout;
534};
535
537
538static const struct fax_options default_options = {
540 .maxrate = RES_FAX_MAXRATE,
541 .statusevents = RES_FAX_STATUSEVENTS,
542 .modems = RES_FAX_MODEM,
544 .t38timeout = RES_FAX_T38TIMEOUT,
545};
546
548
549static void get_general_options(struct fax_options* options);
550static void set_general_options(const struct fax_options* options);
551
552static const char *config = "res_fax.conf";
553
554static int global_fax_debug = 0;
555
556enum {
557 OPT_CALLEDMODE = (1 << 0),
558 OPT_CALLERMODE = (1 << 1),
559 OPT_DEBUG = (1 << 2),
560 OPT_STATUS = (1 << 3),
561 OPT_ALLOWAUDIO = (1 << 5),
562 OPT_REQUEST_T38 = (1 << 6),
563 OPT_FORCE_AUDIO = (1 << 7),
564};
565
575
576static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
577{
578 struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
579 int dspsilence;
580 unsigned int last_consec_frames, last_consec_ms;
581 unsigned char wassil;
582 struct timeval diff;
583
584 diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
585
587 ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
588
589 wassil = history->silence;
590 history->silence = (dspsilence != 0) ? 1 : 0;
591 if (history->silence != wassil) {
592 last_consec_frames = history->consec_frames;
593 last_consec_ms = history->consec_ms;
594 history->consec_frames = 0;
595 history->consec_ms = 0;
596
597 if ((last_consec_frames != 0)) {
598 ast_verb(0, "Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
599 s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
600 (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
601 (wassil) ? "silence" : "energy");
602 }
603 }
604
605 history->consec_frames++;
606 history->consec_ms += (frame->samples / 8);
607}
608
609static void destroy_callback(void *data)
610{
611 if (data) {
612 ao2_ref(data, -1);
613 }
614}
615
616static void fixup_callback(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
617
618static const struct ast_datastore_info fax_datastore = {
619 .type = "res_fax",
620 .destroy = destroy_callback,
621 .chan_fixup = fixup_callback,
622};
623
624static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_details *details);
625static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags);
627static struct ast_fax_session *fax_v21_session_new (struct ast_channel *chan);
628
629
630/*! \brief Copies fax detection and gateway framehooks during masquerades
631 *
632 * \note must be called with both old_chan and new_chan locked. Since this
633 * is only called by do_masquerade, that shouldn't be an issue.
634 */
635static void fixup_callback(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
636{
637 struct ast_fax_session_details *old_details = data;
638 struct ast_datastore *datastore = ast_channel_datastore_find(old_chan, &fax_datastore, NULL);
639
640 if (old_details->gateway_id >= 0) {
641 struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
642
643 ast_framehook_detach(old_chan, old_details->gateway_id);
644 new_details->is_t38_negotiated = old_details->is_t38_negotiated;
645 fax_gateway_attach(new_chan, new_details);
646 ao2_cleanup(new_details);
647 }
648
649 if (old_details->faxdetect_id >= 0) {
650 ast_framehook_detach(old_chan, old_details->faxdetect_id);
651 fax_detect_attach(new_chan, old_details->faxdetect_timeout, old_details->faxdetect_flags);
652 }
653
654 if (datastore) {
655 ast_channel_datastore_remove(old_chan, datastore);
656 ast_datastore_free(datastore);
657 }
658}
659
660/*! \brief returns a reference counted pointer to a fax datastore, if it exists */
662{
663 struct ast_fax_session_details *details;
664 struct ast_datastore *datastore;
665
666 ast_channel_lock(chan);
667 if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
668 ast_channel_unlock(chan);
669 return NULL;
670 }
671 if (!(details = datastore->data)) {
672 ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", ast_channel_name(chan));
673 ast_channel_unlock(chan);
674 return NULL;
675 }
676 ao2_ref(details, 1);
677 ast_channel_unlock(chan);
678
679 return details;
680}
681
682/*! \brief destroy a FAX session details structure */
683static void destroy_session_details(void *details)
684{
685 struct ast_fax_session_details *d = details;
686 struct ast_fax_document *doc;
687
688 while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
689 ast_free(doc);
690 }
692}
693
694/*! \brief create a FAX session details structure */
696{
698 struct fax_options options;
699
700 if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
701 return NULL;
702 }
703
704 if (ast_string_field_init(d, 512)) {
705 ao2_ref(d, -1);
706 return NULL;
707 }
708
710
711 AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
712
713 /* These options need to be set to the configured default and may be overridden by
714 * SendFAX, ReceiveFAX, or FAXOPT */
715 d->option.request_t38 = AST_FAX_OPTFLAG_FALSE;
716 d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
717 d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
718 d->option.ecm = options.ecm;
719 d->option.statusevents = options.statusevents;
720 d->modems = options.modems;
721 d->minrate = options.minrate;
722 d->maxrate = options.maxrate;
723 d->t38timeout = options.t38timeout;
724 d->gateway_id = -1;
725 d->faxdetect_id = -1;
726 d->gateway_timeout = 0;
727 d->negotiate_both = 0;
728
729 return d;
730}
731
733 .version = 0,
734 .max_ifp = 400,
735 .rate = AST_T38_RATE_14400,
737};
738
740{
741 dst->version = src->version;
742 dst->max_ifp = src->max_ifp;
743 dst->rate = src->rate;
748}
749
751{
752 dst->version = src->version;
753 dst->max_ifp = src->max_ifp;
754 dst->rate = src->rate;
759}
760
761/*! \brief returns a reference counted details structure from the channel's fax datastore. If the datastore
762 * does not exist it will be created */
764{
765 struct ast_fax_session_details *details;
766 struct ast_datastore *datastore;
767
768 if ((details = find_details(chan))) {
769 return details;
770 }
771 /* channel does not have one so we must create one */
772 if (!(details = session_details_new())) {
773 ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", ast_channel_name(chan));
774 return NULL;
775 }
776 if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
777 ao2_ref(details, -1);
778 ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", ast_channel_name(chan));
779 return NULL;
780 }
781 /* add the datastore to the channel and increment the refcount */
782 datastore->data = details;
783
784 /* initialize default T.38 parameters */
787
788 ao2_ref(details, 1);
789 ast_channel_lock(chan);
790 ast_channel_datastore_add(chan, datastore);
791 ast_channel_unlock(chan);
792 return details;
793}
794
795unsigned int ast_fax_maxrate(void)
796{
797 struct fax_options options;
799
800 return options.maxrate;
801}
802
803unsigned int ast_fax_minrate(void)
804{
805 struct fax_options options;
807
808 return options.minrate;
809}
810
811static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
812{
813 char *m[5], *tok, *v = (char *) value, *rest;
814 int i = 0, j;
815
816 if (!strchr(v, ',')) {
817 m[i++] = v;
818 m[i] = NULL;
819 } else {
820 tok = strtok_r(v, ", ", &rest);
821 while (tok && i < ARRAY_LEN(m) - 1) {
822 m[i++] = tok;
823 tok = strtok_r(NULL, ", ", &rest);
824 }
825 m[i] = NULL;
826 }
827
828 *bits = 0;
829 for (j = 0; j < i; j++) {
830 if (!strcasecmp(m[j], "v17")) {
831 *bits |= AST_FAX_MODEM_V17;
832 } else if (!strcasecmp(m[j], "v27")) {
833 *bits |= AST_FAX_MODEM_V27TER;
834 } else if (!strcasecmp(m[j], "v29")) {
835 *bits |= AST_FAX_MODEM_V29;
836 } else if (!strcasecmp(m[j], "v34")) {
837 *bits |= AST_FAX_MODEM_V34;
838 } else {
839 ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
840 }
841 }
842 return 0;
843}
844
845static char *ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
846{
847 char *out = buf;
848 size_t size = bufsize;
849 int first = 1;
850
851 if (caps & AST_FAX_TECH_SEND) {
852 if (!first) {
853 ast_build_string(&buf, &size, ",");
854 }
855 ast_build_string(&buf, &size, "SEND");
856 first = 0;
857 }
858 if (caps & AST_FAX_TECH_RECEIVE) {
859 if (!first) {
860 ast_build_string(&buf, &size, ",");
861 }
862 ast_build_string(&buf, &size, "RECEIVE");
863 first = 0;
864 }
865 if (caps & AST_FAX_TECH_AUDIO) {
866 if (!first) {
867 ast_build_string(&buf, &size, ",");
868 }
869 ast_build_string(&buf, &size, "AUDIO");
870 first = 0;
871 }
872 if (caps & AST_FAX_TECH_T38) {
873 if (!first) {
874 ast_build_string(&buf, &size, ",");
875 }
876 ast_build_string(&buf, &size, "T38");
877 first = 0;
878 }
879 if (caps & AST_FAX_TECH_MULTI_DOC) {
880 if (!first) {
881 ast_build_string(&buf, &size, ",");
882 }
883 ast_build_string(&buf, &size, "MULTI_DOC");
884 first = 0;
885 }
886 if (caps & AST_FAX_TECH_GATEWAY) {
887 if (!first) {
888 ast_build_string(&buf, &size, ",");
889 }
890 ast_build_string(&buf, &size, "GATEWAY");
891 first = 0;
892 }
893 if (caps & AST_FAX_TECH_V21_DETECT) {
894 if (!first) {
895 ast_build_string(&buf, &size, ",");
896 }
897 ast_build_string(&buf, &size, "V21");
898 first = 0;
899 }
900
901 return out;
902}
903
904static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
905{
906 int count = 0;
907
908 if (bits & AST_FAX_MODEM_V17) {
909 strcat(tbuf, "V17");
910 count++;
911 }
912 if (bits & AST_FAX_MODEM_V27TER) {
913 if (count) {
914 strcat(tbuf, ",");
915 }
916 strcat(tbuf, "V27");
917 count++;
918 }
919 if (bits & AST_FAX_MODEM_V29) {
920 if (count) {
921 strcat(tbuf, ",");
922 }
923 strcat(tbuf, "V29");
924 count++;
925 }
926 if (bits & AST_FAX_MODEM_V34) {
927 if (count) {
928 strcat(tbuf, ",");
929 }
930 strcat(tbuf, "V34");
931 count++;
932 }
933
934 return 0;
935}
936
937static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
938{
939 switch (rate) {
940 case 2400:
941 case 4800:
943 return 1;
944 }
945 break;
946 case 7200:
947 case 9600:
949 return 1;
950 }
951 break;
952 case 12000:
953 case 14400:
955 return 1;
956 }
957 break;
958 case 28800:
959 case 33600:
960 if (!(modems & AST_FAX_MODEM_V34)) {
961 return 1;
962 }
963 break;
964 default:
965 /* this should never happen */
966 return 1;
967 }
968
969 return 0;
970}
971
972/*! \brief register a FAX technology module */
974{
975 struct fax_module *fax;
976
977 if (!(fax = ast_calloc(1, sizeof(*fax)))) {
978 return -1;
979 }
980 fax->tech = tech;
984
985 ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
986
987 return 0;
988}
989
990/*! \brief unregister a FAX technology module */
992{
993 struct fax_module *fax;
994
995 ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
996
999 if (fax->tech != tech) {
1000 continue;
1001 }
1003 ast_free(fax);
1004 ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
1005 break;
1006 }
1009}
1010
1011/*! \brief convert a ast_fax_state to a string */
1013{
1014 switch (state) {
1016 return "Uninitialized";
1018 return "Initialized";
1019 case AST_FAX_STATE_OPEN:
1020 return "Open";
1022 return "Active";
1024 return "Complete";
1026 return "Reserved";
1028 return "Inactive";
1029 default:
1030 ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state);
1031 return "Unknown";
1032 }
1033}
1034
1035void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
1036{
1037 if (fax_logger_level != -1) {
1039 } else {
1040 ast_log(level, file, line, function, "%s", msg);
1041 }
1042}
1043
1044/*! \brief convert a rate string to a rate */
1045static unsigned int fax_rate_str_to_int(const char *ratestr)
1046{
1047 int rate;
1048
1049 if (sscanf(ratestr, "%d", &rate) != 1) {
1050 ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
1051 return 0;
1052 }
1053 switch (rate) {
1054 case 2400:
1055 case 4800:
1056 case 7200:
1057 case 9600:
1058 case 12000:
1059 case 14400:
1060 case 28800:
1061 case 33600:
1062 return rate;
1063 default:
1064 ast_log(LOG_WARNING, "ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
1065 return 0;
1066 }
1067}
1068
1069/*! \brief Release a session token.
1070 * \param s a session returned from fax_session_reserve()
1071 * \param token a token generated from fax_session_reserve()
1072 *
1073 * This function releases the given token and marks the given session as no
1074 * longer reserved. It is safe to call on a session that is not actually
1075 * reserved and with a NULL token. This is so that sessions returned by
1076 * technologies that do not support reserved sessions don't require extra logic
1077 * to handle.
1078 *
1079 * \note This function DOES NOT release the given fax session, only the given
1080 * token.
1081 */
1082static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
1083{
1084 if (token) {
1085 s->tech->release_token(token);
1086 }
1087
1088 if (s->state == AST_FAX_STATE_RESERVED) {
1089 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1091 }
1092}
1093
1094/*! \brief destroy a FAX session structure */
1095static void destroy_session(void *session)
1096{
1097 struct ast_fax_session *s = session;
1098
1099 if (s->tech) {
1101 if (s->tech_pvt) {
1102 s->tech->destroy_session(s);
1103 }
1105 }
1106
1107 if (s->details) {
1108 if (s->details->caps & AST_FAX_TECH_GATEWAY) {
1109 s->details->caps &= ~AST_FAX_TECH_GATEWAY;
1110 }
1111 ao2_ref(s->details, -1);
1112 s->details = NULL;
1113 }
1114
1115 if (s->debug_info) {
1117 ast_free(s->debug_info);
1118 }
1119
1120 if (s->smoother) {
1122 }
1123
1124 if (s->state != AST_FAX_STATE_INACTIVE) {
1125 ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
1126 }
1127
1128 ast_free(s->channame);
1130}
1131
1132/*! \brief Reserve a fax session.
1133 * \param details the fax session details
1134 * \param token a pointer to a place to store a token to be passed to fax_session_new() later
1135 *
1136 * This function reserves a fax session for use later. If the selected fax
1137 * technology does not support reserving sessions a session will still be
1138 * returned but token will not be set.
1139 *
1140 * \note The reference returned by this function does not get consumed by
1141 * fax_session_new() and must always be dereferenced separately.
1142 *
1143 * \return NULL or an uninitialized and possibly reserved session
1144 */
1145static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
1146{
1147 struct ast_fax_session *s;
1148 struct fax_module *faxmod;
1149
1150 if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
1151 return NULL;
1152 }
1153
1155 s->details = details;
1156 ao2_ref(s->details, 1);
1157
1158 /* locate a FAX technology module that can handle said requirements
1159 * Note: the requirements have not yet been finalized as T.38
1160 * negotiation has not yet occured. */
1162 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
1163 if ((faxmod->tech->caps & details->caps) != details->caps) {
1164 continue;
1165 }
1166 if (!ast_module_running_ref(faxmod->tech->module)) {
1167 continue;
1168 }
1169 ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
1170 s->tech = faxmod->tech;
1171 break;
1172 }
1174
1175 if (!faxmod) {
1176 char caps[128] = "";
1177 ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->caps, caps, sizeof(caps)));
1178 ao2_ref(s, -1);
1179 return NULL;
1180 }
1181
1182 if (!s->tech->reserve_session) {
1183 ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
1184 return s;
1185 }
1186
1187 if (!(*token = s->tech->reserve_session(s))) {
1188 ao2_ref(s, -1);
1189 return NULL;
1190 }
1191
1193 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
1194
1195 return s;
1196}
1197
1198/*! \brief create a FAX session
1199 *
1200 * \param details details for the session
1201 * \param chan the channel the session will run on
1202 * \param reserved a reserved session to base this session on (can be NULL)
1203 * \param token the token for a reserved session (can be NULL)
1204 *
1205 * Create a new fax session based on the given details structure.
1206 *
1207 * \note The given token is always consumed (by tech->new_session() or by
1208 * fax_session_release() in the event of a failure). The given reference to a
1209 * reserved session is never consumed and must be dereferenced separately from
1210 * the reference returned by this function.
1211 *
1212 * \return NULL or a reference to a new fax session
1213 */
1214static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *details, struct ast_channel *chan, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
1215{
1216 struct ast_fax_session *s = NULL;
1217 struct fax_module *faxmod;
1218
1219 if (reserved) {
1220 s = reserved;
1221 ao2_ref(reserved, +1);
1222 ao2_unlink(faxregistry.container, reserved);
1223
1224 /* NOTE: we don't consume the reference to the reserved
1225 * session. The session returned from fax_session_new() is a
1226 * new reference and must be derefed in addition to the
1227 * reserved session.
1228 */
1229
1230 if (s->state == AST_FAX_STATE_RESERVED) {
1231 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1233 }
1234 }
1235
1236 if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
1237 return NULL;
1238 }
1239
1240 ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
1242
1243 if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
1244 if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
1245 fax_session_release(s, token);
1246 ao2_ref(s, -1);
1247 return NULL;
1248 }
1249 if (!(s->debug_info->dsp = ast_dsp_new())) {
1250 ast_free(s->debug_info);
1251 s->debug_info = NULL;
1252 fax_session_release(s, token);
1253 ao2_ref(s, -1);
1254 return NULL;
1255 }
1257 }
1258
1259 if (!(s->channame = ast_strdup(ast_channel_name(chan)))) {
1260 fax_session_release(s, token);
1261 ao2_ref(s, -1);
1262 return NULL;
1263 }
1264
1265 if (!(s->chan_uniqueid = ast_strdup(ast_channel_uniqueid(chan)))) {
1266 fax_session_release(s, token);
1267 ao2_ref(s, -1);
1268 return NULL;
1269 }
1270
1271 s->chan = chan;
1272 if (!s->details) {
1273 s->details = details;
1274 ao2_ref(s->details, 1);
1275 }
1276
1277 details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
1278
1279 if (!token) {
1280 /* locate a FAX technology module that can handle said requirements */
1282 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
1283 if ((faxmod->tech->caps & details->caps) != details->caps) {
1284 continue;
1285 }
1286 if (!ast_module_running_ref(faxmod->tech->module)) {
1287 continue;
1288 }
1289 ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
1290 if (reserved) {
1291 /* Balance module ref from reserved session */
1292 ast_module_unref(reserved->tech->module);
1293 }
1294 s->tech = faxmod->tech;
1295 break;
1296 }
1298
1299 if (!faxmod) {
1300 char caps[128] = "";
1301 ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->caps, caps, sizeof(caps)));
1302 ao2_ref(s, -1);
1303 return NULL;
1304 }
1305 }
1306
1307 if (!(s->tech_pvt = s->tech->new_session(s, token))) {
1308 ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
1309 ao2_ref(s, -1);
1310 return NULL;
1311 }
1312 /* link the session to the session container */
1313 if (!(ao2_link(faxregistry.container, s))) {
1314 ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id);
1315 ao2_ref(s, -1);
1316 return NULL;
1317 }
1318 ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id);
1319
1320 return s;
1321}
1322
1323/*!
1324 * \internal
1325 * \brief Convert the filenames in a fax session into a JSON array
1326 * \retval NULL on error
1327 * \retval A \ref ast_json array on success
1328 */
1330{
1331 RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
1332 struct ast_fax_document *doc;
1333
1334 if (!details || !json_array) {
1335 return NULL;
1336 }
1337
1338 /* don't process empty lists */
1339 if (AST_LIST_EMPTY(&details->documents)) {
1340 return NULL;
1341 }
1342
1343 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1345 if (!entry) {
1346 return NULL;
1347 }
1348 if (ast_json_array_append(json_array, entry)) {
1349 return NULL;
1350 }
1351 }
1352
1353 ast_json_ref(json_array);
1354 return json_array;
1355}
1356
1357/*!
1358 * \brief Generate a string of filenames using the given prefix and separator.
1359 * \param details the fax session details
1360 * \param prefix the prefix to each filename
1361 * \param separator the separator between filenames
1362 *
1363 * This function generates a string of filenames from the given details
1364 * structure and using the given prefix and separator.
1365 *
1366 * \retval NULL there was an error generating the string
1367 * \return the string generated string
1368 */
1369static char *generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
1370{
1371 char *filenames, *c;
1372 size_t size = 0;
1373 int first = 1;
1374 struct ast_fax_document *doc;
1375
1376 /* don't process empty lists */
1377 if (AST_LIST_EMPTY(&details->documents)) {
1378 return ast_strdup("");
1379 }
1380
1381 /* Calculate the total length of all of the file names */
1382 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1383 size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
1384 }
1385 size += 1; /* add space for the terminating null */
1386
1387 if (!(filenames = ast_malloc(size))) {
1388 return NULL;
1389 }
1390 c = filenames;
1391
1392 ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
1393 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1394 if (first) {
1395 first = 0;
1396 continue;
1397 }
1398
1399 ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
1400 }
1401
1402 return filenames;
1403}
1404
1405/*! \brief send a FAX status manager event */
1406static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
1407{
1408 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1410 struct ast_json *json_filenames = NULL;
1411
1412 if (!details->option.statusevents) {
1413 return 0;
1414 }
1415
1416 json_filenames = generate_filenames_json(details);
1417 if (!json_filenames) {
1418 return -1;
1419 }
1420
1421 json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}",
1422 "type", "status",
1423 "operation", (details->caps & AST_FAX_TECH_GATEWAY)
1424 ? "gateway"
1425 : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
1426 "status", status,
1427 "local_station_id", AST_JSON_UTF8_VALIDATE(details->localstationid),
1428 "filenames", json_filenames);
1429 if (!json_object) {
1430 return -1;
1431 }
1432
1433 {
1434 SCOPED_CHANNELLOCK(lock, chan);
1435
1437 if (!message) {
1438 return -1;
1439 }
1441 }
1442 return 0;
1443}
1444
1445/*! \brief Set fax related channel variables. */
1446static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
1447{
1448 char buf[10];
1449
1450 pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
1451 pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
1452 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
1453 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", AST_JSON_UTF8_VALIDATE(details->remotestationid));
1454 pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", AST_JSON_UTF8_VALIDATE(details->localstationid));
1455 pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
1456 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
1457
1458 if (details->is_t38_negotiated) {
1459 pbx_builtin_setvar_helper(chan, "FAXMODE", "T38");
1460 } else {
1461 pbx_builtin_setvar_helper(chan, "FAXMODE", "audio");
1462 }
1463
1464 snprintf(buf, sizeof(buf), "%u", details->pages_transferred);
1465 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
1466}
1467
1468#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason) \
1469 do { \
1470 if (ast_strlen_zero(fax->details->result)) \
1471 ast_string_field_set(fax->details, result, "FAILED"); \
1472 if (ast_strlen_zero(fax->details->resultstr)) \
1473 ast_string_field_set(fax->details, resultstr, reason); \
1474 if (ast_strlen_zero(fax->details->error)) \
1475 ast_string_field_set(fax->details, error, errorstr); \
1476 set_channel_variables(chan, fax->details); \
1477 } while (0)
1478
1479#define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) \
1480 do { \
1481 GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
1482 } while (0)
1483
1484#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) \
1485 do { \
1486 ast_log(LOG_ERROR, "channel '%s' FAX session '%u' failure, reason: '%s' (%s)\n", ast_channel_name(chan), fax->id, reason, errorstr); \
1487 GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
1488 } while (0)
1489
1490static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
1491{
1492 switch (ast_channel_get_t38_state(chan)) {
1493 case T38_STATE_UNKNOWN:
1494 details->caps |= AST_FAX_TECH_T38;
1495 break;
1496 case T38_STATE_REJECTED:
1498 details->caps |= AST_FAX_TECH_AUDIO;
1499 break;
1501 /* already in T.38 mode? This should not happen. */
1502 case T38_STATE_NEGOTIATING: {
1503 /* the other end already sent us a T.38 reinvite, so we need to prod the channel
1504 * driver into resending their parameters to us if it supports doing so... if
1505 * not, we can't proceed, because we can't create a proper reply without them.
1506 * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
1507 * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
1508 * that gets called after this one completes
1509 */
1511 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
1512 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1513 return -1;
1514 }
1515 details->caps |= AST_FAX_TECH_T38;
1516 break;
1517 }
1518 default:
1519 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1520 return -1;
1521 }
1522
1523 return 0;
1524}
1525
1526static int disable_t38(struct ast_channel *chan)
1527{
1528 int timeout_ms;
1529 struct ast_frame *frame = NULL;
1531 struct timeval start;
1532 int ms;
1533
1534 ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(chan));
1535 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
1536 ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1537 return -1;
1538 }
1539
1540 /* wait up to five seconds for negotiation to complete */
1541 timeout_ms = 5000;
1542 start = ast_tvnow();
1543 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1544 ms = ast_waitfor(chan, ms);
1545
1546 if (ms == 0) {
1547 break;
1548 }
1549 if (ms < 0) {
1550 ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1551 return -1;
1552 }
1553
1554 if (!(frame = ast_read(chan))) {
1555 return -1;
1556 }
1557 if ((frame->frametype == AST_FRAME_CONTROL) &&
1559 (frame->datalen == sizeof(t38_parameters))) {
1560 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1561
1562 switch (parameters->request_response) {
1563 case AST_T38_TERMINATED:
1564 ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(chan));
1565 break;
1566 case AST_T38_REFUSED:
1567 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(chan));
1568 ast_frfree(frame);
1569 return -1;
1570 default:
1571 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(chan));
1572 ast_frfree(frame);
1573 return -1;
1574 }
1575 ast_frfree(frame);
1576 break;
1577 }
1578 ast_frfree(frame);
1579 }
1580
1581 if (ms == 0) { /* all done, nothing happened */
1582 ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
1583 }
1584
1585 return 0;
1586}
1587
1588/*! \brief this is the generic FAX session handling function */
1589static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
1590{
1591 int ms;
1592 int timeout = RES_FAX_TIMEOUT;
1593 int chancount;
1594 unsigned int expected_frametype = -1;
1595 struct ast_frame_subclass expected_framesubclass = { .integer = 0, };
1596 unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
1597 struct ast_control_t38_parameters t38_parameters;
1598 const char *tempvar;
1599 struct ast_fax_session *fax = NULL;
1600 struct ast_frame *frame = NULL;
1601 struct ast_channel *c = chan;
1602 RAII_VAR(struct ast_format *, orig_write_format, NULL, ao2_cleanup);
1603 RAII_VAR(struct ast_format *, orig_read_format, NULL, ao2_cleanup);
1604 int remaining_time;
1605 struct timeval start;
1606
1607 chancount = 1;
1608
1609 /* Make sure one or the other is set to avoid race condition */
1610 if (t38negotiated) {
1611 details->caps |= AST_FAX_TECH_T38;
1612 } else {
1613 details->caps |= AST_FAX_TECH_AUDIO;
1614 }
1615
1616 /* create the FAX session */
1617 if (!(fax = fax_session_new(details, chan, reserved, token))) {
1618 ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
1619 report_fax_status(chan, details, "No Available Resource");
1620 return -1;
1621 }
1622
1623 ast_channel_lock(chan);
1624 /* update session details */
1625 if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
1626 ast_string_field_set(details, headerinfo, tempvar);
1627 }
1628 if (ast_strlen_zero(details->localstationid)) {
1629 tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
1630 ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
1631 }
1632 ast_channel_unlock(chan);
1633
1634 report_fax_status(chan, details, "Allocating Resources");
1635
1636 if (details->caps & AST_FAX_TECH_AUDIO) {
1637 expected_frametype = AST_FRAME_VOICE;
1638 expected_framesubclass.format = ast_format_slin;
1639 orig_write_format = ao2_bump(ast_channel_writeformat(chan));
1640 if (ast_set_write_format(chan, ast_format_slin) < 0) {
1641 ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
1642 ao2_unlink(faxregistry.container, fax);
1643 ao2_ref(fax, -1);
1644 return -1;
1645 }
1646 orig_read_format = ao2_bump(ast_channel_readformat(chan));
1647 if (ast_set_read_format(chan, ast_format_slin) < 0) {
1648 ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
1649 ao2_unlink(faxregistry.container, fax);
1650 ao2_ref(fax, -1);
1651 return -1;
1652 }
1653 if (fax->smoother) {
1655 fax->smoother = NULL;
1656 }
1657 if (!(fax->smoother = ast_smoother_new(320))) {
1658 ast_log(LOG_WARNING, "Channel '%s' FAX session '%u' failed to obtain a smoother.\n", ast_channel_name(chan), fax->id);
1659 }
1660 } else {
1661 expected_frametype = AST_FRAME_MODEM;
1662 expected_framesubclass.integer = AST_MODEM_T38;
1663 }
1664
1665 if (fax->debug_info) {
1666 fax->debug_info->base_tv = ast_tvnow();
1667 }
1668
1669 /* reset our result fields just in case the fax tech driver wants to
1670 * set custom error messages */
1671 ast_string_field_set(details, result, "");
1672 ast_string_field_set(details, resultstr, "");
1673 ast_string_field_set(details, error, "");
1674 details->is_t38_negotiated = t38negotiated;
1675 set_channel_variables(chan, details);
1676
1677 if (fax->tech->start_session(fax) < 0) {
1678 GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
1679 }
1680
1681 report_fax_status(chan, details, "FAX Transmission In Progress");
1682
1683 ast_debug(5, "channel %s will wait on FAX fd %d\n", ast_channel_name(chan), fax->fd);
1684
1685 /* handle frames for the session */
1686 remaining_time = timeout;
1687 start = ast_tvnow();
1688 while (remaining_time > 0) {
1689 struct ast_channel *ready_chan;
1690 int ofd, exception;
1691
1692 ms = 1000;
1693 errno = 0;
1694 ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
1695 if (ready_chan) {
1696 if (!(frame = ast_read(chan))) {
1697 /* the channel is probably gone, so lets stop polling on it and let the
1698 * FAX session complete before we exit the application. if needed,
1699 * send the FAX stack silence so the modems can finish their session without
1700 * any problems */
1701 ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
1702 GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
1703 c = NULL;
1704 chancount = 0;
1705 remaining_time = ast_remaining_ms(start, timeout);
1706 fax->tech->cancel_session(fax);
1707 if (fax->tech->generate_silence) {
1708 fax->tech->generate_silence(fax);
1709 }
1710 continue;
1711 }
1712
1713 if ((frame->frametype == AST_FRAME_CONTROL) &&
1715 (frame->datalen == sizeof(t38_parameters))) {
1716 unsigned int was_t38 = t38negotiated;
1717 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1718
1719 switch (parameters->request_response) {
1721 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1722 * do T.38 as well
1723 */
1724 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1725 if (details->caps & AST_FAX_TECH_T38) {
1726 details->is_t38_negotiated = 1;
1727 t38_parameters.request_response = AST_T38_NEGOTIATED;
1728 } else {
1729 t38_parameters.request_response = AST_T38_REFUSED;
1730 }
1731 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1732 break;
1733 case AST_T38_NEGOTIATED:
1734 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1735 t38negotiated = 1;
1736 details->is_t38_negotiated = 1;
1737 break;
1738 default:
1739 break;
1740 }
1741 if (t38negotiated && !was_t38) {
1742 if (fax->tech->switch_to_t38(fax)) {
1743 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "T.38 switch failed");
1744 break;
1745 }
1746 details->caps &= ~AST_FAX_TECH_AUDIO;
1747 expected_frametype = AST_FRAME_MODEM;
1748 expected_framesubclass.integer = AST_MODEM_T38;
1749 if (fax->smoother) {
1751 fax->smoother = NULL;
1752 }
1753
1754 report_fax_status(chan, details, "T.38 Negotiated");
1755
1756 ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", ast_channel_name(chan), fax->id);
1757 }
1758 } else if ((frame->frametype == expected_frametype) && (expected_framesubclass.integer == frame->subclass.integer) &&
1759 ((!frame->subclass.format && !expected_framesubclass.format) ||
1760 (frame->subclass.format && expected_framesubclass.format &&
1761 (ast_format_cmp(frame->subclass.format, expected_framesubclass.format) != AST_FORMAT_CMP_NOT_EQUAL)))) {
1762 struct ast_frame *f;
1763
1764 if (fax->smoother) {
1765 /* push the frame into a smoother */
1766 if (ast_smoother_feed(fax->smoother, frame) < 0) {
1767 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
1768 }
1769 while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
1770 if (fax->debug_info) {
1772 }
1773 /* write the frame to the FAX stack */
1774 fax->tech->write(fax, f);
1775 fax->frames_received++;
1776 if (f != frame) {
1777 ast_frfree(f);
1778 }
1779 }
1780 } else {
1781 /* write the frame to the FAX stack */
1782 fax->tech->write(fax, frame);
1783 fax->frames_received++;
1784 }
1785 start = ast_tvnow();
1786 }
1787 ast_frfree(frame);
1788 } else if (ofd == fax->fd) {
1789 /* read a frame from the FAX stack and send it out the channel.
1790 * the FAX stack will return a NULL if the FAX session has already completed */
1791 if (!(frame = fax->tech->read(fax))) {
1792 break;
1793 }
1794
1795 if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
1796 debug_check_frame_for_silence(fax, 0, frame);
1797 }
1798
1799 ast_write(chan, frame);
1800 fax->frames_sent++;
1801 ast_frfree(frame);
1802 start = ast_tvnow();
1803 } else {
1804 if (ms && (ofd < 0)) {
1805 if ((errno == 0) || (errno == EINTR)) {
1806 remaining_time = ast_remaining_ms(start, timeout);
1807 if (remaining_time <= 0)
1808 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1809 continue;
1810 } else {
1811 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(chan));
1812 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
1813 break;
1814 }
1815 } else {
1816 /* nothing happened */
1817 remaining_time = ast_remaining_ms(start, timeout);
1818 if (remaining_time <= 0) {
1819 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1820 break;
1821 }
1822 }
1823 }
1824 }
1825 ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
1826
1827 set_channel_variables(chan, details);
1828
1829 ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
1830 if (!strcasecmp(details->result, "FAILED")) {
1831 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1832 }
1833
1834 if (fax) {
1835 ao2_unlink(faxregistry.container, fax);
1836 ao2_ref(fax, -1);
1837 }
1838
1839 /* if the channel is still alive, and we changed its read/write formats,
1840 * restore them now
1841 */
1842 if (chancount) {
1843 if (orig_read_format) {
1844 ast_set_read_format(chan, orig_read_format);
1845 }
1846 if (orig_write_format) {
1847 ast_set_write_format(chan, orig_write_format);
1848 }
1849 }
1850
1851 /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
1852 return chancount;
1853}
1854
1855static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
1856{
1857 int timeout_ms;
1858 struct ast_frame *frame = NULL;
1859 struct ast_control_t38_parameters t38_parameters;
1860 struct timeval start;
1861 int ms;
1862
1863 /* don't send any audio if we've already received a T.38 reinvite */
1865 /* generate 3 seconds of CED */
1866 if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
1867 ast_log(LOG_ERROR, "error generating CED tone on %s\n", ast_channel_name(chan));
1868 return -1;
1869 }
1870
1871 timeout_ms = 3000;
1872 start = ast_tvnow();
1873 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1874 ms = ast_waitfor(chan, ms);
1875
1876 if (ms < 0) {
1877 ast_log(LOG_ERROR, "error while generating CED tone on %s\n", ast_channel_name(chan));
1878 ast_playtones_stop(chan);
1879 return -1;
1880 }
1881
1882 if (ms == 0) { /* all done, nothing happened */
1883 break;
1884 }
1885
1886 if (!(frame = ast_read(chan))) {
1887 ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", ast_channel_name(chan));
1888 ast_playtones_stop(chan);
1889 return -1;
1890 }
1891
1892 if ((frame->frametype == AST_FRAME_CONTROL) &&
1894 (frame->datalen == sizeof(t38_parameters))) {
1895 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1896
1897 switch (parameters->request_response) {
1899 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1900 * do T.38 as well
1901 */
1902 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1904 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1905 ast_playtones_stop(chan);
1906 break;
1907 case AST_T38_NEGOTIATED:
1908 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
1909 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1910 details->caps &= ~AST_FAX_TECH_AUDIO;
1911 report_fax_status(chan, details, "T.38 Negotiated");
1912 break;
1913 default:
1914 break;
1915 }
1916 }
1917 ast_frfree(frame);
1918 }
1919
1920 ast_playtones_stop(chan);
1921 }
1922
1923 /* if T.38 was negotiated, we are done initializing */
1925 return 0;
1926 }
1927
1928 /* request T.38 */
1929 ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(chan));
1930
1931 /* wait for negotiation to complete */
1932 timeout_ms = details->t38timeout;
1933
1934 /* set parameters based on the session's parameters */
1935 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1937 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1938 return -1;
1939 }
1940
1941 start = ast_tvnow();
1942 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1943 int break_loop = 0;
1944
1945 ms = ast_waitfor(chan, ms);
1946 if (ms < 0) {
1947 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1948 return -1;
1949 }
1950 if (ms == 0) { /* all done, nothing happened */
1951 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
1952 details->caps &= ~AST_FAX_TECH_T38;
1953 break;
1954 }
1955
1956 if (!(frame = ast_read(chan))) {
1957 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1958 return -1;
1959 }
1960
1961 if ((frame->frametype == AST_FRAME_CONTROL) &&
1963 (frame->datalen == sizeof(t38_parameters))) {
1964 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1965
1966 switch (parameters->request_response) {
1968 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1969 t38_parameters.request_response = AST_T38_NEGOTIATED;
1970 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1971 break;
1972 case AST_T38_NEGOTIATED:
1973 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
1974 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1975 details->caps &= ~AST_FAX_TECH_AUDIO;
1976 report_fax_status(chan, details, "T.38 Negotiated");
1977 break_loop = 1;
1978 break;
1979 case AST_T38_REFUSED:
1980 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
1981 details->caps &= ~AST_FAX_TECH_T38;
1982 break_loop = 1;
1983 break;
1984 default:
1985 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
1986 details->caps &= ~AST_FAX_TECH_T38;
1987 break_loop = 1;
1988 break;
1989 }
1990 }
1991 ast_frfree(frame);
1992 if (break_loop) {
1993 break;
1994 }
1995 }
1996
1997 /* if T.38 was negotiated, we are done initializing */
1999 return 0;
2000 }
2001
2002 /* if we made it here, then T.38 failed, check the 'f' flag */
2003 if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
2004 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2005 return -1;
2006 }
2007
2008 /* ok, audio fallback is allowed */
2009 details->caps |= AST_FAX_TECH_AUDIO;
2010
2011 return 0;
2012}
2013
2014/*! \brief Report on the final state of a receive fax operation
2015 * \note This will lock the \ref ast_channel
2016 */
2017static int report_receive_fax_status(struct ast_channel *chan, const char *filename)
2018{
2019 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
2021 RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
2022 struct ast_json *json_filename = ast_json_string_create(filename);
2023
2024 if (!json_array || !json_filename) {
2025 ast_json_unref(json_filename);
2026 return -1;
2027 }
2028 ast_json_array_append(json_array, json_filename);
2029
2030 {
2031 const char *remote_station_id;
2032 const char *local_station_id;
2033 const char *fax_pages;
2034 const char *fax_resolution;
2035 const char *fax_bitrate;
2036 SCOPED_CHANNELLOCK(lock, chan);
2037
2038 remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2039 if (!ast_strlen_zero(remote_station_id)) {
2040 remote_station_id = ast_strdupa(remote_station_id);
2041 }
2042 local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2043 if (!ast_strlen_zero(local_station_id)) {
2044 local_station_id = ast_strdupa(local_station_id);
2045 }
2046 fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2047 if (!ast_strlen_zero(fax_pages)) {
2048 fax_pages = ast_strdupa(fax_pages);
2049 }
2050 fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2051 if (!ast_strlen_zero(fax_resolution)) {
2052 fax_resolution = ast_strdupa(fax_resolution);
2053 }
2054 fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2055 if (!ast_strlen_zero(fax_bitrate)) {
2056 fax_bitrate = ast_strdupa(fax_bitrate);
2057 }
2058
2059 json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2060 "type", "receive",
2061 "remote_station_id", S_OR(remote_station_id, ""),
2062 "local_station_id", S_OR(local_station_id, ""),
2063 "fax_pages", S_OR(fax_pages, ""),
2064 "fax_resolution", S_OR(fax_resolution, ""),
2065 "fax_bitrate", S_OR(fax_bitrate, ""),
2066 "filenames", ast_json_ref(json_array));
2067 if (!json_object) {
2068 return -1;
2069 }
2070
2072 if (!message) {
2073 return -1;
2074 }
2076 }
2077 return 0;
2078}
2079
2080/*! \brief initiate a receive FAX session */
2081static int receivefax_exec(struct ast_channel *chan, const char *data)
2082{
2083 char *parse, modems[128] = "";
2084 int channel_alive;
2086 RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
2087 struct ast_fax_tech_token *token = NULL;
2088 struct ast_fax_document *doc;
2092 );
2093 struct ast_flags opts = { 0, };
2094 enum ast_t38_state t38state;
2095
2096 /* initialize output channel variables */
2097 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2098 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2099 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2100 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2101 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2102 pbx_builtin_setvar_helper(chan, "FAXMODE", NULL);
2103
2104 /* Get a FAX session details structure from the channel's FAX datastore and create one if
2105 * it does not already exist. */
2106 if (!(details = find_or_create_details(chan))) {
2107 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2108 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2109 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2110 return -1;
2111 }
2112
2113 ast_string_field_set(details, result, "FAILED");
2114 ast_string_field_set(details, resultstr, "error starting fax session");
2115 ast_string_field_set(details, error, "INIT_ERROR");
2116 set_channel_variables(chan, details);
2117
2118 if (details->gateway_id > 0) {
2119 ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
2120 set_channel_variables(chan, details);
2121 ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
2122 return -1;
2123 }
2124
2125 if (details->maxrate < details->minrate) {
2126 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2127 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2128 set_channel_variables(chan, details);
2129 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2130 return -1;
2131 }
2132
2133 if (check_modem_rate(details->modems, details->minrate)) {
2134 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2135 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2136 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2137 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2138 set_channel_variables(chan, details);
2139 return -1;
2140 }
2141
2142 if (check_modem_rate(details->modems, details->maxrate)) {
2143 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2144 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2145 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2146 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2147 set_channel_variables(chan, details);
2148 return -1;
2149 }
2150
2151 if (ast_strlen_zero(data)) {
2152 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2153 ast_string_field_set(details, resultstr, "invalid arguments");
2154 set_channel_variables(chan, details);
2155 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
2156 return -1;
2157 }
2158 parse = ast_strdupa(data);
2160
2161 if (!ast_strlen_zero(args.options) &&
2162 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2163 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2164 ast_string_field_set(details, resultstr, "invalid arguments");
2165 set_channel_variables(chan, details);
2166 return -1;
2167 }
2168 if (ast_strlen_zero(args.filename)) {
2169 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2170 ast_string_field_set(details, resultstr, "invalid arguments");
2171 set_channel_variables(chan, details);
2172 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
2173 return -1;
2174 }
2175
2176 /* check for unsupported FAX application options */
2178 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2179 ast_string_field_set(details, resultstr, "invalid arguments");
2180 set_channel_variables(chan, details);
2181 ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
2182 return -1;
2183 }
2184
2185 ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
2186
2187 pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
2188 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
2189
2190 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
2191 ast_string_field_set(details, error, "MEMORY_ERROR");
2192 ast_string_field_set(details, resultstr, "error allocating memory");
2193 set_channel_variables(chan, details);
2194 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2195 return -1;
2196 }
2197
2198 strcpy(doc->filename, args.filename);
2199 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2200
2201 ast_verb(3, "Channel '%s' receiving FAX '%s'\n", ast_channel_name(chan), args.filename);
2202
2203 details->caps = AST_FAX_TECH_RECEIVE;
2204 details->option.send_ced = AST_FAX_OPTFLAG_TRUE;
2205
2206 /* check for debug */
2207 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2208 details->option.debug = AST_FAX_OPTFLAG_TRUE;
2209 }
2210
2211 /* check for request for status events */
2212 if (ast_test_flag(&opts, OPT_STATUS)) {
2213 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2214 }
2215
2216 t38state = ast_channel_get_t38_state(chan);
2217 if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
2218 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2220 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2221 }
2222
2223 if (!(s = fax_session_reserve(details, &token))) {
2224 ast_string_field_set(details, resultstr, "error reserving fax session");
2225 set_channel_variables(chan, details);
2226 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2227 return -1;
2228 }
2229
2230 /* make sure the channel is up */
2231 if (ast_channel_state(chan) != AST_STATE_UP) {
2232 if (ast_answer(chan)) {
2233 ast_string_field_set(details, resultstr, "error answering channel");
2234 set_channel_variables(chan, details);
2235 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2236 fax_session_release(s, token);
2237 return -1;
2238 }
2239 }
2240
2241 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2242 if (set_fax_t38_caps(chan, details)) {
2243 ast_string_field_set(details, error, "T38_NEG_ERROR");
2244 ast_string_field_set(details, resultstr, "error negotiating T.38");
2245 set_channel_variables(chan, details);
2246 fax_session_release(s, token);
2247 return -1;
2248 }
2249 } else {
2250 details->caps |= AST_FAX_TECH_AUDIO;
2251 }
2252
2253 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2254 if (receivefax_t38_init(chan, details)) {
2255 ast_string_field_set(details, error, "T38_NEG_ERROR");
2256 ast_string_field_set(details, resultstr, "error negotiating T.38");
2257 set_channel_variables(chan, details);
2258 fax_session_release(s, token);
2259 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2260 return -1;
2261 }
2262 }
2263
2264 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2265 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2266 }
2267
2269 if (disable_t38(chan)) {
2270 ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
2271 }
2272 }
2273
2274 if (report_receive_fax_status(chan, args.filename)) {
2275 ast_log(AST_LOG_ERROR, "Error publishing ReceiveFAX status message\n");
2276 }
2277
2278 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2279 return (!channel_alive) ? -1 : 0;
2280}
2281
2282static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
2283{
2284 int timeout_ms;
2285 struct ast_frame *frame = NULL;
2286 struct ast_control_t38_parameters t38_parameters;
2287 struct timeval start;
2288 int ms;
2289
2290 /* send CNG tone while listening for the receiver to initiate a switch
2291 * to T.38 mode; if they do, stop sending the CNG tone and proceed with
2292 * the switch.
2293 *
2294 * 10500 is enough time for 3 CNG tones
2295 */
2296 timeout_ms = 10500;
2297
2298 /* don't send any audio if we've already received a T.38 reinvite */
2300 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
2301 ast_log(LOG_ERROR, "error generating CNG tone on %s\n", ast_channel_name(chan));
2302 return -1;
2303 }
2304 }
2305
2306 start = ast_tvnow();
2307 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2308 int break_loop = 0;
2309 ms = ast_waitfor(chan, ms);
2310
2311 if (ms < 0) {
2312 ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", ast_channel_name(chan));
2313 ast_playtones_stop(chan);
2314 return -1;
2315 }
2316
2317 if (ms == 0) { /* all done, nothing happened */
2318 break;
2319 }
2320
2321 if (!(frame = ast_read(chan))) {
2322 ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", ast_channel_name(chan));
2323 ast_playtones_stop(chan);
2324 return -1;
2325 }
2326
2327 if ((frame->frametype == AST_FRAME_CONTROL) &&
2329 (frame->datalen == sizeof(t38_parameters))) {
2330 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2331
2332 switch (parameters->request_response) {
2334 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2335 * do T.38 as well
2336 */
2337 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2339 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2340 ast_playtones_stop(chan);
2341 break;
2342 case AST_T38_NEGOTIATED:
2343 ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2344 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2345 details->caps &= ~AST_FAX_TECH_AUDIO;
2346 report_fax_status(chan, details, "T.38 Negotiated");
2347 break_loop = 1;
2348 break;
2349 default:
2350 break;
2351 }
2352 }
2353 ast_frfree(frame);
2354 if (break_loop) {
2355 break;
2356 }
2357 }
2358
2359 ast_playtones_stop(chan);
2360
2362 return 0;
2363 }
2364
2365 /* T.38 negotiation did not happen, initiate a switch if requested */
2366 if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
2367 ast_debug(1, "Negotiating T.38 for send on %s\n", ast_channel_name(chan));
2368
2369 /* wait up to five seconds for negotiation to complete */
2370 timeout_ms = 5000;
2371
2372 /* set parameters based on the session's parameters */
2373 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2375 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
2376 return -1;
2377 }
2378
2379 start = ast_tvnow();
2380 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2381 int break_loop = 0;
2382
2383 ms = ast_waitfor(chan, ms);
2384 if (ms < 0) {
2385 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2386 return -1;
2387 }
2388 if (ms == 0) { /* all done, nothing happened */
2389 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
2390 details->caps &= ~AST_FAX_TECH_T38;
2391 break;
2392 }
2393
2394 if (!(frame = ast_read(chan))) {
2395 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2396 return -1;
2397 }
2398
2399 if ((frame->frametype == AST_FRAME_CONTROL) &&
2401 (frame->datalen == sizeof(t38_parameters))) {
2402 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2403
2404 switch (parameters->request_response) {
2406 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2407 t38_parameters.request_response = AST_T38_NEGOTIATED;
2408 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2409 break;
2410 case AST_T38_NEGOTIATED:
2411 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
2412 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2413 details->caps &= ~AST_FAX_TECH_AUDIO;
2414 report_fax_status(chan, details, "T.38 Negotiated");
2415 break_loop = 1;
2416 break;
2417 case AST_T38_REFUSED:
2418 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
2419 details->caps &= ~AST_FAX_TECH_T38;
2420 break_loop = 1;
2421 break;
2422 default:
2423 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
2424 details->caps &= ~AST_FAX_TECH_T38;
2425 break_loop = 1;
2426 break;
2427 }
2428 }
2429 ast_frfree(frame);
2430 if (break_loop) {
2431 break;
2432 }
2433 }
2434
2435 /* if T.38 was negotiated, we are done initializing */
2437 return 0;
2438 }
2439
2440 /* send one more CNG tone to get audio going again for some
2441 * carriers if we are going to fall back to audio mode */
2442 if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
2443 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
2444 ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", ast_channel_name(chan));
2445 return -1;
2446 }
2447
2448 timeout_ms = 3500;
2449 start = ast_tvnow();
2450 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2451 int break_loop = 0;
2452
2453 ms = ast_waitfor(chan, ms);
2454 if (ms < 0) {
2455 ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", ast_channel_name(chan));
2456 ast_playtones_stop(chan);
2457 return -1;
2458 }
2459 if (ms == 0) { /* all done, nothing happened */
2460 break;
2461 }
2462
2463 if (!(frame = ast_read(chan))) {
2464 ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", ast_channel_name(chan));
2465 ast_playtones_stop(chan);
2466 return -1;
2467 }
2468
2469 if ((frame->frametype == AST_FRAME_CONTROL) &&
2471 (frame->datalen == sizeof(t38_parameters))) {
2472 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2473
2474 switch (parameters->request_response) {
2476 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2477 * do T.38 as well
2478 */
2479 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2481 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2482 ast_playtones_stop(chan);
2483 break;
2484 case AST_T38_NEGOTIATED:
2485 ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2486 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2487 details->caps &= ~AST_FAX_TECH_AUDIO;
2488 report_fax_status(chan, details, "T.38 Negotiated");
2489 break_loop = 1;
2490 break;
2491 default:
2492 break;
2493 }
2494 }
2495 ast_frfree(frame);
2496 if (break_loop) {
2497 break;
2498 }
2499 }
2500
2501 ast_playtones_stop(chan);
2502
2503 /* if T.38 was negotiated, we are done initializing */
2505 return 0;
2506 }
2507 }
2508 }
2509
2510 /* if we made it here, then T.38 failed, check the 'f' flag */
2511 if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
2512 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2513 return -1;
2514 }
2515
2516 /* ok, audio fallback is allowed */
2517 details->caps |= AST_FAX_TECH_AUDIO;
2518
2519 return 0;
2520}
2521
2522/*!
2523 * \brief Report on the status of a completed fax send attempt
2524 * \note This will lock the \ref ast_channel
2525 */
2526static int report_send_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details)
2527{
2528 RAII_VAR(struct ast_json *, json_obj, NULL, ast_json_unref);
2530 struct ast_json *json_filenames;
2531
2532 json_filenames = generate_filenames_json(details);
2533 if (!json_filenames) {
2534 return -1;
2535 }
2536
2537 {
2538 const char *remote_station_id;
2539 const char *local_station_id;
2540 const char *fax_pages;
2541 const char *fax_resolution;
2542 const char *fax_bitrate;
2543 SCOPED_CHANNELLOCK(lock, chan);
2544
2545 remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2546 if (!ast_strlen_zero(remote_station_id)) {
2547 remote_station_id = ast_strdupa(remote_station_id);
2548 }
2549 local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2550 if (!ast_strlen_zero(local_station_id)) {
2551 local_station_id = ast_strdupa(local_station_id);
2552 }
2553 fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2554 if (!ast_strlen_zero(fax_pages)) {
2555 fax_pages = ast_strdupa(fax_pages);
2556 }
2557 fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2558 if (!ast_strlen_zero(fax_resolution)) {
2559 fax_resolution = ast_strdupa(fax_resolution);
2560 }
2561 fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2562 if (!ast_strlen_zero(fax_bitrate)) {
2563 fax_bitrate = ast_strdupa(fax_bitrate);
2564 }
2565 json_obj = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2566 "type", "send",
2567 "remote_station_id", S_OR(remote_station_id, ""),
2568 "local_station_id", S_OR(local_station_id, ""),
2569 "fax_pages", S_OR(fax_pages, ""),
2570 "fax_resolution", S_OR(fax_resolution, ""),
2571 "fax_bitrate", S_OR(fax_bitrate, ""),
2572 "filenames", json_filenames);
2573 if (!json_obj) {
2574 return -1;
2575 }
2576
2578 if (!message) {
2579 return -1;
2580 }
2582 }
2583 return 0;
2584}
2585
2586
2587
2588/*! \brief initiate a send FAX session */
2589static int sendfax_exec(struct ast_channel *chan, const char *data)
2590{
2591 char *parse, *filenames, *c, modems[128] = "";
2592 int channel_alive, file_count;
2593 RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
2595 struct ast_fax_tech_token *token = NULL;
2596 struct ast_fax_document *doc;
2598 AST_APP_ARG(filenames);
2600 );
2601 struct ast_flags opts = { 0, };
2602 enum ast_t38_state t38state;
2603
2604 /* initialize output channel variables */
2605 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2606 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2607 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2608 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2609 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2610 pbx_builtin_setvar_helper(chan, "FAXMODE", NULL);
2611
2612 /* Get a requirement structure and set it. This structure is used
2613 * to tell the FAX technology module about the higher level FAX session */
2614 if (!(details = find_or_create_details(chan))) {
2615 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2616 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2617 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2618 return -1;
2619 }
2620
2621 ast_string_field_set(details, result, "FAILED");
2622 ast_string_field_set(details, resultstr, "error starting fax session");
2623 ast_string_field_set(details, error, "INIT_ERROR");
2624 set_channel_variables(chan, details);
2625
2626 if (details->gateway_id > 0) {
2627 ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
2628 set_channel_variables(chan, details);
2629 ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
2630 return -1;
2631 }
2632
2633 if (details->maxrate < details->minrate) {
2634 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2635 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2636 set_channel_variables(chan, details);
2637 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2638 return -1;
2639 }
2640
2641 if (check_modem_rate(details->modems, details->minrate)) {
2642 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2643 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2644 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2645 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2646 set_channel_variables(chan, details);
2647 return -1;
2648 }
2649
2650 if (check_modem_rate(details->modems, details->maxrate)) {
2651 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2652 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2653 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2654 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2655 set_channel_variables(chan, details);
2656 return -1;
2657 }
2658
2659 if (ast_strlen_zero(data)) {
2660 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2661 ast_string_field_set(details, resultstr, "invalid arguments");
2662 set_channel_variables(chan, details);
2663 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
2664 return -1;
2665 }
2666 parse = ast_strdupa(data);
2668
2669
2670 if (!ast_strlen_zero(args.options) &&
2671 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2672 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2673 ast_string_field_set(details, resultstr, "invalid arguments");
2674 set_channel_variables(chan, details);
2675 return -1;
2676 }
2677 if (ast_strlen_zero(args.filenames)) {
2678 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2679 ast_string_field_set(details, resultstr, "invalid arguments");
2680 set_channel_variables(chan, details);
2681 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
2682 return -1;
2683 }
2684
2685 /* check for unsupported FAX application options */
2687 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2688 ast_string_field_set(details, resultstr, "invalid arguments");
2689 set_channel_variables(chan, details);
2690 ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
2691 return -1;
2692 }
2693
2694 ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
2695
2696 file_count = 0;
2697 filenames = args.filenames;
2698 while ((c = strsep(&filenames, "&"))) {
2699 if (access(c, (F_OK | R_OK)) < 0) {
2700 ast_string_field_set(details, error, "FILE_ERROR");
2701 ast_string_field_set(details, resultstr, "error reading file");
2702 set_channel_variables(chan, details);
2703 ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames);
2704 return -1;
2705 }
2706
2707 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
2708 ast_string_field_set(details, error, "MEMORY_ERROR");
2709 ast_string_field_set(details, resultstr, "error allocating memory");
2710 set_channel_variables(chan, details);
2711 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2712 return -1;
2713 }
2714
2715 strcpy(doc->filename, c);
2716 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2717 file_count++;
2718 }
2719
2720 ast_verb(3, "Channel '%s' sending FAX:\n", ast_channel_name(chan));
2721 AST_LIST_TRAVERSE(&details->documents, doc, next) {
2722 ast_verb(3, " %s\n", doc->filename);
2723 }
2724
2725 details->caps = AST_FAX_TECH_SEND;
2726
2727 if (file_count > 1) {
2728 details->caps |= AST_FAX_TECH_MULTI_DOC;
2729 }
2730
2731 /* check for debug */
2732 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2733 details->option.debug = AST_FAX_OPTFLAG_TRUE;
2734 }
2735
2736 /* check for request for status events */
2737 if (ast_test_flag(&opts, OPT_STATUS)) {
2738 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2739 }
2740
2741 t38state = ast_channel_get_t38_state(chan);
2742 if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
2743 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2745 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2746 }
2747
2748 if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
2749 details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
2750 }
2751
2752 if (!(s = fax_session_reserve(details, &token))) {
2753 ast_string_field_set(details, resultstr, "error reserving fax session");
2754 set_channel_variables(chan, details);
2755 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2756 return -1;
2757 }
2758
2759 /* make sure the channel is up */
2760 if (ast_channel_state(chan) != AST_STATE_UP) {
2761 if (ast_answer(chan)) {
2762 ast_string_field_set(details, resultstr, "error answering channel");
2763 set_channel_variables(chan, details);
2764 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2765 fax_session_release(s, token);
2766 return -1;
2767 }
2768 }
2769
2770 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2771 if (set_fax_t38_caps(chan, details)) {
2772 ast_string_field_set(details, error, "T38_NEG_ERROR");
2773 ast_string_field_set(details, resultstr, "error negotiating T.38");
2774 set_channel_variables(chan, details);
2775 fax_session_release(s, token);
2776 return -1;
2777 }
2778 } else {
2779 details->caps |= AST_FAX_TECH_AUDIO;
2780 }
2781
2782 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2783 if (sendfax_t38_init(chan, details)) {
2784 ast_string_field_set(details, error, "T38_NEG_ERROR");
2785 ast_string_field_set(details, resultstr, "error negotiating T.38");
2786 set_channel_variables(chan, details);
2787 fax_session_release(s, token);
2788 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2789 return -1;
2790 }
2791 } else {
2792 details->option.send_cng = 1;
2793 }
2794
2795 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2796 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2797 }
2798
2800 if (disable_t38(chan)) {
2801 ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
2802 }
2803 }
2804
2805 if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
2806 ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
2807 return (!channel_alive) ? -1 : 0;
2808 }
2809
2810 /* send out the AMI completion event */
2811 if (report_send_fax_status(chan, details)) {
2812 ast_log(AST_LOG_ERROR, "Error publishing SendFAX status message\n");
2813 }
2814
2815 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2816 return (!channel_alive) ? -1 : 0;
2817}
2818
2819/*! \brief destroy the v21 detection parts of a fax gateway session */
2820static void destroy_v21_sessions(struct fax_gateway *gateway)
2821{
2822 if (gateway->chan_v21_session) {
2823 ao2_unlink(faxregistry.container, gateway->chan_v21_session);
2824
2825 ao2_ref(gateway->chan_v21_session, -1);
2826 gateway->chan_v21_session = NULL;
2827 }
2828
2829 if (gateway->peer_v21_session) {
2830 ao2_unlink(faxregistry.container, gateway->peer_v21_session);
2831
2832 ao2_ref(gateway->peer_v21_session, -1);
2833 gateway->peer_v21_session = NULL;
2834 }
2835}
2836
2837/*! \brief destroy a FAX gateway session structure */
2838static void destroy_gateway(void *data)
2839{
2840 struct fax_gateway *gateway = data;
2841
2842 destroy_v21_sessions(gateway);
2843
2844 if (gateway->s) {
2845 fax_session_release(gateway->s, gateway->token);
2846 gateway->token = NULL;
2847
2848 ao2_unlink(faxregistry.container, gateway->s);
2849
2850 ao2_ref(gateway->s, -1);
2851 gateway->s = NULL;
2852 }
2853
2854 ao2_cleanup(gateway->chan_read_format);
2856 ao2_cleanup(gateway->peer_read_format);
2858}
2859
2861 struct ast_fax_session_details *v21_details;
2862 struct ast_fax_session *v21_session;
2863
2864 if (!chan || !(v21_details = session_details_new())) {
2865 return NULL;
2866 }
2867
2868 v21_details->caps = AST_FAX_TECH_V21_DETECT;
2869 v21_session = fax_session_new(v21_details, chan, NULL, NULL);
2870 ao2_ref(v21_details, -1);
2871 return v21_session;
2872}
2873
2874/*! \brief Create a new fax gateway object.
2875 * \param chan the channel the gateway object will be attached to
2876 * \param details the fax session details
2877 * \return NULL or a fax gateway object
2878 */
2879static struct fax_gateway *fax_gateway_new(struct ast_channel *chan, struct ast_fax_session_details *details)
2880{
2881 struct fax_gateway *gateway = ao2_alloc(sizeof(*gateway), destroy_gateway);
2882 if (!gateway) {
2883 return NULL;
2884 }
2885
2886 if (!(gateway->chan_v21_session = fax_v21_session_new(chan))) {
2887 ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2888 ao2_ref(gateway, -1);
2889 return NULL;
2890 }
2891
2892 gateway->framehook = -1;
2893
2894 details->caps = AST_FAX_TECH_GATEWAY;
2895 if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
2896 details->caps &= ~AST_FAX_TECH_GATEWAY;
2897 ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
2898 ao2_ref(gateway, -1);
2899 return NULL;
2900 }
2901
2902 return gateway;
2903}
2904
2905/*!
2906 * \brief Create a fax session and start T.30<->T.38 gateway mode
2907 *
2908 * \param gateway a fax gateway object
2909 * \param details fax session details
2910 * \param chan active channel
2911 *
2912 * \pre chan is locked on entry
2913 *
2914 * \return 0 on error 1 on success
2915 */
2916static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
2917{
2918 struct ast_fax_session *s;
2919 int start_res;
2920
2921 /* if the fax gateway is already started then do nothing */
2922 if (gateway->s &&
2923 gateway->s->state != AST_FAX_STATE_RESERVED && gateway->s->state != AST_FAX_STATE_INACTIVE) {
2924 return 0;
2925 }
2926
2927 /* if we start gateway we don't need v21 detection sessions any more */
2928 destroy_v21_sessions(gateway);
2929
2930 /* create the FAX session */
2931 if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) {
2932 gateway->token = NULL;
2934 ast_string_field_set(details, resultstr, "error starting gateway session");
2935 ast_string_field_set(details, error, "INIT_ERROR");
2938 report_fax_status(chan, details, "No Available Resource");
2939 ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
2940 return -1;
2941 }
2942 /* release the reference for the reserved session and replace it with
2943 * the real session */
2944 if (gateway->s) {
2945 ao2_ref(gateway->s, -1);
2946 }
2947 gateway->s = s;
2948 gateway->token = NULL;
2949
2951 start_res = gateway->s->tech->start_session(gateway->s);
2953 if (start_res < 0) {
2955 ast_string_field_set(details, resultstr, "error starting gateway session");
2956 ast_string_field_set(details, error, "INIT_ERROR");
2959 return -1;
2960 }
2961
2962 gateway->timeout_start.tv_sec = 0;
2963 gateway->timeout_start.tv_usec = 0;
2964
2965 report_fax_status(chan, details, "FAX Transmission In Progress");
2966
2967 return 0;
2968}
2969
2970/*! \pre chan is locked on entry */
2971static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan)
2972{
2973 struct ast_frame *fp;
2974 struct ast_control_t38_parameters t38_parameters = {
2976 };
2977 struct ast_frame control_frame = {
2978 .src = "res_fax",
2979 .frametype = AST_FRAME_CONTROL,
2980 .datalen = sizeof(t38_parameters),
2982 .data.ptr = &t38_parameters,
2983 };
2984
2985 struct ast_fax_session_details *details = find_details(chan);
2986
2987 if (!details) {
2988 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
2989 ast_framehook_detach(chan, gateway->framehook);
2990 return NULL;
2991 }
2992
2993 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2994 ao2_ref(details, -1);
2995
2996 if (!(fp = ast_frisolate(&control_frame))) {
2997 ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2998 return NULL;
2999 }
3000
3002 gateway->timeout_start = ast_tvnow();
3003 details->is_t38_negotiated = 0;
3005
3006 ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
3007 return fp;
3008}
3009
3010/*! \pre chan is locked on entry */
3011static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
3012{
3013 struct ast_channel *other = (active == chan) ? peer : chan;
3014 struct ast_fax_session *active_v21_session = (active == chan) ? gateway->chan_v21_session : gateway->peer_v21_session;
3015
3016 if (!active_v21_session || gateway->detected_v21) {
3017 return f;
3018 }
3019
3020 if (active_v21_session->tech->write(active_v21_session, f) == 0 &&
3021 active_v21_session->details->option.v21_detected) {
3022 gateway->detected_v21 = 1;
3023 }
3024
3025 if (gateway->detected_v21) {
3026 enum ast_t38_state state_other;
3027 enum ast_t38_state state_active;
3028 struct ast_frame *fp;
3029 struct ast_fax_session_details *details;
3030 int negotiate_both = 0;
3031
3032 /*
3033 * The default behavior is to wait for the active endpoint to initiate negotiation.
3034 * Find out if this has been overridden. If so, instead of waiting have Asterisk
3035 * initiate the negotiation requests out to both endpoints.
3036 */
3037 details = find_or_create_details(active);
3038 if (details) {
3039 negotiate_both = details->negotiate_both;
3040 ao2_ref(details, -1);
3041 } else {
3042 ast_log(LOG_WARNING, "Detect v21 - no session details for channel '%s'\n",
3043 ast_channel_name(chan));
3044 }
3045
3046 destroy_v21_sessions(gateway);
3047
3048 ast_channel_unlock(chan);
3049 state_active = ast_channel_get_t38_state(active);
3050 state_other = ast_channel_get_t38_state(other);
3051 ast_channel_lock(chan);
3052
3053 ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
3054
3055 if (state_active == T38_STATE_UNKNOWN || state_other == T38_STATE_UNKNOWN) {
3056 if (!(fp = fax_gateway_request_t38(gateway, chan))) {
3057 return f;
3058 }
3059 /* May be called endpoint is improperly configured to rely on the calling endpoint
3060 * to initiate T.38 re-INVITEs, send T.38 negotiation request to called endpoint */
3061 if (negotiate_both && state_active == T38_STATE_UNKNOWN) {
3062 ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(active));
3063 if (active == chan) {
3064 ast_channel_unlock(chan);
3065 }
3066 ast_write(active, fp);
3067 if (active == chan) {
3068 ast_channel_lock(chan);
3069 }
3070 }
3071 if (state_other == T38_STATE_UNKNOWN) {
3072 ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(other));
3073 return fp;
3074 }
3075 } else {
3076 ast_debug(1, "neither %s nor %s support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
3077 }
3078 }
3079
3080 return f;
3081}
3082
3083/*! \pre chan is locked on entry */
3084static void fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
3085{
3086 if (active == chan) {
3087 ast_channel_unlock(chan);
3088 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3089 ast_channel_lock(chan);
3090 } else {
3091 ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3092 }
3093}
3094
3095/*!
3096 * \brief T38 Gateway Negotiate t38 parameters
3097 *
3098 * \param gateway gateway object
3099 * \param chan channel running the gateway
3100 * \param peer channel im bridged too
3101 * \param active channel the frame originated on
3102 * \param f the control frame to process
3103 *
3104 * \pre chan is locked on entry
3105 *
3106 * \return processed control frame or null frame
3107 */
3108static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
3109{
3110 struct ast_control_t38_parameters *control_params = f->data.ptr;
3111 struct ast_channel *other = (active == chan) ? peer : chan;
3112 struct ast_fax_session_details *details;
3113 enum ast_t38_state state_other;
3114
3115 if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
3116 /* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
3117 * do anything with it, pass it on */
3118 return f;
3119 }
3120
3121 /* ignore frames from ourselves */
3122 if ((gateway->t38_state == T38_STATE_NEGOTIATED && control_params->request_response == AST_T38_NEGOTIATED)
3123 || (gateway->t38_state == T38_STATE_REJECTED && control_params->request_response == AST_T38_REFUSED)
3124 || (gateway->t38_state == T38_STATE_NEGOTIATING && control_params->request_response == AST_T38_REQUEST_TERMINATE)) {
3125
3126 return f;
3127 }
3128
3129 if (!(details = find_details(chan))) {
3130 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3131 ast_framehook_detach(chan, gateway->framehook);
3132 return f;
3133 }
3134
3135 if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
3136 ast_channel_unlock(chan);
3137 state_other = ast_channel_get_t38_state(other);
3138 ast_channel_lock(chan);
3139
3140 if (state_other == T38_STATE_UNKNOWN) {
3141 /* we detected a request to negotiate T.38 and the
3142 * other channel appears to support T.38, we'll pass
3143 * the request through and only step in if the other
3144 * channel rejects the request */
3145 ast_debug(1, "%s is attempting to negotiate T.38 with %s, we'll see what happens\n", ast_channel_name(active), ast_channel_name(other));
3146 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3147 gateway->t38_state = T38_STATE_UNKNOWN;
3148 gateway->timeout_start = ast_tvnow();
3149 details->is_t38_negotiated = 0;
3151 ao2_ref(details, -1);
3152 return f;
3153 } else if (state_other == T38_STATE_UNAVAILABLE || state_other == T38_STATE_REJECTED) {
3154 /* the other channel does not support T.38, we need to
3155 * step in here */
3156 ast_debug(1, "%s is attempting to negotiate T.38 but %s does not support it\n", ast_channel_name(active), ast_channel_name(other));
3157 ast_debug(1, "starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
3158
3159 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3160 t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
3161
3162 if (fax_gateway_start(gateway, details, chan)) {
3163 ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
3164 gateway->t38_state = T38_STATE_REJECTED;
3165 details->is_t38_negotiated = 0;
3166 control_params->request_response = AST_T38_REFUSED;
3167
3168 ast_framehook_detach(chan, details->gateway_id);
3169 details->gateway_id = -1;
3170 } else {
3172 details->is_t38_negotiated = chan == active;
3173 control_params->request_response = AST_T38_NEGOTIATED;
3174 report_fax_status(chan, details, "T.38 Negotiated");
3175 }
3176
3177 fax_gateway_indicate_t38(chan, active, control_params);
3178
3179 ao2_ref(details, -1);
3180 return &ast_null_frame;
3181 } else if (gateway->t38_state == T38_STATE_NEGOTIATING) {
3182 /* we got a request to negotiate T.38 after we already
3183 * sent one to the other party based on v21 preamble
3184 * detection. We'll just pretend we passed this request
3185 * through in the first place. */
3186
3187 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3188 gateway->t38_state = T38_STATE_UNKNOWN;
3189 gateway->timeout_start = ast_tvnow();
3190 details->is_t38_negotiated = 0;
3192
3193 ast_debug(1, "%s is attempting to negotiate T.38 after we already sent a negotiation request based on v21 preamble detection\n", ast_channel_name(active));
3194 ao2_ref(details, -1);
3195 return &ast_null_frame;
3196 } else if (gateway->t38_state == T38_STATE_NEGOTIATED) {
3197 /* we got a request to negotiate T.38 after we already
3198 * sent one to the other party based on v21 preamble
3199 * detection and received a response. We need to
3200 * respond to this and shut down the gateway. */
3201
3202 t38_parameters_fax_to_ast(control_params, &details->their_t38_parameters);
3203 ast_framehook_detach(chan, details->gateway_id);
3204 details->gateway_id = -1;
3205
3206 control_params->request_response = AST_T38_NEGOTIATED;
3207
3208 fax_gateway_indicate_t38(chan, active, control_params);
3209
3210 ast_string_field_set(details, result, "SUCCESS");
3211 ast_string_field_set(details, resultstr, "no gateway necessary");
3212 ast_string_field_set(details, error, "NATIVE_T38");
3213 details->is_t38_negotiated = 1;
3214 set_channel_variables(chan, details);
3215
3216 ast_debug(1, "%s is attempting to negotiate T.38 after we already negotiated T.38 with %s, disabling the gateway\n", ast_channel_name(active), ast_channel_name(other));
3217 ao2_ref(details, -1);
3218 return &ast_null_frame;
3219 } else {
3220 ast_log(LOG_WARNING, "%s is attempting to negotiate T.38 while %s is in an unsupported state\n", ast_channel_name(active), ast_channel_name(other));
3221 ao2_ref(details, -1);
3222 return f;
3223 }
3224 } else if (gateway->t38_state == T38_STATE_NEGOTIATING
3225 && control_params->request_response == AST_T38_REFUSED) {
3226
3227 ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
3228 details->is_t38_negotiated = 0;
3229
3230 /* our request to negotiate T.38 was refused, if the other
3231 * channel supports T.38, they might still reinvite and save
3232 * the day. Otherwise disable the gateway. */
3233 ast_channel_unlock(chan);
3234 state_other = ast_channel_get_t38_state(other);
3235 ast_channel_lock(chan);
3236 if (state_other == T38_STATE_UNKNOWN) {
3238 } else if (state_other != T38_STATE_NEGOTIATING) {
3239 ast_framehook_detach(chan, details->gateway_id);
3240 details->gateway_id = -1;
3241
3242 ast_string_field_set(details, result, "FAILED");
3243 ast_string_field_set(details, resultstr, "unable to negotiate T.38");
3244 ast_string_field_set(details, error, "T38_NEG_ERROR");
3245 set_channel_variables(chan, details);
3246 }
3247
3248 ao2_ref(details, -1);
3249 return &ast_null_frame;
3250 } else if (gateway->t38_state == T38_STATE_NEGOTIATING
3251 && control_params->request_response == AST_T38_NEGOTIATED) {
3252
3253 ast_debug(1, "starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
3254
3255 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3256
3257 if (fax_gateway_start(gateway, details, chan)) {
3258 ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
3260 details->is_t38_negotiated = 0;
3262
3263 fax_gateway_indicate_t38(chan, active, control_params);
3264 } else {
3266 details->is_t38_negotiated = chan == active;
3267 report_fax_status(chan, details, "T.38 Negotiated");
3268 }
3269
3270 ao2_ref(details, -1);
3271 return &ast_null_frame;
3272 } else if (control_params->request_response == AST_T38_REFUSED) {
3273 /* the other channel refused the request to negotiate T.38,
3274 * we'll step in here and pretend the request was accepted */
3275
3276 ast_debug(1, "%s attempted to negotiate T.38 but %s refused the request\n", ast_channel_name(other), ast_channel_name(active));
3277 ast_debug(1, "starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(other), ast_channel_name(active));
3278
3279 t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
3280
3281 if (fax_gateway_start(gateway, details, chan)) {
3282 ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(other), ast_channel_name(active));
3283 gateway->t38_state = T38_STATE_REJECTED;
3284 details->is_t38_negotiated = 0;
3285 control_params->request_response = AST_T38_REFUSED;
3286
3287 ast_framehook_detach(chan, details->gateway_id);
3288 details->gateway_id = -1;
3289 } else {
3291 details->is_t38_negotiated = chan == other;
3292 control_params->request_response = AST_T38_NEGOTIATED;
3293 }
3294
3295 ao2_ref(details, -1);
3296 return f;
3297 } else if (control_params->request_response == AST_T38_REQUEST_TERMINATE) {
3298 /* the channel wishes to end our short relationship, we shall
3299 * oblige */
3300
3301 ast_debug(1, "T.38 channel %s is requesting a shutdown of T.38, disabling the gateway\n", ast_channel_name(active));
3302
3303 ast_framehook_detach(chan, details->gateway_id);
3304 details->gateway_id = -1;
3305
3306 gateway->t38_state = T38_STATE_REJECTED;
3307 details->is_t38_negotiated = 0;
3308 control_params->request_response = AST_T38_TERMINATED;
3309
3310 fax_gateway_indicate_t38(chan, active, control_params);
3311
3312 ao2_ref(details, -1);
3313 return &ast_null_frame;
3314 } else if (control_params->request_response == AST_T38_NEGOTIATED) {
3315 ast_debug(1, "T.38 successfully negotiated between %s and %s, no gateway necessary\n", ast_channel_name(active), ast_channel_name(other));
3316
3317 ast_framehook_detach(chan, details->gateway_id);
3318 details->gateway_id = -1;
3319
3320 ast_string_field_set(details, result, "SUCCESS");
3321 ast_string_field_set(details, resultstr, "no gateway necessary");
3322 ast_string_field_set(details, error, "NATIVE_T38");
3323 details->is_t38_negotiated = 1;
3324 set_channel_variables(chan, details);
3325
3326 ao2_ref(details, -1);
3327 return f;
3328 } else if (control_params->request_response == AST_T38_TERMINATED) {
3329 ast_debug(1, "T.38 disabled on channel %s\n", ast_channel_name(active));
3330
3331 ast_framehook_detach(chan, details->gateway_id);
3332 details->gateway_id = -1;
3333
3334 ao2_ref(details, -1);
3335 return &ast_null_frame;
3336 }
3337
3338 ao2_ref(details, -1);
3339 return f;
3340}
3341
3342/*! \brief Destroy the gateway data structure when the framehook is detached
3343 * \param data framehook data (gateway data)*/
3344static void fax_gateway_framehook_destroy(void *data)
3345{
3346 struct fax_gateway *gateway = data;
3347
3348 if (gateway->s) {
3349 switch (gateway->s->state) {
3351 case AST_FAX_STATE_OPEN:
3354 if (gateway->s->tech->cancel_session) {
3355 gateway->s->tech->cancel_session(gateway->s);
3356 }
3357 /* fall through */
3358 default:
3359 break;
3360 }
3361 }
3362
3363 ao2_ref(gateway, -1);
3364}
3365
3366/*!
3367 * \brief T.30<->T.38 gateway framehook.
3368 *
3369 * Intercept packets on bridged channels and determine if a T.38 gateway is
3370 * required. If a gateway is required, start a gateway and handle T.38
3371 * negotiation if necessary.
3372 *
3373 * \param chan channel running the gateway
3374 * \param f frame to handle may be NULL
3375 * \param event framehook event
3376 * \param data framehook data (struct fax_gateway *)
3377 *
3378 * \pre chan is locked on entry
3379 *
3380 * \return processed frame or NULL when f is NULL or a null frame
3381 */
3382static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
3383{
3384 struct fax_gateway *gateway = data;
3385 struct ast_channel *active;
3386 RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
3387 RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3388 RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3389
3390 /* Ref bump channel for when we have to unlock it */
3391 ao2_ref(chan_ref, 1);
3392
3393 if (gateway->s) {
3394 details = gateway->s->details;
3395 ao2_ref(details, 1);
3396 } else {
3397 if (!(details = find_details(chan))) {
3398 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3399 ast_framehook_detach(chan, gateway->framehook);
3400 return f;
3401 }
3402 }
3403
3404 /* restore audio formats when we are detached */
3406 set_channel_variables(chan, details);
3407
3408 if (gateway->bridged) {
3409 ast_set_read_format(chan, gateway->chan_read_format);
3411
3412 ast_channel_unlock(chan);
3413 peer = ast_channel_bridge_peer(chan);
3414 if (peer) {
3415 ast_set_read_format(peer, gateway->peer_read_format);
3417 ast_channel_make_compatible(chan, peer);
3418 }
3419 ast_channel_lock(chan);
3420 }
3421 return NULL;
3422 }
3423
3424 if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
3425 return NULL;
3426 };
3427
3428 /* this frame was generated by the fax gateway, pass it on */
3430 return f;
3431 }
3432
3433 /* If we aren't bridged or we don't have a peer, don't do anything */
3434 ast_channel_unlock(chan);
3435 peer = ast_channel_bridge_peer(chan);
3436 ast_channel_lock(chan);
3437 if (!peer) {
3438 return f;
3439 }
3440
3441 if (!gateway->bridged) {
3442 enum ast_t38_state state_chan;
3443 enum ast_t38_state state_peer;
3444 int chan_is_hungup;
3445 int peer_is_hungup;
3446
3447 chan_is_hungup = ast_check_hangup(chan);
3448 peer_is_hungup = ast_check_hangup(peer);
3449 /* Don't start a gateway if either channel is hung up */
3450 if (chan_is_hungup || peer_is_hungup) {
3451 return f;
3452 }
3453
3454 ast_channel_unlock(chan);
3455 state_chan = ast_channel_get_t38_state(chan);
3456 state_peer = ast_channel_get_t38_state(peer);
3457 ast_channel_lock(chan);
3458
3459 /* don't start a gateway if neither channel can handle T.38 */
3460 if (state_chan == T38_STATE_UNAVAILABLE && state_peer == T38_STATE_UNAVAILABLE) {
3461 ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
3462 ast_framehook_detach(chan, gateway->framehook);
3463 details->gateway_id = -1;
3464
3465 ast_string_field_set(details, result, "FAILED");
3466 ast_string_field_set(details, resultstr, "neither channel supports T.38");
3467 ast_string_field_set(details, error, "T38_NEG_ERROR");
3468 details->is_t38_negotiated = 0;
3469 set_channel_variables(chan, details);
3470 return f;
3471 }
3472
3473 if (details->gateway_timeout) {
3474 gateway->timeout_start = ast_tvnow();
3475 }
3476
3477 ast_channel_unlock(chan);
3478 ast_channel_lock_both(chan, peer);
3479
3480 /* we are bridged, change r/w formats to SLIN for v21 preamble
3481 * detection and T.30 */
3484
3487
3490
3493
3494 ast_channel_unlock(peer);
3495
3496 gateway->bridged = 1;
3497 if (!(gateway->peer_v21_session = fax_v21_session_new(peer))) {
3498 ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(peer));
3499 ast_framehook_detach(chan, gateway->framehook);
3500 return f;
3501 }
3502 }
3503
3504 if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
3505 if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > details->gateway_timeout) {
3506 ast_debug(1, "no fax activity between %s and %s after %d ms, disabling gateway\n", ast_channel_name(chan), ast_channel_name(peer), details->gateway_timeout);
3507 ast_framehook_detach(chan, gateway->framehook);
3508 details->gateway_id = -1;
3509
3510 ast_string_field_set(details, result, "FAILED");
3511 ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
3512 ast_string_field_set(details, error, "TIMEOUT");
3513 details->is_t38_negotiated = 0;
3514 set_channel_variables(chan, details);
3515 return f;
3516 }
3517 }
3518
3519 /* only handle VOICE, MODEM, and CONTROL frames*/
3520 switch (f->frametype) {
3521 case AST_FRAME_VOICE:
3525 return f;
3526 }
3527 break;
3528 case AST_FRAME_MODEM:
3529 if (f->subclass.integer == AST_MODEM_T38) {
3530 break;
3531 }
3532 return f;
3533 case AST_FRAME_CONTROL:
3535 break;
3536 }
3537 return f;
3538 default:
3539 return f;
3540 }
3541
3542 /* detect the active channel */
3543 switch (event) {
3545 active = peer;
3546 break;
3548 active = chan;
3549 break;
3550 default:
3551 ast_log(LOG_WARNING, "unhandled framehook event %u\n", event);
3552 return f;
3553 }
3554
3555 /* handle control frames */
3557 return fax_gateway_detect_t38(gateway, chan, peer, active, f);
3558 }
3559
3560 if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
3561 /* not in gateway mode and have not detected v21 yet, listen
3562 * for v21 */
3563 return fax_gateway_detect_v21(gateway, chan, peer, active, f);
3564 }
3565
3566 /* in gateway mode, gateway some packets */
3567 if (gateway->t38_state == T38_STATE_NEGOTIATED) {
3568 struct ast_trans_pvt *readtrans;
3569
3570 if (!gateway->s || !gateway->s->tech_pvt) {
3571 ast_log(LOG_ERROR, "no FAX session on chan %s for T.38 gateway session, odd", ast_channel_name(chan));
3572 return f;
3573 }
3574
3575 /* framehooks are called in __ast_read() before frame format
3576 * translation is done, so we need to translate here */
3578 && (readtrans = ast_channel_readtrans(active))) {
3579 if ((f = ast_translate(readtrans, f, event == AST_FRAMEHOOK_EVENT_WRITE ? 0 : 1)) == NULL) {
3580 f = &ast_null_frame;
3581 return f;
3582 }
3583 /* XXX we ignore the return value here, perhaps we should
3584 * disable the gateway if a write fails. I am not sure how a
3585 * write would fail, or even if a failure would be fatal so for
3586 * now we'll just ignore the return value. */
3587 gateway->s->tech->write(gateway->s, f);
3588 ast_frfree(f);
3589 } else {
3590 gateway->s->tech->write(gateway->s, f);
3591 }
3592
3593 f = &ast_null_frame;
3594 return f;
3595 }
3596
3597 /* force silence on the line if T.38 negotiation might be taking place */
3598 if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
3599 if (f->frametype == AST_FRAME_VOICE &&
3601 short silence_buf[f->samples];
3602 struct ast_frame silence_frame = {
3604 .subclass.format = ast_format_slin,
3605 .data.ptr = silence_buf,
3606 .samples = f->samples,
3607 .datalen = sizeof(silence_buf),
3608 };
3609 memset(silence_buf, 0, sizeof(silence_buf));
3610 return ast_frisolate(&silence_frame);
3611 } else {
3612 return &ast_null_frame;
3613 }
3614 }
3615
3616 return f;
3617}
3618
3619/*! \brief Attach a gateway framehook object to a channel.
3620 * \param chan the channel to attach to
3621 * \param details fax session details
3622 * \return the framehook id of the attached framehook or -1 on error
3623 * \retval -1 error
3624 */
3625static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_details *details)
3626{
3627 struct fax_gateway *gateway;
3628 struct ast_framehook_interface fr_hook = {
3630 .event_cb = fax_gateway_framehook,
3631 .destroy_cb = fax_gateway_framehook_destroy,
3632 .disable_inheritance = 1, /* Masquerade inheritance is handled through the datastore fixup */
3633 };
3634
3635 if (global_fax_debug) {
3637 }
3638
3639 ast_string_field_set(details, result, "SUCCESS");
3640 ast_string_field_set(details, resultstr, "gateway operation started successfully");
3641 ast_string_field_set(details, error, "NO_ERROR");
3642 set_channel_variables(chan, details);
3643
3644 /* set up the frame hook*/
3645 gateway = fax_gateway_new(chan, details);
3646 if (!gateway) {
3647 ast_string_field_set(details, result, "FAILED");
3648 ast_string_field_set(details, resultstr, "error initializing gateway session");
3649 ast_string_field_set(details, error, "INIT_ERROR");
3650 details->is_t38_negotiated = 0;
3651 set_channel_variables(chan, details);
3652 report_fax_status(chan, details, "No Available Resource");
3653 return -1;
3654 }
3655
3656 fr_hook.data = gateway;
3657 ast_channel_lock(chan);
3658 gateway->framehook = ast_framehook_attach(chan, &fr_hook);
3659 ast_channel_unlock(chan);
3660
3661 if (gateway->framehook < 0) {
3662 ao2_ref(gateway, -1);
3663 ast_string_field_set(details, result, "FAILED");
3664 ast_string_field_set(details, resultstr, "error attaching gateway to channel");
3665 ast_string_field_set(details, error, "INIT_ERROR");
3666 details->is_t38_negotiated = 0;
3667 set_channel_variables(chan, details);
3668 return -1;
3669 }
3670
3671 return gateway->framehook;
3672}
3673
3674/*! \brief destroy a FAX detect structure */
3675static void destroy_faxdetect(void *data)
3676{
3677 struct fax_detect *faxdetect = data;
3678
3679 if (faxdetect->dsp) {
3680 ast_dsp_free(faxdetect->dsp);
3681 faxdetect->dsp = NULL;
3682 }
3683 ao2_cleanup(faxdetect->details);
3684 ao2_cleanup(faxdetect->orig_format);
3685}
3686
3687/*! \brief Create a new fax detect object.
3688 * \param chan the channel attaching to
3689 * \param timeout in ms to remove framehook in this time if not zero
3690 * \param flags required options
3691 * \return NULL or a fax gateway object
3692 */
3693static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int flags)
3694{
3695 struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
3696 if (!faxdetect) {
3697 return NULL;
3698 }
3699
3700 faxdetect->flags = flags;
3701
3702 if (timeout) {
3703 faxdetect->timeout_start = ast_tvnow();
3704 } else {
3705 faxdetect->timeout_start.tv_sec = 0;
3706 faxdetect->timeout_start.tv_usec = 0;
3707 }
3708
3709 if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
3710 faxdetect->dsp = ast_dsp_new();
3711 if (!faxdetect->dsp) {
3712 ao2_ref(faxdetect, -1);
3713 return NULL;
3714 }
3717 } else {
3718 faxdetect->dsp = NULL;
3719 }
3720
3721 return faxdetect;
3722}
3723
3724/*! \brief Deref the faxdetect data structure when the faxdetect framehook is detached
3725 * \param data framehook data (faxdetect data)*/
3726static void fax_detect_framehook_destroy(void *data)
3727{
3728 struct fax_detect *faxdetect = data;
3729
3730 ao2_ref(faxdetect, -1);
3731}
3732
3733/*! \brief Fax Detect Framehook
3734 *
3735 * Listen for fax tones in audio path and enable jumping to a extension when detected.
3736 *
3737 * \param chan channel
3738 * \param f frame to handle may be NULL
3739 * \param event framehook event
3740 * \param data framehook data (struct fax_detect *)
3741 *
3742 * \return processed frame or NULL when f is NULL or a null frame
3743 */
3744static struct ast_frame *fax_detect_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
3745{
3746 struct fax_detect *faxdetect = data;
3747 struct ast_fax_session_details *details;
3748 struct ast_control_t38_parameters *control_params;
3749 RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3750 RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3751 int result = 0;
3752
3753 /* Ref bump the channel for when we have to unlock it */
3754 ao2_ref(chan, 1);
3755
3756 details = faxdetect->details;
3757
3758 switch (event) {
3760 /* Setup format for DSP on ATTACH*/
3762
3767 ast_framehook_detach(chan, details->faxdetect_id);
3768 details->faxdetect_id = -1;
3769 return f;
3770 }
3771 }
3772
3773 return NULL;
3775 /* restore audio formats when we are detached */
3776 ast_set_read_format(chan, faxdetect->orig_format);
3777 ast_channel_unlock(chan);
3778 peer = ast_channel_bridge_peer(chan);
3779 if (peer) {
3780 ast_channel_make_compatible(chan, peer);
3781 }
3782 ast_channel_lock(chan);
3783 return NULL;
3785 if (f) {
3786 break;
3787 }
3788 default:
3789 return f;
3790 };
3791
3792 if (details->faxdetect_id < 0) {
3793 return f;
3794 }
3795
3796 if (!ast_tvzero(faxdetect->timeout_start)
3797 && ast_tvdiff_ms(ast_tvnow(), faxdetect->timeout_start) > details->faxdetect_timeout) {
3798 ast_debug(1, "FAXOPT(faxdetect) timeout on %s\n", ast_channel_name(chan));
3799 ast_framehook_detach(chan, details->faxdetect_id);
3800 details->faxdetect_id = -1;
3801 return f;
3802 }
3803
3804 /* only handle VOICE and CONTROL frames*/
3805 switch (f->frametype) {
3806 case AST_FRAME_VOICE:
3807 /* we have no DSP this means we not detecting CNG */
3808 if (!faxdetect->dsp) {
3809 return f;
3810 }
3811 /* We can only process some formats*/
3815 return f;
3816 }
3817 break;
3818 case AST_FRAME_CONTROL:
3820 (faxdetect->flags & FAX_DETECT_MODE_T38)) {
3821 break;
3822 }
3823 return f;
3824 default:
3825 return f;
3826 }
3827
3828 if (f->frametype == AST_FRAME_VOICE) {
3829 f = ast_dsp_process(chan, faxdetect->dsp, f);
3830 if (f->frametype == AST_FRAME_DTMF) {
3831 result = f->subclass.integer;
3832 }
3833 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
3834 control_params = f->data.ptr;
3835 switch (control_params->request_response) {
3836 case AST_T38_NEGOTIATED:
3838 result = 't';
3839 break;
3840 default:
3841 break;
3842 }
3843 }
3844
3845 if (result) {
3846 const char *target_context;
3847
3848 switch (result) {
3849 case 'f':
3850 case 't':
3851 target_context = ast_channel_context(chan);
3852
3853 ast_channel_unlock(chan);
3854 ast_frfree(f);
3855 f = &ast_null_frame;
3856 if (ast_exists_extension(chan, target_context, "fax", 1,
3857 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
3858 ast_verb(2, "Redirecting '%s' to fax extension due to %s detection\n",
3859 ast_channel_name(chan), (result == 'f') ? "CNG" : "T38");
3860 pbx_builtin_setvar_helper(chan, "FAXEXTEN", ast_channel_exten(chan));
3861 if (ast_async_goto(chan, target_context, "fax", 1)) {
3862 ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(chan), target_context);
3863 }
3864 } else {
3865 ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
3866 (result == 'f') ? "CNG" : "T38", target_context);
3867 }
3868 ast_channel_lock(chan);
3869
3870 ast_framehook_detach(chan, details->faxdetect_id);
3871 details->faxdetect_id = -1;
3872 break;
3873 default:
3874 break;
3875 }
3876 }
3877
3878 return f;
3879}
3880
3881/*! \brief Attach a faxdetect framehook object to a channel.
3882 * \param chan the channel to attach to
3883 * \param timeout in ms to remove framehook in this time if not zero
3884 * \return the faxdetect structure or NULL on error
3885 * \param flags required options
3886 * \retval -1 error
3887 */
3888static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
3889{
3890 struct fax_detect *faxdetect;
3891 struct ast_fax_session_details *details;
3892 struct ast_framehook_interface fr_hook = {
3894 .event_cb = fax_detect_framehook,
3895 .destroy_cb = fax_detect_framehook_destroy,
3896 };
3897
3898 if (!(details = find_or_create_details(chan))) {
3899 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
3900 return -1;
3901 }
3902
3903 /* set up the frame hook*/
3904 faxdetect = fax_detect_new(chan, timeout, flags);
3905 if (!faxdetect) {
3906 ao2_ref(details, -1);
3907 return -1;
3908 }
3909
3910 fr_hook.data = faxdetect;
3911 faxdetect->details = details;
3912 ast_channel_lock(chan);
3913 details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
3914 details->faxdetect_timeout = timeout;
3915 details->faxdetect_flags = flags;
3916 ast_channel_unlock(chan);
3917
3918 if (details->faxdetect_id < 0) {
3919 ao2_ref(faxdetect, -1);
3920 }
3921
3922 return details->faxdetect_id;
3923}
3924
3925/*! \brief hash callback for ao2 */
3926static int session_hash_cb(const void *obj, const int flags)
3927{
3928 const struct ast_fax_session *s = obj;
3929
3930 return s->id;
3931}
3932
3933/*! \brief compare callback for ao2 */
3934static int session_cmp_cb(void *obj, void *arg, int flags)
3935{
3936 struct ast_fax_session *lhs = obj, *rhs = arg;
3937
3938 return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
3939}
3940
3941/*! \brief fax session tab completion */
3943{
3944 int tklen;
3945 int wordnum = 0;
3946 char *name = NULL;
3947 struct ao2_iterator i;
3948 struct ast_fax_session *s;
3949 char tbuf[5];
3950
3951 if (a->pos != 3) {
3952 return NULL;
3953 }
3954
3955 tklen = strlen(a->word);
3956 i = ao2_iterator_init(faxregistry.container, 0);
3957 while ((s = ao2_iterator_next(&i))) {
3958 snprintf(tbuf, sizeof(tbuf), "%u", s->id);
3959 if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
3960 name = ast_strdup(tbuf);
3961 ao2_ref(s, -1);
3962 break;
3963 }
3964 ao2_ref(s, -1);
3965 }
3967 return name;
3968}
3969
3970static char *cli_fax_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3971{
3972 struct fax_module *fax;
3973
3974 switch(cmd) {
3975 case CLI_INIT:
3976 e->command = "fax show version";
3977 e->usage =
3978 "Usage: fax show version\n"
3979 " Show versions of FAX For Asterisk components.\n";
3980 return NULL;
3981 case CLI_GENERATE:
3982 return NULL;
3983 }
3984
3985 if (a->argc != 3) {
3986 return CLI_SHOWUSAGE;
3987 }
3988
3989 ast_cli(a->fd, "FAX For Asterisk Components:\n");
3990 ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
3992 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
3993 ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
3994 }
3996 ast_cli(a->fd, "\n");
3997
3998 return CLI_SUCCESS;
3999}
4000
4001/*! \brief enable FAX debugging */
4002static char *cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4003{
4004 int flag;
4005 const char *what;
4006
4007 switch (cmd) {
4008 case CLI_INIT:
4009 e->command = "fax set debug {on|off}";
4010 e->usage =
4011 "Usage: fax set debug { on | off }\n"
4012 " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n"
4013 " additional events sent to manager sessions with 'call' class permissions. When\n"
4014 " verbosity is greater than '5' events will be displayed to the console and audio versus\n"
4015 " energy analysis will be performed and displayed to the console.\n";
4016 return NULL;
4017 case CLI_GENERATE:
4018 return NULL;
4019 }
4020
4021 what = a->argv[e->args-1]; /* guaranteed to exist */
4022 if (!strcasecmp(what, "on")) {
4023 flag = 1;
4024 } else if (!strcasecmp(what, "off")) {
4025 flag = 0;
4026 } else {
4027 return CLI_SHOWUSAGE;
4028 }
4029
4031 ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
4032
4033 return CLI_SUCCESS;
4034}
4035
4036/*! \brief display registered FAX capabilities */
4037static char *cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4038{
4039 struct fax_module *fax;
4040 unsigned int num_modules = 0;
4041
4042 switch (cmd) {
4043 case CLI_INIT:
4044 e->command = "fax show capabilities";
4045 e->usage =
4046 "Usage: fax show capabilities\n"
4047 " Shows the capabilities of the registered FAX technology modules\n";
4048 return NULL;
4049 case CLI_GENERATE:
4050 return NULL;
4051 }
4052
4053 ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
4055 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4056 ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
4057 fax->tech->cli_show_capabilities(a->fd);
4058 num_modules++;
4059 }
4061 ast_cli(a->fd, "%u registered modules\n\n", num_modules);
4062
4063 return CLI_SUCCESS;
4064}
4065
4066/*! \brief display global defaults and settings */
4067static char *cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4068{
4069 struct fax_module *fax;
4070 char modems[128] = "";
4071 struct fax_options options;
4072
4073 switch (cmd) {
4074 case CLI_INIT:
4075 e->command = "fax show settings";
4076 e->usage =
4077 "Usage: fax show settings\n"
4078 " Show the global settings and defaults of both the FAX core and technology modules\n";
4079 return NULL;
4080 case CLI_GENERATE:
4081 return NULL;
4082 }
4083
4085
4086 ast_cli(a->fd, "FAX For Asterisk Settings:\n");
4087 ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
4088 ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off");
4089 ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate);
4090 ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate);
4091 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4092 ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
4093 ast_cli(a->fd, "\tT.38 Negotiation Timeout: %u\n", options.t38timeout);
4094 ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
4096 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4097 ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
4098 fax->tech->cli_show_settings(a->fd);
4099 }
4101
4102 return CLI_SUCCESS;
4103}
4104
4105/*! \brief display details of a specified fax session */
4106static char *cli_fax_show_session(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4107{
4108 struct ast_fax_session *s, tmp;
4109
4110 switch (cmd) {
4111 case CLI_INIT:
4112 e->command = "fax show session";
4113 e->usage =
4114 "Usage: fax show session <session number>\n"
4115 " Shows status of the named FAX session\n";
4116 return NULL;
4117 case CLI_GENERATE:
4119 }
4120
4121 if (a->argc != 4) {
4122 return CLI_SHOWUSAGE;
4123 }
4124
4125 if (sscanf(a->argv[3], "%u", &tmp.id) != 1) {
4126 ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
4127 return RESULT_SUCCESS;
4128 }
4129
4130 ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
4131 s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
4132 if (s) {
4133 ast_cli(a->fd, "%-22s : %s\n", "channel", s->channame);
4134 s->tech->cli_show_session(s, a->fd);
4135 ao2_ref(s, -1);
4136 }
4137 ast_cli(a->fd, "\n\n");
4138
4139 return CLI_SUCCESS;
4140}
4141
4142static int manager_fax_session(struct mansession *s, const struct message *m)
4143{
4144 const char *action_id = astman_get_header(m, "ActionID");
4145 const char *session_number = astman_get_header(m, "SessionNumber");
4146 char id_text[256] = "";
4147 struct ast_fax_session *session;
4149
4150 if (sscanf(session_number, "%30u", &find_session.id) != 1) {
4151 astman_send_error(s, m, "Invalid session ID");
4152 return 0;
4153 }
4154
4156 if (!session) {
4157 astman_send_error(s, m, "Session not found");
4158 return 0;
4159 }
4160
4161 if (!session->tech->manager_fax_session) {
4162 astman_send_error(s, m, "Fax technology doesn't provide a handler for FAXSession");
4163 ao2_ref(session, -1);
4164 return 0;
4165 }
4166
4167 if (!ast_strlen_zero(action_id)) {
4168 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4169 }
4170
4171 astman_send_ack(s, m, "FAXSession event will follow");
4172
4173 session->tech->manager_fax_session(s, id_text, session);
4174 ao2_ref(session, -1);
4175
4176 return 0;
4177}
4178
4179/*! \brief display fax stats */
4180static char *cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4181{
4182 struct fax_module *fax;
4183
4184 switch (cmd) {
4185 case CLI_INIT:
4186 e->command = "fax show stats";
4187 e->usage =
4188 "Usage: fax show stats\n"
4189 " Shows a statistical summary of FAX transmissions\n";
4190 return NULL;
4191 case CLI_GENERATE:
4192 return NULL;
4193 }
4194
4195 ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
4196 ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
4197 ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
4198 ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
4199 ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
4200 ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
4201 ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
4203 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4204 fax->tech->cli_show_stats(a->fd);
4205 }
4207 ast_cli(a->fd, "\n\n");
4208
4209 return CLI_SUCCESS;
4210}
4211
4212static int manager_fax_stats(struct mansession *s, const struct message *m)
4213{
4214 const char *action_id = astman_get_header(m, "ActionID");
4215
4216 char id_text[256] = "";
4217
4218 astman_send_ack(s, m, "FAXStats event will follow");
4219
4220 if (!ast_strlen_zero(action_id)) {
4221 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4222 }
4223
4224 astman_append(s, "Event: FAXStats\r\n"
4225 "%s"
4226 "CurrentSessions: %d\r\n"
4227 "ReservedSessions: %d\r\n"
4228 "TransmitAttempts: %d\r\n"
4229 "ReceiveAttempts: %d\r\n"
4230 "CompletedFAXes: %d\r\n"
4231 "FailedFAXes: %d\r\n"
4232 "\r\n",
4233 id_text,
4234 faxregistry.active_sessions, faxregistry.reserved_sessions,
4235 faxregistry.fax_tx_attempts, faxregistry.fax_rx_attempts,
4236 faxregistry.fax_complete, faxregistry.fax_failures);
4237
4238 return 0;
4239}
4240
4241static const char *fax_session_type(struct ast_fax_session *s)
4242{
4243 if (s->details->caps & AST_FAX_TECH_AUDIO) {
4244 return "G.711";
4245 }
4246 if (s->details->caps & AST_FAX_TECH_T38) {
4247 return "T.38";
4248 }
4249
4250 return "none";
4251}
4252
4254{
4255 if (s->details->caps & AST_FAX_TECH_GATEWAY) {
4256 return "gateway";
4257 }
4258 if (s->details->caps & AST_FAX_TECH_SEND) {
4259 return "send";
4260 }
4261 if (s->details->caps & AST_FAX_TECH_RECEIVE) {
4262 return "receive";
4263 }
4265 return "V.21";
4266 }
4267
4268 return "none";
4269}
4270
4271/*! \brief display fax sessions */
4272static char *cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4273{
4274 struct ast_fax_session *s;
4275 struct ao2_iterator i;
4276 int session_count;
4277 char *filenames;
4278
4279 switch (cmd) {
4280 case CLI_INIT:
4281 e->command = "fax show sessions";
4282 e->usage =
4283 "Usage: fax show sessions\n"
4284 " Shows the current FAX sessions\n";
4285 return NULL;
4286 case CLI_GENERATE:
4287 return NULL;
4288 }
4289
4290 ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
4291 ast_cli(a->fd, "%-30.30s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
4292 "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
4293 i = ao2_iterator_init(faxregistry.container, 0);
4294 while ((s = ao2_iterator_next(&i))) {
4295 ao2_lock(s);
4296
4297 filenames = generate_filenames_string(s->details, "", ", ");
4298
4299 ast_cli(a->fd, "%-30.30s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
4300 s->channame, s->tech->type, s->id,
4303 ast_fax_state_to_str(s->state), S_OR(filenames, ""));
4304
4305 ast_free(filenames);
4306 ao2_unlock(s);
4307 ao2_ref(s, -1);
4308 }
4311 ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
4312
4313 return CLI_SUCCESS;
4314}
4315
4317 struct ast_fax_session *session, const char *id_text)
4318{
4319 char *filenames;
4320
4322 filenames = generate_filenames_string(session->details, "", ",");
4323
4324 if (!filenames) {
4325 ast_log(LOG_ERROR, "Error generating Files string");
4327 return -1;
4328 }
4329
4330 astman_append(s, "Event: FAXSessionsEntry\r\n"
4331 "%s" /* ActionID if present */
4332 "Channel: %s\r\n" /* Channel name */
4333 "Technology: %s\r\n" /* Fax session technology */
4334 "SessionNumber: %u\r\n" /* Session ID */
4335 "SessionType: %s\r\n" /* G711 or T38 */
4336 "Operation: %s\r\n"
4337 "State: %s\r\n"
4338 "Files: %s\r\n"
4339 "\r\n",
4340 id_text, session->channame, session->tech->type, session->id,
4342 ast_fax_state_to_str(session->state), S_OR(filenames, ""));
4343 ast_free(filenames);
4345 return 0;
4346}
4347
4348static int manager_fax_sessions(struct mansession *s, const struct message *m)
4349{
4350 const char *action_id = astman_get_header(m, "ActionID");
4351 char id_text[256];
4352 struct ast_fax_session *session;
4353 struct ao2_iterator iter;
4354 int session_count = 0;
4355
4356 id_text[0] = '\0';
4357 if (!ast_strlen_zero(action_id)) {
4358 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4359 }
4360
4361 astman_send_listack(s, m, "FAXSessionsEntry event list will follow", "Start");
4362
4363 iter = ao2_iterator_init(faxregistry.container, 0);
4364 while ((session = ao2_iterator_next(&iter))) {
4365 if (!manager_fax_sessions_entry(s, session, id_text)) {
4366 session_count++;
4367 }
4368 ao2_ref(session, -1);
4369 }
4370 ao2_iterator_destroy(&iter);
4371
4372 astman_send_list_complete_start(s, m, "FAXSessionsComplete", session_count);
4373 astman_append(s, "Total: %d\r\n", session_count);
4375
4376 return 0;
4377}
4378
4379static struct ast_cli_entry fax_cli[] = {
4380 AST_CLI_DEFINE(cli_fax_show_version, "Show versions of FAX For Asterisk components"),
4381 AST_CLI_DEFINE(cli_fax_set_debug, "Enable/Disable FAX debugging on new FAX sessions"),
4382 AST_CLI_DEFINE(cli_fax_show_capabilities, "Show the capabilities of the registered FAX technology modules"),
4383 AST_CLI_DEFINE(cli_fax_show_settings, "Show the global settings and defaults of both the FAX core and technology modules"),
4384 AST_CLI_DEFINE(cli_fax_show_session, "Show the status of the named FAX sessions"),
4385 AST_CLI_DEFINE(cli_fax_show_sessions, "Show the current FAX sessions"),
4386 AST_CLI_DEFINE(cli_fax_show_stats, "Summarize FAX session history"),
4387};
4388
4389static void set_general_options(const struct fax_options *options)
4390{
4394}
4395
4397{
4401}
4402
4403static int set_t38timeout(const char *value, unsigned int *t38timeout)
4404{
4405 unsigned int timeout;
4406
4407 if (sscanf(value, "%u", &timeout) != 1) {
4408 ast_log(LOG_ERROR, "Unable to get timeout from '%s'\n", value);
4409 return -1;
4410 } else if (timeout) {
4411 *t38timeout = timeout;
4412 } else {
4413 ast_log(LOG_ERROR, "T.38 negotiation timeout must be non-zero\n");
4414 return -1;
4415 }
4416
4417 return 0;
4418}
4419
4420/*! \brief configure res_fax */
4421static int set_config(int reload)
4422{
4423 struct ast_config *cfg;
4424 struct ast_variable *v;
4425 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
4426 char modems[128] = "";
4427 struct fax_options options;
4428 int res = 0;
4429
4431
4432 /* When we're not reloading, we have to be certain to set the general options
4433 * to the defaults in case config loading goes wrong at some point. On a reload,
4434 * the general options need to stay the same as what they were prior to the
4435 * reload rather than being reset to the defaults.
4436 */
4437 if (!reload) {
4439 }
4440
4441 /* read configuration */
4442 if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
4443 ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
4444 config, reload ? "not changing" : "using default");
4445 return 0;
4446 }
4447
4448 if (cfg == CONFIG_STATUS_FILEINVALID) {
4449 ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
4450 config, reload ? "not changing" : "using default");
4451 return 0;
4452 }
4453
4454 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
4455 return 0;
4456 }
4457
4458 if (reload) {
4460 }
4461
4462 /* create configuration */
4463 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
4464 int rate;
4465
4466 if (!strcasecmp(v->name, "minrate")) {
4467 ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
4468 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4469 res = -1;
4470 goto end;
4471 }
4472 options.minrate = rate;
4473 } else if (!strcasecmp(v->name, "maxrate")) {
4474 ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
4475 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4476 res = -1;
4477 goto end;
4478 }
4479 options.maxrate = rate;
4480 } else if (!strcasecmp(v->name, "statusevents")) {
4481 ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
4482 options.statusevents = ast_true(v->value);
4483 } else if (!strcasecmp(v->name, "ecm")) {
4484 ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
4485 options.ecm = ast_true(v->value);
4486 } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
4487 options.modems = 0;
4488 update_modem_bits(&options.modems, v->value);
4489 } else if (!strcasecmp(v->name, "t38timeout")) {
4490 if (set_t38timeout(v->value, &options.t38timeout)) {
4491 res = -1;
4492 goto end;
4493 }
4494 }
4495 }
4496
4497 if (options.maxrate < options.minrate) {
4498 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
4499 res = -1;
4500 goto end;
4501 }
4502
4503 if (check_modem_rate(options.modems, options.minrate)) {
4504 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4505 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
4506 res = -1;
4507 goto end;
4508 }
4509
4510 if (check_modem_rate(options.modems, options.maxrate)) {
4511 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4512 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
4513 res = -1;
4514 goto end;
4515 }
4516
4518
4519end:
4520 ast_config_destroy(cfg);
4521 return res;
4522}
4523
4524/*! \brief FAXOPT read function returns the contents of a FAX option */
4525static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
4526{
4527 struct ast_fax_session_details *details = find_details(chan);
4528 int res = 0;
4529 char *filenames;
4530
4531 if (!details) {
4532 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4533 return -1;
4534 }
4535 if (!strcasecmp(data, "ecm")) {
4536 ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
4537 } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
4538 !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
4539 ast_copy_string(buf, details->gateway_id != -1 ? "yes" : "no", len);
4540 } else if (!strcasecmp(data, "faxdetect")) {
4541 ast_copy_string(buf, details->faxdetect_id != -1 ? "yes" : "no", len);
4542 } else if (!strcasecmp(data, "error")) {
4543 ast_copy_string(buf, details->error, len);
4544 } else if (!strcasecmp(data, "filename")) {
4545 if (AST_LIST_EMPTY(&details->documents)) {
4546 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4547 res = -1;
4548 } else {
4549 ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
4550 }
4551 } else if (!strcasecmp(data, "filenames")) {
4552 if (AST_LIST_EMPTY(&details->documents)) {
4553 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4554 res = -1;
4555 } else if ((filenames = generate_filenames_string(details, "", ","))) {
4556 ast_copy_string(buf, filenames, len);
4557 ast_free(filenames);
4558 } else {
4559 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", ast_channel_name(chan), data);
4560 res = -1;
4561 }
4562 } else if (!strcasecmp(data, "headerinfo")) {
4563 ast_copy_string(buf, details->headerinfo, len);
4564 } else if (!strcasecmp(data, "localstationid")) {
4566 } else if (!strcasecmp(data, "maxrate")) {
4567 snprintf(buf, len, "%u", details->maxrate);
4568 } else if (!strcasecmp(data, "minrate")) {
4569 snprintf(buf, len, "%u", details->minrate);
4570 } else if (!strcasecmp(data, "pages")) {
4571 snprintf(buf, len, "%u", details->pages_transferred);
4572 } else if (!strcasecmp(data, "rate")) {
4574 } else if (!strcasecmp(data, "remotestationid")) {
4576 } else if (!strcasecmp(data, "resolution")) {
4577 ast_copy_string(buf, details->resolution, len);
4578 } else if (!strcasecmp(data, "sessionid")) {
4579 snprintf(buf, len, "%u", details->id);
4580 } else if (!strcasecmp(data, "status")) {
4581 ast_copy_string(buf, details->result, len);
4582 } else if (!strcasecmp(data, "statusstr")) {
4583 ast_copy_string(buf, details->resultstr, len);
4584 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
4585 ast_fax_modem_to_str(details->modems, buf, len);
4586 } else if (!strcasecmp(data, "t38timeout")) {
4587 snprintf(buf, len, "%u", details->t38timeout);
4588 } else if (!strcasecmp(data, "negotiate_both")) {
4589 ast_copy_string(buf, details->negotiate_both != -1 ? "yes" : "no", len);
4590 } else {
4591 ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", ast_channel_name(chan), data);
4592 res = -1;
4593 }
4594 ao2_ref(details, -1);
4595
4596 return res;
4597}
4598
4599/*! \brief FAXOPT write function modifies the contents of a FAX option */
4600static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
4601{
4602 int res = 0;
4603 struct ast_fax_session_details *details;
4604
4605 if (!(details = find_or_create_details(chan))) {
4606 ast_log(LOG_WARNING, "channel '%s' can't set FAXOPT(%s) to '%s' because it failed to create a datastore.\n", ast_channel_name(chan), data, value);
4607 return -1;
4608 }
4609 ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", ast_channel_name(chan), data, value);
4610
4611 if (!strcasecmp(data, "ecm")) {
4612 const char *val = ast_skip_blanks(value);
4613 if (ast_true(val)) {
4614 details->option.ecm = AST_FAX_OPTFLAG_TRUE;
4615 } else if (ast_false(val)) {
4616 details->option.ecm = AST_FAX_OPTFLAG_FALSE;
4617 } else {
4618 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
4619 }
4620 } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
4621 !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
4622 const char *val = ast_skip_blanks(value);
4623 char *timeout = strchr(val, ',');
4624
4625 if (timeout) {
4626 *timeout++ = '\0';
4627 }
4628
4629 if (ast_true(val)) {
4630 if (details->gateway_id < 0) {
4631 details->gateway_timeout = 0;
4632 if (timeout) {
4633 unsigned int gwtimeout;
4634
4635 if (sscanf(timeout, "%30u", &gwtimeout) == 1) {
4636 details->gateway_timeout = gwtimeout * 1000;
4637 } else {
4638 ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
4639 }
4640 }
4641
4642 details->gateway_id = fax_gateway_attach(chan, details);
4643 if (details->gateway_id < 0) {
4644 ast_log(LOG_ERROR, "Error attaching T.38 gateway to channel %s.\n", ast_channel_name(chan));
4645 res = -1;
4646 } else {
4647 ast_debug(1, "Attached T.38 gateway to channel %s.\n", ast_channel_name(chan));
4648 }
4649 } else {
4650 ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
4651 }
4652 } else if (ast_false(val)) {
4653 ast_channel_lock(chan);
4654 ast_framehook_detach(chan, details->gateway_id);
4655 ast_channel_unlock(chan);
4656 details->gateway_id = -1;
4657 } else {
4658 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4659 }
4660 } else if (!strcasecmp(data, "faxdetect")) {
4661 const char *val = ast_skip_blanks(value);
4662 char *timeout = strchr(val, ',');
4663 unsigned int fdtimeout = 0;
4664 int flags;
4665 int faxdetect;
4666
4667 if (timeout) {
4668 *timeout++ = '\0';
4669 }
4670
4671 if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
4672 if (details->faxdetect_id < 0) {
4673 if (timeout) {
4674 if (sscanf(timeout, "%30u", &fdtimeout) == 1) {
4675 fdtimeout *= 1000;
4676 } else {
4677 ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n",
4678 timeout, data);
4679 }
4680 }
4681
4682 if (!strcasecmp(val, "t38")) {
4683 flags = FAX_DETECT_MODE_T38;
4684 } else if (!strcasecmp(val, "cng")) {
4685 flags = FAX_DETECT_MODE_CNG;
4686 } else {
4687 flags = FAX_DETECT_MODE_BOTH;
4688 }
4689
4690 faxdetect = fax_detect_attach(chan, fdtimeout, flags);
4691 if (faxdetect < 0) {
4692 ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", ast_channel_name(chan));
4693 res = -1;
4694 } else {
4695 ast_debug(1, "Attached FAX detect to channel %s.\n", ast_channel_name(chan));
4696 }
4697 } else {
4698 ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
4699 }
4700 } else if (ast_false(val)) {
4701 ast_channel_lock(chan);
4702 ast_framehook_detach(chan, details->faxdetect_id);
4703 ast_channel_unlock(chan);
4704 details->faxdetect_id = -1;
4705 } else {
4706 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4707 }
4708 } else if (!strcasecmp(data, "headerinfo")) {
4710 } else if (!strcasecmp(data, "localstationid")) {
4712 } else if (!strcasecmp(data, "maxrate")) {
4713 details->maxrate = fax_rate_str_to_int(value);
4714 if (!details->maxrate) {
4715 details->maxrate = ast_fax_maxrate();
4716 }
4717 } else if (!strcasecmp(data, "minrate")) {
4718 details->minrate = fax_rate_str_to_int(value);
4719 if (!details->minrate) {
4720 details->minrate = ast_fax_minrate();
4721 }
4722 } else if (!strcasecmp(data, "t38timeout")) {
4723 if (set_t38timeout(value, &details->t38timeout)) {
4724 res = -1;
4725 }
4726 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
4727 update_modem_bits(&details->modems, value);
4728 } else if (!strcasecmp(data, "negotiate_both")) {
4730 } else {
4731 ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", ast_channel_name(chan), data, value);
4732 res = -1;
4733 }
4734
4735 ao2_ref(details, -1);
4736
4737 return res;
4738}
4739
4740/*! \brief FAXOPT dialplan function */
4742 .name = "FAXOPT",
4743 .read = acf_faxopt_read,
4744 .write = acf_faxopt_write,
4745};
4746
4747/*! \brief unload res_fax */
4748static int unload_module(void)
4749{
4751
4753 ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
4754 }
4755
4757 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
4758 }
4759
4761 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
4762 }
4763
4764 ast_manager_unregister("FAXSessions");
4765 ast_manager_unregister("FAXSession");
4766 ast_manager_unregister("FAXStats");
4767
4768 if (fax_logger_level != -1) {
4770 }
4771
4772 ao2_ref(faxregistry.container, -1);
4773
4774 return 0;
4775}
4776
4777/*!
4778 * \brief Load the module
4779 *
4780 * Module loading including tests for configuration or dependencies.
4781 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
4782 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
4783 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
4784 * configuration file or other non-critical problem return
4785 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
4786 */
4787static int load_module(void)
4788{
4789 int res;
4790
4791 /* initialize the registry */
4792 faxregistry.active_sessions = 0;
4793 faxregistry.reserved_sessions = 0;
4796 if (!faxregistry.container) {
4798 }
4799
4800 if (set_config(0) < 0) {
4801 ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
4802 ao2_ref(faxregistry.container, -1);
4804 }
4805
4806 /* register CLI operations and applications */
4808 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
4809 ao2_ref(faxregistry.container, -1);
4811 }
4813 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
4815 ao2_ref(faxregistry.container, -1);
4817 }
4818
4820 ast_log(LOG_WARNING, "failed to register 'FAXSessions' AMI command.\n");
4823 ao2_ref(faxregistry.container, -1);
4825 }
4826
4828 ast_log(LOG_WARNING, "failed to register 'FAXSession' AMI command.\n");
4829 ast_manager_unregister("FAXSession");
4832 ao2_ref(faxregistry.container, -1);
4834 }
4835
4837 ast_log(LOG_WARNING, "failed to register 'FAXStats' AMI command.\n");
4838 ast_manager_unregister("FAXSession");
4839 ast_manager_unregister("FAXSessions");
4842 ao2_ref(faxregistry.container, -1);
4844 }
4845
4849
4850 return res;
4851}
4852
4853static int reload_module(void)
4854{
4855 set_config(1);
4856 return 0;
4857}
4858
4859
4861 .support_level = AST_MODULE_SUPPORT_CORE,
4862 .load = load_module,
4863 .unload = unload_module,
4865 .load_pri = AST_MODPRI_APP_DEPEND,
static int fdtimeout
jack_status_t status
Definition: app_jack.c:146
struct sla_ringing_trunk * first
Definition: app_sla.c:332
ast_mutex_t lock
Definition: app_sla.c:331
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
Asterisk version information.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define OBJ_POINTER
Definition: astobj2.h:1150
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
static int tmp()
Definition: bt_open.c:389
static PGresult * result
Definition: cel_pgsql.c:84
static int chancount
Definition: channel.c:93
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:3007
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2896
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2404
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2413
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10586
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
#define ast_channel_lock(chan)
Definition: channel.h:2968
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6739
ast_t38_state
Possible T38 states on channels.
Definition: channel.h:898
@ T38_STATE_UNAVAILABLE
Definition: channel.h:899
@ T38_STATE_UNKNOWN
Definition: channel.h:900
@ T38_STATE_REJECTED
Definition: channel.h:902
@ T38_STATE_NEGOTIATED
Definition: channel.h:903
@ T38_STATE_NEGOTIATING
Definition: channel.h:901
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3181
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2975
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:5163
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4276
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition: channel.c:1257
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5781
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4672
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5822
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2824
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2969
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2418
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define RESULT_SUCCESS
Definition: cli.h:40
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
Convenient Signal Processing routines.
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
Definition: dsp.c:1788
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1488
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
Definition: dsp.c:1843
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress,...
Definition: dsp.c:1499
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
#define DSP_FAXMODE_DETECT_SQUELCH
Definition: dsp.h:49
#define DSP_FAXMODE_DETECT_CNG
Definition: dsp.h:47
int ast_dsp_set_faxmode(struct ast_dsp *dsp, int faxmode)
Set fax mode.
Definition: dsp.c:1883
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
char * end
Definition: eagi_proxy.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
long int flag
Definition: f2c.h:83
Generic File Format Support. Should be included by clients of the file handling routines....
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
@ AST_FORMAT_CMP_NOT_EQUAL
Definition: format.h:38
Media Format Cache API.
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
static const char name[]
Definition: format_mp3.c:68
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
Definition: framehook.h:151
@ AST_FRAMEHOOK_EVENT_ATTACHED
Definition: framehook.h:154
@ AST_FRAMEHOOK_EVENT_DETACHED
Definition: framehook.h:155
@ AST_FRAMEHOOK_EVENT_WRITE
Definition: framehook.h:153
@ AST_FRAMEHOOK_EVENT_READ
Definition: framehook.h:152
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:2011
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1969
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:2047
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2001
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1630
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2055
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1890
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7608
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
static char prefix[MAX_PREFIX]
Definition: http.c:144
static int session_count
Definition: http.c:109
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define END_OPTIONS
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define BEGIN_OPTIONS
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
char * strsep(char **str, const char *delims)
Configuration File Parser.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3336
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
@ AST_T38_REQUEST_PARMS
@ AST_T38_TERMINATED
@ AST_T38_REFUSED
@ AST_T38_REQUEST_TERMINATE
@ AST_T38_NEGOTIATED
@ AST_T38_REQUEST_NEGOTIATE
#define AST_FRAME_DTMF
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define AST_MODEM_T38
#define ast_frfree(fr)
@ AST_T38_RATE_14400
@ AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF
@ AST_FRAME_VOICE
@ AST_FRAME_MODEM
@ AST_FRAME_CONTROL
@ AST_CONTROL_T38_PARAMETERS
struct ast_frame ast_null_frame
Definition: main/frame.c:79
Support for logging to various files, console and syslog Configuration in file logger....
#define AST_LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:2851
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:2909
Tone Indication Support.
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:302
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393
I/O Management (derived from Cheops-NG)
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:278
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:378
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:362
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
#define AST_JSON_UTF8_VALIDATE(str)
Check str for UTF-8 and replace with an empty string if fails the check.
Definition: json.h:224
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
Definition: linkedlists.h:333
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:415
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
Asterisk locking-related definitions:
#define ast_rwlock_wrlock(a)
Definition: lock.h:236
#define ast_rwlock_rdlock(a)
Definition: lock.h:235
#define AST_RWLOCK_DEFINE_STATIC(rwlock)
Definition: lock.h:543
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:619
#define ast_rwlock_unlock(a)
Definition: lock.h:234
int errno
static struct mansession_session * find_session(uint32_t ident, int incinuse)
Definition: manager.c:7828
#define EVENT_FLAG_REPORTING
Definition: manager.h:84
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
#define EVENT_FLAG_CALL
Definition: manager.h:76
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:331
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:330
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_APP_DEPEND
Definition: module.h:342
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:469
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
Options provided by main asterisk program.
Core PBX routines and definitions.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:6969
static int reload(void)
void ast_fax_tech_unregister(struct ast_fax_tech *tech)
unregister a FAX technology module
Definition: res_fax.c:991
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Release a session token.
Definition: res_fax.c:1082
#define RES_FAX_MAXRATE
Definition: res_fax.c:522
static int session_cmp_cb(void *obj, void *arg, int flags)
compare callback for ao2
Definition: res_fax.c:3934
static int manager_fax_sessions_entry(struct mansession *s, struct ast_fax_session *session, const char *id_text)
Definition: res_fax.c:4316
static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
Create a fax session and start T.30<->T.38 gateway mode.
Definition: res_fax.c:2916
static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
FAXOPT write function modifies the contents of a FAX option.
Definition: res_fax.c:4600
static int session_hash_cb(const void *obj, const int flags)
hash callback for ao2
Definition: res_fax.c:3926
static char * cli_fax_show_session(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display details of a specified fax session
Definition: res_fax.c:4106
static struct ast_fax_session_details * session_details_new(void)
create a FAX session details structure
Definition: res_fax.c:695
unsigned int ast_fax_minrate(void)
get the minimum supported fax rate
Definition: res_fax.c:803
static struct ast_fax_session_details * find_details(struct ast_channel *chan)
returns a reference counted pointer to a fax datastore, if it exists
Definition: res_fax.c:661
static struct ast_fax_session * fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
Reserve a fax session.
Definition: res_fax.c:1145
static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
Definition: res_fax.c:811
static void set_general_options(const struct fax_options *options)
Definition: res_fax.c:4389
static void fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
Definition: res_fax.c:3084
#define FAX_DETECT_MODE_BOTH
Definition: res_fax.c:484
static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1855
static const struct ast_app_option fax_exec_options[128]
Definition: res_fax.c:574
static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
FAXOPT read function returns the contents of a FAX option.
Definition: res_fax.c:4525
static void destroy_gateway(void *data)
destroy a FAX gateway session structure
Definition: res_fax.c:2838
static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
send a FAX status manager event
Definition: res_fax.c:1406
static const char app_receivefax[]
Definition: res_fax.c:427
int fax_rx_attempts
Definition: res_fax.c:505
static void destroy_v21_sessions(struct fax_gateway *gateway)
destroy the v21 detection parts of a fax gateway session
Definition: res_fax.c:2820
static int fax_logger_level
Definition: res_fax.c:486
static char * cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display fax stats
Definition: res_fax.c:4180
static void destroy_session_details(void *details)
destroy a FAX session details structure
Definition: res_fax.c:683
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert a ast_fax_state to a string
Definition: res_fax.c:1012
@ OPT_CALLEDMODE
Definition: res_fax.c:557
@ OPT_REQUEST_T38
Definition: res_fax.c:562
@ OPT_FORCE_AUDIO
Definition: res_fax.c:563
@ OPT_CALLERMODE
Definition: res_fax.c:558
@ OPT_ALLOWAUDIO
Definition: res_fax.c:561
@ OPT_STATUS
Definition: res_fax.c:560
@ OPT_DEBUG
Definition: res_fax.c:559
static char * ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
Definition: res_fax.c:845
static const struct fax_options default_options
Definition: res_fax.c:538
static const struct ast_datastore_info fax_datastore
Definition: res_fax.c:618
static struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
Definition: res_fax.c:4741
static void fax_detect_framehook_destroy(void *data)
Deref the faxdetect data structure when the faxdetect framehook is detached.
Definition: res_fax.c:3726
#define RES_FAX_MODEM
Definition: res_fax.c:524
static struct ast_fax_session * fax_v21_session_new(struct ast_channel *chan)
Definition: res_fax.c:2860
int fax_tx_attempts
Definition: res_fax.c:503
static struct ast_frame * fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
T.30<->T.38 gateway framehook.
Definition: res_fax.c:3382
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:750
static void fixup_callback(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Copies fax detection and gateway framehooks during masquerades.
Definition: res_fax.c:635
static const char * config
Definition: res_fax.c:552
static int set_t38timeout(const char *value, unsigned int *t38timeout)
Definition: res_fax.c:4403
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition: res_fax.c:937
static int sendfax_exec(struct ast_channel *chan, const char *data)
initiate a send FAX session
Definition: res_fax.c:2589
static char * fax_session_tab_complete(struct ast_cli_args *a)
fax session tab completion
Definition: res_fax.c:3942
#define FAX_MAXBUCKETS
maximum buckets for res_fax ao2 containers
Definition: res_fax.c:489
static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
Attach a faxdetect framehook object to a channel.
Definition: res_fax.c:3888
static const char * fax_session_type(struct ast_fax_session *s)
Definition: res_fax.c:4241
#define RES_FAX_MINRATE
Definition: res_fax.c:521
static int receivefax_exec(struct ast_channel *chan, const char *data)
initiate a receive FAX session
Definition: res_fax.c:2081
static ast_rwlock_t options_lock
Definition: res_fax.c:547
static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
this is the generic FAX session handling function
Definition: res_fax.c:1589
static void fax_gateway_framehook_destroy(void *data)
Destroy the gateway data structure when the framehook is detached.
Definition: res_fax.c:3344
static int reload_module(void)
Definition: res_fax.c:4853
struct ao2_container * container
Definition: res_fax.c:501
static struct fax_detect * fax_detect_new(struct ast_channel *chan, int timeout, int flags)
Create a new fax detect object.
Definition: res_fax.c:3693
static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_details *details)
Attach a gateway framehook object to a channel.
Definition: res_fax.c:3625
static int set_config(int reload)
configure res_fax
Definition: res_fax.c:4421
static struct ast_control_t38_parameters our_t38_parameters
Definition: res_fax.c:732
static const char app_sendfax[]
Definition: res_fax.c:428
static char * cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display registered FAX capabilities
Definition: res_fax.c:4037
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:904
static struct ast_frame * fax_gateway_detect_v21(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
Definition: res_fax.c:3011
#define FAX_DETECT_MODE_T38
Definition: res_fax.c:483
static char * cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display global defaults and settings
Definition: res_fax.c:4067
const char * ast_fax_session_operation_str(struct ast_fax_session *s)
get string representation of a FAX session's operation
Definition: res_fax.c:4253
static struct ast_json * generate_filenames_json(struct ast_fax_session_details *details)
Definition: res_fax.c:1329
unsigned int ast_fax_maxrate(void)
get the maxiumum supported fax rate
Definition: res_fax.c:795
int ast_fax_tech_register(struct ast_fax_tech *tech)
register a FAX technology module
Definition: res_fax.c:973
static void destroy_session(void *session)
destroy a FAX session structure
Definition: res_fax.c:1095
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:4396
static struct ast_frame * fax_detect_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
Fax Detect Framehook.
Definition: res_fax.c:3744
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:739
static int manager_fax_session(struct mansession *s, const struct message *m)
Definition: res_fax.c:4142
static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
Definition: res_fax.c:576
static struct ast_fax_session * fax_session_new(struct ast_fax_session_details *details, struct ast_channel *chan, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
create a FAX session
Definition: res_fax.c:1214
static char * cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
enable FAX debugging
Definition: res_fax.c:4002
#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason)
Definition: res_fax.c:1484
#define RES_FAX_STATUSEVENTS
Definition: res_fax.c:523
#define RES_FAX_T38TIMEOUT
Definition: res_fax.c:525
int active_sessions
Definition: res_fax.c:497
static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1490
void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
Log message at FAX or recommended level.
Definition: res_fax.c:1035
static void destroy_callback(void *data)
Definition: res_fax.c:609
static int manager_fax_stats(struct mansession *s, const struct message *m)
Definition: res_fax.c:4212
static int load_module(void)
Load the module.
Definition: res_fax.c:4787
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel's fax datastore. If the datastore does...
Definition: res_fax.c:763
static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:2282
#define FAX_GATEWAY_TIMEOUT
Definition: res_fax.c:492
#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason)
Definition: res_fax.c:1468
int fax_complete
Definition: res_fax.c:507
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Definition: res_fax.c:1045
static char * cli_fax_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_fax.c:3970
static int unload_module(void)
unload res_fax
Definition: res_fax.c:4748
static struct fax_gateway * fax_gateway_new(struct ast_channel *chan, struct ast_fax_session_details *details)
Create a new fax gateway object.
Definition: res_fax.c:2879
static void destroy_faxdetect(void *data)
destroy a FAX detect structure
Definition: res_fax.c:3675
static char * generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
Generate a string of filenames using the given prefix and separator.
Definition: res_fax.c:1369
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1446
static struct ast_frame * fax_gateway_detect_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
T38 Gateway Negotiate t38 parameters.
Definition: res_fax.c:3108
static int disable_t38(struct ast_channel *chan)
Definition: res_fax.c:1526
int nextsessionname
Definition: res_fax.c:511
static char * cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display fax sessions
Definition: res_fax.c:4272
static struct ast_cli_entry fax_cli[]
Definition: res_fax.c:4379
static struct @435 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
static int manager_fax_sessions(struct mansession *s, const struct message *m)
Definition: res_fax.c:4348
#define FAX_DETECT_MODE_CNG
FAX Detect flags.
Definition: res_fax.c:482
int fax_failures
Definition: res_fax.c:509
static int report_receive_fax_status(struct ast_channel *chan, const char *filename)
Report on the final state of a receive fax operation.
Definition: res_fax.c:2017
static struct ast_frame * fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan)
Definition: res_fax.c:2971
int reserved_sessions
Definition: res_fax.c:499
static int global_fax_debug
Definition: res_fax.c:554
static int report_send_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details)
Report on the status of a completed fax send attempt.
Definition: res_fax.c:2526
#define RES_FAX_TIMEOUT
Definition: res_fax.c:491
static struct fax_options general_options
Definition: res_fax.c:536
@ AST_FAX_OPTFLAG_FALSE
Definition: res_fax.h:85
@ AST_FAX_OPTFLAG_TRUE
Definition: res_fax.h:87
ast_fax_capabilities
capabilities for res_fax to locate a fax technology module
Definition: res_fax.h:35
@ AST_FAX_TECH_T38
Definition: res_fax.h:43
@ AST_FAX_TECH_AUDIO
Definition: res_fax.h:41
@ AST_FAX_TECH_RECEIVE
Definition: res_fax.h:39
@ AST_FAX_TECH_V21_DETECT
Definition: res_fax.h:49
@ AST_FAX_TECH_MULTI_DOC
Definition: res_fax.h:45
@ AST_FAX_TECH_SEND
Definition: res_fax.h:37
@ AST_FAX_TECH_GATEWAY
Definition: res_fax.h:47
#define AST_FAX_FRFLAG_GATEWAY
Definition: res_fax.h:232
ast_fax_state
current state of a fax session
Definition: res_fax.h:65
@ AST_FAX_STATE_INITIALIZED
Definition: res_fax.h:69
@ AST_FAX_STATE_INACTIVE
Definition: res_fax.h:79
@ AST_FAX_STATE_ACTIVE
Definition: res_fax.h:73
@ AST_FAX_STATE_COMPLETE
Definition: res_fax.h:75
@ AST_FAX_STATE_OPEN
Definition: res_fax.h:71
@ AST_FAX_STATE_UNINITIALIZED
Definition: res_fax.h:67
@ AST_FAX_STATE_RESERVED
Definition: res_fax.h:77
ast_fax_modems
fax modem capabilities
Definition: res_fax.h:53
@ AST_FAX_MODEM_V17
Definition: res_fax.h:55
@ AST_FAX_MODEM_V29
Definition: res_fax.h:59
@ AST_FAX_MODEM_V27TER
Definition: res_fax.h:57
@ AST_FAX_MODEM_V34
Definition: res_fax.h:61
#define NULL
Definition: resample.c:96
Asterisk internal frame definitions.
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: smoother.c:169
#define ast_smoother_feed(s, f)
Definition: smoother.h:75
struct ast_smoother * ast_smoother_new(int bytes)
Definition: smoother.c:108
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1512
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
String manipulation functions.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: utils.c:2167
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Main Channel structure associated with a channel.
descriptor for a cli entry.
Definition: cli.h:171
int args
This gets set in ast_cli_register()
Definition: cli.h:185
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
enum ast_control_t38_rate rate
enum ast_control_t38_rate_management rate_management
enum ast_control_t38 request_response
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
Definition: dsp.c:407
struct debug_info_history c2s s2c
Definition: res_fax.c:438
struct timeval base_tv
Definition: res_fax.c:437
struct ast_dsp * dsp
Definition: res_fax.c:439
struct ast_fax_document * next
Definition: res_fax.h:103
char filename[0]
Definition: res_fax.h:104
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
const ast_string_field localstationid
Definition: res_fax.h:142
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:177
struct ast_fax_documents documents
Definition: res_fax.h:119
const ast_string_field result
Definition: res_fax.h:142
enum ast_fax_modems modems
Definition: res_fax.h:115
unsigned int t38timeout
Definition: res_fax.h:179
const ast_string_field headerinfo
Definition: res_fax.h:142
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:175
union ast_fax_session_details::@251 option
unsigned int minrate
Definition: res_fax.h:171
const ast_string_field resultstr
Definition: res_fax.h:142
unsigned int maxrate
Definition: res_fax.h:173
const ast_string_field error
Definition: res_fax.h:142
unsigned int id
Definition: res_fax.h:117
unsigned int pages_transferred
Definition: res_fax.h:144
const ast_string_field resolution
Definition: res_fax.h:142
const ast_string_field remotestationid
Definition: res_fax.h:142
const ast_string_field transfer_rate
Definition: res_fax.h:142
enum ast_fax_capabilities caps
Definition: res_fax.h:113
The data required to handle a fax session.
Definition: res_fax.h:202
void * tech_pvt
Definition: res_fax.h:216
char * chan_uniqueid
Definition: res_fax.h:222
struct ast_smoother * smoother
Definition: res_fax.h:228
const struct ast_fax_tech * tech
Definition: res_fax.h:214
unsigned long frames_received
Definition: res_fax.h:210
unsigned long frames_sent
Definition: res_fax.h:212
struct ast_channel * chan
Definition: res_fax.h:224
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:226
char * channame
Definition: res_fax.h:220
unsigned int id
Definition: res_fax.h:204
enum ast_fax_state state
Definition: res_fax.h:218
struct ast_fax_session_details * details
Definition: res_fax.h:208
unsigned int transcoding_jbig
Definition: res_fax.h:99
enum ast_control_t38_rate rate
Definition: res_fax.h:95
unsigned int version
Definition: res_fax.h:93
unsigned int max_ifp
Definition: res_fax.h:94
unsigned int transcoding_mmr
Definition: res_fax.h:98
enum ast_control_t38_rate_management rate_management
Definition: res_fax.h:96
unsigned int fill_bit_removal
Definition: res_fax.h:97
used to register a FAX technology module with res_fax
Definition: res_fax.h:235
void(*const release_token)(struct ast_fax_tech_token *)
Definition: res_fax.h:249
void(*const destroy_session)(struct ast_fax_session *)
Definition: res_fax.h:253
char *(*const cli_show_settings)(int)
Definition: res_fax.h:276
struct ast_frame *(*const read)(struct ast_fax_session *)
Definition: res_fax.h:255
int(*const switch_to_t38)(struct ast_fax_session *)
Definition: res_fax.h:265
void *(*const new_session)(struct ast_fax_session *, struct ast_fax_tech_token *)
Definition: res_fax.h:251
int(*const cancel_session)(struct ast_fax_session *)
Definition: res_fax.h:261
struct ast_module * module
Definition: res_fax.h:245
const char *const type
Definition: res_fax.h:237
int(*const write)(struct ast_fax_session *, const struct ast_frame *)
Definition: res_fax.h:257
int(*const generate_silence)(struct ast_fax_session *)
Definition: res_fax.h:263
char *(*const cli_show_capabilities)(int)
Definition: res_fax.h:267
const char *const version
Definition: res_fax.h:241
const char *const description
Definition: res_fax.h:239
char *(*const cli_show_stats)(int)
Definition: res_fax.h:274
char *(*const cli_show_session)(struct ast_fax_session *, int)
Definition: res_fax.h:269
int(*const start_session)(struct ast_fax_session *)
Definition: res_fax.h:259
enum ast_fax_capabilities caps
Definition: res_fax.h:243
struct ast_fax_tech_token *(*const reserve_session)(struct ast_fax_session *)
Definition: res_fax.h:247
Structure used to handle boolean flags.
Definition: utils.h:199
Definition of a media format.
Definition: format.c:43
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
const char * src
Abstract JSON element (object, array, string, int, ...).
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
struct ast_frame f
Definition: translate.h:215
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
unsigned int consec_ms
Definition: res_fax.c:432
unsigned int consec_frames
Definition: res_fax.c:431
unsigned char silence
Definition: res_fax.c:433
Definition: search.h:40
Definition: astman.c:222
used for fax detect framehook
Definition: res_fax.c:468
struct timeval timeout_start
the start of our timeout counter
Definition: res_fax.c:470
struct ast_dsp * dsp
DSP Processor.
Definition: res_fax.c:472
int flags
mode
Definition: res_fax.c:478
struct ast_format * orig_format
original audio formats
Definition: res_fax.c:474
struct ast_fax_session_details * details
fax session details
Definition: res_fax.c:476
used for gateway framehook
Definition: res_fax.c:443
struct ast_fax_session * peer_v21_session
Definition: res_fax.c:446
int bridged
bridged
Definition: res_fax.c:455
struct timeval timeout_start
the start of our timeout counter
Definition: res_fax.c:451
enum ast_t38_state t38_state
a flag to track the state of our negotiation
Definition: res_fax.c:459
struct ast_format * chan_read_format
original audio formats
Definition: res_fax.c:461
struct ast_format * chan_write_format
Definition: res_fax.c:462
struct ast_fax_session * chan_v21_session
Definition: res_fax.c:447
struct ast_format * peer_write_format
Definition: res_fax.c:464
struct ast_format * peer_read_format
Definition: res_fax.c:463
struct ast_fax_session * s
FAX Session.
Definition: res_fax.c:445
int framehook
framehook used in gateway mode
Definition: res_fax.c:453
struct ast_fax_tech_token * token
reserved fax session token
Definition: res_fax.c:449
int detected_v21
1 if a v21 preamble has been detected
Definition: res_fax.c:457
registered FAX technology modules are put into this list
Definition: res_fax.c:515
const struct ast_fax_tech * tech
Definition: res_fax.c:516
enum ast_fax_modems modems
Definition: res_fax.c:528
unsigned int t38timeout
Definition: res_fax.c:533
uint32_t statusevents
Definition: res_fax.c:529
unsigned int minrate
Definition: res_fax.c:531
unsigned int maxrate
Definition: res_fax.c:532
uint32_t ecm
Definition: res_fax.c:530
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:326
Number structure.
Definition: app_followme.c:154
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
const char * args
static struct test_options options
static struct test_val a
static struct test_val d
static struct test_val c
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2297
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
Support for translation of data formats. translate.c.
struct ast_frame * ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, int consume)
translates one or more frames Apply an input frame into the translator and receive zero or one output...
Definition: translate.c:566
FILE * out
Definition: utils/frame.c:33
int error(const char *format,...)
Definition: utils/frame.c:999
Utility functions.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ARRAY_LEN(a)
Definition: utils.h:666