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