/***************************************************************************** * prifax.c PRI Fax Server * * Author(s): Anthony Minessale II * Nenad Corbic * * Copyright: (c) 2005 Anthony Minessale II * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * ============================================================================ */ #include #include #include #include #include #include #include #include #include static int pidmap[SANGOMA_MAX_CHAN_PER_SPAN]; static void phase_e_handler(t30_state_t *s, void *user_data, int result) { t30_stats_t t; char local_ident[21]; char far_ident[21]; if (result) { fax_get_transfer_statistics(s, &t); fax_get_far_ident(s, far_ident); fax_get_local_ident(s, local_ident); printf( "==============================================================================\n"); printf( "Fax successfully received.\n"); printf( "Remote station id: %s\n", far_ident); printf( "Local station id: %s\n", local_ident); printf( "Pages transferred: %i\n", t.pages_transferred); printf( "Image resolution: %i x %i\n", t.column_resolution, t.row_resolution); printf( "Transfer Rate: %i\n", t.bit_rate); printf( "==============================================================================\n"); } else { printf( "==============================================================================\n"); printf( "Fax receive not successful.\n"); printf( "==============================================================================\n"); } } /*- End of function --------------------------------------------------------*/ static void phase_d_handler(t30_state_t *s, void *user_data, int result) { t30_stats_t t; if (result) { fax_get_transfer_statistics(s, &t); printf( "==============================================================================\n"); printf( "Pages transferred: %i\n", t.pages_transferred); printf( "Image size: %i x %i\n", t.columns, t.rows); printf( "Image resolution %i x %i\n", t.column_resolution, t.row_resolution); printf( "Transfer Rate: %i\n", t.bit_rate); printf( "Bad rows %i\n", t.bad_rows); printf( "Longest bad row run %i\n", t.longest_bad_row_run); printf( "Compression type %i\n", t.encoding); printf( "Image size (bytes) %i\n", t.image_size); printf( "==============================================================================\n"); } } /* Stupid runtime process to play a file to a b channel*/ #define BYTES 160 #define BLEN 512 static void launch_channel(struct sangoma_pri *spri, int channo) { pid_t pid; int fd = 0, inlen = 0, flen = 0, wrote; unsigned char inframe[BLEN], outframe[BLEN]; sangoma_api_hdr_t hdrframe; fd_set readfds; t30_state_t fax; pid = fork(); if (pid) { pidmap[channo-1] = pid; printf("-- Launching process %d to handle channel %d\n", pid, channo); } else { char tfile[128]; memset(inframe, 0, BLEN); memset(outframe, 0, BLEN); fax_init(&fax, TRUE, NULL); fax.verbose = 1; fax_set_local_ident(&fax, "TEST"); fax_set_header_info(&fax, "TRY"); snprintf(tfile, sizeof(tfile), "/tmp/fax.%d.tif", getpid()); fax_set_rx_file(&fax, tfile); fax_set_phase_d_handler(&fax, phase_d_handler, NULL); fax_set_phase_e_handler(&fax, phase_e_handler, NULL); if((fd = sangoma_create_socket_intr(spri->span, channo)) < 0) { printf("DEBUG can't open fd!\n"); } for(;;) { FD_ZERO(&readfds); FD_SET(fd, &readfds); if (!select(fd + 1, &readfds, NULL, NULL, NULL)) { break; } if((inlen = sangoma_readmsg_socket(fd, &hdrframe, sizeof(hdrframe), inframe, BLEN, 0)) < 0) { break; } if (fax_rx_process(&fax, (int16_t *) inframe, inlen / sizeof(int16_t))) { break; } flen = fax_tx_process(&fax, (int16_t *) outframe, BYTES / sizeof(int16_t)); wrote = sangoma_sendmsg_socket(fd, &hdrframe, sizeof(hdrframe), outframe, (flen * sizeof(int16_t)), 0); //inlen=176 flen=88 wrote=104 //printf("inlen=%d flen=%d wrote=%d\n", inlen, flen, wrote); } close(fd); exit(0); } } /* Event Handlers */ static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) { printf( "number is: %s\n", event->ring.callednum); if(strlen(event->ring.callednum) > 3) { printf( "final number is: %s\n", event->ring.callednum); pri_answer(spri->pri, event->ring.call, 0, 1); } return 0; } static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) { pri_hangup(spri->pri, event->hangup.call, event->hangup.cause); printf("-- Hanging up channel %d\n", event->hangup.channel); if(pidmap[event->hangup.channel-1]) { kill(pidmap[event->hangup.channel-1], SIGINT); pidmap[event->hangup.channel-1] = 0; } return 0; } static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) { printf("-- Ring on channel %d (from %s to %s), answering...\n", event->ring.channel, event->ring.callingnum, event->ring.callednum); pri_answer(spri->pri, event->ring.call, event->ring.channel, 1); launch_channel(spri, event->ring.channel); return 0; } static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) { printf("-- Restarting channel %d\n", event->restart.channel); return 0; } static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) { printf("%s: Caught Event %d (%s)\n", __FUNCTION__, event_type, sangoma_pri_event_str(event_type)); return 0; } /* Generic Reaper */ static void chan_ended(int sig) { int status; int x; struct rusage rusage; pid_t pid; pid = wait4(-1, &status, WNOHANG, &rusage); printf("-- PID %d ended\n", pid); for (x=0;x -1) { fprintf(stderr, "--!! Unknown PID %d exited\n", pid); return; } } /* Our Program */ int main(int argc, char *argv[]) { struct sangoma_pri spri; int debug = 0; if (argv[1]) { debug = atoi(argv[1]); } if (sangoma_init_pri(&spri, 1, // span 24, // dchan 23, // bchans SANGOMA_PRI_SWITCH_DMS100, SANGOMA_PRI_CPE, debug) < 0) { return -1; } SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_ANY, on_anything); SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_RING, on_ring); SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_HANGUP_REQ, on_hangup); SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_INFO_RECEIVED, on_info); SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_RESTART, on_restart); signal(SIGCHLD, chan_ended); sangoma_run_pri(&spri); return 0; }