mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
				synced 2025-11-03 21:43:32 +00:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			rhizomatic
			...
			laforge/li
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					15f64b5199 | 
							
								
								
									
										118
									
								
								.clang-format
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								.clang-format
									
									
									
									
									
								
							@@ -1,118 +0,0 @@
 | 
			
		||||
# SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
#
 | 
			
		||||
# clang-format configuration file. Intended for clang-format >= 4.
 | 
			
		||||
#
 | 
			
		||||
# For more information, see:
 | 
			
		||||
#
 | 
			
		||||
#   Documentation/process/clang-format.rst
 | 
			
		||||
#   https://clang.llvm.org/docs/ClangFormat.html
 | 
			
		||||
#   https://clang.llvm.org/docs/ClangFormatStyleOptions.html
 | 
			
		||||
#
 | 
			
		||||
---
 | 
			
		||||
AccessModifierOffset: -4
 | 
			
		||||
AlignAfterOpenBracket: Align
 | 
			
		||||
AlignConsecutiveAssignments: false
 | 
			
		||||
AlignConsecutiveDeclarations: false
 | 
			
		||||
#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
 | 
			
		||||
AlignOperands: true
 | 
			
		||||
AlignTrailingComments: false
 | 
			
		||||
AllowAllParametersOfDeclarationOnNextLine: false
 | 
			
		||||
AllowShortBlocksOnASingleLine: false
 | 
			
		||||
AllowShortCaseLabelsOnASingleLine: false
 | 
			
		||||
AllowShortFunctionsOnASingleLine: None
 | 
			
		||||
AllowShortIfStatementsOnASingleLine: false
 | 
			
		||||
AllowShortLoopsOnASingleLine: false
 | 
			
		||||
AlwaysBreakAfterDefinitionReturnType: None
 | 
			
		||||
AlwaysBreakAfterReturnType: None
 | 
			
		||||
AlwaysBreakBeforeMultilineStrings: false
 | 
			
		||||
AlwaysBreakTemplateDeclarations: false
 | 
			
		||||
BinPackArguments: true
 | 
			
		||||
BinPackParameters: true
 | 
			
		||||
BraceWrapping:
 | 
			
		||||
  AfterClass: false
 | 
			
		||||
  AfterControlStatement: false
 | 
			
		||||
  AfterEnum: false
 | 
			
		||||
  AfterFunction: true
 | 
			
		||||
  AfterNamespace: true
 | 
			
		||||
  AfterObjCDeclaration: false
 | 
			
		||||
  AfterStruct: false
 | 
			
		||||
  AfterUnion: false
 | 
			
		||||
  #AfterExternBlock: false # Unknown to clang-format-5.0
 | 
			
		||||
  BeforeCatch: false
 | 
			
		||||
  BeforeElse: false
 | 
			
		||||
  IndentBraces: false
 | 
			
		||||
  #SplitEmptyFunction: true # Unknown to clang-format-4.0
 | 
			
		||||
  #SplitEmptyRecord: true # Unknown to clang-format-4.0
 | 
			
		||||
  #SplitEmptyNamespace: true # Unknown to clang-format-4.0
 | 
			
		||||
BreakBeforeBinaryOperators: None
 | 
			
		||||
BreakBeforeBraces: Custom
 | 
			
		||||
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
 | 
			
		||||
BreakBeforeTernaryOperators: false
 | 
			
		||||
BreakConstructorInitializersBeforeComma: false
 | 
			
		||||
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
 | 
			
		||||
BreakAfterJavaFieldAnnotations: false
 | 
			
		||||
BreakStringLiterals: false
 | 
			
		||||
ColumnLimit: 120
 | 
			
		||||
CommentPragmas: '^ IWYU pragma:'
 | 
			
		||||
#CompactNamespaces: false # Unknown to clang-format-4.0
 | 
			
		||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
 | 
			
		||||
ConstructorInitializerIndentWidth: 8
 | 
			
		||||
ContinuationIndentWidth: 8
 | 
			
		||||
Cpp11BracedListStyle: false
 | 
			
		||||
DerivePointerAlignment: false
 | 
			
		||||
DisableFormat: false
 | 
			
		||||
ExperimentalAutoDetectBinPacking: false
 | 
			
		||||
#FixNamespaceComments: false # Unknown to clang-format-4.0
 | 
			
		||||
 | 
			
		||||
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
 | 
			
		||||
IncludeCategories:
 | 
			
		||||
  - Regex: '.*'
 | 
			
		||||
    Priority: 1
 | 
			
		||||
IncludeIsMainRegex: '(Test)?$'
 | 
			
		||||
IndentCaseLabels: false
 | 
			
		||||
#IndentPPDirectives: None # Unknown to clang-format-5.0
 | 
			
		||||
IndentWidth: 8
 | 
			
		||||
IndentWrappedFunctionNames: false
 | 
			
		||||
JavaScriptQuotes: Leave
 | 
			
		||||
JavaScriptWrapImports: true
 | 
			
		||||
KeepEmptyLinesAtTheStartOfBlocks: false
 | 
			
		||||
MacroBlockBegin: ''
 | 
			
		||||
MacroBlockEnd: ''
 | 
			
		||||
MaxEmptyLinesToKeep: 1
 | 
			
		||||
NamespaceIndentation: None
 | 
			
		||||
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
 | 
			
		||||
ObjCBlockIndentWidth: 8
 | 
			
		||||
ObjCSpaceAfterProperty: true
 | 
			
		||||
ObjCSpaceBeforeProtocolList: true
 | 
			
		||||
 | 
			
		||||
# Taken from git's rules
 | 
			
		||||
#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
 | 
			
		||||
PenaltyBreakBeforeFirstCallParameter: 30
 | 
			
		||||
PenaltyBreakComment: 10
 | 
			
		||||
PenaltyBreakFirstLessLess: 0
 | 
			
		||||
PenaltyBreakString: 10
 | 
			
		||||
PenaltyExcessCharacter: 100
 | 
			
		||||
PenaltyReturnTypeOnItsOwnLine: 60
 | 
			
		||||
 | 
			
		||||
PointerAlignment: Right
 | 
			
		||||
ReflowComments: false
 | 
			
		||||
SortIncludes: false
 | 
			
		||||
#SortUsingDeclarations: false # Unknown to clang-format-4.0
 | 
			
		||||
SpaceAfterCStyleCast: false
 | 
			
		||||
SpaceAfterTemplateKeyword: true
 | 
			
		||||
SpaceBeforeAssignmentOperators: true
 | 
			
		||||
#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
 | 
			
		||||
#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
 | 
			
		||||
SpaceBeforeParens: ControlStatements
 | 
			
		||||
#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
 | 
			
		||||
SpaceInEmptyParentheses: false
 | 
			
		||||
SpacesBeforeTrailingComments: 1
 | 
			
		||||
SpacesInAngles: false
 | 
			
		||||
SpacesInContainerLiterals: false
 | 
			
		||||
SpacesInCStyleCastParentheses: false
 | 
			
		||||
SpacesInParentheses: false
 | 
			
		||||
SpacesInSquareBrackets: false
 | 
			
		||||
Standard: Cpp03
 | 
			
		||||
TabWidth: 8
 | 
			
		||||
UseTab: Always
 | 
			
		||||
...
 | 
			
		||||
							
								
								
									
										58
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -2,21 +2,26 @@ debian/*.log
 | 
			
		||||
*.o
 | 
			
		||||
*.lo
 | 
			
		||||
*.a
 | 
			
		||||
*.la
 | 
			
		||||
.deps
 | 
			
		||||
Makefile
 | 
			
		||||
Makefile.in
 | 
			
		||||
bscconfig.h
 | 
			
		||||
bscconfig.h.in
 | 
			
		||||
src/osmo-mgw/osmo-mgw
 | 
			
		||||
openbsc.pc
 | 
			
		||||
src/osmo-nitb/osmo-nitb
 | 
			
		||||
src/osmo-bsc_mgcp/osmo-bsc_mgcp
 | 
			
		||||
src/osmo-bsc/osmo-bsc
 | 
			
		||||
src/utils/meas_vis
 | 
			
		||||
src/utils/meas_json
 | 
			
		||||
src/utils/osmo-meas-pcap2db
 | 
			
		||||
src/utils/osmo-meas-udp2db
 | 
			
		||||
src/utils/smpp_mirror
 | 
			
		||||
*.*~
 | 
			
		||||
*.sw?
 | 
			
		||||
.libs
 | 
			
		||||
*.pyc
 | 
			
		||||
*.gcda
 | 
			
		||||
*.gcno
 | 
			
		||||
*.pc
 | 
			
		||||
*~
 | 
			
		||||
 | 
			
		||||
#configure
 | 
			
		||||
aclocal.m4
 | 
			
		||||
@@ -33,16 +38,38 @@ missing
 | 
			
		||||
stamp-h1
 | 
			
		||||
libtool
 | 
			
		||||
ltmain.sh
 | 
			
		||||
m4/*.m4
 | 
			
		||||
 | 
			
		||||
# git-version-gen magic
 | 
			
		||||
.tarball-version
 | 
			
		||||
.version
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# apps and app data
 | 
			
		||||
hlr.sqlite3
 | 
			
		||||
src/utils/bs11_config
 | 
			
		||||
src/ipaccess/ipaccess-config
 | 
			
		||||
src/ipaccess/abisip-find
 | 
			
		||||
src/ipaccess/ipaccess-firmware
 | 
			
		||||
src/ipaccess/ipaccess-proxy
 | 
			
		||||
src/utils/isdnsync
 | 
			
		||||
src/nat/bsc_nat
 | 
			
		||||
src/gprs/osmo-sgsn
 | 
			
		||||
src/gprs/osmo-gbproxy
 | 
			
		||||
src/gprs/osmo-gtphub
 | 
			
		||||
src/osmo-bsc_nat/osmo-bsc_nat
 | 
			
		||||
src/libcommon/gsup_test_client
 | 
			
		||||
src/osmo-msc/osmo-msc
 | 
			
		||||
 | 
			
		||||
#tests
 | 
			
		||||
tests/testsuite.dir
 | 
			
		||||
tests/*/*_test
 | 
			
		||||
# ignore compiled binaries like msc_vlr_test_foo; do not ignore
 | 
			
		||||
# msc_vlr_test_foo.{c,ok,err}, but do still ignore the corresponding .o object
 | 
			
		||||
# files:
 | 
			
		||||
tests/msc_vlr/msc_vlr_test_*
 | 
			
		||||
!tests/msc_vlr/msc_vlr_test_*.*
 | 
			
		||||
tests/msc_vlr/msc_vlr_test_*.o
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
tests/atconfig
 | 
			
		||||
tests/atlocal
 | 
			
		||||
@@ -50,22 +77,7 @@ tests/package.m4
 | 
			
		||||
tests/testsuite
 | 
			
		||||
tests/testsuite.log
 | 
			
		||||
 | 
			
		||||
gsn_restart
 | 
			
		||||
src/openbsc.cfg*
 | 
			
		||||
writtenconfig/
 | 
			
		||||
 | 
			
		||||
# manuals
 | 
			
		||||
doc/manuals/*.html
 | 
			
		||||
doc/manuals/*.svg
 | 
			
		||||
doc/manuals/*.pdf
 | 
			
		||||
doc/manuals/*__*.png
 | 
			
		||||
doc/manuals/*.check
 | 
			
		||||
doc/manuals/generated/
 | 
			
		||||
doc/manuals/osmomsc-usermanual.xml
 | 
			
		||||
doc/manuals/common
 | 
			
		||||
doc/manuals/build
 | 
			
		||||
 | 
			
		||||
contrib/osmo-mgw.spec
 | 
			
		||||
 | 
			
		||||
#vs code
 | 
			
		||||
.cache
 | 
			
		||||
.vscode
 | 
			
		||||
 | 
			
		||||
gtphub_restart_count
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								Makefile.am
									
									
									
									
									
								
							@@ -9,29 +9,22 @@ AM_CPPFLAGS = \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
SUBDIRS = \
 | 
			
		||||
	doc \
 | 
			
		||||
	include \
 | 
			
		||||
	src \
 | 
			
		||||
	tests \
 | 
			
		||||
	doc \
 | 
			
		||||
	contrib \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
pkgconfigdir = $(libdir)/pkgconfig
 | 
			
		||||
pkgconfig_DATA = \
 | 
			
		||||
	libosmo-legacy-mgcp.pc \
 | 
			
		||||
	libosmo-mgcp-client.pc \
 | 
			
		||||
	libosmo-mgcp.pc \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
BUILT_SOURCES = $(top_srcdir)/.version
 | 
			
		||||
EXTRA_DIST = \
 | 
			
		||||
	     .version \
 | 
			
		||||
	     README.md \
 | 
			
		||||
	     debian \
 | 
			
		||||
	     git-version-gen \
 | 
			
		||||
	     osmoappdesc.py \
 | 
			
		||||
	     $(NULL)
 | 
			
		||||
 | 
			
		||||
AM_DISTCHECK_CONFIGURE_FLAGS = \
 | 
			
		||||
	--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
 | 
			
		||||
EXTRA_DIST = git-version-gen osmoappdesc.py .version
 | 
			
		||||
 | 
			
		||||
@RELMAKE@
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
About OsmoMGW
 | 
			
		||||
=============
 | 
			
		||||
 | 
			
		||||
OsmoMGW originated from the OpenBSC project, which started as a minimalistic
 | 
			
		||||
all-in-one implementation of the GSM Network. In 2017, OpenBSC had reached
 | 
			
		||||
maturity and diversity (including M3UA SIGTRAN and 3G support in the form of
 | 
			
		||||
IuCS and IuPS interfaces) that naturally lead to a separation of the all-in-one
 | 
			
		||||
approach to fully independent separate programs as in typical GSM networks.
 | 
			
		||||
 | 
			
		||||
OsmoMGW was one of the parts split off from the old openbsc.git. It originated
 | 
			
		||||
as a solution to merely navigate RTP streams through a NAT, but has since
 | 
			
		||||
matured to a Media Gateway implementation that is capable of streaming RTP for
 | 
			
		||||
2G (AoIP) and 3G (IuCS) GSM networks as well as (still not implemented at time
 | 
			
		||||
of writing) transcoding between TRAU, various RTP payloads and IuUP.
 | 
			
		||||
 | 
			
		||||
The OsmoMGW program exposes an MGCP interface towards clients like OsmoMSC and
 | 
			
		||||
OsmoBSC, and receives and sends RTP streams as configured via MGCP.
 | 
			
		||||
 | 
			
		||||
The libosmo-mgcp-client library exposes utilities used by e.g. OsmoMSC (found
 | 
			
		||||
in osmo-msc.git) to instruct OsmoMGW via its MGCP service.
 | 
			
		||||
 | 
			
		||||
The libosmo-mgcp library exposes MGCP server utilities used by e.g. OsmoBSC-NAT
 | 
			
		||||
(found in osmo-bsc.git) to navigate RTP streams through a NAT.
 | 
			
		||||
(At time of writing, this is still called libosmo-legacy-mgcp.)
 | 
			
		||||
 | 
			
		||||
Find OsmoMGW issue tracker and wiki online at
 | 
			
		||||
https://osmocom.org/projects/osmo-mgw
 | 
			
		||||
https://osmocom.org/projects/osmo-mgw/wiki
 | 
			
		||||
							
								
								
									
										102
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								README.md
									
									
									
									
									
								
							@@ -1,102 +0,0 @@
 | 
			
		||||
osmo-mgw - Osmocom MGW (Media GateWay) Implementation
 | 
			
		||||
=====================================================
 | 
			
		||||
 | 
			
		||||
This repository contains a C-language implementation of an MGW (Media
 | 
			
		||||
GateWay) for use [not only] within the 2G (GSM) and/or 3G (UMTS)
 | 
			
		||||
Cellular Network built using Osmocom CNI (Cellular Network
 | 
			
		||||
Infrastructure) software.
 | 
			
		||||
 | 
			
		||||
The OsmoMGW program provides an MGCP interface towards an MGCP call agent
 | 
			
		||||
(client) like OsmoMSC and OsmoBSC, and receives and sends RTP streams as
 | 
			
		||||
configured via the MGCP control plane.
 | 
			
		||||
 | 
			
		||||
This Media Gateway implementation is capable of
 | 
			
		||||
 | 
			
		||||
* streaming RTP for 2G (3GPP AoIP and Abis-over-IP)
 | 
			
		||||
* streaming RTP for 3G (IuCS including the IuFP protocol)
 | 
			
		||||
* TDM (E1/T1) based Abis interface with TRAU frames on 16k sub-slots
 | 
			
		||||
* basic support for LCLS (Local Call, Local Switch) related features
 | 
			
		||||
* various built-in translation capabilities
 | 
			
		||||
  * between Abis TRAU frames and RTP formats
 | 
			
		||||
  * between 2G AMR/RTP and 3G AMR/IuFP/RTP
 | 
			
		||||
  * between bandwidth-efficient and octet-aligned AMR
 | 
			
		||||
  * between different standards for encapsulating GSM HR codec frames in RTP
 | 
			
		||||
 | 
			
		||||
osmo-mgw is typically co-located with
 | 
			
		||||
 | 
			
		||||
 * osmo-bsc (GSM BSC)
 | 
			
		||||
 * osmo-msc (GSM/UMTS MSC)
 | 
			
		||||
 * osmo-hnbgw (UMTS HNBGW); osmo-mgw implements RTP relay between Iuh
 | 
			
		||||
   and IuCS interfaces
 | 
			
		||||
 | 
			
		||||
The libosmo-mgcp-client library exposes utilities used by e.g. OsmoMSC
 | 
			
		||||
(found in osmo-msc.git) to instruct OsmoMGW via its MGCP service.
 | 
			
		||||
 | 
			
		||||
Homepage
 | 
			
		||||
--------
 | 
			
		||||
 | 
			
		||||
You can find the OsmoMGW issue tracker and wiki online at
 | 
			
		||||
<https://osmocom.org/projects/osmo-mgw> and <https://osmocom.org/projects/osmo-mgw/wiki>.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GIT Repository
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
You can clone from the official osmo-mgw.git repository using
 | 
			
		||||
 | 
			
		||||
        git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw
 | 
			
		||||
 | 
			
		||||
There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Documentation
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
User Manuals and VTY reference manuals are [optionally] built in PDF form
 | 
			
		||||
as part of the build process.
 | 
			
		||||
 | 
			
		||||
Pre-rendered PDF version of the current "master" can be found at
 | 
			
		||||
[User Manual](https://ftp.osmocom.org/docs/latest/osmomgw-usermanual.pdf)
 | 
			
		||||
as well as the [VTY Reference Manual](https://ftp.osmocom.org/docs/latest/osmomgw-vty-reference.pdf)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Mailing List
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
Discussions related to osmo-mgw are happening on the
 | 
			
		||||
openbsc@lists.osmocom.org mailing list, please see
 | 
			
		||||
<https://lists.osmocom.org/mailman/listinfo/openbsc> for subscription
 | 
			
		||||
options and the list archive.
 | 
			
		||||
 | 
			
		||||
Please observe the [Osmocom Mailing List
 | 
			
		||||
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
 | 
			
		||||
when posting.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Contributing
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
Our coding standards are described at
 | 
			
		||||
<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
 | 
			
		||||
 | 
			
		||||
We use a gerrit based patch submission/review process for managing
 | 
			
		||||
contributions.  Please see
 | 
			
		||||
<https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for
 | 
			
		||||
more details
 | 
			
		||||
 | 
			
		||||
The current patch queue for osmo-mgw can be seen at
 | 
			
		||||
<https://gerrit.osmocom.org/#/q/project:osmo-mgw+status:open>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
History
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
OsmoMGW originated from the OpenBSC project, which started as a minimalistic
 | 
			
		||||
all-in-one implementation of the GSM Network. In 2017, OpenBSC had reached
 | 
			
		||||
maturity and diversity (including M3UA SIGTRAN and 3G support in the form of
 | 
			
		||||
IuCS and IuPS interfaces) that naturally lead to a separation of the all-in-one
 | 
			
		||||
approach to fully independent separate programs as in typical GSM networks.
 | 
			
		||||
 | 
			
		||||
OsmoMGW was one of the parts split off from the old openbsc.git. It originated
 | 
			
		||||
as a solution to merely navigate RTP streams through a NAT, but has since
 | 
			
		||||
matured.
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
To run the configuration parsing and output (VTY) test suite, first install
 | 
			
		||||
 | 
			
		||||
  https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests
 | 
			
		||||
  git://git.osmocom.org/python/osmo-python-tests
 | 
			
		||||
 | 
			
		||||
and pass the following configure options here:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								TODO-RELEASE
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								TODO-RELEASE
									
									
									
									
									
								
							@@ -1,11 +1,29 @@
 | 
			
		||||
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
 | 
			
		||||
# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
 | 
			
		||||
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
 | 
			
		||||
# LIBVERSION=c:r:a
 | 
			
		||||
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
 | 
			
		||||
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a.
 | 
			
		||||
# If any interfaces have been added since the last public release: c:r:a + 1.
 | 
			
		||||
# If any interfaces have been removed or changed since the last public release: c:r:0.
 | 
			
		||||
#library	what			description / commit summary line
 | 
			
		||||
libosmocore		bump_dep; workaround	Bump libosmocore version dependency after I68328adb952ca8833ba047cb3b49ccc6f8a1f1b5
 | 
			
		||||
						has been merged to libosmocore.git; then remove my_msgb_copy_c wrapper function.
 | 
			
		||||
# When cleaning up this file upon a release:
 | 
			
		||||
#
 | 
			
		||||
# - Note that the release version number is entirely unrelated to the API
 | 
			
		||||
#   versions. A release version 5.2.3 may happily have an API version of 42:7:5.
 | 
			
		||||
#
 | 
			
		||||
# - Bump API version in src/lib*/Makefile.am files according to chapter
 | 
			
		||||
#   "Library interface versions" of the libtool documentation.
 | 
			
		||||
#   https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
 | 
			
		||||
#
 | 
			
		||||
# - Iff the 'current' API version has changed, rename debian/lib*.install
 | 
			
		||||
#
 | 
			
		||||
# API version bumping for the impatient:
 | 
			
		||||
# LIBVERSION=c:r:a  (current:revision_of_current:backwards_compat_age)
 | 
			
		||||
# 5:2:4 means that
 | 
			
		||||
# - this implements version 5 of the API;
 | 
			
		||||
# - this is the 2nd (compatible) revision of API version 5;
 | 
			
		||||
# - this is backwards compatible to all APIs since 4 versions ago,
 | 
			
		||||
#   i.e. callers that need API versions from 1 to 5 can use this.
 | 
			
		||||
#
 | 
			
		||||
# Bumping API versions recipe:
 | 
			
		||||
# If the library source code has changed at all since the last update, r++;
 | 
			
		||||
# If any interfaces have been added, removed, or changed since the last update, c++, r=0;
 | 
			
		||||
# If any interfaces have been added since the last public release, a++;
 | 
			
		||||
# If any interfaces have been removed or changed since the last public release, a=0.
 | 
			
		||||
#
 | 
			
		||||
#library		what		description / commit summary line
 | 
			
		||||
libosmo-mgcp		API/ABI change	parse and represent connection identifiers as hex strings
 | 
			
		||||
libosmo-mgcp		API/ABI change	connection identifiers are assigned by the server, not CA
 | 
			
		||||
libosmo-mgcp-client	API/ABI change	parse and store connection identifier in response
 | 
			
		||||
							
								
								
									
										152
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								configure.ac
									
									
									
									
									
								
							@@ -9,8 +9,6 @@ AC_CONFIG_AUX_DIR([.])
 | 
			
		||||
AM_INIT_AUTOMAKE([dist-bzip2])
 | 
			
		||||
AC_CONFIG_TESTDIR(tests)
 | 
			
		||||
 | 
			
		||||
CFLAGS="$CFLAGS -std=gnu11"
 | 
			
		||||
 | 
			
		||||
dnl kernel style compile messages
 | 
			
		||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 | 
			
		||||
 | 
			
		||||
@@ -24,11 +22,6 @@ AC_PROG_CC
 | 
			
		||||
AC_PROG_INSTALL
 | 
			
		||||
LT_INIT
 | 
			
		||||
 | 
			
		||||
dnl patching ${archive_cmds} to affect generation of file "libtool" to fix linking with clang
 | 
			
		||||
AS_CASE(["$LD"],[*clang*],
 | 
			
		||||
  [AS_CASE(["${host_os}"],
 | 
			
		||||
     [*linux*],[archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'])])
 | 
			
		||||
 | 
			
		||||
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
 | 
			
		||||
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
 | 
			
		||||
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
 | 
			
		||||
@@ -36,25 +29,20 @@ if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
 | 
			
		||||
fi
 | 
			
		||||
PKG_PROG_PKG_CONFIG([0.20])
 | 
			
		||||
 | 
			
		||||
dnl check for AX_CHECK_COMPILE_FLAG
 | 
			
		||||
m4_ifdef([AX_CHECK_COMPILE_FLAG], [], [
 | 
			
		||||
	AC_MSG_ERROR([Please install autoconf-archive; re-run 'autoreconf -fi' for it to take effect.])
 | 
			
		||||
	])
 | 
			
		||||
 | 
			
		||||
dnl checks for libraries
 | 
			
		||||
AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DL="$LIBS";LIBS=""])
 | 
			
		||||
AC_SUBST(LIBRARY_DL)
 | 
			
		||||
 | 
			
		||||
AC_SEARCH_LIBS([dlsym], [dl dld], [LIBRARY_DLSYM="$LIBS";LIBS=""])
 | 
			
		||||
AC_SUBST(LIBRARY_DLSYM)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.11.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.11.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.11.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.11.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.6.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 2.0.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 2.0.0)
 | 
			
		||||
 | 
			
		||||
CFLAGS="$CFLAGS -DBUILDING_LIBOSMOMGCPCLIENT -pthread"
 | 
			
		||||
CPPFLAGS="$CPPFLAGS -DBUILDING_LIBOSMOMGCPCLIENT -pthread"
 | 
			
		||||
LDFLAGS="$LDFLAGS -pthread"
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.1.0)
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(sanitize,
 | 
			
		||||
	[AS_HELP_STRING(
 | 
			
		||||
@@ -68,24 +56,41 @@ then
 | 
			
		||||
	CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(werror,
 | 
			
		||||
	[AS_HELP_STRING(
 | 
			
		||||
		[--enable-werror],
 | 
			
		||||
		[Turn all compiler warnings into errors, with exceptions:
 | 
			
		||||
		 a) deprecation (allow upstream to mark deprecation without breaking builds);
 | 
			
		||||
		 b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds)
 | 
			
		||||
		]
 | 
			
		||||
	)],
 | 
			
		||||
	[werror=$enableval], [werror="no"])
 | 
			
		||||
if test x"$werror" = x"yes"
 | 
			
		||||
then
 | 
			
		||||
	WERROR_FLAGS="-Werror"
 | 
			
		||||
	WERROR_FLAGS+=" -Werror=implicit-int -Werror=int-conversion -Werror=old-style-definition"
 | 
			
		||||
	WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
 | 
			
		||||
	WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
 | 
			
		||||
	CFLAGS="$CFLAGS $WERROR_FLAGS"
 | 
			
		||||
	CPPFLAGS="$CPPFLAGS $WERROR_FLAGS"
 | 
			
		||||
# Enable/disable transcoding within osmo-bsc_mgcp?
 | 
			
		||||
AC_ARG_ENABLE([mgcp-transcoding], [AS_HELP_STRING([--enable-mgcp-transcoding], [Build the MGCP gateway with internal transcoding enabled.])],
 | 
			
		||||
    [osmo_ac_mgcp_transcoding="$enableval"],[osmo_ac_mgcp_transcoding="no"])
 | 
			
		||||
AC_ARG_WITH([g729], [AS_HELP_STRING([--with-g729], [Enable G.729 encoding/decoding.])], [osmo_ac_with_g729="$withval"],[osmo_ac_with_g729="no"])
 | 
			
		||||
 | 
			
		||||
if test "$osmo_ac_mgcp_transcoding" = "yes" ; then
 | 
			
		||||
    AC_SEARCH_LIBS([gsm_create], [gsm], [LIBRARY_GSM="$LIBS";LIBS=""], [AC_MSG_ERROR([--enable-mgcp-transcoding: cannot find usable libgsm])])
 | 
			
		||||
    AC_SUBST(LIBRARY_GSM)
 | 
			
		||||
    if test "$osmo_ac_with_g729" = "yes" ; then
 | 
			
		||||
	PKG_CHECK_MODULES(LIBBCG729, libbcg729 >= 0.1, [AC_DEFINE([HAVE_BCG729], [1], [Use bgc729 decoder/encoder])])
 | 
			
		||||
    fi
 | 
			
		||||
    AC_DEFINE(BUILD_MGCP_TRANSCODING, 1, [Define if we want to build the MGCP gateway with transcoding support])
 | 
			
		||||
fi
 | 
			
		||||
AM_CONDITIONAL(BUILD_MGCP_TRANSCODING, test "x$osmo_ac_mgcp_transcoding" = "xyes")
 | 
			
		||||
AC_SUBST(osmo_ac_mgcp_transcoding)
 | 
			
		||||
 | 
			
		||||
dnl Checks for typedefs, structures and compiler characteristics
 | 
			
		||||
 | 
			
		||||
# The following test is taken from WebKit's webkit.m4
 | 
			
		||||
saved_CFLAGS="$CFLAGS"
 | 
			
		||||
CFLAGS="$CFLAGS -fvisibility=hidden "
 | 
			
		||||
AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden])
 | 
			
		||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
 | 
			
		||||
      [ AC_MSG_RESULT([yes])
 | 
			
		||||
        SYMBOL_VISIBILITY="-fvisibility=hidden"],
 | 
			
		||||
        AC_MSG_RESULT([no]))
 | 
			
		||||
CFLAGS="$saved_CFLAGS"
 | 
			
		||||
AC_SUBST(SYMBOL_VISIBILITY)
 | 
			
		||||
 | 
			
		||||
AX_CHECK_COMPILE_FLAG([-Werror=implicit], [CFLAGS="$CFLAGS -Werror=implicit"])
 | 
			
		||||
AX_CHECK_COMPILE_FLAG([-Werror=maybe-uninitialized], [CFLAGS="$CFLAGS -Werror=maybe-uninitialized"])
 | 
			
		||||
AX_CHECK_COMPILE_FLAG([-Werror=memset-transposed-args], [CFLAGS="$CFLAGS -Werror=memset-transposed-args"])
 | 
			
		||||
AX_CHECK_COMPILE_FLAG([-Werror=null-dereference], [CFLAGS="$CFLAGS -Werror=null-dereference"])
 | 
			
		||||
AX_CHECK_COMPILE_FLAG([-Werror=sizeof-array-argument], [CFLAGS="$CFLAGS -Werror=sizeof-array-argument"])
 | 
			
		||||
AX_CHECK_COMPILE_FLAG([-Werror=sizeof-pointer-memaccess], [CFLAGS="$CFLAGS -Werror=sizeof-pointer-memaccess"])
 | 
			
		||||
 | 
			
		||||
# Coverage build taken from WebKit's configure.in
 | 
			
		||||
AC_MSG_CHECKING([whether to enable code coverage support])
 | 
			
		||||
@@ -114,94 +119,37 @@ if test "x$enable_ext_tests" = "xyes" ; then
 | 
			
		||||
	AM_PATH_PYTHON
 | 
			
		||||
	AC_CHECK_PROG(OSMOTESTEXT_CHECK,osmotestvty.py,yes)
 | 
			
		||||
	 if test "x$OSMOTESTEXT_CHECK" != "xyes" ; then
 | 
			
		||||
		AC_MSG_ERROR([Please install https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests to run the VTY/CTRL tests.])
 | 
			
		||||
		AC_MSG_ERROR([Please install git://osmocom.org/python/osmo-python-tests to run the VTY/CTRL tests.])
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
AC_MSG_CHECKING([whether to enable VTY/CTRL tests])
 | 
			
		||||
AC_MSG_RESULT([$enable_ext_tests])
 | 
			
		||||
AM_CONDITIONAL(ENABLE_EXT_TESTS, test "x$enable_ext_tests" = "xyes")
 | 
			
		||||
 | 
			
		||||
# Generate manuals
 | 
			
		||||
AC_ARG_ENABLE(manuals,
 | 
			
		||||
	[AS_HELP_STRING(
 | 
			
		||||
		[--enable-manuals],
 | 
			
		||||
		[Generate manual PDFs [default=no]],
 | 
			
		||||
	)],
 | 
			
		||||
	[osmo_ac_build_manuals=$enableval], [osmo_ac_build_manuals="no"])
 | 
			
		||||
AM_CONDITIONAL([BUILD_MANUALS], [test x"$osmo_ac_build_manuals" = x"yes"])
 | 
			
		||||
AC_ARG_VAR(OSMO_GSM_MANUALS_DIR, [path to common osmo-gsm-manuals files, overriding pkg-config and "../osmo-gsm-manuals"
 | 
			
		||||
	fallback])
 | 
			
		||||
if test x"$osmo_ac_build_manuals" = x"yes"
 | 
			
		||||
then
 | 
			
		||||
	# Find OSMO_GSM_MANUALS_DIR (env, pkg-conf, fallback)
 | 
			
		||||
	if test -n "$OSMO_GSM_MANUALS_DIR"; then
 | 
			
		||||
		echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from env)"
 | 
			
		||||
	else
 | 
			
		||||
		OSMO_GSM_MANUALS_DIR="$($PKG_CONFIG osmo-gsm-manuals --variable=osmogsmmanualsdir 2>/dev/null)"
 | 
			
		||||
		if test -n "$OSMO_GSM_MANUALS_DIR"; then
 | 
			
		||||
			echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from pkg-conf)"
 | 
			
		||||
		else
 | 
			
		||||
			OSMO_GSM_MANUALS_DIR="../osmo-gsm-manuals"
 | 
			
		||||
			echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (fallback)"
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
	if ! test -d "$OSMO_GSM_MANUALS_DIR"; then
 | 
			
		||||
		AC_MSG_ERROR("OSMO_GSM_MANUALS_DIR does not exist! Install osmo-gsm-manuals or set OSMO_GSM_MANUALS_DIR.")
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	# Find and run check-depends
 | 
			
		||||
	CHECK_DEPENDS="$OSMO_GSM_MANUALS_DIR/check-depends.sh"
 | 
			
		||||
	if ! test -x "$CHECK_DEPENDS"; then
 | 
			
		||||
		CHECK_DEPENDS="osmo-gsm-manuals-check-depends"
 | 
			
		||||
	fi
 | 
			
		||||
	if ! $CHECK_DEPENDS; then
 | 
			
		||||
		AC_MSG_ERROR("missing dependencies for --enable-manuals")
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	# Put in Makefile with absolute path
 | 
			
		||||
	OSMO_GSM_MANUALS_DIR="$(realpath "$OSMO_GSM_MANUALS_DIR")"
 | 
			
		||||
	AC_SUBST([OSMO_GSM_MANUALS_DIR])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# https://www.freedesktop.org/software/systemd/man/daemon.html
 | 
			
		||||
AC_ARG_WITH([systemdsystemunitdir],
 | 
			
		||||
     [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],,
 | 
			
		||||
     [with_systemdsystemunitdir=auto])
 | 
			
		||||
AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
 | 
			
		||||
     def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
 | 
			
		||||
 | 
			
		||||
     AS_IF([test "x$def_systemdsystemunitdir" = "x"],
 | 
			
		||||
   [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"],
 | 
			
		||||
    [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
 | 
			
		||||
    with_systemdsystemunitdir=no],
 | 
			
		||||
   [with_systemdsystemunitdir="$def_systemdsystemunitdir"])])
 | 
			
		||||
AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
 | 
			
		||||
      [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
 | 
			
		||||
AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
 | 
			
		||||
 | 
			
		||||
AC_MSG_RESULT([CFLAGS="$CFLAGS"])
 | 
			
		||||
AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
 | 
			
		||||
 | 
			
		||||
dnl Generate the output
 | 
			
		||||
AM_CONFIG_HEADER(bscconfig.h)
 | 
			
		||||
 | 
			
		||||
AC_OUTPUT(
 | 
			
		||||
    libosmo-legacy-mgcp.pc
 | 
			
		||||
    libosmo-mgcp-client.pc
 | 
			
		||||
    libosmo-mgcp.pc
 | 
			
		||||
    include/Makefile
 | 
			
		||||
    include/osmocom/Makefile
 | 
			
		||||
    include/osmocom/legacy_mgcp/Makefile
 | 
			
		||||
    include/osmocom/mgcp_client/Makefile
 | 
			
		||||
    include/osmocom/mgcp/Makefile
 | 
			
		||||
    src/Makefile
 | 
			
		||||
    src/libosmo-legacy-mgcp/Makefile
 | 
			
		||||
    src/libosmo-mgcp-client/Makefile
 | 
			
		||||
    src/libosmo-mgcp/Makefile
 | 
			
		||||
    src/osmo-bsc_mgcp/Makefile
 | 
			
		||||
    src/osmo-mgw/Makefile
 | 
			
		||||
    tests/Makefile
 | 
			
		||||
    tests/atlocal
 | 
			
		||||
    tests/legacy_mgcp/Makefile
 | 
			
		||||
    tests/mgcp_client/Makefile
 | 
			
		||||
    tests/mgcp/Makefile
 | 
			
		||||
    doc/Makefile
 | 
			
		||||
    doc/examples/Makefile
 | 
			
		||||
    doc/manuals/Makefile
 | 
			
		||||
    contrib/Makefile
 | 
			
		||||
    contrib/systemd/Makefile
 | 
			
		||||
    Makefile)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1 @@
 | 
			
		||||
SUBDIRS = systemd
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = ipa.py
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,10 @@
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License along
 | 
			
		||||
 * with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 */
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,5 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
# jenkins build helper script for openbsc.  This is how we build on jenkins.osmocom.org
 | 
			
		||||
#
 | 
			
		||||
# environment variables:
 | 
			
		||||
# * WITH_MANUALS: build manual PDFs if set to "1"
 | 
			
		||||
# * PUBLISH: upload manuals after building if set to "1" (ignored without WITH_MANUALS = "1")
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
 | 
			
		||||
	echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
 | 
			
		||||
@@ -22,22 +17,15 @@ export deps inst
 | 
			
		||||
osmo-clean-workspace.sh
 | 
			
		||||
 | 
			
		||||
mkdir "$deps" || true
 | 
			
		||||
osmo-build-dep.sh libosmocore "" --disable-doxygen
 | 
			
		||||
osmo-build-dep.sh libosmocore "" ac_cv_path_DOXYGEN=false
 | 
			
		||||
 | 
			
		||||
verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
 | 
			
		||||
 | 
			
		||||
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
 | 
			
		||||
export LD_LIBRARY_PATH="$inst/lib"
 | 
			
		||||
export PATH="$inst/bin:$PATH"
 | 
			
		||||
 | 
			
		||||
osmo-build-dep.sh libosmo-netif "" --disable-doxygen
 | 
			
		||||
osmo-build-dep.sh libosmo-abis
 | 
			
		||||
 | 
			
		||||
# Additional configure options and depends
 | 
			
		||||
CONFIG=""
 | 
			
		||||
if [ "$WITH_MANUALS" = "1" ]; then
 | 
			
		||||
	CONFIG="--enable-manuals"
 | 
			
		||||
fi
 | 
			
		||||
osmo-build-dep.sh libosmo-netif
 | 
			
		||||
 | 
			
		||||
set +x
 | 
			
		||||
echo
 | 
			
		||||
@@ -49,18 +37,13 @@ set -x
 | 
			
		||||
 | 
			
		||||
cd "$base"
 | 
			
		||||
autoreconf --install --force
 | 
			
		||||
./configure --enable-sanitize --enable-vty-tests --enable-external-tests --enable-werror $CONFIG
 | 
			
		||||
./configure $MGCP --enable-vty-tests --enable-external-tests
 | 
			
		||||
$MAKE $PARALLEL_MAKE
 | 
			
		||||
LD_LIBRARY_PATH="$inst/lib" $MAKE check \
 | 
			
		||||
  || cat-testlogs.sh
 | 
			
		||||
LD_LIBRARY_PATH="$inst/lib" \
 | 
			
		||||
  DISTCHECK_CONFIGURE_FLAGS="--enable-vty-tests --enable-external-tests $CONFIG" \
 | 
			
		||||
  $MAKE $PARALLEL_MAKE distcheck \
 | 
			
		||||
  DISTCHECK_CONFIGURE_FLAGS="$MGCP --enable-vty-tests --enable-external-tests" \
 | 
			
		||||
  $MAKE distcheck \
 | 
			
		||||
  || cat-testlogs.sh
 | 
			
		||||
 | 
			
		||||
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
 | 
			
		||||
	make -C "$base/doc/manuals" publish
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
$MAKE $PARALLEL_MAKE maintainer-clean
 | 
			
		||||
osmo-clean-workspace.sh
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +0,0 @@
 | 
			
		||||
EXTRA_DIST = osmo-mgw.service
 | 
			
		||||
 | 
			
		||||
if HAVE_SYSTEMD
 | 
			
		||||
systemdsystemunit_DATA = \
 | 
			
		||||
  osmo-mgw.service
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										11
									
								
								contrib/systemd/osmo-bsc-mgcp.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								contrib/systemd/osmo-bsc-mgcp.service
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=OpenBSC MGCP
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
Restart=always
 | 
			
		||||
ExecStart=/usr/bin/osmo-bsc_mgcp -s -c /etc/osmocom/osmo-bsc-mgcp.cfg
 | 
			
		||||
RestartSec=2
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
@@ -1,24 +1,11 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Osmocom Media Gateway (MGW)
 | 
			
		||||
After=network-online.target
 | 
			
		||||
Wants=network-online.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
LimitNOFILE=65536
 | 
			
		||||
StateDirectory=osmocom
 | 
			
		||||
WorkingDirectory=%S/osmocom
 | 
			
		||||
Restart=always
 | 
			
		||||
User=osmocom
 | 
			
		||||
Group=osmocom
 | 
			
		||||
ExecStart=/usr/bin/osmo-mgw -s -c /etc/osmocom/osmo-mgw.cfg
 | 
			
		||||
RestartSec=2
 | 
			
		||||
AmbientCapabilities=CAP_SYS_NICE
 | 
			
		||||
# CPU scheduling policy:
 | 
			
		||||
CPUSchedulingPolicy=rr
 | 
			
		||||
# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
			
		||||
CPUSchedulingPriority=1
 | 
			
		||||
# See sched(7) for further details on real-time policies and priorities
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1107
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1107
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2
									
								
								debian/compat
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/compat
									
									
									
									
										vendored
									
									
								
							@@ -1 +1 @@
 | 
			
		||||
10
 | 
			
		||||
9
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -1,26 +1,40 @@
 | 
			
		||||
Source: osmo-mgw
 | 
			
		||||
Section: net
 | 
			
		||||
Priority: extra
 | 
			
		||||
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
 | 
			
		||||
Build-Depends: debhelper (>= 10),
 | 
			
		||||
Maintainer: Alexander Couzens <lynxis@fe80.eu>
 | 
			
		||||
Build-Depends: debhelper (>=9),
 | 
			
		||||
               dh-autoreconf,
 | 
			
		||||
               pkg-config,
 | 
			
		||||
               autotools-dev,
 | 
			
		||||
               libosmocore-dev (>= 1.11.0),
 | 
			
		||||
               libosmo-netif-dev (>= 1.6.0),
 | 
			
		||||
               libosmo-abis-dev (>= 2.0.0),
 | 
			
		||||
               libosmocore-dev,
 | 
			
		||||
               libosmo-netif-dev
 | 
			
		||||
Standards-Version: 3.9.8
 | 
			
		||||
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw
 | 
			
		||||
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw
 | 
			
		||||
Vcs-Git: git://git.osmocom.org/osmo-mgw.git
 | 
			
		||||
Vcs-Browser: https://git.osmocom.org/osmo-mgw/
 | 
			
		||||
Homepage: https://osmocom.org/projects/osmo-mgw
 | 
			
		||||
 | 
			
		||||
Package: osmo-mgw
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: foreign
 | 
			
		||||
Depends: ${misc:Depends}, ${shlibs:Depends}
 | 
			
		||||
Depends: libosmo-mgcp1, ${misc:Depends}, ${shlibs:Depends}
 | 
			
		||||
Description: OsmoMGW: Osmocom's Media Gateway for 2G and 3G circuit-switched mobile networks
 | 
			
		||||
 | 
			
		||||
Package: libosmo-mgcp-client14
 | 
			
		||||
Package: libosmo-mgcp1
 | 
			
		||||
Section: libs
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: same
 | 
			
		||||
Pre-Depends: ${misc:Pre-Depends}
 | 
			
		||||
Depends: ${misc:Depends}, ${shlibs:Depends}
 | 
			
		||||
Description: libosmo-mgcp: Osmocom's Media Gateway server library
 | 
			
		||||
 | 
			
		||||
Package: libosmo-mgcp-dev
 | 
			
		||||
Section: libdevel
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: same
 | 
			
		||||
Depends: libosmo-mgcp1 (= ${binary:Version}), ${misc:Depends}
 | 
			
		||||
Description: libosmo-mgcp: Osmocom's Media Gateway server library
 | 
			
		||||
 | 
			
		||||
Package: libosmo-mgcp-client2
 | 
			
		||||
Section: libs
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: same
 | 
			
		||||
@@ -32,6 +46,26 @@ Package: libosmo-mgcp-client-dev
 | 
			
		||||
Section: libdevel
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: same
 | 
			
		||||
Depends: libosmo-mgcp-client14 (= ${binary:Version}), ${misc:Depends}
 | 
			
		||||
Depends: libosmo-mgcp-client2 (= ${binary:Version}), ${misc:Depends}
 | 
			
		||||
Description: libosmo-mgcp-client: Osmocom's Media Gateway Control Protocol client utilities
 | 
			
		||||
 | 
			
		||||
Package: osmo-bsc-mgcp
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: foreign
 | 
			
		||||
Depends: libosmo-legacy-mgcp0, ${misc:Depends}, ${shlibs:Depends}
 | 
			
		||||
Description: OsmoBSC-MGCP: Osmocom's Legacy Media Gateway; use osmo-mgw instead.
 | 
			
		||||
 | 
			
		||||
Package: libosmo-legacy-mgcp0
 | 
			
		||||
Section: libs
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: same
 | 
			
		||||
Pre-Depends: ${misc:Pre-Depends}
 | 
			
		||||
Depends: ${misc:Depends}, ${shlibs:Depends}
 | 
			
		||||
Description: libosmo-legacy-mgcp: Osmocom's Legacy Media Gateway server library; use libosmo-mgcp instead.
 | 
			
		||||
 | 
			
		||||
Package: libosmo-legacy-mgcp-dev
 | 
			
		||||
Section: libdevel
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: same
 | 
			
		||||
Depends: libosmo-legacy-mgcp0 (= ${binary:Version}), ${misc:Depends}
 | 
			
		||||
Description: libosmo-legacy-mgcp: Osmocom's Legacy Media Gateway server library; use libosmo-mgcp instead.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +1,12 @@
 | 
			
		||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 | 
			
		||||
Upstream-Name: osmo-mgw
 | 
			
		||||
Source: https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw
 | 
			
		||||
Source: git://git.osmocom.org/osmo-mgw
 | 
			
		||||
 | 
			
		||||
Files:     *
 | 
			
		||||
Copyright: 2009-2014 On-Waves
 | 
			
		||||
           2009-2015 Holger Hans Peter Freyther <zecke@selfish.org>
 | 
			
		||||
           2013 Jacob Erlbeck <jerlbeck@sysmocom.de>
 | 
			
		||||
           2016-2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
           2016-2017 sysmocom s.m.f.c. GmbH <info@sysmocom.de>
 | 
			
		||||
License:   AGPL-3.0+
 | 
			
		||||
 This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
@@ -21,12 +21,11 @@ License:   AGPL-3.0+
 | 
			
		||||
 You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
Files:     src/libosmo-mgcp-client/* include/osmocom/mgcp_client/*
 | 
			
		||||
Copyright: 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
           Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
 | 
			
		||||
           2009 by Harald Welte <laforge@gnumonks.org>
 | 
			
		||||
           2009-2011 by Holger Hans Peter Freyther
 | 
			
		||||
Files:     src/libosmo-legacy-mgcp/g711common.h
 | 
			
		||||
Copyright: 2000 Abramo Bagnara <abramo@alsa-project.org>
 | 
			
		||||
License:   GPL-2.0+
 | 
			
		||||
 Wrapper for linphone Codec class by Simon Morlat <simon.morlat@linphone.org>
 | 
			
		||||
 .
 | 
			
		||||
 This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 it under the terms of the GNU General Public License as published by
 | 
			
		||||
 the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
@@ -38,7 +37,13 @@ License:   GPL-2.0+
 | 
			
		||||
 GNU General Public License for more details.
 | 
			
		||||
 .
 | 
			
		||||
 You should have received a copy of the GNU General Public License
 | 
			
		||||
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 along with this program; if not, write to the Free Software
 | 
			
		||||
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 .
 | 
			
		||||
 The FSF address in the above text is the old one.
 | 
			
		||||
 .
 | 
			
		||||
 On Debian systems, the complete text of the GNU General Public License
 | 
			
		||||
 Version 2 can be found in `/usr/share/common-licenses/GPL-2'.
 | 
			
		||||
 | 
			
		||||
Files:     tests/vty_test_runner.py
 | 
			
		||||
Copyright: 2013 Holger Hans Peter Freyther
 | 
			
		||||
@@ -63,3 +68,15 @@ License:   GPL-3.0+
 | 
			
		||||
Files:     osmoappdesc.py
 | 
			
		||||
Copyright: 2013 Katerina Barone-Adesi <kat.obsc@gmail.com>
 | 
			
		||||
License:   GPL-3.0+
 | 
			
		||||
 | 
			
		||||
Files:     src/libosmo-legacy-mgcp/mgcp_osmux.c
 | 
			
		||||
Copyright: 2012-2013 On Waves ehf <http://www.on-waves.com>
 | 
			
		||||
           2012-2013 Pablo Neira Ayuso <pablo@gnumonks.org>
 | 
			
		||||
License:   AGPL-3.0+
 | 
			
		||||
 All rights not specifically granted under this license are reserved.
 | 
			
		||||
 .
 | 
			
		||||
 This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 under the terms of the GNU Affero General Public License as published by the
 | 
			
		||||
 Free Software Foundation; either version 3 of the License, or (at your
 | 
			
		||||
 option) any later version.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								debian/libosmo-legacy-mgcp-dev.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								debian/libosmo-legacy-mgcp-dev.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
usr/include/osmocom/legacy_mgcp
 | 
			
		||||
usr/lib/*/libosmo-legacy-mgcp.so
 | 
			
		||||
usr/lib/*/libosmo-legacy-mgcp.a
 | 
			
		||||
usr/lib/*/pkgconfig/libosmo-legacy-mgcp.pc
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/libosmo-legacy-mgcp0.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/libosmo-legacy-mgcp0.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
usr/lib/*/libosmo-legacy-mgcp.so.*
 | 
			
		||||
							
								
								
									
										4
									
								
								debian/libosmo-mgcp-dev.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								debian/libosmo-mgcp-dev.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
usr/include/osmocom/mgcp
 | 
			
		||||
usr/lib/*/libosmo-mgcp.so
 | 
			
		||||
usr/lib/*/libosmo-mgcp.a
 | 
			
		||||
usr/lib/*/pkgconfig/libosmo-mgcp.pc
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/libosmo-mgcp1.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/libosmo-mgcp1.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
usr/lib/*/libosmo-mgcp.so.*
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/osmo-bsc-mgcp.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-bsc-mgcp.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
usr/bin/osmo-bsc_mgcp
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/osmo-bsc-mgcp.service
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-bsc-mgcp.service
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
../contrib/systemd/osmo-bsc-mgcp.service
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/osmo-mgw-doc.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-mgw-doc.install
									
									
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
			
		||||
usr/share/doc/osmo-mgw-doc/*.pdf
 | 
			
		||||
							
								
								
									
										4
									
								
								debian/osmo-mgw.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/osmo-mgw.install
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1 @@
 | 
			
		||||
etc/osmocom/osmo-mgw.cfg
 | 
			
		||||
lib/systemd/system/osmo-mgw.service
 | 
			
		||||
usr/bin/osmo-mgw
 | 
			
		||||
usr/share/doc/osmo-mgw/examples/osmo-mgw/osmo-mgw.cfg
 | 
			
		||||
usr/share/doc/osmo-mgw/examples/osmo-mgw/osmo-mgw-abis_e1.cfg
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/osmo-mgw.service
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-mgw.service
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
../contrib/systemd/osmo-mgw.service
 | 
			
		||||
							
								
								
									
										38
									
								
								debian/postinst
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								debian/postinst
									
									
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
			
		||||
#!/bin/sh -e
 | 
			
		||||
case "$1" in
 | 
			
		||||
	configure)
 | 
			
		||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
			
		||||
		if ! getent group osmocom >/dev/null; then
 | 
			
		||||
			groupadd --system osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		if ! getent passwd osmocom >/dev/null; then
 | 
			
		||||
			useradd \
 | 
			
		||||
				--system \
 | 
			
		||||
				--gid osmocom \
 | 
			
		||||
				--home-dir /var/lib/osmocom \
 | 
			
		||||
				--shell /sbin/nologin \
 | 
			
		||||
				--comment "Open Source Mobile Communications" \
 | 
			
		||||
				osmocom
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
			
		||||
		if dpkg --compare-versions "$2" le "1.13.0"; then
 | 
			
		||||
			if [ -e /etc/osmocom/osmo-mgw.cfg ]; then
 | 
			
		||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-mgw.cfg
 | 
			
		||||
				chmod -v 0660 /etc/osmocom/osmo-mgw.cfg
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			if [ -d /etc/osmocom ]; then
 | 
			
		||||
				chown -v root:osmocom /etc/osmocom
 | 
			
		||||
				chmod -v 2775 /etc/osmocom
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			mkdir -p /var/lib/osmocom
 | 
			
		||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
			
		||||
# generated by other debhelper scripts.
 | 
			
		||||
#DEBHELPER#
 | 
			
		||||
							
								
								
									
										11
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							@@ -14,7 +14,7 @@ CFLAGS += -g
 | 
			
		||||
 | 
			
		||||
# main packaging script based on dh7 syntax
 | 
			
		||||
%:
 | 
			
		||||
	dh $@ --with autoreconf
 | 
			
		||||
	dh $@ --with autoreconf 
 | 
			
		||||
 | 
			
		||||
# debmake generated override targets
 | 
			
		||||
# Set options for ./configure
 | 
			
		||||
@@ -29,11 +29,8 @@ CFLAGS += -g
 | 
			
		||||
override_dh_auto_test:
 | 
			
		||||
	dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
 | 
			
		||||
 | 
			
		||||
override_dh_auto_configure:
 | 
			
		||||
	dh_auto_configure -- --with-systemdsystemunitdir=/lib/systemd/system
 | 
			
		||||
 | 
			
		||||
# Don't create .pdf.gz files (barely saves space and they can't be opened directly by most pdf readers)
 | 
			
		||||
override_dh_compress:
 | 
			
		||||
	dh_compress -X.pdf
 | 
			
		||||
override_dh_autoreconf:
 | 
			
		||||
	echo $(VERSION) > .tarball-version
 | 
			
		||||
	dh_autoreconf
 | 
			
		||||
 | 
			
		||||
# See https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html#bpp-dbg
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
SUBDIRS = \
 | 
			
		||||
	examples \
 | 
			
		||||
	manuals \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,3 @@
 | 
			
		||||
OSMOCONF_FILES = \
 | 
			
		||||
	osmo-mgw/osmo-mgw.cfg
 | 
			
		||||
 | 
			
		||||
osmoconfdir = $(sysconfdir)/osmocom
 | 
			
		||||
osmoconf_DATA = $(OSMOCONF_FILES)
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = $(OSMOCONF_FILES)
 | 
			
		||||
 | 
			
		||||
CFG_FILES = find $(srcdir) -name '*.cfg*' | sed -e 's,^$(srcdir),,'
 | 
			
		||||
 | 
			
		||||
dist-hook:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								doc/examples/osmo-bsc_mgcp/mgcp.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								doc/examples/osmo-bsc_mgcp/mgcp.cfg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
!
 | 
			
		||||
! MGCP configuration example
 | 
			
		||||
!
 | 
			
		||||
mgcp
 | 
			
		||||
 !local ip 10.23.24.2
 | 
			
		||||
 !bts ip 10.24.24.1
 | 
			
		||||
 !bind ip 10.23.24.1
 | 
			
		||||
 bind port 2427
 | 
			
		||||
 rtp base 4000
 | 
			
		||||
 rtp force-ptime 20
 | 
			
		||||
 sdp audio payload number 98
 | 
			
		||||
 sdp audio payload name AMR/8000
 | 
			
		||||
 number endpoints 31
 | 
			
		||||
 no rtcp-omit
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
!
 | 
			
		||||
! MGCP configuration example
 | 
			
		||||
!
 | 
			
		||||
log stderr
 | 
			
		||||
 logging color 1
 | 
			
		||||
 logging print category-hex 0
 | 
			
		||||
 logging print category 1
 | 
			
		||||
 logging timestamp 0
 | 
			
		||||
 logging print file basename last
 | 
			
		||||
 logging print level 1
 | 
			
		||||
 | 
			
		||||
e1_input
 | 
			
		||||
 e1_line 0 driver dahdi
 | 
			
		||||
 e1_line 0 port 0
 | 
			
		||||
mgcp
 | 
			
		||||
  bind ip 127.0.0.1
 | 
			
		||||
  rtp port-range 4002 16001
 | 
			
		||||
  rtp bind-ip 127.0.0.1
 | 
			
		||||
  rtp ip-probing
 | 
			
		||||
  rtp ip-dscp 46
 | 
			
		||||
  bind port 2427
 | 
			
		||||
  number endpoints 512
 | 
			
		||||
  force-realloc 1
 | 
			
		||||
  rtcp-omit
 | 
			
		||||
  rtp-patch ssrc
 | 
			
		||||
  rtp-patch timestamp
 | 
			
		||||
  trunk 1
 | 
			
		||||
   rtp keep-alive once
 | 
			
		||||
   no rtp keep-alive
 | 
			
		||||
   line 0
 | 
			
		||||
@@ -1,22 +1,17 @@
 | 
			
		||||
!
 | 
			
		||||
! MGCP configuration example
 | 
			
		||||
!
 | 
			
		||||
log stderr
 | 
			
		||||
 logging color 1
 | 
			
		||||
 logging print category-hex 0
 | 
			
		||||
 logging print category 1
 | 
			
		||||
 logging timestamp 0
 | 
			
		||||
 logging print file basename last
 | 
			
		||||
 logging print level 1
 | 
			
		||||
 | 
			
		||||
mgcp
 | 
			
		||||
  bind ip 127.0.0.1
 | 
			
		||||
  rtp port-range 4002 16001
 | 
			
		||||
  rtp bind-ip 127.0.0.1
 | 
			
		||||
  rtp port-range 4002 16000
 | 
			
		||||
  rtp bind-ip 10.9.1.122
 | 
			
		||||
  rtp ip-probing
 | 
			
		||||
  rtp ip-dscp 46
 | 
			
		||||
  rtp ip-tos 184
 | 
			
		||||
  bind port 2427
 | 
			
		||||
  number endpoints 512
 | 
			
		||||
  sdp audio payload number 98
 | 
			
		||||
  sdp audio payload name GSM
 | 
			
		||||
  number endpoints 31
 | 
			
		||||
  loop 0
 | 
			
		||||
  force-realloc 1
 | 
			
		||||
  rtcp-omit
 | 
			
		||||
  rtp-patch ssrc
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
EXTRA_DIST = osmomgw-usermanual.adoc \
 | 
			
		||||
    osmomgw-usermanual-docinfo.xml \
 | 
			
		||||
    osmomgw-vty-reference.xml \
 | 
			
		||||
    regen_doc.sh \
 | 
			
		||||
    chapters \
 | 
			
		||||
    vty
 | 
			
		||||
 | 
			
		||||
if BUILD_MANUALS
 | 
			
		||||
  ASCIIDOC = osmomgw-usermanual.adoc
 | 
			
		||||
  ASCIIDOC_DEPS = $(srcdir)/chapters/*.adoc
 | 
			
		||||
  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
 | 
			
		||||
 | 
			
		||||
  VTY_REFERENCE = osmomgw-vty-reference.xml
 | 
			
		||||
  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
 | 
			
		||||
 | 
			
		||||
  BUILT_REFERENCE_XML = $(builddir)/vty/mgw_vty_reference.xml
 | 
			
		||||
  $(builddir)/vty/mgw_vty_reference.xml: $(top_builddir)/src/osmo-mgw/osmo-mgw
 | 
			
		||||
	mkdir -p $(builddir)/vty
 | 
			
		||||
	$(top_builddir)/src/osmo-mgw/osmo-mgw --vty-ref-xml > $@
 | 
			
		||||
 | 
			
		||||
  OSMO_REPOSITORY = osmo-mgw
 | 
			
		||||
  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc
 | 
			
		||||
endif
 | 
			
		||||
@@ -1,129 +0,0 @@
 | 
			
		||||
== Configuring OsmoMGW
 | 
			
		||||
 | 
			
		||||
A basic configation of OsmoMGW mainly consists of specifying the IP address
 | 
			
		||||
and port on which to listen to MGCP commands, but changing the port range at
 | 
			
		||||
which the RTP streams terminate as well as limiting operation to a single call
 | 
			
		||||
agent can be done as well as changing the number of endpoints.
 | 
			
		||||
 | 
			
		||||
=== Configuring MGCP
 | 
			
		||||
 | 
			
		||||
By default OsmoMGW listens for MGCP on port 2427 on any IP address. If a call
 | 
			
		||||
agent address is configured then OsmoMGW will only answer MGCP commands from
 | 
			
		||||
that IP port 2727, otherwise all sources are handled. A domain can be
 | 
			
		||||
specified
 | 
			
		||||
 | 
			
		||||
.Example: MGCP configuration
 | 
			
		||||
----
 | 
			
		||||
OsmoMGW(config-mgcp)# bind ip 127.0.0.1
 | 
			
		||||
OsmoMGW(config-mgcp)# bind port 2427
 | 
			
		||||
OsmoMGW(config-mgcp)# call-agent ip 127.0.0.1
 | 
			
		||||
OsmoMGW(config-mgcp)# domain mgw-bsc
 | 
			
		||||
OsmoMGW(config-mgcp)# local ip 127.0.0.1
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
=== Configuring the trunk
 | 
			
		||||
 | 
			
		||||
The first trunk is considered a virtual trunk in OsmoMGW. All
 | 
			
		||||
endpoints of type "rtpbridge" are routed here. The virtual trunk is configured
 | 
			
		||||
in the config-mgcp context.
 | 
			
		||||
 | 
			
		||||
All other trunks are configured in the config-mgcp-trunk context, but the
 | 
			
		||||
commands used are identical. Right now trunks are considered only for "ds/e1"
 | 
			
		||||
type endpoints.
 | 
			
		||||
 | 
			
		||||
.Example: MGCP trunk configuration
 | 
			
		||||
----
 | 
			
		||||
OsmoMGW(config-mgcp)# number endpoints 63 <1>
 | 
			
		||||
OsmoMGW(config-mgcp)# rtp bind-ip 10.0.0.1 <2>
 | 
			
		||||
OsmoMGW(config-mgcp)# rtp port-range 12000-14000 <3>
 | 
			
		||||
----
 | 
			
		||||
<1> Maximum number of endpoints that can be allocated at once
 | 
			
		||||
<2> Use this IP when binding RTP endpoints
 | 
			
		||||
<3> Use ports in this range when binding RTP endpoints
 | 
			
		||||
 | 
			
		||||
There are some options to tweak how RTP forwarding behaves in OsmoMGW:
 | 
			
		||||
 | 
			
		||||
.Example: MGCP trunk rtp options
 | 
			
		||||
----
 | 
			
		||||
OsmoMGW(config-mgcp)# rtp keep-alive 30 <1>
 | 
			
		||||
OsmoMGW(config-mgcp)# rtp-patch ssrc <2>
 | 
			
		||||
OsmoMGW(config-mgcp)# rtp-patch timestamp <3>
 | 
			
		||||
----
 | 
			
		||||
<1> Send dummy UDP packets periodically to RTP destination
 | 
			
		||||
<2> Hide SSRC changes
 | 
			
		||||
<3> Ensure RTP timestamp is aligned with frame duration
 | 
			
		||||
 | 
			
		||||
NOTE: Changes to trunks that affect resource allocation, such as newly created
 | 
			
		||||
trunks or a change of the number of available endpoints, require a full restart
 | 
			
		||||
of osmo-mgw!
 | 
			
		||||
 | 
			
		||||
=== E1 trunk considerations
 | 
			
		||||
 | 
			
		||||
While the RTP bridge trunks are natively based on IP no special considerations
 | 
			
		||||
are required during setup. E1 trunks are mapped on a physical E1 line, which has
 | 
			
		||||
to be configured as shown below.
 | 
			
		||||
 | 
			
		||||
.Example: E1 line setup
 | 
			
		||||
----
 | 
			
		||||
OsmoMGW(config-e1_input)# e1_line 0 driver dahdi <1>
 | 
			
		||||
OsmoMGW(config-e1_input)# e1_line 0 port 2 <2>
 | 
			
		||||
----
 | 
			
		||||
<1> Name of the libosmo-abis driver implementation ("dahdi")
 | 
			
		||||
<2> Port number of the physical E1 port to use (2)
 | 
			
		||||
 | 
			
		||||
In osmo-mgw the e1_input node is used to configure the physical E1 line. The
 | 
			
		||||
line number will be used internally to identify the configured E1 line. The
 | 
			
		||||
port number is the physical E1 connector (sometimes called 'span') at the E1
 | 
			
		||||
hardware. Per trunk an individual E1 line will be needed. Beware that the E1
 | 
			
		||||
driver may also need configuration settings that are not discussed here.
 | 
			
		||||
 | 
			
		||||
.Example: E1 trunk setup
 | 
			
		||||
----
 | 
			
		||||
OsmoMGW(config-mgcp)# trunk 0 <1>
 | 
			
		||||
OsmoMGW(config-mgcp-trunk)# line 0 <2>
 | 
			
		||||
----
 | 
			
		||||
<1> Creation of a trunk (0)
 | 
			
		||||
<2> Reference to the E1 line to use (0)
 | 
			
		||||
 | 
			
		||||
The E1 trunk is created along with a number, typically starting at 0, but if
 | 
			
		||||
required any number from 0-64 is allowed. The E1 trunk configuration concerning
 | 
			
		||||
the IP related aspects is nearly identical to the configuration of the virtual
 | 
			
		||||
trunk. However, it is important that the user assigns one of the E1 line numbers
 | 
			
		||||
that were configured under the e1_input node.
 | 
			
		||||
 | 
			
		||||
NOTE: The endpoint name that is used on MGCP level will include the trunk number,
 | 
			
		||||
not the E1 line number. For simplicity (and compatibility with OsmoBSC) it is
 | 
			
		||||
recommended to use equal numbers for trunk and E1 line. However, if required any
 | 
			
		||||
E1 line can be mapped flexible on any trunk as long as the mapping is bijective.
 | 
			
		||||
 | 
			
		||||
.Example: A typical configuration with one E1 trunk
 | 
			
		||||
----
 | 
			
		||||
e1_input
 | 
			
		||||
 e1_line 0 driver dahdi
 | 
			
		||||
 e1_line 0 port 2
 | 
			
		||||
mgcp
 | 
			
		||||
 bind ip 127.0.0.1
 | 
			
		||||
 rtp net-range 6000 6011
 | 
			
		||||
 rtp net-bind-ip 192.168.100.130
 | 
			
		||||
 rtp ip-probing
 | 
			
		||||
 rtp ip-dscp 46
 | 
			
		||||
 no rtp keep-alive
 | 
			
		||||
 bind port 2428
 | 
			
		||||
 number endpoints 30
 | 
			
		||||
 loop 0
 | 
			
		||||
 force-realloc 1
 | 
			
		||||
 osmux off
 | 
			
		||||
 rtp-patch rfc5993hr
 | 
			
		||||
 trunk 0
 | 
			
		||||
  rtp keep-alive once
 | 
			
		||||
  no rtp keep-alive
 | 
			
		||||
  line 0
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
NOTE: One E1 trunk always covers a whole E1 line. All subslots (I.640) will be mapped
 | 
			
		||||
to individual MGCP endpoints. As long as the endpoints remain unused the
 | 
			
		||||
underlying E1 timeslot is not used.
 | 
			
		||||
 | 
			
		||||
NOTE: The E1 trunk implementation also works with T1 lines, however since T1 has
 | 
			
		||||
24 instead of 31 usable timeslots only the endpoints that fall into that 1-24 timeslot
 | 
			
		||||
range will be useable.
 | 
			
		||||
@@ -1,4 +0,0 @@
 | 
			
		||||
[[counters]]
 | 
			
		||||
== Counters
 | 
			
		||||
 | 
			
		||||
include::./counters_generated.adoc[]
 | 
			
		||||
@@ -1,83 +0,0 @@
 | 
			
		||||
 | 
			
		||||
// autogenerated by show asciidoc counters
 | 
			
		||||
These counters and their description based on OsmoMGW 1.5.0.64-189f (OsmoMGW).
 | 
			
		||||
 | 
			
		||||
=== Rate Counters
 | 
			
		||||
 | 
			
		||||
// generating tables for rate_ctr_group
 | 
			
		||||
// rate_ctr_group table aggregated statistics for all rtp connections
 | 
			
		||||
.all_rtp_conn - aggregated statistics for all rtp connections
 | 
			
		||||
[options="header"]
 | 
			
		||||
|===
 | 
			
		||||
| Name | Reference | Description
 | 
			
		||||
| all_rtp:err_tstmp_in | <<all_rtp_conn_all_rtp:err_tstmp_in>> | Total inbound rtp-stream timestamp errors.
 | 
			
		||||
| all_rtp:err_tstmp_out | <<all_rtp_conn_all_rtp:err_tstmp_out>> | Total outbound rtp-stream timestamp errors.
 | 
			
		||||
| all_rtp:packets_rx | <<all_rtp_conn_all_rtp:packets_rx>> | Total inbound rtp packets.
 | 
			
		||||
| all_rtp:octets_rx | <<all_rtp_conn_all_rtp:octets_rx>> | Total inbound rtp octets.
 | 
			
		||||
| all_rtp:packets_tx | <<all_rtp_conn_all_rtp:packets_tx>> | Total outbound rtp packets.
 | 
			
		||||
| all_rtp:octets_tx | <<all_rtp_conn_all_rtp:octets_tx>> | Total outbound rtp octets.
 | 
			
		||||
| all_rtp:dropped | <<all_rtp_conn_all_rtp:dropped>> | Total dropped rtp packets.
 | 
			
		||||
| all_rtp:num_closed_conns | <<all_rtp_conn_all_rtp:num_closed_conns>> | Total number of rtp connections closed.
 | 
			
		||||
|===
 | 
			
		||||
// rate_ctr_group table dlcx statistics
 | 
			
		||||
.dlcx - dlcx statistics
 | 
			
		||||
[options="header"]
 | 
			
		||||
|===
 | 
			
		||||
| Name | Reference | Description
 | 
			
		||||
| dlcx:success | <<dlcx_dlcx:success>> | DLCX command processed successfully.
 | 
			
		||||
| dlcx:wildcard | <<dlcx_dlcx:wildcard>> | wildcard names in DLCX commands are unsupported.
 | 
			
		||||
| dlcx:no_conn | <<dlcx_dlcx:no_conn>> | endpoint specified in DLCX command has no active connections.
 | 
			
		||||
| dlcx:callid | <<dlcx_dlcx:callid>> | CallId specified in DLCX command mismatches endpoint's CallId .
 | 
			
		||||
| dlcx:connid | <<dlcx_dlcx:connid>> | connection ID specified in DLCX command does not exist on endpoint.
 | 
			
		||||
| dlcx:unhandled_param | <<dlcx_dlcx:unhandled_param>> | unhandled parameter in DLCX command.
 | 
			
		||||
| dlcx:rejected | <<dlcx_dlcx:rejected>> | connection deletion rejected by policy.
 | 
			
		||||
| dlcx:deferred | <<dlcx_dlcx:deferred>> | connection deletion deferred by policy.
 | 
			
		||||
|===
 | 
			
		||||
// rate_ctr_group table mdcx statistics
 | 
			
		||||
.mdcx - mdcx statistics
 | 
			
		||||
[options="header"]
 | 
			
		||||
|===
 | 
			
		||||
| Name | Reference | Description
 | 
			
		||||
| mdcx:success | <<mdcx_mdcx:success>> | MDCX command processed successfully.
 | 
			
		||||
| mdcx:wildcard | <<mdcx_mdcx:wildcard>> | wildcard endpoint names in MDCX commands are unsupported.
 | 
			
		||||
| mdcx:no_conn | <<mdcx_mdcx:no_conn>> | endpoint specified in MDCX command has no active connections.
 | 
			
		||||
| mdcx:callid | <<mdcx_mdcx:callid>> | invalid CallId specified in MDCX command.
 | 
			
		||||
| mdcx:connid | <<mdcx_mdcx:connid>> | invalid connection ID specified in MDCX command.
 | 
			
		||||
| crcx:unhandled_param | <<mdcx_crcx:unhandled_param>> | unhandled parameter in MDCX command.
 | 
			
		||||
| mdcx:no_connid | <<mdcx_mdcx:no_connid>> | no connection ID specified in MDCX command.
 | 
			
		||||
| mdcx:conn_not_found | <<mdcx_mdcx:conn_not_found>> | connection specified in MDCX command does not exist.
 | 
			
		||||
| mdcx:invalid_mode | <<mdcx_mdcx:invalid_mode>> | invalid connection mode in MDCX command.
 | 
			
		||||
| mdcx:conn_opt | <<mdcx_mdcx:conn_opt>> | connection options invalid.
 | 
			
		||||
| mdcx:no_remote_conn_desc | <<mdcx_mdcx:no_remote_conn_desc>> | no opposite end specified for connection.
 | 
			
		||||
| mdcx:start_rtp_failure | <<mdcx_mdcx:start_rtp_failure>> | failure to start RTP processing.
 | 
			
		||||
| mdcx:conn_rejected | <<mdcx_mdcx:conn_rejected>> | connection rejected by policy.
 | 
			
		||||
| mdcx:conn_deferred | <<mdcx_mdcx:conn_deferred>> | connection deferred by policy.
 | 
			
		||||
|===
 | 
			
		||||
// rate_ctr_group table crxc statistics
 | 
			
		||||
.crcx - crxc statistics
 | 
			
		||||
[options="header"]
 | 
			
		||||
|===
 | 
			
		||||
| Name | Reference | Description
 | 
			
		||||
| crcx:success | <<crcx_crcx:success>> | CRCX command processed successfully.
 | 
			
		||||
| crcx:bad_action | <<crcx_crcx:bad_action>> | bad action in CRCX command.
 | 
			
		||||
| crcx:unhandled_param | <<crcx_crcx:unhandled_param>> | unhandled parameter in CRCX command.
 | 
			
		||||
| crcx:missing_callid | <<crcx_crcx:missing_callid>> | missing CallId in CRCX command.
 | 
			
		||||
| crcx:invalid_mode | <<crcx_crcx:invalid_mode>> | invalid connection mode in CRCX command.
 | 
			
		||||
| crcx:limit_exceeded | <<crcx_crcx:limit_exceeded>> | limit of concurrent connections was reached.
 | 
			
		||||
| crcx:unkown_callid | <<crcx_crcx:unkown_callid>> | unknown CallId in CRCX command.
 | 
			
		||||
| crcx:alloc_conn_fail | <<crcx_crcx:alloc_conn_fail>> | connection allocation failure.
 | 
			
		||||
| crcx:no_remote_conn_desc | <<crcx_crcx:no_remote_conn_desc>> | no opposite end specified for connection.
 | 
			
		||||
| crcx:start_rtp_failure | <<crcx_crcx:start_rtp_failure>> | failure to start RTP processing.
 | 
			
		||||
| crcx:conn_rejected | <<crcx_crcx:conn_rejected>> | connection rejected by policy.
 | 
			
		||||
| crcx:no_osmux | <<crcx_crcx:no_osmux>> | no osmux offered by peer.
 | 
			
		||||
| crcx:conn_opt | <<crcx_crcx:conn_opt>> | connection options invalid.
 | 
			
		||||
| crcx:codec_nego | <<crcx_crcx:codec_nego>> | codec negotiation failure.
 | 
			
		||||
| crcx:bind_port | <<crcx_crcx:bind_port>> | port bind failure.
 | 
			
		||||
|===
 | 
			
		||||
== Osmo Stat Items
 | 
			
		||||
 | 
			
		||||
// generating tables for osmo_stat_items
 | 
			
		||||
== Osmo Counters
 | 
			
		||||
 | 
			
		||||
// generating tables for osmo_counters
 | 
			
		||||
// there are no ungrouped osmo_counters
 | 
			
		||||
@@ -1,100 +0,0 @@
 | 
			
		||||
== MGCP Endpoints
 | 
			
		||||
 | 
			
		||||
MGCP organizes the switching resources in so called endpoints. Each endpoint is
 | 
			
		||||
referenced by its unique identifier. While RFC 3435 specifies a naming scheme, the
 | 
			
		||||
actual identifier naming is subject to the implementation and configuration.
 | 
			
		||||
 | 
			
		||||
=== RTP proxy / RTP bridge endpoints
 | 
			
		||||
 | 
			
		||||
OsmoMGW implements a freely configurable number of `rtpbridge` endpoints. Those
 | 
			
		||||
endpoints are able to host two connections at a time to model the functionality
 | 
			
		||||
of a tandem switch.
 | 
			
		||||
 | 
			
		||||
RTP bridge endpoint identifiers are referenced by the string `rtpbridge/`, a
 | 
			
		||||
hexadecimal number without leading zeros and a domain name (configurable).
 | 
			
		||||
 | 
			
		||||
----
 | 
			
		||||
rtpbridge/<number>@<domain>
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Example: List of virtual endpoints
 | 
			
		||||
----
 | 
			
		||||
rtpbridge/1@mgw
 | 
			
		||||
rtpbridge/2@mgw
 | 
			
		||||
rtpbridge/3@mgw
 | 
			
		||||
rtpbridge/4@mgw
 | 
			
		||||
rtpbridge/5@mgw
 | 
			
		||||
rtpbridge/6@mgw
 | 
			
		||||
rtpbridge/7@mgw
 | 
			
		||||
rtpbridge/8@mgw
 | 
			
		||||
rtpbridge/9@mgw
 | 
			
		||||
rtpbridge/a@mgw
 | 
			
		||||
rtpbridge/b@mgw
 | 
			
		||||
rtpbridge/c@mgw
 | 
			
		||||
rtpbridge/d@mgw
 | 
			
		||||
rtpbridge/e@mgw
 | 
			
		||||
rtpbridge/f@mgw
 | 
			
		||||
rtpbridge/10@mgw
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
=== E1/T1 endpoints
 | 
			
		||||
 | 
			
		||||
OsmoMGW supports E1 subslot multiplexing as specified by I.460. All possible
 | 
			
		||||
subslot combinations are mapped on individual endpoints. The endpoint names
 | 
			
		||||
are prefixed with `ds/e1-` followed by the trunk number and the E1 timeslot.
 | 
			
		||||
The subslot is defined by a bit rate and a bit offset.
 | 
			
		||||
 | 
			
		||||
----
 | 
			
		||||
ds/e1-<trunk>/s-<timeslot>/su<bitrate>-<bitoffset>@<domain>
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Example: List of endpoints on E1 trunk 0 at E1 timeslot 2
 | 
			
		||||
----
 | 
			
		||||
ds/e1-0/s-2/su64-0@mgw
 | 
			
		||||
ds/e1-0/s-2/su32-0@mgw
 | 
			
		||||
ds/e1-0/s-2/su32-4@mgw
 | 
			
		||||
ds/e1-0/s-2/su16-0@mgw
 | 
			
		||||
ds/e1-0/s-2/su16-2@mgw
 | 
			
		||||
ds/e1-0/s-2/su16-4@mgw
 | 
			
		||||
ds/e1-0/s-2/su16-6@mgw
 | 
			
		||||
ds/e1-0/s-2/su8-0@mgw
 | 
			
		||||
ds/e1-0/s-2/su8-1@mgw
 | 
			
		||||
ds/e1-0/s-2/su8-2@mgw
 | 
			
		||||
ds/e1-0/s-2/su8-3@mgw
 | 
			
		||||
ds/e1-0/s-2/su8-4@mgw
 | 
			
		||||
ds/e1-0/s-2/su8-5@mgw
 | 
			
		||||
ds/e1-0/s-2/su8-6@mgw
 | 
			
		||||
ds/e1-0/s-2/su8-7@mgw
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
When creating connections on endpoints that reside in one E1 timeslot the call
 | 
			
		||||
agent must make sure that no overlapping endpoints are used. It is for example
 | 
			
		||||
not possible to use `ds/e1-0/s-2/su16-2@mgw` and `ds/e1-0/s-2/su8-3@mgw` at the
 | 
			
		||||
same time because they overlap.
 | 
			
		||||
 | 
			
		||||
.Subslot overlapping
 | 
			
		||||
[options="header"]
 | 
			
		||||
|===
 | 
			
		||||
| Bit offset  4+| Subslots
 | 
			
		||||
| 0 | 8k .2+| 16k .4+| 32k .8+| 64k
 | 
			
		||||
| 1 | 8k
 | 
			
		||||
| 2 | 8k .2+| 16k
 | 
			
		||||
| 3 | 8k
 | 
			
		||||
| 4 | 8k .2+| 16k .4+| 32k
 | 
			
		||||
| 5 | 8k
 | 
			
		||||
| 6 | 8k .2+| 16k
 | 
			
		||||
| 7 | 8k
 | 
			
		||||
|===
 | 
			
		||||
 | 
			
		||||
NOTE: The current implementation (December 2020) only implements TRAU frame
 | 
			
		||||
encoding/decoding for 16K and 8K subslots. Endpoints with other bitrates are
 | 
			
		||||
not yet useable.
 | 
			
		||||
 | 
			
		||||
NOTE: the VTY command "show mgcp" can be used to get a list of all available
 | 
			
		||||
endpoints (including identifiers)
 | 
			
		||||
 | 
			
		||||
=== The `null` endpoint
 | 
			
		||||
 | 
			
		||||
OsmoMGW offers a special `null@<domain>` endpoint which can be audited at all times.
 | 
			
		||||
This is useful for MGCP clients who wish to submit requests to OsmoMGW
 | 
			
		||||
periodically to find out whether it is still reachable and in a working state.
 | 
			
		||||
@@ -1,72 +0,0 @@
 | 
			
		||||
== MGCP Extensions
 | 
			
		||||
 | 
			
		||||
The MGCP protocol is extendable. The following non-standard extensions are
 | 
			
		||||
understood by OsmoMGW.
 | 
			
		||||
 | 
			
		||||
=== `X-Osmo-IGN`
 | 
			
		||||
 | 
			
		||||
`X-Osmo-IGN` indicates to OsmoMGW that specific items of an endpoint should be
 | 
			
		||||
ignored, so that it is lenient on mismatching values that would normally
 | 
			
		||||
indicate collisions or configuration errors.
 | 
			
		||||
 | 
			
		||||
==== `X-Osmo-IGN` Format
 | 
			
		||||
 | 
			
		||||
The value part of `X-Osmo-IGN` must be one or more items separated by one or more
 | 
			
		||||
spaces. Each item consists of one or more non-whitespace characters.
 | 
			
		||||
 | 
			
		||||
.Example: `X-Osmo-IGN` format with three ficticious items "X", "abc" and "123".
 | 
			
		||||
----
 | 
			
		||||
X-Osmo-IGN: X abc 123
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
`X-Osmo-IGN` must be issued in the MGCP header section (typically as its last item),
 | 
			
		||||
before the SDP section starts.
 | 
			
		||||
 | 
			
		||||
==== Supported `X-Osmo-IGN` Items
 | 
			
		||||
 | 
			
		||||
Currently, the following `X-Osmo-IGN` items are supported:
 | 
			
		||||
 | 
			
		||||
* `C`: ignore CallID mismatches, i.e. differing "C" values between connections
 | 
			
		||||
  on the same endpoint.
 | 
			
		||||
 | 
			
		||||
.Note:
 | 
			
		||||
`X-Osmo-IGN` does not support ignoring mismatches on the domain part of
 | 
			
		||||
an endpoint name, e.g. ignoring a mismatch on "example.com" in
 | 
			
		||||
`rtpbridge/123abc@example.com`. Instead, you may globally configure OsmoMGW
 | 
			
		||||
with `mgcp` / `domain *` to permit all domain parts.
 | 
			
		||||
 | 
			
		||||
===== `X-Osmo-IGN: C`
 | 
			
		||||
 | 
			
		||||
By default, OsmoMGW verifies that all CallIDs ("C" values) match for all
 | 
			
		||||
connections on any one given endpoint. To ignore CallID mismatches, pass a `C`
 | 
			
		||||
in the `X-Osmo-IGN` header, for the first or the second `CRCX` on an endpoint.
 | 
			
		||||
When the `X-Osmo-IGN: C` is sent for any one `CRCX` on an endpoint, CallID
 | 
			
		||||
mismatches will be ignored for that and all subsequent messages for that
 | 
			
		||||
endpoint. Hence this header only needs to be included once per endpoint, in any
 | 
			
		||||
`CRCX` message that precedes or coincides with a CallID mismatch.
 | 
			
		||||
 | 
			
		||||
This is particularly useful for a BSC that is connected to an A/SCCPlite MSC,
 | 
			
		||||
where the BSC and MSC each are expected to configure their respective own
 | 
			
		||||
connection on a shared endpoint. For A/SCCPlite, it is impossible for the BSC
 | 
			
		||||
to know the CallID that the MSC will use, so CallID mismatches are inevitable.
 | 
			
		||||
See also OsmoBSC, which will by default pass the `X-Osmo-IGN: C` header for
 | 
			
		||||
endpoints associated with an A/SCCPlite MSC.
 | 
			
		||||
 | 
			
		||||
.Example: `CRCX` message that instructs OsmoMGW to ignore CallID mismatches
 | 
			
		||||
----
 | 
			
		||||
CRCX 2 rtpbridge/123abc@mgw MGCP 1.0
 | 
			
		||||
M: recvonly
 | 
			
		||||
C: 2
 | 
			
		||||
L: p:20
 | 
			
		||||
X-Osmo-IGN: C
 | 
			
		||||
 | 
			
		||||
v=0
 | 
			
		||||
c=IN IP4 123.12.12.123
 | 
			
		||||
m=audio 5904 RTP/AVP 97
 | 
			
		||||
a=rtpmap:97 GSM-EFR/8000
 | 
			
		||||
a=ptime:40
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
=== `X-Osmux`
 | 
			
		||||
 | 
			
		||||
See <<mgcp-extension-osmux>>
 | 
			
		||||
@@ -1,115 +0,0 @@
 | 
			
		||||
[[overview]]
 | 
			
		||||
== Overview
 | 
			
		||||
 | 
			
		||||
This manual should help you getting started with OsmoMGW. It will cover
 | 
			
		||||
aspects of configuring and running the media gateway.
 | 
			
		||||
 | 
			
		||||
[[intro_overview]]
 | 
			
		||||
=== About OsmoMGW
 | 
			
		||||
 | 
			
		||||
OsmoMGW is the Osmocom implementation of a media gateway to handle user
 | 
			
		||||
plane (voice) traffic in cellular networks. It can connect and optionally
 | 
			
		||||
transcode RTP voice streams between different network elements such as BTSs
 | 
			
		||||
and external entities like SIP. It is typically co-located with both OsmoBSC
 | 
			
		||||
and OsmoMSC and controlled by them via MGCP, the Media Gateway Control
 | 
			
		||||
Protocol.
 | 
			
		||||
 | 
			
		||||
[[fig-bsc]]
 | 
			
		||||
.OsmoMGW used with OsmoBSC
 | 
			
		||||
[graphviz]
 | 
			
		||||
----
 | 
			
		||||
digraph G {
 | 
			
		||||
    rankdir = LR;
 | 
			
		||||
    OsmoBTS -> OsmoBSC [label="Abis/IP"];
 | 
			
		||||
    OsmoBSC -> "core-network" [label="3GPP AoIP"];
 | 
			
		||||
    OsmoBSC -> OsmoMGW [label="MGCP"];
 | 
			
		||||
    OsmoBTS -> OsmoMGW [label="RTP",dir=both];
 | 
			
		||||
    OsmoMGW -> "core-network" [label="RTP",dir=both];
 | 
			
		||||
    {rank=same OsmoBSC OsmoMGW}
 | 
			
		||||
    OsmoMGW [color=red];
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
[[fig-msc]]
 | 
			
		||||
.OsmoMGW used with OsmoMSC
 | 
			
		||||
[graphviz]
 | 
			
		||||
----
 | 
			
		||||
digraph G {
 | 
			
		||||
    rankdir = LR;
 | 
			
		||||
    "2G BSS" -> OsmoMSC [label="3GPP AoIP"];
 | 
			
		||||
    OsmoMSC -> OsmoMGW [label="MGCP"];
 | 
			
		||||
    "2G BSS" -> OsmoMGW [label="RTP",dir=both];
 | 
			
		||||
    OsmoMSC -> OsmoSIP [label="MNCC"];
 | 
			
		||||
    OsmoSIP -> PBX [label="SIP Trunk"];
 | 
			
		||||
    OsmoMGW -> PBX [label="RTP",dir=both];
 | 
			
		||||
    {rank=same OsmoMSC OsmoMGW}
 | 
			
		||||
    OsmoSIP [label="osmo-sip-connector"];
 | 
			
		||||
    OsmoMGW [color=red];
 | 
			
		||||
 | 
			
		||||
    hNodeB -> OsmoHNBGW [label="Iuh"];
 | 
			
		||||
    OsmoHNBGW -> OsmoMSC [label="IuCS"];
 | 
			
		||||
    hNodeB -> OsmoMGW [label="RTP",dir=both];
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
[[fig-bsc-e1]]
 | 
			
		||||
.Integration of legacy E1 BTS in AoIP network
 | 
			
		||||
[graphviz]
 | 
			
		||||
----
 | 
			
		||||
digraph G {
 | 
			
		||||
    rankdir = LR;
 | 
			
		||||
    BTS -> OsmoBSC [label="Abis/E1"];
 | 
			
		||||
    OsmoBSC -> "core-network" [label="3GPP AoIP"];
 | 
			
		||||
    OsmoBSC -> OsmoMGW [label="MGCP"];
 | 
			
		||||
    BTS -> OsmoMGW [label="TRAU/E1",dir=both];
 | 
			
		||||
    OsmoMGW -> "core-network" [label="RTP",dir=both];
 | 
			
		||||
    {rank=same OsmoBSC OsmoMGW}
 | 
			
		||||
    OsmoMGW [color=red];
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
=== Software Components
 | 
			
		||||
 | 
			
		||||
OsmoMGW contains a variety of different software components, which we’ll
 | 
			
		||||
quickly describe in this section.
 | 
			
		||||
 | 
			
		||||
==== MGCP Implementation
 | 
			
		||||
 | 
			
		||||
OsmoMGW brings its own MGCP implementation through which OsmoMGW is
 | 
			
		||||
controlled.
 | 
			
		||||
 | 
			
		||||
The commands implemented are CRCX, MDCX, DLCX and RSIP. The command AUEP is
 | 
			
		||||
implemented as a stub and will simply respond with OK.
 | 
			
		||||
 | 
			
		||||
==== RTP implementation
 | 
			
		||||
 | 
			
		||||
Support for IuUP which is used in 3G cells is quite lacking at the moment.
 | 
			
		||||
3G<->3G and 2G<->2G calls should work, but 3G<->2G does not.
 | 
			
		||||
 | 
			
		||||
==== Audio transcoder
 | 
			
		||||
 | 
			
		||||
Transcoding is currently not supported in OsmoMGW.
 | 
			
		||||
 | 
			
		||||
=== Limitations
 | 
			
		||||
 | 
			
		||||
At the moment (November 2020), OsmoMGW implements RTP proxy / RTP bridge
 | 
			
		||||
type endpoints and E1/T1 16k/8k sub-slots with TRAU frames for classic BTS
 | 
			
		||||
support. To the RTP proxy / RTP bridge endpoints two RTP connections can
 | 
			
		||||
be established, which then work as a tandem. E1/T1 endpoints support one
 | 
			
		||||
RTP connection at a time that is associated with a sub-slot on an E1 line.
 | 
			
		||||
We are planning to add further endpoint types for:
 | 
			
		||||
 | 
			
		||||
- classic E1/T1 timeslots (64kBps alaw/ulaw)
 | 
			
		||||
- announcement/playout end-points
 | 
			
		||||
- conference endpoints
 | 
			
		||||
 | 
			
		||||
=== Additional resources
 | 
			
		||||
 | 
			
		||||
You can find the OsmoMGW issue tracker and wiki online at
 | 
			
		||||
 | 
			
		||||
- https://osmocom.org/projects/osmo-mgw
 | 
			
		||||
- https://osmocom.org/projects/osmo-mgw/wiki
 | 
			
		||||
 | 
			
		||||
RFC 3435 for MGCP is located at
 | 
			
		||||
 | 
			
		||||
- https://tools.ietf.org/html/rfc3435
 | 
			
		||||
@@ -1,42 +0,0 @@
 | 
			
		||||
==== Full example of QoS for osmo-mgw
 | 
			
		||||
 | 
			
		||||
In the below example we will show the full set of configuration required
 | 
			
		||||
for both DSCP and PCP differentiation of RTP traffic by osmo-mgw.
 | 
			
		||||
 | 
			
		||||
What we want to achieve in this example is the following configuration:
 | 
			
		||||
 | 
			
		||||
.DSCP and PCP assignments for osmo-mgw Abis downlink traffic in this example
 | 
			
		||||
[options="header",width="30%",cols="2,1,1"]
 | 
			
		||||
|===
 | 
			
		||||
|Traffic      |DSCP|PCP
 | 
			
		||||
|RTP    |  46|  6
 | 
			
		||||
|===
 | 
			
		||||
 | 
			
		||||
. configure the osmo-mgw program to set the DSCP value
 | 
			
		||||
. configure an egrees QoS map to map from priority to PCP
 | 
			
		||||
 | 
			
		||||
.Example Step 1: add related VTY configuration to `osmo-mgw.cfg`
 | 
			
		||||
----
 | 
			
		||||
...
 | 
			
		||||
mgcp
 | 
			
		||||
 rtp ip-dscp 46
 | 
			
		||||
 rtp socket-priority 6
 | 
			
		||||
...
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Example Step 2: egress QoS map to map from socket priority to PCP values
 | 
			
		||||
----
 | 
			
		||||
$ sudo ip link set dev eth0.9<1> type vlan egress-qos-map 0:0 5:5 6:6 7:7 <2>
 | 
			
		||||
----
 | 
			
		||||
<1> make sure to specify your specific VLAN interface name here instead of `eth0.9`.
 | 
			
		||||
<2> create a egress QoS map that maps the priority value 1:1 to the PCP. We also include the
 | 
			
		||||
    mapping 5:5 and 7:7 from the osmo-bsc example (see <<userman-osmobsc>>) here.
 | 
			
		||||
 | 
			
		||||
NOTE:: The settings of the `ip` command are volatile and only active until
 | 
			
		||||
the next reboot (or the network device or VLAN is removed).  Please refer to
 | 
			
		||||
the documentation of your specific Linux distribution in order to find out how
 | 
			
		||||
to make such settings persistent by means of an `ifup` hook whenever the interface
 | 
			
		||||
comes up.  For CentOS/RHEL 8 this can e.g. be achieved by means of an `/sbin/ifup-local
 | 
			
		||||
script` (when using `network-scripts` and not NetworkManager).  For Debian or Ubuntu,
 | 
			
		||||
this typically involves adding `up` lines to `/etc/network/interfaces` or a `/etc/network/if-up.d`
 | 
			
		||||
script.
 | 
			
		||||
@@ -1,42 +0,0 @@
 | 
			
		||||
== Running OsmoMGW
 | 
			
		||||
 | 
			
		||||
The OsmoMGW executable (`osmo-mgw`) offers the following command-line
 | 
			
		||||
arguments:
 | 
			
		||||
 | 
			
		||||
=== SYNOPSIS
 | 
			
		||||
 | 
			
		||||
*osmo-mgw* [-h|-V] [-D] [-c 'CONFIGFILE'] [-s]
 | 
			
		||||
 | 
			
		||||
=== OPTIONS
 | 
			
		||||
 | 
			
		||||
*-h, --help*::
 | 
			
		||||
	Print a short help message about the supported options
 | 
			
		||||
*-V, --version*::
 | 
			
		||||
	Print the compile-time version number of the program
 | 
			
		||||
*-D, --daemonize*::
 | 
			
		||||
	Fork the process as a daemon into background.
 | 
			
		||||
*-c, --config-file 'CONFIGFILE'*::
 | 
			
		||||
	Specify the file and path name of the configuration file to be
 | 
			
		||||
	used. If none is specified, use `osmo-mgw.cfg` in the current
 | 
			
		||||
	working directory.
 | 
			
		||||
*-s, --disable-color*::
 | 
			
		||||
	Disable colors for logging to stderr. This has mostly been
 | 
			
		||||
	deprecated by VTY based logging configuration, see <<logging>>
 | 
			
		||||
	for more information.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== Configure limits
 | 
			
		||||
 | 
			
		||||
When servicing hundreds of media endpoints, it may be necessary to adjust the
 | 
			
		||||
operating system's limit on open file descriptors for the osmo-mgw process. A
 | 
			
		||||
typical default limit imposed by operating systems is 1024; this would be
 | 
			
		||||
exceeded by, for example, about 256 active voice calls with 4 RTP/RTPC ports
 | 
			
		||||
each, sockets for other interfaces not considered yet.
 | 
			
		||||
 | 
			
		||||
It should be ok to set an OS limit on open file descriptors as high as 65536
 | 
			
		||||
for osmo-mgw, which practically rules out failure from running out of file
 | 
			
		||||
descriptors anywhere (<16,000 active calls).
 | 
			
		||||
 | 
			
		||||
When using systemd, the file descriptor limit may be adjusted in the service
 | 
			
		||||
file by the `LimitNOFILE` setting ("Number of Open FILE descriptors"). OsmoMGW
 | 
			
		||||
ships a systemd service file with a high LimitNOFILE setting.
 | 
			
		||||
@@ -1,47 +0,0 @@
 | 
			
		||||
<revhistory>
 | 
			
		||||
  <revision>
 | 
			
		||||
    <revnumber>1</revnumber>
 | 
			
		||||
    <date>July 24th, 2018</date>
 | 
			
		||||
    <authorinitials>DW</authorinitials>
 | 
			
		||||
    <revremark>
 | 
			
		||||
      Initial version
 | 
			
		||||
    </revremark>
 | 
			
		||||
  </revision>
 | 
			
		||||
</revhistory>
 | 
			
		||||
 | 
			
		||||
<authorgroup>
 | 
			
		||||
  <author>
 | 
			
		||||
    <firstname>Daniel</firstname>
 | 
			
		||||
    <surname>Willmann</surname>
 | 
			
		||||
    <email>dwillmann@sysmocom.de</email>
 | 
			
		||||
    <authorinitials>DW</authorinitials>
 | 
			
		||||
    <affiliation>
 | 
			
		||||
      <shortaffil>sysmocom</shortaffil>
 | 
			
		||||
      <orgname>sysmocom - s.f.m.c. GmbH</orgname>
 | 
			
		||||
    </affiliation>
 | 
			
		||||
  </author>
 | 
			
		||||
</authorgroup>
 | 
			
		||||
 | 
			
		||||
<copyright>
 | 
			
		||||
  <year>2018</year>
 | 
			
		||||
  <holder>sysmocom - s.f.m.c. GmbH</holder>
 | 
			
		||||
</copyright>
 | 
			
		||||
 | 
			
		||||
<legalnotice>
 | 
			
		||||
  <para>
 | 
			
		||||
	Permission is granted to copy, distribute and/or modify this
 | 
			
		||||
	document under the terms of the GNU Free Documentation License,
 | 
			
		||||
	Version 1.3 or any later version published by the Free Software
 | 
			
		||||
	Foundation; with the Invariant Sections being just 'Foreword',
 | 
			
		||||
	'Acknowledgements' and 'Preface', with no Front-Cover Texts,
 | 
			
		||||
	and no Back-Cover Texts.  A copy of the license is included in
 | 
			
		||||
	the section entitled "GNU Free Documentation License".
 | 
			
		||||
  </para>
 | 
			
		||||
  <para>
 | 
			
		||||
	The Asciidoc source code of this manual can be found at
 | 
			
		||||
	<ulink url="http://git.osmocom.org/osmo-gsm-manuals/">
 | 
			
		||||
		http://git.osmocom.org/osmo-gsm-manuals/
 | 
			
		||||
	</ulink>
 | 
			
		||||
  </para>
 | 
			
		||||
</legalnotice>
 | 
			
		||||
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
:gfdl-enabled:
 | 
			
		||||
:program-name: OsmoMGW
 | 
			
		||||
 | 
			
		||||
OsmoMGW User Manual
 | 
			
		||||
====================
 | 
			
		||||
Daniel Willmann <dwillmann@sysmocom.de>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/preface.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/overview.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/running.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/vty.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/logging.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/configuration.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/mgcp_endpoints.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/mgcp_extensions.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/osmux/osmux.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/qos-dscp-pcp.adoc[]
 | 
			
		||||
 | 
			
		||||
//include::{srcdir}/chapters/counters.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/vty_cpu_sched.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/port_numbers.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/bibliography.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/glossary.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/gfdl.adoc[]
 | 
			
		||||
@@ -1,38 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
  ex:ts=2:sw=42sts=2:et
 | 
			
		||||
  -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
-->
 | 
			
		||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML 5.0//EN"
 | 
			
		||||
"http://docbook.org/xml/5.0/dtd/docbook.dtd" [
 | 
			
		||||
<!ENTITY chapter-vty      SYSTEM      "./common/chapters/vty.xml" >
 | 
			
		||||
<!ENTITY sections-vty     SYSTEM      "generated/docbook_vty.xml"  >
 | 
			
		||||
]>
 | 
			
		||||
 | 
			
		||||
<book>
 | 
			
		||||
  <info>
 | 
			
		||||
    <revhistory>
 | 
			
		||||
        <revision>
 | 
			
		||||
            <revnumber>v1</revnumber>
 | 
			
		||||
            <date>12th December 2017</date>
 | 
			
		||||
            <authorinitials>pm</authorinitials>
 | 
			
		||||
            <revremark>Initial</revremark>
 | 
			
		||||
        </revision>
 | 
			
		||||
    </revhistory>
 | 
			
		||||
 | 
			
		||||
    <title>OsmoMGW VTY Reference</title>
 | 
			
		||||
 | 
			
		||||
    <copyright>
 | 
			
		||||
      <year>2017</year>
 | 
			
		||||
    </copyright>
 | 
			
		||||
 | 
			
		||||
    <legalnotice>
 | 
			
		||||
      <para>This work is copyright by <orgname>sysmocom - s.f.m.c. GmbH</orgname>. All rights reserved.
 | 
			
		||||
      </para>
 | 
			
		||||
    </legalnotice>
 | 
			
		||||
  </info>
 | 
			
		||||
 | 
			
		||||
  <!-- Main chapters-->
 | 
			
		||||
  &chapter-vty;
 | 
			
		||||
</book>
 | 
			
		||||
 | 
			
		||||
@@ -1,17 +0,0 @@
 | 
			
		||||
#!/bin/sh -x
 | 
			
		||||
 | 
			
		||||
if [ -z "$DOCKER_PLAYGROUND" ]; then
 | 
			
		||||
	echo "You need to set DOCKER_PLAYGROUND"
 | 
			
		||||
	exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
SCRIPT=$(realpath "$0")
 | 
			
		||||
MANUAL_DIR=$(dirname "$SCRIPT")
 | 
			
		||||
 | 
			
		||||
COMMIT=${COMMIT:-$(git log -1 --format=format:%H)}
 | 
			
		||||
 | 
			
		||||
cd "$DOCKER_PLAYGROUND/scripts" || exit 1
 | 
			
		||||
 | 
			
		||||
OSMO_MGW_BRANCH=$COMMIT ./regen_doc.sh osmo-mgw 4243 \
 | 
			
		||||
	"$MANUAL_DIR/chapters/counters_generated.adoc" \
 | 
			
		||||
	"$MANUAL_DIR/vty/mgw_vty_reference.xml"
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
<vtydoc xmlns='urn:osmocom:xml:libosmocore:vty:doc:1.0'>
 | 
			
		||||
</vtydoc>
 | 
			
		||||
@@ -92,8 +92,8 @@ fi
 | 
			
		||||
if test -n "$v"
 | 
			
		||||
then
 | 
			
		||||
    : # use $v
 | 
			
		||||
elif
 | 
			
		||||
       v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
 | 
			
		||||
elif test -d ./.git \
 | 
			
		||||
    && v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
 | 
			
		||||
	  || git describe --abbrev=4 HEAD 2>/dev/null` \
 | 
			
		||||
    && case $v in
 | 
			
		||||
	 [0-9]*) ;;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,21 +3,13 @@ SUBDIRS = \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
nobase_include_HEADERS = \
 | 
			
		||||
	osmocom/mgcp_client/defs.h \
 | 
			
		||||
	osmocom/legacy_mgcp/mgcp.h \
 | 
			
		||||
	osmocom/legacy_mgcp/mgcp_internal.h \
 | 
			
		||||
	osmocom/legacy_mgcp/osmux.h \
 | 
			
		||||
	osmocom/mgcp_client/mgcp_client.h \
 | 
			
		||||
	osmocom/mgcp_client/mgcp_client_endpoint_fsm.h \
 | 
			
		||||
	osmocom/mgcp_client/mgcp_client_fsm.h \
 | 
			
		||||
	osmocom/mgcp_client/mgcp_client_pool.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
noinst_HEADERS = \
 | 
			
		||||
	osmocom/mgcp_client/mgcp_common.h \
 | 
			
		||||
	osmocom/mgcp/mgcp.h \
 | 
			
		||||
	osmocom/mgcp/mgcp_common.h \
 | 
			
		||||
	osmocom/mgcp/mgcp_internal.h \
 | 
			
		||||
	osmocom/mgcp/osmux.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
# This gets copied during make from osmocom/mgcp/mgcp_common.h. Therefore it is not included in the source tree and we
 | 
			
		||||
# don't need to distribute it (OS#4084).
 | 
			
		||||
nobase_nodist_include_HEADERS = \
 | 
			
		||||
	osmocom/mgcp_client/mgcp_common.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
SUBDIRS = \
 | 
			
		||||
	legacy_mgcp \
 | 
			
		||||
	mgcp_client \
 | 
			
		||||
	mgcp \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								include/osmocom/legacy_mgcp/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								include/osmocom/legacy_mgcp/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
noinst_HEADERS = \
 | 
			
		||||
	mgcp_transcode.h \
 | 
			
		||||
	vty.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
							
								
								
									
										292
									
								
								include/osmocom/legacy_mgcp/mgcp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								include/osmocom/legacy_mgcp/mgcp.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,292 @@
 | 
			
		||||
/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
 | 
			
		||||
 * (C) 2009-2012 by On-Waves
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef OPENBSC_MGCP_H
 | 
			
		||||
#define OPENBSC_MGCP_H
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/msgb.h>
 | 
			
		||||
#include <osmocom/core/write_queue.h>
 | 
			
		||||
#include <osmocom/core/timer.h>
 | 
			
		||||
#include <osmocom/core/logging.h>
 | 
			
		||||
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
 | 
			
		||||
#define RTP_PORT_DEFAULT 4000
 | 
			
		||||
#define RTP_PORT_NET_DEFAULT 16000
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculate the RTP audio port for the given multiplex
 | 
			
		||||
 * and the direction. This allows a semi static endpoint
 | 
			
		||||
 * to port calculation removing the need for the BSC
 | 
			
		||||
 * and the MediaGateway to communicate.
 | 
			
		||||
 *
 | 
			
		||||
 * Port usage explained:
 | 
			
		||||
 *       base + (multiplex * 2) + 0 == local port to wait for network packets
 | 
			
		||||
 *       base + (multiplex * 2) + 1 == local port for rtcp
 | 
			
		||||
 *
 | 
			
		||||
 * The above port will receive packets from the BTS that need
 | 
			
		||||
 * to be patched and forwarded to the network.
 | 
			
		||||
 * The above port will receive packets from the network that
 | 
			
		||||
 * need to be patched and forwarded to the BTS.
 | 
			
		||||
 *
 | 
			
		||||
 * We assume to have a static BTS IP address so we can differentiate
 | 
			
		||||
 * network and BTS.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
static inline int rtp_calculate_port(int multiplex, int base)
 | 
			
		||||
{
 | 
			
		||||
	return base + (multiplex * 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Handling of MGCP Endpoints and the MGCP Config
 | 
			
		||||
 */
 | 
			
		||||
struct mgcp_endpoint;
 | 
			
		||||
struct mgcp_config;
 | 
			
		||||
struct mgcp_trunk_config;
 | 
			
		||||
struct mgcp_rtp_end;
 | 
			
		||||
 | 
			
		||||
#define MGCP_ENDP_CRCX 1
 | 
			
		||||
#define MGCP_ENDP_DLCX 2
 | 
			
		||||
#define MGCP_ENDP_MDCX 3
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * what to do with the msg?
 | 
			
		||||
 *	- continue as usual?
 | 
			
		||||
 *	- reject and send a failure code?
 | 
			
		||||
 *	- defer? do not send anything
 | 
			
		||||
 */
 | 
			
		||||
#define MGCP_POLICY_CONT	4
 | 
			
		||||
#define MGCP_POLICY_REJECT	5
 | 
			
		||||
#define MGCP_POLICY_DEFER	6
 | 
			
		||||
 | 
			
		||||
typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
 | 
			
		||||
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
 | 
			
		||||
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
 | 
			
		||||
typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
 | 
			
		||||
typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return:
 | 
			
		||||
 *   <  0 in case no audio was processed
 | 
			
		||||
 *   >= 0 in case audio was processed. The remaining payload
 | 
			
		||||
 *   length will be returned.
 | 
			
		||||
 */
 | 
			
		||||
typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
 | 
			
		||||
			       struct mgcp_rtp_end *dst_end,
 | 
			
		||||
			       char *data, int *len, int buf_size);
 | 
			
		||||
typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
 | 
			
		||||
				     struct mgcp_rtp_end *dst_end,
 | 
			
		||||
				     struct mgcp_rtp_end *src_end);
 | 
			
		||||
 | 
			
		||||
typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
 | 
			
		||||
				int *payload_type,
 | 
			
		||||
				const char**subtype_name,
 | 
			
		||||
				const char**fmtp_extra);
 | 
			
		||||
 | 
			
		||||
#define PORT_ALLOC_STATIC	0
 | 
			
		||||
#define PORT_ALLOC_DYNAMIC	1
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This holds information on how to allocate ports
 | 
			
		||||
 */
 | 
			
		||||
struct mgcp_port_range {
 | 
			
		||||
	int mode;
 | 
			
		||||
 | 
			
		||||
	/* addr or NULL to fall-back to default */
 | 
			
		||||
	char *bind_addr;
 | 
			
		||||
 | 
			
		||||
	/* pre-allocated from a base? */
 | 
			
		||||
	int base_port;
 | 
			
		||||
 | 
			
		||||
	/* dynamically allocated */
 | 
			
		||||
	int range_start;
 | 
			
		||||
	int range_end;
 | 
			
		||||
	int last_port;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MGCP_KEEPALIVE_ONCE (-1)
 | 
			
		||||
 | 
			
		||||
struct mgcp_trunk_config {
 | 
			
		||||
	struct llist_head entry;
 | 
			
		||||
 | 
			
		||||
	struct mgcp_config *cfg;
 | 
			
		||||
 | 
			
		||||
	int trunk_nr;
 | 
			
		||||
	int trunk_type;
 | 
			
		||||
 | 
			
		||||
	char *audio_fmtp_extra;
 | 
			
		||||
	char *audio_name;
 | 
			
		||||
	int audio_payload;
 | 
			
		||||
	int audio_send_ptime;
 | 
			
		||||
	int audio_send_name;
 | 
			
		||||
	int audio_loop;
 | 
			
		||||
 | 
			
		||||
	int no_audio_transcoding;
 | 
			
		||||
 | 
			
		||||
	int omit_rtcp;
 | 
			
		||||
	int keepalive_interval;
 | 
			
		||||
 | 
			
		||||
	/* RTP patching */
 | 
			
		||||
	int force_constant_ssrc; /* 0: don't, 1: once */
 | 
			
		||||
	int force_aligned_timing;
 | 
			
		||||
 | 
			
		||||
	/* spec handling */
 | 
			
		||||
	int force_realloc;
 | 
			
		||||
 | 
			
		||||
	/* timer */
 | 
			
		||||
	struct osmo_timer_list keepalive_timer;
 | 
			
		||||
 | 
			
		||||
	unsigned int number_endpoints;
 | 
			
		||||
	struct mgcp_endpoint *endpoints;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum mgcp_role {
 | 
			
		||||
	MGCP_BSC = 0,
 | 
			
		||||
	MGCP_BSC_NAT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum mgcp_connection_mode {
 | 
			
		||||
	MGCP_CONN_NONE = 0,
 | 
			
		||||
	MGCP_CONN_RECV_ONLY = 1,
 | 
			
		||||
	MGCP_CONN_SEND_ONLY = 2,
 | 
			
		||||
	MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
 | 
			
		||||
	MGCP_CONN_LOOPBACK  = 4 | MGCP_CONN_RECV_SEND,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_config {
 | 
			
		||||
	int source_port;
 | 
			
		||||
	char *local_ip;
 | 
			
		||||
	char *source_addr;
 | 
			
		||||
	char *bts_ip;
 | 
			
		||||
	char *call_agent_addr;
 | 
			
		||||
 | 
			
		||||
	struct in_addr bts_in;
 | 
			
		||||
 | 
			
		||||
	/* transcoder handling */
 | 
			
		||||
	char *transcoder_ip;
 | 
			
		||||
	struct in_addr transcoder_in;
 | 
			
		||||
	int transcoder_remote_base;
 | 
			
		||||
 | 
			
		||||
	/* RTP processing */
 | 
			
		||||
	mgcp_processing rtp_processing_cb;
 | 
			
		||||
	mgcp_processing_setup setup_rtp_processing_cb;
 | 
			
		||||
 | 
			
		||||
	mgcp_get_format get_net_downlink_format_cb;
 | 
			
		||||
 | 
			
		||||
	struct osmo_wqueue gw_fd;
 | 
			
		||||
 | 
			
		||||
	struct mgcp_port_range bts_ports;
 | 
			
		||||
	struct mgcp_port_range net_ports;
 | 
			
		||||
	struct mgcp_port_range transcoder_ports;
 | 
			
		||||
	int endp_dscp;
 | 
			
		||||
 | 
			
		||||
	int bts_force_ptime;
 | 
			
		||||
 | 
			
		||||
	mgcp_change change_cb;
 | 
			
		||||
	mgcp_policy policy_cb;
 | 
			
		||||
	mgcp_reset reset_cb;
 | 
			
		||||
	mgcp_realloc realloc_cb;
 | 
			
		||||
	mgcp_rqnt rqnt_cb;
 | 
			
		||||
	void *data;
 | 
			
		||||
 | 
			
		||||
	uint32_t last_call_id;
 | 
			
		||||
 | 
			
		||||
	/* trunk handling */
 | 
			
		||||
	struct mgcp_trunk_config trunk;
 | 
			
		||||
	struct llist_head trunks;
 | 
			
		||||
 | 
			
		||||
	/* only used for start with a static configuration */
 | 
			
		||||
	int last_net_port;
 | 
			
		||||
	int last_bts_port;
 | 
			
		||||
 | 
			
		||||
	enum mgcp_role role;
 | 
			
		||||
 | 
			
		||||
	/* osmux translator: 0 means disabled, 1 means enabled */
 | 
			
		||||
	int osmux;
 | 
			
		||||
	/* addr to bind the server to */
 | 
			
		||||
	char *osmux_addr;
 | 
			
		||||
	/* The BSC-NAT may ask for enabling osmux on demand. This tells us if
 | 
			
		||||
	 * the osmux socket is already initialized.
 | 
			
		||||
	 */
 | 
			
		||||
	int osmux_init;
 | 
			
		||||
	/* osmux batch factor: from 1 to 4 maximum */
 | 
			
		||||
	int osmux_batch;
 | 
			
		||||
	/* osmux batch size (in bytes) */
 | 
			
		||||
	int osmux_batch_size;
 | 
			
		||||
	/* osmux port */
 | 
			
		||||
	uint16_t osmux_port;
 | 
			
		||||
	/* Pad circuit with dummy messages until we see the first voice
 | 
			
		||||
	 * message.
 | 
			
		||||
	 */
 | 
			
		||||
	uint16_t osmux_dummy;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* config management */
 | 
			
		||||
struct mgcp_config *mgcp_config_alloc(void);
 | 
			
		||||
int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
 | 
			
		||||
		      enum mgcp_role role);
 | 
			
		||||
int mgcp_vty_init(void);
 | 
			
		||||
int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
 | 
			
		||||
void mgcp_release_endp(struct mgcp_endpoint *endp);
 | 
			
		||||
void mgcp_initialize_endp(struct mgcp_endpoint *endp);
 | 
			
		||||
int mgcp_reset_transcoder(struct mgcp_config *cfg);
 | 
			
		||||
void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size);
 | 
			
		||||
int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter);
 | 
			
		||||
 | 
			
		||||
void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * format helper functions
 | 
			
		||||
 */
 | 
			
		||||
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
 | 
			
		||||
 | 
			
		||||
/* adc helper */
 | 
			
		||||
static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
 | 
			
		||||
{
 | 
			
		||||
	if (timeslot == 0) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "Timeslot should not be 0\n");
 | 
			
		||||
		timeslot = 255;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return timeslot + (32 * multiplex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot)
 | 
			
		||||
{
 | 
			
		||||
	*multiplex = endpoint / 32;
 | 
			
		||||
	*timeslot = endpoint % 32;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
 | 
			
		||||
int mgcp_send_reset_all(struct mgcp_config *cfg);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
 | 
			
		||||
int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp, struct sockaddr_in *addr, char *buf, int rc);
 | 
			
		||||
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										337
									
								
								include/osmocom/legacy_mgcp/mgcp_internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										337
									
								
								include/osmocom/legacy_mgcp/mgcp_internal.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,337 @@
 | 
			
		||||
/* MGCP Private Data */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
 | 
			
		||||
 * (C) 2009-2012 by On-Waves
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/select.h>
 | 
			
		||||
 | 
			
		||||
#define CI_UNUSED 0
 | 
			
		||||
 | 
			
		||||
enum mgcp_trunk_type {
 | 
			
		||||
	MGCP_TRUNK_VIRTUAL,
 | 
			
		||||
	MGCP_TRUNK_E1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_stream_state {
 | 
			
		||||
	uint32_t ssrc;
 | 
			
		||||
	uint16_t last_seq;
 | 
			
		||||
	uint32_t last_timestamp;
 | 
			
		||||
	uint32_t err_ts_counter;
 | 
			
		||||
	int32_t last_tsdelta;
 | 
			
		||||
	uint32_t last_arrival_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_state {
 | 
			
		||||
	int initialized;
 | 
			
		||||
	int patch_ssrc;
 | 
			
		||||
 | 
			
		||||
	uint32_t orig_ssrc;
 | 
			
		||||
 | 
			
		||||
	int seq_offset;
 | 
			
		||||
 | 
			
		||||
	int32_t  timestamp_offset;
 | 
			
		||||
	uint32_t packet_duration;
 | 
			
		||||
 | 
			
		||||
	struct mgcp_rtp_stream_state in_stream;
 | 
			
		||||
	struct mgcp_rtp_stream_state out_stream;
 | 
			
		||||
 | 
			
		||||
	/* jitter and packet loss calculation */
 | 
			
		||||
	int stats_initialized;
 | 
			
		||||
	uint16_t stats_base_seq;
 | 
			
		||||
	uint16_t stats_max_seq;
 | 
			
		||||
	uint32_t stats_ssrc;
 | 
			
		||||
	uint32_t stats_jitter;
 | 
			
		||||
	int32_t stats_transit;
 | 
			
		||||
	int stats_cycles;
 | 
			
		||||
	bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_codec {
 | 
			
		||||
	uint32_t rate;
 | 
			
		||||
	int channels;
 | 
			
		||||
	uint32_t frame_duration_num;
 | 
			
		||||
	uint32_t frame_duration_den;
 | 
			
		||||
 | 
			
		||||
	int payload_type;
 | 
			
		||||
	char *audio_name;
 | 
			
		||||
	char *subtype_name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_end {
 | 
			
		||||
	/* statistics */
 | 
			
		||||
	unsigned int packets;
 | 
			
		||||
	unsigned int octets;
 | 
			
		||||
	unsigned int dropped_packets;
 | 
			
		||||
	struct in_addr addr;
 | 
			
		||||
 | 
			
		||||
	/* in network byte order */
 | 
			
		||||
	int rtp_port, rtcp_port;
 | 
			
		||||
 | 
			
		||||
	/* audio codec information */
 | 
			
		||||
	struct mgcp_rtp_codec codec;
 | 
			
		||||
	struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */
 | 
			
		||||
 | 
			
		||||
	/* per endpoint data */
 | 
			
		||||
	int  frames_per_packet;
 | 
			
		||||
	uint32_t packet_duration_ms;
 | 
			
		||||
	char *fmtp_extra;
 | 
			
		||||
	int output_enabled;
 | 
			
		||||
	int force_output_ptime;
 | 
			
		||||
 | 
			
		||||
	/* RTP patching */
 | 
			
		||||
	int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
 | 
			
		||||
	int force_aligned_timing;
 | 
			
		||||
	void *rtp_process_data;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Each end has a socket...
 | 
			
		||||
	 */
 | 
			
		||||
	struct osmo_fd rtp;
 | 
			
		||||
	struct osmo_fd rtcp;
 | 
			
		||||
 | 
			
		||||
	int local_port;
 | 
			
		||||
	int local_alloc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	MGCP_TAP_BTS_IN,
 | 
			
		||||
	MGCP_TAP_BTS_OUT,
 | 
			
		||||
	MGCP_TAP_NET_IN,
 | 
			
		||||
	MGCP_TAP_NET_OUT,
 | 
			
		||||
 | 
			
		||||
	/* last element */
 | 
			
		||||
	MGCP_TAP_COUNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_tap {
 | 
			
		||||
	int enabled;
 | 
			
		||||
	struct sockaddr_in forward;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_lco {
 | 
			
		||||
	char *string;
 | 
			
		||||
	char *codec;
 | 
			
		||||
	int pkt_period_min; /* time in ms */
 | 
			
		||||
	int pkt_period_max; /* time in ms */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum mgcp_type {
 | 
			
		||||
	MGCP_RTP_DEFAULT	= 0,
 | 
			
		||||
	MGCP_RTP_TRANSCODED,
 | 
			
		||||
	MGCP_OSMUX_BSC,
 | 
			
		||||
	MGCP_OSMUX_BSC_NAT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#include <osmocom/legacy_mgcp/osmux.h>
 | 
			
		||||
 | 
			
		||||
struct mgcp_endpoint {
 | 
			
		||||
	int allocated;
 | 
			
		||||
	uint32_t ci;
 | 
			
		||||
	char *callid;
 | 
			
		||||
	struct mgcp_lco local_options;
 | 
			
		||||
	int conn_mode;
 | 
			
		||||
	int orig_mode;
 | 
			
		||||
 | 
			
		||||
	/* backpointer */
 | 
			
		||||
	struct mgcp_config *cfg;
 | 
			
		||||
	struct mgcp_trunk_config *tcfg;
 | 
			
		||||
 | 
			
		||||
	/* port status for bts/net */
 | 
			
		||||
	struct mgcp_rtp_end bts_end;
 | 
			
		||||
	struct mgcp_rtp_end net_end;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * For transcoding we will send from the local_port
 | 
			
		||||
	 * of trans_bts and it will arrive at trans_net from
 | 
			
		||||
	 * where we will forward it to the network.
 | 
			
		||||
	 */
 | 
			
		||||
	struct mgcp_rtp_end trans_bts;
 | 
			
		||||
	struct mgcp_rtp_end trans_net;
 | 
			
		||||
	enum mgcp_type type;
 | 
			
		||||
 | 
			
		||||
	/* sequence bits */
 | 
			
		||||
	struct mgcp_rtp_state net_state;
 | 
			
		||||
	struct mgcp_rtp_state bts_state;
 | 
			
		||||
 | 
			
		||||
	/* fields for re-transmission */
 | 
			
		||||
	char *last_trans;
 | 
			
		||||
	char *last_response;
 | 
			
		||||
 | 
			
		||||
	/* tap for the endpoint */
 | 
			
		||||
	struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		/* Osmux state: disabled, activating, active */
 | 
			
		||||
		enum osmux_state state;
 | 
			
		||||
		/* Allocated Osmux circuit ID for this endpoint */
 | 
			
		||||
		int allocated_cid;
 | 
			
		||||
		/* Used Osmux circuit ID for this endpoint */
 | 
			
		||||
		uint8_t cid;
 | 
			
		||||
		/* handle to batch messages */
 | 
			
		||||
		struct osmux_in_handle *in;
 | 
			
		||||
		/* handle to unbatch messages */
 | 
			
		||||
		struct osmux_out_handle out;
 | 
			
		||||
		/* statistics */
 | 
			
		||||
		struct {
 | 
			
		||||
			uint32_t chunks;
 | 
			
		||||
			uint32_t octets;
 | 
			
		||||
		} stats;
 | 
			
		||||
	} osmux;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define for_each_line(line, save)			\
 | 
			
		||||
	for (line = strline_r(NULL, &save); line;\
 | 
			
		||||
	     line = strline_r(NULL, &save))
 | 
			
		||||
 | 
			
		||||
static inline char *strline_r(char *str, char **saveptr)
 | 
			
		||||
{
 | 
			
		||||
	char *result;
 | 
			
		||||
 | 
			
		||||
	if (str)
 | 
			
		||||
		*saveptr = str;
 | 
			
		||||
 | 
			
		||||
	result = *saveptr;
 | 
			
		||||
 | 
			
		||||
	if (*saveptr != NULL) {
 | 
			
		||||
		*saveptr = strpbrk(*saveptr, "\r\n");
 | 
			
		||||
 | 
			
		||||
		if (*saveptr != NULL) {
 | 
			
		||||
			char *eos = *saveptr;
 | 
			
		||||
 | 
			
		||||
			if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
 | 
			
		||||
				(*saveptr)++;
 | 
			
		||||
			(*saveptr)++;
 | 
			
		||||
			if ((*saveptr)[0] == '\0')
 | 
			
		||||
				*saveptr = NULL;
 | 
			
		||||
 | 
			
		||||
			*eos = '\0';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Internal structure while parsing a request
 | 
			
		||||
 */
 | 
			
		||||
struct mgcp_parse_data {
 | 
			
		||||
	struct mgcp_config *cfg;
 | 
			
		||||
	struct mgcp_endpoint *endp;
 | 
			
		||||
	char *trans;
 | 
			
		||||
	char *save;
 | 
			
		||||
	int found;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int mgcp_send_dummy(struct mgcp_endpoint *endp);
 | 
			
		||||
int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
 | 
			
		||||
int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
 | 
			
		||||
int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
 | 
			
		||||
int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
 | 
			
		||||
int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
 | 
			
		||||
 | 
			
		||||
/* For transcoding we need to manage an in and an output that are connected */
 | 
			
		||||
static inline int endp_back_channel(int endpoint)
 | 
			
		||||
{
 | 
			
		||||
	return endpoint + 60;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
 | 
			
		||||
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
 | 
			
		||||
 | 
			
		||||
void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
 | 
			
		||||
			 struct mgcp_rtp_end *rtp);
 | 
			
		||||
uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
 | 
			
		||||
				  struct mgcp_rtp_end *rtp);
 | 
			
		||||
 | 
			
		||||
void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
 | 
			
		||||
			uint32_t *expected, int *loss);
 | 
			
		||||
uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
 | 
			
		||||
 | 
			
		||||
/* payload processing default functions */
 | 
			
		||||
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
 | 
			
		||||
				char *data, int *len, int buf_size);
 | 
			
		||||
 | 
			
		||||
int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
 | 
			
		||||
				      struct mgcp_rtp_end *dst_end,
 | 
			
		||||
				      struct mgcp_rtp_end *src_end);
 | 
			
		||||
 | 
			
		||||
void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
 | 
			
		||||
					  int *payload_type,
 | 
			
		||||
					  const char**subtype_name,
 | 
			
		||||
					  const char**fmtp_extra);
 | 
			
		||||
 | 
			
		||||
/* internal RTP Annex A counting */
 | 
			
		||||
void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
 | 
			
		||||
			const uint16_t seq, const int32_t transit,
 | 
			
		||||
			const uint32_t ssrc);
 | 
			
		||||
 | 
			
		||||
int mgcp_set_ip_tos(int fd, int tos);
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	MGCP_DEST_NET = 0,
 | 
			
		||||
	MGCP_DEST_BTS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MGCP_DUMMY_LOAD 0x23
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SDP related information
 | 
			
		||||
 */
 | 
			
		||||
/* Assume audio frame length of 20ms */
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
 | 
			
		||||
 | 
			
		||||
#define PTYPE_UNDEFINED (-1)
 | 
			
		||||
int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p);
 | 
			
		||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
 | 
			
		||||
			int payload_type, const char *audio_name);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Internal network related
 | 
			
		||||
 */
 | 
			
		||||
static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
 | 
			
		||||
{
 | 
			
		||||
	if (endp->cfg->net_ports.bind_addr)
 | 
			
		||||
		return endp->cfg->net_ports.bind_addr;
 | 
			
		||||
	return endp->cfg->source_addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
 | 
			
		||||
{
 | 
			
		||||
	if (endp->cfg->bts_ports.bind_addr)
 | 
			
		||||
		return endp->cfg->bts_ports.bind_addr;
 | 
			
		||||
	return endp->cfg->source_addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mgcp_msg_terminate_nul(struct msgb *msg);
 | 
			
		||||
							
								
								
									
										90
									
								
								include/osmocom/legacy_mgcp/mgcp_transcode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								include/osmocom/legacy_mgcp/mgcp_transcode.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2014 by On-Waves
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef OPENBSC_MGCP_TRANSCODE_H
 | 
			
		||||
#define OPENBSC_MGCP_TRANSCODE_H
 | 
			
		||||
 | 
			
		||||
#include "bscconfig.h"
 | 
			
		||||
 | 
			
		||||
#include <gsm.h>
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
#include <bcg729/decoder.h>
 | 
			
		||||
#include <bcg729/encoder.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum audio_format {
 | 
			
		||||
	AF_INVALID,
 | 
			
		||||
	AF_S16,
 | 
			
		||||
	AF_L16,
 | 
			
		||||
	AF_GSM,
 | 
			
		||||
	AF_G729,
 | 
			
		||||
	AF_PCMA,
 | 
			
		||||
	AF_PCMU
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct mgcp_process_rtp_state {
 | 
			
		||||
	/* decoding */
 | 
			
		||||
	enum audio_format src_fmt;
 | 
			
		||||
	union {
 | 
			
		||||
		gsm gsm_handle;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
		bcg729DecoderChannelContextStruct *g729_dec;
 | 
			
		||||
#endif
 | 
			
		||||
	} src;
 | 
			
		||||
	size_t src_frame_size;
 | 
			
		||||
	size_t src_samples_per_frame;
 | 
			
		||||
 | 
			
		||||
	/* processing */
 | 
			
		||||
 | 
			
		||||
	/* encoding */
 | 
			
		||||
	enum audio_format dst_fmt;
 | 
			
		||||
	union {
 | 
			
		||||
		gsm gsm_handle;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
		bcg729EncoderChannelContextStruct *g729_enc;
 | 
			
		||||
#endif
 | 
			
		||||
	} dst;
 | 
			
		||||
	size_t dst_frame_size;
 | 
			
		||||
	size_t dst_samples_per_frame;
 | 
			
		||||
	int dst_packet_duration;
 | 
			
		||||
 | 
			
		||||
	int is_running;
 | 
			
		||||
	uint16_t next_seq;
 | 
			
		||||
	uint32_t next_time;
 | 
			
		||||
	int16_t samples[10*160];
 | 
			
		||||
	size_t sample_cnt;
 | 
			
		||||
	size_t sample_offs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
 | 
			
		||||
			   struct mgcp_rtp_end *dst_end,
 | 
			
		||||
			   struct mgcp_rtp_end *src_end);
 | 
			
		||||
 | 
			
		||||
void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp,
 | 
			
		||||
					  int *payload_type,
 | 
			
		||||
					  const char**audio_name,
 | 
			
		||||
					  const char**fmtp_extra);
 | 
			
		||||
 | 
			
		||||
int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
 | 
			
		||||
				 struct mgcp_rtp_end *dst_end,
 | 
			
		||||
				 char *data, int *len, int buf_size);
 | 
			
		||||
 | 
			
		||||
int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst);
 | 
			
		||||
#endif /* OPENBSC_MGCP_TRANSCODE_H */
 | 
			
		||||
							
								
								
									
										41
									
								
								include/osmocom/legacy_mgcp/osmux.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								include/osmocom/legacy_mgcp/osmux.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
#ifndef _OPENBSC_OSMUX_H_
 | 
			
		||||
#define _OPENBSC_OSMUX_H_
 | 
			
		||||
 | 
			
		||||
#include <osmocom/netif/osmux.h>
 | 
			
		||||
 | 
			
		||||
#define OSMUX_PORT	1984
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	OSMUX_ROLE_BSC = 0,
 | 
			
		||||
	OSMUX_ROLE_BSC_NAT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int osmux_init(int role, struct mgcp_config *cfg);
 | 
			
		||||
int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port);
 | 
			
		||||
void osmux_disable_endpoint(struct mgcp_endpoint *endp);
 | 
			
		||||
void osmux_allocate_cid(struct mgcp_endpoint *endp);
 | 
			
		||||
void osmux_release_cid(struct mgcp_endpoint *endp);
 | 
			
		||||
 | 
			
		||||
int osmux_xfrm_to_rtp(struct mgcp_endpoint *endp, int type, char *buf, int rc);
 | 
			
		||||
int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp);
 | 
			
		||||
 | 
			
		||||
int osmux_send_dummy(struct mgcp_endpoint *endp);
 | 
			
		||||
 | 
			
		||||
int osmux_get_cid(void);
 | 
			
		||||
void osmux_put_cid(uint8_t osmux_cid);
 | 
			
		||||
int osmux_used_cid(void);
 | 
			
		||||
 | 
			
		||||
enum osmux_state {
 | 
			
		||||
	OSMUX_STATE_DISABLED = 0,
 | 
			
		||||
	OSMUX_STATE_NEGOTIATING,
 | 
			
		||||
	OSMUX_STATE_ACTIVATING,
 | 
			
		||||
	OSMUX_STATE_ENABLED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum osmux_usage {
 | 
			
		||||
	OSMUX_USAGE_OFF = 0,
 | 
			
		||||
	OSMUX_USAGE_ON = 1,
 | 
			
		||||
	OSMUX_USAGE_ONLY = 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										31
									
								
								include/osmocom/legacy_mgcp/vty.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								include/osmocom/legacy_mgcp/vty.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
#ifndef OPENBSC_VTY_H
 | 
			
		||||
#define OPENBSC_VTY_H
 | 
			
		||||
 | 
			
		||||
#include <osmocom/vty/vty.h>
 | 
			
		||||
#include <osmocom/vty/buffer.h>
 | 
			
		||||
#include <osmocom/vty/command.h>
 | 
			
		||||
 | 
			
		||||
struct gsm_network;
 | 
			
		||||
struct vty;
 | 
			
		||||
 | 
			
		||||
void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
 | 
			
		||||
 | 
			
		||||
struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
 | 
			
		||||
 | 
			
		||||
extern struct cmd_element cfg_description_cmd;
 | 
			
		||||
extern struct cmd_element cfg_no_description_cmd;
 | 
			
		||||
 | 
			
		||||
enum mgcp_vty_node {
 | 
			
		||||
	MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
 | 
			
		||||
	TRUNK_NODE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct log_info;
 | 
			
		||||
int bsc_vty_init(struct gsm_network *network);
 | 
			
		||||
int bsc_vty_init_extra(void);
 | 
			
		||||
 | 
			
		||||
void msc_vty_init(struct gsm_network *msc_network);
 | 
			
		||||
 | 
			
		||||
struct gsm_network *gsmnet_from_vty(struct vty *vty);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,18 +1,9 @@
 | 
			
		||||
noinst_HEADERS = \
 | 
			
		||||
	vty.h \
 | 
			
		||||
	mgcp_msg.h \
 | 
			
		||||
	mgcp_codec.h \
 | 
			
		||||
	mgcp_conn.h \
 | 
			
		||||
	mgcp_stat.h \
 | 
			
		||||
	mgcp_endp.h \
 | 
			
		||||
	mgcp_ep.h \
 | 
			
		||||
	mgcp_sdp.h \
 | 
			
		||||
	mgcp_codec.h \
 | 
			
		||||
	mgcp_trunk.h \
 | 
			
		||||
	debug.h \
 | 
			
		||||
	mgcp_ratectr.h \
 | 
			
		||||
	mgcp_e1.h \
 | 
			
		||||
	mgcp_network.h \
 | 
			
		||||
	mgcp_protocol.h \
 | 
			
		||||
	mgcp_iuup.h \
 | 
			
		||||
	mgcp_rtp_end.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -29,8 +29,6 @@
 | 
			
		||||
/* Debug Areas of the code */
 | 
			
		||||
enum {
 | 
			
		||||
	DRTP,
 | 
			
		||||
	DE1,
 | 
			
		||||
	DOSMUX,
 | 
			
		||||
	Debug_LastEntry,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,22 +23,16 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/msgb.h>
 | 
			
		||||
#include <osmocom/core/socket.h>
 | 
			
		||||
#include <osmocom/core/osmo_io.h>
 | 
			
		||||
#include <osmocom/core/write_queue.h>
 | 
			
		||||
#include <osmocom/core/timer.h>
 | 
			
		||||
#include <osmocom/core/logging.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp/mgcp_common.h>
 | 
			
		||||
#include <osmocom/mgcp/osmux.h>
 | 
			
		||||
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#include "mgcp_ratectr.h"
 | 
			
		||||
 | 
			
		||||
#define RTP_PORT_DEFAULT_RANGE_START 16002
 | 
			
		||||
#define RTP_PORT_DEFAULT_RANGE_END RTP_PORT_DEFAULT_RANGE_START + 64
 | 
			
		||||
@@ -48,7 +42,7 @@
 | 
			
		||||
 */
 | 
			
		||||
struct mgcp_endpoint;
 | 
			
		||||
struct mgcp_config;
 | 
			
		||||
struct mgcp_trunk;
 | 
			
		||||
struct mgcp_trunk_config;
 | 
			
		||||
struct mgcp_rtp_end;
 | 
			
		||||
 | 
			
		||||
#define MGCP_ENDP_CRCX 1
 | 
			
		||||
@@ -65,38 +59,38 @@ struct mgcp_rtp_end;
 | 
			
		||||
#define MGCP_POLICY_REJECT	5
 | 
			
		||||
#define MGCP_POLICY_DEFER	6
 | 
			
		||||
 | 
			
		||||
typedef int (*mgcp_reset)(struct mgcp_trunk *cfg);
 | 
			
		||||
typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
 | 
			
		||||
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
 | 
			
		||||
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
 | 
			
		||||
typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
 | 
			
		||||
typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return:
 | 
			
		||||
 *   <  0 in case no audio was processed
 | 
			
		||||
 *   >= 0 in case audio was processed.
 | 
			
		||||
 *   >= 0 in case audio was processed. The remaining payload
 | 
			
		||||
 *   length will be returned.
 | 
			
		||||
 */
 | 
			
		||||
typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
 | 
			
		||||
			       struct mgcp_rtp_end *dst_end, struct msgb *msg);
 | 
			
		||||
			       struct mgcp_rtp_end *dst_end,
 | 
			
		||||
			       char *data, int *len, int buf_size);
 | 
			
		||||
typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
 | 
			
		||||
				     struct mgcp_rtp_end *dst_end,
 | 
			
		||||
				     struct mgcp_rtp_end *src_end);
 | 
			
		||||
 | 
			
		||||
struct mgcp_conn_rtp;
 | 
			
		||||
 | 
			
		||||
typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
 | 
			
		||||
				     struct mgcp_conn_rtp *conn_dst,
 | 
			
		||||
				     struct mgcp_conn_rtp *conn_src);
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_codec;
 | 
			
		||||
 | 
			
		||||
typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
 | 
			
		||||
				const struct mgcp_rtp_codec **codec,
 | 
			
		||||
				const char **fmtp_extra,
 | 
			
		||||
				int *payload_type,
 | 
			
		||||
				const char**subtype_name,
 | 
			
		||||
				const char**fmtp_extra,
 | 
			
		||||
				struct mgcp_conn_rtp *conn);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This holds information on how to allocate ports
 | 
			
		||||
 */
 | 
			
		||||
struct mgcp_port_range {
 | 
			
		||||
	pthread_mutex_t lock;
 | 
			
		||||
	/* addr or NULL to fall-back to default */
 | 
			
		||||
	char bind_addr_v4[INET6_ADDRSTRLEN];
 | 
			
		||||
	char bind_addr_v6[INET6_ADDRSTRLEN];
 | 
			
		||||
	char *bind_addr;
 | 
			
		||||
 | 
			
		||||
	/* dynamically allocated */
 | 
			
		||||
	int range_start;
 | 
			
		||||
@@ -111,17 +105,56 @@ struct mgcp_port_range {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* There are up to three modes in which the keep-alive dummy packet can be
 | 
			
		||||
 * sent. The behaviour is controlled via the keepalive_interval member of the
 | 
			
		||||
 * sent. The beviour is controlled viw the keepalive_interval member of the
 | 
			
		||||
 * trunk config. If that member is set to 0 (MGCP_KEEPALIVE_NEVER) no dummy-
 | 
			
		||||
 * packet is sent at all and the timer that sends regular dummy packets
 | 
			
		||||
 * is no longer scheduled. If the keepalive_interval is set to -1, only
 | 
			
		||||
 * one dummy packet is sent when an CRCX or an MDCX is performed. No timer
 | 
			
		||||
 * is scheduled. For all vales greater 0, the timer is scheduled and the
 | 
			
		||||
 * is scheduled. For all vales greater 0, the a timer is scheduled and the
 | 
			
		||||
 * value is used as interval. See also mgcp_keepalive_timer_cb(),
 | 
			
		||||
 * handle_modify_con(), and handle_create_con() */
 | 
			
		||||
#define MGCP_KEEPALIVE_ONCE (-1)
 | 
			
		||||
#define MGCP_KEEPALIVE_NEVER 0
 | 
			
		||||
 | 
			
		||||
struct mgcp_trunk_config {
 | 
			
		||||
	struct llist_head entry;
 | 
			
		||||
 | 
			
		||||
	struct mgcp_config *cfg;
 | 
			
		||||
 | 
			
		||||
	int trunk_nr;
 | 
			
		||||
	int trunk_type;
 | 
			
		||||
 | 
			
		||||
	char *audio_fmtp_extra;
 | 
			
		||||
	char *audio_name;
 | 
			
		||||
	int audio_payload;
 | 
			
		||||
	int audio_send_ptime;
 | 
			
		||||
	int audio_send_name;
 | 
			
		||||
	int audio_loop;
 | 
			
		||||
 | 
			
		||||
	int no_audio_transcoding;
 | 
			
		||||
 | 
			
		||||
	int omit_rtcp;
 | 
			
		||||
	int keepalive_interval;
 | 
			
		||||
 | 
			
		||||
	/* RTP patching */
 | 
			
		||||
	int force_constant_ssrc; /* 0: don't, 1: once */
 | 
			
		||||
	int force_aligned_timing;
 | 
			
		||||
 | 
			
		||||
	/* spec handling */
 | 
			
		||||
	int force_realloc;
 | 
			
		||||
 | 
			
		||||
	/* timer */
 | 
			
		||||
	struct osmo_timer_list keepalive_timer;
 | 
			
		||||
 | 
			
		||||
	/* When set, incoming RTP packets are not filtered
 | 
			
		||||
	 * when ports and ip-address do not match (debug) */
 | 
			
		||||
	int rtp_accept_all;
 | 
			
		||||
 | 
			
		||||
	unsigned int number_endpoints;
 | 
			
		||||
	int vty_number_endpoints;
 | 
			
		||||
	struct mgcp_endpoint *endpoints;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum mgcp_role {
 | 
			
		||||
	MGCP_BSC = 0,
 | 
			
		||||
	MGCP_BSC_NAT,
 | 
			
		||||
@@ -129,63 +162,56 @@ enum mgcp_role {
 | 
			
		||||
 | 
			
		||||
struct mgcp_config {
 | 
			
		||||
	int source_port;
 | 
			
		||||
	char local_ip[INET6_ADDRSTRLEN];
 | 
			
		||||
	char source_addr[INET6_ADDRSTRLEN];
 | 
			
		||||
	char call_agent_addr[INET6_ADDRSTRLEN];
 | 
			
		||||
	char *local_ip;
 | 
			
		||||
	char *source_addr;
 | 
			
		||||
	char *call_agent_addr;
 | 
			
		||||
 | 
			
		||||
	/* RTP processing */
 | 
			
		||||
	mgcp_processing rtp_processing_cb;
 | 
			
		||||
	mgcp_processing_setup setup_rtp_processing_cb;
 | 
			
		||||
 | 
			
		||||
	mgcp_get_format get_net_downlink_format_cb;
 | 
			
		||||
 | 
			
		||||
	struct osmo_wqueue gw_fd;
 | 
			
		||||
 | 
			
		||||
	struct mgcp_port_range net_ports;
 | 
			
		||||
	int endp_dscp;
 | 
			
		||||
	int endp_priority;
 | 
			
		||||
 | 
			
		||||
	int force_ptime;
 | 
			
		||||
 | 
			
		||||
	mgcp_change change_cb;
 | 
			
		||||
	mgcp_policy policy_cb;
 | 
			
		||||
	mgcp_reset reset_cb;
 | 
			
		||||
	mgcp_realloc realloc_cb;
 | 
			
		||||
	mgcp_rqnt rqnt_cb;
 | 
			
		||||
	void *data;
 | 
			
		||||
 | 
			
		||||
	/* list holding the trunks */
 | 
			
		||||
	uint32_t last_call_id;
 | 
			
		||||
 | 
			
		||||
	/* trunk handling */
 | 
			
		||||
	struct mgcp_trunk_config trunk;
 | 
			
		||||
	struct llist_head trunks;
 | 
			
		||||
 | 
			
		||||
	enum mgcp_role role;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		/* Osmux usage policy: */
 | 
			
		||||
		enum osmux_usage usage;
 | 
			
		||||
		/* addr to bind the server to */
 | 
			
		||||
		char *local_addr_v4;
 | 
			
		||||
		char *local_addr_v6;
 | 
			
		||||
		/* osmux port */
 | 
			
		||||
		uint16_t local_port;
 | 
			
		||||
		/* The osmux socket is allocated on demand (1st time used).
 | 
			
		||||
		* This tells us if the osmux socket is already initialized.  */
 | 
			
		||||
		bool initialized;
 | 
			
		||||
		/* osmux batch factor: from 1 to 4 maximum */
 | 
			
		||||
		int batch_factor;
 | 
			
		||||
		/* osmux batch size (in bytes) */
 | 
			
		||||
		int batch_size;
 | 
			
		||||
		/* Pad circuit with dummy AMR frames if no payload to transmit is available */
 | 
			
		||||
		bool dummy_padding;
 | 
			
		||||
		/* Whether peer is behind NAT (Retrieve remote addr from 1st received Osmux packet) */
 | 
			
		||||
		bool peer_behind_nat;
 | 
			
		||||
	} osmux;
 | 
			
		||||
	/* domain name of the media gateway */
 | 
			
		||||
	char domain[255+1];
 | 
			
		||||
 | 
			
		||||
	/* time after which inactive connections (CIs) get closed */
 | 
			
		||||
	int conn_timeout;
 | 
			
		||||
 | 
			
		||||
	/* osmocom CTRL interface */
 | 
			
		||||
	struct ctrl_handle *ctrl;
 | 
			
		||||
 | 
			
		||||
	/* global rate counters to measure the MGWs overall performance and
 | 
			
		||||
	 * health */
 | 
			
		||||
	struct mgcp_ratectr_global ratectr;
 | 
			
		||||
	/* osmux translator: 0 means disabled, 1 means enabled */
 | 
			
		||||
	int osmux;
 | 
			
		||||
	/* addr to bind the server to */
 | 
			
		||||
	char *osmux_addr;
 | 
			
		||||
	/* The BSC-NAT may ask for enabling osmux on demand. This tells us if
 | 
			
		||||
	 * the osmux socket is already initialized.
 | 
			
		||||
	 */
 | 
			
		||||
	int osmux_init;
 | 
			
		||||
	/* osmux batch factor: from 1 to 4 maximum */
 | 
			
		||||
	int osmux_batch;
 | 
			
		||||
	/* osmux batch size (in bytes) */
 | 
			
		||||
	int osmux_batch_size;
 | 
			
		||||
	/* osmux port */
 | 
			
		||||
	uint16_t osmux_port;
 | 
			
		||||
	/* Pad circuit with dummy messages until we see the first voice
 | 
			
		||||
	 * message.
 | 
			
		||||
	 */
 | 
			
		||||
	uint16_t osmux_dummy;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* config management */
 | 
			
		||||
@@ -193,7 +219,9 @@ struct mgcp_config *mgcp_config_alloc(void);
 | 
			
		||||
int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
 | 
			
		||||
		      enum mgcp_role role);
 | 
			
		||||
int mgcp_vty_init(void);
 | 
			
		||||
void mgcp_trunk_set_keepalive(struct mgcp_trunk *trunk, int interval);
 | 
			
		||||
int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
 | 
			
		||||
void mgcp_release_endp(struct mgcp_endpoint *endp);
 | 
			
		||||
void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * format helper functions
 | 
			
		||||
@@ -201,9 +229,9 @@ void mgcp_trunk_set_keepalive(struct mgcp_trunk *trunk, int interval);
 | 
			
		||||
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int mgcp_send_reset_ep(struct mgcp_endpoint *endp);
 | 
			
		||||
int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
 | 
			
		||||
int mgcp_send_reset_all(struct mgcp_config *cfg);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int mgcp_create_bind(const char *source_addr, int port, uint8_t dscp, uint8_t prio);
 | 
			
		||||
int mgcp_udp_send(struct osmo_io_fd *iofd, const struct osmo_sockaddr *addr, const char *buf, int len);
 | 
			
		||||
int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
 | 
			
		||||
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,48 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_common.h>
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
 | 
			
		||||
 | 
			
		||||
#define PTYPE_UNDEFINED (-1)
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_codec {
 | 
			
		||||
	uint32_t rate;
 | 
			
		||||
	int channels;
 | 
			
		||||
	uint32_t frame_duration_num;
 | 
			
		||||
	uint32_t frame_duration_den;
 | 
			
		||||
 | 
			
		||||
	int payload_type;
 | 
			
		||||
	char audio_name[64];
 | 
			
		||||
	char subtype_name[64];
 | 
			
		||||
 | 
			
		||||
	bool param_present;
 | 
			
		||||
	struct mgcp_codec_param param;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool mgcp_codec_amr_align_mode_is_indicated(const struct mgcp_rtp_codec *codec);
 | 
			
		||||
bool mgcp_codec_amr_is_octet_aligned(const struct mgcp_rtp_codec *codec);
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_codecset {
 | 
			
		||||
	/* currently selected audio codec */
 | 
			
		||||
	struct mgcp_rtp_codec *codec;
 | 
			
		||||
	/* array with assigned audio codecs to choose from (SDP) */
 | 
			
		||||
	struct mgcp_rtp_codec codecs[MGCP_MAX_CODECS];
 | 
			
		||||
	/* number of assigned audio codecs (SDP) */
 | 
			
		||||
	unsigned int codecs_assigned;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void mgcp_codecset_reset(struct mgcp_rtp_codecset *cset);
 | 
			
		||||
void mgcp_codecset_summary(struct mgcp_rtp_codecset *cset, const char *prefix_str);
 | 
			
		||||
int mgcp_codecset_add_codec(struct mgcp_rtp_codecset *cset, int payload_type,
 | 
			
		||||
			    const char *audio_name, const struct mgcp_codec_param *param);
 | 
			
		||||
int mgcp_codecset_decide(struct mgcp_rtp_codecset *cset_src, struct mgcp_rtp_codecset *cset_dst);
 | 
			
		||||
const struct mgcp_rtp_codec *mgcp_codecset_pt_find_by_subtype_name(const struct mgcp_rtp_codecset *cset,
 | 
			
		||||
								const char *subtype_name, unsigned int match_nr);
 | 
			
		||||
struct mgcp_rtp_codec *mgcp_codecset_find_codec_from_pt(struct mgcp_rtp_codecset *cset, int payload_type);
 | 
			
		||||
@@ -47,32 +47,16 @@ enum mgcp_connection_mode {
 | 
			
		||||
	MGCP_CONN_SEND_ONLY = 2,
 | 
			
		||||
	MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
 | 
			
		||||
	MGCP_CONN_LOOPBACK  = 4 | MGCP_CONN_RECV_SEND,
 | 
			
		||||
	MGCP_CONN_CONFECHO  = 8 | MGCP_CONN_RECV_SEND,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MGCP_X_OSMO_IGN_HEADER "X-Osmo-IGN:"
 | 
			
		||||
#define MGCP_X_OSMO_OSMUX_HEADER "X-Osmux:"
 | 
			
		||||
 | 
			
		||||
/* Values should be bitwise-OR-able */
 | 
			
		||||
enum mgcp_x_osmo_ign {
 | 
			
		||||
	MGCP_X_OSMO_IGN_NONE = 0,
 | 
			
		||||
	MGCP_X_OSMO_IGN_CALLID = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Codec parameters (communicated via SDP/fmtp) */
 | 
			
		||||
struct mgcp_codec_param {
 | 
			
		||||
	bool amr_octet_aligned_present;
 | 
			
		||||
	bool amr_octet_aligned;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Ensure that the msg->l2h is NUL terminated. */
 | 
			
		||||
static inline int mgcp_msg_terminate_nul(struct msgb *msg)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char *tail = msg->tail; /* char after l2 data */
 | 
			
		||||
	unsigned char *tail = msg->l2h + msgb_l2len(msg); /* char after l2 data */
 | 
			
		||||
	if (tail[-1] == '\0')
 | 
			
		||||
		/* nothing to do */;
 | 
			
		||||
	else if (msgb_tailroom(msg) > 0)
 | 
			
		||||
		msgb_put_u8(msg, (uint8_t)'\0');
 | 
			
		||||
		tail[0] = '\0';
 | 
			
		||||
	else if (tail[-1] == '\r' || tail[-1] == '\n')
 | 
			
		||||
		tail[-1] = '\0';
 | 
			
		||||
	else {
 | 
			
		||||
@@ -84,29 +68,8 @@ static inline int mgcp_msg_terminate_nul(struct msgb *msg)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Maximum length of the comment field */
 | 
			
		||||
#define MGCP_COMMENT_MAXLEN 256
 | 
			
		||||
 | 
			
		||||
/* Maximum allowed String length of Connection Identifiers as per spec
 | 
			
		||||
 * (see also RFC3435 2.1.3.2 Names of Connections), plus one for '\0'. */
 | 
			
		||||
#define MGCP_CONN_ID_MAXLEN 32+1
 | 
			
		||||
 | 
			
		||||
/* Deprecated: old name of MGCP_CONN_ID_MAXLEN. */
 | 
			
		||||
#define MGCP_CONN_ID_LENGTH MGCP_CONN_ID_MAXLEN
 | 
			
		||||
 | 
			
		||||
/* String length of Endpoint Identifiers.
 | 
			
		||||
/  (see also RFC3435 section 3.2.1.3) */
 | 
			
		||||
#define MGCP_ENDPOINT_MAXLEN (255*2+1+1)
 | 
			
		||||
 | 
			
		||||
/* A prefix to denote the virtual trunk (RTP on both ends) */
 | 
			
		||||
#define MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK "rtpbridge/"
 | 
			
		||||
 | 
			
		||||
/* A prefix to denote the e1 trunk
 | 
			
		||||
 * (see also RFC3435 section E.2) */
 | 
			
		||||
#define MGCP_ENDPOINT_PREFIX_E1_TRUNK "ds/e1-"
 | 
			
		||||
 | 
			
		||||
/* Maximal number of payload types / codecs that can be negotiated via SDP at
 | 
			
		||||
 * at once. */
 | 
			
		||||
#define MGCP_MAX_CODECS 10
 | 
			
		||||
/* String length of Connection Identifiers
 | 
			
		||||
 * (see also RFC3435 2.1.3.2 Names of Connections) */
 | 
			
		||||
#define MGCP_CONN_ID_LENGTH 32+1
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -23,233 +23,17 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp/mgcp.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_common.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_network.h>
 | 
			
		||||
#include <osmocom/mgcp/osmux.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_internal.h>
 | 
			
		||||
#include <osmocom/core/linuxlist.h>
 | 
			
		||||
#include <osmocom/core/rate_ctr.h>
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/gsm/iuup.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_rtp_end.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
#define LOGPCONN(conn, cat, level, fmt, args...) \
 | 
			
		||||
LOGPENDP((conn)->endp, cat, level, "CI:%s " fmt, \
 | 
			
		||||
         (conn)->id, \
 | 
			
		||||
         ## args)
 | 
			
		||||
 | 
			
		||||
#define LOG_CONN(conn, level, fmt, args...) \
 | 
			
		||||
	LOGP(DRTP, level, "(%s I:%s) " fmt, \
 | 
			
		||||
	     (conn)->endp ? (conn)->endp->name : "none", (conn)->id, ## args)
 | 
			
		||||
 | 
			
		||||
#define LOG_CONN_RTP(conn_rtp, level, fmt, args...) \
 | 
			
		||||
	LOG_CONN((conn_rtp)->conn, level, fmt, ## args)
 | 
			
		||||
 | 
			
		||||
/* Specific rtp connection type (see struct mgcp_conn_rtp) */
 | 
			
		||||
enum mgcp_conn_rtp_type {
 | 
			
		||||
	MGCP_RTP_DEFAULT	= 0,
 | 
			
		||||
	MGCP_RTP_OSMUX,
 | 
			
		||||
	MGCP_RTP_IUUP,
 | 
			
		||||
};
 | 
			
		||||
extern const struct value_string mgcp_conn_rtp_type_names[];
 | 
			
		||||
static inline const char *mgcp_conn_rtp_type_name(enum mgcp_conn_rtp_type val)
 | 
			
		||||
{
 | 
			
		||||
	return get_value_string(mgcp_conn_rtp_type_names, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*! Connection type, specifies which member of the union "u" in mgcp_conn
 | 
			
		||||
 *  contains a useful connection description (currently only RTP) */
 | 
			
		||||
enum mgcp_conn_type {
 | 
			
		||||
	MGCP_CONN_TYPE_RTP,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* MGCP connection (RTP) */
 | 
			
		||||
struct mgcp_conn_rtp {
 | 
			
		||||
 | 
			
		||||
	/* Backpointer to conn struct */
 | 
			
		||||
	struct mgcp_conn *conn;
 | 
			
		||||
 | 
			
		||||
	/* Specific connection type */
 | 
			
		||||
	enum mgcp_conn_rtp_type type;
 | 
			
		||||
 | 
			
		||||
	/* Port status */
 | 
			
		||||
	struct mgcp_rtp_end end;
 | 
			
		||||
 | 
			
		||||
	/* Sequence bits */
 | 
			
		||||
	struct mgcp_rtp_state state;
 | 
			
		||||
 | 
			
		||||
	/* taps for the rtp connection; one per direction */
 | 
			
		||||
	struct mgcp_rtp_tap tap_in;
 | 
			
		||||
	struct mgcp_rtp_tap tap_out;
 | 
			
		||||
 | 
			
		||||
	/* Osmux states (optional) */
 | 
			
		||||
	struct {
 | 
			
		||||
		/* Osmux state: disabled, activating, active */
 | 
			
		||||
		enum osmux_state state;
 | 
			
		||||
		/* Is local_cid holding valid data? is it allocated from pool? */
 | 
			
		||||
		bool local_cid_allocated;
 | 
			
		||||
		/* Allocated local Osmux circuit ID for this conn */
 | 
			
		||||
		uint8_t local_cid;
 | 
			
		||||
		/* Is remote_cid holding valid data? was it already received from client? */
 | 
			
		||||
		bool remote_cid_present;
 | 
			
		||||
		/* Received remote Osmux circuit ID for this conn */
 | 
			
		||||
		uint8_t remote_cid;
 | 
			
		||||
		/* handle to batch messages, shared (refcounted) among several conns */
 | 
			
		||||
		struct osmux_in_handle *in;
 | 
			
		||||
		/* handle to unbatch messages, one allocated and owned per conn */
 | 
			
		||||
		struct osmux_out_handle *out;
 | 
			
		||||
		/* statistics: */
 | 
			
		||||
		struct rate_ctr_group *ctrg;
 | 
			
		||||
	} osmux;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		struct osmo_iuup_instance *iui;
 | 
			
		||||
		bool active_init; /* true: Send IuUP Init */
 | 
			
		||||
		int rfci_id_no_data; /* RFCI Id for RFCI NO_DATA (-1 if not available) */
 | 
			
		||||
		bool configured;
 | 
			
		||||
		struct osmo_iuup_rnl_prim *init_ind;
 | 
			
		||||
	} iuup;
 | 
			
		||||
 | 
			
		||||
	struct rate_ctr_group *ctrg;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*! MGCP connection (untyped) */
 | 
			
		||||
struct mgcp_conn {
 | 
			
		||||
	/*! list head */
 | 
			
		||||
	struct llist_head entry;
 | 
			
		||||
 | 
			
		||||
	/*! Backpointer to the endpoint where the conn belongs to */
 | 
			
		||||
	struct mgcp_endpoint *endp;
 | 
			
		||||
 | 
			
		||||
	/*! type of the connection (union) */
 | 
			
		||||
	enum mgcp_conn_type type;
 | 
			
		||||
 | 
			
		||||
	/*! mode of the connection */
 | 
			
		||||
	enum mgcp_connection_mode mode;
 | 
			
		||||
 | 
			
		||||
	/*! copy of the mode to restore the original setting (VTY) */
 | 
			
		||||
	enum mgcp_connection_mode mode_orig;
 | 
			
		||||
 | 
			
		||||
	/*! connection id to identify the connection */
 | 
			
		||||
	char id[MGCP_CONN_ID_MAXLEN];
 | 
			
		||||
 | 
			
		||||
	/*! human readable name (vty, logging) */
 | 
			
		||||
	char name[256];
 | 
			
		||||
 | 
			
		||||
	/*! activity tracker (for cleaning up inactive connections) */
 | 
			
		||||
	struct osmo_timer_list watchdog;
 | 
			
		||||
 | 
			
		||||
	/*! union with connection description */
 | 
			
		||||
	union {
 | 
			
		||||
		struct mgcp_conn_rtp rtp;
 | 
			
		||||
	} u;
 | 
			
		||||
 | 
			
		||||
	/*! pointer to optional private data */
 | 
			
		||||
	void *priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* RTP connection related counters */
 | 
			
		||||
enum {
 | 
			
		||||
	IN_STREAM_ERR_TSTMP_CTR,
 | 
			
		||||
	OUT_STREAM_ERR_TSTMP_CTR,
 | 
			
		||||
	RTP_PACKETS_RX_CTR,
 | 
			
		||||
	RTP_OCTETS_RX_CTR,
 | 
			
		||||
	RTP_PACKETS_TX_CTR,
 | 
			
		||||
	RTP_OCTETS_TX_CTR,
 | 
			
		||||
	RTP_DROPPED_PACKETS_CTR,
 | 
			
		||||
	RTP_NUM_CONNECTIONS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* RTP per-connection statistics. Instances of the corresponding rate counter group
 | 
			
		||||
 * exist for the lifetime of an RTP connection.
 | 
			
		||||
 * Must be kept in sync with all_rtp_conn_rate_ctr_desc below */
 | 
			
		||||
static const struct rate_ctr_desc mgcp_conn_rate_ctr_desc[] = {
 | 
			
		||||
	[IN_STREAM_ERR_TSTMP_CTR] = {"stream_err_tstmp:in", "Inbound rtp-stream timestamp errors."},
 | 
			
		||||
	[OUT_STREAM_ERR_TSTMP_CTR] = {"stream_err_tstmp:out", "Outbound rtp-stream timestamp errors."},
 | 
			
		||||
	[RTP_PACKETS_RX_CTR] = {"rtp:packets_rx", "Inbound rtp packets."},
 | 
			
		||||
	[RTP_OCTETS_RX_CTR] = {"rtp:octets_rx", "Inbound rtp octets."},
 | 
			
		||||
	[RTP_PACKETS_TX_CTR] = {"rtp:packets_tx", "Outbound rtp packets."},
 | 
			
		||||
	[RTP_OCTETS_TX_CTR] = {"rtp:octets_tx", "Outbound rtp octets."},
 | 
			
		||||
	[RTP_DROPPED_PACKETS_CTR] = {"rtp:dropped", "Dropped rtp packets."}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Aggregated RTP connection stats. These are updated when an RTP connection is freed.
 | 
			
		||||
 * Must be kept in sync with mgcp_conn_rate_ctr_desc above */
 | 
			
		||||
static const struct rate_ctr_desc all_rtp_conn_rate_ctr_desc[] = {
 | 
			
		||||
	[IN_STREAM_ERR_TSTMP_CTR] = {"all_rtp:err_tstmp_in", "Total inbound rtp-stream timestamp errors."},
 | 
			
		||||
	[OUT_STREAM_ERR_TSTMP_CTR] = {"all_rtp:err_tstmp_out", "Total outbound rtp-stream timestamp errors."},
 | 
			
		||||
	[RTP_PACKETS_RX_CTR] = {"all_rtp:packets_rx", "Total inbound rtp packets."},
 | 
			
		||||
	[RTP_OCTETS_RX_CTR] = {"all_rtp:octets_rx", "Total inbound rtp octets."},
 | 
			
		||||
	[RTP_PACKETS_TX_CTR] = {"all_rtp:packets_tx", "Total outbound rtp packets."},
 | 
			
		||||
	[RTP_OCTETS_TX_CTR] = {"all_rtp:octets_tx", "Total outbound rtp octets."},
 | 
			
		||||
	[RTP_DROPPED_PACKETS_CTR] = {"all_rtp:dropped", "Total dropped rtp packets."},
 | 
			
		||||
 | 
			
		||||
	/* This last counter does not exist in per-connection stats, only here. */
 | 
			
		||||
	[RTP_NUM_CONNECTIONS] = {"all_rtp:num_closed_conns", "Total number of rtp connections closed."}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Osmux connection related counters */
 | 
			
		||||
enum {
 | 
			
		||||
	OSMUX_CHUNKS_RX_CTR,
 | 
			
		||||
	OSMUX_OCTETS_RX_CTR,
 | 
			
		||||
	OSMUX_RTP_PACKETS_TX_CTR,
 | 
			
		||||
	OSMUX_RTP_PACKETS_TX_DROPPED_CTR,
 | 
			
		||||
	OSMUX_AMR_OCTETS_TX_CTR,
 | 
			
		||||
	/* Only available in global stats: */
 | 
			
		||||
	OSMUX_NUM_CONNECTIONS,
 | 
			
		||||
	OSMUX_PACKETS_RX_CTR,
 | 
			
		||||
	OSMUX_PACKETS_TX_CTR,
 | 
			
		||||
	OSMUX_DROPPED_PACKETS_CTR,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* RTP per-connection statistics. Instances of the corresponding rate counter group
 | 
			
		||||
 * exist for the lifetime of an RTP connection.
 | 
			
		||||
 * Must be kept in sync with all_rtp_conn_rate_ctr_desc below */
 | 
			
		||||
static const struct rate_ctr_desc mgcp_conn_osmux_rate_ctr_desc[] = {
 | 
			
		||||
	[OSMUX_CHUNKS_RX_CTR] = {"osmux:chunks_rx", "Inbound Osmux chunks."},
 | 
			
		||||
	[OSMUX_OCTETS_RX_CTR] = {"osmux:octets_rx", "Inbound Osmux octets."},
 | 
			
		||||
	[OSMUX_RTP_PACKETS_TX_CTR] = {"osmux:rtp_packets_tx", "Tx outbound RTP packets to encode as Osmux."},
 | 
			
		||||
	[OSMUX_RTP_PACKETS_TX_DROPPED_CTR] = {"osmux:rtp_packets_tx_dropped", "Dropped Tx outbound RTP packets to encode as Osmux."},
 | 
			
		||||
	[OSMUX_AMR_OCTETS_TX_CTR] = {"osmux:amr_octets_tx", "Tx outbound AMD payload octets."},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Aggregated Osmux connection stats. These are updated when an Osmux connection is freed.
 | 
			
		||||
 * Must be kept in sync with mgcp_conn_osmux_rate_ctr_desc above */
 | 
			
		||||
static const struct rate_ctr_desc all_osmux_conn_rate_ctr_desc[] = {
 | 
			
		||||
	[OSMUX_CHUNKS_RX_CTR] = {"all_osmux:chunks_rx", "Inbound Osmux chunks."},
 | 
			
		||||
	[OSMUX_OCTETS_RX_CTR] = {"all_osmux:octets_rx", "Inbound Osmux octets."},
 | 
			
		||||
	[OSMUX_RTP_PACKETS_TX_CTR] = {"all_osmux:rtp_packets_tx", "Tx outbound RTP packets to encode as Osmux."},
 | 
			
		||||
	[OSMUX_RTP_PACKETS_TX_DROPPED_CTR] = {"all_osmux:rtp_packets_tx_dropped", "Dropped Tx outbound RTP packets to encode as Osmux."},
 | 
			
		||||
	[OSMUX_AMR_OCTETS_TX_CTR] = {"all_osmux:amr_octets_tx", "Tx outbound AMD payload octets."},
 | 
			
		||||
	/* These last counters below do not exist in per-connection stats, only here: */
 | 
			
		||||
	[OSMUX_NUM_CONNECTIONS] = {"all_osmux:num_closed_conns", "Total number of osmux connections closed."},
 | 
			
		||||
	[OSMUX_PACKETS_RX_CTR] = {"all_osmux:packets_rx", "Total inbound UDP/Osmux packets."},
 | 
			
		||||
	[OSMUX_PACKETS_TX_CTR] = {"all_osmux:packets_tx", "Total outbound UDP/Osmux packets."},
 | 
			
		||||
	[OSMUX_DROPPED_PACKETS_CTR] = {"all_osmux:dropped_packets", "Dropped outbound UDP/Osmux packets."}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Was conn configured to handle Osmux? */
 | 
			
		||||
static inline bool mgcp_conn_rtp_is_osmux(const struct mgcp_conn_rtp *conn) {
 | 
			
		||||
	return conn->type == MGCP_RTP_OSMUX;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Was conn configured to handle Osmux? */
 | 
			
		||||
static inline bool mgcp_conn_rtp_is_iuup(const struct mgcp_conn_rtp *conn)
 | 
			
		||||
{
 | 
			
		||||
	return conn->type == MGCP_RTP_IUUP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct mgcp_conn_rtp *mgcp_conn_get_conn_rtp(struct mgcp_conn *conn)
 | 
			
		||||
{
 | 
			
		||||
	OSMO_ASSERT(conn->type == MGCP_CONN_TYPE_RTP);
 | 
			
		||||
	return &conn->u.rtp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
 | 
			
		||||
				  enum mgcp_conn_type type, char *name);
 | 
			
		||||
void mgcp_conn_free(struct mgcp_conn *conn);
 | 
			
		||||
int mgcp_conn_set_mode(struct mgcp_conn *conn, enum mgcp_connection_mode mode);
 | 
			
		||||
struct mgcp_conn *mgcp_conn_get(struct mgcp_endpoint *endp, const char *id);
 | 
			
		||||
struct mgcp_conn_rtp *mgcp_conn_get_rtp(struct mgcp_endpoint *endp,
 | 
			
		||||
					const char *id);
 | 
			
		||||
void mgcp_conn_free(struct mgcp_endpoint *endp, const char *id);
 | 
			
		||||
void mgcp_conn_free_oldest(struct mgcp_endpoint *endp);
 | 
			
		||||
void mgcp_conn_free_all(struct mgcp_endpoint *endp);
 | 
			
		||||
char *mgcp_conn_dump(struct mgcp_conn *conn);
 | 
			
		||||
struct mgcp_conn *mgcp_find_dst_conn(struct mgcp_conn *conn);
 | 
			
		||||
void mgcp_conn_watchdog_kick(struct mgcp_conn *conn);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,27 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
/* A 64k timeslot on an E1 line can be subdevied into the following
 | 
			
		||||
 * subslot combinations:
 | 
			
		||||
 *
 | 
			
		||||
 * subslot:                                          offset:
 | 
			
		||||
 * [          ][          ][   16k    ][8k_subslot]  0
 | 
			
		||||
 * [          ][   32k    ][_subslot__][8k_subslot]  1
 | 
			
		||||
 * [          ][ subslot  ][   16k    ][8k_subslot]  2
 | 
			
		||||
 * [   64k    ][__________][_subslot__][8k_subslot]  3
 | 
			
		||||
 * [ timeslot ][          ][   16k    ][8k_subslot]  4
 | 
			
		||||
 * [          ][   32K    ][_subslot__][8k_subslot]  5
 | 
			
		||||
 * [          ][ subslot  ][   16k    ][8k_subslot]  6
 | 
			
		||||
 * [          ][          ][ subslot  ][8k_subslot]  7
 | 
			
		||||
 *
 | 
			
		||||
 * Since overlapping assignment of subslots is not possible there is a limited
 | 
			
		||||
 * set of subslot assignments possible. The e1_rates array lists the possible
 | 
			
		||||
 * assignments as depicted above. Also each subslot assignment comes along with
 | 
			
		||||
 * a bit offset in the E1 bitstream. The e1_offsets arrays lists the bit
 | 
			
		||||
 * offsets. */
 | 
			
		||||
static const uint8_t e1_rates[] = { 64, 32, 32, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8 };
 | 
			
		||||
static const uint8_t e1_offsets[] = { 0, 0, 4, 0, 2, 4, 6, 0, 1, 2, 3, 4, 5, 6, 7 };
 | 
			
		||||
 | 
			
		||||
int mgcp_e1_endp_equip(struct mgcp_endpoint *endp, uint8_t ts, uint8_t ss, uint8_t offs);
 | 
			
		||||
void mgcp_e1_endp_update(struct mgcp_endpoint *endp);
 | 
			
		||||
void mgcp_e1_endp_release(struct mgcp_endpoint *endp, uint8_t ts);
 | 
			
		||||
int mgcp_e1_send_rtp(struct mgcp_endpoint *endp, struct mgcp_rtp_codec *codec, struct msgb *msg);
 | 
			
		||||
@@ -1,157 +0,0 @@
 | 
			
		||||
/* Endpoint types */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Philipp Maier
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/msgb.h>
 | 
			
		||||
#include <osmocom/gsm/i460_mux.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_protocol.h>
 | 
			
		||||
 | 
			
		||||
struct sockaddr;
 | 
			
		||||
struct mgcp_conn;
 | 
			
		||||
struct mgcp_conn_rtp;
 | 
			
		||||
struct mgcp_endpoint;
 | 
			
		||||
 | 
			
		||||
/* Number of E1 subslots (different variants, not all useable at the same time) */
 | 
			
		||||
#define MGCP_ENDP_E1_SUBSLOTS 15
 | 
			
		||||
 | 
			
		||||
#define LOGPENDP(endp, cat, level, fmt, args...) \
 | 
			
		||||
LOGP(cat, level, "endpoint:%s " fmt, \
 | 
			
		||||
     endp ? endp->name : "none", \
 | 
			
		||||
     ## args)
 | 
			
		||||
 | 
			
		||||
enum rtp_proto {
 | 
			
		||||
	MGCP_PROTO_RTP,
 | 
			
		||||
	MGCP_PROTO_RTCP,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct osmo_rtp_msg_ctx {
 | 
			
		||||
	enum rtp_proto proto;
 | 
			
		||||
	struct mgcp_conn_rtp *conn_src;
 | 
			
		||||
	struct osmo_sockaddr *from_addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define OSMO_RTP_MSG_CTX(MSGB) ((struct osmo_rtp_msg_ctx*)(MSGB)->cb)
 | 
			
		||||
 | 
			
		||||
osmo_static_assert(sizeof(((struct msgb*)0)->cb) >= sizeof(struct osmo_rtp_msg_ctx), osmo_rtp_msg_ctx_fits_in_msgb_cb);
 | 
			
		||||
 | 
			
		||||
/* Callback type for RTP dispatcher functions (e.g mgcp_dispatch_rtp_bridge_cb, see below).
 | 
			
		||||
 * The OSMO_RTP_MSG_CTX() should be set appropriately on the msg. */
 | 
			
		||||
typedef int (*mgcp_dispatch_rtp_cb) (struct msgb *msg);
 | 
			
		||||
 | 
			
		||||
/* Callback type for endpoint specific cleanup actions. This function
 | 
			
		||||
 * is automatically executed when a connection is freed (see mgcp_conn_free()
 | 
			
		||||
 * in mgcp_conn.c). Depending on the type of the endpoint there may be endpoint
 | 
			
		||||
 * specific things to take care of once a connection has been removed. */
 | 
			
		||||
typedef void (*mgcp_cleanup_cp) (struct mgcp_endpoint *endp,
 | 
			
		||||
				 struct mgcp_conn *conn);
 | 
			
		||||
 | 
			
		||||
/*! MGCP endpoint properties */
 | 
			
		||||
struct mgcp_endpoint_type {
 | 
			
		||||
	/*! maximum number of connections */
 | 
			
		||||
	int max_conns;
 | 
			
		||||
 | 
			
		||||
	/*! callback that defines how to dispatch incoming RTP data */
 | 
			
		||||
	mgcp_dispatch_rtp_cb dispatch_rtp_cb;
 | 
			
		||||
 | 
			
		||||
	/*! callback that implements endpoint specific cleanup actions */
 | 
			
		||||
	mgcp_cleanup_cp cleanup_cb;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*! MGCP endpoint typeset */
 | 
			
		||||
struct mgcp_endpoint_typeset {
 | 
			
		||||
	struct mgcp_endpoint_type rtp;
 | 
			
		||||
	struct mgcp_endpoint_type e1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*! static MGCP endpoint typeset (pre-initalized, read-only) */
 | 
			
		||||
extern const struct mgcp_endpoint_typeset ep_typeset;
 | 
			
		||||
 | 
			
		||||
/*! MGCP endpoint model */
 | 
			
		||||
struct mgcp_endpoint {
 | 
			
		||||
 | 
			
		||||
	/*! Unique endpoint name, used for addressing via MGCP */
 | 
			
		||||
	char *name;
 | 
			
		||||
 | 
			
		||||
	/*! Call identifier string (as supplied by the call agant) */
 | 
			
		||||
	char *callid;
 | 
			
		||||
 | 
			
		||||
	/*! Local connection options (see mgcp_internal.h) */
 | 
			
		||||
	struct mgcp_lco local_options;
 | 
			
		||||
 | 
			
		||||
	/*! List of struct mgcp_conn, of the connections active on this endpoint */
 | 
			
		||||
	struct llist_head conns;
 | 
			
		||||
 | 
			
		||||
	/*! Backpointer to the trunk this endpoint belongs to */
 | 
			
		||||
	struct mgcp_trunk *trunk;
 | 
			
		||||
 | 
			
		||||
	/*! Endpoint properties (see above) */
 | 
			
		||||
	const struct mgcp_endpoint_type *type;
 | 
			
		||||
 | 
			
		||||
	/*! Last MGCP transmission (in case re-transmission is required) */
 | 
			
		||||
	char *last_trans;
 | 
			
		||||
 | 
			
		||||
	/*! Last MGCP response (in case re-transmission is required) */
 | 
			
		||||
	char *last_response;
 | 
			
		||||
 | 
			
		||||
	/*! MGCP_X_OSMO_IGN_* flags from 'X-Osmo-IGN:' header */
 | 
			
		||||
	uint32_t x_osmo_ign;
 | 
			
		||||
 | 
			
		||||
	/* E1 specific */
 | 
			
		||||
	struct {
 | 
			
		||||
		struct osmo_i460_schan_desc scd;
 | 
			
		||||
		struct osmo_i460_subchan *schan;
 | 
			
		||||
		struct osmo_fsm_inst *trau_sync_fi;
 | 
			
		||||
		struct osmo_trau2rtp_state *trau_rtp_st;
 | 
			
		||||
		uint8_t last_amr_ft;
 | 
			
		||||
		struct mgcp_rtp_codec *last_codec;
 | 
			
		||||
	} e1;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_endpoint *mgcp_endp_alloc(struct mgcp_trunk *trunk, unsigned int index);
 | 
			
		||||
int mgcp_endp_claim(struct mgcp_endpoint *endp, const char *callid);
 | 
			
		||||
void mgcp_endp_update(struct mgcp_endpoint *endp);
 | 
			
		||||
bool mgcp_endp_is_wildcarded(const char *epname);
 | 
			
		||||
bool mgcp_endp_is_null(const char *epname);
 | 
			
		||||
struct mgcp_endpoint *mgcp_endp_by_name_trunk(int *cause, const char *epname,
 | 
			
		||||
					      const struct mgcp_trunk *trunk);
 | 
			
		||||
struct mgcp_endpoint *mgcp_endp_by_name(int *cause, const char *epname,
 | 
			
		||||
					struct mgcp_config *cfg);
 | 
			
		||||
bool mgcp_endp_avail(const struct mgcp_endpoint *endp);
 | 
			
		||||
unsigned int mgcp_endp_num_conns(const struct mgcp_endpoint *endp);
 | 
			
		||||
bool mgcp_endp_is_full(const struct mgcp_endpoint *endp);
 | 
			
		||||
void mgcp_endp_add_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
 | 
			
		||||
void mgcp_endp_remove_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
 | 
			
		||||
void mgcp_endp_free_conn_oldest(struct mgcp_endpoint *endp);
 | 
			
		||||
void mgcp_endp_free_conn_all(struct mgcp_endpoint *endp);
 | 
			
		||||
void mgcp_endp_strip_name(char *epname_stripped, const char *epname,
 | 
			
		||||
			 const struct mgcp_trunk *trunk);
 | 
			
		||||
struct mgcp_endpoint *mgcp_endp_find_specific(const char *epname,
 | 
			
		||||
			const struct mgcp_trunk *trunk);
 | 
			
		||||
void mgcp_endp_release(struct mgcp_endpoint *endp);
 | 
			
		||||
 | 
			
		||||
struct mgcp_conn *mgcp_endp_get_conn(struct mgcp_endpoint *endp, const char *id);
 | 
			
		||||
struct mgcp_conn *mgcp_endp_get_conn_oldest(struct mgcp_endpoint *endp);
 | 
			
		||||
struct mgcp_conn_rtp *mgcp_endp_get_conn_rtp(struct mgcp_endpoint *endp,
 | 
			
		||||
					const char *id);
 | 
			
		||||
							
								
								
									
										50
									
								
								include/osmocom/mgcp/mgcp_ep.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								include/osmocom/mgcp/mgcp_ep.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/* Endpoint types */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Philipp Maier
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
struct sockaddr_in;
 | 
			
		||||
struct mgcp_conn;
 | 
			
		||||
 | 
			
		||||
/* Callback type for RTP dispatcher functions
 | 
			
		||||
   (e.g mgcp_dispatch_rtp_bridge_cb, see below) */
 | 
			
		||||
typedef int (*mgcp_dispatch_rtp_cb) (int proto, struct sockaddr_in * addr,
 | 
			
		||||
				     char *buf, unsigned int buf_size,
 | 
			
		||||
				     struct mgcp_conn * conn);
 | 
			
		||||
 | 
			
		||||
/*! MGCP endpoint properties */
 | 
			
		||||
struct mgcp_endpoint_type {
 | 
			
		||||
	/*!< maximum number of connections */
 | 
			
		||||
	int max_conns;
 | 
			
		||||
 | 
			
		||||
	/*!< callback that defines how to dispatch incoming RTP data */
 | 
			
		||||
	mgcp_dispatch_rtp_cb dispatch_rtp_cb;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*! MGCP endpoint typeset */
 | 
			
		||||
struct mgcp_endpoint_typeset {
 | 
			
		||||
	struct mgcp_endpoint_type rtp;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*! static MGCP endpoint typeset (pre-initalized, read-only) */
 | 
			
		||||
extern const struct mgcp_endpoint_typeset ep_typeset;
 | 
			
		||||
							
								
								
									
										323
									
								
								include/osmocom/mgcp/mgcp_internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								include/osmocom/mgcp/mgcp_internal.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,323 @@
 | 
			
		||||
/* MGCP Private Data */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
 | 
			
		||||
 * (C) 2009-2012 by On-Waves
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <osmocom/core/select.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp.h>
 | 
			
		||||
#include <osmocom/core/linuxlist.h>
 | 
			
		||||
 | 
			
		||||
#define CI_UNUSED 0
 | 
			
		||||
 | 
			
		||||
/* FIXME: This this is only needed to compile the currently
 | 
			
		||||
 * broken OSMUX support. Remove when fixed */
 | 
			
		||||
#define CONN_ID_BTS "0"
 | 
			
		||||
#define CONN_ID_NET "1"
 | 
			
		||||
 | 
			
		||||
enum mgcp_trunk_type {
 | 
			
		||||
	MGCP_TRUNK_VIRTUAL,
 | 
			
		||||
	MGCP_TRUNK_E1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_stream_state {
 | 
			
		||||
	uint32_t ssrc;
 | 
			
		||||
	uint16_t last_seq;
 | 
			
		||||
	uint32_t last_timestamp;
 | 
			
		||||
	uint32_t err_ts_counter;
 | 
			
		||||
	int32_t last_tsdelta;
 | 
			
		||||
	uint32_t last_arrival_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_state {
 | 
			
		||||
	int initialized;
 | 
			
		||||
	int patch_ssrc;
 | 
			
		||||
 | 
			
		||||
	uint32_t orig_ssrc;
 | 
			
		||||
 | 
			
		||||
	int seq_offset;
 | 
			
		||||
 | 
			
		||||
	int32_t  timestamp_offset;
 | 
			
		||||
	uint32_t packet_duration;
 | 
			
		||||
 | 
			
		||||
	struct mgcp_rtp_stream_state in_stream;
 | 
			
		||||
	struct mgcp_rtp_stream_state out_stream;
 | 
			
		||||
 | 
			
		||||
	/* jitter and packet loss calculation */
 | 
			
		||||
	int stats_initialized;
 | 
			
		||||
	uint16_t stats_base_seq;
 | 
			
		||||
	uint16_t stats_max_seq;
 | 
			
		||||
	uint32_t stats_ssrc;
 | 
			
		||||
	uint32_t stats_jitter;
 | 
			
		||||
	int32_t stats_transit;
 | 
			
		||||
	int stats_cycles;
 | 
			
		||||
	bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_codec {
 | 
			
		||||
	uint32_t rate;
 | 
			
		||||
	int channels;
 | 
			
		||||
	uint32_t frame_duration_num;
 | 
			
		||||
	uint32_t frame_duration_den;
 | 
			
		||||
 | 
			
		||||
	int payload_type;
 | 
			
		||||
	char *audio_name;
 | 
			
		||||
	char *subtype_name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_end {
 | 
			
		||||
	/* statistics */
 | 
			
		||||
	unsigned int packets_rx;
 | 
			
		||||
	unsigned int octets_rx;
 | 
			
		||||
	unsigned int packets_tx;
 | 
			
		||||
	unsigned int octets_tx;
 | 
			
		||||
	unsigned int dropped_packets;
 | 
			
		||||
	struct in_addr addr;
 | 
			
		||||
 | 
			
		||||
	/* in network byte order */
 | 
			
		||||
	int rtp_port, rtcp_port;
 | 
			
		||||
 | 
			
		||||
	/* audio codec information */
 | 
			
		||||
	struct mgcp_rtp_codec codec;
 | 
			
		||||
	struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */
 | 
			
		||||
 | 
			
		||||
	/* per endpoint data */
 | 
			
		||||
	int  frames_per_packet;
 | 
			
		||||
	uint32_t packet_duration_ms;
 | 
			
		||||
	char *fmtp_extra;
 | 
			
		||||
	int output_enabled;
 | 
			
		||||
	int force_output_ptime;
 | 
			
		||||
 | 
			
		||||
	/* RTP patching */
 | 
			
		||||
	int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
 | 
			
		||||
	int force_aligned_timing;
 | 
			
		||||
	void *rtp_process_data;
 | 
			
		||||
 | 
			
		||||
	/* Each end has a separate socket for RTP and RTCP */
 | 
			
		||||
	struct osmo_fd rtp;
 | 
			
		||||
	struct osmo_fd rtcp;
 | 
			
		||||
 | 
			
		||||
	int local_port;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_tap {
 | 
			
		||||
	int enabled;
 | 
			
		||||
	struct sockaddr_in forward;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_lco {
 | 
			
		||||
	char *string;
 | 
			
		||||
	char *codec;
 | 
			
		||||
	int pkt_period_min; /* time in ms */
 | 
			
		||||
	int pkt_period_max; /* time in ms */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Specific rtp connection type (see struct mgcp_conn_rtp) */
 | 
			
		||||
enum mgcp_conn_rtp_type {
 | 
			
		||||
	MGCP_RTP_DEFAULT	= 0,
 | 
			
		||||
	MGCP_OSMUX_BSC,
 | 
			
		||||
	MGCP_OSMUX_BSC_NAT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp/osmux.h>
 | 
			
		||||
struct mgcp_conn;
 | 
			
		||||
 | 
			
		||||
/* MGCP connection (RTP) */
 | 
			
		||||
struct mgcp_conn_rtp {
 | 
			
		||||
 | 
			
		||||
	/* Backpointer to conn struct */
 | 
			
		||||
	struct mgcp_conn *conn;
 | 
			
		||||
 | 
			
		||||
	/* Specific connection type */
 | 
			
		||||
	enum mgcp_conn_rtp_type type;
 | 
			
		||||
 | 
			
		||||
	/* Port status */
 | 
			
		||||
	struct mgcp_rtp_end end;
 | 
			
		||||
 | 
			
		||||
	/* Sequence bits */
 | 
			
		||||
	struct mgcp_rtp_state state;
 | 
			
		||||
 | 
			
		||||
	/* taps for the rtp connection */
 | 
			
		||||
	struct mgcp_rtp_tap tap_in;
 | 
			
		||||
	struct mgcp_rtp_tap tap_out;
 | 
			
		||||
 | 
			
		||||
	/* Osmux states (optional) */
 | 
			
		||||
	struct {
 | 
			
		||||
		/* Osmux state: disabled, activating, active */
 | 
			
		||||
		enum osmux_state state;
 | 
			
		||||
		/* Allocated Osmux circuit ID for this endpoint */
 | 
			
		||||
		int allocated_cid;
 | 
			
		||||
		/* Used Osmux circuit ID for this endpoint */
 | 
			
		||||
		uint8_t cid;
 | 
			
		||||
		/* handle to batch messages */
 | 
			
		||||
		struct osmux_in_handle *in;
 | 
			
		||||
		/* handle to unbatch messages */
 | 
			
		||||
		struct osmux_out_handle out;
 | 
			
		||||
		/* statistics */
 | 
			
		||||
		struct {
 | 
			
		||||
			uint32_t chunks;
 | 
			
		||||
			uint32_t octets;
 | 
			
		||||
		} stats;
 | 
			
		||||
	} osmux;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*! Connection type, specifies which member of the union "u" in mgcp_conn
 | 
			
		||||
 *  contains a useful connection description (currently only RTP) */
 | 
			
		||||
enum mgcp_conn_type {
 | 
			
		||||
	MGCP_CONN_TYPE_RTP,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*! MGCP connection (untyped) */
 | 
			
		||||
struct mgcp_conn {
 | 
			
		||||
	/*!< list head */
 | 
			
		||||
	struct llist_head entry;
 | 
			
		||||
 | 
			
		||||
	/*!< Backpointer to the endpoint where the conn belongs to */
 | 
			
		||||
	struct mgcp_endpoint *endp;
 | 
			
		||||
 | 
			
		||||
	/*!< type of the connection (union) */
 | 
			
		||||
	enum mgcp_conn_type type;
 | 
			
		||||
 | 
			
		||||
	/*!< mode of the connection */
 | 
			
		||||
	enum mgcp_connection_mode mode;
 | 
			
		||||
 | 
			
		||||
	/*!< copy of the mode to restore the original setting (VTY) */
 | 
			
		||||
	enum mgcp_connection_mode mode_orig;
 | 
			
		||||
 | 
			
		||||
	/*!< connection id to identify the conntion */
 | 
			
		||||
	char id[MGCP_CONN_ID_LENGTH];
 | 
			
		||||
 | 
			
		||||
	/*!< human readable name (vty, logging) */
 | 
			
		||||
	char name[256];
 | 
			
		||||
 | 
			
		||||
	/*!< union with connection description */
 | 
			
		||||
	union {
 | 
			
		||||
		struct mgcp_conn_rtp rtp;
 | 
			
		||||
	} u;
 | 
			
		||||
 | 
			
		||||
	/*!< pointer to optional private data */
 | 
			
		||||
	void *priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp/mgcp_conn.h>
 | 
			
		||||
 | 
			
		||||
struct mgcp_endpoint_type;
 | 
			
		||||
 | 
			
		||||
struct mgcp_endpoint {
 | 
			
		||||
	char *callid;
 | 
			
		||||
	struct mgcp_lco local_options;
 | 
			
		||||
 | 
			
		||||
	struct llist_head conns;
 | 
			
		||||
 | 
			
		||||
	/* backpointer */
 | 
			
		||||
	struct mgcp_config *cfg;
 | 
			
		||||
	struct mgcp_trunk_config *tcfg;
 | 
			
		||||
 | 
			
		||||
	const struct mgcp_endpoint_type *type;
 | 
			
		||||
 | 
			
		||||
	/* fields for re-transmission */
 | 
			
		||||
	char *last_trans;
 | 
			
		||||
	char *last_response;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Internal structure while parsing a request
 | 
			
		||||
 */
 | 
			
		||||
struct mgcp_parse_data {
 | 
			
		||||
	struct mgcp_config *cfg;
 | 
			
		||||
	struct mgcp_endpoint *endp;
 | 
			
		||||
	char *trans;
 | 
			
		||||
	char *save;
 | 
			
		||||
	int found;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
 | 
			
		||||
	      char *buf, int rc, struct mgcp_conn_rtp *conn_src,
 | 
			
		||||
	      struct mgcp_conn_rtp *conn_dst);
 | 
			
		||||
int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
 | 
			
		||||
int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr, char *buf,
 | 
			
		||||
				unsigned int buf_size, struct mgcp_conn *conn);
 | 
			
		||||
int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
 | 
			
		||||
			   struct mgcp_conn_rtp *conn);
 | 
			
		||||
void mgcp_free_rtp_port(struct mgcp_rtp_end *end);
 | 
			
		||||
 | 
			
		||||
/* For transcoding we need to manage an in and an output that are connected */
 | 
			
		||||
static inline int endp_back_channel(int endpoint)
 | 
			
		||||
{
 | 
			
		||||
	return endpoint + 60;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
 | 
			
		||||
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
 | 
			
		||||
 | 
			
		||||
void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
 | 
			
		||||
			 struct mgcp_rtp_end *rtp);
 | 
			
		||||
uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
 | 
			
		||||
				  struct mgcp_rtp_end *rtp);
 | 
			
		||||
 | 
			
		||||
/* payload processing default functions */
 | 
			
		||||
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
 | 
			
		||||
				char *data, int *len, int buf_size);
 | 
			
		||||
 | 
			
		||||
int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
 | 
			
		||||
				      struct mgcp_rtp_end *dst_end,
 | 
			
		||||
				      struct mgcp_rtp_end *src_end);
 | 
			
		||||
 | 
			
		||||
void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
 | 
			
		||||
					  int *payload_type,
 | 
			
		||||
					  const char**audio_name,
 | 
			
		||||
					  const char**fmtp_extra,
 | 
			
		||||
					  struct mgcp_conn_rtp *conn);
 | 
			
		||||
 | 
			
		||||
/* internal RTP Annex A counting */
 | 
			
		||||
void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
 | 
			
		||||
			const uint16_t seq, const int32_t transit,
 | 
			
		||||
			const uint32_t ssrc);
 | 
			
		||||
 | 
			
		||||
int mgcp_set_ip_tos(int fd, int tos);
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	MGCP_DEST_NET = 0,
 | 
			
		||||
	MGCP_DEST_BTS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MGCP_DUMMY_LOAD 0x23
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SDP related information
 | 
			
		||||
 */
 | 
			
		||||
/* Assume audio frame length of 20ms */
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
 | 
			
		||||
#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
 | 
			
		||||
 | 
			
		||||
#define PTYPE_UNDEFINED (-1)
 | 
			
		||||
 | 
			
		||||
void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn);
 | 
			
		||||
@@ -25,25 +25,21 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp/mgcp_common.h>
 | 
			
		||||
 | 
			
		||||
struct mgcp_conn;
 | 
			
		||||
struct mgcp_parse_data;
 | 
			
		||||
struct mgcp_endpoint;
 | 
			
		||||
struct mgcp_trunk;
 | 
			
		||||
 | 
			
		||||
void mgcp_disp_msg(unsigned char *message, unsigned int len, char *preamble);
 | 
			
		||||
 | 
			
		||||
enum mgcp_connection_mode mgcp_parse_conn_mode(const char *msg);
 | 
			
		||||
int mgcp_parse_conn_mode(const char *msg, struct mgcp_endpoint *endp,
 | 
			
		||||
			 struct mgcp_conn *conn);
 | 
			
		||||
 | 
			
		||||
int mgcp_parse_header(struct mgcp_parse_data *pdata, char *data);
 | 
			
		||||
int mgcp_parse_hdr_pars(struct mgcp_parse_data *pdata);
 | 
			
		||||
 | 
			
		||||
int mgcp_parse_osmux_cid(const char *line);
 | 
			
		||||
 | 
			
		||||
bool mgcp_check_param(const char *line);
 | 
			
		||||
int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line);
 | 
			
		||||
 | 
			
		||||
int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,125 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/socket.h>
 | 
			
		||||
#include <osmocom/core/osmo_io.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp/mgcp.h>
 | 
			
		||||
 | 
			
		||||
/* The following constant defines an RTP dummy payload that is used for
 | 
			
		||||
 * "UDP Hole Punching" (NAT) */
 | 
			
		||||
#define MGCP_DUMMY_LOAD 0x23
 | 
			
		||||
static const char rtp_dummy_payload[] = { MGCP_DUMMY_LOAD };
 | 
			
		||||
 | 
			
		||||
/* Check if the data in a given message buffer matches the rtp dummy payload
 | 
			
		||||
 * defined above */
 | 
			
		||||
#define mgcp_is_rtp_dummy_payload(msg) \
 | 
			
		||||
	(msgb_length(msg) == sizeof(rtp_dummy_payload) && \
 | 
			
		||||
	memcmp(msgb_data(msg), rtp_dummy_payload, sizeof(rtp_dummy_payload)) == 0)
 | 
			
		||||
 | 
			
		||||
#define RTP_BUF_SIZE	4096
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_stream_state {
 | 
			
		||||
	uint32_t ssrc;
 | 
			
		||||
	uint16_t last_seq;
 | 
			
		||||
	uint32_t last_timestamp;
 | 
			
		||||
	struct rate_ctr *err_ts_ctr;
 | 
			
		||||
	int32_t last_tsdelta;
 | 
			
		||||
	uint32_t last_arrival_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_state {
 | 
			
		||||
	/* has this state structure been initialized? */
 | 
			
		||||
	int initialized;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		/* are we patching the SSRC value? */
 | 
			
		||||
		bool patch_ssrc;
 | 
			
		||||
		/* original SSRC (to which we shall patch any different SSRC) */
 | 
			
		||||
		uint32_t orig_ssrc;
 | 
			
		||||
		/* offset to apply on the sequence number */
 | 
			
		||||
		int seq_offset;
 | 
			
		||||
		/* offset to apply on the timestamp number */
 | 
			
		||||
		int32_t timestamp_offset;
 | 
			
		||||
	} patch;
 | 
			
		||||
 | 
			
		||||
	/* duration of a packet (FIXME: in which unit?) */
 | 
			
		||||
	uint32_t packet_duration;
 | 
			
		||||
 | 
			
		||||
	/* Note: These states are not continuously updated, they serve as an
 | 
			
		||||
	 * information source to patch certain values in the RTP header. Do
 | 
			
		||||
	 * not use this state if constantly updated data about the RTP stream
 | 
			
		||||
	 * is needed. (see also mgcp_patch_and_count() */
 | 
			
		||||
	struct mgcp_rtp_stream_state in_stream;
 | 
			
		||||
	struct mgcp_rtp_stream_state out_stream;
 | 
			
		||||
 | 
			
		||||
	/* jitter and packet loss calculation */
 | 
			
		||||
	struct {
 | 
			
		||||
		int initialized;
 | 
			
		||||
		uint16_t base_seq;
 | 
			
		||||
		uint16_t max_seq;
 | 
			
		||||
		uint32_t ssrc;
 | 
			
		||||
		uint32_t jitter;
 | 
			
		||||
		int32_t transit;
 | 
			
		||||
		int cycles;
 | 
			
		||||
	} stats;
 | 
			
		||||
 | 
			
		||||
	/* Alternative values for RTP tx, in case no sufficient header
 | 
			
		||||
	 * information is available so the header needs to be generated
 | 
			
		||||
	 * locally (when just forwarding packets, the header of incoming
 | 
			
		||||
	 * data is just re-used) */
 | 
			
		||||
	uint16_t alt_rtp_tx_sequence;
 | 
			
		||||
	uint32_t alt_rtp_tx_ssrc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_tap {
 | 
			
		||||
	/* is this tap active (1) or not (0) */
 | 
			
		||||
	int enabled;
 | 
			
		||||
	/* IP/port to which we're forwarding the tapped data */
 | 
			
		||||
	struct osmo_sockaddr forward;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_conn;
 | 
			
		||||
 | 
			
		||||
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct osmo_sockaddr *addr,
 | 
			
		||||
	      struct msgb *msg, struct mgcp_conn_rtp *conn_src,
 | 
			
		||||
	      struct mgcp_conn_rtp *conn_dst);
 | 
			
		||||
int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
 | 
			
		||||
int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg);
 | 
			
		||||
void mgcp_cleanup_rtp_bridge_cb(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
 | 
			
		||||
int mgcp_dispatch_e1_bridge_cb(struct msgb *msg);
 | 
			
		||||
void mgcp_cleanup_e1_bridge_cb(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
 | 
			
		||||
int mgcp_conn_rtp_bind_rtp_ports(struct mgcp_conn_rtp *conn, int rtp_port);
 | 
			
		||||
void mgcp_patch_and_count(const struct mgcp_endpoint *endp,
 | 
			
		||||
			  struct mgcp_rtp_state *state,
 | 
			
		||||
			  struct mgcp_rtp_end *rtp_end,
 | 
			
		||||
			  struct osmo_sockaddr *addr, struct msgb *msg);
 | 
			
		||||
int mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn);
 | 
			
		||||
 | 
			
		||||
/* payload processing default functions */
 | 
			
		||||
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end, struct msgb *msg);
 | 
			
		||||
 | 
			
		||||
int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
 | 
			
		||||
				      struct mgcp_conn_rtp *conn_dst,
 | 
			
		||||
				      struct mgcp_conn_rtp *conn_src);
 | 
			
		||||
 | 
			
		||||
void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
 | 
			
		||||
					  const struct mgcp_rtp_codec **codec,
 | 
			
		||||
					  const char **fmtp_extra,
 | 
			
		||||
					  struct mgcp_conn_rtp *conn);
 | 
			
		||||
 | 
			
		||||
/* internal RTP Annex A counting */
 | 
			
		||||
void mgcp_rtp_annex_count(const struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
 | 
			
		||||
			const uint16_t seq, const int32_t transit,
 | 
			
		||||
			const uint32_t ssrc, const bool marker_bit);
 | 
			
		||||
 | 
			
		||||
void rtpconn_rate_ctr_add(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp,
 | 
			
		||||
				 int id, int inc);
 | 
			
		||||
void rtpconn_rate_ctr_inc(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp,
 | 
			
		||||
				 int id);
 | 
			
		||||
void forward_data_tap(struct osmo_io_fd *iofd, struct mgcp_rtp_tap *tap, struct msgb *msg);
 | 
			
		||||
uint32_t mgcp_get_current_ts(unsigned codec_rate);
 | 
			
		||||
 | 
			
		||||
int amr_oa_bwe_convert(struct mgcp_endpoint *endp, struct msgb *msg, bool target_is_oa);
 | 
			
		||||
@@ -1,96 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/core/socket.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_common.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_codec.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MGCP_PARSE_SDP_PTIME_UNSET (-1)
 | 
			
		||||
#define MGCP_PARSE_SDP_MAXPTIME_UNSET (-1)
 | 
			
		||||
#define MGCP_PARSE_SDP_RTP_PORT_UNSET (0)
 | 
			
		||||
 | 
			
		||||
struct mgcp_parse_sdp {
 | 
			
		||||
	int ptime;
 | 
			
		||||
	int maxptime;
 | 
			
		||||
	int rtp_port;
 | 
			
		||||
	struct osmo_sockaddr rem_addr; /* Only IP address, port is in rtp_port above */
 | 
			
		||||
	struct mgcp_rtp_codecset cset;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline void mgcp_parse_sdp_init(struct mgcp_parse_sdp *sdp)
 | 
			
		||||
{
 | 
			
		||||
	sdp->ptime = MGCP_PARSE_SDP_PTIME_UNSET;
 | 
			
		||||
	sdp->maxptime = MGCP_PARSE_SDP_MAXPTIME_UNSET;
 | 
			
		||||
	sdp->rtp_port = MGCP_PARSE_SDP_RTP_PORT_UNSET;
 | 
			
		||||
	sdp->rem_addr = (struct osmo_sockaddr){ .u.sa.sa_family = AF_UNSPEC };
 | 
			
		||||
	mgcp_codecset_reset(&sdp->cset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET (-2)
 | 
			
		||||
#define MGCP_PARSE_HDR_PARS_OSMUX_CID_WILDCARD (-1)
 | 
			
		||||
 | 
			
		||||
struct mgcp_parse_hdr_pars {
 | 
			
		||||
	const char *local_options;
 | 
			
		||||
	const char *callid;
 | 
			
		||||
	const char *connid;
 | 
			
		||||
	enum mgcp_connection_mode mode;
 | 
			
		||||
	int remote_osmux_cid;
 | 
			
		||||
	bool have_sdp;
 | 
			
		||||
	/*! MGCP_X_OSMO_IGN_* flags from 'X-Osmo-IGN:' header */
 | 
			
		||||
	uint32_t x_osmo_ign;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline void mgcp_parse_hdr_pars_init(struct mgcp_parse_hdr_pars *hpars)
 | 
			
		||||
{
 | 
			
		||||
	*hpars = (struct mgcp_parse_hdr_pars){
 | 
			
		||||
		.local_options = NULL,
 | 
			
		||||
		.callid = NULL,
 | 
			
		||||
		.connid = NULL,
 | 
			
		||||
		.mode = MGCP_CONN_NONE,
 | 
			
		||||
		.remote_osmux_cid = MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET,
 | 
			
		||||
		.have_sdp = false,
 | 
			
		||||
		.x_osmo_ign = 0,
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Internal structure while parsing a request */
 | 
			
		||||
struct mgcp_parse_data {
 | 
			
		||||
	struct mgcp_config *cfg;
 | 
			
		||||
	char *save;
 | 
			
		||||
	/* MGCP Header: */
 | 
			
		||||
	char *epname;
 | 
			
		||||
	char *trans;
 | 
			
		||||
	struct mgcp_parse_hdr_pars hpars;
 | 
			
		||||
	/* MGCP Body: */
 | 
			
		||||
	struct mgcp_parse_sdp sdp;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Local connection options */
 | 
			
		||||
struct mgcp_lco {
 | 
			
		||||
	char *string;
 | 
			
		||||
	char *codec;
 | 
			
		||||
	int pkt_period_min; /* time in ms */
 | 
			
		||||
	int pkt_period_max; /* time in ms */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
char *mgcp_debug_get_last_endpoint_name(void);
 | 
			
		||||
 | 
			
		||||
char *get_lco_identifier(const char *options);
 | 
			
		||||
int check_local_cx_options(void *ctx, const char *options);
 | 
			
		||||
 | 
			
		||||
struct mgcp_rtp_end;
 | 
			
		||||
struct mgcp_endpoint;
 | 
			
		||||
 | 
			
		||||
uint32_t mgcp_rtp_packet_duration(const struct mgcp_endpoint *endp,
 | 
			
		||||
				  const struct mgcp_rtp_end *rtp);
 | 
			
		||||
 | 
			
		||||
extern const struct value_string mgcp_connection_mode_strs[];
 | 
			
		||||
static inline const char *mgcp_cmode_name(enum mgcp_connection_mode mode)
 | 
			
		||||
{
 | 
			
		||||
	return get_value_string(mgcp_connection_mode_strs, mode);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,109 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
/* Global MCGP general rate counters */
 | 
			
		||||
enum {
 | 
			
		||||
	MGCP_GENERAL_RX_MSGS_TOTAL,
 | 
			
		||||
	MGCP_GENERAL_RX_MSGS_RETRANSMITTED,
 | 
			
		||||
	MGCP_GENERAL_RX_MSGS_HANDLED,
 | 
			
		||||
	MGCP_GENERAL_RX_MSGS_UNHANDLED,
 | 
			
		||||
	MGCP_GENERAL_RX_FAIL_MSG_PARSE,
 | 
			
		||||
	MGCP_GENERAL_RX_FAIL_NO_ENDPOINT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Trunk-global MCGP CRCX related rate counters */
 | 
			
		||||
enum {
 | 
			
		||||
	MGCP_CRCX_SUCCESS,
 | 
			
		||||
	MGCP_CRCX_FAIL_BAD_ACTION,
 | 
			
		||||
	MGCP_CRCX_FAIL_UNHANDLED_PARAM,
 | 
			
		||||
	MGCP_CRCX_FAIL_MISSING_CALLID,
 | 
			
		||||
	MGCP_CRCX_FAIL_INVALID_MODE,
 | 
			
		||||
	MGCP_CRCX_FAIL_LIMIT_EXCEEDED,
 | 
			
		||||
	MGCP_CRCX_FAIL_UNKNOWN_CALLID,
 | 
			
		||||
	MGCP_CRCX_FAIL_ALLOC_CONN,
 | 
			
		||||
	MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC,
 | 
			
		||||
	MGCP_CRCX_FAIL_START_RTP,
 | 
			
		||||
	MGCP_CRCX_FAIL_NO_OSMUX,
 | 
			
		||||
	MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS,
 | 
			
		||||
	MGCP_CRCX_FAIL_CODEC_NEGOTIATION,
 | 
			
		||||
	MGCP_CRCX_FAIL_BIND_PORT,
 | 
			
		||||
	MGCP_CRCX_FAIL_AVAIL,
 | 
			
		||||
	MGCP_CRCX_FAIL_CLAIM,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Trunk-global MCGP MDCX related rate counters */
 | 
			
		||||
enum {
 | 
			
		||||
	MGCP_MDCX_SUCCESS,
 | 
			
		||||
	MGCP_MDCX_FAIL_WILDCARD,
 | 
			
		||||
	MGCP_MDCX_FAIL_NO_CONN,
 | 
			
		||||
	MGCP_MDCX_FAIL_INVALID_CALLID,
 | 
			
		||||
	MGCP_MDCX_FAIL_INVALID_CONNID,
 | 
			
		||||
	MGCP_MDCX_FAIL_UNHANDLED_PARAM,
 | 
			
		||||
	MGCP_MDCX_FAIL_NO_CONNID,
 | 
			
		||||
	MGCP_MDCX_FAIL_CONN_NOT_FOUND,
 | 
			
		||||
	MGCP_MDCX_FAIL_INVALID_MODE,
 | 
			
		||||
	MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS,
 | 
			
		||||
	MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC,
 | 
			
		||||
	MGCP_MDCX_FAIL_START_RTP,
 | 
			
		||||
	MGCP_MDCX_FAIL_AVAIL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Trunk-global MCGP DLCX related rate counters */
 | 
			
		||||
enum {
 | 
			
		||||
	MGCP_DLCX_SUCCESS,
 | 
			
		||||
	MGCP_DLCX_FAIL_NO_CONN,
 | 
			
		||||
	MGCP_DLCX_FAIL_INVALID_CALLID,
 | 
			
		||||
	MGCP_DLCX_FAIL_INVALID_CONNID,
 | 
			
		||||
	MGCP_DLCX_FAIL_UNHANDLED_PARAM,
 | 
			
		||||
	MGCP_DLCX_FAIL_AVAIL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Trunk-global E1 related counters */
 | 
			
		||||
enum {
 | 
			
		||||
        E1_I460_TRAU_RX_FAIL_CTR,
 | 
			
		||||
        E1_I460_TRAU_TX_FAIL_CTR,
 | 
			
		||||
        E1_I460_TRAU_MUX_EMPTY_CTR,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* NOTE: When adding counters, also the dump_ratectr_* routines in vty.c must be updated. */
 | 
			
		||||
 | 
			
		||||
struct mgcp_ratectr_global {
 | 
			
		||||
	/* Rate counter group which contains stats for generic MGCP events. */
 | 
			
		||||
	struct rate_ctr_group *mgcp_general_ctr_group;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_ratectr_trunk {
 | 
			
		||||
	/* Rate counter group which contains stats for processed CRCX commands. */
 | 
			
		||||
	struct rate_ctr_group *mgcp_crcx_ctr_group;
 | 
			
		||||
	/* Rate counter group which contains stats for processed MDCX commands. */
 | 
			
		||||
	struct rate_ctr_group *mgcp_mdcx_ctr_group;
 | 
			
		||||
	/* Rate counter group which contains stats for processed DLCX commands. */
 | 
			
		||||
	struct rate_ctr_group *mgcp_dlcx_ctr_group;
 | 
			
		||||
	/* Rate counter group which aggregates stats of individual RTP connections. */
 | 
			
		||||
	struct rate_ctr_group *all_rtp_conn_stats;
 | 
			
		||||
	/* Rate counter group which aggregates stats of individual Osmux connections. */
 | 
			
		||||
	struct rate_ctr_group *all_osmux_conn_stats;
 | 
			
		||||
	/* Rate counter group which contains stats for E1 events (only valid for E1 trunks) */
 | 
			
		||||
	struct rate_ctr_group *e1_stats;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_config;
 | 
			
		||||
struct mgcp_trunk;
 | 
			
		||||
 | 
			
		||||
int mgcp_ratectr_global_alloc(struct mgcp_config *cfg);
 | 
			
		||||
void mgcp_ratectr_global_free(struct mgcp_config *cfg);
 | 
			
		||||
int mgcp_ratectr_trunk_alloc(struct mgcp_trunk *trunk);
 | 
			
		||||
void mgcp_ratectr_trunk_free(struct mgcp_trunk *trunk);
 | 
			
		||||
 | 
			
		||||
/* Trunk-global common stat items */
 | 
			
		||||
enum {
 | 
			
		||||
	TRUNK_STAT_ENDPOINTS_TOTAL,
 | 
			
		||||
	TRUNK_STAT_ENDPOINTS_USED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_stat_trunk {
 | 
			
		||||
	/* Stat item group which contains general status values of the trunk. */
 | 
			
		||||
	struct osmo_stat_item_group *common;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int mgcp_stat_trunk_alloc(struct mgcp_trunk *trunk);
 | 
			
		||||
void mgcp_stat_trunk_free(struct mgcp_trunk *trunk);
 | 
			
		||||
@@ -1,53 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/socket.h>
 | 
			
		||||
#include <osmocom/core/osmo_io.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp/mgcp.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_codec.h>
 | 
			
		||||
 | 
			
		||||
/* 'mgcp_rtp_end': basically a wrapper around the RTP+RTCP ports */
 | 
			
		||||
struct mgcp_rtp_end {
 | 
			
		||||
	struct mgcp_conn_rtp *conn_rtp; /* backpointer */
 | 
			
		||||
	/* remote IP address of the RTP socket */
 | 
			
		||||
	struct osmo_sockaddr addr;
 | 
			
		||||
 | 
			
		||||
	/* in network byte order */
 | 
			
		||||
	uint16_t rtcp_port;
 | 
			
		||||
 | 
			
		||||
	struct mgcp_rtp_codecset cset;
 | 
			
		||||
 | 
			
		||||
	/* per endpoint data */
 | 
			
		||||
	int  frames_per_packet;
 | 
			
		||||
	uint32_t packet_duration_ms;
 | 
			
		||||
	int maximum_packet_time; /* -1: not set */
 | 
			
		||||
	/* are we transmitting packets (true) or dropping (false) outbound packets */
 | 
			
		||||
	bool output_enabled;
 | 
			
		||||
	/* FIXME: This parameter can be set + printed, but is nowhere used! */
 | 
			
		||||
	int force_output_ptime;
 | 
			
		||||
 | 
			
		||||
	/* RTP patching */
 | 
			
		||||
	bool force_constant_ssrc;
 | 
			
		||||
	/* should we perform align_rtp_timestamp_offset() (1) or not (0) */
 | 
			
		||||
	int force_aligned_timing;
 | 
			
		||||
	bool rfc5993_hr_convert;
 | 
			
		||||
 | 
			
		||||
	/* Each end has a separate socket for RTP and RTCP */
 | 
			
		||||
	struct osmo_io_fd *rtp;
 | 
			
		||||
	struct osmo_io_fd *rtcp;
 | 
			
		||||
 | 
			
		||||
	/* local UDP port number of the RTP socket; RTCP is +1 */
 | 
			
		||||
	int local_port;
 | 
			
		||||
	/* where the endpoint RTP connection binds to, set during CRCX and
 | 
			
		||||
	 * possibly updated during MDCX */
 | 
			
		||||
	char local_addr[INET6_ADDRSTRLEN];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void mgcp_rtp_end_init(struct mgcp_rtp_end *end, struct mgcp_conn_rtp *conn_rtp);
 | 
			
		||||
void mgcp_rtp_end_cleanup(struct mgcp_rtp_end *end);
 | 
			
		||||
void mgcp_rtp_end_set_packet_duration_ms(struct mgcp_rtp_end *end, uint32_t packet_duration_ms);
 | 
			
		||||
bool mgcp_rtp_end_remote_addr_available(const struct mgcp_rtp_end *rtp_end);
 | 
			
		||||
void mgcp_rtp_end_free_port(struct mgcp_rtp_end *end);
 | 
			
		||||
@@ -21,10 +21,14 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <osmocom/mgcp/mgcp_sdp.h>
 | 
			
		||||
 | 
			
		||||
struct mgcp_parse_data;
 | 
			
		||||
int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
 | 
			
		||||
			struct mgcp_conn_rtp *conn,
 | 
			
		||||
			struct mgcp_parse_data *p);
 | 
			
		||||
 | 
			
		||||
int mgcp_parse_sdp_data(struct mgcp_parse_data *p);
 | 
			
		||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
 | 
			
		||||
			int payload_type, const char *audio_name);
 | 
			
		||||
 | 
			
		||||
int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
 | 
			
		||||
			    const struct mgcp_conn_rtp *conn, struct msgb *sdp,
 | 
			
		||||
 
 | 
			
		||||
@@ -24,12 +24,14 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp/mgcp_internal.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
void mgcp_format_stats(char *str, size_t str_len,  struct mgcp_conn *conn);
 | 
			
		||||
 | 
			
		||||
/* Exposed for test purposes only, do not use actively */
 | 
			
		||||
void calc_loss(struct mgcp_conn_rtp *conn, uint32_t *expected, int *loss);
 | 
			
		||||
void calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
 | 
			
		||||
			uint32_t *expected, int *loss);
 | 
			
		||||
 | 
			
		||||
/* Exposed for test purposes only, do not use actively */
 | 
			
		||||
uint32_t calc_jitter(struct mgcp_rtp_state *);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,52 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2021 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Eric Wild
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdatomic.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
struct spsc {
 | 
			
		||||
	atomic_uint readptr;
 | 
			
		||||
	atomic_uint writeptr;
 | 
			
		||||
 | 
			
		||||
	int efd_r, efd_w; /* eventfds used to block/notify readers/writers */
 | 
			
		||||
 | 
			
		||||
	int count;
 | 
			
		||||
	int size_per_buf;
 | 
			
		||||
 | 
			
		||||
	void *buf; /* buffer size count*size_per_buf */
 | 
			
		||||
	uintptr_t data[0]; /* count sized array of pointers to size_per_buf chunks in buf array*/
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct qchan {
 | 
			
		||||
	struct spsc *a;
 | 
			
		||||
	struct spsc *b;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool spsc_push(struct spsc *q, void *elem);
 | 
			
		||||
bool spsc_pop(struct spsc *q, void *elem);
 | 
			
		||||
ssize_t spsc_prep_pop(struct spsc *q);
 | 
			
		||||
int spsc_get_a_rdfd(struct qchan *q);
 | 
			
		||||
 | 
			
		||||
struct qchan spsc_chan_init(void *talloc_ctx, unsigned int count, unsigned int size_per_buf);
 | 
			
		||||
struct qchan spsc_chan_init_ex(void *talloc_ctx, unsigned int count, unsigned int size_per_buf, bool blockr_a,
 | 
			
		||||
			       bool blockw_a, bool blockr_b, bool blockw_b);
 | 
			
		||||
void spsc_chan_close(struct qchan *q);
 | 
			
		||||
@@ -1,87 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/gsm/i460_mux.h>
 | 
			
		||||
#include <osmocom/abis/e1_input.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_conn.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_network.h>
 | 
			
		||||
#include <osmocom/mgcp/mgcp_ratectr.h>
 | 
			
		||||
 | 
			
		||||
#define LOGPTRUNK(trunk, cat, level, fmt, args...) \
 | 
			
		||||
LOGP(cat, level, "trunk:%u " fmt, \
 | 
			
		||||
     trunk ? trunk->trunk_nr : 0, \
 | 
			
		||||
     ## args)
 | 
			
		||||
 | 
			
		||||
enum mgcp_trunk_type {
 | 
			
		||||
	MGCP_TRUNK_VIRTUAL,
 | 
			
		||||
	MGCP_TRUNK_E1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const struct value_string mgcp_trunk_type_strs[];
 | 
			
		||||
static inline const char *mgcp_trunk_type_strs_str(enum mgcp_trunk_type val)
 | 
			
		||||
{ return get_value_string(mgcp_trunk_type_strs, val); }
 | 
			
		||||
 | 
			
		||||
struct mgcp_trunk {
 | 
			
		||||
	struct llist_head entry;
 | 
			
		||||
 | 
			
		||||
	struct mgcp_config *cfg;
 | 
			
		||||
 | 
			
		||||
	unsigned int trunk_nr;
 | 
			
		||||
	enum mgcp_trunk_type trunk_type;
 | 
			
		||||
 | 
			
		||||
	int audio_send_ptime;
 | 
			
		||||
	int audio_send_name;
 | 
			
		||||
 | 
			
		||||
	int omit_rtcp;
 | 
			
		||||
	int keepalive_interval;
 | 
			
		||||
 | 
			
		||||
	/* RTP patching */
 | 
			
		||||
	bool force_constant_ssrc;
 | 
			
		||||
	int force_aligned_timing;
 | 
			
		||||
	bool rfc5993_hr_convert;
 | 
			
		||||
 | 
			
		||||
	/* spec handling */
 | 
			
		||||
	int force_realloc;
 | 
			
		||||
 | 
			
		||||
	/* timer */
 | 
			
		||||
	struct osmo_timer_list keepalive_timer;
 | 
			
		||||
 | 
			
		||||
	/* When set, incoming RTP packets are not filtered
 | 
			
		||||
	 * when ports and ip-address do not match (debug) */
 | 
			
		||||
	int rtp_accept_all;
 | 
			
		||||
 | 
			
		||||
	unsigned int number_endpoints;
 | 
			
		||||
	struct mgcp_endpoint **endpoints;
 | 
			
		||||
 | 
			
		||||
	/* rate counters and stat items to measure the trunks overall performance and health */
 | 
			
		||||
	struct mgcp_ratectr_trunk ratectr;
 | 
			
		||||
	struct mgcp_stat_trunk stats;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		/* Virtual trunk specific */
 | 
			
		||||
		struct {
 | 
			
		||||
			unsigned int vty_number_endpoints;
 | 
			
		||||
		} v;
 | 
			
		||||
		/* E1 specific */
 | 
			
		||||
		struct {
 | 
			
		||||
			unsigned int vty_line_nr;
 | 
			
		||||
			uint8_t ts_usecount[NUM_E1_TS-1];
 | 
			
		||||
			struct osmo_i460_timeslot i460_ts[NUM_E1_TS-1];
 | 
			
		||||
			/* Note: on an E1 line TS 0 is devoted to framing and
 | 
			
		||||
			 * alignment and therefore only NUM_E1_TS-1 timeslots
 | 
			
		||||
			 * are available for traffic. */
 | 
			
		||||
		} e1;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_type ttype, unsigned int nr);
 | 
			
		||||
int mgcp_trunk_equip(struct mgcp_trunk *trunk);
 | 
			
		||||
struct mgcp_trunk *mgcp_trunk_by_num(const struct mgcp_config *cfg, enum mgcp_trunk_type ttype, unsigned int nr);
 | 
			
		||||
struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char *epname);
 | 
			
		||||
int e1_trunk_nr_from_epname(unsigned int *trunk_nr, const char *epname);
 | 
			
		||||
struct mgcp_trunk *mgcp_trunk_by_line_num(const struct mgcp_config *cfg, unsigned int num);
 | 
			
		||||
int mgcp_trunk_allocate_conn_rtp_ports(struct mgcp_trunk *trunk, struct mgcp_conn_rtp *conn_rtp);
 | 
			
		||||
 | 
			
		||||
/* The virtual trunk is always created on trunk id 0 for historical reasons,
 | 
			
		||||
 * use this define constant as ID when allocating a virtual trunk. Other
 | 
			
		||||
 * trunks may be assigned with arbritrary id numbers */
 | 
			
		||||
#define MGCP_VIRT_TRUNK_ID 0
 | 
			
		||||
@@ -1,41 +1,38 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/socket.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/netif/osmux.h>
 | 
			
		||||
struct mgcp_conn_rtp;
 | 
			
		||||
struct mgcp_trunk;
 | 
			
		||||
struct mgcp_endpoint;
 | 
			
		||||
struct mgcp_conn_rtp;
 | 
			
		||||
 | 
			
		||||
int osmux_init(struct mgcp_trunk *trunk);
 | 
			
		||||
int osmux_init_conn(struct mgcp_conn_rtp *conn);
 | 
			
		||||
int conn_osmux_enable(struct mgcp_conn_rtp *conn);
 | 
			
		||||
void conn_osmux_disable(struct mgcp_conn_rtp *conn);
 | 
			
		||||
int conn_osmux_event_rx_crcx_mdcx(struct mgcp_conn_rtp *conn);
 | 
			
		||||
int conn_osmux_send_rtp(struct mgcp_conn_rtp *conn, struct msgb *msg);
 | 
			
		||||
int osmux_send_dummy(struct mgcp_conn_rtp *conn);
 | 
			
		||||
#define OSMUX_PORT	1984
 | 
			
		||||
 | 
			
		||||
void osmux_cid_pool_get(uint8_t osmux_cid);
 | 
			
		||||
int osmux_cid_pool_get_next(void);
 | 
			
		||||
void osmux_cid_pool_put(uint8_t osmux_cid);
 | 
			
		||||
bool osmux_cid_pool_allocated(uint8_t osmux_cid);
 | 
			
		||||
int osmux_cid_pool_count_used(void);
 | 
			
		||||
 | 
			
		||||
enum osmux_state {
 | 
			
		||||
	OSMUX_STATE_DISABLED = 0, /* Osmux not being currently used by endp */
 | 
			
		||||
	OSMUX_STATE_ACTIVATING,   /* Osmux was accepted in MGCP CRCX ACK. It can now be enabled by \ref conn_osmux_enable. */
 | 
			
		||||
	OSMUX_STATE_ENABLED,	  /* Osmux was initialized by \ref conn_osmux_enable and can process frames */
 | 
			
		||||
enum {
 | 
			
		||||
	OSMUX_ROLE_BSC = 0,
 | 
			
		||||
	OSMUX_ROLE_BSC_NAT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const struct value_string osmux_state_strs[];
 | 
			
		||||
static inline const char *osmux_state_str(enum osmux_state val)
 | 
			
		||||
{ return get_value_string(osmux_state_strs, val); }
 | 
			
		||||
int osmux_init(int role, struct mgcp_config *cfg);
 | 
			
		||||
int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
 | 
			
		||||
		      struct in_addr *addr, uint16_t port);
 | 
			
		||||
void osmux_disable_conn(struct mgcp_conn_rtp *conn);
 | 
			
		||||
void osmux_allocate_cid(struct mgcp_conn_rtp *conn);
 | 
			
		||||
void osmux_release_cid(struct mgcp_conn_rtp *conn);
 | 
			
		||||
int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn);
 | 
			
		||||
int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
 | 
			
		||||
int osmux_get_cid(void);
 | 
			
		||||
void osmux_put_cid(uint8_t osmux_cid);
 | 
			
		||||
int osmux_used_cid(void);
 | 
			
		||||
 | 
			
		||||
enum osmux_state {
 | 
			
		||||
	OSMUX_STATE_DISABLED = 0,
 | 
			
		||||
	OSMUX_STATE_NEGOTIATING,
 | 
			
		||||
	OSMUX_STATE_ACTIVATING,
 | 
			
		||||
	OSMUX_STATE_ENABLED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum osmux_usage {
 | 
			
		||||
	OSMUX_USAGE_OFF = 0,
 | 
			
		||||
	OSMUX_USAGE_ON = 1,
 | 
			
		||||
	OSMUX_USAGE_ONLY = 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,31 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#ifndef OPENBSC_VTY_H
 | 
			
		||||
#define OPENBSC_VTY_H
 | 
			
		||||
 | 
			
		||||
#include <osmocom/vty/vty.h>
 | 
			
		||||
#include <osmocom/vty/buffer.h>
 | 
			
		||||
#include <osmocom/vty/command.h>
 | 
			
		||||
 | 
			
		||||
struct gsm_network;
 | 
			
		||||
struct vty;
 | 
			
		||||
 | 
			
		||||
void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
 | 
			
		||||
 | 
			
		||||
struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
 | 
			
		||||
 | 
			
		||||
extern struct cmd_element cfg_description_cmd;
 | 
			
		||||
extern struct cmd_element cfg_no_description_cmd;
 | 
			
		||||
 | 
			
		||||
enum mgcp_vty_node {
 | 
			
		||||
	MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
 | 
			
		||||
	TRUNK_NODE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum mgw_vty_cmd_attr {
 | 
			
		||||
	MGW_CMD_ATTR_NEWCONN = 0,
 | 
			
		||||
};
 | 
			
		||||
struct log_info;
 | 
			
		||||
int bsc_vty_init(struct gsm_network *network);
 | 
			
		||||
int bsc_vty_init_extra(void);
 | 
			
		||||
 | 
			
		||||
void msc_vty_init(struct gsm_network *msc_network);
 | 
			
		||||
 | 
			
		||||
struct gsm_network *gsmnet_from_vty(struct vty *vty);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@ BUILT_SOURCES = \
 | 
			
		||||
 | 
			
		||||
noinst_HEADERS = \
 | 
			
		||||
	mgcp_client_internal.h \
 | 
			
		||||
	mgcp_client_pool_internal.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
mgcp_common.h: $(top_srcdir)/include/osmocom/mgcp/mgcp_common.h
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
#include <osmocom/core/defs.h>
 | 
			
		||||
 | 
			
		||||
#if BUILDING_LIBOSMOMGCPCLIENT
 | 
			
		||||
# define OSMO_DEPRECATED_OUTSIDE_LIBOSMOMGCPCLIENT(text)
 | 
			
		||||
#else
 | 
			
		||||
# define OSMO_DEPRECATED_OUTSIDE_LIBOSMOMGCPCLIENT(text) OSMO_DEPRECATED(text)
 | 
			
		||||
#endif
 | 
			
		||||
@@ -3,16 +3,12 @@
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp_client/defs.h>
 | 
			
		||||
#include <osmocom/mgcp_client/mgcp_common.h>
 | 
			
		||||
 | 
			
		||||
/* See also: RFC 3435, chapter 3.5 Transmission over UDP */
 | 
			
		||||
#define MGCP_CLIENT_LOCAL_ADDR_DEFAULT NULL /* INADDR(6)_ANY */
 | 
			
		||||
#define MGCP_CLIENT_LOCAL_ADDR_DEFAULT "0.0.0.0"
 | 
			
		||||
#define MGCP_CLIENT_LOCAL_PORT_DEFAULT 0
 | 
			
		||||
#define MGCP_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1"
 | 
			
		||||
#define MGCP_CLIENT_REMOTE_PORT_DEFAULT 2427
 | 
			
		||||
#define MGCP_CLIENT_KEEPALIVE_DEFAULT_ENDP "null"
 | 
			
		||||
#define MGCP_CLIENT_MGW_STR "Configure MGCP connection to Media Gateway\n"
 | 
			
		||||
 | 
			
		||||
struct msgb;
 | 
			
		||||
struct vty;
 | 
			
		||||
@@ -23,63 +19,26 @@ struct mgcp_client_conf {
 | 
			
		||||
	int local_port;
 | 
			
		||||
	const char *remote_addr;
 | 
			
		||||
	int remote_port;
 | 
			
		||||
 | 
			
		||||
	/* By default, we are always addressing the MGW with e.g. 'rtpbridge/123@mgw'.
 | 
			
		||||
	 * If this is nonempty, the contained name will be used instead of 'mgw'. */
 | 
			
		||||
	char endpoint_domain_name[MGCP_ENDPOINT_MAXLEN];
 | 
			
		||||
 | 
			
		||||
	/* The user may configure certain endpoint names that are reset via DLCX
 | 
			
		||||
	 * on startup. Usually this will be one wildcarded endpoint e.g.
 | 
			
		||||
	 * 'rtpbridge/(wildcard)' or a number of specific E1 like e.g.
 | 
			
		||||
	 * 'ds/e1-0/s-3/su16-4' */
 | 
			
		||||
	struct llist_head reset_epnames;
 | 
			
		||||
 | 
			
		||||
	/* human readable name / description */
 | 
			
		||||
	char *description;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		uint32_t timeout_sec;
 | 
			
		||||
		uint32_t req_interval_sec;
 | 
			
		||||
		char req_endpoint_name[MGCP_ENDPOINT_MAXLEN];
 | 
			
		||||
	} keepalive;
 | 
			
		||||
	uint16_t first_endpoint;
 | 
			
		||||
	uint16_t last_endpoint;
 | 
			
		||||
	uint16_t bts_base;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef unsigned int mgcp_trans_id_t;
 | 
			
		||||
 | 
			
		||||
/*! Enumeration of the codec types that mgcp_client is able to handle. */
 | 
			
		||||
enum mgcp_codecs {
 | 
			
		||||
	CODEC_PCMU_8000_1 = 0,
 | 
			
		||||
	CODEC_GSM_8000_1 = 3,
 | 
			
		||||
	CODEC_PCMA_8000_1 = 8,
 | 
			
		||||
	CODEC_G729_8000_1 = 18,
 | 
			
		||||
	CODEC_GSMEFR_8000_1 = 110,	/* 3GPP TS 48.103 table 5.4.2.2.1 */
 | 
			
		||||
	CODEC_GSMHR_8000_1 = 111,	/* 3GPP TS 48.103 table 5.4.2.2.1 */
 | 
			
		||||
	CODEC_AMR_8000_1 = 112,		/* 3GPP TS 48.103 table 5.4.2.2.1 */
 | 
			
		||||
	CODEC_AMRWB_16000_1 = 113,	/* 3GPP TS 48.103 table 5.4.2.2.1 */
 | 
			
		||||
	CODEC_IUFP = 96,
 | 
			
		||||
	CODEC_CLEARMODE = 120,		/* 3GPP TS 48.103 table 5.4.2.2.1 */
 | 
			
		||||
};
 | 
			
		||||
/* Note: when new codec types are added, the corresponding value strings
 | 
			
		||||
 * in mgcp_client.c (codec_table) must be updated as well. Enumerations
 | 
			
		||||
 * in enum mgcp_codecs must correspond to a valid payload type. However,
 | 
			
		||||
 * this is an internal assumption that is made to avoid lookup tables.
 | 
			
		||||
 * The API-User should not rely on this coincidence! */
 | 
			
		||||
 | 
			
		||||
extern const struct value_string osmo_mgcpc_codec_names[];
 | 
			
		||||
static inline const char *osmo_mgcpc_codec_name(enum mgcp_codecs val)
 | 
			
		||||
{ return get_value_string(osmo_mgcpc_codec_names, val); }
 | 
			
		||||
 | 
			
		||||
/*! Structure to build a payload type map to allow the defiition custom payload
 | 
			
		||||
 *  types. */
 | 
			
		||||
struct ptmap {
 | 
			
		||||
	/*! codec for which a payload type number should be defined */
 | 
			
		||||
	enum mgcp_codecs codec;
 | 
			
		||||
 | 
			
		||||
	/*! payload type number (96-127) */
 | 
			
		||||
	unsigned int pt;
 | 
			
		||||
struct mgcp_response_head {
 | 
			
		||||
	int response_code;
 | 
			
		||||
	mgcp_trans_id_t trans_id;
 | 
			
		||||
	const char *comment;
 | 
			
		||||
	char conn_id[MGCP_CONN_ID_LENGTH];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int ptmap_cmp(const struct ptmap *a, const struct ptmap *b);
 | 
			
		||||
struct mgcp_response {
 | 
			
		||||
	char *body;
 | 
			
		||||
	struct mgcp_response_head head;
 | 
			
		||||
	uint16_t audio_port;
 | 
			
		||||
	char audio_ip[INET_ADDRSTRLEN];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum mgcp_verb {
 | 
			
		||||
	MGCP_VERB_CRCX,
 | 
			
		||||
@@ -89,8 +48,29 @@ enum mgcp_verb {
 | 
			
		||||
	MGCP_VERB_RSIP,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_client_conf *mgcp_client_conf_alloc(void *ctx);
 | 
			
		||||
void mgcp_client_conf_init(struct mgcp_client_conf *conf) OSMO_DEPRECATED_OUTSIDE_LIBOSMOMGCPCLIENT("use mgcp_client_conf_alloc() (or even better, switch to the mgcp_client_pool API!)");
 | 
			
		||||
#define MGCP_MSG_PRESENCE_ENDPOINT	0x0001
 | 
			
		||||
#define MGCP_MSG_PRESENCE_CALL_ID	0x0002
 | 
			
		||||
#define MGCP_MSG_PRESENCE_CONN_ID	0x0004
 | 
			
		||||
#define MGCP_MSG_PRESENCE_AUDIO_IP	0x0008
 | 
			
		||||
#define MGCP_MSG_PRESENCE_AUDIO_PORT	0x0010
 | 
			
		||||
#define MGCP_MSG_PRESENCE_CONN_MODE	0x0020
 | 
			
		||||
 | 
			
		||||
/* See also RFC3435 section 3.2.1.3 */
 | 
			
		||||
#define MGCP_ENDPOINT_MAXLEN (255*2+1+1)
 | 
			
		||||
 | 
			
		||||
struct mgcp_msg {
 | 
			
		||||
	enum mgcp_verb verb;
 | 
			
		||||
	/* See MGCP_MSG_PRESENCE_* constants */
 | 
			
		||||
	uint32_t presence;
 | 
			
		||||
	char endpoint[MGCP_ENDPOINT_MAXLEN];
 | 
			
		||||
	unsigned int call_id;
 | 
			
		||||
	char *conn_id;
 | 
			
		||||
	uint16_t audio_port;
 | 
			
		||||
	char *audio_ip;
 | 
			
		||||
	enum mgcp_connection_mode conn_mode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void mgcp_client_conf_init(struct mgcp_client_conf *conf);
 | 
			
		||||
void mgcp_client_vty_init(void *talloc_ctx, int node, struct mgcp_client_conf *conf);
 | 
			
		||||
int mgcp_client_config_write(struct vty *vty, const char *indent);
 | 
			
		||||
struct mgcp_client_conf *mgcp_client_conf_actual(struct mgcp_client *mgcp);
 | 
			
		||||
@@ -98,30 +78,44 @@ struct mgcp_client_conf *mgcp_client_conf_actual(struct mgcp_client *mgcp);
 | 
			
		||||
struct mgcp_client *mgcp_client_init(void *ctx,
 | 
			
		||||
				     struct mgcp_client_conf *conf);
 | 
			
		||||
int mgcp_client_connect(struct mgcp_client *mgcp);
 | 
			
		||||
int mgcp_client_connect2(struct mgcp_client *mgcp, unsigned int retry_n_ports) OSMO_DEPRECATED("Use mgcp_client_connect() instead");
 | 
			
		||||
void mgcp_client_disconnect(struct mgcp_client *mgcp);
 | 
			
		||||
 | 
			
		||||
const char *mgcp_client_remote_addr_str(struct mgcp_client *mgcp);
 | 
			
		||||
uint16_t mgcp_client_remote_port(struct mgcp_client *mgcp);
 | 
			
		||||
uint32_t mgcp_client_remote_addr_n(struct mgcp_client *mgcp) OSMO_DEPRECATED("deprecated, returns 0");
 | 
			
		||||
uint32_t mgcp_client_remote_addr_n(struct mgcp_client *mgcp);
 | 
			
		||||
 | 
			
		||||
const char *mgcp_client_endpoint_domain(const struct mgcp_client *mgcp);
 | 
			
		||||
const char *mgcp_client_rtpbridge_wildcard(const struct mgcp_client *mgcp);
 | 
			
		||||
const char *mgcp_client_e1_epname(void *ctx, const struct mgcp_client *mgcp, uint8_t trunk_id, uint8_t ts,
 | 
			
		||||
				  uint8_t rate, uint8_t offset);
 | 
			
		||||
int mgcp_client_next_endpoint(struct mgcp_client *client);
 | 
			
		||||
void mgcp_client_release_endpoint(uint16_t id, struct mgcp_client *client);
 | 
			
		||||
 | 
			
		||||
/* Invoked when an MGCP response is received or sending failed.  When the
 | 
			
		||||
 * response is passed as NULL, this indicates failure during transmission. */
 | 
			
		||||
typedef void (* mgcp_response_cb_t )(struct mgcp_response *response, void *priv);
 | 
			
		||||
int mgcp_response_parse_params(struct mgcp_response *r);
 | 
			
		||||
 | 
			
		||||
int mgcp_client_tx(struct mgcp_client *mgcp, struct msgb *msg,
 | 
			
		||||
		   mgcp_response_cb_t response_cb, void *priv);
 | 
			
		||||
int mgcp_client_cancel(struct mgcp_client *mgcp, mgcp_trans_id_t trans_id);
 | 
			
		||||
 | 
			
		||||
enum mgcp_connection_mode;
 | 
			
		||||
 | 
			
		||||
struct msgb *mgcp_msg_crcx(struct mgcp_client *mgcp,
 | 
			
		||||
			   uint16_t rtp_endpoint, unsigned int call_id,
 | 
			
		||||
			   enum mgcp_connection_mode mode)
 | 
			
		||||
OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
 | 
			
		||||
 | 
			
		||||
struct msgb *mgcp_msg_mdcx(struct mgcp_client *mgcp,
 | 
			
		||||
			   uint16_t rtp_endpoint, const char *rtp_conn_addr,
 | 
			
		||||
			   uint16_t rtp_port, enum mgcp_connection_mode mode)
 | 
			
		||||
OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
 | 
			
		||||
 | 
			
		||||
struct msgb *mgcp_msg_dlcx(struct mgcp_client *mgcp, uint16_t rtp_endpoint,
 | 
			
		||||
			   unsigned int call_id)
 | 
			
		||||
OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
 | 
			
		||||
 | 
			
		||||
struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg);
 | 
			
		||||
mgcp_trans_id_t mgcp_msg_trans_id(struct msgb *msg);
 | 
			
		||||
 | 
			
		||||
extern const struct value_string mgcp_client_connection_mode_strs[];
 | 
			
		||||
static inline const char *mgcp_client_cmode_name(enum mgcp_connection_mode mode)
 | 
			
		||||
{
 | 
			
		||||
	return get_value_string(mgcp_client_connection_mode_strs, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum mgcp_codecs map_str_to_codec(const char *str);
 | 
			
		||||
unsigned int map_codec_to_pt(const struct ptmap *ptmap, unsigned int ptmap_len,
 | 
			
		||||
			     enum mgcp_codecs codec);
 | 
			
		||||
enum mgcp_codecs map_pt_to_codec(struct ptmap *ptmap, unsigned int ptmap_len,
 | 
			
		||||
				 unsigned int pt);
 | 
			
		||||
 | 
			
		||||
const char *mgcp_client_name(const struct mgcp_client *mgcp);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,55 +0,0 @@
 | 
			
		||||
/* FSM to manage multiple connections of an MGW endpoint */
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp_client/mgcp_client_fsm.h>
 | 
			
		||||
 | 
			
		||||
#define LOG_MGCPC_EP(ep, level, fmt, args...) do { \
 | 
			
		||||
	LOGPFSML(ep->fi, level, "%s " fmt, \
 | 
			
		||||
		 osmo_mgcpc_ep_name(ep), ## args); \
 | 
			
		||||
	} while(0)
 | 
			
		||||
 | 
			
		||||
struct osmo_mgcpc_ep;
 | 
			
		||||
struct osmo_mgcpc_ep_ci;
 | 
			
		||||
struct osmo_tdef;
 | 
			
		||||
 | 
			
		||||
struct osmo_mgcpc_ep *osmo_mgcpc_ep_alloc(struct osmo_fsm_inst *parent, uint32_t parent_term_event,
 | 
			
		||||
					  struct mgcp_client *mgcp_client,
 | 
			
		||||
					  const struct osmo_tdef *T_defs,
 | 
			
		||||
					  const char *fsm_id,
 | 
			
		||||
					  const char *endpoint_str_fmt, ...);
 | 
			
		||||
 | 
			
		||||
struct osmo_mgcpc_ep_ci *osmo_mgcpc_ep_ci_add(struct osmo_mgcpc_ep *ep, const char *label_fmt, ...);
 | 
			
		||||
const struct mgcp_conn_peer *osmo_mgcpc_ep_ci_get_rtp_info(const struct osmo_mgcpc_ep_ci *ci);
 | 
			
		||||
bool osmo_mgcpc_ep_ci_get_crcx_info_to_sockaddr(const struct osmo_mgcpc_ep_ci *ci, struct sockaddr_storage *dest);
 | 
			
		||||
bool osmo_mgcpc_ep_ci_get_crcx_info_to_osmux_cid(const struct osmo_mgcpc_ep_ci *ci, uint8_t* cid);
 | 
			
		||||
 | 
			
		||||
const struct mgcp_conn_peer *osmo_mgcpc_ep_ci_get_remote_rtp_info(const struct osmo_mgcpc_ep_ci *ci);
 | 
			
		||||
 | 
			
		||||
void osmo_mgcpc_ep_ci_request(struct osmo_mgcpc_ep_ci *ci,
 | 
			
		||||
			      enum mgcp_verb verb, const struct mgcp_conn_peer *verb_info,
 | 
			
		||||
			      struct osmo_fsm_inst *notify,
 | 
			
		||||
			      uint32_t event_success, uint32_t event_failure,
 | 
			
		||||
			      void *notify_data);
 | 
			
		||||
 | 
			
		||||
void osmo_mgcpc_ep_cancel_notify(struct osmo_mgcpc_ep *ep, struct osmo_fsm_inst *notify);
 | 
			
		||||
struct osmo_mgcpc_ep *osmo_mgcpc_ep_ci_ep(struct osmo_mgcpc_ep_ci *ci);
 | 
			
		||||
 | 
			
		||||
/*! Dispatch a DLCX for the given connection.
 | 
			
		||||
 * \param ci  Connection identifier as obtained from osmo_mgcpc_ep_ci_add().
 | 
			
		||||
 */
 | 
			
		||||
static inline void osmo_mgcpc_ep_ci_dlcx(struct osmo_mgcpc_ep_ci *ci)
 | 
			
		||||
{
 | 
			
		||||
	osmo_mgcpc_ep_ci_request(ci, MGCP_VERB_DLCX, NULL, NULL, 0, 0, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void osmo_mgcpc_ep_clear(struct osmo_mgcpc_ep *ep);
 | 
			
		||||
 | 
			
		||||
const char *osmo_mgcpc_ep_name(const struct osmo_mgcpc_ep *ep);
 | 
			
		||||
const char *osmo_mgcpc_ep_local_name(const struct osmo_mgcpc_ep *ep);
 | 
			
		||||
const char *osmo_mgcpc_ep_ci_name(const struct osmo_mgcpc_ep_ci *ci);
 | 
			
		||||
const char *osmo_mgcpc_ep_ci_id(const struct osmo_mgcpc_ep_ci *ci);
 | 
			
		||||
struct mgcp_client *osmo_mgcpc_ep_client(const struct osmo_mgcpc_ep *ep);
 | 
			
		||||
 | 
			
		||||
extern const struct value_string osmo_mgcp_verb_names[];
 | 
			
		||||
static inline const char *osmo_mgcp_verb_name(enum mgcp_verb val)
 | 
			
		||||
{ return get_value_string(osmo_mgcp_verb_names, val); }
 | 
			
		||||
@@ -1,78 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp_client/mgcp_common.h>
 | 
			
		||||
#include <osmocom/mgcp_client/mgcp_client.h>
 | 
			
		||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
 | 
			
		||||
 | 
			
		||||
/*! This struct organizes the connection infromation one connection side
 | 
			
		||||
 *  (either remote or local). It is used to pass parameters (local) to the FSM
 | 
			
		||||
 *  and get responses (remote) from the FSM as pointer attached to the FSM
 | 
			
		||||
 *  event.
 | 
			
		||||
 *
 | 
			
		||||
 *  When modifiying a connection, the endpoint and call_id members may be left
 | 
			
		||||
 *  unpopulated. The call_id field is ignored in this case. If an endpoint
 | 
			
		||||
 *  identifier is supplied it is checked against the internal state to make
 | 
			
		||||
 *  sure it is correct. */
 | 
			
		||||
struct mgcp_conn_peer {
 | 
			
		||||
	/*! RTP connection IP-Address (optional, string e.g. "127.0.0.1") */
 | 
			
		||||
	char addr[INET6_ADDRSTRLEN];
 | 
			
		||||
 | 
			
		||||
	/*! RTP connection IP-Port (optional)  */
 | 
			
		||||
	uint16_t port;
 | 
			
		||||
 | 
			
		||||
	/*! RTP endpoint */
 | 
			
		||||
	char endpoint[MGCP_ENDPOINT_MAXLEN];
 | 
			
		||||
 | 
			
		||||
	/*! CALL ID (unique per connection) */
 | 
			
		||||
	unsigned int call_id;
 | 
			
		||||
 | 
			
		||||
	/*! RTP packetization interval (optional) */
 | 
			
		||||
	unsigned int ptime;
 | 
			
		||||
 | 
			
		||||
	/*! Deprecated. Use only ptmap[].codec in new code. */
 | 
			
		||||
	enum mgcp_codecs codecs[MGCP_MAX_CODECS]
 | 
			
		||||
		OSMO_DEPRECATED_OUTSIDE_LIBOSMOMGCPCLIENT("use ptmap[i].codec instead");
 | 
			
		||||
	unsigned int codecs_len
 | 
			
		||||
		OSMO_DEPRECATED_OUTSIDE_LIBOSMOMGCPCLIENT("use ptmap[] and ptmap_len instead");
 | 
			
		||||
 | 
			
		||||
	/*! RTP payload type map (optional, only needed when payload types are
 | 
			
		||||
	 * used that differ from what IANA/3GPP defines) */
 | 
			
		||||
	struct ptmap ptmap[MGCP_MAX_CODECS];
 | 
			
		||||
 | 
			
		||||
	/*! RTP payload type map length (optional, only needed when payload
 | 
			
		||||
	 * types are used that differ from what IANA/3GPP defines) */
 | 
			
		||||
	unsigned int ptmap_len;
 | 
			
		||||
 | 
			
		||||
	/*! If nonzero, send 'X-Osmo-IGN:' header. This is useful e.g. for SCCPlite MSCs where the MSC is
 | 
			
		||||
	 * known to issue incoherent or unknown CallIDs / to issue CRCX commands with a different domain
 | 
			
		||||
	 * name than the BSC. An OsmoMGW will then ignore these and not fail on mismatches. */
 | 
			
		||||
	uint32_t x_osmo_ign;
 | 
			
		||||
 | 
			
		||||
	/*! send 'X-Osmux: %d' header (or "*" as wildcard). */
 | 
			
		||||
	bool x_osmo_osmux_use;
 | 
			
		||||
	/*! -1 means send wildcard. */
 | 
			
		||||
	int x_osmo_osmux_cid;
 | 
			
		||||
 | 
			
		||||
	/*! If left MGCP_CONN_NONE, use MGCP_CONN_RECV_ONLY or MGCP_CONN_RECV_SEND, depending on whether an audio RTP
 | 
			
		||||
	 * address is set. If != MGCP_CONN_NONE, force this conn mode. */
 | 
			
		||||
	enum mgcp_connection_mode conn_mode;
 | 
			
		||||
 | 
			
		||||
	/*! If the codec requires additional format parameters (fmtp), those cann be set here, see also
 | 
			
		||||
	 * mgcp_common.h */
 | 
			
		||||
	bool param_present;
 | 
			
		||||
	struct mgcp_codec_param param;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct osmo_fsm_inst *mgcp_conn_create(struct mgcp_client *mgcp, struct osmo_fsm_inst *parent_fi, uint32_t parent_term_evt,
 | 
			
		||||
				       uint32_t parent_evt, struct mgcp_conn_peer *conn_peer)
 | 
			
		||||
	OSMO_DEPRECATED_OUTSIDE_LIBOSMOMGCPCLIENT("use osmo_mgcpc_ep_alloc() and osmo_mgcpc_ep_ci_add() instead");
 | 
			
		||||
int mgcp_conn_modify(struct osmo_fsm_inst *fi, uint32_t parent_evt, struct mgcp_conn_peer *conn_peer)
 | 
			
		||||
	OSMO_DEPRECATED_OUTSIDE_LIBOSMOMGCPCLIENT("use osmo_mgcpc_ep_ci_request() instead");
 | 
			
		||||
void mgcp_conn_delete(struct osmo_fsm_inst *fi)
 | 
			
		||||
	OSMO_DEPRECATED_OUTSIDE_LIBOSMOMGCPCLIENT("use osmo_mgcpc_ep_ci_dlcx() instead");
 | 
			
		||||
 | 
			
		||||
const char *mgcp_conn_get_ci(struct osmo_fsm_inst *fi)
 | 
			
		||||
	OSMO_DEPRECATED_OUTSIDE_LIBOSMOMGCPCLIENT("use osmo_mgcpc_ep_ci.mgcp_ci_str instead");
 | 
			
		||||
struct mgcp_client *mgcp_conn_get_client(struct osmo_fsm_inst *fi);
 | 
			
		||||
 | 
			
		||||
const char *osmo_mgcpc_conn_peer_name(const struct mgcp_conn_peer *info);
 | 
			
		||||
@@ -1,53 +1,23 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/osmo_io.h>
 | 
			
		||||
#include <osmocom/core/timer.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/mgcp_client/mgcp_client.h>
 | 
			
		||||
#include <osmocom/core/write_queue.h>
 | 
			
		||||
 | 
			
		||||
#define MSGB_CB_MGCP_TRANS_ID 0
 | 
			
		||||
 | 
			
		||||
/* Struct that holds one endpoint name */
 | 
			
		||||
struct reset_ep {
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
	char name[MGCP_ENDPOINT_MAXLEN];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_client {
 | 
			
		||||
	struct mgcp_client_conf actual;
 | 
			
		||||
	struct osmo_io_fd *iofd;
 | 
			
		||||
	uint32_t remote_addr;
 | 
			
		||||
	struct osmo_wqueue wq;
 | 
			
		||||
	mgcp_trans_id_t next_trans_id;
 | 
			
		||||
	struct llist_head responses_pending;
 | 
			
		||||
	struct mgcp_client_pool_member *pool_member;
 | 
			
		||||
	struct osmo_timer_list keepalive_tx_timer;
 | 
			
		||||
	struct osmo_timer_list keepalive_rx_timer;
 | 
			
		||||
	bool conn_up;
 | 
			
		||||
	struct llist_head inuse_endpoints;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_response_head {
 | 
			
		||||
	int response_code;
 | 
			
		||||
	mgcp_trans_id_t trans_id;
 | 
			
		||||
	char comment[MGCP_COMMENT_MAXLEN];
 | 
			
		||||
	char conn_id[MGCP_CONN_ID_MAXLEN];
 | 
			
		||||
	char endpoint[MGCP_ENDPOINT_MAXLEN];
 | 
			
		||||
	bool x_osmo_osmux_use;
 | 
			
		||||
	uint8_t x_osmo_osmux_cid;
 | 
			
		||||
struct mgcp_inuse_endpoint {
 | 
			
		||||
	struct llist_head entry;
 | 
			
		||||
	uint16_t id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_response {
 | 
			
		||||
	char *body;
 | 
			
		||||
	struct mgcp_response_head head;
 | 
			
		||||
	uint16_t audio_port;
 | 
			
		||||
	char audio_ip[INET6_ADDRSTRLEN];
 | 
			
		||||
	unsigned int ptime;
 | 
			
		||||
	struct ptmap ptmap[MGCP_MAX_CODECS];
 | 
			
		||||
	unsigned int ptmap_len;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Invoked when an MGCP response is received or sending failed.  When the
 | 
			
		||||
 * response is passed as NULL, this indicates failure during transmission. */
 | 
			
		||||
typedef void (*mgcp_response_cb_t)(struct mgcp_response *response, void *priv);
 | 
			
		||||
 | 
			
		||||
struct mgcp_response_pending {
 | 
			
		||||
	struct llist_head entry;
 | 
			
		||||
 | 
			
		||||
@@ -63,41 +33,3 @@ struct mgcp_response_pending * mgcp_client_pending_add(
 | 
			
		||||
					mgcp_trans_id_t trans_id,
 | 
			
		||||
					mgcp_response_cb_t response_cb,
 | 
			
		||||
					void *priv);
 | 
			
		||||
 | 
			
		||||
#define MGCP_MSG_PRESENCE_ENDPOINT	0x0001
 | 
			
		||||
#define MGCP_MSG_PRESENCE_CALL_ID	0x0002
 | 
			
		||||
#define MGCP_MSG_PRESENCE_CONN_ID	0x0004
 | 
			
		||||
#define MGCP_MSG_PRESENCE_AUDIO_IP	0x0008
 | 
			
		||||
#define MGCP_MSG_PRESENCE_AUDIO_PORT	0x0010
 | 
			
		||||
#define MGCP_MSG_PRESENCE_CONN_MODE	0x0020
 | 
			
		||||
#define MGCP_MSG_PRESENCE_X_OSMO_OSMUX_CID 0x4000
 | 
			
		||||
#define MGCP_MSG_PRESENCE_X_OSMO_IGN	0x8000
 | 
			
		||||
 | 
			
		||||
struct mgcp_msg {
 | 
			
		||||
	enum mgcp_verb verb;
 | 
			
		||||
	/* See MGCP_MSG_PRESENCE_* constants */
 | 
			
		||||
	uint32_t presence;
 | 
			
		||||
	char endpoint[MGCP_ENDPOINT_MAXLEN];
 | 
			
		||||
	unsigned int call_id;
 | 
			
		||||
	char *conn_id;
 | 
			
		||||
	uint16_t audio_port;
 | 
			
		||||
	char *audio_ip;
 | 
			
		||||
	enum mgcp_connection_mode conn_mode;
 | 
			
		||||
	unsigned int ptime;
 | 
			
		||||
	struct ptmap ptmap[MGCP_MAX_CODECS];
 | 
			
		||||
	unsigned int ptmap_len;
 | 
			
		||||
	uint32_t x_osmo_ign;
 | 
			
		||||
	bool x_osmo_osmux_use;
 | 
			
		||||
	int x_osmo_osmux_cid; /* -1 is wildcard */
 | 
			
		||||
	bool param_present;
 | 
			
		||||
	struct mgcp_codec_param param;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int mgcp_response_parse_params(struct mgcp_response *r);
 | 
			
		||||
 | 
			
		||||
int mgcp_client_tx(struct mgcp_client *mgcp, struct msgb *msg,
 | 
			
		||||
		   mgcp_response_cb_t response_cb, void *priv);
 | 
			
		||||
int mgcp_client_cancel(struct mgcp_client *mgcp, mgcp_trans_id_t trans_id);
 | 
			
		||||
 | 
			
		||||
struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg);
 | 
			
		||||
mgcp_trans_id_t mgcp_msg_trans_id(struct msgb *msg);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,24 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/vty/vty.h>
 | 
			
		||||
 | 
			
		||||
struct mgcp_client;
 | 
			
		||||
struct mgcp_client_pool;
 | 
			
		||||
struct mgcp_client_pool_member;
 | 
			
		||||
 | 
			
		||||
struct mgcp_client_pool *mgcp_client_pool_alloc(void *talloc_ctx);
 | 
			
		||||
 | 
			
		||||
void mgcp_client_pool_vty_init(int parent_node, int mgw_node, const char *indent, struct mgcp_client_pool *pool);
 | 
			
		||||
int mgcp_client_pool_config_write(struct vty *vty, const char *indent);
 | 
			
		||||
unsigned int mgcp_client_pool_connect(struct mgcp_client_pool *pool);
 | 
			
		||||
void mgcp_client_pool_register_single(struct mgcp_client_pool *pool, struct mgcp_client *mgcp_client);
 | 
			
		||||
bool mgcp_client_pool_empty(const struct mgcp_client_pool *pool);
 | 
			
		||||
 | 
			
		||||
struct mgcp_client *mgcp_client_pool_get(struct mgcp_client_pool *pool);
 | 
			
		||||
void mgcp_client_pool_put(struct mgcp_client *mgcp_client);
 | 
			
		||||
 | 
			
		||||
struct mgcp_client_pool_member *mgcp_client_pool_find_member_by_nr(struct mgcp_client_pool *pool, unsigned int nr);
 | 
			
		||||
struct mgcp_client *mgcp_client_pool_member_get(struct mgcp_client_pool_member *pool_member);
 | 
			
		||||
bool mgcp_client_pool_member_is_blocked(const struct mgcp_client_pool_member *pool_member);
 | 
			
		||||
@@ -1,52 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
/* Struct to handle a pool of MGWs. (Use _pool functions) */
 | 
			
		||||
struct mgcp_client_pool {
 | 
			
		||||
 | 
			
		||||
	/* A pointer to a 'single' mgcp client. This is a non-pooled MGCP client that is configured using
 | 
			
		||||
	 * mgcp_client_vty_init() and actively registered by the API user using mgcp_client_pool_register_single() */
 | 
			
		||||
	struct mgcp_client *mgcp_client_single;
 | 
			
		||||
 | 
			
		||||
	/* A list that manages the pool members (see mgcp_client_pool_member->list above) */
 | 
			
		||||
	struct llist_head member_list;
 | 
			
		||||
 | 
			
		||||
	/* String to use for indentation when writing the configuration file to the VTY. This field is populated by
 | 
			
		||||
	 * mgcp_client_pool_vty_init() */
 | 
			
		||||
	char *vty_indent;
 | 
			
		||||
 | 
			
		||||
	/* VTY node specification used with this pool. This field is populated by mgcp_client_pool_vty_init() */
 | 
			
		||||
	struct cmd_node *vty_node;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Struct to handle a member of a pool of MGWs. */
 | 
			
		||||
struct mgcp_client_pool_member {
 | 
			
		||||
	/* Entry in llist mgcp_client_pool->pool. */
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
 | 
			
		||||
	/* The pool managing this object: */
 | 
			
		||||
	struct mgcp_client_pool *pool;
 | 
			
		||||
 | 
			
		||||
	/* Reference number assinged by VTY. This number is used to manage the pool from the VTY and to identify it in
 | 
			
		||||
	 * the log. */
 | 
			
		||||
	unsigned int nr;
 | 
			
		||||
 | 
			
		||||
	/* MGCP client configuration, this is not the running configuration, when mgcp_client_init() is executed, a
 | 
			
		||||
	 * copy of this config is created. */
 | 
			
		||||
	struct mgcp_client_conf conf;
 | 
			
		||||
 | 
			
		||||
	/* MGCP client descriptor, will be automatically allocated when mgcp_client_pool_connect() is called. (the MGCP
 | 
			
		||||
	 * client is connected when this pointer is populated) */
 | 
			
		||||
	struct mgcp_client *client;
 | 
			
		||||
 | 
			
		||||
	/* A pool member may be set as 'blocked' from the VTY, this means that the pool member may still work and serve
 | 
			
		||||
	 * ongoing calls, but it won't be picked from the pool anymore. */
 | 
			
		||||
	bool blocked;
 | 
			
		||||
 | 
			
		||||
	/* Reference counter to count how often this pool member is currently picked. */
 | 
			
		||||
	unsigned int refcount;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mgcp_client_pool_member *mgcp_client_pool_member_alloc(struct mgcp_client_pool *pool, unsigned int nr);
 | 
			
		||||
void mgcp_client_pool_member_free(struct mgcp_client_pool_member *pool_member);
 | 
			
		||||
int mgcp_client_pool_member_reinit_client(struct mgcp_client_pool_member *pool_member);
 | 
			
		||||
const char *mgcp_client_pool_member_name(const struct mgcp_client_pool_member *pool_member);
 | 
			
		||||
							
								
								
									
										10
									
								
								libosmo-legacy-mgcp.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								libosmo-legacy-mgcp.pc.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
prefix=@prefix@
 | 
			
		||||
exec_prefix=@exec_prefix@
 | 
			
		||||
libdir=@libdir@
 | 
			
		||||
includedir=@includedir@
 | 
			
		||||
 | 
			
		||||
Name: Osmocom legacy Media Gateway Control Protocol library
 | 
			
		||||
Description: C Utility Library
 | 
			
		||||
Version: @VERSION@
 | 
			
		||||
Libs: -L${libdir} -losmo-legacy-mgcp
 | 
			
		||||
Cflags: -I${includedir}/
 | 
			
		||||
							
								
								
									
										10
									
								
								libosmo-mgcp.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								libosmo-mgcp.pc.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
prefix=@prefix@
 | 
			
		||||
exec_prefix=@exec_prefix@
 | 
			
		||||
libdir=@libdir@
 | 
			
		||||
includedir=@includedir@
 | 
			
		||||
 | 
			
		||||
Name: Osmocom Media Gateway Control Protocol library
 | 
			
		||||
Description: C Utility Library
 | 
			
		||||
Version: @VERSION@
 | 
			
		||||
Libs: -L${libdir} -losmo-mgcp
 | 
			
		||||
Cflags: -I${includedir}/
 | 
			
		||||
							
								
								
									
										74
									
								
								m4/ax_check_compile_flag.m4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								m4/ax_check_compile_flag.m4
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
# ===========================================================================
 | 
			
		||||
#   http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
 | 
			
		||||
# ===========================================================================
 | 
			
		||||
#
 | 
			
		||||
# SYNOPSIS
 | 
			
		||||
#
 | 
			
		||||
#   AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
 | 
			
		||||
#
 | 
			
		||||
# DESCRIPTION
 | 
			
		||||
#
 | 
			
		||||
#   Check whether the given FLAG works with the current language's compiler
 | 
			
		||||
#   or gives an error.  (Warnings, however, are ignored)
 | 
			
		||||
#
 | 
			
		||||
#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
 | 
			
		||||
#   success/failure.
 | 
			
		||||
#
 | 
			
		||||
#   If EXTRA-FLAGS is defined, it is added to the current language's default
 | 
			
		||||
#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
 | 
			
		||||
#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
 | 
			
		||||
#   force the compiler to issue an error when a bad flag is given.
 | 
			
		||||
#
 | 
			
		||||
#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
 | 
			
		||||
#
 | 
			
		||||
#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
 | 
			
		||||
#   macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
 | 
			
		||||
#
 | 
			
		||||
# LICENSE
 | 
			
		||||
#
 | 
			
		||||
#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
 | 
			
		||||
#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
 | 
			
		||||
#
 | 
			
		||||
#   This program is free software: you can redistribute it and/or modify it
 | 
			
		||||
#   under the terms of the GNU General Public License as published by the
 | 
			
		||||
#   Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
#   option) any later version.
 | 
			
		||||
#
 | 
			
		||||
#   This program is distributed in the hope that it will be useful, but
 | 
			
		||||
#   WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 | 
			
		||||
#   Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
#   You should have received a copy of the GNU General Public License along
 | 
			
		||||
#   with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
#   As a special exception, the respective Autoconf Macro's copyright owner
 | 
			
		||||
#   gives unlimited permission to copy, distribute and modify the configure
 | 
			
		||||
#   scripts that are the output of Autoconf when processing the Macro. You
 | 
			
		||||
#   need not follow the terms of the GNU General Public License when using
 | 
			
		||||
#   or distributing such scripts, even though portions of the text of the
 | 
			
		||||
#   Macro appear in them. The GNU General Public License (GPL) does govern
 | 
			
		||||
#   all other use of the material that constitutes the Autoconf Macro.
 | 
			
		||||
#
 | 
			
		||||
#   This special exception to the GPL applies to versions of the Autoconf
 | 
			
		||||
#   Macro released by the Autoconf Archive. When you make and distribute a
 | 
			
		||||
#   modified version of the Autoconf Macro, you may extend this special
 | 
			
		||||
#   exception to the GPL to apply to your modified version as well.
 | 
			
		||||
 | 
			
		||||
#serial 4
 | 
			
		||||
 | 
			
		||||
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
 | 
			
		||||
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
 | 
			
		||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
 | 
			
		||||
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
 | 
			
		||||
  ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
 | 
			
		||||
  _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
 | 
			
		||||
  AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
 | 
			
		||||
    [AS_VAR_SET(CACHEVAR,[yes])],
 | 
			
		||||
    [AS_VAR_SET(CACHEVAR,[no])])
 | 
			
		||||
  _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
 | 
			
		||||
AS_VAR_IF(CACHEVAR,yes,
 | 
			
		||||
  [m4_default([$2], :)],
 | 
			
		||||
  [m4_default([$3], :)])
 | 
			
		||||
AS_VAR_POPDEF([CACHEVAR])dnl
 | 
			
		||||
])dnl AX_CHECK_COMPILE_FLAGS
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
# (C) 2013 by Katerina Barone-Adesi <kat.obsc@gmail.com>
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
@@ -17,9 +17,11 @@
 | 
			
		||||
 | 
			
		||||
app_configs = {
 | 
			
		||||
    "osmo-mgw": ["doc/examples/osmo-mgw/osmo-mgw.cfg"],
 | 
			
		||||
    "osmo-bsc_mgcp": ["doc/examples/osmo-bsc_mgcp/mgcp.cfg"],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
apps = [(4243, "src/osmo-mgw/osmo-mgw", "OsmoMGW", "osmo-mgw"),
 | 
			
		||||
        (4243, "src/osmo-bsc_mgcp/osmo-bsc_mgcp", "OpenBSC MGCP", "osmo-bsc_mgcp"),
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
vty_command = ["./src/osmo-mgw/osmo-mgw", "-c",
 | 
			
		||||
 
 | 
			
		||||
@@ -13,13 +13,21 @@ AM_CFLAGS = \
 | 
			
		||||
	$(COVERAGE_CFLAGS) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
AM_LDFLAGS = \
 | 
			
		||||
	$(LIBOSMOCORE_LIBS) \
 | 
			
		||||
	$(LIBOSMOGSM_LIBS) \
 | 
			
		||||
	$(COVERAGE_LDFLAGS) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
# Libraries
 | 
			
		||||
SUBDIRS = \
 | 
			
		||||
	libosmo-legacy-mgcp \
 | 
			
		||||
	libosmo-mgcp-client \
 | 
			
		||||
	libosmo-mgcp \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
# Programs
 | 
			
		||||
SUBDIRS += \
 | 
			
		||||
	osmo-bsc_mgcp \
 | 
			
		||||
	osmo-mgw \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								src/libosmo-legacy-mgcp/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/libosmo-legacy-mgcp/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
AM_CPPFLAGS = \
 | 
			
		||||
	$(all_includes) \
 | 
			
		||||
	-I$(top_srcdir)/include \
 | 
			
		||||
	-I$(top_builddir) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
AM_CFLAGS = \
 | 
			
		||||
	-Wall \
 | 
			
		||||
	$(LIBOSMOCORE_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOVTY_CFLAGS) \
 | 
			
		||||
	$(LIBOSMONETIF_CFLAGS) \
 | 
			
		||||
	$(COVERAGE_CFLAGS) \
 | 
			
		||||
	$(LIBBCG729_CFLAGS) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
AM_LDFLAGS = \
 | 
			
		||||
	$(LIBOSMOCORE_LIBS) \
 | 
			
		||||
	$(LIBOSMOVTY_LIBS) \
 | 
			
		||||
	$(LIBOSMONETIF_LIBS) \
 | 
			
		||||
	$(COVERAGE_LDFLAGS) \
 | 
			
		||||
	$(LIBBCG729_LIBS) \
 | 
			
		||||
	$(LIBRARY_GSM) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
# This is not at all related to the release version, but a range of supported
 | 
			
		||||
# API versions. Read TODO_RELEASE in the source tree's root!
 | 
			
		||||
LEGACY_MGCP_LIBVERSION=0:0:0
 | 
			
		||||
 | 
			
		||||
lib_LTLIBRARIES = \
 | 
			
		||||
	libosmo-legacy-mgcp.la \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
noinst_HEADERS = \
 | 
			
		||||
	g711common.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
libosmo_legacy_mgcp_la_SOURCES = \
 | 
			
		||||
	mgcp_common.c \
 | 
			
		||||
	mgcp_protocol.c \
 | 
			
		||||
	mgcp_network.c \
 | 
			
		||||
	mgcp_vty.c \
 | 
			
		||||
	mgcp_osmux.c \
 | 
			
		||||
	mgcp_sdp.c \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
if BUILD_MGCP_TRANSCODING
 | 
			
		||||
libosmo_legacy_mgcp_la_SOURCES += \
 | 
			
		||||
	mgcp_transcode.c \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
libosmo_legacy_mgcp_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LEGACY_MGCP_LIBVERSION)
 | 
			
		||||
							
								
								
									
										187
									
								
								src/libosmo-legacy-mgcp/g711common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/libosmo-legacy-mgcp/g711common.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,187 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  PCM - A-Law conversion
 | 
			
		||||
 *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
 | 
			
		||||
 *
 | 
			
		||||
 *  Wrapper for linphone Codec class by Simon Morlat <simon.morlat@linphone.org>
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 *  it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *  the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 *  (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License
 | 
			
		||||
 *  along with this program; if not, write to the Free Software
 | 
			
		||||
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static inline int val_seg(int val)
 | 
			
		||||
{
 | 
			
		||||
	int r = 0;
 | 
			
		||||
	val >>= 7; /*7 = 4 + 3*/
 | 
			
		||||
	if (val & 0xf0) {
 | 
			
		||||
		val >>= 4;
 | 
			
		||||
		r += 4;
 | 
			
		||||
	}
 | 
			
		||||
	if (val & 0x0c) {
 | 
			
		||||
		val >>= 2;
 | 
			
		||||
		r += 2;
 | 
			
		||||
	}
 | 
			
		||||
	if (val & 0x02)
 | 
			
		||||
		r += 1;
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * s16_to_alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
 | 
			
		||||
 *
 | 
			
		||||
 * s16_to_alaw() accepts an 16-bit integer and encodes it as A-law data.
 | 
			
		||||
 *
 | 
			
		||||
 *		Linear Input Code	Compressed Code
 | 
			
		||||
 *	------------------------	---------------
 | 
			
		||||
 *	0000000wxyza			000wxyz
 | 
			
		||||
 *	0000001wxyza			001wxyz
 | 
			
		||||
 *	000001wxyzab			010wxyz
 | 
			
		||||
 *	00001wxyzabc			011wxyz
 | 
			
		||||
 *	0001wxyzabcd			100wxyz
 | 
			
		||||
 *	001wxyzabcde			101wxyz
 | 
			
		||||
 *	01wxyzabcdef			110wxyz
 | 
			
		||||
 *	1wxyzabcdefg			111wxyz
 | 
			
		||||
 *
 | 
			
		||||
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 | 
			
		||||
 * John Wiley & Sons, pps 98-111 and 472-476.
 | 
			
		||||
 * G711 is designed for 13 bits input signal, this function add extra shifting to take this into account.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static inline unsigned char s16_to_alaw(int pcm_val)
 | 
			
		||||
{
 | 
			
		||||
	int		mask;
 | 
			
		||||
	int		seg;
 | 
			
		||||
	unsigned char	aval;
 | 
			
		||||
 | 
			
		||||
	if (pcm_val >= 0) {
 | 
			
		||||
		mask = 0xD5;
 | 
			
		||||
	} else {
 | 
			
		||||
		mask = 0x55;
 | 
			
		||||
		pcm_val = -pcm_val;
 | 
			
		||||
		if (pcm_val > 0x7fff)
 | 
			
		||||
			pcm_val = 0x7fff;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pcm_val < 256) /*256 = 32 << 3*/
 | 
			
		||||
		aval = pcm_val >> 4; /*4 = 1 + 3*/
 | 
			
		||||
	else {
 | 
			
		||||
		/* Convert the scaled magnitude to segment number. */
 | 
			
		||||
		seg = val_seg(pcm_val);
 | 
			
		||||
		aval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f);
 | 
			
		||||
	}
 | 
			
		||||
	return aval ^ mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * alaw_to_s16() - Convert an A-law value to 16-bit linear PCM
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
static inline int alaw_to_s16(unsigned char a_val)
 | 
			
		||||
{
 | 
			
		||||
	int		t;
 | 
			
		||||
	int		seg;
 | 
			
		||||
 | 
			
		||||
	a_val ^= 0x55;
 | 
			
		||||
	t = a_val & 0x7f;
 | 
			
		||||
	if (t < 16)
 | 
			
		||||
		t = (t << 4) + 8;
 | 
			
		||||
	else {
 | 
			
		||||
		seg = (t >> 4) & 0x07;
 | 
			
		||||
		t = ((t & 0x0f) << 4) + 0x108;
 | 
			
		||||
		t <<= seg -1;
 | 
			
		||||
	}
 | 
			
		||||
	return ((a_val & 0x80) ? t : -t);
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * s16_to_ulaw() - Convert a linear PCM value to u-law
 | 
			
		||||
 *
 | 
			
		||||
 * In order to simplify the encoding process, the original linear magnitude
 | 
			
		||||
 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
 | 
			
		||||
 * (33 - 8191). The result can be seen in the following encoding table:
 | 
			
		||||
 *
 | 
			
		||||
 *	Biased Linear Input Code	Compressed Code
 | 
			
		||||
 *	------------------------	---------------
 | 
			
		||||
 *	00000001wxyza			000wxyz
 | 
			
		||||
 *	0000001wxyzab			001wxyz
 | 
			
		||||
 *	000001wxyzabc			010wxyz
 | 
			
		||||
 *	00001wxyzabcd			011wxyz
 | 
			
		||||
 *	0001wxyzabcde			100wxyz
 | 
			
		||||
 *	001wxyzabcdef			101wxyz
 | 
			
		||||
 *	01wxyzabcdefg			110wxyz
 | 
			
		||||
 *	1wxyzabcdefgh			111wxyz
 | 
			
		||||
 *
 | 
			
		||||
 * Each biased linear code has a leading 1 which identifies the segment
 | 
			
		||||
 * number. The value of the segment number is equal to 7 minus the number
 | 
			
		||||
 * of leading 0's. The quantization interval is directly available as the
 | 
			
		||||
 * four bits wxyz.  * The trailing bits (a - h) are ignored.
 | 
			
		||||
 *
 | 
			
		||||
 * Ordinarily the complement of the resulting code word is used for
 | 
			
		||||
 * transmission, and so the code word is complemented before it is returned.
 | 
			
		||||
 *
 | 
			
		||||
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 | 
			
		||||
 * John Wiley & Sons, pps 98-111 and 472-476.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static inline unsigned char s16_to_ulaw(int pcm_val)	/* 2's complement (16-bit range) */
 | 
			
		||||
{
 | 
			
		||||
	int mask;
 | 
			
		||||
	int seg;
 | 
			
		||||
	unsigned char uval;
 | 
			
		||||
 | 
			
		||||
	if (pcm_val < 0) {
 | 
			
		||||
		pcm_val = 0x84 - pcm_val;
 | 
			
		||||
		mask = 0x7f;
 | 
			
		||||
	} else {
 | 
			
		||||
		pcm_val += 0x84;
 | 
			
		||||
		mask = 0xff;
 | 
			
		||||
	}
 | 
			
		||||
	if (pcm_val > 0x7fff)
 | 
			
		||||
		pcm_val = 0x7fff;
 | 
			
		||||
 | 
			
		||||
	/* Convert the scaled magnitude to segment number. */
 | 
			
		||||
	seg = val_seg(pcm_val);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Combine the sign, segment, quantization bits;
 | 
			
		||||
	 * and complement the code word.
 | 
			
		||||
	 */
 | 
			
		||||
	uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f);
 | 
			
		||||
	return uval ^ mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ulaw_to_s16() - Convert a u-law value to 16-bit linear PCM
 | 
			
		||||
 *
 | 
			
		||||
 * First, a biased linear code is derived from the code word. An unbiased
 | 
			
		||||
 * output can then be obtained by subtracting 33 from the biased code.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that this function expects to be passed the complement of the
 | 
			
		||||
 * original code word. This is in keeping with ISDN conventions.
 | 
			
		||||
 */
 | 
			
		||||
static inline int ulaw_to_s16(unsigned char u_val)
 | 
			
		||||
{
 | 
			
		||||
	int t;
 | 
			
		||||
 | 
			
		||||
	/* Complement to obtain normal u-law value. */
 | 
			
		||||
	u_val = ~u_val;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Extract and bias the quantization bits. Then
 | 
			
		||||
	 * shift up by the segment number and subtract out the bias.
 | 
			
		||||
	 */
 | 
			
		||||
	t = ((u_val & 0x0f) << 3) + 0x84;
 | 
			
		||||
	t <<= (u_val & 0x70) >> 4;
 | 
			
		||||
 | 
			
		||||
	return ((u_val & 0x80) ? (0x84 - t) : (t - 0x84));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								src/libosmo-legacy-mgcp/mgcp_common.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/libosmo-legacy-mgcp/mgcp_common.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
/* Media Gateway Control Protocol Media Gateway: RFC 3435 */
 | 
			
		||||
/* Implementations useful both for the MGCP GW as well as MGCP GW clients */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/legacy_mgcp/mgcp.h>
 | 
			
		||||
 | 
			
		||||
const struct value_string mgcp_connection_mode_strs[] = {
 | 
			
		||||
	{ MGCP_CONN_NONE, "none" },
 | 
			
		||||
	{ MGCP_CONN_RECV_SEND, "sendrecv" },
 | 
			
		||||
	{ MGCP_CONN_SEND_ONLY, "sendonly" },
 | 
			
		||||
	{ MGCP_CONN_RECV_ONLY, "recvonly" },
 | 
			
		||||
	{ MGCP_CONN_LOOPBACK, "loopback" },
 | 
			
		||||
	{ 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Ensure that the msg->l2h is NUL terminated. */
 | 
			
		||||
int mgcp_msg_terminate_nul(struct msgb *msg)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char *tail = msg->l2h + msgb_l2len(msg); /* char after l2 data */
 | 
			
		||||
	if (tail[-1] == '\0')
 | 
			
		||||
		/* nothing to do */;
 | 
			
		||||
	else if (msgb_tailroom(msg) > 0)
 | 
			
		||||
		tail[0] = '\0';
 | 
			
		||||
	else if (tail[-1] == '\r' || tail[-1] == '\n')
 | 
			
		||||
		tail[-1] = '\0';
 | 
			
		||||
	else {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "Cannot NUL terminate MGCP message: "
 | 
			
		||||
		     "Length: %d, Buffer size: %d\n",
 | 
			
		||||
		     msgb_l2len(msg), msg->data_len);
 | 
			
		||||
		return -ENOTSUP;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1166
									
								
								src/libosmo-legacy-mgcp/mgcp_network.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1166
									
								
								src/libosmo-legacy-mgcp/mgcp_network.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										583
									
								
								src/libosmo-legacy-mgcp/mgcp_osmux.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										583
									
								
								src/libosmo-legacy-mgcp/mgcp_osmux.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,583 @@
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2012-2013 by Pablo Neira Ayuso <pablo@gnumonks.org>
 | 
			
		||||
 * (C) 2012-2013 by On Waves ehf <http://www.on-waves.com>
 | 
			
		||||
 * All rights not specifically granted under this license are reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 * under the terms of the GNU Affero General Public License as published by the
 | 
			
		||||
 * Free Software Foundation; either version 3 of the License, or (at your
 | 
			
		||||
 * option) any later version.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h> /* for printf */
 | 
			
		||||
#include <string.h> /* for memcpy */
 | 
			
		||||
#include <stdlib.h> /* for abs */
 | 
			
		||||
#include <inttypes.h> /* for PRIu64 */
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <osmocom/core/msgb.h>
 | 
			
		||||
#include <osmocom/core/talloc.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/netif/osmux.h>
 | 
			
		||||
#include <osmocom/netif/rtp.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/legacy_mgcp/mgcp.h>
 | 
			
		||||
#include <osmocom/legacy_mgcp/mgcp_internal.h>
 | 
			
		||||
#include <osmocom/legacy_mgcp/osmux.h>
 | 
			
		||||
 | 
			
		||||
static struct osmo_fd osmux_fd;
 | 
			
		||||
 | 
			
		||||
static LLIST_HEAD(osmux_handle_list);
 | 
			
		||||
 | 
			
		||||
struct osmux_handle {
 | 
			
		||||
	struct llist_head head;
 | 
			
		||||
	struct osmux_in_handle *in;
 | 
			
		||||
	struct in_addr rem_addr;
 | 
			
		||||
	int rem_port;
 | 
			
		||||
	int refcnt;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void *osmux;
 | 
			
		||||
 | 
			
		||||
static void osmux_deliver(struct msgb *batch_msg, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct osmux_handle *handle = data;
 | 
			
		||||
	struct sockaddr_in out = {
 | 
			
		||||
		.sin_family = AF_INET,
 | 
			
		||||
		.sin_port = handle->rem_port,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	memcpy(&out.sin_addr, &handle->rem_addr, sizeof(handle->rem_addr));
 | 
			
		||||
	sendto(osmux_fd.fd, batch_msg->data, batch_msg->len, 0,
 | 
			
		||||
		(struct sockaddr *)&out, sizeof(out));
 | 
			
		||||
	msgb_free(batch_msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct osmux_handle *
 | 
			
		||||
osmux_handle_find_get(struct in_addr *addr, int rem_port)
 | 
			
		||||
{
 | 
			
		||||
	struct osmux_handle *h;
 | 
			
		||||
 | 
			
		||||
	/* Lookup for existing OSMUX handle for this destination address. */
 | 
			
		||||
	llist_for_each_entry(h, &osmux_handle_list, head) {
 | 
			
		||||
		if (memcmp(&h->rem_addr, addr, sizeof(struct in_addr)) == 0 &&
 | 
			
		||||
		    h->rem_port == rem_port) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_DEBUG, "using existing OSMUX handle "
 | 
			
		||||
						"for addr=%s:%d\n",
 | 
			
		||||
				inet_ntoa(*addr), ntohs(rem_port));
 | 
			
		||||
			h->refcnt++;
 | 
			
		||||
			return h;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void osmux_handle_put(struct osmux_in_handle *in)
 | 
			
		||||
{
 | 
			
		||||
	struct osmux_handle *h;
 | 
			
		||||
 | 
			
		||||
	/* Lookup for existing OSMUX handle for this destination address. */
 | 
			
		||||
	llist_for_each_entry(h, &osmux_handle_list, head) {
 | 
			
		||||
		if (h->in == in) {
 | 
			
		||||
			if (--h->refcnt == 0) {
 | 
			
		||||
				LOGP(DLMGCP, LOGL_INFO,
 | 
			
		||||
				     "Releasing unused osmux handle for %s:%d\n",
 | 
			
		||||
				     inet_ntoa(h->rem_addr),
 | 
			
		||||
				     ntohs(h->rem_port));
 | 
			
		||||
				LOGP(DLMGCP, LOGL_INFO, "Stats: "
 | 
			
		||||
				     "input RTP msgs: %u bytes: %"PRIu64" "
 | 
			
		||||
				     "output osmux msgs: %u bytes: %"PRIu64"\n",
 | 
			
		||||
				     in->stats.input_rtp_msgs,
 | 
			
		||||
				     in->stats.input_rtp_bytes,
 | 
			
		||||
				     in->stats.output_osmux_msgs,
 | 
			
		||||
				     in->stats.output_osmux_bytes);
 | 
			
		||||
				llist_del(&h->head);
 | 
			
		||||
				osmux_xfrm_input_fini(h->in);
 | 
			
		||||
				talloc_free(h);
 | 
			
		||||
			}
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	LOGP(DLMGCP, LOGL_ERROR, "cannot find Osmux input handle %p\n", in);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct osmux_handle *
 | 
			
		||||
osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
 | 
			
		||||
{
 | 
			
		||||
	struct osmux_handle *h;
 | 
			
		||||
 | 
			
		||||
	h = talloc_zero(osmux, struct osmux_handle);
 | 
			
		||||
	if (!h)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	h->rem_addr = *addr;
 | 
			
		||||
	h->rem_port = rem_port;
 | 
			
		||||
	h->refcnt++;
 | 
			
		||||
 | 
			
		||||
	h->in = talloc_zero(h, struct osmux_in_handle);
 | 
			
		||||
	if (!h->in) {
 | 
			
		||||
		talloc_free(h);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	h->in->osmux_seq = 0; /* sequence number to start OSmux message from */
 | 
			
		||||
	h->in->batch_factor = cfg->osmux_batch;
 | 
			
		||||
	/* If batch size is zero, the library defaults to 1470 bytes. */
 | 
			
		||||
	h->in->batch_size = cfg->osmux_batch_size;
 | 
			
		||||
	h->in->deliver = osmux_deliver;
 | 
			
		||||
	osmux_xfrm_input_init(h->in);
 | 
			
		||||
	h->in->data = h;
 | 
			
		||||
 | 
			
		||||
	llist_add(&h->head, &osmux_handle_list);
 | 
			
		||||
 | 
			
		||||
	LOGP(DLMGCP, LOGL_DEBUG, "created new OSMUX handle for addr=%s:%d\n",
 | 
			
		||||
		inet_ntoa(*addr), ntohs(rem_port));
 | 
			
		||||
 | 
			
		||||
	return h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct osmux_in_handle *
 | 
			
		||||
osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
 | 
			
		||||
{
 | 
			
		||||
	struct osmux_handle *h;
 | 
			
		||||
 | 
			
		||||
	h = osmux_handle_find_get(addr, rem_port);
 | 
			
		||||
	if (h != NULL)
 | 
			
		||||
		return h->in;
 | 
			
		||||
 | 
			
		||||
	h = osmux_handle_alloc(cfg, addr, rem_port);
 | 
			
		||||
	if (h == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return h->in;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct msgb *msg;
 | 
			
		||||
 | 
			
		||||
	msg = msgb_alloc(4096, "RTP");
 | 
			
		||||
	if (!msg)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	memcpy(msg->data, buf, rc);
 | 
			
		||||
	msgb_put(msg, rc);
 | 
			
		||||
 | 
			
		||||
	while ((ret = osmux_xfrm_input(endp->osmux.in, msg, endp->osmux.cid)) > 0) {
 | 
			
		||||
		/* batch full, build and deliver it */
 | 
			
		||||
		osmux_xfrm_input_deliver(endp->osmux.in);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct mgcp_endpoint *
 | 
			
		||||
endpoint_lookup(struct mgcp_config *cfg, int cid,
 | 
			
		||||
		struct in_addr *from_addr, int type)
 | 
			
		||||
{
 | 
			
		||||
	struct mgcp_endpoint *tmp = NULL;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	/* Lookup for the endpoint that corresponds to this port */
 | 
			
		||||
	for (i=0; i<cfg->trunk.number_endpoints; i++) {
 | 
			
		||||
		struct in_addr *this;
 | 
			
		||||
 | 
			
		||||
		tmp = &cfg->trunk.endpoints[i];
 | 
			
		||||
 | 
			
		||||
		if (!tmp->allocated)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		switch(type) {
 | 
			
		||||
		case MGCP_DEST_NET:
 | 
			
		||||
			this = &tmp->net_end.addr;
 | 
			
		||||
			break;
 | 
			
		||||
		case MGCP_DEST_BTS:
 | 
			
		||||
			this = &tmp->bts_end.addr;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			/* Should not ever happen */
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR, "Bad type %d. Fix your code.\n", type);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (tmp->osmux.cid == cid && this->s_addr == from_addr->s_addr)
 | 
			
		||||
			return tmp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LOGP(DLMGCP, LOGL_ERROR, "Cannot find endpoint with cid=%d\n", cid);
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void scheduled_tx_net_cb(struct msgb *msg, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct mgcp_endpoint *endp = data;
 | 
			
		||||
	struct sockaddr_in addr = {
 | 
			
		||||
		.sin_addr = endp->net_end.addr,
 | 
			
		||||
		.sin_port = endp->net_end.rtp_port,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	endp->bts_end.octets += msg->len;
 | 
			
		||||
	endp->bts_end.packets++;
 | 
			
		||||
 | 
			
		||||
	mgcp_send(endp, MGCP_DEST_NET, 1, &addr, (char *)msg->data, msg->len);
 | 
			
		||||
	msgb_free(msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void scheduled_tx_bts_cb(struct msgb *msg, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct mgcp_endpoint *endp = data;
 | 
			
		||||
	struct sockaddr_in addr = {
 | 
			
		||||
		.sin_addr = endp->bts_end.addr,
 | 
			
		||||
		.sin_port = endp->bts_end.rtp_port,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	endp->net_end.octets += msg->len;
 | 
			
		||||
	endp->net_end.packets++;
 | 
			
		||||
 | 
			
		||||
	mgcp_send(endp, MGCP_DEST_BTS, 1, &addr, (char *)msg->data, msg->len);
 | 
			
		||||
	msgb_free(msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct msgb *osmux_recv(struct osmo_fd *ofd, struct sockaddr_in *addr)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg;
 | 
			
		||||
	socklen_t slen = sizeof(*addr);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	msg = msgb_alloc(4096, "OSMUX");
 | 
			
		||||
	if (!msg) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "cannot allocate message\n");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	ret = recvfrom(ofd->fd, msg->data, msg->data_len, 0,
 | 
			
		||||
			(struct sockaddr *)addr, &slen);
 | 
			
		||||
	if (ret <= 0) {
 | 
			
		||||
		msgb_free(msg);
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "cannot receive message\n");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	msgb_put(msg, ret);
 | 
			
		||||
 | 
			
		||||
	return msg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define osmux_chunk_length(msg, rem) (rem - msg->len);
 | 
			
		||||
 | 
			
		||||
int osmux_read_from_bsc_nat_cb(struct osmo_fd *ofd, unsigned int what)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg;
 | 
			
		||||
	struct osmux_hdr *osmuxh;
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
	struct sockaddr_in addr;
 | 
			
		||||
	struct mgcp_config *cfg = ofd->data;
 | 
			
		||||
	uint32_t rem;
 | 
			
		||||
 | 
			
		||||
	msg = osmux_recv(ofd, &addr);
 | 
			
		||||
	if (!msg)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* not any further processing dummy messages */
 | 
			
		||||
	if (msg->data[0] == MGCP_DUMMY_LOAD)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	rem = msg->len;
 | 
			
		||||
	while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) {
 | 
			
		||||
		struct mgcp_endpoint *endp;
 | 
			
		||||
 | 
			
		||||
		/* Yes, we use MGCP_DEST_NET to locate the origin */
 | 
			
		||||
		endp = endpoint_lookup(cfg, osmuxh->circuit_id,
 | 
			
		||||
				       &addr.sin_addr, MGCP_DEST_NET);
 | 
			
		||||
		if (!endp) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
			     "Cannot find an endpoint for circuit_id=%d\n",
 | 
			
		||||
			     osmuxh->circuit_id);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
 | 
			
		||||
		endp->osmux.stats.chunks++;
 | 
			
		||||
		rem = msg->len;
 | 
			
		||||
 | 
			
		||||
		osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
 | 
			
		||||
		osmux_tx_sched(&list, scheduled_tx_bts_cb, endp);
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	msgb_free(msg);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is called from the bsc-nat */
 | 
			
		||||
static int osmux_handle_dummy(struct mgcp_config *cfg, struct sockaddr_in *addr,
 | 
			
		||||
			      struct msgb *msg)
 | 
			
		||||
{
 | 
			
		||||
	struct mgcp_endpoint *endp;
 | 
			
		||||
	uint8_t osmux_cid;
 | 
			
		||||
 | 
			
		||||
	if (msg->len < 1 + sizeof(osmux_cid)) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
		     "Discarding truncated Osmux dummy load\n");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LOGP(DLMGCP, LOGL_DEBUG, "Received Osmux dummy load from %s\n",
 | 
			
		||||
	     inet_ntoa(addr->sin_addr));
 | 
			
		||||
 | 
			
		||||
	if (!cfg->osmux) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
		     "bsc wants to use Osmux but bsc-nat did not request it\n");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* extract the osmux CID from the dummy message */
 | 
			
		||||
	memcpy(&osmux_cid, &msg->data[1], sizeof(osmux_cid));
 | 
			
		||||
 | 
			
		||||
	endp = endpoint_lookup(cfg, osmux_cid, &addr->sin_addr, MGCP_DEST_BTS);
 | 
			
		||||
	if (!endp) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
		     "Cannot find endpoint for Osmux CID %d\n", osmux_cid);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (endp->osmux.state == OSMUX_STATE_ENABLED)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	if (osmux_enable_endpoint(endp, &addr->sin_addr, addr->sin_port) < 0 ) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
		     "Could not enable osmux in endpoint %d\n",
 | 
			
		||||
		     ENDPOINT_NUMBER(endp));
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LOGP(DLMGCP, LOGL_INFO, "Enabling osmux in endpoint %d for %s:%u\n",
 | 
			
		||||
	     ENDPOINT_NUMBER(endp), inet_ntoa(addr->sin_addr),
 | 
			
		||||
	     ntohs(addr->sin_port));
 | 
			
		||||
out:
 | 
			
		||||
	msgb_free(msg);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int osmux_read_from_bsc_cb(struct osmo_fd *ofd, unsigned int what)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg;
 | 
			
		||||
	struct osmux_hdr *osmuxh;
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
	struct sockaddr_in addr;
 | 
			
		||||
	struct mgcp_config *cfg = ofd->data;
 | 
			
		||||
	uint32_t rem;
 | 
			
		||||
 | 
			
		||||
	msg = osmux_recv(ofd, &addr);
 | 
			
		||||
	if (!msg)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* not any further processing dummy messages */
 | 
			
		||||
	if (msg->data[0] == MGCP_DUMMY_LOAD)
 | 
			
		||||
		return osmux_handle_dummy(cfg, &addr, msg);
 | 
			
		||||
 | 
			
		||||
	rem = msg->len;
 | 
			
		||||
	while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) {
 | 
			
		||||
		struct mgcp_endpoint *endp;
 | 
			
		||||
 | 
			
		||||
		/* Yes, we use MGCP_DEST_BTS to locate the origin */
 | 
			
		||||
		endp = endpoint_lookup(cfg, osmuxh->circuit_id,
 | 
			
		||||
				       &addr.sin_addr, MGCP_DEST_BTS);
 | 
			
		||||
		if (!endp) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
			     "Cannot find an endpoint for circuit_id=%d\n",
 | 
			
		||||
			     osmuxh->circuit_id);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
 | 
			
		||||
		endp->osmux.stats.chunks++;
 | 
			
		||||
		rem = msg->len;
 | 
			
		||||
 | 
			
		||||
		osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
 | 
			
		||||
		osmux_tx_sched(&list, scheduled_tx_net_cb, endp);
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	msgb_free(msg);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int osmux_init(int role, struct mgcp_config *cfg)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	switch(role) {
 | 
			
		||||
	case OSMUX_ROLE_BSC:
 | 
			
		||||
		osmux_fd.cb = osmux_read_from_bsc_nat_cb;
 | 
			
		||||
		break;
 | 
			
		||||
	case OSMUX_ROLE_BSC_NAT:
 | 
			
		||||
		osmux_fd.cb = osmux_read_from_bsc_cb;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "wrong role for OSMUX\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	osmux_fd.data = cfg;
 | 
			
		||||
 | 
			
		||||
	ret = mgcp_create_bind(cfg->osmux_addr, &osmux_fd, cfg->osmux_port);
 | 
			
		||||
	if (ret < 0) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "cannot bind OSMUX socket\n");
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	mgcp_set_ip_tos(osmux_fd.fd, cfg->endp_dscp);
 | 
			
		||||
	osmux_fd.when |= BSC_FD_READ;
 | 
			
		||||
 | 
			
		||||
	ret = osmo_fd_register(&osmux_fd);
 | 
			
		||||
	if (ret < 0) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "cannot register OSMUX socket\n");
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	cfg->osmux_init = 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
	/* If osmux is enabled, initialize the output handler. This handler is
 | 
			
		||||
	 * used to reconstruct the RTP flow from osmux. The RTP SSRC is
 | 
			
		||||
	 * allocated based on the circuit ID (endp->osmux.cid), which is unique
 | 
			
		||||
	 * in the local scope to the BSC/BSC-NAT. We use it to divide the RTP
 | 
			
		||||
	 * SSRC space (2^32) by the 256 possible circuit IDs, then randomly
 | 
			
		||||
	 * select one value from that window. Thus, we have no chance to have
 | 
			
		||||
	 * overlapping RTP SSRC traveling to the BTSes behind the BSC,
 | 
			
		||||
	 * similarly, for flows traveling to the MSC.
 | 
			
		||||
	 */
 | 
			
		||||
	static const uint32_t rtp_ssrc_winlen = UINT32_MAX / 256;
 | 
			
		||||
 | 
			
		||||
	if (endp->osmux.state == OSMUX_STATE_DISABLED) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "Endpoint %u didn't request Osmux\n",
 | 
			
		||||
		     ENDPOINT_NUMBER(endp));
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	osmux_xfrm_output_init(&endp->osmux.out,
 | 
			
		||||
			       (endp->osmux.cid * rtp_ssrc_winlen) +
 | 
			
		||||
			       (random() % rtp_ssrc_winlen));
 | 
			
		||||
 | 
			
		||||
	endp->osmux.in = osmux_handle_lookup(endp->cfg, addr, port);
 | 
			
		||||
	if (!endp->osmux.in) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "Cannot allocate input osmux handle\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	if (!osmux_xfrm_input_open_circuit(endp->osmux.in, endp->osmux.cid,
 | 
			
		||||
					   endp->cfg->osmux_dummy)) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR, "Cannot open osmux circuit %u\n",
 | 
			
		||||
		     endp->osmux.cid);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (endp->cfg->role) {
 | 
			
		||||
		case MGCP_BSC_NAT:
 | 
			
		||||
			endp->type = MGCP_OSMUX_BSC_NAT;
 | 
			
		||||
			break;
 | 
			
		||||
		case MGCP_BSC:
 | 
			
		||||
			endp->type = MGCP_OSMUX_BSC;
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	endp->osmux.state = OSMUX_STATE_ENABLED;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void osmux_disable_endpoint(struct mgcp_endpoint *endp)
 | 
			
		||||
{
 | 
			
		||||
	LOGP(DLMGCP, LOGL_INFO, "Releasing endpoint %u using Osmux CID %u\n",
 | 
			
		||||
	     ENDPOINT_NUMBER(endp), endp->osmux.cid);
 | 
			
		||||
	osmux_xfrm_input_close_circuit(endp->osmux.in, endp->osmux.cid);
 | 
			
		||||
	endp->osmux.state = OSMUX_STATE_DISABLED;
 | 
			
		||||
	endp->osmux.cid = -1;
 | 
			
		||||
	osmux_handle_put(endp->osmux.in);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void osmux_release_cid(struct mgcp_endpoint *endp)
 | 
			
		||||
{
 | 
			
		||||
	if (endp->osmux.allocated_cid >= 0)
 | 
			
		||||
		osmux_put_cid(endp->osmux.allocated_cid);
 | 
			
		||||
	endp->osmux.allocated_cid = -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void osmux_allocate_cid(struct mgcp_endpoint *endp)
 | 
			
		||||
{
 | 
			
		||||
	osmux_release_cid(endp);
 | 
			
		||||
	endp->osmux.allocated_cid = osmux_get_cid();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* We don't need to send the dummy load for osmux so often as another endpoint
 | 
			
		||||
 * may have already punched the hole in the firewall. This approach is simple
 | 
			
		||||
 * though.
 | 
			
		||||
 */
 | 
			
		||||
int osmux_send_dummy(struct mgcp_endpoint *endp)
 | 
			
		||||
{
 | 
			
		||||
	char buf[1 + sizeof(uint8_t)];
 | 
			
		||||
	struct in_addr addr_unset = {};
 | 
			
		||||
 | 
			
		||||
	buf[0] = MGCP_DUMMY_LOAD;
 | 
			
		||||
	memcpy(&buf[1], &endp->osmux.cid, sizeof(endp->osmux.cid));
 | 
			
		||||
 | 
			
		||||
	/* Wait until we have the connection information from MDCX */
 | 
			
		||||
	if (memcmp(&endp->net_end.addr, &addr_unset, sizeof(addr_unset)) == 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (endp->osmux.state == OSMUX_STATE_ACTIVATING) {
 | 
			
		||||
		if (osmux_enable_endpoint(endp, &endp->net_end.addr,
 | 
			
		||||
					  htons(endp->cfg->osmux_port)) < 0) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
			     "Could not activate osmux in endpoint %d\n",
 | 
			
		||||
			     ENDPOINT_NUMBER(endp));
 | 
			
		||||
		}
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
		     "Osmux CID %u for %s:%u is now enabled\n",
 | 
			
		||||
		     endp->osmux.cid, inet_ntoa(endp->net_end.addr),
 | 
			
		||||
		     endp->cfg->osmux_port);
 | 
			
		||||
	}
 | 
			
		||||
	LOGP(DLMGCP, LOGL_DEBUG,
 | 
			
		||||
	     "sending OSMUX dummy load to %s CID %u\n",
 | 
			
		||||
	     inet_ntoa(endp->net_end.addr), endp->osmux.cid);
 | 
			
		||||
 | 
			
		||||
	return mgcp_udp_send(osmux_fd.fd, &endp->net_end.addr,
 | 
			
		||||
			     htons(endp->cfg->osmux_port), buf, sizeof(buf));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* bsc-nat allocates/releases the Osmux circuit ID */
 | 
			
		||||
static uint8_t osmux_cid_bitmap[(OSMUX_CID_MAX + 1) / 8];
 | 
			
		||||
 | 
			
		||||
int osmux_used_cid(void)
 | 
			
		||||
{
 | 
			
		||||
	int i, j, used = 0;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sizeof(osmux_cid_bitmap); i++) {
 | 
			
		||||
		for (j = 0; j < 8; j++) {
 | 
			
		||||
			if (osmux_cid_bitmap[i] & (1 << j))
 | 
			
		||||
				used += 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return used;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int osmux_get_cid(void)
 | 
			
		||||
{
 | 
			
		||||
	int i, j;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sizeof(osmux_cid_bitmap); i++) {
 | 
			
		||||
		for (j = 0; j < 8; j++) {
 | 
			
		||||
			if (osmux_cid_bitmap[i] & (1 << j))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			osmux_cid_bitmap[i] |= (1 << j);
 | 
			
		||||
			LOGP(DLMGCP, LOGL_DEBUG,
 | 
			
		||||
			     "Allocating Osmux CID %u from pool\n", (i * 8) + j);
 | 
			
		||||
			return (i * 8) + j;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LOGP(DLMGCP, LOGL_ERROR, "All Osmux circuits are in use!\n");
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void osmux_put_cid(uint8_t osmux_cid)
 | 
			
		||||
{
 | 
			
		||||
	LOGP(DLMGCP, LOGL_DEBUG, "Osmux CID %u is back to the pool\n", osmux_cid);
 | 
			
		||||
	osmux_cid_bitmap[osmux_cid / 8] &= ~(1 << (osmux_cid % 8));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1640
									
								
								src/libosmo-legacy-mgcp/mgcp_protocol.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1640
									
								
								src/libosmo-legacy-mgcp/mgcp_protocol.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										305
									
								
								src/libosmo-legacy-mgcp/mgcp_sdp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								src/libosmo-legacy-mgcp/mgcp_sdp.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,305 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Some SDP file parsing...
 | 
			
		||||
 *
 | 
			
		||||
 * (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
 | 
			
		||||
 * (C) 2009-2014 by On-Waves
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <osmocom/legacy_mgcp/mgcp.h>
 | 
			
		||||
#include <osmocom/legacy_mgcp/mgcp_internal.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
struct sdp_rtp_map {
 | 
			
		||||
	/* the type */
 | 
			
		||||
	int payload_type;
 | 
			
		||||
	/* null, static or later dynamic codec name */
 | 
			
		||||
	char *codec_name;
 | 
			
		||||
	/* A pointer to the original line for later parsing */
 | 
			
		||||
	char *map_line;
 | 
			
		||||
 | 
			
		||||
	int rate;
 | 
			
		||||
	int channels;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
 | 
			
		||||
			int payload_type, const char *audio_name)
 | 
			
		||||
{
 | 
			
		||||
	int rate = codec->rate;
 | 
			
		||||
	int channels = codec->channels;
 | 
			
		||||
	char audio_codec[64];
 | 
			
		||||
 | 
			
		||||
	talloc_free(codec->subtype_name);
 | 
			
		||||
	codec->subtype_name = NULL;
 | 
			
		||||
	talloc_free(codec->audio_name);
 | 
			
		||||
	codec->audio_name = NULL;
 | 
			
		||||
 | 
			
		||||
	if (payload_type != PTYPE_UNDEFINED)
 | 
			
		||||
		codec->payload_type = payload_type;
 | 
			
		||||
 | 
			
		||||
	if (!audio_name) {
 | 
			
		||||
		switch (payload_type) {
 | 
			
		||||
		case 0: audio_name = "PCMU/8000/1"; break;
 | 
			
		||||
		case 3: audio_name = "GSM/8000/1"; break;
 | 
			
		||||
		case 8: audio_name = "PCMA/8000/1"; break;
 | 
			
		||||
		case 18: audio_name = "G729/8000/1"; break;
 | 
			
		||||
		default:
 | 
			
		||||
			 /* Payload type is unknown, don't change rate and
 | 
			
		||||
			  * channels. */
 | 
			
		||||
			 /* TODO: return value? */
 | 
			
		||||
			 return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sscanf(audio_name, "%63[^/]/%d/%d",
 | 
			
		||||
		   audio_codec, &rate, &channels) < 1)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	codec->rate = rate;
 | 
			
		||||
	codec->channels = channels;
 | 
			
		||||
	codec->subtype_name = talloc_strdup(ctx, audio_codec);
 | 
			
		||||
	codec->audio_name = talloc_strdup(ctx, audio_name);
 | 
			
		||||
 | 
			
		||||
	if (!strcmp(audio_codec, "G729")) {
 | 
			
		||||
		codec->frame_duration_num = 10;
 | 
			
		||||
		codec->frame_duration_den = 1000;
 | 
			
		||||
	} else {
 | 
			
		||||
		codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM;
 | 
			
		||||
		codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (payload_type < 0) {
 | 
			
		||||
		payload_type = 96;
 | 
			
		||||
		if (rate == 8000 && channels == 1) {
 | 
			
		||||
			if (!strcmp(audio_codec, "GSM"))
 | 
			
		||||
				payload_type = 3;
 | 
			
		||||
			else if (!strcmp(audio_codec, "PCMA"))
 | 
			
		||||
				payload_type = 8;
 | 
			
		||||
			else if (!strcmp(audio_codec, "PCMU"))
 | 
			
		||||
				payload_type = 0;
 | 
			
		||||
			else if (!strcmp(audio_codec, "G729"))
 | 
			
		||||
				payload_type = 18;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		codec->payload_type = payload_type;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (channels != 1)
 | 
			
		||||
		LOGP(DLMGCP, LOGL_NOTICE,
 | 
			
		||||
		     "Channels != 1 in SDP: '%s'\n", audio_name);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < used; ++i) {
 | 
			
		||||
		switch (codecs[i].payload_type) {
 | 
			
		||||
		case 0:
 | 
			
		||||
			codecs[i].codec_name = "PCMU";
 | 
			
		||||
			codecs[i].rate = 8000;
 | 
			
		||||
			codecs[i].channels = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 3:
 | 
			
		||||
			codecs[i].codec_name = "GSM";
 | 
			
		||||
			codecs[i].rate = 8000;
 | 
			
		||||
			codecs[i].channels = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 8:
 | 
			
		||||
			codecs[i].codec_name = "PCMA";
 | 
			
		||||
			codecs[i].rate = 8000;
 | 
			
		||||
			codecs[i].channels = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 18:
 | 
			
		||||
			codecs[i].codec_name = "G729";
 | 
			
		||||
			codecs[i].rate = 8000;
 | 
			
		||||
			codecs[i].channels = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int payload, char *audio_name)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < used; ++i) {
 | 
			
		||||
		char audio_codec[64];
 | 
			
		||||
		int rate = -1;
 | 
			
		||||
		int channels = -1;
 | 
			
		||||
		if (codecs[i].payload_type != payload)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (sscanf(audio_name, "%63[^/]/%d/%d",
 | 
			
		||||
				audio_codec, &rate, &channels) < 1) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR, "Failed to parse '%s'\n", audio_name);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		codecs[i].map_line = talloc_strdup(ctx, audio_name);
 | 
			
		||||
		codecs[i].codec_name = talloc_strdup(ctx, audio_codec);
 | 
			
		||||
		codecs[i].rate = rate;
 | 
			
		||||
		codecs[i].channels = channels;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LOGP(DLMGCP, LOGL_ERROR, "Unconfigured PT(%d) with %s\n", payload, audio_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec)
 | 
			
		||||
{
 | 
			
		||||
	char *bts_codec;
 | 
			
		||||
	char audio_codec[64];
 | 
			
		||||
 | 
			
		||||
	if (!codec->codec_name)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * GSM, GSM/8000 and GSM/8000/1 should all be compatible.. let's go
 | 
			
		||||
	 * by name first.
 | 
			
		||||
	 */
 | 
			
		||||
	bts_codec = endp->tcfg->audio_name;
 | 
			
		||||
	if (sscanf(bts_codec, "%63[^/]/%*d/%*d", audio_codec) < 1)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return strcasecmp(audio_codec, codec->codec_name) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
 | 
			
		||||
{
 | 
			
		||||
	struct sdp_rtp_map codecs[10];
 | 
			
		||||
	int codecs_used = 0;
 | 
			
		||||
	char *line;
 | 
			
		||||
	int maxptime = -1;
 | 
			
		||||
	int i;
 | 
			
		||||
	int codecs_assigned = 0;
 | 
			
		||||
	void *tmp_ctx = talloc_new(NULL);
 | 
			
		||||
 | 
			
		||||
	memset(&codecs, 0, sizeof(codecs));
 | 
			
		||||
 | 
			
		||||
	for_each_line(line, p->save) {
 | 
			
		||||
		switch (line[0]) {
 | 
			
		||||
		case 'o':
 | 
			
		||||
		case 's':
 | 
			
		||||
		case 't':
 | 
			
		||||
		case 'v':
 | 
			
		||||
			/* skip these SDP attributes */
 | 
			
		||||
			break;
 | 
			
		||||
		case 'a': {
 | 
			
		||||
			int payload;
 | 
			
		||||
			int ptime, ptime2 = 0;
 | 
			
		||||
			char audio_name[64];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			if (sscanf(line, "a=rtpmap:%d %63s",
 | 
			
		||||
				   &payload, audio_name) == 2) {
 | 
			
		||||
				codecs_update(tmp_ctx, codecs, codecs_used, payload, audio_name);
 | 
			
		||||
			} else if (sscanf(line, "a=ptime:%d-%d",
 | 
			
		||||
					  &ptime, &ptime2) >= 1) {
 | 
			
		||||
				if (ptime2 > 0 && ptime2 != ptime)
 | 
			
		||||
					rtp->packet_duration_ms = 0;
 | 
			
		||||
				else
 | 
			
		||||
					rtp->packet_duration_ms = ptime;
 | 
			
		||||
			} else if (sscanf(line, "a=maxptime:%d", &ptime2) == 1) {
 | 
			
		||||
				maxptime = ptime2;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case 'm': {
 | 
			
		||||
			int port, rc;
 | 
			
		||||
 | 
			
		||||
			rc = sscanf(line, "m=audio %d RTP/AVP %d %d %d %d %d %d %d %d %d %d",
 | 
			
		||||
					&port,
 | 
			
		||||
					&codecs[0].payload_type,
 | 
			
		||||
					&codecs[1].payload_type,
 | 
			
		||||
					&codecs[2].payload_type,
 | 
			
		||||
					&codecs[3].payload_type,
 | 
			
		||||
					&codecs[4].payload_type,
 | 
			
		||||
					&codecs[5].payload_type,
 | 
			
		||||
					&codecs[6].payload_type,
 | 
			
		||||
					&codecs[7].payload_type,
 | 
			
		||||
					&codecs[8].payload_type,
 | 
			
		||||
					&codecs[9].payload_type);
 | 
			
		||||
			if (rc >= 2) {
 | 
			
		||||
				rtp->rtp_port = htons(port);
 | 
			
		||||
				rtp->rtcp_port = htons(port + 1);
 | 
			
		||||
				codecs_used = rc - 1;
 | 
			
		||||
				codecs_initialize(tmp_ctx, codecs, codecs_used);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case 'c': {
 | 
			
		||||
			char ipv4[16];
 | 
			
		||||
 | 
			
		||||
			if (sscanf(line, "c=IN IP4 %15s", ipv4) == 1) {
 | 
			
		||||
				inet_aton(ipv4, &rtp->addr);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		default:
 | 
			
		||||
			if (p->endp)
 | 
			
		||||
				LOGP(DLMGCP, LOGL_NOTICE,
 | 
			
		||||
				     "Unhandled SDP option: '%c'/%d on 0x%x\n",
 | 
			
		||||
				     line[0], line[0], ENDPOINT_NUMBER(p->endp));
 | 
			
		||||
			else
 | 
			
		||||
				LOGP(DLMGCP, LOGL_NOTICE,
 | 
			
		||||
				     "Unhandled SDP option: '%c'/%d\n",
 | 
			
		||||
				     line[0], line[0]);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Now select the primary and alt_codec */
 | 
			
		||||
	for (i = 0; i < codecs_used && codecs_assigned < 2; ++i) {
 | 
			
		||||
		struct mgcp_rtp_codec *codec = codecs_assigned == 0 ?
 | 
			
		||||
					&rtp->codec : &rtp->alt_codec;
 | 
			
		||||
 | 
			
		||||
		if (endp->tcfg->no_audio_transcoding &&
 | 
			
		||||
			!is_codec_compatible(endp, &codecs[i])) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_NOTICE, "Skipping codec %s\n",
 | 
			
		||||
				codecs[i].codec_name);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mgcp_set_audio_info(p->cfg, codec,
 | 
			
		||||
					codecs[i].payload_type,
 | 
			
		||||
					codecs[i].map_line);
 | 
			
		||||
		codecs_assigned += 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (codecs_assigned > 0) {
 | 
			
		||||
		/* TODO/XXX: Store this per codec and derive it on use */
 | 
			
		||||
		if (maxptime >= 0 && maxptime * rtp->codec.frame_duration_den >
 | 
			
		||||
				rtp->codec.frame_duration_num * 1500) {
 | 
			
		||||
			/* more than 1 frame */
 | 
			
		||||
			rtp->packet_duration_ms = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		LOGP(DLMGCP, LOGL_NOTICE,
 | 
			
		||||
		     "Got media info via SDP: port %d, payload %d (%s), "
 | 
			
		||||
		     "duration %d, addr %s\n",
 | 
			
		||||
		     ntohs(rtp->rtp_port), rtp->codec.payload_type,
 | 
			
		||||
		     rtp->codec.subtype_name ? rtp->codec.subtype_name : "unknown",
 | 
			
		||||
		     rtp->packet_duration_ms, inet_ntoa(rtp->addr));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	talloc_free(tmp_ctx);
 | 
			
		||||
	return codecs_assigned > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										611
									
								
								src/libosmo-legacy-mgcp/mgcp_transcode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										611
									
								
								src/libosmo-legacy-mgcp/mgcp_transcode.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,611 @@
 | 
			
		||||
/*
 | 
			
		||||
 * (C) 2014 by On-Waves
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "g711common.h"
 | 
			
		||||
 | 
			
		||||
#include <osmocom/legacy_mgcp/mgcp.h>
 | 
			
		||||
#include <osmocom/legacy_mgcp/mgcp_internal.h>
 | 
			
		||||
#include <osmocom/legacy_mgcp/mgcp_transcode.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/talloc.h>
 | 
			
		||||
#include <osmocom/netif/rtp.h>
 | 
			
		||||
 | 
			
		||||
int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst)
 | 
			
		||||
{
 | 
			
		||||
	struct mgcp_process_rtp_state *state = state_;
 | 
			
		||||
	if (dst)
 | 
			
		||||
		return (nsamples >= 0 ?
 | 
			
		||||
			nsamples / state->dst_samples_per_frame :
 | 
			
		||||
			1) * state->dst_frame_size;
 | 
			
		||||
	else
 | 
			
		||||
		return (nsamples >= 0 ?
 | 
			
		||||
			nsamples / state->src_samples_per_frame :
 | 
			
		||||
			1) * state->src_frame_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum audio_format get_audio_format(const struct mgcp_rtp_codec *codec)
 | 
			
		||||
{
 | 
			
		||||
	if (codec->subtype_name) {
 | 
			
		||||
		if (!strcasecmp("GSM", codec->subtype_name))
 | 
			
		||||
			return AF_GSM;
 | 
			
		||||
		if (!strcasecmp("PCMA", codec->subtype_name))
 | 
			
		||||
			return AF_PCMA;
 | 
			
		||||
		if (!strcasecmp("PCMU", codec->subtype_name))
 | 
			
		||||
			return AF_PCMU;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
		if (!strcasecmp("G729", codec->subtype_name))
 | 
			
		||||
			return AF_G729;
 | 
			
		||||
#endif
 | 
			
		||||
		if (!strcasecmp("L16", codec->subtype_name))
 | 
			
		||||
			return AF_L16;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (codec->payload_type) {
 | 
			
		||||
	case 0 /* PCMU */:
 | 
			
		||||
		return AF_PCMU;
 | 
			
		||||
	case 3 /* GSM */:
 | 
			
		||||
		return AF_GSM;
 | 
			
		||||
	case 8 /* PCMA */:
 | 
			
		||||
		return AF_PCMA;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
	case 18 /* G.729 */:
 | 
			
		||||
		return AF_G729;
 | 
			
		||||
#endif
 | 
			
		||||
	case 11 /* L16 */:
 | 
			
		||||
		return AF_L16;
 | 
			
		||||
	default:
 | 
			
		||||
		return AF_INVALID;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void l16_encode(short *sample, unsigned char *buf, size_t n)
 | 
			
		||||
{
 | 
			
		||||
	for (; n > 0; --n, ++sample, buf += 2) {
 | 
			
		||||
		buf[0] = sample[0] >> 8;
 | 
			
		||||
		buf[1] = sample[0] & 0xff;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void l16_decode(unsigned char *buf, short *sample, size_t n)
 | 
			
		||||
{
 | 
			
		||||
	for (; n > 0; --n, ++sample, buf += 2)
 | 
			
		||||
		sample[0] = ((short)buf[0] << 8) | buf[1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void alaw_encode(short *sample, unsigned char *buf, size_t n)
 | 
			
		||||
{
 | 
			
		||||
	for (; n > 0; --n)
 | 
			
		||||
		*(buf++) = s16_to_alaw(*(sample++));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void alaw_decode(unsigned char *buf, short *sample, size_t n)
 | 
			
		||||
{
 | 
			
		||||
	for (; n > 0; --n)
 | 
			
		||||
		*(sample++) = alaw_to_s16(*(buf++));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ulaw_encode(short *sample, unsigned char *buf, size_t n)
 | 
			
		||||
{
 | 
			
		||||
	for (; n > 0; --n)
 | 
			
		||||
		*(buf++) = s16_to_ulaw(*(sample++));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ulaw_decode(unsigned char *buf, short *sample, size_t n)
 | 
			
		||||
{
 | 
			
		||||
	for (; n > 0; --n)
 | 
			
		||||
		*(sample++) = ulaw_to_s16(*(buf++));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int processing_state_destructor(struct mgcp_process_rtp_state *state)
 | 
			
		||||
{
 | 
			
		||||
	switch (state->src_fmt) {
 | 
			
		||||
	case AF_GSM:
 | 
			
		||||
		if (state->src.gsm_handle)
 | 
			
		||||
			gsm_destroy(state->src.gsm_handle);
 | 
			
		||||
		break;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
	case AF_G729:
 | 
			
		||||
		if (state->src.g729_dec)
 | 
			
		||||
			closeBcg729DecoderChannel(state->src.g729_dec);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	switch (state->dst_fmt) {
 | 
			
		||||
	case AF_GSM:
 | 
			
		||||
		if (state->dst.gsm_handle)
 | 
			
		||||
			gsm_destroy(state->dst.gsm_handle);
 | 
			
		||||
		break;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
	case AF_G729:
 | 
			
		||||
		if (state->dst.g729_enc)
 | 
			
		||||
			closeBcg729EncoderChannel(state->dst.g729_enc);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
 | 
			
		||||
			   struct mgcp_rtp_end *dst_end,
 | 
			
		||||
			   struct mgcp_rtp_end *src_end)
 | 
			
		||||
{
 | 
			
		||||
	struct mgcp_process_rtp_state *state;
 | 
			
		||||
	enum audio_format src_fmt, dst_fmt;
 | 
			
		||||
	const struct mgcp_rtp_codec *dst_codec = &dst_end->codec;
 | 
			
		||||
 | 
			
		||||
	/* cleanup first */
 | 
			
		||||
	if (dst_end->rtp_process_data) {
 | 
			
		||||
		talloc_free(dst_end->rtp_process_data);
 | 
			
		||||
		dst_end->rtp_process_data = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!src_end)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	const struct mgcp_rtp_codec *src_codec = &src_end->codec;
 | 
			
		||||
 | 
			
		||||
	if (endp->tcfg->no_audio_transcoding) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_NOTICE,
 | 
			
		||||
			"Transcoding disabled on endpoint 0x%x\n",
 | 
			
		||||
			ENDPOINT_NUMBER(endp));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	src_fmt = get_audio_format(src_codec);
 | 
			
		||||
	dst_fmt = get_audio_format(dst_codec);
 | 
			
		||||
 | 
			
		||||
	LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
	     "Checking transcoding: %s (%d) -> %s (%d)\n",
 | 
			
		||||
	     src_codec->subtype_name, src_codec->payload_type,
 | 
			
		||||
	     dst_codec->subtype_name, dst_codec->payload_type);
 | 
			
		||||
 | 
			
		||||
	if (src_fmt == AF_INVALID || dst_fmt == AF_INVALID) {
 | 
			
		||||
		if (!src_codec->subtype_name || !dst_codec->subtype_name)
 | 
			
		||||
			/* Not enough info, do nothing */
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		if (strcasecmp(src_codec->subtype_name, dst_codec->subtype_name) == 0)
 | 
			
		||||
			/* Nothing to do */
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
		     "Cannot transcode: %s codec not supported (%s -> %s).\n",
 | 
			
		||||
		     src_fmt != AF_INVALID ? "destination" : "source",
 | 
			
		||||
		     src_codec->audio_name, dst_codec->audio_name);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (src_codec->rate && dst_codec->rate && src_codec->rate != dst_codec->rate) {
 | 
			
		||||
		LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
		     "Cannot transcode: rate conversion (%d -> %d) not supported.\n",
 | 
			
		||||
		     src_codec->rate, dst_codec->rate);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	state = talloc_zero(endp->tcfg->cfg, struct mgcp_process_rtp_state);
 | 
			
		||||
	talloc_set_destructor(state, processing_state_destructor);
 | 
			
		||||
	dst_end->rtp_process_data = state;
 | 
			
		||||
 | 
			
		||||
	state->src_fmt = src_fmt;
 | 
			
		||||
 | 
			
		||||
	switch (state->src_fmt) {
 | 
			
		||||
	case AF_L16:
 | 
			
		||||
	case AF_S16:
 | 
			
		||||
		state->src_frame_size = 80 * sizeof(short);
 | 
			
		||||
		state->src_samples_per_frame = 80;
 | 
			
		||||
		break;
 | 
			
		||||
	case AF_GSM:
 | 
			
		||||
		state->src_frame_size = sizeof(gsm_frame);
 | 
			
		||||
		state->src_samples_per_frame = 160;
 | 
			
		||||
		state->src.gsm_handle = gsm_create();
 | 
			
		||||
		if (!state->src.gsm_handle) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
			     "Failed to initialize GSM decoder.\n");
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
	case AF_G729:
 | 
			
		||||
		state->src_frame_size = 10;
 | 
			
		||||
		state->src_samples_per_frame = 80;
 | 
			
		||||
		state->src.g729_dec = initBcg729DecoderChannel();
 | 
			
		||||
		if (!state->src.g729_dec) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
			     "Failed to initialize G.729 decoder.\n");
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	case AF_PCMU:
 | 
			
		||||
	case AF_PCMA:
 | 
			
		||||
		state->src_frame_size = 80;
 | 
			
		||||
		state->src_samples_per_frame = 80;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	state->dst_fmt = dst_fmt;
 | 
			
		||||
 | 
			
		||||
	switch (state->dst_fmt) {
 | 
			
		||||
	case AF_L16:
 | 
			
		||||
	case AF_S16:
 | 
			
		||||
		state->dst_frame_size = 80*sizeof(short);
 | 
			
		||||
		state->dst_samples_per_frame = 80;
 | 
			
		||||
		break;
 | 
			
		||||
	case AF_GSM:
 | 
			
		||||
		state->dst_frame_size = sizeof(gsm_frame);
 | 
			
		||||
		state->dst_samples_per_frame = 160;
 | 
			
		||||
		state->dst.gsm_handle = gsm_create();
 | 
			
		||||
		if (!state->dst.gsm_handle) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
			     "Failed to initialize GSM encoder.\n");
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
	case AF_G729:
 | 
			
		||||
		state->dst_frame_size = 10;
 | 
			
		||||
		state->dst_samples_per_frame = 80;
 | 
			
		||||
		state->dst.g729_enc = initBcg729EncoderChannel();
 | 
			
		||||
		if (!state->dst.g729_enc) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
			     "Failed to initialize G.729 decoder.\n");
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	case AF_PCMU:
 | 
			
		||||
	case AF_PCMA:
 | 
			
		||||
		state->dst_frame_size = 80;
 | 
			
		||||
		state->dst_samples_per_frame = 80;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dst_end->force_output_ptime)
 | 
			
		||||
		state->dst_packet_duration = mgcp_rtp_packet_duration(endp, dst_end);
 | 
			
		||||
 | 
			
		||||
	LOGP(DLMGCP, LOGL_INFO,
 | 
			
		||||
	     "Initialized RTP processing on: 0x%x "
 | 
			
		||||
	     "conv: %d (%d, %d, %s) -> %d (%d, %d, %s)\n",
 | 
			
		||||
	     ENDPOINT_NUMBER(endp),
 | 
			
		||||
	     src_fmt, src_codec->payload_type, src_codec->rate, src_end->fmtp_extra,
 | 
			
		||||
	     dst_fmt, dst_codec->payload_type, dst_codec->rate, dst_end->fmtp_extra);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp,
 | 
			
		||||
					  int *payload_type,
 | 
			
		||||
					  const char**audio_name,
 | 
			
		||||
					  const char**fmtp_extra)
 | 
			
		||||
{
 | 
			
		||||
	struct mgcp_process_rtp_state *state = endp->net_end.rtp_process_data;
 | 
			
		||||
	struct mgcp_rtp_codec *net_codec = &endp->net_end.codec;
 | 
			
		||||
	struct mgcp_rtp_codec *bts_codec = &endp->bts_end.codec;
 | 
			
		||||
 | 
			
		||||
	if (!state || net_codec->payload_type < 0) {
 | 
			
		||||
		*payload_type = bts_codec->payload_type;
 | 
			
		||||
		*audio_name = bts_codec->audio_name;
 | 
			
		||||
		*fmtp_extra = endp->bts_end.fmtp_extra;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*payload_type = net_codec->payload_type;
 | 
			
		||||
	*audio_name = net_codec->audio_name;
 | 
			
		||||
	*fmtp_extra = endp->net_end.fmtp_extra;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int decode_audio(struct mgcp_process_rtp_state *state,
 | 
			
		||||
			uint8_t **src, size_t *nbytes)
 | 
			
		||||
{
 | 
			
		||||
	while (*nbytes >= state->src_frame_size) {
 | 
			
		||||
		if (state->sample_cnt + state->src_samples_per_frame > ARRAY_SIZE(state->samples)) {
 | 
			
		||||
			LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
			     "Sample buffer too small: %zu > %zu.\n",
 | 
			
		||||
			     state->sample_cnt + state->src_samples_per_frame,
 | 
			
		||||
			     ARRAY_SIZE(state->samples));
 | 
			
		||||
			return -ENOSPC;
 | 
			
		||||
		}
 | 
			
		||||
		switch (state->src_fmt) {
 | 
			
		||||
		case AF_GSM:
 | 
			
		||||
			if (gsm_decode(state->src.gsm_handle,
 | 
			
		||||
				       (gsm_byte *)*src, state->samples + state->sample_cnt) < 0) {
 | 
			
		||||
				LOGP(DLMGCP, LOGL_ERROR,
 | 
			
		||||
				     "Failed to decode GSM.\n");
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
		case AF_G729:
 | 
			
		||||
			bcg729Decoder(state->src.g729_dec, *src, 0, state->samples + state->sample_cnt);
 | 
			
		||||
			break;
 | 
			
		||||
#endif
 | 
			
		||||
		case AF_PCMU:
 | 
			
		||||
			ulaw_decode(*src, state->samples + state->sample_cnt,
 | 
			
		||||
				    state->src_samples_per_frame);
 | 
			
		||||
			break;
 | 
			
		||||
		case AF_PCMA:
 | 
			
		||||
			alaw_decode(*src, state->samples + state->sample_cnt,
 | 
			
		||||
				    state->src_samples_per_frame);
 | 
			
		||||
			break;
 | 
			
		||||
		case AF_S16:
 | 
			
		||||
			memmove(state->samples + state->sample_cnt, *src,
 | 
			
		||||
				state->src_frame_size);
 | 
			
		||||
			break;
 | 
			
		||||
		case AF_L16:
 | 
			
		||||
			l16_decode(*src, state->samples + state->sample_cnt,
 | 
			
		||||
				   state->src_samples_per_frame);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		*src        += state->src_frame_size;
 | 
			
		||||
		*nbytes     -= state->src_frame_size;
 | 
			
		||||
		state->sample_cnt += state->src_samples_per_frame;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int encode_audio(struct mgcp_process_rtp_state *state,
 | 
			
		||||
			uint8_t *dst, size_t buf_size, size_t max_samples)
 | 
			
		||||
{
 | 
			
		||||
	int nbytes = 0;
 | 
			
		||||
	size_t nsamples = 0;
 | 
			
		||||
	/* Encode samples into dst */
 | 
			
		||||
	while (nsamples + state->dst_samples_per_frame <= max_samples) {
 | 
			
		||||
		if (nbytes + state->dst_frame_size > buf_size) {
 | 
			
		||||
			if (nbytes > 0)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			/* Not even one frame fits into the buffer */
 | 
			
		||||
			LOGP(DLMGCP, LOGL_INFO,
 | 
			
		||||
			     "Encoding (RTP) buffer too small: %zu > %zu.\n",
 | 
			
		||||
			     nbytes + state->dst_frame_size, buf_size);
 | 
			
		||||
			return -ENOSPC;
 | 
			
		||||
		}
 | 
			
		||||
		switch (state->dst_fmt) {
 | 
			
		||||
		case AF_GSM:
 | 
			
		||||
			gsm_encode(state->dst.gsm_handle,
 | 
			
		||||
				   state->samples + state->sample_offs, dst);
 | 
			
		||||
			break;
 | 
			
		||||
#ifdef HAVE_BCG729
 | 
			
		||||
		case AF_G729:
 | 
			
		||||
			bcg729Encoder(state->dst.g729_enc,
 | 
			
		||||
				      state->samples + state->sample_offs, dst);
 | 
			
		||||
			break;
 | 
			
		||||
#endif
 | 
			
		||||
		case AF_PCMU:
 | 
			
		||||
			ulaw_encode(state->samples + state->sample_offs, dst,
 | 
			
		||||
				    state->src_samples_per_frame);
 | 
			
		||||
			break;
 | 
			
		||||
		case AF_PCMA:
 | 
			
		||||
			alaw_encode(state->samples + state->sample_offs, dst,
 | 
			
		||||
				    state->src_samples_per_frame);
 | 
			
		||||
			break;
 | 
			
		||||
		case AF_S16:
 | 
			
		||||
			memmove(dst, state->samples + state->sample_offs,
 | 
			
		||||
				state->dst_frame_size);
 | 
			
		||||
			break;
 | 
			
		||||
		case AF_L16:
 | 
			
		||||
			l16_encode(state->samples + state->sample_offs, dst,
 | 
			
		||||
				   state->src_samples_per_frame);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		dst        += state->dst_frame_size;
 | 
			
		||||
		nbytes     += state->dst_frame_size;
 | 
			
		||||
		state->sample_offs += state->dst_samples_per_frame;
 | 
			
		||||
		nsamples   += state->dst_samples_per_frame;
 | 
			
		||||
	}
 | 
			
		||||
	state->sample_cnt -= nsamples;
 | 
			
		||||
	return nbytes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct mgcp_rtp_end *source_for_dest(struct mgcp_endpoint *endp,
 | 
			
		||||
					struct mgcp_rtp_end *dst_end)
 | 
			
		||||
{
 | 
			
		||||
	if (&endp->bts_end == dst_end)
 | 
			
		||||
		return &endp->net_end;
 | 
			
		||||
	else if (&endp->net_end == dst_end)
 | 
			
		||||
		return &endp->bts_end;
 | 
			
		||||
	OSMO_ASSERT(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * With some modems we get offered multiple codecs
 | 
			
		||||
 * and we have selected one of them. It might not
 | 
			
		||||
 * be the right one and we need to detect this with
 | 
			
		||||
 * the first audio packets. One difficulty is that
 | 
			
		||||
 * we patch the rtp payload type in place, so we
 | 
			
		||||
 * need to discuss this.
 | 
			
		||||
 */
 | 
			
		||||
struct mgcp_process_rtp_state *check_transcode_state(
 | 
			
		||||
				struct mgcp_endpoint *endp,
 | 
			
		||||
				struct mgcp_rtp_end *dst_end,
 | 
			
		||||
				struct rtp_hdr *rtp_hdr)
 | 
			
		||||
{
 | 
			
		||||
	struct mgcp_rtp_end *src_end;
 | 
			
		||||
 | 
			
		||||
	/* Only deal with messages from net to bts */
 | 
			
		||||
	if (&endp->bts_end != dst_end)
 | 
			
		||||
		goto done;
 | 
			
		||||
 | 
			
		||||
	src_end = source_for_dest(endp, dst_end);
 | 
			
		||||
 | 
			
		||||
	/* Already patched */
 | 
			
		||||
	if (rtp_hdr->payload_type == dst_end->codec.payload_type)
 | 
			
		||||
		goto done;
 | 
			
		||||
	/* The payload we expect */
 | 
			
		||||
	if (rtp_hdr->payload_type == src_end->codec.payload_type)
 | 
			
		||||
		goto done;
 | 
			
		||||
	/* The matching alternate payload type? Then switch */
 | 
			
		||||
	if (rtp_hdr->payload_type == src_end->alt_codec.payload_type) {
 | 
			
		||||
		struct mgcp_config *cfg = endp->cfg;
 | 
			
		||||
		struct mgcp_rtp_codec tmp_codec = src_end->alt_codec;
 | 
			
		||||
		src_end->alt_codec = src_end->codec;
 | 
			
		||||
		src_end->codec = tmp_codec;
 | 
			
		||||
		cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end);
 | 
			
		||||
		cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
	return dst_end->rtp_process_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
 | 
			
		||||
				struct mgcp_rtp_end *dst_end,
 | 
			
		||||
			     char *data, int *len, int buf_size)
 | 
			
		||||
{
 | 
			
		||||
	struct mgcp_process_rtp_state *state;
 | 
			
		||||
	const size_t rtp_hdr_size = sizeof(struct rtp_hdr);
 | 
			
		||||
	struct rtp_hdr *rtp_hdr = (struct rtp_hdr *) data;
 | 
			
		||||
	char *payload_data = (char *) &rtp_hdr->data[0];
 | 
			
		||||
	int payload_len = *len - rtp_hdr_size;
 | 
			
		||||
	uint8_t *src = (uint8_t *)payload_data;
 | 
			
		||||
	uint8_t *dst = (uint8_t *)payload_data;
 | 
			
		||||
	size_t nbytes = payload_len;
 | 
			
		||||
	size_t nsamples;
 | 
			
		||||
	size_t max_samples;
 | 
			
		||||
	uint32_t ts_no;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	state = check_transcode_state(endp, dst_end, rtp_hdr);
 | 
			
		||||
	if (!state)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (state->src_fmt == state->dst_fmt) {
 | 
			
		||||
		if (!state->dst_packet_duration)
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		/* TODO: repackage without transcoding */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* If the remaining samples do not fit into a fixed ptime,
 | 
			
		||||
	 * a) discard them, if the next packet is much later
 | 
			
		||||
	 * b) add silence and * send it, if the current packet is not
 | 
			
		||||
	 *    yet too late
 | 
			
		||||
	 * c) append the sample data, if the timestamp matches exactly
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/* TODO: check payload type (-> G.711 comfort noise) */
 | 
			
		||||
 | 
			
		||||
	if (payload_len > 0) {
 | 
			
		||||
		ts_no = ntohl(rtp_hdr->timestamp);
 | 
			
		||||
		if (!state->is_running) {
 | 
			
		||||
			state->next_seq = ntohs(rtp_hdr->sequence);
 | 
			
		||||
			state->next_time = ts_no;
 | 
			
		||||
			state->is_running = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		if (state->sample_cnt > 0) {
 | 
			
		||||
			int32_t delta = ts_no - state->next_time;
 | 
			
		||||
			/* TODO: check sequence? reordering? packet loss? */
 | 
			
		||||
 | 
			
		||||
			if (delta > state->sample_cnt) {
 | 
			
		||||
				/* There is a time gap between the last packet
 | 
			
		||||
				 * and the current one. Just discard the
 | 
			
		||||
				 * partial data that is left in the buffer.
 | 
			
		||||
				 * TODO: This can be improved by adding silence
 | 
			
		||||
				 * instead if the delta is small enough.
 | 
			
		||||
				 */
 | 
			
		||||
				LOGP(DLMGCP, LOGL_NOTICE,
 | 
			
		||||
					"0x%x dropping sample buffer due delta=%d sample_cnt=%zu\n",
 | 
			
		||||
					ENDPOINT_NUMBER(endp), delta, state->sample_cnt);
 | 
			
		||||
				state->sample_cnt = 0;
 | 
			
		||||
				state->next_time = ts_no;
 | 
			
		||||
			} else if (delta < 0) {
 | 
			
		||||
				LOGP(DLMGCP, LOGL_NOTICE,
 | 
			
		||||
				     "RTP time jumps backwards, delta = %d, "
 | 
			
		||||
				     "discarding buffered samples\n",
 | 
			
		||||
				     delta);
 | 
			
		||||
				state->sample_cnt = 0;
 | 
			
		||||
				state->sample_offs = 0;
 | 
			
		||||
				return -EAGAIN;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Make sure the samples start without offset */
 | 
			
		||||
			if (state->sample_offs && state->sample_cnt)
 | 
			
		||||
				memmove(&state->samples[0],
 | 
			
		||||
					&state->samples[state->sample_offs],
 | 
			
		||||
					state->sample_cnt *
 | 
			
		||||
					sizeof(state->samples[0]));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		state->sample_offs = 0;
 | 
			
		||||
 | 
			
		||||
		/* Append decoded audio to samples */
 | 
			
		||||
		decode_audio(state, &src, &nbytes);
 | 
			
		||||
 | 
			
		||||
		if (nbytes > 0)
 | 
			
		||||
			LOGP(DLMGCP, LOGL_NOTICE,
 | 
			
		||||
			     "Skipped audio frame in RTP packet: %zu octets\n",
 | 
			
		||||
			     nbytes);
 | 
			
		||||
	} else
 | 
			
		||||
		ts_no = state->next_time;
 | 
			
		||||
 | 
			
		||||
	if (state->sample_cnt < state->dst_packet_duration)
 | 
			
		||||
		return -EAGAIN;
 | 
			
		||||
 | 
			
		||||
	max_samples =
 | 
			
		||||
		state->dst_packet_duration ?
 | 
			
		||||
		state->dst_packet_duration : state->sample_cnt;
 | 
			
		||||
 | 
			
		||||
	nsamples = state->sample_cnt;
 | 
			
		||||
 | 
			
		||||
	rc = encode_audio(state, dst, buf_size, max_samples);
 | 
			
		||||
	/*
 | 
			
		||||
	 * There were no samples to encode?
 | 
			
		||||
	 * TODO: how does this work for comfort noise?
 | 
			
		||||
	 */
 | 
			
		||||
	if (rc == 0)
 | 
			
		||||
		return -ENOMSG;
 | 
			
		||||
	/* Any other error during the encoding */
 | 
			
		||||
	if (rc < 0)
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
	nsamples -= state->sample_cnt;
 | 
			
		||||
 | 
			
		||||
	*len = rtp_hdr_size + rc;
 | 
			
		||||
	rtp_hdr->sequence = htons(state->next_seq);
 | 
			
		||||
	rtp_hdr->timestamp = htonl(ts_no);
 | 
			
		||||
 | 
			
		||||
	state->next_seq += 1;
 | 
			
		||||
	state->next_time = ts_no + nsamples;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * XXX: At this point we should always have consumed
 | 
			
		||||
	 * samples. So doing OSMO_ASSERT(nsamples > 0) and returning
 | 
			
		||||
	 * rtp_hdr_size should be fine.
 | 
			
		||||
	 */
 | 
			
		||||
	return nsamples ? rtp_hdr_size : 0;
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user