Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
bdb9ed8b
提交
bdb9ed8b
authored
5月 21, 2010
作者:
Anthony Minessale
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
remove mod_t38_gateway
上级
8f32c803
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
0 行增加
和
1373 行删除
+0
-1373
Makefile.am
src/mod/applications/mod_t38gateway/Makefile.am
+0
-17
mod_t38gateway.2008.vcproj
...od/applications/mod_t38gateway/mod_t38gateway.2008.vcproj
+0
-291
mod_t38gateway.c
src/mod/applications/mod_t38gateway/mod_t38gateway.c
+0
-349
udptl.c
src/mod/applications/mod_t38gateway/udptl.c
+0
-563
udptl.h
src/mod/applications/mod_t38gateway/udptl.h
+0
-153
没有找到文件。
src/mod/applications/mod_t38gateway/Makefile.am
deleted
100644 → 0
浏览文件 @
8f32c803
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
src/mod/applications/mod_t38gateway/mod_t38gateway.2008.vcproj
deleted
100644 → 0
浏览文件 @
8f32c803
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType=
"Visual C++"
Version=
"9.00"
Name=
"mod_t38gateway"
ProjectGUID=
"{14E4A972-9CFB-436D-B0A5-4943F3F80D47}"
RootNamespace=
"mod_t38gateway"
Keyword=
"Win32Proj"
TargetFrameworkVersion=
"131072"
>
<Platforms>
<Platform
Name=
"Win32"
/>
<Platform
Name=
"x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name=
"Debug|Win32"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_debug.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCPreBuildEventTool"
/>
<Tool
Name=
"VCCustomBuildTool"
/>
<Tool
Name=
"VCXMLDataGeneratorTool"
/>
<Tool
Name=
"VCWebServiceProxyGeneratorTool"
/>
<Tool
Name=
"VCMIDLTool"
/>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""$(InputDir)..\..\..\..\libs\spandsp\src\msvc";"$(InputDir)..\..\..\..\libs\spandsp\src";"$(InputDir)..\..\..\..\libs\tiff-3.8.2\libtiff""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCManagedResourceCompilerTool"
/>
<Tool
Name=
"VCResourceCompilerTool"
/>
<Tool
Name=
"VCPreLinkEventTool"
/>
<Tool
Name=
"VCLinkerTool"
RandomizedBaseAddress=
"1"
DataExecutionPrevention=
"0"
/>
<Tool
Name=
"VCALinkTool"
/>
<Tool
Name=
"VCManifestTool"
/>
<Tool
Name=
"VCXDCMakeTool"
/>
<Tool
Name=
"VCBscMakeTool"
/>
<Tool
Name=
"VCFxCopTool"
/>
<Tool
Name=
"VCAppVerifierTool"
/>
<Tool
Name=
"VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name=
"Debug|x64"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_debug.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCPreBuildEventTool"
/>
<Tool
Name=
"VCCustomBuildTool"
/>
<Tool
Name=
"VCXMLDataGeneratorTool"
/>
<Tool
Name=
"VCWebServiceProxyGeneratorTool"
/>
<Tool
Name=
"VCMIDLTool"
TargetEnvironment=
"3"
/>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""$(InputDir)..\..\..\..\libs\spandsp\src\msvc";"$(InputDir)..\..\..\..\libs\spandsp\src";"$(InputDir)..\..\..\..\libs\tiff-3.8.2\libtiff""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCManagedResourceCompilerTool"
/>
<Tool
Name=
"VCResourceCompilerTool"
/>
<Tool
Name=
"VCPreLinkEventTool"
/>
<Tool
Name=
"VCLinkerTool"
OutputFile=
"$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
RandomizedBaseAddress=
"1"
DataExecutionPrevention=
"0"
TargetMachine=
"17"
/>
<Tool
Name=
"VCALinkTool"
/>
<Tool
Name=
"VCManifestTool"
/>
<Tool
Name=
"VCXDCMakeTool"
/>
<Tool
Name=
"VCBscMakeTool"
/>
<Tool
Name=
"VCFxCopTool"
/>
<Tool
Name=
"VCAppVerifierTool"
/>
<Tool
Name=
"VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name=
"Release|Win32"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_release.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCPreBuildEventTool"
/>
<Tool
Name=
"VCCustomBuildTool"
/>
<Tool
Name=
"VCXMLDataGeneratorTool"
/>
<Tool
Name=
"VCWebServiceProxyGeneratorTool"
/>
<Tool
Name=
"VCMIDLTool"
/>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""$(InputDir)..\..\..\..\libs\spandsp\src\msvc";"$(InputDir)..\..\..\..\libs\spandsp\src";"$(InputDir)..\..\..\..\libs\tiff-3.8.2\libtiff""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCManagedResourceCompilerTool"
/>
<Tool
Name=
"VCResourceCompilerTool"
/>
<Tool
Name=
"VCPreLinkEventTool"
/>
<Tool
Name=
"VCLinkerTool"
RandomizedBaseAddress=
"1"
DataExecutionPrevention=
"0"
/>
<Tool
Name=
"VCALinkTool"
/>
<Tool
Name=
"VCManifestTool"
/>
<Tool
Name=
"VCXDCMakeTool"
/>
<Tool
Name=
"VCBscMakeTool"
/>
<Tool
Name=
"VCFxCopTool"
/>
<Tool
Name=
"VCAppVerifierTool"
/>
<Tool
Name=
"VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name=
"Release|x64"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_release.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCPreBuildEventTool"
/>
<Tool
Name=
"VCCustomBuildTool"
/>
<Tool
Name=
"VCXMLDataGeneratorTool"
/>
<Tool
Name=
"VCWebServiceProxyGeneratorTool"
/>
<Tool
Name=
"VCMIDLTool"
TargetEnvironment=
"3"
/>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""$(InputDir)..\..\..\..\libs\spandsp\src\msvc";"$(InputDir)..\..\..\..\libs\spandsp\src";"$(InputDir)..\..\..\..\libs\tiff-3.8.2\libtiff""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCManagedResourceCompilerTool"
/>
<Tool
Name=
"VCResourceCompilerTool"
/>
<Tool
Name=
"VCPreLinkEventTool"
/>
<Tool
Name=
"VCLinkerTool"
OutputFile=
"$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
RandomizedBaseAddress=
"1"
DataExecutionPrevention=
"0"
TargetMachine=
"17"
/>
<Tool
Name=
"VCALinkTool"
/>
<Tool
Name=
"VCManifestTool"
/>
<Tool
Name=
"VCXDCMakeTool"
/>
<Tool
Name=
"VCBscMakeTool"
/>
<Tool
Name=
"VCFxCopTool"
/>
<Tool
Name=
"VCAppVerifierTool"
/>
<Tool
Name=
"VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=
".\mod_t38gateway.c"
>
</File>
<File
RelativePath=
".\udptl.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
src/mod/applications/mod_t38gateway/mod_t38gateway.c
deleted
100644 → 0
浏览文件 @
8f32c803
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2009, Steve Underwood <steveu@coppice.org>
*
* 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 <steveu@coppice.org>
*
* 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 <switch.h>
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
#include <spandsp.h>
#include <spandsp/version.h>
#include "udptl.h"
/*! Syntax of the API call. */
#define T38GATEWAY_SYNTAX "<uuid> <command>"
/*! 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:
*/
src/mod/applications/mod_t38gateway/udptl.c
deleted
100644 → 0
浏览文件 @
8f32c803
//#define UDPTL_DEBUG
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2009, Steve Underwood <steveu@coppice.org>
*
* 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 <steveu@coppice.org>
*
* udptl.c -- UDPTL handling for T.38
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <inttypes.h>
#include <memory.h>
#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 ------------------------------------------------------------*/
src/mod/applications/mod_t38gateway/udptl.h
deleted
100644 → 0
浏览文件 @
8f32c803
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2009, Steve Underwood <steveu@coppice.org>
*
* 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 <steveu@coppice.org>
*
* 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 ------------------------------------------------------------*/
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论