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