Sat Sep 16 07:28:11 2006

Asterisk developer's documentation


app_rxfax.c File Reference

#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 Documentation

#define MAX_BLOCK_SIZE   240

Definition at line 64 of file app_rxfax.c.

Referenced by rxfax_exec(), and txfax_exec().


Function Documentation

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your 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;
 }

Returns:
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.

Returns:
int Always 0.

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]

Definition at line 80 of file app_rxfax.c.

00081 {
00082     //TODO:
00083 }

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).

Returns:
Zero on success, or non-zero on error.

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.

Returns:
The module's usecount.

Definition at line 373 of file app_rxfax.c.

References STANDARD_USECOUNT.

00374 {
00375     int res;
00376     STANDARD_USECOUNT(res);
00377     return res;
00378 }


Variable Documentation

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.

LOCAL_USER_DECL

Definition at line 62 of file app_rxfax.c.

STANDARD_LOCAL_USER

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.


Generated on Sat Sep 16 07:28:11 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7