52#define ASTMM_LIBC ASTMM_IGNORE
66#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
68#include <spandsp/version.h>
70#define SPANDSP_FAX_SAMPLES 160
71#define SPANDSP_FAX_TIMER_RATE 8000 / SPANDSP_FAX_SAMPLES
72#define SPANDSP_ENGAGE_UDPTL_NAT_RETRY 3
97 .description =
"Spandsp FAX Driver",
98#if SPANDSP_RELEASE_DATE >= 20090220
100 .version = SPANDSP_RELEASE_DATETIME_STRING,
105 .version =
"pre-20090220",
172#if SPANDSP_RELEASE_DATE >= 20120902
175static void spandsp_log(
void *user_data,
int level,
const char *msg);
179static void spandsp_log(
int level,
const char *msg);
190 t30_state_t *t30_to_terminate;
194 }
else if (p->
ist38) {
195#if SPANDSP_RELEASE_DATE >= 20080725
198 t30_to_terminate = &p->
t38_state.t30_state;
201#if SPANDSP_RELEASE_DATE >= 20080725
204 t30_to_terminate = &p->
fax_state.t30_state;
208 t30_terminate(t30_to_terminate);
232 .src =
"res_fax_spandsp_t38",
266 switch (completion_code) {
272 case T30_ERR_CEDTONE:
273 case T30_ERR_T0_EXPIRED:
274 case T30_ERR_T1_EXPIRED:
275 case T30_ERR_T3_EXPIRED:
276 case T30_ERR_HDLC_CARRIER:
277 case T30_ERR_CANNOT_TRAIN:
281 case T30_ERR_OPER_INT_FAIL:
282 case T30_ERR_INCOMPATIBLE:
283 case T30_ERR_RX_INCAPABLE:
284 case T30_ERR_TX_INCAPABLE:
285 case T30_ERR_NORESSUPPORT:
286 case T30_ERR_NOSIZESUPPORT:
290 case T30_ERR_UNEXPECTED:
295 case T30_ERR_TX_BADDCS:
296 case T30_ERR_TX_BADPG:
297 case T30_ERR_TX_ECMPHD:
298 case T30_ERR_TX_GOTDCN:
299 case T30_ERR_TX_INVALRSP:
300 case T30_ERR_TX_NODIS:
301 case T30_ERR_TX_PHBDEAD:
302 case T30_ERR_TX_PHDDEAD:
303 case T30_ERR_TX_T5EXP:
308 case T30_ERR_RX_ECMPHD:
309 case T30_ERR_RX_GOTDCS:
310 case T30_ERR_RX_INVALCMD:
311 case T30_ERR_RX_NOCARRIER:
312 case T30_ERR_RX_NOEOL:
315 case T30_ERR_RX_NOFAX:
318 case T30_ERR_RX_T2EXPDCN:
319 case T30_ERR_RX_T2EXPD:
320 case T30_ERR_RX_T2EXPFAX:
321 case T30_ERR_RX_T2EXPMPS:
322 case T30_ERR_RX_T2EXPRR:
323 case T30_ERR_RX_T2EXP:
324 case T30_ERR_RX_DCNWHY:
325 case T30_ERR_RX_DCNDATA:
326 case T30_ERR_RX_DCNFAX:
327 case T30_ERR_RX_DCNPHD:
328 case T30_ERR_RX_DCNRRD:
329 case T30_ERR_RX_DCNNORTN:
334 case T30_ERR_FILEERROR:
336 case T30_ERR_BADTIFF:
337 case T30_ERR_BADPAGE:
339 case T30_ERR_BADTIFFHDR:
347 case T30_ERR_RETRYDCN:
350 case T30_ERR_CALLDROPPED:
356 case T30_ERR_IDENT_UNACCEPTABLE:
357 case T30_ERR_SUB_UNACCEPTABLE:
358 case T30_ERR_SEP_UNACCEPTABLE:
359 case T30_ERR_PSA_UNACCEPTABLE:
360 case T30_ERR_SID_UNACCEPTABLE:
361 case T30_ERR_PWD_UNACCEPTABLE:
362 case T30_ERR_TSA_UNACCEPTABLE:
363 case T30_ERR_IRA_UNACCEPTABLE:
364 case T30_ERR_CIA_UNACCEPTABLE:
365 case T30_ERR_ISP_UNACCEPTABLE:
366 case T30_ERR_CSA_UNACCEPTABLE:
371 ast_log(
LOG_WARNING,
"unknown FAX session result '%d' (%s)\n", completion_code, t30_completion_code_to_str(completion_code));
385#if SPANDSP_RELEASE_DATE >= 20120902
395 char headerinfo[T30_MAX_PAGE_HEADER_INFO + 1];
398#if SPANDSP_RELEASE_DATE >= 20120902
403 ast_debug(5,
"FAX session '%u' entering phase E\n", s->
id);
411 if (completion_code == T30_ERR_OK) {
430#if SPANDSP_RELEASE_DATE >= 20090220
440 t30_get_tx_page_header_info(
t30_state, headerinfo);
450#if SPANDSP_RELEASE_DATE >= 20120902
452static void spandsp_log(
void *user_data,
int level,
const char *msg)
458 if (level == SPAN_LOG_ERROR) {
460 }
else if (level == SPAN_LOG_WARNING) {
469 int level = SPAN_LOG_WARNING;
472 level = SPAN_LOG_DEBUG_3;
475#if SPANDSP_RELEASE_DATE >= 20120902
482 span_log_set_level(
state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);
511#if SPANDSP_RELEASE_DATE >= 20120902
513 t30_set_supported_compressions(
t30_state, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6);
516 t30_set_supported_compressions(
t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
538 modems |= T30_SUPPORT_V17;
541 modems |= T30_SUPPORT_V27TER;
544 modems |= T30_SUPPORT_V29;
547#if defined(T30_SUPPORT_V34)
548 modems |= T30_SUPPORT_V34;
549#elif defined(T30_SUPPORT_V34HDX)
550 modems |= T30_SUPPORT_V34HDX;
566 ast_log(
LOG_ERROR,
"Cannot initialize the spandsp private FAX technology structure.\n");
572 ast_log(
LOG_ERROR,
"Cannot initialize the spandsp private v21 technology structure.\n");
591 ast_log(
LOG_ERROR,
"Are we sending or receiving? The FAX requirements (capabilities: 0x%X) were not properly set.\n", s->
details->
caps);
666 .src =
"res_fax_spandsp_g711",
679 ast_debug(5,
"FAX session '%u' is complete.\n", s->
id);
703 if (code == MODEM_CONNECT_TONES_FAX_PREAMBLE) {
712 g711_state_t *decoder;
723 ast_debug(5,
"frame={ datalen=%d, samples=%d, mallocd=%d, src=%s, flags=%u, ts=%ld, len=%ld, seqno=%d, data.ptr=%p, subclass.format=%s }\n", f->
datalen, f->
samples, f->
mallocd, f->
src, f->
flags, f->
ts, f->
len, f->
seqno, f->
data.
ptr,
ast_format_get_name(f->
subclass.
format));
739 g711_release(decoder);
740#if SPANDSP_RELEASE_DATE >= 20090220
810 .src =
"res_fax_spandsp_g711",
818 return p->
isdone ? -1 : res;
827 return p->
isdone ? -1 : res;
860#if SPANDSP_RELEASE_DATE >= 20081012
911#if SPANDSP_RELEASE_DATE >= 20091228
912 t38_core_send_indicator(&p->
t38_gw_state.t38x.t38, T38_IND_NO_SIGNAL);
913#elif SPANDSP_RELEASE_DATE >= 20081012
954 t38_stats_t t38_stats;
956 t38_gateway_get_transfer_statistics(&p->
t38_gw_state, &t38_stats);
975#if SPANDSP_RELEASE_DATE >= 20080725
985#if SPANDSP_RELEASE_DATE >= 20080725
1025 fax_set_transmit_on_idle(&p->
fax_state, 1);
1031 ast_log(
LOG_ERROR,
"FAX session '%u' error setting rate on timing source.\n", s->
id);
1078 ast_cli(fd,
"SEND RECEIVE T.38 G.711 GATEWAY\n\n");
1089 ast_cli(fd,
"%-22s : %u\n",
"session", s->
id);
1090 ast_cli(fd,
"%-22s : %s\n",
"operation",
"Gateway");
1095 ast_cli(fd,
"%-22s : %s\n",
"ECM Mode",
stats.error_correcting_mode ?
"Yes" :
"No");
1096 ast_cli(fd,
"%-22s : %d\n",
"Data Rate",
stats.bit_rate);
1097 ast_cli(fd,
"%-22s : %d\n",
"Page Number",
stats.pages_transferred + 1);
1100 ast_cli(fd,
"%-22s : %u\n",
"session", s->
id);
1101 ast_cli(fd,
"%-22s : %s\n",
"operation",
"V.21 Detect");
1106 ast_cli(fd,
"%-22s : %u\n",
"session", s->
id);
1112 ast_cli(fd,
"%-22s : %s\n",
"Last Status", t30_completion_code_to_str(
stats.current_status));
1113 ast_cli(fd,
"%-22s : %s\n",
"ECM Mode",
stats.error_correcting_mode ?
"Yes" :
"No");
1114 ast_cli(fd,
"%-22s : %d\n",
"Data Rate",
stats.bit_rate);
1115 ast_cli(fd,
"%-22s : %dx%d\n",
"Image Resolution",
stats.x_resolution,
stats.y_resolution);
1116#if SPANDSP_RELEASE_DATE >= 20090220
1119 ast_cli(fd,
"%-22s : %d\n",
"Page Number",
stats.pages_transferred + 1);
1123 ast_cli(fd,
"\nData Statistics:\n");
1124#if SPANDSP_RELEASE_DATE >= 20090220
1125 ast_cli(fd,
"%-22s : %d\n",
"Tx Pages",
stats.pages_tx);
1126 ast_cli(fd,
"%-22s : %d\n",
"Rx Pages",
stats.pages_rx);
1131 ast_cli(fd,
"%-22s : %d\n",
"Longest Bad Line Run",
stats.longest_bad_row_run);
1132 ast_cli(fd,
"%-22s : %d\n",
"Total Bad Lines",
stats.bad_rows);
1143 struct ast_str *message_string;
1149 if (!message_string) {
1162 goto skip_cap_additions;
1166 res |=
ast_str_append(&message_string, 0,
"ErrorCorrectionMode: %s\r\n",
1167 stats.error_correcting_mode ?
"yes" :
"no");
1171 stats.pages_transferred + 1);
1176 goto skip_cap_additions;
1180 res |=
ast_str_append(&message_string, 0,
"ErrorCorrectionMode: %s\r\n",
1181 stats.error_correcting_mode ?
"Yes" :
"No");
1184 res |=
ast_str_append(&message_string, 0,
"ImageResolution: %dx%d\r\n",
1186#if SPANDSP_RELEASE_DATE >= 20090220
1191 stats.pages_transferred + 1);
1196#if SPANDSP_RELEASE_DATE >= 20090220
1197 res |=
ast_str_append(&message_string, 0,
"PagesTransmitted: %d\r\n",
1199 res |=
ast_str_append(&message_string, 0,
"PagesReceived: %d\r\n",
1202 res |=
ast_str_append(&message_string, 0,
"PagesTransmitted: %d\r\n",
1204 res |=
ast_str_append(&message_string, 0,
"PagesReceived: %d\r\n",
1207 res |=
ast_str_append(&message_string, 0,
"TotalBadLines: %d\r\n",
1235 ast_cli(fd,
"\n%-20.20s\n",
"Spandsp G.711");
1250 ast_cli(fd,
"\n%-20.20s\n",
"Spandsp T.38");
1294#if SPANDSP_RELEASE_DATE >= 20120902
1296 span_set_message_handler(
NULL,
NULL);
1299 span_set_message_handler(
NULL);
1310 .enhances =
"res_fax",
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_malloc(len)
A wrapper for malloc()
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
General Asterisk PBX channel definitions.
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
ast_t38_state
Possible T38 states on channels.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
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.
Standard Command Line Interface.
void ast_cli(int fd, const char *fmt,...)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_append(struct mansession *s, const char *fmt,...)
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
@ AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF
#define AST_FRAME_SET_BUFFER(fr, _base, _ofs, _datalen)
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
struct ast_frame ast_null_frame
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_EXTENDED
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
void ast_fax_tech_unregister(struct ast_fax_tech *tech)
unregister a fax technology
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert an ast_fax_state to a string
@ AST_FAX_TECH_V21_DETECT
#define AST_FAX_FRFLAG_GATEWAY
const char * ast_fax_session_operation_str(struct ast_fax_session *s)
get string representation of a FAX session's operation
int ast_fax_tech_register(struct ast_fax_tech *tech)
register a fax technology
@ AST_FAX_STATE_INITIALIZED
@ AST_FAX_STATE_UNINITIALIZED
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.
static void t30_phase_e_handler(t30_state_t *t30_state, void *data, int completion_code)
Phase E handler callback.
static void spandsp_log(int level, const char *msg)
Send spandsp log messages to asterisk.
static char * spandsp_fax_cli_show_session(struct ast_fax_session *s, int fd)
static int t38_tx_packet_handler(t38_core_state_t *t38_core_state, void *data, const uint8_t *buf, int len, int count)
static struct ast_fax_tech spandsp_fax_tech
#define SPANDSP_FAX_SAMPLES
static void session_destroy(struct spandsp_pvt *p)
struct spandsp_fax_stats g711
static int spandsp_fax_switch_to_t38(struct ast_fax_session *s)
static void spandsp_v21_tone(void *data, int code, int level, int delay)
static void spandsp_manager_fax_session(struct mansession *s, const char *id_text, struct ast_fax_session *session)
static void set_file(t30_state_t *t30_state, struct ast_fax_session_details *details)
static char * spandsp_fax_cli_show_stats(int fd)
static void * spandsp_fax_new(struct ast_fax_session *s, struct ast_fax_tech_token *token)
create an instance of the spandsp tech_pvt for a fax session
static int spandsp_modems(struct ast_fax_session_details *details)
static void set_logging(logging_state_t *state, struct ast_fax_session_details *details)
static struct ast_frame * spandsp_fax_read(struct ast_fax_session *s)
Read a frame from the spandsp fax stack.
static void * spandsp_fax_gw_gen_alloc(struct ast_channel *chan, void *params)
simple routine to allocate data to generator
static int spandsp_fax_gateway_process(struct ast_fax_session *s, const struct ast_frame *f)
process a frame from the bridge
static char * spandsp_fax_cli_show_capabilities(int fd)
static void set_local_info(t30_state_t *t30_state, struct ast_fax_session_details *details)
#define SPANDSP_FAX_TIMER_RATE
static int spandsp_fax_cancel(struct ast_fax_session *s)
static int load_module(void)
load res_fax_spandsp
static int spandsp_v21_new(struct spandsp_pvt *p)
#define SPANDSP_ENGAGE_UDPTL_NAT_RETRY
static int spandsp_fax_gateway_start(struct ast_fax_session *s)
activate a spandsp gateway based on the information in the given fax session
static char * spandsp_fax_cli_show_settings(int fd)
Show res_fax_spandsp settings.
static struct @437 spandsp_global_stats
static int unload_module(void)
unload res_fax_spandsp
static void spandsp_fax_gateway_cleanup(struct ast_fax_session *s)
gather data and clean up after gateway ends
static void spandsp_fax_gw_gen_release(struct ast_channel *chan, void *data)
static int spandsp_v21_detect(struct ast_fax_session *s, const struct ast_frame *f)
static void spandsp_v21_cleanup(struct ast_fax_session *s)
static int update_stats(struct spandsp_pvt *p, int completion_code)
static void set_ecm(t30_state_t *t30_state, struct ast_fax_session_details *details)
static int spandsp_fax_start(struct ast_fax_session *s)
struct spandsp_fax_stats t38
static int spandsp_fax_write(struct ast_fax_session *s, const struct ast_frame *f)
Write a frame to the spandsp fax stack.
static int spandsp_fax_gw_t30_gen(struct ast_channel *chan, void *data, int len, int samples)
generate T.30 packets sent to the T.30 leg of gateway
static void spandsp_fax_destroy(struct ast_fax_session *s)
Destroy a spandsp fax session.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Main Channel structure associated with a channel.
The data communicated between the high level applications and the generic fax function.
const ast_string_field localstationid
struct ast_fax_t38_parameters their_t38_parameters
struct ast_fax_documents documents
const ast_string_field result
enum ast_fax_modems modems
const ast_string_field headerinfo
struct ast_fax_t38_parameters our_t38_parameters
union ast_fax_session_details::@251 option
const ast_string_field resultstr
unsigned int pages_transferred
enum ast_fax_capabilities caps
The data required to handle a fax session.
struct ast_channel * chan
struct ast_fax_session_details * details
unsigned int transcoding_jbig
unsigned int transcoding_mmr
enum ast_control_t38_rate_management rate_management
unsigned int fill_bit_removal
used to register a FAX technology module with res_fax
struct ast_module * module
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
void *(* alloc)(struct ast_channel *chan, void *params)
Structure for mutex and tracking information.
Support for dynamic strings.
In case you didn't read that giant block of text above the mansession_session struct,...
struct spandsp_fax_stats * stats
t38_core_state_t * t38_core_state
struct spandsp_pvt::frame_queue read_frames
struct spandsp_fax_gw_stats * t38stats
modem_connect_tones_rx_state_t * tone_state
t38_terminal_state_t t38_state
t38_gateway_state_t t38_gw_state
enum ast_t38_state ast_t38_state
Timing source management.
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
struct ast_timer * ast_timer_open(void)
Open a timer.
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
int error(const char *format,...)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_set_flag(p, flag)