mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-24 21:22:09 +00:00
Merge branch 'master' into arnaldo.zt_chan_next_event
This commit is contained in:
+3
-3
@@ -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
|
||||
|
||||
@@ -290,6 +290,10 @@
|
||||
RelativePath=".\esl.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\esl_buffer.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\esl_config.c"
|
||||
>
|
||||
@@ -316,6 +320,10 @@
|
||||
RelativePath=".\include\esl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\esl_buffer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\esl_config.h"
|
||||
>
|
||||
|
||||
@@ -128,6 +128,7 @@
|
||||
<ClCompile Include="esl_event.c" />
|
||||
<ClCompile Include="esl_json.c" />
|
||||
<ClCompile Include="esl_threadmutex.c" />
|
||||
<ClCompile Include="esl_buffer.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\esl.h" />
|
||||
@@ -135,6 +136,7 @@
|
||||
<ClInclude Include="include\esl_event.h" />
|
||||
<ClInclude Include="include\esl_json.h" />
|
||||
<ClInclude Include="include\esl_threadmutex.h" />
|
||||
<ClInclude Include="include\esl_buffer.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
+86
-70
@@ -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 len1;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
@@ -1177,7 +1194,6 @@ ESL_DECLARE(esl_status_t) esl_send_recv_timed(esl_handle_t *handle, const char *
|
||||
return ESL_FAIL;
|
||||
}
|
||||
|
||||
esl_event_safe_destroy(&handle->last_event);
|
||||
esl_event_safe_destroy(&handle->last_sr_event);
|
||||
|
||||
*handle->last_sr_reply = '\0';
|
||||
|
||||
@@ -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 *data1;
|
||||
|
||||
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;
|
||||
data1 = realloc(buffer->data, new_size);
|
||||
if (!data1) {
|
||||
return 0;
|
||||
}
|
||||
buffer->data = data1;
|
||||
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:
|
||||
*/
|
||||
@@ -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 <esl_threadmutex.h>
|
||||
#include <esl_buffer.h>
|
||||
|
||||
/*! \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 */
|
||||
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#! /bin/sh
|
||||
./configure "$@" --with-pic
|
||||
|
||||
srcpath=$(dirname $0 2>/dev/null ) || srcpath="."
|
||||
$srcpath/configure "$@" --with-pic
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
FreeTDM can both notify and set signaling status changes in the different protocols thru a unified interface. More
|
||||
specific details on the C data types and function prototypes are found in freetdm.h
|
||||
|
||||
The API provides the following functions and data types to do it:
|
||||
|
||||
The signaling status in any channel/span is represented thru ftdm_signaling_status_t
|
||||
|
||||
/* The signaling link is down (no d-chans up in the span/group, MFC-R2 bit pattern unidentified) */
|
||||
FTDM_SIG_STATE_DOWN,
|
||||
/* The signaling link is suspended (MFC-R2 bit pattern blocked, PRI maintenance, ss7 blocked?) */
|
||||
FTDM_SIG_STATE_SUSPENDED,
|
||||
/* The signaling link is ready and calls can be placed (ie: d-chan up, MFC-R2 both rx and tx in IDLE) */
|
||||
FTDM_SIG_STATE_UP,
|
||||
/* Invalid status */
|
||||
FTDM_SIG_STATE_INVALID
|
||||
|
||||
Changes in the signaling status are notified to the user using the standard callback notification function provided
|
||||
during configuration using the sigevent type FTDM_SIGEVENT_SIGSTATUS_CHANGED which is sent when the line status changes.
|
||||
|
||||
On startup the signalling status default is FTDM_SIG_STATE_DOWN, and no notification is provided until the state change,
|
||||
so applications must assume the status is down unless told otherwise.
|
||||
|
||||
When ftdm_span_start is called, the signaling stack takes care of attempting to bring the status to UP
|
||||
but it will ultimately depend on the other side too.
|
||||
|
||||
== Setting the signaling status ==
|
||||
|
||||
Users can set the signaling status on a given channel/span thru FreeTDM the following API functions:
|
||||
|
||||
ftdm_channel_set_sig_status
|
||||
ftdm_span_set_sig_status
|
||||
|
||||
If the user calls ftdm_channel_set_sig_status(chan, FTDM_SIG_STATE_SUSPENDED), the signaling stack will try to set
|
||||
the status of the line to the one requested, if successful, it will result in a SIGEVENT_SIGSTATUS_CHANGED notification
|
||||
being sent with status FTDM_SIG_STATE_SUSPENDED.
|
||||
|
||||
** MFC-R2 Signaling Notes **
|
||||
For MFC-R2, calling ftdm_span_start() results in setting the tx CAS bits to IDLE. However, if the rx bits are in BLOCKED state
|
||||
the signaling status will be reported as SUSPENDED.
|
||||
|
||||
If the user calls ftdm_channel_set_sig_status(chan, SUSPENDED), the tx CAS bits will be set to BLOCKED and, if, the current rx bits
|
||||
are IDLE then a SIGEVENT_SIGSTATUS_CHANGED with state SUSPENDED will be sent. If the rx bits are already in blocked then no further
|
||||
SIGEVENT_SIGSTATUS_CHANGED notification is needed (because it was already sent when the rx bits were initially detected as BLOCKED).
|
||||
|
||||
If the user calls ftdm_channel_set_sig_status(chan, UP), the tx CAS bits will be set to IDLE and, if, the current rx bits
|
||||
are IDLE, then SIGEVENT_SIGSTATUS_CHANGED with state UP will be sent. If the rx bits are BLOCKED, then no notification is
|
||||
sent at all until the rx bits change.
|
||||
|
||||
Bottom line is, for MFC-R2, SIGEVENT_SIGSTATUS_CHANGED UP is only sent to the user when both the rx and tx bits are in IDLE, and
|
||||
SIGEVENT_SIGSTATUS_CHANGED SUSPENDED is only sent to the user when any of the rx or tx bits are in BLOCKED.
|
||||
|
||||
== Getting the signaling status ==
|
||||
Users can get the signaling status on a given channel/span thru FreeTDM the following API functions:
|
||||
|
||||
ftdm_channel_get_sig_status
|
||||
ftdm_span_get_sig_status
|
||||
|
||||
The line status returned should be the same as the last time a SIGEVENT_SIGSTATUS_CHANGED was reported.
|
||||
|
||||
@@ -119,10 +119,8 @@ Global
|
||||
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64
|
||||
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64
|
||||
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32
|
||||
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|x64
|
||||
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|x64
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>mod_freetdm</ProjectName>
|
||||
<ProjectGuid>{FE3540C5-3303-46E0-A69E-D92F775687F1}</ProjectGuid>
|
||||
<RootNamespace>mod_freetdm</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(PlatformName)\$(Configuration)\mod\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(PlatformName)\$(Configuration)\mod\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(PlatformName)\$(Configuration)\mod\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(PlatformName)\$(Configuration)\mod\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>FreeSwitch.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<ImportLibrary>$(OutDir)mod_freetdm.lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>FreeSwitch.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<ImportLibrary>$(OutDir)mod_freetdm.lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>FreeSwitchCore.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<ImportLibrary>$(OutDir)mod_freetdm.lib</ImportLibrary>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>FreeSwitchCore.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<ImportLibrary>$(OutDir)mod_freetdm.lib</ImportLibrary>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="mod_freetdm.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\msvc\freetdm.2010.vcxproj">
|
||||
<Project>{93b8812c-3ec4-4f78-8970-ffbfc99e167d}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="mod_freetdm.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -429,7 +429,7 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
|
||||
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);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -1278,6 +1282,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);
|
||||
@@ -1329,7 +1337,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
|
||||
char *v = h->name + FREETDM_VAR_PREFIX_LEN;
|
||||
if (!zstr(v)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id);
|
||||
ftdm_channel_add_var(ftdmchan, v, h->value);
|
||||
ftdm_call_add_var(&caller_data, v, h->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1363,7 +1371,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);
|
||||
@@ -1528,6 +1535,7 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
|
||||
switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chanid);
|
||||
switch_channel_set_variable_printf(channel, "freetdm_bearer_capability", "%d", channel_caller_data->bearer_capability);
|
||||
switch_channel_set_variable_printf(channel, "freetdm_bearer_layer1", "%d", channel_caller_data->bearer_layer1);
|
||||
|
||||
if (globals.sip_headers) {
|
||||
switch_channel_set_variable(channel, "sip_h_X-FreeTDM-SpanName", ftdm_channel_get_span_name(sigmsg->channel));
|
||||
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-SpanNumber", "%d", spanid);
|
||||
@@ -1561,8 +1569,18 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
|
||||
ftdm_channel_get_current_var(curr, &var_name, &var_value);
|
||||
snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
|
||||
switch_channel_set_variable_printf(channel, name, "%s", var_value);
|
||||
}
|
||||
|
||||
/* Add any call variable to the dial plan */
|
||||
iter = ftdm_call_get_var_iterator(channel_caller_data, iter);
|
||||
for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) {
|
||||
ftdm_call_get_current_var(curr, &var_name, &var_value);
|
||||
snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
|
||||
switch_channel_set_variable_printf(channel, name, "%s", var_value);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s=%s\n", name, var_value);
|
||||
}
|
||||
ftdm_iterator_free(iter);
|
||||
|
||||
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
|
||||
@@ -1661,11 +1679,11 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
|
||||
ftdm_status_t status;
|
||||
uint32_t spanid;
|
||||
uint32_t chanid;
|
||||
ftdm_caller_data_t *callerdata;
|
||||
ftdm_caller_data_t *caller_data;
|
||||
|
||||
spanid = ftdm_channel_get_span_id(sigmsg->channel);
|
||||
chanid = ftdm_channel_get_id(sigmsg->channel);
|
||||
callerdata = ftdm_channel_get_caller_data(sigmsg->channel);
|
||||
caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "got FXO sig %d:%d [%s]\n", spanid, chanid, ftdm_signal_event2str(sigmsg->event_id));
|
||||
|
||||
@@ -1688,7 +1706,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
|
||||
ftdm_channel_clear_token(sigmsg->channel, 0);
|
||||
channel = switch_core_session_get_channel(session);
|
||||
switch_channel_hangup(channel, callerdata->hangup_cause);
|
||||
switch_channel_hangup(channel, caller_data->hangup_cause);
|
||||
ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
@@ -1712,8 +1730,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
|
||||
|
||||
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
|
||||
case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { /* twiddle */ } break;
|
||||
|
||||
default:
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
|
||||
@@ -1767,7 +1786,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
|
||||
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
|
||||
|
||||
case FTDM_SIGEVENT_STOP:
|
||||
{
|
||||
private_t *tech_pvt = NULL;
|
||||
@@ -1799,7 +1819,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);
|
||||
@@ -1899,7 +1921,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);
|
||||
@@ -1991,8 +2013,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
|
||||
}
|
||||
break;
|
||||
|
||||
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
|
||||
|
||||
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
|
||||
|
||||
/* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
|
||||
case FTDM_SIGEVENT_COLLECTED_DIGIT:
|
||||
{
|
||||
@@ -2065,7 +2087,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->sigstatus;
|
||||
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));
|
||||
}
|
||||
@@ -2104,14 +2126,14 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
|
||||
switch(sigmsg->event_id) {
|
||||
case FTDM_SIGEVENT_START:
|
||||
{
|
||||
ftdm_channel_add_var(sigmsg->channel, "screening_ind", ftdm_screening2str(caller_data->screen));
|
||||
ftdm_channel_add_var(sigmsg->channel, "presentation_ind", ftdm_presentation2str(caller_data->pres));
|
||||
ftdm_call_add_var(caller_data, "screening_ind", ftdm_screening2str(caller_data->screen));
|
||||
ftdm_call_add_var(caller_data, "presentation_ind", ftdm_presentation2str(caller_data->pres));
|
||||
return ftdm_channel_from_event(sigmsg, &session);
|
||||
}
|
||||
break;
|
||||
|
||||
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
|
||||
|
||||
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
|
||||
|
||||
case FTDM_SIGEVENT_STOP:
|
||||
case FTDM_SIGEVENT_RESTART:
|
||||
{
|
||||
@@ -2155,6 +2177,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
|
||||
}
|
||||
break;
|
||||
case FTDM_SIGEVENT_PROGRESS:
|
||||
case FTDM_SIGEVENT_RINGING:
|
||||
{
|
||||
if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
|
||||
channel = switch_core_session_get_channel(session);
|
||||
@@ -2170,13 +2193,13 @@ 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->sigstatus;
|
||||
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));
|
||||
}
|
||||
break;
|
||||
case FTDM_SIGEVENT_PROCEED:
|
||||
case FTDM_SIGEVENT_MSG:
|
||||
case FTDM_SIGEVENT_FACILITY:
|
||||
/* FS does not have handlers for these messages, so ignore them for now */
|
||||
break;
|
||||
default:
|
||||
@@ -3513,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 <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix] || gains <txgain> <rxgain> <span_id> [<chan_id>] || dtmf on|off <span_id> [<chan_id>]"
|
||||
#define FT_SYNTAX "USAGE:\n" \
|
||||
"--------------------------------------------------------------------------------\n" \
|
||||
"ftdm list\n" \
|
||||
"ftdm start|stop <span_name|span_id>\n" \
|
||||
"ftdm restart <span_id|span_name> <chan_id>\n" \
|
||||
"ftdm dump <span_id|span_name> [<chan_id>]\n" \
|
||||
"ftdm sigstatus get|set [<span_id|span_name>] [<channel>] [<sigstatus>]\n" \
|
||||
"ftdm trace <path> <span_id|span_name> [<chan_id>]\n" \
|
||||
"ftdm notrace <span_id|span_name> [<chan_id>]\n" \
|
||||
"ftdm q931_pcap <span_id> on|off [pcapfilename without suffix]\n" \
|
||||
"ftdm gains <txgain> <rxgain> <span_id> [<chan_id>]\n" \
|
||||
"ftdm dtmf on|off <span_id> [<chan_id>]\n" \
|
||||
"--------------------------------------------------------------------------------\n"
|
||||
SWITCH_STANDARD_API(ft_function)
|
||||
{
|
||||
char *mycmd = NULL, *argv[10] = { 0 };
|
||||
@@ -3530,7 +3565,83 @@ SWITCH_STANDARD_API(ft_function)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[0], "dump")) {
|
||||
if (!strcasecmp(argv[0], "sigstatus")) {
|
||||
ftdm_span_t *span = NULL;
|
||||
ftdm_signaling_status_t sigstatus;
|
||||
|
||||
if (argc < 3) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm sigstatus get|set [<span_id>] [<channel>] [<sigstatus>]\n");
|
||||
goto end;
|
||||
}
|
||||
if (!strcasecmp(argv[1], "get") && argc < 3) {
|
||||
stream->write_function(stream, "-ERR sigstatus get usage: get <span_id>\n");
|
||||
goto end;
|
||||
}
|
||||
if (!strcasecmp(argv[1], "set") && argc != 5) {
|
||||
stream->write_function(stream, "-ERR sigstatus set usage: set <span_id> <channel>|all <sigstatus>\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
ftdm_span_find_by_name(argv[2], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[1], "get")) {
|
||||
if (argc == 4) {
|
||||
uint32_t chan_id = atol(argv[3]);
|
||||
ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
|
||||
if (!fchan) {
|
||||
stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((FTDM_SUCCESS == ftdm_channel_get_sig_status(fchan, &sigstatus))) {
|
||||
stream->write_function(stream, "channel %d signaling status: %s\n", chan_id, ftdm_signaling_status2str(sigstatus));
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR failed to get channel sigstatus\n");
|
||||
}
|
||||
goto end;
|
||||
} else {
|
||||
if ((FTDM_SUCCESS == ftdm_span_get_sig_status(span, &sigstatus))) {
|
||||
stream->write_function(stream, "signaling_status: %s\n", ftdm_signaling_status2str(sigstatus));
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR failed to read span status: %s\n", ftdm_span_get_last_error(span));
|
||||
}
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (!strcasecmp(argv[1], "set")) {
|
||||
sigstatus = ftdm_str2ftdm_signaling_status(argv[4]);
|
||||
|
||||
if (!strcasecmp(argv[3], "all")) {
|
||||
if ((FTDM_SUCCESS == ftdm_span_set_sig_status(span, sigstatus))) {
|
||||
stream->write_function(stream, "Signaling status of all channels from span %s set to %s\n",
|
||||
ftdm_span_get_name(span), ftdm_signaling_status2str(sigstatus));
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus));
|
||||
}
|
||||
goto end;
|
||||
} else {
|
||||
uint32_t chan_id = atol(argv[3]);
|
||||
ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
|
||||
if (!fchan) {
|
||||
stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((FTDM_SUCCESS == ftdm_channel_set_sig_status(fchan, sigstatus))) {
|
||||
stream->write_function(stream, "Signaling status of channel %d set to %s\n", chan_id,
|
||||
ftdm_signaling_status2str(sigstatus));
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus));
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (!strcasecmp(argv[0], "dump")) {
|
||||
if (argc < 2) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm dump <span_id> [<chan_id>]\n");
|
||||
goto end;
|
||||
@@ -3910,6 +4021,28 @@ SWITCH_STANDARD_API(ft_function)
|
||||
}
|
||||
}
|
||||
stream->write_function(stream, "+OK gains set to Rx %f and Tx %f\n", rxgain, txgain);
|
||||
} else if (!strcasecmp(argv[0], "restart")) {
|
||||
uint32_t chan_id = 0;
|
||||
ftdm_channel_t *chan;
|
||||
ftdm_span_t *span = NULL;
|
||||
if (argc < 3) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm restart <span_id> <chan_id>\n");
|
||||
goto end;
|
||||
}
|
||||
ftdm_span_find_by_name(argv[1], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
chan_id = atoi(argv[2]);
|
||||
chan = ftdm_span_get_channel(span, chan_id);
|
||||
if (!chan) {
|
||||
stream->write_function(stream, "-ERR Could not find chan\n");
|
||||
goto end;
|
||||
}
|
||||
stream->write_function(stream, "Resetting channel %s:%s\n", argv[2], argv[3]);
|
||||
ftdm_channel_reset(chan);
|
||||
} else {
|
||||
|
||||
char *rply = ftdm_api_execute(cmd);
|
||||
|
||||
@@ -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 <moy@sangoma.com>
|
||||
* Ricardo Barroetaveña <rbarroetavena@anura.com.ar>
|
||||
*
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
+456
-140
File diff suppressed because it is too large
Load Diff
@@ -156,7 +156,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
||||
release_request_id((m3ua_request_id_t)ftdmchan->extra_id);
|
||||
ftdmchan->extra_id = 0;
|
||||
}
|
||||
ftdm_channel_done(ftdmchan);
|
||||
ftdm_channel_close(&ftdmchan);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -491,9 +513,12 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GENERATE_RING_OFF, NULL);
|
||||
}
|
||||
|
||||
if (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)) {
|
||||
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_UP)) {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
|
||||
} else {
|
||||
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
|
||||
@@ -716,7 +741,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;
|
||||
}
|
||||
@@ -883,14 +908,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);
|
||||
@@ -908,7 +933,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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -916,16 +946,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);
|
||||
@@ -939,12 +969,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;
|
||||
@@ -956,9 +986,24 @@ 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);
|
||||
}
|
||||
}
|
||||
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));
|
||||
|
||||
@@ -329,8 +329,8 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
|
||||
{
|
||||
if (state_counter > 500) {
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
|
||||
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|
||||
|| ftdmchan->last_state >= FTDM_CHANNEL_STATE_IDLE)) {
|
||||
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|
||||
|| ftdmchan->last_state == FTDM_CHANNEL_STATE_RING)) {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
|
||||
} else {
|
||||
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
|
||||
@@ -340,7 +340,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
case FTDM_CHANNEL_STATE_IDLE:
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
{
|
||||
ftdm_sleep(interval);
|
||||
continue;
|
||||
@@ -386,7 +386,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
|
||||
ftdm_channel_use(ftdmchan);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_IDLE:
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
{
|
||||
ftdm_channel_use(ftdmchan);
|
||||
|
||||
@@ -421,7 +421,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_WINK, NULL);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
{
|
||||
ftdm_buffer_zero(dt_buffer);
|
||||
teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -477,7 +477,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
|
||||
|
||||
if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr))) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
|
||||
last_digit = 0;
|
||||
collecting = 0;
|
||||
}
|
||||
|
||||
@@ -1325,7 +1325,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
||||
}
|
||||
Q931ReleaseCRV(&isdn_data->q931, gen->CRV);
|
||||
}
|
||||
ftdm_channel_done(ftdmchan);
|
||||
ftdm_channel_close(&ftdmchan);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
|
||||
@@ -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;
|
||||
@@ -1403,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);
|
||||
}
|
||||
}
|
||||
@@ -1440,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);
|
||||
}
|
||||
|
||||
@@ -127,24 +127,24 @@ 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;
|
||||
|
||||
memset(&((unsigned char*)buf)[res], 0, 2);
|
||||
res += 2;
|
||||
|
||||
if (res > 0) {
|
||||
memset(&((unsigned char*)buf)[res], 0, 2);
|
||||
res += 2;
|
||||
#ifdef IODEBUG
|
||||
{
|
||||
char bb[2048] = { 0 };
|
||||
{
|
||||
char bb[2048] = { 0 };
|
||||
|
||||
print_hex_bytes(buf, res - 2, bb, sizeof(bb));
|
||||
ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2);
|
||||
}
|
||||
print_hex_bytes(buf, res - 2, bb, sizeof(bb));
|
||||
ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -155,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
|
||||
|
||||
@@ -280,12 +280,12 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
||||
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_DOWN:
|
||||
{
|
||||
ftdm_channel_done(ftdmchan);
|
||||
{
|
||||
ftdmchan->call_data = NULL;
|
||||
ftdm_channel_close(&ftdmchan);
|
||||
|
||||
ftdm_channel_done(peerchan);
|
||||
peerchan->call_data = NULL;
|
||||
ftdm_channel_close(&peerchan);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -29,6 +29,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:
|
||||
*
|
||||
* Arnaldo Pereira <arnaldo@sangoma.com>
|
||||
* Ricardo Barroetaveña <rbarroetavena@anura.com.ar>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -44,16 +50,15 @@
|
||||
#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 users kills a span we clear this flag to kill the signaling thread */
|
||||
/* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread
|
||||
* knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the
|
||||
* signaling thread is done. */
|
||||
/* FIXME: what about the calls that are already up-and-running? */
|
||||
typedef enum {
|
||||
FTDM_R2_RUNNING = (1 << 0),
|
||||
FTDM_R2_SPAN_STARTED = (1 << 1),
|
||||
} ftdm_r2_flag_t;
|
||||
|
||||
/* private call information stored in ftdmchan->call_data void* ptr,
|
||||
@@ -250,7 +255,7 @@ static void ftdm_r2_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling
|
||||
sig.span_id = ftdmchan->span_id;
|
||||
sig.channel = ftdmchan;
|
||||
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sig.sigstatus = status;
|
||||
sig.ev_data.sigstatus.status = status;
|
||||
if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status));
|
||||
}
|
||||
@@ -372,11 +377,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;
|
||||
|
||||
@@ -389,6 +455,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);
|
||||
@@ -396,9 +468,9 @@ 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,
|
||||
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");
|
||||
@@ -419,13 +491,14 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
|
||||
static ftdm_status_t ftdm_r2_start(ftdm_span_t *span)
|
||||
{
|
||||
ftdm_r2_data_t *r2_data = span->signal_data;
|
||||
ftdm_set_flag(r2_data, FTDM_R2_RUNNING);
|
||||
ftdm_set_flag(r2_data, FTDM_R2_SPAN_STARTED);
|
||||
return ftdm_thread_create_detached(ftdm_r2_run, span);
|
||||
}
|
||||
|
||||
static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span)
|
||||
{
|
||||
ftdm_r2_data_t *r2_data = span->signal_data;
|
||||
ftdm_clear_flag(r2_data, FTDM_R2_SPAN_STARTED);
|
||||
while (ftdm_test_flag(r2_data, FTDM_R2_RUNNING)) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Waiting for R2 span %s\n", span->name);
|
||||
ftdm_sleep(100);
|
||||
@@ -444,6 +517,95 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status)
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
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_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;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status)
|
||||
{
|
||||
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 non-idle, report SUSPENDED. UP otherwise. */
|
||||
*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;
|
||||
}
|
||||
|
||||
static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status)
|
||||
{
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *citer = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
/* 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);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* always called from the monitor thread */
|
||||
static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
|
||||
{
|
||||
@@ -510,13 +672,21 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons
|
||||
ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = (%d)\n", ani, dnis, category);
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
|
||||
|
||||
/* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */
|
||||
if (r2data->mf_dump_size) {
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
|
||||
}
|
||||
|
||||
/* check if this is a collect call and if we should accept it */
|
||||
if (!r2data->allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Rejecting collect call\n");
|
||||
openr2_chan_disconnect_call(r2chan, OR2_CAUSE_COLLECT_CALL_REJECTED);
|
||||
} else {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
|
||||
}
|
||||
ftdmchan->caller_data.cpc = ftdm_openr2_cpc_to_r2_ftdm_cpc(category);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -556,14 +726,14 @@ static void dump_mf(openr2_chan_t *r2chan)
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in prefix %s\n", logname);
|
||||
snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.input.alaw" : "%s/s%dc%d.input.alaw",
|
||||
logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
|
||||
f = fopen(dfile, "w");
|
||||
f = fopen(dfile, "wb");
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO input in file %s\n", dfile);
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.output.alaw" : "%s/s%dc%d.output.alaw",
|
||||
logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
|
||||
f = fopen(dfile, "w");
|
||||
f = fopen(dfile, "wb");
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in file %s\n", dfile);
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_OUTPUT, f);
|
||||
fclose(f);
|
||||
@@ -573,6 +743,8 @@ static void dump_mf(openr2_chan_t *r2chan)
|
||||
static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
|
||||
{
|
||||
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
|
||||
ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call accepted\n");
|
||||
|
||||
clear_accept_pending(ftdmchan);
|
||||
@@ -595,6 +767,11 @@ static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t m
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */
|
||||
if (r2data->mf_dump_size) {
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
|
||||
}
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
}
|
||||
}
|
||||
@@ -653,7 +830,7 @@ static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf
|
||||
static void ftdm_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
|
||||
{
|
||||
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Alarm notification: %d\n", alarm);
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Alarm notification: %d\n", alarm);
|
||||
}
|
||||
|
||||
static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
|
||||
@@ -895,7 +1072,7 @@ static int ftdm_r2_io_write(openr2_chan_t *r2chan, const void *buf, int size)
|
||||
if (FTDM_FAIL == status) {
|
||||
return -1;
|
||||
}
|
||||
return outsize;
|
||||
return (int)outsize;
|
||||
}
|
||||
|
||||
static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size)
|
||||
@@ -906,7 +1083,7 @@ static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size)
|
||||
if (FTDM_FAIL == status) {
|
||||
return -1;
|
||||
}
|
||||
return outsize;
|
||||
return (int)outsize;
|
||||
}
|
||||
|
||||
static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block)
|
||||
@@ -988,6 +1165,10 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fevent->e_type != FTDM_EVENT_OOB) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (fevent->enum_id) {
|
||||
case FTDM_OOB_CAS_BITS_CHANGE:
|
||||
{
|
||||
@@ -1396,13 +1577,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
|
||||
span->sig_read = NULL;
|
||||
span->sig_write = NULL;
|
||||
|
||||
/* let the core set the states, we just read them */
|
||||
span->get_channel_sig_status = ftdm_r2_get_channel_sig_status;
|
||||
|
||||
span->signal_cb = sig_cb;
|
||||
span->signal_type = FTDM_SIGTYPE_R2;
|
||||
span->signal_data = r2data;
|
||||
span->outgoing_call = r2_outgoing_call;
|
||||
span->get_span_sig_status = ftdm_r2_get_span_sig_status;
|
||||
span->set_span_sig_status = ftdm_r2_set_span_sig_status;
|
||||
span->get_channel_sig_status = ftdm_r2_get_channel_sig_status;
|
||||
span->set_channel_sig_status = ftdm_r2_set_channel_sig_status;
|
||||
|
||||
span->state_map = &r2_state_map;
|
||||
|
||||
@@ -1593,6 +1775,13 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
|
||||
}
|
||||
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));
|
||||
@@ -1639,9 +1828,13 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||
int index = 0;
|
||||
struct timeval start, end;
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *citer = NULL;
|
||||
uint32_t txqueue_size = 4;
|
||||
short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
|
||||
|
||||
/* as long as this thread is running, this flag is set */
|
||||
ftdm_set_flag(r2data, FTDM_R2_RUNNING);
|
||||
|
||||
#ifdef __linux__
|
||||
r2data->monitor_thread_id = syscall(SYS_gettid);
|
||||
#endif
|
||||
@@ -1649,8 +1842,12 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||
ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %lu started.\n", r2data->monitor_thread_id);
|
||||
r2chan = NULL;
|
||||
chaniter = ftdm_span_get_chan_iterator(span, NULL);
|
||||
for (i = 1; chaniter; chaniter = ftdm_iterator_next(chaniter), i++) {
|
||||
ftdmchan = ftdm_iterator_current(chaniter);
|
||||
if (!chaniter) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
|
||||
goto done;
|
||||
}
|
||||
for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) {
|
||||
ftdmchan = ftdm_iterator_current(citer);
|
||||
r2chan = R2CALL(ftdmchan)->r2chan;
|
||||
openr2_chan_set_span_id(r2chan, span->span_id);
|
||||
openr2_chan_set_idle(r2chan);
|
||||
@@ -1660,7 +1857,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||
|
||||
memset(&start, 0, sizeof(start));
|
||||
memset(&end, 0, sizeof(end));
|
||||
while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) {
|
||||
while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_SPAN_STARTED)) {
|
||||
res = gettimeofday(&end, NULL);
|
||||
if (res) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno));
|
||||
@@ -1685,24 +1882,24 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||
|
||||
/* deliver the actual channel events to the user now without any channel locking */
|
||||
ftdm_span_trigger_signals(span);
|
||||
#ifndef WIN32
|
||||
|
||||
/* figure out what event to poll each channel for. POLLPRI when the channel is down,
|
||||
* POLLPRI|POLLIN|POLLOUT otherwise */
|
||||
memset(poll_events, 0, sizeof(short)*span->chan_count);
|
||||
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
|
||||
for (i = 0; chaniter; chaniter = ftdm_iterator_next(chaniter), i++) {
|
||||
ftdmchan = ftdm_iterator_current(chaniter);
|
||||
citer = ftdm_span_get_chan_iterator(span, chaniter);
|
||||
if (!citer) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
|
||||
goto done;
|
||||
}
|
||||
for (i = 0; citer; citer = ftdm_iterator_next(citer), i++) {
|
||||
ftdmchan = ftdm_iterator_current(citer);
|
||||
r2chan = R2CALL(ftdmchan)->r2chan;
|
||||
poll_events[i] = POLLPRI;
|
||||
poll_events[i] = FTDM_EVENTS;
|
||||
if (openr2_chan_get_read_enabled(r2chan)) {
|
||||
poll_events[i] |= POLLIN;
|
||||
poll_events[i] |= FTDM_READ;
|
||||
}
|
||||
}
|
||||
|
||||
status = ftdm_span_poll_event(span, waitms, poll_events);
|
||||
#else
|
||||
status = ftdm_span_poll_event(span, waitms, NULL);
|
||||
#endif
|
||||
|
||||
/* run any span timers */
|
||||
ftdm_sched_run(r2data->sched);
|
||||
@@ -1732,9 +1929,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||
|
||||
/* this main loop takes care of MF and CAS signaling during call setup and tear down
|
||||
* for every single channel in the span, do not perform blocking operations here! */
|
||||
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
|
||||
for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) {
|
||||
ftdmchan = ftdm_iterator_current(chaniter);
|
||||
citer = ftdm_span_get_chan_iterator(span, chaniter);
|
||||
for ( ; citer; citer = ftdm_iterator_next(citer)) {
|
||||
ftdmchan = ftdm_iterator_current(citer);
|
||||
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
@@ -1761,10 +1958,11 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
|
||||
for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) {
|
||||
ftdmchan = ftdm_iterator_current(chaniter);
|
||||
|
||||
done:
|
||||
citer = ftdm_span_get_chan_iterator(span, chaniter);
|
||||
for ( ; citer; citer = ftdm_iterator_next(citer)) {
|
||||
ftdmchan = ftdm_iterator_current(citer);
|
||||
r2chan = R2CALL(ftdmchan)->r2chan;
|
||||
openr2_chan_set_blocked(r2chan);
|
||||
}
|
||||
@@ -1821,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 <span_id|span_name>\n" \
|
||||
"ftdm r2 loopstats <span_id|span_name>\n" \
|
||||
"ftdm r2 block|unblock <span_id|span_name> [<chan_id>]\n" \
|
||||
"ftdm r2 version\n" \
|
||||
"ftdm r2 variants\n" \
|
||||
"--------------------------------------------------------------------------------\n"
|
||||
static FIO_API_FUNCTION(ftdm_r2_api)
|
||||
{
|
||||
ftdm_span_t *span = NULL;
|
||||
@@ -1922,7 +2128,7 @@ static FIO_API_FUNCTION(ftdm_r2_api)
|
||||
"Max DNIS: %d\n"
|
||||
"ANI First: %s\n"
|
||||
"Immediate Accept: %s\n"
|
||||
"Job Thread: %lu\n"
|
||||
"Job Thread: %u\n"
|
||||
"Job Max ms: %d\n"
|
||||
"Job Loops: %lu\n",
|
||||
openr2_proto_get_variant_string(r2variant),
|
||||
@@ -2004,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");
|
||||
@@ -2037,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:
|
||||
|
||||
@@ -2066,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;
|
||||
}
|
||||
|
||||
@@ -2086,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -839,7 +839,7 @@ static void handle_call_released(ftdm_span_t *span, sangomabc_connection_t *mcon
|
||||
if ((ftdmchan = find_ftdmchan(span, event, 1))) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Releasing completely chan s%dc%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event),
|
||||
BOOST_EVENT_CHAN(mcon->sigmod, event));
|
||||
ftdm_channel_done(ftdmchan);
|
||||
ftdm_channel_close(&ftdmchan);
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Odd, We could not find chan: s%dc%d to release the call completely!!\n",
|
||||
BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
|
||||
@@ -1105,8 +1105,9 @@ static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mc
|
||||
|
||||
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, res);
|
||||
if (res != FTDM_SUCCESS) {
|
||||
ftdm_channel_t *toclose = ftdmchan;
|
||||
ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel to IN_LOOP, loop will fail\n");
|
||||
ftdm_channel_done(ftdmchan);
|
||||
ftdm_channel_close(&toclose);
|
||||
return;
|
||||
}
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%d:%d starting loop\n", ftdmchan->span_id, ftdmchan->chan_id);
|
||||
@@ -1426,11 +1427,12 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
|
||||
ftdmchan->sflags = 0;
|
||||
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 */
|
||||
/* we dont want to call ftdm_channel_close 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",
|
||||
ftdmchan->span_id, ftdmchan->chan_id);
|
||||
} else {
|
||||
ftdm_channel_done(ftdmchan);
|
||||
ftdm_channel_t *toclose = ftdmchan;
|
||||
ftdm_channel_close(&toclose);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2476,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;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#if HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
@@ -65,7 +65,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
|
||||
ZSD_INBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_ANY_STATE, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}
|
||||
{FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_END}
|
||||
},
|
||||
{
|
||||
ZSD_INBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_RESET, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END}
|
||||
},
|
||||
{
|
||||
ZSD_INBOUND,
|
||||
@@ -170,7 +176,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
|
||||
ZSD_OUTBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_ANY_STATE, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
|
||||
{FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
|
||||
},
|
||||
{
|
||||
ZSD_OUTBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_RESET, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END}
|
||||
},
|
||||
{
|
||||
ZSD_OUTBOUND,
|
||||
@@ -203,7 +215,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_DIALING, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
|
||||
FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
|
||||
FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
|
||||
FTDM_CHANNEL_STATE_DOWN, FTDM_END}
|
||||
},
|
||||
{
|
||||
@@ -211,14 +223,20 @@ ftdm_state_map_t sangoma_isdn_state_map = {
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
|
||||
FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
|
||||
},
|
||||
FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
|
||||
},
|
||||
{
|
||||
ZSD_OUTBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
|
||||
},
|
||||
{
|
||||
ZSD_OUTBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_RINGING, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
|
||||
},
|
||||
{
|
||||
ZSD_OUTBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
@@ -626,8 +644,11 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
|
||||
case FTDM_CHANNEL_STATE_GET_CALLERID:
|
||||
{
|
||||
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
|
||||
/* By default, we do not send a progress indicator in the proceed */
|
||||
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
|
||||
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
|
||||
sngisdn_snd_proceed(ftdmchan);
|
||||
sngisdn_snd_proceed(ftdmchan, prog_ind);
|
||||
}
|
||||
/* Wait in this state until we get FACILITY msg */
|
||||
}
|
||||
@@ -666,16 +687,28 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
} else {
|
||||
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
|
||||
/* By default, we do not send a progress indicator in the proceed */
|
||||
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
|
||||
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
|
||||
sngisdn_snd_proceed(ftdmchan);
|
||||
sngisdn_snd_proceed(ftdmchan, prog_ind);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
{
|
||||
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
|
||||
sngisdn_snd_alert(ftdmchan, prog_ind);
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||
/* OUTBOUND...so we were told by the line of this so notify the user */
|
||||
sigev.event_id = FTDM_SIGEVENT_RINGING;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
}
|
||||
} else {
|
||||
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
|
||||
sngisdn_snd_alert(ftdmchan, prog_ind);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
@@ -686,12 +719,9 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
|
||||
sigev.event_id = FTDM_SIGEVENT_PROGRESS;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
} else {
|
||||
/* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */
|
||||
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) {
|
||||
/* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */
|
||||
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
|
||||
sngisdn_snd_progress(ftdmchan, prog_ind);
|
||||
}
|
||||
/* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */
|
||||
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
|
||||
sngisdn_snd_progress(ftdmchan, prog_ind);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -774,7 +804,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
|
||||
sngisdn_snd_release(ftdmchan, 0);
|
||||
|
||||
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
|
||||
sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
|
||||
sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
|
||||
}
|
||||
} else {
|
||||
sngisdn_snd_disconnect(ftdmchan);
|
||||
@@ -832,6 +862,11 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
|
||||
/* IMPLEMENT ME */
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RESET:
|
||||
{
|
||||
sngisdn_snd_restart(ftdmchan);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
@@ -851,6 +886,22 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
|
||||
return;
|
||||
}
|
||||
|
||||
static FIO_CHANNEL_SEND_MSG_FUNCTION(ftdm_sangoma_isdn_send_msg)
|
||||
{
|
||||
ftdm_status_t status = FTDM_FAIL;
|
||||
|
||||
switch (sigmsg->event_id) {
|
||||
case FTDM_SIGEVENT_FACILITY:
|
||||
sngisdn_snd_fac_req(ftdmchan);
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unsupported signalling msg requested\n");
|
||||
status = FTDM_BREAK;
|
||||
}
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
return status;
|
||||
}
|
||||
|
||||
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
|
||||
{
|
||||
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
|
||||
@@ -925,7 +976,8 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
|
||||
}
|
||||
|
||||
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
|
||||
{
|
||||
{
|
||||
sngisdn_span_data_t *signal_data = span->signal_data;
|
||||
ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
|
||||
if (sngisdn_stack_start(span) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
|
||||
@@ -935,6 +987,14 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
|
||||
ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
|
||||
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
|
||||
|
||||
if (signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) {
|
||||
sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
|
||||
}
|
||||
|
||||
if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) {
|
||||
sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
|
||||
}
|
||||
|
||||
/*start the span monitor thread*/
|
||||
if (ftdm_thread_create_detached(ftdm_sangoma_isdn_run, span) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN Span Monitor Thread!\n");
|
||||
@@ -1030,6 +1090,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
|
||||
span->stop = ftdm_sangoma_isdn_stop;
|
||||
span->signal_type = FTDM_SIGTYPE_ISDN;
|
||||
span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
|
||||
span->send_msg = ftdm_sangoma_isdn_send_msg;
|
||||
span->channel_request = NULL;
|
||||
span->signal_cb = sig_cb;
|
||||
span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
|
||||
@@ -1040,11 +1101,12 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
|
||||
ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
|
||||
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
|
||||
ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
|
||||
ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
|
||||
|
||||
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
|
||||
span->trunk_type == FTDM_TRUNK_BRI) {
|
||||
|
||||
sngisdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
|
||||
sngisdn_set_span_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
|
||||
}
|
||||
|
||||
/* Initialize scheduling context */
|
||||
@@ -1139,6 +1201,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* TODO: Move functions to table + function pointers */
|
||||
if (!strcasecmp(argv[0], "trace")) {
|
||||
char *trace_opt;
|
||||
|
||||
@@ -1156,6 +1219,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
|
||||
stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!strcasecmp(trace_opt, "q921")) {
|
||||
sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
|
||||
} else if (!strcasecmp(trace_opt, "q931")) {
|
||||
@@ -1164,7 +1228,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
|
||||
sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(argv[0], "l1_stats")) {
|
||||
ftdm_span_t *span;
|
||||
@@ -1182,7 +1246,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
|
||||
}
|
||||
sngisdn_print_phy_stats(stream, span);
|
||||
}
|
||||
|
||||
|
||||
if (!strcasecmp(argv[0], "show_spans")) {
|
||||
ftdm_span_t *span = NULL;
|
||||
if (argc == 2) {
|
||||
|
||||
@@ -101,9 +101,11 @@ typedef enum {
|
||||
FLAG_GLARE = (1 << 6),
|
||||
FLAG_DELAYED_REL = (1 << 7),
|
||||
FLAG_SENT_PROCEED = (1 << 8),
|
||||
FLAG_SEND_DISC = (1 << 9),
|
||||
FLAG_SEND_DISC = (1 << 9),
|
||||
/* Used for BRI only, flag is set after we request line CONNECTED */
|
||||
FLAG_ACTIVATING = (1 << 10),
|
||||
FLAG_ACTIVATING = (1 << 10),
|
||||
/* Used when we receive an ALERT msg + inband tones ready */
|
||||
FLAG_MEDIA_READY = (1 << 11),
|
||||
} sngisdn_flag_t;
|
||||
|
||||
|
||||
@@ -259,6 +261,8 @@ typedef struct sngisdn_span_data {
|
||||
int8_t facility_timeout;
|
||||
uint8_t num_local_numbers;
|
||||
uint8_t ignore_cause_value;
|
||||
uint8_t raw_trace_q931;
|
||||
uint8_t raw_trace_q921;
|
||||
uint8_t timer_t3;
|
||||
uint8_t restart_opt;
|
||||
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
|
||||
@@ -352,8 +356,11 @@ void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
|
||||
ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
|
||||
ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
|
||||
|
||||
ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
|
||||
ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail);
|
||||
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
|
||||
void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status);
|
||||
|
||||
ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
|
||||
ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
|
||||
|
||||
|
||||
@@ -363,7 +370,7 @@ void stack_pst_init(Pst *pst);
|
||||
/* Outbound Call Control functions */
|
||||
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
|
||||
void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
|
||||
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
|
||||
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
|
||||
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
|
||||
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
|
||||
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
|
||||
@@ -374,6 +381,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
|
||||
void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan);
|
||||
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
|
||||
void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
|
||||
void sngisdn_snd_restart(ftdm_channel_t *ftdmchan);
|
||||
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
|
||||
void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event);
|
||||
|
||||
@@ -421,8 +429,11 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event);
|
||||
void sngisdn_rcv_phy_ind(SuId suId, Reason reason);
|
||||
void sngisdn_rcv_q921_ind(BdMngmt *status);
|
||||
|
||||
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
|
||||
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
|
||||
void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
|
||||
void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
|
||||
void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
|
||||
void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
|
||||
|
||||
void get_memory_info(void);
|
||||
|
||||
ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
|
||||
@@ -436,6 +447,7 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
|
||||
void sngisdn_rcv_sng_assert(char *message);
|
||||
|
||||
ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
|
||||
ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
|
||||
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
|
||||
ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
|
||||
ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display);
|
||||
@@ -443,16 +455,20 @@ ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *us
|
||||
ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
|
||||
ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd);
|
||||
ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
|
||||
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len);
|
||||
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len);
|
||||
|
||||
ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
|
||||
ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
|
||||
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
|
||||
ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
|
||||
ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
|
||||
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
|
||||
ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind);
|
||||
ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap);
|
||||
ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId);
|
||||
ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd);
|
||||
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
|
||||
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len);
|
||||
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len);
|
||||
|
||||
|
||||
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability);
|
||||
@@ -480,7 +496,6 @@ static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngis
|
||||
|
||||
|
||||
void handle_sng_log(uint8_t level, char *fmt,...);
|
||||
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
|
||||
void sngisdn_delayed_setup(void* p_sngisdn_info);
|
||||
void sngisdn_delayed_release(void* p_sngisdn_info);
|
||||
void sngisdn_delayed_connect(void* p_sngisdn_info);
|
||||
|
||||
@@ -296,6 +296,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
|
||||
parse_yesno(var, val, &signal_data->facility_ie_decode);
|
||||
} else if (!strcasecmp(var, "ignore-cause-value")) {
|
||||
parse_yesno(var, val, &signal_data->ignore_cause_value);
|
||||
} else if (!strcasecmp(var, "q931-raw-trace")) {
|
||||
parse_yesno(var, val, &signal_data->raw_trace_q931);
|
||||
} else if (!strcasecmp(var, "q921-raw-trace")) {
|
||||
parse_yesno(var, val, &signal_data->raw_trace_q921);
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status
|
||||
sig.span_id = ftdmchan->span_id;
|
||||
sig.channel = ftdmchan;
|
||||
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sig.sigstatus = status;
|
||||
sig.ev_data.sigstatus.status = status;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sig);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
*/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
|
||||
static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
|
||||
static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan);
|
||||
|
||||
/* Remote side transmit a SETUP */
|
||||
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
@@ -123,12 +124,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Export ftdmchan variables here if we need to */
|
||||
ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1");
|
||||
#endif
|
||||
/* Fill in call information */
|
||||
get_calling_num(ftdmchan, &conEvnt->cgPtyNmb);
|
||||
get_calling_num2(ftdmchan, &conEvnt->cgPtyNmb2);
|
||||
get_called_num(ftdmchan, &conEvnt->cdPtyNmb);
|
||||
get_redir_num(ftdmchan, &conEvnt->redirNmb);
|
||||
get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
|
||||
@@ -235,6 +233,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RESET:
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
break;
|
||||
@@ -277,6 +278,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||
switch(ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_PROCEED:
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
@@ -288,6 +290,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
case FTDM_CHANNEL_STATE_HANGUP:
|
||||
/* Race condition, we just hung up the call - ignore this message */
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RESET:
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
@@ -304,6 +309,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
|
||||
/* Race condition, We just hung up an incoming call right after we sent a CONNECT - ignore this message */
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RESET:
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
@@ -357,27 +365,47 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
goto sngisdn_process_cnst_ind_end;
|
||||
}
|
||||
|
||||
|
||||
switch(ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
case FTDM_CHANNEL_STATE_PROCEED:
|
||||
if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
} else if (evntType == MI_CALLPROC) {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
|
||||
} else {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY);
|
||||
}
|
||||
switch (evntType) {
|
||||
case MI_CALLPROC:
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
|
||||
}
|
||||
break;
|
||||
case MI_ALERTING:
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RINGING);
|
||||
}
|
||||
break;
|
||||
case MI_PROGRESS:
|
||||
if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
|
||||
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
} else if (ftdmchan->state != FTDM_CHANNEL_STATE_PROGRESS) {
|
||||
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* We should never reach this section !*/
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle this event %d\n", evntType);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
/* We are already in progress media, we can't go to any higher state except up */
|
||||
/* Do nothing */
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RESET:
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing ALERT/PROCEED/PROGRESS in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
@@ -410,12 +438,16 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
case FTDM_CHANNEL_STATE_PROCEED:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Receiving more digits %s, but we already proceeded with call\n", cnStEvnt->cdPtyNmb.nmbDigits.val);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RESET:
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "\n", suId, suInstId, spInstId);
|
||||
break;
|
||||
@@ -450,6 +482,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
case FTDM_CHANNEL_STATE_PROCEED:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
@@ -478,6 +511,9 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
/* This is a race condition. We just sent a DISCONNECT, on this channel */
|
||||
/* Do nothing */
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RESET:
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
@@ -532,7 +568,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
/* Remote side rejected our SETUP message on outbound call */
|
||||
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
|
||||
sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
|
||||
sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
|
||||
}
|
||||
/* fall-through */
|
||||
case FTDM_CHANNEL_STATE_PROCEED:
|
||||
@@ -540,6 +576,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
/* If we previously had a glare on this channel,
|
||||
this RELEASE could be for the previous call. Confirm whether call_data has
|
||||
not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */
|
||||
@@ -581,6 +618,9 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
/* set abort flag so that we do not transmit another release complete on this channel once FS core is done */
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_RESET:
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
@@ -757,14 +797,14 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
{
|
||||
ftdm_sigmsg_t sigev;
|
||||
if (facEvnt->facElmt.facStr.pres) {
|
||||
get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len);
|
||||
get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len-2);
|
||||
}
|
||||
memset(&sigev, 0, sizeof(sigev));
|
||||
sigev.chan_id = ftdmchan->chan_id;
|
||||
sigev.span_id = ftdmchan->span_id;
|
||||
sigev.channel = ftdmchan;
|
||||
|
||||
sigev.event_id = FTDM_SIGEVENT_MSG;
|
||||
sigev.event_id = FTDM_SIGEVENT_FACILITY;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
}
|
||||
break;
|
||||
@@ -884,6 +924,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROCEED:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n");
|
||||
sngisdn_snd_disconnect(ftdmchan);
|
||||
@@ -902,6 +943,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_PROCEED:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
/* T310 timer has expired */
|
||||
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T310 Timer expired, hanging up call\n");
|
||||
@@ -938,6 +980,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
break;
|
||||
case 9: /* Remote switch is in "Incoming call proceeding" state */
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_RINGING:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
case FTDM_CHANNEL_STATE_GET_CALLERID:
|
||||
@@ -1047,18 +1090,91 @@ void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
return;
|
||||
}
|
||||
|
||||
static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_RESET:
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_DOWN:
|
||||
/* Do nothing */
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RESTART CFM in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
|
||||
{
|
||||
int16_t suId = sngisdn_event->suId;
|
||||
int16_t dChan = sngisdn_event->dChan;
|
||||
uint8_t ces = sngisdn_event->ces;
|
||||
uint8_t evntType = sngisdn_event->evntType;
|
||||
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
|
||||
/* Function does not require any info from ssHlEvnt struct for now */
|
||||
/*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
|
||||
uint8_t chan_no = 0;
|
||||
Rst *rstEvnt = &sngisdn_event->event.rstEvnt;
|
||||
|
||||
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[dChan].spans[1];
|
||||
if (!signal_data) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on unconfigured span (suId:%d)\n", suId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Receved RESTART, but Restart Indicator IE not present\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(rstEvnt->rstInd.rstClass.val) {
|
||||
case IN_CL_INDCHAN: /* Indicated b-channel */
|
||||
if (rstEvnt->chanId.eh.pres) {
|
||||
if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
|
||||
if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
|
||||
chan_no = rstEvnt->chanId.infoChanSel.val;
|
||||
}
|
||||
} else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
|
||||
if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
|
||||
chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!chan_no) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case IN_CL_SNGINT: /* Single interface */
|
||||
case IN_CL_ALLINT: /* All interfaces */
|
||||
/* In case restart class indicates all interfaces, we will duplicate
|
||||
this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
|
||||
so treat it as a single interface anyway */
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
|
||||
return;
|
||||
}
|
||||
|
||||
if (chan_no) { /* For a single channel */
|
||||
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no);
|
||||
} else {
|
||||
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no);
|
||||
sngisdn_process_restart_confirm(ftdmchan);
|
||||
}
|
||||
} else { /* for all channels */
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *curr = NULL;
|
||||
|
||||
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
|
||||
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
|
||||
sngisdn_process_restart_confirm((ftdm_channel_t*)ftdm_iterator_current(curr));
|
||||
}
|
||||
ftdm_iterator_free(chaniter);
|
||||
}
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
@@ -1087,7 +1203,7 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
return;
|
||||
}
|
||||
|
||||
ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
|
||||
static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
|
||||
{
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
|
||||
@@ -51,72 +51,6 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
|
||||
ftdm_mutex_unlock(g_sngisdn_data.ccs[signal_data->cc_id].mutex);
|
||||
|
||||
memset(&conEvnt, 0, sizeof(conEvnt));
|
||||
|
||||
conEvnt.bearCap[0].eh.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].infoTranCap.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
|
||||
|
||||
conEvnt.bearCap[0].codeStand0.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].codeStand0.val = IN_CSTD_CCITT;
|
||||
conEvnt.bearCap[0].infoTranRate0.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].infoTranRate0.val = IN_ITR_64KBIT;
|
||||
conEvnt.bearCap[0].tranMode.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].tranMode.val = IN_TM_CIRCUIT;
|
||||
|
||||
conEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
conEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
conEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
conEvnt.chanId.intIdent.pres = NOTPRSNT;
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
/* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
|
||||
Check with Trillium if this ever causes calls to fail in the field */
|
||||
|
||||
/* BRI only params */
|
||||
conEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
/* PRI only params */
|
||||
conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
|
||||
|
||||
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
|
||||
conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
|
||||
|
||||
/* We are bridging a call from T1 */
|
||||
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
|
||||
|
||||
} else if (conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
|
||||
|
||||
/* We are bridging a call from E1 */
|
||||
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
|
||||
}
|
||||
|
||||
conEvnt.bearCap[0].lyr1Ident.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].lyr1Ident.val = IN_L1_IDENT;
|
||||
|
||||
conEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
|
||||
conEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
conEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
conEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
conEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
conEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
|
||||
conEvnt.sndCmplt.eh.pres = PRSNT_NODEF;
|
||||
}
|
||||
@@ -126,8 +60,11 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
|
||||
}
|
||||
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
|
||||
|
||||
set_chan_id_ie(ftdmchan, &conEvnt.chanId);
|
||||
set_bear_cap_ie(ftdmchan, &conEvnt.bearCap[0]);
|
||||
set_called_num(ftdmchan, &conEvnt.cdPtyNmb);
|
||||
set_calling_num(ftdmchan, &conEvnt.cgPtyNmb);
|
||||
set_calling_num2(ftdmchan, &conEvnt.cgPtyNmb2);
|
||||
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
|
||||
set_redir_num(ftdmchan, &conEvnt.redirNmb);
|
||||
set_calling_name(ftdmchan, &conEvnt);
|
||||
@@ -160,38 +97,7 @@ void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan)
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
|
||||
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
/* BRI only params */
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
|
||||
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
|
||||
@@ -220,38 +126,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
|
||||
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
/* BRI only params */
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
|
||||
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
|
||||
@@ -262,10 +137,9 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
|
||||
}
|
||||
|
||||
|
||||
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
|
||||
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
|
||||
{
|
||||
CnStEvnt cnStEvnt;
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
@@ -277,40 +151,12 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
|
||||
}
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
|
||||
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
/* BRI only params */
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
|
||||
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
|
||||
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
|
||||
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
|
||||
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
|
||||
@@ -343,6 +189,7 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
|
||||
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
|
||||
@@ -369,6 +216,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind
|
||||
|
||||
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
|
||||
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
|
||||
@@ -393,41 +241,11 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
|
||||
}
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
|
||||
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
/* BRI only params */
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
|
||||
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
|
||||
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
|
||||
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
|
||||
@@ -450,10 +268,17 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
|
||||
|
||||
memset(&facEvnt, 0, sizeof(facEvnt));
|
||||
|
||||
set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (ftdm_size_t*)&facEvnt.facElmt.facStr.len);
|
||||
if (set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (uint8_t*)&facEvnt.facElmt.facStr.len) != FTDM_SUCCESS) {
|
||||
/* No point in sending a FACILITY message if there is no Facility IE to transmit */
|
||||
return;
|
||||
}
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
|
||||
facEvnt.facElmt.eh.pres = PRSNT_NODEF;
|
||||
facEvnt.facElmt.facStr.pres = PRSNT_NODEF;
|
||||
facEvnt.facElmt.facStr.val[0] = 0x1C;
|
||||
facEvnt.facElmt.facStr.val[1] = facEvnt.facElmt.facStr.len;
|
||||
facEvnt.facElmt.facStr.val[1] = (uint8_t)facEvnt.facElmt.facStr.len;
|
||||
facEvnt.facElmt.facStr.len +=2; /* Need to include the size of identifier + len */
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
|
||||
@@ -481,6 +306,8 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
|
||||
//ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ\n");
|
||||
|
||||
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces);
|
||||
|
||||
if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, signal_data->dchan_id, sngisdn_info->ces)) {
|
||||
@@ -501,6 +328,8 @@ void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan)
|
||||
|
||||
memset(&staEvnt, 0, sizeof(StaEvnt));
|
||||
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
if (sng_isdn_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused Status ENQ request\n");
|
||||
@@ -539,6 +368,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
|
||||
discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
|
||||
|
||||
set_facility_ie(ftdmchan, &discEvnt.facilityStr);
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) {
|
||||
@@ -546,6 +376,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
|
||||
{
|
||||
RelEvnt relEvnt;
|
||||
@@ -585,6 +416,7 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
|
||||
}
|
||||
|
||||
set_facility_ie(ftdmchan, &relEvnt.facilityStr);
|
||||
ftdm_call_clear_data(&ftdmchan->caller_data);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId);
|
||||
|
||||
@@ -600,6 +432,24 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_snd_restart(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
Rst rstEvnt;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
memset(&rstEvnt, 0, sizeof(rstEvnt));
|
||||
|
||||
set_chan_id_ie(ftdmchan, &rstEvnt.chanId);
|
||||
set_restart_ind_ie(ftdmchan, &rstEvnt.rstInd);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RESTART (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, CES_MNGMNT);
|
||||
|
||||
if (sng_isdn_restart_request(signal_data->cc_id, &rstEvnt, signal_data->dchan_id, CES_MNGMNT, IN_SND_RST)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RESTART request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* We received an incoming frame on the d-channel, send data to the stack */
|
||||
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
|
||||
|
||||
@@ -34,9 +34,6 @@
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
#define MAX_DECODE_STR_LEN 2000
|
||||
|
||||
|
||||
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
uint8_t bchan_no = 0;
|
||||
@@ -630,8 +627,9 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
|
||||
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
|
||||
|
||||
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
|
||||
|
||||
|
||||
/* Enqueue the event to each span within the dChan */
|
||||
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
|
||||
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
|
||||
@@ -725,14 +723,25 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
|
||||
ftdmspan = signal_data->ftdm_span;
|
||||
|
||||
if (status->t.usta.alarm.event == LCM_EVENT_UP) {
|
||||
uint32_t chan_no = status->t.usta.evntParm[2];
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
|
||||
status->t.usta.suId,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
|
||||
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
|
||||
sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
|
||||
|
||||
if (chan_no) {
|
||||
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(ftdmspan, chan_no);
|
||||
if (ftdmchan) {
|
||||
sngisdn_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
|
||||
sngisdn_set_chan_avail_rate(ftdmchan, SNGISDN_AVAIL_UP);
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_CRIT, "stack alarm event on invalid channel :%d\n", chan_no);
|
||||
}
|
||||
} else {
|
||||
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
|
||||
sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
|
||||
}
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
|
||||
status->t.usta.suId,
|
||||
@@ -741,7 +750,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
|
||||
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
|
||||
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
|
||||
sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
|
||||
sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -765,9 +774,6 @@ void sngisdn_rcv_cc_ind(CcMngmt *status)
|
||||
return;
|
||||
}
|
||||
|
||||
#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
|
||||
(event == TL3PKTRX)?"RX":"UNKNOWN"
|
||||
|
||||
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
|
||||
{
|
||||
MsgLen mlen;
|
||||
@@ -776,13 +782,20 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
|
||||
Buffer *tmp;
|
||||
Data *cptr;
|
||||
uint8_t data;
|
||||
ftdm_trace_dir_t dir;
|
||||
uint8_t tdata[1000];
|
||||
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
|
||||
|
||||
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.suId];
|
||||
|
||||
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
|
||||
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
|
||||
|
||||
if (mlen != 0) {
|
||||
|
||||
if (trc->t.trc.evnt == TL3PKTTX) {
|
||||
dir = FTDM_TRACE_OUTGOING;
|
||||
} else {
|
||||
dir = FTDM_TRACE_INCOMING;
|
||||
}
|
||||
|
||||
if (mlen) {
|
||||
tmp = mBuf->b_cont;
|
||||
cptr = tmp->b_rptr;
|
||||
data = *cptr++;
|
||||
@@ -797,41 +810,40 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
|
||||
}
|
||||
data = *cptr++;
|
||||
}
|
||||
|
||||
sngisdn_trace_q931(data_str, tdata, mlen);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d FRAME %s:%s\n", trc->t.trc.suId, Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
|
||||
if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) {
|
||||
sngisdn_trace_raw_q931(signal_data, dir, tdata, mlen);
|
||||
} else {
|
||||
sngisdn_trace_interpreted_q931(signal_data, dir, tdata, mlen);
|
||||
}
|
||||
}
|
||||
|
||||
ftdm_safe_free(data_str);
|
||||
/* We do not need to free mBuf in this case because stack does it */
|
||||
/* SPutMsg(mBuf); */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
|
||||
(event == TL2FRMTX)?"TX": \
|
||||
(event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
|
||||
|
||||
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
|
||||
{
|
||||
MsgLen mlen;
|
||||
Buffer *tmp;
|
||||
MsgLen i;
|
||||
int16_t j;
|
||||
Buffer *tmp;
|
||||
Data *cptr;
|
||||
uint8_t data;
|
||||
uint8_t tdata[16];
|
||||
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
|
||||
|
||||
ftdm_trace_dir_t dir;
|
||||
uint8_t tdata[1000];
|
||||
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.lnkNmb];
|
||||
|
||||
if (trc->t.trc.evnt == TL2TMR) {
|
||||
goto end_of_trace;
|
||||
return;
|
||||
}
|
||||
|
||||
if (trc->t.trc.evnt == TL2FRMTX) {
|
||||
dir = FTDM_TRACE_OUTGOING;
|
||||
} else {
|
||||
dir = FTDM_TRACE_INCOMING;
|
||||
}
|
||||
|
||||
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
|
||||
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
|
||||
|
||||
if (mlen != 0) {
|
||||
tmp = mBuf->b_cont;
|
||||
cptr = tmp->b_rptr;
|
||||
@@ -853,12 +865,12 @@ void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
|
||||
}
|
||||
|
||||
}
|
||||
sngisdn_trace_q921(data_str, tdata, mlen);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", trc->t.trc.lnkNmb, Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
|
||||
if (signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) {
|
||||
sngisdn_trace_raw_q921(signal_data, dir, tdata, mlen);
|
||||
} else {
|
||||
sngisdn_trace_interpreted_q921(signal_data, dir, tdata, mlen);
|
||||
}
|
||||
}
|
||||
end_of_trace:
|
||||
ftdm_safe_free(data_str);
|
||||
SPutMsg(mBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,19 +136,25 @@ ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
|
||||
ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail)
|
||||
{
|
||||
if (span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
if (FTDM_SPAN_IS_BRI(chan->span)) {
|
||||
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
|
||||
chan->availability_rate = avail;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
|
||||
{
|
||||
if (FTDM_SPAN_IS_BRI(span)) {
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *curr = NULL;
|
||||
|
||||
|
||||
chaniter = ftdm_span_get_chan_iterator(span, NULL);
|
||||
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
|
||||
ftdm_log_chan(((ftdm_channel_t*)ftdm_iterator_current(curr)), FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
|
||||
((ftdm_channel_t*)ftdm_iterator_current(curr))->availability_rate = avail;
|
||||
sngisdn_set_chan_avail_rate(((ftdm_channel_t*)ftdm_iterator_current(curr)), avail);
|
||||
}
|
||||
ftdm_iterator_free(chaniter);
|
||||
}
|
||||
@@ -185,6 +191,39 @@ ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
|
||||
{
|
||||
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
|
||||
if (cgPtyNmb->eh.pres != PRSNT_NODEF) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) {
|
||||
ftdm_call_add_var(caller_data, "isdn.cg_pty2.screen_ind", ftdm_screening2str(cgPtyNmb->screenInd.val));
|
||||
}
|
||||
|
||||
if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) {
|
||||
ftdm_call_add_var(caller_data, "isdn.cg_pty2.presentation_ind", ftdm_presentation2str(cgPtyNmb->presInd0.val));
|
||||
}
|
||||
|
||||
if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
|
||||
ftdm_call_add_var(caller_data, "isdn.cg_pty2.npi", ftdm_npi2str(cgPtyNmb->nmbPlanId.val));
|
||||
}
|
||||
|
||||
if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) {
|
||||
ftdm_call_add_var(caller_data, "isdn.cg_pty2.ton", ftdm_ton2str(cgPtyNmb->typeNmb1.val));
|
||||
}
|
||||
|
||||
if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
|
||||
char digits_string [32];
|
||||
memcpy(digits_string, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len);
|
||||
digits_string[cgPtyNmb->nmbDigits.len] = '\0';
|
||||
ftdm_call_add_var(caller_data, "isdn.cg_pty2.digits", digits_string);
|
||||
}
|
||||
memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani));
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
|
||||
{
|
||||
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
|
||||
@@ -278,7 +317,7 @@ ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
|
||||
|
||||
memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len);
|
||||
subaddress[cgPtySad->sadInfo.len] = '\0';
|
||||
ftdm_channel_add_var(ftdmchan, "isdn.calling_subaddr", subaddress);
|
||||
ftdm_call_add_var(&ftdmchan->caller_data, "isdn.calling_subaddr", subaddress);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -291,17 +330,16 @@ ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr
|
||||
return get_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, facilityStr->facilityStr.len);
|
||||
}
|
||||
|
||||
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len)
|
||||
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len)
|
||||
{
|
||||
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
|
||||
if (data_len > sizeof(caller_data->raw_data)-2) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n");
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
/* size of facilityStr->facilityStr.len is a uint8_t so no need to check
|
||||
for overflow here as facilityStr->facilityStr.len will always be smaller
|
||||
than sizeof(caller_data->raw_data) */
|
||||
|
||||
memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data));
|
||||
/* Always include Facility IE identifier + len so this can be used as a sanity check by the user */
|
||||
caller_data->raw_data[0] = SNGISDN_Q931_FACILITY_IE_ID;
|
||||
@@ -348,7 +386,7 @@ ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
|
||||
val = SNGISDN_PROGIND_DESCR_INVALID;
|
||||
break;
|
||||
}
|
||||
ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
|
||||
ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
|
||||
}
|
||||
|
||||
if (progInd->location.pres) {
|
||||
@@ -379,7 +417,7 @@ ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
|
||||
val = SNGISDN_PROGIND_LOC_INVALID;
|
||||
break;
|
||||
}
|
||||
ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
|
||||
ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
@@ -423,6 +461,89 @@ ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
|
||||
{
|
||||
const char* string = NULL;
|
||||
uint8_t len,val;
|
||||
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
|
||||
|
||||
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.digits");
|
||||
if ((string == NULL) || !(*string)) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
cgPtyNmb->eh.pres = PRSNT_NODEF;
|
||||
|
||||
len = strlen(string);
|
||||
cgPtyNmb->nmbDigits.len = len;
|
||||
|
||||
cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
|
||||
memcpy(cgPtyNmb->nmbDigits.val, string, len);
|
||||
|
||||
/* Screening Indicator */
|
||||
cgPtyNmb->screenInd.pres = PRSNT_NODEF;
|
||||
|
||||
val = FTDM_SCREENING_INVALID;
|
||||
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.screening_ind");
|
||||
if ((string != NULL) && (*string)) {
|
||||
val = ftdm_str2ftdm_screening(string);
|
||||
}
|
||||
|
||||
/* isdn.cg_pty2.screen_ind does not exist or we could not parse its value */
|
||||
if (val == FTDM_SCREENING_INVALID) {
|
||||
/* default to caller data screening ind */
|
||||
cgPtyNmb->screenInd.val = caller_data->screen;
|
||||
} else {
|
||||
cgPtyNmb->screenInd.val = val;
|
||||
}
|
||||
|
||||
/* Presentation Indicator */
|
||||
cgPtyNmb->presInd0.pres = PRSNT_NODEF;
|
||||
|
||||
val = FTDM_PRES_INVALID;
|
||||
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.presentation_ind");
|
||||
if ((string != NULL) && (*string)) {
|
||||
val = ftdm_str2ftdm_presentation(string);
|
||||
}
|
||||
|
||||
if (val == FTDM_PRES_INVALID) {
|
||||
cgPtyNmb->presInd0.val = caller_data->pres;
|
||||
} else {
|
||||
cgPtyNmb->presInd0.val = val;
|
||||
}
|
||||
|
||||
/* Numbering Plan Indicator */
|
||||
cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
|
||||
|
||||
val = FTDM_NPI_INVALID;
|
||||
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.npi");
|
||||
if ((string != NULL) && (*string)) {
|
||||
val = ftdm_str2ftdm_npi(string);
|
||||
}
|
||||
|
||||
if (val == FTDM_NPI_INVALID) {
|
||||
cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
|
||||
} else {
|
||||
cgPtyNmb->nmbPlanId.val = val;
|
||||
}
|
||||
|
||||
cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
|
||||
|
||||
/* Type of Number */
|
||||
val = FTDM_TON_INVALID;
|
||||
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.ton");
|
||||
if ((string != NULL) && (*string)) {
|
||||
val = ftdm_str2ftdm_ton(string);
|
||||
}
|
||||
|
||||
if (val == FTDM_TON_INVALID) {
|
||||
cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
|
||||
} else {
|
||||
cgPtyNmb->typeNmb1.val = val;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
|
||||
{
|
||||
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
|
||||
@@ -544,7 +665,7 @@ ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
|
||||
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
|
||||
{
|
||||
const char* clg_subaddr = NULL;
|
||||
clg_subaddr = ftdm_channel_get_var(ftdmchan, "isdn.calling_subaddr");
|
||||
clg_subaddr = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.calling_subaddr");
|
||||
if ((clg_subaddr != NULL) && (*clg_subaddr)) {
|
||||
unsigned len = strlen (clg_subaddr);
|
||||
cgPtySad->eh.pres = PRSNT_NODEF;
|
||||
@@ -561,11 +682,10 @@ ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
|
||||
{
|
||||
ftdm_status_t status;
|
||||
status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (ftdm_size_t*)&facilityStr->facilityStr.len);
|
||||
status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (uint8_t*)&(facilityStr->facilityStr.len));
|
||||
if (status == FTDM_SUCCESS) {
|
||||
facilityStr->eh.pres = PRSNT_NODEF;
|
||||
facilityStr->facilityStr.pres = PRSNT_NODEF;
|
||||
@@ -573,13 +693,15 @@ ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr
|
||||
return status;
|
||||
}
|
||||
|
||||
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len)
|
||||
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len)
|
||||
{
|
||||
int len;
|
||||
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
|
||||
|
||||
if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) {
|
||||
*data_len = caller_data->raw_data[1];
|
||||
memcpy(data, &caller_data->raw_data[2], *data_len);
|
||||
len = caller_data->raw_data[1];
|
||||
memcpy(data, &caller_data->raw_data[2], len);
|
||||
*data_len = len;
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
return FTDM_FAIL;
|
||||
@@ -591,7 +713,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
|
||||
int descr = prog_ind.descr;
|
||||
int loc = prog_ind.loc;
|
||||
|
||||
str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.descr");
|
||||
str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.descr");
|
||||
if (str && *str) {
|
||||
/* User wants to override progress indicator */
|
||||
descr = ftdm_str2ftdm_sngisdn_progind_descr(str);
|
||||
@@ -602,8 +724,8 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.loc");
|
||||
if (str && *str) {
|
||||
str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.loc");
|
||||
if (str && *str) {
|
||||
loc = ftdm_str2ftdm_sngisdn_progind_loc(str);
|
||||
}
|
||||
if (loc == SNGISDN_PROGIND_LOC_INVALID) {
|
||||
@@ -672,6 +794,93 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
|
||||
{
|
||||
if (!ftdmchan) {
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
chanId->eh.pres = PRSNT_NODEF;
|
||||
chanId->prefExc.pres = PRSNT_NODEF;
|
||||
chanId->prefExc.val = IN_PE_EXCLSVE;
|
||||
chanId->dChanInd.pres = PRSNT_NODEF;
|
||||
chanId->dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
chanId->intIdentPres.pres = PRSNT_NODEF;
|
||||
chanId->intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
/* BRI only params */
|
||||
chanId->intType.pres = PRSNT_NODEF;
|
||||
chanId->intType.val = IN_IT_BASIC;
|
||||
chanId->infoChanSel.pres = PRSNT_NODEF;
|
||||
chanId->infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
chanId->intType.pres = PRSNT_NODEF;
|
||||
chanId->intType.val = IN_IT_OTHER;
|
||||
chanId->infoChanSel.pres = PRSNT_NODEF;
|
||||
chanId->infoChanSel.val = IN_ICS_B1CHAN;
|
||||
chanId->chanMapType.pres = PRSNT_NODEF;
|
||||
chanId->chanMapType.val = IN_CMT_BCHAN;
|
||||
chanId->nmbMap.pres = PRSNT_NODEF;
|
||||
chanId->nmbMap.val = IN_NM_CHNNMB;
|
||||
chanId->codeStand1.pres = PRSNT_NODEF;
|
||||
chanId->codeStand1.val = IN_CSTD_CCITT;
|
||||
chanId->chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
chanId->chanNmbSlotMap.len = 1;
|
||||
chanId->chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap)
|
||||
{
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
bearCap->eh.pres = PRSNT_NODEF;
|
||||
bearCap->infoTranCap.pres = PRSNT_NODEF;
|
||||
bearCap->infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
|
||||
|
||||
bearCap->codeStand0.pres = PRSNT_NODEF;
|
||||
bearCap->codeStand0.val = IN_CSTD_CCITT;
|
||||
bearCap->infoTranRate0.pres = PRSNT_NODEF;
|
||||
bearCap->infoTranRate0.val = IN_ITR_64KBIT;
|
||||
bearCap->tranMode.pres = PRSNT_NODEF;
|
||||
bearCap->tranMode.val = IN_TM_CIRCUIT;
|
||||
|
||||
if (!FTDM_SPAN_IS_BRI(ftdmchan->span)) {
|
||||
/* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
|
||||
Check with Trillium if this ever causes calls to fail in the field */
|
||||
|
||||
/* PRI only params */
|
||||
bearCap->usrInfoLyr1Prot.pres = PRSNT_NODEF;
|
||||
bearCap->usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
|
||||
|
||||
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
|
||||
bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
|
||||
|
||||
/* We are bridging a call from T1 */
|
||||
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
|
||||
|
||||
} else if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
|
||||
|
||||
/* We are bridging a call from E1 */
|
||||
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
|
||||
}
|
||||
|
||||
bearCap->lyr1Ident.pres = PRSNT_NODEF;
|
||||
bearCap->lyr1Ident.val = IN_L1_IDENT;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd)
|
||||
{
|
||||
rstInd->eh.pres = PRSNT_NODEF;
|
||||
rstInd->rstClass.pres = PRSNT_NODEF;
|
||||
rstInd->rstClass.val = IN_CL_INDCHAN;
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
void sngisdn_t3_timeout(void* p_sngisdn_info)
|
||||
{
|
||||
|
||||
@@ -36,14 +36,15 @@
|
||||
#include "ftmod_sangoma_isdn_trace.h"
|
||||
|
||||
#define OCTET(x) (ieData[x-1] & 0xFF)
|
||||
#define MAX_DECODE_STR_LEN 2000
|
||||
|
||||
void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
|
||||
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
|
||||
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
|
||||
uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
|
||||
|
||||
uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
|
||||
char* get_code_2_str(int code, struct code2str *pCodeTable);
|
||||
void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len);
|
||||
void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len);
|
||||
|
||||
char* get_code_2_str(int code, struct code2str *pCodeTable)
|
||||
{
|
||||
@@ -97,7 +98,43 @@ uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
|
||||
void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
|
||||
sngisdn_decode_q921(data_str, data, data_len);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
|
||||
ftdm_safe_free(data_str);
|
||||
}
|
||||
|
||||
void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t *raw_data;
|
||||
ftdm_sigmsg_t sigev;
|
||||
|
||||
memset(&sigev, 0, sizeof(sigev));
|
||||
|
||||
sigev.span_id = signal_data->ftdm_span->span_id;
|
||||
sigev.chan_id = signal_data->dchan->chan_id;
|
||||
sigev.channel = signal_data->dchan;
|
||||
sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
|
||||
|
||||
sigev.ev_data.logevent.dir = dir;
|
||||
sigev.ev_data.logevent.level = 2;
|
||||
|
||||
/* TODO: Map trace to call ID here */
|
||||
sigev.call_id = 0;
|
||||
|
||||
raw_data = ftdm_malloc(data_len);
|
||||
ftdm_assert(raw_data, "Failed to malloc");
|
||||
|
||||
memcpy(raw_data, data, 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);
|
||||
}
|
||||
|
||||
void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len)
|
||||
{
|
||||
int str_len;
|
||||
uint32_t i;
|
||||
@@ -169,7 +206,43 @@ void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len)
|
||||
|
||||
void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
|
||||
sngisdn_decode_q931(data_str, data, data_len);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
|
||||
ftdm_safe_free(data_str);
|
||||
}
|
||||
|
||||
void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t *raw_data;
|
||||
ftdm_sigmsg_t sigev;
|
||||
|
||||
memset(&sigev, 0, sizeof(sigev));
|
||||
|
||||
sigev.span_id = signal_data->ftdm_span->span_id;
|
||||
sigev.chan_id = signal_data->dchan->chan_id;
|
||||
sigev.channel = signal_data->dchan;
|
||||
sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
|
||||
|
||||
sigev.ev_data.logevent.dir = dir;
|
||||
sigev.ev_data.logevent.level = 3;
|
||||
|
||||
/* TODO: Map trace to call ID here */
|
||||
|
||||
raw_data = ftdm_malloc(data_len);
|
||||
ftdm_assert(raw_data, "Failed to malloc");
|
||||
|
||||
memcpy(raw_data, data, 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);
|
||||
}
|
||||
|
||||
void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
|
||||
{
|
||||
uint32_t str_len;
|
||||
uint8_t prot_disc, callRefFlag;
|
||||
|
||||
@@ -1589,7 +1589,7 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
|
||||
sigev.span_id = ftdmchan->span_id;
|
||||
sigev.channel = ftdmchan;
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
|
||||
/* if this is the first channel in the range */
|
||||
@@ -1689,7 +1689,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
|
||||
sigev.span_id = ftdmchan->span_id;
|
||||
sigev.channel = ftdmchan;
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_UP;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
|
||||
/* if this is the first channel in the range */
|
||||
|
||||
@@ -211,10 +211,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
|
||||
|
||||
/* add any special variables for the dialplan */
|
||||
sprintf(nadi, "%d", siConEvnt->cgPtyNum.natAddrInd.val);
|
||||
ftdm_channel_add_var(ftdmchan, "ss7_clg_nadi", nadi);
|
||||
ftdm_call_add_var(&ftdmchan->caller_data, "ss7_clg_nadi", nadi);
|
||||
|
||||
sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
|
||||
ftdm_channel_add_var(ftdmchan, "ss7_cld_nadi", nadi);
|
||||
ftdm_call_add_var(&ftdmchan->caller_data, "ss7_cld_nadi", nadi);
|
||||
|
||||
|
||||
/* check if a COT test is requested */
|
||||
@@ -2004,7 +2004,7 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
|
||||
|
||||
/* bring the sig status down */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
|
||||
/* unlock the channel again before we exit */
|
||||
@@ -2135,7 +2135,7 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
|
||||
|
||||
/* bring the sig status down */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_UP;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
|
||||
/* unlock the channel again before we exit */
|
||||
|
||||
@@ -502,6 +502,8 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
/**************************************************************************/
|
||||
case FTDM_CHANNEL_STATE_COLLECT: /* IAM received but wating on digits */
|
||||
|
||||
isup_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
|
||||
|
||||
if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
|
||||
SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
|
||||
break;
|
||||
@@ -521,8 +523,8 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
/*now go to the RING state */
|
||||
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
|
||||
|
||||
} else if (i >= g_ftdm_sngss7_data.min_digits) {
|
||||
SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits);
|
||||
} else if (i >= isup_intf->min_digits) {
|
||||
SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, isup_intf->min_digits);
|
||||
|
||||
/*now go to the RING state */
|
||||
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
|
||||
@@ -532,7 +534,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) {
|
||||
SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n",
|
||||
i,
|
||||
g_ftdm_sngss7_data.min_digits,
|
||||
isup_intf->min_digits,
|
||||
ftdmchan->caller_data.dnis.digits);
|
||||
|
||||
/* start ISUP t35 */
|
||||
@@ -839,7 +841,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
|
||||
/* all flags are down so we can bring up the sig status */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_UP;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
|
||||
ftdm_span_send_signal (ftdmchan->span, &sigev);
|
||||
} /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */
|
||||
} /* if !blocked */
|
||||
@@ -947,7 +949,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
/* if the sig_status is up...bring it down */
|
||||
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
|
||||
ftdm_span_send_signal (ftdmchan->span, &sigev);
|
||||
}
|
||||
|
||||
@@ -1031,7 +1033,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
|
||||
/* bring the sig status back up */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_UP;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
}
|
||||
|
||||
@@ -1044,7 +1046,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
|
||||
/* bring the sig status down */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
|
||||
/* go back to the last state */
|
||||
@@ -1056,7 +1058,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
|
||||
/* bring the sig status down */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
|
||||
/* send a BLA */
|
||||
@@ -1074,7 +1076,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
|
||||
/* bring the sig status up */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_UP;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
|
||||
/* send a uba */
|
||||
@@ -1090,7 +1092,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
|
||||
/* bring the sig status down */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
|
||||
/* send a blo */
|
||||
@@ -1108,7 +1110,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
|
||||
/* bring the sig status up */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_UP;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
|
||||
/* send a ubl */
|
||||
@@ -1147,7 +1149,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
|
||||
|
||||
/* bring the channel signaling status to down */
|
||||
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
|
||||
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
|
||||
ftdm_span_send_signal (ftdmchan->span, &sigev);
|
||||
|
||||
/* remove any reset flags */
|
||||
@@ -1520,9 +1522,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
|
||||
/* initalize the global gen_config flag */
|
||||
g_ftdm_sngss7_data.gen_config = 0;
|
||||
|
||||
/* min. number of digitis to wait for */
|
||||
g_ftdm_sngss7_data.min_digits = 7;
|
||||
|
||||
/* function trace initizalation */
|
||||
g_ftdm_sngss7_data.function_trace = 1;
|
||||
g_ftdm_sngss7_data.function_trace_level = 7;
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
/******************************************************************************/
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
#define MAX_NAME_LEN 10
|
||||
#define MAX_NAME_LEN 25
|
||||
#define MAX_PATH 255
|
||||
|
||||
#define MAX_CIC_LENGTH 5
|
||||
@@ -224,6 +224,7 @@ typedef struct sng_isup_intf {
|
||||
uint32_t isap;
|
||||
uint32_t clg_nadi;
|
||||
uint32_t cld_nadi;
|
||||
uint32_t min_digits;
|
||||
uint16_t t4;
|
||||
uint32_t t10;
|
||||
uint32_t t11;
|
||||
@@ -326,7 +327,6 @@ typedef struct sng_ss7_cfg {
|
||||
typedef struct ftdm_sngss7_data {
|
||||
sng_ss7_cfg_t cfg;
|
||||
int gen_config;
|
||||
int min_digits;
|
||||
int function_trace;
|
||||
int function_trace_level;
|
||||
int message_trace;
|
||||
|
||||
@@ -187,7 +187,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||
copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum);
|
||||
|
||||
/* check if the user would like a custom NADI value for the calling Pty Num */
|
||||
clg_nadi = ftdm_channel_get_var(ftdmchan, "ss7_clg_nadi");
|
||||
clg_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_nadi");
|
||||
if ((clg_nadi != NULL) && (*clg_nadi)) {
|
||||
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
|
||||
iam.cgPtyNum.natAddrInd.val = atoi(clg_nadi);
|
||||
@@ -196,7 +196,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||
SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLG, using \"%d\"\n", iam.cgPtyNum.natAddrInd.val);
|
||||
}
|
||||
|
||||
cld_nadi = ftdm_channel_get_var(ftdmchan, "ss7_cld_nadi");
|
||||
cld_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_nadi");
|
||||
if ((cld_nadi != NULL) && (*cld_nadi)) {
|
||||
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi);
|
||||
iam.cdPtyNum.natAddrInd.val = atoi(cld_nadi);
|
||||
@@ -206,7 +206,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||
}
|
||||
|
||||
/* check if the user would like us to send a clg_sub-address */
|
||||
clg_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_clg_subaddr");
|
||||
clg_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_subaddr");
|
||||
if ((clg_subAddr != NULL) && (*clg_subAddr)) {
|
||||
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr);
|
||||
|
||||
@@ -245,7 +245,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||
}
|
||||
|
||||
/* check if the user would like us to send a cld_sub-address */
|
||||
cld_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_cld_subaddr");
|
||||
cld_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_subaddr");
|
||||
if ((cld_subAddr != NULL) && (*cld_subAddr)) {
|
||||
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr);
|
||||
|
||||
@@ -298,7 +298,8 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||
iam.cgPtyNum.natAddrInd.val,
|
||||
ftdmchan->caller_data.dnis.digits,
|
||||
iam.cdPtyNum.natAddrInd.val);
|
||||
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -379,7 +380,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
|
||||
ADDRCMPLT);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -403,7 +404,7 @@ void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
|
||||
5);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -438,7 +439,7 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
|
||||
sngss7_info->circuit->cic,
|
||||
ftdmchan->caller_data.hangup_cause );
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -461,7 +462,7 @@ void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan)
|
||||
&rlc);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -482,7 +483,7 @@ void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan)
|
||||
NULL);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -503,7 +504,7 @@ void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan)
|
||||
NULL);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -524,7 +525,7 @@ void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan)
|
||||
NULL);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -545,7 +546,7 @@ void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan)
|
||||
NULL);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -567,7 +568,7 @@ ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
|
||||
NULL);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -588,7 +589,7 @@ void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan)
|
||||
NULL);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -609,7 +610,7 @@ void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan)
|
||||
NULL);
|
||||
|
||||
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic);
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -654,6 +655,7 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
|
||||
sngss7_info->circuit->cic,
|
||||
(sngss7_info->circuit->cic + sngss7_span->rx_grs.range));
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -686,7 +688,8 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
|
||||
sngss7_info->circuit->cic,
|
||||
sngss7_info->circuit->cic,
|
||||
(sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
|
||||
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -735,7 +738,7 @@ void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan)
|
||||
|
||||
/* clean out the saved data */
|
||||
memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t));
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -785,6 +788,7 @@ void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan)
|
||||
/* clean out the saved data */
|
||||
memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t));
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -835,6 +839,7 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan)
|
||||
/* clean out the saved data */
|
||||
memset(&sngss7_span->tx_cgb, 0x0, sizeof(sngss7_group_data_t));
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
@@ -885,6 +890,7 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)
|
||||
/* clean out the saved data */
|
||||
memset(&sngss7_span->tx_cgu, 0x0, sizeof(sngss7_group_data_t));
|
||||
|
||||
ftdm_call_clear_vars(&ftdmchan->caller_data);
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
|
||||
|
||||
if (!strcasecmp(var, "ch_map")) {
|
||||
/**********************************************************************/
|
||||
strcpy(isupCkt.ch_map, val);
|
||||
strncpy(isupCkt.ch_map, val, MAX_CIC_MAP_LENGTH-1);
|
||||
SS7_DEBUG("\tFound channel map \"%s\"\n", isupCkt.ch_map);
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(var, "typeCntrl")) {
|
||||
@@ -393,7 +393,7 @@ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset)
|
||||
for (i = 0; i < num_parms; i++) {
|
||||
/**********************************************************************/
|
||||
if (!strcasecmp(parm->var, "name")) {
|
||||
strcpy((char *)mtpLinkSet.name, parm->val);
|
||||
strncpy((char *)mtpLinkSet.name, parm->val, MAX_NAME_LEN-1);
|
||||
SS7_DEBUG("\tFound an \"mtp_linkset\" named = %s\n", mtpLinkSet.name);
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(parm->var, "apc")) {
|
||||
@@ -508,7 +508,7 @@ static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *
|
||||
/* try to match the parameter to what we expect */
|
||||
/**********************************************************************/
|
||||
if (!strcasecmp(parm->var, "name")) {
|
||||
strcpy((char *)mtpLink->name, parm->val);
|
||||
strncpy((char *)mtpLink->name, parm->val, MAX_NAME_LEN-1);
|
||||
SS7_DEBUG("\tFound an \"mtp_link\" named = %s\n", mtpLink->name);
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(parm->var, "span")) {
|
||||
@@ -827,7 +827,7 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
|
||||
/* try to match the parameter to what we expect */
|
||||
/**********************************************************************/
|
||||
if (!strcasecmp(parm->var, "name")) {
|
||||
strcpy((char *)mtpRoute.name, parm->val);
|
||||
strncpy((char *)mtpRoute.name, parm->val, MAX_NAME_LEN-1);
|
||||
SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtpRoute.name);
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(parm->var, "dpc")) {
|
||||
@@ -999,7 +999,7 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
|
||||
/* try to match the parameter to what we expect */
|
||||
/**********************************************************************/
|
||||
if (!strcasecmp(parm->var, "name")) {
|
||||
strcpy((char *)sng_isup.name, parm->val);
|
||||
strncpy((char *)sng_isup.name, parm->val, MAX_NAME_LEN-1);
|
||||
SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name);
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(parm->var, "spc")) {
|
||||
@@ -1047,6 +1047,11 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
|
||||
SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val);
|
||||
}
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(parm->var, "min_digits")) {
|
||||
sng_isup.min_digits = atoi(parm->val);
|
||||
|
||||
SS7_DEBUG("\tFound min_digits = %d\n", sng_isup.min_digits);
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(parm->var, "ssf")) {
|
||||
if (!strcasecmp(parm->val, "nat")) {
|
||||
sng_isup.ssf = SSF_NAT;
|
||||
@@ -1067,8 +1072,8 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(parm->var, "license")) {
|
||||
/**********************************************************************/
|
||||
strcpy(g_ftdm_sngss7_data.cfg.license, parm->val);
|
||||
strcpy(g_ftdm_sngss7_data.cfg.signature, parm->val);
|
||||
strncpy(g_ftdm_sngss7_data.cfg.license, parm->val, MAX_PATH-1);
|
||||
strncpy(g_ftdm_sngss7_data.cfg.signature, parm->val, MAX_PATH-1);
|
||||
strcat(g_ftdm_sngss7_data.cfg.signature, ".sig");
|
||||
SS7_DEBUG("\tFound license file = %s\n", g_ftdm_sngss7_data.cfg.license);
|
||||
SS7_DEBUG("\tFound signature file = %s\n", g_ftdm_sngss7_data.cfg.signature);
|
||||
@@ -1304,6 +1309,13 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
|
||||
sng_isup.clg_nadi = 0x03;
|
||||
}
|
||||
|
||||
/* check if the user requested min_digits value */
|
||||
if (sng_isup.min_digits == 0) {
|
||||
/* default to 7 */
|
||||
sng_isup.min_digits = 7;
|
||||
}
|
||||
|
||||
|
||||
/* trickle down the SPC to all sub entities */
|
||||
linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].linkSetId;
|
||||
|
||||
@@ -1359,7 +1371,7 @@ static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink)
|
||||
}
|
||||
|
||||
/* fill in the information */
|
||||
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name);
|
||||
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name, MAX_NAME_LEN-1);
|
||||
|
||||
g_ftdm_sngss7_data.cfg.mtpLink[i].id = mtpLink->id;
|
||||
|
||||
@@ -1521,7 +1533,7 @@ static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet)
|
||||
{
|
||||
int i = mtpLinkSet->id;
|
||||
|
||||
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name);
|
||||
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name, MAX_NAME_LEN-1);
|
||||
|
||||
g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id = mtpLinkSet->id;
|
||||
g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc = mtpLinkSet->apc;
|
||||
@@ -1559,7 +1571,7 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
|
||||
SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id);
|
||||
}
|
||||
|
||||
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name);
|
||||
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name, MAX_NAME_LEN-1);
|
||||
|
||||
g_ftdm_sngss7_data.cfg.mtpRoute[i].id = mtp3_route->id;
|
||||
g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc = mtp3_route->dpc;
|
||||
@@ -1693,7 +1705,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
|
||||
SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id);
|
||||
}
|
||||
|
||||
strcpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name);
|
||||
strncpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name, MAX_NAME_LEN-1);
|
||||
|
||||
g_ftdm_sngss7_data.cfg.isupIntf[i].id = sng_isup->id;
|
||||
g_ftdm_sngss7_data.cfg.isupIntf[i].mtpRouteId = sng_isup->mtpRouteId;
|
||||
@@ -1705,6 +1717,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
|
||||
g_ftdm_sngss7_data.cfg.isupIntf[i].isap = sng_isup->isap;
|
||||
g_ftdm_sngss7_data.cfg.isupIntf[i].cld_nadi = sng_isup->cld_nadi;
|
||||
g_ftdm_sngss7_data.cfg.isupIntf[i].clg_nadi = sng_isup->clg_nadi;
|
||||
g_ftdm_sngss7_data.cfg.isupIntf[i].min_digits = sng_isup->min_digits;
|
||||
g_ftdm_sngss7_data.cfg.isupIntf[i].options = sng_isup->options;
|
||||
if (sng_isup->t4 != 0) {
|
||||
g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = sng_isup->t4;
|
||||
@@ -1976,7 +1989,7 @@ static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, i
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route");
|
||||
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route", MAX_NAME_LEN-1);
|
||||
|
||||
g_ftdm_sngss7_data.cfg.mtpRoute[0].id = 0;
|
||||
g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc = spc;
|
||||
@@ -2230,7 +2243,7 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
|
||||
int lower;
|
||||
int upper;
|
||||
char tmp[5]; /*KONRAD FIX ME*/
|
||||
char new_ch_map[MAX_CIC_LENGTH];
|
||||
char new_ch_map[MAX_CIC_MAP_LENGTH];
|
||||
|
||||
memset(&tmp[0], '\0', sizeof(tmp));
|
||||
memset(&new_ch_map[0], '\0', sizeof(new_ch_map));
|
||||
@@ -2337,7 +2350,9 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
|
||||
/* the the rest of ch_map to new_ch_map */
|
||||
strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x]));
|
||||
|
||||
|
||||
/* set the new cic map to ch_map*/
|
||||
memset(ch_map, '\0', sizeof(ch_map));
|
||||
strcpy(ch_map, new_ch_map);
|
||||
|
||||
} else if (ch_map[x] == ',') {
|
||||
@@ -2345,16 +2360,21 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
|
||||
x++;
|
||||
|
||||
/* copy the rest of the list to new_ch_map */
|
||||
memset(new_ch_map, '\0', sizeof(new_ch_map));
|
||||
strcpy(new_ch_map, &ch_map[x]);
|
||||
|
||||
/* copy the new_ch_map over the old one */
|
||||
memset(ch_map, '\0', sizeof(ch_map));
|
||||
strcpy(ch_map, new_ch_map);
|
||||
|
||||
} else if (ch_map[x] == '\0') {
|
||||
|
||||
/* we're at the end of the string...copy the rest of the list to new_ch_map */
|
||||
memset(new_ch_map, '\0', sizeof(new_ch_map));
|
||||
strcpy(new_ch_map, &ch_map[x]);
|
||||
|
||||
/* set the new cic map to ch_map*/
|
||||
memset(ch_map, '\0', sizeof(ch_map));
|
||||
strcpy(ch_map, new_ch_map);
|
||||
} else {
|
||||
/* nothing to do */
|
||||
|
||||
@@ -811,13 +811,14 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t
|
||||
ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
|
||||
}
|
||||
|
||||
if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_number_of_frames_in_queue) {
|
||||
ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
|
||||
if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_tx_idle_packets) {
|
||||
/* HDLC channels do not always transmit, so its ok for drivers to fill with idle
|
||||
* also do not report idle warning when we just started transmitting */
|
||||
if (ftdmchan->iostats.tx.packets && FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle: %d\n", ftdmchan->iostats.tx.idle_packets);
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle changed from %d to %d\n",
|
||||
ftdmchan->iostats.tx.idle_packets, tx_stats->wp_api_tx_hdr_tx_idle_packets);
|
||||
}
|
||||
ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
|
||||
}
|
||||
|
||||
if (!ftdmchan->iostats.tx.packets) {
|
||||
@@ -941,7 +942,6 @@ static FIO_WRITE_FUNCTION(wanpipe_write)
|
||||
{
|
||||
int bsent = 0;
|
||||
int err = 0;
|
||||
ftdm_time_t ms = 0;
|
||||
wp_tdm_api_tx_hdr_t hdrframe;
|
||||
|
||||
/* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
|
||||
@@ -1051,16 +1051,34 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
|
||||
|
||||
for(i = 1; i <= span->chan_count; i++) {
|
||||
ftdm_channel_t *ftdmchan = span->channels[i];
|
||||
uint32_t chan_events = 0;
|
||||
|
||||
/* translate events from ftdm to libsnagoma. if the user don't specify which events to poll the
|
||||
* channel for, we just use SANG_WAIT_OBJ_HAS_EVENTS */
|
||||
if (poll_events) {
|
||||
if (poll_events[j] & FTDM_READ) {
|
||||
chan_events = SANG_WAIT_OBJ_HAS_INPUT;
|
||||
}
|
||||
if (poll_events[j] & FTDM_WRITE) {
|
||||
chan_events |= SANG_WAIT_OBJ_HAS_OUTPUT;
|
||||
}
|
||||
if (poll_events[j] & FTDM_EVENTS) {
|
||||
chan_events |= SANG_WAIT_OBJ_HAS_EVENTS;
|
||||
}
|
||||
} else {
|
||||
chan_events = SANG_WAIT_OBJ_HAS_EVENTS;
|
||||
}
|
||||
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
if (!ftdmchan->io_data) {
|
||||
continue; /* should never happen but happens when shutting down */
|
||||
}
|
||||
pfds[j] = ftdmchan->io_data;
|
||||
inflags[j] = poll_events ? poll_events[j] : POLLPRI;
|
||||
inflags[j] = chan_events;
|
||||
#else
|
||||
memset(&pfds[j], 0, sizeof(pfds[j]));
|
||||
pfds[j].fd = span->channels[i]->sockfd;
|
||||
pfds[j].events = poll_events ? poll_events[j] : POLLPRI;
|
||||
pfds[j].events = chan_events;
|
||||
#endif
|
||||
|
||||
/* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */
|
||||
|
||||
@@ -31,10 +31,14 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "private/ftdm_core.h"
|
||||
#include "ftmod_zt.h"
|
||||
|
||||
/* used by dahdi to indicate there is no data available, but events to read */
|
||||
#ifndef ELAST
|
||||
#define ELAST 500
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Zaptel globals
|
||||
*/
|
||||
@@ -48,42 +52,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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1183,7 +1193,6 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
|
||||
}
|
||||
|
||||
return FTDM_FAIL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1202,12 +1211,19 @@ static FIO_READ_FUNCTION(zt_read)
|
||||
if ((r = read(ftdmchan->sockfd, data, *datalen)) > 0) {
|
||||
break;
|
||||
}
|
||||
ftdm_sleep(10);
|
||||
if (r == 0) {
|
||||
errs--;
|
||||
else if (r == 0) {
|
||||
ftdm_sleep(10);
|
||||
if (errs) errs--;
|
||||
}
|
||||
else {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
if (errno == ELAST)
|
||||
break;
|
||||
|
||||
ftdm_log(FTDM_LOG_ERROR, "read failed: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
if (r > 0) {
|
||||
*datalen = r;
|
||||
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
|
||||
@@ -1215,7 +1231,9 @@ static FIO_READ_FUNCTION(zt_read)
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
else if (errno == ELAST) {
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
return r == 0 ? FTDM_TIMEOUT : FTDM_FAIL;
|
||||
}
|
||||
|
||||
@@ -1236,6 +1254,7 @@ static FIO_WRITE_FUNCTION(zt_write)
|
||||
bytes += 2;
|
||||
}
|
||||
|
||||
tryagain:
|
||||
w = write(ftdmchan->sockfd, data, bytes);
|
||||
|
||||
if (w >= 0) {
|
||||
@@ -1243,6 +1262,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -265,13 +267,32 @@ 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 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 */
|
||||
@@ -280,18 +301,25 @@ 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 */
|
||||
uint32_t raw_data_len; /*!< Raw data length */
|
||||
/* these 2 are undocumented right now, only used by boost: */
|
||||
/* bearer capability */
|
||||
ftdm_bearer_cap_t bearer_capability;
|
||||
/* user information layer 1 protocol */
|
||||
ftdm_user_layer1_prot_t bearer_layer1;
|
||||
ftdm_calling_party_category_t cpc; /*!< Calling party category */
|
||||
ftdm_variable_container_t variables; /*!< Variables attached to this call */
|
||||
/* We need call_id inside caller_data for the user to be able to retrieve
|
||||
* the call_id when ftdm_channel_call_place is called. This is the only time
|
||||
* that the user can use caller_data.call_id to obtain the call_id. The user
|
||||
* should use the call_id from sigmsg otherwise */
|
||||
uint32_t call_id; /*!< Unique call ID for this call */
|
||||
} ftdm_caller_data_t;
|
||||
|
||||
/*! \brief Tone type */
|
||||
@@ -306,7 +334,8 @@ typedef enum {
|
||||
FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */
|
||||
FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */
|
||||
FTDM_SIGEVENT_FLASH, /*!< Flash event (typically on-hook/off-hook for analog devices) */
|
||||
FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got a response */
|
||||
FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got a response */
|
||||
FTDM_SIGEVENT_RINGING, /*!< Remote side is in ringing state */
|
||||
FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */
|
||||
FTDM_SIGEVENT_PROGRESS_MEDIA, /*!< Outgoing call is making progress and there is media available */
|
||||
FTDM_SIGEVENT_ALARM_TRAP, /*!< Hardware alarm ON */
|
||||
@@ -316,12 +345,14 @@ typedef enum {
|
||||
FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */
|
||||
FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */
|
||||
FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */
|
||||
FTDM_SIGEVENT_MSG, /*!< We received an in-call msg */
|
||||
FTDM_SIGEVENT_INVALID
|
||||
FTDM_SIGEVENT_FACILITY, /*!< In call facility event */
|
||||
FTDM_SIGEVENT_TRACE, /*!<Interpreted trace event */
|
||||
FTDM_SIGEVENT_TRACE_RAW, /*!<Raw trace event */
|
||||
FTDM_SIGEVENT_INVALID, /*!<Invalid */
|
||||
} ftdm_signal_event_t;
|
||||
#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "PROGRESS", \
|
||||
#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "RINGING", "PROGRESS", \
|
||||
"PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \
|
||||
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "MSG", "INVALID"
|
||||
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "FACILITY", "TRACE", "TRACE_RAW", "INVALID"
|
||||
|
||||
/*! \brief Move from string to ftdm_signal_event_t and viceversa */
|
||||
FTDM_STR2ENUM_P(ftdm_str2ftdm_signal_event, ftdm_signal_event2str, ftdm_signal_event_t)
|
||||
@@ -356,6 +387,7 @@ typedef struct ftdm_channel_config {
|
||||
|
||||
/*!
|
||||
\brief Signaling status on a given span or specific channel on protocols that support it
|
||||
\note see docs/sigstatus.txt for more extensive documentation on signaling status
|
||||
*/
|
||||
typedef enum {
|
||||
/* The signaling link is down (no d-chans up in the span/group, MFC-R2 bit pattern unidentified) */
|
||||
@@ -372,15 +404,52 @@ typedef enum {
|
||||
/*! \brief Move from string to ftdm_signaling_status_t and viceversa */
|
||||
FTDM_STR2ENUM_P(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t)
|
||||
|
||||
|
||||
typedef struct {
|
||||
ftdm_signaling_status_t status;
|
||||
} ftdm_event_sigstatus_t;
|
||||
|
||||
typedef enum {
|
||||
/* This is an received frame */
|
||||
FTDM_TRACE_INCOMING,
|
||||
/* This is a transmitted frame */
|
||||
FTDM_TRACE_OUTGOING,
|
||||
/* Invalid */
|
||||
FTDM_TRACE_INVALID,
|
||||
} ftdm_trace_dir_t;
|
||||
#define TRACE_DIR_STRINGS "INCOMING", "OUTGOING", "INVALID"
|
||||
|
||||
/*! \brief Move string to ftdm_trace_dir_t and viceversa */
|
||||
FTDM_STR2ENUM_P(ftdm_str2ftdm_trace_dir, ftdm_trace_dir2str, ftdm_trace_dir_t)
|
||||
|
||||
typedef struct {
|
||||
/* Direction - incoming or outgoing */
|
||||
ftdm_trace_dir_t dir;
|
||||
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 */
|
||||
ftdm_signaling_status_t sigstatus; /*!< Signaling status (valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED) */
|
||||
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
|
||||
@@ -507,6 +576,7 @@ struct ftdm_memory_handler {
|
||||
* You don't need these unless your implementing an I/O interface module (most users don't) */
|
||||
#define FIO_CHANNEL_REQUEST_ARGS (ftdm_span_t *span, uint32_t chan_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
|
||||
#define FIO_CHANNEL_OUTGOING_CALL_ARGS (ftdm_channel_t *ftdmchan)
|
||||
#define FIO_CHANNEL_SEND_MSG_ARGS (ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg)
|
||||
#define FIO_CHANNEL_SET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
|
||||
#define FIO_CHANNEL_GET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *status)
|
||||
#define FIO_SPAN_SET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t status)
|
||||
@@ -539,6 +609,7 @@ struct ftdm_memory_handler {
|
||||
* You don't need these unless your implementing an I/O interface module (most users don't) */
|
||||
typedef ftdm_status_t (*fio_channel_request_t) FIO_CHANNEL_REQUEST_ARGS ;
|
||||
typedef ftdm_status_t (*fio_channel_outgoing_call_t) FIO_CHANNEL_OUTGOING_CALL_ARGS ;
|
||||
typedef ftdm_status_t (*fio_channel_send_msg_t) FIO_CHANNEL_SEND_MSG_ARGS;
|
||||
typedef ftdm_status_t (*fio_channel_set_sig_status_t) FIO_CHANNEL_SET_SIG_STATUS_ARGS;
|
||||
typedef ftdm_status_t (*fio_channel_get_sig_status_t) FIO_CHANNEL_GET_SIG_STATUS_ARGS;
|
||||
typedef ftdm_status_t (*fio_span_set_sig_status_t) FIO_SPAN_SET_SIG_STATUS_ARGS;
|
||||
@@ -572,6 +643,7 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ;
|
||||
* You don't need these unless your implementing an I/O interface module (most users don't) */
|
||||
#define FIO_CHANNEL_REQUEST_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_REQUEST_ARGS
|
||||
#define FIO_CHANNEL_OUTGOING_CALL_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_OUTGOING_CALL_ARGS
|
||||
#define FIO_CHANNEL_SEND_MSG_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_SEND_MSG_ARGS
|
||||
#define FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_SET_SIG_STATUS_ARGS
|
||||
#define FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_GET_SIG_STATUS_ARGS
|
||||
#define FIO_SPAN_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_SET_SIG_STATUS_ARGS
|
||||
@@ -654,6 +726,14 @@ typedef enum {
|
||||
/*! \brief Override the default queue handler */
|
||||
FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *handler);
|
||||
|
||||
/*! \brief Return the availability rate for a channel
|
||||
* \param ftdmchan Channel to get the availability from
|
||||
*
|
||||
* \retval > 0 if availability is supported
|
||||
* \retval -1 if availability is not supported
|
||||
*/
|
||||
FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan);
|
||||
|
||||
/*! \brief Answer call */
|
||||
#define ftdm_channel_call_answer(ftdmchan) _ftdm_channel_call_answer(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
|
||||
|
||||
@@ -672,6 +752,12 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char
|
||||
/*! \brief Indicate a new condition in an incoming call recording the source code point where it was called (see ftdm_channel_call_indicate for an easy to use macro) */
|
||||
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);
|
||||
|
||||
/*! \brief Send a message on a call */
|
||||
#define ftdm_channel_call_send_msg(ftdmchan, sigmsg) _ftdm_channel_call_send_msg(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (sigmsg))
|
||||
|
||||
/*! \brief Send a signal on a call recording the source code point where it was called (see ftdm_channel_call_send_msg for an easy to use macro) */
|
||||
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_send_msg(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg);
|
||||
|
||||
/*! \brief Hangup the call without cause */
|
||||
#define ftdm_channel_call_hangup(ftdmchan) _ftdm_channel_call_hangup(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
|
||||
|
||||
@@ -684,6 +770,14 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char
|
||||
/*! \brief Hangup the call with cause recording the source code point where it was called (see ftdm_channel_call_hangup_with_cause for an easy to use macro) */
|
||||
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t);
|
||||
|
||||
/*! \brief Reset the channel */
|
||||
#define ftdm_channel_reset(ftdmchan) _ftdm_channel_reset(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
|
||||
|
||||
/*! \brief Reset the channel (see _ftdm_channel_reset for an easy to use macro)
|
||||
* \note if there was a call on this channel, call will be cleared without any notifications to the user
|
||||
*/
|
||||
FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan);
|
||||
|
||||
/*! \brief Put a call on hold (if supported by the signaling stack) */
|
||||
#define ftdm_channel_call_hold(ftdmchan) _ftdm_channel_call_hold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
|
||||
|
||||
@@ -723,6 +817,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_set_sig_status(ftdm_span_t *span, ftdm_signa
|
||||
/*! \brief Get span signaling status (ie: whether protocol layer is up or down) */
|
||||
FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signaling_status_t *status);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Set user private data in the channel
|
||||
*
|
||||
@@ -1128,6 +1223,45 @@ FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter);
|
||||
*/
|
||||
FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter);
|
||||
|
||||
/*! \brief Add a custom variable to the call
|
||||
* \note This variables may be used by signaling modules to override signaling parameters
|
||||
* \todo Document which signaling variables are available
|
||||
* */
|
||||
FT_DECLARE(ftdm_status_t) ftdm_call_add_var(ftdm_caller_data_t *caller_data, const char *var_name, const char *value);
|
||||
|
||||
/*! \brief Get a custom variable from the call.
|
||||
* \note The variable pointer returned is only valid during the callback receiving SIGEVENT. */
|
||||
FT_DECLARE(const char *) ftdm_call_get_var(ftdm_caller_data_t *caller_data, const char *var_name);
|
||||
|
||||
/*! \brief Get an iterator to iterate over the channel variables
|
||||
* \param caller_data The signal msg structure containing the variables
|
||||
* \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator.
|
||||
* \note The iterator pointer returned is only valid while the signal message and it'll be destroyed when the signal message is processed.
|
||||
* This iterator is completely non-thread safe, if you are adding variables or removing variables while iterating
|
||||
* results are unpredictable
|
||||
*/
|
||||
FT_DECLARE(ftdm_iterator_t *) ftdm_call_get_var_iterator(const ftdm_caller_data_t *caller_data, ftdm_iterator_t *iter);
|
||||
|
||||
/*! \brief Get variable name and value for the current iterator position */
|
||||
FT_DECLARE(ftdm_status_t) ftdm_call_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val);
|
||||
|
||||
/*! \brief Clear all variables attached to the call
|
||||
* \note Variables are cleared at the end of each call back, so it is not necessary for the user to call this function.
|
||||
* \todo Document which signaling variables are available
|
||||
* */
|
||||
FT_DECLARE(ftdm_status_t) ftdm_call_clear_vars(ftdm_caller_data_t *caller_data);
|
||||
|
||||
/*! \brief Remove a variable attached to the call
|
||||
* \note Removes a variable that was attached to the call.
|
||||
* \todo Document which call variables are available
|
||||
* */
|
||||
FT_DECLARE(ftdm_status_t) ftdm_call_remove_var(ftdm_caller_data_t *caller_data, const char *var_name);
|
||||
|
||||
/*! \brief Clears all the temporary data attached to this call
|
||||
* \note Clears caller_data->variables and caller_data->raw_data.
|
||||
* */
|
||||
FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data);
|
||||
|
||||
/*! \brief Get the span pointer associated to the channel */
|
||||
FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan);
|
||||
|
||||
|
||||
@@ -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 <moy@sangoma.com>
|
||||
* Ricardo Barroetaveña <rbarroetavena@anura.com.ar>
|
||||
*
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
|
||||
|
||||
@@ -158,12 +158,16 @@ typedef __int64 int64_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int8 int8_t;
|
||||
#define FTDM_O_BINARY O_BINARY
|
||||
#define FTDM_SIZE_FMT "Id"
|
||||
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
|
||||
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
|
||||
#else
|
||||
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
|
||||
#endif /* _MSC_VER */
|
||||
#else /* __WINDOWS__ */
|
||||
#define FTDM_O_BINARY 0
|
||||
#define FTDM_SIZE_FMT "zd"
|
||||
#define FTDM_INVALID_SOCKET -1
|
||||
typedef int ftdm_socket_t;
|
||||
#include <stdio.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 <string.h>
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -503,6 +504,7 @@ struct ftdm_span {
|
||||
teletone_multi_tone_t tone_finder[FTDM_TONEMAP_INVALID+1];
|
||||
ftdm_channel_t *channels[FTDM_MAX_CHANNELS_SPAN+1];
|
||||
fio_channel_outgoing_call_t outgoing_call;
|
||||
fio_channel_send_msg_t send_msg;
|
||||
fio_channel_set_sig_status_t set_channel_sig_status;
|
||||
fio_channel_get_sig_status_t get_channel_sig_status;
|
||||
fio_span_set_sig_status_t set_span_sig_status;
|
||||
@@ -598,7 +600,6 @@ FT_DECLARE(void) ftdm_channel_rotate_tokens(ftdm_channel_t *ftdmchan);
|
||||
FT_DECLARE(int) ftdm_load_module(const char *name);
|
||||
FT_DECLARE(int) ftdm_load_module_assume(const char *name);
|
||||
FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap);
|
||||
FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan);
|
||||
|
||||
FT_DECLARE(ftdm_status_t) ftdm_span_close_all(void);
|
||||
FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan);
|
||||
|
||||
@@ -184,6 +184,9 @@ typedef enum {
|
||||
FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10),
|
||||
/* If this flag is set, channel will be moved to proceed state when calls goes to routing */
|
||||
FTDM_SPAN_USE_PROCEED_STATE = (1 << 11),
|
||||
/* If this flag is set, the signalling module supports jumping directly to state up, without
|
||||
going through PROGRESS/PROGRESS_MEDIA */
|
||||
FTDM_SPAN_USE_SKIP_STATES = (1 << 12),
|
||||
} ftdm_span_flag_t;
|
||||
|
||||
/*! \brief Channel supported features */
|
||||
@@ -225,60 +228,50 @@ typedef enum {
|
||||
FTDM_CHANNEL_STATE_HANGUP,
|
||||
FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
|
||||
FTDM_CHANNEL_STATE_IN_LOOP,
|
||||
FTDM_CHANNEL_STATE_RESET,
|
||||
FTDM_CHANNEL_STATE_INVALID
|
||||
} ftdm_channel_state_t;
|
||||
#define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \
|
||||
"RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
|
||||
"RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
|
||||
"HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "INVALID"
|
||||
"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, 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 (1ULL << 32)
|
||||
|
||||
typedef enum {
|
||||
ZSM_NONE,
|
||||
|
||||
@@ -48,12 +48,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef __linux__
|
||||
#ifndef __USE_BSD
|
||||
#define __USE_BSD
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "freetdm.h"
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -39,8 +39,9 @@
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
@INSERT_MATH_HEADER@
|
||||
#if !defined(SPANDSP_NO_TIFF)
|
||||
#include <tiffio.h>
|
||||
|
||||
#endif
|
||||
#include <spandsp/telephony.h>
|
||||
#include <spandsp/fast_convert.h>
|
||||
#include <spandsp/logging.h>
|
||||
|
||||
+667
-106
@@ -27,58 +27,162 @@
|
||||
*/
|
||||
#include "stfu.h"
|
||||
|
||||
//#define DB_JB 1
|
||||
|
||||
#ifndef UINT_MAX
|
||||
# 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)
|
||||
/* 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)
|
||||
|
||||
static int stfu_log_level = 7;
|
||||
|
||||
struct stfu_queue {
|
||||
struct stfu_frame *array;
|
||||
struct stfu_frame int_frame;
|
||||
uint32_t real_array_size;
|
||||
uint32_t array_size;
|
||||
uint32_t array_len;
|
||||
uint32_t wr_len;
|
||||
uint32_t last_index;
|
||||
int32_t last_jitter;
|
||||
};
|
||||
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 last_wr_ts;
|
||||
uint32_t last_rd_ts;
|
||||
uint32_t interval;
|
||||
uint32_t samples_per_packet;
|
||||
uint32_t samples_per_second;
|
||||
uint32_t miss_count;
|
||||
uint32_t max_plc;
|
||||
uint32_t qlen;
|
||||
uint32_t max_qlen;
|
||||
uint32_t orig_qlen;
|
||||
uint32_t packet_count;
|
||||
uint32_t consecutive_good_count;
|
||||
uint32_t consecutive_bad_count;
|
||||
uint32_t period_good_count;
|
||||
uint32_t period_bad_count;
|
||||
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;
|
||||
|
||||
uint32_t session_clean_count;
|
||||
uint32_t session_missing_count;
|
||||
|
||||
uint32_t session_packet_in_count;
|
||||
uint32_t session_packet_out_count;
|
||||
|
||||
uint32_t sync_out;
|
||||
uint32_t sync_in;
|
||||
|
||||
|
||||
int32_t ts_diff;
|
||||
int32_t last_ts_diff;
|
||||
int32_t same_ts;
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned char *m;
|
||||
|
||||
if (qlen <= queue->array_size) {
|
||||
return STFU_IT_FAILED;;
|
||||
if (qlen <= queue->real_array_size) {
|
||||
queue->array_size = qlen;
|
||||
if (queue->array_len > qlen) {
|
||||
queue->array_len = qlen;
|
||||
}
|
||||
} else {
|
||||
m = realloc(queue->array, qlen * sizeof(struct stfu_frame));
|
||||
assert(m);
|
||||
memset(m + queue->array_size * sizeof(struct stfu_frame), 0, (qlen * sizeof(struct stfu_frame)) - (queue->array_size * sizeof(struct stfu_frame)));
|
||||
queue->array = (struct stfu_frame *) m;
|
||||
queue->real_array_size = queue->array_size = qlen;
|
||||
}
|
||||
|
||||
m = realloc(queue->array, qlen * sizeof(struct stfu_frame));
|
||||
assert(m);
|
||||
memset(m + queue->array_size, 0, qlen * sizeof(struct stfu_frame) - queue->array_size);
|
||||
queue->array = (struct stfu_frame *) m;
|
||||
queue->array_size = qlen;
|
||||
return STFU_IT_WORKED;
|
||||
}
|
||||
|
||||
static void stfu_n_init_aqueue(stfu_queue_t *queue, uint32_t qlen)
|
||||
{
|
||||
|
||||
queue->array = calloc(qlen, sizeof(struct stfu_frame));
|
||||
assert(queue->array != NULL);
|
||||
memset(queue->array, 0, sizeof(struct stfu_frame) * qlen);
|
||||
queue->array_size = qlen;
|
||||
queue->real_array_size = queue->array_size = qlen;
|
||||
queue->int_frame.plc = 1;
|
||||
memset(queue->int_frame.data, 255, sizeof(queue->int_frame.data));
|
||||
}
|
||||
|
||||
|
||||
void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata)
|
||||
{
|
||||
i->callback = callback;
|
||||
i->udata = udata;
|
||||
}
|
||||
|
||||
void stfu_n_destroy(stfu_instance_t **i)
|
||||
@@ -88,33 +192,66 @@ 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);
|
||||
r->in_len = i->in_queue->array_len;
|
||||
r->in_size = i->in_queue->array_size;
|
||||
r->out_len = i->out_queue->array_len;
|
||||
r->out_size = i->out_queue->array_size;
|
||||
r->qlen = i->qlen;
|
||||
r->packet_in_count = i->period_packet_in_count;
|
||||
r->clean_count = i->period_clean_count;
|
||||
r->consecutive_good_count = i->consecutive_good_count;
|
||||
r->consecutive_bad_count = i->consecutive_bad_count;
|
||||
}
|
||||
|
||||
stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen)
|
||||
{
|
||||
stfu_status_t s;
|
||||
|
||||
if (i->qlen == i->max_qlen) {
|
||||
return STFU_IT_FAILED;
|
||||
}
|
||||
|
||||
if (i->max_qlen && qlen > i->max_qlen) {
|
||||
if (i->qlen < i->max_qlen) {
|
||||
qlen = i->max_qlen;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc)
|
||||
stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second)
|
||||
{
|
||||
struct stfu_instance *i;
|
||||
|
||||
@@ -123,116 +260,259 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc)
|
||||
return NULL;
|
||||
}
|
||||
memset(i, 0, sizeof(*i));
|
||||
|
||||
i->qlen = qlen;
|
||||
i->max_qlen = max_qlen;
|
||||
i->orig_qlen = qlen;
|
||||
i->samples_per_packet = samples_per_packet;
|
||||
|
||||
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;
|
||||
|
||||
if (max_plc) {
|
||||
i->max_plc = max_plc;
|
||||
} else {
|
||||
i->max_plc = qlen / 2;
|
||||
}
|
||||
i->samples_per_second = samples_per_second ? samples_per_second : 8000;
|
||||
|
||||
i->period_time = ((i->samples_per_second * 20) / i->samples_per_packet);
|
||||
i->decrement_time = ((i->samples_per_second * 15) / i->samples_per_packet);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void stfu_n_reset_counters(stfu_instance_t *i)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
i->consecutive_good_count = 0;
|
||||
i->consecutive_bad_count = 0;
|
||||
i->period_good_count = 0;
|
||||
i->period_clean_count = 0;
|
||||
i->period_bad_count = 0;
|
||||
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)
|
||||
{
|
||||
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->miss_count = 0;
|
||||
i->in_queue->last_jitter = 0;
|
||||
i->out_queue->last_jitter = 0;
|
||||
|
||||
|
||||
stfu_n_reset_counters(i);
|
||||
stfu_n_sync(i, 1);
|
||||
|
||||
i->cur_ts = 0;
|
||||
i->last_wr_ts = 0;
|
||||
i->miss_count = 0;
|
||||
i->interval = 0;
|
||||
i->last_rd_ts = 0;
|
||||
i->miss_count = 0;
|
||||
i->packet_count = 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int32_t stfu_n_measure_interval(stfu_queue_t *queue)
|
||||
stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets)
|
||||
{
|
||||
uint32_t index;
|
||||
int32_t d, most = 0, last = 0, this, track[STFU_MAX_TRACK] = {0};
|
||||
|
||||
for(index = 0; index < queue->array_len; index++) {
|
||||
this = queue->array[index].ts;
|
||||
if (last) {
|
||||
if (packets > i->qlen) {
|
||||
stfu_n_reset(i);
|
||||
} else {
|
||||
i->sync_out = packets;
|
||||
i->sync_in = packets;
|
||||
}
|
||||
|
||||
if ((d = this - last) > 0 && d / 10 < STFU_MAX_TRACK) {
|
||||
track[(d/10)]++;
|
||||
}
|
||||
}
|
||||
|
||||
last = this;
|
||||
}
|
||||
|
||||
for(index = 0; index < STFU_MAX_TRACK; index++) {
|
||||
if (track[index] > track[most]) {
|
||||
most = index;
|
||||
}
|
||||
}
|
||||
|
||||
return most * 10;
|
||||
return STFU_IT_WORKED;
|
||||
}
|
||||
|
||||
static int16_t stfu_n_process(stfu_instance_t *i, stfu_queue_t *queue)
|
||||
{
|
||||
if (!i->interval && !(i->interval = stfu_n_measure_interval(queue))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
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;
|
||||
uint32_t index = 0;
|
||||
stfu_frame_t *frame;
|
||||
size_t cplen = 0;
|
||||
int good_ts = 0;
|
||||
|
||||
if (!i->samples_per_packet && ts && i->last_rd_ts) {
|
||||
i->ts_diff = ts - i->last_rd_ts;
|
||||
|
||||
if (i->last_ts_diff == i->ts_diff) {
|
||||
if (++i->same_ts == 5) {
|
||||
i->samples_per_packet = i->ts_diff;
|
||||
}
|
||||
} else {
|
||||
i->same_ts = 0;
|
||||
}
|
||||
|
||||
i->last_ts_diff = i->ts_diff;
|
||||
|
||||
if (!i->samples_per_packet) {
|
||||
i->last_rd_ts = ts;
|
||||
return STFU_IT_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
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))) {
|
||||
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++;
|
||||
}
|
||||
return STFU_ITS_TOO_LATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (good_ts) {
|
||||
i->period_clean_count++;
|
||||
i->session_clean_count++;
|
||||
}
|
||||
|
||||
i->period_packet_in_count++;
|
||||
i->session_packet_in_count++;
|
||||
|
||||
i->period_need_range_avg = i->period_need_range / least1(i->period_missing_count);
|
||||
|
||||
if (i->period_missing_count > i->qlen * 2) {
|
||||
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 {
|
||||
if (i->qlen > i->orig_qlen && (i->consecutive_good_count > i->decrement_time || i->period_clean_count > i->decrement_time)) {
|
||||
stfu_n_resize(i, i->qlen - 1);
|
||||
stfu_n_reset_counters(i);
|
||||
stfu_n_sync(i, i->qlen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
stfu_n_resize(i, i->qlen - 1);
|
||||
stfu_n_sync(i, i->qlen);
|
||||
}
|
||||
|
||||
stfu_n_reset_counters(i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
if (i->out_queue->wr_len < i->out_queue->array_len) {
|
||||
return STFU_IT_FAILED;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (stfu_n_process(i, i->out_queue) < 0) {
|
||||
if (i->in_queue->array_len == i->in_queue->array_size && i->out_queue->array_len == i->out_queue->array_size) {
|
||||
stfu_n_resize(i, i->out_queue->array_size * 2);
|
||||
}
|
||||
//return STFU_IT_FAILED;
|
||||
}
|
||||
for(index = 0; index < i->out_queue->array_len; index++) {
|
||||
i->out_queue->array[index].was_read = 0;
|
||||
}
|
||||
}
|
||||
stfu_n_swap(i);
|
||||
}
|
||||
|
||||
if (last) {
|
||||
return STFU_IM_DONE;
|
||||
}
|
||||
|
||||
index = 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_rd_ts = ts;
|
||||
i->packet_count++;
|
||||
|
||||
memcpy(frame->data, data, cplen);
|
||||
|
||||
frame->pt = pt;
|
||||
frame->ts = ts;
|
||||
frame->dlen = cplen;
|
||||
@@ -241,23 +521,51 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void
|
||||
return STFU_IT_WORKED;
|
||||
}
|
||||
|
||||
static int stfu_n_find_frame(stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame, uint32_t *index)
|
||||
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;
|
||||
|
||||
assert(r_frame);
|
||||
assert(index);
|
||||
|
||||
*r_frame = NULL;
|
||||
|
||||
for(i = 0; i < queue->array_len; i++) {
|
||||
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, 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) {
|
||||
*r_frame = frame;
|
||||
*index = i;
|
||||
frame->was_read = 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -267,47 +575,300 @@ static int stfu_n_find_frame(stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_
|
||||
|
||||
stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
|
||||
{
|
||||
uint32_t index;
|
||||
stfu_frame_t *rframe = NULL;
|
||||
|
||||
if (((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) {
|
||||
return NULL;
|
||||
}
|
||||
int found = 0;
|
||||
|
||||
if (i->cur_ts == 0) {
|
||||
i->cur_ts = i->out_queue->array[0].ts;
|
||||
} else {
|
||||
i->cur_ts += i->interval;
|
||||
if (!i->samples_per_packet) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!i->ready) {
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s XXXSKIP\n", i->name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (stfu_n_find_frame(i->out_queue, i->cur_ts, &rframe, &index) || stfu_n_find_frame(i->in_queue, i->cur_ts, &rframe, &index)) {
|
||||
|
||||
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_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 (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 (!i->cur_ts) {
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s NO TS\n", i->name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (!found && i->samples_per_packet) {
|
||||
uint32_t y;
|
||||
stfu_frame_t *frame = NULL;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
i->period_missing_count++;
|
||||
i->session_missing_count++;
|
||||
i->period_need_range += need;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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, "\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);
|
||||
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, "\n%s\n\n\n", i->name);
|
||||
|
||||
}
|
||||
|
||||
if (delay < 0) {
|
||||
stfu_n_reset(i);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
i->consecutive_good_count++;
|
||||
i->period_good_count++;
|
||||
i->consecutive_bad_count = 0;
|
||||
} else {
|
||||
i->consecutive_bad_count++;
|
||||
i->period_bad_count++;
|
||||
i->consecutive_good_count = 0;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
i->last_frame = rframe;
|
||||
i->out_queue->wr_len++;
|
||||
i->last_wr_ts = rframe->ts;
|
||||
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;
|
||||
rframe = &i->out_queue->int_frame;
|
||||
|
||||
if (i->last_frame && i->last_frame != rframe) {
|
||||
rframe->dlen = i->last_frame->dlen;
|
||||
/* poor man's plc.. Copy the last frame, but we flag it so you can use a better one if you wish */
|
||||
memcpy(rframe->data, i->last_frame->data, rframe->dlen);
|
||||
rframe->dlen = i->plc_len;
|
||||
rframe->pt = i->plc_pt;
|
||||
rframe->ts = i->cur_ts;
|
||||
i->miss_count++;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
rframe->ts = i->cur_ts;
|
||||
|
||||
if (++i->miss_count > i->max_plc) {
|
||||
i->out_queue->wr_len = i->out_queue->array_size;
|
||||
i->cur_ts = 0;
|
||||
if (i->miss_count > i->max_plc) {
|
||||
stfu_n_reset(i);
|
||||
rframe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
+93
-7
@@ -38,6 +38,8 @@ extern "C" {
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifndef uint32_t
|
||||
@@ -62,6 +64,85 @@ typedef unsigned long in_addr_t;
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
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 <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#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);
|
||||
|
||||
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,7 +150,8 @@ 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 {
|
||||
@@ -86,21 +168,25 @@ struct stfu_instance;
|
||||
typedef struct stfu_instance stfu_instance_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t in_len;
|
||||
uint32_t in_size;
|
||||
uint32_t out_len;
|
||||
uint32_t out_size;
|
||||
|
||||
uint32_t qlen;
|
||||
uint32_t packet_in_count;
|
||||
uint32_t clean_count;
|
||||
uint32_t consecutive_good_count;
|
||||
uint32_t consecutive_bad_count;
|
||||
} stfu_report_t;
|
||||
|
||||
typedef void (*stfu_n_call_me_t)(stfu_instance_t *i, void *);
|
||||
|
||||
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_plc);
|
||||
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_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,p,d,l) stfu_n_add_data(i, t, p, d, l, 0)
|
||||
|
||||
Reference in New Issue
Block a user