/***************************************************************************** * priserver.c Refactoring of pritest.c * * 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 "openzap.h" #include #include #include #include #include #include typedef struct { int pid; q931_call call; void *pri; int ready; }call_info_t; #define SANGOMA_MAX_CHAN_PER_SPAN 32 static call_info_t pidmap[SANGOMA_MAX_CHAN_PER_SPAN]; ZIO_EVENT_CB_FUNCTION(my_zap_event_handler) { if (event->e_type = ZAP_EVENT_DTMF) { char *dtmf = event->data; printf("DTMF %s\n", dtmf); } } /* Stupid runtime process to play a file to a b channel*/ #define BYTES 320 #define MAX_BYTES 1000 static int ready = 1; static void handle_SIGINT(int sig) { if (sig) { ready = 0; } return; } static void launch_channel(struct sangoma_pri *spri, int channo) { pid_t pid; int fd = 0, file = 0, inlen = 0, outlen = 0; unsigned char inframe[MAX_BYTES], outframe[MAX_BYTES]; fd_set readfds; int mtu_mru=BYTES / 2; int err; zap_channel_t *chan; zap_codec_t codec = ZAP_CODEC_SLIN; unsigned ms = 20; unsigned int lead = 50; int ifd = -1; zap_tone_type_t tt = ZAP_TONE_DTMF; char dtmf[] = "1234567890"; int loops = 0; pid = fork(); if (pid) { pidmap[channo-1].pid = pid; printf("-- Launching process %d to handle channel %d\n", pid, channo); return; } signal(SIGINT, handle_SIGINT); //ifd = open("/nfs/sounds/ptest.raw", O_WRONLY|O_CREAT|O_TRUNC, 777); memset(inframe, 0, MAX_BYTES); memset(outframe, 0, MAX_BYTES); if (zap_channel_open(spri->span, channo, &chan) != ZAP_SUCCESS) { printf("DEBUG cant open fd!\n"); } #if 1 if (zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &codec) != ZAP_SUCCESS) { printf("Critical Error: Failed to set driver codec!\n"); zap_channel_close(&chan); exit(-1); } #endif #if 1 if (zap_channel_command(chan, ZAP_COMMAND_ENABLE_DTMF_DETECT, &tt) != ZAP_SUCCESS) { printf("Critical Error: Failed to set dtmf detect!\n"); zap_channel_close(&chan); exit(-1); } zap_channel_set_event_callback(chan, my_zap_event_handler); #endif if (zap_channel_command(chan, ZAP_COMMAND_SET_INTERVAL, &ms) != ZAP_SUCCESS) { printf("Critical Error: Failed to set codec interval!\n"); zap_channel_close(&chan); exit(-1); } file = open("sound.raw", O_RDONLY); if (file < 0){ printf("Critical Error: Failed to open sound file!\n"); zap_channel_close(&chan); exit(-1); } while(ready) { zap_wait_flag_t flags = ZAP_READ; zap_size_t len; loops++; if (lead) { lead--; } if (!lead && loops == 300) { #if 1 if (zap_channel_command(chan, ZAP_COMMAND_SEND_DTMF, dtmf) != ZAP_SUCCESS) { printf("Critical Error: Failed to send dtmf\n"); zap_channel_close(&chan); exit(-1); } #endif } if (zap_channel_wait(chan, &flags, 2000) != ZAP_SUCCESS) { printf("wait FAIL! [%s]\n", chan->last_error); break; } if (flags & ZAP_READ) { len = MAX_BYTES; if (zap_channel_read(chan, inframe, &len) == ZAP_SUCCESS) { //printf("READ: %d\n", len); //write(ifd, inframe, len); if(!lead && (outlen = read(file, outframe, len)) <= 0) { break; } } else { printf("READ FAIL! %d [%s]\n", len, chan->last_error); break; } if (lead) { continue; } zap_channel_write(chan, outframe, sizeof(outframe), &len); } else { printf("BREAK"); break; } } printf("loop done\n"); //sangoma_get_full_cfg(fd, &tdm_api); close(file); //close(ifd); pri_hangup(spri->pri, channo, 16); if (zap_channel_close(&chan) != ZAP_SUCCESS) { printf("Critical Error: Failed to close channel [%s]\n", chan->last_error); } printf("Call Handler: Process Finished\n"); 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].pid) { pri_hangup(spri->pri, event->hangup.call, 16); pri_destroycall(spri->pri, event->hangup.call); kill(pidmap[event->hangup.channel-1].pid, SIGINT); pidmap[event->hangup.channel-1].pid = 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); memcpy(&pidmap[event->ring.channel-1].call, event->ring.call, sizeof(q931_call)); pidmap[event->ring.channel-1].pri=spri->pri; pidmap[event->ring.channel-1].call = *event->ring.call; 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); signal(SIGCHLD, chan_ended); return; } } /* Our Program */ int main(int argc, char *argv[]) { struct sangoma_pri spri; int debug = 0; if (argv[1]) { debug = atoi(argv[1]); } zap_global_set_default_logger(ZAP_LOG_LEVEL_DEBUG); if (zap_global_init() != ZAP_SUCCESS) { fprintf(stderr, "Error loading OpenZAP\n"); exit(-1); } printf("OpenZAP loaded\n"); debug = PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE; printf("WTF %d\n", debug); if (sangoma_init_pri(&spri, 1, // span 24, // dchan SANGOMA_PRI_SWITCH_DMS100, SANGOMA_PRI_CPE, debug) < 0) { return -1; } //spri.pri->debug = (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE); //pri_set_debug(&spri.pri, (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)); 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, on_hangup); 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; } /* For Emacs: * Local Variables: * mode:c * indent-tabs-mode:t * tab-width:4 * c-basic-offset:4 * End: * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4: */