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