Merge remote branch 'fsorig/master'
This commit is contained in:
commit
764b990849
|
@ -1,6 +1,6 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchConsole", "w32\Console\FreeSwitchConsole.2008.vcproj", "{1AF3A893-F7BE-43DD-B697-8AB2397C0D67}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
|
||||
|
@ -11,6 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Li
|
|||
ProjectSection(ProjectDependencies) = postProject
|
||||
{8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9}
|
||||
{89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C}
|
||||
{1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}
|
||||
{F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3}
|
||||
{03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD}
|
||||
{F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}
|
||||
|
|
|
@ -276,7 +276,8 @@ bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav fs_encode
|
|||
##
|
||||
## fs_cli ()
|
||||
##
|
||||
fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c
|
||||
fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \
|
||||
libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c
|
||||
fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include
|
||||
fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm
|
||||
|
||||
|
@ -304,7 +305,8 @@ tone2wav_LDADD = libfreeswitch.la
|
|||
##
|
||||
## fs_ivrd ()
|
||||
##
|
||||
fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c
|
||||
fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \
|
||||
libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c
|
||||
fs_ivrd_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include
|
||||
fs_ivrd_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
*/
|
|
@ -802,7 +802,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio
|
|||
phy_id = ftdm_channel_get_ph_id(tech_pvt->ftdmchan);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Got Freeswitch message in R2 channel %d [%d]\n", phy_id, msg->message_id);
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -849,7 +849,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -892,7 +892,7 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio
|
|||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -924,7 +924,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
|
|||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -981,7 +981,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
|
|||
switch (msg->message_id) {
|
||||
case SWITCH_MESSAGE_INDICATE_PROGRESS:
|
||||
case SWITCH_MESSAGE_INDICATE_ANSWER:
|
||||
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
if ((var = switch_channel_get_variable(channel, "freetdm_pre_buffer_size"))) {
|
||||
int tmp = atoi(var);
|
||||
if (tmp > -1) {
|
||||
|
@ -1363,7 +1363,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
|
|||
tech_pvt->caller_profile = caller_profile;
|
||||
|
||||
|
||||
switch_channel_set_flag(channel, CF_OUTBOUND);
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
if (ftdm_channel_add_token(ftdmchan, switch_core_session_get_uuid(*new_session), ftdm_channel_get_token_count(ftdmchan)) != FTDM_SUCCESS) {
|
||||
switch_core_session_destroy(new_session);
|
||||
|
@ -1811,7 +1810,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
|
|||
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
|
||||
}
|
||||
|
||||
if (channel_a && channel_b && !switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_test_flag(channel_b, CF_OUTBOUND)) {
|
||||
if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND &&
|
||||
switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
|
||||
cause = SWITCH_CAUSE_ATTENDED_TRANSFER;
|
||||
if (br_a_uuid && br_b_uuid) {
|
||||
switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid);
|
||||
|
|
|
@ -53,42 +53,48 @@ static struct {
|
|||
float txgain;
|
||||
} zt_globals;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
typedef unsigned long ioctlcmd;
|
||||
#else
|
||||
typedef int ioctlcmd;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief General IOCTL codes
|
||||
*/
|
||||
struct ioctl_codes {
|
||||
int GET_BLOCKSIZE;
|
||||
int SET_BLOCKSIZE;
|
||||
int FLUSH;
|
||||
int SYNC;
|
||||
int GET_PARAMS;
|
||||
int SET_PARAMS;
|
||||
int HOOK;
|
||||
int GETEVENT;
|
||||
int IOMUX;
|
||||
int SPANSTAT;
|
||||
int MAINT;
|
||||
int GETCONF;
|
||||
int SETCONF;
|
||||
int CONFLINK;
|
||||
int CONFDIAG;
|
||||
int GETGAINS;
|
||||
int SETGAINS;
|
||||
int SPANCONFIG;
|
||||
int CHANCONFIG;
|
||||
int SET_BUFINFO;
|
||||
int GET_BUFINFO;
|
||||
int AUDIOMODE;
|
||||
int ECHOCANCEL;
|
||||
int HDLCRAWMODE;
|
||||
int HDLCFCSMODE;
|
||||
int SPECIFY;
|
||||
int SETLAW;
|
||||
int SETLINEAR;
|
||||
int GETCONFMUTE;
|
||||
int ECHOTRAIN;
|
||||
int SETTXBITS;
|
||||
int GETRXBITS;
|
||||
ioctlcmd GET_BLOCKSIZE;
|
||||
ioctlcmd SET_BLOCKSIZE;
|
||||
ioctlcmd FLUSH;
|
||||
ioctlcmd SYNC;
|
||||
ioctlcmd GET_PARAMS;
|
||||
ioctlcmd SET_PARAMS;
|
||||
ioctlcmd HOOK;
|
||||
ioctlcmd GETEVENT;
|
||||
ioctlcmd IOMUX;
|
||||
ioctlcmd SPANSTAT;
|
||||
ioctlcmd MAINT;
|
||||
ioctlcmd GETCONF;
|
||||
ioctlcmd SETCONF;
|
||||
ioctlcmd CONFLINK;
|
||||
ioctlcmd CONFDIAG;
|
||||
ioctlcmd GETGAINS;
|
||||
ioctlcmd SETGAINS;
|
||||
ioctlcmd SPANCONFIG;
|
||||
ioctlcmd CHANCONFIG;
|
||||
ioctlcmd SET_BUFINFO;
|
||||
ioctlcmd GET_BUFINFO;
|
||||
ioctlcmd AUDIOMODE;
|
||||
ioctlcmd ECHOCANCEL;
|
||||
ioctlcmd HDLCRAWMODE;
|
||||
ioctlcmd HDLCFCSMODE;
|
||||
ioctlcmd SPECIFY;
|
||||
ioctlcmd SETLAW;
|
||||
ioctlcmd SETLINEAR;
|
||||
ioctlcmd GETCONFMUTE;
|
||||
ioctlcmd ECHOTRAIN;
|
||||
ioctlcmd SETTXBITS;
|
||||
ioctlcmd GETRXBITS;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
609
libs/stfu/stfu.c
609
libs/stfu/stfu.c
|
@ -33,11 +33,21 @@
|
|||
# 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;
|
||||
|
@ -53,13 +63,13 @@ typedef struct stfu_queue stfu_queue_t;
|
|||
struct stfu_instance {
|
||||
struct stfu_queue a_queue;
|
||||
struct stfu_queue b_queue;
|
||||
struct stfu_queue c_queue;
|
||||
struct stfu_queue *in_queue;
|
||||
struct stfu_queue *out_queue;
|
||||
struct stfu_queue *old_queue;
|
||||
struct stfu_frame *last_frame;
|
||||
uint32_t cur_ts;
|
||||
uint32_t cur_seq;
|
||||
uint32_t last_wr_ts;
|
||||
uint32_t last_wr_seq;
|
||||
uint32_t last_rd_ts;
|
||||
uint32_t samples_per_packet;
|
||||
uint32_t samples_per_second;
|
||||
|
@ -76,6 +86,7 @@ struct stfu_instance {
|
|||
uint32_t period_packet_in_count;
|
||||
uint32_t period_packet_out_count;
|
||||
uint32_t period_missing_count;
|
||||
|
||||
uint32_t period_need_range;
|
||||
uint32_t period_need_range_avg;
|
||||
uint32_t period_clean_count;
|
||||
|
@ -86,25 +97,55 @@ struct stfu_instance {
|
|||
uint32_t session_packet_in_count;
|
||||
uint32_t session_packet_out_count;
|
||||
|
||||
uint32_t sync;
|
||||
uint32_t sync_out;
|
||||
uint32_t sync_in;
|
||||
|
||||
|
||||
int32_t ts_diff;
|
||||
int32_t last_ts_diff;
|
||||
int32_t same_ts;
|
||||
|
||||
uint32_t last_seq;
|
||||
|
||||
uint32_t period_time;
|
||||
uint32_t decrement_time;
|
||||
|
||||
uint32_t plc_len;
|
||||
uint32_t plc_pt;
|
||||
uint32_t diff;
|
||||
uint32_t diff_total;
|
||||
uint8_t ready;
|
||||
uint8_t debug;
|
||||
|
||||
char *name;
|
||||
stfu_n_call_me_t callback;
|
||||
void *udata;
|
||||
};
|
||||
|
||||
static void stfu_n_reset_counters(stfu_instance_t *i);
|
||||
static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...);
|
||||
static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...);
|
||||
|
||||
stfu_logger_t stfu_log = null_logger;
|
||||
|
||||
void stfu_global_set_logger(stfu_logger_t logger)
|
||||
{
|
||||
if (logger) {
|
||||
stfu_log = logger;
|
||||
} else {
|
||||
stfu_log = null_logger;
|
||||
}
|
||||
}
|
||||
|
||||
void stfu_global_set_default_logger(int level)
|
||||
{
|
||||
if (level < 0 || level > 7) {
|
||||
level = 7;
|
||||
}
|
||||
|
||||
stfu_log = default_logger;
|
||||
stfu_log_level = level;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static stfu_status_t stfu_n_resize_aqueue(stfu_queue_t *queue, uint32_t qlen)
|
||||
{
|
||||
|
@ -151,12 +192,27 @@ void stfu_n_destroy(stfu_instance_t **i)
|
|||
if (i && *i) {
|
||||
ii = *i;
|
||||
*i = NULL;
|
||||
if (ii->name) free(ii->name);
|
||||
free(ii->a_queue.array);
|
||||
free(ii->b_queue.array);
|
||||
free(ii->c_queue.array);
|
||||
free(ii);
|
||||
}
|
||||
}
|
||||
|
||||
void stfu_n_debug(stfu_instance_t *i, const char *name)
|
||||
{
|
||||
if (i->name) free(i->name);
|
||||
|
||||
if (name) {
|
||||
i->name = strdup(name);
|
||||
i->debug = 1;
|
||||
} else {
|
||||
i->name = strdup("none");
|
||||
i->debug = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void stfu_n_report(stfu_instance_t *i, stfu_report_t *r)
|
||||
{
|
||||
assert(i);
|
||||
|
@ -172,7 +228,6 @@ stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen)
|
|||
stfu_status_t s;
|
||||
|
||||
if (i->qlen == i->max_qlen) {
|
||||
printf("FUCKER1\n");
|
||||
return STFU_IT_FAILED;
|
||||
}
|
||||
|
||||
|
@ -180,13 +235,14 @@ stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen)
|
|||
if (i->qlen < i->max_qlen) {
|
||||
qlen = i->max_qlen;
|
||||
} else {
|
||||
printf("FUCKER2\n");
|
||||
return STFU_IT_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if ((s = stfu_n_resize_aqueue(&i->a_queue, qlen)) == STFU_IT_WORKED) {
|
||||
s = stfu_n_resize_aqueue(&i->b_queue, qlen);
|
||||
s = stfu_n_resize_aqueue(&i->c_queue, qlen);
|
||||
|
||||
i->qlen = qlen;
|
||||
i->max_plc = 5;
|
||||
i->last_frame = NULL;
|
||||
|
@ -205,11 +261,6 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_
|
|||
}
|
||||
memset(i, 0, sizeof(*i));
|
||||
|
||||
|
||||
#ifdef DB_JB
|
||||
printf("INIT %u %u\n", qlen, max_qlen);
|
||||
#endif
|
||||
|
||||
i->qlen = qlen;
|
||||
i->max_qlen = max_qlen;
|
||||
i->orig_qlen = qlen;
|
||||
|
@ -217,8 +268,12 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_
|
|||
|
||||
stfu_n_init_aqueue(&i->a_queue, qlen);
|
||||
stfu_n_init_aqueue(&i->b_queue, qlen);
|
||||
stfu_n_init_aqueue(&i->c_queue, qlen);
|
||||
|
||||
i->in_queue = &i->a_queue;
|
||||
i->out_queue = &i->b_queue;
|
||||
i->old_queue = &i->c_queue;
|
||||
i->name = strdup("none");
|
||||
|
||||
i->max_plc = i->qlen / 2;
|
||||
|
||||
|
@ -232,9 +287,9 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_
|
|||
|
||||
static void stfu_n_reset_counters(stfu_instance_t *i)
|
||||
{
|
||||
#ifdef DB_JB
|
||||
printf("COUNTER RESET........\n");
|
||||
#endif
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s COUNTER RESET........\n", i->name);
|
||||
}
|
||||
|
||||
if (i->callback) {
|
||||
i->callback(i, i->udata);
|
||||
|
@ -248,36 +303,44 @@ static void stfu_n_reset_counters(stfu_instance_t *i)
|
|||
i->period_packet_in_count = 0;
|
||||
i->period_packet_out_count = 0;
|
||||
i->period_missing_count = 0;
|
||||
|
||||
i->period_need_range = 0;
|
||||
i->period_need_range_avg = 0;
|
||||
|
||||
i->diff = 0;
|
||||
i->diff_total = 0;
|
||||
|
||||
}
|
||||
|
||||
void stfu_n_reset(stfu_instance_t *i)
|
||||
{
|
||||
#ifdef DB_JB
|
||||
printf("RESET\n");
|
||||
#endif
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s RESET\n", i->name);
|
||||
}
|
||||
|
||||
i->ready = 0;
|
||||
i->in_queue = &i->a_queue;
|
||||
i->out_queue = &i->b_queue;
|
||||
i->old_queue = &i->c_queue;
|
||||
|
||||
i->in_queue->array_len = 0;
|
||||
i->out_queue->array_len = 0;
|
||||
i->out_queue->wr_len = 0;
|
||||
i->last_frame = NULL;
|
||||
|
||||
i->in_queue->last_jitter = 0;
|
||||
i->out_queue->last_jitter = 0;
|
||||
|
||||
|
||||
stfu_n_reset_counters(i);
|
||||
|
||||
i->last_seq = 0;
|
||||
|
||||
stfu_n_sync(i, 1);
|
||||
|
||||
i->cur_ts = 0;
|
||||
i->cur_seq = 0;
|
||||
i->last_wr_ts = 0;
|
||||
i->last_wr_seq = 0;
|
||||
i->last_rd_ts = 0;
|
||||
i->miss_count = 0;
|
||||
i->packet_count = 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets)
|
||||
|
@ -286,20 +349,39 @@ stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets)
|
|||
if (packets > i->qlen) {
|
||||
stfu_n_reset(i);
|
||||
} else {
|
||||
i->sync = packets;
|
||||
i->sync_out = packets;
|
||||
i->sync_in = packets;
|
||||
}
|
||||
|
||||
return STFU_IT_WORKED;
|
||||
}
|
||||
|
||||
|
||||
stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uint32_t pt, void *data, size_t datalen, int last)
|
||||
static void stfu_n_swap(stfu_instance_t *i)
|
||||
{
|
||||
stfu_queue_t *last_in = i->in_queue, *last_out = i->out_queue, *last_old = i->old_queue;
|
||||
|
||||
i->ready = 1;
|
||||
|
||||
i->in_queue = last_out;
|
||||
i->out_queue = last_old;
|
||||
i->old_queue = last_in;
|
||||
|
||||
i->in_queue->array_len = 0;
|
||||
i->out_queue->wr_len = 0;
|
||||
i->last_frame = NULL;
|
||||
i->miss_count = 0;
|
||||
i->in_queue->last_index = 0;
|
||||
i->out_queue->last_index = 0;
|
||||
i->out_queue->last_jitter = 0;
|
||||
}
|
||||
|
||||
stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
stfu_frame_t *frame;
|
||||
size_t cplen = 0;
|
||||
int good_seq = 0, good_ts = 0;
|
||||
uint32_t min_seq = UINT_MAX, min_ts = UINT_MAX, min_index = 0;
|
||||
int good_ts = 0;
|
||||
|
||||
if (!i->samples_per_packet && ts && i->last_rd_ts) {
|
||||
i->ts_diff = ts - i->last_rd_ts;
|
||||
|
@ -320,16 +402,27 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
|
|||
}
|
||||
}
|
||||
|
||||
if ((seq && seq == i->last_seq + 1) || (i->last_seq > 65500 && seq == 0)) {
|
||||
good_seq = 1;
|
||||
}
|
||||
|
||||
if ((ts && ts == i->last_rd_ts + i->samples_per_packet) || (i->last_rd_ts > 4294900000 && ts < 5000)) {
|
||||
if (i->sync_in) {
|
||||
good_ts = 1;
|
||||
i->sync_in = 0;
|
||||
} else {
|
||||
|
||||
if ((ts && ts == i->last_rd_ts + i->samples_per_packet) || (i->last_rd_ts > 4294900000 && ts < 5000)) {
|
||||
good_ts = 1;
|
||||
}
|
||||
|
||||
if (i->last_wr_ts) {
|
||||
if ((ts <= i->last_wr_ts && (i->last_wr_ts != UINT_MAX || ts == i->last_wr_ts))) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts);
|
||||
if (i->in_queue->array_len < i->in_queue->array_size) {
|
||||
i->in_queue->array_len++;
|
||||
}
|
||||
return STFU_ITS_TOO_LATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (good_seq || good_ts) {
|
||||
if (good_ts) {
|
||||
i->period_clean_count++;
|
||||
i->session_clean_count++;
|
||||
}
|
||||
|
@ -337,12 +430,12 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
|
|||
i->period_packet_in_count++;
|
||||
i->session_packet_in_count++;
|
||||
|
||||
i->period_need_range_avg = i->period_need_range / (i->period_missing_count || 1);
|
||||
i->period_need_range_avg = i->period_need_range / least1(i->period_missing_count);
|
||||
|
||||
if (i->period_missing_count > i->qlen * 2) {
|
||||
#ifdef DB_JB
|
||||
printf("resize %u %u\n", i->qlen, i->qlen + 1);
|
||||
#endif
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s resize %u %u\n", i->name, i->qlen, i->qlen + 1);
|
||||
}
|
||||
stfu_n_resize(i, i->qlen + 1);
|
||||
stfu_n_reset_counters(i);
|
||||
} else {
|
||||
|
@ -353,7 +446,24 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
i->diff = 0;
|
||||
|
||||
if (i->last_wr_ts) {
|
||||
if (ts < 1000 && i->last_wr_ts > (UINT_MAX - 1000)) {
|
||||
i->diff = abs(((UINT_MAX - i->last_wr_ts) + ts) / i->samples_per_packet);
|
||||
} else if (ts) {
|
||||
i->diff = abs(i->last_wr_ts - ts) / i->samples_per_packet;
|
||||
}
|
||||
}
|
||||
|
||||
i->diff_total += i->diff;
|
||||
|
||||
if ((i->period_packet_in_count > i->period_time)) {
|
||||
uint32_t avg;
|
||||
|
||||
avg = i->diff_total / least1(i->period_packet_in_count);
|
||||
|
||||
i->period_packet_in_count = 0;
|
||||
|
||||
if (i->period_missing_count == 0 && i->qlen > i->orig_qlen) {
|
||||
|
@ -364,68 +474,38 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
|
|||
stfu_n_reset_counters(i);
|
||||
}
|
||||
|
||||
#ifdef DB_JB
|
||||
printf("%u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u/%u - %u %d\n",
|
||||
i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count,
|
||||
i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count,
|
||||
seq, ts,
|
||||
i->period_missing_count, i->period_need_range_avg);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d\n", i->name,
|
||||
i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count,
|
||||
i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count,
|
||||
ts, ts / i->samples_per_packet,
|
||||
i->period_missing_count, i->period_need_range_avg,
|
||||
i->last_wr_ts, ts, i->diff, i->diff_total / least1(i->period_packet_in_count));
|
||||
}
|
||||
|
||||
if (last || i->in_queue->array_len == i->in_queue->array_size) {
|
||||
stfu_queue_t *other_queue;
|
||||
|
||||
other_queue = i->in_queue;
|
||||
i->in_queue = i->out_queue;
|
||||
i->out_queue = other_queue;
|
||||
|
||||
i->in_queue->array_len = 0;
|
||||
i->out_queue->wr_len = 0;
|
||||
i->last_frame = NULL;
|
||||
i->miss_count = 0;
|
||||
i->in_queue->last_index = 0;
|
||||
i->out_queue->last_index = 0;
|
||||
i->out_queue->last_jitter = 0;
|
||||
stfu_n_swap(i);
|
||||
}
|
||||
|
||||
if (last) {
|
||||
return STFU_IM_DONE;
|
||||
}
|
||||
|
||||
for(index = 0; index < i->in_queue->array_size; index++) {
|
||||
|
||||
if (i->in_queue->array[index].was_read) {
|
||||
min_index = index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i->in_queue->array[index].seq < min_seq) {
|
||||
min_seq = i->in_queue->array[index].seq;
|
||||
min_index = index;
|
||||
}
|
||||
|
||||
if (i->in_queue->array[index].ts < min_ts) {
|
||||
min_ts = i->in_queue->array[index].ts;
|
||||
min_index = index;
|
||||
}
|
||||
}
|
||||
|
||||
index = min_index;
|
||||
|
||||
if (i->in_queue->array_len < i->in_queue->array_size) {
|
||||
i->in_queue->array_len++;
|
||||
}
|
||||
|
||||
index = i->in_queue->array_len++;
|
||||
assert(index < i->in_queue->array_size);
|
||||
|
||||
frame = &i->in_queue->array[index];
|
||||
|
||||
if (i->in_queue->array_len == i->in_queue->array_size) {
|
||||
stfu_n_swap(i);
|
||||
}
|
||||
|
||||
if ((cplen = datalen) > sizeof(frame->data)) {
|
||||
cplen = sizeof(frame->data);
|
||||
}
|
||||
|
||||
i->last_seq = seq;
|
||||
i->last_rd_ts = ts;
|
||||
i->packet_count++;
|
||||
|
||||
|
@ -433,44 +513,13 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
|
|||
|
||||
frame->pt = pt;
|
||||
frame->ts = ts;
|
||||
frame->seq = seq;
|
||||
frame->dlen = cplen;
|
||||
frame->was_read = 0;
|
||||
|
||||
return STFU_IT_WORKED;
|
||||
}
|
||||
|
||||
static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_frame_t **r_frame)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
stfu_frame_t *frame = NULL;
|
||||
stfu_queue_t *queue;
|
||||
|
||||
assert(r_frame);
|
||||
|
||||
*r_frame = NULL;
|
||||
|
||||
for (queue = in->out_queue ; queue && queue != in->in_queue ; queue = in->in_queue) {
|
||||
|
||||
for(i = 0; i < queue->real_array_size; i++) {
|
||||
frame = &queue->array[i];
|
||||
if (!frame->was_read) {
|
||||
*r_frame = frame;
|
||||
queue->last_index = i;
|
||||
frame->was_read = 1;
|
||||
in->period_packet_out_count++;
|
||||
in->session_packet_out_count++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, uint32_t seq, stfu_frame_t **r_frame)
|
||||
static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_queue_t *queue, stfu_frame_t **r_frame)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
stfu_frame_t *frame = NULL;
|
||||
|
@ -481,8 +530,7 @@ static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t
|
|||
|
||||
for(i = 0; i < queue->real_array_size; i++) {
|
||||
frame = &queue->array[i];
|
||||
|
||||
if (((seq || in->last_seq) && frame->seq == seq) || frame->ts == ts) {
|
||||
if (!frame->was_read) {
|
||||
*r_frame = frame;
|
||||
queue->last_index = i;
|
||||
frame->was_read = 1;
|
||||
|
@ -492,6 +540,34 @@ static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
stfu_frame_t *frame = NULL;
|
||||
|
||||
if (r_frame) {
|
||||
*r_frame = NULL;
|
||||
}
|
||||
|
||||
for(i = 0; i < queue->array_size; i++) {
|
||||
frame = &queue->array[i];
|
||||
|
||||
if (frame->ts == ts) {
|
||||
if (r_frame) {
|
||||
*r_frame = frame;
|
||||
queue->last_index = i;
|
||||
frame->was_read = 1;
|
||||
in->period_packet_out_count++;
|
||||
in->session_packet_out_count++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -500,48 +576,76 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
|
|||
stfu_frame_t *rframe = NULL;
|
||||
int found = 0;
|
||||
|
||||
if (!i->samples_per_packet || !i->out_queue->array_len) {
|
||||
//|| ((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (i->cur_ts == 0) {
|
||||
i->cur_ts = i->out_queue->array[0].ts;
|
||||
} else {
|
||||
i->cur_ts += i->samples_per_packet;
|
||||
if (!i->samples_per_packet) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (i->cur_seq == 0) {
|
||||
i->cur_seq = i->out_queue->array[0].seq;
|
||||
if (!i->ready) {
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s XXXSKIP\n", i->name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (i->cur_ts == 0 && i->last_wr_ts < 1000) {
|
||||
uint32_t x = 0;
|
||||
for (x = 0; x < i->out_queue->array_len; x++) {
|
||||
if (!i->out_queue->array[x].was_read) {
|
||||
i->cur_ts = i->out_queue->array[x].ts;
|
||||
break;
|
||||
}
|
||||
if (i->cur_ts == 0) {
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s XXXPUNT\n", i->name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i->cur_seq++;
|
||||
/* if we bother using this for anything that doesn't have 16 bit seq, we'll make this a param */
|
||||
if (i->cur_seq == 65535) {
|
||||
i->cur_seq = 0;
|
||||
i->cur_ts = i->cur_ts + i->samples_per_packet;
|
||||
}
|
||||
|
||||
found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, &rframe);
|
||||
|
||||
if (found) {
|
||||
if (i->out_queue->array_len) {
|
||||
i->out_queue->array_len--;
|
||||
}
|
||||
} else {
|
||||
found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, &rframe);
|
||||
|
||||
if (!found) {
|
||||
found = stfu_n_find_frame(i, i->old_queue, i->cur_ts, &rframe);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, i->cur_seq, &rframe))) {
|
||||
found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, i->cur_seq, &rframe);
|
||||
if (i->sync_out) {
|
||||
if (!found) {
|
||||
if ((found = stfu_n_find_any_frame(i, i->out_queue, &rframe))) {
|
||||
i->cur_ts = rframe->ts;
|
||||
}
|
||||
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s SYNC %u %u:%u\n", i->name, i->sync_out, i->cur_ts, i->cur_ts / i->samples_per_packet);
|
||||
}
|
||||
|
||||
}
|
||||
i->sync_out = 0;
|
||||
}
|
||||
|
||||
if (!found && i->sync) {
|
||||
#ifdef DB_JB
|
||||
printf("SYNC %u\n", i->sync);
|
||||
#endif
|
||||
if ((found = stfu_n_find_any_frame(i, &rframe))) {
|
||||
i->cur_seq = rframe->seq;
|
||||
i->cur_ts = rframe->ts;
|
||||
if (!i->cur_ts) {
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s NO TS\n", i->name);
|
||||
}
|
||||
i->sync = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (!found && i->samples_per_packet) {
|
||||
#ifdef DB_JB
|
||||
int y;
|
||||
uint32_t y;
|
||||
stfu_frame_t *frame = NULL;
|
||||
#endif
|
||||
|
||||
int32_t delay = i->last_rd_ts - i->cur_ts;
|
||||
uint32_t need = abs(i->last_rd_ts - i->cur_ts) / i->samples_per_packet;
|
||||
|
||||
|
@ -550,30 +654,33 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
|
|||
i->session_missing_count++;
|
||||
i->period_need_range += need;
|
||||
|
||||
#ifdef DB_JB
|
||||
printf("MISSING %u %u %u %u %d %u %d\n", i->cur_seq, i->cur_ts, i->packet_count, i->last_rd_ts, delay, i->qlen, need);
|
||||
#endif
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s MISSING %u:%u %u %u %d %u %d\n", i->name,
|
||||
i->cur_ts, i->cur_ts / i->samples_per_packet, i->packet_count, i->last_rd_ts, delay, i->qlen, need);
|
||||
}
|
||||
|
||||
if (i->packet_count > i->orig_qlen * 100 && delay > 0 && need > i->qlen && need < (i->qlen + 5)) {
|
||||
i->packet_count = 0;
|
||||
}
|
||||
|
||||
#ifdef DB_JB
|
||||
for(y = 0; y < i->out_queue->array_size; y++) {
|
||||
if ((y % 5) == 0) printf("\n");
|
||||
frame = &i->out_queue->array[y];
|
||||
printf("%u:%u\t", frame->seq, frame->ts);
|
||||
}
|
||||
printf("\n\n");
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
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) printf("\n");
|
||||
frame = &i->in_queue->array[y];
|
||||
printf("%u:%u\t", frame->seq, frame->ts);
|
||||
for(y = 0; y < i->in_queue->array_size; y++) {
|
||||
if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s ", i->name);
|
||||
frame = &i->in_queue->array[y];
|
||||
stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet);
|
||||
}
|
||||
stfu_log(STFU_LOG_EMERG, "\n%s\n\n\n", i->name);
|
||||
|
||||
}
|
||||
printf("\n\n");
|
||||
#endif
|
||||
|
||||
if (delay < 0) {
|
||||
stfu_n_reset(i);
|
||||
|
@ -581,14 +688,11 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DB_JB
|
||||
if (found) {
|
||||
printf("O: %u:%u %u %d\n", rframe->seq, rframe->ts, rframe->plc, rframe->seq - i->last_seq);
|
||||
} else {
|
||||
printf("DATA: %u %u %d %s %d\n", i->packet_count, i->consecutive_good_count, i->out_queue->last_jitter, found ? "found" : "not found", i->qlen);
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
if (found) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s O: %u:%u %u\n", i->name, rframe->ts, rframe->ts / i->samples_per_packet, rframe->plc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (found) {
|
||||
i->consecutive_good_count++;
|
||||
|
@ -602,36 +706,28 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
|
|||
|
||||
if (found) {
|
||||
i->last_frame = rframe;
|
||||
i->out_queue->wr_len++;
|
||||
i->last_wr_ts = rframe->ts;
|
||||
i->last_wr_seq = rframe->seq;
|
||||
i->miss_count = 0;
|
||||
i->out_queue->wr_len++;
|
||||
i->last_wr_ts = rframe->ts;
|
||||
|
||||
i->miss_count = 0;
|
||||
if (rframe->dlen) {
|
||||
i->plc_len = rframe->dlen;
|
||||
}
|
||||
|
||||
i->plc_pt = rframe->pt;
|
||||
|
||||
} else {
|
||||
i->last_wr_ts = i->cur_ts;
|
||||
i->last_wr_seq = i->cur_seq;
|
||||
rframe = &i->out_queue->int_frame;
|
||||
rframe->dlen = i->plc_len;
|
||||
|
||||
#if 0
|
||||
if (i->last_frame) {
|
||||
/* poor man's plc.. Copy the last frame, but we flag it so you can use a better one if you wish */
|
||||
if (i->miss_count) {
|
||||
memset(rframe->data, 255, rframe->dlen);
|
||||
} else {
|
||||
memcpy(rframe->data, i->last_frame->data, rframe->dlen);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rframe->pt = i->plc_pt;
|
||||
rframe->ts = i->cur_ts;
|
||||
|
||||
i->miss_count++;
|
||||
|
||||
#ifdef DB_JB
|
||||
printf("PLC %d %d %ld %u %u\n", i->miss_count, rframe->plc, rframe->dlen, rframe->seq, rframe->ts);
|
||||
#endif
|
||||
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "%s PLC %d %d %ld %u:%u\n", i->name,
|
||||
i->miss_count, rframe->plc, rframe->dlen, rframe->ts, rframe->ts / i->samples_per_packet);
|
||||
}
|
||||
|
||||
if (i->miss_count > i->max_plc) {
|
||||
stfu_n_reset(i);
|
||||
|
@ -639,9 +735,138 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
|
|||
}
|
||||
}
|
||||
|
||||
return rframe;
|
||||
return rframe;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef vsnprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
int vasprintf(char **ret, const char *format, va_list ap);
|
||||
|
||||
int stfu_vasprintf(char **ret, const char *fmt, va_list ap)
|
||||
{
|
||||
#if !defined(WIN32) && !defined(__sun)
|
||||
return vasprintf(ret, fmt, ap);
|
||||
#else
|
||||
char *buf;
|
||||
int len;
|
||||
size_t buflen;
|
||||
va_list ap2;
|
||||
char *tmp = NULL;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER >= 1500
|
||||
/* hack for incorrect assumption in msvc header files for code analysis */
|
||||
__analysis_assume(tmp);
|
||||
#endif
|
||||
ap2 = ap;
|
||||
#else
|
||||
va_copy(ap2, ap);
|
||||
#endif
|
||||
|
||||
len = vsnprintf(tmp, 0, fmt, ap2);
|
||||
|
||||
if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) {
|
||||
len = vsnprintf(buf, buflen, fmt, ap);
|
||||
*ret = buf;
|
||||
} else {
|
||||
*ret = NULL;
|
||||
len = -1;
|
||||
}
|
||||
|
||||
va_end(ap2);
|
||||
return len;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int stfu_snprintf(char *buffer, size_t count, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vsnprintf(buffer, count-1, fmt, ap);
|
||||
if (ret < 0)
|
||||
buffer[count-1] = '\0';
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
|
||||
{
|
||||
if (file && func && line && level && fmt) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *LEVEL_NAMES[] = {
|
||||
"EMERG",
|
||||
"ALERT",
|
||||
"CRIT",
|
||||
"ERROR",
|
||||
"WARNING",
|
||||
"NOTICE",
|
||||
"INFO",
|
||||
"DEBUG",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *cut_path(const char *in)
|
||||
{
|
||||
const char *p, *ret = in;
|
||||
char delims[] = "/\\";
|
||||
char *i;
|
||||
|
||||
for (i = delims; *i; i++) {
|
||||
p = in;
|
||||
while ((p = strchr(p, *i)) != 0) {
|
||||
ret = ++p;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
|
||||
{
|
||||
const char *fp;
|
||||
char *data;
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
if (level < 0 || level > 7) {
|
||||
level = 7;
|
||||
}
|
||||
if (level > stfu_log_level) {
|
||||
return;
|
||||
}
|
||||
|
||||
fp = cut_path(file);
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
ret = stfu_vasprintf(&data, fmt, ap);
|
||||
|
||||
if (ret != -1) {
|
||||
fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
|
|
@ -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,13 +150,13 @@ typedef unsigned long in_addr_t;
|
|||
typedef enum {
|
||||
STFU_IT_FAILED,
|
||||
STFU_IT_WORKED,
|
||||
STFU_IM_DONE
|
||||
STFU_IM_DONE,
|
||||
STFU_ITS_TOO_LATE
|
||||
} stfu_status_t;
|
||||
|
||||
struct stfu_frame {
|
||||
uint32_t ts;
|
||||
uint32_t pt;
|
||||
uint32_t seq;
|
||||
uint8_t data[STFU_DATALEN];
|
||||
size_t dlen;
|
||||
uint8_t was_read;
|
||||
|
@ -100,14 +181,15 @@ void stfu_n_report(stfu_instance_t *i, stfu_report_t *r);
|
|||
void stfu_n_destroy(stfu_instance_t **i);
|
||||
stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second);
|
||||
stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen);
|
||||
stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uint32_t pt, void *data, size_t datalen, int last);
|
||||
stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last);
|
||||
stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i);
|
||||
void stfu_n_reset(stfu_instance_t *i);
|
||||
stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets);
|
||||
void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata);
|
||||
void stfu_n_debug(stfu_instance_t *i, const char *name);
|
||||
|
||||
#define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 1)
|
||||
#define stfu_n_eat(i,t,s,p,d,l) stfu_n_add_data(i, t, s, p, d, l, 0)
|
||||
#define stfu_n_eat(i,t,p,d,l) stfu_n_add_data(i, t, p, d, l, 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -234,6 +234,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *
|
|||
uint32_t max_queue_frames,
|
||||
uint32_t samples_per_packet, uint32_t samples_per_second);
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name);
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session);
|
||||
|
||||
/*!
|
||||
|
|
|
@ -1095,6 +1095,7 @@ typedef enum {
|
|||
CF_BRIDGE_NOWRITE,
|
||||
CF_RECOVERED,
|
||||
CF_JITTERBUFFER,
|
||||
CF_DIALPLAN,
|
||||
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
|
||||
CF_FLAG_MAX
|
||||
} switch_channel_flag_t;
|
||||
|
|
|
@ -2456,7 +2456,7 @@ static void conference_loop_output(conference_member_t *member)
|
|||
switch_event_destroy(&event);
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
/* test to see if outbound channel has answered */
|
||||
if (switch_channel_test_flag(channel, CF_ANSWERED) && !switch_test_flag(member->conference, CFLAG_ANSWERED)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG,
|
||||
|
@ -2599,7 +2599,7 @@ static void conference_loop_output(conference_member_t *member)
|
|||
switch_channel_cause2str(switch_channel_get_cause(channel)));
|
||||
|
||||
/* if it's an outbound channel, store the release cause in the conference struct, we might need it */
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
member->conference->bridge_hangup_cause = switch_channel_get_cause(channel);
|
||||
}
|
||||
|
||||
|
@ -5446,7 +5446,7 @@ SWITCH_STANDARD_APP(conference_function)
|
|||
launch_conference_thread(conference);
|
||||
|
||||
} else {
|
||||
int enforce_security = !switch_channel_test_flag(channel, CF_OUTBOUND);
|
||||
int enforce_security = switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND;
|
||||
const char *pvar = switch_channel_get_variable(channel, "conference_enforce_security");
|
||||
|
||||
if (pvar) {
|
||||
|
@ -5655,7 +5655,7 @@ SWITCH_STANDARD_APP(conference_function)
|
|||
} else {
|
||||
/* if we're not using "bridge:" set the conference answered flag */
|
||||
/* and this isn't an outbound channel, answer the call */
|
||||
if (!switch_channel_test_flag(channel, CF_OUTBOUND))
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND)
|
||||
switch_set_flag(conference, CFLAG_ANSWERED);
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,6 @@ SWITCH_STANDARD_API(dump_hash)
|
|||
static switch_status_t process_event(switch_event_t *event)
|
||||
{
|
||||
switch_core_session_t *session = NULL;
|
||||
switch_channel_t *channel;
|
||||
char *username[3] = { 0 };
|
||||
char *domain[3] = { 0 };
|
||||
char key[512];
|
||||
|
@ -172,18 +171,19 @@ static switch_status_t process_event(switch_event_t *event)
|
|||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
session = switch_core_session_locate(uuid);
|
||||
channel = switch_core_session_get_channel(session);
|
||||
if ((session = switch_core_session_locate(uuid))) {
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key);
|
||||
my_uuid = switch_event_get_header(event, "Unique-ID");
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key);
|
||||
my_uuid = switch_event_get_header(event, "Unique-ID");
|
||||
|
||||
switch_channel_set_variable(channel, "spy_uuid", my_uuid);
|
||||
switch_channel_set_variable(channel, "spy_uuid", my_uuid);
|
||||
|
||||
switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
|
||||
switch_channel_set_flag(channel, CF_BREAK);
|
||||
switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
|
||||
switch_channel_set_flag(channel, CF_BREAK);
|
||||
|
||||
switch_core_session_rwunlock(session);
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
|
|
@ -1324,7 +1324,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
|
|||
caller_profile = tech_pvt->caller_profile;
|
||||
caller_profile->destination_number = rdest;
|
||||
|
||||
switch_channel_set_flag(channel, CF_OUTBOUND);
|
||||
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
gsmopen_call(tech_pvt, rdest, 30);
|
||||
|
|
|
@ -725,7 +725,6 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran
|
|||
name += outbound_profile->destination_number;
|
||||
switch_channel_set_name(m_fsChannel, name);
|
||||
|
||||
switch_channel_set_flag(m_fsChannel, CF_OUTBOUND);
|
||||
switch_channel_set_state(m_fsChannel, CS_INIT);
|
||||
}
|
||||
|
||||
|
@ -1508,7 +1507,7 @@ switch_status_t FSH323Connection::receive_message(switch_core_session_message_t
|
|||
break;
|
||||
}
|
||||
case SWITCH_MESSAGE_INDICATE_ANSWER: {
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
AnsweringCall(H323Connection::AnswerCallNow);
|
||||
|
|
|
@ -868,7 +868,6 @@ switch_status_t Board::KhompPvt::justStart(switch_caller_profile_t *profile)
|
|||
_caller_profile = switch_caller_profile_clone(_session, profile);
|
||||
switch_channel_set_caller_profile(channel, _caller_profile);
|
||||
|
||||
switch_channel_set_flag(channel, CF_OUTBOUND);
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -580,7 +580,6 @@ FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, void* userDat
|
|||
name += outbound_profile->destination_number;
|
||||
switch_channel_set_name(m_fsChannel, name);
|
||||
|
||||
switch_channel_set_flag(m_fsChannel, CF_OUTBOUND);
|
||||
switch_channel_set_state(m_fsChannel, CS_INIT);
|
||||
}
|
||||
}
|
||||
|
@ -966,7 +965,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg
|
|||
It would only happen if someone called switch_channel_answer() instead of switch_channel_mark_answered() on an outbound call.
|
||||
it should not do anything if someone does it by accident somewhere hense this in both cases:
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1025,7 +1024,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg
|
|||
{
|
||||
int fixed = 0;
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1080,8 +1080,6 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi
|
|||
switch_channel_set_caller_profile(nchannel, caller_profile);
|
||||
tech_pvt->caller_profile = caller_profile;
|
||||
|
||||
switch_channel_set_flag(nchannel, CF_OUTBOUND);
|
||||
|
||||
if ((sql = switch_mprintf(
|
||||
"INSERT INTO skinny_active_lines "
|
||||
"(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) "
|
||||
|
|
|
@ -547,12 +547,15 @@ struct PACKED service_url_stat_res_message {
|
|||
#define USER_TO_DEVICE_DATA_VERSION1_MESSAGE 0x013F
|
||||
/* See struct PACKED extended_data_message */
|
||||
|
||||
/* XMLAlarmMessage */
|
||||
#define XML_ALARM_MESSAGE 0x015A
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SKINNY MESSAGE */
|
||||
/*****************************************************************************/
|
||||
#define SKINNY_MESSAGE_FIELD_SIZE 4 /* 4-bytes field */
|
||||
#define SKINNY_MESSAGE_HEADERSIZE 12 /* three 4-bytes fields */
|
||||
#define SKINNY_MESSAGE_MAXSIZE 1000
|
||||
#define SKINNY_MESSAGE_MAXSIZE 2048
|
||||
|
||||
union skinny_data {
|
||||
/* no data for KEEP_ALIVE_MESSAGE */
|
||||
|
|
|
@ -343,7 +343,7 @@ switch_status_t skinny_session_send_call_info(switch_core_session_t *session, li
|
|||
zstr((called_party_number = switch_channel_get_variable(channel, "destination_number")))) {
|
||||
called_party_number = "0000000000";
|
||||
}
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
call_type = SKINNY_INBOUND_CALL;
|
||||
} else {
|
||||
call_type = SKINNY_OUTBOUND_CALL;
|
||||
|
@ -1674,7 +1674,7 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste
|
|||
);
|
||||
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_IO);
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
switch_channel_mark_answered(channel);
|
||||
}
|
||||
if (switch_channel_test_flag(channel, CF_HOLD)) {
|
||||
|
@ -1970,7 +1970,7 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
|
|||
"Received %s (type=%x,length=%d) from %s:%d.\n", skinny_message_type2str(request->type), request->type, request->length,
|
||||
listener->device_name, listener->device_instance);
|
||||
}
|
||||
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE) {
|
||||
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Device should send a register message first.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
|
|
|
@ -99,6 +99,7 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
|
|||
{"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE},
|
||||
{"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE},
|
||||
{"UserToDeviceDataVersion1Message", USER_TO_DEVICE_DATA_VERSION1_MESSAGE},
|
||||
{"XMLAlarmMessage", XML_ALARM_MESSAGE},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_message_type2str, SKINNY_MESSAGE_TYPES, "UnknownMessage")
|
||||
|
|
|
@ -87,7 +87,7 @@ uint32_t func(const char *str)\
|
|||
}
|
||||
|
||||
|
||||
extern struct skinny_table SKINNY_MESSAGE_TYPES[65];
|
||||
extern struct skinny_table SKINNY_MESSAGE_TYPES[66];
|
||||
const char *skinny_message_type2str(uint32_t id);
|
||||
uint32_t skinny_str2message_type(const char *str);
|
||||
#define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES)
|
||||
|
|
|
@ -1364,7 +1364,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
|
|||
caller_profile = tech_pvt->caller_profile;
|
||||
caller_profile->destination_number = rdest;
|
||||
|
||||
switch_channel_set_flag(channel, CF_OUTBOUND);
|
||||
switch_mutex_lock(tech_pvt->flag_mutex);
|
||||
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
|
||||
switch_mutex_unlock(tech_pvt->flag_mutex);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
# Add your debugging flag (or not) to CFLAGS
|
||||
ifeq ($(DEBUG),y)
|
||||
DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
|
||||
DEBFLAGS = -O -g -DSKYPOPEN_DEBUG # "-O" is needed to expand inlines
|
||||
else
|
||||
DEBFLAGS = -O2 -Wall
|
||||
endif
|
||||
|
@ -15,9 +15,9 @@ EXTRA_CFLAGS += -I$(LDDINC)
|
|||
ifneq ($(KERNELRELEASE),)
|
||||
# call from kernel build system
|
||||
|
||||
scull-objs := main.o
|
||||
skypopen-objs := main.o
|
||||
|
||||
obj-m := scull.o
|
||||
obj-m := skypopen.o
|
||||
|
||||
else
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* main.c -- the bare scull char module
|
||||
* main.c -- the bare skypopen char module
|
||||
*
|
||||
* Copyright (C) 2010 Giovanni Maruzzelli
|
||||
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
|
||||
|
@ -41,117 +41,198 @@
|
|||
#include <linux/hrtimer.h>
|
||||
#include <linux/ktime.h>
|
||||
|
||||
#include "scull.h" /* local definitions */
|
||||
#include "skypopen.h" /* local definitions */
|
||||
|
||||
/*
|
||||
* Our parameters which can be set at load time.
|
||||
*/
|
||||
|
||||
int scull_major = SCULL_MAJOR;
|
||||
int scull_minor = 3;
|
||||
int scull_nr_devs = SCULL_NR_DEVS; /* number of bare scull devices */
|
||||
int skypopen_major = SKYPOPEN_MAJOR;
|
||||
int skypopen_minor = 3;
|
||||
int skypopen_nr_devs = SKYPOPEN_NR_DEVS; /* number of bare skypopen devices */
|
||||
|
||||
module_param(scull_major, int, S_IRUGO);
|
||||
module_param(scull_minor, int, S_IRUGO);
|
||||
module_param(scull_nr_devs, int, S_IRUGO);
|
||||
module_param(skypopen_major, int, S_IRUGO);
|
||||
module_param(skypopen_minor, int, S_IRUGO);
|
||||
module_param(skypopen_nr_devs, int, S_IRUGO);
|
||||
|
||||
MODULE_AUTHOR("Original: Alessandro Rubini, Jonathan Corbet. Heavy modified by: Giovanni Maruzzelli");
|
||||
MODULE_AUTHOR("Original: Alessandro Rubini, Jonathan Corbet. Modified by: Giovanni Maruzzelli for FreeSWITCH skypopen");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
static struct scull_dev *scull_devices; /* allocated in scull_init_module */
|
||||
static struct skypopen_dev *skypopen_devices; /* allocated in skypopen_init_module */
|
||||
|
||||
#define GIOVA_BLK 1920
|
||||
#define GIOVA_SLEEP 20
|
||||
static int unload = 0;
|
||||
#ifdef CENTOS
|
||||
#define HRTIMER_MODE_REL HRTIMER_REL
|
||||
#endif// CENTOS
|
||||
|
||||
#ifndef WANT_HRTIMER
|
||||
void my_timer_callback_inq( unsigned long data )
|
||||
{
|
||||
struct scull_dev *dev = (void *)data;
|
||||
struct skypopen_dev *dev = (void *)data;
|
||||
|
||||
//dev->readable=1;
|
||||
wake_up_interruptible(&dev->inq);
|
||||
mod_timer( &dev->timer_inq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) );
|
||||
mod_timer( &dev->timer_inq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
|
||||
|
||||
}
|
||||
|
||||
void my_timer_callback_outq( unsigned long data )
|
||||
{
|
||||
struct scull_dev *dev = (void *)data;
|
||||
struct skypopen_dev *dev = (void *)data;
|
||||
|
||||
//dev->writable=1;
|
||||
wake_up_interruptible(&dev->outq);
|
||||
mod_timer( &dev->timer_outq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) );
|
||||
mod_timer( &dev->timer_outq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
|
||||
}
|
||||
#else// WANT_HRTIMER
|
||||
|
||||
#ifndef CENTOS
|
||||
static enum hrtimer_restart my_hrtimer_callback_inq( struct hrtimer *timer_inq )
|
||||
{
|
||||
struct skypopen_dev *dev = container_of(timer_inq, struct skypopen_dev, timer_inq);
|
||||
ktime_t now;
|
||||
|
||||
if(unload)
|
||||
return HRTIMER_NORESTART;
|
||||
|
||||
now = ktime_get();
|
||||
hrtimer_forward(&dev->timer_inq, now, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
|
||||
wake_up_interruptible(&dev->inq);
|
||||
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
static enum hrtimer_restart my_hrtimer_callback_outq( struct hrtimer *timer_outq )
|
||||
{
|
||||
struct skypopen_dev *dev = container_of(timer_outq, struct skypopen_dev, timer_outq);
|
||||
ktime_t now;
|
||||
|
||||
if(unload)
|
||||
return HRTIMER_NORESTART;
|
||||
|
||||
now = ktime_get();
|
||||
hrtimer_forward(&dev->timer_outq, now, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
|
||||
wake_up_interruptible(&dev->outq);
|
||||
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
#else// CENTOS
|
||||
static int my_hrtimer_callback_inq( struct hrtimer *timer_inq )
|
||||
{
|
||||
struct skypopen_dev *dev = container_of(timer_inq, struct skypopen_dev, timer_inq);
|
||||
|
||||
if(unload)
|
||||
return HRTIMER_NORESTART;
|
||||
|
||||
hrtimer_forward(&dev->timer_inq, timer_inq->expires, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
|
||||
wake_up_interruptible(&dev->inq);
|
||||
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
static int my_hrtimer_callback_outq( struct hrtimer *timer_outq )
|
||||
{
|
||||
struct skypopen_dev *dev = container_of(timer_outq, struct skypopen_dev, timer_outq);
|
||||
|
||||
if(unload)
|
||||
return HRTIMER_NORESTART;
|
||||
|
||||
hrtimer_forward(&dev->timer_outq, timer_outq->expires, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
|
||||
wake_up_interruptible(&dev->outq);
|
||||
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
#endif// CENTOS
|
||||
#endif// WANT_HRTIMER
|
||||
|
||||
/* The clone-specific data structure includes a key field */
|
||||
|
||||
struct scull_listitem {
|
||||
struct scull_dev device;
|
||||
struct skypopen_listitem {
|
||||
struct skypopen_dev device;
|
||||
dev_t key;
|
||||
struct list_head list;
|
||||
|
||||
};
|
||||
|
||||
/* The list of devices, and a lock to protect it */
|
||||
static LIST_HEAD(scull_c_list);
|
||||
static spinlock_t scull_c_lock = SPIN_LOCK_UNLOCKED;
|
||||
static LIST_HEAD(skypopen_c_list);
|
||||
static spinlock_t skypopen_c_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
/* Look for a device or create one if missing */
|
||||
static struct scull_dev *scull_c_lookfor_device(dev_t key)
|
||||
static struct skypopen_dev *skypopen_c_lookfor_device(dev_t key)
|
||||
{
|
||||
struct scull_listitem *lptr;
|
||||
struct skypopen_listitem *lptr;
|
||||
#ifdef WANT_HRTIMER
|
||||
#if 0
|
||||
ktime_t ktime_inq;
|
||||
ktime_t ktime_outq;
|
||||
#endif //0
|
||||
#endif// WANT_HRTIMER
|
||||
|
||||
list_for_each_entry(lptr, &scull_c_list, list) {
|
||||
list_for_each_entry(lptr, &skypopen_c_list, list) {
|
||||
if (lptr->key == key)
|
||||
return &(lptr->device);
|
||||
}
|
||||
|
||||
/* not found */
|
||||
lptr = kmalloc(sizeof(struct scull_listitem), GFP_KERNEL);
|
||||
lptr = kmalloc(sizeof(struct skypopen_listitem), GFP_KERNEL);
|
||||
if (!lptr)
|
||||
return NULL;
|
||||
|
||||
/* initialize the device */
|
||||
memset(lptr, 0, sizeof(struct scull_listitem));
|
||||
memset(lptr, 0, sizeof(struct skypopen_listitem));
|
||||
lptr->key = key;
|
||||
|
||||
init_waitqueue_head(&lptr->device.inq);
|
||||
init_waitqueue_head(&lptr->device.outq);
|
||||
printk(" Timer installing\n");
|
||||
#ifndef WANT_HRTIMER
|
||||
setup_timer( &lptr->device.timer_inq, my_timer_callback_inq, (long int)lptr );
|
||||
setup_timer( &lptr->device.timer_outq, my_timer_callback_outq, (long int)lptr );
|
||||
printk( "Starting timer to fire in %dms (%ld)\n", GIOVA_SLEEP, jiffies );
|
||||
mod_timer( &lptr->device.timer_inq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) );
|
||||
mod_timer( &lptr->device.timer_outq, jiffies + msecs_to_jiffies(GIOVA_SLEEP) );
|
||||
printk( "Starting skypopen OSS driver read timer (%dms) skype client:(%d)\n", SKYPOPEN_SLEEP, current->tgid );
|
||||
mod_timer( &lptr->device.timer_inq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
|
||||
printk( "Starting skypopen OSS driver write timer (%dms) skype client:(%d)\n", SKYPOPEN_SLEEP, current->tgid );
|
||||
mod_timer( &lptr->device.timer_outq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
|
||||
#else// WANT_HRTIMER
|
||||
#if 0
|
||||
ktime_inq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
|
||||
hrtimer_init( &lptr->device.timer_inq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
|
||||
lptr->device.timer_inq.function = &my_hrtimer_callback_inq;
|
||||
hrtimer_start( &lptr->device.timer_inq, ktime_inq, HRTIMER_MODE_REL );
|
||||
|
||||
ktime_outq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
|
||||
hrtimer_init( &lptr->device.timer_outq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
|
||||
lptr->device.timer_outq.function = &my_hrtimer_callback_outq;
|
||||
hrtimer_start( &lptr->device.timer_outq, ktime_outq, HRTIMER_MODE_REL );
|
||||
#endif
|
||||
|
||||
#endif// WANT_HRTIMER
|
||||
|
||||
/* place it in the list */
|
||||
list_add(&lptr->list, &scull_c_list);
|
||||
list_add(&lptr->list, &skypopen_c_list);
|
||||
|
||||
return &(lptr->device);
|
||||
}
|
||||
static int scull_c_open(struct inode *inode, struct file *filp)
|
||||
|
||||
/*
|
||||
* Open and close
|
||||
*/
|
||||
static int skypopen_c_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct scull_dev *dev;
|
||||
struct skypopen_dev *dev;
|
||||
dev_t key;
|
||||
|
||||
if (!current->pid) {
|
||||
printk("Process \"%s\" has no pid\n", current->comm);
|
||||
return -EINVAL;
|
||||
}
|
||||
key = current->pid;
|
||||
key = current->tgid;
|
||||
|
||||
/* look for a scullc device in the list */
|
||||
spin_lock(&scull_c_lock);
|
||||
dev = scull_c_lookfor_device(key);
|
||||
spin_unlock(&scull_c_lock);
|
||||
/* look for a skypopenc device in the list */
|
||||
spin_lock(&skypopen_c_lock);
|
||||
dev = skypopen_c_lookfor_device(key);
|
||||
spin_unlock(&skypopen_c_lock);
|
||||
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* then, everything else is copied from the bare scull device */
|
||||
/* then, everything else is copied from the bare skypopen device */
|
||||
filp->private_data = dev;
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
static int scull_c_release(struct inode *inode, struct file *filp)
|
||||
static int skypopen_c_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
/*
|
||||
* Nothing to do, because the device is persistent.
|
||||
|
@ -163,39 +244,59 @@ static int scull_c_release(struct inode *inode, struct file *filp)
|
|||
|
||||
|
||||
/*************************************************************/
|
||||
/*
|
||||
* Open and close
|
||||
*/
|
||||
|
||||
ssize_t scull_read(struct file *filp, char __user *buf, size_t count,
|
||||
static ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count,
|
||||
loff_t *f_pos)
|
||||
{
|
||||
struct scull_dev *dev = filp->private_data;
|
||||
|
||||
DEFINE_WAIT(wait);
|
||||
struct skypopen_dev *dev = filp->private_data;
|
||||
#ifdef WANT_HRTIMER
|
||||
#if 1
|
||||
if(dev->timer_inq_started == 0){
|
||||
ktime_t ktime_inq;
|
||||
|
||||
ktime_inq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
|
||||
hrtimer_init( &dev->timer_inq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
|
||||
dev->timer_inq.function = &my_hrtimer_callback_inq;
|
||||
hrtimer_start( &dev->timer_inq, ktime_inq, HRTIMER_MODE_REL );
|
||||
dev->timer_inq_started = 1;
|
||||
}
|
||||
#endif
|
||||
#endif// WANT_HRTIMER
|
||||
|
||||
|
||||
//printk("READ\n");
|
||||
prepare_to_wait(&dev->inq, &wait, TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
finish_wait(&dev->inq, &wait);
|
||||
//memset(buf, 255, count);
|
||||
|
||||
//wait_event_interruptible(dev->inq, dev->readable);
|
||||
//dev->readable=0;
|
||||
return count;
|
||||
|
||||
}
|
||||
|
||||
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,
|
||||
static ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count,
|
||||
loff_t *f_pos)
|
||||
{
|
||||
struct scull_dev *dev = filp->private_data;
|
||||
DEFINE_WAIT(wait);
|
||||
struct skypopen_dev *dev = filp->private_data;
|
||||
#ifdef WANT_HRTIMER
|
||||
#if 1
|
||||
if(dev->timer_outq_started == 0){
|
||||
ktime_t ktime_outq;
|
||||
|
||||
ktime_outq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
|
||||
hrtimer_init( &dev->timer_outq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
|
||||
dev->timer_outq.function = &my_hrtimer_callback_outq;
|
||||
hrtimer_start( &dev->timer_outq, ktime_outq, HRTIMER_MODE_REL );
|
||||
dev->timer_outq_started = 1;
|
||||
}
|
||||
#endif
|
||||
#endif// WANT_HRTIMER
|
||||
|
||||
|
||||
//printk("WRITE\n");
|
||||
prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
finish_wait(&dev->outq, &wait);
|
||||
|
||||
//wait_event_interruptible(dev->outq, dev->writable);
|
||||
//dev->writable=0;
|
||||
|
||||
return count;
|
||||
|
||||
}
|
||||
|
@ -203,7 +304,7 @@ ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,
|
|||
* The ioctl() implementation
|
||||
*/
|
||||
|
||||
int scull_ioctl(struct inode *inode, struct file *filp,
|
||||
static int skypopen_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
@ -213,7 +314,7 @@ int scull_ioctl(struct inode *inode, struct file *filp,
|
|||
case OSS_GETVERSION:
|
||||
return put_user(SOUND_VERSION, p);
|
||||
case SNDCTL_DSP_GETBLKSIZE:
|
||||
return put_user(GIOVA_BLK, p);
|
||||
return put_user(SKYPOPEN_BLK, p);
|
||||
case SNDCTL_DSP_GETFMTS:
|
||||
return put_user(28731, p);
|
||||
|
||||
|
@ -223,14 +324,14 @@ int scull_ioctl(struct inode *inode, struct file *filp,
|
|||
|
||||
}
|
||||
|
||||
struct file_operations scull_fops = {
|
||||
struct file_operations skypopen_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = scull_read,
|
||||
.write = scull_write,
|
||||
.ioctl = scull_ioctl,
|
||||
.open = scull_c_open,
|
||||
.release = scull_c_release,
|
||||
.read = skypopen_read,
|
||||
.write = skypopen_write,
|
||||
.ioctl = skypopen_ioctl,
|
||||
.open = skypopen_c_open,
|
||||
.release = skypopen_c_release,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -243,34 +344,46 @@ struct file_operations scull_fops = {
|
|||
* have not been initialized
|
||||
*/
|
||||
|
||||
void scull_cleanup_module(void)
|
||||
void skypopen_cleanup_module(void)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
struct scull_listitem *lptr, *next;
|
||||
dev_t devno = MKDEV(scull_major, scull_minor);
|
||||
struct skypopen_listitem *lptr, *next;
|
||||
dev_t devno = MKDEV(skypopen_major, skypopen_minor);
|
||||
|
||||
|
||||
unload = 1;
|
||||
|
||||
msleep(100);
|
||||
|
||||
/* Get rid of our char dev entries */
|
||||
if (scull_devices) {
|
||||
for (i = 0; i < scull_nr_devs; i++) {
|
||||
cdev_del(&scull_devices[i].cdev);
|
||||
if (skypopen_devices) {
|
||||
for (i = 0; i < skypopen_nr_devs; i++) {
|
||||
cdev_del(&skypopen_devices[i].cdev);
|
||||
}
|
||||
kfree(scull_devices);
|
||||
kfree(skypopen_devices);
|
||||
}
|
||||
|
||||
|
||||
/* And all the cloned devices */
|
||||
list_for_each_entry_safe(lptr, next, &scull_c_list, list) {
|
||||
list_for_each_entry_safe(lptr, next, &skypopen_c_list, list) {
|
||||
#ifndef WANT_HRTIMER
|
||||
ret= del_timer( &lptr->device.timer_inq );
|
||||
if (ret) printk("The inq timer was still in use...\n");
|
||||
printk( "Stopped skypopen OSS driver read timer\n");
|
||||
ret= del_timer( &lptr->device.timer_outq );
|
||||
if (ret) printk("The outq timer was still in use...\n");
|
||||
printk( "Stopped skypopen OSS driver write timer\n");
|
||||
#else// WANT_HRTIMER
|
||||
ret = hrtimer_cancel( &lptr->device.timer_inq );
|
||||
printk( "Stopped skypopen OSS driver read HRtimer\n");
|
||||
ret = hrtimer_cancel( &lptr->device.timer_outq );
|
||||
printk( "Stopped skypopen OSS driver write HRtimer\n");
|
||||
|
||||
#endif// WANT_HRTIMER
|
||||
list_del(&lptr->list);
|
||||
kfree(lptr);
|
||||
}
|
||||
printk("Timer uninstalling\n");
|
||||
/* cleanup_module is never called if registering failed */
|
||||
unregister_chrdev_region(devno, scull_nr_devs);
|
||||
unregister_chrdev_region(devno, skypopen_nr_devs);
|
||||
printk("skypopen OSS driver unloaded\n");
|
||||
|
||||
}
|
||||
|
||||
|
@ -278,40 +391,41 @@ void scull_cleanup_module(void)
|
|||
/*
|
||||
* Set up the char_dev structure for this device.
|
||||
*/
|
||||
static void scull_setup_cdev(struct scull_dev *dev, int index)
|
||||
static void skypopen_setup_cdev(struct skypopen_dev *dev, int index)
|
||||
{
|
||||
int err, devno = MKDEV(scull_major, scull_minor + index);
|
||||
int err, devno = MKDEV(skypopen_major, skypopen_minor + index);
|
||||
|
||||
cdev_init(&dev->cdev, &scull_fops);
|
||||
cdev_init(&dev->cdev, &skypopen_fops);
|
||||
dev->cdev.owner = THIS_MODULE;
|
||||
dev->cdev.ops = &scull_fops;
|
||||
dev->cdev.ops = &skypopen_fops;
|
||||
err = cdev_add (&dev->cdev, devno, 1);
|
||||
/* Fail gracefully if need be */
|
||||
if (err)
|
||||
printk(KERN_NOTICE "Error %d adding scull%d", err, index);
|
||||
printk(KERN_NOTICE "Error %d adding skypopen%d", err, index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int scull_init_module(void)
|
||||
int skypopen_init_module(void)
|
||||
{
|
||||
int result, i;
|
||||
dev_t dev = 0;
|
||||
|
||||
printk("skypopen OSS driver loading (www.freeswitch.org)\n");
|
||||
/*
|
||||
* Get a range of minor numbers to work with, asking for a dynamic
|
||||
* major unless directed otherwise at load time.
|
||||
*/
|
||||
if (scull_major) {
|
||||
dev = MKDEV(scull_major, scull_minor);
|
||||
result = register_chrdev_region(dev, scull_nr_devs, "dsp");
|
||||
if (skypopen_major) {
|
||||
dev = MKDEV(skypopen_major, skypopen_minor);
|
||||
result = register_chrdev_region(dev, skypopen_nr_devs, "dsp");
|
||||
} else {
|
||||
result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,
|
||||
result = alloc_chrdev_region(&dev, skypopen_minor, skypopen_nr_devs,
|
||||
"dsp");
|
||||
scull_major = MAJOR(dev);
|
||||
skypopen_major = MAJOR(dev);
|
||||
}
|
||||
if (result < 0) {
|
||||
printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
|
||||
printk(KERN_WARNING "skypopen OSS driver: can't get major %d\n", skypopen_major);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -319,26 +433,26 @@ int scull_init_module(void)
|
|||
* allocate the devices -- we can't have them static, as the number
|
||||
* can be specified at load time
|
||||
*/
|
||||
scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
|
||||
if (!scull_devices) {
|
||||
skypopen_devices = kmalloc(skypopen_nr_devs * sizeof(struct skypopen_dev), GFP_KERNEL);
|
||||
if (!skypopen_devices) {
|
||||
result = -ENOMEM;
|
||||
goto fail; /* Make this more graceful */
|
||||
}
|
||||
memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev));
|
||||
memset(skypopen_devices, 0, skypopen_nr_devs * sizeof(struct skypopen_dev));
|
||||
|
||||
/* Initialize each device. */
|
||||
for (i = 0; i < scull_nr_devs; i++) {
|
||||
scull_setup_cdev(&scull_devices[i], i);
|
||||
for (i = 0; i < skypopen_nr_devs; i++) {
|
||||
skypopen_setup_cdev(&skypopen_devices[i], i);
|
||||
}
|
||||
|
||||
/* At this point call the init function for any friend device */
|
||||
dev = MKDEV(scull_major, scull_minor + scull_nr_devs);
|
||||
dev = MKDEV(skypopen_major, skypopen_minor + skypopen_nr_devs);
|
||||
return 0; /* succeed */
|
||||
|
||||
fail:
|
||||
scull_cleanup_module();
|
||||
skypopen_cleanup_module();
|
||||
return result;
|
||||
}
|
||||
|
||||
module_init(scull_init_module);
|
||||
module_exit(scull_cleanup_module);
|
||||
module_init(skypopen_init_module);
|
||||
module_exit(skypopen_cleanup_module);
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* scull.h -- definitions for the char module
|
||||
*
|
||||
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
|
||||
* Copyright (C) 2001 O'Reilly & Associates
|
||||
*
|
||||
* The source code in this file can be freely used, adapted,
|
||||
* and redistributed in source or binary form, so long as an
|
||||
* acknowledgment appears in derived source files. The citation
|
||||
* should list that the code comes from the book "Linux Device
|
||||
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
|
||||
* by O'Reilly & Associates. No warranty is attached;
|
||||
* we cannot take responsibility for errors or fitness for use.
|
||||
*
|
||||
* $Id: scull.h,v 1.15 2004/11/04 17:51:18 rubini Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SCULL_H_
|
||||
#define _SCULL_H_
|
||||
|
||||
#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */
|
||||
|
||||
#ifndef SCULL_MAJOR
|
||||
#define SCULL_MAJOR 14 /* dynamic major by default */
|
||||
#endif
|
||||
|
||||
#ifndef SCULL_NR_DEVS
|
||||
#define SCULL_NR_DEVS 1 /* scull0 through scull3 */
|
||||
#endif
|
||||
|
||||
struct scull_dev {
|
||||
struct cdev cdev; /* Char device structure */
|
||||
wait_queue_head_t inq; /* read and write queues */
|
||||
wait_queue_head_t outq; /* read and write queues */
|
||||
struct timer_list timer_inq;
|
||||
struct timer_list timer_outq;
|
||||
int readable;
|
||||
int writable;
|
||||
//unsigned long read_howmany;
|
||||
//unsigned long write_howmany;
|
||||
//unsigned long read_sleeped_acc;
|
||||
//unsigned long write_sleeped_acc;
|
||||
//double read_delay; /* how much delay last time */
|
||||
//double write_delay; /* how much delay last time */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The different configurable parameters
|
||||
*/
|
||||
extern int scull_major; /* main.c */
|
||||
extern int scull_nr_devs;
|
||||
|
||||
|
||||
/*
|
||||
* Prototypes for shared functions
|
||||
*/
|
||||
|
||||
ssize_t scull_read(struct file *filp, char __user *buf, size_t count,
|
||||
loff_t *f_pos);
|
||||
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,
|
||||
loff_t *f_pos);
|
||||
int scull_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
#endif /* _SCULL_H_ */
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* skypopen.h -- definitions for the char module
|
||||
*
|
||||
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
|
||||
* Copyright (C) 2001 O'Reilly & Associates
|
||||
*
|
||||
* The source code in this file can be freely used, adapted,
|
||||
* and redistributed in source or binary form, so long as an
|
||||
* acknowledgment appears in derived source files. The citation
|
||||
* should list that the code comes from the book "Linux Device
|
||||
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
|
||||
* by O'Reilly & Associates. No warranty is attached;
|
||||
* we cannot take responsibility for errors or fitness for use.
|
||||
*
|
||||
* $Id: skypopen.h,v 1.15 2004/11/04 17:51:18 rubini Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SKYPOPEN_H_
|
||||
#define _SKYPOPEN_H_
|
||||
|
||||
#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */
|
||||
|
||||
#define SKYPOPEN_BLK 960
|
||||
#define SKYPOPEN_SLEEP 10
|
||||
|
||||
#define CENTOS
|
||||
|
||||
#ifndef SKYPOPEN_MAJOR
|
||||
#define SKYPOPEN_MAJOR 14 /* dynamic major by default */
|
||||
#endif
|
||||
|
||||
#ifndef SKYPOPEN_NR_DEVS
|
||||
#define SKYPOPEN_NR_DEVS 1 /* skypopen0 through skypopen3 */
|
||||
#endif
|
||||
|
||||
#define WANT_HRTIMER
|
||||
struct skypopen_dev {
|
||||
struct cdev cdev; /* Char device structure */
|
||||
wait_queue_head_t inq; /* read and write queues */
|
||||
wait_queue_head_t outq; /* read and write queues */
|
||||
#ifndef WANT_HRTIMER
|
||||
struct timer_list timer_inq;
|
||||
struct timer_list timer_outq;
|
||||
#else// WANT_HRTIMER
|
||||
struct hrtimer timer_inq;
|
||||
struct hrtimer timer_outq;
|
||||
#endif// WANT_HRTIMER
|
||||
int timer_inq_started;
|
||||
int timer_outq_started;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The different configurable parameters
|
||||
*/
|
||||
extern int skypopen_major; /* main.c */
|
||||
extern int skypopen_nr_devs;
|
||||
|
||||
|
||||
/*
|
||||
* Prototypes for shared functions
|
||||
*/
|
||||
|
||||
//ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count,
|
||||
//loff_t *f_pos);
|
||||
//ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count,
|
||||
//loff_t *f_pos);
|
||||
//int skypopen_ioctl(struct inode *inode, struct file *filp,
|
||||
//unsigned int cmd, unsigned long arg);
|
||||
|
||||
#endif /* _SKYPOPEN_H_ */
|
|
@ -508,7 +508,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
|
|||
TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)), TAG_END());
|
||||
}
|
||||
} else {
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending CANCEL to %s\n", switch_channel_get_name(channel));
|
||||
if (!tech_pvt->got_bye) {
|
||||
switch_channel_set_variable(channel, "sip_hangup_disposition", "send_cancel");
|
||||
|
@ -573,7 +573,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
|
|||
char *sticky = NULL;
|
||||
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
|
||||
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -653,7 +653,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
|
|||
switch_channel_clear_flag(channel, CF_PROXY_MODE);
|
||||
}
|
||||
|
||||
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
|
||||
tech_pvt->num_codecs = 0;
|
||||
sofia_glue_tech_prepare_codecs(tech_pvt);
|
||||
|
@ -1339,6 +1339,17 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
|||
|
||||
if (msg->string_arg) {
|
||||
char *p;
|
||||
const char *s;
|
||||
|
||||
if (!strncasecmp(msg->string_arg, "debug:", 6)) {
|
||||
s = msg->string_arg + 6;
|
||||
if (s && !strcmp(s, "off")) {
|
||||
s = NULL;
|
||||
}
|
||||
switch_rtp_debug_jitter_buffer(tech_pvt->rtp_session, s);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
if ((len = atoi(msg->string_arg))) {
|
||||
qlen = len / (tech_pvt->read_impl.microseconds_per_packet / 1000);
|
||||
|
@ -1672,7 +1683,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
|||
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
|
||||
|
||||
if (!(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag(channel, CF_EARLY_MEDIA))) {
|
||||
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
|
||||
|
||||
tech_pvt->num_codecs = 0;
|
||||
|
@ -2187,7 +2198,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
|||
} else {
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || !tech_pvt->iananame) {
|
||||
sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION);
|
||||
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
|
||||
|
||||
tech_pvt->num_codecs = 0;
|
||||
|
|
|
@ -357,7 +357,7 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
switch_channel_answer(channel);
|
||||
switch_channel_set_variable(channel, "auto_answer_destination", switch_channel_get_variable(channel, "destination_number"));
|
||||
switch_ivr_session_transfer(session, "auto_answer", NULL, NULL);
|
||||
|
@ -4114,7 +4114,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|
|||
|
||||
}
|
||||
|
||||
if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
sip_contact_t *p_contact = sip->sip_contact;
|
||||
int i = 0;
|
||||
char var_name[80];
|
||||
|
@ -4645,7 +4645,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
status = 183;
|
||||
}
|
||||
|
||||
if (channel && (status == 180 || status == 183) && switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
const char *val;
|
||||
if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) {
|
||||
nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR("talk"), TAG_END());
|
||||
|
@ -4692,7 +4692,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
|
||||
if (r_sdp) {
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA");
|
||||
}
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
|
||||
|
@ -4715,7 +4715,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
}
|
||||
goto done;
|
||||
} else {
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "DELAYED NEGOTIATION");
|
||||
} else {
|
||||
if (sofia_glue_tech_media(tech_pvt, (char *) r_sdp) != SWITCH_STATUS_SUCCESS) {
|
||||
|
@ -4910,7 +4910,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
|||
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
|
||||
|
||||
if (!switch_channel_media_ready(channel)) {
|
||||
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
//const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
|
||||
|
||||
tech_pvt->num_codecs = 0;
|
||||
|
@ -6255,7 +6255,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
|
|||
|
||||
if (!is_nat && profile->nat_acl_count) {
|
||||
uint32_t x = 0;
|
||||
int ok = 1;
|
||||
int contact_private_ip = 1;
|
||||
int network_private_ip = 0;
|
||||
char *last_acl = NULL;
|
||||
const char *contact_host = NULL;
|
||||
|
||||
|
@ -6264,35 +6265,37 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
|
|||
}
|
||||
|
||||
if (!zstr(contact_host)) {
|
||||
/* NAT mode double check logic and examples.
|
||||
|
||||
Example 1: the contact_host is 192.168.1.100 and the network_ip is also 192.168.1.100 the end point
|
||||
is most likely behind nat with us so we need to veto that decision to turn on nat processing.
|
||||
|
||||
Example 2: the contact_host is 192.168.1.100 and the network_ip is 192.0.2.100 which is a public internet ip
|
||||
the remote endpoint is likely behind a remote nat traversing the public internet.
|
||||
|
||||
This secondary check is here to double check the conclusion of nat settigs to ensure we don't set net
|
||||
in cases where we don't really need to be doing this.
|
||||
|
||||
Why would you want to do this? Well if your FreeSWITCH is behind nat and you want to talk to endpoints behind
|
||||
remote NAT over the public internet in addition to endpoints behind nat with you. This simplifies that process.
|
||||
|
||||
*/
|
||||
|
||||
for (x = 0; x < profile->nat_acl_count; x++) {
|
||||
last_acl = profile->nat_acl[x];
|
||||
if (!(ok = switch_check_network_list_ip(contact_host, last_acl))) {
|
||||
/* NAT mode double check logic and examples.
|
||||
|
||||
Example 1: the contact_host is 192.168.1.100 and the network_ip is also 192.168.1.100 the end point
|
||||
is most likely behind nat with us so we need to veto that decision to turn on nat processing.
|
||||
|
||||
Example 2: the contact_host is 192.168.1.100 and the network_ip is 192.0.2.100 which is a public internet ip
|
||||
the remote endpoint is likely behind a remote nat traversing the public internet.
|
||||
|
||||
This secondary check is here to double check the conclusion of nat settigs to ensure we don't set net
|
||||
in cases where we don't really need to be doing this.
|
||||
|
||||
Why would you want to do this? Well if your FreeSWITCH is behind nat and you want to talk to endpoints behind
|
||||
remote NAT over the public internet in addition to endpoints behind nat with you. This simplifies that process.
|
||||
|
||||
*/
|
||||
if ((ok = switch_check_network_list_ip(network_ip, last_acl))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Endpoint is already inside nat with us.\n");
|
||||
ok = 0;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Decision stands they are behind nat.\n");
|
||||
}
|
||||
if ((contact_private_ip = switch_check_network_list_ip(contact_host, last_acl))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (contact_private_ip) {
|
||||
for (x = 0; x < profile->nat_acl_count; x++) {
|
||||
if ((network_private_ip = switch_check_network_list_ip(network_ip, profile->nat_acl[x]))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (contact_private_ip && !network_private_ip) {
|
||||
is_nat = last_acl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4687,8 +4687,8 @@ void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp)
|
|||
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, sdp);
|
||||
|
||||
if (!sofia_test_flag(tech_pvt, TFLAG_CHANGE_MEDIA) && !sofia_test_flag(tech_pvt, TFLAG_RECOVERING) &&
|
||||
(switch_channel_test_flag(other_channel, CF_OUTBOUND) &&
|
||||
switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND) && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) {
|
||||
(switch_channel_direction(other_channel) == SWITCH_CALL_DIRECTION_OUTBOUND &&
|
||||
switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) {
|
||||
switch_ivr_nomedia(val, SMF_FORCE);
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_CHANGE_MEDIA);
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
*/
|
||||
#include <switch.h>
|
||||
#define CMD_BUFLEN 1024 * 1000
|
||||
#define MAX_QUEUE_LEN 5000
|
||||
#define MAX_MISSED 200
|
||||
#define MAX_QUEUE_LEN 25000
|
||||
#define MAX_MISSED 2000
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_event_socket_load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_event_socket_shutdown);
|
||||
SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_socket_runtime);
|
||||
|
@ -170,7 +170,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l
|
|||
if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) {
|
||||
switch_log_node_t *dnode = switch_log_node_dup(node);
|
||||
|
||||
if (switch_queue_trypush(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) {
|
||||
if (switch_queue_push(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) {
|
||||
if (l->lost_logs) {
|
||||
int ll = l->lost_logs;
|
||||
switch_event_t *event;
|
||||
|
@ -366,7 +366,7 @@ static void event_handler(switch_event_t *event)
|
|||
|
||||
if (send) {
|
||||
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
|
||||
if (switch_queue_trypush(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) {
|
||||
if (switch_queue_push(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) {
|
||||
if (l->lost_events) {
|
||||
int le = l->lost_events;
|
||||
l->lost_events = 0;
|
||||
|
@ -1233,7 +1233,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
|
|||
if (switch_channel_get_state(chan) < CS_HANGUP && switch_channel_test_flag(chan, CF_DIVERT_EVENTS)) {
|
||||
switch_event_t *e = NULL;
|
||||
while (switch_core_session_dequeue_event(listener->session, &e, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
|
||||
if (switch_queue_trypush(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) {
|
||||
if (switch_queue_push(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_core_session_queue_event(listener->session, &e);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2386,6 +2386,8 @@ SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *chann
|
|||
{
|
||||
switch_assert(channel != NULL);
|
||||
|
||||
switch_channel_set_flag(channel, CF_DIALPLAN);
|
||||
|
||||
switch_mutex_lock(channel->profile_mutex);
|
||||
caller_extension->next = channel->caller_profile->caller_extension;
|
||||
channel->caller_profile->caller_extension = caller_extension;
|
||||
|
@ -2622,7 +2624,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_pre_answer(switch_channel
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_PROGRESS;
|
||||
msg.from = channel->name;
|
||||
status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
|
||||
|
@ -2657,7 +2659,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready_value(switch_c
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING;
|
||||
msg.from = channel->name;
|
||||
msg.numeric_arg = rv;
|
||||
|
@ -2800,7 +2802,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t *
|
|||
|
||||
switch_assert(channel != NULL);
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ static void switch_core_standard_on_routing(switch_core_session_t *session)
|
|||
}
|
||||
|
||||
if (!count) {
|
||||
if (switch_channel_test_flag(session->channel, CF_OUTBOUND)) {
|
||||
if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
if (switch_channel_test_flag(session->channel, CF_ANSWERED)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"No Dialplan on answered channel, changing state to HANGUP\n");
|
||||
|
|
|
@ -1206,7 +1206,7 @@ SWITCH_DECLARE(void) bridge(CoreSession &session_a, CoreSession &session_b)
|
|||
|
||||
if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) {
|
||||
session_a.begin_allow_threads();
|
||||
if (!switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_media_ready(channel_a)) {
|
||||
if (switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_media_ready(channel_a)) {
|
||||
switch_channel_pre_answer(channel_a);
|
||||
}
|
||||
|
||||
|
|
|
@ -339,7 +339,7 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
|
|||
launch_dispatch_threads(SOFT_MAX_DISPATCH + 1, DISPATCH_QUEUE_LEN, RUNTIME_POOL);
|
||||
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of threads!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of event dispatch threads! Slowing things down.\n");
|
||||
switch_yield(1000000);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
|
|||
const char *var;
|
||||
|
||||
/*
|
||||
if (!switch_channel_test_flag(channel, CF_OUTBOUND) && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
|
||||
!switch_channel_media_ready(channel) && !switch_channel_test_flag(channel, CF_SERVICE)) {
|
||||
if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot establish media.\n");
|
||||
|
@ -2300,7 +2300,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3
|
|||
break;
|
||||
}
|
||||
|
||||
stfu_n_eat(jb, ts, 0, read_frame->payload, read_frame->data, read_frame->datalen);
|
||||
stfu_n_eat(jb, ts, read_frame->payload, read_frame->data, read_frame->datalen);
|
||||
ts += interval;
|
||||
|
||||
if ((jb_frame = stfu_n_read_a_frame(jb))) {
|
||||
|
|
|
@ -100,7 +100,7 @@ static void send_display(switch_core_session_t *session, switch_core_session_t *
|
|||
caller_channel = switch_core_session_get_channel(session);
|
||||
caller_profile = switch_channel_get_caller_profile(caller_channel);
|
||||
|
||||
if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(caller_channel, CF_DIALPLAN)) {
|
||||
name = caller_profile->callee_id_name;
|
||||
number = caller_profile->callee_id_number;
|
||||
|
||||
|
@ -435,8 +435,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
switch_channel_t *un = ans_a ? chan_b : chan_a;
|
||||
switch_channel_t *a = un == chan_b ? chan_a : chan_b;
|
||||
|
||||
if (!switch_channel_test_flag(un, CF_OUTBOUND)) {
|
||||
if (switch_channel_test_flag(a, CF_OUTBOUND) || (un == chan_a && !originator)) {
|
||||
if (switch_channel_direction(un) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
if (switch_channel_direction(a) == SWITCH_CALL_DIRECTION_OUTBOUND || (un == chan_a && !originator)) {
|
||||
switch_channel_pass_callee_id(a, un);
|
||||
}
|
||||
|
||||
|
|
|
@ -1751,6 +1751,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
|||
early_state_t early_state = { 0 };
|
||||
int read_packet = 0;
|
||||
int check_reject = 1;
|
||||
switch_codec_implementation_t read_impl = { 0 };
|
||||
|
||||
if (strstr(bridgeto, SWITCH_ENT_ORIGINATE_DELIM)) {
|
||||
return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override,
|
||||
|
@ -1777,6 +1778,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
|||
switch_channel_set_flag(caller_channel, CF_ORIGINATOR);
|
||||
oglobals.session = session;
|
||||
|
||||
switch_core_session_get_read_impl(session, &read_impl);
|
||||
|
||||
if ((to_var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
|
||||
timelimit_sec = atoi(to_var);
|
||||
|
@ -3066,7 +3068,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
|
|||
|
||||
if ((ringback.fh || silence || ringback.audio_buffer || oglobals.bridge_early_media > -1) && write_frame.codec && write_frame.datalen) {
|
||||
if (silence) {
|
||||
write_frame.datalen = write_frame.codec->implementation->decoded_bytes_per_packet;
|
||||
write_frame.datalen = read_impl.decoded_bytes_per_packet;
|
||||
switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, silence);
|
||||
}
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ struct switch_rtp {
|
|||
uint32_t sync_packets;
|
||||
int rtcp_interval;
|
||||
switch_bool_t rtcp_fresh_frame;
|
||||
|
||||
uint8_t checked_jb;
|
||||
#ifdef ENABLE_ZRTP
|
||||
zrtp_session_t *zrtp_session;
|
||||
zrtp_profile_t *zrtp_profile;
|
||||
|
@ -1652,6 +1652,32 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void jb_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
char *data;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = switch_vasprintf(&data, fmt, ap);
|
||||
if (ret != -1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "%s", data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
//switch_log_printf(SWITCH_CHANNEL_ID_LOG_CLEAN, file, func, line, NULL, level, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name)
|
||||
{
|
||||
|
||||
stfu_n_debug(rtp_session->jb, name);
|
||||
stfu_global_set_logger(jb_logger);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session,
|
||||
uint32_t queue_frames,
|
||||
uint32_t max_queue_frames,
|
||||
|
@ -1674,6 +1700,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *
|
|||
if (rtp_session->jb) {
|
||||
switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session");
|
||||
stfu_n_call_me(rtp_session->jb, jb_callback, session);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2108,12 +2135,18 @@ static void do_flush(switch_rtp_t *rtp_session)
|
|||
|
||||
flushed++;
|
||||
|
||||
if (rtp_session->jb) {
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push) /* remove this stuff when "if (0" is removed */
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
if (0 && rtp_session->jb) {
|
||||
stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts),
|
||||
ntohs((uint16_t) rtp_session->recv_msg.header.seq),
|
||||
rtp_session->recv_msg.header.pt,
|
||||
rtp_session->recv_msg.body, bytes - rtp_header_len);
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
rtp_session->stats.inbound.raw_bytes += bytes;
|
||||
rtp_session->stats.inbound.flush_packet_count++;
|
||||
|
@ -2177,7 +2210,6 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
|||
}
|
||||
|
||||
stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts),
|
||||
ntohs((uint16_t) rtp_session->recv_msg.header.seq),
|
||||
rtp_session->recv_msg.header.pt,
|
||||
rtp_session->recv_msg.body, *bytes - rtp_header_len);
|
||||
*bytes = 0;
|
||||
|
@ -2195,9 +2227,9 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
|||
*bytes = jb_frame->dlen + rtp_header_len;
|
||||
rtp_session->recv_msg.header.ts = htonl(jb_frame->ts);
|
||||
rtp_session->recv_msg.header.pt = jb_frame->pt;
|
||||
rtp_session->recv_msg.header.seq = htons((uint16_t)jb_frame->seq);
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
rtp_session->checked_jb++;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -2342,6 +2374,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
|||
|
||||
READ_INC(rtp_session);
|
||||
|
||||
rtp_session->checked_jb = 0;
|
||||
|
||||
while (switch_rtp_ready(rtp_session)) {
|
||||
int do_cng = 0;
|
||||
bytes = 0;
|
||||
|
@ -2894,7 +2928,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
|||
if (do_cng) {
|
||||
uint8_t *data = (uint8_t *) rtp_session->recv_msg.body;
|
||||
int fdr;
|
||||
|
||||
|
||||
if ((poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, 0)) == SWITCH_STATUS_SUCCESS) {
|
||||
goto recvfrom;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue