Asterisk - The Open Source Telephony Project GIT-master-7e7a603
Data Structures | Macros | Functions | Variables
res_fax_spandsp.c File Reference

Spandsp T.38 and G.711 FAX Resource. More...

#include "asterisk.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/strings.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/timing.h"
#include "asterisk/astobj2.h"
#include "asterisk/res_fax.h"
#include "asterisk/channel.h"
#include "asterisk/format_cache.h"
#include <spandsp.h>
#include <spandsp/version.h>
Include dependency graph for res_fax_spandsp.c:

Go to the source code of this file.

Data Structures

struct  spandsp_pvt::frame_queue
 
struct  spandsp_fax_stats
 
struct  spandsp_pvt
 

Macros

#define ASTMM_LIBC   ASTMM_IGNORE
 
#define SPANDSP_ENGAGE_UDPTL_NAT_RETRY   3
 
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
 
#define SPANDSP_FAX_SAMPLES   160
 
#define SPANDSP_FAX_TIMER_RATE   8000 / SPANDSP_FAX_SAMPLES /* 50 ticks per second, 20ms, 160 samples per second */
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int load_module (void)
 load res_fax_spandsp More...
 
static void session_destroy (struct spandsp_pvt *p)
 
static void set_ecm (t30_state_t *t30_state, struct ast_fax_session_details *details)
 
static void set_file (t30_state_t *t30_state, struct ast_fax_session_details *details)
 
static void set_local_info (t30_state_t *t30_state, struct ast_fax_session_details *details)
 
static void set_logging (logging_state_t *state, struct ast_fax_session_details *details)
 
static int spandsp_fax_cancel (struct ast_fax_session *s)
 
static char * spandsp_fax_cli_show_capabilities (int fd)
 
static char * spandsp_fax_cli_show_session (struct ast_fax_session *s, int fd)
 
static char * spandsp_fax_cli_show_settings (int fd)
 Show res_fax_spandsp settings. More...
 
static char * spandsp_fax_cli_show_stats (int fd)
 
static void spandsp_fax_destroy (struct ast_fax_session *s)
 Destroy a spandsp fax session. More...
 
static void spandsp_fax_gateway_cleanup (struct ast_fax_session *s)
 gather data and clean up after gateway ends More...
 
static int spandsp_fax_gateway_process (struct ast_fax_session *s, const struct ast_frame *f)
 process a frame from the bridge More...
 
static int spandsp_fax_gateway_start (struct ast_fax_session *s)
 activate a spandsp gateway based on the information in the given fax session More...
 
static void * spandsp_fax_gw_gen_alloc (struct ast_channel *chan, void *params)
 simple routine to allocate data to generator More...
 
static void spandsp_fax_gw_gen_release (struct ast_channel *chan, void *data)
 
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 More...
 
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 More...
 
static struct ast_framespandsp_fax_read (struct ast_fax_session *s)
 Read a frame from the spandsp fax stack. More...
 
static int spandsp_fax_start (struct ast_fax_session *s)
 
static int spandsp_fax_switch_to_t38 (struct ast_fax_session *s)
 
static int spandsp_fax_write (struct ast_fax_session *s, const struct ast_frame *f)
 Write a frame to the spandsp fax stack. More...
 
static void spandsp_log (int level, const char *msg)
 Send spandsp log messages to asterisk. More...
 
static void spandsp_manager_fax_session (struct mansession *s, const char *id_text, struct ast_fax_session *session)
 
static int spandsp_modems (struct ast_fax_session_details *details)
 
static void spandsp_v21_cleanup (struct ast_fax_session *s)
 
static int spandsp_v21_detect (struct ast_fax_session *s, const struct ast_frame *f)
 
static int spandsp_v21_new (struct spandsp_pvt *p)
 
static void spandsp_v21_tone (void *data, int code, int level, int delay)
 
static void t30_phase_e_handler (t30_state_t *t30_state, void *data, int completion_code)
 Phase E handler callback. More...
 
static int t38_tx_packet_handler (t38_core_state_t *t38_core_state, void *data, const uint8_t *buf, int len, int count)
 
static int unload_module (void)
 unload res_fax_spandsp More...
 
static int update_stats (struct spandsp_pvt *p, int completion_code)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Spandsp G.711 and T.38 FAX Technologies" , .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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .enhances = "res_fax", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_fax_tech spandsp_fax_tech
 
struct {
   struct spandsp_fax_stats   g711
 
   ast_mutex_t   lock
 
   struct spandsp_fax_stats   t38
 
spandsp_global_stats
 

Detailed Description

Spandsp T.38 and G.711 FAX Resource.

Author
Matthew Nicholson mnich.nosp@m.olso.nosp@m.n@dig.nosp@m.ium..nosp@m.com
Gregory H. Nietsky grego.nosp@m.ry@d.nosp@m.istro.nosp@m.tech.nosp@m..co.z.nosp@m.a

This module registers the Spandsp FAX technology with the res_fax module.

Definition in file res_fax_spandsp.c.

Macro Definition Documentation

◆ ASTMM_LIBC

#define ASTMM_LIBC   ASTMM_IGNORE

Definition at line 52 of file res_fax_spandsp.c.

◆ SPANDSP_ENGAGE_UDPTL_NAT_RETRY

#define SPANDSP_ENGAGE_UDPTL_NAT_RETRY   3

Definition at line 72 of file res_fax_spandsp.c.

◆ SPANDSP_EXPOSE_INTERNAL_STRUCTURES

#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES

Definition at line 66 of file res_fax_spandsp.c.

◆ SPANDSP_FAX_SAMPLES

#define SPANDSP_FAX_SAMPLES   160

Definition at line 70 of file res_fax_spandsp.c.

◆ SPANDSP_FAX_TIMER_RATE

#define SPANDSP_FAX_TIMER_RATE   8000 / SPANDSP_FAX_SAMPLES /* 50 ticks per second, 20ms, 160 samples per second */

Definition at line 71 of file res_fax_spandsp.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1311 of file res_fax_spandsp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1311 of file res_fax_spandsp.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1311 of file res_fax_spandsp.c.

◆ load_module()

static int load_module ( void  )
static

load res_fax_spandsp

Definition at line 1284 of file res_fax_spandsp.c.

1285{
1289 ast_log(LOG_ERROR, "failed to register FAX technology\n");
1291 }
1292
1293 /* prevent logging to stderr */
1294#if SPANDSP_RELEASE_DATE >= 20120902
1295 /* for spandsp shaphots 3.0.0 and higher */
1296 span_set_message_handler(NULL, NULL);
1297#else
1298 /* for spandsp release 0.0.6 */
1299 span_set_message_handler(NULL);
1300#endif
1301
1303}
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
#define ast_mutex_init(pmutex)
Definition: lock.h:186
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_fax_tech_register(struct ast_fax_tech *tech)
register a fax technology
Definition: res_fax.c:973
static struct ast_fax_tech spandsp_fax_tech
static struct @437 spandsp_global_stats
#define NULL
Definition: resample.c:96
struct ast_module * module
Definition: res_fax.h:245
struct ast_module * self
Definition: module.h:342

References ast_fax_tech_register(), ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init, LOG_ERROR, ast_fax_tech::module, NULL, ast_module_info::self, spandsp_fax_tech, and spandsp_global_stats.

◆ session_destroy()

static void session_destroy ( struct spandsp_pvt p)
static

Definition at line 187 of file res_fax_spandsp.c.

188{
189 struct ast_frame *f;
190 t30_state_t *t30_to_terminate;
191
192 if (p->t30_state) {
193 t30_to_terminate = p->t30_state;
194 } else if (p->ist38) {
195#if SPANDSP_RELEASE_DATE >= 20080725
196 t30_to_terminate = &p->t38_state.t30;
197#else
198 t30_to_terminate = &p->t38_state.t30_state;
199#endif
200 } else {
201#if SPANDSP_RELEASE_DATE >= 20080725
202 t30_to_terminate = &p->fax_state.t30;
203#else
204 t30_to_terminate = &p->fax_state.t30_state;
205#endif
206 }
207
208 t30_terminate(t30_to_terminate);
209 p->isdone = 1;
210
212 p->timer = NULL;
213 fax_release(&p->fax_state);
214 t38_terminal_release(&p->t38_state);
215
216 while ((f = AST_LIST_REMOVE_HEAD(&p->read_frames, frame_list))) {
217 ast_frfree(f);
218 }
219}
#define ast_frfree(fr)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
Data structure associated with a single frame of data.
struct spandsp_pvt::frame_queue read_frames
fax_state_t fax_state
struct ast_timer * timer
unsigned int ist38
t38_terminal_state_t t38_state
t30_state_t * t30_state
unsigned int isdone
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
Definition: timing.c:154

References ast_frfree, AST_LIST_REMOVE_HEAD, ast_timer_close(), spandsp_pvt::fax_state, spandsp_pvt::isdone, spandsp_pvt::ist38, NULL, spandsp_pvt::read_frames, spandsp_pvt::t30_state, spandsp_pvt::t38_state, and spandsp_pvt::timer.

Referenced by spandsp_fax_destroy().

◆ set_ecm()

static void set_ecm ( t30_state_t *  t30_state,
struct ast_fax_session_details details 
)
static

Definition at line 508 of file res_fax_spandsp.c.

509{
510 t30_set_ecm_capability(t30_state, details->option.ecm);
511#if SPANDSP_RELEASE_DATE >= 20120902
512 /* for spandsp shaphots 3.0.0 and higher */
513 t30_set_supported_compressions(t30_state, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6);
514#else
515 /* for spandsp release 0.0.6 */
516 t30_set_supported_compressions(t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
517#endif
518}
union ast_fax_session_details::@251 option

References ast_fax_session_details::ecm, ast_fax_session_details::option, and spandsp_pvt::t30_state.

Referenced by spandsp_fax_start().

◆ set_file()

static void set_file ( t30_state_t *  t30_state,
struct ast_fax_session_details details 
)
static

Definition at line 496 of file res_fax_spandsp.c.

497{
498 if (details->caps & AST_FAX_TECH_RECEIVE) {
499 t30_set_rx_file(t30_state, AST_LIST_FIRST(&details->documents)->filename, -1);
500 } else {
501 /* if not AST_FAX_TECH_RECEIVE, assume AST_FAX_TECH_SEND, this
502 * should be safe because we ensure either RECEIVE or SEND is
503 * indicated in spandsp_fax_new() */
504 t30_set_tx_file(t30_state, AST_LIST_FIRST(&details->documents)->filename, -1, -1);
505 }
506}
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
@ AST_FAX_TECH_RECEIVE
Definition: res_fax.h:39
struct ast_fax_documents documents
Definition: res_fax.h:119
enum ast_fax_capabilities caps
Definition: res_fax.h:113

References AST_FAX_TECH_RECEIVE, AST_LIST_FIRST, ast_fax_session_details::caps, ast_fax_session_details::documents, and spandsp_pvt::t30_state.

Referenced by spandsp_fax_start().

◆ set_local_info()

static void set_local_info ( t30_state_t *  t30_state,
struct ast_fax_session_details details 
)
static

Definition at line 485 of file res_fax_spandsp.c.

486{
487 if (!ast_strlen_zero(details->localstationid)) {
488 t30_set_tx_ident(t30_state, details->localstationid);
489 }
490
491 if (!ast_strlen_zero(details->headerinfo)) {
492 t30_set_tx_page_header_info(t30_state, details->headerinfo);
493 }
494}
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
const ast_string_field localstationid
Definition: res_fax.h:142
const ast_string_field headerinfo
Definition: res_fax.h:142

References ast_strlen_zero(), ast_fax_session_details::headerinfo, ast_fax_session_details::localstationid, and spandsp_pvt::t30_state.

Referenced by spandsp_fax_start().

◆ set_logging()

static void set_logging ( logging_state_t *  state,
struct ast_fax_session_details details 
)
static

Definition at line 467 of file res_fax_spandsp.c.

468{
469 int level = SPAN_LOG_WARNING;
470
471 if (details->option.debug) {
472 level = SPAN_LOG_DEBUG_3;
473 }
474
475#if SPANDSP_RELEASE_DATE >= 20120902
476 /* for spandsp shaphots 3.0.0 and higher */
477 span_log_set_message_handler(state, spandsp_log, NULL);
478#else
479 /* for spandsp release 0.0.6 */
480 span_log_set_message_handler(state, spandsp_log);
481#endif
482 span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);
483}
static void spandsp_log(int level, const char *msg)
Send spandsp log messages to asterisk.

References ast_fax_session_details::debug, NULL, ast_fax_session_details::option, and spandsp_log().

Referenced by spandsp_fax_gateway_start(), spandsp_fax_new(), and spandsp_fax_start().

◆ spandsp_fax_cancel()

static int spandsp_fax_cancel ( struct ast_fax_session s)
static

Definition at line 1041 of file res_fax_spandsp.c.

1042{
1043 struct spandsp_pvt *p = s->tech_pvt;
1044
1045 if (s->details->caps & AST_FAX_TECH_GATEWAY) {
1046 p->isdone = 1;
1047 return 0;
1048 }
1049
1050 t30_terminate(p->t30_state);
1051 p->isdone = 1;
1052 return 0;
1053}
@ AST_FAX_TECH_GATEWAY
Definition: res_fax.h:47
void * tech_pvt
Definition: res_fax.h:216
struct ast_fax_session_details * details
Definition: res_fax.h:208

References AST_FAX_TECH_GATEWAY, ast_fax_session_details::caps, ast_fax_session::details, spandsp_pvt::isdone, spandsp_pvt::t30_state, and ast_fax_session::tech_pvt.

◆ spandsp_fax_cli_show_capabilities()

static char * spandsp_fax_cli_show_capabilities ( int  fd)
static

Definition at line 1076 of file res_fax_spandsp.c.

1077{
1078 ast_cli(fd, "SEND RECEIVE T.38 G.711 GATEWAY\n\n");
1079 return CLI_SUCCESS;
1080}
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6

References ast_cli(), and CLI_SUCCESS.

◆ spandsp_fax_cli_show_session()

static char * spandsp_fax_cli_show_session ( struct ast_fax_session s,
int  fd 
)
static

Definition at line 1083 of file res_fax_spandsp.c.

1084{
1085 ao2_lock(s);
1086 if (s->details->caps & AST_FAX_TECH_GATEWAY) {
1087 struct spandsp_pvt *p = s->tech_pvt;
1088
1089 ast_cli(fd, "%-22s : %u\n", "session", s->id);
1090 ast_cli(fd, "%-22s : %s\n", "operation", "Gateway");
1091 ast_cli(fd, "%-22s : %s\n", "state", ast_fax_state_to_str(s->state));
1093 t38_stats_t stats;
1094 t38_gateway_get_transfer_statistics(&p->t38_gw_state, &stats);
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);
1098 }
1099 } else if (s->details->caps & AST_FAX_TECH_V21_DETECT) {
1100 ast_cli(fd, "%-22s : %u\n", "session", s->id);
1101 ast_cli(fd, "%-22s : %s\n", "operation", "V.21 Detect");
1102 ast_cli(fd, "%-22s : %s\n", "state", ast_fax_state_to_str(s->state));
1103 } else {
1104 struct spandsp_pvt *p = s->tech_pvt;
1105
1106 ast_cli(fd, "%-22s : %u\n", "session", s->id);
1107 ast_cli(fd, "%-22s : %s\n", "operation", (s->details->caps & AST_FAX_TECH_RECEIVE) ? "Receive" : "Transmit");
1108 ast_cli(fd, "%-22s : %s\n", "state", ast_fax_state_to_str(s->state));
1110 t30_stats_t stats;
1111 t30_get_transfer_statistics(p->t30_state, &stats);
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
1117 ast_cli(fd, "%-22s : %d\n", "Page Number", ((s->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx) + 1);
1118#else
1119 ast_cli(fd, "%-22s : %d\n", "Page Number", stats.pages_transferred + 1);
1120#endif
1121 ast_cli(fd, "%-22s : %s\n", "File Name", s->details->caps & AST_FAX_TECH_RECEIVE ? p->t30_state->rx_file : p->t30_state->tx_file);
1122
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);
1127#else
1128 ast_cli(fd, "%-22s : %d\n", "Tx Pages", (s->details->caps & AST_FAX_TECH_SEND) ? stats.pages_transferred : 0);
1129 ast_cli(fd, "%-22s : %d\n", "Rx Pages", (s->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_transferred : 0);
1130#endif
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);
1133 }
1134 }
1135 ao2_unlock(s);
1136 ast_cli(fd, "\n\n");
1137 return CLI_SUCCESS;
1138}
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert an ast_fax_state to a string
Definition: res_fax.c:1012
@ AST_FAX_TECH_V21_DETECT
Definition: res_fax.h:49
@ AST_FAX_TECH_SEND
Definition: res_fax.h:37
@ AST_FAX_STATE_UNINITIALIZED
Definition: res_fax.h:67
unsigned int id
Definition: res_fax.h:204
enum ast_fax_state state
Definition: res_fax.h:218
struct spandsp_fax_stats * stats
t38_gateway_state_t t38_gw_state

References ao2_lock, ao2_unlock, ast_cli(), ast_fax_state_to_str(), AST_FAX_STATE_UNINITIALIZED, AST_FAX_TECH_GATEWAY, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_SEND, AST_FAX_TECH_V21_DETECT, ast_fax_session_details::caps, CLI_SUCCESS, ast_fax_session::details, ast_fax_session::id, ast_fax_session::state, spandsp_pvt::stats, spandsp_pvt::t30_state, spandsp_pvt::t38_gw_state, and ast_fax_session::tech_pvt.

◆ spandsp_fax_cli_show_settings()

static char * spandsp_fax_cli_show_settings ( int  fd)
static

Show res_fax_spandsp settings.

Definition at line 1269 of file res_fax_spandsp.c.

1270{
1271 /* no settings at the moment */
1272 return CLI_SUCCESS;
1273}

References CLI_SUCCESS.

◆ spandsp_fax_cli_show_stats()

static char * spandsp_fax_cli_show_stats ( int  fd)
static

Definition at line 1232 of file res_fax_spandsp.c.

1233{
1235 ast_cli(fd, "\n%-20.20s\n", "Spandsp G.711");
1236 ast_cli(fd, "%-20.20s : %d\n", "Success", spandsp_global_stats.g711.success);
1237 ast_cli(fd, "%-20.20s : %d\n", "Switched to T.38", spandsp_global_stats.g711.switched);
1238 ast_cli(fd, "%-20.20s : %d\n", "Call Dropped", spandsp_global_stats.g711.call_dropped);
1239 ast_cli(fd, "%-20.20s : %d\n", "No FAX", spandsp_global_stats.g711.nofax);
1240 ast_cli(fd, "%-20.20s : %d\n", "Negotiation Failed", spandsp_global_stats.g711.neg_failed);
1241 ast_cli(fd, "%-20.20s : %d\n", "Train Failure", spandsp_global_stats.g711.failed_to_train);
1242 ast_cli(fd, "%-20.20s : %d\n", "Retries Exceeded", spandsp_global_stats.g711.retries_exceeded);
1243 ast_cli(fd, "%-20.20s : %d\n", "Protocol Error", spandsp_global_stats.g711.protocol_error);
1244 ast_cli(fd, "%-20.20s : %d\n", "TX Protocol Error", spandsp_global_stats.g711.tx_protocol_error);
1245 ast_cli(fd, "%-20.20s : %d\n", "RX Protocol Error", spandsp_global_stats.g711.rx_protocol_error);
1246 ast_cli(fd, "%-20.20s : %d\n", "File Error", spandsp_global_stats.g711.file_error);
1247 ast_cli(fd, "%-20.20s : %d\n", "Memory Error", spandsp_global_stats.g711.mem_error);
1248 ast_cli(fd, "%-20.20s : %d\n", "Unknown Error", spandsp_global_stats.g711.unknown_error);
1249
1250 ast_cli(fd, "\n%-20.20s\n", "Spandsp T.38");
1251 ast_cli(fd, "%-20.20s : %d\n", "Success", spandsp_global_stats.t38.success);
1252 ast_cli(fd, "%-20.20s : %d\n", "Call Dropped", spandsp_global_stats.t38.call_dropped);
1253 ast_cli(fd, "%-20.20s : %d\n", "No FAX", spandsp_global_stats.t38.nofax);
1254 ast_cli(fd, "%-20.20s : %d\n", "Negotiation Failed", spandsp_global_stats.t38.neg_failed);
1255 ast_cli(fd, "%-20.20s : %d\n", "Train Failure", spandsp_global_stats.t38.failed_to_train);
1256 ast_cli(fd, "%-20.20s : %d\n", "Retries Exceeded", spandsp_global_stats.t38.retries_exceeded);
1257 ast_cli(fd, "%-20.20s : %d\n", "Protocol Error", spandsp_global_stats.t38.protocol_error);
1258 ast_cli(fd, "%-20.20s : %d\n", "TX Protocol Error", spandsp_global_stats.t38.tx_protocol_error);
1259 ast_cli(fd, "%-20.20s : %d\n", "RX Protocol Error", spandsp_global_stats.t38.rx_protocol_error);
1260 ast_cli(fd, "%-20.20s : %d\n", "File Error", spandsp_global_stats.t38.file_error);
1261 ast_cli(fd, "%-20.20s : %d\n", "Memory Error", spandsp_global_stats.t38.mem_error);
1262 ast_cli(fd, "%-20.20s : %d\n", "Unknown Error", spandsp_global_stats.t38.unknown_error);
1264
1265 return CLI_SUCCESS;
1266}
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189

References ast_cli(), ast_mutex_lock, ast_mutex_unlock, CLI_SUCCESS, and spandsp_global_stats.

◆ spandsp_fax_destroy()

static void spandsp_fax_destroy ( struct ast_fax_session s)
static

Destroy a spandsp fax session.

Definition at line 638 of file res_fax_spandsp.c.

639{
640 struct spandsp_pvt *p = s->tech_pvt;
641
644 } else if (s->details->caps & AST_FAX_TECH_V21_DETECT) {
646 } else {
648 }
649
650 ast_free(p);
651 s->tech_pvt = NULL;
652 s->fd = -1;
653}
#define ast_free(a)
Definition: astmm.h:180
static void session_destroy(struct spandsp_pvt *p)
static void spandsp_fax_gateway_cleanup(struct ast_fax_session *s)
gather data and clean up after gateway ends
static void spandsp_v21_cleanup(struct ast_fax_session *s)

References AST_FAX_TECH_GATEWAY, AST_FAX_TECH_V21_DETECT, ast_free, ast_fax_session_details::caps, ast_fax_session::details, ast_fax_session::fd, NULL, session_destroy(), spandsp_fax_gateway_cleanup(), spandsp_v21_cleanup(), and ast_fax_session::tech_pvt.

◆ spandsp_fax_gateway_cleanup()

static void spandsp_fax_gateway_cleanup ( struct ast_fax_session s)
static

gather data and clean up after gateway ends

Parameters
sfax session

Definition at line 951 of file res_fax_spandsp.c.

952{
953 struct spandsp_pvt *p = s->tech_pvt;
954 t38_stats_t t38_stats;
955
956 t38_gateway_get_transfer_statistics(&p->t38_gw_state, &t38_stats);
957
958 s->details->option.ecm = t38_stats.error_correcting_mode ? AST_FAX_OPTFLAG_TRUE : AST_FAX_OPTFLAG_FALSE;
959 s->details->pages_transferred = t38_stats.pages_transferred;
960 ast_string_field_build(s->details, transfer_rate, "%d", t38_stats.bit_rate);
961}
@ AST_FAX_OPTFLAG_FALSE
Definition: res_fax.h:85
@ AST_FAX_OPTFLAG_TRUE
Definition: res_fax.h:87
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
unsigned int pages_transferred
Definition: res_fax.h:144

References AST_FAX_OPTFLAG_FALSE, AST_FAX_OPTFLAG_TRUE, ast_string_field_build, ast_fax_session::details, ast_fax_session_details::ecm, ast_fax_session_details::option, ast_fax_session_details::pages_transferred, spandsp_pvt::t38_gw_state, and ast_fax_session::tech_pvt.

Referenced by spandsp_fax_destroy().

◆ spandsp_fax_gateway_process()

static int spandsp_fax_gateway_process ( struct ast_fax_session s,
const struct ast_frame f 
)
static

process a frame from the bridge

Parameters
sfax session
fframe to process
Returns
1 on sucess 0 on incorrect packet

Definition at line 929 of file res_fax_spandsp.c.

930{
931 struct spandsp_pvt *p = s->tech_pvt;
932
933 /*invalid frame*/
934 if (!f->data.ptr || !f->datalen) {
935 return -1;
936 }
937
938 /* Process a IFP packet */
939 if ((f->frametype == AST_FRAME_MODEM) && (f->subclass.integer == AST_MODEM_T38)) {
940 return t38_core_rx_ifp_packet(p->t38_core_state, f->data.ptr, f->datalen, f->seqno);
941 } else if ((f->frametype == AST_FRAME_VOICE) &&
943 return t38_gateway_rx(&p->t38_gw_state, f->data.ptr, f->samples);
944 }
945
946 return -1;
947}
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
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define AST_MODEM_T38
@ AST_FRAME_VOICE
@ AST_FRAME_MODEM
struct ast_format * format
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
t38_core_state_t * t38_core_state

References ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_slin, AST_FRAME_MODEM, AST_FRAME_VOICE, AST_MODEM_T38, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::ptr, ast_frame::samples, ast_frame::seqno, ast_frame::subclass, spandsp_pvt::t38_core_state, spandsp_pvt::t38_gw_state, and ast_fax_session::tech_pvt.

Referenced by spandsp_fax_write().

◆ spandsp_fax_gateway_start()

static int spandsp_fax_gateway_start ( struct ast_fax_session s)
static

activate a spandsp gateway based on the information in the given fax session

Parameters
sfax session
Returns
-1 on error 0 on sucess

Definition at line 848 of file res_fax_spandsp.c.

849{
850 struct spandsp_pvt *p = s->tech_pvt;
851 struct ast_fax_t38_parameters *t38_param;
852 int i;
853 RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
854 static struct ast_generator t30_gen = {
857 .generate = spandsp_fax_gw_t30_gen,
858 };
859
860#if SPANDSP_RELEASE_DATE >= 20081012
861 /* for spandsp shaphots 0.0.6 and higher */
862 p->t38_core_state=&p->t38_gw_state.t38x.t38;
863#else
864 /* for spandsp release 0.0.5 */
865 p->t38_core_state=&p->t38_gw_state.t38;
866#endif
867
868 if (!t38_gateway_init(&p->t38_gw_state, t38_tx_packet_handler, s)) {
869 return -1;
870 }
871
872 p->ist38 = 1;
874 peer = ast_channel_bridge_peer(s->chan);
875 if (!peer) {
876 return -1;
877 }
878
879 /* we can be in T38_STATE_NEGOTIATING or T38_STATE_NEGOTIATED when the
880 * gateway is started. We treat both states the same. */
883 }
884
885 ast_activate_generator(p->ast_t38_state == T38_STATE_NEGOTIATED ? peer : s->chan, &t30_gen , s);
886
887 set_logging(&p->t38_gw_state.logging, s->details);
888 set_logging(&p->t38_core_state->logging, s->details);
889
891 t38_set_t38_version(p->t38_core_state, t38_param->version);
892 t38_gateway_set_ecm_capability(&p->t38_gw_state, s->details->option.ecm);
893 t38_set_max_datagram_size(p->t38_core_state, t38_param->max_ifp);
894 t38_set_fill_bit_removal(p->t38_core_state, t38_param->fill_bit_removal);
895 t38_set_mmr_transcoding(p->t38_core_state, t38_param->transcoding_mmr);
896 t38_set_jbig_transcoding(p->t38_core_state, t38_param->transcoding_jbig);
897 t38_set_data_rate_management_method(p->t38_core_state,
899
900 t38_gateway_set_transmit_on_idle(&p->t38_gw_state, TRUE);
901 t38_set_sequence_number_handling(p->t38_core_state, TRUE);
902
903
904 t38_gateway_set_supported_modems(&p->t38_gw_state, spandsp_modems(s->details));
905
906 /* engage udptl nat on other side of T38 line
907 * (Asterisk changes media ports thus we send a few packets to reinitialize
908 * pinholes in NATs and FWs
909 */
910 for (i=0; i < SPANDSP_ENGAGE_UDPTL_NAT_RETRY; i++) {
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
914 t38_core_send_indicator(&p->t38_gw_state.t38x.t38, T38_IND_NO_SIGNAL, p->t38_gw_state.t38x.t38.indicator_tx_count);
915#else
916 t38_core_send_indicator(&p->t38_gw_state.t38, T38_IND_NO_SIGNAL, p->t38_gw_state.t38.indicator_tx_count);
917#endif
918 }
919
921
922 return 0;
923}
#define TRUE
Definition: app_minivm.c:524
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
Definition: channel.c:2951
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:2850
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:10564
@ T38_STATE_NEGOTIATED
Definition: channel.h:883
@ T38_STATE_NEGOTIATING
Definition: channel.h:881
@ AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF
@ AST_FAX_STATE_ACTIVE
Definition: res_fax.h:73
static int t38_tx_packet_handler(t38_core_state_t *t38_core_state, void *data, const uint8_t *buf, int len, int count)
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 void * spandsp_fax_gw_gen_alloc(struct ast_channel *chan, void *params)
simple routine to allocate data to generator
#define SPANDSP_ENGAGE_UDPTL_NAT_RETRY
static void spandsp_fax_gw_gen_release(struct ast_channel *chan, void *data)
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
Main Channel structure associated with a channel.
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:177
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:175
struct ast_channel * chan
Definition: res_fax.h:224
unsigned int transcoding_jbig
Definition: res_fax.h:99
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
void *(* alloc)(struct ast_channel *chan, void *params)
Definition: channel.h:226
enum ast_t38_state ast_t38_state
#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

References ast_generator::alloc, ao2_cleanup, ast_activate_generator(), ast_channel_bridge_peer(), ast_channel_get_t38_state(), AST_FAX_STATE_ACTIVE, AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF, spandsp_pvt::ast_t38_state, ast_fax_session::chan, ast_fax_session::details, ast_fax_session_details::ecm, ast_fax_t38_parameters::fill_bit_removal, spandsp_pvt::ist38, ast_fax_t38_parameters::max_ifp, NULL, ast_fax_session_details::option, ast_fax_session_details::our_t38_parameters, RAII_VAR, ast_fax_t38_parameters::rate_management, set_logging(), SPANDSP_ENGAGE_UDPTL_NAT_RETRY, spandsp_fax_gw_gen_alloc(), spandsp_fax_gw_gen_release(), spandsp_fax_gw_t30_gen(), spandsp_modems(), ast_fax_session::state, spandsp_pvt::t38_core_state, spandsp_pvt::t38_gw_state, T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, t38_tx_packet_handler(), ast_fax_session::tech_pvt, ast_fax_session_details::their_t38_parameters, ast_fax_t38_parameters::transcoding_jbig, ast_fax_t38_parameters::transcoding_mmr, TRUE, and ast_fax_t38_parameters::version.

Referenced by spandsp_fax_start().

◆ spandsp_fax_gw_gen_alloc()

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

simple routine to allocate data to generator

Parameters
chanchannel
paramsgenerator data
Returns
data to use in generator call

Definition at line 834 of file res_fax_spandsp.c.

835{
836 ao2_ref(params, +1);
837 return params;
838}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459

References ao2_ref.

Referenced by spandsp_fax_gateway_start().

◆ spandsp_fax_gw_gen_release()

static void spandsp_fax_gw_gen_release ( struct ast_channel chan,
void *  data 
)
static

Definition at line 840 of file res_fax_spandsp.c.

841{
842 ao2_ref(data, -1);
843}

References ao2_ref, and ast_frame::data.

Referenced by spandsp_fax_gateway_start().

◆ spandsp_fax_gw_t30_gen()

static int spandsp_fax_gw_t30_gen ( struct ast_channel chan,
void *  data,
int  len,
int  samples 
)
static

generate T.30 packets sent to the T.30 leg of gateway

Parameters
chanT.30 channel
datafax session structure
lennot used
samplesno of samples generated
Returns
-1 on failure or 0 on sucess

Definition at line 800 of file res_fax_spandsp.c.

801{
802 int res = -1;
803 struct ast_fax_session *s = data;
804 struct spandsp_pvt *p = s->tech_pvt;
805 uint8_t buffer[AST_FRIENDLY_OFFSET + samples * sizeof(uint16_t)];
806 struct ast_frame *f;
807 struct ast_frame t30_frame = {
809 .subclass.format = ast_format_slin,
810 .src = "res_fax_spandsp_g711",
811 .samples = samples,
812 .flags = AST_FAX_FRFLAG_GATEWAY,
813 };
814
815 AST_FRAME_SET_BUFFER(&t30_frame, buffer, AST_FRIENDLY_OFFSET, t30_frame.samples * sizeof(int16_t));
816
817 if (!(f = ast_frisolate(&t30_frame))) {
818 return p->isdone ? -1 : res;
819 }
820
821 /* generate a T.30 packet */
822 if ((f->samples = t38_gateway_tx(&p->t38_gw_state, f->data.ptr, f->samples))) {
823 f->datalen = f->samples * sizeof(int16_t);
824 res = ast_write(chan, f);
825 }
826 ast_frfree(f);
827 return p->isdone ? -1 : res;
828}
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:5144
short int16_t
Definition: db.h:59
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define AST_FRAME_SET_BUFFER(fr, _base, _ofs, _datalen)
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
#define AST_FAX_FRFLAG_GATEWAY
Definition: res_fax.h:232
The data required to handle a fax session.
Definition: res_fax.h:202

References AST_FAX_FRFLAG_GATEWAY, ast_format_slin, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_frisolate, ast_write(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, spandsp_pvt::isdone, ast_frame::ptr, ast_frame::samples, spandsp_pvt::t38_gw_state, and ast_fax_session::tech_pvt.

Referenced by spandsp_fax_gateway_start().

◆ spandsp_fax_new()

static void * spandsp_fax_new ( struct ast_fax_session s,
struct ast_fax_tech_token *  token 
)
static

create an instance of the spandsp tech_pvt for a fax session

Definition at line 560 of file res_fax_spandsp.c.

561{
562 struct spandsp_pvt *p;
563 int caller_mode;
564
565 if ((!(p = ast_calloc(1, sizeof(*p))))) {
566 ast_log(LOG_ERROR, "Cannot initialize the spandsp private FAX technology structure.\n");
567 goto e_return;
568 }
569
571 if (spandsp_v21_new(p)) {
572 ast_log(LOG_ERROR, "Cannot initialize the spandsp private v21 technology structure.\n");
573 goto e_return;
574 }
576 return p;
577 }
578
581 return p;
582 }
583
585
587 caller_mode = 0;
588 } else if (s->details->caps & AST_FAX_TECH_SEND) {
589 caller_mode = 1;
590 } else {
591 ast_log(LOG_ERROR, "Are we sending or receiving? The FAX requirements (capabilities: 0x%X) were not properly set.\n", s->details->caps);
592 goto e_free;
593 }
594
595 if (!(p->timer = ast_timer_open())) {
596 ast_log(LOG_ERROR, "Channel '%s' FAX session '%u' failed to create timing source.\n", s->channame, s->id);
597 goto e_free;
598 }
599
600 s->fd = ast_timer_fd(p->timer);
601
602 p->stats = &spandsp_global_stats.g711;
603
605 if ((s->details->caps & AST_FAX_TECH_AUDIO) == 0) {
606 /* audio mode was not requested, start in T.38 mode */
607 p->ist38 = 1;
608 p->stats = &spandsp_global_stats.t38;
609 }
610
611 /* init t38 stuff */
612 t38_terminal_init(&p->t38_state, caller_mode, t38_tx_packet_handler, s);
613 set_logging(&p->t38_state.logging, s->details);
614
615 /* init audio stuff */
616 fax_init(&p->fax_state, caller_mode);
617 set_logging(&p->fax_state.logging, s->details);
618 }
619
621 return p;
622
623e_free:
624 ast_free(p);
625e_return:
626 return NULL;
627}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
@ AST_FAX_TECH_T38
Definition: res_fax.h:43
@ AST_FAX_TECH_AUDIO
Definition: res_fax.h:41
@ AST_FAX_STATE_INITIALIZED
Definition: res_fax.h:69
static int spandsp_v21_new(struct spandsp_pvt *p)
char * channame
Definition: res_fax.h:220
struct ast_timer * ast_timer_open(void)
Open a timer.
Definition: timing.c:122
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
Definition: timing.c:161

References ast_calloc, AST_FAX_STATE_ACTIVE, AST_FAX_STATE_INITIALIZED, AST_FAX_TECH_AUDIO, AST_FAX_TECH_GATEWAY, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_SEND, AST_FAX_TECH_T38, AST_FAX_TECH_V21_DETECT, ast_free, AST_LIST_HEAD_INIT, ast_log, ast_timer_fd(), ast_timer_open(), ast_fax_session_details::caps, ast_fax_session::channame, ast_fax_session::details, spandsp_pvt::fax_state, ast_fax_session::fd, ast_fax_session::id, spandsp_pvt::ist38, LOG_ERROR, NULL, spandsp_pvt::read_frames, set_logging(), spandsp_global_stats, spandsp_v21_new(), ast_fax_session::state, spandsp_pvt::stats, spandsp_pvt::t38_state, t38_tx_packet_handler(), and spandsp_pvt::timer.

◆ spandsp_fax_read()

static struct ast_frame * spandsp_fax_read ( struct ast_fax_session s)
static

Read a frame from the spandsp fax stack.

Definition at line 657 of file res_fax_spandsp.c.

658{
659 struct spandsp_pvt *p = s->tech_pvt;
660 uint8_t buffer[AST_FRIENDLY_OFFSET + SPANDSP_FAX_SAMPLES * sizeof(uint16_t)];
661 int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
662 int samples;
663
664 struct ast_frame fax_frame = {
666 .src = "res_fax_spandsp_g711",
667 .subclass.format = ast_format_slin,
668 };
669 struct ast_frame *f = &fax_frame;
670
671 if (ast_timer_ack(p->timer, 1) < 0) {
672 ast_log(LOG_ERROR, "Failed to acknowledge timer for FAX session '%u'\n", s->id);
673 return NULL;
674 }
675
676 /* XXX do we need to lock here? */
677 if (p->isdone) {
679 ast_debug(5, "FAX session '%u' is complete.\n", s->id);
680 return NULL;
681 }
682
683 if (p->ist38) {
684 t38_terminal_send_timeout(&p->t38_state, SPANDSP_FAX_SAMPLES);
686 return f;
687 }
688 } else {
689 if ((samples = fax_tx(&p->fax_state, buf, SPANDSP_FAX_SAMPLES)) > 0) {
690 f->samples = samples;
692 return ast_frisolate(f);
693 }
694 }
695
696 return &ast_null_frame;
697}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_debug(level,...)
Log a DEBUG message.
@ AST_FAX_STATE_COMPLETE
Definition: res_fax.h:75
#define SPANDSP_FAX_SAMPLES
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
Definition: timing.c:171

References ast_debug, AST_FAX_STATE_COMPLETE, ast_format_slin, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate, AST_LIST_REMOVE_HEAD, ast_log, ast_null_frame, ast_timer_ack(), buf, spandsp_pvt::fax_state, ast_frame::frametype, ast_fax_session::id, spandsp_pvt::isdone, spandsp_pvt::ist38, LOG_ERROR, NULL, spandsp_pvt::read_frames, ast_frame::samples, SPANDSP_FAX_SAMPLES, ast_fax_session::state, spandsp_pvt::t38_state, ast_fax_session::tech_pvt, and spandsp_pvt::timer.

◆ spandsp_fax_start()

static int spandsp_fax_start ( struct ast_fax_session s)
static

Definition at line 964 of file res_fax_spandsp.c.

965{
966 struct spandsp_pvt *p = s->tech_pvt;
967
969
972 }
973
974 if (p->ist38) {
975#if SPANDSP_RELEASE_DATE >= 20080725
976 /* for spandsp shaphots 0.0.6 and higher */
977 p->t30_state = &p->t38_state.t30;
978 p->t38_core_state = &p->t38_state.t38_fe.t38;
979#else
980 /* for spandsp releases 0.0.5 */
981 p->t30_state = &p->t38_state.t30_state;
982 p->t38_core_state = &p->t38_state.t38;
983#endif
984 } else {
985#if SPANDSP_RELEASE_DATE >= 20080725
986 /* for spandsp shaphots 0.0.6 and higher */
987 p->t30_state = &p->fax_state.t30;
988#else
989 /* for spandsp release 0.0.5 */
990 p->t30_state = &p->fax_state.t30_state;
991#endif
992 }
993
994 set_logging(&p->t30_state->logging, s->details);
995
996 /* set some parameters */
998 set_file(p->t30_state, s->details);
999 set_ecm(p->t30_state, s->details);
1000 t30_set_supported_modems(p->t30_state, spandsp_modems(s->details));
1001
1002 /* perhaps set_transmit_on_idle() should be called */
1003
1004 t30_set_phase_e_handler(p->t30_state, t30_phase_e_handler, s);
1005
1006 /* set T.38 parameters */
1007 if (p->ist38) {
1008 set_logging(&p->t38_core_state->logging, s->details);
1009
1010 t38_set_max_datagram_size(p->t38_core_state, s->details->their_t38_parameters.max_ifp);
1011
1013 t38_set_fill_bit_removal(p->t38_core_state, TRUE);
1014 }
1015
1017 t38_set_mmr_transcoding(p->t38_core_state, TRUE);
1018 }
1019
1021 t38_set_jbig_transcoding(p->t38_core_state, TRUE);
1022 }
1023 } else {
1024 /* have the fax stack generate silence if it has no data to send */
1025 fax_set_transmit_on_idle(&p->fax_state, 1);
1026 }
1027
1028
1029 /* start the timer */
1031 ast_log(LOG_ERROR, "FAX session '%u' error setting rate on timing source.\n", s->id);
1032 return -1;
1033 }
1034
1036
1037 return 0;
1038}
@ AST_FAX_STATE_OPEN
Definition: res_fax.h:71
static void t30_phase_e_handler(t30_state_t *t30_state, void *data, int completion_code)
Phase E handler callback.
static void set_file(t30_state_t *t30_state, struct ast_fax_session_details *details)
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_gateway_start(struct ast_fax_session *s)
activate a spandsp gateway based on the information in the given fax session
static void set_ecm(t30_state_t *t30_state, struct ast_fax_session_details *details)
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
Definition: timing.c:166

References AST_FAX_STATE_ACTIVE, AST_FAX_STATE_OPEN, AST_FAX_TECH_GATEWAY, ast_log, ast_timer_set_rate(), ast_fax_session_details::caps, ast_fax_session::details, spandsp_pvt::fax_state, ast_fax_t38_parameters::fill_bit_removal, ast_fax_session::id, spandsp_pvt::ist38, LOG_ERROR, ast_fax_t38_parameters::max_ifp, set_ecm(), set_file(), set_local_info(), set_logging(), spandsp_fax_gateway_start(), SPANDSP_FAX_TIMER_RATE, spandsp_modems(), ast_fax_session::state, t30_phase_e_handler(), spandsp_pvt::t30_state, spandsp_pvt::t38_core_state, spandsp_pvt::t38_state, ast_fax_session::tech_pvt, ast_fax_session_details::their_t38_parameters, spandsp_pvt::timer, ast_fax_t38_parameters::transcoding_jbig, ast_fax_t38_parameters::transcoding_mmr, and TRUE.

Referenced by spandsp_fax_switch_to_t38().

◆ spandsp_fax_switch_to_t38()

static int spandsp_fax_switch_to_t38 ( struct ast_fax_session s)
static

Definition at line 1056 of file res_fax_spandsp.c.

1057{
1058 struct spandsp_pvt *p = s->tech_pvt;
1059
1060 /* prevent the phase E handler from running, this is not a real termination */
1061 t30_set_phase_e_handler(p->t30_state, NULL, NULL);
1062
1063 t30_terminate(p->t30_state);
1064
1067
1068 p->ist38 = 1;
1069 p->stats = &spandsp_global_stats.t38;
1071
1072 return 0;
1073}
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
static int spandsp_fax_start(struct ast_fax_session *s)
uint32_t switch_to_t38
Definition: res_fax.h:159

References ast_atomic_fetchadd_int(), ast_fax_session::details, spandsp_pvt::ist38, NULL, ast_fax_session_details::option, spandsp_fax_start(), spandsp_global_stats, spandsp_pvt::stats, ast_fax_session_details::switch_to_t38, spandsp_fax_stats::switched, spandsp_pvt::t30_state, and ast_fax_session::tech_pvt.

◆ spandsp_fax_write()

static int spandsp_fax_write ( struct ast_fax_session s,
const struct ast_frame f 
)
static

Write a frame to the spandsp fax stack.

Parameters
sa fax session
fthe frame to write
Note
res_fax does not currently use the return value of this function. Also the fax_rx() function never fails.
Return values
0success
-1failure

Definition at line 769 of file res_fax_spandsp.c.

770{
771 struct spandsp_pvt *p = s->tech_pvt;
772
774 return spandsp_v21_detect(s, f);
775 }
776
778 return spandsp_fax_gateway_process(s, f);
779 }
780
781 /* XXX do we need to lock here? */
782 if (s->state == AST_FAX_STATE_COMPLETE) {
783 ast_log(LOG_WARNING, "FAX session '%u' is in the '%s' state.\n", s->id, ast_fax_state_to_str(s->state));
784 return -1;
785 }
786
787 if (p->ist38) {
788 return t38_core_rx_ifp_packet(p->t38_core_state, f->data.ptr, f->datalen, f->seqno);
789 } else {
790 return fax_rx(&p->fax_state, f->data.ptr, f->samples);
791 }
792}
#define LOG_WARNING
static int spandsp_fax_gateway_process(struct ast_fax_session *s, const struct ast_frame *f)
process a frame from the bridge
static int spandsp_v21_detect(struct ast_fax_session *s, const struct ast_frame *f)

References AST_FAX_STATE_COMPLETE, ast_fax_state_to_str(), AST_FAX_TECH_GATEWAY, AST_FAX_TECH_V21_DETECT, ast_log, ast_fax_session_details::caps, ast_frame::data, ast_frame::datalen, ast_fax_session::details, spandsp_pvt::fax_state, ast_fax_session::id, spandsp_pvt::ist38, LOG_WARNING, ast_frame::ptr, ast_frame::samples, ast_frame::seqno, spandsp_fax_gateway_process(), spandsp_v21_detect(), ast_fax_session::state, spandsp_pvt::t38_core_state, and ast_fax_session::tech_pvt.

◆ spandsp_log()

static void spandsp_log ( int  level,
const char *  msg 
)
static

Send spandsp log messages to asterisk.

Parameters
levelthe spandsp logging level
msgthe log message
Note
This function is a callback function called by spandsp.

Definition at line 455 of file res_fax_spandsp.c.

457{
458 if (level == SPAN_LOG_ERROR) {
459 ast_log(LOG_ERROR, "%s", msg);
460 } else if (level == SPAN_LOG_WARNING) {
461 ast_log(LOG_WARNING, "%s", msg);
462 } else {
464 }
465}
#define LOG_DEBUG
void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
Log message at FAX or recommended level.
Definition: res_fax.c:1035

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

Referenced by set_logging().

◆ spandsp_manager_fax_session()

static void spandsp_manager_fax_session ( struct mansession s,
const char *  id_text,
struct ast_fax_session session 
)
static

Definition at line 1140 of file res_fax_spandsp.c.

1142{
1143 struct ast_str *message_string;
1144 struct spandsp_pvt *span_pvt = session->tech_pvt;
1145 int res;
1146
1147 message_string = ast_str_create(128);
1148
1149 if (!message_string) {
1150 return;
1151 }
1152
1154 res = ast_str_append(&message_string, 0, "SessionNumber: %u\r\n", session->id);
1155 res |= ast_str_append(&message_string, 0, "Operation: %s\r\n", ast_fax_session_operation_str(session));
1156 res |= ast_str_append(&message_string, 0, "State: %s\r\n", ast_fax_state_to_str(session->state));
1157
1158 if (session->details->caps & AST_FAX_TECH_GATEWAY) {
1159 t38_stats_t stats;
1160
1161 if (session->state == AST_FAX_STATE_UNINITIALIZED) {
1162 goto skip_cap_additions;
1163 }
1164
1165 t38_gateway_get_transfer_statistics(&span_pvt->t38_gw_state, &stats);
1166 res |= ast_str_append(&message_string, 0, "ErrorCorrectionMode: %s\r\n",
1167 stats.error_correcting_mode ? "yes" : "no");
1168 res |= ast_str_append(&message_string, 0, "DataRate: %d\r\n",
1169 stats.bit_rate);
1170 res |= ast_str_append(&message_string, 0, "PageNumber: %d\r\n",
1171 stats.pages_transferred + 1);
1172 } else if (!(session->details->caps & AST_FAX_TECH_V21_DETECT)) { /* caps is SEND/RECEIVE */
1173 t30_stats_t stats;
1174
1175 if (session->state == AST_FAX_STATE_UNINITIALIZED) {
1176 goto skip_cap_additions;
1177 }
1178
1179 t30_get_transfer_statistics(span_pvt->t30_state, &stats);
1180 res |= ast_str_append(&message_string, 0, "ErrorCorrectionMode: %s\r\n",
1181 stats.error_correcting_mode ? "Yes" : "No");
1182 res |= ast_str_append(&message_string, 0, "DataRate: %d\r\n",
1183 stats.bit_rate);
1184 res |= ast_str_append(&message_string, 0, "ImageResolution: %dx%d\r\n",
1185 stats.x_resolution, stats.y_resolution);
1186#if SPANDSP_RELEASE_DATE >= 20090220
1187 res |= ast_str_append(&message_string, 0, "PageNumber: %d\r\n",
1188 ((session->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx) + 1);
1189#else
1190 res |= ast_str_append(&message_string, 0, "PageNumber: %d\r\n",
1191 stats.pages_transferred + 1);
1192#endif
1193 res |= ast_str_append(&message_string, 0, "FileName: %s\r\n",
1194 session->details->caps & AST_FAX_TECH_RECEIVE ? span_pvt->t30_state->rx_file :
1195 span_pvt->t30_state->tx_file);
1196#if SPANDSP_RELEASE_DATE >= 20090220
1197 res |= ast_str_append(&message_string, 0, "PagesTransmitted: %d\r\n",
1198 stats.pages_tx);
1199 res |= ast_str_append(&message_string, 0, "PagesReceived: %d\r\n",
1200 stats.pages_rx);
1201#else
1202 res |= ast_str_append(&message_string, 0, "PagesTransmitted: %d\r\n",
1203 (session->details->caps & AST_FAX_TECH_SEND) ? stats.pages_transferred : 0);
1204 res |= ast_str_append(&message_string, 0, "PagesReceived: %d\r\n",
1205 (session->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_transferred : 0);
1206#endif
1207 res |= ast_str_append(&message_string, 0, "TotalBadLines: %d\r\n",
1208 stats.bad_rows);
1209 }
1210
1211skip_cap_additions:
1212
1214
1215 if (res < 0) {
1216 /* One or more of the ast_str_append attempts failed, cancel the message */
1217 ast_free(message_string);
1218 return;
1219 }
1220
1221 astman_append(s, "Event: FAXSession\r\n"
1222 "%s"
1223 "%s"
1224 "\r\n",
1225 id_text,
1226 ast_str_buffer(message_string));
1227
1228 ast_free(message_string);
1229}
static struct ast_mansession session
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3302
const char * ast_fax_session_operation_str(struct ast_fax_session *s)
get string representation of a FAX session's operation
Definition: res_fax.c:4253
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
Support for dynamic strings.
Definition: strings.h:623

References ao2_lock, ao2_unlock, ast_fax_session_operation_str(), ast_fax_state_to_str(), AST_FAX_STATE_UNINITIALIZED, AST_FAX_TECH_GATEWAY, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_SEND, AST_FAX_TECH_V21_DETECT, ast_free, ast_str_append(), ast_str_buffer(), ast_str_create, astman_append(), session, spandsp_pvt::stats, spandsp_pvt::t30_state, and spandsp_pvt::t38_gw_state.

◆ spandsp_modems()

static int spandsp_modems ( struct ast_fax_session_details details)
static

Definition at line 534 of file res_fax_spandsp.c.

535{
536 int modems = 0;
537 if (AST_FAX_MODEM_V17 & details->modems) {
538 modems |= T30_SUPPORT_V17;
539 }
540 if (AST_FAX_MODEM_V27TER & details->modems) {
541 modems |= T30_SUPPORT_V27TER;
542 }
543 if (AST_FAX_MODEM_V29 & details->modems) {
544 modems |= T30_SUPPORT_V29;
545 }
546 if (AST_FAX_MODEM_V34 & details->modems) {
547#if defined(T30_SUPPORT_V34)
548 modems |= T30_SUPPORT_V34;
549#elif defined(T30_SUPPORT_V34HDX)
550 modems |= T30_SUPPORT_V34HDX;
551#else
552 ast_log(LOG_WARNING, "v34 not supported in this version of spandsp\n");
553#endif
554 }
555
556 return modems;
557}
@ 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
enum ast_fax_modems modems
Definition: res_fax.h:115

References AST_FAX_MODEM_V17, AST_FAX_MODEM_V27TER, AST_FAX_MODEM_V29, AST_FAX_MODEM_V34, ast_log, LOG_WARNING, and ast_fax_session_details::modems.

Referenced by spandsp_fax_gateway_start(), and spandsp_fax_start().

◆ spandsp_v21_cleanup()

static void spandsp_v21_cleanup ( struct ast_fax_session s)
static

Definition at line 629 of file res_fax_spandsp.c.

630{
631 struct spandsp_pvt *p = s->tech_pvt;
632
633 modem_connect_tones_rx_free(p->tone_state);
634}
modem_connect_tones_rx_state_t * tone_state

References ast_fax_session::tech_pvt, and spandsp_pvt::tone_state.

Referenced by spandsp_fax_destroy().

◆ spandsp_v21_detect()

static int spandsp_v21_detect ( struct ast_fax_session s,
const struct ast_frame f 
)
static

Definition at line 708 of file res_fax_spandsp.c.

709{
710 struct spandsp_pvt *p = s->tech_pvt;
711 int16_t *slndata;
712 g711_state_t *decoder;
713
714 if (p->v21_detected) {
715 return 0;
716 }
717
718 /*invalid frame*/
719 if (!f->data.ptr || !f->datalen) {
720 return -1;
721 }
722
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));
724
725 /* slinear frame can be passed to spandsp */
727 modem_connect_tones_rx(p->tone_state, f->data.ptr, f->samples);
728
729 /* alaw/ulaw frame must be converted to slinear before passing to spandsp */
732 if (!(slndata = ast_malloc(sizeof(*slndata) * f->samples))) {
733 return -1;
734 }
735 decoder = g711_init(NULL, (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL ? G711_ALAW : G711_ULAW));
736 g711_decode(decoder, slndata, f->data.ptr, f->samples);
737 ast_debug(5, "spandsp transcoding frame from %s to slinear for v21 detection\n", ast_format_get_name(f->subclass.format));
738 modem_connect_tones_rx(p->tone_state, slndata, f->samples);
739 g711_release(decoder);
740#if SPANDSP_RELEASE_DATE >= 20090220
741 g711_free(decoder);
742#endif
743 ast_free(slndata);
744
745 /* frame in other formats cannot be passed to spandsp, it could cause segfault */
746 } else {
747 ast_log(LOG_WARNING, "Frame format %s not supported, v.21 detection skipped\n", ast_format_get_name(f->subclass.format));
748 return -1;
749 }
750
751 if (p->v21_detected) {
753 ast_debug(5, "v.21 detected\n");
754 }
755
756 return 0;
757}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
unsigned int flags
const char * src

References ast_debug, ast_format_alaw, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_name(), ast_format_slin, ast_format_ulaw, ast_free, ast_log, ast_malloc, ast_frame::data, ast_frame::datalen, ast_fax_session::details, ast_frame::flags, ast_frame_subclass::format, ast_frame::len, LOG_WARNING, ast_frame::mallocd, NULL, ast_fax_session_details::option, ast_frame::ptr, ast_frame::samples, ast_frame::seqno, ast_frame::src, ast_frame::subclass, ast_fax_session::tech_pvt, spandsp_pvt::tone_state, ast_frame::ts, ast_fax_session_details::v21_detected, and spandsp_pvt::v21_detected.

Referenced by spandsp_fax_write().

◆ spandsp_v21_new()

static int spandsp_v21_new ( struct spandsp_pvt p)
static

Definition at line 520 of file res_fax_spandsp.c.

521{
522 /* XXX Here we use MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE even though
523 * we don't care about CED tones. Using MODEM_CONNECT_TONES_PREAMBLE
524 * doesn't seem to work right all the time.
525 */
526 p->tone_state = modem_connect_tones_rx_init(NULL, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, spandsp_v21_tone, p);
527 if (!p->tone_state) {
528 return -1;
529 }
530
531 return 0;
532}
static void spandsp_v21_tone(void *data, int code, int level, int delay)

References NULL, spandsp_v21_tone(), and spandsp_pvt::tone_state.

Referenced by spandsp_fax_new().

◆ spandsp_v21_tone()

static void spandsp_v21_tone ( void *  data,
int  code,
int  level,
int  delay 
)
static

Definition at line 699 of file res_fax_spandsp.c.

700{
701 struct spandsp_pvt *p = data;
702
703 if (code == MODEM_CONNECT_TONES_FAX_PREAMBLE) {
704 p->v21_detected = 1;
705 }
706}

References spandsp_pvt::v21_detected.

Referenced by spandsp_v21_new().

◆ t30_phase_e_handler()

static void t30_phase_e_handler ( t30_state_t *  t30_state,
void *  data,
int  completion_code 
)
static

Phase E handler callback.

Parameters
t30_statethe span t30 state
datathis will be the ast_fax_session
completion_codethe result of the fax session

This function pulls stats from the spandsp stack and stores them for res_fax to use later.

Definition at line 390 of file res_fax_spandsp.c.

392{
393 struct ast_fax_session *s = data;
394 struct spandsp_pvt *p = s->tech_pvt;
395 char headerinfo[T30_MAX_PAGE_HEADER_INFO + 1];
396 const char *c;
397 t30_stats_t stats;
398#if SPANDSP_RELEASE_DATE >= 20120902
399 /* for spandsp shaphots 3.0.0 and higher */
400 t30_state_t *t30_state = p->t30_state;
401#endif
402
403 ast_debug(5, "FAX session '%u' entering phase E\n", s->id);
404
405 p->isdone = 1;
406
407 update_stats(p, completion_code);
408
409 t30_get_transfer_statistics(t30_state, &stats);
410
411 if (completion_code == T30_ERR_OK) {
412 ast_string_field_set(s->details, result, "SUCCESS");
413 } else {
414 ast_string_field_set(s->details, result, "FAILED");
415 ast_string_field_set(s->details, error, t30_completion_code_to_str(completion_code));
416 }
417
418 ast_string_field_set(s->details, resultstr, t30_completion_code_to_str(completion_code));
419
420 ast_debug(5, "FAX session '%u' completed with result: %s (%s)\n", s->id, s->details->result, s->details->resultstr);
421
422 if ((c = t30_get_tx_ident(t30_state))) {
423 ast_string_field_set(s->details, localstationid, c);
424 }
425
426 if ((c = t30_get_rx_ident(t30_state))) {
427 ast_string_field_set(s->details, remotestationid, c);
428 }
429
430#if SPANDSP_RELEASE_DATE >= 20090220
431 s->details->pages_transferred = (s->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx;
432#else
433 s->details->pages_transferred = stats.pages_transferred;
434#endif
435
436 ast_string_field_build(s->details, transfer_rate, "%d", stats.bit_rate);
437
438 ast_string_field_build(s->details, resolution, "%dx%d", stats.x_resolution, stats.y_resolution);
439
440 t30_get_tx_page_header_info(t30_state, headerinfo);
441 ast_string_field_set(s->details, headerinfo, headerinfo);
442}
static PGresult * result
Definition: cel_pgsql.c:84
static int update_stats(struct spandsp_pvt *p, int completion_code)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
const ast_string_field result
Definition: res_fax.h:142
const ast_string_field resultstr
Definition: res_fax.h:142
static struct test_val c
int error(const char *format,...)
Definition: utils/frame.c:999

References ast_debug, AST_FAX_TECH_RECEIVE, ast_string_field_build, ast_string_field_set, c, ast_fax_session_details::caps, ast_fax_session::details, error(), ast_fax_session::id, spandsp_pvt::isdone, ast_fax_session_details::pages_transferred, result, ast_fax_session_details::result, ast_fax_session_details::resultstr, spandsp_pvt::stats, spandsp_pvt::t30_state, ast_fax_session::tech_pvt, and update_stats().

Referenced by spandsp_fax_start().

◆ t38_tx_packet_handler()

static int t38_tx_packet_handler ( t38_core_state_t *  t38_core_state,
void *  data,
const uint8_t *  buf,
int  len,
int  count 
)
static

Definition at line 224 of file res_fax_spandsp.c.

225{
226 int res = -1;
227 struct ast_fax_session *s = data;
228 struct spandsp_pvt *p = s->tech_pvt;
229 struct ast_frame fax_frame = {
231 .subclass.integer = AST_MODEM_T38,
232 .src = "res_fax_spandsp_t38",
233 };
234
235 struct ast_frame *f = &fax_frame;
236
237
238 /* TODO: Asterisk does not provide means of resending the same packet multiple
239 times so count is ignored at the moment */
240
242
243 if (!(f = ast_frisolate(f))) {
244 return res;
245 }
246
250 res = ast_write(s->chan, f);
251 } else {
252 res = ast_queue_frame(s->chan, f);
253 }
254 ast_frfree(f);
255 } else {
256 /* no need to lock, this all runs in the same thread */
258 res = 0;
259 }
260
261 return res;
262}
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define ast_set_flag(p, flag)
Definition: utils.h:70

References AST_FAX_FRFLAG_GATEWAY, AST_FAX_TECH_GATEWAY, AST_FRAME_MODEM, AST_FRAME_SET_BUFFER, ast_frfree, ast_frisolate, AST_LIST_INSERT_TAIL, AST_MODEM_T38, ast_queue_frame(), ast_set_flag, spandsp_pvt::ast_t38_state, ast_write(), buf, ast_fax_session_details::caps, ast_fax_session::chan, ast_fax_session::details, ast_frame::frametype, len(), spandsp_pvt::read_frames, T38_STATE_NEGOTIATED, and ast_fax_session::tech_pvt.

Referenced by spandsp_fax_gateway_start(), and spandsp_fax_new().

◆ unload_module()

static int unload_module ( void  )
static

unload res_fax_spandsp

Definition at line 1276 of file res_fax_spandsp.c.

1277{
1281}
#define ast_mutex_destroy(a)
Definition: lock.h:188
void ast_fax_tech_unregister(struct ast_fax_tech *tech)
unregister a fax technology
Definition: res_fax.c:991

References ast_fax_tech_unregister(), AST_MODULE_LOAD_SUCCESS, ast_mutex_destroy, spandsp_fax_tech, and spandsp_global_stats.

◆ update_stats()

static int update_stats ( struct spandsp_pvt p,
int  completion_code 
)
static

The CED tone exceeded 5s

Timed out waiting for initial communication

Timed out waiting for the first message

Timed out waiting for procedural interrupt

The HDLC carrier did not stop in a timely manner

Failed to train with any of the compatible modems

Operator intervention failed

Far end is not compatible

Far end is not able to receive

Far end is not able to transmit

Far end cannot receive at the resolution of the image

Far end cannot receive at the size of image

Unexpected message received

Received bad response to DCS or training

Received a DCN from remote after sending a page

Invalid ECM response received from receiver

Received a DCN while waiting for a DIS

Invalid response after sending a page

Received other than DIS while waiting for DIS

Received no response to DCS, training or TCF

No response after sending a page

Timed out waiting for receiver ready (ECM mode)

Invalid ECM response received from transmitter

DCS received while waiting for DTC

Unexpected command after page received

Carrier lost during fax receive

Timed out while waiting for EOL (end Of line)

Timed out while waiting for first line

Timer T2 expired while waiting for DCN

Timer T2 expired while waiting for phase D

Timer T2 expired while waiting for fax page

Timer T2 expired while waiting for next fax page

Timer T2 expired while waiting for RR command

Timer T2 expired while waiting for NSS, DCS or MCF

Unexpected DCN while waiting for DCS or DIS

Unexpected DCN while waiting for image data

Unexpected DCN while waiting for EOM, EOP or MPS

Unexpected DCN after EOM or MPS sequence

Unexpected DCN after RR/RNR sequence

Unexpected DCN after requested retransmission

TIFF/F file cannot be opened

TIFF/F page not found

TIFF/F format is not compatible

TIFF/F page number tag missing

Incorrect values for TIFF/F tags

Bad TIFF/F header - incorrect values in fields

Cannot allocate memory for more pages

Disconnected after permitted retries

The call dropped prematurely

Poll not accepted

Far end's ident is not acceptable

Far end's sub-address is not acceptable

Far end's selective polling address is not acceptable

Far end's polled sub-address is not acceptable

Far end's sender identification is not acceptable

Far end's password is not acceptable

Far end's transmitting subscriber internet address is not acceptable

Far end's internet routing address is not acceptable

Far end's calling subscriber internet address is not acceptable

Far end's internet selective polling address is not acceptable

Far end's called subscriber internet address is not acceptable

Definition at line 264 of file res_fax_spandsp.c.

265{
266 switch (completion_code) {
267 case T30_ERR_OK:
269 break;
270
271 /* Link problems */
272 case T30_ERR_CEDTONE: /*! The CED tone exceeded 5s */
273 case T30_ERR_T0_EXPIRED: /*! Timed out waiting for initial communication */
274 case T30_ERR_T1_EXPIRED: /*! Timed out waiting for the first message */
275 case T30_ERR_T3_EXPIRED: /*! Timed out waiting for procedural interrupt */
276 case T30_ERR_HDLC_CARRIER: /*! The HDLC carrier did not stop in a timely manner */
277 case T30_ERR_CANNOT_TRAIN: /*! Failed to train with any of the compatible modems */
279 break;
280
281 case T30_ERR_OPER_INT_FAIL: /*! Operator intervention failed */
282 case T30_ERR_INCOMPATIBLE: /*! Far end is not compatible */
283 case T30_ERR_RX_INCAPABLE: /*! Far end is not able to receive */
284 case T30_ERR_TX_INCAPABLE: /*! Far end is not able to transmit */
285 case T30_ERR_NORESSUPPORT: /*! Far end cannot receive at the resolution of the image */
286 case T30_ERR_NOSIZESUPPORT: /*! Far end cannot receive at the size of image */
288 break;
289
290 case T30_ERR_UNEXPECTED: /*! Unexpected message received */
292 break;
293
294 /* Phase E status values returned to a transmitter */
295 case T30_ERR_TX_BADDCS: /*! Received bad response to DCS or training */
296 case T30_ERR_TX_BADPG: /*! Received a DCN from remote after sending a page */
297 case T30_ERR_TX_ECMPHD: /*! Invalid ECM response received from receiver */
298 case T30_ERR_TX_GOTDCN: /*! Received a DCN while waiting for a DIS */
299 case T30_ERR_TX_INVALRSP: /*! Invalid response after sending a page */
300 case T30_ERR_TX_NODIS: /*! Received other than DIS while waiting for DIS */
301 case T30_ERR_TX_PHBDEAD: /*! Received no response to DCS, training or TCF */
302 case T30_ERR_TX_PHDDEAD: /*! No response after sending a page */
303 case T30_ERR_TX_T5EXP: /*! Timed out waiting for receiver ready (ECM mode) */
305 break;
306
307 /* Phase E status values returned to a receiver */
308 case T30_ERR_RX_ECMPHD: /*! Invalid ECM response received from transmitter */
309 case T30_ERR_RX_GOTDCS: /*! DCS received while waiting for DTC */
310 case T30_ERR_RX_INVALCMD: /*! Unexpected command after page received */
311 case T30_ERR_RX_NOCARRIER: /*! Carrier lost during fax receive */
312 case T30_ERR_RX_NOEOL: /*! Timed out while waiting for EOL (end Of line) */
314 break;
315 case T30_ERR_RX_NOFAX: /*! Timed out while waiting for first line */
317 break;
318 case T30_ERR_RX_T2EXPDCN: /*! Timer T2 expired while waiting for DCN */
319 case T30_ERR_RX_T2EXPD: /*! Timer T2 expired while waiting for phase D */
320 case T30_ERR_RX_T2EXPFAX: /*! Timer T2 expired while waiting for fax page */
321 case T30_ERR_RX_T2EXPMPS: /*! Timer T2 expired while waiting for next fax page */
322 case T30_ERR_RX_T2EXPRR: /*! Timer T2 expired while waiting for RR command */
323 case T30_ERR_RX_T2EXP: /*! Timer T2 expired while waiting for NSS, DCS or MCF */
324 case T30_ERR_RX_DCNWHY: /*! Unexpected DCN while waiting for DCS or DIS */
325 case T30_ERR_RX_DCNDATA: /*! Unexpected DCN while waiting for image data */
326 case T30_ERR_RX_DCNFAX: /*! Unexpected DCN while waiting for EOM, EOP or MPS */
327 case T30_ERR_RX_DCNPHD: /*! Unexpected DCN after EOM or MPS sequence */
328 case T30_ERR_RX_DCNRRD: /*! Unexpected DCN after RR/RNR sequence */
329 case T30_ERR_RX_DCNNORTN: /*! Unexpected DCN after requested retransmission */
331 break;
332
333 /* TIFF file problems */
334 case T30_ERR_FILEERROR: /*! TIFF/F file cannot be opened */
335 case T30_ERR_NOPAGE: /*! TIFF/F page not found */
336 case T30_ERR_BADTIFF: /*! TIFF/F format is not compatible */
337 case T30_ERR_BADPAGE: /*! TIFF/F page number tag missing */
338 case T30_ERR_BADTAG: /*! Incorrect values for TIFF/F tags */
339 case T30_ERR_BADTIFFHDR: /*! Bad TIFF/F header - incorrect values in fields */
341 break;
342 case T30_ERR_NOMEM: /*! Cannot allocate memory for more pages */
344 break;
345
346 /* General problems */
347 case T30_ERR_RETRYDCN: /*! Disconnected after permitted retries */
349 break;
350 case T30_ERR_CALLDROPPED: /*! The call dropped prematurely */
352 break;
353
354 /* Feature negotiation issues */
355 case T30_ERR_NOPOLL: /*! Poll not accepted */
356 case T30_ERR_IDENT_UNACCEPTABLE: /*! Far end's ident is not acceptable */
357 case T30_ERR_SUB_UNACCEPTABLE: /*! Far end's sub-address is not acceptable */
358 case T30_ERR_SEP_UNACCEPTABLE: /*! Far end's selective polling address is not acceptable */
359 case T30_ERR_PSA_UNACCEPTABLE: /*! Far end's polled sub-address is not acceptable */
360 case T30_ERR_SID_UNACCEPTABLE: /*! Far end's sender identification is not acceptable */
361 case T30_ERR_PWD_UNACCEPTABLE: /*! Far end's password is not acceptable */
362 case T30_ERR_TSA_UNACCEPTABLE: /*! Far end's transmitting subscriber internet address is not acceptable */
363 case T30_ERR_IRA_UNACCEPTABLE: /*! Far end's internet routing address is not acceptable */
364 case T30_ERR_CIA_UNACCEPTABLE: /*! Far end's calling subscriber internet address is not acceptable */
365 case T30_ERR_ISP_UNACCEPTABLE: /*! Far end's internet selective polling address is not acceptable */
366 case T30_ERR_CSA_UNACCEPTABLE: /*! Far end's called subscriber internet address is not acceptable */
368 break;
369 default:
371 ast_log(LOG_WARNING, "unknown FAX session result '%d' (%s)\n", completion_code, t30_completion_code_to_str(completion_code));
372 return -1;
373 }
374 return 0;
375}

References ast_atomic_fetchadd_int(), ast_log, spandsp_fax_stats::call_dropped, spandsp_fax_stats::failed_to_train, spandsp_fax_stats::file_error, LOG_WARNING, spandsp_fax_stats::mem_error, spandsp_fax_stats::neg_failed, spandsp_fax_stats::nofax, spandsp_fax_stats::protocol_error, spandsp_fax_stats::retries_exceeded, spandsp_fax_stats::rx_protocol_error, spandsp_pvt::stats, spandsp_fax_stats::success, spandsp_fax_stats::tx_protocol_error, and spandsp_fax_stats::unknown_error.

Referenced by t30_phase_e_handler().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Spandsp G.711 and T.38 FAX Technologies" , .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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .enhances = "res_fax", }
static

Definition at line 1311 of file res_fax_spandsp.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1311 of file res_fax_spandsp.c.

◆ g711

struct spandsp_fax_stats g711

Definition at line 142 of file res_fax_spandsp.c.

◆ lock

Definition at line 141 of file res_fax_spandsp.c.

◆ spandsp_fax_tech

struct ast_fax_tech spandsp_fax_tech
static

Definition at line 95 of file res_fax_spandsp.c.

Referenced by load_module(), and unload_module().

◆ 

struct { ... } spandsp_global_stats

◆ t38

struct spandsp_fax_stats t38

Definition at line 143 of file res_fax_spandsp.c.