wanpipe/api/libsangoma/examples/priserver.c

214 lines
5.4 KiB
C

/*****************************************************************************
* priserver.c Refactoring of pritest.c
*
* Author(s): Anthony Minessale II <anthmct@yahoo.com>
* Nenad Corbic <ncorbic@sangoma.com>
*
* 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 <libsangoma.h>
#include <sangoma_pri.h>
typedef struct {
int pid;
q931_call call;
void *pri;
}call_info_t;
#define SANGOMA_MAX_CHAN_PER_SPAN 32
static call_info_t pidmap[SANGOMA_MAX_CHAN_PER_SPAN];
/* Stupid runtime process to play a file to a b channel*/
#define BYTES 80
#define MAX_BYTES 1000
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];
sangoma_api_hdr_t hdrframe;
fd_set readfds;
int mtu_mru=BYTES;
wanpipe_tdm_api_t tdm_api;
int err;
pid = fork();
if (pid) {
pidmap[channo-1].pid = pid;
printf("-- Launching process %d to handle channel %d\n", pid, channo);
} else {
memset(inframe, 0, MAX_BYTES);
memset(outframe, 0, MAX_BYTES);
if((fd = sangoma_open_tdmapi_span_chan(spri->span, channo)) < 0) {
printf("DEBUG cant open fd!\n");
}
err=sangoma_tdm_set_codec(fd, &tdm_api, WP_SLINEAR);
if (err < 0){
printf("Critical Error: Failed to set driver codec!\n");
close (fd);
exit(-1);
}
mtu_mru = sangoma_tdm_get_usr_mtu_mru(fd,&tdm_api);
if (mtu_mru < 8){
printf("Critical Error: Failed to obtain MTU/MRU from the card!\n");
close (fd);
exit(-1);
}
file = open("sound.raw", O_RDONLY);
if (file < 0){
printf("Critical Error: Failed to open sound file!\n");
close (fd);
exit(-1);
}
for(;;) {
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
if (!select(fd + 1, &readfds, NULL, NULL, NULL)) {
break;
}
if((outlen = read(file, outframe, mtu_mru)) != mtu_mru) {
break;
}
if((inlen = sangoma_readmsg_tdm(fd, &hdrframe, sizeof(hdrframe),
inframe, MAX_BYTES, 0)) < 0) {
break;
}
sangoma_writemsg_tdm(fd, &hdrframe, sizeof(hdrframe), outframe, outlen, 0);
}
sangoma_get_full_cfg(fd, &tdm_api);
close(file);
close(fd);
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) {
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;
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<SANGOMA_MAX_CHAN_PER_SPAN;x++) {
if (pid == pidmap[x].pid) {
pidmap[x].pid = 0;
if (pidmap[x].pri){
int err=pri_hangup(pidmap[x].pri, &pidmap[x].call, -1);
printf("Hanging up on PID %i Err=%i\n",pid,err);
}
pidmap[x].pri=NULL;
return;
}
}
if (pid > -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
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;
}