Merge root@192.168.1.163:/freeswitch
Conflicts: libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c
This commit is contained in:
commit
c4f821f822
|
@ -112,3 +112,9 @@ QTime Call::getCurrentStateTime()
|
|||
int now = QDateTime::fromTime_t(time).secsTo(QDateTime::currentDateTime());
|
||||
return QTime::fromString(QString::number(now), "s");
|
||||
}
|
||||
|
||||
/*bool Call::transfer()
|
||||
{
|
||||
|
||||
g_FSHost.sendCmd("uuid_bridge", "")
|
||||
}*/
|
||||
|
|
|
@ -38,7 +38,8 @@ typedef enum {
|
|||
FSCOMM_CALL_STATE_RINGING = 0,
|
||||
FSCOMM_CALL_STATE_TRYING = 1,
|
||||
FSCOMM_CALL_STATE_ANSWERED = 2,
|
||||
FSCOMM_CALL_STATE_FAILED = 3
|
||||
FSCOMM_CALL_STATE_FAILED = 3,
|
||||
FSCOMM_CALL_STATE_TRANSFER = 4
|
||||
} fscomm_call_state_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -76,6 +77,8 @@ public:
|
|||
void setAnsweredEpoch(qulonglong time) { _answeredEpoch = time/1000000; }
|
||||
QTime getCurrentStateTime();
|
||||
|
||||
/*bool transfer();*/
|
||||
|
||||
private:
|
||||
QSharedPointer<Channel> _channel; /* This should be our portaudio channel */
|
||||
QSharedPointer<Channel> _otherLegChannel;
|
||||
|
|
|
@ -105,9 +105,23 @@ void ConsoleWindow::cmdSendClicked()
|
|||
|
||||
QString res;
|
||||
g_FSHost.sendCmd(cmd.toAscii().data(), args.toAscii().data(), &res);
|
||||
QStandardItem *item = new QStandardItem(res);
|
||||
item->setData(SWITCH_LOG_CONSOLE, ConsoleModel::LogLevelRole);
|
||||
addNewConsoleItem(item);
|
||||
if (!res.isEmpty())
|
||||
{
|
||||
/* Remove \r\n */
|
||||
QStringList textList = res.split(QRegExp("(\r+)"), QString::SkipEmptyParts);
|
||||
QString final_str;
|
||||
for (int line = 0; line<textList.size(); line++)
|
||||
{
|
||||
final_str += textList[line];
|
||||
}
|
||||
QStringList lines = final_str.split(QRegExp("(\n+)"), QString::SkipEmptyParts);
|
||||
for (int line = 0; line < lines.size(); ++line)
|
||||
{
|
||||
QStandardItem *item = new QStandardItem(lines[line]);
|
||||
item->setData(SWITCH_LOG_CONSOLE, ConsoleModel::LogLevelRole);
|
||||
addNewConsoleItem(item);
|
||||
}
|
||||
}
|
||||
ui->lineCmd->clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
connect(ui->hangupBtn, SIGNAL(clicked()), this, SLOT(paHangup()));
|
||||
connect(ui->recoredCallBtn, SIGNAL(toggled(bool)), SLOT(recordCall(bool)));
|
||||
connect(ui->btnHold, SIGNAL(toggled(bool)), this, SLOT(holdCall(bool)));
|
||||
/*connect(ui->btnTransfer, SIGNAL(clicked()), this, SLOT(transferCall()));*/
|
||||
connect(ui->tableCalls, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this, SLOT(callTableDoubleClick(QTableWidgetItem*)));
|
||||
connect(ui->action_Preferences, SIGNAL(triggered()), this, SLOT(prefTriggered()));
|
||||
connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(close()));
|
||||
|
@ -280,9 +281,9 @@ void MainWindow::callTableDoubleClick(QTableWidgetItem *item)
|
|||
|
||||
void MainWindow::makeCall()
|
||||
{
|
||||
bool ok;
|
||||
bool ok = true;
|
||||
QString dialstring = QInputDialog::getText(this, tr("Make new call"),
|
||||
tr("Number to dial:"), QLineEdit::Normal, NULL,&ok);
|
||||
tr("Number to dial:"), QLineEdit::Normal, NULL,&ok);
|
||||
|
||||
QSharedPointer<Account> acc = g_FSHost.getCurrentDefaultAccount();
|
||||
if (!acc.isNull()) {
|
||||
|
|
|
@ -77,6 +77,7 @@ private slots:
|
|||
void callFailed(QSharedPointer<Call>);
|
||||
void recordCall(bool);
|
||||
void holdCall(bool);
|
||||
/*void transferCall();*/
|
||||
void setDefaultAccount();
|
||||
void accountAdd(QSharedPointer<Account>);
|
||||
void accountDel(QSharedPointer<Account>);
|
||||
|
|
|
@ -91,6 +91,7 @@ static struct {
|
|||
char hold_music[256];
|
||||
switch_mutex_t *mutex;
|
||||
analog_option_t analog_options;
|
||||
switch_hash_t *ss7_configs;
|
||||
} globals;
|
||||
|
||||
struct private_object {
|
||||
|
@ -1961,6 +1962,15 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
|
|||
}
|
||||
|
||||
|
||||
static FIO_SIGNAL_CB_FUNCTION(on_ss7_signal)
|
||||
{
|
||||
if (on_common_signal(sigmsg) == FTDM_BREAK) {
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
ftdm_log(FTDM_LOG_DEBUG, "got ss7 sig %d:%d [%s]\n", sigmsg->channel->span_id, sigmsg->channel->chan_id, ftdm_signal_event2str(sigmsg->event_id));
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
static FIO_SIGNAL_CB_FUNCTION(on_analog_signal)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
@ -2022,10 +2032,140 @@ static uint32_t enable_analog_option(const char *str, uint32_t current_options)
|
|||
|
||||
}
|
||||
|
||||
/* create ftdm_conf_node_t tree based on a fixed pattern XML configuration list
|
||||
* last 2 args are for limited aka dumb recursivity
|
||||
* */
|
||||
static int add_config_list_nodes(switch_xml_t swnode, ftdm_conf_node_t *rootnode,
|
||||
const char *list_name, const char *list_element_name,
|
||||
const char *sub_list_name, const char *sub_list_element_name)
|
||||
{
|
||||
char *var, *val;
|
||||
switch_xml_t list;
|
||||
switch_xml_t element;
|
||||
switch_xml_t param;
|
||||
|
||||
ftdm_conf_node_t *n_list;
|
||||
ftdm_conf_node_t *n_element;
|
||||
|
||||
list = switch_xml_child(swnode, list_name);
|
||||
if (!list) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no list %s found\n", list_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((FTDM_SUCCESS != ftdm_conf_node_create(list_name, &n_list, rootnode))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node\n", list_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (element = switch_xml_child(list, list_element_name); element; element = element->next) {
|
||||
char *element_name = (char *) switch_xml_attr(element, "name");
|
||||
|
||||
if (!element_name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((FTDM_SUCCESS != ftdm_conf_node_create(list_element_name, &n_element, n_list))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node for %s\n", list_element_name, element_name);
|
||||
return -1;
|
||||
}
|
||||
ftdm_conf_node_add_param(n_element, "name", element_name);
|
||||
|
||||
for (param = switch_xml_child(element, "param"); param; param = param->next) {
|
||||
var = (char *) switch_xml_attr_soft(param, "name");
|
||||
val = (char *) switch_xml_attr_soft(param, "value");
|
||||
ftdm_conf_node_add_param(n_element, var, val);
|
||||
}
|
||||
|
||||
if (sub_list_name && sub_list_element_name) {
|
||||
if (add_config_list_nodes(element, n_element, sub_list_name, sub_list_element_name, NULL, NULL)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ftdm_conf_node_t *get_ss7_config_node(switch_xml_t cfg, const char *confname)
|
||||
{
|
||||
switch_xml_t signode, ss7configs, isup;
|
||||
ftdm_conf_node_t *rootnode;
|
||||
|
||||
/* try to find the conf in the hash first */
|
||||
rootnode = switch_core_hash_find(globals.ss7_configs, confname);
|
||||
if (rootnode) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ss7 config %s was found in the hash already\n", confname);
|
||||
return rootnode;
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not found %s config in hash, searching in xml ...\n", confname);
|
||||
|
||||
signode = switch_xml_child(cfg, "signaling_configs");
|
||||
if (!signode) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'signaling_configs' XML config section\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ss7configs = switch_xml_child(signode, "sngss7_configs");
|
||||
if (!ss7configs) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'sngss7_configs' XML config section\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* search the isup config */
|
||||
for (isup = switch_xml_child(ss7configs, "sng_isup"); isup; isup = isup->next) {
|
||||
char *name = (char *) switch_xml_attr(isup, "name");
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
if (!strcasecmp(name, confname)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isup) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found '%s' sng_isup XML config section\n", confname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* found our XML chunk, create the root node */
|
||||
if ((FTDM_SUCCESS != ftdm_conf_node_create("sng_isup", &rootnode, NULL))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create root node for sng_isup config %s\n", confname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add mtp linksets */
|
||||
if (add_config_list_nodes(isup, rootnode, "mtp_linksets", "mtp_linkset", "mtp_links", "mtp_link")) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_linksets for sng_isup config %s\n", confname);
|
||||
ftdm_conf_node_destroy(rootnode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add mtp routes */
|
||||
if (add_config_list_nodes(isup, rootnode, "mtp_routes", "mtp_route", NULL, NULL)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_routes for sng_isup config %s\n", confname);
|
||||
ftdm_conf_node_destroy(rootnode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add isup interfaces */
|
||||
if (add_config_list_nodes(isup, rootnode, "isup_interfaces", "isup_interface", NULL, NULL)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process isup_interfaces for sng_isup config %s\n", confname);
|
||||
ftdm_conf_node_destroy(rootnode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch_core_hash_insert(globals.ss7_configs, confname, rootnode);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added SS7 node configuration %s\n", confname);
|
||||
return rootnode;
|
||||
}
|
||||
|
||||
static switch_status_t load_config(void)
|
||||
{
|
||||
const char *cf = "freetdm.conf";
|
||||
switch_xml_t cfg, xml, settings, param, spans, myspan;
|
||||
ftdm_conf_node_t *ss7confnode = NULL;
|
||||
ftdm_span_t *boost_spans[FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN];
|
||||
ftdm_span_t *boost_span = NULL;
|
||||
unsigned boosti = 0;
|
||||
|
@ -2054,6 +2194,91 @@ static switch_status_t load_config(void)
|
|||
}
|
||||
}
|
||||
|
||||
switch_core_hash_init(&globals.ss7_configs, module_pool);
|
||||
if ((spans = switch_xml_child(cfg, "ss7_spans"))) {
|
||||
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
|
||||
ftdm_status_t zstatus = FTDM_FAIL;
|
||||
const char *context = "default";
|
||||
const char *dialplan = "XML";
|
||||
ftdm_conf_parameter_t spanparameters[30];
|
||||
char *id = (char *) switch_xml_attr(myspan, "id");
|
||||
char *name = (char *) switch_xml_attr(myspan, "name");
|
||||
char *configname = (char *) switch_xml_attr(myspan, "config");
|
||||
ftdm_span_t *span = NULL;
|
||||
uint32_t span_id = 0;
|
||||
unsigned paramindex = 0;
|
||||
if (!name && !id) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute 'id' or 'name', skipping ...\n");
|
||||
continue;
|
||||
}
|
||||
if (!configname) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute, skipping ...\n");
|
||||
continue;
|
||||
}
|
||||
if (name) {
|
||||
zstatus = ftdm_span_find_by_name(name, &span);
|
||||
} else {
|
||||
if (switch_is_number(id)) {
|
||||
span_id = atoi(id);
|
||||
zstatus = ftdm_span_find(span_id, &span);
|
||||
}
|
||||
|
||||
if (zstatus != FTDM_SUCCESS) {
|
||||
zstatus = ftdm_span_find_by_name(id, &span);
|
||||
}
|
||||
}
|
||||
|
||||
if (zstatus != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!span_id) {
|
||||
span_id = span->span_id;
|
||||
}
|
||||
|
||||
ss7confnode = get_ss7_config_node(cfg, configname);
|
||||
if (!ss7confnode) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Error finding ss7config '%s' for FreeTDM span id: %s\n", configname, switch_str_nil(id));
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(spanparameters, 0, sizeof(spanparameters));
|
||||
for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
|
||||
char *var = (char *) switch_xml_attr_soft(param, "name");
|
||||
char *val = (char *) switch_xml_attr_soft(param, "value");
|
||||
|
||||
if (sizeof(spanparameters)/sizeof(spanparameters[0]) == paramindex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for ss7 span, ignoring any parameter after %s\n", var);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcasecmp(var, "context")) {
|
||||
context = val;
|
||||
} else if (!strcasecmp(var, "dialplan")) {
|
||||
dialplan = val;
|
||||
} else {
|
||||
spanparameters[paramindex].var = var;
|
||||
spanparameters[paramindex].val = val;
|
||||
paramindex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ftdm_configure_span("ss7", span, on_ss7_signal,
|
||||
"confnode", ss7confnode,
|
||||
"parameters", spanparameters,
|
||||
TAG_END) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Error configuring ss7 FreeTDM span %d\n", span_id);
|
||||
continue;
|
||||
}
|
||||
SPAN_CONFIG[span->span_id].span = span;
|
||||
switch_copy_string(SPAN_CONFIG[span->span_id].context, context, sizeof(SPAN_CONFIG[span->span_id].context));
|
||||
switch_copy_string(SPAN_CONFIG[span->span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span->span_id].dialplan));
|
||||
switch_copy_string(SPAN_CONFIG[span->span_id].type, "Sangoma (SS7)", sizeof(SPAN_CONFIG[span->span_id].type));
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Configured ss7 FreeTDM span %d with config node %s\n", span_id, configname);
|
||||
}
|
||||
}
|
||||
|
||||
if ((spans = switch_xml_child(cfg, "analog_spans"))) {
|
||||
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
|
||||
char *id = (char *) switch_xml_attr(myspan, "id");
|
||||
|
@ -2504,7 +2729,6 @@ static switch_status_t load_config(void)
|
|||
const char *dialplan = "XML";
|
||||
uint32_t span_id = 0;
|
||||
ftdm_span_t *span = NULL;
|
||||
const char *tonegroup = NULL;
|
||||
ftdm_conf_parameter_t spanparameters[30];
|
||||
unsigned paramindex = 0;
|
||||
|
||||
|
@ -2526,9 +2750,8 @@ static switch_status_t load_config(void)
|
|||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for boost span, ignoring any parameter after %s\n", var);
|
||||
break;
|
||||
}
|
||||
if (!strcasecmp(var, "tonegroup")) {
|
||||
tonegroup = val;
|
||||
} else if (!strcasecmp(var, "context")) {
|
||||
|
||||
if (!strcasecmp(var, "context")) {
|
||||
context = val;
|
||||
} else if (!strcasecmp(var, "dialplan")) {
|
||||
dialplan = val;
|
||||
|
@ -2539,10 +2762,6 @@ static switch_status_t load_config(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (!tonegroup) {
|
||||
tonegroup = "us";
|
||||
}
|
||||
|
||||
if (name) {
|
||||
zstatus = ftdm_span_find_by_name(name, &span);
|
||||
} else {
|
||||
|
@ -3194,6 +3413,17 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
|
|||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown)
|
||||
{
|
||||
switch_hash_index_t *hi;
|
||||
|
||||
const void *var;
|
||||
void *val;
|
||||
|
||||
/* destroy ss7 configs */
|
||||
for (hi = switch_hash_first(NULL, globals.ss7_configs); hi; hi = switch_hash_next(hi)) {
|
||||
switch_hash_this(hi, &var, NULL, &val);
|
||||
ftdm_conf_node_destroy(val);
|
||||
}
|
||||
|
||||
ftdm_global_destroy();
|
||||
|
||||
// this breaks pika but they are MIA so *shrug*
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
* 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 <moy@sangoma.com>
|
||||
*/
|
||||
|
||||
#include "freetdm.h"
|
||||
|
@ -239,6 +243,82 @@ FT_DECLARE (int) ftdm_config_get_cas_bits(char *strvalue, unsigned char *outbits
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define PARAMETERS_CHUNK_SIZE 20
|
||||
FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent)
|
||||
{
|
||||
ftdm_conf_node_t *newnode;
|
||||
ftdm_conf_node_t *sibling = NULL;
|
||||
|
||||
ftdm_assert_return(name != NULL, FTDM_FAIL, "null node name");
|
||||
|
||||
newnode = ftdm_calloc(1, sizeof(**node));
|
||||
if (!newnode) {
|
||||
return FTDM_MEMERR;
|
||||
}
|
||||
|
||||
strncpy(newnode->name, name, sizeof(newnode->name)-1);
|
||||
newnode->name[sizeof(newnode->name)-1] = 0;
|
||||
|
||||
newnode->parameters = ftdm_calloc(PARAMETERS_CHUNK_SIZE, sizeof(*newnode->parameters));
|
||||
if (!newnode->parameters) {
|
||||
ftdm_safe_free(newnode);
|
||||
return FTDM_MEMERR;
|
||||
}
|
||||
newnode->t_parameters = PARAMETERS_CHUNK_SIZE;
|
||||
|
||||
if (parent) {
|
||||
/* store who my parent is */
|
||||
newnode->parent = parent;
|
||||
/* save any siblings */
|
||||
sibling = parent->child;
|
||||
/* as a newborn I am first */
|
||||
parent->child = newnode;
|
||||
if (sibling) {
|
||||
/* store a pointer to my next sibling */
|
||||
newnode->next = sibling;
|
||||
}
|
||||
}
|
||||
|
||||
*node = newnode;
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val)
|
||||
{
|
||||
void *newparameters;
|
||||
|
||||
ftdm_assert_return(param != NULL, FTDM_FAIL, "param is null");
|
||||
ftdm_assert_return(val != NULL, FTDM_FAIL, "val is null");
|
||||
|
||||
if (node->n_parameters == node->t_parameters) {
|
||||
newparameters = ftdm_realloc(node->parameters, (node->t_parameters + PARAMETERS_CHUNK_SIZE) * sizeof(*node->parameters));
|
||||
if (!newparameters) {
|
||||
return FTDM_MEMERR;
|
||||
}
|
||||
node->parameters = newparameters;
|
||||
node->t_parameters = node->n_parameters + PARAMETERS_CHUNK_SIZE;
|
||||
}
|
||||
node->parameters[node->n_parameters].var = param;
|
||||
node->parameters[node->n_parameters].val = val;
|
||||
node->n_parameters++;
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node)
|
||||
{
|
||||
ftdm_conf_node_t *curr = NULL;
|
||||
ftdm_conf_node_t *child = node->child;
|
||||
while (child) {
|
||||
curr = child;
|
||||
child = curr->next;
|
||||
ftdm_conf_node_destroy(curr);
|
||||
}
|
||||
ftdm_free(node->parameters);
|
||||
ftdm_free(node);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
|
|
@ -1087,16 +1087,20 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(ftdm_channel_t *ftdmchan, ftdm_
|
|||
}
|
||||
}
|
||||
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "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));
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (lock) {
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
}
|
||||
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "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 (lock) {
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
}
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
|
||||
if (ftdmchan->span->state_map) {
|
||||
ok = ftdm_parse_state_map(ftdmchan, state, ftdmchan->span->state_map);
|
||||
goto end;
|
||||
|
@ -1353,7 +1357,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc
|
|||
ftdm_span_channel_use_count(span, &count);
|
||||
|
||||
if (count >= span->chan_count) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy.\n");
|
||||
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy: active=%i max=%i.\n",
|
||||
count, span->chan_count);
|
||||
*ftdmchan = NULL;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
@ -1623,8 +1628,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_get_sig_status(ftdm_channel_t *ftdmchan,
|
|||
if (ftdmchan->span->get_channel_sig_status) {
|
||||
return ftdmchan->span->get_channel_sig_status(ftdmchan, sigstatus);
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "get_channel_sig_status method not implemented!\n");
|
||||
return FTDM_FAIL;
|
||||
/* don't log error here, it can be called just to test if its supported */
|
||||
return FTDM_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -414,7 +414,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
|
|||
for (i = 0; i < size; i++) {
|
||||
ints[i] = interrupts[i]->event;
|
||||
if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
|
||||
ints[i+numdevices] = interrupts[i]->device;
|
||||
ints[size+numdevices] = interrupts[i]->device;
|
||||
numdevices++;
|
||||
}
|
||||
}
|
||||
|
@ -446,9 +446,9 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
|
|||
ints[i].revents = 0;
|
||||
ints[i].fd = interrupts[i]->readfd;
|
||||
if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
|
||||
ints[i+numdevices].events = POLLIN;
|
||||
ints[i+numdevices].revents = 0;
|
||||
ints[i+numdevices].fd = interrupts[i]->device;
|
||||
ints[size+numdevices].events = POLLIN;
|
||||
ints[size+numdevices].revents = 0;
|
||||
ints[size+numdevices].fd = interrupts[i]->device;
|
||||
numdevices++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,6 @@ typedef uint16_t sangoma_boost_request_id_t;
|
|||
typedef enum {
|
||||
BST_FREE,
|
||||
BST_WAITING,
|
||||
BST_ACK,
|
||||
BST_READY,
|
||||
BST_FAIL
|
||||
} sangoma_boost_request_status_t;
|
||||
|
@ -109,6 +108,13 @@ typedef struct {
|
|||
int flags;
|
||||
} sangoma_boost_request_t;
|
||||
|
||||
typedef struct {
|
||||
int call_setup_id;
|
||||
int last_event_id;
|
||||
} sangoma_boost_call_t;
|
||||
|
||||
#define CALL_DATA(ftdmchan) ((sangoma_boost_call_t*)((ftdmchan)->call_data))
|
||||
|
||||
//#define MAX_REQ_ID FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN * FTDM_MAX_CHANNELS_PHYSICAL_SPAN
|
||||
#define MAX_REQ_ID 6000
|
||||
|
||||
|
@ -179,7 +185,7 @@ static sangoma_boost_request_id_t __next_request_id(const char *func, int line)
|
|||
r = ++last_req;
|
||||
|
||||
if (r >= MAX_REQ_ID) {
|
||||
r = i = last_req = 1;
|
||||
r = last_req = 1;
|
||||
}
|
||||
|
||||
if (req_map[r]) {
|
||||
|
@ -204,6 +210,25 @@ static sangoma_boost_request_id_t __next_request_id(const char *func, int line)
|
|||
}
|
||||
#define next_request_id() __next_request_id(__FUNCTION__, __LINE__)
|
||||
|
||||
|
||||
static void print_request_ids(void)
|
||||
{
|
||||
sangoma_boost_request_id_t i = 0;
|
||||
|
||||
ftdm_mutex_lock(request_mutex);
|
||||
|
||||
for (i=1; i<= MAX_REQ_ID; i++){
|
||||
if (req_map[i]) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Used Request ID=%i\n",i);
|
||||
}
|
||||
}
|
||||
|
||||
ftdm_mutex_unlock(request_mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Finds the channel that triggered an event
|
||||
* \param span Span where to search the channel
|
||||
|
@ -215,10 +240,26 @@ static ftdm_channel_t *find_ftdmchan(ftdm_span_t *span, sangomabc_short_event_t
|
|||
{
|
||||
uint32_t i;
|
||||
ftdm_channel_t *ftdmchan = NULL;
|
||||
|
||||
ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
|
||||
uint32_t targetspan = BOOST_EVENT_SPAN(sangoma_boost_data->sigmod, event);
|
||||
uint32_t targetchan = BOOST_EVENT_CHAN(sangoma_boost_data->sigmod, event);
|
||||
|
||||
/* NC: Sanity check in case the call setup id does not relate
|
||||
to span. This can happen if RESTART is received on a
|
||||
full load. Where stray ACK messages can arrive after
|
||||
a RESTART has taken place.
|
||||
*/
|
||||
if (!span) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "No Span for Event=%s s%dc%d cid=%d\n",
|
||||
BOOST_DECODE_EVENT_ID(event->event_id),
|
||||
event->span,
|
||||
event->chan,
|
||||
event->call_setup_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
for(i = 1; i <= span->chan_count; i++) {
|
||||
if (span->channels[i]->physical_span_id == targetspan && span->channels[i]->physical_chan_id == targetchan) {
|
||||
ftdmchan = span->channels[i];
|
||||
|
@ -276,6 +317,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
|
|||
* and PRI stack will retransmit a second SETUP after the first timeout, so
|
||||
* we should allow for at least 8 seconds.
|
||||
*/
|
||||
|
||||
int boost_request_timeout = 10000;
|
||||
sangoma_boost_request_status_t st;
|
||||
char dnis[128] = "";
|
||||
|
@ -283,6 +325,13 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
|
|||
uint32_t count = 0;
|
||||
int tg=0;
|
||||
|
||||
/* NC: On large number of calls 10 seconds is not enough.
|
||||
Resetting to 30 seconds. Especially on ss7 when
|
||||
links are reset during large call volume */
|
||||
if (!sangoma_boost_data->sigmod) {
|
||||
boost_request_timeout = 30000;
|
||||
}
|
||||
|
||||
if (sangoma_boost_data->sigmod) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "This function should not be called when sigmod was configured in boost\n");
|
||||
*ftdmchan = NULL;
|
||||
|
@ -290,12 +339,22 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
|
|||
}
|
||||
|
||||
if (ftdm_test_flag(span, FTDM_SPAN_SUSPENDED)) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "SPAN is not online.\n");
|
||||
ftdm_log(FTDM_LOG_CRIT, "SPAN is Suspended.\n");
|
||||
*ftdmchan = NULL;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
ftdm_set_string(dnis, caller_data->dnis.digits);
|
||||
if (check_congestion(tg)) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy. Trunk Group=%i (CONGESTION)\n",tg+1);
|
||||
*ftdmchan = NULL;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (count >= span->chan_count) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy.\n");
|
||||
*ftdmchan = NULL;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
r = next_request_id();
|
||||
if (r == 0) {
|
||||
|
@ -303,7 +362,11 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
|
|||
*ftdmchan = NULL;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
sangomabc_call_init(&event, caller_data->cid_num.digits, dnis, r);
|
||||
|
||||
/* After this point we must release request id before we leave the function
|
||||
in case of an error. */
|
||||
|
||||
ftdm_set_string(dnis, caller_data->dnis.digits);
|
||||
|
||||
if ((gr = strchr(dnis, '@'))) {
|
||||
*gr++ = '\0';
|
||||
|
@ -315,22 +378,14 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
|
|||
tg--;
|
||||
}
|
||||
}
|
||||
|
||||
sangomabc_call_init(&event, caller_data->cid_num.digits, dnis, r);
|
||||
|
||||
event.trunk_group = tg;
|
||||
|
||||
if (check_congestion(tg)) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy. Trunk Group=%i (BOOST REQUESTED BACK OFF)\n",tg+1);
|
||||
*ftdmchan = NULL;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
ftdm_span_channel_use_count(span, &count);
|
||||
|
||||
if (count >= span->chan_count) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "All circuits are busy.\n");
|
||||
*ftdmchan = NULL;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (gr && *(gr+1)) {
|
||||
switch(*gr) {
|
||||
case 'g':
|
||||
|
@ -373,7 +428,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
|
|||
|
||||
if (sangomabc_connection_write(&sangoma_boost_data->mcon, &event) <= 0) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to tx boost event [%s]\n", strerror(errno));
|
||||
status = FTDM_FAIL;
|
||||
status = OUTBOUND_REQUESTS[r].status = FTDM_FAIL;
|
||||
if (!sangoma_boost_data->sigmod) {
|
||||
*ftdmchan = NULL;
|
||||
}
|
||||
|
@ -387,7 +442,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
|
|||
if (!sangoma_boost_data->sigmod) {
|
||||
*ftdmchan = NULL;
|
||||
}
|
||||
ftdm_log(FTDM_LOG_CRIT, "s%dc%d: Csid:%d Timed out waiting for boost channel request response, current status: BST_WAITING\n", (*ftdmchan)->physical_span_id, (*ftdmchan)->physical_chan_id, r);
|
||||
ftdm_log(FTDM_LOG_CRIT, "Csid:%d Timed out waiting for boost channel request response, current status: BST_WAITING\n", r);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
@ -494,6 +549,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(sangoma_boost_outgoing_call)
|
|||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Dialing number %s over boost channel with request id %d\n", event.called_number_digits, r);
|
||||
if (sangomabc_connection_write(&sangoma_boost_data->mcon, &event) <= 0) {
|
||||
release_request_id(r);
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to tx boost event [%s]\n", strerror(errno));
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
@ -550,7 +606,12 @@ static void handle_call_start_ack(sangomabc_connection_t *mcon, sangomabc_short_
|
|||
uint32_t event_span = BOOST_EVENT_SPAN(mcon->sigmod, event);
|
||||
uint32_t event_chan = BOOST_EVENT_CHAN(mcon->sigmod, event);
|
||||
|
||||
|
||||
if (nack_map[event->call_setup_id]) {
|
||||
/* In this scenario outgoing call was alrady stopped
|
||||
via NACK and now we are expecting an NACK_ACK.
|
||||
If we receive an ACK its a race condition thus
|
||||
ignor it */
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -607,15 +668,43 @@ static void handle_call_start_ack(sangomabc_connection_t *mcon, sangomabc_short_
|
|||
OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
ftdm_assert(!mcon->sigmod, "CALL STOP ACK: Invalid Sigmod Path");
|
||||
|
||||
if ((ftdmchan = find_ftdmchan(OUTBOUND_REQUESTS[event->call_setup_id].span, (sangomabc_short_event_t*)event, 1))) {
|
||||
int r;
|
||||
/* NC: If we get CALL START ACK and channel is in active state
|
||||
then we are completely out of sync with the other end.
|
||||
Treat CALL START ACK as CALL STOP and hangup the current call.
|
||||
*/
|
||||
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_UP ||
|
||||
ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA ||
|
||||
ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "FTDM_CHAN STATE UP/PROG/PROG_MEDIA -> Changed to HANGUP %d:%d\n", event->span+1,event->chan+1);
|
||||
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP, 0, r);
|
||||
|
||||
} else if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) {
|
||||
/* Do nothing because outgoing STOP will generaate a stop ack */
|
||||
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_CRIT, "FTDM_CHAN STATE INVALID %s on IN CALL ACK %d:%d\n", ftdm_channel_state2str(ftdmchan->state),event->span+1,event->chan+1);
|
||||
|
||||
}
|
||||
ftdmchan=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!ftdmchan) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "START ACK CANT FIND A CHAN %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
|
||||
} else {
|
||||
/* only reason to be here is failed to open channel when we we're in sigmod */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
|
||||
}
|
||||
ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
|
||||
|
||||
sangomabc_exec_command(mcon,
|
||||
event->span,
|
||||
event->chan,
|
||||
|
@ -677,6 +766,7 @@ static void handle_call_done(ftdm_span_t *span, sangomabc_connection_t *mcon, sa
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Handler for call start nack event
|
||||
* \param span Span where event was fired
|
||||
|
@ -718,7 +808,7 @@ static void handle_call_start_nack(ftdm_span_t *span, sangomabc_connection_t *mc
|
|||
if (event->call_setup_id) {
|
||||
if (sangoma_boost_data->sigmod) {
|
||||
ftdmchan = OUTBOUND_REQUESTS[event->call_setup_id].ftdmchan;
|
||||
ftdmchan->call_data = (void*)(intptr_t)event->event_id;
|
||||
CALL_DATA(ftdmchan)->last_event_id = event->event_id;
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
} else {
|
||||
sangomabc_exec_command(mcon,
|
||||
|
@ -740,7 +830,7 @@ static void handle_call_start_nack(ftdm_span_t *span, sangomabc_connection_t *mc
|
|||
/* if there is no call setup id this should not be an outbound channel for sure */
|
||||
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), "Yay, outbound flag should not be set here!\n");
|
||||
|
||||
ftdmchan->call_data = (void*)(intptr_t)event->event_id;
|
||||
CALL_DATA(ftdmchan)->last_event_id = event->event_id;
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r);
|
||||
if (r == FTDM_STATE_CHANGE_SUCCESS) {
|
||||
|
@ -793,7 +883,16 @@ static void handle_call_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sa
|
|||
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) {
|
||||
if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) ||
|
||||
ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ||
|
||||
ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
|
||||
|
||||
/* NC: Checking for state DOWN because ss7box can
|
||||
send CALL_STOP twice in a row. If we do not check for
|
||||
STATE_DOWN we will set the state back to termnating
|
||||
and block the channel forever
|
||||
*/
|
||||
|
||||
/* racing condition where both sides initiated a hangup
|
||||
* Do not change current state as channel is already clearing
|
||||
* itself through local initiated hangup */
|
||||
|
@ -848,8 +947,18 @@ static void handle_call_answer(ftdm_span_t *span, sangomabc_connection_t *mcon,
|
|||
|
||||
if ((ftdmchan = find_ftdmchan(span, event, 1))) {
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) {
|
||||
|
||||
if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) ||
|
||||
ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ||
|
||||
ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
|
||||
|
||||
/* NC: Do nothing here because we are in process
|
||||
of stopping the call. So ignore the ANSWER. */
|
||||
ftdm_log(FTDM_LOG_CRIT, "ANSWER BUT CALL IS HANGUP %d:%d\n", event->span+1,event->chan+1);
|
||||
|
||||
} else if (ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) {
|
||||
ftdmchan->init_state = FTDM_CHANNEL_STATE_UP;
|
||||
|
||||
} else {
|
||||
int r = 0;
|
||||
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_UP, 0, r);
|
||||
|
@ -881,6 +990,12 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s
|
|||
if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
|
||||
if ((ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
|
||||
int r;
|
||||
|
||||
/* NC: If we get CALL START and channel is in active state
|
||||
then we are completely out of sync with the other end.
|
||||
Treat CALL START as CALL STOP and hangup the current call.
|
||||
*/
|
||||
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_UP) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "ZCHAN STATE UP -> Changed to TERMINATING %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
|
||||
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, 0, r);
|
||||
|
@ -1179,8 +1294,12 @@ static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon,
|
|||
handle_call_done(span, mcon, event);
|
||||
break;
|
||||
case SIGBOOST_EVENT_CALL_START_NACK_ACK:
|
||||
handle_call_done(span, mcon, event);
|
||||
nack_map[event->call_setup_id] = 0;
|
||||
/* On NACK ack span chan are always invalid
|
||||
All there is to do is to clear the id */
|
||||
if (event->call_setup_id) {
|
||||
nack_map[event->call_setup_id] = 0;
|
||||
release_request_id(event->call_setup_id);
|
||||
}
|
||||
break;
|
||||
case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
|
||||
handle_call_loop_start(span, mcon, event);
|
||||
|
@ -1246,7 +1365,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
|||
if (!ftdm_test_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG)) {
|
||||
ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG);
|
||||
|
||||
if (ftdmchan->call_data && ((uint32_t)(intptr_t)ftdmchan->call_data == SIGBOOST_EVENT_CALL_START_NACK)) {
|
||||
if (ftdmchan->call_data && CALL_DATA(ftdmchan)->last_event_id == SIGBOOST_EVENT_CALL_START_NACK) {
|
||||
sangomabc_exec_command(mcon,
|
||||
BOOST_SPAN(ftdmchan),
|
||||
BOOST_CHAN(ftdmchan),
|
||||
|
@ -1266,7 +1385,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
|||
}
|
||||
}
|
||||
ftdmchan->sflags = 0;
|
||||
ftdmchan->call_data = NULL;
|
||||
memset(ftdmchan->call_data,0,sizeof(sangoma_boost_call_t));
|
||||
|
||||
if (sangoma_boost_data->sigmod && call_stopped_ack_sent) {
|
||||
/* we dont want to call ftdm_channel_done just yet until call released is received */
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Waiting for call release confirmation before declaring chan %d:%d as available \n",
|
||||
|
@ -1457,13 +1577,17 @@ static __inline__ void check_state(ftdm_span_t *span)
|
|||
uint32_t j;
|
||||
ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
|
||||
if (susp) {
|
||||
for (j = 0; j <= span->chan_count; j++) {
|
||||
ftdm_mutex_lock(span->channels[j]->mutex);
|
||||
ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
|
||||
ftdm_channel_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART, 0);
|
||||
state_advance(span->channels[j]);
|
||||
ftdm_channel_complete_state(span->channels[j]);
|
||||
ftdm_mutex_unlock(span->channels[j]->mutex);
|
||||
for(j = 1; j <= span->chan_count; j++) {
|
||||
if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE) || susp) {
|
||||
ftdm_mutex_lock(span->channels[j]->mutex);
|
||||
ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
|
||||
if (susp && span->channels[j]->state != FTDM_CHANNEL_STATE_DOWN) {
|
||||
ftdm_channel_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART, 0);
|
||||
}
|
||||
state_advance(span->channels[j]);
|
||||
ftdm_channel_complete_state(span->channels[j]);
|
||||
ftdm_mutex_unlock(span->channels[j]->mutex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) {
|
||||
|
@ -1642,8 +1766,8 @@ static int ftdm_boost_wait_event(ftdm_span_t *span)
|
|||
sangoma_boost_data->iteration = 0;
|
||||
}
|
||||
#endif
|
||||
res = ftdm_interrupt_multiple_wait(ints, numints, -1);
|
||||
if (FTDM_SUCCESS != res) {
|
||||
res = ftdm_interrupt_multiple_wait(ints, numints, 100);
|
||||
if (FTDM_SUCCESS != res && FTDM_TIMEOUT != res) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Unexpected return value from interrupt waiting: %d\n", res);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1730,7 +1854,6 @@ static void *ftdm_sangoma_boost_run(ftdm_thread_t *me, void *obj)
|
|||
|
||||
if (ftdm_boost_wait_event(span) < 0) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "ftdm_boost_wait_event failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
while ((event = ftdm_boost_read_event(span))) {
|
||||
|
@ -1743,7 +1866,6 @@ static void *ftdm_sangoma_boost_run(ftdm_thread_t *me, void *obj)
|
|||
|
||||
goto end;
|
||||
|
||||
error:
|
||||
ftdm_log(FTDM_LOG_CRIT, "Boost event processing Error!\n");
|
||||
|
||||
end:
|
||||
|
@ -1758,6 +1880,37 @@ end:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int sigmod_ss7box_isup_exec_cmd(ftdm_stream_handle_t *stream, char *cmd)
|
||||
{
|
||||
FILE *fp;
|
||||
int status=0;
|
||||
char path[1024];
|
||||
|
||||
fp = popen(cmd, "r");
|
||||
if (fp == NULL) {
|
||||
stream->write_function(stream, "%s: -ERR failed to execute cmd: %s\n",
|
||||
__FILE__,cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(path, sizeof(path)-1, fp) != NULL) {
|
||||
path[sizeof(path)-1]='\0';
|
||||
stream->write_function(stream,"%s", path);
|
||||
}
|
||||
|
||||
|
||||
status = pclose(fp);
|
||||
if (status == -1) {
|
||||
/* Error reported by pclose() */
|
||||
} else {
|
||||
/* Use macros described under wait() to inspect `status' in order
|
||||
to determine success/failure of command executed by popen() */
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define FTDM_BOOST_SYNTAX "list sigmods | <sigmod_name> <command>"
|
||||
/**
|
||||
|
@ -1780,11 +1933,63 @@ static FIO_API_FUNCTION(ftdm_sangoma_boost_api)
|
|||
if (!strcasecmp(argv[0], "list")) {
|
||||
if (!strcasecmp(argv[1], "sigmods")) {
|
||||
if (ftdm_sangoma_boost_list_sigmods(stream) != FTDM_SUCCESS) {
|
||||
stream->write_function(stream, "%s: -ERR failed to execute cmd\n", __FILE__);
|
||||
stream->write_function(stream, "-ERR failed to list sigmods\n");
|
||||
goto done;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[1], "ids")) {
|
||||
print_request_ids();
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
#if 0
|
||||
/* NC: This code crashes the kernel due to fork on heavy fs load */
|
||||
} else if (!strcasecmp(argv[0], "ss7box_isupd_ckt")) {
|
||||
|
||||
if (!strcasecmp(argv[1], "used")) {
|
||||
stream->write_function(stream, "ss7box_isupd: in use\n", FTDM_BOOST_SYNTAX);
|
||||
sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh inuse");
|
||||
} else if (!strcasecmp(argv[1], "reset")) {
|
||||
stream->write_function(stream, "ss7box_isupd: in reset\n", FTDM_BOOST_SYNTAX);
|
||||
sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh reset");
|
||||
} else if (!strcasecmp(argv[1], "ready")) {
|
||||
stream->write_function(stream, "ss7box_isupd: ready \n", FTDM_BOOST_SYNTAX);
|
||||
sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh free");
|
||||
} else {
|
||||
stream->write_function(stream, "ss7box_isupd: list\n", FTDM_BOOST_SYNTAX);
|
||||
sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh");
|
||||
}
|
||||
|
||||
goto done;
|
||||
#endif
|
||||
#endif
|
||||
} else if (!strcasecmp(argv[0], "restart")) {
|
||||
sangomabc_connection_t *pcon;
|
||||
ftdm_sangoma_boost_data_t *sangoma_boost_data;
|
||||
ftdm_span_t *span;
|
||||
int err = ftdm_span_find_by_name(argv[1], &span);
|
||||
if (FTDM_SUCCESS != err) {
|
||||
stream->write_function(stream, "-ERR failed to find span by name %s\n",argv[1]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
sangoma_boost_data = span->signal_data;
|
||||
pcon = &sangoma_boost_data->pcon;
|
||||
|
||||
/* No need to set any span flags because
|
||||
our RESTART will generate a RESTART from the sig daemon */
|
||||
sangomabc_exec_commandp(pcon,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
SIGBOOST_EVENT_SYSTEM_RESTART,
|
||||
0);
|
||||
|
||||
goto done;
|
||||
|
||||
} else {
|
||||
boost_sigmod_interface_t *sigmod_iface = NULL;
|
||||
sigmod_iface = hashtable_search(g_boost_modules_hash, argv[0]);
|
||||
|
@ -1822,7 +2027,7 @@ done:
|
|||
*/
|
||||
static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_boost_io_init)
|
||||
{
|
||||
assert(fio != NULL);
|
||||
ftdm_assert(fio != NULL, "fio is NULL");
|
||||
memset(&ftdm_sangoma_boost_interface, 0, sizeof(ftdm_sangoma_boost_interface));
|
||||
|
||||
ftdm_sangoma_boost_interface.name = "boost";
|
||||
|
@ -2205,6 +2410,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span)
|
|||
ftdm_dso_lib_t lib = NULL;
|
||||
char path[255] = "";
|
||||
char *err = NULL;
|
||||
int j = 0;
|
||||
unsigned paramindex = 0;
|
||||
ftdm_status_t rc = FTDM_SUCCESS;
|
||||
|
||||
|
@ -2299,6 +2505,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span)
|
|||
ftdm_set_string(sangoma_boost_data->mcon.cfg.remote_ip, remote_ip);
|
||||
sangoma_boost_data->mcon.cfg.remote_port = remote_port;
|
||||
}
|
||||
|
||||
for (j = 1; j <= span->chan_count; j++) {
|
||||
span->channels[j]->call_data = ftdm_calloc(1,sizeof(sangoma_boost_call_t));
|
||||
if (!span->channels[j]->call_data) {
|
||||
FAIL_CONFIG_RETURN(FTDM_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
span->signal_cb = sig_cb;
|
||||
span->start = ftdm_sangoma_boost_start;
|
||||
span->stop = ftdm_sangoma_boost_stop;
|
||||
|
|
|
@ -77,7 +77,7 @@ static void sangomabc_print_event_call(sangomabc_connection_t *mcon, sangomabc_e
|
|||
if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
|
||||
return;
|
||||
|
||||
ftdm_log(file, func, line, FTDM_LOG_LEVEL_DEBUG, "%s EVENT (%s): %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s] Rdnis=[%s]\n",
|
||||
ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "%s EVENT (%s): %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s] Rdnis=[%s]\n",
|
||||
dir ? "TX":"RX",
|
||||
priority ? "P":"N",
|
||||
sangomabc_event_id_name(event->event_id),
|
||||
|
@ -96,7 +96,7 @@ static void sangomabc_print_event_short(sangomabc_connection_t *mcon, sangomabc_
|
|||
{
|
||||
if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
|
||||
return;
|
||||
ftdm_log(file, func, line, FTDM_LOG_LEVEL_DEBUG, "%s EVENT (%s): %s:(%X) [s%dc%d] Rc=%i CSid=%i Seq=%i \n",
|
||||
ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "%s EVENT (%s): %s:(%X) [s%dc%d] Rc=%i CSid=%i Seq=%i \n",
|
||||
dir ? "TX":"RX",
|
||||
priority ? "P":"N",
|
||||
sangomabc_event_id_name(event->event_id),
|
||||
|
|
|
@ -51,6 +51,24 @@ enum e_sigboost_event_id_values
|
|||
SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE = 0x8c, /*140*/
|
||||
SIGBOOST_EVENT_DIGIT_IN = 0x8d, /*141*/
|
||||
};
|
||||
|
||||
#define BOOST_DECODE_EVENT_ID(id) \
|
||||
(id==SIGBOOST_EVENT_CALL_START)?"SIGBOOST_EVENT_CALL_START": \
|
||||
(id==SIGBOOST_EVENT_CALL_START_ACK)?"SIGBOOST_EVENT_CALL_START_ACK": \
|
||||
(id==SIGBOOST_EVENT_CALL_START_NACK)?"SIGBOOST_EVENT_CALL_START_NACK": \
|
||||
(id==SIGBOOST_EVENT_CALL_ANSWERED)?"SIGBOOST_EVENT_CALL_ANSWERED": \
|
||||
(id==SIGBOOST_EVENT_CALL_STOPPED)?"SIGBOOST_EVENT_CALL_STOPPED": \
|
||||
(id==SIGBOOST_EVENT_CALL_STOPPED_ACK)?"SIGBOOST_EVENT_CALL_STOPPED_ACK": \
|
||||
(id==SIGBOOST_EVENT_SYSTEM_RESTART)?"SIGBOOST_EVENT_SYSTEM_RESTART": \
|
||||
(id==SIGBOOST_EVENT_SYSTEM_RESTART_ACK)?"SIGBOOST_EVENT_SYSTEM_RESTART_ACK": \
|
||||
(id==SIGBOOST_EVENT_CALL_RELEASED)?"SIGBOOST_EVENT_CALL_RELEASED": \
|
||||
(id==SIGBOOST_EVENT_CALL_PROGRESS)?"SIGBOOST_EVENT_CALL_PROGRESS": \
|
||||
(id==SIGBOOST_EVENT_HEARTBEAT)?"SIGBOOST_EVENT_HEARTBEAT": \
|
||||
(id==SIGBOOST_EVENT_INSERT_CHECK_LOOP)?"SIGBOOST_EVENT_INSERT_CHECK_LOOP": \
|
||||
(id==SIGBOOST_EVENT_REMOVE_CHECK_LOOP)?"SIGBOOST_EVENT_REMOVE_CHECK_LOOP": \
|
||||
(id==SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE)?"SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE": \
|
||||
(id==SIGBOOST_EVENT_DIGIT_IN)?"SIGBOOST_EVENT_DIGIT_IN": "Unknown"
|
||||
|
||||
enum e_sigboost_release_cause_values
|
||||
{
|
||||
SIGBOOST_RELEASE_CAUSE_UNDEFINED = 0,
|
||||
|
|
|
@ -827,6 +827,9 @@ FT_DECLARE(char *) ftdm_api_execute(const char *type, const char *cmd);
|
|||
FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap);
|
||||
FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data);
|
||||
FT_DECLARE(void) ftdm_cpu_monitor_disable(void);
|
||||
FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent);
|
||||
FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val);
|
||||
FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node);
|
||||
|
||||
FIO_CODEC_FUNCTION(fio_slin2ulaw);
|
||||
FIO_CODEC_FUNCTION(fio_ulaw2slin);
|
||||
|
|
|
@ -572,6 +572,30 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ;
|
|||
|
||||
#include "ftdm_dso.h"
|
||||
|
||||
#define FTDM_NODE_NAME_SIZE 50
|
||||
typedef struct ftdm_conf_node_s {
|
||||
/* node name */
|
||||
char name[FTDM_NODE_NAME_SIZE];
|
||||
|
||||
/* total slots for parameters */
|
||||
unsigned int t_parameters;
|
||||
|
||||
/* current number of parameters */
|
||||
unsigned int n_parameters;
|
||||
|
||||
/* array of parameters */
|
||||
ftdm_conf_parameter_t *parameters;
|
||||
|
||||
/* first node child */
|
||||
struct ftdm_conf_node_s *child;
|
||||
|
||||
/* next node sibling */
|
||||
struct ftdm_conf_node_s *next;
|
||||
|
||||
/* my parent if any */
|
||||
struct ftdm_conf_node_s *parent;
|
||||
} ftdm_conf_node_t;
|
||||
|
||||
typedef struct {
|
||||
char name[256];
|
||||
fio_io_load_t io_load;
|
||||
|
@ -583,9 +607,9 @@ typedef struct {
|
|||
\brief configure a given span signaling
|
||||
\see sig_configure
|
||||
This is just like sig_configure but receives
|
||||
an array of paramters instead of va_list
|
||||
an an ftdm_conf_node_t instead
|
||||
I'd like to deprecate sig_configure and move
|
||||
all modules to use sigparam_configure
|
||||
all modules to use configure_span_signaling
|
||||
*/
|
||||
fio_configure_span_signaling_t configure_span_signaling;
|
||||
ftdm_dso_lib_t lib;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#ifndef __WINDOWS__
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#define MAX_TRUNK_GROUPS 64
|
||||
static time_t congestion_timeouts[MAX_TRUNK_GROUPS];
|
||||
|
@ -484,6 +487,30 @@ static void handle_call_start_ack(sangomabc_connection_t *mcon, sangomabc_short_
|
|||
OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, (sangomabc_short_event_t*)event, 1))) {
|
||||
int r;
|
||||
|
||||
/* NC: If we get CALL START ACK and channel is in active state
|
||||
then we are completely out of sync with the other end.
|
||||
Treat CALL START ACK as CALL STOP and hangup the current call.
|
||||
*/
|
||||
|
||||
if (zchan->state == ZAP_CHANNEL_STATE_UP ||
|
||||
zchan->state == ZAP_CHANNEL_STATE_PROGRESS_MEDIA ||
|
||||
zchan->state == ZAP_CHANNEL_STATE_PROGRESS) {
|
||||
zap_log(ZAP_LOG_CRIT, "ZCHAN STATE UP/PROG/PROG_MEDIA -> Changed to HANGUP %d:%d\n", event->span+1,event->chan+1);
|
||||
zap_set_state_r(zchan, ZAP_CHANNEL_STATE_HANGUP, 0, r);
|
||||
|
||||
} else if (zap_test_sflag(zchan, SFLAG_HANGUP)) {
|
||||
/* Do nothing because outgoing STOP will generaate a stop ack */
|
||||
|
||||
} else {
|
||||
zap_log(ZAP_LOG_CRIT, "ZCHAN STATE INVALID %s on IN CALL ACK %d:%d\n", zap_channel_state2str(zchan->state),event->span+1,event->chan+1);
|
||||
|
||||
}
|
||||
zchan=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("WTF BAD ACK CSid=%d span=%d chan=%d\n", event->call_setup_id, event->span+1,event->chan+1);
|
||||
|
@ -640,7 +667,14 @@ static void handle_call_stop(zap_span_t *span, sangomabc_connection_t *mcon, san
|
|||
|
||||
zap_mutex_lock(zchan->mutex);
|
||||
|
||||
if (zap_test_sflag(zchan, SFLAG_HANGUP)) {
|
||||
if (zap_test_sflag(zchan, SFLAG_HANGUP) || zchan->state == ZAP_CHANNEL_STATE_DOWN) {
|
||||
|
||||
/* NC: Checking for state DOWN because ss7box can
|
||||
send CALL_STOP twice in a row. If we do not check for
|
||||
STATE_DOWN we will set the state back to termnating
|
||||
and block the channel forever
|
||||
*/
|
||||
|
||||
/* racing condition where both sides initiated a hangup
|
||||
* Do not change current state as channel is already clearing
|
||||
* itself through local initiated hangup */
|
||||
|
@ -697,7 +731,14 @@ static void handle_call_answer(zap_span_t *span, sangomabc_connection_t *mcon, s
|
|||
|
||||
if ((zchan = find_zchan(span, event, 1))) {
|
||||
zap_mutex_lock(zchan->mutex);
|
||||
if (zchan->state == ZAP_CHANNEL_STATE_HOLD) {
|
||||
if (zap_test_sflag(zchan, SFLAG_HANGUP) ||
|
||||
zchan->state == ZAP_CHANNEL_STATE_DOWN ||
|
||||
zchan->state == ZAP_CHANNEL_STATE_TERMINATING) {
|
||||
/* NC: Do nothing here because we are in process
|
||||
of stopping the call. So ignore the ANSWER. */
|
||||
zap_log(ZAP_LOG_CRIT, "ANSWER BUT CALL IS HANGUP %d:%d\n", event->span+1,event->chan+1);
|
||||
|
||||
} else if (zchan->state == ZAP_CHANNEL_STATE_HOLD) {
|
||||
zchan->init_state = ZAP_CHANNEL_STATE_UP;
|
||||
} else {
|
||||
int r = 0;
|
||||
|
@ -731,6 +772,12 @@ static void handle_call_start(zap_span_t *span, sangomabc_connection_t *mcon, sa
|
|||
if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 0))) {
|
||||
if ((zchan = find_zchan(span, (sangomabc_short_event_t*)event, 1))) {
|
||||
int r;
|
||||
|
||||
/* NC: If we get CALL START and channel is in active state
|
||||
then we are completely out of sync with the other end.
|
||||
Treat CALL START as CALL STOP and hangup the current call.
|
||||
*/
|
||||
|
||||
if (zchan->state == ZAP_CHANNEL_STATE_UP) {
|
||||
zap_log(ZAP_LOG_CRIT, "ZCHAN STATE UP -> Changed to TERMINATING %d:%d\n", event->span+1,event->chan+1);
|
||||
zap_set_state_r(zchan, ZAP_CHANNEL_STATE_TERMINATING, 0, r);
|
||||
|
@ -1380,6 +1427,65 @@ static void *zap_sangoma_events_run(zap_thread_t *me, void *obj)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
static int waitfor_2sockets(int fda, int fdb, char *a, char *b, int timeout)
|
||||
{
|
||||
struct pollfd pfds[2];
|
||||
int res = 0;
|
||||
int errflags = (POLLERR | POLLHUP | POLLNVAL);
|
||||
|
||||
if (fda < 0 || fdb < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
waitfor_2sockets_tryagain:
|
||||
|
||||
*a=0;
|
||||
*b=0;
|
||||
|
||||
|
||||
memset(pfds, 0, sizeof(pfds));
|
||||
|
||||
pfds[0].fd = fda;
|
||||
pfds[1].fd = fdb;
|
||||
pfds[0].events = POLLIN | errflags;
|
||||
pfds[1].events = POLLIN | errflags;
|
||||
|
||||
res = poll(pfds, 2, timeout);
|
||||
|
||||
if (res > 0) {
|
||||
res = 1;
|
||||
if ((pfds[0].revents & errflags) || (pfds[1].revents & errflags)) {
|
||||
res = -1;
|
||||
} else {
|
||||
if ((pfds[0].revents & POLLIN)) {
|
||||
*a=1;
|
||||
res++;
|
||||
}
|
||||
if ((pfds[1].revents & POLLIN)) {
|
||||
*b=1;
|
||||
res++;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == 1) {
|
||||
/* No event found what to do */
|
||||
res=-1;
|
||||
}
|
||||
} else if (res < 0) {
|
||||
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
goto waitfor_2sockets_tryagain;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Main thread function for sangoma boost span (monitor)
|
||||
* \param me Current thread
|
||||
|
@ -1391,7 +1497,13 @@ static void *zap_sangoma_boost_run(zap_thread_t *me, void *obj)
|
|||
zap_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
|
||||
sangomabc_connection_t *mcon, *pcon;
|
||||
uint32_t ms = 10; //, too_long = 20000;
|
||||
|
||||
int max, activity, i;
|
||||
sangomabc_event_t *event;
|
||||
struct timeval tv;
|
||||
fd_set rfds, efds;
|
||||
#ifndef __WINDOWS__
|
||||
char a=0,b=0;
|
||||
#endif
|
||||
|
||||
sangoma_boost_data->pcon = sangoma_boost_data->mcon;
|
||||
|
||||
|
@ -1427,10 +1539,13 @@ static void *zap_sangoma_boost_run(zap_thread_t *me, void *obj)
|
|||
zap_set_flag(mcon, MSU_FLAG_DOWN);
|
||||
|
||||
while (zap_test_flag(sangoma_boost_data, ZAP_SANGOMA_BOOST_RUNNING)) {
|
||||
fd_set rfds, efds;
|
||||
struct timeval tv = { 0, ms * 1000 };
|
||||
int max, activity, i = 0;
|
||||
sangomabc_event_t *event = NULL;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = ms* 1000;
|
||||
max=0;
|
||||
activity=0;
|
||||
i=0;
|
||||
event = NULL;
|
||||
|
||||
if (!zap_running()) {
|
||||
sangomabc_exec_commandp(pcon,
|
||||
|
@ -1452,6 +1567,7 @@ static void *zap_sangoma_boost_run(zap_thread_t *me, void *obj)
|
|||
|
||||
max = ((pcon->socket > mcon->socket) ? pcon->socket : mcon->socket) + 1;
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
if ((activity = select(max, &rfds, NULL, &efds, &tv)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -1477,7 +1593,33 @@ static void *zap_sangoma_boost_run(zap_thread_t *me, void *obj)
|
|||
}
|
||||
|
||||
}
|
||||
#else
|
||||
|
||||
a=0;
|
||||
b=0;
|
||||
i=0;
|
||||
tv.tv_sec=0;
|
||||
activity = waitfor_2sockets(pcon->socket,mcon->socket,&a,&b,ms);
|
||||
if (activity) {
|
||||
if (a) {
|
||||
while ((event = sangomabc_connection_readp(pcon, i))) {
|
||||
parse_sangoma_event(span, pcon, (sangomabc_short_event_t*)event);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i=0;
|
||||
|
||||
if (b) {
|
||||
if ((event = sangomabc_connection_read(mcon, i))) {
|
||||
parse_sangoma_event(span, mcon, (sangomabc_short_event_t*)event);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else if (activity < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
pcon->hb_elapsed += ms;
|
||||
|
||||
|
|
|
@ -57,6 +57,24 @@ enum e_sigboost_event_id_values
|
|||
SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE = 0x8c, /*140*/
|
||||
SIGBOOST_EVENT_DIGIT_IN = 0x8d, /*141*/
|
||||
};
|
||||
|
||||
#define BOOST_DECODE_EVENT_ID(id) \
|
||||
(id==SIGBOOST_EVENT_CALL_START)?"SIGBOOST_EVENT_CALL_START": \
|
||||
(id==SIGBOOST_EVENT_CALL_START_ACK)?"SIGBOOST_EVENT_CALL_START_ACK": \
|
||||
(id==SIGBOOST_EVENT_CALL_START_NACK)?"SIGBOOST_EVENT_CALL_START_NACK": \
|
||||
(id==SIGBOOST_EVENT_CALL_ANSWERED)?"SIGBOOST_EVENT_CALL_ANSWERED": \
|
||||
(id==SIGBOOST_EVENT_CALL_STOPPED)?"SIGBOOST_EVENT_CALL_STOPPED": \
|
||||
(id==SIGBOOST_EVENT_CALL_STOPPED_ACK)?"SIGBOOST_EVENT_CALL_STOPPED_ACK": \
|
||||
(id==SIGBOOST_EVENT_SYSTEM_RESTART)?"SIGBOOST_EVENT_SYSTEM_RESTART": \
|
||||
(id==SIGBOOST_EVENT_SYSTEM_RESTART_ACK)?"SIGBOOST_EVENT_SYSTEM_RESTART_ACK": \
|
||||
(id==SIGBOOST_EVENT_CALL_RELEASED)?"SIGBOOST_EVENT_CALL_RELEASED": \
|
||||
(id==SIGBOOST_EVENT_CALL_PROGRESS)?"SIGBOOST_EVENT_CALL_PROGRESS": \
|
||||
(id==SIGBOOST_EVENT_HEARTBEAT)?"SIGBOOST_EVENT_HEARTBEAT": \
|
||||
(id==SIGBOOST_EVENT_INSERT_CHECK_LOOP)?"SIGBOOST_EVENT_INSERT_CHECK_LOOP": \
|
||||
(id==SIGBOOST_EVENT_REMOVE_CHECK_LOOP)?"SIGBOOST_EVENT_REMOVE_CHECK_LOOP": \
|
||||
(id==SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE)?"SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE": \
|
||||
(id==SIGBOOST_EVENT_DIGIT_IN)?"SIGBOOST_EVENT_DIGIT_IN": "Unknown"
|
||||
|
||||
enum e_sigboost_release_cause_values
|
||||
{
|
||||
SIGBOOST_RELEASE_CAUSE_UNDEFINED = 0,
|
||||
|
|
|
@ -2622,10 +2622,12 @@ SWITCH_STANDARD_API(session_audio_function)
|
|||
#define BREAK_SYNTAX "<uuid> [all]"
|
||||
SWITCH_STANDARD_API(break_function)
|
||||
{
|
||||
switch_core_session_t *psession = NULL;
|
||||
switch_core_session_t *psession = NULL, *qsession = NULL;
|
||||
char *mycmd = NULL, *flag;
|
||||
switch_channel_t *channel = NULL;
|
||||
switch_channel_t *channel = NULL, *qchannel = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
int all = 0;
|
||||
int both = 0;
|
||||
|
||||
if (zstr(cmd)) {
|
||||
stream->write_function(stream, "-USAGE: %s\n", BREAK_SYNTAX);
|
||||
|
@ -2644,22 +2646,58 @@ SWITCH_STANDARD_API(break_function)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (flag && !strcasecmp(flag, "all")) {
|
||||
switch_core_session_flush_private_events(psession);
|
||||
if (flag) {
|
||||
if (strstr(flag, "all")) {
|
||||
all++;
|
||||
}
|
||||
if (strstr(flag, "both")) {
|
||||
both++;
|
||||
}
|
||||
}
|
||||
|
||||
channel = switch_core_session_get_channel(psession);
|
||||
|
||||
if (both) {
|
||||
const char *quuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
|
||||
if (quuid) {
|
||||
qsession = switch_core_session_locate(quuid);
|
||||
qchannel = switch_core_session_get_channel(qsession);
|
||||
}
|
||||
}
|
||||
|
||||
if (all) {
|
||||
switch_core_session_flush_private_events(psession);
|
||||
if (qsession) {
|
||||
switch_core_session_flush_private_events(qsession);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_BROADCAST)) {
|
||||
switch_channel_stop_broadcast(channel);
|
||||
} else {
|
||||
switch_channel_set_flag(channel, CF_BREAK);
|
||||
}
|
||||
|
||||
if (qchannel) {
|
||||
if (switch_channel_test_flag(qchannel, CF_BROADCAST)) {
|
||||
switch_channel_stop_broadcast(qchannel);
|
||||
} else {
|
||||
switch_channel_set_flag(qchannel, CF_BREAK);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (psession) {
|
||||
switch_core_session_rwunlock(psession);
|
||||
}
|
||||
|
||||
if (qsession) {
|
||||
switch_core_session_rwunlock(qsession);
|
||||
}
|
||||
|
||||
switch_safe_free(mycmd);
|
||||
|
||||
return status;
|
||||
|
@ -4164,6 +4202,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
|||
SWITCH_ADD_API(commands_api_interface, "user_data", "find user data", user_data_function, "<user>@<domain> [var|param|attr] <name>");
|
||||
SWITCH_ADD_API(commands_api_interface, "user_exists", "find a user", user_exists_function, "<key> <user> <domain>");
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_audio", "uuid_audio", session_audio_function, AUDIO_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_break", "Break", break_function, BREAK_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_bridge", "uuid_bridge", uuid_bridge_function, "");
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_broadcast", "broadcast", uuid_broadcast_function, BROADCAST_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_chat", "Send a chat message", uuid_chat, UUID_CHAT_SYNTAX);
|
||||
|
@ -4261,6 +4300,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
|||
switch_console_set_complete("add uuid_audio ::console::list_uuid start write mute");
|
||||
switch_console_set_complete("add uuid_audio ::console::list_uuid start write level");
|
||||
switch_console_set_complete("add uuid_audio ::console::list_uuid stop");
|
||||
switch_console_set_complete("add uuid_break ::console::list_uuid all");
|
||||
switch_console_set_complete("add uuid_break ::console::list_uuid both");
|
||||
switch_console_set_complete("add uuid_bridge ::console::list_uuid ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_broadcast ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_chat ::console::list_uuid");
|
||||
|
|
|
@ -261,6 +261,7 @@ SWITCH_STANDARD_APP(valet_parking_function)
|
|||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Lot-Name", lot_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Extension", ext);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "hold");
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
|
@ -286,6 +287,14 @@ SWITCH_STANDARD_APP(valet_parking_function)
|
|||
switch_mutex_lock(lot->mutex);
|
||||
switch_core_hash_delete(lot->hash, ext);
|
||||
switch_mutex_unlock(lot->mutex);
|
||||
|
||||
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VALET_EVENT) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Lot-Name", lot_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Extension", ext);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "exit");
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", VALET_APP_SYNTAX);
|
||||
}
|
||||
|
|
|
@ -3353,7 +3353,7 @@ SWITCH_STANDARD_API(prefs_api_function)
|
|||
stream->write_function(stream, "-ERR No such profile\n");
|
||||
goto done;
|
||||
}
|
||||
if (!(profile = get_profile("default"))) {
|
||||
if (!profile && !(profile = get_profile("default"))) {
|
||||
stream->write_function(stream, "-ERR profile 'default' doesn't exist\n");
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -71,10 +71,10 @@ static switch_mutex_t *g_sessions_lock = NULL;
|
|||
unsigned long long g_next_session_id = 0;
|
||||
|
||||
/* hash of sessions (I think a linked list suits better here, but FS does not have the data type) */
|
||||
switch_hash_t *g_sessions_hash = NULL;
|
||||
static switch_hash_t *g_sessions_hash = NULL;
|
||||
|
||||
/* global memory pool provided by FS */
|
||||
switch_memory_pool_t *g_pool = NULL;
|
||||
static switch_memory_pool_t *g_pool = NULL;
|
||||
|
||||
typedef struct vocallo_codec_s {
|
||||
int codec_id; /* vocallo codec ID */
|
||||
|
|
|
@ -651,7 +651,7 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN
|
|||
|
||||
skinny_line_set_state(listener, line_instance, call_id, SKINNY_ON_HOOK);
|
||||
send_select_soft_keys(listener, line_instance, call_id, SKINNY_KEY_SET_ON_HOOK, 0xffff);
|
||||
/* TODO: DefineTimeDate */
|
||||
send_define_current_time_date(listener);
|
||||
send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF);
|
||||
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, call_id);
|
||||
}
|
||||
|
|
|
@ -584,8 +584,12 @@ int skinny_session_process_dest_callback(void *pArg, int argc, char **argv, char
|
|||
&& (line_instance == helper->line_instance)) {/* the calling line */
|
||||
/* nothing */
|
||||
} else {
|
||||
/* TODO: capture and check what should happen here*/
|
||||
skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
|
||||
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
|
||||
skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
|
||||
send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, 10, 0xffff);
|
||||
send_display_prompt_status(listener, 0, "\200\037",
|
||||
line_instance, helper->tech_pvt->call_id);
|
||||
skinny_send_call_info(helper->tech_pvt->session, listener, line_instance);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -604,21 +608,24 @@ switch_status_t skinny_session_process_dest(switch_core_session_t *session, list
|
|||
tech_pvt = switch_core_session_get_private(session);
|
||||
|
||||
if (!dest) {
|
||||
if (backspace) { /* backspace */
|
||||
*tech_pvt->caller_profile->destination_number++ = '\0';
|
||||
if (strlen(tech_pvt->caller_profile->destination_number) == 0) {/* no digit yet */
|
||||
send_start_tone(listener, SKINNY_TONE_DIALTONE, 0, line_instance, tech_pvt->call_id);
|
||||
}
|
||||
if (append_dest != '\0' && !backspace) {/* append digit */
|
||||
if (backspace) { /* backspace */
|
||||
tech_pvt->caller_profile->destination_number[strlen(tech_pvt->caller_profile->destination_number)-1] = '\0';
|
||||
if (strlen(tech_pvt->caller_profile->destination_number) == 0) {
|
||||
send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff);
|
||||
}
|
||||
send_back_space_request(listener, line_instance, tech_pvt->call_id);
|
||||
}
|
||||
if (append_dest != '\0') {/* append digit */
|
||||
tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
|
||||
"%s%c", tech_pvt->caller_profile->destination_number, append_dest);
|
||||
}
|
||||
if (strlen(tech_pvt->caller_profile->destination_number) == 0) {/* no digit yet */
|
||||
send_start_tone(listener, SKINNY_TONE_DIALTONE, 0, line_instance, tech_pvt->call_id);
|
||||
if(backspace) {
|
||||
send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff);
|
||||
/* TODO: How to clear the screen? */
|
||||
}
|
||||
} else if (strlen(tech_pvt->caller_profile->destination_number) == 1) {/* first digit */
|
||||
send_stop_tone(listener, line_instance, tech_pvt->call_id);
|
||||
if (strlen(tech_pvt->caller_profile->destination_number) == 1) {/* first digit */
|
||||
if(!backspace) {
|
||||
send_stop_tone(listener, line_instance, tech_pvt->call_id);
|
||||
}
|
||||
send_select_soft_keys(listener, line_instance, tech_pvt->call_id,
|
||||
SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, 0xffff);
|
||||
}
|
||||
|
@ -1476,6 +1483,20 @@ switch_status_t send_activate_call_plane(listener_t *listener,
|
|||
return skinny_send_reply(listener, message);
|
||||
}
|
||||
|
||||
switch_status_t send_back_space_request(listener_t *listener,
|
||||
uint32_t line_instance,
|
||||
uint32_t call_id)
|
||||
{
|
||||
skinny_message_t *message;
|
||||
message = switch_core_alloc(listener->pool, 12+sizeof(message->data.back_space_req));
|
||||
message->type = BACK_SPACE_REQ_MESSAGE;
|
||||
message->length = 4 + sizeof(message->data.back_space_req);
|
||||
message->data.back_space_req.line_instance = line_instance;
|
||||
message->data.back_space_req.call_id = call_id;
|
||||
return skinny_send_reply(listener, message);
|
||||
|
||||
}
|
||||
|
||||
switch_status_t send_dialed_number(listener_t *listener,
|
||||
char called_party[24],
|
||||
uint32_t line_instance,
|
||||
|
@ -2202,6 +2223,7 @@ switch_status_t skinny_handle_off_hook_message(listener_t *listener, skinny_mess
|
|||
|
||||
switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_message_t *request)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
struct speed_dial_stat_res_message *button = NULL;
|
||||
uint32_t line_instance = 0;
|
||||
uint32_t call_id = 0;
|
||||
|
@ -2218,10 +2240,6 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess
|
|||
skinny_create_ingoing_session(listener, &line_instance, &session);
|
||||
skinny_session_process_dest(session, listener, line_instance, "redial", '\0', 0);
|
||||
break;
|
||||
case SKINNY_BUTTON_VOICEMAIL:
|
||||
skinny_create_ingoing_session(listener, &line_instance, &session);
|
||||
skinny_session_process_dest(session, listener, line_instance, "vmain", '\0', 0);
|
||||
break;
|
||||
case SKINNY_BUTTON_SPEED_DIAL:
|
||||
skinny_speed_dial_get(listener, request->data.stimulus.instance, &button);
|
||||
if(strlen(button->line) > 0) {
|
||||
|
@ -2229,6 +2247,17 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess
|
|||
skinny_session_process_dest(session, listener, line_instance, button->line, '\0', 0);
|
||||
}
|
||||
break;
|
||||
case SKINNY_BUTTON_HOLD:
|
||||
session = skinny_profile_find_session(listener->profile, listener, &line_instance, call_id);
|
||||
|
||||
if(session) {
|
||||
status = skinny_session_hold_line(session, listener, line_instance);
|
||||
}
|
||||
break;
|
||||
case SKINNY_BUTTON_VOICEMAIL:
|
||||
skinny_create_ingoing_session(listener, &line_instance, &session);
|
||||
skinny_session_process_dest(session, listener, line_instance, "vmain", '\0', 0);
|
||||
break;
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown Stimulus Type Received [%d]\n", request->data.stimulus.instance_type);
|
||||
}
|
||||
|
@ -2237,7 +2266,7 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess
|
|||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *listener, skinny_message_t *request)
|
||||
|
@ -2442,55 +2471,52 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
|
|||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
switch(request->type) {
|
||||
case ALARM_MESSAGE:
|
||||
return skinny_handle_alarm(listener, request);
|
||||
/* registering phase */
|
||||
case KEEP_ALIVE_MESSAGE:
|
||||
return skinny_handle_keep_alive_message(listener, request);
|
||||
case REGISTER_MESSAGE:
|
||||
return skinny_handle_register(listener, request);
|
||||
case HEADSET_STATUS_MESSAGE:
|
||||
return skinny_headset_status_message(listener, request);
|
||||
case CONFIG_STAT_REQ_MESSAGE:
|
||||
return skinny_handle_config_stat_request(listener, request);
|
||||
case CAPABILITIES_RES_MESSAGE:
|
||||
return skinny_handle_capabilities_response(listener, request);
|
||||
case PORT_MESSAGE:
|
||||
return skinny_handle_port_message(listener, request);
|
||||
case BUTTON_TEMPLATE_REQ_MESSAGE:
|
||||
return skinny_handle_button_template_request(listener, request);
|
||||
case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
|
||||
return skinny_handle_soft_key_template_request(listener, request);
|
||||
case SOFT_KEY_SET_REQ_MESSAGE:
|
||||
return skinny_handle_soft_key_set_request(listener, request);
|
||||
case LINE_STAT_REQ_MESSAGE:
|
||||
return skinny_handle_line_stat_request(listener, request);
|
||||
case KEYPAD_BUTTON_MESSAGE:
|
||||
return skinny_handle_keypad_button_message(listener, request);
|
||||
case STIMULUS_MESSAGE:
|
||||
return skinny_handle_stimulus_message(listener, request);
|
||||
case OFF_HOOK_MESSAGE:
|
||||
return skinny_handle_off_hook_message(listener, request);
|
||||
case ON_HOOK_MESSAGE:
|
||||
return skinny_handle_on_hook_message(listener, request);
|
||||
case SPEED_DIAL_STAT_REQ_MESSAGE:
|
||||
return skinny_handle_speed_dial_stat_request(listener, request);
|
||||
case LINE_STAT_REQ_MESSAGE:
|
||||
return skinny_handle_line_stat_request(listener, request);
|
||||
case CONFIG_STAT_REQ_MESSAGE:
|
||||
return skinny_handle_config_stat_request(listener, request);
|
||||
case TIME_DATE_REQ_MESSAGE:
|
||||
return skinny_handle_time_date_request(listener, request);
|
||||
case BUTTON_TEMPLATE_REQ_MESSAGE:
|
||||
return skinny_handle_button_template_request(listener, request);
|
||||
case CAPABILITIES_RES_MESSAGE:
|
||||
return skinny_handle_capabilities_response(listener, request);
|
||||
case ALARM_MESSAGE:
|
||||
return skinny_handle_alarm(listener, request);
|
||||
case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
|
||||
return skinny_handle_open_receive_channel_ack_message(listener, request);
|
||||
case SOFT_KEY_SET_REQ_MESSAGE:
|
||||
return skinny_handle_soft_key_set_request(listener, request);
|
||||
case SOFT_KEY_EVENT_MESSAGE:
|
||||
return skinny_handle_soft_key_event_message(listener, request);
|
||||
case UNREGISTER_MESSAGE:
|
||||
return skinny_handle_unregister(listener, request);
|
||||
case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
|
||||
return skinny_handle_soft_key_template_request(listener, request);
|
||||
case SERVICE_URL_STAT_REQ_MESSAGE:
|
||||
return skinny_handle_service_url_stat_request(listener, request);
|
||||
case FEATURE_STAT_REQ_MESSAGE:
|
||||
return skinny_handle_feature_stat_request(listener, request);
|
||||
case HEADSET_STATUS_MESSAGE:
|
||||
return skinny_headset_status_message(listener, request);
|
||||
case REGISTER_AVAILABLE_LINES_MESSAGE:
|
||||
return skinny_handle_register_available_lines_message(listener, request);
|
||||
case TIME_DATE_REQ_MESSAGE:
|
||||
return skinny_handle_time_date_request(listener, request);
|
||||
/* live phase */
|
||||
case KEEP_ALIVE_MESSAGE:
|
||||
return skinny_handle_keep_alive_message(listener, request);
|
||||
case SOFT_KEY_EVENT_MESSAGE:
|
||||
return skinny_handle_soft_key_event_message(listener, request);
|
||||
case OFF_HOOK_MESSAGE:
|
||||
return skinny_handle_off_hook_message(listener, request);
|
||||
case STIMULUS_MESSAGE:
|
||||
return skinny_handle_stimulus_message(listener, request);
|
||||
case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
|
||||
return skinny_handle_open_receive_channel_ack_message(listener, request);
|
||||
case KEYPAD_BUTTON_MESSAGE:
|
||||
return skinny_handle_keypad_button_message(listener, request);
|
||||
case ON_HOOK_MESSAGE:
|
||||
return skinny_handle_on_hook_message(listener, request);
|
||||
/* end phase */
|
||||
case UNREGISTER_MESSAGE:
|
||||
return skinny_handle_unregister(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);
|
||||
|
|
|
@ -457,6 +457,13 @@ struct unregister_ack_message {
|
|||
uint32_t unregister_status;
|
||||
};
|
||||
|
||||
/* BackSpaceReqMessage */
|
||||
#define BACK_SPACE_REQ_MESSAGE 0x0119
|
||||
struct back_space_req_message {
|
||||
uint32_t line_instance;
|
||||
uint32_t call_id;
|
||||
};
|
||||
|
||||
/* DialedNumberMessage */
|
||||
#define DIALED_NUMBER_MESSAGE 0x011D
|
||||
struct dialed_number_message {
|
||||
|
@ -540,6 +547,7 @@ union skinny_data {
|
|||
struct clear_prompt_status_message clear_prompt_status;
|
||||
struct activate_call_plane_message activate_call_plane;
|
||||
struct unregister_ack_message unregister_ack;
|
||||
struct back_space_req_message back_space_req;
|
||||
struct dialed_number_message dialed_number;
|
||||
struct feature_stat_res_message feature_res;
|
||||
struct display_pri_notify_message display_pri_notify;
|
||||
|
@ -748,6 +756,9 @@ switch_status_t send_clear_prompt_status(listener_t *listener,
|
|||
uint32_t call_id);
|
||||
switch_status_t send_activate_call_plane(listener_t *listener,
|
||||
uint32_t line_instance);
|
||||
switch_status_t send_back_space_request(listener_t *listener,
|
||||
uint32_t line_instance,
|
||||
uint32_t call_id);
|
||||
switch_status_t send_dialed_number(listener_t *listener,
|
||||
char called_party[24],
|
||||
uint32_t line_instance,
|
||||
|
|
|
@ -86,6 +86,7 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
|
|||
{"ClearPromptStatusMessage", CLEAR_PROMPT_STATUS_MESSAGE},
|
||||
{"ActivateCallPlaneMessage", ACTIVATE_CALL_PLANE_MESSAGE},
|
||||
{"UnregisterAckMessage", UNREGISTER_ACK_MESSAGE},
|
||||
{"BackSpaceReqMessage", BACK_SPACE_REQ_MESSAGE},
|
||||
{"DialedNumberMessage", DIALED_NUMBER_MESSAGE},
|
||||
{"FeatureResMessage", FEATURE_STAT_RES_MESSAGE},
|
||||
{"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE},
|
||||
|
@ -117,6 +118,7 @@ struct skinny_table SKINNY_BUTTONS[] = {
|
|||
{"Unknown", SKINNY_BUTTON_UNKNOWN},
|
||||
{"LastNumberRedial", SKINNY_BUTTON_LAST_NUMBER_REDIAL},
|
||||
{"SpeedDial", SKINNY_BUTTON_SPEED_DIAL},
|
||||
{"Hold", SKINNY_BUTTON_HOLD},
|
||||
{"Line", SKINNY_BUTTON_LINE},
|
||||
{"Voicemail", SKINNY_BUTTON_VOICEMAIL},
|
||||
{"Privacy", SKINNY_BUTTON_PRIVACY},
|
||||
|
|
|
@ -84,7 +84,7 @@ uint32_t func(const char *str)\
|
|||
}
|
||||
|
||||
|
||||
struct skinny_table SKINNY_MESSAGE_TYPES[56];
|
||||
struct skinny_table SKINNY_MESSAGE_TYPES[57];
|
||||
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)
|
||||
|
@ -151,13 +151,14 @@ enum skinny_button_definition {
|
|||
SKINNY_BUTTON_UNKNOWN = 0x00,
|
||||
SKINNY_BUTTON_LAST_NUMBER_REDIAL = 0x01,
|
||||
SKINNY_BUTTON_SPEED_DIAL = 0x02,
|
||||
SKINNY_BUTTON_HOLD = 0x03,
|
||||
SKINNY_BUTTON_LINE = 0x09,
|
||||
SKINNY_BUTTON_VOICEMAIL = 0x0F,
|
||||
SKINNY_BUTTON_PRIVACY = 0x13,
|
||||
SKINNY_BUTTON_SERVICE_URL = 0x14,
|
||||
SKINNY_BUTTON_UNDEFINED = 0xFF,
|
||||
};
|
||||
struct skinny_table SKINNY_BUTTONS[9];
|
||||
struct skinny_table SKINNY_BUTTONS[10];
|
||||
const char *skinny_button2str(uint32_t id);
|
||||
uint32_t skinny_str2button(const char *str);
|
||||
#define SKINNY_PUSH_STIMULI SKINNY_DECLARE_PUSH_MATCH(SKINNY_BUTTONS)
|
||||
|
|
|
@ -614,12 +614,12 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
|
|||
#endif
|
||||
|
||||
if (uuid) {
|
||||
sql = switch_mprintf("update sip_dialogs set call_info_state='%q' where hostname='%q' and uuid='%q'",
|
||||
call_info_state, mod_sofia_globals.hostname, uuid);
|
||||
sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' where hostname='%q' and uuid='%q'",
|
||||
call_info, call_info_state, mod_sofia_globals.hostname, uuid);
|
||||
} else {
|
||||
sql = switch_mprintf("update sip_dialogs set call_info_state='%q' where hostname='%q' and sip_dialogs.sip_from_user='%q' "
|
||||
sql = switch_mprintf("update sip_dialogs set call_info='%q', call_info_state='%q' where hostname='%q' and sip_dialogs.sip_from_user='%q' "
|
||||
"and sip_dialogs.sip_from_host='%q' and call_info='%q'",
|
||||
call_info_state, mod_sofia_globals.hostname, euser, host, call_info);
|
||||
call_info, call_info_state, mod_sofia_globals.hostname, euser, host, call_info);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue