root/src/priserver.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. FIO_EVENT_CB_FUNCTION
  2. handle_SIGINT
  3. launch_channel
  4. on_info
  5. on_hangup
  6. on_ring
  7. on_restart
  8. on_anything
  9. chan_ended
  10. main

   1 /*****************************************************************************
   2  * priserver.c Refactoring of pritest.c
   3  *
   4  * Author(s):   Anthony Minessale II <anthm@freeswitch.org>
   5  *              Nenad Corbic <ncorbic@sangoma.com>
   6  *
   7  * Copyright:   (c) 2005 Anthony Minessale II
   8  *
   9  *      This program is free software; you can redistribute it and/or
  10  *      modify it under the terms of the GNU General Public License
  11  *      as published by the Free Software Foundation; either version
  12  *      2 of the License, or (at your option) any later version.
  13  * ============================================================================
  14  */
  15 
  16 #include "freetdm.h"
  17 #include <sangoma_pri.h>
  18 #include <signal.h>
  19 #include <sys/types.h>
  20 #include <sys/time.h>
  21 #include <sys/resource.h>
  22 #include <sys/wait.h>
  23 
  24 typedef struct {
  25         int pid;
  26         q931_call call;
  27         void *pri;
  28         int ready;
  29 }call_info_t;
  30 
  31 
  32 #define SANGOMA_MAX_CHAN_PER_SPAN 32
  33 
  34 static call_info_t pidmap[SANGOMA_MAX_CHAN_PER_SPAN];
  35 
  36 FIO_EVENT_CB_FUNCTION(my_ftdm_event_handler)
  37 {
  38         if (event->e_type = FTDM_EVENT_DTMF) {
  39                 char *dtmf = event->data;
  40                 printf("DTMF %s\n", dtmf);
  41         }
  42 }
  43 
  44 /* Stupid runtime process to play a file to a b channel*/
  45 #define BYTES 320
  46 #define MAX_BYTES 1000
  47 
  48 static int ready = 1;
  49 
  50 static void handle_SIGINT(int sig)
  51 {
  52         if (sig) {
  53                 ready = 0;
  54         }
  55 
  56         return;
  57 }
  58 
  59 static void launch_channel(struct sangoma_pri *spri, int channo)
  60 {
  61         pid_t pid;
  62         int fd = 0, file = 0, inlen = 0, outlen = 0;
  63         unsigned char inframe[MAX_BYTES], outframe[MAX_BYTES];
  64         fd_set readfds;
  65         int mtu_mru=BYTES / 2;
  66         int err;
  67         ftdm_channel_t *chan;
  68         ftdm_codec_t codec = FTDM_CODEC_SLIN;
  69         unsigned ms = 20;
  70         unsigned int lead = 50;
  71         int ifd = -1;
  72         ftdm_tone_type_t tt = FTDM_TONE_DTMF;
  73         char dtmf[] = "1234567890";
  74         int loops = 0;
  75 
  76         pid = fork();
  77         
  78         if (pid) {
  79                 pidmap[channo-1].pid = pid;
  80                 printf("-- Launching process %d to handle channel %d\n", pid, channo);
  81                 return;
  82         }
  83 
  84         signal(SIGINT, handle_SIGINT);
  85 
  86         //ifd = open("/nfs/sounds/ptest.raw", O_WRONLY|O_CREAT|O_TRUNC, 777);
  87         
  88         memset(inframe, 0, MAX_BYTES);
  89         memset(outframe, 0, MAX_BYTES);
  90                 
  91         if (ftdm_channel_open(spri->span, channo, &chan) != FTDM_SUCCESS) {
  92                 printf("DEBUG cant open fd!\n");
  93         }
  94         
  95 
  96 
  97 #if 1
  98         if (ftdm_channel_command(chan, FTDM_COMMAND_SET_CODEC, &codec) != FTDM_SUCCESS) {
  99                 printf("Critical Error: Failed to set driver codec!\n");
 100                 ftdm_channel_close(&chan);
 101                 exit(-1);
 102         }
 103 #endif
 104         
 105 #if 1
 106         if (ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_DTMF_DETECT, &tt) != FTDM_SUCCESS) {
 107                 printf("Critical Error: Failed to set dtmf detect!\n");
 108                 ftdm_channel_close(&chan);
 109                 exit(-1);
 110         }
 111         ftdm_channel_set_event_callback(chan, my_ftdm_event_handler);
 112 #endif
 113 
 114 
 115         if (ftdm_channel_command(chan, FTDM_COMMAND_SET_INTERVAL, &ms) != FTDM_SUCCESS) {
 116                 printf("Critical Error: Failed to set codec interval!\n");
 117                 ftdm_channel_close(&chan);
 118                 exit(-1);
 119         }
 120                 
 121         file = open("sound.raw", O_RDONLY);
 122         if (file < 0){
 123                 printf("Critical Error: Failed to open sound file!\n");
 124                 ftdm_channel_close(&chan);
 125                 exit(-1);
 126         }
 127 
 128 
 129         while(ready) {
 130                 ftdm_wait_flag_t flags = FTDM_READ;
 131                 ftdm_size_t len;
 132                 loops++;
 133 
 134                 if (lead) {
 135                         lead--;
 136                 }
 137 
 138                 if (!lead && loops == 300) {
 139 #if 1
 140                         if (ftdm_channel_command(chan, FTDM_COMMAND_SEND_DTMF, dtmf) != FTDM_SUCCESS) {
 141                                 printf("Critical Error: Failed to send dtmf\n");
 142                                 ftdm_channel_close(&chan);
 143                                 exit(-1);
 144                         }
 145 #endif
 146 
 147                 }
 148 
 149                 if (ftdm_channel_wait(chan, &flags, 2000) != FTDM_SUCCESS) {
 150                         printf("wait FAIL! [%s]\n", chan->last_error);
 151                         break;
 152                 }
 153         
 154                 if (flags & FTDM_READ) {
 155                         len = MAX_BYTES;
 156                         if (ftdm_channel_read(chan, inframe, &len) == FTDM_SUCCESS) {
 157                                 //printf("READ: %d\n", len);
 158                                 //write(ifd, inframe, len);
 159                                 if(!lead && (outlen = read(file, outframe, len)) <= 0) {
 160                                         break;
 161                                 }
 162 
 163                         } else {
 164                                 printf("READ FAIL! %d [%s]\n", len, chan->last_error);
 165                                 break;
 166                         }
 167                         if (lead) {
 168                                 continue;
 169                         } 
 170                         ftdm_channel_write(chan, outframe, sizeof(outframe), &len);
 171                 } else {
 172                         printf("BREAK");
 173                         break;
 174                 }
 175         }
 176 
 177         printf("loop done\n");
 178 
 179         //sangoma_get_full_cfg(fd, &tdm_api);
 180         close(file);
 181         //close(ifd);
 182 
 183         pri_hangup(spri->pri, channo, 16);
 184         if (ftdm_channel_close(&chan) != FTDM_SUCCESS) {
 185                 printf("Critical Error: Failed to close channel [%s]\n", chan->last_error);
 186         }
 187 
 188         printf("Call Handler: Process Finished\n");
 189         exit(0);
 190 }
 191 
 192 
 193 /* Event Handlers */
 194 
 195 static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) 
 196 {
 197         printf( "number is: %s\n", event->ring.callednum);
 198         if(strlen(event->ring.callednum) > 3) {
 199                 printf( "final number is: %s\n", event->ring.callednum);
 200                 pri_answer(spri->pri, event->ring.call, 0, 1);
 201         }
 202         return 0;
 203 }
 204 
 205 static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) 
 206 {
 207         //pri_hangup(spri->pri, event->hangup.call, event->hangup.cause);
 208         printf("-- Hanging up channel %d\n", event->hangup.channel);
 209         if(pidmap[event->hangup.channel-1].pid) {
 210                 pri_hangup(spri->pri, event->hangup.call, 16);
 211                 pri_destroycall(spri->pri, event->hangup.call);
 212                 kill(pidmap[event->hangup.channel-1].pid, SIGINT);
 213                 pidmap[event->hangup.channel-1].pid = 0;
 214         }
 215         return 0;
 216 }
 217 
 218 static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) 
 219 {
 220         printf("-- Ring on channel %d (from %s to %s), answering...\n", event->ring.channel, event->ring.callingnum, event->ring.callednum);
 221         pri_answer(spri->pri, event->ring.call, event->ring.channel, 1);
 222         memcpy(&pidmap[event->ring.channel-1].call, event->ring.call, sizeof(q931_call));
 223         pidmap[event->ring.channel-1].pri=spri->pri;
 224         pidmap[event->ring.channel-1].call = *event->ring.call;
 225         launch_channel(spri, event->ring.channel);
 226         return 0;
 227 }
 228 
 229 static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
 230 {
 231         printf("-- Restarting channel %d\n", event->restart.channel);
 232         return 0;
 233 }
 234 
 235 static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) 
 236 {
 237         printf("%s: Caught Event %d (%s)\n", __FUNCTION__, event_type, sangoma_pri_event_str(event_type));
 238         return 0;
 239 }
 240 
 241 /* Generic Reaper */
 242 static void chan_ended(int sig)
 243 {
 244         int status;
 245         int x;
 246         struct rusage rusage;
 247         pid_t pid;
 248         pid = wait4(-1, &status, WNOHANG, &rusage);
 249 
 250         printf("-- PID %d ended\n", pid);
 251 
 252         for (x=0;x<SANGOMA_MAX_CHAN_PER_SPAN;x++) {
 253                 if (pid == pidmap[x].pid) {
 254                         pidmap[x].pid = 0;
 255                         if (pidmap[x].pri){
 256                                 int err=pri_hangup(pidmap[x].pri, &pidmap[x].call, 16);
 257                                 //pri_destroycall(pidmap[x].pri, &pidmap[x].call);
 258                                 printf("Hanging up on PID %i Err=%i\n",pid,err);
 259                         }
 260 
 261                         pidmap[x].pri=NULL;
 262                         signal(SIGCHLD, chan_ended);
 263                         return;
 264                 }
 265         }
 266 
 267         if (pid > -1) {
 268                 fprintf(stderr, "--!! Unknown PID %d exited\n", pid);
 269                 signal(SIGCHLD, chan_ended);
 270                 return;
 271         }
 272 }
 273 
 274 /* Our Program */
 275 int main(int argc, char *argv[])
 276 {
 277         struct sangoma_pri spri;
 278         int debug = 0;
 279         if (argv[1]) {
 280                 debug = atoi(argv[1]);
 281         }
 282 
 283         ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG);
 284         if (ftdm_global_init() != FTDM_SUCCESS) {
 285         fprintf(stderr, "Error loading FreeTDM\n");
 286         exit(-1);
 287     }
 288 
 289     printf("FreeTDM loaded\n");
 290 
 291 
 292         debug = PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE;
 293         printf("WTF %d\n", debug);
 294 
 295         if (sangoma_init_pri(&spri,
 296                                                  1,  // span
 297                                                  24, // dchan
 298                                                  SANGOMA_PRI_SWITCH_DMS100,
 299                                                  SANGOMA_PRI_CPE,
 300                                                  debug) < 0) {
 301                 return -1;
 302         }
 303         //spri.pri->debug = (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE);
 304 
 305         //pri_set_debug(&spri.pri, (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE));
 306 
 307         SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_ANY, on_anything);
 308         SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_RING, on_ring);
 309         SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_HANGUP, on_hangup);
 310         SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_HANGUP_REQ, on_hangup);
 311         SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_INFO_RECEIVED, on_info);
 312         SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_RESTART, on_restart);
 313 
 314         signal(SIGCHLD, chan_ended);
 315         sangoma_run_pri(&spri);
 316         return 0;
 317 }
 318 
 319 /* For Emacs:
 320  * Local Variables:
 321  * mode:c
 322  * indent-tabs-mode:t
 323  * tab-width:4
 324  * c-basic-offset:4
 325  * End:
 326  * For VIM:
 327  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
 328  */

/* [<][>][^][v][top][bottom][index][help] */