From fa05585f1a55255ec937ed2cb3eb52743613b972 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 9 Dec 2010 12:48:33 -0200 Subject: [PATCH 001/179] freetdm: ftmod_zt - created zt_channel_next_event() to poll for events on a single channel --- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 102 +++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index 9247edc72e..9a6597c892 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -177,6 +177,7 @@ static ftdm_socket_t CONTROL_FD = ZT_INVALID_SOCKET; FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event); FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event); +FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event); /** * \brief Initialises codec, and rx/tx gains @@ -981,6 +982,107 @@ FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event) return k ? FTDM_SUCCESS : FTDM_FAIL; } +/** + * \brief Retrieves an event from a ftdmtel span + * \param ftdmchan Channel to retrieve event from + * \param event FreeTDM event to return + * \return Success or failure + */ +FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event) +{ + uint32_t i, event_id = FTDM_OOB_INVALID; + zt_event_t zt_event_id = 0; + ftdm_span_t *span = ftdmchan->span; + + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) { + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); + if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) { + snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); + return FTDM_FAIL; + } + + switch(zt_event_id) { + case ZT_EVENT_RINGEROFF: + { + return FTDM_FAIL; + } + break; + case ZT_EVENT_RINGERON: + { + return FTDM_FAIL; + } + break; + case ZT_EVENT_RINGBEGIN: + { + event_id = FTDM_OOB_RING_START; + } + break; + case ZT_EVENT_ONHOOK: + { + event_id = FTDM_OOB_ONHOOK; + } + break; + case ZT_EVENT_WINKFLASH: + { + if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN || ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { + event_id = FTDM_OOB_WINK; + } else { + event_id = FTDM_OOB_FLASH; + } + } + break; + case ZT_EVENT_RINGOFFHOOK: + { + if (ftdmchan->type == FTDM_CHAN_TYPE_FXS || (ftdmchan->type == FTDM_CHAN_TYPE_EM && ftdmchan->state != FTDM_CHANNEL_STATE_UP)) { + ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); + event_id = FTDM_OOB_OFFHOOK; + } else if (ftdmchan->type == FTDM_CHAN_TYPE_FXO) { + event_id = FTDM_OOB_RING_START; + } else { + event_id = FTDM_OOB_NOOP; + } + } + break; + case ZT_EVENT_ALARM: + { + event_id = FTDM_OOB_ALARM_TRAP; + } + break; + case ZT_EVENT_NOALARM: + { + event_id = FTDM_OOB_ALARM_CLEAR; + } + break; + case ZT_EVENT_BITSCHANGED: + { + event_id = FTDM_OOB_CAS_BITS_CHANGE; + int bits = 0; + int err = ioctl(ftdmchan->sockfd, codes.GETRXBITS, &bits); + if (err) { + return FTDM_FAIL; + } + ftdmchan->rx_cas_bits = bits; + } + break; + default: + { + ftdm_log(FTDM_LOG_WARNING, "Unhandled event %d for %d:%d\n", zt_event_id, span->span_id, i); + event_id = FTDM_OOB_INVALID; + } + break; + } + + ftdmchan->last_event_time = 0; + span->event_header.e_type = FTDM_EVENT_OOB; + span->event_header.enum_id = event_id; + span->event_header.channel = ftdmchan; + *event = &span->event_header; + return FTDM_SUCCESS; + } + + return FTDM_FAIL; +} + /** * \brief Retrieves an event from a ftdmtel span * \param span Span to retrieve event from From 36a84423e7c788a73348420ebcd9dcee95d34fd3 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 9 Dec 2010 12:52:32 -0200 Subject: [PATCH 002/179] freetdm: ftmod_zt - fixed typo on documentation --- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index 9a6597c892..e1d664092a 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -983,7 +983,7 @@ FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event) } /** - * \brief Retrieves an event from a ftdmtel span + * \brief Retrieves an event from a ftdm channel * \param ftdmchan Channel to retrieve event from * \param event FreeTDM event to return * \return Success or failure From eafd7e5e15b2a5b6b28d75e107a1490e60e64563 Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Tue, 14 Dec 2010 16:55:31 -0600 Subject: [PATCH 003/179] skypopen: tweaking the OSS audio driver --- src/mod/endpoints/mod_skypopen/oss/Makefile | 6 +- src/mod/endpoints/mod_skypopen/oss/main.c | 190 +++++++++--------- .../mod_skypopen/oss/{scull.h => skypopen.h} | 40 ++-- 3 files changed, 110 insertions(+), 126 deletions(-) rename src/mod/endpoints/mod_skypopen/oss/{scull.h => skypopen.h} (55%) diff --git a/src/mod/endpoints/mod_skypopen/oss/Makefile b/src/mod/endpoints/mod_skypopen/oss/Makefile index 465db533e4..8df20f68c5 100644 --- a/src/mod/endpoints/mod_skypopen/oss/Makefile +++ b/src/mod/endpoints/mod_skypopen/oss/Makefile @@ -4,7 +4,7 @@ # Add your debugging flag (or not) to CFLAGS ifeq ($(DEBUG),y) - DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines + DEBFLAGS = -O -g -DSKYPOPEN_DEBUG # "-O" is needed to expand inlines else DEBFLAGS = -O2 -Wall endif @@ -15,9 +15,9 @@ EXTRA_CFLAGS += -I$(LDDINC) ifneq ($(KERNELRELEASE),) # call from kernel build system -scull-objs := main.o +skypopen-objs := main.o -obj-m := scull.o +obj-m := skypopen.o else diff --git a/src/mod/endpoints/mod_skypopen/oss/main.c b/src/mod/endpoints/mod_skypopen/oss/main.c index 8da9c549ac..4fd959f44a 100644 --- a/src/mod/endpoints/mod_skypopen/oss/main.c +++ b/src/mod/endpoints/mod_skypopen/oss/main.c @@ -1,5 +1,5 @@ /* - * main.c -- the bare scull char module + * main.c -- the bare skypopen char module * * Copyright (C) 2010 Giovanni Maruzzelli * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet @@ -41,33 +41,32 @@ #include #include -#include "scull.h" /* local definitions */ +#include "skypopen.h" /* local definitions */ /* * Our parameters which can be set at load time. */ -int scull_major = SCULL_MAJOR; -int scull_minor = 3; -int scull_nr_devs = SCULL_NR_DEVS; /* number of bare scull devices */ +int skypopen_major = SKYPOPEN_MAJOR; +int skypopen_minor = 3; +int skypopen_nr_devs = SKYPOPEN_NR_DEVS; /* number of bare skypopen devices */ -module_param(scull_major, int, S_IRUGO); -module_param(scull_minor, int, S_IRUGO); -module_param(scull_nr_devs, int, S_IRUGO); +module_param(skypopen_major, int, S_IRUGO); +module_param(skypopen_minor, int, S_IRUGO); +module_param(skypopen_nr_devs, int, S_IRUGO); -MODULE_AUTHOR("Original: Alessandro Rubini, Jonathan Corbet. Heavy modified by: Giovanni Maruzzelli"); +MODULE_AUTHOR("Original: Alessandro Rubini, Jonathan Corbet. Modified by: Giovanni Maruzzelli for FreeSWITCH skypopen"); MODULE_LICENSE("Dual BSD/GPL"); -static struct scull_dev *scull_devices; /* allocated in scull_init_module */ +static struct skypopen_dev *skypopen_devices; /* allocated in skypopen_init_module */ #define GIOVA_BLK 1920 #define GIOVA_SLEEP 20 void my_timer_callback_inq( unsigned long data ) { - struct scull_dev *dev = (void *)data; + struct skypopen_dev *dev = (void *)data; - //dev->readable=1; wake_up_interruptible(&dev->inq); mod_timer( &dev->timer_inq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); @@ -75,83 +74,83 @@ void my_timer_callback_inq( unsigned long data ) void my_timer_callback_outq( unsigned long data ) { - struct scull_dev *dev = (void *)data; + struct skypopen_dev *dev = (void *)data; - //dev->writable=1; wake_up_interruptible(&dev->outq); mod_timer( &dev->timer_outq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); } /* The clone-specific data structure includes a key field */ -struct scull_listitem { - struct scull_dev device; +struct skypopen_listitem { + struct skypopen_dev device; dev_t key; struct list_head list; }; /* The list of devices, and a lock to protect it */ -static LIST_HEAD(scull_c_list); -static spinlock_t scull_c_lock = SPIN_LOCK_UNLOCKED; +static LIST_HEAD(skypopen_c_list); +static spinlock_t skypopen_c_lock = SPIN_LOCK_UNLOCKED; /* Look for a device or create one if missing */ -static struct scull_dev *scull_c_lookfor_device(dev_t key) +static struct skypopen_dev *skypopen_c_lookfor_device(dev_t key) { - struct scull_listitem *lptr; + struct skypopen_listitem *lptr; - list_for_each_entry(lptr, &scull_c_list, list) { + list_for_each_entry(lptr, &skypopen_c_list, list) { if (lptr->key == key) return &(lptr->device); } /* not found */ - lptr = kmalloc(sizeof(struct scull_listitem), GFP_KERNEL); + lptr = kmalloc(sizeof(struct skypopen_listitem), GFP_KERNEL); if (!lptr) return NULL; /* initialize the device */ - memset(lptr, 0, sizeof(struct scull_listitem)); + memset(lptr, 0, sizeof(struct skypopen_listitem)); lptr->key = key; - init_waitqueue_head(&lptr->device.inq); - init_waitqueue_head(&lptr->device.outq); - printk(" Timer installing\n"); - setup_timer( &lptr->device.timer_inq, my_timer_callback_inq, (long int)lptr ); - setup_timer( &lptr->device.timer_outq, my_timer_callback_outq, (long int)lptr ); - printk( "Starting timer to fire in %dms (%ld)\n", GIOVA_SLEEP, jiffies ); - mod_timer( &lptr->device.timer_inq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); - mod_timer( &lptr->device.timer_outq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); + init_waitqueue_head(&lptr->device.inq); + init_waitqueue_head(&lptr->device.outq); + setup_timer( &lptr->device.timer_inq, my_timer_callback_inq, (long int)lptr ); + setup_timer( &lptr->device.timer_outq, my_timer_callback_outq, (long int)lptr ); + printk( "Starting skypopen OSS driver read timer (%dms) skype client:(%d)\n", GIOVA_SLEEP, current->tgid ); + mod_timer( &lptr->device.timer_inq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); + printk( "Starting skypopen OSS driver write timer (%dms) skype client:(%d)\n", GIOVA_SLEEP, current->tgid ); + mod_timer( &lptr->device.timer_outq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); + /* place it in the list */ - list_add(&lptr->list, &scull_c_list); + list_add(&lptr->list, &skypopen_c_list); return &(lptr->device); } -static int scull_c_open(struct inode *inode, struct file *filp) + +/* + * Open and close + */ +static int skypopen_c_open(struct inode *inode, struct file *filp) { - struct scull_dev *dev; + struct skypopen_dev *dev; dev_t key; - if (!current->pid) { - printk("Process \"%s\" has no pid\n", current->comm); - return -EINVAL; - } key = current->pid; - /* look for a scullc device in the list */ - spin_lock(&scull_c_lock); - dev = scull_c_lookfor_device(key); - spin_unlock(&scull_c_lock); + /* look for a skypopenc device in the list */ + spin_lock(&skypopen_c_lock); + dev = skypopen_c_lookfor_device(key); + spin_unlock(&skypopen_c_lock); if (!dev) return -ENOMEM; - /* then, everything else is copied from the bare scull device */ + /* then, everything else is copied from the bare skypopen device */ filp->private_data = dev; return 0; /* success */ } -static int scull_c_release(struct inode *inode, struct file *filp) +static int skypopen_c_release(struct inode *inode, struct file *filp) { /* * Nothing to do, because the device is persistent. @@ -163,39 +162,29 @@ static int scull_c_release(struct inode *inode, struct file *filp) /*************************************************************/ -/* - * Open and close - */ -ssize_t scull_read(struct file *filp, char __user *buf, size_t count, +ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { - struct scull_dev *dev = filp->private_data; - + struct skypopen_dev *dev = filp->private_data; DEFINE_WAIT(wait); + prepare_to_wait(&dev->inq, &wait, TASK_INTERRUPTIBLE); schedule(); finish_wait(&dev->inq, &wait); - //memset(buf, 255, count); - - //wait_event_interruptible(dev->inq, dev->readable); - //dev->readable=0; return count; } -ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, +ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { - struct scull_dev *dev = filp->private_data; + struct skypopen_dev *dev = filp->private_data; DEFINE_WAIT(wait); + prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE); schedule(); finish_wait(&dev->outq, &wait); - - //wait_event_interruptible(dev->outq, dev->writable); - //dev->writable=0; - return count; } @@ -203,7 +192,7 @@ ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, * The ioctl() implementation */ -int scull_ioctl(struct inode *inode, struct file *filp, +int skypopen_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; @@ -223,14 +212,14 @@ int scull_ioctl(struct inode *inode, struct file *filp, } -struct file_operations scull_fops = { +struct file_operations skypopen_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .read = scull_read, - .write = scull_write, - .ioctl = scull_ioctl, - .open = scull_c_open, - .release = scull_c_release, + .read = skypopen_read, + .write = skypopen_write, + .ioctl = skypopen_ioctl, + .open = skypopen_c_open, + .release = skypopen_c_release, }; /* @@ -243,34 +232,34 @@ struct file_operations scull_fops = { * have not been initialized */ -void scull_cleanup_module(void) +void skypopen_cleanup_module(void) { int i; int ret; - struct scull_listitem *lptr, *next; - dev_t devno = MKDEV(scull_major, scull_minor); + struct skypopen_listitem *lptr, *next; + dev_t devno = MKDEV(skypopen_major, skypopen_minor); /* Get rid of our char dev entries */ - if (scull_devices) { - for (i = 0; i < scull_nr_devs; i++) { - cdev_del(&scull_devices[i].cdev); + if (skypopen_devices) { + for (i = 0; i < skypopen_nr_devs; i++) { + cdev_del(&skypopen_devices[i].cdev); } - kfree(scull_devices); + kfree(skypopen_devices); } /* And all the cloned devices */ - list_for_each_entry_safe(lptr, next, &scull_c_list, list) { + list_for_each_entry_safe(lptr, next, &skypopen_c_list, list) { ret= del_timer( &lptr->device.timer_inq ); - if (ret) printk("The inq timer was still in use...\n"); + //printk( "Stopped skypopen OSS driver read timer (%dms) skype client:(%d)\n", GIOVA_SLEEP, current->tgid ); ret= del_timer( &lptr->device.timer_outq ); - if (ret) printk("The outq timer was still in use...\n"); + //printk( "Stopped skypopen OSS driver write timer (%dms) skype client:(%d)\n", GIOVA_SLEEP, current->tgid ); list_del(&lptr->list); kfree(lptr); } - printk("Timer uninstalling\n"); /* cleanup_module is never called if registering failed */ - unregister_chrdev_region(devno, scull_nr_devs); + unregister_chrdev_region(devno, skypopen_nr_devs); + printk("skypopen OSS driver unloaded\n"); } @@ -278,40 +267,41 @@ void scull_cleanup_module(void) /* * Set up the char_dev structure for this device. */ -static void scull_setup_cdev(struct scull_dev *dev, int index) +static void skypopen_setup_cdev(struct skypopen_dev *dev, int index) { - int err, devno = MKDEV(scull_major, scull_minor + index); + int err, devno = MKDEV(skypopen_major, skypopen_minor + index); - cdev_init(&dev->cdev, &scull_fops); + cdev_init(&dev->cdev, &skypopen_fops); dev->cdev.owner = THIS_MODULE; - dev->cdev.ops = &scull_fops; + dev->cdev.ops = &skypopen_fops; err = cdev_add (&dev->cdev, devno, 1); /* Fail gracefully if need be */ if (err) - printk(KERN_NOTICE "Error %d adding scull%d", err, index); + printk(KERN_NOTICE "Error %d adding skypopen%d", err, index); } -int scull_init_module(void) +int skypopen_init_module(void) { int result, i; dev_t dev = 0; + printk("skypopen OSS driver loading (www.freeswitch.org)\n"); /* * Get a range of minor numbers to work with, asking for a dynamic * major unless directed otherwise at load time. */ - if (scull_major) { - dev = MKDEV(scull_major, scull_minor); - result = register_chrdev_region(dev, scull_nr_devs, "dsp"); + if (skypopen_major) { + dev = MKDEV(skypopen_major, skypopen_minor); + result = register_chrdev_region(dev, skypopen_nr_devs, "dsp"); } else { - result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, + result = alloc_chrdev_region(&dev, skypopen_minor, skypopen_nr_devs, "dsp"); - scull_major = MAJOR(dev); + skypopen_major = MAJOR(dev); } if (result < 0) { - printk(KERN_WARNING "scull: can't get major %d\n", scull_major); + printk(KERN_WARNING "skypopen OSS driver: can't get major %d\n", skypopen_major); return result; } @@ -319,26 +309,26 @@ int scull_init_module(void) * allocate the devices -- we can't have them static, as the number * can be specified at load time */ - scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL); - if (!scull_devices) { + skypopen_devices = kmalloc(skypopen_nr_devs * sizeof(struct skypopen_dev), GFP_KERNEL); + if (!skypopen_devices) { result = -ENOMEM; goto fail; /* Make this more graceful */ } - memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev)); + memset(skypopen_devices, 0, skypopen_nr_devs * sizeof(struct skypopen_dev)); /* Initialize each device. */ - for (i = 0; i < scull_nr_devs; i++) { - scull_setup_cdev(&scull_devices[i], i); + for (i = 0; i < skypopen_nr_devs; i++) { + skypopen_setup_cdev(&skypopen_devices[i], i); } /* At this point call the init function for any friend device */ - dev = MKDEV(scull_major, scull_minor + scull_nr_devs); + dev = MKDEV(skypopen_major, skypopen_minor + skypopen_nr_devs); return 0; /* succeed */ fail: - scull_cleanup_module(); + skypopen_cleanup_module(); return result; } -module_init(scull_init_module); -module_exit(scull_cleanup_module); +module_init(skypopen_init_module); +module_exit(skypopen_cleanup_module); diff --git a/src/mod/endpoints/mod_skypopen/oss/scull.h b/src/mod/endpoints/mod_skypopen/oss/skypopen.h similarity index 55% rename from src/mod/endpoints/mod_skypopen/oss/scull.h rename to src/mod/endpoints/mod_skypopen/oss/skypopen.h index 565b8b38b7..5469048c04 100644 --- a/src/mod/endpoints/mod_skypopen/oss/scull.h +++ b/src/mod/endpoints/mod_skypopen/oss/skypopen.h @@ -1,5 +1,5 @@ /* - * scull.h -- definitions for the char module + * skypopen.h -- definitions for the char module * * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly & Associates @@ -12,55 +12,49 @@ * by O'Reilly & Associates. No warranty is attached; * we cannot take responsibility for errors or fitness for use. * - * $Id: scull.h,v 1.15 2004/11/04 17:51:18 rubini Exp $ + * $Id: skypopen.h,v 1.15 2004/11/04 17:51:18 rubini Exp $ */ -#ifndef _SCULL_H_ -#define _SCULL_H_ +#ifndef _SKYPOPEN_H_ +#define _SKYPOPEN_H_ #include /* needed for the _IOW etc stuff used later */ -#ifndef SCULL_MAJOR -#define SCULL_MAJOR 14 /* dynamic major by default */ +#ifndef SKYPOPEN_MAJOR +#define SKYPOPEN_MAJOR 14 /* dynamic major by default */ #endif -#ifndef SCULL_NR_DEVS -#define SCULL_NR_DEVS 1 /* scull0 through scull3 */ +#ifndef SKYPOPEN_NR_DEVS +#define SKYPOPEN_NR_DEVS 1 /* skypopen0 through skypopen3 */ #endif -struct scull_dev { +struct skypopen_dev { struct cdev cdev; /* Char device structure */ wait_queue_head_t inq; /* read and write queues */ wait_queue_head_t outq; /* read and write queues */ struct timer_list timer_inq; struct timer_list timer_outq; - int readable; - int writable; - //unsigned long read_howmany; - //unsigned long write_howmany; - //unsigned long read_sleeped_acc; - //unsigned long write_sleeped_acc; - //double read_delay; /* how much delay last time */ - //double write_delay; /* how much delay last time */ + int timer_inq_started; + int timer_outq_started; }; /* * The different configurable parameters */ -extern int scull_major; /* main.c */ -extern int scull_nr_devs; +extern int skypopen_major; /* main.c */ +extern int skypopen_nr_devs; /* * Prototypes for shared functions */ -ssize_t scull_read(struct file *filp, char __user *buf, size_t count, +ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); -ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, +ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); -int scull_ioctl(struct inode *inode, struct file *filp, +int skypopen_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -#endif /* _SCULL_H_ */ +#endif /* _SKYPOPEN_H_ */ From 2324c299177be42375610c4928a3b77e60a8bf10 Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 14 Dec 2010 22:29:25 -0600 Subject: [PATCH 004/179] round two better code thanks mikej --- src/mod/endpoints/mod_sofia/sofia.c | 51 +++++++++++++++-------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index f2a555e946..7e4e34f4ab 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -6255,7 +6255,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (!is_nat && profile->nat_acl_count) { uint32_t x = 0; - int ok = 1; + int contact_private_ip = 1; + int network_private_ip = 0; char *last_acl = NULL; const char *contact_host = NULL; @@ -6264,35 +6265,37 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } if (!zstr(contact_host)) { + /* NAT mode double check logic and examples. + + Example 1: the contact_host is 192.168.1.100 and the network_ip is also 192.168.1.100 the end point + is most likely behind nat with us so we need to veto that decision to turn on nat processing. + + Example 2: the contact_host is 192.168.1.100 and the network_ip is 192.0.2.100 which is a public internet ip + the remote endpoint is likely behind a remote nat traversing the public internet. + + This secondary check is here to double check the conclusion of nat settigs to ensure we don't set net + in cases where we don't really need to be doing this. + + Why would you want to do this? Well if your FreeSWITCH is behind nat and you want to talk to endpoints behind + remote NAT over the public internet in addition to endpoints behind nat with you. This simplifies that process. + + */ + for (x = 0; x < profile->nat_acl_count; x++) { last_acl = profile->nat_acl[x]; - if (!(ok = switch_check_network_list_ip(contact_host, last_acl))) { - /* NAT mode double check logic and examples. - - Example 1: the contact_host is 192.168.1.100 and the network_ip is also 192.168.1.100 the end point - is most likely behind nat with us so we need to veto that decision to turn on nat processing. - - Example 2: the contact_host is 192.168.1.100 and the network_ip is 192.0.2.100 which is a public internet ip - the remote endpoint is likely behind a remote nat traversing the public internet. - - This secondary check is here to double check the conclusion of nat settigs to ensure we don't set net - in cases where we don't really need to be doing this. - - Why would you want to do this? Well if your FreeSWITCH is behind nat and you want to talk to endpoints behind - remote NAT over the public internet in addition to endpoints behind nat with you. This simplifies that process. - - */ - if ((ok = switch_check_network_list_ip(network_ip, last_acl))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Endpoint is already inside nat with us.\n"); - ok = 0; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Decision stands they are behind nat.\n"); - } + if ((contact_private_ip = switch_check_network_list_ip(contact_host, last_acl))) { break; } } + if (contact_private_ip) { + for (x = 0; x < profile->nat_acl_count; x++) { + if ((network_private_ip = switch_check_network_list_ip(network_ip, profile->nat_acl[x]))) { + break; + } + } + } - if (ok) { + if (contact_private_ip && !network_private_ip) { is_nat = last_acl; } } From e9958c5b0c37b44ff4dd644245412a526ba6118f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 14 Dec 2010 23:46:26 -0600 Subject: [PATCH 005/179] more jb work, add debug command and logging (sorry jlenk if this breaks win32) --- src/include/switch_rtp.h | 2 ++ src/mod/endpoints/mod_sofia/mod_sofia.c | 11 +++++++ src/switch_ivr.c | 2 +- src/switch_rtp.c | 39 +++++++++++++++++++++---- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index e3e9f665a3..c48a40e6d1 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -234,6 +234,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t * uint32_t max_queue_frames, uint32_t samples_per_packet, uint32_t samples_per_second); +SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name); + SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session); /*! diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index d4f8b1b45a..4a3c7c0479 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1339,6 +1339,17 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi if (msg->string_arg) { char *p; + const char *s; + + if (!strncasecmp(msg->string_arg, "debug:", 6)) { + s = msg->string_arg + 6; + if (s && !strcmp(s, "off")) { + s = NULL; + } + switch_rtp_debug_jitter_buffer(tech_pvt->rtp_session, s); + goto end; + } + if ((len = atoi(msg->string_arg))) { qlen = len / (tech_pvt->read_impl.microseconds_per_packet / 1000); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 6e2aeaf637..5cd4d4d34f 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2300,7 +2300,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3 break; } - stfu_n_eat(jb, ts, 0, read_frame->payload, read_frame->data, read_frame->datalen); + stfu_n_eat(jb, ts, read_frame->payload, read_frame->data, read_frame->datalen); ts += interval; if ((jb_frame = stfu_n_read_a_frame(jb))) { diff --git a/src/switch_rtp.c b/src/switch_rtp.c index b4f60fcd55..306e58a839 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -229,7 +229,7 @@ struct switch_rtp { uint32_t sync_packets; int rtcp_interval; switch_bool_t rtcp_fresh_frame; - + uint8_t checked_jb; #ifdef ENABLE_ZRTP zrtp_session_t *zrtp_session; zrtp_profile_t *zrtp_profile; @@ -1652,6 +1652,32 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t return SWITCH_STATUS_SUCCESS; } +static void jb_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) +{ + int ret; + char *data; + va_list ap; + + va_start(ap, fmt); + ret = stfu_vasprintf(&data, fmt, ap); + if (ret != -1) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "%s", data); + free(data); + } + + //switch_log_printf(SWITCH_CHANNEL_ID_LOG_CLEAN, file, func, line, NULL, level, fmt, ap); + va_end(ap); +} + +SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name) +{ + + stfu_n_debug(rtp_session->jb, name); + stfu_global_set_logger(jb_logger); + + return SWITCH_STATUS_SUCCESS; +} + SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames, uint32_t max_queue_frames, @@ -1674,6 +1700,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t * if (rtp_session->jb) { switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session"); stfu_n_call_me(rtp_session->jb, jb_callback, session); + return SWITCH_STATUS_SUCCESS; } @@ -2108,9 +2135,8 @@ static void do_flush(switch_rtp_t *rtp_session) flushed++; - if (rtp_session->jb) { + if (0 && rtp_session->jb) { stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts), - ntohs((uint16_t) rtp_session->recv_msg.header.seq), rtp_session->recv_msg.header.pt, rtp_session->recv_msg.body, bytes - rtp_header_len); } @@ -2177,7 +2203,6 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t } stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts), - ntohs((uint16_t) rtp_session->recv_msg.header.seq), rtp_session->recv_msg.header.pt, rtp_session->recv_msg.body, *bytes - rtp_header_len); *bytes = 0; @@ -2195,9 +2220,9 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes = jb_frame->dlen + rtp_header_len; rtp_session->recv_msg.header.ts = htonl(jb_frame->ts); rtp_session->recv_msg.header.pt = jb_frame->pt; - rtp_session->recv_msg.header.seq = htons((uint16_t)jb_frame->seq); status = SWITCH_STATUS_SUCCESS; } + rtp_session->checked_jb++; } return status; @@ -2342,6 +2367,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ READ_INC(rtp_session); + rtp_session->checked_jb = 0; + while (switch_rtp_ready(rtp_session)) { int do_cng = 0; bytes = 0; @@ -2894,7 +2921,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (do_cng) { uint8_t *data = (uint8_t *) rtp_session->recv_msg.body; int fdr; - + if ((poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, 0)) == SWITCH_STATUS_SUCCESS) { goto recvfrom; } From c4154633cca4b5b9764e192770d08c04f71a6970 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Wed, 15 Dec 2010 09:43:36 -0500 Subject: [PATCH 006/179] FS-2929 --- src/mod/applications/mod_spy/mod_spy.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/mod/applications/mod_spy/mod_spy.c b/src/mod/applications/mod_spy/mod_spy.c index 5093ad8f22..cb8981d264 100644 --- a/src/mod/applications/mod_spy/mod_spy.c +++ b/src/mod/applications/mod_spy/mod_spy.c @@ -131,7 +131,6 @@ SWITCH_STANDARD_API(dump_hash) static switch_status_t process_event(switch_event_t *event) { switch_core_session_t *session = NULL; - switch_channel_t *channel; char *username[3] = { 0 }; char *domain[3] = { 0 }; char key[512]; @@ -172,18 +171,19 @@ static switch_status_t process_event(switch_event_t *event) return SWITCH_STATUS_FALSE; } - session = switch_core_session_locate(uuid); - channel = switch_core_session_get_channel(session); + if ((session = switch_core_session_locate(uuid))) { + switch_channel_t *channel = switch_core_session_get_channel(session); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key); - my_uuid = switch_event_get_header(event, "Unique-ID"); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key); + my_uuid = switch_event_get_header(event, "Unique-ID"); - switch_channel_set_variable(channel, "spy_uuid", my_uuid); + switch_channel_set_variable(channel, "spy_uuid", my_uuid); - switch_channel_set_state(channel, CS_EXCHANGE_MEDIA); - switch_channel_set_flag(channel, CF_BREAK); + switch_channel_set_state(channel, CS_EXCHANGE_MEDIA); + switch_channel_set_flag(channel, CF_BREAK); - switch_core_session_rwunlock(session); + switch_core_session_rwunlock(session); + } return SWITCH_STATUS_SUCCESS; } From 5fd5ee0d4889440f443446994dc74be157f78653 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 15 Dec 2010 09:39:42 -0600 Subject: [PATCH 007/179] doh --- libs/stfu/stfu.c | 604 ++++++++++++++++++++++++++++++++--------------- libs/stfu/stfu.h | 90 ++++++- 2 files changed, 499 insertions(+), 195 deletions(-) diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 547c337278..72459caad9 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -33,11 +33,19 @@ # define UINT_MAX 4294967295U #endif +#ifndef UINT16_MAX +# define UINT16_MAX 65535 +#endif + #ifdef _MSC_VER /* warning C4706: assignment within conditional expression*/ #pragma warning(disable: 4706) #endif +#define least1(_z) (_z ? _z : 1) + +static int stfu_log_level = 7; + struct stfu_queue { struct stfu_frame *array; struct stfu_frame int_frame; @@ -53,13 +61,13 @@ typedef struct stfu_queue stfu_queue_t; struct stfu_instance { struct stfu_queue a_queue; struct stfu_queue b_queue; + struct stfu_queue c_queue; struct stfu_queue *in_queue; struct stfu_queue *out_queue; + struct stfu_queue *old_queue; struct stfu_frame *last_frame; uint32_t cur_ts; - uint32_t cur_seq; uint32_t last_wr_ts; - uint32_t last_wr_seq; uint32_t last_rd_ts; uint32_t samples_per_packet; uint32_t samples_per_second; @@ -76,6 +84,7 @@ struct stfu_instance { uint32_t period_packet_in_count; uint32_t period_packet_out_count; uint32_t period_missing_count; + uint32_t period_need_range; uint32_t period_need_range_avg; uint32_t period_clean_count; @@ -86,25 +95,55 @@ struct stfu_instance { uint32_t session_packet_in_count; uint32_t session_packet_out_count; - uint32_t sync; + uint32_t sync_out; + uint32_t sync_in; int32_t ts_diff; int32_t last_ts_diff; int32_t same_ts; - uint32_t last_seq; - uint32_t period_time; uint32_t decrement_time; uint32_t plc_len; + uint32_t plc_pt; + uint32_t diff; + uint32_t diff_total; + uint8_t ready; + uint8_t debug; + char *name; stfu_n_call_me_t callback; void *udata; }; static void stfu_n_reset_counters(stfu_instance_t *i); +static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...); +static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...); + +stfu_logger_t stfu_log = null_logger; + +void stfu_global_set_logger(stfu_logger_t logger) +{ + if (logger) { + stfu_log = logger; + } else { + stfu_log = null_logger; + } +} + +void stfu_global_set_default_logger(int level) +{ + if (level < 0 || level > 7) { + level = 7; + } + + stfu_log = default_logger; + stfu_log_level = level; +} + + static stfu_status_t stfu_n_resize_aqueue(stfu_queue_t *queue, uint32_t qlen) { @@ -151,12 +190,27 @@ void stfu_n_destroy(stfu_instance_t **i) if (i && *i) { ii = *i; *i = NULL; + if (ii->name) free(ii->name); free(ii->a_queue.array); free(ii->b_queue.array); + free(ii->c_queue.array); free(ii); } } +void stfu_n_debug(stfu_instance_t *i, const char *name) +{ + if (i->name) free(i->name); + + if (name) { + i->name = strdup(name); + i->debug = 1; + } else { + i->name = strdup("none"); + i->debug = 0; + } +} + void stfu_n_report(stfu_instance_t *i, stfu_report_t *r) { assert(i); @@ -172,7 +226,6 @@ stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen) stfu_status_t s; if (i->qlen == i->max_qlen) { - printf("FUCKER1\n"); return STFU_IT_FAILED; } @@ -180,13 +233,14 @@ stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen) if (i->qlen < i->max_qlen) { qlen = i->max_qlen; } else { - printf("FUCKER2\n"); return STFU_IT_FAILED; } } if ((s = stfu_n_resize_aqueue(&i->a_queue, qlen)) == STFU_IT_WORKED) { s = stfu_n_resize_aqueue(&i->b_queue, qlen); + s = stfu_n_resize_aqueue(&i->c_queue, qlen); + i->qlen = qlen; i->max_plc = 5; i->last_frame = NULL; @@ -205,11 +259,6 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_ } memset(i, 0, sizeof(*i)); - -#ifdef DB_JB - printf("INIT %u %u\n", qlen, max_qlen); -#endif - i->qlen = qlen; i->max_qlen = max_qlen; i->orig_qlen = qlen; @@ -217,8 +266,12 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_ stfu_n_init_aqueue(&i->a_queue, qlen); stfu_n_init_aqueue(&i->b_queue, qlen); + stfu_n_init_aqueue(&i->c_queue, qlen); + i->in_queue = &i->a_queue; i->out_queue = &i->b_queue; + i->old_queue = &i->c_queue; + i->name = strdup("none"); i->max_plc = i->qlen / 2; @@ -232,9 +285,9 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_ static void stfu_n_reset_counters(stfu_instance_t *i) { -#ifdef DB_JB - printf("COUNTER RESET........\n"); -#endif + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s COUNTER RESET........\n", i->name); + } if (i->callback) { i->callback(i, i->udata); @@ -248,36 +301,44 @@ static void stfu_n_reset_counters(stfu_instance_t *i) i->period_packet_in_count = 0; i->period_packet_out_count = 0; i->period_missing_count = 0; + i->period_need_range = 0; i->period_need_range_avg = 0; + + i->diff = 0; + i->diff_total = 0; + } void stfu_n_reset(stfu_instance_t *i) { -#ifdef DB_JB - printf("RESET\n"); -#endif + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s RESET\n", i->name); + } + + i->ready = 0; i->in_queue = &i->a_queue; i->out_queue = &i->b_queue; + i->old_queue = &i->c_queue; + i->in_queue->array_len = 0; i->out_queue->array_len = 0; i->out_queue->wr_len = 0; i->last_frame = NULL; - i->in_queue->last_jitter = 0; i->out_queue->last_jitter = 0; + stfu_n_reset_counters(i); - - i->last_seq = 0; - + stfu_n_sync(i, 1); + i->cur_ts = 0; - i->cur_seq = 0; i->last_wr_ts = 0; - i->last_wr_seq = 0; i->last_rd_ts = 0; i->miss_count = 0; i->packet_count = 0; + + } stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets) @@ -286,20 +347,39 @@ stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets) if (packets > i->qlen) { stfu_n_reset(i); } else { - i->sync = packets; + i->sync_out = packets; + i->sync_in = packets; } return STFU_IT_WORKED; } -stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uint32_t pt, void *data, size_t datalen, int last) +static void stfu_n_swap(stfu_instance_t *i) +{ + stfu_queue_t *last_in = i->in_queue, *last_out = i->out_queue, *last_old = i->old_queue; + + i->ready = 1; + + i->in_queue = last_out; + i->out_queue = last_old; + i->old_queue = last_in; + + i->in_queue->array_len = 0; + i->out_queue->wr_len = 0; + i->last_frame = NULL; + i->miss_count = 0; + i->in_queue->last_index = 0; + i->out_queue->last_index = 0; + i->out_queue->last_jitter = 0; +} + +stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last) { uint32_t index = 0; stfu_frame_t *frame; size_t cplen = 0; - int good_seq = 0, good_ts = 0; - uint32_t min_seq = UINT_MAX, min_ts = UINT_MAX, min_index = 0; + int good_ts = 0; if (!i->samples_per_packet && ts && i->last_rd_ts) { i->ts_diff = ts - i->last_rd_ts; @@ -320,16 +400,27 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin } } - if ((seq && seq == i->last_seq + 1) || (i->last_seq > 65500 && seq == 0)) { - good_seq = 1; - } - - if ((ts && ts == i->last_rd_ts + i->samples_per_packet) || (i->last_rd_ts > 4294900000 && ts < 5000)) { + if (i->sync_in) { good_ts = 1; + i->sync_in = 0; + } else { + + if ((ts && ts == i->last_rd_ts + i->samples_per_packet) || (i->last_rd_ts > 4294900000 && ts < 5000)) { + good_ts = 1; + } + + if (i->last_wr_ts) { + if ((ts <= i->last_wr_ts && (i->last_wr_ts != UINT_MAX || ts == i->last_wr_ts))) { + stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts); + if (i->in_queue->array_len < i->in_queue->array_size) { + i->in_queue->array_len++; + } + return STFU_ITS_TOO_LATE; + } + } } - - if (good_seq || good_ts) { + if (good_ts) { i->period_clean_count++; i->session_clean_count++; } @@ -337,12 +428,12 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin i->period_packet_in_count++; i->session_packet_in_count++; - i->period_need_range_avg = i->period_need_range / (i->period_missing_count || 1); + i->period_need_range_avg = i->period_need_range / least1(i->period_missing_count); if (i->period_missing_count > i->qlen * 2) { -#ifdef DB_JB - printf("resize %u %u\n", i->qlen, i->qlen + 1); -#endif + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s resize %u %u\n", i->name, i->qlen, i->qlen + 1); + } stfu_n_resize(i, i->qlen + 1); stfu_n_reset_counters(i); } else { @@ -353,7 +444,24 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin } } + + i->diff = 0; + + if (i->last_wr_ts) { + if (ts < 1000 && i->last_wr_ts > (UINT_MAX - 1000)) { + i->diff = abs(((UINT_MAX - i->last_wr_ts) + ts) / i->samples_per_packet); + } else if (ts) { + i->diff = abs(i->last_wr_ts - ts) / i->samples_per_packet; + } + } + + i->diff_total += i->diff; + if ((i->period_packet_in_count > i->period_time)) { + uint32_t avg; + + avg = i->diff_total / least1(i->period_packet_in_count); + i->period_packet_in_count = 0; if (i->period_missing_count == 0 && i->qlen > i->orig_qlen) { @@ -364,68 +472,38 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin stfu_n_reset_counters(i); } -#ifdef DB_JB - printf("%u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u/%u - %u %d\n", - i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count, - i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count, - seq, ts, - i->period_missing_count, i->period_need_range_avg); -#endif + + + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d\n", i->name, + i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count, + i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count, + ts, ts / i->samples_per_packet, + i->period_missing_count, i->period_need_range_avg, + i->last_wr_ts, ts, i->diff, i->diff_total / least1(i->period_packet_in_count)); + } if (last || i->in_queue->array_len == i->in_queue->array_size) { - stfu_queue_t *other_queue; - - other_queue = i->in_queue; - i->in_queue = i->out_queue; - i->out_queue = other_queue; - - i->in_queue->array_len = 0; - i->out_queue->wr_len = 0; - i->last_frame = NULL; - i->miss_count = 0; - i->in_queue->last_index = 0; - i->out_queue->last_index = 0; - i->out_queue->last_jitter = 0; + stfu_n_swap(i); } if (last) { return STFU_IM_DONE; } - for(index = 0; index < i->in_queue->array_size; index++) { - - if (i->in_queue->array[index].was_read) { - min_index = index; - break; - } - - if (i->in_queue->array[index].seq < min_seq) { - min_seq = i->in_queue->array[index].seq; - min_index = index; - } - - if (i->in_queue->array[index].ts < min_ts) { - min_ts = i->in_queue->array[index].ts; - min_index = index; - } - } - - index = min_index; - - if (i->in_queue->array_len < i->in_queue->array_size) { - i->in_queue->array_len++; - } - + index = i->in_queue->array_len++; assert(index < i->in_queue->array_size); - frame = &i->in_queue->array[index]; + if (i->in_queue->array_len == i->in_queue->array_size) { + stfu_n_swap(i); + } + if ((cplen = datalen) > sizeof(frame->data)) { cplen = sizeof(frame->data); } - i->last_seq = seq; i->last_rd_ts = ts; i->packet_count++; @@ -433,44 +511,13 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin frame->pt = pt; frame->ts = ts; - frame->seq = seq; frame->dlen = cplen; frame->was_read = 0; return STFU_IT_WORKED; } -static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_frame_t **r_frame) -{ - uint32_t i = 0; - stfu_frame_t *frame = NULL; - stfu_queue_t *queue; - - assert(r_frame); - - *r_frame = NULL; - - for (queue = in->out_queue ; queue && queue != in->in_queue ; queue = in->in_queue) { - - for(i = 0; i < queue->real_array_size; i++) { - frame = &queue->array[i]; - if (!frame->was_read) { - *r_frame = frame; - queue->last_index = i; - frame->was_read = 1; - in->period_packet_out_count++; - in->session_packet_out_count++; - return 1; - } - } - - } - - return 0; -} - - -static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, uint32_t seq, stfu_frame_t **r_frame) +static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_queue_t *queue, stfu_frame_t **r_frame) { uint32_t i = 0; stfu_frame_t *frame = NULL; @@ -481,8 +528,7 @@ static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t for(i = 0; i < queue->real_array_size; i++) { frame = &queue->array[i]; - - if (((seq || in->last_seq) && frame->seq == seq) || frame->ts == ts) { + if (!frame->was_read) { *r_frame = frame; queue->last_index = i; frame->was_read = 1; @@ -492,6 +538,34 @@ static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t } } + return 0; +} + + +static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame) +{ + uint32_t i = 0; + stfu_frame_t *frame = NULL; + + if (r_frame) { + *r_frame = NULL; + } + + for(i = 0; i < queue->array_size; i++) { + frame = &queue->array[i]; + + if (frame->ts == ts) { + if (r_frame) { + *r_frame = frame; + queue->last_index = i; + frame->was_read = 1; + in->period_packet_out_count++; + in->session_packet_out_count++; + } + return 1; + } + } + return 0; } @@ -500,48 +574,76 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) stfu_frame_t *rframe = NULL; int found = 0; - if (!i->samples_per_packet || !i->out_queue->array_len) { - //|| ((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) { - return NULL; - } - - if (i->cur_ts == 0) { - i->cur_ts = i->out_queue->array[0].ts; - } else { - i->cur_ts += i->samples_per_packet; + if (!i->samples_per_packet) { + return NULL; } - if (i->cur_seq == 0) { - i->cur_seq = i->out_queue->array[0].seq; + if (!i->ready) { + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s XXXSKIP\n", i->name); + } + return NULL; + } + + + if (i->cur_ts == 0 && i->last_wr_ts < 1000) { + uint32_t x = 0; + for (x = 0; x < i->out_queue->array_len; x++) { + if (!i->out_queue->array[x].was_read) { + i->cur_ts = i->out_queue->array[x].ts; + break; + } + if (i->cur_ts == 0) { + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s XXXPUNT\n", i->name); + return NULL; + } + } + } } else { - i->cur_seq++; - /* if we bother using this for anything that doesn't have 16 bit seq, we'll make this a param */ - if (i->cur_seq == 65535) { - i->cur_seq = 0; + i->cur_ts = i->cur_ts + i->samples_per_packet; + } + + found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, &rframe); + + if (found) { + if (i->out_queue->array_len) { + i->out_queue->array_len--; + } + } else { + found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, &rframe); + + if (!found) { + found = stfu_n_find_frame(i, i->old_queue, i->cur_ts, &rframe); } } - if (!(found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, i->cur_seq, &rframe))) { - found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, i->cur_seq, &rframe); + if (i->sync_out) { + if (!found) { + if ((found = stfu_n_find_any_frame(i, i->out_queue, &rframe))) { + i->cur_ts = rframe->ts; + } + + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s SYNC %u %u:%u\n", i->name, i->sync_out, i->cur_ts, i->cur_ts / i->samples_per_packet); + } + + } + i->sync_out = 0; } - if (!found && i->sync) { -#ifdef DB_JB - printf("SYNC %u\n", i->sync); -#endif - if ((found = stfu_n_find_any_frame(i, &rframe))) { - i->cur_seq = rframe->seq; - i->cur_ts = rframe->ts; + if (!i->cur_ts) { + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s NO TS\n", i->name); } - i->sync = 0; + return NULL; } if (!found && i->samples_per_packet) { -#ifdef DB_JB int y; stfu_frame_t *frame = NULL; -#endif + int32_t delay = i->last_rd_ts - i->cur_ts; uint32_t need = abs(i->last_rd_ts - i->cur_ts) / i->samples_per_packet; @@ -550,30 +652,32 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) i->session_missing_count++; i->period_need_range += need; -#ifdef DB_JB - printf("MISSING %u %u %u %u %d %u %d\n", i->cur_seq, i->cur_ts, i->packet_count, i->last_rd_ts, delay, i->qlen, need); -#endif + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s MISSING %u:%u %u %u %d %u %d\n", i->name, + i->cur_ts, i->cur_ts / i->samples_per_packet, i->packet_count, i->last_rd_ts, delay, i->qlen, need); + } if (i->packet_count > i->orig_qlen * 100 && delay > 0 && need > i->qlen && need < (i->qlen + 5)) { i->packet_count = 0; } -#ifdef DB_JB - for(y = 0; y < i->out_queue->array_size; y++) { - if ((y % 5) == 0) printf("\n"); - frame = &i->out_queue->array[y]; - printf("%u:%u\t", frame->seq, frame->ts); - } - printf("\n\n"); + if (stfu_log != null_logger && i->debug) { + for(y = 0; y < i->out_queue->array_size; y++) { + if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s", i->name); + frame = &i->out_queue->array[y]; + stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet); + } + stfu_log(STFU_LOG_EMERG, "%s\n", i->name); - for(y = 0; y < i->in_queue->array_size; y++) { - if ((y % 5) == 0) printf("\n"); - frame = &i->in_queue->array[y]; - printf("%u:%u\t", frame->seq, frame->ts); + for(y = 0; y < i->in_queue->array_size; y++) { + if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s", i->name); + frame = &i->in_queue->array[y]; + stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet); + } + stfu_log(STFU_LOG_EMERG, "%s\n\n\n", i->name); + } - printf("\n\n"); -#endif if (delay < 0) { stfu_n_reset(i); @@ -581,14 +685,11 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) } } -#ifdef DB_JB - if (found) { - printf("O: %u:%u %u %d\n", rframe->seq, rframe->ts, rframe->plc, rframe->seq - i->last_seq); - } else { - printf("DATA: %u %u %d %s %d\n", i->packet_count, i->consecutive_good_count, i->out_queue->last_jitter, found ? "found" : "not found", i->qlen); + if (stfu_log != null_logger && i->debug) { + if (found) { + stfu_log(STFU_LOG_EMERG, "%s O: %u:%u %u\n", i->name, rframe->ts, rframe->ts / i->samples_per_packet, rframe->plc); + } } -#endif - if (found) { i->consecutive_good_count++; @@ -602,36 +703,28 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) if (found) { i->last_frame = rframe; - i->out_queue->wr_len++; - i->last_wr_ts = rframe->ts; - i->last_wr_seq = rframe->seq; - i->miss_count = 0; + i->out_queue->wr_len++; + i->last_wr_ts = rframe->ts; + + i->miss_count = 0; if (rframe->dlen) { i->plc_len = rframe->dlen; } + + i->plc_pt = rframe->pt; + } else { i->last_wr_ts = i->cur_ts; - i->last_wr_seq = i->cur_seq; rframe = &i->out_queue->int_frame; rframe->dlen = i->plc_len; - -#if 0 - if (i->last_frame) { - /* poor man's plc.. Copy the last frame, but we flag it so you can use a better one if you wish */ - if (i->miss_count) { - memset(rframe->data, 255, rframe->dlen); - } else { - memcpy(rframe->data, i->last_frame->data, rframe->dlen); - } - } -#endif + rframe->pt = i->plc_pt; rframe->ts = i->cur_ts; - i->miss_count++; - -#ifdef DB_JB - printf("PLC %d %d %ld %u %u\n", i->miss_count, rframe->plc, rframe->dlen, rframe->seq, rframe->ts); -#endif + + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s PLC %d %d %ld %u:%u\n", i->name, + i->miss_count, rframe->plc, rframe->dlen, rframe->ts, rframe->ts / i->samples_per_packet); + } if (i->miss_count > i->max_plc) { stfu_n_reset(i); @@ -639,9 +732,138 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) } } - return rframe; + return rframe; } +#ifdef WIN32 +#ifndef vsnprintf +#define vsnprintf _vsnprintf +#endif +#endif + + +int vasprintf(char **ret, const char *format, va_list ap); + +int stfu_vasprintf(char **ret, const char *fmt, va_list ap) +{ +#if !defined(WIN32) && !defined(__sun) + return vasprintf(ret, fmt, ap); +#else + char *buf; + int len; + size_t buflen; + va_list ap2; + char *tmp = NULL; + +#ifdef _MSC_VER +#if _MSC_VER >= 1500 + /* hack for incorrect assumption in msvc header files for code analysis */ + __analysis_assume(tmp); +#endif + ap2 = ap; +#else + va_copy(ap2, ap); +#endif + + len = vsnprintf(tmp, 0, fmt, ap2); + + if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) { + len = vsnprintf(buf, buflen, fmt, ap); + *ret = buf; + } else { + *ret = NULL; + len = -1; + } + + va_end(ap2); + return len; +#endif +} + + + + +int stfu_snprintf(char *buffer, size_t count, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = vsnprintf(buffer, count-1, fmt, ap); + if (ret < 0) + buffer[count-1] = '\0'; + va_end(ap); + return ret; +} + +static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) +{ + if (file && func && line && level && fmt) { + return; + } + return; +} + + + +static const char *LEVEL_NAMES[] = { + "EMERG", + "ALERT", + "CRIT", + "ERROR", + "WARNING", + "NOTICE", + "INFO", + "DEBUG", + NULL +}; + +static const char *cut_path(const char *in) +{ + const char *p, *ret = in; + char delims[] = "/\\"; + char *i; + + for (i = delims; *i; i++) { + p = in; + while ((p = strchr(p, *i)) != 0) { + ret = ++p; + } + } + return ret; +} + + +static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) +{ + const char *fp; + char *data; + va_list ap; + int ret; + + if (level < 0 || level > 7) { + level = 7; + } + if (level > stfu_log_level) { + return; + } + + fp = cut_path(file); + + va_start(ap, fmt); + + ret = stfu_vasprintf(&data, fmt, ap); + + if (ret != -1) { + fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data); + free(data); + } + + va_end(ap); + +} + + /* For Emacs: * Local Variables: * mode:c diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h index d2760b27bc..f65511b5f4 100644 --- a/libs/stfu/stfu.h +++ b/libs/stfu/stfu.h @@ -38,6 +38,8 @@ extern "C" { #include #include #include +#include + #ifdef _MSC_VER #ifndef uint32_t @@ -62,6 +64,85 @@ typedef unsigned long in_addr_t; #endif #include + + +#ifdef WIN32 +#include +#include +typedef SOCKET stfu_socket_t; +typedef unsigned __int64 uint64_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int8 uint8_t; +typedef __int64 int64_t; +typedef __int32 int32_t; +typedef __int16 int16_t; +typedef __int8 int8_t; +typedef intptr_t stfu_ssize_t; +typedef int stfu_filehandle_t; +#define STFU_SOCK_INVALID INVALID_SOCKET +#define strerror_r(num, buf, size) strerror_s(buf, size, num) +#if defined(STFU_DECLARE_STATIC) +#define STFU_DECLARE(type) type __stdcall +#define STFU_DECLARE_NONSTD(type) type __cdecl +#define STFU_DECLARE_DATA +#elif defined(STFU_EXPORTS) +#define STFU_DECLARE(type) __declspec(dllexport) type __stdcall +#define STFU_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl +#define STFU_DECLARE_DATA __declspec(dllexport) +#else +#define STFU_DECLARE(type) __declspec(dllimport) type __stdcall +#define STFU_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl +#define STFU_DECLARE_DATA __declspec(dllimport) +#endif +#else +#define STFU_DECLARE(type) type +#define STFU_DECLARE_NONSTD(type) type +#define STFU_DECLARE_DATA +#include +#include +#include +#include +#include +#include +#include +#define STFU_SOCK_INVALID -1 +typedef int stfu_socket_t; +typedef ssize_t stfu_ssize_t; +typedef int stfu_filehandle_t; +#endif + + +#define STFU_PRE __FILE__, __FUNCTION__, __LINE__ +#define STFU_LOG_LEVEL_DEBUG 7 +#define STFU_LOG_LEVEL_INFO 6 +#define STFU_LOG_LEVEL_NOTICE 5 +#define STFU_LOG_LEVEL_WARNING 4 +#define STFU_LOG_LEVEL_ERROR 3 +#define STFU_LOG_LEVEL_CRIT 2 +#define STFU_LOG_LEVEL_ALERT 1 +#define STFU_LOG_LEVEL_EMERG 0 + +#define STFU_LOG_DEBUG STFU_PRE, STFU_LOG_LEVEL_DEBUG +#define STFU_LOG_INFO STFU_PRE, STFU_LOG_LEVEL_INFO +#define STFU_LOG_NOTICE STFU_PRE, STFU_LOG_LEVEL_NOTICE +#define STFU_LOG_WARNING STFU_PRE, STFU_LOG_LEVEL_WARNING +#define STFU_LOG_ERROR STFU_PRE, STFU_LOG_LEVEL_ERROR +#define STFU_LOG_CRIT STFU_PRE, STFU_LOG_LEVEL_CRIT +#define STFU_LOG_ALERT STFU_PRE, STFU_LOG_LEVEL_ALERT +#define STFU_LOG_EMERG STFU_PRE, STFU_LOG_LEVEL_EMERG +typedef void (*stfu_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...); + + +int stfu_vasprintf(char **ret, const char *fmt, va_list ap); + +STFU_DECLARE_DATA extern stfu_logger_t stfu_log; + +/*! Sets the logger for libstfu. Default is the null_logger */ +void stfu_global_set_logger(stfu_logger_t logger); +/*! Sets the default log level for libstfu */ +void stfu_global_set_default_logger(int level); + #define STFU_DATALEN 16384 #define STFU_QLEN 300 #define STFU_MAX_TRACK 256 @@ -69,13 +150,13 @@ typedef unsigned long in_addr_t; typedef enum { STFU_IT_FAILED, STFU_IT_WORKED, - STFU_IM_DONE + STFU_IM_DONE, + STFU_ITS_TOO_LATE } stfu_status_t; struct stfu_frame { uint32_t ts; uint32_t pt; - uint32_t seq; uint8_t data[STFU_DATALEN]; size_t dlen; uint8_t was_read; @@ -100,14 +181,15 @@ void stfu_n_report(stfu_instance_t *i, stfu_report_t *r); void stfu_n_destroy(stfu_instance_t **i); stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second); stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen); -stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uint32_t pt, void *data, size_t datalen, int last); +stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last); stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i); void stfu_n_reset(stfu_instance_t *i); stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets); void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata); +void stfu_n_debug(stfu_instance_t *i, const char *name); #define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 1) -#define stfu_n_eat(i,t,s,p,d,l) stfu_n_add_data(i, t, s, p, d, l, 0) +#define stfu_n_eat(i,t,p,d,l) stfu_n_add_data(i, t, p, d, l, 0) #ifdef __cplusplus } From 2c8d5d8ec9833f02f6a7b58079dbeb71da0e2456 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 15 Dec 2010 10:22:45 -0600 Subject: [PATCH 008/179] use our version for better compat --- src/switch_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 306e58a839..08a22ccac2 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1659,7 +1659,7 @@ static void jb_logger(const char *file, const char *func, int line, int level, c va_list ap; va_start(ap, fmt); - ret = stfu_vasprintf(&data, fmt, ap); + ret = switch_vasprintf(&data, fmt, ap); if (ret != -1) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "%s", data); free(data); From 416f6388c3756b92b99bd36ab12de957cf55409b Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 15 Dec 2010 10:37:57 -0600 Subject: [PATCH 009/179] windows build fixes for last commit --- libs/stfu/stfu.c | 4 +++- libs/stfu/stfu.h | 2 +- src/switch_rtp.c | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 72459caad9..4965b12e34 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -40,6 +40,8 @@ #ifdef _MSC_VER /* warning C4706: assignment within conditional expression*/ #pragma warning(disable: 4706) +/* warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. */ +#pragma warning(disable:4996) #endif #define least1(_z) (_z ? _z : 1) @@ -641,7 +643,7 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) if (!found && i->samples_per_packet) { - int y; + uint32_t y; stfu_frame_t *frame = NULL; int32_t delay = i->last_rd_ts - i->cur_ts; diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h index f65511b5f4..ad769c62e2 100644 --- a/libs/stfu/stfu.h +++ b/libs/stfu/stfu.h @@ -136,7 +136,7 @@ typedef void (*stfu_logger_t)(const char *file, const char *func, int line, int int stfu_vasprintf(char **ret, const char *fmt, va_list ap); -STFU_DECLARE_DATA extern stfu_logger_t stfu_log; +extern stfu_logger_t stfu_log; /*! Sets the logger for libstfu. Default is the null_logger */ void stfu_global_set_logger(stfu_logger_t logger); diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 08a22ccac2..4e667fb49b 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -2135,11 +2135,18 @@ static void do_flush(switch_rtp_t *rtp_session) flushed++; +#ifdef _MSC_VER +#pragma warning(push) /* remove this stuff when "if (0" is removed */ +#pragma warning(disable:4127) +#endif if (0 && rtp_session->jb) { stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts), rtp_session->recv_msg.header.pt, rtp_session->recv_msg.body, bytes - rtp_header_len); } +#ifdef _MSC_VER +#pragma warning(pop) +#endif rtp_session->stats.inbound.raw_bytes += bytes; rtp_session->stats.inbound.flush_packet_count++; From 8e62bfcb95fb3f0eb68214c8cb2586a3cfe8de8e Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 15 Dec 2010 11:50:41 -0600 Subject: [PATCH 010/179] vs2008 express fix build dependency --- Freeswitch.2008.express.sln | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Freeswitch.2008.express.sln b/Freeswitch.2008.express.sln index 672406bda2..ad3cafe5cd 100644 --- a/Freeswitch.2008.express.sln +++ b/Freeswitch.2008.express.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 +# Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchConsole", "w32\Console\FreeSwitchConsole.2008.vcproj", "{1AF3A893-F7BE-43DD-B697-8AB2397C0D67}" ProjectSection(ProjectDependencies) = postProject {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} @@ -11,6 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Li ProjectSection(ProjectDependencies) = postProject {8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9} {89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C} + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} {F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3} {03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD} {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} From a95af703237509fa55c07df6e381dd6b19550665 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 15 Dec 2010 19:43:13 +0100 Subject: [PATCH 011/179] Skinny: set max message size to 2048 for now (part of FS-2912) --- src/mod/endpoints/mod_skinny/skinny_protocol.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index d85a190ba8..4d0b7922ec 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -552,7 +552,7 @@ struct PACKED service_url_stat_res_message { /*****************************************************************************/ #define SKINNY_MESSAGE_FIELD_SIZE 4 /* 4-bytes field */ #define SKINNY_MESSAGE_HEADERSIZE 12 /* three 4-bytes fields */ -#define SKINNY_MESSAGE_MAXSIZE 1000 +#define SKINNY_MESSAGE_MAXSIZE 2048 union skinny_data { /* no data for KEEP_ALIVE_MESSAGE */ From 715d250e171a94736b19019ac742f739899ad997 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 15 Dec 2010 21:29:52 +0100 Subject: [PATCH 012/179] Skinny: handle new XMLAlarmMessage This add support for new SCCP Firmware 9.1 (part of FS-2912) --- src/mod/endpoints/mod_skinny/skinny_protocol.h | 3 +++ src/mod/endpoints/mod_skinny/skinny_server.c | 2 +- src/mod/endpoints/mod_skinny/skinny_tables.c | 1 + src/mod/endpoints/mod_skinny/skinny_tables.h | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index 4d0b7922ec..ee3c33a497 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -547,6 +547,9 @@ struct PACKED service_url_stat_res_message { #define USER_TO_DEVICE_DATA_VERSION1_MESSAGE 0x013F /* See struct PACKED extended_data_message */ +/* XMLAlarmMessage */ +#define XML_ALARM_MESSAGE 0x015A + /*****************************************************************************/ /* SKINNY MESSAGE */ /*****************************************************************************/ diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index cfafea6f01..c03e3ce8af 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -1970,7 +1970,7 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re "Received %s (type=%x,length=%d) from %s:%d.\n", skinny_message_type2str(request->type), request->type, request->length, listener->device_name, listener->device_instance); } - if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE) { + if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Device should send a register message first.\n"); return SWITCH_STATUS_FALSE; diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.c b/src/mod/endpoints/mod_skinny/skinny_tables.c index 0a27ad76c4..053b350b46 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.c +++ b/src/mod/endpoints/mod_skinny/skinny_tables.c @@ -99,6 +99,7 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = { {"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE}, {"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE}, {"UserToDeviceDataVersion1Message", USER_TO_DEVICE_DATA_VERSION1_MESSAGE}, + {"XMLAlarmMessage", XML_ALARM_MESSAGE}, {NULL, 0} }; SKINNY_DECLARE_ID2STR(skinny_message_type2str, SKINNY_MESSAGE_TYPES, "UnknownMessage") diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.h b/src/mod/endpoints/mod_skinny/skinny_tables.h index 14962b8b78..c119e1f141 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.h +++ b/src/mod/endpoints/mod_skinny/skinny_tables.h @@ -87,7 +87,7 @@ uint32_t func(const char *str)\ } -extern struct skinny_table SKINNY_MESSAGE_TYPES[65]; +extern struct skinny_table SKINNY_MESSAGE_TYPES[66]; const char *skinny_message_type2str(uint32_t id); uint32_t skinny_str2message_type(const char *str); #define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES) From 00046ee0f232cdd4dd9b98c376ad849cbbb90147 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 15 Dec 2010 20:01:34 -0600 Subject: [PATCH 013/179] FS-2933 --- src/switch_ivr_originate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index e61534798b..b6ae346a66 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -1751,6 +1751,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess early_state_t early_state = { 0 }; int read_packet = 0; int check_reject = 1; + switch_codec_implementation_t read_impl = { 0 }; if (strstr(bridgeto, SWITCH_ENT_ORIGINATE_DELIM)) { return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override, @@ -1777,6 +1778,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess switch_channel_set_flag(caller_channel, CF_ORIGINATOR); oglobals.session = session; + switch_core_session_get_read_impl(session, &read_impl); if ((to_var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) { timelimit_sec = atoi(to_var); @@ -3066,7 +3068,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess if ((ringback.fh || silence || ringback.audio_buffer || oglobals.bridge_early_media > -1) && write_frame.codec && write_frame.datalen) { if (silence) { - write_frame.datalen = write_frame.codec->implementation->decoded_bytes_per_packet; + write_frame.datalen = read_impl.decoded_bytes_per_packet; switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, silence); } From 93cc3dc556939a99288b50d8324d0299d0c61b86 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 15 Dec 2010 20:59:23 -0600 Subject: [PATCH 014/179] normalize tests for outbound channels to use switch_channel_direction instead of testing for CF_OUTBOUND --- src/mod/applications/mod_conference/mod_conference.c | 8 ++++---- src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp | 1 - src/mod/endpoints/mod_h323/mod_h323.cpp | 3 +-- src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp | 1 - src/mod/endpoints/mod_opal/mod_opal.cpp | 5 ++--- src/mod/endpoints/mod_skinny/mod_skinny.c | 2 -- src/mod/endpoints/mod_skinny/skinny_server.c | 4 ++-- src/mod/endpoints/mod_skypopen/mod_skypopen.c | 1 - src/mod/endpoints/mod_sofia/mod_sofia.c | 10 +++++----- src/mod/endpoints/mod_sofia/sofia.c | 12 ++++++------ src/mod/endpoints/mod_sofia/sofia_glue.c | 4 ++-- src/switch_channel.c | 6 +++--- src/switch_core_state_machine.c | 2 +- src/switch_cpp.cpp | 2 +- src/switch_ivr.c | 2 +- src/switch_ivr_bridge.c | 4 ++-- 16 files changed, 30 insertions(+), 37 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 9b170a32e0..53ce82b4cb 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -2456,7 +2456,7 @@ static void conference_loop_output(conference_member_t *member) switch_event_destroy(&event); } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { /* test to see if outbound channel has answered */ if (switch_channel_test_flag(channel, CF_ANSWERED) && !switch_test_flag(member->conference, CFLAG_ANSWERED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, @@ -2599,7 +2599,7 @@ static void conference_loop_output(conference_member_t *member) switch_channel_cause2str(switch_channel_get_cause(channel))); /* if it's an outbound channel, store the release cause in the conference struct, we might need it */ - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { member->conference->bridge_hangup_cause = switch_channel_get_cause(channel); } @@ -5446,7 +5446,7 @@ SWITCH_STANDARD_APP(conference_function) launch_conference_thread(conference); } else { - int enforce_security = !switch_channel_test_flag(channel, CF_OUTBOUND); + int enforce_security = switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND; const char *pvar = switch_channel_get_variable(channel, "conference_enforce_security"); if (pvar) { @@ -5655,7 +5655,7 @@ SWITCH_STANDARD_APP(conference_function) } else { /* if we're not using "bridge:" set the conference answered flag */ /* and this isn't an outbound channel, answer the call */ - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) switch_set_flag(conference, CFLAG_ANSWERED); } diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp index 7e20b7c25e..13e433557d 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp @@ -1324,7 +1324,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi caller_profile = tech_pvt->caller_profile; caller_profile->destination_number = rdest; - switch_channel_set_flag(channel, CF_OUTBOUND); switch_set_flag(tech_pvt, TFLAG_OUTBOUND); switch_channel_set_state(channel, CS_INIT); gsmopen_call(tech_pvt, rdest, 30); diff --git a/src/mod/endpoints/mod_h323/mod_h323.cpp b/src/mod/endpoints/mod_h323/mod_h323.cpp index 74fb6ae11a..3d79917434 100644 --- a/src/mod/endpoints/mod_h323/mod_h323.cpp +++ b/src/mod/endpoints/mod_h323/mod_h323.cpp @@ -725,7 +725,6 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran name += outbound_profile->destination_number; switch_channel_set_name(m_fsChannel, name); - switch_channel_set_flag(m_fsChannel, CF_OUTBOUND); switch_channel_set_state(m_fsChannel, CS_INIT); } @@ -1508,7 +1507,7 @@ switch_status_t FSH323Connection::receive_message(switch_core_session_message_t break; } case SWITCH_MESSAGE_INDICATE_ANSWER: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_FALSE; } AnsweringCall(H323Connection::AnswerCallNow); diff --git a/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp b/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp index 3abbe3ecfb..1b126eb277 100644 --- a/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp +++ b/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp @@ -868,7 +868,6 @@ switch_status_t Board::KhompPvt::justStart(switch_caller_profile_t *profile) _caller_profile = switch_caller_profile_clone(_session, profile); switch_channel_set_caller_profile(channel, _caller_profile); - switch_channel_set_flag(channel, CF_OUTBOUND); switch_channel_set_state(channel, CS_INIT); } else diff --git a/src/mod/endpoints/mod_opal/mod_opal.cpp b/src/mod/endpoints/mod_opal/mod_opal.cpp index 8935bbb06d..0760588019 100644 --- a/src/mod/endpoints/mod_opal/mod_opal.cpp +++ b/src/mod/endpoints/mod_opal/mod_opal.cpp @@ -580,7 +580,6 @@ FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, void* userDat name += outbound_profile->destination_number; switch_channel_set_name(m_fsChannel, name); - switch_channel_set_flag(m_fsChannel, CF_OUTBOUND); switch_channel_set_state(m_fsChannel, CS_INIT); } } @@ -966,7 +965,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg It would only happen if someone called switch_channel_answer() instead of switch_channel_mark_answered() on an outbound call. it should not do anything if someone does it by accident somewhere hense this in both cases: - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_FALSE; } @@ -1025,7 +1024,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg { int fixed = 0; - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_FALSE; } diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 2df8937647..5320ca52d1 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -1080,8 +1080,6 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi switch_channel_set_caller_profile(nchannel, caller_profile); tech_pvt->caller_profile = caller_profile; - switch_channel_set_flag(nchannel, CF_OUTBOUND); - if ((sql = switch_mprintf( "INSERT INTO skinny_active_lines " "(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) " diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index c03e3ce8af..9bf9d9fb9b 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -343,7 +343,7 @@ switch_status_t skinny_session_send_call_info(switch_core_session_t *session, li zstr((called_party_number = switch_channel_get_variable(channel, "destination_number")))) { called_party_number = "0000000000"; } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { call_type = SKINNY_INBOUND_CALL; } else { call_type = SKINNY_OUTBOUND_CALL; @@ -1674,7 +1674,7 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste ); switch_set_flag_locked(tech_pvt, TFLAG_IO); - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { switch_channel_mark_answered(channel); } if (switch_channel_test_flag(channel, CF_HOLD)) { diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index 65c1b120fd..56188a4188 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -1364,7 +1364,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi caller_profile = tech_pvt->caller_profile; caller_profile->destination_number = rdest; - switch_channel_set_flag(channel, CF_OUTBOUND); switch_mutex_lock(tech_pvt->flag_mutex); switch_set_flag(tech_pvt, TFLAG_OUTBOUND); switch_mutex_unlock(tech_pvt->flag_mutex); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 4a3c7c0479..07e125ad6c 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -508,7 +508,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session) TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)), TAG_END()); } } else { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending CANCEL to %s\n", switch_channel_get_name(channel)); if (!tech_pvt->got_bye) { switch_channel_set_variable(channel, "sip_hangup_disposition", "send_cancel"); @@ -573,7 +573,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) char *sticky = NULL; const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full"); - if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -653,7 +653,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) switch_channel_clear_flag(channel, CF_PROXY_MODE); } - if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); tech_pvt->num_codecs = 0; sofia_glue_tech_prepare_codecs(tech_pvt); @@ -1683,7 +1683,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE); if (!(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag(channel, CF_EARLY_MEDIA))) { - if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); tech_pvt->num_codecs = 0; @@ -2198,7 +2198,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } else { if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || !tech_pvt->iananame) { sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION); - if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); tech_pvt->num_codecs = 0; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 7e4e34f4ab..94eab68858 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -357,7 +357,7 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status, goto error; } - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { switch_channel_answer(channel); switch_channel_set_variable(channel, "auto_answer_destination", switch_channel_get_variable(channel, "destination_number")); switch_ivr_session_transfer(session, "auto_answer", NULL, NULL); @@ -4114,7 +4114,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status } - if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { sip_contact_t *p_contact = sip->sip_contact; int i = 0; char var_name[80]; @@ -4645,7 +4645,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, status = 183; } - if (channel && (status == 180 || status == 183) && switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { const char *val; if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) { nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR("talk"), TAG_END()); @@ -4692,7 +4692,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (r_sdp) { if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { - if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA"); } sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA); @@ -4715,7 +4715,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } goto done; } else { - if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "DELAYED NEGOTIATION"); } else { if (sofia_glue_tech_media(tech_pvt, (char *) r_sdp) != SWITCH_STATUS_SUCCESS) { @@ -4910,7 +4910,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE); if (!switch_channel_media_ready(channel)) { - if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { //const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); tech_pvt->num_codecs = 0; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 803059a8da..0f52bbc8fb 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4687,8 +4687,8 @@ void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp) switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, sdp); if (!sofia_test_flag(tech_pvt, TFLAG_CHANGE_MEDIA) && !sofia_test_flag(tech_pvt, TFLAG_RECOVERING) && - (switch_channel_test_flag(other_channel, CF_OUTBOUND) && - switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND) && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) { + (switch_channel_direction(other_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && + switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) { switch_ivr_nomedia(val, SMF_FORCE); sofia_set_flag_locked(tech_pvt, TFLAG_CHANGE_MEDIA); } diff --git a/src/switch_channel.c b/src/switch_channel.c index a9c87c5954..b0ee9f527c 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -2622,7 +2622,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_pre_answer(switch_channel return SWITCH_STATUS_SUCCESS; } - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { msg.message_id = SWITCH_MESSAGE_INDICATE_PROGRESS; msg.from = channel->name; status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line); @@ -2657,7 +2657,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready_value(switch_c return SWITCH_STATUS_SUCCESS; } - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING; msg.from = channel->name; msg.numeric_arg = rv; @@ -2800,7 +2800,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t * switch_assert(channel != NULL); - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index c77f3f1a68..ccd6dacc9c 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -124,7 +124,7 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) } if (!count) { - if (switch_channel_test_flag(session->channel, CF_OUTBOUND)) { + if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_channel_test_flag(session->channel, CF_ANSWERED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No Dialplan on answered channel, changing state to HANGUP\n"); diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp index 40462db567..1ba850d7e4 100644 --- a/src/switch_cpp.cpp +++ b/src/switch_cpp.cpp @@ -1206,7 +1206,7 @@ SWITCH_DECLARE(void) bridge(CoreSession &session_a, CoreSession &session_b) if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) { session_a.begin_allow_threads(); - if (!switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_media_ready(channel_a)) { + if (switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_media_ready(channel_a)) { switch_channel_pre_answer(channel_a); } diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 5cd4d4d34f..494871ec8a 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -140,7 +140,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, const char *var; /* - if (!switch_channel_test_flag(channel, CF_OUTBOUND) && !switch_channel_test_flag(channel, CF_PROXY_MODE) && + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_test_flag(channel, CF_PROXY_MODE) && !switch_channel_media_ready(channel) && !switch_channel_test_flag(channel, CF_SERVICE)) { if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot establish media.\n"); diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index afd33f16a0..ceab8b1b96 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -435,8 +435,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) switch_channel_t *un = ans_a ? chan_b : chan_a; switch_channel_t *a = un == chan_b ? chan_a : chan_b; - if (!switch_channel_test_flag(un, CF_OUTBOUND)) { - if (switch_channel_test_flag(a, CF_OUTBOUND) || (un == chan_a && !originator)) { + if (switch_channel_direction(un) == SWITCH_CALL_DIRECTION_INBOUND) { + if (switch_channel_direction(a) == SWITCH_CALL_DIRECTION_OUTBOUND || (un == chan_a && !originator)) { switch_channel_pass_callee_id(a, un); } From 43393f26d102ef63b24e776d33f53b5f44b84d3c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 15 Dec 2010 20:59:33 -0600 Subject: [PATCH 015/179] normalize tests for outbound channels to use switch_channel_direction instead of testing for CF_OUTBOUND --- libs/freetdm/mod_freetdm/mod_freetdm.c | 15 ++++++++------- libs/openzap/mod_openzap/mod_openzap.c | 25 +++++++++++++------------ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 38197bb2f0..e0961e3f9a 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -802,7 +802,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio phy_id = ftdm_channel_get_ph_id(tech_pvt->ftdmchan); ftdm_log(FTDM_LOG_DEBUG, "Got Freeswitch message in R2 channel %d [%d]\n", phy_id, msg->message_id); - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -849,7 +849,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, return SWITCH_STATUS_SUCCESS; } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -892,7 +892,7 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio return SWITCH_STATUS_FALSE; } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -924,7 +924,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio return SWITCH_STATUS_FALSE; } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -981,7 +981,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_PROGRESS: case SWITCH_MESSAGE_INDICATE_ANSWER: - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { if ((var = switch_channel_get_variable(channel, "freetdm_pre_buffer_size"))) { int tmp = atoi(var); if (tmp > -1) { @@ -1363,7 +1363,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi tech_pvt->caller_profile = caller_profile; - switch_channel_set_flag(channel, CF_OUTBOUND); switch_channel_set_state(channel, CS_INIT); if (ftdm_channel_add_token(ftdmchan, switch_core_session_get_uuid(*new_session), ftdm_channel_get_token_count(ftdmchan)) != FTDM_SUCCESS) { switch_core_session_destroy(new_session); @@ -1811,7 +1810,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal) switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); } - if (channel_a && channel_b && !switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_test_flag(channel_b, CF_OUTBOUND)) { + if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && + switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) { + cause = SWITCH_CAUSE_ATTENDED_TRANSFER; if (br_a_uuid && br_b_uuid) { switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid); diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c index 8425372ef5..6a75dc85ff 100644 --- a/libs/openzap/mod_openzap/mod_openzap.c +++ b/libs/openzap/mod_openzap/mod_openzap.c @@ -821,7 +821,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_RINGING: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); } else { zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS); @@ -830,7 +830,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio break; case SWITCH_MESSAGE_INDICATE_PROGRESS: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA); } else { @@ -841,7 +841,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio break; case SWITCH_MESSAGE_INDICATE_ANSWER: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED); } else { /* lets make the ozmod_r2 module life easier by moving thru each @@ -888,7 +888,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_RINGING: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); } else { zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS); @@ -897,7 +897,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, break; case SWITCH_MESSAGE_INDICATE_PROGRESS: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_MEDIA); } else { @@ -914,7 +914,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, break; case SWITCH_MESSAGE_INDICATE_ANSWER: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED); } else { /* Don't skip messages in the ISDN call setup @@ -957,7 +957,7 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_PROGRESS: case SWITCH_MESSAGE_INDICATE_ANSWER: - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA); @@ -991,7 +991,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_PROGRESS: case SWITCH_MESSAGE_INDICATE_ANSWER: - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA); @@ -1000,7 +1000,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio } break; case SWITCH_MESSAGE_INDICATE_RINGING: - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { if (!switch_channel_test_flag(channel, CF_ANSWERED) && !switch_channel_test_flag(channel, CF_EARLY_MEDIA) && @@ -1052,7 +1052,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_PROGRESS: case SWITCH_MESSAGE_INDICATE_ANSWER: - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { if ((var = switch_channel_get_variable(channel, "openzap_pre_buffer_size"))) { int tmp = atoi(var); if (tmp > -1) { @@ -1327,7 +1327,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi tech_pvt->caller_profile = caller_profile; - switch_channel_set_flag(channel, CF_OUTBOUND); switch_channel_set_state(channel, CS_INIT); if (zap_channel_add_token(zchan, switch_core_session_get_uuid(*new_session), zchan->token_count) != ZAP_SUCCESS) { switch_core_session_destroy(new_session); @@ -1678,7 +1677,9 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal) switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); } - if (channel_a && channel_b && !switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_test_flag(channel_b, CF_OUTBOUND)) { + if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && + switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) { + cause = SWITCH_CAUSE_ATTENDED_TRANSFER; if (br_a_uuid && br_b_uuid) { switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid); From 3ff07445d4846f5b6c7b5338b396e60d330074fd Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 16 Dec 2010 09:45:43 -0600 Subject: [PATCH 016/179] add CF_DIALPLAN --- src/include/switch_types.h | 1 + src/switch_core_state_machine.c | 4 +++- src/switch_ivr_bridge.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index d020775d48..e04f437eb3 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1095,6 +1095,7 @@ typedef enum { CF_BRIDGE_NOWRITE, CF_RECOVERED, CF_JITTERBUFFER, + CF_DIALPLAN, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ CF_FLAG_MAX } switch_channel_flag_t; diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index ccd6dacc9c..59cc17d33a 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -123,7 +123,9 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) } } - if (!count) { + if (count) { + switch_channel_set_flag(session->channel, CF_DIALPLAN); + } else { if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_channel_test_flag(session->channel, CF_ANSWERED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index ceab8b1b96..aa5ddb9232 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -100,7 +100,7 @@ static void send_display(switch_core_session_t *session, switch_core_session_t * caller_channel = switch_core_session_get_channel(session); caller_profile = switch_channel_get_caller_profile(caller_channel); - if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(caller_channel, CF_DIALPLAN)) { name = caller_profile->callee_id_name; number = caller_profile->callee_id_number; From c44b7a74651d2b7ae896a9180ce1f84433c540ed Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 16 Dec 2010 10:10:15 -0600 Subject: [PATCH 017/179] fix formatting in debug mode --- libs/stfu/stfu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 4965b12e34..2ffb86fdb6 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -664,20 +664,21 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) } if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s ", i->name); for(y = 0; y < i->out_queue->array_size; y++) { - if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s", i->name); + if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s ", i->name); frame = &i->out_queue->array[y]; stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet); } - stfu_log(STFU_LOG_EMERG, "%s\n", i->name); + stfu_log(STFU_LOG_EMERG, "\n%s ", i->name); for(y = 0; y < i->in_queue->array_size; y++) { - if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s", i->name); + if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s ", i->name); frame = &i->in_queue->array[y]; stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet); } - stfu_log(STFU_LOG_EMERG, "%s\n\n\n", i->name); + stfu_log(STFU_LOG_EMERG, "\n%s\n\n\n", i->name); } From 2081bf97b9836f5299c22edbb1ead077842ea2bc Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 16 Dec 2010 11:33:38 -0600 Subject: [PATCH 018/179] use a packet buffer for ESL --- Makefile.am | 6 +- libs/esl/Makefile | 6 +- libs/esl/src/esl.c | 155 ++++++++++++++++++++----------------- libs/esl/src/include/esl.h | 8 +- libs/esl/testclient.c | 41 ++++++++++ 5 files changed, 141 insertions(+), 75 deletions(-) diff --git a/Makefile.am b/Makefile.am index da89572c6f..df1ee2e0d0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -276,7 +276,8 @@ bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav fs_encode ## ## fs_cli () ## -fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c +fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \ + libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm @@ -304,7 +305,8 @@ tone2wav_LDADD = libfreeswitch.la ## ## fs_ivrd () ## -fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c +fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \ + libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c fs_ivrd_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include fs_ivrd_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm diff --git a/libs/esl/Makefile b/libs/esl/Makefile index a180406bda..ab50bac4d9 100644 --- a/libs/esl/Makefile +++ b/libs/esl/Makefile @@ -9,9 +9,9 @@ CXXFLAGS=$(BASE_FLAGS) -Wall -Werror -Wno-unused-variable MYLIB=libesl.a LIBS=-lncurses -lpthread -lesl -lm LDFLAGS=-L. -OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o -SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c -HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h +OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o src/esl_buffer.o +SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c src/esl_buffer.c +HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h src/include/esl_buffer.h SOLINK=-shared -Xlinker -x # comment the next line to disable c++ (no swig mods for you then) OBJS += src/esl_oop.o diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index ce582d3837..3397dbfb55 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -428,6 +428,10 @@ ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t s esl_mutex_create(&handle->mutex); } + if (!handle->packet_buf) { + esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0); + } + handle->connected = 1; esl_send_recv(handle, "connect\n\n"); @@ -632,6 +636,10 @@ ESL_DECLARE(esl_status_t) esl_connect_timeout(esl_handle_t *handle, const char * if (!handle->mutex) { esl_mutex_create(&handle->mutex); } + + if (!handle->packet_buf) { + esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0); + } handle->sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -805,6 +813,11 @@ ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle) esl_mutex_destroy(&mutex); } + if (handle->packet_buf) { + esl_buffer_destroy(&handle->packet_buf); + } + + return status; } @@ -825,7 +838,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms if (check_q) { esl_mutex_lock(handle->mutex); - if (handle->race_event) { + if (handle->race_event || esl_buffer_packet_count(handle->packet_buf)) { esl_mutex_unlock(handle->mutex); return esl_recv_event(handle, check_q, save_event); } @@ -894,12 +907,15 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms } +static esl_ssize_t handle_recv(esl_handle_t *handle, void *data, esl_size_t datalen) +{ + return recv(handle->sock, data, datalen, 0); +} ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event) { char *c; esl_ssize_t rrval; - int crc = 0; esl_event_t *revent = NULL; char *beg; char *hname, *hval; @@ -907,7 +923,6 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_ char *cl; esl_ssize_t len; int zc = 0; - int bread = 0; if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID) { return ESL_FAIL; @@ -916,9 +931,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_ esl_mutex_lock(handle->mutex); if (!handle->connected || handle->sock == ESL_SOCK_INVALID) { - handle->connected = 0; - esl_mutex_unlock(handle->mutex); - return ESL_FAIL; + goto fail; } esl_event_safe_destroy(&handle->last_event); @@ -932,76 +945,62 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_ goto parse_event; } - memset(handle->header_buf, 0, sizeof(handle->header_buf)); + + while(!revent && handle->connected) { + esl_size_t len; + + if ((len = esl_buffer_read_packet(handle->packet_buf, handle->socket_buf, sizeof(handle->socket_buf)))) { + char *data = (char *) handle->socket_buf; + char *p, *e; + + esl_event_create(&revent, ESL_EVENT_CLONE); + revent->event_id = ESL_EVENT_SOCKET_DATA; + esl_event_add_header_string(revent, ESL_STACK_BOTTOM, "Event-Name", "SOCKET_DATA"); + + hname = p = data; + while(p) { + hname = p; + p = NULL; - c = handle->header_buf; - beg = c; + if ((hval = strchr(hname, ':'))) { + *hval++ = '\0'; + while(*hval == ' ' || *hval == '\t') hval++; - while(handle->connected) { - if (bread + 2 >= sizeof(handle->header_buf)) { - esl_log(ESL_LOG_CRIT, "OUT OF BUFFER SPACE!\n"); - handle->connected = 0; - esl_mutex_unlock(handle->mutex); - return ESL_DISCONNECTED; + if ((e = strchr(hval, '\n'))) { + *e++ = '\0'; + while(*e == '\n' || *e == '\r') e++; + + if (hname && hval) { + esl_url_decode(hval); + esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval); + esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval); + } + + p = e; + } + } + } + + break; } - rrval = recv(handle->sock, c, 1, 0); + rrval = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf)); + if (rrval == 0) { if (++zc >= 100) { - handle->connected = 0; - esl_mutex_unlock(handle->mutex); - return ESL_DISCONNECTED; + goto fail; } + continue; } else if (rrval < 0) { strerror_r(handle->errnum, handle->err, sizeof(handle->err)); goto fail; - } else { - zc = 0; - - if (*c == '\n') { - - *(c+1) = '\0'; - - if (++crc == 2) { - break; - } - - if (!revent) { - esl_event_create(&revent, ESL_EVENT_CLONE); - revent->event_id = ESL_EVENT_SOCKET_DATA; - esl_event_add_header_string(revent, ESL_STACK_BOTTOM, "Event-Name", "SOCKET_DATA"); - - } - - hname = beg; - hval = col = NULL; - - if (hname && (col = strchr(hname, ':'))) { - hval = col + 1; - *col = '\0'; - while(*hval == ' ') hval++; - } - - *c = '\0'; - - if (hname && hval) { - esl_url_decode(hval); - esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval); - esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval); - } - - c = beg; - bread = 0; - continue; - - } else { - crc = 0; - } - - c++; } - } + zc = 0; + + esl_buffer_write(handle->packet_buf, handle->socket_buf, rrval); + } + if (!revent) { goto fail; } @@ -1016,12 +1015,28 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_ *(body + len) = '\0'; do { - esl_ssize_t r; - if ((r = recv(handle->sock, body + sofar, len - sofar, 0)) < 0) { - strerror_r(handle->errnum, handle->err, sizeof(handle->err)); - goto fail; + esl_ssize_t r,s = esl_buffer_inuse(handle->packet_buf); + + if (s >= len) { + sofar = esl_buffer_read(handle->packet_buf, body, len); + } else { + r = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf)); + + if (r < 0) { + strerror_r(handle->errnum, handle->err, sizeof(handle->err)); + goto fail; + } else if (r == 0) { + if (++zc >= 100) { + goto fail; + } + continue; + } + + zc = 0; + + esl_buffer_write(handle->packet_buf, handle->socket_buf, r); } - sofar += r; + } while (sofar < len); revent->body = body; @@ -1123,6 +1138,8 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_ fail: + esl_mutex_unlock(handle->mutex); + handle->connected = 0; return ESL_FAIL; diff --git a/libs/esl/src/include/esl.h b/libs/esl/src/include/esl.h index 9f28c3d925..99ab53ae95 100644 --- a/libs/esl/src/include/esl.h +++ b/libs/esl/src/include/esl.h @@ -251,6 +251,7 @@ typedef int esl_filehandle_t; #include "esl_json.h" typedef int16_t esl_port_t; +typedef size_t esl_size_t; typedef enum { ESL_SUCCESS, @@ -259,7 +260,11 @@ typedef enum { ESL_DISCONNECTED } esl_status_t; +#define BUF_CHUNK 65536 * 50 +#define BUF_START 65536 * 100 + #include +#include /*! \brief A handle that will hold the socket information and different events received. */ @@ -273,7 +278,8 @@ typedef struct { /*! The error number reported by the OS */ int errnum; /*! The inner contents received by the socket. Used only internally. */ - char header_buf[4196]; + esl_buffer_t *packet_buf; + char socket_buf[65536]; /*! Last command reply */ char last_reply[1024]; /*! Las command reply when called with esl_send_recv */ diff --git a/libs/esl/testclient.c b/libs/esl/testclient.c index 9fa271fd0b..a031836d50 100644 --- a/libs/esl/testclient.c +++ b/libs/esl/testclient.c @@ -6,6 +6,47 @@ int main(void) { esl_handle_t handle = {{0}}; + esl_buffer_t *buffer; + char doh[65536]; + + esl_buffer_create(&buffer, 32 * 1024, 32 * 1024, 0); + + snprintf(doh, sizeof(doh), "TEST 1 FOO BAR 1234\n"); + esl_buffer_write(buffer, doh, strlen(doh)); + esl_buffer_write(buffer, doh, strlen(doh)); + esl_buffer_write(buffer, doh, strlen(doh)); + snprintf(doh, sizeof(doh), "TEST 1 END\n\n"); + esl_buffer_write(buffer, doh, strlen(doh)); + + + + snprintf(doh, sizeof(doh), "TEST 2 BAR FOO 4321\n"); + esl_buffer_write(buffer, doh, strlen(doh)); + esl_buffer_write(buffer, doh, strlen(doh)); + esl_buffer_write(buffer, doh, strlen(doh)); + snprintf(doh, sizeof(doh), "TEST 2 END\n\n"); + esl_buffer_write(buffer, doh, strlen(doh)); + + snprintf(doh, sizeof(doh), "TEST 2 BAR FOO 4321\n"); + esl_buffer_write(buffer, doh, strlen(doh)); + esl_buffer_write(buffer, doh, strlen(doh)); + esl_buffer_write(buffer, doh, strlen(doh)); + snprintf(doh, sizeof(doh), "TEST 2 END\n\n"); + esl_buffer_write(buffer, doh, strlen(doh)); + + printf("COUNT %ld\n", esl_buffer_packet_count(buffer)); + + memset(doh, 0, sizeof(doh)); + esl_buffer_read_packet(buffer, doh, sizeof(doh)); + printf("TEST: [%s]\n", doh); + + memset(doh, 0, sizeof(doh)); + + + esl_buffer_read_packet(buffer, doh, sizeof(doh)); + printf("TEST2: [%s]\n", doh); + + return 0; esl_connect(&handle, "localhost", 8021, NULL, "ClueCon"); From 2800ea199d6c233fe0aeee91de3be33dfee19607 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 16 Dec 2010 11:34:02 -0600 Subject: [PATCH 019/179] tune event socket params a bit --- .../event_handlers/mod_event_socket/mod_event_socket.c | 10 +++++----- src/switch_event.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index ee7cfc9eaf..596a953dcb 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -31,8 +31,8 @@ */ #include #define CMD_BUFLEN 1024 * 1000 -#define MAX_QUEUE_LEN 5000 -#define MAX_MISSED 200 +#define MAX_QUEUE_LEN 25000 +#define MAX_MISSED 2000 SWITCH_MODULE_LOAD_FUNCTION(mod_event_socket_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_event_socket_shutdown); SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_socket_runtime); @@ -170,7 +170,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) { switch_log_node_t *dnode = switch_log_node_dup(node); - if (switch_queue_trypush(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) { + if (switch_queue_push(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) { if (l->lost_logs) { int ll = l->lost_logs; switch_event_t *event; @@ -366,7 +366,7 @@ static void event_handler(switch_event_t *event) if (send) { if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) { - if (switch_queue_trypush(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) { + if (switch_queue_push(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) { if (l->lost_events) { int le = l->lost_events; l->lost_events = 0; @@ -1233,7 +1233,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, if (switch_channel_get_state(chan) < CS_HANGUP && switch_channel_test_flag(chan, CF_DIVERT_EVENTS)) { switch_event_t *e = NULL; while (switch_core_session_dequeue_event(listener->session, &e, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { - if (switch_queue_trypush(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) { + if (switch_queue_push(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) { switch_core_session_queue_event(listener->session, &e); break; } diff --git a/src/switch_event.c b/src/switch_event.c index f782c15900..dce42f8e29 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -339,7 +339,7 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi launch_dispatch_threads(SOFT_MAX_DISPATCH + 1, DISPATCH_QUEUE_LEN, RUNTIME_POOL); switch_mutex_unlock(EVENT_QUEUE_MUTEX); } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of threads!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of event dispatch threads! Slowing things down.\n"); switch_yield(1000000); } } From 526436fd1f8c15b5a8bb82557245d56a5587c536 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 16 Dec 2010 11:58:18 -0600 Subject: [PATCH 020/179] doh --- libs/esl/src/esl_buffer.c | 354 ++++++++++++++++++++++++++++++ libs/esl/src/include/esl_buffer.h | 146 ++++++++++++ 2 files changed, 500 insertions(+) create mode 100644 libs/esl/src/esl_buffer.c create mode 100644 libs/esl/src/include/esl_buffer.h diff --git a/libs/esl/src/esl_buffer.c b/libs/esl/src/esl_buffer.c new file mode 100644 index 0000000000..51fbfb2768 --- /dev/null +++ b/libs/esl/src/esl_buffer.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2010, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "esl_buffer.h" + +static unsigned buffer_id = 0; + +struct esl_buffer { + unsigned char *data; + unsigned char *head; + esl_size_t used; + esl_size_t actually_used; + esl_size_t datalen; + esl_size_t max_len; + esl_size_t blocksize; + unsigned id; + int loops; +}; + + +ESL_DECLARE(esl_status_t) esl_buffer_create(esl_buffer_t **buffer, esl_size_t blocksize, esl_size_t start_len, esl_size_t max_len) +{ + esl_buffer_t *new_buffer; + + new_buffer = malloc(sizeof(*new_buffer)); + if (new_buffer) { + memset(new_buffer, 0, sizeof(*new_buffer)); + + if (start_len) { + new_buffer->data = malloc(start_len); + if (!new_buffer->data) { + free(new_buffer); + return ESL_FAIL; + } + memset(new_buffer->data, 0, start_len); + } + + new_buffer->max_len = max_len; + new_buffer->datalen = start_len; + new_buffer->id = buffer_id++; + new_buffer->blocksize = blocksize; + new_buffer->head = new_buffer->data; + + *buffer = new_buffer; + return ESL_SUCCESS; + } + + return ESL_FAIL; +} + +ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer) +{ + + assert(buffer != NULL); + + return buffer->datalen; + +} + + +ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer) +{ + assert(buffer != NULL); + + + if (buffer->max_len) { + return (esl_size_t) (buffer->max_len - buffer->used); + } + return 1000000; + +} + +ESL_DECLARE(esl_size_t) esl_buffer_inuse(esl_buffer_t *buffer) +{ + assert(buffer != NULL); + + return buffer->used; +} + +ESL_DECLARE(esl_size_t) esl_buffer_seek(esl_buffer_t *buffer, esl_size_t datalen) +{ + esl_size_t reading = 0; + + assert(buffer != NULL); + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else if (buffer->used >= datalen) { + reading = datalen; + } else { + reading = buffer->used; + } + + buffer->used = buffer->actually_used - reading; + buffer->head = buffer->data + reading; + + return reading; +} + +ESL_DECLARE(esl_size_t) esl_buffer_toss(esl_buffer_t *buffer, esl_size_t datalen) +{ + esl_size_t reading = 0; + + assert(buffer != NULL); + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else if (buffer->used >= datalen) { + reading = datalen; + } else { + reading = buffer->used; + } + + buffer->used -= reading; + buffer->head += reading; + + return buffer->used; +} + +ESL_DECLARE(void) esl_buffer_set_loops(esl_buffer_t *buffer, int loops) +{ + buffer->loops = loops; +} + +ESL_DECLARE(esl_size_t) esl_buffer_read_loop(esl_buffer_t *buffer, void *data, esl_size_t datalen) +{ + esl_size_t len; + if ((len = esl_buffer_read(buffer, data, datalen)) < datalen) { + if (buffer->loops == 0) { + return len; + } + buffer->head = buffer->data; + buffer->used = buffer->actually_used; + len = esl_buffer_read(buffer, (char*)data + len, datalen - len); + buffer->loops--; + } + return len; +} + +ESL_DECLARE(esl_size_t) esl_buffer_read(esl_buffer_t *buffer, void *data, esl_size_t datalen) +{ + esl_size_t reading = 0; + + assert(buffer != NULL); + assert(data != NULL); + + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else if (buffer->used >= datalen) { + reading = datalen; + } else { + reading = buffer->used; + } + + memcpy(data, buffer->head, reading); + buffer->used -= reading; + buffer->head += reading; + + /* if (buffer->id == 4) printf("%u o %d = %d\n", buffer->id, (unsigned)reading, (unsigned)buffer->used); */ + return reading; +} + + +ESL_DECLARE(esl_size_t) esl_buffer_packet_count(esl_buffer_t *buffer) +{ + char *pe, *p, *e, *head = (char *) buffer->head; + esl_size_t x = 0; + + assert(buffer != NULL); + + e = (head + buffer->used); + + for (p = head; p && *p && p < e; p++) { + if (*p == '\n') { + pe = p+1; + if (*pe == '\r') pe++; + if (pe <= e && *pe == '\n') { + p = pe++; + x++; + } + } + } + + return x; +} + +ESL_DECLARE(esl_size_t) esl_buffer_read_packet(esl_buffer_t *buffer, void *data, esl_size_t maxlen) +{ + char *pe, *p, *e, *head = (char *) buffer->head; + esl_size_t datalen = 0; + + assert(buffer != NULL); + assert(data != NULL); + + e = (head + buffer->used); + + for (p = head; p && *p && p < e; p++) { + if (*p == '\n') { + pe = p+1; + if (*pe == '\r') pe++; + if (pe <= e && *pe == '\n') { + pe++; + datalen = pe - head; + if (datalen > maxlen) { + datalen = maxlen; + } + break; + } + } + } + + return esl_buffer_read(buffer, data, datalen); +} + +ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, esl_size_t datalen) +{ + esl_size_t freespace, actual_freespace; + + assert(buffer != NULL); + assert(data != NULL); + assert(buffer->data != NULL); + + if (!datalen) { + return buffer->used; + } + + actual_freespace = buffer->datalen - buffer->actually_used; + if (actual_freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) { + memmove(buffer->data, buffer->head, buffer->used); + buffer->head = buffer->data; + buffer->actually_used = buffer->used; + } + + freespace = buffer->datalen - buffer->used; + + /* + if (buffer->data != buffer->head) { + memmove(buffer->data, buffer->head, buffer->used); + buffer->head = buffer->data; + } + */ + + if (freespace < datalen) { + esl_size_t new_size, new_block_size; + void *data; + + new_size = buffer->datalen + datalen; + new_block_size = buffer->datalen + buffer->blocksize; + + if (new_block_size > new_size) { + new_size = new_block_size; + } + buffer->head = buffer->data; + data = realloc(buffer->data, new_size); + if (!data) { + return 0; + } + buffer->data = data; + buffer->head = buffer->data; + buffer->datalen = new_size; + } + + + freespace = buffer->datalen - buffer->used; + + if (freespace < datalen) { + return 0; + } else { + memcpy(buffer->head + buffer->used, data, datalen); + buffer->used += datalen; + buffer->actually_used += datalen; + } + /* if (buffer->id == 4) printf("%u i %d = %d\n", buffer->id, (unsigned)datalen, (unsigned)buffer->used); */ + + return buffer->used; +} + +ESL_DECLARE(void) esl_buffer_zero(esl_buffer_t *buffer) +{ + assert(buffer != NULL); + assert(buffer->data != NULL); + + buffer->used = 0; + buffer->actually_used = 0; + buffer->head = buffer->data; +} + +ESL_DECLARE(esl_size_t) esl_buffer_zwrite(esl_buffer_t *buffer, const void *data, esl_size_t datalen) +{ + esl_size_t w; + + if (!(w = esl_buffer_write(buffer, data, datalen))) { + esl_buffer_zero(buffer); + return esl_buffer_write(buffer, data, datalen); + } + + return w; +} + +ESL_DECLARE(void) esl_buffer_destroy(esl_buffer_t **buffer) +{ + if (*buffer) { + free((*buffer)->data); + free(*buffer); + } + + *buffer = NULL; +} + +/* 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: + */ diff --git a/libs/esl/src/include/esl_buffer.h b/libs/esl/src/include/esl_buffer.h new file mode 100644 index 0000000000..c7901e4ede --- /dev/null +++ b/libs/esl/src/include/esl_buffer.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2010, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "esl.h" +#ifndef ESL_BUFFER_H +#define ESL_BUFFER_H +/** + * @defgroup esl_buffer Buffer Routines + * @ingroup buffer + * The purpose of this module is to make a plain buffering interface that can be used for read/write buffers + * throughout the application. + * @{ + */ +struct esl_buffer; +typedef struct esl_buffer esl_buffer_t; + +/*! \brief Allocate a new dynamic esl_buffer + * \param buffer returned pointer to the new buffer + * \param blocksize length to realloc by as data is added + * \param start_len ammount of memory to reserve initially + * \param max_len length the buffer is allowed to grow to + * \return status + */ +ESL_DECLARE(esl_status_t) esl_buffer_create(esl_buffer_t **buffer, esl_size_t blocksize, esl_size_t start_len, esl_size_t max_len); + +/*! \brief Get the length of a esl_buffer_t + * \param buffer any buffer of type esl_buffer_t + * \return int size of the buffer. + */ +ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer); + +/*! \brief Get the freespace of a esl_buffer_t + * \param buffer any buffer of type esl_buffer_t + * \return int freespace in the buffer. + */ +ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer); + +/*! \brief Get the in use amount of a esl_buffer_t + * \param buffer any buffer of type esl_buffer_t + * \return int ammount of buffer curently in use + */ +ESL_DECLARE(esl_size_t) esl_buffer_inuse(esl_buffer_t *buffer); + +/*! \brief Read data from a esl_buffer_t up to the ammount of datalen if it is available. Remove read data from buffer. + * \param buffer any buffer of type esl_buffer_t + * \param data pointer to the read data to be returned + * \param datalen amount of data to be returned + * \return int ammount of data actually read + */ +ESL_DECLARE(esl_size_t) esl_buffer_read(esl_buffer_t *buffer, void *data, esl_size_t datalen); + +ESL_DECLARE(esl_size_t) esl_buffer_read_packet(esl_buffer_t *buffer, void *data, esl_size_t maxlen); +ESL_DECLARE(esl_size_t) esl_buffer_packet_count(esl_buffer_t *buffer); + +/*! \brief Read data endlessly from a esl_buffer_t + * \param buffer any buffer of type esl_buffer_t + * \param data pointer to the read data to be returned + * \param datalen amount of data to be returned + * \return int ammount of data actually read + * \note Once you have read all the data from the buffer it will loop around. + */ +ESL_DECLARE(esl_size_t) esl_buffer_read_loop(esl_buffer_t *buffer, void *data, esl_size_t datalen); + +/*! \brief Assign a number of loops to read + * \param buffer any buffer of type esl_buffer_t + * \param loops the number of loops (-1 for infinite) + */ +ESL_DECLARE(void) esl_buffer_set_loops(esl_buffer_t *buffer, int32_t loops); + +/*! \brief Write data into a esl_buffer_t up to the length of datalen + * \param buffer any buffer of type esl_buffer_t + * \param data pointer to the data to be written + * \param datalen amount of data to be written + * \return int amount of buffer used after the write, or 0 if no space available + */ +ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, esl_size_t datalen); + +/*! \brief Remove data from the buffer + * \param buffer any buffer of type esl_buffer_t + * \param datalen amount of data to be removed + * \return int size of buffer, or 0 if unable to toss that much data + */ +ESL_DECLARE(esl_size_t) esl_buffer_toss(esl_buffer_t *buffer, esl_size_t datalen); + +/*! \brief Remove all data from the buffer + * \param buffer any buffer of type esl_buffer_t + */ +ESL_DECLARE(void) esl_buffer_zero(esl_buffer_t *buffer); + +/*! \brief Destroy the buffer + * \param buffer buffer to destroy + * \note only neccessary on dynamic buffers (noop on pooled ones) + */ +ESL_DECLARE(void) esl_buffer_destroy(esl_buffer_t **buffer); + +/*! \brief Seek to offset from the beginning of the buffer + * \param buffer buffer to seek + * \param datalen offset in bytes + * \return new position + */ +ESL_DECLARE(esl_size_t) esl_buffer_seek(esl_buffer_t *buffer, esl_size_t datalen); + +/** @} */ + +ESL_DECLARE(esl_size_t) esl_buffer_zwrite(esl_buffer_t *buffer, const void *data, esl_size_t datalen); + +#endif +/* 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: + */ From 871c871b80d314b08bdf82e40e5ea04193c0f5a6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 16 Dec 2010 12:17:02 -0600 Subject: [PATCH 021/179] wrong week to quit sniffing glue --- libs/esl/testclient.c | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/libs/esl/testclient.c b/libs/esl/testclient.c index a031836d50..9fa271fd0b 100644 --- a/libs/esl/testclient.c +++ b/libs/esl/testclient.c @@ -6,47 +6,6 @@ int main(void) { esl_handle_t handle = {{0}}; - esl_buffer_t *buffer; - char doh[65536]; - - esl_buffer_create(&buffer, 32 * 1024, 32 * 1024, 0); - - snprintf(doh, sizeof(doh), "TEST 1 FOO BAR 1234\n"); - esl_buffer_write(buffer, doh, strlen(doh)); - esl_buffer_write(buffer, doh, strlen(doh)); - esl_buffer_write(buffer, doh, strlen(doh)); - snprintf(doh, sizeof(doh), "TEST 1 END\n\n"); - esl_buffer_write(buffer, doh, strlen(doh)); - - - - snprintf(doh, sizeof(doh), "TEST 2 BAR FOO 4321\n"); - esl_buffer_write(buffer, doh, strlen(doh)); - esl_buffer_write(buffer, doh, strlen(doh)); - esl_buffer_write(buffer, doh, strlen(doh)); - snprintf(doh, sizeof(doh), "TEST 2 END\n\n"); - esl_buffer_write(buffer, doh, strlen(doh)); - - snprintf(doh, sizeof(doh), "TEST 2 BAR FOO 4321\n"); - esl_buffer_write(buffer, doh, strlen(doh)); - esl_buffer_write(buffer, doh, strlen(doh)); - esl_buffer_write(buffer, doh, strlen(doh)); - snprintf(doh, sizeof(doh), "TEST 2 END\n\n"); - esl_buffer_write(buffer, doh, strlen(doh)); - - printf("COUNT %ld\n", esl_buffer_packet_count(buffer)); - - memset(doh, 0, sizeof(doh)); - esl_buffer_read_packet(buffer, doh, sizeof(doh)); - printf("TEST: [%s]\n", doh); - - memset(doh, 0, sizeof(doh)); - - - esl_buffer_read_packet(buffer, doh, sizeof(doh)); - printf("TEST2: [%s]\n", doh); - - return 0; esl_connect(&handle, "localhost", 8021, NULL, "ClueCon"); From dfdf4e1e23e527e82c6bd1c44870fbe59d1db312 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 16 Dec 2010 12:27:55 -0600 Subject: [PATCH 022/179] windows fix for last esl commit --- libs/esl/src/esl.2008.vcproj | 8 ++++++++ libs/esl/src/esl.2010.vcxproj | 2 ++ 2 files changed, 10 insertions(+) diff --git a/libs/esl/src/esl.2008.vcproj b/libs/esl/src/esl.2008.vcproj index 101348dd59..89daa17d9e 100644 --- a/libs/esl/src/esl.2008.vcproj +++ b/libs/esl/src/esl.2008.vcproj @@ -290,6 +290,10 @@ RelativePath=".\esl.c" > + + @@ -316,6 +320,10 @@ RelativePath=".\include\esl.h" > + + diff --git a/libs/esl/src/esl.2010.vcxproj b/libs/esl/src/esl.2010.vcxproj index b215fe4bc8..fd5e3a8353 100644 --- a/libs/esl/src/esl.2010.vcxproj +++ b/libs/esl/src/esl.2010.vcxproj @@ -128,6 +128,7 @@ + @@ -135,6 +136,7 @@ + From dcce6bb510ccc2096350abba07ff9f9efb8e6b9f Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 16 Dec 2010 13:52:46 -0600 Subject: [PATCH 023/179] vs2010 fix build --- libs/esl/src/esl_buffer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/esl/src/esl_buffer.c b/libs/esl/src/esl_buffer.c index 51fbfb2768..8032169fe3 100644 --- a/libs/esl/src/esl_buffer.c +++ b/libs/esl/src/esl_buffer.c @@ -277,7 +277,7 @@ ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, if (freespace < datalen) { esl_size_t new_size, new_block_size; - void *data; + void *data1; new_size = buffer->datalen + datalen; new_block_size = buffer->datalen + buffer->blocksize; @@ -286,11 +286,11 @@ ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, new_size = new_block_size; } buffer->head = buffer->data; - data = realloc(buffer->data, new_size); - if (!data) { + data1 = realloc(buffer->data, new_size); + if (!data1) { return 0; } - buffer->data = data; + buffer->data = data1; buffer->head = buffer->data; buffer->datalen = new_size; } From 7b1de56baa504c97cd42790fa3defc9f2182f9c1 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 16 Dec 2010 14:24:54 -0600 Subject: [PATCH 024/179] vs2010 fix build --- libs/esl/src/esl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index 3397dbfb55..f5bab62fcb 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -947,9 +947,9 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_ while(!revent && handle->connected) { - esl_size_t len; + esl_size_t len1; - if ((len = esl_buffer_read_packet(handle->packet_buf, handle->socket_buf, sizeof(handle->socket_buf)))) { + if ((len1 = esl_buffer_read_packet(handle->packet_buf, handle->socket_buf, sizeof(handle->socket_buf)))) { char *data = (char *) handle->socket_buf; char *p, *e; From 9db4a8265c8e43d36a3333f96e4cc13a8fc1c37c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 16 Dec 2010 16:03:05 -0600 Subject: [PATCH 025/179] tweak on calle[re] id --- src/switch_channel.c | 2 ++ src/switch_core_state_machine.c | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/switch_channel.c b/src/switch_channel.c index b0ee9f527c..ef21e8c8f1 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -2386,6 +2386,8 @@ SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *chann { switch_assert(channel != NULL); + switch_channel_set_flag(channel, CF_DIALPLAN); + switch_mutex_lock(channel->profile_mutex); caller_extension->next = channel->caller_profile->caller_extension; channel->caller_profile->caller_extension = caller_extension; diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 59cc17d33a..ccd6dacc9c 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -123,9 +123,7 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) } } - if (count) { - switch_channel_set_flag(session->channel, CF_DIALPLAN); - } else { + if (!count) { if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_channel_test_flag(session->channel, CF_ANSWERED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, From ae7279f1741234e4c3209c7eec9e743791df1087 Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Fri, 17 Dec 2010 08:44:20 -0600 Subject: [PATCH 026/179] skypopen: added hrtimers support to OSS audio driver --- src/mod/endpoints/mod_skypopen/oss/main.c | 168 +++++++++++++++--- src/mod/endpoints/mod_skypopen/oss/skypopen.h | 23 ++- 2 files changed, 163 insertions(+), 28 deletions(-) diff --git a/src/mod/endpoints/mod_skypopen/oss/main.c b/src/mod/endpoints/mod_skypopen/oss/main.c index 4fd959f44a..2abc5b342a 100644 --- a/src/mod/endpoints/mod_skypopen/oss/main.c +++ b/src/mod/endpoints/mod_skypopen/oss/main.c @@ -60,15 +60,18 @@ MODULE_LICENSE("Dual BSD/GPL"); static struct skypopen_dev *skypopen_devices; /* allocated in skypopen_init_module */ -#define GIOVA_BLK 1920 -#define GIOVA_SLEEP 20 +static int unload = 0; +#ifdef CENTOS +#define HRTIMER_MODE_REL HRTIMER_REL +#endif// CENTOS +#ifndef WANT_HRTIMER void my_timer_callback_inq( unsigned long data ) { struct skypopen_dev *dev = (void *)data; wake_up_interruptible(&dev->inq); - mod_timer( &dev->timer_inq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); + mod_timer( &dev->timer_inq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) ); } @@ -77,8 +80,66 @@ void my_timer_callback_outq( unsigned long data ) struct skypopen_dev *dev = (void *)data; wake_up_interruptible(&dev->outq); - mod_timer( &dev->timer_outq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); + mod_timer( &dev->timer_outq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) ); } +#else// WANT_HRTIMER + +#ifndef CENTOS +static enum hrtimer_restart my_hrtimer_callback_inq( struct hrtimer *timer_inq ) +{ + struct skypopen_dev *dev = container_of(timer_inq, struct skypopen_dev, timer_inq); + ktime_t now; + + if(unload) + return HRTIMER_NORESTART; + + now = ktime_get(); + hrtimer_forward(&dev->timer_inq, now, ktime_set(0, SKYPOPEN_SLEEP * 1000000)); + wake_up_interruptible(&dev->inq); + + return HRTIMER_RESTART; +} +static enum hrtimer_restart my_hrtimer_callback_outq( struct hrtimer *timer_outq ) +{ + struct skypopen_dev *dev = container_of(timer_outq, struct skypopen_dev, timer_outq); + ktime_t now; + + if(unload) + return HRTIMER_NORESTART; + + now = ktime_get(); + hrtimer_forward(&dev->timer_outq, now, ktime_set(0, SKYPOPEN_SLEEP * 1000000)); + wake_up_interruptible(&dev->outq); + + return HRTIMER_RESTART; +} +#else// CENTOS +static int my_hrtimer_callback_inq( struct hrtimer *timer_inq ) +{ + struct skypopen_dev *dev = container_of(timer_inq, struct skypopen_dev, timer_inq); + + if(unload) + return HRTIMER_NORESTART; + + hrtimer_forward(&dev->timer_inq, timer_inq->expires, ktime_set(0, SKYPOPEN_SLEEP * 1000000)); + wake_up_interruptible(&dev->inq); + + return HRTIMER_RESTART; +} +static int my_hrtimer_callback_outq( struct hrtimer *timer_outq ) +{ + struct skypopen_dev *dev = container_of(timer_outq, struct skypopen_dev, timer_outq); + + if(unload) + return HRTIMER_NORESTART; + + hrtimer_forward(&dev->timer_outq, timer_outq->expires, ktime_set(0, SKYPOPEN_SLEEP * 1000000)); + wake_up_interruptible(&dev->outq); + + return HRTIMER_RESTART; +} +#endif// CENTOS +#endif// WANT_HRTIMER /* The clone-specific data structure includes a key field */ @@ -97,6 +158,12 @@ static spinlock_t skypopen_c_lock = SPIN_LOCK_UNLOCKED; static struct skypopen_dev *skypopen_c_lookfor_device(dev_t key) { struct skypopen_listitem *lptr; +#ifdef WANT_HRTIMER +#if 0 + ktime_t ktime_inq; + ktime_t ktime_outq; +#endif //0 +#endif// WANT_HRTIMER list_for_each_entry(lptr, &skypopen_c_list, list) { if (lptr->key == key) @@ -112,14 +179,29 @@ static struct skypopen_dev *skypopen_c_lookfor_device(dev_t key) memset(lptr, 0, sizeof(struct skypopen_listitem)); lptr->key = key; - init_waitqueue_head(&lptr->device.inq); - init_waitqueue_head(&lptr->device.outq); - setup_timer( &lptr->device.timer_inq, my_timer_callback_inq, (long int)lptr ); - setup_timer( &lptr->device.timer_outq, my_timer_callback_outq, (long int)lptr ); - printk( "Starting skypopen OSS driver read timer (%dms) skype client:(%d)\n", GIOVA_SLEEP, current->tgid ); - mod_timer( &lptr->device.timer_inq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); - printk( "Starting skypopen OSS driver write timer (%dms) skype client:(%d)\n", GIOVA_SLEEP, current->tgid ); - mod_timer( &lptr->device.timer_outq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) ); + init_waitqueue_head(&lptr->device.inq); + init_waitqueue_head(&lptr->device.outq); +#ifndef WANT_HRTIMER + setup_timer( &lptr->device.timer_inq, my_timer_callback_inq, (long int)lptr ); + setup_timer( &lptr->device.timer_outq, my_timer_callback_outq, (long int)lptr ); + printk( "Starting skypopen OSS driver read timer (%dms) skype client:(%d)\n", SKYPOPEN_SLEEP, current->tgid ); + mod_timer( &lptr->device.timer_inq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) ); + printk( "Starting skypopen OSS driver write timer (%dms) skype client:(%d)\n", SKYPOPEN_SLEEP, current->tgid ); + mod_timer( &lptr->device.timer_outq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) ); +#else// WANT_HRTIMER +#if 0 + ktime_inq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000); + hrtimer_init( &lptr->device.timer_inq, CLOCK_MONOTONIC, HRTIMER_MODE_REL ); + lptr->device.timer_inq.function = &my_hrtimer_callback_inq; + hrtimer_start( &lptr->device.timer_inq, ktime_inq, HRTIMER_MODE_REL ); + + ktime_outq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000); + hrtimer_init( &lptr->device.timer_outq, CLOCK_MONOTONIC, HRTIMER_MODE_REL ); + lptr->device.timer_outq.function = &my_hrtimer_callback_outq; + hrtimer_start( &lptr->device.timer_outq, ktime_outq, HRTIMER_MODE_REL ); +#endif + +#endif// WANT_HRTIMER /* place it in the list */ list_add(&lptr->list, &skypopen_c_list); @@ -135,7 +217,7 @@ static int skypopen_c_open(struct inode *inode, struct file *filp) struct skypopen_dev *dev; dev_t key; - key = current->pid; + key = current->tgid; /* look for a skypopenc device in the list */ spin_lock(&skypopen_c_lock); @@ -163,12 +245,27 @@ static int skypopen_c_release(struct inode *inode, struct file *filp) /*************************************************************/ -ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count, +static ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { - struct skypopen_dev *dev = filp->private_data; DEFINE_WAIT(wait); + struct skypopen_dev *dev = filp->private_data; +#ifdef WANT_HRTIMER +#if 1 + if(dev->timer_inq_started == 0){ + ktime_t ktime_inq; + ktime_inq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000); + hrtimer_init( &dev->timer_inq, CLOCK_MONOTONIC, HRTIMER_MODE_REL ); + dev->timer_inq.function = &my_hrtimer_callback_inq; + hrtimer_start( &dev->timer_inq, ktime_inq, HRTIMER_MODE_REL ); + dev->timer_inq_started = 1; + } +#endif +#endif// WANT_HRTIMER + + + //printk("READ\n"); prepare_to_wait(&dev->inq, &wait, TASK_INTERRUPTIBLE); schedule(); finish_wait(&dev->inq, &wait); @@ -176,12 +273,27 @@ ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count, } -ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count, +static ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { - struct skypopen_dev *dev = filp->private_data; DEFINE_WAIT(wait); + struct skypopen_dev *dev = filp->private_data; +#ifdef WANT_HRTIMER +#if 1 + if(dev->timer_outq_started == 0){ + ktime_t ktime_outq; + ktime_outq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000); + hrtimer_init( &dev->timer_outq, CLOCK_MONOTONIC, HRTIMER_MODE_REL ); + dev->timer_outq.function = &my_hrtimer_callback_outq; + hrtimer_start( &dev->timer_outq, ktime_outq, HRTIMER_MODE_REL ); + dev->timer_outq_started = 1; + } +#endif +#endif// WANT_HRTIMER + + + //printk("WRITE\n"); prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE); schedule(); finish_wait(&dev->outq, &wait); @@ -192,7 +304,7 @@ ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count, * The ioctl() implementation */ -int skypopen_ioctl(struct inode *inode, struct file *filp, +static int skypopen_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; @@ -202,7 +314,7 @@ int skypopen_ioctl(struct inode *inode, struct file *filp, case OSS_GETVERSION: return put_user(SOUND_VERSION, p); case SNDCTL_DSP_GETBLKSIZE: - return put_user(GIOVA_BLK, p); + return put_user(SKYPOPEN_BLK, p); case SNDCTL_DSP_GETFMTS: return put_user(28731, p); @@ -239,6 +351,11 @@ void skypopen_cleanup_module(void) struct skypopen_listitem *lptr, *next; dev_t devno = MKDEV(skypopen_major, skypopen_minor); + + unload = 1; + + msleep(100); + /* Get rid of our char dev entries */ if (skypopen_devices) { for (i = 0; i < skypopen_nr_devs; i++) { @@ -247,13 +364,20 @@ void skypopen_cleanup_module(void) kfree(skypopen_devices); } - /* And all the cloned devices */ list_for_each_entry_safe(lptr, next, &skypopen_c_list, list) { +#ifndef WANT_HRTIMER ret= del_timer( &lptr->device.timer_inq ); - //printk( "Stopped skypopen OSS driver read timer (%dms) skype client:(%d)\n", GIOVA_SLEEP, current->tgid ); + printk( "Stopped skypopen OSS driver read timer\n"); ret= del_timer( &lptr->device.timer_outq ); - //printk( "Stopped skypopen OSS driver write timer (%dms) skype client:(%d)\n", GIOVA_SLEEP, current->tgid ); + printk( "Stopped skypopen OSS driver write timer\n"); +#else// WANT_HRTIMER + ret = hrtimer_cancel( &lptr->device.timer_inq ); + printk( "Stopped skypopen OSS driver read HRtimer\n"); + ret = hrtimer_cancel( &lptr->device.timer_outq ); + printk( "Stopped skypopen OSS driver write HRtimer\n"); + +#endif// WANT_HRTIMER list_del(&lptr->list); kfree(lptr); } diff --git a/src/mod/endpoints/mod_skypopen/oss/skypopen.h b/src/mod/endpoints/mod_skypopen/oss/skypopen.h index 5469048c04..2324e448cb 100644 --- a/src/mod/endpoints/mod_skypopen/oss/skypopen.h +++ b/src/mod/endpoints/mod_skypopen/oss/skypopen.h @@ -20,6 +20,11 @@ #include /* needed for the _IOW etc stuff used later */ +#define SKYPOPEN_BLK 960 +#define SKYPOPEN_SLEEP 10 + +#define CENTOS + #ifndef SKYPOPEN_MAJOR #define SKYPOPEN_MAJOR 14 /* dynamic major by default */ #endif @@ -28,12 +33,18 @@ #define SKYPOPEN_NR_DEVS 1 /* skypopen0 through skypopen3 */ #endif +#define WANT_HRTIMER struct skypopen_dev { struct cdev cdev; /* Char device structure */ wait_queue_head_t inq; /* read and write queues */ wait_queue_head_t outq; /* read and write queues */ +#ifndef WANT_HRTIMER struct timer_list timer_inq; struct timer_list timer_outq; +#else// WANT_HRTIMER + struct hrtimer timer_inq; + struct hrtimer timer_outq; +#endif// WANT_HRTIMER int timer_inq_started; int timer_outq_started; }; @@ -50,11 +61,11 @@ extern int skypopen_nr_devs; * Prototypes for shared functions */ -ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count, - loff_t *f_pos); -ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count, - loff_t *f_pos); -int skypopen_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +//ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count, + //loff_t *f_pos); +//ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count, + //loff_t *f_pos); +//int skypopen_ioctl(struct inode *inode, struct file *filp, + //unsigned int cmd, unsigned long arg); #endif /* _SKYPOPEN_H_ */ From c2262aba2be55a9df2a14be5560ac0227516cd49 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 17 Dec 2010 09:52:26 -0500 Subject: [PATCH 027/179] freetdm: Fix for OPENZAP-128 ioctl interface in FreeBSD expects unsigned long --- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 70 ++++++++++++---------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index 7320934a49..f40196499c 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -53,42 +53,48 @@ static struct { float txgain; } zt_globals; +#if defined(__FreeBSD__) +typedef unsigned long ioctlcmd; +#else +typedef int ioctlcmd; +#endif + /** * \brief General IOCTL codes */ struct ioctl_codes { - int GET_BLOCKSIZE; - int SET_BLOCKSIZE; - int FLUSH; - int SYNC; - int GET_PARAMS; - int SET_PARAMS; - int HOOK; - int GETEVENT; - int IOMUX; - int SPANSTAT; - int MAINT; - int GETCONF; - int SETCONF; - int CONFLINK; - int CONFDIAG; - int GETGAINS; - int SETGAINS; - int SPANCONFIG; - int CHANCONFIG; - int SET_BUFINFO; - int GET_BUFINFO; - int AUDIOMODE; - int ECHOCANCEL; - int HDLCRAWMODE; - int HDLCFCSMODE; - int SPECIFY; - int SETLAW; - int SETLINEAR; - int GETCONFMUTE; - int ECHOTRAIN; - int SETTXBITS; - int GETRXBITS; + ioctlcmd GET_BLOCKSIZE; + ioctlcmd SET_BLOCKSIZE; + ioctlcmd FLUSH; + ioctlcmd SYNC; + ioctlcmd GET_PARAMS; + ioctlcmd SET_PARAMS; + ioctlcmd HOOK; + ioctlcmd GETEVENT; + ioctlcmd IOMUX; + ioctlcmd SPANSTAT; + ioctlcmd MAINT; + ioctlcmd GETCONF; + ioctlcmd SETCONF; + ioctlcmd CONFLINK; + ioctlcmd CONFDIAG; + ioctlcmd GETGAINS; + ioctlcmd SETGAINS; + ioctlcmd SPANCONFIG; + ioctlcmd CHANCONFIG; + ioctlcmd SET_BUFINFO; + ioctlcmd GET_BUFINFO; + ioctlcmd AUDIOMODE; + ioctlcmd ECHOCANCEL; + ioctlcmd HDLCRAWMODE; + ioctlcmd HDLCFCSMODE; + ioctlcmd SPECIFY; + ioctlcmd SETLAW; + ioctlcmd SETLINEAR; + ioctlcmd GETCONFMUTE; + ioctlcmd ECHOTRAIN; + ioctlcmd SETTXBITS; + ioctlcmd GETRXBITS; }; /** From d3a24be0baa8a98eabacef7b0ee7b3d088ada316 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 17 Dec 2010 15:50:11 -0200 Subject: [PATCH 028/179] freetdm: ftmod_r2 - updated ftdm_r2_set_channel_sig_status() to notify the user of signaling changes just when specified on docs/sigstatus.txt. also updated ftdm_r2_set_span_sig_status(), so that it uses the former to set channels status, instead of doing it directly. --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 56 +++++++++++++--------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 14eca429e8..5377250588 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -456,19 +456,43 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status) static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status) { openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; + openr2_cas_signal_t rxcas, txcas; + + /* get the current rx and tx cas bits */ + openr2_chan_get_cas(r2chan, &rxcas, &txcas); + + /* if we're already in the state the user asks us to be, we have nothing to do */ + if (status == FTDM_SIG_STATE_SUSPENDED && txcas == OR2_CAS_BLOCK) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in BLOCK state\n"); + return FTDM_SUCCESS; + } + if (status == FTDM_SIG_STATE_UP && txcas == OR2_CAS_IDLE) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in IDLE state\n"); + return FTDM_SUCCESS; + } + + /* set the signaling as requested and send SIGEVENT_SIGSTATUS_CHANGED, if applicable. + * see docs/sigstatus.txt for details */ switch(status) { - case FTDM_SIG_STATE_DOWN: case FTDM_SIG_STATE_SUSPENDED: openr2_chan_set_blocked(r2chan); + if (rxcas == OR2_CAS_IDLE) { + ftdm_r2_set_chan_sig_status(ftdmchan, status); + } break; case FTDM_SIG_STATE_UP: openr2_chan_set_idle(r2chan); + if (rxcas == OR2_CAS_IDLE) { + ftdm_r2_set_chan_sig_status(ftdmchan, status); + } break; + case FTDM_SIG_STATE_DOWN: + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "The user is not allowed to set signaling status to DOWN\n"); + return FTDM_FAIL; default: ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); return FTDM_FAIL; } - ftdm_r2_set_chan_sig_status(ftdmchan, status); return FTDM_SUCCESS; } @@ -497,20 +521,10 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) { ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *citer = NULL; - uint32_t span_opr = -1; - /* we either set the channels to BLOCK or IDLE */ - switch(status) { - case FTDM_SIG_STATE_DOWN: - case FTDM_SIG_STATE_SUSPENDED: - span_opr = 0; - break; - case FTDM_SIG_STATE_UP: - span_opr = 1; - break; - default: - ftdm_log(FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); - return FTDM_FAIL; + if (status == FTDM_SIG_STATE_DOWN) { + ftdm_log(FTDM_LOG_WARNING, "The user is not allowed to set the span signaling status to DOWN\n"); + return FTDM_FAIL; } chaniter = ftdm_span_get_chan_iterator(span, NULL); @@ -521,15 +535,11 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) /* iterate over all channels, setting them to the requested state */ for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { ftdm_channel_t *fchan = ftdm_iterator_current(citer); - openr2_chan_t *r2chan = R2CALL(fchan)->r2chan; - if (span_opr == 0) { - openr2_chan_set_blocked(r2chan); - ftdm_log_chan_msg(fchan, FTDM_LOG_NOTICE, "Channel blocked\n"); - } else { - openr2_chan_set_idle(r2chan); - ftdm_log_chan_msg(fchan, FTDM_LOG_NOTICE, "Channel idle\n"); + /* we set channel's state through ftdm_r2_set_channel_sig_status(), since it already takes + * care of notifying the user when appropriate */ + if ((ftdm_r2_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) { + ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status)); } - ftdm_r2_set_chan_sig_status(fchan, status); } ftdm_iterator_free(chaniter); return FTDM_SUCCESS; From bad1eb118358e0b814cde075388c4e342992e4bf Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Fri, 17 Dec 2010 12:19:14 -0800 Subject: [PATCH 029/179] Update ChangeLog through Dec 16, 2010 --- docs/ChangeLog | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/ChangeLog b/docs/ChangeLog index 96066b6e8c..0ca48c0e81 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -20,6 +20,7 @@ freeswitch (1.0.7) build: Remove mod_spidermonkey from windows 2008 x64 builds - does not work (r:280e894d) build: fix warnings on windows x64 builds src and mods projects - only libsofia included on the libs side (r:45ecbc2f) build: Patch debian init.d script to set ulimit values (r:0eb33e57/FS-2844) + build: add plc to core (r:b7c80a84) codec2: working prototype, still for testing only (r:04ca0751) config: move limit.conf to db.conf config: Update VM phrase macros to voice option then action on main, config menus @@ -33,6 +34,7 @@ freeswitch (1.0.7) config: Fix phrase files, still missing a sound file (r:6741f350/FS-2742) config: Disallow global-intercept and group-intercept can intercept an outbound call in default dialplan (r:890871ba/FS-2777) config: fix single domain assumption in default config to be more portable *cough* bkw *cough* (r:f987903e) + config: Bump Doxygen.conf version to 1.0.6... belatedly (r:cfeae1ba) core: Add RTCP support (FSRTP-14) core: handle some errors on missing db handle conditions core: add ... and shutdown as a fail-safe when no modules are loaded @@ -145,6 +147,15 @@ freeswitch (1.0.7) core: Application intercept causes FS to stop processing calls (r:12fc65f7/FS-2872) core: fix edge cases for endless loop in sql thread (r:5d7c09ed) core: prevent race while changing codecs mid call (r:7aa72b67) + core: Fix crash in ODBC when SQL Server kills TCP connection (r:5aba96e3/FS-2910) + core: Fix fallback to CORE_DB when MSSQL fails init (r:3406d05b) + core: add new function to init an empty switch_sockaddr_t to avoid an unnecessary dns lookup on 0.0.0.0 (r:009c41d4) + core: fix endless RTP loop in Windows (r:cb2d0736/FS-2924) + core: play_and_get_digits should actually timeout, not last forever... (r:28cab5ed/FS-2923) + core: Fix crash w/o core dump (r:00046ee0/FS-2933) + core: normalize tests for outbound channels to use switch_channel_direction instead of testing for CF_OUTBOUND (r:93cc3dc5) + core: add CF_DIALPLAN (r:3ff07445) + core: tweak on calle[re] id (r:9db4a826) lang: Improve French phrase files (FSCONFIG-23) libapr: Fix issue where after a bridge with a member, uuid of Agent is set to single quote character ' (r:3fee704d/FS-2738) libdingaling: fix race on shutdown causing crash (FSMOD-47) @@ -163,6 +174,8 @@ freeswitch (1.0.7) libesl: fix leak-on-error in esl_connect_timeout() (r:4263d60e) libesl: Call close on connection handle if the connection fails (r:413dcc4c/ESL-50) libesl: allow fs_cli -x to have args up to 1024 chars (was 256) (r:7039ba47) + libesl: Make last_event pointer last longer (r:a15f51d5/ESL-37) + libesl: use a packet buffer for ESL (r:2081bf97) libfreetdm: implemented freetdm config nodes and ss7 initial configuration libfreetdm: fix codec for CAS signaling (r:b76e7f18) libfreetdm: freetdm: ss7- added support for incoming group blocks, started adding support for ansi (r:c219a73c) @@ -220,6 +233,8 @@ freeswitch (1.0.7) mod_commands: add escaping empty strings to sql_escape (r:7bd0a5a6/FS-2833) mod_commands: add uuid_fileman : <-- same vals as the callbacks in js and lua to control the currently playing file of a channel from the cli or ESL (for the people who were ignoring me on the conference call so I decided to implement it instead of try to explain it ) (r:c4369fc8) mod_commands: FS-2210 Add support for auto completion for uuid_simplify (r:72bcc01b/FS-2210) + mod_commands: allow epoch in strftime_tz (r:bbf1cd1f) + mod_commands: Dramatic jitterbuffer changes (r:d5470961) mod_conference: Fix reporting of volume up/down (MODAPP-419) mod_conference: add last talking time per member to conference xml list mod_conference: add terminate-on-silence conference param @@ -229,6 +244,7 @@ freeswitch (1.0.7) mod_conference: Fix floor change events not always firing (r:8f1767d3/MODAPP-424) mod_conference: refactor conference to use switch_ivr_dmachine for the digit parsing controls are now bound to each member separately based on conference_controls channel var, then the caller-controls param in the profile or a default to "default" (r:ac19f73c) mod_conference: Fix crash on dtmf action (r:4d5389bd/FS-2781) + mod_conference: revert to the last transfered conference on recover (r:d11c83b1) mod_curl: use method=post when post requested (r:c6a4ddd0/FSMOD-69) mod_db: fix stack corruption (MODAPP-407) mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13) @@ -500,6 +516,11 @@ freeswitch (1.0.7) mod_sofia: Fix wrong IP in VIA and contact HEADER for MESSAGE method while fs run in private network (r:59ea4a1b/FS-2886) mod_sofia: SIP-header History-Info might exist multiple times, but only last header is exposed as a channel variable (r:8cf15012/FS-2881) mod_sofia: Add support to reboot Yealink phone remotely (r:fdc31908/FS-2897) + mod_sofia: Add reuse-connections sofia profile param to allow users to turn off TPTAG_REUSE, thus not re-using TCP connections (r:98ed05cc) + mod_sofia: Make sofia recover also work on custom uuid (r:3a645dee/FS-2913) + mod_sofia: remove check for va_list completely in sofia since i don't even think it happens ever (r:dfecc914) + mod_sofia: have mod_sofia always elect to be the session refresher so we know it will work, also make the session-expires set to 0 imply 100% disabled session timers (r:321013ef) + mod_sofia: Do not set nat mode when the device's network_ip is within the acl also so if your FS is behind nat and your phone is too then it will still make the right decisions (r:6c6eab8c) mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8) mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642) mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45) @@ -515,6 +536,7 @@ freeswitch (1.0.7) mod_spidermonkey: fix seg in js hangup (r:7d554c11) mod_spidermonkey: Fix mod_spidermonkey build on FreeBSD, (Undefined symbol PR_LocalTimeParameters). (r:3edb8419) mod_spy: add support for loopback endpoint (MODAPP-416) + mod_spy: fix crash when session can't be located (r:c4154633/FS-2929) mod_tts_commandline: fix core dump, temp file problem. flush can be called several times (FSMOD-35) mod_unimrcp: fix fortify findings for mod_unimrcp (r:336f0b4e/FSMOD-67) mod_valet_parking: add event data to valet parking hold event From 6b522089574944f85c94825f3b0bbc3ebfe8a715 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Fri, 17 Dec 2010 18:28:57 -0200 Subject: [PATCH 030/179] freetdm: core - moved validation of sigstatus from implementation to core, on sigstatus getters/setters core - locking the channel on ftdm_channel_get_sig_status() and ftdm_channel_set_sig_status(), but not on ftdm_span_get_sig_status() nor ftdm_span_set_sig_status() ftmod_r2 - locking channels on ftdm_r2_get_span_sig_status() and ftdm_r2_set_span_sig_status() --- libs/freetdm/src/ftdm_io.c | 24 +++++++++++++++++++--- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 13 +++++------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 1750d6d7d9..7fb5afdb59 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2488,9 +2488,18 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *ftdmchan, { ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n"); ftdm_assert_return(ftdmchan->span != NULL, FTDM_FAIL, "Null span\n"); - + + if (sigstatus == FTDM_SIG_STATE_DOWN) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "The user is not allowed to set the signaling status to DOWN, valid states are UP or SUSPENDED\n"); + return FTDM_FAIL; + } + if (ftdmchan->span->set_channel_sig_status) { - return ftdmchan->span->set_channel_sig_status(ftdmchan, sigstatus); + ftdm_status_t res; + ftdm_channel_lock(ftdmchan); + res = ftdmchan->span->set_channel_sig_status(ftdmchan, sigstatus); + ftdm_channel_unlock(ftdmchan); + return res; } else { ftdm_log(FTDM_LOG_ERROR, "set_channel_sig_status method not implemented!\n"); return FTDM_FAIL; @@ -2504,7 +2513,11 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_get_sig_status(ftdm_channel_t *ftdmchan, ftdm_assert_return(sigstatus != NULL, FTDM_FAIL, "Null sig status parameter\n"); if (ftdmchan->span->get_channel_sig_status) { - return ftdmchan->span->get_channel_sig_status(ftdmchan, sigstatus); + ftdm_status_t res; + ftdm_channel_lock(ftdmchan); + res = ftdmchan->span->get_channel_sig_status(ftdmchan, sigstatus); + ftdm_channel_unlock(ftdmchan); + return res; } else { /* don't log error here, it can be called just to test if its supported */ return FTDM_NOTIMPL; @@ -2515,6 +2528,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_set_sig_status(ftdm_span_t *span, ftdm_signa { ftdm_assert_return(span != NULL, FTDM_FAIL, "Null span\n"); + if (sigstatus == FTDM_SIG_STATE_DOWN) { + ftdm_log(FTDM_LOG_WARNING, "The user is not allowed to set the signaling status to DOWN, valid states are UP or SUSPENDED\n"); + return FTDM_FAIL; + } + if (span->set_span_sig_status) { return span->set_span_sig_status(span, sigstatus); } else { diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 5377250588..ccf7fdf89a 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -486,9 +486,6 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status) ftdm_r2_set_chan_sig_status(ftdmchan, status); } break; - case FTDM_SIG_STATE_DOWN: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "The user is not allowed to set signaling status to DOWN\n"); - return FTDM_FAIL; default: ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); return FTDM_FAIL; @@ -508,10 +505,13 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status) *status = FTDM_SIG_STATE_SUSPENDED; for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { ftdm_channel_t *fchan = ftdm_iterator_current(citer); + ftdm_channel_lock(fchan); if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) { *status = FTDM_SIG_STATE_UP; + ftdm_channel_unlock(fchan); break; } + ftdm_channel_unlock(fchan); } ftdm_iterator_free(chaniter); return FTDM_SUCCESS; @@ -522,11 +522,6 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *citer = NULL; - if (status == FTDM_SIG_STATE_DOWN) { - ftdm_log(FTDM_LOG_WARNING, "The user is not allowed to set the span signaling status to DOWN\n"); - return FTDM_FAIL; - } - chaniter = ftdm_span_get_chan_iterator(span, NULL); if (!chaniter) { ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); @@ -537,9 +532,11 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) ftdm_channel_t *fchan = ftdm_iterator_current(citer); /* we set channel's state through ftdm_r2_set_channel_sig_status(), since it already takes * care of notifying the user when appropriate */ + ftdm_channel_lock(fchan); if ((ftdm_r2_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) { ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status)); } + ftdm_channel_unlock(fchan); } ftdm_iterator_free(chaniter); return FTDM_SUCCESS; From 8f452bc5199c6964518f9b505fa904493b3814e9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 17 Dec 2010 14:35:53 -0600 Subject: [PATCH 031/179] cid logic changes for calle[re] --- src/include/switch_channel.h | 2 ++ src/mod/endpoints/mod_sofia/mod_sofia.c | 2 ++ src/switch_channel.c | 40 +++++++++++++++++++++++-- src/switch_ivr.c | 15 ---------- src/switch_ivr_bridge.c | 4 +++ src/switch_ivr_originate.c | 18 ----------- 6 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index d6bce5e8bf..e726554d81 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -312,6 +312,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switc */ SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension); +SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in); + /*! \brief Retrieve caller extension from a given channel \param channel channel to retrieve extension from diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 07e125ad6c..884e5bf9f5 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -4065,6 +4065,8 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session switch_channel_set_variable(nchannel, "sip_invite_params", "intercom=true"); } + DUMP_EVENT(var_event); + if (((hval = switch_event_get_header(var_event, "effective_callee_id_name")) || (hval = switch_event_get_header(var_event, "sip_callee_id_name"))) && !zstr(hval)) { caller_profile->callee_id_name = switch_core_strdup(caller_profile->pool, hval); diff --git a/src/switch_channel.c b/src/switch_channel.c index ef21e8c8f1..aa7f6699b7 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -2382,12 +2382,48 @@ SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switc return status; } +SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in) +{ + + if (in) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(channel, CF_DIALPLAN)) { + switch_channel_set_flag(channel, CF_DIALPLAN); + + switch_mutex_lock(channel->profile_mutex); + if (channel->caller_profile->callee_id_name) { + switch_channel_set_variable(channel, "pre_transfer_caller_id_name", channel->caller_profile->caller_id_name); + channel->caller_profile->caller_id_name = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_name); + } + channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING; + + if (channel->caller_profile->callee_id_number) { + switch_channel_set_variable(channel, "pre_transfer_caller_id_number", channel->caller_profile->caller_id_number); + channel->caller_profile->caller_id_number = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_number); + } + channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING; + switch_mutex_unlock(channel->profile_mutex); + } + + return; + } + + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(channel, CF_DIALPLAN)) { + switch_channel_clear_flag(channel, CF_DIALPLAN); + switch_mutex_lock(channel->profile_mutex); + channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING; + channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING; + switch_mutex_unlock(channel->profile_mutex); + } + +} + + SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension) { switch_assert(channel != NULL); - switch_channel_set_flag(channel, CF_DIALPLAN); - + switch_channel_sort_cid(channel, SWITCH_TRUE); + switch_mutex_lock(channel->profile_mutex); caller_extension->next = channel->caller_profile->caller_extension; channel->caller_profile->caller_extension = caller_extension; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 494871ec8a..cd74c332b7 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -1544,21 +1544,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_ new_profile->destination_number = switch_core_strdup(new_profile->pool, extension); new_profile->rdnis = switch_core_strdup(new_profile->pool, profile->destination_number); - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - if (profile->callee_id_name) { - switch_channel_set_variable(channel, "pre_transfer_caller_id_name", new_profile->caller_id_name); - new_profile->caller_id_name = switch_core_strdup(new_profile->pool, profile->callee_id_name); - profile->callee_id_name = SWITCH_BLANK_STRING; - } - - if (profile->callee_id_number) { - switch_channel_set_variable(channel, "pre_transfer_caller_id_number", new_profile->caller_id_number); - new_profile->caller_id_number = switch_core_strdup(new_profile->pool, profile->callee_id_number); - profile->callee_id_number = SWITCH_BLANK_STRING; - } - } - - switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, NULL); /* If HANGUP_AFTER_BRIDGE is set to 'true', SWITCH_SIGNAL_BRIDGE_VARIABLE diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index aa5ddb9232..2f2dcdbc95 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1052,6 +1052,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_signal_bridge(switch_core_session_t * switch_channel_set_variable(caller_channel, "signal_bridge", "true"); switch_channel_set_variable(peer_channel, "signal_bridge", "true"); + switch_channel_sort_cid(peer_channel, SWITCH_FALSE); + /* fire events that will change the data table from "show channels" */ if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(caller_channel, event); @@ -1117,6 +1119,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_channel_set_flag_recursive(caller_channel, CF_BRIDGE_ORIGINATOR); switch_channel_clear_flag(peer_channel, CF_BRIDGE_ORIGINATOR); + switch_channel_sort_cid(peer_channel, SWITCH_FALSE); + b_leg->session = peer_session; switch_copy_string(b_leg->b_uuid, switch_core_session_get_uuid(session), sizeof(b_leg->b_uuid)); b_leg->stream_id = stream_id; diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index b6ae346a66..87a47e65aa 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -2383,24 +2383,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess new_profile->chan_name = SWITCH_BLANK_STRING; new_profile->destination_number = switch_core_strdup(new_profile->pool, chan_data); - if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - const char *callee_id_name = new_profile->callee_id_name; - const char *callee_id_number = new_profile->callee_id_number; - - if (zstr(callee_id_number)) { - callee_id_number = caller_caller_profile->destination_number; - } - - if (zstr(callee_id_name)) { - callee_id_name = callee_id_number; - } - - new_profile->caller_id_name = callee_id_name; - new_profile->caller_id_number = callee_id_number; - new_profile->callee_id_name = SWITCH_BLANK_STRING; - new_profile->callee_id_number = SWITCH_BLANK_STRING; - } - if (cid_name_override) { new_profile->caller_id_name = switch_core_strdup(new_profile->pool, cid_name_override); } From 1e0df408cfb343599e30df7ed41137431cdf4a51 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 17 Dec 2010 15:28:19 -0600 Subject: [PATCH 032/179] oops --- src/mod/endpoints/mod_sofia/mod_sofia.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 884e5bf9f5..07e125ad6c 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -4065,8 +4065,6 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session switch_channel_set_variable(nchannel, "sip_invite_params", "intercom=true"); } - DUMP_EVENT(var_event); - if (((hval = switch_event_get_header(var_event, "effective_callee_id_name")) || (hval = switch_event_get_header(var_event, "sip_callee_id_name"))) && !zstr(hval)) { caller_profile->callee_id_name = switch_core_strdup(caller_profile->pool, hval); From ee562c82e1e3e321c2ece3b5970114a31b693f33 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 17 Dec 2010 16:06:11 -0600 Subject: [PATCH 033/179] FS-2879 --- src/mod/applications/mod_fifo/mod_fifo.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 3943ac6ea6..f275363706 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -3075,16 +3075,24 @@ SWITCH_STANDARD_APP(fifo_function) done: switch_mutex_lock(globals.mutex); - if (node && node->ready == FIFO_DELAY_DESTROY && node->consumer_count == 0 && node_caller_count(node) == 0) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s removed.\n", node->name); - switch_core_hash_delete(globals.fifo_hash, node->name); + if (node && node->ready == FIFO_DELAY_DESTROY) { + int doit = 0; + switch_thread_rwlock_wrlock(node->rwlock); - node->ready = 0; - switch_mutex_lock(node->mutex); - switch_core_hash_destroy(&node->consumer_hash); - switch_mutex_unlock(node->mutex); + doit = node->consumer_count == 0 && node_caller_count(node) == 0; switch_thread_rwlock_unlock(node->rwlock); - switch_core_destroy_memory_pool(&node->pool); + + if (doit) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s removed.\n", node->name); + switch_core_hash_delete(globals.fifo_hash, node->name); + + node->ready = 0; + switch_mutex_lock(node->mutex); + switch_core_hash_destroy(&node->consumer_hash); + switch_mutex_unlock(node->mutex); + switch_thread_rwlock_unlock(node->rwlock); + switch_core_destroy_memory_pool(&node->pool); + } } switch_mutex_unlock(globals.mutex); From 6e2f07f1e63a3bba9721ccaebf2a4d03e02edc9b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 17 Dec 2010 16:19:56 -0600 Subject: [PATCH 034/179] hide debug line --- libs/stfu/stfu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 2ffb86fdb6..b7df8ea870 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -413,7 +413,9 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void if (i->last_wr_ts) { if ((ts <= i->last_wr_ts && (i->last_wr_ts != UINT_MAX || ts == i->last_wr_ts))) { - stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts); + if (stfu_log != null_logger && i->debug) { + stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts); + } if (i->in_queue->array_len < i->in_queue->array_size) { i->in_queue->array_len++; } From 257c7edaf7d7e6151d11e5ef924d87a77f2c369b Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Fri, 17 Dec 2010 14:54:51 -0800 Subject: [PATCH 035/179] Update phrase_en.xml for version 1.0.14 of the sounds package --- docs/phrase/phrase_en.xml | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index a028a2aae0..41bc69cde1 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -221,6 +221,7 @@ + @@ -241,6 +242,8 @@ + + @@ -259,6 +262,12 @@ + + + + + + @@ -362,8 +371,6 @@ - - @@ -390,15 +397,10 @@ - - - - - @@ -409,10 +411,7 @@ - - - @@ -425,20 +424,10 @@ - - - - - - - - - - - - - + + + From ab0a2bfa034aa535de9dae1cf7cbf03224ad2bf3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 17 Dec 2010 17:08:24 -0600 Subject: [PATCH 036/179] prune --- src/mod/applications/mod_fifo/mod_fifo.c | 103 ++++++++++++----------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index f275363706..9d9896956e 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -291,6 +291,7 @@ static switch_status_t fifo_queue_popfly(fifo_queue_t *queue, const char *uuid) struct fifo_node { char *name; switch_mutex_t *mutex; + switch_mutex_t *update_mutex; fifo_queue_t *fifo_list[MAX_PRI]; switch_hash_t *consumer_hash; int outbound_priority; @@ -801,6 +802,7 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu switch_core_hash_init(&node->consumer_hash, node->pool); switch_thread_rwlock_create(&node->rwlock, node->pool); switch_mutex_init(&node->mutex, SWITCH_MUTEX_NESTED, node->pool); + switch_mutex_init(&node->update_mutex, SWITCH_MUTEX_NESTED, node->pool); cbt.buf = outbound_count; cbt.len = sizeof(outbound_count); sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", name); @@ -1193,10 +1195,10 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void if (node) { - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); node->busy = 0; node->ring_consumer_count = 1; - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); } else { goto end; } @@ -1437,10 +1439,10 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void cbh->ready = 1; if (node) { - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); node->ring_consumer_count = 0; node->busy = 0; - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); } @@ -1501,10 +1503,10 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj) switch_mutex_unlock(globals.mutex); if (node) { - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); node->ring_consumer_count++; node->busy = 0; - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); } switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS); @@ -1601,12 +1603,12 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj) switch_event_destroy(&ovars); if (node) { - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); if (node->ring_consumer_count-- < 0) { node->ring_consumer_count = 0; } node->busy = 0; - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); } switch_core_destroy_memory_pool(&h->pool); @@ -1754,9 +1756,35 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Trying priority: %d\n", cur_priority); + restart: + for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, &var, NULL, &val); if ((node = (fifo_node_t *) val)) { + + if (node->ready == FIFO_DELAY_DESTROY) { + int doit = 0; + + switch_mutex_lock(node->update_mutex); + doit = node->consumer_count == 0 && node_caller_count(node) == 0; + switch_mutex_unlock(node->update_mutex); + + if (doit) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name); + switch_core_hash_delete(globals.fifo_hash, node->name); + + node->ready = 0; + switch_mutex_lock(node->mutex); + switch_core_hash_destroy(&node->consumer_hash); + switch_mutex_unlock(node->mutex); + switch_mutex_unlock(node->update_mutex); + switch_core_destroy_memory_pool(&node->pool); + goto restart; + } + + } + + if (node->outbound_priority == 0) node->outbound_priority = 5; if (node->has_outbound && node->ready && !node->busy && node->outbound_priority == cur_priority) { ppl_waiting = node_caller_count(node); @@ -2219,6 +2247,7 @@ SWITCH_STANDARD_APP(fifo_function) if (!(node = switch_core_hash_find(globals.fifo_hash, nlist[i]))) { node = create_node(nlist[i], importance, globals.sql_mutex); node->ready = 1; + switch_thread_rwlock_rdlock(node->rwlock); } node_list[node_count++] = node; } @@ -2306,7 +2335,7 @@ SWITCH_STANDARD_APP(fifo_function) switch_channel_answer(channel); - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); if ((pri = switch_channel_get_variable(channel, "fifo_priority"))) { p = atoi(pri); @@ -2344,7 +2373,7 @@ SWITCH_STANDARD_APP(fifo_function) switch_channel_set_variable(channel, "fifo_priority", tmp); } - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); ts = switch_micro_time_now(); switch_time_exp_lt(&tm, ts); @@ -2450,9 +2479,9 @@ SWITCH_STANDARD_APP(fifo_function) } switch_mutex_lock(globals.mutex); - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); node_remove_uuid(node, uuid); - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); send_presence(node); check_cancel(node); switch_mutex_unlock(globals.mutex); @@ -2682,9 +2711,9 @@ SWITCH_STANDARD_APP(fifo_function) } if (pop && !node_caller_count(node)) { - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); node->start_waiting = 0; - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); } } @@ -3074,29 +3103,9 @@ SWITCH_STANDARD_APP(fifo_function) done: - switch_mutex_lock(globals.mutex); - if (node && node->ready == FIFO_DELAY_DESTROY) { - int doit = 0; - - switch_thread_rwlock_wrlock(node->rwlock); - doit = node->consumer_count == 0 && node_caller_count(node) == 0; + if (node) { switch_thread_rwlock_unlock(node->rwlock); - - if (doit) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s removed.\n", node->name); - switch_core_hash_delete(globals.fifo_hash, node->name); - - node->ready = 0; - switch_mutex_lock(node->mutex); - switch_core_hash_destroy(&node->consumer_hash); - switch_mutex_unlock(node->mutex); - switch_thread_rwlock_unlock(node->rwlock); - switch_core_destroy_memory_pool(&node->pool); - } - } - switch_mutex_unlock(globals.mutex); - switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG); @@ -3707,9 +3716,9 @@ SWITCH_STANDARD_API(fifo_api_function) switch_hash_this(hi, &var, NULL, &val); node = (fifo_node_t *) val; len = node_caller_count(node); - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); stream->write_function(stream, "%s:%d:%d:%d\n", (char *) var, node->consumer_count, node_caller_count(node), len); - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); x++; } @@ -3718,9 +3727,9 @@ SWITCH_STANDARD_API(fifo_api_function) } } else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) { len = node_caller_count(node); - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); stream->write_function(stream, "%s:%d:%d:%d\n", argv[1], node->consumer_count, node_caller_count(node), len); - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); } else { stream->write_function(stream, "none\n"); } @@ -3730,9 +3739,9 @@ SWITCH_STANDARD_API(fifo_api_function) switch_hash_this(hi, &var, NULL, &val); node = (fifo_node_t *) val; len = node_caller_count(node); - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); stream->write_function(stream, "%s:%d\n", (char *) var, node->has_outbound); - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); x++; } @@ -3741,9 +3750,9 @@ SWITCH_STANDARD_API(fifo_api_function) } } else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) { len = node_caller_count(node); - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); stream->write_function(stream, "%s:%d\n", argv[1], node->has_outbound); - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); } else { stream->write_function(stream, "none\n"); } @@ -4116,7 +4125,7 @@ static switch_status_t load_config(int reload, int del_all) node->ready = FIFO_DELAY_DESTROY; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name); - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); for (x = 0; x < MAX_PRI; x++) { while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) { switch_event_destroy(&pop); @@ -4125,7 +4134,7 @@ static switch_status_t load_config(int reload, int del_all) switch_core_hash_delete(globals.fifo_hash, node->name); switch_core_hash_destroy(&node->consumer_hash); - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); switch_core_destroy_memory_pool(&node->pool); goto top; } @@ -4401,7 +4410,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown) switch_hash_this(hi, NULL, NULL, &val); node = (fifo_node_t *) val; - switch_thread_rwlock_wrlock(node->rwlock); + switch_mutex_lock(node->update_mutex); switch_mutex_lock(node->mutex); for (x = 0; x < MAX_PRI; x++) { while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) { @@ -4411,7 +4420,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown) switch_mutex_unlock(node->mutex); switch_core_hash_delete(globals.fifo_hash, node->name); switch_core_hash_destroy(&node->consumer_hash); - switch_thread_rwlock_unlock(node->rwlock); + switch_mutex_unlock(node->update_mutex); switch_core_destroy_memory_pool(&node->pool); } From 668763f4907b1b6115827160037b867800224df6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 17 Dec 2010 17:27:23 -0600 Subject: [PATCH 037/179] prevent race on codec change mid-call --- src/mod/endpoints/mod_sofia/mod_sofia.c | 5 ++++- src/mod/endpoints/mod_sofia/sofia_glue.c | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 07e125ad6c..8aa37b95be 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1084,7 +1084,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f tech_pvt->last_ts = 0; /* inform them of the codec they are actually sending */ - +#if 0 if (++tech_pvt->codec_reinvites > 2) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Ok, some devices *cough* X-lite *cough*\n" @@ -1093,7 +1093,10 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f } else { sofia_glue_do_invite(session); } +#endif + *frame = &silence_frame; + return SWITCH_STATUS_SUCCESS; } } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0f52bbc8fb..029f60ad33 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2669,7 +2669,8 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force) tech_pvt->rm_encoding, tech_pvt->codec_ms, tech_pvt->rm_rate); - + + switch_yield(tech_pvt->read_impl.microseconds_per_packet); switch_core_session_lock_codec_write(tech_pvt->session); switch_core_session_lock_codec_read(tech_pvt->session); resetting = 1; From 2343708a9c13f942d0db94281a953215297d5b39 Mon Sep 17 00:00:00 2001 From: cypromis Date: Sat, 18 Dec 2010 01:15:55 +0100 Subject: [PATCH 038/179] Sun Studio does not like __FUNCTION__ and -mt makes better multithreaded code --- configure.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.in b/configure.in index de7261266e..b1ab0f1723 100644 --- a/configure.in +++ b/configure.in @@ -205,10 +205,14 @@ if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then APR_ADDTO(SWITCH_AM_CFLAGS, -DPIC) APR_ADDTO(SWITCH_AM_CFLAGS, -erroff=E_END_OF_LOOP_CODE_NOT_REACHED) APR_ADDTO(SWITCH_AM_CFLAGS, -errtags=yes) + APR_ADDTO(SWITCH_AM_CFLAGS, -D__FUNCTION__=__func__ ) + APR_ADDTO(SWITCH_AM_CFLAGS, -mt) APR_ADDTO(SWITCH_AM_CXXFLAGS, -errtags=yes) APR_ADDTO(SWITCH_AM_CXXFLAGS, -KPIC) APR_ADDTO(SWITCH_AM_CXXFLAGS, -DPIC) APR_ADDTO(SWITCH_AM_CXXFLAGS, "-features=extensions") + APR_ADDTO(SWITCH_AM_CXXFLAGS, -D__FUNCTION__=__func__) + APR_ADDTO(SWITCH_AM_CXXFLAGS, -mt) APR_ADDTO(SWITCH_AM_LDFLAGS, -R${prefix}/lib) if test "${enable_64}" = "yes"; then From c81a94485765bd1a5a437c2d1e0d318733677786 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Fri, 17 Dec 2010 16:16:39 -0800 Subject: [PATCH 039/179] lang: Update langs - Add pt_PT, update es to have es_ES and es_MX, update mod_say_es and add mod_say_pt (FS-2937) --- build/modules.conf.in | 1 + docs/phrase/phrase_es_ES.xml | 994 ++++++++++++++++++ docs/phrase/phrase_es_MX.xml | 993 +++++++++++++++++ docs/phrase/phrase_pt_BR.xml | 987 +++++++++++++++++ docs/phrase/phrase_pt_PT.xml | 987 +++++++++++++++++ src/mod/say/mod_say_es/mod_say_es.c | 12 +- src/mod/say/mod_say_pt/Makefile | 2 + src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj | 283 +++++ .../say/mod_say_pt/mod_say_pt.2010.vcxproj | 131 +++ src/mod/say/mod_say_pt/mod_say_pt.c | 548 ++++++++++ src/mod/say/mod_say_pt/mod_say_pt.vcproj | 51 + 11 files changed, 4986 insertions(+), 3 deletions(-) create mode 100644 docs/phrase/phrase_es_ES.xml create mode 100644 docs/phrase/phrase_es_MX.xml create mode 100644 docs/phrase/phrase_pt_BR.xml create mode 100644 docs/phrase/phrase_pt_PT.xml create mode 100644 src/mod/say/mod_say_pt/Makefile create mode 100644 src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj create mode 100644 src/mod/say/mod_say_pt/mod_say_pt.2010.vcxproj create mode 100644 src/mod/say/mod_say_pt/mod_say_pt.c create mode 100644 src/mod/say/mod_say_pt/mod_say_pt.vcproj diff --git a/build/modules.conf.in b/build/modules.conf.in index 13e655672c..bd5d49a7ad 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -100,6 +100,7 @@ say/mod_say_en #say/mod_say_fr #say/mod_say_it #say/mod_say_nl +#say/mod_say_pt say/mod_say_ru #say/mod_say_zh #say/mod_say_hu diff --git a/docs/phrase/phrase_es_ES.xml b/docs/phrase/phrase_es_ES.xml new file mode 100644 index 0000000000..ad99c1bf73 --- /dev/null +++ b/docs/phrase/phrase_es_ES.xml @@ -0,0 +1,994 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/phrase/phrase_es_MX.xml b/docs/phrase/phrase_es_MX.xml new file mode 100644 index 0000000000..527f8c3c89 --- /dev/null +++ b/docs/phrase/phrase_es_MX.xml @@ -0,0 +1,993 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/phrase/phrase_pt_BR.xml b/docs/phrase/phrase_pt_BR.xml new file mode 100644 index 0000000000..9cc400c76b --- /dev/null +++ b/docs/phrase/phrase_pt_BR.xml @@ -0,0 +1,987 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/phrase/phrase_pt_PT.xml b/docs/phrase/phrase_pt_PT.xml new file mode 100644 index 0000000000..a0e59deb85 --- /dev/null +++ b/docs/phrase/phrase_pt_PT.xml @@ -0,0 +1,987 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/say/mod_say_es/mod_say_es.c b/src/mod/say/mod_say_es/mod_say_es.c index cf4d2f9b12..ff0ee944c2 100644 --- a/src/mod/say/mod_say_es/mod_say_es.c +++ b/src/mod/say/mod_say_es/mod_say_es.c @@ -39,8 +39,9 @@ * * Anthony Minessale II * Michael B. Murdock + * François Delawarde * - * mod_say_es.c -- Say for English + * mod_say_es.c -- Say for Spanish * */ @@ -102,7 +103,7 @@ static switch_status_t play_group(switch_say_method_t method, int a, int b, int break; default: say_file("digits/%d.wav", a); - say_file("digits/hundred.wav"); + say_file("digits/hundreds.wav"); break; } } @@ -175,7 +176,12 @@ static switch_status_t es_say_general_count(switch_core_session_t *session, char switch (say_args->method) { case SSM_COUNTED: case SSM_PRONOUNCED: - if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/million.wav", session, args)) != SWITCH_STATUS_SUCCESS) { + /* specific case, one million => un millón */ + if (!places[8] && !places[7] && (places[6] == 1)) { + say_file("digits/un.wav"); + say_file("digits/million.wav"); + } + else if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/millions.wav", session, args)) != SWITCH_STATUS_SUCCESS) { return status; } if ((status = play_group(SSM_PRONOUNCED, places[5], places[4], places[3], "digits/thousand.wav", session, args)) != SWITCH_STATUS_SUCCESS) { diff --git a/src/mod/say/mod_say_pt/Makefile b/src/mod/say/mod_say_pt/Makefile new file mode 100644 index 0000000000..2c35e6e98f --- /dev/null +++ b/src/mod/say/mod_say_pt/Makefile @@ -0,0 +1,2 @@ +BASE=../../../.. +include $(BASE)/build/modmake.rules diff --git a/src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj b/src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj new file mode 100644 index 0000000000..bf8c0333c5 --- /dev/null +++ b/src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj @@ -0,0 +1,283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/say/mod_say_pt/mod_say_pt.2010.vcxproj b/src/mod/say/mod_say_pt/mod_say_pt.2010.vcxproj new file mode 100644 index 0000000000..63fba6fae0 --- /dev/null +++ b/src/mod/say/mod_say_pt/mod_say_pt.2010.vcxproj @@ -0,0 +1,131 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + mod_say_pt + {FA429E98-8B03-45E6-A096-A4BC5E821DE4} + mod_say_pt + Win32Proj + + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + {202d7a4e-760d-4d0e-afa1-d7459ced30ff} + false + + + + + + diff --git a/src/mod/say/mod_say_pt/mod_say_pt.c b/src/mod/say/mod_say_pt/mod_say_pt.c new file mode 100644 index 0000000000..747a0c8984 --- /dev/null +++ b/src/mod/say/mod_say_pt/mod_say_pt.c @@ -0,0 +1,548 @@ +/* + * Copyright (c) 2007, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * Michael B. Murdock + * António Silva + * + * mod_say_pt.c -- Say for Portuguese + * + */ + +#include +#include +#include + +SWITCH_MODULE_LOAD_FUNCTION(mod_say_pt_load); +SWITCH_MODULE_DEFINITION(mod_say_pt, mod_say_pt_load, NULL, NULL); + +#define say_num(num, meth) { \ + char tmp[80]; \ + switch_status_t tstatus; \ + switch_say_method_t smeth = say_args->method; \ + switch_say_type_t stype = say_args->type; \ + say_args->type = SST_ITEMS; say_args->method = meth; \ + switch_snprintf(tmp, sizeof(tmp), "%u", (unsigned)num); \ + if ((tstatus = \ + pt_say_general_count(session, tmp, say_args, args)) \ + != SWITCH_STATUS_SUCCESS) { \ + return tstatus; \ + } \ + say_args->method = smeth; say_args->type = stype; \ + } \ + + +#define say_file(...) { \ + char tmp[80]; \ + switch_status_t tstatus; \ + switch_snprintf(tmp, sizeof(tmp), __VA_ARGS__); \ + if ((tstatus = \ + switch_ivr_play_file(session, NULL, tmp, args)) \ + != SWITCH_STATUS_SUCCESS){ \ + return tstatus; \ + } \ + if (!switch_channel_ready(switch_core_session_get_channel(session))) { \ + return SWITCH_STATUS_FALSE; \ + }} \ + + +static switch_status_t play_group(switch_say_method_t method, int a, int b, int c, char *what, switch_core_session_t *session, switch_input_args_t *args) +{ + + /*a => 1xx-9xx*/ + if (a) { + switch (a) { + case 1: + if (b || c) { + say_file("digits/hundred.wav"); + } else { + say_file("digits/100.wav"); + } + break; + case 2: + say_file("digits/200.wav"); + break; + case 3: + say_file("digits/300.wav"); + break; + case 5: + say_file("digits/500.wav"); + break; + default: + say_file("digits/%d.wav", a); + say_file("digits/hundreds.wav"); + break; + } + if (b || c) { + say_file("currency/and.wav"); + } + } + /* b => 1x - 9x */ + if (b) { + if (b > 1) { + if (method == SSM_COUNTED) { + say_file("digits/h-%d0.wav", b); + } else { + say_file("digits/%d0.wav", b); + if (c > 0) { + say_file("currency/and.wav"); + } + } + } else { + say_file("digits/%d%d.wav", b, c); + c = 0; + } + } + /* c => 0 - 9*/ + if (c) { + if (method == SSM_COUNTED) { + say_file("digits/h-%d.wav", c); + } else { + say_file("digits/%d.wav", c); + } + } + + if (what && (a || b || c)) { + say_file(what); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t pt_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args) +{ + int in; + int x = 0; + int places[9] = { 0 }; + char sbuf[128] = ""; + switch_status_t status; + + if (say_args->method == SSM_ITERATED) { + if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)))) { + char *p; + for (p = tosay; p && *p; p++) { + say_file("digits/%c.wav", *p); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n"); + return SWITCH_STATUS_GENERR; + } + return SWITCH_STATUS_SUCCESS; + } + + if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n"); + return SWITCH_STATUS_GENERR; + } + + in = atoi(tosay); + + if (in != 0) { + for (x = 8; x >= 0; x--) { + int num = (int) pow(10, x); + if ((places[(uint32_t) x] = in / num)) { + in -= places[(uint32_t) x] * num; + } + } + + switch (say_args->method) { + case SSM_COUNTED: + case SSM_PRONOUNCED: + /* specific case, one million => um milhão */ + if (!places[8] && !places[7] && (places[6] == 1)) { + say_file("digits/1.wav"); + say_file("digits/million.wav"); + } else if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/millions.wav", session, args)) != SWITCH_STATUS_SUCCESS) { + return status; + } + if ((status = play_group(SSM_PRONOUNCED, places[5], places[4], places[3], "digits/thousand.wav", session, args)) != SWITCH_STATUS_SUCCESS) { + return status; + } + if ((status = play_group(say_args->method, places[2], places[1], places[0], NULL, session, args)) != SWITCH_STATUS_SUCCESS) { + return status; + } + break; + default: + break; + } + } else { + say_file("digits/0.wav"); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t pt_say_time(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args) +{ + int32_t t; + switch_time_t target = 0, target_now = 0; + switch_time_exp_t tm, tm_now; + uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0; + switch_channel_t *channel = switch_core_session_get_channel(session); + const char *tz = switch_channel_get_variable(channel, "timezone"); + + if (say_args->type == SST_TIME_MEASUREMENT) { + int64_t hours = 0; + int64_t minutes = 0; + int64_t seconds = 0; + int64_t r = 0; + + if (strchr(tosay, ':')) { + char *tme = switch_core_session_strdup(session, tosay); + char *p; + + if ((p = strrchr(tme, ':'))) { + *p++ = '\0'; + seconds = atoi(p); + if ((p = strchr(tme, ':'))) { + *p++ = '\0'; + minutes = atoi(p); + if (tme) { + hours = atoi(tme); + } + } else { + minutes = atoi(tme); + } + } + } else { + if ((seconds = atol(tosay)) <= 0) { + seconds = (int64_t) switch_epoch_time_now(NULL); + } + + if (seconds >= 60) { + minutes = seconds / 60; + r = seconds % 60; + seconds = r; + } + + if (minutes >= 60) { + hours = minutes / 60; + r = minutes % 60; + minutes = r; + } + } + + if (hours) { + say_num(hours, SSM_PRONOUNCED); + if (hours == 1) { + say_file("time/hour.wav"); + } else { + say_file("time/hours.wav"); + } + } else { + say_file("digits/0.wav"); + say_file("time/hours.wav"); + } + + if (minutes) { + say_num(minutes, SSM_PRONOUNCED); + if (minutes == 1) { + say_file("time/minute.wav"); + } else { + say_file("time/minutes.wav"); + } + } else { + say_file("digits/0.wav"); + say_file("time/minutes.wav"); + } + + if (seconds) { + say_num(seconds, SSM_PRONOUNCED); + if (seconds == 1) { + say_file("time/second.wav"); + } else { + say_file("time/seconds.wav"); + } + } else { + say_file("digits/0.wav"); + say_file("time/seconds.wav"); + } + + return SWITCH_STATUS_SUCCESS; + } + + if ((t = atol(tosay)) > 0) { + target = switch_time_make(t, 0); + target_now = switch_micro_time_now(); + } else { + target = switch_micro_time_now(); + target_now = switch_micro_time_now(); + } + + if (tz) { + int check = atoi(tz); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz); + if (check) { + switch_time_exp_tz(&tm, target, check); + switch_time_exp_tz(&tm_now, target_now, check); + } else { + switch_time_exp_tz_name(tz, &tm, target); + switch_time_exp_tz_name(tz, &tm_now, target_now); + } + } else { + switch_time_exp_lt(&tm, target); + switch_time_exp_lt(&tm_now, target_now); + } + + switch (say_args->type) { + case SST_CURRENT_DATE_TIME: + say_date = say_time = 1; + break; + case SST_CURRENT_DATE: + say_date = 1; + break; + case SST_CURRENT_TIME: + say_time = 1; + break; + case SST_SHORT_DATE_TIME: + say_time = 1; + if (tm.tm_year != tm_now.tm_year) { + say_date = 1; + break; + } + if (tm.tm_yday == tm_now.tm_yday) { + say_today = 1; + break; + } + if (tm.tm_yday == tm_now.tm_yday - 1) { + say_yesterday = 1; + break; + } + if (tm.tm_yday >= tm_now.tm_yday - 5) { + say_dow = 1; + break; + } + if (tm.tm_mon != tm_now.tm_mon) { + say_month = say_day = say_dow = 1; + break; + } + + say_month = say_day = say_dow = 1; + + break; + default: + break; + } + + if (say_today) { + say_file("time/today.wav"); + } + if (say_yesterday) { + say_file("time/yesterday.wav"); + } + if (say_dow) { + say_file("time/day-%d.wav", tm.tm_wday); + } + + if (say_date) { + say_year = say_month = say_day = say_dow = 1; + say_today = say_yesterday = 0; + } + + if (say_month) { + say_file("time/mon-%d.wav", tm.tm_mon); + } + if (say_day) { + say_num(tm.tm_mday, SSM_COUNTED); + } + if (say_year) { + say_num(tm.tm_year + 1900, SSM_PRONOUNCED); + } + + if (say_time) { + int32_t hour = tm.tm_hour, pm = 0; + + if (say_date || say_today || say_yesterday || say_dow) { + if (hour == 1) { + say_file("time/at.wav"); + } else { + say_file("time/ats.wav"); + } + } + + if (hour > 12) { + hour -= 12; + pm = 1; + } else if (hour == 12) { + pm = 1; + } else if (hour == 0) { + hour = 12; + pm = 0; + } + + say_num(hour, SSM_PRONOUNCED); + + if (tm.tm_min) { + say_file("currency/and.wav"); + say_num(tm.tm_min, SSM_PRONOUNCED); + } else { + say_file("time/oclock.wav"); + } + + say_file("time/%s.wav", pm ? "p-m" : "a-m"); + } + + return SWITCH_STATUS_SUCCESS; +} + + +static switch_status_t pt_say_money(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args) +{ + char sbuf[16] = ""; /* enough for 999,999,999,999.99 (w/o the commas or leading $) */ + char *dollars = NULL; + char *cents = NULL; + + if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n"); + return SWITCH_STATUS_GENERR; + } + + dollars = sbuf; + + if ((cents = strchr(sbuf, '.'))) { + *cents++ = '\0'; + if (strlen(cents) > 2) { + cents[2] = '\0'; + } + } + + /* If positive sign - skip over" */ + if (sbuf[0] == '+') { + dollars++; + } + + /* If negative say "negative" */ + if (sbuf[0] == '-') { + say_file("currency/negative.wav"); + dollars++; + } + + /* Say dollar amount */ + pt_say_general_count(session, dollars, say_args, args); + if (atoi(dollars) == 1) { + say_file("currency/dollar.wav"); + } else { + say_file("currency/dollars.wav"); + } + + /* Say "and" */ + say_file("currency/and.wav"); + + /* Say cents */ + if (cents) { + pt_say_general_count(session, cents, say_args, args); + if (atoi(cents) == 1) { + say_file("currency/cent.wav"); + } else { + say_file("currency/cents.wav"); + } + } else { + say_file("digits/0.wav"); + say_file("currency/cents.wav"); + } + + return SWITCH_STATUS_SUCCESS; +} + + + +static switch_status_t pt_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args) +{ + + switch_say_callback_t say_cb = NULL; + + switch (say_args->type) { + case SST_NUMBER: + case SST_ITEMS: + case SST_PERSONS: + case SST_MESSAGES: + say_cb = pt_say_general_count; + break; + case SST_TIME_MEASUREMENT: + case SST_CURRENT_DATE: + case SST_CURRENT_TIME: + case SST_CURRENT_DATE_TIME: + case SST_SHORT_DATE_TIME: + say_cb = pt_say_time; + break; + case SST_IP_ADDRESS: + return switch_ivr_say_ip(session, tosay, pt_say_general_count, say_args, args); + break; + case SST_NAME_SPELLED: + case SST_NAME_PHONETIC: + return switch_ivr_say_spell(session, tosay, say_args, args); + break; + case SST_CURRENCY: + say_cb = pt_say_money; + break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown Say type=[%d]\n", say_args->type); + break; + } + + if (say_cb) { + return say_cb(session, tosay, say_args, args); + } + + return SWITCH_STATUS_FALSE; +} + +SWITCH_MODULE_LOAD_FUNCTION(mod_say_pt_load) +{ + switch_say_interface_t *say_interface; + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE); + say_interface->interface_name = "pt"; + say_interface->say_function = pt_say; + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +/* 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: + */ diff --git a/src/mod/say/mod_say_pt/mod_say_pt.vcproj b/src/mod/say/mod_say_pt/mod_say_pt.vcproj new file mode 100644 index 0000000000..fb5d2dbab9 --- /dev/null +++ b/src/mod/say/mod_say_pt/mod_say_pt.vcproj @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + From d349290f7b3f61e87bf47a683bffe9b056bd89f4 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 17 Dec 2010 19:26:43 -0500 Subject: [PATCH 040/179] freetdm: fix OPENZAP-125 (Add basic calling party category support into ftmod_r2) (Patched by ric) --- libs/freetdm/mod_freetdm/mod_freetdm.c | 4 ++ libs/freetdm/src/ftdm_call_utils.c | 23 +++++++ libs/freetdm/src/ftdm_io.c | 3 + libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 70 +++++++++++++++++++++- libs/freetdm/src/include/freetdm.h | 18 +++++- libs/freetdm/src/include/ftdm_call_utils.h | 17 ++++++ 6 files changed, 133 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index c459a57c11..0615b3821b 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -1278,6 +1278,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi caller_data.dnis.type = outbound_profile->destination_number_ton; } + if ((var = channel_get_variable(session, var_event, "freetdm_calling_party_category"))) { + ftdm_set_calling_party_category(var, (uint8_t *)&caller_data.cpc); + } + if ((var = channel_get_variable(session, var_event, "freetdm_custom_call_data"))) { ftdm_set_string(caller_data.raw_data, var); caller_data.raw_data_len = (uint32_t)strlen(var); diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c index 69f2fb4fff..2b72f05b77 100644 --- a/libs/freetdm/src/ftdm_call_utils.c +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -30,6 +30,12 @@ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributors: + * + * Moises Silva + * Ricardo Barroetaveña + * */ #include "private/ftdm_core.h" @@ -144,3 +150,20 @@ FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number) return FTDM_SUCCESS; } + +FT_DECLARE(ftdm_status_t) ftdm_set_calling_party_category(const char *string, uint8_t *target) +{ + uint8_t val; + ftdm_status_t status = FTDM_SUCCESS; + + val = ftdm_str2ftdm_calling_party_category(string); + if (val == FTDM_CPC_INVALID) { + ftdm_log(FTDM_LOG_WARNING, "Invalid category string (%s)\n", string); + val = FTDM_CPC_ORDINARY; + status = FTDM_FAIL; + } + + *target = val; + return status; +} + diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 1750d6d7d9..36b7632cb3 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -301,6 +301,9 @@ FTDM_STR2ENUM(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t, FTDM_ENUM_NAMES(USER_LAYER1_PROT_NAMES, USER_LAYER1_PROT_STRINGS) FTDM_STR2ENUM(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t, USER_LAYER1_PROT_NAMES, FTDM_USER_LAYER1_PROT_INVALID) +FTDM_ENUM_NAMES(CALLING_PARTY_CATEGORY_NAMES, CALLING_PARTY_CATEGORY_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_calling_party_category, ftdm_calling_party_category2str, ftdm_calling_party_category_t, CALLING_PARTY_CATEGORY_NAMES, FTDM_CPC_INVALID) + static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name); static const char *cut_path(const char *in) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 14eca429e8..efd58b0af5 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -380,11 +380,72 @@ static void ft_r2_answer_call(ftdm_channel_t *ftdmchan) R2CALL(ftdmchan)->answer_pending = 0; } +static __inline__ ftdm_calling_party_category_t ftdm_openr2_cpc_to_r2_ftdm_cpc(openr2_calling_party_category_t cpc) +{ + switch (cpc) { + case OR2_CALLING_PARTY_CATEGORY_UNKNOWN: + return FTDM_CPC_UNKNOWN; + + case OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER: + return FTDM_CPC_ORDINARY; + + case OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER: + return FTDM_CPC_PRIORITY; + + case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_SUBSCRIBER: + return FTDM_CPC_UNKNOWN; + + case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_PRIORITY_SUBSCRIBER: + return FTDM_CPC_UNKNOWN; + + case OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT: + return FTDM_CPC_TEST; + + case OR2_CALLING_PARTY_CATEGORY_PAY_PHONE: + return FTDM_CPC_PAYPHONE; + + case OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL: + return FTDM_CPC_OPERATOR; + } + return FTDM_CPC_INVALID; +} + +static __inline openr2_calling_party_category_t ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdm_calling_party_category_t cpc) +{ + switch (cpc) { + case FTDM_CPC_UNKNOWN: + return OR2_CALLING_PARTY_CATEGORY_UNKNOWN; + + case FTDM_CPC_OPERATOR: + return OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL; + + case FTDM_CPC_ORDINARY: + return OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; + + case FTDM_CPC_PRIORITY: + return OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER; + + case FTDM_CPC_DATA: + return OR2_CALLING_PARTY_CATEGORY_UNKNOWN; + + case FTDM_CPC_TEST: + return OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT; + + case FTDM_CPC_PAYPHONE: + return OR2_CALLING_PARTY_CATEGORY_PAY_PHONE; + + case FTDM_CPC_INVALID: + return OR2_CALLING_PARTY_CATEGORY_UNKNOWN; + } + return OR2_CALLING_PARTY_CATEGORY_UNKNOWN; +} + /* this function must be called with the chan mutex held! */ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) { openr2_call_status_t callstatus; ftdm_r2_data_t *r2data; + openr2_calling_party_category_t category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; r2data = ftdmchan->span->signal_data; @@ -397,6 +458,12 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) ft_r2_clean_call(ftdmchan->call_data); + if (ftdmchan->caller_data.cpc == FTDM_CPC_INVALID || ftdmchan->caller_data.cpc == FTDM_CPC_UNKNOWN) { + category = r2data->category; + } else { + category = ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdmchan->caller_data.cpc); + } + /* start io dump */ if (r2data->mf_dump_size) { ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_INPUT_DUMP, &r2data->mf_dump_size); @@ -406,7 +473,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) callstatus = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan, ftdmchan->caller_data.cid_num.digits, ftdmchan->caller_data.dnis.digits, - r2data->category); + category); if (callstatus) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n"); @@ -615,6 +682,7 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons } else { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); } + ftdmchan->caller_data.cpc = ftdm_openr2_cpc_to_r2_ftdm_cpc(category); } /* diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 56a9dc0577..dce130f5be 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -265,6 +265,21 @@ typedef enum { #define USER_LAYER1_PROT_STRINGS "V.110", "u-law", "a-law", "Invalid" FTDM_STR2ENUM_P(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t) +/*! Calling Party Category */ +typedef enum { + FTDM_CPC_UNKNOWN, + FTDM_CPC_OPERATOR, + FTDM_CPC_ORDINARY, + FTDM_CPC_PRIORITY, + FTDM_CPC_DATA, + FTDM_CPC_TEST, + FTDM_CPC_PAYPHONE, + FTDM_CPC_INVALID +} ftdm_calling_party_category_t; +#define CALLING_PARTY_CATEGORY_STRINGS "unknown", "operator", "ordinary", "priority", "data-call", "test-call", "payphone", "invalid" +FTDM_STR2ENUM_P(ftdm_str2ftdm_calling_party_category, ftdm_calling_party_category2str, ftdm_calling_party_category_t) + + /*! \brief Number abstraction */ typedef struct { char digits[25]; @@ -294,7 +309,8 @@ typedef struct ftdm_caller_data { ftdm_bearer_cap_t bearer_capability; /* user information layer 1 protocol */ ftdm_user_layer1_prot_t bearer_layer1; - ftdm_variable_container_t variables; /*! + * Ricardo Barroetaveña + * */ #ifndef __FTDM_CALL_UTILS_H__ @@ -114,5 +120,16 @@ FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t */ FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number); +/*! + * \brief Set the Calling Party Category from an enum + * + * \param cpc_string string value + * \param target the target to set value to + * + * \retval FTDM_SUCCESS success + * \retval FTDM_FAIL failure + */ +FT_DECLARE(ftdm_status_t) ftdm_set_calling_party_category(const char *string, uint8_t *target); + #endif /* __FTDM_CALL_UTILS_H__ */ From a1a50c87ece4c26a389a8a879a04d4616a2c9e0f Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 17 Dec 2010 19:33:43 -0500 Subject: [PATCH 041/179] freetdm: OPENZAP-123 - Restrict ANI presentation in ftmod_r2 (Patched by ric) --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index efd58b0af5..9a5a2b1295 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -33,6 +33,7 @@ * Contributors: * * Arnaldo Pereira + * Ricardo Barroetaveña * */ @@ -471,7 +472,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) } callstatus = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan, - ftdmchan->caller_data.cid_num.digits, + ftdmchan->caller_data.pres == FTDM_PRES_ALLOWED ? ftdmchan->caller_data.cid_num.digits : NULL, ftdmchan->caller_data.dnis.digits, category); From aa69927b8fec99064da113bd6181dd38e82e0d46 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 17 Dec 2010 20:04:30 -0500 Subject: [PATCH 042/179] freetdm: OPENZAP-124 - Add round robin hunting direction (Patched by Ric) --- libs/freetdm/mod_freetdm/mod_freetdm.c | 4 ++ libs/freetdm/src/ftdm_io.c | 41 +++++++++++++++++++- libs/freetdm/src/include/freetdm.h | 4 +- libs/freetdm/src/include/private/ftdm_core.h | 1 + 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 0615b3821b..7637932b79 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -1136,6 +1136,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi direction = FTDM_BOTTOM_UP; } else if (*argv[1] == 'a') { direction = FTDM_TOP_DOWN; + } else if (*argv[1] == 'r') { + direction = FTDM_RR_DOWN; + } else if (*argv[1] == 'R') { + direction = FTDM_RR_UP; } else { chan_id = atoi(argv[1]); } diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 36b7632cb3..94a01aa7ba 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1706,6 +1706,21 @@ static ftdm_status_t __inline__ get_best_rated(ftdm_channel_t **fchan, ftdm_chan return FTDM_SUCCESS; } +static uint32_t __inline__ rr_next(uint32_t last, uint32_t min, uint32_t max, ftdm_direction_t direction) +{ + uint32_t next = min; + + ftdm_log(FTDM_LOG_DEBUG, "last = %d, min = %d, max = %d\n", last, min, max); + + if (direction == FTDM_RR_DOWN) { + next = (last >= max) ? min : ++last; + } else { + next = (last <= min) ? max : --last; + } + return next; +} + + FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan) { int availability = -1; @@ -1748,6 +1763,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir if (direction == FTDM_TOP_DOWN) { i = 0; + } else if (direction == FTDM_RR_DOWN || direction == FTDM_RR_UP) { + i = rr_next(group->last_used_index, 0, group->chan_count - 1, direction); } else { i = group->chan_count-1; } @@ -1762,16 +1779,24 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir if (request_voice_channel(check, ftdmchan, caller_data, direction)) { status = FTDM_SUCCESS; + if (direction == FTDM_RR_UP || direction == FTDM_RR_DOWN) { + group->last_used_index = i; + } break; } calculate_best_rate(check, &best_rated, &best_rate); if (direction == FTDM_TOP_DOWN) { - if (i >= group->chan_count) { + if (i >= (group->chan_count - 1)) { break; } i++; + } else if (direction == FTDM_RR_DOWN || direction == FTDM_RR_UP) { + if (check == best_rated) { + group->last_used_index = i; + } + i = rr_next(i, 0, group->chan_count - 1, direction); } else { if (i == 0) { break; @@ -1850,6 +1875,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc if (direction == FTDM_TOP_DOWN) { i = 1; + } else if (direction == FTDM_RR_DOWN || direction == FTDM_RR_UP) { + i = rr_next(span->last_used_index, 1, span->chan_count, direction); } else { i = span->chan_count; } @@ -1860,6 +1887,10 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc if (i > span->chan_count) { break; } + } else if (direction == FTDM_RR_DOWN || direction == FTDM_RR_UP) { + if (i == span->last_used_index) { + break; + } } else { if (i == 0) { break; @@ -1873,6 +1904,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc if (request_voice_channel(check, ftdmchan, caller_data, direction)) { status = FTDM_SUCCESS; + if (direction == FTDM_RR_UP || direction == FTDM_RR_DOWN) { + span->last_used_index = i; + } break; } @@ -1880,6 +1914,11 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc if (direction == FTDM_TOP_DOWN) { i++; + } else if (direction == FTDM_RR_DOWN || direction == FTDM_RR_UP) { + if (check == best_rated) { + span->last_used_index = i; + } + i = rr_next(i, 1, span->chan_count, direction); } else { i--; } diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index dce130f5be..69b90f1acd 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -144,7 +144,9 @@ typedef enum { /*! \brief Hunting direction (when hunting for free channels) */ typedef enum { FTDM_TOP_DOWN, - FTDM_BOTTOM_UP + FTDM_BOTTOM_UP, + FTDM_RR_DOWN, + FTDM_RR_UP, } ftdm_direction_t; /*! \brief I/O channel type */ diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 9222da3a42..e8ee7156f8 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -493,6 +493,7 @@ struct ftdm_span { ftdm_trunk_type_t trunk_type; ftdm_analog_start_type_t start_type; ftdm_signal_type_t signal_type; + uint32_t last_used_index; /* Private signaling data. Do not touch unless you are a signaling module */ void *signal_data; fio_signal_cb_t signal_cb; From 6066993d21568fa60b5319943f58931767513d99 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Sat, 18 Dec 2010 02:24:28 +0100 Subject: [PATCH 043/179] ftmod_libpri: remove ftdm_channel_done(), only use ftdm_channel_close(). Signed-off-by: Stefan Knoblich --- .../src/ftmod/ftmod_libpri/ftmod_libpri.c | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 68f0e9e5a4..8cbc0f4f45 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -515,23 +515,17 @@ static __inline__ void state_advance(ftdm_channel_t *chan) switch (ftdm_channel_get_state(chan)) { case FTDM_CHANNEL_STATE_DOWN: { + ftdm_channel_t *chtmp = chan; chan->call_data = NULL; - ftdm_channel_done(chan); - /* - * Close channel completely, BRI PTMP will thank us - */ - if (ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_t *chtmp = chan; - if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - } else { - ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n", - ftdm_channel_get_span_id(chan), - ftdm_channel_get_id(chan)); - } + if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); + } else { + ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n", + ftdm_channel_get_span_id(chan), + ftdm_channel_get_id(chan)); } } break; From 2b0bba8e94fd352904e5bc46c802488aa1d538ce Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 17 Dec 2010 20:27:37 -0500 Subject: [PATCH 044/179] freetdm: add __USE_BSD to ftdm_os, needed by unistd.h for usleep() and string.h to define strcasecmp() add -Werror even when the compiler is unknown. This is just a work-around to gcc not being detected as GNU by our current standalone build (not bootstrapped through FreeSWITCH) --- libs/freetdm/Makefile.am | 5 +++-- libs/freetdm/configure.ac | 2 +- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 1 - libs/freetdm/src/include/ftdm_os.h | 5 ++++- libs/freetdm/src/testsangomaboost.c | 7 +------ 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index af26f7f2af..5e804b7505 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -49,6 +49,7 @@ if HAVE_SNG_ISDN INCS += -I/usr/include/sng_isdn endif +# we needed to separate CFLAGS in FTDM_COMPAT_CFLAGS and FTDM_CFLAGS due to -c99 which causes problems with wanpipe headers FTDM_COMPAT_CFLAGS = $(INCS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_COMPAT_CFLAGS@ @DEFS@ FTDM_CFLAGS = $(INCS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_CFLAGS@ @DEFS@ COMPILE = $(CC) $(FTDM_CFLAGS) @@ -183,8 +184,8 @@ ftmod_analog_em_la_LIBADD = libfreetdm.la if HAVE_LIBSANGOMA mod_LTLIBRARIES += ftmod_wanpipe.la ftmod_wanpipe_la_SOURCES = $(SRC)/ftmod/ftmod_wanpipe/ftmod_wanpipe.c -#some structures within Wanpipe drivers are not c99 compatible, so we need to compile ftmod_wanpipe -#without c99 flags +# some structures within Wanpipe drivers are not c99 compatible, so we need to compile ftmod_wanpipe +# without c99 flags, use FTDM_COMPAT_CFLAGS instead ftmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(FTDM_COMPAT_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe ftmod_wanpipe_la_LDFLAGS = -shared -module -avoid-version -lsangoma ftmod_wanpipe_la_LIBADD = libfreetdm.la diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 592dfd82a3..e26f10b0b2 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -82,7 +82,7 @@ sun) fi ;; *) - COMP_VENDOR_COMPAT_CFLAGS="-Wall -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes" + COMP_VENDOR_COMPAT_CFLAGS="-Wall -Werror -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes" COMP_VENDOR_CFLAGS="-std=c99 $COMP_VENDOR_COMPAT_CFLAGS" ;; esac diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index f40196499c..09208f8d2c 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -31,7 +31,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #include "private/ftdm_core.h" #include "ftmod_zt.h" diff --git a/libs/freetdm/src/include/ftdm_os.h b/libs/freetdm/src/include/ftdm_os.h index 5026bb7236..f3ebee9ea2 100644 --- a/libs/freetdm/src/include/ftdm_os.h +++ b/libs/freetdm/src/include/ftdm_os.h @@ -39,9 +39,12 @@ extern "C" { #endif +#if defined(__linux__) && !defined(__USE_BSD) +#define __USE_BSD +#endif + #include "ftdm_declare.h" #include "ftdm_threadmutex.h" - #include #ifndef __WINDOWS__ diff --git a/libs/freetdm/src/testsangomaboost.c b/libs/freetdm/src/testsangomaboost.c index b254a08bb8..b007fc186b 100644 --- a/libs/freetdm/src/testsangomaboost.c +++ b/libs/freetdm/src/testsangomaboost.c @@ -48,12 +48,7 @@ #include #include #include -#if defined(__linux__) && !defined(__USE_BSD) -#define __USE_BSD -#endif -#ifndef WIN32 -#include -#endif + #include "freetdm.h" From 282b156207ccae94c8d80efec72c106cf7e3b4f2 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Fri, 17 Dec 2010 21:25:45 -0600 Subject: [PATCH 045/179] windows tweak mod_say_pt add to vs2010 others not for now --- Freeswitch.2010.sln | 20 +++++++++++++++++++ src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj | 2 +- .../say/mod_say_pt/mod_say_pt.2010.vcxproj | 2 +- src/mod/say/mod_say_pt/mod_say_pt.vcproj | 2 +- w32/Setup/Setup.wixproj | 9 +++++++++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index 186969891a..edee701d51 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -707,6 +707,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_distributor", "src\mod\ EndProject Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Setup", "w32\Setup\Setup.wixproj", "{47213370-B933-487D-9F45-BCA26D7E2B6F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_say_pt", "src\mod\say\mod_say_pt\mod_say_pt.2010.vcxproj", "{7C22BDFF-CC09-400C-8A09-660733980028}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution All|Win32 = All|Win32 @@ -3619,6 +3621,23 @@ Global {47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x64 Setup.Build.0 = Release|x64 {47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x86 Setup.ActiveCfg = Release|x86 {47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x86 Setup.Build.0 = Release|x86 + {7C22BDFF-CC09-400C-8A09-660733980028}.All|Win32.ActiveCfg = Release|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.All|x64.ActiveCfg = Release|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.All|x64.Build.0 = Release|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.All|x64 Setup.ActiveCfg = Release|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.All|x86 Setup.ActiveCfg = Release|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.Debug|Win32.ActiveCfg = Debug|Win32 + {7C22BDFF-CC09-400C-8A09-660733980028}.Debug|Win32.Build.0 = Debug|Win32 + {7C22BDFF-CC09-400C-8A09-660733980028}.Debug|x64.ActiveCfg = Debug|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.Debug|x64.Build.0 = Debug|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.Debug|x86 Setup.ActiveCfg = Debug|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.Release|Win32.ActiveCfg = Release|Win32 + {7C22BDFF-CC09-400C-8A09-660733980028}.Release|Win32.Build.0 = Release|Win32 + {7C22BDFF-CC09-400C-8A09-660733980028}.Release|x64.ActiveCfg = Release|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.Release|x64.Build.0 = Release|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.Release|x64 Setup.ActiveCfg = Release|x64 + {7C22BDFF-CC09-400C-8A09-660733980028}.Release|x86 Setup.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3769,6 +3788,7 @@ Global {A4B122CF-5196-476B-8C0E-D8BD59AC3C14} = {6CD61A1D-797C-470A-BE08-8C31B68BB336} {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E} = {6CD61A1D-797C-470A-BE08-8C31B68BB336} {0382E8FD-CFDC-41C0-8B03-792C7C84FC31} = {6CD61A1D-797C-470A-BE08-8C31B68BB336} + {7C22BDFF-CC09-400C-8A09-660733980028} = {6CD61A1D-797C-470A-BE08-8C31B68BB336} {3B08FEFD-4D3D-4C16-BA94-EE83509E32A0} = {57D119DC-484F-420F-B9E9-8589FD9A8DF8} {7BFD517E-7F8F-4A40-A78E-8D3632738227} = {57D119DC-484F-420F-B9E9-8589FD9A8DF8} {6374D55C-FABE-4A02-9CF1-4145308A56C5} = {57D119DC-484F-420F-B9E9-8589FD9A8DF8} diff --git a/src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj b/src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj index bf8c0333c5..ee0fffde02 100644 --- a/src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj +++ b/src/mod/say/mod_say_pt/mod_say_pt.2008.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="9.00" Name="mod_say_pt" - ProjectGUID="{FA429E98-8B03-45E6-A096-A4BC5E821DE4}" + ProjectGUID="{7C22BDFF-CC09-400C-8A09-660733980028}" RootNamespace="mod_say_pt" Keyword="Win32Proj" TargetFrameworkVersion="131072" diff --git a/src/mod/say/mod_say_pt/mod_say_pt.2010.vcxproj b/src/mod/say/mod_say_pt/mod_say_pt.2010.vcxproj index 63fba6fae0..8c94e2cb65 100644 --- a/src/mod/say/mod_say_pt/mod_say_pt.2010.vcxproj +++ b/src/mod/say/mod_say_pt/mod_say_pt.2010.vcxproj @@ -20,7 +20,7 @@ mod_say_pt - {FA429E98-8B03-45E6-A096-A4BC5E821DE4} + {7C22BDFF-CC09-400C-8A09-660733980028} mod_say_pt Win32Proj diff --git a/src/mod/say/mod_say_pt/mod_say_pt.vcproj b/src/mod/say/mod_say_pt/mod_say_pt.vcproj index fb5d2dbab9..ce2a3344fc 100644 --- a/src/mod/say/mod_say_pt/mod_say_pt.vcproj +++ b/src/mod/say/mod_say_pt/mod_say_pt.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="8.00" Name="mod_say_pt" - ProjectGUID="{FA429E98-8B03-45E6-A096-A4BC5E821DE4}" + ProjectGUID="{7C22BDFF-CC09-400C-8A09-660733980028}" RootNamespace="mod_say_pt" Keyword="Win32Proj" > diff --git a/w32/Setup/Setup.wixproj b/w32/Setup/Setup.wixproj index fa6c832777..f97000b585 100644 --- a/w32/Setup/Setup.wixproj +++ b/w32/Setup/Setup.wixproj @@ -723,6 +723,15 @@ Binaries;Content;Satellites MODLOCATION + + mod_say_pt + {7c22bdff-cc09-400c-8a09-660733980028} + True + + + Binaries;Content;Satellites + MODLOCATION + mod_say_ru {0382e8fd-cfdc-41c0-8b03-792c7c84fc31} From 1f26f2f86ad63865a13df010cc3c62e34a2d6d55 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 17 Dec 2010 22:29:33 -0600 Subject: [PATCH 046/179] presence is a 4-letter word --- src/mod/endpoints/mod_sofia/sofia_presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 5d666f03ee..f0cade3e61 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -818,7 +818,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); switch_safe_free(sql); - if ((sql = switch_mprintf("select sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host," + if ((sql = switch_mprintf("select distinct sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host," "sip_subscriptions.sub_to_user,sip_subscriptions.sub_to_host,sip_subscriptions.event," "sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from," "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent," From fcd6c54162a6270554de3b037c03398d7655732c Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Sun, 19 Dec 2010 00:13:08 -0500 Subject: [PATCH 047/179] freetdm: fix attempt for OPENZAP-130 --- libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c | 9 ++++----- libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 12 ++++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c index fbe6ca0822..bfb67e4c78 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c @@ -127,9 +127,8 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen) } else { ftdm_log(FTDM_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id); } - - ftdm_clear_flag(spri, LPWRAP_PRI_READY); - return -1; + /* we cannot return -1, libpri seems to expect values >= 0 */ + return 0; } spri->errs = 0; res = (int)len; @@ -156,8 +155,8 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen) if (ftdm_channel_write(spri->dchan, buf, buflen, &len) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error); - ftdm_clear_flag(spri, LPWRAP_PRI_READY); - return -1; + /* we cannot return -1, libpri seems to expect values >= 0 */ + return 0; } #ifdef IODEBUG diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index 09208f8d2c..b16ead7a66 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -1152,6 +1152,7 @@ static FIO_WRITE_FUNCTION(zt_write) bytes += 2; } +tryagain: w = write(ftdmchan->sockfd, data, bytes); if (w >= 0) { @@ -1159,6 +1160,17 @@ static FIO_WRITE_FUNCTION(zt_write) return FTDM_SUCCESS; } + if (errno == ELAST) { + zt_event_t zt_event_id = 0; + if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event after ELAST on write: %s\n", strerror(errno)); + return FTDM_FAIL; + } + /* we should enqueue this event somewhere so it can be retrieved by the user, for now, dropping it to see what it is! */ + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dropping event %d to be able to write data\n", zt_event_id); + goto tryagain; + } + return FTDM_FAIL; } From dd4bad220ca1f4ddcacfe69e720e7d32b744b6f9 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Sun, 19 Dec 2010 12:55:55 -0500 Subject: [PATCH 048/179] freetdm: ftmod_libpri - update to use proper structure member for signaling status change notifications --- libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c | 5 ++--- libs/freetdm/src/include/freetdm.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 8cbc0f4f45..1d3c76d2e2 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -1397,8 +1397,7 @@ static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev sig.chan_id = ftdm_channel_get_id(chan); sig.channel = chan; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.raw_data = &status; - + sig.ev_data.sigstatus.status = status; ftdm_span_send_signal(span, &sig); } } @@ -1434,7 +1433,7 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ sig.chan_id = ftdm_channel_get_id(chan); sig.channel = chan; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.raw_data = &status; + sig.ev_data.sigstatus.status = status; ftdm_span_send_signal(span, &sig); } diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 69b90f1acd..a74fd7075a 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -438,7 +438,7 @@ struct ftdm_sigmsg { union { ftdm_event_sigstatus_t sigstatus; /*!< valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED */ ftdm_event_trace_t logevent; /*!< valid if event_id is FTDM_SIGEVENT_TRACE or FTDM_SIGEVENT_TRACE_RAW */ - }ev_data; + } ev_data; }; /*! \brief Crash policy From 299c139c3ec6c9b276cefce4d6f1568d0d7100dc Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Sun, 19 Dec 2010 13:40:27 -0600 Subject: [PATCH 049/179] skypopen: refined hrtimers support to OSS audio driver --- src/mod/endpoints/mod_skypopen/oss/main.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_skypopen/oss/main.c b/src/mod/endpoints/mod_skypopen/oss/main.c index 2abc5b342a..a96e38d68a 100644 --- a/src/mod/endpoints/mod_skypopen/oss/main.c +++ b/src/mod/endpoints/mod_skypopen/oss/main.c @@ -250,6 +250,10 @@ static ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count, { DEFINE_WAIT(wait); struct skypopen_dev *dev = filp->private_data; + + if(unload) + return -1; + #ifdef WANT_HRTIMER #if 1 if(dev->timer_inq_started == 0){ @@ -278,6 +282,10 @@ static ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t { DEFINE_WAIT(wait); struct skypopen_dev *dev = filp->private_data; + + if(unload) + return -1; + #ifdef WANT_HRTIMER #if 1 if(dev->timer_outq_started == 0){ @@ -372,10 +380,14 @@ void skypopen_cleanup_module(void) ret= del_timer( &lptr->device.timer_outq ); printk( "Stopped skypopen OSS driver write timer\n"); #else// WANT_HRTIMER - ret = hrtimer_cancel( &lptr->device.timer_inq ); - printk( "Stopped skypopen OSS driver read HRtimer\n"); - ret = hrtimer_cancel( &lptr->device.timer_outq ); - printk( "Stopped skypopen OSS driver write HRtimer\n"); + if(lptr->device.timer_inq_started){ + ret = hrtimer_cancel( &lptr->device.timer_inq ); + printk( "Stopped skypopen OSS driver read HRtimer\n"); + } + if(lptr->device.timer_outq_started){ + ret = hrtimer_cancel( &lptr->device.timer_outq ); + printk( "Stopped skypopen OSS driver write HRtimer\n"); + } #endif// WANT_HRTIMER list_del(&lptr->list); From b84b71defa49a715d04d9776a5f0c7040103d6db Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Sun, 19 Dec 2010 21:09:50 +0100 Subject: [PATCH 050/179] FreeTDM: Stop using raw_data for FTDM_SIGEVENT_SIGSTATUS_CHANGED events. The raw_data member is used for passing heap allocated data with an event, (e.g. strings of dtmf data) the memory is freed after the event has been processed. Recent changes in the event structure added a way to pass sig status changes inline, so remove the raw_data usage for FTDM_SIGEVENT_SIGSTATUS_CHANGED events. NOTE: This (finally) fixes a bug in ftmod_libpri that was caused by the event handling changes (stack corruption due to using free() on a variable on the stack, which turned into a NULL ptr deref caused by some compat code in ftdm_io.c:ftdm_span_send_signal(). Compiles and tested on my BRI setup, i did a quick audit of all places that generate FTDM_SIGEVENT_SIGSTATUS_CHANGED events and except for the sangoma_boost module there's nothing else that left using raw_data for this event. Signed-off-by: Stefan Knoblich --- libs/freetdm/mod_freetdm/mod_freetdm.c | 2 +- libs/freetdm/src/ftdm_io.c | 3 +-- .../src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 7637932b79..80006f1ae5 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -2086,7 +2086,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal) case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { - ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->ev_data.sigstatus.status; + ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to: %s\n", spanid, chanid, ftdm_signaling_status2str(sigstatus)); } diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 94a01aa7ba..297c08e5ea 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -5403,8 +5403,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { - ftdm_signaling_status_t sigstatus = ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE) ? sigmsg->ev_data.sigstatus.status : *((ftdm_signaling_status_t*)(sigmsg->raw_data)); - if (sigstatus == FTDM_SIG_STATE_UP) { + if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_UP) { ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); } else { ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index f59b3b8c4f..97e242dacb 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -2478,7 +2478,7 @@ static BOOST_SIG_STATUS_CB_FUNCTION(ftdm_boost_sig_status_change) sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.raw_data = &status; + sig.ev_data.sigstatus.status = status; ftdm_span_send_signal(ftdmchan->span, &sig); return; } From 1c4c84fc0ffdba48fd42154e7f0e85ddbb1c5ede Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Sun, 19 Dec 2010 21:38:55 +0100 Subject: [PATCH 051/179] Perl's Net::Skinny : update to current handle PACKED structs --- src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm b/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm index 90de304817..94708881e3 100644 --- a/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm +++ b/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm @@ -48,7 +48,7 @@ sub _find { my ($name, $value) = ($1,hex($2)); $sub{$name} = sub () { $value }; $const{$name} = $value; - } elsif(/^\s*struct\s+([a-z_]+)\s*\{\s*$/) { + } elsif(/^\s*struct\s+PACKED\s+([a-z_]+)\s*\{\s*$/) { my $struct_name = $1; $struct{$struct_name} = []; while(<$fh>) { From 709c4e5f9729dfad0862fa2daaf2f0687d04a56f Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Sun, 19 Dec 2010 22:16:09 +0100 Subject: [PATCH 052/179] Skinny: Event skinny::xml_alarm --- src/mod/endpoints/mod_skinny/mod_skinny.h | 1 + .../endpoints/mod_skinny/skinny_protocol.h | 3 +-- src/mod/endpoints/mod_skinny/skinny_server.c | 22 +++++++++++++++++++ src/mod/endpoints/mod_skinny/test-skinny.pl | 6 +++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h index b5cc96b7ae..20d68faba5 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.h +++ b/src/mod/endpoints/mod_skinny/mod_skinny.h @@ -42,6 +42,7 @@ #define SKINNY_EVENT_UNREGISTER "skinny::unregister" #define SKINNY_EVENT_EXPIRE "skinny::expire" #define SKINNY_EVENT_ALARM "skinny::alarm" +#define SKINNY_EVENT_XML_ALARM "skinny::xml_alarm" #define SKINNY_EVENT_CALL_STATE "skinny::call_state" #define SKINNY_EVENT_USER_TO_DEVICE "skinny::user_to_device" #define SKINNY_EVENT_DEVICE_TO_USER "skinny::device_to_user" diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index ee3c33a497..20e7d7f92f 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -627,8 +627,7 @@ union skinny_data { struct extended_data_message extended_data; uint16_t as_uint16; - char as_char; - void *raw; + char as_char[1]; }; /* diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index 9bf9d9fb9b..5874be4c6c 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -1963,6 +1963,26 @@ switch_status_t skinny_handle_extended_data_message(listener_t *listener, skinny return SWITCH_STATUS_SUCCESS; } +switch_status_t skinny_handle_xml_alarm(listener_t *listener, skinny_message_t *request) +{ + switch_event_t *event = NULL; + char *tmp = NULL; + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, + "Received XML alarm.\n"); + /* skinny::xml_alarm event */ + skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_XML_ALARM); + /* Ensure that the body is null-terminated */ + tmp = malloc(request->length - 4 + 1); + memcpy(tmp, request->data.as_char, request->length - 4); + tmp[request->length - 4] = '\0'; + switch_event_add_body(event, "%s", tmp); + switch_safe_free(tmp); + switch_event_fire(&event); + + return SWITCH_STATUS_SUCCESS; +} + switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *request) { if (listener->profile->debug >= 10 || request->type != KEEP_ALIVE_MESSAGE) { @@ -2032,6 +2052,8 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re return skinny_handle_extended_data_message(listener, request); case DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE: return skinny_handle_extended_data_message(listener, request); + case XML_ALARM_MESSAGE: + return skinny_handle_xml_alarm(listener, request); default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled request %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length); diff --git a/src/mod/endpoints/mod_skinny/test-skinny.pl b/src/mod/endpoints/mod_skinny/test-skinny.pl index a44afa33dc..02cf3cc2f6 100644 --- a/src/mod/endpoints/mod_skinny/test-skinny.pl +++ b/src/mod/endpoints/mod_skinny/test-skinny.pl @@ -34,6 +34,12 @@ if(!$socket) { exit 1; } # ============================================================================= +$socket->send_raw( + XML_ALARM_MESSAGE, + "\x0a\x0a\x0a\x0aSEP002699438F62\x0a192.168.3.201/24\x0a192.168.3.254\x0a\x0a\x0aCP-7961G\x0a192.168.0.253\x0a\x0asw2.wvds.local\x0a3\x0a1\x0a0\x0a0\x0a0\x0a0\x0a0\x0a4095\x0a\x0a-1\x0a1289313813826\x0a\x0a1:Register\x0a129:RegisterAck\x0a\x0a\x0a\x0a" + ); + $socket->sleep(20); + exit; $socket->send_message( REGISTER_MESSAGE, device_name => $device_name, From 9b70d9a7a565b7af2f6ee4511f687316d1ba5a48 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Sun, 19 Dec 2010 22:20:09 +0100 Subject: [PATCH 053/179] Revert perl's Net::Skinny test --- src/mod/endpoints/mod_skinny/test-skinny.pl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/test-skinny.pl b/src/mod/endpoints/mod_skinny/test-skinny.pl index 02cf3cc2f6..a44afa33dc 100644 --- a/src/mod/endpoints/mod_skinny/test-skinny.pl +++ b/src/mod/endpoints/mod_skinny/test-skinny.pl @@ -34,12 +34,6 @@ if(!$socket) { exit 1; } # ============================================================================= -$socket->send_raw( - XML_ALARM_MESSAGE, - "\x0a\x0a\x0a\x0aSEP002699438F62\x0a192.168.3.201/24\x0a192.168.3.254\x0a\x0a\x0aCP-7961G\x0a192.168.0.253\x0a\x0asw2.wvds.local\x0a3\x0a1\x0a0\x0a0\x0a0\x0a0\x0a0\x0a4095\x0a\x0a-1\x0a1289313813826\x0a\x0a1:Register\x0a129:RegisterAck\x0a\x0a\x0a\x0a" - ); - $socket->sleep(20); - exit; $socket->send_message( REGISTER_MESSAGE, device_name => $device_name, From f4d52d4caae78359b59d97bf596a269e47f4def3 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 20 Dec 2010 08:43:13 -0600 Subject: [PATCH 054/179] FS-2943: improve fail2ban logging --- src/mod/endpoints/mod_sofia/sofia_reg.c | 46 ++++++++++++------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 570e297f6d..945740eb57 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1139,30 +1139,24 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } if (auth_res != AUTH_OK && !stale) { - if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { - if (regtype == REG_REGISTER) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP auth %s (REGISTER) on sofia profile '%s' " - "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge", profile->name, to_user, to_host, network_ip); - } + if (auth_res == AUTH_FORBIDDEN) { + nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END()); + forbidden = 1; + } else { + nua_respond(nh, SIP_401_UNAUTHORIZED, NUTAG_WITH_THIS(nua), TAG_END()); } if (profile->debug) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s for [%s@%s]\n", forbidden ? "forbidden" : "challenge", to_user, to_host); } - if (auth_res == AUTH_FORBIDDEN) { - nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END()); - - /* Log line added to support Fail2Ban */ - if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { - if (regtype == REG_INVITE) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth failure (INVITE) on sofia profile '%s' " - "for [%s@%s] from ip %s\n", profile->name, to_user, to_host, network_ip); - } - } - } else { - nua_respond(nh, SIP_401_UNAUTHORIZED, NUTAG_WITH_THIS(nua), TAG_END()); + /* Log line added to support Fail2Ban */ + if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth %s (%s) on sofia profile '%s' " + "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge", + (regtype == REG_INVITE) ? "INVITE" : "REGISTER", profile->name, to_user, to_host, network_ip); } + switch_goto_int(r, 1, end); } } @@ -1193,14 +1187,18 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand realm = from_host; } - if (regtype == REG_REGISTER) { - sofia_reg_auth_challenge(nua, profile, nh, regtype, realm, stale); - if (profile->debug) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Requesting Registration from: [%s@%s]\n", to_user, to_host); - } - } else { - sofia_reg_auth_challenge(nua, profile, nh, regtype, realm, stale); + sofia_reg_auth_challenge(nua, profile, nh, regtype, realm, stale); + + if (profile->debug) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send challenge for [%s@%s]\n", to_user, to_host); } + /* Log line added to support Fail2Ban */ + if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth challenge (%s) on sofia profile '%s' " + "for [%s@%s] from ip %s\n", (regtype == REG_INVITE) ? "INVITE" : "REGISTER", + profile->name, to_user, to_host, network_ip); + } + switch_goto_int(r, 1, end); } reg: From 34690e47ff48f5c52b13cfb7b2c0226f3c0dc92e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 20 Dec 2010 11:16:14 -0600 Subject: [PATCH 055/179] FS-2879 --- src/mod/applications/mod_fifo/mod_fifo.c | 44 +++++++++++++++--------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 9d9896956e..e9d7cfb0e6 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1761,27 +1761,28 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, &var, NULL, &val); if ((node = (fifo_node_t *) val)) { + int x = 0; + switch_event_t *pop; if (node->ready == FIFO_DELAY_DESTROY) { - int doit = 0; - - switch_mutex_lock(node->update_mutex); - doit = node->consumer_count == 0 && node_caller_count(node) == 0; - switch_mutex_unlock(node->update_mutex); - - if (doit) { + if (switch_thread_rwlock_trywrlock(node->rwlock) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name); switch_core_hash_delete(globals.fifo_hash, node->name); + + for (x = 0; x < MAX_PRI; x++) { + while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) { + switch_event_destroy(&pop); + } + } node->ready = 0; - switch_mutex_lock(node->mutex); switch_core_hash_destroy(&node->consumer_hash); switch_mutex_unlock(node->mutex); switch_mutex_unlock(node->update_mutex); + switch_thread_rwlock_unlock(node->rwlock); switch_core_destroy_memory_pool(&node->pool); goto restart; } - } @@ -2172,7 +2173,7 @@ SWITCH_STANDARD_APP(fifo_function) char *mydata = NULL, *argv[5] = { 0 }; fifo_node_t *node = NULL, *node_list[MAX_NODES_PER_CONSUMER + 1] = { 0 }; switch_channel_t *channel = switch_core_session_get_channel(session); - int do_wait = 1, node_count = 0, i = 0; + int do_destroy = 0, do_wait = 1, node_count = 0, i = 0; const char *moh = NULL; const char *announce = NULL; switch_event_t *event = NULL; @@ -2247,13 +2248,10 @@ SWITCH_STANDARD_APP(fifo_function) if (!(node = switch_core_hash_find(globals.fifo_hash, nlist[i]))) { node = create_node(nlist[i], importance, globals.sql_mutex); node->ready = 1; - switch_thread_rwlock_rdlock(node->rwlock); } - node_list[node_count++] = node; - } - if (switch_true(switch_channel_get_variable(channel, "fifo_destroy_after_use")) && node->ready == 1) { - node->ready = FIFO_DELAY_DESTROY; + switch_thread_rwlock_rdlock(node->rwlock); + node_list[node_count++] = node; } switch_mutex_unlock(globals.mutex); @@ -3103,10 +3101,22 @@ SWITCH_STANDARD_APP(fifo_function) done: - if (node) { - switch_thread_rwlock_unlock(node->rwlock); + if (switch_true(switch_channel_get_variable(channel, "fifo_destroy_after_use"))) { + do_destroy = 1; } + switch_mutex_lock(globals.mutex); + for (i = 0; i < node_count; i++) { + if (!(node = node_list[i])) { + continue; + } + switch_thread_rwlock_unlock(node->rwlock); + if (node->ready == 1 && do_destroy) { + node->ready = FIFO_DELAY_DESTROY; + } + } + switch_mutex_unlock(globals.mutex); + switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG); switch_core_media_bug_resume(session); From a1a710482b8533d181bbf29eb67d2646036614ee Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 20 Dec 2010 12:15:41 -0600 Subject: [PATCH 056/179] freetdm windows build tweaks --- .../mod_freetdm/mod_freetdm.2010.vcxproj | 4 ++-- .../ftmod_sangoma_isdn.2008.vcproj | 10 +++++++--- .../ftmod_sangoma_isdn.2010.vcxproj | 18 +++++++++++++----- w32/Library/FreeSwitchCore.2010.vcxproj | 3 +-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj b/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj index 9f01a3b1a1..ec69333410 100644 --- a/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj +++ b/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj @@ -103,7 +103,7 @@ ProgramDatabase - FreeSwitch.lib;%(AdditionalDependencies) + FreeSwitchCore.lib;%(AdditionalDependencies) ../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) true $(OutDir)$(TargetName).pdb @@ -127,7 +127,7 @@ ProgramDatabase - FreeSwitch.lib;%(AdditionalDependencies) + FreeSwitchCore.lib;%(AdditionalDependencies) ../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) true $(OutDir)$(TargetName).pdb diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj index e3930d8188..2e7fb82041 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj @@ -40,11 +40,12 @@ Disabled - C:\Program Files\libsng_isdn\include;C:\Program Files\libsng_isdn\include\sng_isdn;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + C:\Program Files\sangoma\sng_isdn\include;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true @@ -95,10 +95,11 @@ Level3 EditAndContinue + MultiThreadedDebugDLL freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies) - $(OutDir);C:\Program Files\libsng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) + $(OutDir);C:\Program Files\sangoma\sng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) true Console false @@ -110,7 +111,7 @@ Disabled - C:\Program Files\libsng_isdn\include;C:\Program Files\libsng_isdn\include\sng_isdn;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + C:\Program Files\sangoma\sng_isdn\include;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -119,6 +120,7 @@ Level3 ProgramDatabase + MultiThreadedDebugDLL freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies) @@ -135,11 +137,13 @@ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks - MultiThreadedDebugDLL + MultiThreadedDLL Level3 ProgramDatabase + C:\Program Files\sangoma\sng_isdn\include;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) + Disabled true @@ -147,23 +151,27 @@ true true MachineX86 + freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies) + $(OutDir);C:\Program Files\sangoma\sng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks - MultiThreadedDebugDLL + MultiThreadedDLL Level3 ProgramDatabase + C:\Program Files\sangoma\sng_isdn\include;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories) true Windows true true + freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies) diff --git a/w32/Library/FreeSwitchCore.2010.vcxproj b/w32/Library/FreeSwitchCore.2010.vcxproj index e218445a02..c74ad944b1 100644 --- a/w32/Library/FreeSwitchCore.2010.vcxproj +++ b/w32/Library/FreeSwitchCore.2010.vcxproj @@ -120,8 +120,7 @@ false - - + $(OutDir)FreeSwitchCore.lib MachineX86 From b5b2f6134dcc06ba994b1f71d619b8b4a5626b1e Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 20 Dec 2010 14:06:54 -0500 Subject: [PATCH 057/179] freetdm: multiple fixes for the core and analog * Replace ftdm_channel_flag_t with defines. We reached the 32bit limit where does not seem reliable to keep using enum. * Flags member for ftdm_channel_t is now uint64_t * Added FTDM_CHANNEL_CALL_STARTED flag to indicate when the API user knows about a call * Refactored raw_data member for ftdm_sigmsg_t. If raw_data needs to be freed it must be requested explicitly through the autofree member * Added collected member to ftdm_sigmsg_t for FTDM_SIGEVENT_COLLECTED data instead of using raw_data * Created define FTDM_DIGITS_LIMIT for DNIS/ANI digits limit * Fix some stat checks and outdated code in ftmod_analog * Refactored ftdm_channel_get_history_str API to return the time offsets and time since last state change * Do not send FTDM_SIGEVENT_STOP and FTDM_SIGEVENT_RELEASED on calls that were never reported to the user --- libs/freetdm/mod_freetdm/mod_freetdm.c | 4 +- libs/freetdm/src/ftdm_io.c | 98 +++++++++++++------ .../src/ftmod/ftmod_analog/ftmod_analog.c | 37 ++++--- .../ftmod/ftmod_analog_em/ftmod_analog_em.c | 2 +- .../ftmod_sangoma_isdn_trace.c | 10 +- libs/freetdm/src/include/freetdm.h | 23 +++-- libs/freetdm/src/include/private/ftdm_core.h | 2 +- libs/freetdm/src/include/private/ftdm_types.h | 81 +++++++-------- 8 files changed, 153 insertions(+), 104 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 80006f1ae5..584ed27a83 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -1920,7 +1920,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal) case FTDM_SIGEVENT_COLLECTED_DIGIT: { int span_id = ftdm_channel_get_span_id(sigmsg->channel); - char *dtmf = sigmsg->raw_data; + char *dtmf = sigmsg->ev_data.collected.digits; char *regex = SPAN_CONFIG[span_id].dial_regex; char *fail_regex = SPAN_CONFIG[span_id].fail_dial_regex; ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel); @@ -2192,7 +2192,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) break; case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { - ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->ev_data.sigstatus.status; + ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to :%s\n", spanid, chanid, ftdm_signaling_status2str(sigstatus)); } diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0494ef8c0e..131d92ea92 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2512,17 +2512,20 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char ftdm_log(FTDM_LOG_ERROR, "outgoing_call method not implemented in this span!\n"); } + if (status == FTDM_SUCCESS) { + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED); + ftdm_call_set_call_id(&ftdmchan->caller_data); + ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100); + } + + ftdm_channel_unlock(ftdmchan); + #ifdef __WINDOWS__ UNREFERENCED_PARAMETER(file); UNREFERENCED_PARAMETER(func); UNREFERENCED_PARAMETER(line); #endif - ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100); - - ftdm_call_set_call_id(&ftdmchan->caller_data); - ftdm_channel_unlock(ftdmchan); - return status; } @@ -2633,7 +2636,7 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan) ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL); ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL); - if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { + if (FTDM_IS_VOICE_CHANNEL(ftdmchan) && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED)) { ftdm_sigmsg_t sigmsg; memset(&sigmsg, 0, sizeof(sigmsg)); sigmsg.span_id = ftdmchan->span_id; @@ -2642,6 +2645,7 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan) sigmsg.event_id = FTDM_SIGEVENT_RELEASED; ftdm_span_send_signal(ftdmchan->span, &sigmsg); ftdm_call_clear_call_id(&ftdmchan->caller_data); + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED); } if (ftdmchan->txdrops || ftdmchan->rxdrops) { @@ -3712,23 +3716,21 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data } status = ftdm_raw_read(ftdmchan, data, datalen); - if (status != FTDM_SUCCESS) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "raw I/O read filed\n"); + goto done; } - if (status == FTDM_SUCCESS) { - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN) - && (ftdmchan->native_codec == FTDM_CODEC_ALAW || ftdmchan->native_codec == FTDM_CODEC_ULAW)) { - unsigned char *rdata = data; - for (i = 0; i < *datalen; i++) { - rdata[i] = ftdmchan->rxgain_table[rdata[i]]; - } + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN) + && (ftdmchan->native_codec == FTDM_CODEC_ALAW || ftdmchan->native_codec == FTDM_CODEC_ULAW)) { + unsigned char *rdata = data; + for (i = 0; i < *datalen; i++) { + rdata[i] = ftdmchan->rxgain_table[rdata[i]]; } - handle_dtmf(ftdmchan, *datalen); } + handle_dtmf(ftdmchan, *datalen); - if (status == FTDM_SUCCESS && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) { if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) { codec_func = fio_ulaw2slin; } else if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_ALAW) { @@ -5333,7 +5335,6 @@ static void ftdm_group_add(ftdm_group_t *group) ftdm_mutex_unlock(globals.group_mutex); } - FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *name) { ftdm_group_t *new_group = NULL; @@ -5367,7 +5368,11 @@ static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigm if (sigmsg->channel) { ftdm_call_clear_data(&(sigmsg->channel->caller_data)); } - ftdm_safe_free(sigmsg->raw_data); + if (sigmsg->raw.autofree) { + ftdm_safe_free(sigmsg->raw.data); + sigmsg->raw.data = NULL; + sigmsg->raw.len = 0; + } return status; } @@ -5431,6 +5436,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t case FTDM_SIGEVENT_START: { + ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED); ftdm_call_set_call_id(&sigmsg->channel->caller_data); ftdm_set_echocancel_call_begin(sigmsg->channel); if (sigmsg->channel->dtmfdbg.requested) { @@ -5446,6 +5452,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t break; case FTDM_SIGEVENT_STOP: + if (!ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED)) { + /* this happens for FXS devices which blindly send SIGEVENT_STOP, we should fix it there ... */ + ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user never knew about a call in this channel\n"); + goto done; + } if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_USER_HANGUP)) { ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n"); goto done; @@ -6011,12 +6022,34 @@ FT_DECLARE(char *) ftdm_strndup(const char *str, ftdm_size_t inlen) return new; } -FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan) + +static void write_history_entry(const ftdm_channel_t *fchan, ftdm_stream_handle_t *stream, int i, ftdm_time_t *prevtime) { char func[255]; char line[255]; char states[255]; + const char *filename = NULL; + snprintf(states, sizeof(states), "%-5.15s => %-5.15s", ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state)); + snprintf(func, sizeof(func), "[%s]", fchan->history[i].func); + filename = strrchr(fchan->history[i].file, *FTDM_PATH_SEPARATOR); + if (!filename) { + filename = fchan->history[i].file; + } else { + filename++; + } + if (!(*prevtime)) { + *prevtime = fchan->history[i].time; + } + snprintf(line, sizeof(func), "[%s:%d]", filename, fchan->history[i].line); + stream->write_function(stream, "%-30.30s %-30.30s %-30.30s %lums\n", states, func, line, (fchan->history[i].time - *prevtime)); + *prevtime = fchan->history[i].time; +} + +FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan) +{ uint8_t i = 0; + ftdm_time_t currtime = 0; + ftdm_time_t prevtime = 0; ftdm_stream_handle_t stream = { 0 }; FTDM_STANDARD_STREAM(stream); @@ -6025,25 +6058,24 @@ FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan) return stream.data; } - stream.write_function(&stream, "%-30.30s %-30.30s %s", "-- States --", "-- Function --", "-- Location --\n"); + stream.write_function(&stream, "%-30.30s %-30.30s %-30.30s %s", + "-- States --", "-- Function --", "-- Location --", "-- Time Offset --\n"); for (i = fchan->hindex; i < ftdm_array_len(fchan->history); i++) { if (!fchan->history[i].file) { break; } - snprintf(states, sizeof(states), "%-5.15s => %-5.15s", ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state)); - snprintf(func, sizeof(func), "[%s]", fchan->history[i].func); - snprintf(line, sizeof(func), "[%s:%d]", fchan->history[i].file, fchan->history[i].line); - stream.write_function(&stream, "%-30.30s %-30.30s %s\n", states, func, line); + write_history_entry(fchan, &stream, i, &prevtime); } for (i = 0; i < fchan->hindex; i++) { - snprintf(states, sizeof(states), "%-5.15s => %-5.15s", ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state)); - snprintf(func, sizeof(func), "[%s]", fchan->history[i].func); - snprintf(line, sizeof(func), "[%s:%d]", fchan->history[i].file, fchan->history[i].line); - stream.write_function(&stream, "%-30.30s %-30.30s %s\n", states, func, line); + write_history_entry(fchan, &stream, i, &prevtime); } + currtime = ftdm_current_time_in_ms(); + + stream.write_function(&stream, "\nTime since last state change: %lums\n", (currtime - prevtime)); + return stream.data; } @@ -6074,15 +6106,23 @@ static ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data) static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data) { - ftdm_assert_return((caller_data->call_id && caller_data->call_id <= MAX_CALLIDS), FTDM_FAIL, "Clearing call with invalid call-id\n"); + if (caller_data->call_id) { + ftdm_assert_return((caller_data->call_id <= MAX_CALLIDS), FTDM_FAIL, "Cannot clear call with invalid call-id\n"); + } else { + /* there might not be a call at all */ + return FTDM_SUCCESS; + } + ftdm_mutex_lock(globals.call_id_mutex); if (globals.call_ids[caller_data->call_id]) { + ftdm_log(FTDM_LOG_DEBUG, "Cleared call with id %u\n", caller_data->call_id); caller_data->call_id = 0; globals.call_ids[caller_data->call_id] = NULL; } else { ftdm_log(FTDM_LOG_CRIT, "call-id did not exist %u\n", caller_data->call_id); } ftdm_mutex_unlock(globals.call_id_mutex); + return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c index f07f48b0d6..5b68098ed7 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c @@ -493,8 +493,10 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) if (ftdmchan->type == FTDM_CHAN_TYPE_FXS && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && - (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE - || ftdmchan->last_state == FTDM_CHANNEL_STATE_RING)) { + (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING + || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE + || ftdmchan->last_state == FTDM_CHANNEL_STATE_RING + || ftdmchan->last_state == FTDM_CHANNEL_STATE_UP)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); } else { ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; @@ -717,7 +719,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) dtmf_offset = strlen(dtmf); last_digit = elapsed; sig.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT; - sig.raw_data = dtmf; + ftdm_set_string(sig.ev_data.collected.digits, dtmf); if (ftdm_span_send_signal(ftdmchan->span, &sig) == FTDM_BREAK) { collecting = 0; } @@ -884,14 +886,14 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e { if (event->channel->type != FTDM_CHAN_TYPE_FXO) { ftdm_log_chan_msg(event->channel, FTDM_LOG_ERROR, "Cannot get a RING_START event on a non-fxo channel, please check your config.\n"); - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN); + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); goto end; } if (!event->channel->ring_count && (event->channel->state == FTDM_CHANNEL_STATE_DOWN && !ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD))) { if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID); + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID); } else { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RING); + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_RING); } event->channel->ring_count = 1; ftdm_mutex_unlock(event->channel->mutex); @@ -909,7 +911,12 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e } if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN); + if (event->channel->state == FTDM_CHANNEL_STATE_HANGUP && + ftdm_test_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_clear_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE); + /* we do not need to process HANGUP since the device also hangup already */ + } + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); } } @@ -917,16 +924,16 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e case FTDM_OOB_FLASH: { if (event->channel->state == FTDM_CHANNEL_STATE_CALLWAITING) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP); - ftdm_clear_flag_locked(event->channel, FTDM_CHANNEL_STATE_CHANGE); - ftdm_clear_flag_locked(event->channel->span, FTDM_SPAN_STATE_CHANGE); + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP); + ftdm_clear_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE); + ftdm_clear_flag(event->channel->span, FTDM_SPAN_STATE_CHANGE); event->channel->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0; } ftdm_channel_rotate_tokens(event->channel); if (ftdm_test_flag(event->channel, FTDM_CHANNEL_HOLD) && event->channel->token_count != 1) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP); + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP); } else { sig.event_id = FTDM_SIGEVENT_FLASH; ftdm_span_send_signal(span, &sig); @@ -940,12 +947,12 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e if (ftdm_test_flag(event->channel, FTDM_CHANNEL_RINGING)) { ftdm_channel_command(event->channel, FTDM_COMMAND_GENERATE_RING_OFF, NULL); } - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP); + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP); } else { if(!analog_data->max_dialstr) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_COLLECT); + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_COLLECT); } else { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DIALTONE); + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DIALTONE); } ftdm_mutex_unlock(event->channel->mutex); locked = 0; @@ -957,7 +964,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e ftdm_channel_command(event->channel, FTDM_COMMAND_ONHOOK, NULL); } } - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN); + ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); } } default: diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c index 886c4a8fec..843ac484a5 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c @@ -467,7 +467,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj) dtmf_offset = strlen(dtmf); last_digit = elapsed; sig.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT; - sig.raw_data = dtmf; + ftdm_set_string(sig.ev_data.collected.digits, dtmf); if (ftdm_span_send_signal(ftdmchan->span, &sig) == FTDM_BREAK) { collecting = 0; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c index c03976a1c2..8c421b0691 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c @@ -128,8 +128,9 @@ void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d ftdm_assert(raw_data, "Failed to malloc"); memcpy(raw_data, data, data_len); - sigev.raw_data = raw_data; - sigev.raw_data_len = data_len; + sigev.raw.data = raw_data; + sigev.raw.len = data_len; + sigev.raw.autofree = 1; ftdm_span_send_signal(signal_data->ftdm_span, &sigev); } @@ -235,8 +236,9 @@ void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d ftdm_assert(raw_data, "Failed to malloc"); memcpy(raw_data, data, data_len); - sigev.raw_data = raw_data; - sigev.raw_data_len = data_len; + sigev.raw.data = raw_data; + sigev.raw.len = data_len; + sigev.raw.autofree = 1; ftdm_span_send_signal(signal_data->ftdm_span, &sigev); } diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index a74fd7075a..79e873390e 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -281,16 +281,18 @@ typedef enum { #define CALLING_PARTY_CATEGORY_STRINGS "unknown", "operator", "ordinary", "priority", "data-call", "test-call", "payphone", "invalid" FTDM_STR2ENUM_P(ftdm_str2ftdm_calling_party_category, ftdm_calling_party_category2str, ftdm_calling_party_category_t) +/*! \brief Digit limit used in DNIS/ANI */ +#define FTDM_DIGITS_LIMIT 25 /*! \brief Number abstraction */ typedef struct { - char digits[25]; + char digits[FTDM_DIGITS_LIMIT]; uint8_t type; uint8_t plan; } ftdm_number_t; typedef void * ftdm_variable_container_t; - + /*! \brief Caller information */ typedef struct ftdm_caller_data { char cid_date[8]; /*!< Caller ID date */ @@ -299,10 +301,10 @@ typedef struct ftdm_caller_data { ftdm_number_t ani; /*!< ANI (Automatic Number Identification) */ ftdm_number_t dnis; /*!< DNIS (Dialed Number Identification Service) */ ftdm_number_t rdnis; /*!< RDNIS (Redirected Dialed Number Identification Service) */ - char aniII[25]; /*! ANI II */ + char aniII[FTDM_DIGITS_LIMIT]; /*! ANI II */ uint8_t screen; /*!< Screening */ uint8_t pres; /*!< Presentation*/ - char collected[25]; /*!< Collected digits so far */ + char collected[FTDM_DIGITS_LIMIT]; /*!< Collected digits so far */ int hangup_cause; /*!< Hangup cause */ char raw_data[1024]; /*!< Protocol specific raw caller data */ uint32_t raw_data_len; /*!< Raw data length */ @@ -426,19 +428,28 @@ typedef struct { uint8_t level; /* 1 for phy layer, 2 for q921/mtp2, 3 for q931/mtp3 */ } ftdm_event_trace_t; +typedef struct { + /* Digits collected */ + char digits[FTDM_DIGITS_LIMIT]; +} ftdm_event_collected_t; + /*! \brief Generic signaling message */ struct ftdm_sigmsg { ftdm_signal_event_t event_id; /*!< The type of message */ ftdm_channel_t *channel; /*!< Related channel */ uint32_t chan_id; /*!< easy access to chan id */ uint32_t span_id; /*!< easy access to span_id */ - void *raw_data; /*!< Message specific data if any */ - uint32_t raw_data_len; /*!< Data len in case is needed */ uint32_t call_id; /*!< unique call id for this call */ union { ftdm_event_sigstatus_t sigstatus; /*!< valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED */ ftdm_event_trace_t logevent; /*!< valid if event_id is FTDM_SIGEVENT_TRACE or FTDM_SIGEVENT_TRACE_RAW */ + ftdm_event_collected_t collected; /*!< valif if event_id is FTDM_SIGEVENT_COLLECTED_DIGIT */ } ev_data; + struct { + uint8_t autofree; /*!< Whether the freetdm core will free it after message delivery */ + uint32_t len; /*!< Data len */ + void *data; /*!< Signaling module specific data */ + } raw; }; /*! \brief Crash policy diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index e8ee7156f8..606a89fc77 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -411,7 +411,7 @@ struct ftdm_channel { uint32_t extra_id; ftdm_chan_type_t type; ftdm_socket_t sockfd; - uint32_t flags; + uint64_t flags; uint32_t pflags; uint32_t sflags; ftdm_alarm_flag_t alarm_flags; diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index f03c060e5a..6c521e3481 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -237,52 +237,41 @@ typedef enum { "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "RESET", "INVALID" FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t) -typedef enum { - FTDM_CHANNEL_CONFIGURED = (1 << 0), - FTDM_CHANNEL_READY = (1 << 1), - FTDM_CHANNEL_OPEN = (1 << 2), - FTDM_CHANNEL_DTMF_DETECT = (1 << 3), - FTDM_CHANNEL_SUPRESS_DTMF = (1 << 4), - FTDM_CHANNEL_TRANSCODE = (1 << 5), - FTDM_CHANNEL_BUFFER = (1 << 6), - FTDM_CHANNEL_EVENT = (1 << 7), - FTDM_CHANNEL_INTHREAD = (1 << 8), - FTDM_CHANNEL_WINK = (1 << 9), - FTDM_CHANNEL_FLASH = (1 << 10), - FTDM_CHANNEL_STATE_CHANGE = (1 << 11), - FTDM_CHANNEL_HOLD = (1 << 12), - FTDM_CHANNEL_INUSE = (1 << 13), - FTDM_CHANNEL_OFFHOOK = (1 << 14), - FTDM_CHANNEL_RINGING = (1 << 15), - FTDM_CHANNEL_PROGRESS_DETECT = (1 << 16), - FTDM_CHANNEL_CALLERID_DETECT = (1 << 17), - FTDM_CHANNEL_OUTBOUND = (1 << 18), - FTDM_CHANNEL_SUSPENDED = (1 << 19), - FTDM_CHANNEL_3WAY = (1 << 20), - FTDM_CHANNEL_PROGRESS = (1 << 21), - FTDM_CHANNEL_MEDIA = (1 << 22), - FTDM_CHANNEL_ANSWERED = (1 << 23), - FTDM_CHANNEL_MUTE = (1 << 24), - FTDM_CHANNEL_USE_RX_GAIN = (1 << 25), - FTDM_CHANNEL_USE_TX_GAIN = (1 << 26), - FTDM_CHANNEL_IN_ALARM = (1 << 27), - FTDM_CHANNEL_SIG_UP = (1 << 28), - FTDM_CHANNEL_USER_HANGUP = (1 << 29), - FTDM_CHANNEL_RX_DISABLED = (1 << 30), - FTDM_CHANNEL_TX_DISABLED = (1 << 31), - /* ok, when we reach 32, we need to move to uint64_t all the flag stuff */ -} ftdm_channel_flag_t; -#if defined(__cplusplus) && defined(WIN32) - // fix C2676 -__inline__ ftdm_channel_flag_t operator|=(ftdm_channel_flag_t a, int32_t b) { - a = (ftdm_channel_flag_t)(a | b); - return a; -} -__inline__ ftdm_channel_flag_t operator&=(ftdm_channel_flag_t a, int32_t b) { - a = (ftdm_channel_flag_t)(a & b); - return a; -} -#endif +/*!< Channel flags. This used to be an enum but we reached the 32bit limit for enums */ +#define FTDM_CHANNEL_CONFIGURED (1UL << 0) +#define FTDM_CHANNEL_READY (1UL << 1) +#define FTDM_CHANNEL_OPEN (1UL << 2) +#define FTDM_CHANNEL_DTMF_DETECT (1UL << 3) +#define FTDM_CHANNEL_SUPRESS_DTMF (1UL << 4) +#define FTDM_CHANNEL_TRANSCODE (1UL << 5) +#define FTDM_CHANNEL_BUFFER (1UL << 6) +#define FTDM_CHANNEL_EVENT (1UL << 7) +#define FTDM_CHANNEL_INTHREAD (1UL << 8) +#define FTDM_CHANNEL_WINK (1UL << 9) +#define FTDM_CHANNEL_FLASH (1UL << 10) +#define FTDM_CHANNEL_STATE_CHANGE (1UL << 11) +#define FTDM_CHANNEL_HOLD (1UL << 12) +#define FTDM_CHANNEL_INUSE (1UL << 13) +#define FTDM_CHANNEL_OFFHOOK (1UL << 14) +#define FTDM_CHANNEL_RINGING (1UL << 15) +#define FTDM_CHANNEL_PROGRESS_DETECT (1UL << 16) +#define FTDM_CHANNEL_CALLERID_DETECT (1UL << 17) +#define FTDM_CHANNEL_OUTBOUND (1UL << 18) +#define FTDM_CHANNEL_SUSPENDED (1UL << 19) +#define FTDM_CHANNEL_3WAY (1UL << 20) +#define FTDM_CHANNEL_PROGRESS (1UL << 21) +#define FTDM_CHANNEL_MEDIA (1UL << 22) +#define FTDM_CHANNEL_ANSWERED (1UL << 23) +#define FTDM_CHANNEL_MUTE (1UL << 24) +#define FTDM_CHANNEL_USE_RX_GAIN (1UL << 25) +#define FTDM_CHANNEL_USE_TX_GAIN (1UL << 26) +#define FTDM_CHANNEL_IN_ALARM (1UL << 27) +#define FTDM_CHANNEL_SIG_UP (1UL << 28) +#define FTDM_CHANNEL_USER_HANGUP (1UL << 29) +#define FTDM_CHANNEL_RX_DISABLED (1UL << 30) +#define FTDM_CHANNEL_TX_DISABLED (1UL << 31) +/*!< The user knows about a call in this channel */ +#define FTDM_CHANNEL_CALL_STARTED (1UL << 32) typedef enum { ZSM_NONE, From cfd6876c2127bd64b7c2ced80407b5b9f962549b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 20 Dec 2010 14:36:03 -0600 Subject: [PATCH 058/179] more presence and not the kind with bows and ribbons --- src/mod/endpoints/mod_sofia/sofia_presence.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index f0cade3e61..059018986c 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -840,10 +840,11 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "where sip_subscriptions.expires > -1 and " "(event='%q' or event='%q') and sub_to_user='%q' " "and (sub_to_host='%q' or presence_hosts like '%%%q%%') " - "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host)", + "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host) " + "and (presence_id is null or presence_id = '%q@%q')", switch_str_nil(status), switch_str_nil(rpid), host, dh.status,dh.rpid, - event_type, alt_event_type, euser, host, host, profile->name))) { + event_type, alt_event_type, euser, host, host, profile->name, euser, host))) { struct presence_helper helper = { 0 }; From 82ad5278b3fac8adeebbb32bf155d024d423c43c Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 20 Dec 2010 14:55:18 -0600 Subject: [PATCH 059/179] tweak vs2010 freetdm wanpipe --- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj index b165ac82d3..40d0a73a5b 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2010.vcxproj @@ -100,7 +100,7 @@ EditAndContinue - freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + libsangoma.lib;%(AdditionalDependencies) $(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) true Console @@ -127,7 +127,7 @@ ProgramDatabase - freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + libsangoma.lib;%(AdditionalDependencies) $(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories) true Console @@ -148,7 +148,7 @@ ProgramDatabase - freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + libsangoma.lib;%(AdditionalDependencies) $(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories) true Console @@ -174,7 +174,7 @@ ProgramDatabase - freetdm.lib;libsangoma.lib;%(AdditionalDependencies) + libsangoma.lib;%(AdditionalDependencies) $(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories) true Console From a78922a21221b1c88ebfe0093c7a55bb4bfd6be7 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 20 Dec 2010 15:05:07 -0600 Subject: [PATCH 060/179] nope --- src/mod/endpoints/mod_sofia/sofia_presence.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 059018986c..f0cade3e61 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -840,11 +840,10 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "where sip_subscriptions.expires > -1 and " "(event='%q' or event='%q') and sub_to_user='%q' " "and (sub_to_host='%q' or presence_hosts like '%%%q%%') " - "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host) " - "and (presence_id is null or presence_id = '%q@%q')", + "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host)", switch_str_nil(status), switch_str_nil(rpid), host, dh.status,dh.rpid, - event_type, alt_event_type, euser, host, host, profile->name, euser, host))) { + event_type, alt_event_type, euser, host, host, profile->name))) { struct presence_helper helper = { 0 }; From 38968d15fe3250bb86751ebb099fd6844c6346d3 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 20 Dec 2010 16:15:41 -0500 Subject: [PATCH 061/179] freetdm: fake signaling status notifications in ftmod_analog --- libs/freetdm/mod_freetdm/mod_freetdm.c | 1 + .../src/ftmod/ftmod_analog/ftmod_analog.c | 39 ++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 584ed27a83..7e099853a6 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -1731,6 +1731,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal) } break; case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break; + case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { /* twiddle */ } break; default: { diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c index 5b68098ed7..0acf70b18d 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c @@ -96,6 +96,10 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call) static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_get_channel_sig_status) { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { + *status = FTDM_SIG_STATE_DOWN; + return FTDM_SUCCESS; + } *status = FTDM_SIG_STATE_UP; return FTDM_SUCCESS; } @@ -109,7 +113,25 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_get_channel_sig_status) static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_get_span_sig_status) { - *status = FTDM_SIG_STATE_UP; + ftdm_iterator_t *citer = NULL; + ftdm_iterator_t *chaniter = ftdm_span_get_chan_iterator(span, NULL); + if (!chaniter) { + ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); + return FTDM_FAIL; + } + /* if ALL channels are in alarm, report DOWN, UP otherwise. */ + *status = FTDM_SIG_STATE_DOWN; + for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { + ftdm_channel_t *fchan = ftdm_iterator_current(citer); + ftdm_channel_lock(fchan); + if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) { + *status = FTDM_SIG_STATE_UP; + ftdm_channel_unlock(fchan); + break; + } + ftdm_channel_unlock(fchan); + } + ftdm_iterator_free(chaniter); return FTDM_SUCCESS; } @@ -967,6 +989,21 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); } } + break; + case FTDM_OOB_ALARM_TRAP: + { + sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sig.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN; + ftdm_span_send_signal(span, &sig); + } + break; + case FTDM_OOB_ALARM_CLEAR: + { + sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sig.ev_data.sigstatus.status = FTDM_SIG_STATE_UP; + ftdm_span_send_signal(span, &sig); + } + break; default: { ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "Ignoring event [%s] in state [%s]\n", ftdm_oob_event2str(event->enum_id), ftdm_channel_state2str(event->channel->state)); From f804c75d99598cfce0d4e09c0fcef40bd8827f9d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 20 Dec 2010 15:43:54 -0600 Subject: [PATCH 062/179] presence was drafted by satan --- src/mod/endpoints/mod_sofia/sofia_presence.c | 31 +++++++++----------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index f0cade3e61..4b93492eae 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -55,6 +55,7 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * struct dialog_helper { char status[512]; char rpid[512]; + char presence_id[1024]; }; struct resub_helper { @@ -479,9 +480,10 @@ static int sofia_presence_dialog_callback(void *pArg, int argc, char **argv, cha { struct dialog_helper *helper = (struct dialog_helper *) pArg; - if (argc == 2) { + if (argc == 3) { switch_set_string(helper->status, argv[0]); switch_set_string(helper->rpid, argv[1]); + switch_set_string(helper->presence_id, argv[2]); } return -1; @@ -638,7 +640,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) } if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) { - sql = switch_mprintf("select status,rpid from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", + sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs " + "where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", probe_euser, probe_host, probe_euser, probe_host); sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); @@ -656,16 +659,16 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "sip_dialogs.direction, " "sip_dialogs.sip_to_user, " "sip_dialogs.sip_to_host, " + "sip_presence.status," "sip_presence.rpid," "sip_dialogs.presence_id, " "sip_presence.open_closed," "'%q','%q' " + "from sip_registrations " - "from sip_registrations left join sip_dialogs on " + "left join sip_dialogs on " "sip_dialogs.presence_id = sip_registrations.sip_user || '@' || sip_registrations.sip_host " - - "or (sip_dialogs.sip_from_user = sip_registrations.sip_user " "and sip_dialogs.sip_from_host = sip_registrations.sip_host) " @@ -813,7 +816,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } - sql = switch_mprintf("select status,rpid from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", + sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", euser, host, euser, host); sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); switch_safe_free(sql); @@ -824,25 +827,19 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent," "sip_subscriptions.accept,sip_subscriptions.profile_name" ",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q'," - "sip_subscriptions.version, sip_dialogs.presence_id " + "sip_subscriptions.version, '%q' " "from sip_subscriptions " "left join sip_presence on " "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and " "sip_subscriptions.profile_name=sip_presence.profile_name) " - "left join sip_dialogs on " - - "sip_dialogs.presence_id = sip_subscriptions.sub_to_user || '@' || sip_subscriptions.sub_to_host or " - - - "(sip_dialogs.sip_from_user = sip_subscriptions.sub_to_user " - "and sip_dialogs.sip_from_host = sip_subscriptions.sub_to_host) " "where sip_subscriptions.expires > -1 and " "(event='%q' or event='%q') and sub_to_user='%q' " "and (sub_to_host='%q' or presence_hosts like '%%%q%%') " - "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host)", - switch_str_nil(status), switch_str_nil(rpid), host, - dh.status,dh.rpid, + "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host) ", + + switch_str_nil(status), switch_str_nil(rpid), host, + dh.status,dh.rpid,dh.presence_id, event_type, alt_event_type, euser, host, host, profile->name))) { struct presence_helper helper = { 0 }; From 092d22a2142e00245c93f9a5a6592176c00188a8 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 20 Dec 2010 16:57:01 -0500 Subject: [PATCH 063/179] freetdm: fix get caller id command --- libs/freetdm/src/ftdm_io.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 131d92ea92..c04dd85a17 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2780,7 +2780,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); GOTO_STATUS(done, FTDM_FAIL); } - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT); + GOTO_STATUS(done, FTDM_SUCCESS); } } break; @@ -2788,7 +2789,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co { if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CALLERID)) { ftdm_fsk_demod_destroy(&ftdmchan->fsk); - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT); + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT); + GOTO_STATUS(done, FTDM_SUCCESS); } } break; @@ -3051,7 +3053,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co case FTDM_COMMAND_DISABLE_PROGRESS_DETECT: { if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_PROGRESS)) { - ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT); + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT); ftdm_channel_clear_detected_tones(ftdmchan); ftdm_channel_clear_needed_tones(ftdmchan); GOTO_STATUS(done, FTDM_SUCCESS); @@ -3063,8 +3065,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co /* if they don't have thier own, use ours */ if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); - ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n"); GOTO_STATUS(done, FTDM_SUCCESS); } From d29d83d74323fda1d8c6c50627dab5504c8441b8 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 20 Dec 2010 19:23:13 -0600 Subject: [PATCH 064/179] ESL-53 Noevent/Noevents disparity --- libs/esl/fs_cli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 569e2cd169..1e3bf04ca1 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -656,7 +656,7 @@ static int process_command(esl_handle_t *handle, const char *cmd) "-----------------------------------------------\n" "/help \tHelp\n" "/exit, /quit, /bye, ... \tExit the program.\n" - "/event, /noevent, /nixevent\tEvent commands.\n" + "/event, /noevents, /nixevent\tEvent commands.\n" "/log, /nolog \tLog commands.\n" "/uuid \tFilter logs for a single call uuid\n" "/filter \tFilter commands.\n" @@ -692,7 +692,7 @@ static int process_command(esl_handle_t *handle, const char *cmd) } else if ( !strncasecmp(cmd, "event", 5) || - !strncasecmp(cmd, "noevent", 7) || + !strncasecmp(cmd, "noevents", 8) || !strncasecmp(cmd, "nixevent", 8) || !strncasecmp(cmd, "log", 3) || !strncasecmp(cmd, "nolog", 5) || From 1b1dea020675d588053f0051b5236dd60d115b08 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 20 Dec 2010 20:19:36 -0600 Subject: [PATCH 065/179] FS-2879 --- src/switch_ivr_bridge.c | 4 ---- src/switch_ivr_originate.c | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 2f2dcdbc95..aa5ddb9232 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1052,8 +1052,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_signal_bridge(switch_core_session_t * switch_channel_set_variable(caller_channel, "signal_bridge", "true"); switch_channel_set_variable(peer_channel, "signal_bridge", "true"); - switch_channel_sort_cid(peer_channel, SWITCH_FALSE); - /* fire events that will change the data table from "show channels" */ if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(caller_channel, event); @@ -1119,8 +1117,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_channel_set_flag_recursive(caller_channel, CF_BRIDGE_ORIGINATOR); switch_channel_clear_flag(peer_channel, CF_BRIDGE_ORIGINATOR); - switch_channel_sort_cid(peer_channel, SWITCH_FALSE); - b_leg->session = peer_session; switch_copy_string(b_leg->b_uuid, switch_core_session_get_uuid(session), sizeof(b_leg->b_uuid)); b_leg->stream_id = stream_id; diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 87a47e65aa..51032dec60 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -2410,6 +2410,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } } + new_profile->callee_id_name = switch_core_strdup(new_profile->pool, "Outbound Call"); + new_profile->callee_id_number = switch_core_strdup(new_profile->pool, new_profile->destination_number); + originate_status[i].caller_profile = NULL; originate_status[i].peer_channel = NULL; originate_status[i].peer_session = NULL; From 4f9dd5e164b355d8b116a5f3cb0f0271c3366d10 Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Mon, 20 Dec 2010 23:57:45 -0500 Subject: [PATCH 066/179] mod_conference: Add XML output for conference run time, recording status and member mute-detect. Also add events for recording start and stop. This work was funded by Xpander Communications. --- .../mod_conference/mod_conference.c | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 53ce82b4cb..cf8ae96da0 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -191,7 +191,8 @@ typedef enum { EFLAG_TRANSFER = (1 << 23), EFLAG_BGDIAL_RESULT = (1 << 24), EFLAG_FLOOR_CHANGE = (1 << 25), - EFLAG_MUTE_DETECT = (1 << 26) + EFLAG_MUTE_DETECT = (1 << 26), + EFLAG_RECORD = (1 << 27) } event_type_t; typedef struct conference_file_node { @@ -270,6 +271,7 @@ typedef struct conference_obj { uint32_t not_talking_buf_len; int comfort_noise_level; int is_recording; + int record_count; int video_running; uint32_t eflags; uint32_t verbose_events; @@ -283,6 +285,7 @@ typedef struct conference_obj { uint32_t avg_score; uint32_t avg_itt; uint32_t avg_tally; + switch_time_t run_time; } conference_obj_t; /* Relationship with another member */ @@ -468,6 +471,7 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Hear", "%s", switch_test_flag(member, MFLAG_CAN_HEAR) ? "true" : "false" ); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speak", "%s", switch_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false" ); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Talking", "%s", switch_test_flag(member, MFLAG_TALKING) ? "true" : "false" ); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Mute-Detect", "%s", switch_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false" ); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Type", "%s", switch_test_flag(member, MFLAG_MOD) ? "moderator" : "member"); @@ -563,6 +567,7 @@ static switch_status_t conference_record_stop(conference_obj_t *conference, char return count; } + /* Add a custom relationship to a member */ static conference_relationship_t *member_add_relationship(conference_member_t *member, uint32_t id) { @@ -1035,6 +1040,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v switch_mutex_unlock(globals.hash_mutex); conference->is_recording = 0; + conference->record_count = 0; while (globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) { switch_size_t file_sample_len = samples; @@ -1099,6 +1105,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v /* Start recording if there's more than one participant. */ if (conference->auto_record && !conference->is_recording && conference->count > 1) { conference->is_recording = 1; + conference->record_count++; imember = conference->members; if (imember) { switch_channel_t *channel = switch_core_session_get_channel(imember->session); @@ -2623,6 +2630,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th switch_timer_t timer = { 0 }; uint32_t rlen; switch_size_t data_buf_len; + switch_event_t *event; data_buf_len = samples * sizeof(int16_t); @@ -2701,6 +2709,15 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th switch_core_file_set_string(&fh, SWITCH_AUDIO_COL_STR_ARTIST, "FreeSWITCH mod_conference Software Conference Module"); + if (test_eflag(conference, EFLAG_RECORD) && + switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + conference_add_event_data(conference, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "start-recording"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Path", rec->path); + switch_event_fire(&event); + } + + while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count) { switch_size_t len = 0; mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer); @@ -3759,6 +3776,13 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer switch_xml_set_attr_d(x_conference, "dynamic", "true"); } + if (conference->record_count > 0) { + switch_xml_set_attr_d(x_conference, "recording", "true"); + } + + switch_snprintf(i, sizeof(i), "%d", switch_epoch_time_now(NULL) - conference->run_time); + switch_xml_set_attr_d(x_conference, "run_time", ival); + if (conference->agc_level) { char tmp[30] = ""; switch_snprintf(tmp, sizeof(tmp), "%d", conference->agc_level); @@ -3825,6 +3849,9 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer x_tag = switch_xml_add_child_d(x_flags, "can_speak", count++); switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false"); + x_tag = switch_xml_add_child_d(x_flags, "mute_detect", count++); + switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false"); + x_tag = switch_xml_add_child_d(x_flags, "talking", count++); switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_TALKING) ? "true" : "false"); @@ -4414,6 +4441,7 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_ return SWITCH_STATUS_GENERR; stream->write_function(stream, "Record file %s\n", argv[2]); + conference->record_count++; launch_conference_record_thread(conference, argv[2]); return SWITCH_STATUS_SUCCESS; } @@ -4421,6 +4449,7 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv) { int all; + switch_event_t *event; switch_assert(conference != NULL); switch_assert(stream != NULL); @@ -4432,6 +4461,20 @@ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switc stream->write_function(stream, "Stop recording file %s\n", argv[2]); if (!conference_record_stop(conference, all ? NULL : argv[2]) && !all) { stream->write_function(stream, "non-existant recording '%s'\n", argv[2]); + } else { + if (all) { + conference->record_count = 0; + } else { + conference->record_count--; + } + if (test_eflag(conference, EFLAG_RECORD) && + switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + conference_add_event_data(conference, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "stop-recording"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Path", all ? "all" : argv[2]); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Recordings", conference->record_count ? "true" : "false"); + switch_event_fire(&event); + } } return SWITCH_STATUS_SUCCESS; @@ -5138,6 +5181,8 @@ static void clear_eflags(char *events, uint32_t *f) *f &= ~EFLAG_BGDIAL_RESULT; } else if (!strcmp(event, "floor-change")) { *f &= ~EFLAG_FLOOR_CHANGE; + } else if (!strcmp(event, "record")) { + *f &= ~EFLAG_RECORD; } event = next; @@ -6121,6 +6166,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m conference->caller_id_name = switch_core_strdup(conference->pool, caller_id_name); conference->caller_id_number = switch_core_strdup(conference->pool, caller_id_number); conference->caller_controls = switch_core_strdup(conference->pool, caller_controls); + conference->run_time = switch_epoch_time_now(NULL); if (!zstr(perpetual_sound)) { From 1d7a1bd1311fe633669c7d48ba65e51ccbff24db Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 21 Dec 2010 08:57:11 -0500 Subject: [PATCH 067/179] freetdm: use ULL for flags --- libs/freetdm/src/include/private/ftdm_types.h | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index 6c521e3481..b7c6d4a6f3 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -237,41 +237,41 @@ typedef enum { "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "RESET", "INVALID" FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t) -/*!< Channel flags. This used to be an enum but we reached the 32bit limit for enums */ -#define FTDM_CHANNEL_CONFIGURED (1UL << 0) -#define FTDM_CHANNEL_READY (1UL << 1) -#define FTDM_CHANNEL_OPEN (1UL << 2) -#define FTDM_CHANNEL_DTMF_DETECT (1UL << 3) -#define FTDM_CHANNEL_SUPRESS_DTMF (1UL << 4) -#define FTDM_CHANNEL_TRANSCODE (1UL << 5) -#define FTDM_CHANNEL_BUFFER (1UL << 6) -#define FTDM_CHANNEL_EVENT (1UL << 7) -#define FTDM_CHANNEL_INTHREAD (1UL << 8) -#define FTDM_CHANNEL_WINK (1UL << 9) -#define FTDM_CHANNEL_FLASH (1UL << 10) -#define FTDM_CHANNEL_STATE_CHANGE (1UL << 11) -#define FTDM_CHANNEL_HOLD (1UL << 12) -#define FTDM_CHANNEL_INUSE (1UL << 13) -#define FTDM_CHANNEL_OFFHOOK (1UL << 14) -#define FTDM_CHANNEL_RINGING (1UL << 15) -#define FTDM_CHANNEL_PROGRESS_DETECT (1UL << 16) -#define FTDM_CHANNEL_CALLERID_DETECT (1UL << 17) -#define FTDM_CHANNEL_OUTBOUND (1UL << 18) -#define FTDM_CHANNEL_SUSPENDED (1UL << 19) -#define FTDM_CHANNEL_3WAY (1UL << 20) -#define FTDM_CHANNEL_PROGRESS (1UL << 21) -#define FTDM_CHANNEL_MEDIA (1UL << 22) -#define FTDM_CHANNEL_ANSWERED (1UL << 23) -#define FTDM_CHANNEL_MUTE (1UL << 24) -#define FTDM_CHANNEL_USE_RX_GAIN (1UL << 25) -#define FTDM_CHANNEL_USE_TX_GAIN (1UL << 26) -#define FTDM_CHANNEL_IN_ALARM (1UL << 27) -#define FTDM_CHANNEL_SIG_UP (1UL << 28) -#define FTDM_CHANNEL_USER_HANGUP (1UL << 29) -#define FTDM_CHANNEL_RX_DISABLED (1UL << 30) -#define FTDM_CHANNEL_TX_DISABLED (1UL << 31) +/*!< Channel flags. This used to be an enum but we reached the 32bit limit for enums, is safer this way */ +#define FTDM_CHANNEL_CONFIGURED (1ULL << 0) +#define FTDM_CHANNEL_READY (1ULL << 1) +#define FTDM_CHANNEL_OPEN (1ULL << 2) +#define FTDM_CHANNEL_DTMF_DETECT (1ULL << 3) +#define FTDM_CHANNEL_SUPRESS_DTMF (1ULL << 4) +#define FTDM_CHANNEL_TRANSCODE (1ULL << 5) +#define FTDM_CHANNEL_BUFFER (1ULL << 6) +#define FTDM_CHANNEL_EVENT (1ULL << 7) +#define FTDM_CHANNEL_INTHREAD (1ULL << 8) +#define FTDM_CHANNEL_WINK (1ULL << 9) +#define FTDM_CHANNEL_FLASH (1ULL << 10) +#define FTDM_CHANNEL_STATE_CHANGE (1ULL << 11) +#define FTDM_CHANNEL_HOLD (1ULL << 12) +#define FTDM_CHANNEL_INUSE (1ULL << 13) +#define FTDM_CHANNEL_OFFHOOK (1ULL << 14) +#define FTDM_CHANNEL_RINGING (1ULL << 15) +#define FTDM_CHANNEL_PROGRESS_DETECT (1ULL << 16) +#define FTDM_CHANNEL_CALLERID_DETECT (1ULL << 17) +#define FTDM_CHANNEL_OUTBOUND (1ULL << 18) +#define FTDM_CHANNEL_SUSPENDED (1ULL << 19) +#define FTDM_CHANNEL_3WAY (1ULL << 20) +#define FTDM_CHANNEL_PROGRESS (1ULL << 21) +#define FTDM_CHANNEL_MEDIA (1ULL << 22) +#define FTDM_CHANNEL_ANSWERED (1ULL << 23) +#define FTDM_CHANNEL_MUTE (1ULL << 24) +#define FTDM_CHANNEL_USE_RX_GAIN (1ULL << 25) +#define FTDM_CHANNEL_USE_TX_GAIN (1ULL << 26) +#define FTDM_CHANNEL_IN_ALARM (1ULL << 27) +#define FTDM_CHANNEL_SIG_UP (1ULL << 28) +#define FTDM_CHANNEL_USER_HANGUP (1ULL << 29) +#define FTDM_CHANNEL_RX_DISABLED (1ULL << 30) +#define FTDM_CHANNEL_TX_DISABLED (1ULL << 31) /*!< The user knows about a call in this channel */ -#define FTDM_CHANNEL_CALL_STARTED (1UL << 32) +#define FTDM_CHANNEL_CALL_STARTED (1ULL << 32) typedef enum { ZSM_NONE, From e085fea23ec990470dd83d654c6639ed526420c7 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 21 Dec 2010 09:09:10 -0500 Subject: [PATCH 068/179] freetdm: define _GNU_SOURCE to get gethostbyname_r --- .../src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c index 982dd4794d..6ddb74d253 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c @@ -31,6 +31,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define _GNU_SOURCE + #if HAVE_NETDB_H #include #endif From f5c36acfe2437835254210061030f179050f62b2 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Tue, 21 Dec 2010 13:31:21 -0200 Subject: [PATCH 069/179] freetdm: mod_freetdm - updated api commands help ftmod_r2 - updated api help and removed references to threads per channel, not used anymore --- libs/freetdm/mod_freetdm/mod_freetdm.c | 14 ++++++++++++- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 24 ++++++++-------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 7e099853a6..66bc532cbc 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3536,7 +3536,19 @@ void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t * switch_channel_cause2str(caller_data->hangup_cause)); } -#define FT_SYNTAX "list || dump [] || q931_pcap on|off [pcapfilename without suffix] || gains [] || dtmf on|off []" +#define FT_SYNTAX "USAGE:\n" \ +"--------------------------------------------------------------------------------\n" \ +"ftdm list\n" \ +"ftdm start|stop \n" \ +"ftdm restart \n" \ +"ftdm dump []\n" \ +"ftdm sigstatus get|set [] [] []\n" \ +"ftdm trace []\n" \ +"ftdm notrace []\n" \ +"ftdm q931_pcap on|off [pcapfilename without suffix]\n" \ +"ftdm gains []\n" \ +"ftdm dtmf on|off []\n" \ +"--------------------------------------------------------------------------------\n" SWITCH_STANDARD_API(ft_function) { char *mycmd = NULL, *argv[10] = { 0 }; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index d178de53cd..e3ae0cf4c5 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -50,10 +50,6 @@ #include "freetdm.h" #include "private/ftdm_core.h" -/* debug thread count for r2 legs */ -static ftdm_mutex_t* g_thread_count_mutex; -static int32_t g_thread_count = 0; - typedef int openr2_call_status_t; /* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread @@ -2023,6 +2019,14 @@ static void __inline__ unblock_channel(ftdm_channel_t *fchan, ftdm_stream_handle ftdm_mutex_unlock(fchan->mutex); } +#define FT_SYNTAX "USAGE:\n" \ +"--------------------------------------------------------------------------------\n" \ +"ftdm r2 status \n" \ +"ftdm r2 loopstats \n" \ +"ftdm r2 block|unblock []\n" \ +"ftdm r2 version\n" \ +"ftdm r2 variants\n" \ +"--------------------------------------------------------------------------------\n" static FIO_API_FUNCTION(ftdm_r2_api) { ftdm_span_t *span = NULL; @@ -2206,14 +2210,6 @@ static FIO_API_FUNCTION(ftdm_r2_api) } if (argc == 1) { - if (!strcasecmp(argv[0], "threads")) { - ftdm_mutex_lock(g_thread_count_mutex); - stream->write_function(stream, "%d R2 channel threads up\n", g_thread_count); - ftdm_mutex_unlock(g_thread_count_mutex); - stream->write_function(stream, "+OK.\n"); - goto done; - } - if (!strcasecmp(argv[0], "version")) { stream->write_function(stream, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision()); stream->write_function(stream, "+OK.\n"); @@ -2239,7 +2235,7 @@ static FIO_API_FUNCTION(ftdm_r2_api) } } - stream->write_function(stream, "-ERR invalid command.\n"); + stream->write_function(stream, "%s", FT_SYNTAX); done: @@ -2268,7 +2264,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_r2_init) if (!g_mod_data_hash) { return FTDM_FAIL; } - ftdm_mutex_create(&g_thread_count_mutex); return FTDM_SUCCESS; } @@ -2288,7 +2283,6 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy) } } hashtable_destroy(g_mod_data_hash); - ftdm_mutex_destroy(&g_thread_count_mutex); return FTDM_SUCCESS; } From 94bd1a7f26df0f59652364e33f9e9b46729b036a Mon Sep 17 00:00:00 2001 From: Michal Bielicki Date: Tue, 21 Dec 2010 15:52:22 +0000 Subject: [PATCH 070/179] added german ringtone --- conf/vars.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/vars.xml b/conf/vars.xml index fced2ef139..05561d778c 100644 --- a/conf/vars.xml +++ b/conf/vars.xml @@ -204,6 +204,7 @@ + + - + - - + + + + + + + - - + + + + + + + + + + + + + + + + - diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 7e099853a6..0709021aca 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -2717,6 +2717,9 @@ static switch_status_t load_config(void) char *hold_music = NULL; char *fail_dial_regex = NULL; const char *enable_callerid = "true"; + const char *answer_polarity = "false"; + const char *hangup_polarity = "false"; + int polarity_delay = 600; int callwaiting = 1; uint32_t span_id = 0, to = 0, max = 0; @@ -2788,6 +2791,12 @@ static switch_status_t load_config(void) dial_regex = val; } else if (!strcasecmp(var, "enable-callerid")) { enable_callerid = val; + } else if (!strcasecmp(var, "answer-polarity-reverse")) { + answer_polarity = val; + } else if (!strcasecmp(var, "hangup-polarity-reverse")) { + hangup_polarity = val; + } else if (!strcasecmp(var, "polarity-delay")) { + polarity_delay = atoi(val); } else if (!strcasecmp(var, "fail-dial-regex")) { fail_dial_regex = val; } else if (!strcasecmp(var, "hold-music")) { @@ -2848,6 +2857,9 @@ static switch_status_t load_config(void) "max_dialstr", &max, "hotline", hotline ? hotline : "", "enable_callerid", enable_callerid, + "answer_polarity_reverse", answer_polarity, + "hangup_polarity_reverse", hangup_polarity, + "polarity_delay", &polarity_delay, "callwaiting", &callwaiting, FTDM_TAG_END) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span)); diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index c04dd85a17..955729df36 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1541,6 +1541,7 @@ end: ftdm_mutex_unlock(ftdmchan->span->mutex); } else { ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "VETO state change from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); + goto done; } /* there is an inherent race here between set and check of the change flag but we do not care because @@ -1570,7 +1571,7 @@ end: ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "state change from %s to %s was most likely not processed after aprox %dms\n", ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(state), DEFAULT_WAIT_TIME); } - +done: return ok ? FTDM_SUCCESS : FTDM_FAIL; } @@ -2289,8 +2290,15 @@ static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const c ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1); } else { /* the signaling stack did not touch the state, - * core is responsible from clearing flags and stuff */ - ftdm_channel_close(&chan); + * core is responsible from clearing flags and stuff, however, because ftmod_analog + * is a bitch in a serious need of refactoring, we also check whether the channel is open + * to avoid an spurious warning about the channel not being open. This is because ftmod_analog + * does not follow our convention of sending SIGEVENT_STOP and waiting for the user to move + * to HANGUP (implicitly through ftdm_channel_call_hangup(), as soon as ftmod_analog is fixed + * this check can be removed */ + if (ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) { + ftdm_channel_close(&chan); + } } return FTDM_SUCCESS; } @@ -3933,7 +3941,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "cannot write in channel not open\n"); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot write in channel not open\n"); snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open"); status = FTDM_FAIL; goto done; diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h b/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h index 2c79822b29..39cbc5ff2b 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftdm_analog.h @@ -37,7 +37,9 @@ typedef enum { FTDM_ANALOG_RUNNING = (1 << 0), - FTDM_ANALOG_CALLERID = (1 << 1) + FTDM_ANALOG_CALLERID = (1 << 1), + FTDM_ANALOG_ANSWER_POLARITY_REVERSE = (1 << 2), + FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3) } ftdm_analog_flag_t; #define FTDM_MAX_HOTLINE_STR 20 @@ -47,11 +49,13 @@ struct ftdm_analog_data { uint32_t flags; uint32_t max_dialstr; uint32_t wait_dialtone_timeout; + uint32_t polarity_delay; uint32_t digit_timeout; char hotline[FTDM_MAX_HOTLINE_STR]; }; - +/* Analog flags to be set in the sflags (signaling flags) channel memeber */ +#define AF_POLARITY_REVERSE (1 << 0) static void *ftdm_analog_run(ftdm_thread_t *me, void *obj); typedef struct ftdm_analog_data ftdm_analog_data_t; diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c index 0acf70b18d..981df5dcc9 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c @@ -184,6 +184,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) uint32_t digit_timeout = 10; uint32_t wait_dialtone_timeout = 30000; uint32_t max_dialstr = MAX_DTMF; + uint32_t polarity_delay = 600; const char *var, *val; int *intval; uint32_t flags = FTDM_ANALOG_CALLERID; @@ -236,6 +237,29 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) } else { flags &= ~FTDM_ANALOG_CALLERID; } + } else if (!strcasecmp(var, "answer_polarity_reverse")) { + if (!(val = va_arg(ap, char *))) { + break; + } + if (ftdm_true(val)) { + flags |= FTDM_ANALOG_ANSWER_POLARITY_REVERSE; + } else { + flags &= ~FTDM_ANALOG_ANSWER_POLARITY_REVERSE; + } + } else if (!strcasecmp(var, "hangup_polarity_reverse")) { + if (!(val = va_arg(ap, char *))) { + break; + } + if (ftdm_true(val)) { + flags |= FTDM_ANALOG_HANGUP_POLARITY_REVERSE; + } else { + flags &= ~FTDM_ANALOG_HANGUP_POLARITY_REVERSE; + } + } else if (!strcasecmp(var, "polarity_delay")) { + if (!(intval = va_arg(ap, int *))) { + break; + } + polarity_delay = *intval; } else if (!strcasecmp(var, "callwaiting")) { if (!(intval = va_arg(ap, int *))) { break; @@ -276,6 +300,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) analog_data->flags = flags; analog_data->digit_timeout = digit_timeout; analog_data->wait_dialtone_timeout = wait_dialtone_timeout; + analog_data->polarity_delay = polarity_delay; analog_data->max_dialstr = max_dialstr; span->signal_cb = sig_cb; strncpy(analog_data->hotline, hotline, sizeof(analog_data->hotline)); @@ -399,6 +424,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) ftdm_analog_data_t *analog_data = ftdmchan->span->signal_data; ftdm_channel_t *closed_chan; uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = analog_data->wait_dialtone_timeout; + uint32_t answer_on_polarity_counter = 0; ftdm_sigmsg_t sig; ftdm_status_t status; @@ -470,7 +496,12 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) if (ftdmchan->needed_tones[FTDM_TONEMAP_DIAL]) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); } else { - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + /* do not go up if we're waiting for polarity reversal */ + if (ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE)) { + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + } else { + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + } } } } @@ -561,8 +592,30 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) } case FTDM_CHANNEL_STATE_UP: case FTDM_CHANNEL_STATE_RING: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: { - ftdm_sleep(interval); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && + ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA && + ftdm_test_sflag(ftdmchan, AF_POLARITY_REVERSE)) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Answering on polarity reverse\n"); + ftdm_clear_sflag(ftdmchan, AF_POLARITY_REVERSE); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + answer_on_polarity_counter = state_counter; + } else if (ftdmchan->state == FTDM_CHANNEL_STATE_UP + && ftdm_test_sflag(ftdmchan, AF_POLARITY_REVERSE)){ + /* if this polarity reverse is close to the answer polarity reverse, ignore it */ + if (answer_on_polarity_counter + && (state_counter - answer_on_polarity_counter) > analog_data->polarity_delay) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Hanging up on polarity reverse\n"); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + } else { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, + "Not hanging up on polarity reverse, too close to Answer reverse\n"); + } + ftdm_clear_sflag(ftdmchan, AF_POLARITY_REVERSE); + } else { + ftdm_sleep(interval); + } continue; } break; @@ -615,6 +668,18 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) sig.event_id = FTDM_SIGEVENT_UP; } + if (ftdmchan->type == FTDM_CHAN_TYPE_FXS && + !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && + ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE)) { + ftdm_polarity_t polarity = FTDM_POLARITY_REVERSE; + if (ftdmchan->polarity != FTDM_POLARITY_FORWARD) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Polarity is already reversed on answer??\n"); + } else { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Reversing polarity on answer\n"); + ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_POLARITY, &polarity); + } + } + ftdm_span_send_signal(ftdmchan->span, &sig); continue; } @@ -639,6 +704,22 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) continue; } break; + + case FTDM_CHANNEL_STATE_HANGUP: + /* this state is only used when the user hangup, if the device hang up (onhook) we currently + * go straight to DOWN. If we ever change this (as other signaling modules do) by using this + * state for both user and device hangup, we should check here for the type of hangup since + * some actions (polarity reverse) do not make sense if the device hung up */ + if (ftdmchan->type == FTDM_CHAN_TYPE_FXS && + ftdmchan->last_state == FTDM_CHANNEL_STATE_UP && + ftdm_test_flag(analog_data, FTDM_ANALOG_HANGUP_POLARITY_REVERSE)) { + ftdm_polarity_t polarity = ftdmchan->polarity == FTDM_POLARITY_REVERSE + ? FTDM_POLARITY_FORWARD : FTDM_POLARITY_REVERSE; + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Reversing polarity on hangup\n"); + ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_POLARITY, &polarity); + } + break; + case FTDM_CHANNEL_STATE_DOWN: { sig.event_id = FTDM_SIGEVENT_STOP; @@ -847,6 +928,9 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) done: + closed_chan = ftdmchan; + + ftdm_channel_lock(closed_chan); if (ftdmchan->type == FTDM_CHAN_TYPE_FXO && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL); @@ -857,7 +941,8 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) } - closed_chan = ftdmchan; + ftdm_clear_sflag(ftdmchan, AF_POLARITY_REVERSE); + ftdm_channel_close(&ftdmchan); ftdm_channel_command(closed_chan, FTDM_COMMAND_SET_NATIVE_CODEC, NULL); @@ -875,8 +960,11 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) } ftdm_log_chan(closed_chan, FTDM_LOG_DEBUG, "ANALOG CHANNEL %d:%d thread ended.\n", closed_chan->span_id, closed_chan->chan_id); + ftdm_clear_flag(closed_chan, FTDM_CHANNEL_INTHREAD); + ftdm_channel_unlock(closed_chan); + return NULL; } @@ -903,6 +991,19 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e ftdm_mutex_lock(event->channel->mutex); locked++; + /* MAINTENANCE WARNING: + * 1. Be aware you are working on the locked channel + * 2. We should not be calling ftdm_span_send_signal or ftdm_set_state when there is already a channel thread running + * however, since this is old code I am not changing it now, but new code should adhere to that convention + * otherwise, we have possible races where we compete with the user for state changes, ie, the user requests + * a state change and then we process an event, the state change from the user is pending so our ftdm_set_state + * operation will fail. In cases where we win the race, our state change will be accepted but if a user requests + * a state change before the state change we requested here is processed by the channel thread, we'll end up + * rejecting the user request. + * + * See docs/locking.txt for further information about what guarantees should signaling modules provide when + * locking/unlocking a channel + * */ switch(event->enum_id) { case FTDM_OOB_RING_START: { @@ -940,7 +1041,11 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e } ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); } - + if (event->channel->type == FTDM_CHAN_TYPE_FXS) { + /* we always return to forward when the device goes onhook */ + ftdm_polarity_t forward_polarity = FTDM_POLARITY_FORWARD; + ftdm_channel_command(event->channel, FTDM_COMMAND_SET_POLARITY, &forward_polarity); + } } break; case FTDM_OOB_FLASH: @@ -1004,6 +1109,35 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e ftdm_span_send_signal(span, &sig); } break; + case FTDM_OOB_POLARITY_REVERSE: + { + if (event->channel->type != FTDM_CHAN_TYPE_FXO) { + ftdm_log_chan_msg(event->channel, FTDM_LOG_WARNING, + "Ignoring polarity reversal, this should not happen in non-FXO channels!\n"); + break; + } + if (!ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD) && + ftdm_test_flag(event->channel, FTDM_CHANNEL_OFFHOOK)) { + ftdm_log_chan_msg(event->channel, FTDM_LOG_WARNING, + "Forcing onhook in channel not in thread after polarity reversal\n"); + ftdm_channel_command(event->channel, FTDM_COMMAND_ONHOOK, NULL); + break; + } + if (!ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE) + && !ftdm_test_flag(analog_data, FTDM_ANALOG_HANGUP_POLARITY_REVERSE)) { + ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG, + "Ignoring polarity reversal because this channel is not configured for it\n"); + break; + } + if (event->channel->state == FTDM_CHANNEL_STATE_DOWN) { + ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG, + "Ignoring polarity reversal because this channel is down\n"); + break; + } + /* we have a good channel, set the polarity flag and let the channel thread deal with it */ + ftdm_set_sflag(event->channel, AF_POLARITY_REVERSE); + } + break; default: { ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "Ignoring event [%s] in state [%s]\n", ftdm_oob_event2str(event->enum_id), ftdm_channel_state2str(event->channel->state)); diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 2db4326847..5e9318f7e5 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -784,17 +784,27 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) err = sangoma_set_tx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size); } break; + case FTDM_COMMAND_SET_POLARITY: + { + ftdm_polarity_t polarity = FTDM_COMMAND_OBJ_INT; + err = sangoma_tdm_set_polarity(ftdmchan->sockfd, &tdm_api, polarity); + if (!err) { + ftdmchan->polarity = polarity; + } + } + break; default: err = FTDM_NOTIMPL; break; }; if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); + int myerrno = errno; + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Wanpipe failed to execute command %d: %s\n", command, strerror(myerrno)); + errno = myerrno; return err; } - return FTDM_SUCCESS; } @@ -1237,8 +1247,9 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) wanpipe_tdm_api_t tdm_api; ftdm_span_t *span = ftdmchan->span; - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) { ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); + } memset(&tdm_api, 0, sizeof(tdm_api)); status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); @@ -1251,7 +1262,7 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) { - case WP_TDMAPI_EVENT_LINK_STATUS: + case WP_API_EVENT_LINK_STATUS: { switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) { case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: @@ -1264,7 +1275,7 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) } break; - case WP_TDMAPI_EVENT_RXHOOK: + case WP_API_EVENT_RXHOOK: { if (ftdmchan->type == FTDM_CHAN_TYPE_FXS) { event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK; @@ -1300,26 +1311,26 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) } } break; - case WP_TDMAPI_EVENT_RING_DETECT: + case WP_API_EVENT_RING_DETECT: { event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP; } break; /* disabled this ones when configuring, we don't need them, do we? - case WP_TDMAPI_EVENT_RING_TRIP_DETECT: + case WP_API_EVENT_RING_TRIP_DETECT: { event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK; } break; */ - case WP_TDMAPI_EVENT_RBS: + case WP_API_EVENT_RBS: { event_id = FTDM_OOB_CAS_BITS_CHANGE; ftdmchan->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); } break; - case WP_TDMAPI_EVENT_DTMF: + case WP_API_EVENT_DTMF: { char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 }; event_id = FTDM_OOB_NOOP; @@ -1342,12 +1353,18 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event) } } break; - case WP_TDMAPI_EVENT_ALARM: + case WP_API_EVENT_ALARM: { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm); event_id = FTDM_OOB_ALARM_TRAP; } break; + case WP_API_EVENT_POLARITY_REVERSE: + { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got polarity reverse\n"); + event_id = FTDM_OOB_POLARITY_REVERSE; + } + break; default: { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); @@ -1423,7 +1440,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event) ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) { - case WP_TDMAPI_EVENT_LINK_STATUS: + case WP_API_EVENT_LINK_STATUS: { switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) { case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: @@ -1436,7 +1453,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event) } break; - case WP_TDMAPI_EVENT_RXHOOK: + case WP_API_EVENT_RXHOOK: { if (span->channels[i]->type == FTDM_CHAN_TYPE_FXS) { event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK; @@ -1472,26 +1489,26 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event) } } break; - case WP_TDMAPI_EVENT_RING_DETECT: + case WP_API_EVENT_RING_DETECT: { event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP; } break; /* disabled this ones when configuring, we don't need them, do we? - case WP_TDMAPI_EVENT_RING_TRIP_DETECT: + case WP_API_EVENT_RING_TRIP_DETECT: { event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK; } break; */ - case WP_TDMAPI_EVENT_RBS: + case WP_API_EVENT_RBS: { event_id = FTDM_OOB_CAS_BITS_CHANGE; span->channels[i]->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); } break; - case WP_TDMAPI_EVENT_DTMF: + case WP_API_EVENT_DTMF: { char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 }; event_id = FTDM_OOB_NOOP; @@ -1514,12 +1531,18 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event) } } break; - case WP_TDMAPI_EVENT_ALARM: + case WP_API_EVENT_ALARM: { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm); event_id = FTDM_OOB_ALARM_TRAP; } break; + case WP_API_EVENT_POLARITY_REVERSE: + { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got polarity reverse\n"); + event_id = FTDM_OOB_POLARITY_REVERSE; + } + break; default: { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 79e873390e..dfb3f1fc02 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -557,8 +557,14 @@ typedef enum { FTDM_COMMAND_COUNT, FTDM_COMMAND_SET_RX_QUEUE_SIZE, FTDM_COMMAND_SET_TX_QUEUE_SIZE, + FTDM_COMMAND_SET_POLARITY, } ftdm_command_t; +typedef enum { + FTDM_POLARITY_FORWARD = 0, + FTDM_POLARITY_REVERSE = 1 +} ftdm_polarity_t; + /*! \brief Custom memory handler hooks. Not recommended to use unless you need memory allocation customizations */ typedef void *(*ftdm_malloc_func_t)(void *pool, ftdm_size_t len); typedef void *(*ftdm_calloc_func_t)(void *pool, ftdm_size_t elements, ftdm_size_t len); diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 606a89fc77..b90e98736a 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -143,7 +143,9 @@ extern "C" { \return true value if the object has the flags defined */ #define ftdm_test_flag(obj, flag) ((obj)->flags & flag) +/*!< Physical (IO) module specific flags */ #define ftdm_test_pflag(obj, flag) ((obj)->pflags & flag) +/*!< signaling module specific flags */ #define ftdm_test_sflag(obj, flag) ((obj)->sflags & flag) #define ftdm_set_alarm_flag(obj, flag) (obj)->alarm_flags |= (flag) @@ -456,6 +458,7 @@ struct ftdm_channel { ftdm_fsk_data_state_t fsk; uint8_t fsk_buf[80]; uint32_t ring_count; + ftdm_polarity_t polarity; /* Private I/O data. Do not touch unless you are an I/O module */ void *io_data; /* Private signaling data. Do not touch unless you are a signaling module */ diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index 6c521e3481..db15b106c1 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -123,6 +123,7 @@ typedef enum { FTDM_STR2ENUM_P(ftdm_str2ftdm_analog_start_type, ftdm_analog_start_type2str, ftdm_analog_start_type_t) typedef enum { + FTDM_OOB_NOOP, FTDM_OOB_ONHOOK, FTDM_OOB_OFFHOOK, FTDM_OOB_WINK, @@ -131,11 +132,11 @@ typedef enum { FTDM_OOB_RING_STOP, FTDM_OOB_ALARM_TRAP, FTDM_OOB_ALARM_CLEAR, - FTDM_OOB_NOOP, FTDM_OOB_CAS_BITS_CHANGE, + FTDM_OOB_POLARITY_REVERSE, FTDM_OOB_INVALID } ftdm_oob_event_t; -#define OOB_STRINGS "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "NOOP", "CAS_BITS_CHANGE", "INVALID" +#define OOB_STRINGS "NOOP", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "CAS_BITS_CHANGE", "POLARITY_REVERSE", "INVALID" FTDM_STR2ENUM_P(ftdm_str2ftdm_oob_event, ftdm_oob_event2str, ftdm_oob_event_t) /*! \brief Event types */ From a3b01c195be3c1454c60e634477d8c825c60ac77 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 21 Dec 2010 15:35:13 -0600 Subject: [PATCH 074/179] rtp adjustments when using jitterbuffer --- src/switch_ivr.c | 2 +- src/switch_rtp.c | 39 ++++++++++++--------------------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index cd74c332b7..68d5a55b40 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2285,7 +2285,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3 break; } - stfu_n_eat(jb, ts, read_frame->payload, read_frame->data, read_frame->datalen); + stfu_n_eat(jb, ts, read_frame->payload, read_frame->data, read_frame->datalen, 0); ts += interval; if ((jb_frame = stfu_n_read_a_frame(jb))) { diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 4e667fb49b..aa4ca7a5ca 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -2135,19 +2135,6 @@ static void do_flush(switch_rtp_t *rtp_session) flushed++; -#ifdef _MSC_VER -#pragma warning(push) /* remove this stuff when "if (0" is removed */ -#pragma warning(disable:4127) -#endif - if (0 && rtp_session->jb) { - stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts), - rtp_session->recv_msg.header.pt, - rtp_session->recv_msg.body, bytes - rtp_header_len); - } -#ifdef _MSC_VER -#pragma warning(pop) -#endif - rtp_session->stats.inbound.raw_bytes += bytes; rtp_session->stats.inbound.flush_packet_count++; rtp_session->stats.inbound.packet_count++; @@ -2196,12 +2183,13 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t rtp_session->stats.inbound.packet_count++; } - if ((rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) || - *bytes < rtp_header_len || - switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) { - return SWITCH_STATUS_SUCCESS; + if (*bytes != 0 && !rtp_session->jb) { + if ((rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) || + *bytes < rtp_header_len || + switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) { + return SWITCH_STATUS_SUCCESS; + } } - if (rtp_session->jb && rtp_session->recv_msg.header.version == 2 && *bytes) { if (rtp_session->recv_msg.header.m && rtp_session->recv_msg.header.pt != rtp_session->recv_te && @@ -2211,14 +2199,15 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts), rtp_session->recv_msg.header.pt, - rtp_session->recv_msg.body, *bytes - rtp_header_len); + rtp_session->recv_msg.body, *bytes - rtp_header_len, rtp_session->timer.samplecount); *bytes = 0; status = SWITCH_STATUS_FALSE; } - if (rtp_session->jb) { + if (rtp_session->jb && !rtp_session->checked_jb) { if ((jb_frame = stfu_n_read_a_frame(rtp_session->jb))) { memcpy(rtp_session->recv_msg.body, jb_frame->data, jb_frame->dlen); + if (jb_frame->plc) { (*flags) |= SFF_PLC; } else { @@ -2229,6 +2218,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t rtp_session->recv_msg.header.pt = jb_frame->pt; status = SWITCH_STATUS_SUCCESS; } + rtp_session->checked_jb++; } @@ -2385,7 +2375,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ rtp_session->read_pollfd) { if (switch_poll(rtp_session->read_pollfd, 1, &fdr, 0) == SWITCH_STATUS_SUCCESS) { rtp_session->hot_hits += rtp_session->samples_per_interval; - + if (rtp_session->hot_hits >= rtp_session->samples_per_second * 5) { switch_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH); hot_socket = 1; @@ -2927,12 +2917,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (do_cng) { uint8_t *data = (uint8_t *) rtp_session->recv_msg.body; - int fdr; - - if ((poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, 0)) == SWITCH_STATUS_SUCCESS) { - goto recvfrom; - } - + memset(data, 0, 2); data[0] = 65; rtp_session->recv_msg.header.pt = (uint32_t) rtp_session->cng_pt ? rtp_session->cng_pt : SWITCH_RTP_CNG_PAYLOAD; From e80a40cf6835052ccf9750b6c89cd2fa4b776584 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 21 Dec 2010 15:35:30 -0600 Subject: [PATCH 075/179] rtp adjustments when using jitterbuffer --- libs/stfu/stfu.c | 29 +++++++++++++++++++++-------- libs/stfu/stfu.h | 7 ++++--- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index b7df8ea870..d2c443a9e7 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -100,7 +100,9 @@ struct stfu_instance { uint32_t sync_out; uint32_t sync_in; - + int32_t ts_offset; + int32_t ts_drift; + int32_t ts_diff; int32_t last_ts_diff; int32_t same_ts; @@ -126,6 +128,11 @@ static void default_logger(const char *file, const char *func, int line, int lev stfu_logger_t stfu_log = null_logger; +int32_t stfu_n_get_drift(stfu_instance_t *i) +{ + return i->ts_drift; +} + void stfu_global_set_logger(stfu_logger_t logger) { if (logger) { @@ -376,7 +383,7 @@ static void stfu_n_swap(stfu_instance_t *i) i->out_queue->last_jitter = 0; } -stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last) +stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, uint32_t timer_ts, int last) { uint32_t index = 0; stfu_frame_t *frame; @@ -402,6 +409,12 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void } } + if (timer_ts && ts && !i->ts_offset) { + i->ts_offset = timer_ts - ts; + } + + i->ts_drift = ts + (i->ts_offset - timer_ts); + if (i->sync_in) { good_ts = 1; i->sync_in = 0; @@ -480,12 +493,12 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void if (stfu_log != null_logger && i->debug) { - stfu_log(STFU_LOG_EMERG, "%s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d\n", i->name, - i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count, - i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count, - ts, ts / i->samples_per_packet, - i->period_missing_count, i->period_need_range_avg, - i->last_wr_ts, ts, i->diff, i->diff_total / least1(i->period_packet_in_count)); + stfu_log(STFU_LOG_EMERG, "I: %s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d %d\n", i->name, + i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count, + i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count, + ts, ts / i->samples_per_packet, + i->period_missing_count, i->period_need_range_avg, + i->last_wr_ts, ts, i->diff, i->diff_total / least1(i->period_packet_in_count), i->ts_drift); } if (last || i->in_queue->array_len == i->in_queue->array_size) { diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h index ad769c62e2..b92bb3f839 100644 --- a/libs/stfu/stfu.h +++ b/libs/stfu/stfu.h @@ -181,15 +181,16 @@ void stfu_n_report(stfu_instance_t *i, stfu_report_t *r); void stfu_n_destroy(stfu_instance_t **i); stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second); stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen); -stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last); +stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, uint32_t timer_ts, int last); stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i); void stfu_n_reset(stfu_instance_t *i); stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets); void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata); void stfu_n_debug(stfu_instance_t *i, const char *name); +int32_t stfu_n_get_drift(stfu_instance_t *i); -#define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 1) -#define stfu_n_eat(i,t,p,d,l) stfu_n_add_data(i, t, p, d, l, 0) +#define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 0, 1) +#define stfu_n_eat(i,t,p,d,l,tt) stfu_n_add_data(i, t, p, d, l, tt, 0) #ifdef __cplusplus } From a1e425029c3a123d1b77d8e81acea873af81961e Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 21 Dec 2010 16:59:25 -0600 Subject: [PATCH 076/179] FS-2944 --- conf/directory/default/default.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/directory/default/default.xml b/conf/directory/default/default.xml index 5db60112dc..aa138f18d9 100644 --- a/conf/directory/default/default.xml +++ b/conf/directory/default/default.xml @@ -1,7 +1,7 @@ - + From 81608da0067cb1bca2f718e4973e83af9371a659 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 29 Dec 2010 12:28:12 -0600 Subject: [PATCH 127/179] refactor sofia_contact to try the profile_name first then the domain to resolve the profile then fall back to querying every profile to reduce confusion with multi-homers (d'oh) also special profile name * will force a search-all situation --- src/mod/endpoints/mod_sofia/mod_sofia.c | 137 ++++++++++++++---------- 1 file changed, 81 insertions(+), 56 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 8aa37b95be..af7149b8c8 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -3395,6 +3395,36 @@ SWITCH_STANDARD_API(sofia_count_reg_function) return SWITCH_STATUS_SUCCESS; } +static void select_from_profile(sofia_profile_t *profile, + const char *user, + const char *domain, + const char *concat, + const char *exclude_contact, + switch_stream_handle_t *stream) +{ + struct cb_helper cb; + char *sql; + + cb.row_process = 0; + + cb.profile = profile; + cb.stream = stream; + + if (exclude_contact) { + sql = switch_mprintf("select contact, profile_name, '%q' " + "from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%') " + "and contact not like '%%%s%%'", (concat != NULL) ? concat : "", user, domain, domain, exclude_contact); + } else { + sql = switch_mprintf("select contact, profile_name, '%q' " + "from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", + (concat != NULL) ? concat : "", user, domain, domain); + } + + switch_assert(sql); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, contact_callback, &cb); + switch_safe_free(sql); +} + SWITCH_STANDARD_API(sofia_contact_function) { char *data; @@ -3406,6 +3436,7 @@ SWITCH_STANDARD_API(sofia_contact_function) sofia_profile_t *profile = NULL; const char *exclude_contact = NULL; char *reply = "error/facility_not_subscribed"; + switch_stream_handle_t mystream = { 0 }; if (!cmd) { stream->write_function(stream, "%s", ""); @@ -3440,76 +3471,70 @@ SWITCH_STANDARD_API(sofia_contact_function) } } - if (!profile_name && domain) { - profile_name = domain; + if (zstr(domain)) { + domain = switch_core_get_variable("domain"); } - if (user && profile_name) { - char *sql; + if (!user) goto end; - if (!(profile = sofia_glue_find_profile(profile_name))) { - profile_name = domain; - domain = NULL; - } - - if (!profile && profile_name) { + if (zstr(profile_name) || strcmp(profile_name, "*") || zstr(domain)) { + if (!zstr(profile_name)) { profile = sofia_glue_find_profile(profile_name); } - - if (profile) { - struct cb_helper cb; - switch_stream_handle_t mystream = { 0 }; - - cb.row_process = 0; - - if (!domain || (!strchr(domain, '.') && strcmp(profile_name, domain))) { - domain = profile->name; - } - - SWITCH_STANDARD_STREAM(mystream); - switch_assert(mystream.data); - cb.profile = profile; - cb.stream = &mystream; - - if (exclude_contact) { - sql = switch_mprintf("select contact, profile_name, '%q' " - "from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%') " - "and contact not like '%%%s%%'", (concat != NULL) ? concat : "", user, domain, domain, exclude_contact); - } else { - sql = switch_mprintf("select contact, profile_name, '%q' " - "from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", - (concat != NULL) ? concat : "", user, domain, domain); - } - - switch_assert(sql); - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, contact_callback, &cb); - switch_safe_free(sql); - reply = (char *) mystream.data; - if (!zstr(reply) && end_of(reply) == ',') { - end_of(reply) = '\0'; - } - - if (zstr(reply)) { - reply = "error/user_not_registered"; - } - - stream->write_function(stream, "%s", reply); - reply = NULL; - - switch_safe_free(mystream.data); + + if (!profile) { + profile = sofia_glue_find_profile(domain); } } - if (reply) { - stream->write_function(stream, "%s", reply); + if (profile || !zstr(domain)) { + SWITCH_STANDARD_STREAM(mystream); + switch_assert(mystream.data); } - switch_safe_free(data); - if (profile) { + if (zstr(domain)) { + domain = profile->name; + } + + select_from_profile(profile, user, domain, concat, exclude_contact, &mystream); sofia_glue_release_profile(profile); + + } else if (!zstr(domain)) { + switch_mutex_lock(mod_sofia_globals.hash_mutex); + if (mod_sofia_globals.profile_hash) { + switch_hash_index_t *hi; + const void *var; + void *val; + + for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + if ((profile = (sofia_profile_t *) val) && !strcmp((char *)var, profile->name)) { + select_from_profile(profile, user, domain, concat, exclude_contact, &mystream); + profile = NULL; + } + } + } + switch_mutex_unlock(mod_sofia_globals.hash_mutex); + } + + reply = (char *) mystream.data; + + end: + + if (zstr(reply)) { + reply = "error/user_not_registered"; + } else if (end_of(reply) == ',') { + end_of(reply) = '\0'; } + stream->write_function(stream, "%s", reply); + reply = NULL; + + switch_safe_free(mystream.data); + + switch_safe_free(data); + return SWITCH_STATUS_SUCCESS; } From 090864fa3997cf697f046200e1ea813464ec79d8 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 29 Dec 2010 13:38:43 -0500 Subject: [PATCH 128/179] freetdm: completed most of the code for the new core state processing use new core state processing functions in ftmod_r2 --- libs/freetdm/mod_freetdm/mod_freetdm.c | 15 +- libs/freetdm/src/ftdm_io.c | 63 ++-- libs/freetdm/src/ftdm_state.c | 44 ++- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 350 ++++++++---------- libs/freetdm/src/include/freetdm.h | 14 +- libs/freetdm/src/include/ftdm_declare.h | 1 + libs/freetdm/src/include/private/ftdm_core.h | 2 +- libs/freetdm/src/include/private/ftdm_state.h | 5 +- 8 files changed, 250 insertions(+), 244 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index d9c26db4fe..e08d4c1f3b 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -421,16 +421,18 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) private_t *tech_pvt = NULL; channel = switch_core_session_get_channel(session); - assert(channel != NULL); + switch_assert(channel != NULL); tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); + switch_assert(tech_pvt != NULL); - assert(tech_pvt->ftdmchan != NULL); + switch_assert(tech_pvt->ftdmchan != NULL); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); - ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED); + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { + ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED); + } return SWITCH_STATUS_SUCCESS; } @@ -441,10 +443,10 @@ static switch_status_t channel_on_execute(switch_core_session_t *session) private_t *tech_pvt = NULL; channel = switch_core_session_get_channel(session); - assert(channel != NULL); + switch_assert(channel != NULL); tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); + switch_assert(tech_pvt != NULL); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel)); @@ -2094,6 +2096,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal) break; case FTDM_SIGEVENT_PROCEED:{} break; + case FTDM_SIGEVENT_INDICATION_COMPLETED:{} break; default: { diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 161ccdcc18..0c25054816 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1022,6 +1022,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t } ftdm_set_flag(new_chan, FTDM_CHANNEL_CONFIGURED | FTDM_CHANNEL_READY); + new_chan->state = FTDM_CHANNEL_STATE_DOWN; + new_chan->state_status = FTDM_STATE_STATUS_COMPLETED; *chan = new_chan; return FTDM_SUCCESS; } @@ -2012,10 +2014,14 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char return status; } -FT_DECLARE(void) ftdm_ack_indication(const ftdm_channel_t *fchan, ftdm_channel_indication_t indication, ftdm_status_t status) +FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *fchan, ftdm_channel_indication_t indication, ftdm_status_t status) { ftdm_sigmsg_t msg; + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Acknowledging indication %s in state %s (rc = %d)\n", + ftdm_channel_indication2str(indication), ftdm_channel_state2str(fchan->state), status); + ftdm_clear_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING); memset(&msg, 0, sizeof(msg)); + msg.channel = fchan; msg.event_id = FTDM_SIGEVENT_INDICATION_COMPLETED; msg.ev_data.indication_completed.indication = indication; msg.ev_data.indication_completed.status = status; @@ -2197,21 +2203,39 @@ FT_DECLARE(uint32_t) ftdm_channel_get_ph_span_id(const ftdm_channel_t *ftdmchan) /* * Every user requested indication *MUST* be acknowledged with the proper status (ftdm_status_t) - * If the indication fails before we notify the signaling stack, we *MUST* acknowledge ourselves, + * However, if the indication fails before we notify the signaling stack, we don't need to ack * but if we already notified the signaling stack about the indication, the signaling stack is - * responsible for the acknowledge. + * responsible for the acknowledge. Bottom line is, whenever this function returns FTDM_SUCCESS + * someone *MUST* acknowledge the indication, either the signaling stack, this function or the core + * at some later point * */ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication) { ftdm_status_t status = FTDM_SUCCESS; + ftdm_assert_return(ftdmchan, FTDM_FAIL, "Null channel\n"); + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Indicating %s in state %s\n", + ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state)); + ftdm_channel_lock(ftdmchan); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot indicate %s in channel with indication %s still pending in state %s\n", + ftdm_channel_indication2str(indication), + ftdm_channel_indication2str(ftdmchan->indication), + ftdm_channel_state2str(ftdmchan->state)); + status = FTDM_EBUSY; + goto done; + } + + ftdmchan->indication = indication; + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot indicate %s in outgoing channel in state %s\n", ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state)); status = FTDM_EINVAL; - ftdm_ack_indication(ftdmchan, indication, status); goto done; } @@ -2219,7 +2243,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring indication %s because the call is in %s state\n", ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state)); status = FTDM_ECANCELED; - ftdm_ack_indication(ftdmchan, indication, status); goto done; } @@ -2228,15 +2251,9 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch * (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */ case FTDM_CHANNEL_INDICATE_RINGING: status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RINGING, 1); - if (status != FTDM_SUCCESS) { - ftdm_ack_indication(ftdmchan, indication, status); - } break; case FTDM_CHANNEL_INDICATE_BUSY: status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1); - if (status != FTDM_SUCCESS) { - ftdm_ack_indication(ftdmchan, indication, status); - } break; case FTDM_CHANNEL_INDICATE_PROCEED: if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) { @@ -2244,47 +2261,34 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch goto done; } status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROCEED, 1); - if (status != FTDM_SUCCESS) { - ftdm_ack_indication(ftdmchan, indication, status); - } break; case FTDM_CHANNEL_INDICATE_PROGRESS: status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); - if (status != FTDM_SUCCESS) { - ftdm_ack_indication(ftdmchan, indication, status); - } break; case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA: if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_SKIP_STATES)) { if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); if (status != FTDM_SUCCESS) { - ftdm_ack_indication(ftdmchan, indication, status); goto done; } } /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */ if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n"); - status = FTDM_ECANCELED; - ftdm_ack_indication(ftdmchan, indication, status); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring progress media because the call is terminating\n"); goto done; } } - ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); - if (status != FTDM_SUCCESS) { - ftdm_ack_indication(ftdmchan, indication, status); - } + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); break; case FTDM_CHANNEL_INDICATE_ANSWER: - /* _ftdm_channel_call_indicate takes care of the indication ack */ + /* _ftdm_channel_call_answer takes care of the indication ack */ status = _ftdm_channel_call_answer(file, func, line, ftdmchan); break; default: ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Do not know how to indicate %d\n", indication); - status = FTDM_FAIL; - ftdm_ack_indication(ftdmchan, indication, status); + status = FTDM_EINVAL; break; } @@ -2463,6 +2467,7 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan) ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN; ftdmchan->state = FTDM_CHANNEL_STATE_DOWN; + ftdmchan->state_status = FTDM_STATE_STATUS_COMPLETED; ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_DEBUG_DTMF, NULL); ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL); @@ -5023,7 +5028,7 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const ftdm_assert_return(parameters != NULL, FTDM_FAIL, "No parameters"); if (!span->chan_count) { - ftdm_log(FTDM_LOG_WARNING, "Cannot configure signaling on span with no channels\n"); + ftdm_log(FTDM_LOG_WARNING, "Cannot configure signaling on span %s with no channels\n", span->name); return FTDM_FAIL; } diff --git a/libs/freetdm/src/ftdm_state.c b/libs/freetdm/src/ftdm_state.c index 2b544756ec..12dc37957a 100644 --- a/libs/freetdm/src/ftdm_state.c +++ b/libs/freetdm/src/ftdm_state.c @@ -37,6 +37,9 @@ FTDM_ENUM_NAMES(CHANNEL_STATE_NAMES, CHANNEL_STATE_STRINGS) FTDM_STR2ENUM(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t, CHANNEL_STATE_NAMES, FTDM_CHANNEL_STATE_INVALID) +FTDM_ENUM_NAMES(CHANNEL_STATE_STATUS_NAMES, CHANNEL_STATE_STATUS_STRINGS) +FTDM_STR2ENUM(ftdm_str2ftdm_state_status, ftdm_state_status2str, ftdm_state_status_t, CHANNEL_STATE_STATUS_NAMES, FTDM_STATE_STATUS_INVALID) + /* This function is only needed for boost and we should get rid of it at the next refactoring */ FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *fchan) { @@ -54,12 +57,17 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *fchan) FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const char *func, int line, ftdm_channel_t *fchan) { uint8_t hindex = 0; + ftdm_time_t diff = 0; ftdm_channel_state_t state = fchan->state; if (fchan->state_status == FTDM_STATE_STATUS_COMPLETED) { + ftdm_assert_return(!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE), FTDM_FAIL, + "State change flag set but state is not completed\n"); return FTDM_SUCCESS; } + ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); + if (state == FTDM_CHANNEL_STATE_PROGRESS) { ftdm_set_flag(fchan, FTDM_CHANNEL_PROGRESS); } else if (state == FTDM_CHANNEL_STATE_UP) { @@ -71,19 +79,28 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c ftdm_set_flag(fchan, FTDM_CHANNEL_MEDIA); } - /* if there is a pending ack for an indication */ + /* if there is a pending ack for an indication + * MAINTENANCE WARNING: we're assuming an indication performed + * via state change will involve a single state change + */ if (ftdm_test_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING)) { ftdm_ack_indication(fchan, fchan->indication, FTDM_SUCCESS); - ftdm_clear_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING); } - ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Completed state change from %s to %s\n", ftdm_channel_state2str(fchan->state), ftdm_channel_state2str(state)); - hindex = (fchan->hindex == 0) ? (ftdm_array_len(fchan->history) - 1) : (hindex - 1); + hindex = (fchan->hindex == 0) ? (ftdm_array_len(fchan->history) - 1) : (fchan->hindex - 1); ftdm_assert(!fchan->history[hindex].end_time, "End time should be zero!\n"); fchan->history[hindex].end_time = ftdm_current_time_in_ms(); + fchan->state_status = FTDM_STATE_STATUS_COMPLETED; + + diff = fchan->history[hindex].end_time - fchan->history[hindex].time; + + ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Completed state change from %s to %s in %llums\n", + ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(state), diff); + + /* FIXME: broadcast condition to wake up anyone waiting on state completion if the channel * is blocking (FTDM_CHANNEL_NONBLOCK is not set) */ @@ -93,9 +110,9 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c FT_DECLARE(ftdm_status_t) _ftdm_set_state(const char *file, const char *func, int line, ftdm_channel_t *fchan, ftdm_channel_state_t state) { - if (fchan->state_status == FTDM_STATE_STATUS_NEW) { - /* the current state is new, setting a new state from a signaling module - when the current state is new is equivalent to implicitly acknowledging + if (fchan->state_status != FTDM_STATE_STATUS_COMPLETED) { + /* the current state is not completed, setting a new state from a signaling module + when the current state is not completed is equivalent to implicitly acknowledging the current state */ _ftdm_channel_complete_state(file, func, line, fchan); } @@ -161,9 +178,11 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *f return FTDM_FAIL; } - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_ERROR, "Ignored state change request from %s to %s, the previous state change has not been processed yet\n", - ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); + if (ftdmchan->state_status != FTDM_STATE_STATUS_COMPLETED) { + ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_ERROR, + "Ignored state change request from %s to %s, the previous state change has not been processed yet (status = %s)\n", + ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state), + ftdm_state_status2str(ftdmchan->state_status)); return FTDM_FAIL; } @@ -422,9 +441,10 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_advance_states(ftdm_channel_t *fchan, ftd ftdm_channel_lock(fchan); while (fchan->state_status == FTDM_STATE_STATUS_NEW) { state = fchan->state; + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Executing state processor for %s\n", ftdm_channel_state2str(fchan->state)); state_processor(fchan); - if (state == fchan->state) { - /* if the state did not change, the state status must go to PROCESSED + if (state == fchan->state && fchan->state_status == FTDM_STATE_STATUS_NEW) { + /* if the state did not change and is still NEW, the state status must go to PROCESSED * otherwise we don't touch it since is a new state and the old state was * already completed implicitly by the state_processor() function via some internal * call to ftdm_set_state() */ diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 3809b224c4..530bb2b9b2 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -73,7 +73,6 @@ typedef struct ftdm_r2_call_t { int disconnect_rcvd:1; int ftdm_call_started:1; int protocol_error:1; - ftdm_channel_state_t chanstate; ftdm_size_t dnis_index; ftdm_size_t ani_index; char logname[255]; @@ -168,8 +167,7 @@ static ftdm_hash_t *g_mod_data_hash; /* IO interface for the command API */ static ftdm_io_interface_t g_ftdm_r2_interface; -static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan); -static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan); +static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan); /* whether R2 call accept process is pending */ #define IS_ACCEPTING_PENDING(ftdmchan) \ @@ -349,7 +347,6 @@ static void ft_r2_clean_call(ftdm_r2_call_t *call) call->disconnect_rcvd = 0; call->ftdm_call_started = 0; call->protocol_error = 0; - call->chanstate = FTDM_CHANNEL_STATE_DOWN; call->dnis_index = 0; call->ani_index = 0; call->name[0] = 0; @@ -479,7 +476,6 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) } R2CALL(ftdmchan)->ftdm_call_started = 1; - R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); @@ -624,7 +620,7 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) ftdm_sched_cancel_timer(r2data->sched, r2call->protocol_error_recovery_timer); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Cancelled protocol error recovery timer\n"); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - ftdm_r2_state_advance_all(ftdmchan); + ftdm_channel_advance_states(ftdmchan, ftdm_r2_state_advance); } } @@ -658,7 +654,6 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_OUTPUT_DUMP, &r2data->mf_dump_size); } - R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL); @@ -708,12 +703,10 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons static void clear_accept_pending(ftdm_channel_t *fchan) { if (IS_ACCEPTING_PENDING(fchan)) { - ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); ftdm_channel_complete_state(fchan); } else if (ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE)) { ftdm_log_chan(fchan, FTDM_LOG_CRIT, "State change flag set in state %s, last state = %s\n", ftdm_channel_state2str(fchan->state), ftdm_channel_state2str(fchan->last_state)); - ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); ftdm_channel_complete_state(fchan); } } @@ -821,7 +814,7 @@ static void ftdm_r2_on_call_end(openr2_chan_t *r2chan) ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); /* in some circumstances openr2 can call on_call_init right after this, so let's advance the state right here */ - ftdm_r2_state_advance_all(ftdmchan); + ftdm_channel_advance_states(ftdmchan, ftdm_r2_state_advance); } static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen) @@ -853,7 +846,7 @@ static void ftdm_r2_recover_from_protocol_error(void *data) goto done; } ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - ftdm_r2_state_advance_all(ftdmchan); + ftdm_channel_advance_states(ftdmchan, ftdm_r2_state_advance); done: ftdm_channel_unlock(ftdmchan); } @@ -1620,10 +1613,10 @@ fail: } /* the channel must be locked when calling this function */ -static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) +static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) { ftdm_sigmsg_t sigev; - int ret; + ftdm_status_t ret; ftdm_r2_call_t *r2call = R2CALL(ftdmchan); openr2_chan_t *r2chan = r2call->r2chan; ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; @@ -1633,172 +1626,161 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) sigev.span_id = ftdmchan->span_id; sigev.channel = ftdmchan; - ret = 0; + ret = FTDM_SUCCESS; - /* because we do not always acknowledge the state change (clearing the FTDM_CHANNEL_STATE_CHANGE flag) due to the accept - * procedure described below, we need the chanstate member to NOT process some states twice, so is valid entering this - * function with the FTDM_CHANNEL_STATE_CHANGE flag set but with a state that was already processed and is just waiting - * to complete (the processing is media-bound) - * */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) - && (r2call->chanstate != ftdmchan->state)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); - r2call->chanstate = ftdmchan->state; - - if (IS_ACCEPTING_PENDING(ftdmchan)) { - /* - Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call first, and accepting - the call in R2 means sending a tone, then waiting for the acknowledge from the other end, - since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100) - which means during that time the user should not try to perform any operations like answer, hangup or anything - else, therefore we DO NOT clear the FTDM_CHANNEL_STATE_CHANGE flag here, we rely on ftdm_io.c to block - the user thread until we're done with the accept (see on_call_accepted callback) and then we clear the state change flag, - otherwise we have a race condition between freetdm calling openr2_chan_answer_call and openr2 accepting the call first, - if freetdm calls openr2_chan_answer_call before the accept cycle completes, openr2 will fail to answer the call */ - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "State ack for state %s will have to wait a bit\n", ftdm_channel_state2str(ftdmchan->state)); - } else if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN){ - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); - ftdm_channel_complete_state(ftdmchan); - } - - switch (ftdmchan->state) { - - /* starting an incoming call */ - case FTDM_CHANNEL_STATE_COLLECT: - { - uint32_t interval = 0; - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); - ftdm_assert(interval != 0, "Invalid interval!"); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of incoming call with interval %d\n", interval); - openr2_chan_enable_read(r2chan); - } - break; - - /* starting an outgoing call */ - case FTDM_CHANNEL_STATE_DIALING: - { - uint32_t interval = 0; - ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); - ftdm_assert(interval != 0, "Invalid interval!"); - ftdm_log_chan(ftdmchan, - FTDM_LOG_DEBUG, "Starting processing of outgoing call in channel with interval %d\n", interval); - openr2_chan_enable_read(r2chan); - } - break; - - /* incoming call was offered */ - case FTDM_CHANNEL_STATE_RING: - - /* notify the user about the new call */ - sigev.event_id = FTDM_SIGEVENT_START; - - ftdm_span_send_signal(ftdmchan->span, &sigev); - r2call->ftdm_call_started = 1; - - break; - - /* the call is making progress */ - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - { - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - if (!r2call->accepted) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Accepting call\n"); - ft_r2_accept_call(ftdmchan); - } - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n"); - sigev.event_id = FTDM_SIGEVENT_PROCEED; - ftdm_span_send_signal(ftdmchan->span, &sigev); - - sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } - } - break; - - /* the call was answered */ - case FTDM_CHANNEL_STATE_UP: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call was answered\n"); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - if (!r2call->accepted) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call has not been accepted, need to accept first\n"); - // the answering will be done in the on_call_accepted handler - ft_r2_accept_call(ftdmchan); - r2call->answer_pending = 1; - } else { - ft_r2_answer_call(ftdmchan); - } - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying of call answered\n"); - sigev.event_id = FTDM_SIGEVENT_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } - } - break; - - /* just got hangup */ - case FTDM_CHANNEL_STATE_HANGUP: - { - if (!r2call->disconnect_rcvd) { - openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); - /* this will disconnect the call, but need to wait for the call end before moving to DOWN */ - openr2_chan_disconnect_call(r2chan, disconnect_cause); - } else if (!r2call->protocol_error) { - /* just ack the hangup, on_call_end will be called by openr2 right after */ - openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n"); - /* do not set to down yet, give some time for recovery */ - ftdm_sched_timer(r2data->sched, "protocolerr_recover", 100, - ftdm_r2_recover_from_protocol_error, r2chan, &r2call->protocol_error_recovery_timer); - } - } - break; - - case FTDM_CHANNEL_STATE_TERMINATING: - { - /* if the call has not been started yet we must go to HANGUP right here */ - if (!r2call->ftdm_call_started) { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - } else { - openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); - /* notify the user of the call terminating and we wait for the user to move us to hangup */ - sigev.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } - } - break; - - /* finished call for good */ - case FTDM_CHANNEL_STATE_DOWN: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Call is down\n"); - ret = 1; - } - break; - - /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */ - case FTDM_CHANNEL_STATE_RINGING: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n"); - } - break; - - default: - { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state)); - } - break; - - } + if (IS_ACCEPTING_PENDING(ftdmchan)) { + /* + Moving to PROGRESS, PROGRESS_MEDIA or UP means that we must accept the call first, and accepting + the call in R2 means sending a tone, then waiting for the acknowledge from the other end, + since all of that requires sending and detecting tones, it takes a few milliseconds (I'd say around 100) + which means during that time the user should not try to perform any operations like answer, hangup or anything + else, therefore we DO NOT clear the FTDM_CHANNEL_STATE_CHANGE flag here, we rely on ftdm_io.c to block + the user thread until we're done with the accept (see on_call_accepted callback) and then we clear the state change flag, + otherwise we have a race condition between freetdm calling openr2_chan_answer_call and openr2 accepting the call first, + if freetdm calls openr2_chan_answer_call before the accept cycle completes, openr2 will fail to answer the call */ + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "State ack for state %s will have to wait a bit\n", ftdm_channel_state2str(ftdmchan->state)); + } else if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN){ + ftdm_channel_complete_state(ftdmchan); } - if (ret) { + switch (ftdmchan->state) { + + /* starting an incoming call */ + case FTDM_CHANNEL_STATE_COLLECT: + { + uint32_t interval = 0; + ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); + ftdm_assert(interval != 0, "Invalid interval!"); + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting processing of incoming call with interval %d\n", interval); + openr2_chan_enable_read(r2chan); + } + break; + + /* starting an outgoing call */ + case FTDM_CHANNEL_STATE_DIALING: + { + uint32_t interval = 0; + ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval); + ftdm_assert(interval != 0, "Invalid interval!"); + ftdm_log_chan(ftdmchan, + FTDM_LOG_DEBUG, "Starting processing of outgoing call in channel with interval %d\n", interval); + openr2_chan_enable_read(r2chan); + } + break; + + /* incoming call was offered */ + case FTDM_CHANNEL_STATE_RING: + + /* notify the user about the new call */ + sigev.event_id = FTDM_SIGEVENT_START; + + ftdm_span_send_signal(ftdmchan->span, &sigev); + r2call->ftdm_call_started = 1; + + break; + + /* the call is making progress */ + case FTDM_CHANNEL_STATE_PROGRESS: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: + { + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + if (!r2call->accepted) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Accepting call\n"); + ft_r2_accept_call(ftdmchan); + } + } else { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n"); + sigev.event_id = FTDM_SIGEVENT_PROCEED; + ftdm_span_send_signal(ftdmchan->span, &sigev); + + sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } + } + break; + + /* the call was answered */ + case FTDM_CHANNEL_STATE_UP: + { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call was answered\n"); + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + if (!r2call->accepted) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call has not been accepted, need to accept first\n"); + // the answering will be done in the on_call_accepted handler + ft_r2_accept_call(ftdmchan); + r2call->answer_pending = 1; + } else { + ft_r2_answer_call(ftdmchan); + } + } else { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying of call answered\n"); + sigev.event_id = FTDM_SIGEVENT_UP; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } + } + break; + + /* just got hangup */ + case FTDM_CHANNEL_STATE_HANGUP: + { + if (!r2call->disconnect_rcvd) { + openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); + /* this will disconnect the call, but need to wait for the call end before moving to DOWN */ + openr2_chan_disconnect_call(r2chan, disconnect_cause); + } else if (!r2call->protocol_error) { + /* just ack the hangup, on_call_end will be called by openr2 right after */ + openr2_chan_disconnect_call(r2chan, OR2_CAUSE_NORMAL_CLEARING); + } else { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Clearing call due to protocol error\n"); + /* do not set to down yet, give some time for recovery */ + ftdm_sched_timer(r2data->sched, "protocolerr_recover", 100, + ftdm_r2_recover_from_protocol_error, r2chan, &r2call->protocol_error_recovery_timer); + } + } + break; + + case FTDM_CHANNEL_STATE_TERMINATING: + { + /* if the call has not been started yet we must go to HANGUP right here */ + if (!r2call->ftdm_call_started) { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + } else { + openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan); + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause)); + /* notify the user of the call terminating and we wait for the user to move us to hangup */ + sigev.event_id = FTDM_SIGEVENT_STOP; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } + } + break; + + /* finished call for good */ + case FTDM_CHANNEL_STATE_DOWN: + { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "R2 Call is down\n"); + ret = FTDM_BREAK; + } + break; + + /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */ + case FTDM_CHANNEL_STATE_RINGING: + { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n"); + } + break; + + default: + { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state)); + } + break; + + } + + if (ret == FTDM_BREAK) { ftdm_channel_t *closed_chan; closed_chan = ftdmchan; ftdm_channel_close(&closed_chan); @@ -1807,20 +1789,6 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) return ret; } -/* the channel must be locked when calling this function */ -static void ftdm_r2_state_advance_all(ftdm_channel_t *ftdmchan) -{ - /* because we do not always acknowledge the state change (clearing the FTDM_CHANNEL_STATE_CHANGE flag) due to the accept - * procedure described below, we need the chanstate member to NOT process some states twice, so is valid entering this - * function with the FTDM_CHANNEL_STATE_CHANGE flag set but with a state that was already processed and is just waiting - * to complete (the processing is media-bound) - * */ - while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) - && (R2CALL(ftdmchan)->chanstate != ftdmchan->state)) { - ftdm_r2_state_advance(ftdmchan); - } -} - static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) { openr2_chan_t *r2chan = NULL; @@ -1949,12 +1917,12 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED); - ftdm_r2_state_advance_all(ftdmchan); + ftdm_channel_advance_states(ftdmchan, ftdm_r2_state_advance); r2chan = call->r2chan; openr2_chan_process_signaling(r2chan); - ftdm_r2_state_advance_all(ftdmchan); + ftdm_channel_advance_states(ftdmchan, ftdm_r2_state_advance); if (!call->accepted) { /* if the call is not accepted we do not want users reading */ diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 30fe6ca4f5..ff129636d9 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -777,11 +777,17 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); /*! \brief Indicate a new condition in an incoming call + * * \note Every indication request will result in FTDM_SIGEVENT_INDICATION_COMPLETED event being delivered with - * the proper status that will inform you if the request was successful or not. - * Be aware there is no guarantee of whether the event will arrive after or before your execution thread returns - * from ftdm_channel_call_indicate. This means you could get FTDM_SIGEVENT_INDICATION_COMPLETED even before - * your execution thread returns from the ftdm_channel_call_indicate() API + * the proper status that will inform you if the request was successful or not. The exception is if this + * function returns something different to FTDM_SUCCESS, in which case the request failed right away and no + * further FTDM_SIGEVENT_INDICATION_COMPLETED will be delivered + * Be aware there is no guarantee of whether the completion event will arrive after or before your execution + * thread returns from ftdm_channel_call_indicate. This means you could get FTDM_SIGEVENT_INDICATION_COMPLETED + * even before your execution thread returns from the ftdm_channel_call_indicate() API + * + * \note You cannot send more than one indication at the time. You must wait for the completed event before + * calling this function again (unless the return code was different than FTDM_SUCCESS) */ #define ftdm_channel_call_indicate(ftdmchan, indication) _ftdm_channel_call_indicate(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (indication)) diff --git a/libs/freetdm/src/include/ftdm_declare.h b/libs/freetdm/src/include/ftdm_declare.h index 2e41281baf..88a76930f7 100644 --- a/libs/freetdm/src/include/ftdm_declare.h +++ b/libs/freetdm/src/include/ftdm_declare.h @@ -192,6 +192,7 @@ typedef enum { FTDM_EINVAL, /*!< Invalid argument */ FTDM_ECANCELED, /*!< Operation cancelled */ + FTDM_EBUSY, /*!< Device busy */ } ftdm_status_t; /*! \brief FreeTDM bool type. */ diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 8f97456fb7..605ab8df15 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -583,7 +583,7 @@ FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap); FT_DECLARE(ftdm_status_t) ftdm_span_close_all(void); FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan); -FT_DECLARE(void) ftdm_ack_indication(const ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_status_t status); +FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_status_t status); /*! * \brief Retrieves an event from the span diff --git a/libs/freetdm/src/include/private/ftdm_state.h b/libs/freetdm/src/include/private/ftdm_state.h index 79a3df07e9..36dcc2bef8 100644 --- a/libs/freetdm/src/include/private/ftdm_state.h +++ b/libs/freetdm/src/include/private/ftdm_state.h @@ -138,8 +138,11 @@ FT_DECLARE(int) ftdm_check_state_all(ftdm_span_t *span, ftdm_channel_state_t sta typedef enum { FTDM_STATE_STATUS_NEW, FTDM_STATE_STATUS_PROCESSED, - FTDM_STATE_STATUS_COMPLETED + FTDM_STATE_STATUS_COMPLETED, + FTDM_STATE_STATUS_INVALID } ftdm_state_status_t; +#define CHANNEL_STATE_STATUS_STRINGS "NEW", "PROCESSED", "COMPLETED", "INVALID" +FTDM_STR2ENUM_P(ftdm_str2ftdm_state_status, ftdm_state_status2str, ftdm_state_status_t) typedef enum { ZSM_NONE, From c854fe518adb53683cb0336a9f1f722b9208e42c Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 29 Dec 2010 14:04:31 -0500 Subject: [PATCH 129/179] freetdm: update 2008 freetdm vcproj to include ftdm_state header and C file --- libs/freetdm/msvc/freetdm.2008.vcproj | 152 ++++++++++++++------------ 1 file changed, 80 insertions(+), 72 deletions(-) diff --git a/libs/freetdm/msvc/freetdm.2008.vcproj b/libs/freetdm/msvc/freetdm.2008.vcproj index c72891e525..0539ff3f42 100644 --- a/libs/freetdm/msvc/freetdm.2008.vcproj +++ b/libs/freetdm/msvc/freetdm.2008.vcproj @@ -94,78 +94,6 @@ Name="VCPostBuildEventTool" /> - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -452,6 +456,10 @@ RelativePath="..\src\ftdm_sched.c" > + + From 6fb1e5d9c1221d4943b52a284668c7435596268f Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 29 Dec 2010 14:08:18 -0500 Subject: [PATCH 130/179] freetdm: free the iterator when setting channels to non-block --- libs/freetdm/src/ftdm_io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0c25054816..5c900b91dd 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1902,6 +1902,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_set_blocking_mode(const ftdm_span_t *span, f ftdm_set_flag_locked(fchan, FTDM_CHANNEL_NONBLOCK); } } + ftdm_iterator_free(citer); return FTDM_SUCCESS; } From 650393fb90f79cfbbe9bc4b89f0d0dbdd9e9c3da Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 29 Dec 2010 13:15:14 -0600 Subject: [PATCH 131/179] add recovery_refresh app and api and use it in mod_conference to send a message to the channel telling it to sync its recovery snapshot --- src/include/switch_types.h | 1 + .../applications/mod_commands/mod_commands.c | 36 +++++++++++++++++++ .../mod_conference/mod_conference.c | 6 ++++ .../applications/mod_dptools/mod_dptools.c | 12 +++++++ src/mod/endpoints/mod_sofia/mod_sofia.c | 2 ++ 5 files changed, 57 insertions(+) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 830ea409e8..bb5f59865f 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -791,6 +791,7 @@ typedef enum { SWITCH_MESSAGE_INDICATE_UDPTL_MODE, SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS, SWITCH_MESSAGE_INDICATE_JITTER_BUFFER, + SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH, SWITCH_MESSAGE_INVALID } switch_core_session_message_types_t; diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 1c2e3ebfb9..8daaace7f3 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -2226,6 +2226,40 @@ SWITCH_STANDARD_API(uuid_deflect) return SWITCH_STATUS_SUCCESS; } +#define UUID_RECOVERY_REFRESH_SYNTAX " " +SWITCH_STANDARD_API(uuid_recovery_refresh) +{ + switch_core_session_t *tsession = NULL; + char *uuid = NULL, *text = NULL; + + if (!zstr(cmd) && (uuid = strdup(cmd))) { + if ((text = strchr(uuid, ' '))) { + *text++ = '\0'; + } + } + + if (zstr(uuid) || zstr(text)) { + stream->write_function(stream, "-USAGE: %s\n", UUID_RECOVERY_REFRESH_SYNTAX); + } else { + if ((tsession = switch_core_session_locate(uuid))) { + switch_core_session_message_t msg = { 0 }; + + /* Tell the channel to recovery_refresh the call */ + msg.from = __FILE__; + msg.string_arg = text; + msg.message_id = SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH; + switch_core_session_receive_message(tsession, &msg); + stream->write_function(stream, "+OK:%s\n", msg.string_reply); + switch_core_session_rwunlock(tsession); + } else { + stream->write_function(stream, "-ERR No Such Channel %s!\n", uuid); + } + } + + switch_safe_free(uuid); + return SWITCH_STATUS_SUCCESS; +} + #define SCHED_TRANSFER_SYNTAX "[+]