diff --git a/Freeswitch.2008.express.sln b/Freeswitch.2008.express.sln index 672406bda2..ad3cafe5cd 100644 --- a/Freeswitch.2008.express.sln +++ b/Freeswitch.2008.express.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 +# Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchConsole", "w32\Console\FreeSwitchConsole.2008.vcproj", "{1AF3A893-F7BE-43DD-B697-8AB2397C0D67}" ProjectSection(ProjectDependencies) = postProject {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} @@ -11,6 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Li ProjectSection(ProjectDependencies) = postProject {8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9} {89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C} + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} {F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3} {03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD} {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} diff --git a/Makefile.am b/Makefile.am index da89572c6f..df1ee2e0d0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -276,7 +276,8 @@ bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav fs_encode ## ## fs_cli () ## -fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c +fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \ + libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm @@ -304,7 +305,8 @@ tone2wav_LDADD = libfreeswitch.la ## ## fs_ivrd () ## -fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c +fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \ + libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c fs_ivrd_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include fs_ivrd_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm diff --git a/libs/esl/Makefile b/libs/esl/Makefile index a180406bda..ab50bac4d9 100644 --- a/libs/esl/Makefile +++ b/libs/esl/Makefile @@ -9,9 +9,9 @@ CXXFLAGS=$(BASE_FLAGS) -Wall -Werror -Wno-unused-variable MYLIB=libesl.a LIBS=-lncurses -lpthread -lesl -lm LDFLAGS=-L. -OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o -SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c -HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h +OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o src/esl_buffer.o +SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c src/esl_buffer.c +HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h src/include/esl_buffer.h SOLINK=-shared -Xlinker -x # comment the next line to disable c++ (no swig mods for you then) OBJS += src/esl_oop.o diff --git a/libs/esl/src/esl.2008.vcproj b/libs/esl/src/esl.2008.vcproj index 101348dd59..89daa17d9e 100644 --- a/libs/esl/src/esl.2008.vcproj +++ b/libs/esl/src/esl.2008.vcproj @@ -290,6 +290,10 @@ RelativePath=".\esl.c" > + + @@ -316,6 +320,10 @@ RelativePath=".\include\esl.h" > + + diff --git a/libs/esl/src/esl.2010.vcxproj b/libs/esl/src/esl.2010.vcxproj index b215fe4bc8..fd5e3a8353 100644 --- a/libs/esl/src/esl.2010.vcxproj +++ b/libs/esl/src/esl.2010.vcxproj @@ -128,6 +128,7 @@ + @@ -135,6 +136,7 @@ + diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index ce582d3837..f5bab62fcb 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -428,6 +428,10 @@ ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t s esl_mutex_create(&handle->mutex); } + if (!handle->packet_buf) { + esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0); + } + handle->connected = 1; esl_send_recv(handle, "connect\n\n"); @@ -632,6 +636,10 @@ ESL_DECLARE(esl_status_t) esl_connect_timeout(esl_handle_t *handle, const char * if (!handle->mutex) { esl_mutex_create(&handle->mutex); } + + if (!handle->packet_buf) { + esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0); + } handle->sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -805,6 +813,11 @@ ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle) esl_mutex_destroy(&mutex); } + if (handle->packet_buf) { + esl_buffer_destroy(&handle->packet_buf); + } + + return status; } @@ -825,7 +838,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms if (check_q) { esl_mutex_lock(handle->mutex); - if (handle->race_event) { + if (handle->race_event || esl_buffer_packet_count(handle->packet_buf)) { esl_mutex_unlock(handle->mutex); return esl_recv_event(handle, check_q, save_event); } @@ -894,12 +907,15 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms } +static esl_ssize_t handle_recv(esl_handle_t *handle, void *data, esl_size_t datalen) +{ + return recv(handle->sock, data, datalen, 0); +} ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event) { char *c; esl_ssize_t rrval; - int crc = 0; esl_event_t *revent = NULL; char *beg; char *hname, *hval; @@ -907,7 +923,6 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_ char *cl; esl_ssize_t len; int zc = 0; - int bread = 0; if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID) { return ESL_FAIL; @@ -916,9 +931,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_ esl_mutex_lock(handle->mutex); if (!handle->connected || handle->sock == ESL_SOCK_INVALID) { - handle->connected = 0; - esl_mutex_unlock(handle->mutex); - return ESL_FAIL; + goto fail; } esl_event_safe_destroy(&handle->last_event); @@ -932,76 +945,62 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_ goto parse_event; } - memset(handle->header_buf, 0, sizeof(handle->header_buf)); + + while(!revent && handle->connected) { + esl_size_t 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; diff --git a/libs/esl/src/esl_buffer.c b/libs/esl/src/esl_buffer.c new file mode 100644 index 0000000000..8032169fe3 --- /dev/null +++ b/libs/esl/src/esl_buffer.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2010, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "esl_buffer.h" + +static unsigned buffer_id = 0; + +struct esl_buffer { + unsigned char *data; + unsigned char *head; + esl_size_t used; + esl_size_t actually_used; + esl_size_t datalen; + esl_size_t max_len; + esl_size_t blocksize; + unsigned id; + int loops; +}; + + +ESL_DECLARE(esl_status_t) esl_buffer_create(esl_buffer_t **buffer, esl_size_t blocksize, esl_size_t start_len, esl_size_t max_len) +{ + esl_buffer_t *new_buffer; + + new_buffer = malloc(sizeof(*new_buffer)); + if (new_buffer) { + memset(new_buffer, 0, sizeof(*new_buffer)); + + if (start_len) { + new_buffer->data = malloc(start_len); + if (!new_buffer->data) { + free(new_buffer); + return ESL_FAIL; + } + memset(new_buffer->data, 0, start_len); + } + + new_buffer->max_len = max_len; + new_buffer->datalen = start_len; + new_buffer->id = buffer_id++; + new_buffer->blocksize = blocksize; + new_buffer->head = new_buffer->data; + + *buffer = new_buffer; + return ESL_SUCCESS; + } + + return ESL_FAIL; +} + +ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer) +{ + + assert(buffer != NULL); + + return buffer->datalen; + +} + + +ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer) +{ + assert(buffer != NULL); + + + if (buffer->max_len) { + return (esl_size_t) (buffer->max_len - buffer->used); + } + return 1000000; + +} + +ESL_DECLARE(esl_size_t) esl_buffer_inuse(esl_buffer_t *buffer) +{ + assert(buffer != NULL); + + return buffer->used; +} + +ESL_DECLARE(esl_size_t) esl_buffer_seek(esl_buffer_t *buffer, esl_size_t datalen) +{ + esl_size_t reading = 0; + + assert(buffer != NULL); + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else if (buffer->used >= datalen) { + reading = datalen; + } else { + reading = buffer->used; + } + + buffer->used = buffer->actually_used - reading; + buffer->head = buffer->data + reading; + + return reading; +} + +ESL_DECLARE(esl_size_t) esl_buffer_toss(esl_buffer_t *buffer, esl_size_t datalen) +{ + esl_size_t reading = 0; + + assert(buffer != NULL); + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else if (buffer->used >= datalen) { + reading = datalen; + } else { + reading = buffer->used; + } + + buffer->used -= reading; + buffer->head += reading; + + return buffer->used; +} + +ESL_DECLARE(void) esl_buffer_set_loops(esl_buffer_t *buffer, int loops) +{ + buffer->loops = loops; +} + +ESL_DECLARE(esl_size_t) esl_buffer_read_loop(esl_buffer_t *buffer, void *data, esl_size_t datalen) +{ + esl_size_t len; + if ((len = esl_buffer_read(buffer, data, datalen)) < datalen) { + if (buffer->loops == 0) { + return len; + } + buffer->head = buffer->data; + buffer->used = buffer->actually_used; + len = esl_buffer_read(buffer, (char*)data + len, datalen - len); + buffer->loops--; + } + return len; +} + +ESL_DECLARE(esl_size_t) esl_buffer_read(esl_buffer_t *buffer, void *data, esl_size_t datalen) +{ + esl_size_t reading = 0; + + assert(buffer != NULL); + assert(data != NULL); + + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else if (buffer->used >= datalen) { + reading = datalen; + } else { + reading = buffer->used; + } + + memcpy(data, buffer->head, reading); + buffer->used -= reading; + buffer->head += reading; + + /* if (buffer->id == 4) printf("%u o %d = %d\n", buffer->id, (unsigned)reading, (unsigned)buffer->used); */ + return reading; +} + + +ESL_DECLARE(esl_size_t) esl_buffer_packet_count(esl_buffer_t *buffer) +{ + char *pe, *p, *e, *head = (char *) buffer->head; + esl_size_t x = 0; + + assert(buffer != NULL); + + e = (head + buffer->used); + + for (p = head; p && *p && p < e; p++) { + if (*p == '\n') { + pe = p+1; + if (*pe == '\r') pe++; + if (pe <= e && *pe == '\n') { + p = pe++; + x++; + } + } + } + + return x; +} + +ESL_DECLARE(esl_size_t) esl_buffer_read_packet(esl_buffer_t *buffer, void *data, esl_size_t maxlen) +{ + char *pe, *p, *e, *head = (char *) buffer->head; + esl_size_t datalen = 0; + + assert(buffer != NULL); + assert(data != NULL); + + e = (head + buffer->used); + + for (p = head; p && *p && p < e; p++) { + if (*p == '\n') { + pe = p+1; + if (*pe == '\r') pe++; + if (pe <= e && *pe == '\n') { + pe++; + datalen = pe - head; + if (datalen > maxlen) { + datalen = maxlen; + } + break; + } + } + } + + return esl_buffer_read(buffer, data, datalen); +} + +ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, esl_size_t datalen) +{ + esl_size_t freespace, actual_freespace; + + assert(buffer != NULL); + assert(data != NULL); + assert(buffer->data != NULL); + + if (!datalen) { + return buffer->used; + } + + actual_freespace = buffer->datalen - buffer->actually_used; + if (actual_freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) { + memmove(buffer->data, buffer->head, buffer->used); + buffer->head = buffer->data; + buffer->actually_used = buffer->used; + } + + freespace = buffer->datalen - buffer->used; + + /* + if (buffer->data != buffer->head) { + memmove(buffer->data, buffer->head, buffer->used); + buffer->head = buffer->data; + } + */ + + if (freespace < datalen) { + esl_size_t new_size, new_block_size; + void *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: + */ diff --git a/libs/esl/src/include/esl.h b/libs/esl/src/include/esl.h index 9f28c3d925..99ab53ae95 100644 --- a/libs/esl/src/include/esl.h +++ b/libs/esl/src/include/esl.h @@ -251,6 +251,7 @@ typedef int esl_filehandle_t; #include "esl_json.h" typedef int16_t esl_port_t; +typedef size_t esl_size_t; typedef enum { ESL_SUCCESS, @@ -259,7 +260,11 @@ typedef enum { ESL_DISCONNECTED } esl_status_t; +#define BUF_CHUNK 65536 * 50 +#define BUF_START 65536 * 100 + #include +#include /*! \brief A handle that will hold the socket information and different events received. */ @@ -273,7 +278,8 @@ typedef struct { /*! The error number reported by the OS */ int errnum; /*! The inner contents received by the socket. Used only internally. */ - char header_buf[4196]; + esl_buffer_t *packet_buf; + char socket_buf[65536]; /*! Last command reply */ char last_reply[1024]; /*! Las command reply when called with esl_send_recv */ diff --git a/libs/esl/src/include/esl_buffer.h b/libs/esl/src/include/esl_buffer.h new file mode 100644 index 0000000000..c7901e4ede --- /dev/null +++ b/libs/esl/src/include/esl_buffer.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2010, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "esl.h" +#ifndef ESL_BUFFER_H +#define ESL_BUFFER_H +/** + * @defgroup esl_buffer Buffer Routines + * @ingroup buffer + * The purpose of this module is to make a plain buffering interface that can be used for read/write buffers + * throughout the application. + * @{ + */ +struct esl_buffer; +typedef struct esl_buffer esl_buffer_t; + +/*! \brief Allocate a new dynamic esl_buffer + * \param buffer returned pointer to the new buffer + * \param blocksize length to realloc by as data is added + * \param start_len ammount of memory to reserve initially + * \param max_len length the buffer is allowed to grow to + * \return status + */ +ESL_DECLARE(esl_status_t) esl_buffer_create(esl_buffer_t **buffer, esl_size_t blocksize, esl_size_t start_len, esl_size_t max_len); + +/*! \brief Get the length of a esl_buffer_t + * \param buffer any buffer of type esl_buffer_t + * \return int size of the buffer. + */ +ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer); + +/*! \brief Get the freespace of a esl_buffer_t + * \param buffer any buffer of type esl_buffer_t + * \return int freespace in the buffer. + */ +ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer); + +/*! \brief Get the in use amount of a esl_buffer_t + * \param buffer any buffer of type esl_buffer_t + * \return int ammount of buffer curently in use + */ +ESL_DECLARE(esl_size_t) esl_buffer_inuse(esl_buffer_t *buffer); + +/*! \brief Read data from a esl_buffer_t up to the ammount of datalen if it is available. Remove read data from buffer. + * \param buffer any buffer of type esl_buffer_t + * \param data pointer to the read data to be returned + * \param datalen amount of data to be returned + * \return int ammount of data actually read + */ +ESL_DECLARE(esl_size_t) esl_buffer_read(esl_buffer_t *buffer, void *data, esl_size_t datalen); + +ESL_DECLARE(esl_size_t) esl_buffer_read_packet(esl_buffer_t *buffer, void *data, esl_size_t maxlen); +ESL_DECLARE(esl_size_t) esl_buffer_packet_count(esl_buffer_t *buffer); + +/*! \brief Read data endlessly from a esl_buffer_t + * \param buffer any buffer of type esl_buffer_t + * \param data pointer to the read data to be returned + * \param datalen amount of data to be returned + * \return int ammount of data actually read + * \note Once you have read all the data from the buffer it will loop around. + */ +ESL_DECLARE(esl_size_t) esl_buffer_read_loop(esl_buffer_t *buffer, void *data, esl_size_t datalen); + +/*! \brief Assign a number of loops to read + * \param buffer any buffer of type esl_buffer_t + * \param loops the number of loops (-1 for infinite) + */ +ESL_DECLARE(void) esl_buffer_set_loops(esl_buffer_t *buffer, int32_t loops); + +/*! \brief Write data into a esl_buffer_t up to the length of datalen + * \param buffer any buffer of type esl_buffer_t + * \param data pointer to the data to be written + * \param datalen amount of data to be written + * \return int amount of buffer used after the write, or 0 if no space available + */ +ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, esl_size_t datalen); + +/*! \brief Remove data from the buffer + * \param buffer any buffer of type esl_buffer_t + * \param datalen amount of data to be removed + * \return int size of buffer, or 0 if unable to toss that much data + */ +ESL_DECLARE(esl_size_t) esl_buffer_toss(esl_buffer_t *buffer, esl_size_t datalen); + +/*! \brief Remove all data from the buffer + * \param buffer any buffer of type esl_buffer_t + */ +ESL_DECLARE(void) esl_buffer_zero(esl_buffer_t *buffer); + +/*! \brief Destroy the buffer + * \param buffer buffer to destroy + * \note only neccessary on dynamic buffers (noop on pooled ones) + */ +ESL_DECLARE(void) esl_buffer_destroy(esl_buffer_t **buffer); + +/*! \brief Seek to offset from the beginning of the buffer + * \param buffer buffer to seek + * \param datalen offset in bytes + * \return new position + */ +ESL_DECLARE(esl_size_t) esl_buffer_seek(esl_buffer_t *buffer, esl_size_t datalen); + +/** @} */ + +ESL_DECLARE(esl_size_t) esl_buffer_zwrite(esl_buffer_t *buffer, const void *data, esl_size_t datalen); + +#endif +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index ef3989c19c..c459a57c11 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -802,7 +802,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio phy_id = ftdm_channel_get_ph_id(tech_pvt->ftdmchan); ftdm_log(FTDM_LOG_DEBUG, "Got Freeswitch message in R2 channel %d [%d]\n", phy_id, msg->message_id); - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -849,7 +849,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, return SWITCH_STATUS_SUCCESS; } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -892,7 +892,7 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio return SWITCH_STATUS_FALSE; } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -924,7 +924,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio return SWITCH_STATUS_FALSE; } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -981,7 +981,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_PROGRESS: case SWITCH_MESSAGE_INDICATE_ANSWER: - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { if ((var = switch_channel_get_variable(channel, "freetdm_pre_buffer_size"))) { int tmp = atoi(var); if (tmp > -1) { @@ -1363,7 +1363,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi tech_pvt->caller_profile = caller_profile; - switch_channel_set_flag(channel, CF_OUTBOUND); switch_channel_set_state(channel, CS_INIT); if (ftdm_channel_add_token(ftdmchan, switch_core_session_get_uuid(*new_session), ftdm_channel_get_token_count(ftdmchan)) != FTDM_SUCCESS) { switch_core_session_destroy(new_session); @@ -1811,7 +1810,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal) switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); } - if (channel_a && channel_b && !switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_test_flag(channel_b, CF_OUTBOUND)) { + if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && + switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) { + cause = SWITCH_CAUSE_ATTENDED_TRANSFER; if (br_a_uuid && br_b_uuid) { switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid); diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index 7320934a49..f40196499c 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -53,42 +53,48 @@ static struct { float txgain; } zt_globals; +#if defined(__FreeBSD__) +typedef unsigned long ioctlcmd; +#else +typedef int ioctlcmd; +#endif + /** * \brief General IOCTL codes */ struct ioctl_codes { - int GET_BLOCKSIZE; - int SET_BLOCKSIZE; - int FLUSH; - int SYNC; - int GET_PARAMS; - int SET_PARAMS; - int HOOK; - int GETEVENT; - int IOMUX; - int SPANSTAT; - int MAINT; - int GETCONF; - int SETCONF; - int CONFLINK; - int CONFDIAG; - int GETGAINS; - int SETGAINS; - int SPANCONFIG; - int CHANCONFIG; - int SET_BUFINFO; - int GET_BUFINFO; - int AUDIOMODE; - int ECHOCANCEL; - int HDLCRAWMODE; - int HDLCFCSMODE; - int SPECIFY; - int SETLAW; - int SETLINEAR; - int GETCONFMUTE; - int ECHOTRAIN; - int SETTXBITS; - int GETRXBITS; + ioctlcmd GET_BLOCKSIZE; + ioctlcmd SET_BLOCKSIZE; + ioctlcmd FLUSH; + ioctlcmd SYNC; + ioctlcmd GET_PARAMS; + ioctlcmd SET_PARAMS; + ioctlcmd HOOK; + ioctlcmd GETEVENT; + ioctlcmd IOMUX; + ioctlcmd SPANSTAT; + ioctlcmd MAINT; + ioctlcmd GETCONF; + ioctlcmd SETCONF; + ioctlcmd CONFLINK; + ioctlcmd CONFDIAG; + ioctlcmd GETGAINS; + ioctlcmd SETGAINS; + ioctlcmd SPANCONFIG; + ioctlcmd CHANCONFIG; + ioctlcmd SET_BUFINFO; + ioctlcmd GET_BUFINFO; + ioctlcmd AUDIOMODE; + ioctlcmd ECHOCANCEL; + ioctlcmd HDLCRAWMODE; + ioctlcmd HDLCFCSMODE; + ioctlcmd SPECIFY; + ioctlcmd SETLAW; + ioctlcmd SETLINEAR; + ioctlcmd GETCONFMUTE; + ioctlcmd ECHOTRAIN; + ioctlcmd SETTXBITS; + ioctlcmd GETRXBITS; }; /** diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c index 8425372ef5..6a75dc85ff 100644 --- a/libs/openzap/mod_openzap/mod_openzap.c +++ b/libs/openzap/mod_openzap/mod_openzap.c @@ -821,7 +821,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_RINGING: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); } else { zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS); @@ -830,7 +830,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio break; case SWITCH_MESSAGE_INDICATE_PROGRESS: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA); } else { @@ -841,7 +841,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio break; case SWITCH_MESSAGE_INDICATE_ANSWER: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED); } else { /* lets make the ozmod_r2 module life easier by moving thru each @@ -888,7 +888,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_RINGING: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); } else { zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS); @@ -897,7 +897,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, break; case SWITCH_MESSAGE_INDICATE_PROGRESS: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_MEDIA); } else { @@ -914,7 +914,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, break; case SWITCH_MESSAGE_INDICATE_ANSWER: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED); } else { /* Don't skip messages in the ISDN call setup @@ -957,7 +957,7 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_PROGRESS: case SWITCH_MESSAGE_INDICATE_ANSWER: - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA); @@ -991,7 +991,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_PROGRESS: case SWITCH_MESSAGE_INDICATE_ANSWER: - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS); zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA); @@ -1000,7 +1000,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio } break; case SWITCH_MESSAGE_INDICATE_RINGING: - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { if (!switch_channel_test_flag(channel, CF_ANSWERED) && !switch_channel_test_flag(channel, CF_EARLY_MEDIA) && @@ -1052,7 +1052,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_PROGRESS: case SWITCH_MESSAGE_INDICATE_ANSWER: - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { if ((var = switch_channel_get_variable(channel, "openzap_pre_buffer_size"))) { int tmp = atoi(var); if (tmp > -1) { @@ -1327,7 +1327,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi tech_pvt->caller_profile = caller_profile; - switch_channel_set_flag(channel, CF_OUTBOUND); switch_channel_set_state(channel, CS_INIT); if (zap_channel_add_token(zchan, switch_core_session_get_uuid(*new_session), zchan->token_count) != ZAP_SUCCESS) { switch_core_session_destroy(new_session); @@ -1678,7 +1677,9 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal) switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); } - if (channel_a && channel_b && !switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_test_flag(channel_b, CF_OUTBOUND)) { + if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && + switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) { + cause = SWITCH_CAUSE_ATTENDED_TRANSFER; if (br_a_uuid && br_b_uuid) { switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid); diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 547c337278..2ffb86fdb6 100644 --- a/libs/stfu/stfu.c +++ b/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 diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h index d2760b27bc..ad769c62e2 100644 --- a/libs/stfu/stfu.h +++ b/libs/stfu/stfu.h @@ -38,6 +38,8 @@ extern "C" { #include #include #include +#include + #ifdef _MSC_VER #ifndef uint32_t @@ -62,6 +64,85 @@ typedef unsigned long in_addr_t; #endif #include + + +#ifdef WIN32 +#include +#include +typedef SOCKET stfu_socket_t; +typedef unsigned __int64 uint64_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int8 uint8_t; +typedef __int64 int64_t; +typedef __int32 int32_t; +typedef __int16 int16_t; +typedef __int8 int8_t; +typedef intptr_t stfu_ssize_t; +typedef int stfu_filehandle_t; +#define STFU_SOCK_INVALID INVALID_SOCKET +#define strerror_r(num, buf, size) strerror_s(buf, size, num) +#if defined(STFU_DECLARE_STATIC) +#define STFU_DECLARE(type) type __stdcall +#define STFU_DECLARE_NONSTD(type) type __cdecl +#define STFU_DECLARE_DATA +#elif defined(STFU_EXPORTS) +#define STFU_DECLARE(type) __declspec(dllexport) type __stdcall +#define STFU_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl +#define STFU_DECLARE_DATA __declspec(dllexport) +#else +#define STFU_DECLARE(type) __declspec(dllimport) type __stdcall +#define STFU_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl +#define STFU_DECLARE_DATA __declspec(dllimport) +#endif +#else +#define STFU_DECLARE(type) type +#define STFU_DECLARE_NONSTD(type) type +#define STFU_DECLARE_DATA +#include +#include +#include +#include +#include +#include +#include +#define STFU_SOCK_INVALID -1 +typedef int stfu_socket_t; +typedef ssize_t stfu_ssize_t; +typedef int stfu_filehandle_t; +#endif + + +#define STFU_PRE __FILE__, __FUNCTION__, __LINE__ +#define STFU_LOG_LEVEL_DEBUG 7 +#define STFU_LOG_LEVEL_INFO 6 +#define STFU_LOG_LEVEL_NOTICE 5 +#define STFU_LOG_LEVEL_WARNING 4 +#define STFU_LOG_LEVEL_ERROR 3 +#define STFU_LOG_LEVEL_CRIT 2 +#define STFU_LOG_LEVEL_ALERT 1 +#define STFU_LOG_LEVEL_EMERG 0 + +#define STFU_LOG_DEBUG STFU_PRE, STFU_LOG_LEVEL_DEBUG +#define STFU_LOG_INFO STFU_PRE, STFU_LOG_LEVEL_INFO +#define STFU_LOG_NOTICE STFU_PRE, STFU_LOG_LEVEL_NOTICE +#define STFU_LOG_WARNING STFU_PRE, STFU_LOG_LEVEL_WARNING +#define STFU_LOG_ERROR STFU_PRE, STFU_LOG_LEVEL_ERROR +#define STFU_LOG_CRIT STFU_PRE, STFU_LOG_LEVEL_CRIT +#define STFU_LOG_ALERT STFU_PRE, STFU_LOG_LEVEL_ALERT +#define STFU_LOG_EMERG STFU_PRE, STFU_LOG_LEVEL_EMERG +typedef void (*stfu_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...); + + +int stfu_vasprintf(char **ret, const char *fmt, va_list ap); + +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 } diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index e3e9f665a3..c48a40e6d1 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -234,6 +234,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t * uint32_t max_queue_frames, uint32_t samples_per_packet, uint32_t samples_per_second); +SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name); + SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session); /*! diff --git a/src/include/switch_types.h b/src/include/switch_types.h index d020775d48..e04f437eb3 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1095,6 +1095,7 @@ typedef enum { CF_BRIDGE_NOWRITE, CF_RECOVERED, CF_JITTERBUFFER, + CF_DIALPLAN, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ CF_FLAG_MAX } switch_channel_flag_t; diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 9b170a32e0..53ce82b4cb 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -2456,7 +2456,7 @@ static void conference_loop_output(conference_member_t *member) switch_event_destroy(&event); } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { /* test to see if outbound channel has answered */ if (switch_channel_test_flag(channel, CF_ANSWERED) && !switch_test_flag(member->conference, CFLAG_ANSWERED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, @@ -2599,7 +2599,7 @@ static void conference_loop_output(conference_member_t *member) switch_channel_cause2str(switch_channel_get_cause(channel))); /* if it's an outbound channel, store the release cause in the conference struct, we might need it */ - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { member->conference->bridge_hangup_cause = switch_channel_get_cause(channel); } @@ -5446,7 +5446,7 @@ SWITCH_STANDARD_APP(conference_function) launch_conference_thread(conference); } else { - int enforce_security = !switch_channel_test_flag(channel, CF_OUTBOUND); + int enforce_security = switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND; const char *pvar = switch_channel_get_variable(channel, "conference_enforce_security"); if (pvar) { @@ -5655,7 +5655,7 @@ SWITCH_STANDARD_APP(conference_function) } else { /* if we're not using "bridge:" set the conference answered flag */ /* and this isn't an outbound channel, answer the call */ - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) switch_set_flag(conference, CFLAG_ANSWERED); } diff --git a/src/mod/applications/mod_spy/mod_spy.c b/src/mod/applications/mod_spy/mod_spy.c index 5093ad8f22..cb8981d264 100644 --- a/src/mod/applications/mod_spy/mod_spy.c +++ b/src/mod/applications/mod_spy/mod_spy.c @@ -131,7 +131,6 @@ SWITCH_STANDARD_API(dump_hash) static switch_status_t process_event(switch_event_t *event) { switch_core_session_t *session = NULL; - switch_channel_t *channel; char *username[3] = { 0 }; char *domain[3] = { 0 }; char key[512]; @@ -172,18 +171,19 @@ static switch_status_t process_event(switch_event_t *event) return SWITCH_STATUS_FALSE; } - session = switch_core_session_locate(uuid); - channel = switch_core_session_get_channel(session); + if ((session = switch_core_session_locate(uuid))) { + switch_channel_t *channel = switch_core_session_get_channel(session); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key); - my_uuid = switch_event_get_header(event, "Unique-ID"); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key); + my_uuid = switch_event_get_header(event, "Unique-ID"); - switch_channel_set_variable(channel, "spy_uuid", my_uuid); + switch_channel_set_variable(channel, "spy_uuid", my_uuid); - switch_channel_set_state(channel, CS_EXCHANGE_MEDIA); - switch_channel_set_flag(channel, CF_BREAK); + switch_channel_set_state(channel, CS_EXCHANGE_MEDIA); + switch_channel_set_flag(channel, CF_BREAK); - switch_core_session_rwunlock(session); + switch_core_session_rwunlock(session); + } return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp index 7e20b7c25e..13e433557d 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp @@ -1324,7 +1324,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi caller_profile = tech_pvt->caller_profile; caller_profile->destination_number = rdest; - switch_channel_set_flag(channel, CF_OUTBOUND); switch_set_flag(tech_pvt, TFLAG_OUTBOUND); switch_channel_set_state(channel, CS_INIT); gsmopen_call(tech_pvt, rdest, 30); diff --git a/src/mod/endpoints/mod_h323/mod_h323.cpp b/src/mod/endpoints/mod_h323/mod_h323.cpp index 74fb6ae11a..3d79917434 100644 --- a/src/mod/endpoints/mod_h323/mod_h323.cpp +++ b/src/mod/endpoints/mod_h323/mod_h323.cpp @@ -725,7 +725,6 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran name += outbound_profile->destination_number; switch_channel_set_name(m_fsChannel, name); - switch_channel_set_flag(m_fsChannel, CF_OUTBOUND); switch_channel_set_state(m_fsChannel, CS_INIT); } @@ -1508,7 +1507,7 @@ switch_status_t FSH323Connection::receive_message(switch_core_session_message_t break; } case SWITCH_MESSAGE_INDICATE_ANSWER: { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_FALSE; } AnsweringCall(H323Connection::AnswerCallNow); diff --git a/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp b/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp index 3abbe3ecfb..1b126eb277 100644 --- a/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp +++ b/src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp @@ -868,7 +868,6 @@ switch_status_t Board::KhompPvt::justStart(switch_caller_profile_t *profile) _caller_profile = switch_caller_profile_clone(_session, profile); switch_channel_set_caller_profile(channel, _caller_profile); - switch_channel_set_flag(channel, CF_OUTBOUND); switch_channel_set_state(channel, CS_INIT); } else diff --git a/src/mod/endpoints/mod_opal/mod_opal.cpp b/src/mod/endpoints/mod_opal/mod_opal.cpp index 8935bbb06d..0760588019 100644 --- a/src/mod/endpoints/mod_opal/mod_opal.cpp +++ b/src/mod/endpoints/mod_opal/mod_opal.cpp @@ -580,7 +580,6 @@ FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, void* userDat name += outbound_profile->destination_number; switch_channel_set_name(m_fsChannel, name); - switch_channel_set_flag(m_fsChannel, CF_OUTBOUND); switch_channel_set_state(m_fsChannel, CS_INIT); } } @@ -966,7 +965,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg It would only happen if someone called switch_channel_answer() instead of switch_channel_mark_answered() on an outbound call. it should not do anything if someone does it by accident somewhere hense this in both cases: - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_FALSE; } @@ -1025,7 +1024,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg { int fixed = 0; - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_FALSE; } diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 2df8937647..5320ca52d1 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -1080,8 +1080,6 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi switch_channel_set_caller_profile(nchannel, caller_profile); tech_pvt->caller_profile = caller_profile; - switch_channel_set_flag(nchannel, CF_OUTBOUND); - if ((sql = switch_mprintf( "INSERT INTO skinny_active_lines " "(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) " diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index d85a190ba8..ee3c33a497 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -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 */ diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index cfafea6f01..9bf9d9fb9b 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -343,7 +343,7 @@ switch_status_t skinny_session_send_call_info(switch_core_session_t *session, li zstr((called_party_number = switch_channel_get_variable(channel, "destination_number")))) { called_party_number = "0000000000"; } - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { call_type = SKINNY_INBOUND_CALL; } else { call_type = SKINNY_OUTBOUND_CALL; @@ -1674,7 +1674,7 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste ); switch_set_flag_locked(tech_pvt, TFLAG_IO); - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { switch_channel_mark_answered(channel); } if (switch_channel_test_flag(channel, CF_HOLD)) { @@ -1970,7 +1970,7 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re "Received %s (type=%x,length=%d) from %s:%d.\n", skinny_message_type2str(request->type), request->type, request->length, listener->device_name, listener->device_instance); } - if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE) { + if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Device should send a register message first.\n"); return SWITCH_STATUS_FALSE; diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.c b/src/mod/endpoints/mod_skinny/skinny_tables.c index 0a27ad76c4..053b350b46 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.c +++ b/src/mod/endpoints/mod_skinny/skinny_tables.c @@ -99,6 +99,7 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = { {"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE}, {"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE}, {"UserToDeviceDataVersion1Message", USER_TO_DEVICE_DATA_VERSION1_MESSAGE}, + {"XMLAlarmMessage", XML_ALARM_MESSAGE}, {NULL, 0} }; SKINNY_DECLARE_ID2STR(skinny_message_type2str, SKINNY_MESSAGE_TYPES, "UnknownMessage") diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.h b/src/mod/endpoints/mod_skinny/skinny_tables.h index 14962b8b78..c119e1f141 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.h +++ b/src/mod/endpoints/mod_skinny/skinny_tables.h @@ -87,7 +87,7 @@ uint32_t func(const char *str)\ } -extern struct skinny_table SKINNY_MESSAGE_TYPES[65]; +extern struct skinny_table SKINNY_MESSAGE_TYPES[66]; const char *skinny_message_type2str(uint32_t id); uint32_t skinny_str2message_type(const char *str); #define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES) diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index 65c1b120fd..56188a4188 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -1364,7 +1364,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi caller_profile = tech_pvt->caller_profile; caller_profile->destination_number = rdest; - switch_channel_set_flag(channel, CF_OUTBOUND); switch_mutex_lock(tech_pvt->flag_mutex); switch_set_flag(tech_pvt, TFLAG_OUTBOUND); switch_mutex_unlock(tech_pvt->flag_mutex); diff --git a/src/mod/endpoints/mod_skypopen/oss/Makefile b/src/mod/endpoints/mod_skypopen/oss/Makefile index 465db533e4..8df20f68c5 100644 --- a/src/mod/endpoints/mod_skypopen/oss/Makefile +++ b/src/mod/endpoints/mod_skypopen/oss/Makefile @@ -4,7 +4,7 @@ # Add your debugging flag (or not) to CFLAGS ifeq ($(DEBUG),y) - DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines + DEBFLAGS = -O -g -DSKYPOPEN_DEBUG # "-O" is needed to expand inlines else DEBFLAGS = -O2 -Wall endif @@ -15,9 +15,9 @@ EXTRA_CFLAGS += -I$(LDDINC) ifneq ($(KERNELRELEASE),) # call from kernel build system -scull-objs := main.o +skypopen-objs := main.o -obj-m := scull.o +obj-m := skypopen.o else diff --git a/src/mod/endpoints/mod_skypopen/oss/main.c b/src/mod/endpoints/mod_skypopen/oss/main.c index 8da9c549ac..2abc5b342a 100644 --- a/src/mod/endpoints/mod_skypopen/oss/main.c +++ b/src/mod/endpoints/mod_skypopen/oss/main.c @@ -1,5 +1,5 @@ /* - * main.c -- the bare scull char module + * main.c -- the bare skypopen char module * * Copyright (C) 2010 Giovanni Maruzzelli * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet @@ -41,117 +41,198 @@ #include #include -#include "scull.h" /* local definitions */ +#include "skypopen.h" /* local definitions */ /* * Our parameters which can be set at load time. */ -int scull_major = SCULL_MAJOR; -int scull_minor = 3; -int scull_nr_devs = SCULL_NR_DEVS; /* number of bare scull devices */ +int skypopen_major = SKYPOPEN_MAJOR; +int skypopen_minor = 3; +int skypopen_nr_devs = SKYPOPEN_NR_DEVS; /* number of bare skypopen devices */ -module_param(scull_major, int, S_IRUGO); -module_param(scull_minor, int, S_IRUGO); -module_param(scull_nr_devs, int, S_IRUGO); +module_param(skypopen_major, int, S_IRUGO); +module_param(skypopen_minor, int, S_IRUGO); +module_param(skypopen_nr_devs, int, S_IRUGO); -MODULE_AUTHOR("Original: Alessandro Rubini, Jonathan Corbet. Heavy modified by: Giovanni Maruzzelli"); +MODULE_AUTHOR("Original: Alessandro Rubini, Jonathan Corbet. Modified by: Giovanni Maruzzelli for FreeSWITCH skypopen"); MODULE_LICENSE("Dual BSD/GPL"); -static struct scull_dev *scull_devices; /* allocated in scull_init_module */ +static struct skypopen_dev *skypopen_devices; /* allocated in skypopen_init_module */ -#define GIOVA_BLK 1920 -#define GIOVA_SLEEP 20 +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); diff --git a/src/mod/endpoints/mod_skypopen/oss/scull.h b/src/mod/endpoints/mod_skypopen/oss/scull.h deleted file mode 100644 index 565b8b38b7..0000000000 --- a/src/mod/endpoints/mod_skypopen/oss/scull.h +++ /dev/null @@ -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 /* 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_ */ diff --git a/src/mod/endpoints/mod_skypopen/oss/skypopen.h b/src/mod/endpoints/mod_skypopen/oss/skypopen.h new file mode 100644 index 0000000000..2324e448cb --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/oss/skypopen.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 /* 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_ */ diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index d4f8b1b45a..07e125ad6c 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -508,7 +508,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session) TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)), TAG_END()); } } else { - if (switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending CANCEL to %s\n", switch_channel_get_name(channel)); if (!tech_pvt->got_bye) { switch_channel_set_variable(channel, "sip_hangup_disposition", "send_cancel"); @@ -573,7 +573,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) char *sticky = NULL; const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full"); - if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { return SWITCH_STATUS_SUCCESS; } @@ -653,7 +653,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) switch_channel_clear_flag(channel, CF_PROXY_MODE); } - if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); tech_pvt->num_codecs = 0; sofia_glue_tech_prepare_codecs(tech_pvt); @@ -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; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index f2a555e946..94eab68858 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -357,7 +357,7 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status, goto error; } - if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { switch_channel_answer(channel); switch_channel_set_variable(channel, "auto_answer_destination", switch_channel_get_variable(channel, "destination_number")); switch_ivr_session_transfer(session, "auto_answer", NULL, NULL); @@ -4114,7 +4114,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status } - if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { sip_contact_t *p_contact = sip->sip_contact; int i = 0; char var_name[80]; @@ -4645,7 +4645,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, status = 183; } - if (channel && (status == 180 || status == 183) && switch_channel_test_flag(channel, CF_OUTBOUND)) { + if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { const char *val; if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) { nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR("talk"), TAG_END()); @@ -4692,7 +4692,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (r_sdp) { if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { - if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA"); } sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA); @@ -4715,7 +4715,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } goto done; } else { - if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "DELAYED NEGOTIATION"); } else { if (sofia_glue_tech_media(tech_pvt, (char *) r_sdp) != SWITCH_STATUS_SUCCESS) { @@ -4910,7 +4910,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE); if (!switch_channel_media_ready(channel)) { - if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) { //const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); tech_pvt->num_codecs = 0; @@ -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; } } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 803059a8da..0f52bbc8fb 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4687,8 +4687,8 @@ void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp) switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, sdp); if (!sofia_test_flag(tech_pvt, TFLAG_CHANGE_MEDIA) && !sofia_test_flag(tech_pvt, TFLAG_RECOVERING) && - (switch_channel_test_flag(other_channel, CF_OUTBOUND) && - switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND) && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) { + (switch_channel_direction(other_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && + switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) { switch_ivr_nomedia(val, SMF_FORCE); sofia_set_flag_locked(tech_pvt, TFLAG_CHANGE_MEDIA); } diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index ee7cfc9eaf..596a953dcb 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -31,8 +31,8 @@ */ #include #define CMD_BUFLEN 1024 * 1000 -#define MAX_QUEUE_LEN 5000 -#define MAX_MISSED 200 +#define MAX_QUEUE_LEN 25000 +#define MAX_MISSED 2000 SWITCH_MODULE_LOAD_FUNCTION(mod_event_socket_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_event_socket_shutdown); SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_socket_runtime); @@ -170,7 +170,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) { switch_log_node_t *dnode = switch_log_node_dup(node); - if (switch_queue_trypush(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) { + if (switch_queue_push(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) { if (l->lost_logs) { int ll = l->lost_logs; switch_event_t *event; @@ -366,7 +366,7 @@ static void event_handler(switch_event_t *event) if (send) { if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) { - if (switch_queue_trypush(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) { + if (switch_queue_push(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) { if (l->lost_events) { int le = l->lost_events; l->lost_events = 0; @@ -1233,7 +1233,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, if (switch_channel_get_state(chan) < CS_HANGUP && switch_channel_test_flag(chan, CF_DIVERT_EVENTS)) { switch_event_t *e = NULL; while (switch_core_session_dequeue_event(listener->session, &e, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { - if (switch_queue_trypush(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) { + if (switch_queue_push(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) { switch_core_session_queue_event(listener->session, &e); break; } diff --git a/src/switch_channel.c b/src/switch_channel.c index a9c87c5954..ef21e8c8f1 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -2386,6 +2386,8 @@ SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *chann { switch_assert(channel != NULL); + switch_channel_set_flag(channel, CF_DIALPLAN); + switch_mutex_lock(channel->profile_mutex); caller_extension->next = channel->caller_profile->caller_extension; channel->caller_profile->caller_extension = caller_extension; @@ -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; } diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index c77f3f1a68..ccd6dacc9c 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -124,7 +124,7 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) } if (!count) { - if (switch_channel_test_flag(session->channel, CF_OUTBOUND)) { + if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_channel_test_flag(session->channel, CF_ANSWERED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No Dialplan on answered channel, changing state to HANGUP\n"); diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp index 40462db567..1ba850d7e4 100644 --- a/src/switch_cpp.cpp +++ b/src/switch_cpp.cpp @@ -1206,7 +1206,7 @@ SWITCH_DECLARE(void) bridge(CoreSession &session_a, CoreSession &session_b) if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) { session_a.begin_allow_threads(); - if (!switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_media_ready(channel_a)) { + if (switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_media_ready(channel_a)) { switch_channel_pre_answer(channel_a); } diff --git a/src/switch_event.c b/src/switch_event.c index f782c15900..dce42f8e29 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -339,7 +339,7 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi launch_dispatch_threads(SOFT_MAX_DISPATCH + 1, DISPATCH_QUEUE_LEN, RUNTIME_POOL); switch_mutex_unlock(EVENT_QUEUE_MUTEX); } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of threads!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of event dispatch threads! Slowing things down.\n"); switch_yield(1000000); } } diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 6e2aeaf637..494871ec8a 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -140,7 +140,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, const char *var; /* - if (!switch_channel_test_flag(channel, CF_OUTBOUND) && !switch_channel_test_flag(channel, CF_PROXY_MODE) && + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_test_flag(channel, CF_PROXY_MODE) && !switch_channel_media_ready(channel) && !switch_channel_test_flag(channel, CF_SERVICE)) { if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot establish media.\n"); @@ -2300,7 +2300,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3 break; } - stfu_n_eat(jb, ts, 0, read_frame->payload, read_frame->data, read_frame->datalen); + stfu_n_eat(jb, ts, read_frame->payload, read_frame->data, read_frame->datalen); ts += interval; if ((jb_frame = stfu_n_read_a_frame(jb))) { diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index afd33f16a0..aa5ddb9232 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -100,7 +100,7 @@ static void send_display(switch_core_session_t *session, switch_core_session_t * caller_channel = switch_core_session_get_channel(session); caller_profile = switch_channel_get_caller_profile(caller_channel); - if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(caller_channel, CF_DIALPLAN)) { name = caller_profile->callee_id_name; number = caller_profile->callee_id_number; @@ -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); } diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index e61534798b..b6ae346a66 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -1751,6 +1751,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess early_state_t early_state = { 0 }; int read_packet = 0; int check_reject = 1; + switch_codec_implementation_t read_impl = { 0 }; if (strstr(bridgeto, SWITCH_ENT_ORIGINATE_DELIM)) { return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override, @@ -1777,6 +1778,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess switch_channel_set_flag(caller_channel, CF_ORIGINATOR); oglobals.session = session; + switch_core_session_get_read_impl(session, &read_impl); if ((to_var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) { timelimit_sec = atoi(to_var); @@ -3066,7 +3068,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess if ((ringback.fh || silence || ringback.audio_buffer || oglobals.bridge_early_media > -1) && write_frame.codec && write_frame.datalen) { if (silence) { - write_frame.datalen = write_frame.codec->implementation->decoded_bytes_per_packet; + write_frame.datalen = read_impl.decoded_bytes_per_packet; switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, silence); } diff --git a/src/switch_rtp.c b/src/switch_rtp.c index b4f60fcd55..4e667fb49b 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -229,7 +229,7 @@ struct switch_rtp { uint32_t sync_packets; int rtcp_interval; switch_bool_t rtcp_fresh_frame; - + uint8_t checked_jb; #ifdef ENABLE_ZRTP zrtp_session_t *zrtp_session; zrtp_profile_t *zrtp_profile; @@ -1652,6 +1652,32 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t return SWITCH_STATUS_SUCCESS; } +static void jb_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) +{ + int ret; + char *data; + va_list ap; + + va_start(ap, fmt); + ret = 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; }