#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.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"
Go to the source code of this file.
Defines | |
#define | MAX_BLOCK_SIZE 240 |
Functions | |
char * | description (void) |
Provides a description of the module. | |
char * | key (void) |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
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) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static char * | app = "RxFAX" |
static char * | descrip |
LOCAL_USER_DECL | |
STANDARD_LOCAL_USER | |
static char * | synopsis = "Receive a FAX to a file" |
static char * | tdesc = "Trivial FAX Receive Application" |
#define MAX_BLOCK_SIZE 240 |
char* description | ( | void | ) |
Provides a description of the module.
Definition at line 367 of file app_rxfax.c.
00368 { 00369 return tdesc; 00370 }
char* key | ( | void | ) |
Returns the ASTERISK_GPL_KEY.
This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 381 of file app_rxfax.c.
References ASTERISK_GPL_KEY.
00382 { 00383 return ASTERISK_GPL_KEY; 00384 }
int load_module | ( | void | ) |
Initialize the module.
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 362 of file app_rxfax.c.
References ast_register_application(), and rxfax_exec().
00363 { 00364 return ast_register_application(app, rxfax_exec, synopsis, descrip); 00365 }
static void phase_d_handler | ( | t30_state_t * | s, | |
void * | user_data, | |||
int | result | |||
) | [static] |
Definition at line 136 of file app_rxfax.c.
References ast_log(), LOG_DEBUG, and t.
Referenced by rxfax_exec().
00137 { 00138 struct ast_channel *chan; 00139 t30_stats_t t; 00140 00141 chan = (struct ast_channel *) user_data; 00142 if (result) 00143 { 00144 t30_get_transfer_statistics(s, &t); 00145 ast_log(LOG_DEBUG, "==============================================================================\n"); 00146 ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred); 00147 ast_log(LOG_DEBUG, "Image size: %i x %i\n", t.columns, t.rows); 00148 ast_log(LOG_DEBUG, "Image resolution %i x %i\n", t.column_resolution, t.row_resolution); 00149 ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate); 00150 ast_log(LOG_DEBUG, "Bad rows %i\n", t.bad_rows); 00151 ast_log(LOG_DEBUG, "Longest bad row run %i\n", t.longest_bad_row_run); 00152 ast_log(LOG_DEBUG, "Compression type %i\n", t.encoding); 00153 ast_log(LOG_DEBUG, "Image size (bytes) %i\n", t.image_size); 00154 ast_log(LOG_DEBUG, "==============================================================================\n"); 00155 } 00156 }
static void phase_e_handler | ( | t30_state_t * | s, | |
void * | user_data, | |||
int | result | |||
) | [static] |
Definition at line 86 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(), ast_channel::name, pbx_builtin_setvar_helper(), and t.
Referenced by rxfax_exec(), and txfax_exec().
00087 { 00088 struct ast_channel *chan; 00089 t30_stats_t t; 00090 char local_ident[21]; 00091 char far_ident[21]; 00092 char buf[11]; 00093 00094 chan = (struct ast_channel *) user_data; 00095 if (result == T30_ERR_OK) 00096 { 00097 t30_get_transfer_statistics(s, &t); 00098 t30_get_far_ident(s, far_ident); 00099 t30_get_local_ident(s, local_ident); 00100 ast_log(LOG_DEBUG, "==============================================================================\n"); 00101 ast_log(LOG_DEBUG, "Fax successfully received.\n"); 00102 ast_log(LOG_DEBUG, "Remote station id: %s\n", far_ident); 00103 ast_log(LOG_DEBUG, "Local station id: %s\n", local_ident); 00104 ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred); 00105 ast_log(LOG_DEBUG, "Image resolution: %i x %i\n", t.column_resolution, t.row_resolution); 00106 ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate); 00107 ast_log(LOG_DEBUG, "==============================================================================\n"); 00108 manager_event(EVENT_FLAG_CALL, 00109 "FaxReceived", "Channel: %s\nExten: %s\nCallerID: %s\nRemoteStationID: %s\nLocalStationID: %s\nPagesTransferred: %i\nResolution: %i\nTransferRate: %i\nFileName: %s\n", 00110 chan->name, 00111 chan->exten, 00112 (chan->cid.cid_num) ? chan->cid.cid_num : "", 00113 far_ident, 00114 local_ident, 00115 t.pages_transferred, 00116 t.row_resolution, 00117 t.bit_rate, 00118 s->rx_file); 00119 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident); 00120 snprintf(buf, sizeof(buf), "%i", t.pages_transferred); 00121 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf); 00122 snprintf(buf, sizeof(buf), "%i", t.row_resolution); 00123 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", buf); 00124 snprintf(buf, sizeof(buf), "%i", t.bit_rate); 00125 pbx_builtin_setvar_helper(chan, "FAXBITRATE", buf); 00126 } 00127 else 00128 { 00129 ast_log(LOG_DEBUG, "==============================================================================\n"); 00130 ast_log(LOG_DEBUG, "Fax receive not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result)); 00131 ast_log(LOG_DEBUG, "==============================================================================\n"); 00132 } 00133 }
static int rxfax_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 159 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_read(), ast_set_read_format(), ast_set_write_format(), AST_STATE_UP, ast_waitfor(), ast_write(), ast_frame::data, FALSE, ast_frame::frametype, ast_channel::language, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_DEBUG, LOG_WARNING, MAX_BLOCK_SIZE, ast_channel::name, 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().
00160 { 00161 int res = 0; 00162 char template_file[256]; 00163 char target_file[256]; 00164 char *s; 00165 char *t; 00166 char *v; 00167 char *x; 00168 int option; 00169 int len; 00170 int i; 00171 t30_state_t fax; 00172 int calling_party; 00173 int verbose; 00174 int samples; 00175 00176 struct localuser *u; 00177 struct ast_frame *inf = NULL; 00178 struct ast_frame outf; 00179 00180 int original_read_fmt; 00181 int original_write_fmt; 00182 00183 uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET]; 00184 uint8_t *buf = __buf + AST_FRIENDLY_OFFSET; 00185 00186 if (chan == NULL) 00187 { 00188 ast_log(LOG_WARNING, "Fax receive channel is NULL. Giving up.\n"); 00189 return -1; 00190 } 00191 00192 span_set_message_handler(span_message); 00193 00194 /* The next few lines of code parse out the filename and header from the input string */ 00195 if (data == NULL) 00196 { 00197 /* No data implies no filename or anything is present */ 00198 ast_log(LOG_WARNING, "Rxfax requires an argument (filename)\n"); 00199 return -1; 00200 } 00201 00202 calling_party = FALSE; 00203 verbose = FALSE; 00204 target_file[0] = '\0'; 00205 00206 for (option = 0, v = s = data; v; option++, s++) 00207 { 00208 t = s; 00209 v = strchr(s, '|'); 00210 s = (v) ? v : s + strlen(s); 00211 strncpy((char *) buf, t, s - t); 00212 buf[s - t] = '\0'; 00213 if (option == 0) 00214 { 00215 /* The first option is always the file name */ 00216 len = s - t; 00217 if (len > 255) 00218 len = 255; 00219 strncpy(target_file, t, len); 00220 target_file[len] = '\0'; 00221 /* Allow the use of %d in the file name for a wild card of sorts, to 00222 create a new file with the specified name scheme */ 00223 if ((x = strchr(target_file, '%')) && x[1] == 'd') 00224 { 00225 strcpy(template_file, target_file); 00226 i = 0; 00227 do 00228 { 00229 snprintf(target_file, 256, template_file, 1); 00230 i++; 00231 } 00232 while (ast_fileexists(target_file, "", chan->language) != -1); 00233 } 00234 } 00235 else if (strncmp("caller", t, s - t) == 0) 00236 { 00237 calling_party = TRUE; 00238 } 00239 else if (strncmp("debug", t, s - t) == 0) 00240 { 00241 verbose = TRUE; 00242 } 00243 } 00244 00245 /* Done parsing */ 00246 00247 LOCAL_USER_ADD(u); 00248 00249 if (chan->_state != AST_STATE_UP) 00250 { 00251 /* Shouldn't need this, but checking to see if channel is already answered 00252 * Theoretically asterisk should already have answered before running the app */ 00253 res = ast_answer(chan); 00254 } 00255 00256 if (!res) 00257 { 00258 original_read_fmt = chan->readformat; 00259 if (original_read_fmt != AST_FORMAT_SLINEAR) 00260 { 00261 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00262 if (res < 0) 00263 { 00264 ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n"); 00265 return -1; 00266 } 00267 } 00268 original_write_fmt = chan->writeformat; 00269 if (original_write_fmt != AST_FORMAT_SLINEAR) 00270 { 00271 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); 00272 if (res < 0) 00273 { 00274 ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n"); 00275 res = ast_set_read_format(chan, original_read_fmt); 00276 if (res) 00277 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 00278 return -1; 00279 } 00280 } 00281 fax_init(&fax, calling_party, NULL); 00282 if (verbose) 00283 fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; 00284 x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"); 00285 if (x && x[0]) 00286 t30_set_local_ident(&fax, x); 00287 x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"); 00288 if (x && x[0]) 00289 t30_set_header_info(&fax, x); 00290 t30_set_rx_file(&fax, target_file, -1); 00291 //t30_set_phase_b_handler(&fax, phase_b_handler, chan); 00292 t30_set_phase_d_handler(&fax, phase_d_handler, chan); 00293 t30_set_phase_e_handler(&fax, phase_e_handler, chan); 00294 while (ast_waitfor(chan, -1) > -1) 00295 { 00296 inf = ast_read(chan); 00297 if (inf == NULL) 00298 { 00299 res = -1; 00300 break; 00301 } 00302 if (inf->frametype == AST_FRAME_VOICE) 00303 { 00304 if (fax_rx(&fax, inf->data, inf->samples)) 00305 break; 00306 samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE; 00307 len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples); 00308 if (len) 00309 { 00310 memset(&outf, 0, sizeof(outf)); 00311 outf.frametype = AST_FRAME_VOICE; 00312 outf.subclass = AST_FORMAT_SLINEAR; 00313 outf.datalen = len*sizeof(int16_t); 00314 outf.samples = len; 00315 outf.data = &buf[AST_FRIENDLY_OFFSET]; 00316 outf.offset = AST_FRIENDLY_OFFSET; 00317 outf.src = "RxFAX"; 00318 if (ast_write(chan, &outf) < 0) 00319 { 00320 ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); 00321 break; 00322 } 00323 } 00324 } 00325 ast_frfree(inf); 00326 } 00327 if (inf == NULL) 00328 { 00329 ast_log(LOG_DEBUG, "Got hangup\n"); 00330 res = -1; 00331 } 00332 if (original_read_fmt != AST_FORMAT_SLINEAR) 00333 { 00334 res = ast_set_read_format(chan, original_read_fmt); 00335 if (res) 00336 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 00337 } 00338 if (original_write_fmt != AST_FORMAT_SLINEAR) 00339 { 00340 res = ast_set_write_format(chan, original_write_fmt); 00341 if (res) 00342 ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name); 00343 } 00344 fax_release(&fax); 00345 } 00346 else 00347 { 00348 ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name); 00349 } 00350 LOCAL_USER_REMOVE(u); 00351 return res; 00352 }
static void span_message | ( | int | level, | |
const char * | msg | |||
) | [static] |
Definition at line 66 of file app_rxfax.c.
References __LOG_DEBUG, __LOG_WARNING, and ast_log().
Referenced by rxfax_exec(), and txfax_exec().
00067 { 00068 int ast_level; 00069 00070 if (level == SPAN_LOG_WARNING) 00071 ast_level = __LOG_WARNING; 00072 else if (level == SPAN_LOG_WARNING) 00073 ast_level = __LOG_WARNING; 00074 else 00075 ast_level = __LOG_DEBUG; 00076 ast_log(ast_level, __FILE__, __LINE__, __PRETTY_FUNCTION__, msg); 00077 }
static void t30_flush | ( | t30_state_t * | s, | |
int | which | |||
) | [static] |
int unload_module | ( | void | ) |
Cleanup all module structures, sockets, etc.
This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 355 of file app_rxfax.c.
References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.
00356 { 00357 STANDARD_HANGUP_LOCALUSERS; 00358 return ast_unregister_application(app); 00359 }
int usecount | ( | void | ) |
Provides a usecount.
This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 373 of file app_rxfax.c.
References STANDARD_USECOUNT.
00374 { 00375 int res; 00376 STANDARD_USECOUNT(res); 00377 return res; 00378 }
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 62 of file app_rxfax.c.
Definition at line 60 of file app_rxfax.c.
char* synopsis = "Receive a FAX to a file" [static] |
Definition at line 42 of file app_rxfax.c.
char* tdesc = "Trivial FAX Receive Application" [static] |
Definition at line 38 of file app_rxfax.c.