Wed Jan 8 2020 09:49:53

Asterisk developer's documentation


app_fax.c File Reference
#include "asterisk.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <pthread.h>
#include <errno.h>
#include <tiffio.h>
#include <spandsp.h>
#include <spandsp/version.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/module.h"
#include "asterisk/manager.h"

Go to the source code of this file.

Data Structures

struct  fax_session
 

Macros

#define MAX_SAMPLES   240
 
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
 
#define WATCHDOG_STATE_TIMEOUT   5 * 60
 
#define WATCHDOG_TOTAL_TIMEOUT   30 * 60
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void * fax_generator_alloc (struct ast_channel *chan, void *params)
 
static int fax_generator_generate (struct ast_channel *chan, void *data, int len, int samples)
 
static int load_module (void)
 
static void phase_e_handler (t30_state_t *f, void *user_data, int result)
 
static int rcvfax_exec (struct ast_channel *chan, const char *data)
 
static void set_ecm (t30_state_t *state, int ecm)
 
static void set_file (t30_state_t *state, fax_session *s)
 
static void set_local_info (t30_state_t *state, fax_session *s)
 
static int set_logging (logging_state_t *state)
 
static int sndfax_exec (struct ast_channel *chan, const char *data)
 
static void span_message (int level, const char *msg)
 
static int t38_tx_packet_handler (t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
 
static int transmit (fax_session *s)
 
static int transmit_audio (fax_session *s)
 
static int transmit_t38 (fax_session *s)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Simple FAX Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, }
 
static const char app_rcvfax_name [] = "ReceiveFAX"
 
static const char app_sndfax_name [] = "SendFAX"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_generator generator
 

Macro Definition Documentation

#define MAX_SAMPLES   240

Definition at line 148 of file app_fax.c.

Referenced by fax_generator_generate().

#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES

Definition at line 34 of file app_fax.c.

#define WATCHDOG_STATE_TIMEOUT   5 * 60

Definition at line 157 of file app_fax.c.

Referenced by transmit_audio(), and transmit_t38().

#define WATCHDOG_TOTAL_TIMEOUT   30 * 60

Definition at line 156 of file app_fax.c.

Referenced by transmit_audio(), and transmit_t38().

Function Documentation

static void __reg_module ( void  )
static

Definition at line 1005 of file app_fax.c.

static void __unreg_module ( void  )
static

Definition at line 1005 of file app_fax.c.

static void* fax_generator_alloc ( struct ast_channel chan,
void *  params 
)
static

Definition at line 326 of file app_fax.c.

327 {
328  return params;
329 }
static int fax_generator_generate ( struct ast_channel chan,
void *  data,
int  len,
int  samples 
)
static

Definition at line 331 of file app_fax.c.

References AST_FORMAT_SLINEAR, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), errno, ast_frame::frametype, len(), LOG_WARNING, MAX_SAMPLES, ast_channel::name, and ast_frame::samples.

332 {
333  fax_state_t *fax = (fax_state_t*) data;
334  uint8_t buffer[AST_FRIENDLY_OFFSET + MAX_SAMPLES * sizeof(uint16_t)];
335  int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
336 
337  struct ast_frame outf = {
339  .subclass.codec = AST_FORMAT_SLINEAR,
340  .src = __FUNCTION__,
341  };
342 
343  if (samples > MAX_SAMPLES) {
344  ast_log(LOG_WARNING, "Only generating %d samples, where %d requested\n", MAX_SAMPLES, samples);
346  }
347 
348  if ((len = fax_tx(fax, buf, samples)) > 0) {
349  outf.samples = len;
350  AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET, len * sizeof(int16_t));
351 
352  if (ast_write(chan, &outf) < 0) {
353  ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
354  return -1;
355  }
356  }
357 
358  return 0;
359 }
#define LOG_WARNING
Definition: logger.h:144
#define AST_FRAME_SET_BUFFER(fr, _base, _ofs, _datalen)
Definition: frame.h:183
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
#define MAX_SAMPLES
Definition: app_fax.c:148
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
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:4916
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
int samples
Definition: frame.h:150
static int load_module ( void  )
static

Definition at line 988 of file app_fax.c.

References ast_register_application_xml, rcvfax_exec(), and sndfax_exec().

989 {
990  int res ;
991 
994 
995  /* The default SPAN message handler prints to stderr. It is something we do not want */
996  span_set_message_handler(NULL);
997 
998  return res;
999 }
static const char app_sndfax_name[]
Definition: app_fax.c:145
static const char app_rcvfax_name[]
Definition: app_fax.c:146
static int rcvfax_exec(struct ast_channel *chan, const char *data)
Definition: app_fax.c:909
static int sndfax_exec(struct ast_channel *chan, const char *data)
Definition: app_fax.c:840
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static void phase_e_handler ( t30_state_t *  f,
void *  user_data,
int  result 
)
static

Definition at line 203 of file app_fax.c.

References ast_debug, ast_log(), ast_manager_event, ast_channel::caller, fax_session::chan, ast_channel::connected, fax_session::direction, EVENT_FLAG_CALL, ast_channel::exten, fax_session::file_name, fax_session::finished, ast_party_caller::id, ast_party_connected_line::id, LOG_WARNING, ast_party_id::name, ast_channel::name, ast_party_id::number, pbx_builtin_setvar_helper(), S_COR, S_OR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.

Referenced by transmit_audio(), and transmit_t38().

204 {
205  const char *local_ident;
206  const char *far_ident;
207  char buf[20];
208  fax_session *s = (fax_session *) user_data;
209  t30_stats_t stat;
210  int pages_transferred;
211 
212  ast_debug(1, "Fax phase E handler. result=%d\n", result);
213 
214  t30_get_transfer_statistics(f, &stat);
215 
216  s = (fax_session *) user_data;
217 
218  if (result != T30_ERR_OK) {
219  s->finished = -1;
220 
221  /* FAXSTATUS is already set to FAILED */
222  pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result));
223 
224  ast_log(LOG_WARNING, "Error transmitting fax. result=%d: %s.\n", result, t30_completion_code_to_str(result));
225 
226  return;
227  }
228 
229  s->finished = 1;
230 
231  local_ident = S_OR(t30_get_tx_ident(f), "");
232  far_ident = S_OR(t30_get_rx_ident(f), "");
233  pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS");
234  pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL);
235  pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident);
236 #if SPANDSP_RELEASE_DATE >= 20090220
237  pages_transferred = (s->direction) ? stat.pages_tx : stat.pages_rx;
238 #else
239  pages_transferred = stat.pages_transferred;
240 #endif
241  snprintf(buf, sizeof(buf), "%d", pages_transferred);
242  pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf);
243  snprintf(buf, sizeof(buf), "%d", stat.y_resolution);
244  pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf);
245  snprintf(buf, sizeof(buf), "%d", stat.bit_rate);
246  pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf);
247 
248  ast_debug(1, "Fax transmitted successfully.\n");
249  ast_debug(1, " Remote station ID: %s\n", far_ident);
250  ast_debug(1, " Pages transferred: %d\n", pages_transferred);
251  ast_debug(1, " Image resolution: %d x %d\n", stat.x_resolution, stat.y_resolution);
252  ast_debug(1, " Transfer Rate: %d\n", stat.bit_rate);
253 
255  s->direction ? "FaxSent" : "FaxReceived",
256  "Channel: %s\r\n"
257  "Exten: %s\r\n"
258  "CallerID: %s\r\n"
259  "CallerIDName: %s\r\n"
260  "ConnectedLineNum: %s\r\n"
261  "ConnectedLineName: %s\r\n"
262  "RemoteStationID: %s\r\n"
263  "LocalStationID: %s\r\n"
264  "PagesTransferred: %d\r\n"
265  "Resolution: %d\r\n"
266  "TransferRate: %d\r\n"
267  "FileName: %s\r\n",
268  s->chan->name,
269  s->chan->exten,
271  S_COR(s->chan->caller.id.name.valid, s->chan->caller.id.name.str, ""),
274  far_ident,
275  local_ident,
276  pages_transferred,
277  stat.y_resolution,
278  stat.bit_rate,
279  s->file_name);
280 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
char * file_name
Definition: app_fax.c:164
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
#define LOG_WARNING
Definition: logger.h:144
#define EVENT_FLAG_CALL
Definition: manager.h:72
char * str
Subscriber name (Malloced)
Definition: channel.h:214
#define ast_manager_event(chan, category, event, contents,...)
Definition: manager.h:221
struct ast_channel * chan
Definition: app_fax.c:160
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
int direction
Definition: app_fax.c:162
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#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:83
volatile int finished
Definition: app_fax.c:166
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_format f[]
Definition: format_g726.c:181
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...
Definition: pbx.c:10546
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int rcvfax_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 909 of file app_fax.c.

References args, AST_APP_ARG, ast_channel_queryoption(), ast_channel_setoption(), AST_DECLARE_APP_ARGS, ast_log(), AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), fax_session::caller_mode, fax_session::chan, fax_session::direction, dummy(), FALSE, fax_session::file_name, fax_session::finished, LOG_ERROR, parse(), transmit(), and TRUE.

Referenced by load_module().

910 {
911  int res = 0;
912  char *parse;
913  fax_session session;
914  char restore_digit_detect = 0;
915 
917  AST_APP_ARG(file_name);
918  AST_APP_ARG(options);
919  );
920 
921  if (chan == NULL) {
922  ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
923  return -1;
924  }
925 
926  /* The next few lines of code parse out the filename and header from the input string */
927  if (ast_strlen_zero(data)) {
928  /* No data implies no filename or anything is present */
929  ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");
930  return -1;
931  }
932 
933  parse = ast_strdupa(data);
934  AST_STANDARD_APP_ARGS(args, parse);
935 
936  session.caller_mode = FALSE;
937 
938  if (args.options) {
939  if (strchr(args.options, 'c'))
940  session.caller_mode = TRUE;
941  }
942 
943  /* Done parsing */
944  session.direction = 0;
945  session.file_name = args.file_name;
946  session.chan = chan;
947  session.finished = 0;
948 
949  /* get current digit detection mode, then disable digit detection if enabled */
950  {
951  int dummy = sizeof(restore_digit_detect);
952 
953  ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
954  }
955 
956  if (restore_digit_detect) {
957  char new_digit_detect = 0;
958 
959  ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
960  }
961 
962  /* disable FAX tone detection if enabled */
963  {
964  char new_fax_detect = 0;
965 
966  ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
967  }
968 
969  res = transmit(&session);
970 
971  if (restore_digit_detect) {
972  ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
973  }
974 
975  return res;
976 }
#define FALSE
Definition: app_minivm.c:506
char * file_name
Definition: app_fax.c:164
int ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block)
Checks the value of an option.
Definition: channel.c:7815
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define AST_OPTION_DIGIT_DETECT
Definition: frame.h:508
int caller_mode
Definition: app_fax.c:163
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7795
struct ast_channel * chan
Definition: app_fax.c:160
int direction
Definition: app_fax.c:162
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_OPTION_FAX_DETECT
Definition: frame.h:512
volatile int finished
Definition: app_fax.c:166
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
#define TRUE
Definition: app_minivm.c:503
static int transmit(fax_session *s)
Definition: app_fax.c:782
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
union ast_frame::@172 data
static void set_ecm ( t30_state_t *  state,
int  ecm 
)
static

Definition at line 316 of file app_fax.c.

Referenced by transmit_audio(), and transmit_t38().

317 {
318  t30_set_ecm_capability(state, ecm);
319  t30_set_supported_compressions(state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
320 }
static void set_file ( t30_state_t *  state,
fax_session s 
)
static

Definition at line 308 of file app_fax.c.

References fax_session::direction, and fax_session::file_name.

Referenced by transmit_audio(), and transmit_t38().

309 {
310  if (s->direction)
311  t30_set_tx_file(state, s->file_name, -1, -1);
312  else
313  t30_set_rx_file(state, s->file_name, -1);
314 }
char * file_name
Definition: app_fax.c:164
int direction
Definition: app_fax.c:162
static void set_local_info ( t30_state_t *  state,
fax_session s 
)
static

Definition at line 295 of file app_fax.c.

References ast_strlen_zero(), fax_session::chan, and pbx_builtin_getvar_helper().

Referenced by transmit_audio(), and transmit_t38().

296 {
297  const char *x;
298 
299  x = pbx_builtin_getvar_helper(s->chan, "LOCALSTATIONID");
300  if (!ast_strlen_zero(x))
301  t30_set_tx_ident(state, x);
302 
303  x = pbx_builtin_getvar_helper(s->chan, "LOCALHEADERINFO");
304  if (!ast_strlen_zero(x))
305  t30_set_tx_page_header_info(state, x);
306 }
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
struct ast_channel * chan
Definition: app_fax.c:160
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int set_logging ( logging_state_t *  state)
static

Definition at line 285 of file app_fax.c.

References option_debug, and span_message().

Referenced by transmit_audio(), and transmit_t38().

286 {
287  int level = SPAN_LOG_WARNING + option_debug;
288 
289  span_log_set_message_handler(state, span_message);
290  span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);
291 
292  return 0;
293 }
int option_debug
Definition: asterisk.c:182
static void span_message(int level, const char *msg)
Definition: app_fax.c:169
static int sndfax_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 840 of file app_fax.c.

References args, AST_APP_ARG, ast_channel_queryoption(), ast_channel_setoption(), AST_DECLARE_APP_ARGS, ast_log(), AST_OPTION_DIGIT_DETECT, AST_OPTION_FAX_DETECT, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), fax_session::caller_mode, fax_session::chan, fax_session::direction, dummy(), FALSE, fax_session::file_name, fax_session::finished, LOG_ERROR, parse(), transmit(), and TRUE.

Referenced by load_module().

841 {
842  int res = 0;
843  char *parse;
844  fax_session session = { 0, };
845  char restore_digit_detect = 0;
846 
848  AST_APP_ARG(file_name);
849  AST_APP_ARG(options);
850  );
851 
852  if (chan == NULL) {
853  ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
854  return -1;
855  }
856 
857  /* The next few lines of code parse out the filename and header from the input string */
858  if (ast_strlen_zero(data)) {
859  /* No data implies no filename or anything is present */
860  ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");
861  return -1;
862  }
863 
864  parse = ast_strdupa(data);
865  AST_STANDARD_APP_ARGS(args, parse);
866 
867  session.caller_mode = TRUE;
868 
869  if (args.options) {
870  if (strchr(args.options, 'a'))
871  session.caller_mode = FALSE;
872  }
873 
874  /* Done parsing */
875  session.direction = 1;
876  session.file_name = args.file_name;
877  session.chan = chan;
878  session.finished = 0;
879 
880  /* get current digit detection mode, then disable digit detection if enabled */
881  {
882  int dummy = sizeof(restore_digit_detect);
883 
884  ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
885  }
886 
887  if (restore_digit_detect) {
888  char new_digit_detect = 0;
889 
890  ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
891  }
892 
893  /* disable FAX tone detection if enabled */
894  {
895  char new_fax_detect = 0;
896 
897  ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
898  }
899 
900  res = transmit(&session);
901 
902  if (restore_digit_detect) {
903  ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
904  }
905 
906  return res;
907 }
#define FALSE
Definition: app_minivm.c:506
char * file_name
Definition: app_fax.c:164
int ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block)
Checks the value of an option.
Definition: channel.c:7815
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define AST_OPTION_DIGIT_DETECT
Definition: frame.h:508
int caller_mode
Definition: app_fax.c:163
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7795
struct ast_channel * chan
Definition: app_fax.c:160
int direction
Definition: app_fax.c:162
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_OPTION_FAX_DETECT
Definition: frame.h:512
volatile int finished
Definition: app_fax.c:166
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
#define TRUE
Definition: app_minivm.c:503
static int transmit(fax_session *s)
Definition: app_fax.c:782
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
union ast_frame::@172 data
static void span_message ( int  level,
const char *  msg 
)
static

Definition at line 169 of file app_fax.c.

References ast_log(), LOG_DEBUG, LOG_ERROR, and LOG_WARNING.

Referenced by set_logging().

170 {
171  if (level == SPAN_LOG_ERROR) {
172  ast_log(LOG_ERROR, "%s", msg);
173  } else if (level == SPAN_LOG_WARNING) {
174  ast_log(LOG_WARNING, "%s", msg);
175  } else {
176  ast_log(LOG_DEBUG, "%s", msg);
177  }
178 }
#define LOG_WARNING
Definition: logger.h:144
#define LOG_DEBUG
Definition: logger.h:122
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int t38_tx_packet_handler ( t38_core_state_t *  s,
void *  user_data,
const uint8_t *  buf,
int  len,
int  count 
)
static

Definition at line 180 of file app_fax.c.

References AST_FRAME_MODEM, AST_FRAME_SET_BUFFER, ast_log(), AST_MODEM_T38, ast_write(), errno, ast_frame::frametype, and LOG_WARNING.

Referenced by transmit_t38().

181 {
182  struct ast_channel *chan = (struct ast_channel *) user_data;
183 
184  struct ast_frame outf = {
186  .subclass.integer = AST_MODEM_T38,
187  .src = __FUNCTION__,
188  };
189 
190  /* TODO: Asterisk does not provide means of resending the same packet multiple
191  times so count is ignored at the moment */
192 
193  AST_FRAME_SET_BUFFER(&outf, buf, 0, len);
194 
195  if (ast_write(chan, &outf) < 0) {
196  ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
197  return -1;
198  }
199 
200  return 0;
201 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define LOG_WARNING
Definition: logger.h:144
#define AST_MODEM_T38
Definition: frame.h:216
#define AST_FRAME_SET_BUFFER(fr, _base, _ofs, _datalen)
Definition: frame.h:183
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
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:4916
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
static int transmit ( fax_session s)
static

Definition at line 782 of file app_fax.c.

References ast_channel::_state, ast_answer(), ast_channel_get_t38_state(), ast_debug, ast_log(), AST_STATE_UP, fax_session::chan, fax_session::finished, LOG_ERROR, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), T38_STATE_NEGOTIATED, fax_session::t38state, transmit_audio(), and transmit_t38().

Referenced by rcvfax_exec(), and sndfax_exec().

783 {
784  int res = 0;
785 
786  /* Clear all channel variables which to be set by the application.
787  Pre-set status to error so in case of any problems we can just leave */
788  pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED");
789  pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems");
790 
791  pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);
792  pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
793  pbx_builtin_setvar_helper(s->chan, "FAXPAGES", "0");
794  pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
795  pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL);
796 
797  if (s->chan->_state != AST_STATE_UP) {
798  /* Shouldn't need this, but checking to see if channel is already answered
799  * Theoretically asterisk should already have answered before running the app */
800  res = ast_answer(s->chan);
801  if (res) {
802  ast_log(LOG_WARNING, "Could not answer channel '%s'\n", s->chan->name);
803  return res;
804  }
805  }
806 
808  if (s->t38state != T38_STATE_NEGOTIATED) {
809  /* T38 is not negotiated on the channel yet. First start regular transmission. If it switches to T38, follow */
810  pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio");
811  res = transmit_audio(s);
812  if (res > 0) {
813  /* transmit_audio reports switchover to T38. Update t38state */
815  if (s->t38state != T38_STATE_NEGOTIATED) {
816  ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");
817  }
818  }
819  }
820 
821  if (s->t38state == T38_STATE_NEGOTIATED) {
822  pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38");
823  res = transmit_t38(s);
824  }
825 
826  if (res) {
827  ast_log(LOG_WARNING, "Transmission error\n");
828  res = -1;
829  } else if (s->finished < 0) {
830  ast_log(LOG_WARNING, "Transmission failed\n");
831  } else if (s->finished > 0) {
832  ast_debug(1, "Transmission finished Ok\n");
833  }
834 
835  return res;
836 }
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:2417
#define LOG_WARNING
Definition: logger.h:144
struct ast_channel * chan
Definition: app_fax.c:160
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
volatile int finished
Definition: app_fax.c:166
static int transmit_t38(fax_session *s)
Definition: app_fax.c:606
#define LOG_ERROR
Definition: logger.h:155
static int transmit_audio(fax_session *s)
Definition: app_fax.c:369
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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...
Definition: pbx.c:10546
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
enum ast_t38_state t38state
Definition: app_fax.c:161
static int transmit_audio ( fax_session s)
static

Definition at line 369 of file app_fax.c.

References ast_activate_generator(), ast_channel_get_t38_state(), AST_CONTROL_T38_PARAMETERS, ast_deactivate_generator(), ast_debug, AST_FORMAT_SLINEAR, AST_FRAME_CONTROL, AST_FRAME_VOICE, ast_frfree, ast_indicate_data(), ast_log(), ast_read(), ast_set_read_format(), ast_set_write_format(), AST_T38_NEGOTIATED, AST_T38_RATE_14400, AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, ast_tvdiff_sec(), ast_tvnow(), ast_waitfor(), fax_session::caller_mode, fax_session::chan, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, FALSE, fax_session::finished, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, ast_channel::name, phase_e_handler(), ast_frame::ptr, ast_channel::readformat, ast_control_t38_parameters::request_response, ast_frame::samples, set_ecm(), set_file(), set_local_info(), set_logging(), ast_frame::subclass, T38_STATE_NEGOTIATED, T38_STATE_UNAVAILABLE, fax_session::t38parameters, TRUE, ast_control_t38_parameters::version, WATCHDOG_STATE_TIMEOUT, WATCHDOG_TOTAL_TIMEOUT, and ast_channel::writeformat.

Referenced by transmit().

370 {
371  int res = -1;
372  int original_read_fmt = AST_FORMAT_SLINEAR;
373  int original_write_fmt = AST_FORMAT_SLINEAR;
374  fax_state_t fax;
375  t30_state_t *t30state;
376  struct ast_frame *inf = NULL;
377  int last_state = 0;
378  struct timeval now, start, state_change;
379  enum ast_t38_state t38_state;
380  struct ast_control_t38_parameters t38_parameters = { .version = 0,
381  .max_ifp = 800,
382  .rate = AST_T38_RATE_14400,
383  .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
384  .fill_bit_removal = 1,
385 /*
386  * spandsp has API calls to support MMR and JBIG transcoding, but they aren't
387  * implemented quite yet... so don't offer them to the remote endpoint
388  * .transcoding_mmr = 1,
389  * .transcoding_jbig = 1,
390 */
391  };
392 
393  /* if in called party mode, try to use T.38 */
394  if (s->caller_mode == FALSE) {
395  /* check if we are already in T.38 mode (unlikely), or if we can request
396  * a switch... if so, request it now and wait for the result, rather
397  * than starting an audio FAX session that will have to be cancelled
398  */
399  if ((t38_state = ast_channel_get_t38_state(s->chan)) == T38_STATE_NEGOTIATED) {
400  return 1;
401  } else if ((t38_state != T38_STATE_UNAVAILABLE) &&
403  (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0))) {
404  /* wait up to five seconds for negotiation to complete */
405  unsigned int timeout = 5000;
406  int ms;
407 
408  ast_debug(1, "Negotiating T.38 for receive on %s\n", s->chan->name);
409  while (timeout > 0) {
410  ms = ast_waitfor(s->chan, 1000);
411  if (ms < 0) {
412  ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
413  return -1;
414  }
415  if (!ms) {
416  /* nothing happened */
417  if (timeout > 0) {
418  timeout -= 1000;
419  continue;
420  } else {
421  ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", s->chan->name);
422  break;
423  }
424  }
425  if (!(inf = ast_read(s->chan))) {
426  return -1;
427  }
428  if ((inf->frametype == AST_FRAME_CONTROL) &&
430  (inf->datalen == sizeof(t38_parameters))) {
431  struct ast_control_t38_parameters *parameters = inf->data.ptr;
432 
433  switch (parameters->request_response) {
434  case AST_T38_NEGOTIATED:
435  ast_debug(1, "Negotiated T.38 for receive on %s\n", s->chan->name);
436  res = 1;
437  break;
438  case AST_T38_REFUSED:
439  ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", s->chan->name);
440  break;
441  default:
442  ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", s->chan->name);
443  break;
444  }
445  ast_frfree(inf);
446  if (res == 1) {
447  return 1;
448  } else {
449  break;
450  }
451  }
452  ast_frfree(inf);
453  }
454  }
455  }
456 
457 #if SPANDSP_RELEASE_DATE >= 20080725
458  /* for spandsp shaphots 0.0.6 and higher */
459  t30state = &fax.t30;
460 #else
461  /* for spandsp release 0.0.5 */
462  t30state = &fax.t30_state;
463 #endif
464 
465  original_read_fmt = s->chan->readformat;
466  if (original_read_fmt != AST_FORMAT_SLINEAR) {
468  if (res < 0) {
469  ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
470  goto done;
471  }
472  }
473 
474  original_write_fmt = s->chan->writeformat;
475  if (original_write_fmt != AST_FORMAT_SLINEAR) {
477  if (res < 0) {
478  ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
479  goto done;
480  }
481  }
482 
483  /* Initialize T30 terminal */
484  fax_init(&fax, s->caller_mode);
485 
486  /* Setup logging */
487  set_logging(&fax.logging);
488  set_logging(&t30state->logging);
489 
490  /* Configure terminal */
491  set_local_info(t30state, s);
492  set_file(t30state, s);
493  set_ecm(t30state, TRUE);
494 
495  fax_set_transmit_on_idle(&fax, TRUE);
496 
497  t30_set_phase_e_handler(t30state, phase_e_handler, s);
498 
499  start = state_change = ast_tvnow();
500 
502 
503  while (!s->finished) {
504  inf = NULL;
505 
506  if ((res = ast_waitfor(s->chan, 25)) < 0) {
507  ast_debug(1, "Error waiting for a frame\n");
508  break;
509  }
510 
511  /* Watchdog */
512  now = ast_tvnow();
514  ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
515  res = -1;
516  break;
517  }
518 
519  if (!res) {
520  /* There was timeout waiting for a frame. Loop around and wait again */
521  continue;
522  }
523 
524  /* There is a frame available. Get it */
525  res = 0;
526 
527  if (!(inf = ast_read(s->chan))) {
528  ast_debug(1, "Channel hangup\n");
529  res = -1;
530  break;
531  }
532 
533  ast_debug(10, "frame %d/%llu, len=%d\n", inf->frametype, (unsigned long long) inf->subclass.codec, inf->datalen);
534 
535  /* Check the frame type. Format also must be checked because there is a chance
536  that a frame in old format was already queued before we set channel format
537  to slinear so it will still be received by ast_read */
538  if (inf->frametype == AST_FRAME_VOICE && inf->subclass.codec == AST_FORMAT_SLINEAR) {
539  if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {
540  /* I know fax_rx never returns errors. The check here is for good style only */
541  ast_log(LOG_WARNING, "fax_rx returned error\n");
542  res = -1;
543  break;
544  }
545  if (last_state != t30state->state) {
547  last_state = t30state->state;
548  }
549  } else if ((inf->frametype == AST_FRAME_CONTROL) &&
551  struct ast_control_t38_parameters *parameters = inf->data.ptr;
552 
553  if (parameters->request_response == AST_T38_NEGOTIATED) {
554  /* T38 switchover completed */
555  s->t38parameters = *parameters;
556  ast_debug(1, "T38 negotiated, finishing audio loop\n");
557  res = 1;
558  break;
559  } else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
560  t38_parameters.request_response = AST_T38_NEGOTIATED;
561  ast_debug(1, "T38 request received, accepting\n");
562  /* Complete T38 switchover */
563  ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
564  /* Do not break audio loop, wait until channel driver finally acks switchover
565  * with AST_T38_NEGOTIATED
566  */
567  }
568  }
569 
570  ast_frfree(inf);
571  inf = NULL;
572  }
573 
574  ast_debug(1, "Loop finished, res=%d\n", res);
575 
576  if (inf)
577  ast_frfree(inf);
578 
580 
581  /* If we are switching to T38, remove phase E handler. Otherwise it will be executed
582  by t30_terminate, display diagnostics and set status variables although no transmittion
583  has taken place yet. */
584  if (res > 0) {
585  t30_set_phase_e_handler(t30state, NULL, NULL);
586  }
587 
588  t30_terminate(t30state);
589  fax_release(&fax);
590 
591 done:
592  if (original_write_fmt != AST_FORMAT_SLINEAR) {
593  if (ast_set_write_format(s->chan, original_write_fmt) < 0)
594  ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name);
595  }
596 
597  if (original_read_fmt != AST_FORMAT_SLINEAR) {
598  if (ast_set_read_format(s->chan, original_read_fmt) < 0)
599  ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name);
600  }
601 
602  return res;
603 
604 }
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:2417
union ast_frame_subclass subclass
Definition: frame.h:146
#define FALSE
Definition: app_minivm.c:506
static void set_ecm(t30_state_t *state, int ecm)
Definition: app_fax.c:316
unsigned int version
Definition: frame.h:413
format_t writeformat
Definition: channel.h:854
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
Definition: channel.c:3148
static void set_local_info(t30_state_t *state, fax_session *s)
Definition: app_fax.c:295
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
static int set_logging(logging_state_t *state)
Definition: app_fax.c:285
int64_t ast_tvdiff_sec(struct timeval end, struct timeval start)
Computes the difference (in seconds) between two struct timeval instances.
Definition: time.h:56
struct ast_control_t38_parameters t38parameters
Definition: app_fax.c:165
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
enum ast_control_t38 request_response
Definition: frame.h:412
static void phase_e_handler(t30_state_t *f, void *user_data, int result)
Definition: app_fax.c:203
int caller_mode
Definition: app_fax.c:163
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:4447
ast_t38_state
Possible T38 states on channels.
Definition: channel.h:669
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
format_t codec
Definition: frame.h:137
struct ast_channel * chan
Definition: app_fax.c:160
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
static void set_file(t30_state_t *state, fax_session *s)
Definition: app_fax.c:308
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int datalen
Definition: frame.h:148
volatile int finished
Definition: app_fax.c:166
#define LOG_ERROR
Definition: logger.h:155
static struct ast_generator generator
Definition: app_fax.c:361
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void ast_deactivate_generator(struct ast_channel *chan)
Definition: channel.c:3107
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
format_t readformat
Definition: channel.h:853
#define TRUE
Definition: app_minivm.c:503
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
#define WATCHDOG_STATE_TIMEOUT
Definition: app_fax.c:157
union ast_frame::@172 data
int samples
Definition: frame.h:150
#define WATCHDOG_TOTAL_TIMEOUT
Definition: app_fax.c:156
static int transmit_t38 ( fax_session s)
static

Definition at line 606 of file app_fax.c.

References ast_channel_get_t38_state(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FRAME_CONTROL, AST_FRAME_MODEM, ast_frfree, ast_indicate_data(), ast_log(), AST_MODEM_T38, ast_read(), AST_T38_REFUSED, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_tvdiff_sec(), ast_tvdiff_us(), ast_tvnow(), ast_waitfor(), fax_session::caller_mode, fax_session::chan, ast_frame::data, ast_frame::datalen, disable_t38(), FALSE, ast_control_t38_parameters::fill_bit_removal, fax_session::finished, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, ast_control_t38_parameters::max_ifp, ast_channel::name, phase_e_handler(), ast_frame::ptr, ast_control_t38_parameters::request_response, ast_frame::seqno, set_ecm(), set_file(), set_local_info(), set_logging(), ast_frame::subclass, t38, T38_STATE_NEGOTIATED, t38_tx_packet_handler(), fax_session::t38parameters, ast_control_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_mmr, TRUE, WATCHDOG_STATE_TIMEOUT, and WATCHDOG_TOTAL_TIMEOUT.

Referenced by transmit().

607 {
608  int res = 0;
609  t38_terminal_state_t t38;
610  struct ast_frame *inf = NULL;
611  int last_state = 0;
612  struct timeval now, start, state_change, last_frame;
613  t30_state_t *t30state;
614  t38_core_state_t *t38state;
615 
616 #if SPANDSP_RELEASE_DATE >= 20080725
617  /* for spandsp shaphots 0.0.6 and higher */
618  t30state = &t38.t30;
619  t38state = &t38.t38_fe.t38;
620 #else
621  /* for spandsp releases 0.0.5 */
622  t30state = &t38.t30_state;
623  t38state = &t38.t38;
624 #endif
625 
626  /* Initialize terminal */
627  memset(&t38, 0, sizeof(t38));
628  if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
629  ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
630  res = -1;
631  goto disable_t38;
632  }
633 
634  t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);
635 
637  t38_set_fill_bit_removal(t38state, TRUE);
638  }
640  t38_set_mmr_transcoding(t38state, TRUE);
641  }
643  t38_set_jbig_transcoding(t38state, TRUE);
644  }
645 
646  /* Setup logging */
647  set_logging(&t38.logging);
648  set_logging(&t30state->logging);
649  set_logging(&t38state->logging);
650 
651  /* Configure terminal */
652  set_local_info(t30state, s);
653  set_file(t30state, s);
654  set_ecm(t30state, TRUE);
655 
656  t30_set_phase_e_handler(t30state, phase_e_handler, s);
657 
658  now = start = state_change = ast_tvnow();
659 
660  while (!s->finished) {
661  inf = NULL;
662 
663  if ((res = ast_waitfor(s->chan, 25)) < 0) {
664  ast_debug(1, "Error waiting for a frame\n");
665  break;
666  }
667 
668  last_frame = now;
669 
670  /* Watchdog */
671  now = ast_tvnow();
673  ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
674  res = -1;
675  break;
676  }
677 
678  t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
679 
680  if (!res) {
681  /* There was timeout waiting for a frame. Loop around and wait again */
682  continue;
683  }
684 
685  /* There is a frame available. Get it */
686  res = 0;
687 
688  if (!(inf = ast_read(s->chan))) {
689  ast_debug(1, "Channel hangup\n");
690  res = -1;
691  break;
692  }
693 
694  ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass.integer, inf->datalen);
695 
696  if (inf->frametype == AST_FRAME_MODEM && inf->subclass.integer == AST_MODEM_T38) {
697  t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno);
698  if (last_state != t30state->state) {
700  last_state = t30state->state;
701  }
703  struct ast_control_t38_parameters *parameters = inf->data.ptr;
704  if (parameters->request_response == AST_T38_TERMINATED) {
705  ast_debug(1, "T38 down, finishing\n");
706  break;
707  }
708  }
709 
710  ast_frfree(inf);
711  inf = NULL;
712  }
713 
714  ast_debug(1, "Loop finished, res=%d\n", res);
715 
716  if (inf)
717  ast_frfree(inf);
718 
719  t30_terminate(t30state);
720  t38_terminal_release(&t38);
721 
723  /* if we are not the caller, it's our job to shut down the T.38
724  * session when the FAX transmisson is complete.
725  */
726  if ((s->caller_mode == FALSE) &&
729 
730  if (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) {
731  /* wait up to five seconds for negotiation to complete */
732  unsigned int timeout = 5000;
733  int ms;
734 
735  ast_debug(1, "Shutting down T.38 on %s\n", s->chan->name);
736  while (timeout > 0) {
737  ms = ast_waitfor(s->chan, 1000);
738  if (ms < 0) {
739  ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
740  return -1;
741  }
742  if (!ms) {
743  /* nothing happened */
744  if (timeout > 0) {
745  timeout -= 1000;
746  continue;
747  } else {
748  ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", s->chan->name);
749  break;
750  }
751  }
752  if (!(inf = ast_read(s->chan))) {
753  return -1;
754  }
755  if ((inf->frametype == AST_FRAME_CONTROL) &&
757  (inf->datalen == sizeof(t38_parameters))) {
758  struct ast_control_t38_parameters *parameters = inf->data.ptr;
759 
760  switch (parameters->request_response) {
761  case AST_T38_TERMINATED:
762  ast_debug(1, "Shut down T.38 on %s\n", s->chan->name);
763  break;
764  case AST_T38_REFUSED:
765  ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", s->chan->name);
766  break;
767  default:
768  ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", s->chan->name);
769  break;
770  }
771  ast_frfree(inf);
772  break;
773  }
774  ast_frfree(inf);
775  }
776  }
777  }
778 
779  return res;
780 }
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:2417
union ast_frame_subclass subclass
Definition: frame.h:146
#define FALSE
Definition: app_minivm.c:506
static void set_ecm(t30_state_t *state, int ecm)
Definition: app_fax.c:316
int seqno
Definition: frame.h:172
static void set_local_info(t30_state_t *state, fax_session *s)
Definition: app_fax.c:295
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
static int set_logging(logging_state_t *state)
Definition: app_fax.c:285
int64_t ast_tvdiff_sec(struct timeval end, struct timeval start)
Computes the difference (in seconds) between two struct timeval instances.
Definition: time.h:56
struct ast_control_t38_parameters t38parameters
Definition: app_fax.c:165
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
enum ast_control_t38 request_response
Definition: frame.h:412
static void phase_e_handler(t30_state_t *f, void *user_data, int result)
Definition: app_fax.c:203
#define AST_MODEM_T38
Definition: frame.h:216
int caller_mode
Definition: app_fax.c:163
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:4447
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
struct spandsp_fax_stats t38
struct ast_channel * chan
Definition: app_fax.c:160
static void set_file(t30_state_t *state, fax_session *s)
Definition: app_fax.c:308
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
unsigned int transcoding_mmr
Definition: frame.h:418
static int disable_t38(struct ast_channel *chan)
Definition: res_fax.c:1092
int datalen
Definition: frame.h:148
volatile int finished
Definition: app_fax.c:166
unsigned int max_ifp
Definition: frame.h:414
#define LOG_ERROR
Definition: logger.h:155
unsigned int fill_bit_removal
Definition: frame.h:417
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned int transcoding_jbig
Definition: frame.h:419
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
#define TRUE
Definition: app_minivm.c:503
Data structure associated with a single frame of data.
Definition: frame.h:142
static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
Definition: app_fax.c:180
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:70
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
#define WATCHDOG_STATE_TIMEOUT
Definition: app_fax.c:157
union ast_frame::@172 data
#define WATCHDOG_TOTAL_TIMEOUT
Definition: app_fax.c:156
static int unload_module ( void  )
static

Definition at line 978 of file app_fax.c.

References ast_unregister_application().

979 {
980  int res;
981 
984 
985  return res;
986 }
static const char app_sndfax_name[]
Definition: app_fax.c:145
static const char app_rcvfax_name[]
Definition: app_fax.c:146
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Simple FAX Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, }
static

Definition at line 1005 of file app_fax.c.

const char app_rcvfax_name[] = "ReceiveFAX"
static

Definition at line 146 of file app_fax.c.

const char app_sndfax_name[] = "SendFAX"
static

Definition at line 145 of file app_fax.c.

Definition at line 1005 of file app_fax.c.

struct ast_generator generator
static
Initial value:
= {
}
static void * fax_generator_alloc(struct ast_channel *chan, void *params)
Definition: app_fax.c:326
static int fax_generator_generate(struct ast_channel *chan, void *data, int len, int samples)
Definition: app_fax.c:331

Definition at line 361 of file app_fax.c.

Referenced by ast_read_generator_actions(), cli_alias_passthrough(), and deactivate_generator_nolock().