From bdb9ed8b8e2af8536466cca0a86ce55d8099f93c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 21 May 2010 16:47:05 -0500 Subject: [PATCH] remove mod_t38_gateway --- .../applications/mod_t38gateway/Makefile.am | 17 - .../mod_t38gateway/mod_t38gateway.2008.vcproj | 291 --------- .../mod_t38gateway/mod_t38gateway.c | 349 ----------- src/mod/applications/mod_t38gateway/udptl.c | 563 ------------------ src/mod/applications/mod_t38gateway/udptl.h | 153 ----- 5 files changed, 1373 deletions(-) delete mode 100644 src/mod/applications/mod_t38gateway/Makefile.am delete mode 100644 src/mod/applications/mod_t38gateway/mod_t38gateway.2008.vcproj delete mode 100644 src/mod/applications/mod_t38gateway/mod_t38gateway.c delete mode 100644 src/mod/applications/mod_t38gateway/udptl.c delete mode 100644 src/mod/applications/mod_t38gateway/udptl.h diff --git a/src/mod/applications/mod_t38gateway/Makefile.am b/src/mod/applications/mod_t38gateway/Makefile.am deleted file mode 100644 index b4980bf8a1..0000000000 --- a/src/mod/applications/mod_t38gateway/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -include $(top_srcdir)/build/modmake.rulesam -MODNAME=mod_t38gateway - -TIFF_DIR=$(switch_srcdir)/libs/tiff-3.8.2 -TIFF_BUILDDIR=$(switch_builddir)/libs/tiff-3.8.2 -TIFF_LA=$(TIFF_BUILDDIR)/libtiff/libtiff.la - -SPANDSP_DIR=$(switch_srcdir)/libs/spandsp -SPANDSP_BUILDDIR=$(switch_builddir)/libs/spandsp -SPANDSP_LA=$(SPANDSP_BUILDDIR)/src/libspandsp.la - -mod_LTLIBRARIES = mod_t38gateway.la -mod_t38gateway_la_SOURCES = mod_t38gateway.c udptl.c -mod_t38gateway_la_CFLAGS = $(AM_CFLAGS) -I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff -mod_t38gateway_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA) -mod_t38gateway_la_LDFLAGS = -avoid-version -module -no-undefined -shared -ljpeg - diff --git a/src/mod/applications/mod_t38gateway/mod_t38gateway.2008.vcproj b/src/mod/applications/mod_t38gateway/mod_t38gateway.2008.vcproj deleted file mode 100644 index b790b73e4e..0000000000 --- a/src/mod/applications/mod_t38gateway/mod_t38gateway.2008.vcproj +++ /dev/null @@ -1,291 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mod/applications/mod_t38gateway/mod_t38gateway.c b/src/mod/applications/mod_t38gateway/mod_t38gateway.c deleted file mode 100644 index 13a7cc837e..0000000000 --- a/src/mod/applications/mod_t38gateway/mod_t38gateway.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2009, Steve Underwood - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * Contributor(s): - * - * Steve Underwood - * - * mod_t38gateway.c -- A T.38 gateway - * - * This module uses the T.38 gateway engine of spandsp to create a T.38 gateway suitable for - * V.17, V.29, and V.27ter FAX operation. - * - */ - -#include - -#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES -#include -#include - -#include "udptl.h" - -/*! Syntax of the API call. */ -#define T38GATEWAY_SYNTAX " " - -/*! Number of expected parameters in api call. */ -#define T38GATEWAY_PARAMS 2 - -/*! FreeSWITCH CUSTOM event types. */ -#define T38GATEWAY_EVENT_CNG "t38gateway::cng" -#define T38GATEWAY_EVENT_CED "t38gateway::ced" -#define T38GATEWAY_EVENT_PAGE "t38gateway::page" - -/* Prototypes */ -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_t38gateway_shutdown); -SWITCH_STANDARD_API(t38gateway_api_main); - -SWITCH_MODULE_LOAD_FUNCTION(mod_t38gateway_load); -SWITCH_MODULE_DEFINITION(mod_t38gateway, mod_t38gateway_load, NULL, NULL); -SWITCH_STANDARD_APP(t38gateway_start_function); - -/*! Type that holds codec information. */ -typedef struct { - /*! The sampling rate of the audio stream. */ - int rate; - /*! The number of channels. */ - int channels; -} t38gateway_codec_info_t; - -/*! Type that holds session information pertinent to the t38gateway module. */ -typedef struct { - /*! Internal FreeSWITCH session. */ - switch_core_session_t *session; - /*! Codec information for the session. */ - t38gateway_codec_info_t t38gateway_codec; - t38_gateway_state_t *t38; - t38_core_state_t *t38_core; - udptl_state_t *udptl; -} t38gateway_session_info_t; - -static int tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count) -{ - t38gateway_session_info_t *t; - - t = (t38gateway_session_info_t *) user_data; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -static int rx_packet_handler(void *user_data, const uint8_t *buf, int len, int seq_no) -{ - t38gateway_session_info_t *t; - - t = (t38gateway_session_info_t *) user_data; - t38_core_rx_ifp_packet(t->t38_core, buf, len, seq_no); - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -/*! \brief The callback function that is called when new audio data becomes available - * - * @author Steve Underwood - * @param bug A reference to the media bug. - * @param user_data The session information for this call. - * @param type The switch callback type. - * @return The success or failure of the function. - */ -static switch_bool_t t38gateway_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) -{ - t38gateway_session_info_t *t38gateway_info; - switch_codec_t *read_codec; - switch_frame_t *frame; - int16_t *amp; - - t38gateway_info = (t38gateway_session_info_t *) user_data; - if (t38gateway_info == NULL) { - return SWITCH_FALSE; - } - - switch (type) { - case SWITCH_ABC_TYPE_INIT: - read_codec = switch_core_session_get_read_codec(t38gateway_info->session); - t38gateway_info->t38gateway_codec.rate = read_codec->implementation->samples_per_second; - t38gateway_info->t38gateway_codec.channels = read_codec->implementation->number_of_channels; - break; - case SWITCH_ABC_TYPE_READ_PING: - case SWITCH_ABC_TYPE_CLOSE: - break; - case SWITCH_ABC_TYPE_READ: - frame = switch_core_media_bug_get_read_replace_frame(bug); - amp = (int16_t *) frame->data; - t38_gateway_rx(t38gateway_info->t38, amp, frame->samples); - break; - case SWITCH_ABC_TYPE_WRITE: - case SWITCH_ABC_TYPE_READ_REPLACE: - case SWITCH_ABC_TYPE_WRITE_REPLACE: - break; - } - - return SWITCH_TRUE; -} - -/*! \brief FreeSWITCH module loading function - * - * @author Steve Underwood - * @return Load success or failure. - */ -SWITCH_MODULE_LOAD_FUNCTION(mod_t38gateway_load) -{ - switch_application_interface_t *app_interface; - switch_api_interface_t *api_interface; - /* connect my internal structure to the blank pointer passed to me */ - *module_interface = switch_loadable_module_create_module_interface(pool, modname); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "T.38 gateway enabled\n"); - - SWITCH_ADD_APP(app_interface, "t38gateway", "T.38 gateway", "T.38 gateway", t38gateway_start_function, "[start] [stop]", SAF_NONE); - - SWITCH_ADD_API(api_interface, "t38gateway", "T.38 gateway", t38gateway_api_main, T38GATEWAY_SYNTAX); - - /* indicate that the module should continue to be loaded */ - return SWITCH_STATUS_SUCCESS; -} - -/*! \brief FreeSWITCH application handler function. - * This handles calls made from applications such as LUA and the dialplan - * - * @author Steve Underwood - * @return Success or failure of the function. - */ -SWITCH_STANDARD_APP(t38gateway_start_function) -{ - switch_media_bug_t *bug; - switch_status_t status; - switch_channel_t *channel; - t38gateway_session_info_t *t38gateway_info; - - if (session == NULL) - return; - - channel = switch_core_session_get_channel(session); - - /* Is this channel already set? */ - bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_t38gateway_"); - /* If yes */ - if (bug != NULL) { - /* If we have a stop remove audio bug */ - if (strcasecmp(data, "stop") == 0) { - switch_channel_set_private(channel, "_t38gateway_", NULL); - switch_core_media_bug_remove(session, &bug); - return; - } - - /* We have already started */ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n"); - - return; - } - - t38gateway_info = (t38gateway_session_info_t *) switch_core_session_alloc(session, sizeof(t38gateway_session_info_t)); - - t38gateway_info->session = session; - t38gateway_info->t38 = t38_gateway_init(NULL, tx_packet_handler, (void *) t38gateway_info); - t38gateway_info->t38_core = t38_gateway_get_t38_core_state(t38gateway_info->t38); - t38gateway_info->udptl = udptl_init(NULL, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, rx_packet_handler, (void *) t38gateway_info); - - status = switch_core_media_bug_add(session, "T.38 gateway", NULL, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug); - - if (status != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure hooking to stream\n"); - return; - } - - switch_channel_set_private(channel, "_t38gateway_", bug); -} - -/*! \brief Called when the module shuts down - * - * @author Steve Underwood - * @return The success or failure of the function. - */ -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_t38gateway_shutdown) -{ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "T.38 gateway disabled\n"); - - return SWITCH_STATUS_SUCCESS; -} - -/*! \brief FreeSWITCH API handler function. - * This function handles API calls such as the ones from mod_event_socket and in some cases - * scripts such as LUA scripts. - * - * @author Steve Underwood - * @return The success or failure of the function. - */ -SWITCH_STANDARD_API(t38gateway_api_main) -{ - switch_core_session_t *t38gateway_session; - switch_media_bug_t *bug; - t38gateway_session_info_t *t38gateway_info; - switch_channel_t *channel; - switch_status_t status; - int argc; - char *argv[T38GATEWAY_PARAMS]; - char *ccmd; - char *uuid; - char *command; - - /* No command? Display usage */ - if (cmd == NULL) { - stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX); - return SWITCH_STATUS_SUCCESS; - } - - /* Duplicated contents of original string */ - ccmd = strdup(cmd); - /* Separate the arguments */ - argc = switch_separate_string(ccmd, ' ', argv, T38GATEWAY_PARAMS); - - /* If we don't have the expected number of parameters - * display usage */ - if (argc != T38GATEWAY_PARAMS) { - stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX); - switch_safe_free(ccmd); - return SWITCH_STATUS_SUCCESS; - } - - uuid = argv[0]; - command = argv[1]; - - /* using uuid locate a reference to the FreeSWITCH session */ - t38gateway_session = switch_core_session_locate(uuid); - - /* If the session was not found exit */ - if (t38gateway_session == NULL) { - switch_safe_free(ccmd); - stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX); - return SWITCH_STATUS_FALSE; - } - - /* Get current channel of the session to tag the session - * This indicates that our module is present */ - channel = switch_core_session_get_channel(t38gateway_session); - - /* Is this channel already set? */ - bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_t38gateway_"); - /* If yes */ - if (bug != NULL) { - /* If we have a stop remove audio bug */ - if (strcasecmp(command, "stop") == 0) { - switch_channel_set_private(channel, "_t38gateway_", NULL); - switch_core_media_bug_remove(t38gateway_session, &bug); - switch_safe_free(ccmd); - stream->write_function(stream, "+OK\n"); - return SWITCH_STATUS_SUCCESS; - } - - /* We have already started */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n"); - - switch_safe_free(ccmd); - return SWITCH_STATUS_FALSE; - } - - /* If we don't see the expected start exit */ - if (strcasecmp(command, "start") != 0) { - switch_safe_free(ccmd); - stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX); - return SWITCH_STATUS_FALSE; - } - - /* Allocate memory attached to this FreeSWITCH session for - * use in the callback routine and to store state information */ - t38gateway_info = (t38gateway_session_info_t *) switch_core_session_alloc(t38gateway_session, sizeof(t38gateway_session_info_t)); - - /* Set initial values and states */ - t38gateway_info->session = t38gateway_session; - t38gateway_info->t38 = t38_gateway_init(NULL, tx_packet_handler, (void *) t38gateway_info); - t38gateway_info->t38_core = t38_gateway_get_t38_core_state(t38gateway_info->t38); - t38gateway_info->udptl = udptl_init(NULL, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, rx_packet_handler, (void *) t38gateway_info); - - /* Add a media bug that allows me to intercept the - * reading leg of the audio stream */ - status = switch_core_media_bug_add(t38gateway_session, "T.38 gateway", NULL, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug); - - /* If adding a media bug fails exit */ - if (status != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failure hooking to stream\n"); - - switch_safe_free(ccmd); - return SWITCH_STATUS_FALSE; - } - - /* Set the t38gateway tag to detect an existing t38gateway media bug */ - switch_channel_set_private(channel, "_t38gateway_", bug); - - /* Everything went according to plan! Notify the user */ - stream->write_function(stream, "+OK\n"); - - switch_safe_free(ccmd); - return SWITCH_STATUS_SUCCESS; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: - */ diff --git a/src/mod/applications/mod_t38gateway/udptl.c b/src/mod/applications/mod_t38gateway/udptl.c deleted file mode 100644 index a2651513f0..0000000000 --- a/src/mod/applications/mod_t38gateway/udptl.c +++ /dev/null @@ -1,563 +0,0 @@ -//#define UDPTL_DEBUG -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2009, Steve Underwood - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * Contributor(s): - * - * Steve Underwood - * - * udptl.c -- UDPTL handling for T.38 - * - */ - -#include -#include -#include -#include -#include - -#include "udptl.h" - -#define FALSE 0 -#define TRUE (!FALSE) - -static int decode_length(const uint8_t *buf, int limit, int *len, int *pvalue) -{ - if (*len >= limit) - return -1; - if ((buf[*len] & 0x80) == 0) { - *pvalue = buf[(*len)++]; - return 0; - } - if ((buf[*len] & 0x40) == 0) { - if (*len >= limit - 1) - return -1; - *pvalue = (buf[(*len)++] & 0x3F) << 8; - *pvalue |= buf[(*len)++]; - return 0; - } - *pvalue = (buf[(*len)++] & 0x3F) << 14; - /* Indicate we have a fragment */ - return 1; -} - -/*- End of function --------------------------------------------------------*/ - -static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8_t ** p_object, int *p_num_octets) -{ - int octet_cnt; - int octet_idx; - int stat; - int i; - const uint8_t **pbuf; - - for (octet_idx = 0, *p_num_octets = 0;; octet_idx += octet_cnt) { - if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0) - return -1; - if (octet_cnt > 0) { - *p_num_octets += octet_cnt; - - pbuf = &p_object[octet_idx]; - i = 0; - /* Make sure the buffer contains at least the number of bits requested */ - if ((*len + octet_cnt) > limit) - return -1; - - *pbuf = &buf[*len]; - *len += octet_cnt; - } - if (stat == 0) - break; - } - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -static int encode_length(uint8_t *buf, int *len, int value) -{ - int multiplier; - - if (value < 0x80) { - /* 1 octet */ - buf[(*len)++] = value; - return value; - } - if (value < 0x4000) { - /* 2 octets */ - /* Set the first bit of the first octet */ - buf[(*len)++] = ((0x8000 | value) >> 8) & 0xFF; - buf[(*len)++] = value & 0xFF; - return value; - } - /* Fragmentation */ - multiplier = (value < 0x10000) ? (value >> 14) : 4; - /* Set the first 2 bits of the octet */ - buf[(*len)++] = 0xC0 | multiplier; - return multiplier << 14; -} - -/*- End of function --------------------------------------------------------*/ - -static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num_octets) -{ - int enclen; - int octet_idx; - uint8_t zero_byte; - - /* If open type is of zero length, add a single zero byte (10.1) */ - if (num_octets == 0) { - zero_byte = 0; - data = &zero_byte; - num_octets = 1; - } - /* Encode the open type */ - for (octet_idx = 0;; num_octets -= enclen, octet_idx += enclen) { - if ((enclen = encode_length(buf, len, num_octets)) < 0) - return -1; - if (enclen > 0) { - memcpy(&buf[*len], &data[octet_idx], enclen); - *len += enclen; - } - if (enclen >= num_octets) - break; - } - - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) -{ - int stat; - int stat2; - int i; - int j; - int k; - int l; - int m; - int x; - int limit; - int which; - int ptr; - int count; - int total_count; - int seq_no; - const uint8_t *msg; - const uint8_t *data; - int msg_len; - int repaired[16]; - const uint8_t *bufs[16]; - int lengths[16]; - int span; - int entries; - - ptr = 0; - /* Decode seq_number */ - if (ptr + 2 > len) - return -1; - seq_no = (buf[0] << 8) | buf[1]; - ptr += 2; - /* Break out the primary packet */ - if ((stat = decode_open_type(buf, len, &ptr, &msg, &msg_len)) != 0) - return -1; - /* Decode error_recovery */ - if (ptr + 1 > len) - return -1; - /* Our buffers cannot tolerate overlength packets */ - if (msg_len > LOCAL_FAX_MAX_DATAGRAM) - return -1; - /* Update any missed slots in the buffer */ - for (i = s->rx_seq_no; seq_no > i; i++) { - x = i & UDPTL_BUF_MASK; - s->rx[x].buf_len = -1; - s->rx[x].fec_len[0] = 0; - s->rx[x].fec_span = 0; - s->rx[x].fec_entries = 0; - } - /* Save the new packet. Pure redundancy mode won't use this, but some systems will switch - into FEC mode after sending some redundant packets. */ - x = seq_no & UDPTL_BUF_MASK; - memcpy(s->rx[x].buf, msg, msg_len); - s->rx[x].buf_len = msg_len; - s->rx[x].fec_len[0] = 0; - s->rx[x].fec_span = 0; - s->rx[x].fec_entries = 0; - if ((buf[ptr++] & 0x80) == 0) { - /* Secondary packet mode for error recovery */ - /* We might have the packet we want, but we need to check through - the redundant stuff, and verify the integrity of the UDPTL. - This greatly reduces our chances of accepting garbage. */ - total_count = 0; - do { - if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) - return -1; - for (i = 0; i < count; i++) { - if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) - return -1; - } - total_count += count; - } - while (stat2 > 0); - /* We should now be exactly at the end of the packet. If not, this is a fault. */ - if (ptr != len) - return -1; - if (seq_no > s->rx_seq_no) { - /* We received a later packet than we expected, so we need to check if we can fill in the gap from the - secondary packets. */ - /* Step through in reverse order, so we go oldest to newest */ - for (i = total_count; i > 0; i--) { - if (seq_no - i >= s->rx_seq_no) { - /* This one wasn't seen before */ - /* Decode the secondary packet */ -#if defined(UDPTL_DEBUG) - fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); -#endif - /* Save the new packet. Redundancy mode won't use this, but some systems will switch into - FEC mode after sending some redundant packets, and this may then be important. */ - x = (seq_no - i) & UDPTL_BUF_MASK; - memcpy(s->rx[x].buf, bufs[i - 1], lengths[i - 1]); - s->rx[x].buf_len = lengths[i - 1]; - s->rx[x].fec_len[0] = 0; - s->rx[x].fec_span = 0; - s->rx[x].fec_entries = 0; - if (s->rx_packet_handler(s->user_data, bufs[i - 1], lengths[i - 1], seq_no - i) < 0) - fprintf(stderr, "Bad IFP\n"); - } - } - } - } else { - /* FEC mode for error recovery */ - - /* Decode the FEC packets */ - /* The span is defined as an unconstrained integer, but will never be more - than a small value. */ - if (ptr + 2 > len) - return -1; - if (buf[ptr++] != 1) - return -1; - span = buf[ptr++]; - - x = seq_no & UDPTL_BUF_MASK; - - s->rx[x].fec_span = span; - - memset(repaired, 0, sizeof(repaired)); - repaired[x] = TRUE; - - /* The number of entries is defined as a length, but will only ever be a small - value. Treat it as such. */ - if (ptr + 1 > len) - return -1; - entries = buf[ptr++]; - s->rx[x].fec_entries = entries; - - /* Decode the elements */ - for (i = 0; i < entries; i++) { - if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) - return -1; - if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM) - return -1; - - /* Save the new FEC data */ - memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); -#if 0 - fprintf(stderr, "FEC: "); - for (j = 0; j < s->rx[x].fec_len[i]; j++) - fprintf(stderr, "%02X ", data[j]); - fprintf(stderr, "\n"); -#endif - } - /* We should now be exactly at the end of the packet. If not, this is a fault. */ - if (ptr != len) - return -1; - /* See if we can reconstruct anything which is missing */ - /* TODO: this does not comprehensively hunt back and repair everything that is possible */ - for (l = x; l != ((x - (16 - span * entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { - if (s->rx[l].fec_len[0] <= 0) - continue; - for (m = 0; m < s->rx[l].fec_entries; m++) { - limit = (l + m) & UDPTL_BUF_MASK; - for (which = -1, k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; - k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) { - if (s->rx[k].buf_len <= 0) - which = (which == -1) ? k : -2; - } - if (which >= 0) { - /* Repairable */ - for (j = 0; j < s->rx[l].fec_len[m]; j++) { - s->rx[which].buf[j] = s->rx[l].fec[m][j]; - for (k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; - k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) - s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; - } - s->rx[which].buf_len = s->rx[l].fec_len[m]; - repaired[which] = TRUE; - } - } - } - /* Now play any new packets forwards in time */ - for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { - if (repaired[l]) { -#if defined(UDPTL_DEBUG) - fprintf(stderr, "Fixed packet %d, len %d\n", j, l); -#endif - if (s->rx_packet_handler(s->user_data, s->rx[l].buf, s->rx[l].buf_len, j) < 0) - fprintf(stderr, "Bad IFP\n"); - } - } - } - /* If packets are received out of sequence, we may have already processed this packet from the error - recovery information in a packet already received. */ - if (seq_no >= s->rx_seq_no) { - /* Decode the primary packet */ -#if defined(UDPTL_DEBUG) - fprintf(stderr, "Primary packet %d, len %d\n", seq_no, msg_len); -#endif - if (s->rx_packet_handler(s->user_data, msg, msg_len, seq_no) < 0) - fprintf(stderr, "Bad IFP\n"); - } - - s->rx_seq_no = (seq_no + 1) & 0xFFFF; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int msg_len) -{ - uint8_t fec[LOCAL_FAX_MAX_DATAGRAM]; - int i; - int j; - int seq; - int entry; - int entries; - int span; - int m; - int len; - int limit; - int high_tide; - - /* UDPTL cannot cope with zero length messages, and our buffering for redundancy limits their - maximum length. */ - if (msg_len < 1 || msg_len > LOCAL_FAX_MAX_DATAGRAM) - return -1; - seq = s->tx_seq_no & 0xFFFF; - - /* Map the sequence number to an entry in the circular buffer */ - entry = seq & UDPTL_BUF_MASK; - - /* We save the message in a circular buffer, for generating FEC or - redundancy sets later on. */ - s->tx[entry].buf_len = msg_len; - memcpy(s->tx[entry].buf, msg, msg_len); - - /* Build the UDPTL packet */ - - len = 0; - /* Encode the sequence number */ - buf[len++] = (seq >> 8) & 0xFF; - buf[len++] = seq & 0xFF; - - /* Encode the primary packet */ - if (encode_open_type(buf, &len, msg, msg_len) < 0) - return -1; - - /* Encode the appropriate type of error recovery information */ - switch (s->error_correction_scheme) { - case UDPTL_ERROR_CORRECTION_NONE: - /* Encode the error recovery type */ - buf[len++] = 0x00; - /* The number of entries will always be zero, so it is pointless allowing - for the fragmented case here. */ - if (encode_length(buf, &len, 0) < 0) - return -1; - break; - case UDPTL_ERROR_CORRECTION_REDUNDANCY: - /* Encode the error recovery type */ - buf[len++] = 0x00; - if (s->tx_seq_no > s->error_correction_entries) - entries = s->error_correction_entries; - else - entries = s->tx_seq_no; - /* The number of entries will always be small, so it is pointless allowing - for the fragmented case here. */ - if (encode_length(buf, &len, entries) < 0) - return -1; - /* Encode the elements */ - for (i = 0; i < entries; i++) { - j = (entry - i - 1) & UDPTL_BUF_MASK; - if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) - return -1; - } - break; - case UDPTL_ERROR_CORRECTION_FEC: - span = s->error_correction_span; - entries = s->error_correction_entries; - if (seq < s->error_correction_span * s->error_correction_entries) { - /* In the initial stages, wind up the FEC smoothly */ - entries = seq / s->error_correction_span; - if (seq < s->error_correction_span) - span = 0; - } - /* Encode the error recovery type */ - buf[len++] = 0x80; - /* Span is defined as an inconstrained integer, which it dumb. It will only - ever be a small value. Treat it as such. */ - buf[len++] = 1; - buf[len++] = span; - /* The number of entries is defined as a length, but will only ever be a small - value. Treat it as such. */ - buf[len++] = entries; - for (m = 0; m < entries; m++) { - /* Make an XOR'ed entry the maximum length */ - limit = (entry + m) & UDPTL_BUF_MASK; - high_tide = 0; - for (i = (limit - span * entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { - if (high_tide < s->tx[i].buf_len) { - for (j = 0; j < high_tide; j++) - fec[j] ^= s->tx[i].buf[j]; - for (; j < s->tx[i].buf_len; j++) - fec[j] = s->tx[i].buf[j]; - high_tide = s->tx[i].buf_len; - } else { - for (j = 0; j < s->tx[i].buf_len; j++) - fec[j] ^= s->tx[i].buf[j]; - } - } - if (encode_open_type(buf, &len, fec, high_tide) < 0) - return -1; - } - break; - } - - if (s->verbose) - fprintf(stderr, "\n"); - s->tx_seq_no++; - return len; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_set_error_correction(udptl_state_t *s, int ec_scheme, int span, int entries) -{ - switch (ec_scheme) { - case UDPTL_ERROR_CORRECTION_FEC: - case UDPTL_ERROR_CORRECTION_REDUNDANCY: - case UDPTL_ERROR_CORRECTION_NONE: - s->error_correction_scheme = ec_scheme; - break; - case -1: - /* Just don't change the scheme */ - break; - default: - return -1; - } - if (span >= 0) - s->error_correction_span = span; - if (entries >= 0) - s->error_correction_entries = entries; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_get_error_correction(udptl_state_t *s, int *ec_scheme, int *span, int *entries) -{ - if (ec_scheme) - *ec_scheme = s->error_correction_scheme; - if (span) - *span = s->error_correction_span; - if (entries) - *entries = s->error_correction_entries; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_set_local_max_datagram(udptl_state_t *s, int max_datagram) -{ - s->local_max_datagram_size = max_datagram; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_get_local_max_datagram(udptl_state_t *s) -{ - return s->local_max_datagram_size; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_set_far_max_datagram(udptl_state_t *s, int max_datagram) -{ - s->far_max_datagram_size = max_datagram; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_get_far_max_datagram(udptl_state_t *s) -{ - return s->far_max_datagram_size; -} - -/*- End of function --------------------------------------------------------*/ - -udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries, udptl_rx_packet_handler_t rx_packet_handler, void *user_data) -{ - int i; - - if (rx_packet_handler == NULL) - return NULL; - - if (s == NULL) { - if ((s = (udptl_state_t *) malloc(sizeof(*s))) == NULL) - return NULL; - } - memset(s, 0, sizeof(*s)); - - s->error_correction_scheme = ec_scheme; - s->error_correction_span = span; - s->error_correction_entries = entries; - - s->far_max_datagram_size = LOCAL_FAX_MAX_DATAGRAM; - s->local_max_datagram_size = LOCAL_FAX_MAX_DATAGRAM; - - memset(&s->rx, 0, sizeof(s->rx)); - memset(&s->tx, 0, sizeof(s->tx)); - for (i = 0; i <= UDPTL_BUF_MASK; i++) { - s->rx[i].buf_len = -1; - s->tx[i].buf_len = -1; - } - - s->rx_packet_handler = rx_packet_handler; - s->user_data = user_data; - - return s; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_release(udptl_state_t *s) -{ - return 0; -} - -/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ diff --git a/src/mod/applications/mod_t38gateway/udptl.h b/src/mod/applications/mod_t38gateway/udptl.h deleted file mode 100644 index 39740353d1..0000000000 --- a/src/mod/applications/mod_t38gateway/udptl.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2009, Steve Underwood - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * Contributor(s): - * - * Steve Underwood - * - * udptl.h -- UDPTL handling for T.38 - * - */ - -#if !defined(FREESWITCH_UDPTL_H) -#define FREESWITCH_UDPTL_H - -#define LOCAL_FAX_MAX_DATAGRAM 400 -#define LOCAL_FAX_MAX_FEC_PACKETS 5 - -#define UDPTL_BUF_MASK 15 - -typedef int (udptl_rx_packet_handler_t) (void *user_data, const uint8_t msg[], int len, int seq_no); - -typedef struct { - int buf_len; - uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]; -} udptl_fec_tx_buffer_t; - -typedef struct { - int buf_len; - uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]; - int fec_len[LOCAL_FAX_MAX_FEC_PACKETS]; - uint8_t fec[LOCAL_FAX_MAX_FEC_PACKETS][LOCAL_FAX_MAX_DATAGRAM]; - int fec_span; - int fec_entries; -} udptl_fec_rx_buffer_t; - -struct udptl_state_s { - udptl_rx_packet_handler_t *rx_packet_handler; - void *user_data; - - /*! This option indicates the error correction scheme used in transmitted UDPTL - packets. */ - int error_correction_scheme; - - /*! This option indicates the number of error correction entries transmitted in - UDPTL packets. */ - int error_correction_entries; - - /*! This option indicates the span of the error correction entries in transmitted - UDPTL packets (FEC only). */ - int error_correction_span; - - /*! This option indicates the maximum size of a datagram that can be accepted by - the remote device. */ - int far_max_datagram_size; - - /*! This option indicates the maximum size of a datagram that we are prepared to - accept. */ - int local_max_datagram_size; - - int verbose; - - int tx_seq_no; - int rx_seq_no; - int rx_expected_seq_no; - - udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1]; - udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1]; -}; - -enum { - UDPTL_ERROR_CORRECTION_NONE, - UDPTL_ERROR_CORRECTION_FEC, - UDPTL_ERROR_CORRECTION_REDUNDANCY -}; - -typedef struct udptl_state_s udptl_state_t; - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! \brief Process an arriving UDPTL packet. - \param s The UDPTL context. - \param buf The UDPTL packet buffer. - \param len The length of the packet. - \return 0 for OK. */ - int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len); - -/*! \brief Construct a UDPTL packet, ready for transmission. - \param s The UDPTL context. - \param buf The UDPTL packet buffer. - \param msg The primary packet. - \param len The length of the primary packet. - \return The length of the constructed UDPTL packet. */ - int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int msg_len); - -/*! \brief Change the error correction settings of a UDPTL context. - \param s The UDPTL context. - \param ec_scheme One of the optional error correction schemes. - \param span The packet span over which error correction should be applied. - \param entries The number of error correction entries to include in packets. - \return 0 for OK. */ - int udptl_set_error_correction(udptl_state_t *s, int ec_scheme, int span, int entries); - -/*! \brief Check the error correction settings of a UDPTL context. - \param s The UDPTL context. - \param ec_scheme One of the optional error correction schemes. - \param span The packet span over which error correction is being applied. - \param entries The number of error correction being included in packets. - \return 0 for OK. */ - int udptl_get_error_correction(udptl_state_t *s, int *ec_scheme, int *span, int *entries); - - int udptl_set_local_max_datagram(udptl_state_t *s, int max_datagram); - - int udptl_get_local_max_datagram(udptl_state_t *s); - - int udptl_set_far_max_datagram(udptl_state_t *s, int max_datagram); - - int udptl_get_far_max_datagram(udptl_state_t *s); - -/*! \brief Initialise a UDPTL context. - \param s The UDPTL context. - \param ec_scheme One of the optional error correction schemes. - \param span The packet span over which error correction should be applied. - \param entries The number of error correction entries to include in packets. - \param rx_packet_handler The callback function, used to report arriving IFP packets. - \param user_data An opaque pointer supplied to rx_packet_handler. - \return A pointer to the UDPTL context, or NULL if there was a problem. */ - udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries, udptl_rx_packet_handler_t rx_packet_handler, void *user_data); - -/*! \brief Release a UDPTL context. - \param s The UDPTL context. - \return 0 for OK. */ - int udptl_release(udptl_state_t *s); - -#if defined(__cplusplus) -} -#endif -#endif -/*- End of file ------------------------------------------------------------*/