#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 "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/dsp.h"
#include "asterisk/manager.h"
Include dependency graph for app_rxfax.c:
Go to the source code of this file.
Defines | |
#define | MAX_BLOCK_SIZE 240 |
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Trivial FAX Receive Application") | |
static int | load_module (void) |
static void | phase_d_handler (t30_state_t *s, void *user_data, int result) |
static void | phase_e_handler (t30_state_t *s, void *user_data, int result) |
static int | rxfax_exec (struct ast_channel *chan, void *data) |
static void | span_message (int level, const char *msg) |
static void | t30_flush (t30_state_t *s, int which) |
static int | unload_module (void) |
Variables | |
static char * | app = "RxFAX" |
static char * | descrip |
static char * | synopsis = "Receive a FAX to a file" |
#define MAX_BLOCK_SIZE 240 |
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Trivial FAX Receive Application" | ||||
) |
static int load_module | ( | void | ) | [static] |
Definition at line 331 of file app_rxfax.c.
References app, ast_register_application(), descrip, rxfax_exec(), and synopsis.
00332 { 00333 return ast_register_application(app, rxfax_exec, synopsis, descrip); 00334 }
static void phase_d_handler | ( | t30_state_t * | s, | |
void * | user_data, | |||
int | result | |||
) | [static] |
Definition at line 121 of file app_rxfax.c.
References ast_log(), LOG_DEBUG, and t.
Referenced by rxfax_exec().
00122 { 00123 struct ast_channel *chan; 00124 t30_stats_t t; 00125 00126 chan = (struct ast_channel *) user_data; 00127 if (result) { 00128 t30_get_transfer_statistics(s, &t); 00129 ast_log(LOG_DEBUG, "==============================================================================\n"); 00130 ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred); 00131 ast_log(LOG_DEBUG, "Image size: %i x %i\n", t.width, t.length); 00132 ast_log(LOG_DEBUG, "Image resolution %i x %i\n", t.x_resolution, t.y_resolution); 00133 ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate); 00134 ast_log(LOG_DEBUG, "Bad rows %i\n", t.bad_rows); 00135 ast_log(LOG_DEBUG, "Longest bad row run %i\n", t.longest_bad_row_run); 00136 ast_log(LOG_DEBUG, "Compression type %i\n", t.encoding); 00137 ast_log(LOG_DEBUG, "Image size (bytes) %i\n", t.image_size); 00138 ast_log(LOG_DEBUG, "==============================================================================\n"); 00139 } 00140 }
static void phase_e_handler | ( | t30_state_t * | s, | |
void * | user_data, | |||
int | result | |||
) | [static] |
Definition at line 81 of file app_rxfax.c.
References ast_log(), ast_channel::cid, ast_callerid::cid_num, EVENT_FLAG_CALL, ast_channel::exten, LOG_DEBUG, manager_event(), pbx_builtin_setvar_helper(), and t.
Referenced by rxfax_exec(), and txfax_exec().
00082 { 00083 struct ast_channel *chan; 00084 t30_stats_t t; 00085 char local_ident[21]; 00086 char far_ident[21]; 00087 char buf[11]; 00088 00089 chan = (struct ast_channel *) user_data; 00090 if (result == T30_ERR_OK) { 00091 t30_get_transfer_statistics(s, &t); 00092 t30_get_far_ident(s, far_ident); 00093 t30_get_local_ident(s, local_ident); 00094 ast_log(LOG_DEBUG, "==============================================================================\n"); 00095 ast_log(LOG_DEBUG, "Fax successfully received.\n"); 00096 ast_log(LOG_DEBUG, "Remote station id: %s\n", far_ident); 00097 ast_log(LOG_DEBUG, "Local station id: %s\n", local_ident); 00098 ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred); 00099 ast_log(LOG_DEBUG, "Image resolution: %i x %i\n", t.x_resolution, t.y_resolution); 00100 ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate); 00101 ast_log(LOG_DEBUG, "==============================================================================\n"); 00102 manager_event(EVENT_FLAG_CALL, 00103 "FaxReceived", "Channel: %s\nExten: %s\nCallerID: %s\nRemoteStationID: %s\nLocalStationID: %s\nPagesTransferred: %i\nResolution: %i\nTransferRate: %i\nFileName: %s\n", 00104 chan->name, chan->exten, (chan->cid.cid_num) ? chan->cid.cid_num : "", far_ident, local_ident, t.pages_transferred, t.y_resolution, t.bit_rate, s->rx_file); 00105 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident); 00106 snprintf(buf, sizeof(buf), "%i", t.pages_transferred); 00107 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf); 00108 snprintf(buf, sizeof(buf), "%i", t.y_resolution); 00109 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", buf); 00110 snprintf(buf, sizeof(buf), "%i", t.bit_rate); 00111 pbx_builtin_setvar_helper(chan, "FAXBITRATE", buf); 00112 } else { 00113 ast_log(LOG_DEBUG, "==============================================================================\n"); 00114 ast_log(LOG_DEBUG, "Fax receive not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result)); 00115 ast_log(LOG_DEBUG, "==============================================================================\n"); 00116 } 00117 }
static int rxfax_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 144 of file app_rxfax.c.
References ast_channel::_state, ast_answer(), ast_fileexists(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_frfree(), AST_FRIENDLY_OFFSET, ast_log(), ast_module_user_add, ast_module_user_remove, ast_read(), ast_set_read_format(), ast_set_write_format(), AST_STATE_UP, ast_waitfor(), ast_write(), ast_frame::data, FALSE, ast_frame::frametype, len, LOG_DEBUG, LOG_WARNING, MAX_BLOCK_SIZE, pbx_builtin_getvar_helper(), phase_d_handler(), phase_e_handler(), ast_channel::readformat, s, ast_frame::samples, span_message(), t, TRUE, and ast_channel::writeformat.
Referenced by load_module().
00145 { 00146 int res = 0; 00147 char template_file[256]; 00148 char target_file[256]; 00149 char *s; 00150 char *t; 00151 char *v; 00152 const char *x; 00153 int option; 00154 int len; 00155 int i; 00156 fax_state_t fax; 00157 int calling_party; 00158 int verbose; 00159 int samples; 00160 00161 struct ast_module_user *u; 00162 struct ast_frame *inf = NULL; 00163 struct ast_frame outf; 00164 00165 int original_read_fmt; 00166 int original_write_fmt; 00167 00168 uint8_t __buf[sizeof(uint16_t) * MAX_BLOCK_SIZE + 2 * AST_FRIENDLY_OFFSET]; 00169 uint8_t *buf = __buf + AST_FRIENDLY_OFFSET; 00170 00171 if (chan == NULL) { 00172 ast_log(LOG_WARNING, "Fax receive channel is NULL. Giving up.\n"); 00173 return -1; 00174 } 00175 00176 span_set_message_handler(span_message); 00177 00178 /* The next few lines of code parse out the filename and header from the input string */ 00179 if (data == NULL) { 00180 /* No data implies no filename or anything is present */ 00181 ast_log(LOG_WARNING, "Rxfax requires an argument (filename)\n"); 00182 return -1; 00183 } 00184 00185 calling_party = FALSE; 00186 verbose = FALSE; 00187 target_file[0] = '\0'; 00188 00189 for (option = 0, v = s = data; v; option++, s++) { 00190 t = s; 00191 v = strchr(s, '|'); 00192 s = (v) ? v : s + strlen(s); 00193 strncpy((char *) buf, t, s - t); 00194 buf[s - t] = '\0'; 00195 if (option == 0) { 00196 /* The first option is always the file name */ 00197 len = s - t; 00198 if (len > 255) 00199 len = 255; 00200 strncpy(target_file, t, len); 00201 target_file[len] = '\0'; 00202 /* Allow the use of %d in the file name for a wild card of sorts, to 00203 create a new file with the specified name scheme */ 00204 if ((x = strchr(target_file, '%')) && x[1] == 'd') { 00205 strcpy(template_file, target_file); 00206 i = 0; 00207 do { 00208 snprintf(target_file, 256, template_file, 1); 00209 i++; 00210 } 00211 while (ast_fileexists(target_file, "", chan->language) != -1); 00212 } 00213 } else if (strncmp("caller", t, s - t) == 0) { 00214 calling_party = TRUE; 00215 } else if (strncmp("debug", t, s - t) == 0) { 00216 verbose = TRUE; 00217 } 00218 } 00219 00220 /* Done parsing */ 00221 00222 u = ast_module_user_add(chan); 00223 00224 if (chan->_state != AST_STATE_UP) { 00225 /* Shouldn't need this, but checking to see if channel is already answered 00226 * Theoretically asterisk should already have answered before running the app */ 00227 res = ast_answer(chan); 00228 } 00229 00230 if (!res) { 00231 original_read_fmt = chan->readformat; 00232 if (original_read_fmt != AST_FORMAT_SLINEAR) { 00233 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00234 if (res < 0) { 00235 ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n"); 00236 return -1; 00237 } 00238 } 00239 original_write_fmt = chan->writeformat; 00240 if (original_write_fmt != AST_FORMAT_SLINEAR) { 00241 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); 00242 if (res < 0) { 00243 ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n"); 00244 res = ast_set_read_format(chan, original_read_fmt); 00245 if (res) 00246 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 00247 return -1; 00248 } 00249 } 00250 fax_init(&fax, calling_party); 00251 if (verbose) 00252 fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; 00253 x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"); 00254 if (x && x[0]) 00255 t30_set_local_ident(&fax.t30_state, x); 00256 x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"); 00257 if (x && x[0]) 00258 t30_set_header_info(&fax.t30_state, x); 00259 t30_set_rx_file(&fax.t30_state, target_file, -1); 00260 //t30_set_phase_b_handler(&fax.t30_state, phase_b_handler, chan); 00261 t30_set_phase_d_handler(&fax.t30_state, phase_d_handler, chan); 00262 t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, chan); 00263 t30_set_ecm_capability(&fax.t30_state, TRUE); 00264 t30_set_supported_compressions(&fax.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); 00265 while (ast_waitfor(chan, -1) > -1) { 00266 inf = ast_read(chan); 00267 if (inf == NULL) { 00268 res = -1; 00269 break; 00270 } 00271 if (inf->frametype == AST_FRAME_VOICE) { 00272 if (fax_rx(&fax, inf->data, inf->samples)) 00273 break; 00274 samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE; 00275 len = fax_tx(&fax, (int16_t *) & buf[AST_FRIENDLY_OFFSET], samples); 00276 if (len) { 00277 memset(&outf, 0, sizeof(outf)); 00278 outf.frametype = AST_FRAME_VOICE; 00279 outf.subclass = AST_FORMAT_SLINEAR; 00280 outf.datalen = len * sizeof(int16_t); 00281 outf.samples = len; 00282 outf.data = &buf[AST_FRIENDLY_OFFSET]; 00283 outf.offset = AST_FRIENDLY_OFFSET; 00284 outf.src = "RxFAX"; 00285 if (ast_write(chan, &outf) < 0) { 00286 ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); 00287 break; 00288 } 00289 } 00290 } 00291 ast_frfree(inf); 00292 } 00293 if (inf == NULL) { 00294 ast_log(LOG_DEBUG, "Got hangup\n"); 00295 res = -1; 00296 } 00297 if (original_read_fmt != AST_FORMAT_SLINEAR) { 00298 res = ast_set_read_format(chan, original_read_fmt); 00299 if (res) 00300 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 00301 } 00302 if (original_write_fmt != AST_FORMAT_SLINEAR) { 00303 res = ast_set_write_format(chan, original_write_fmt); 00304 if (res) 00305 ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name); 00306 } 00307 t30_terminate(&fax.t30_state); 00308 } else { 00309 ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name); 00310 } 00311 ast_module_user_remove(u); 00312 return res; 00313 }
static void span_message | ( | int | level, | |
const char * | msg | |||
) | [static] |
Definition at line 59 of file app_rxfax.c.
References __LOG_DEBUG, __LOG_WARNING, and ast_log().
Referenced by rxfax_exec(), and txfax_exec().
00060 { 00061 int ast_level; 00062 00063 if (level == SPAN_LOG_WARNING) 00064 ast_level = __LOG_WARNING; 00065 else if (level == SPAN_LOG_WARNING) 00066 ast_level = __LOG_WARNING; 00067 else 00068 ast_level = __LOG_DEBUG; 00069 ast_log(ast_level, __FILE__, __LINE__, __PRETTY_FUNCTION__, msg); 00070 }
static void t30_flush | ( | t30_state_t * | s, | |
int | which | |||
) | [static] |
static int unload_module | ( | void | ) | [static] |
Definition at line 317 of file app_rxfax.c.
References app, ast_module_user_hangup_all, and ast_unregister_application().
00318 { 00319 int res; 00320 00321 ast_module_user_hangup_all(); 00322 00323 res = ast_unregister_application(app); 00324 00325 00326 return res; 00327 }
char* app = "RxFAX" [static] |
Definition at line 40 of file app_rxfax.c.
char* descrip [static] |
Definition at line 44 of file app_rxfax.c.
Definition at line 42 of file app_rxfax.c.