mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-10-23 08:12:01 +00:00
Compare commits
47 Commits
pmaier/mgw
...
laforge/si
Author | SHA1 | Date | |
---|---|---|---|
|
8e22379d7d | ||
|
1bc597c752 | ||
|
19c430feba | ||
|
3ba409558e | ||
|
60be627557 | ||
|
8cfe7df3f1 | ||
|
ba94b6d7be | ||
|
30e01355f6 | ||
|
06624e13d4 | ||
|
19539866e5 | ||
|
1dc2dcebbf | ||
|
6049a63d1d | ||
|
3ef8e76534 | ||
|
fbf07f3f69 | ||
|
de133113a0 | ||
|
6d0a59a1bf | ||
|
2491401932 | ||
|
fbbe8f2f98 | ||
|
71d42e778a | ||
|
8a2a1b22fe | ||
|
a790f0c082 | ||
|
0ab152b2c6 | ||
|
2741d6bb0e | ||
|
74d0e5c318 | ||
|
c4ef4a21c6 | ||
|
ee2f33bf9a | ||
|
531470a0ca | ||
|
9dc73593a3 | ||
|
ae6858bddf | ||
|
99d4d368e8 | ||
|
8667d5169d | ||
|
1add5a53cb | ||
|
729bf3e45a | ||
|
2f34b53b5b | ||
|
ad79f9eb99 | ||
|
9e494e67c7 | ||
|
5322473d04 | ||
|
c57ad7ff9a | ||
|
c59b5c533d | ||
|
0653cc8a7c | ||
|
246233d0d4 | ||
|
a910a81b7c | ||
|
c8acee2234 | ||
|
55863e42c1 | ||
|
6177cae2a2 | ||
|
6af3ccf65d | ||
|
03cb5f3397 |
@@ -24,3 +24,5 @@
|
||||
# If any interfaces have been removed or changed since the last public release, a=0.
|
||||
#
|
||||
#library what description / commit summary line
|
||||
osmo-mgw update osmo-gsm-manuals dependency to > 0.3.0 for vty_cpu_sched.adoc include
|
||||
libosmo-mgcp-client mgcp_response, mgcp_conn_peer struct size change, breaks ABI
|
||||
|
12
configure.ac
12
configure.ac
@@ -47,13 +47,13 @@ AC_SEARCH_LIBS([dlsym], [dl dld], [LIBRARY_DLSYM="$LIBS";LIBS=""])
|
||||
AC_SUBST(LIBRARY_DLSYM)
|
||||
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.1.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.1.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.1.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.1.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.4.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.4.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.4.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.4.0)
|
||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.6.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.6.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.6.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.0.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 1.0.0)
|
||||
|
||||
AC_ARG_ENABLE(sanitize,
|
||||
[AS_HELP_STRING(
|
||||
|
@@ -35,6 +35,8 @@ BuildRequires: pkgconfig(libosmoctrl) >= 1.1.0
|
||||
BuildRequires: pkgconfig(libosmogsm) >= 1.0.0
|
||||
BuildRequires: pkgconfig(libosmovty) >= 1.0.0
|
||||
BuildRequires: pkgconfig(libosmocoding) >= 1.0.0
|
||||
BuildRequires: pkgconfig(libosmoabis) >= 1.0.0
|
||||
BuildRequires: pkgconfig(libosmotrau) >= 1.0.0
|
||||
%{?systemd_requires}
|
||||
|
||||
%description
|
||||
@@ -111,6 +113,7 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
|
||||
%dir %{_docdir}/%{name}/examples
|
||||
%dir %{_docdir}/%{name}/examples/osmo-mgw
|
||||
%{_docdir}/%{name}/examples/osmo-mgw/osmo-mgw.cfg
|
||||
%{_docdir}/%{name}/examples/osmo-mgw/osmo-mgw-abis_e1.cfg
|
||||
%{_bindir}/osmo-mgw
|
||||
%{_unitdir}/osmo-mgw.service
|
||||
%dir %{_sysconfdir}/osmocom
|
||||
|
11
contrib/simcom2rtp/Makefile
Normal file
11
contrib/simcom2rtp/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
CFLAGS:= -O2 -g -Wall $(shell pkg-config --cflags libosmocore libosmotrau)
|
||||
LIBS:= $(shell pkg-config --libs libosmocore libosmotrau)
|
||||
|
||||
all: osmo-simcom2rtp
|
||||
|
||||
osmo-simcom2rtp: g711.o g711_table.o simcom2rtp.o
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $^
|
||||
|
313
contrib/simcom2rtp/g711.c
Normal file
313
contrib/simcom2rtp/g711.c
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* December 30, 1994:
|
||||
* Functions linear2alaw, linear2ulaw have been updated to correctly
|
||||
* convert unquantized 16 bit values.
|
||||
* Tables for direct u- to A-law and A- to u-law conversions have been
|
||||
* corrected.
|
||||
* Borge Lindberg, Center for PersonKommunikation, Aalborg University.
|
||||
* bli@cpk.auc.dk
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Downloaded from comp.speech site in Cambridge.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "g711.h"
|
||||
|
||||
/*
|
||||
* g711.c
|
||||
*
|
||||
* u-law, A-law and linear PCM conversions.
|
||||
* Source: http://www.speech.kth.se/cost250/refsys/latest/src/g711.c
|
||||
*/
|
||||
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
|
||||
#define QUANT_MASK (0xf) /* Quantization field mask. */
|
||||
#define NSEGS (8) /* Number of A-law segments. */
|
||||
#define SEG_SHIFT (4) /* Left shift for segment number. */
|
||||
#define SEG_MASK (0x70) /* Segment field mask. */
|
||||
|
||||
static short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
|
||||
0x1FF, 0x3FF, 0x7FF, 0xFFF};
|
||||
static short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
|
||||
0x3FF, 0x7FF, 0xFFF, 0x1FFF};
|
||||
|
||||
/* copy from CCITT G.711 specifications */
|
||||
unsigned char _u2a[128] = { /* u- to A-law conversions */
|
||||
1, 1, 2, 2, 3, 3, 4, 4,
|
||||
5, 5, 6, 6, 7, 7, 8, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24,
|
||||
25, 27, 29, 31, 33, 34, 35, 36,
|
||||
37, 38, 39, 40, 41, 42, 43, 44,
|
||||
46, 48, 49, 50, 51, 52, 53, 54,
|
||||
55, 56, 57, 58, 59, 60, 61, 62,
|
||||
64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79,
|
||||
/* corrected:
|
||||
81, 82, 83, 84, 85, 86, 87, 88,
|
||||
should be: */
|
||||
80, 82, 83, 84, 85, 86, 87, 88,
|
||||
89, 90, 91, 92, 93, 94, 95, 96,
|
||||
97, 98, 99, 100, 101, 102, 103, 104,
|
||||
105, 106, 107, 108, 109, 110, 111, 112,
|
||||
113, 114, 115, 116, 117, 118, 119, 120,
|
||||
121, 122, 123, 124, 125, 126, 127, 128};
|
||||
|
||||
unsigned char _a2u[128] = { /* A- to u-law conversions */
|
||||
1, 3, 5, 7, 9, 11, 13, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 32, 33, 33, 34, 34, 35, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43,
|
||||
44, 45, 46, 47, 48, 48, 49, 49,
|
||||
50, 51, 52, 53, 54, 55, 56, 57,
|
||||
58, 59, 60, 61, 62, 63, 64, 64,
|
||||
65, 66, 67, 68, 69, 70, 71, 72,
|
||||
/* corrected:
|
||||
73, 74, 75, 76, 77, 78, 79, 79,
|
||||
should be: */
|
||||
73, 74, 75, 76, 77, 78, 79, 80,
|
||||
80, 81, 82, 83, 84, 85, 86, 87,
|
||||
88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99, 100, 101, 102, 103,
|
||||
104, 105, 106, 107, 108, 109, 110, 111,
|
||||
112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127};
|
||||
|
||||
static short search(
|
||||
short val,
|
||||
short *table,
|
||||
short size)
|
||||
{
|
||||
short i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (val <= *table++)
|
||||
return (i);
|
||||
}
|
||||
return (size);
|
||||
}
|
||||
|
||||
/*
|
||||
* linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
|
||||
*
|
||||
* linear2alaw() 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.
|
||||
*/
|
||||
unsigned char
|
||||
linear2alaw(short pcm_val) /* 2's complement (16-bit range) */
|
||||
{
|
||||
short mask;
|
||||
short seg;
|
||||
unsigned char aval;
|
||||
|
||||
pcm_val = pcm_val >> 3;
|
||||
|
||||
if (pcm_val >= 0) {
|
||||
mask = 0xD5; /* sign (7th) bit = 1 */
|
||||
} else {
|
||||
mask = 0x55; /* sign bit = 0 */
|
||||
pcm_val = -pcm_val - 1;
|
||||
}
|
||||
|
||||
/* Convert the scaled magnitude to segment number. */
|
||||
seg = search(pcm_val, seg_aend, 8);
|
||||
|
||||
/* Combine the sign, segment, and quantization bits. */
|
||||
|
||||
if (seg >= 8) /* out of range, return maximum value. */
|
||||
return (unsigned char) (0x7F ^ mask);
|
||||
else {
|
||||
aval = (unsigned char) seg << SEG_SHIFT;
|
||||
if (seg < 2)
|
||||
aval |= (pcm_val >> 1) & QUANT_MASK;
|
||||
else
|
||||
aval |= (pcm_val >> seg) & QUANT_MASK;
|
||||
return (aval ^ mask);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* alaw2linear() - Convert an A-law value to 16-bit linear PCM
|
||||
*
|
||||
*/
|
||||
short
|
||||
alaw2linear(
|
||||
unsigned char a_val)
|
||||
{
|
||||
short t;
|
||||
short seg;
|
||||
|
||||
a_val ^= 0x55;
|
||||
|
||||
t = (a_val & QUANT_MASK) << 4;
|
||||
seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
|
||||
switch (seg) {
|
||||
case 0:
|
||||
t += 8;
|
||||
break;
|
||||
case 1:
|
||||
t += 0x108;
|
||||
break;
|
||||
default:
|
||||
t += 0x108;
|
||||
t <<= seg - 1;
|
||||
}
|
||||
return ((a_val & SIGN_BIT) ? t : -t);
|
||||
}
|
||||
|
||||
#define BIAS (0x84) /* Bias for linear code. */
|
||||
#define CLIP 8159
|
||||
|
||||
/*
|
||||
* linear2ulaw() - 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.
|
||||
*/
|
||||
unsigned char
|
||||
linear2ulaw(
|
||||
short pcm_val) /* 2's complement (16-bit range) */
|
||||
{
|
||||
short mask;
|
||||
short seg;
|
||||
unsigned char uval;
|
||||
|
||||
/* Get the sign and the magnitude of the value. */
|
||||
pcm_val = pcm_val >> 2;
|
||||
if (pcm_val < 0) {
|
||||
pcm_val = -pcm_val;
|
||||
mask = 0x7F;
|
||||
} else {
|
||||
mask = 0xFF;
|
||||
}
|
||||
if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */
|
||||
pcm_val += (BIAS >> 2);
|
||||
|
||||
/* Convert the scaled magnitude to segment number. */
|
||||
seg = search(pcm_val, seg_uend, 8);
|
||||
|
||||
/*
|
||||
* Combine the sign, segment, quantization bits;
|
||||
* and complement the code word.
|
||||
*/
|
||||
if (seg >= 8) /* out of range, return maximum value. */
|
||||
return (unsigned char) (0x7F ^ mask);
|
||||
else {
|
||||
uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
|
||||
return (uval ^ mask);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* ulaw2linear() - 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.
|
||||
*/
|
||||
short
|
||||
ulaw2linear(
|
||||
unsigned char u_val)
|
||||
{
|
||||
short 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 & QUANT_MASK) << 3) + BIAS;
|
||||
t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
|
||||
|
||||
return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
|
||||
}
|
||||
|
||||
/* A-law to u-law conversion */
|
||||
unsigned char
|
||||
alaw2ulaw(
|
||||
unsigned char aval)
|
||||
{
|
||||
aval &= 0xff;
|
||||
return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
|
||||
(0x7F ^ _a2u[aval ^ 0x55]));
|
||||
}
|
||||
|
||||
/* u-law to A-law conversion */
|
||||
unsigned char
|
||||
ulaw2alaw(
|
||||
unsigned char uval)
|
||||
{
|
||||
uval &= 0xff;
|
||||
return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
|
||||
(0x55 ^ (_u2a[0x7F ^ uval] - 1)));
|
||||
}
|
||||
|
||||
/* ---------- end of g711.c ----------------------------------------------------- */
|
27
contrib/simcom2rtp/g711.h
Normal file
27
contrib/simcom2rtp/g711.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* g711.h
|
||||
*
|
||||
* u-law, A-law and linear PCM conversions.
|
||||
* Source: http://www.speech.kth.se/cost250/refsys/latest/src/g711.h
|
||||
*/
|
||||
|
||||
#ifndef _G711_H_
|
||||
#define _G711_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
unsigned char linear2alaw(short pcm_val);
|
||||
short alaw2linear(unsigned char a_val);
|
||||
unsigned char linear2ulaw(short pcm_val);
|
||||
short ulaw2linear(unsigned char u_val);
|
||||
unsigned char alaw2ulaw(unsigned char aval);
|
||||
unsigned char ulaw2alaw(unsigned char uval);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _G711_H_ */
|
102
contrib/simcom2rtp/g711_table.c
Normal file
102
contrib/simcom2rtp/g711_table.c
Normal file
@@ -0,0 +1,102 @@
|
||||
#ifndef G711_TABLE_H
|
||||
#define G711_TABLE_H
|
||||
|
||||
#include "g711.h"
|
||||
|
||||
/* 16384 entries per table (16 bit) */
|
||||
unsigned char linear_to_alaw[65536];
|
||||
unsigned char linear_to_ulaw[65536];
|
||||
|
||||
/* 16384 entries per table (8 bit) */
|
||||
unsigned short alaw_to_linear[256];
|
||||
unsigned short ulaw_to_linear[256];
|
||||
|
||||
static void build_linear_to_xlaw_table(unsigned char *linear_to_xlaw,
|
||||
unsigned char (*linear2xlaw)(short))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<65536;i++){
|
||||
linear_to_xlaw[i] = linear2xlaw((short) i);
|
||||
}
|
||||
}
|
||||
|
||||
static void build_xlaw_to_linear_table(unsigned short *xlaw_to_linear,
|
||||
short (*xlaw2linear)(unsigned char))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<256;i++){
|
||||
xlaw_to_linear[i] = (unsigned short) xlaw2linear(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void pcm16_to_xlaw(unsigned char *linear_to_xlaw, int src_length, const char *src_samples, char *dst_samples)
|
||||
{
|
||||
int i;
|
||||
const unsigned short *s_samples;
|
||||
|
||||
s_samples = (const unsigned short *)src_samples;
|
||||
|
||||
for (i=0; i < src_length / 2; i++)
|
||||
{
|
||||
dst_samples[i] = linear_to_xlaw[s_samples[i]];
|
||||
}
|
||||
}
|
||||
|
||||
static void xlaw_to_pcm16(unsigned short *xlaw_to_linear, int src_length, const char *src_samples, char *dst_samples)
|
||||
{
|
||||
int i;
|
||||
unsigned char *s_samples;
|
||||
unsigned short *d_samples;
|
||||
|
||||
s_samples = (unsigned char *) src_samples;
|
||||
d_samples = (unsigned short *)dst_samples;
|
||||
|
||||
for (i=0; i < src_length; i++)
|
||||
{
|
||||
d_samples[i] = xlaw_to_linear[s_samples[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void pcm16_to_alaw(int src_length, const char *src_samples, char *dst_samples)
|
||||
{
|
||||
pcm16_to_xlaw(linear_to_alaw, src_length, src_samples, dst_samples);
|
||||
}
|
||||
|
||||
void pcm16_to_ulaw(int src_length, const char *src_samples, char *dst_samples)
|
||||
{
|
||||
pcm16_to_xlaw(linear_to_ulaw, src_length, src_samples, dst_samples);
|
||||
}
|
||||
|
||||
void alaw_to_pcm16(int src_length, const char *src_samples, char *dst_samples)
|
||||
{
|
||||
xlaw_to_pcm16(alaw_to_linear, src_length, src_samples, dst_samples);
|
||||
}
|
||||
|
||||
void ulaw_to_pcm16(int src_length, const char *src_samples, char *dst_samples)
|
||||
{
|
||||
xlaw_to_pcm16(ulaw_to_linear, src_length, src_samples, dst_samples);
|
||||
}
|
||||
|
||||
void pcm16_alaw_tableinit()
|
||||
{
|
||||
build_linear_to_xlaw_table(linear_to_alaw, linear2alaw);
|
||||
}
|
||||
|
||||
void pcm16_ulaw_tableinit()
|
||||
{
|
||||
build_linear_to_xlaw_table(linear_to_ulaw, linear2ulaw);
|
||||
}
|
||||
|
||||
void alaw_pcm16_tableinit()
|
||||
{
|
||||
build_xlaw_to_linear_table(alaw_to_linear, alaw2linear);
|
||||
}
|
||||
|
||||
void ulaw_pcm16_tableinit()
|
||||
{
|
||||
build_xlaw_to_linear_table(ulaw_to_linear, ulaw2linear);
|
||||
}
|
||||
|
||||
#endif // G711_TABLE_H
|
14
contrib/simcom2rtp/g711_table.h
Normal file
14
contrib/simcom2rtp/g711_table.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef G711_TABLE_H
|
||||
#define G711_TABLE_H
|
||||
|
||||
void pcm16_to_alaw(int length, const char *src_samples, char *dst_samples);
|
||||
void pcm16_to_ulaw(int length, const char *src_samples, char *dst_samples);
|
||||
void alaw_to_pcm16(int length, const char *src_samples, char *dst_samples);
|
||||
void ulaw_to_pcm16(int length, const char *src_samples, char *dst_samples);
|
||||
|
||||
void pcm16_alaw_tableinit();
|
||||
void pcm16_ulaw_tableinit();
|
||||
void alaw_pcm16_tableinit();
|
||||
void ulaw_pcm16_tableinit();
|
||||
|
||||
#endif // G711_TABLE_H
|
218
contrib/simcom2rtp/simcom2rtp.c
Normal file
218
contrib/simcom2rtp/simcom2rtp.c
Normal file
@@ -0,0 +1,218 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/serial.h>
|
||||
|
||||
#include <osmocom/trau/osmo_ortp.h>
|
||||
|
||||
#include "g711.h"
|
||||
|
||||
#define RTP_PT_PCMU 0
|
||||
#define RTP_PT_PCMA 8
|
||||
|
||||
struct modem_state {
|
||||
struct osmo_fd data_fd;
|
||||
struct osmo_rtp_socket *rtp;
|
||||
/* queue of linear PCM audio in RTP -> modem direction */
|
||||
struct llist_head rtp2modem;
|
||||
/* message buffer used if samples insufficient for next RTP frame were received */
|
||||
struct msgb *modem2rtp;
|
||||
};
|
||||
|
||||
static void *g_tall_ctx;
|
||||
|
||||
|
||||
/* call-back on received RTP data */
|
||||
static void ortp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *payload,
|
||||
unsigned int payload_len, uint16_t seq_nr, uint32_t timestamp, bool marker)
|
||||
{
|
||||
/* we received a RTP frame */
|
||||
struct modem_state *ms = rs->priv;
|
||||
struct msgb *msg = msgb_alloc(payload_len*2, "RTP Rx");
|
||||
unsigned int i;
|
||||
int16_t *out;
|
||||
|
||||
OSMO_ASSERT(msg);
|
||||
|
||||
out = (int16_t *) msgb_put(msg, payload_len*2);
|
||||
|
||||
if (payload_len != 160) {
|
||||
fprintf(stderr, "RTP payload length %d != 160, dropping\n", payload_len);
|
||||
msgb_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* convert from Alaw to linear PCM (160 -> 320 bytes) */
|
||||
for (i = 0; i < payload_len; i++)
|
||||
out[i] = alaw2linear(payload[i]);
|
||||
|
||||
/* append to the write queue */
|
||||
msgb_enqueue(&ms->rtp2modem, msg);
|
||||
ms->data_fd.when |= OSMO_FD_WRITE;
|
||||
}
|
||||
|
||||
static void modem2rtp(struct modem_state *ms, const uint8_t *data, unsigned int len)
|
||||
{
|
||||
const int16_t *data16 = (const int16_t *)data;
|
||||
unsigned int samples = len / 2;
|
||||
unsigned int offset = 0;
|
||||
unsigned int i;
|
||||
|
||||
/* samples are always 16bit, we cannot read half a sample */
|
||||
OSMO_ASSERT((len & 1) == 0);
|
||||
|
||||
/* first complete any pending incomplete RTP frame */
|
||||
if (ms->modem2rtp) {
|
||||
struct msgb *msg = ms->modem2rtp;
|
||||
unsigned int missing_samples = 160 - msgb_length(msg);
|
||||
for (i = 0; i < missing_samples; i++) {
|
||||
if (i >= samples)
|
||||
break;
|
||||
msgb_put_u8(msg, linear2alaw(data16[i]));
|
||||
}
|
||||
offset = i;
|
||||
if (msgb_length(msg) == 160) {
|
||||
osmo_rtp_send_frame_ext(ms->rtp, msgb_data(msg), msgb_length(msg), 160, false);
|
||||
msgb_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/* then send as many RTP frames as we have samples */
|
||||
for (offset = offset; offset + 160 <= samples; offset += 160) {
|
||||
uint8_t buf[160];
|
||||
for (i = 0; i < sizeof(buf); i++)
|
||||
buf[i] = linear2alaw(data16[offset + i]);
|
||||
osmo_rtp_send_frame_ext(ms->rtp, buf, sizeof(buf), 160, false);
|
||||
}
|
||||
|
||||
/* store remainder in msgb */
|
||||
if (offset < samples) {
|
||||
struct msgb *msg = msgb_alloc_c(ms, 160, "modem2rtp");
|
||||
OSMO_ASSERT(msg);
|
||||
OSMO_ASSERT(len - offset < 160);
|
||||
for (i = 0; i < len - offset; i++)
|
||||
msgb_put_u8(msg, linear2alaw(data16[offset + i]));
|
||||
ms->modem2rtp = msg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* call back on file descriptor events of the modem DATA ttyUSB device */
|
||||
static int modem_data_fd_cb(struct osmo_fd *ofd, unsigned int what)
|
||||
{
|
||||
struct modem_state *ms = ofd->data;
|
||||
int rc;
|
||||
|
||||
if (what & OSMO_FD_READ) {
|
||||
/* SIM5360 USB AUDIO Application Note v1.01 states 1600 bytes every 100ms */
|
||||
uint8_t rx_buf[1600];
|
||||
rc = read(ofd->fd, rx_buf, sizeof(rx_buf));
|
||||
OSMO_ASSERT(rc > 0);
|
||||
modem2rtp(ms, rx_buf, rc);
|
||||
}
|
||||
|
||||
if (what & OSMO_FD_WRITE) {
|
||||
struct msgb *msg = msgb_dequeue(&ms->rtp2modem);
|
||||
if (!msg)
|
||||
ofd->when &= ~OSMO_FD_WRITE;
|
||||
else {
|
||||
/* SIM5300 USB AUDIO Application Note v1.01 states 640 bytes every 40ms;
|
||||
* we simply write every RTP frame individually (320 bytes every 20ms) */
|
||||
rc = write(ofd->fd, msgb_data(msg), msgb_length(msg));
|
||||
if (rc != msgb_length(msg))
|
||||
fprintf(stderr, "Short write: %d < %u\n", rc, msgb_length(msg));
|
||||
msgb_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int modem_data_open(struct modem_state *ms, const char *basepath)
|
||||
{
|
||||
char fname[PATH_MAX+1];
|
||||
int fd;
|
||||
|
||||
/* the assumption is that the caller provides something like
|
||||
* "/dev/serial/by-path/pci-0000:00:14.0-usb-0:2:1" */
|
||||
snprintf(fname, sizeof(fname), "%s.0-port0", basepath);
|
||||
|
||||
fd = osmo_serial_init(fname, 921600);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "failed to open device '%s': %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
osmo_fd_setup(&ms->data_fd, fd, OSMO_FD_READ, modem_data_fd_cb, ms, 0);
|
||||
osmo_fd_register(&ms->data_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct modem_state *modem_create(void *ctx)
|
||||
{
|
||||
struct modem_state *ms = talloc_zero(ctx, struct modem_state);
|
||||
int rc;
|
||||
|
||||
INIT_LLIST_HEAD(&ms->rtp2modem);
|
||||
|
||||
ms->rtp = osmo_rtp_socket_create(ms, 0);
|
||||
OSMO_ASSERT(ms->rtp);
|
||||
osmo_rtp_socket_set_pt(ms->rtp, RTP_PT_PCMA);
|
||||
ms->rtp->priv = ms;
|
||||
ms->rtp->rx_cb = ortp_rx_cb;
|
||||
|
||||
rc = osmo_rtp_socket_bind(ms->rtp, "0.0.0.0", 1111);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
rc = osmo_rtp_socket_connect(ms->rtp, "127.0.0.1", 2222);
|
||||
//rc = osmo_rtp_socket_autoconnect(ms->rtp);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
osmo_rtp_set_source_desc(ms->rtp, "cname", "simcom2rtp", NULL, NULL, NULL,
|
||||
"osmo-simcom2rtp", NULL);
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
talloc_enable_null_tracking();
|
||||
g_tall_ctx = talloc_named_const(NULL, 1, "simcom2rtp");
|
||||
|
||||
msgb_talloc_ctx_init(g_tall_ctx, 0);
|
||||
osmo_init_logging2(g_tall_ctx, NULL);
|
||||
osmo_fsm_log_timeouts(true);
|
||||
osmo_fsm_log_addr(true);
|
||||
//osmo_stats_init(g_tall_ctx);
|
||||
osmo_rtp_init(g_tall_ctx);
|
||||
|
||||
struct modem_state *ms = modem_create(g_tall_ctx);
|
||||
int rc;
|
||||
|
||||
OSMO_ASSERT(ms);
|
||||
rc = modem_data_open(ms, "/dev/serial/by-path/pci-0000:00:14.0-usb-0:2:1");
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
while (1) {
|
||||
osmo_select_main(0);
|
||||
}
|
||||
|
||||
}
|
5
debian/control
vendored
5
debian/control
vendored
@@ -1,13 +1,14 @@
|
||||
Source: osmo-mgw
|
||||
Section: net
|
||||
Priority: extra
|
||||
Maintainer: Alexander Couzens <lynxis@fe80.eu>
|
||||
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
|
||||
Build-Depends: debhelper (>=9),
|
||||
dh-autoreconf,
|
||||
pkg-config,
|
||||
autotools-dev,
|
||||
libosmocore-dev,
|
||||
libosmocore-dev (>= 1.4.0),
|
||||
libosmo-netif-dev,
|
||||
libosmo-abis-dev,
|
||||
osmo-gsm-manuals-dev
|
||||
Standards-Version: 3.9.8
|
||||
Vcs-Git: git://git.osmocom.org/osmo-mgw.git
|
||||
|
1
debian/osmo-mgw.install
vendored
1
debian/osmo-mgw.install
vendored
@@ -2,3 +2,4 @@ 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
|
||||
|
25
doc/examples/osmo-mgw/osmo-mgw-abis_e1.cfg
Normal file
25
doc/examples/osmo-mgw/osmo-mgw-abis_e1.cfg
Normal file
@@ -0,0 +1,25 @@
|
||||
!
|
||||
! MGCP configuration example
|
||||
!
|
||||
e1_input
|
||||
e1_line 0 driver dahdi
|
||||
e1_line 0 port 0
|
||||
mgcp
|
||||
bind ip 127.0.0.1
|
||||
rtp port-range 4002 16000
|
||||
rtp bind-ip 127.0.0.1
|
||||
rtp ip-probing
|
||||
rtp ip-tos 184
|
||||
bind port 2427
|
||||
sdp audio payload number 98
|
||||
sdp audio payload name GSM
|
||||
number endpoints 31
|
||||
loop 0
|
||||
force-realloc 1
|
||||
rtcp-omit
|
||||
rtp-patch ssrc
|
||||
rtp-patch timestamp
|
||||
trunk 1
|
||||
rtp keep-alive once
|
||||
no rtp keep-alive
|
||||
line 0
|
@@ -24,6 +24,8 @@ include::./common/chapters/osmux/osmux.adoc[]
|
||||
|
||||
//include::{srcdir}/chapters/counters.adoc[]
|
||||
|
||||
include::./common/chapters/vty_cpu_sched.adoc[]
|
||||
|
||||
include::./common/chapters/port_numbers.adoc[]
|
||||
|
||||
include::./common/chapters/bibliography.adoc[]
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <osmocom/core/write_queue.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
@@ -94,7 +95,8 @@ typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
|
||||
*/
|
||||
struct mgcp_port_range {
|
||||
/* addr or NULL to fall-back to default */
|
||||
char *bind_addr;
|
||||
char *bind_addr_v4;
|
||||
char *bind_addr_v6;
|
||||
|
||||
/* dynamically allocated */
|
||||
int range_start;
|
||||
@@ -207,4 +209,4 @@ 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_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
|
||||
int mgcp_udp_send(int fd, struct osmo_sockaddr *addr, int port, char *buf, int len);
|
||||
|
@@ -21,7 +21,6 @@
|
||||
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_init(struct mgcp_trunk *trunk, uint8_t ts_nr);
|
||||
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);
|
||||
|
@@ -26,7 +26,7 @@
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/gsm/i460_mux.h>
|
||||
|
||||
struct sockaddr_in;
|
||||
struct sockaddr;
|
||||
struct mgcp_conn;
|
||||
struct mgcp_conn_rtp;
|
||||
struct mgcp_endpoint;
|
||||
@@ -42,7 +42,7 @@ LOGP(cat, level, "endpoint:%s " fmt, \
|
||||
struct osmo_rtp_msg_ctx {
|
||||
int proto;
|
||||
struct mgcp_conn_rtp *conn_src;
|
||||
struct sockaddr_in *from_addr;
|
||||
struct osmo_sockaddr *from_addr;
|
||||
};
|
||||
|
||||
#define OSMO_RTP_MSG_CTX(MSGB) ((struct osmo_rtp_msg_ctx*)(MSGB)->cb)
|
||||
@@ -139,3 +139,5 @@ struct mgcp_endpoint *mgcp_endp_by_name_trunk(int *cause, const char *epname,
|
||||
struct mgcp_endpoint *mgcp_endp_by_name(int *cause, const char *epname,
|
||||
struct mgcp_config *cfg);
|
||||
bool mgcp_endp_avail(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);
|
||||
|
@@ -2,6 +2,9 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <osmocom/core/socket.h>
|
||||
|
||||
#include <osmocom/mgcp/mgcp.h>
|
||||
|
||||
#define MGCP_DUMMY_LOAD 0x23
|
||||
@@ -78,8 +81,8 @@ struct mgcp_rtp_codec {
|
||||
|
||||
/* 'mgcp_rtp_end': basically a wrapper around the RTP+RTCP ports */
|
||||
struct mgcp_rtp_end {
|
||||
/* local IP address of the RTP socket */
|
||||
struct in_addr addr;
|
||||
/* remote IP address of the RTP socket */
|
||||
struct osmo_sockaddr addr;
|
||||
|
||||
/* in network byte order */
|
||||
int rtp_port, rtcp_port;
|
||||
@@ -115,18 +118,21 @@ struct mgcp_rtp_end {
|
||||
|
||||
/* 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];
|
||||
};
|
||||
|
||||
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 sockaddr_in forward;
|
||||
struct osmo_sockaddr forward;
|
||||
};
|
||||
|
||||
struct mgcp_conn;
|
||||
|
||||
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
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);
|
||||
@@ -140,7 +146,7 @@ void mgcp_free_rtp_port(struct mgcp_rtp_end *end);
|
||||
void mgcp_patch_and_count(struct mgcp_endpoint *endp,
|
||||
struct mgcp_rtp_state *state,
|
||||
struct mgcp_rtp_end *rtp_end,
|
||||
struct sockaddr_in *addr, struct msgb *msg);
|
||||
struct osmo_sockaddr *addr, struct msgb *msg);
|
||||
void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn);
|
||||
int mgcp_set_ip_tos(int fd, int tos);
|
||||
|
||||
|
@@ -24,7 +24,6 @@ struct mgcp_trunk {
|
||||
char *audio_fmtp_extra;
|
||||
int audio_send_ptime;
|
||||
int audio_send_name;
|
||||
int audio_loop;
|
||||
|
||||
int no_audio_transcoding;
|
||||
|
||||
@@ -60,7 +59,6 @@ struct mgcp_trunk {
|
||||
/* E1 specific */
|
||||
struct {
|
||||
unsigned int vty_line_nr;
|
||||
struct e1inp_line *line;
|
||||
bool ts_in_use[31];
|
||||
struct osmo_i460_timeslot i460_ts[31];
|
||||
} e1;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/socket.h>
|
||||
|
||||
#include <osmocom/netif/osmux.h>
|
||||
struct mgcp_conn_rtp;
|
||||
@@ -13,7 +14,7 @@ enum {
|
||||
|
||||
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);
|
||||
struct osmo_sockaddr *addr, uint16_t port);
|
||||
void conn_osmux_disable(struct mgcp_conn_rtp *conn);
|
||||
int conn_osmux_allocate_cid(struct mgcp_conn_rtp *conn, int osmux_cid);
|
||||
void conn_osmux_release_cid(struct mgcp_conn_rtp *conn);
|
||||
|
@@ -6,3 +6,7 @@ enum mgcp_vty_node {
|
||||
MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||
TRUNK_NODE,
|
||||
};
|
||||
|
||||
enum mgw_vty_cmd_attr {
|
||||
MGW_CMD_ATTR_NEWCONN = 0,
|
||||
};
|
||||
|
@@ -6,7 +6,7 @@
|
||||
#include <osmocom/mgcp_client/mgcp_common.h>
|
||||
|
||||
/* See also: RFC 3435, chapter 3.5 Transmission over UDP */
|
||||
#define MGCP_CLIENT_LOCAL_ADDR_DEFAULT "0.0.0.0"
|
||||
#define MGCP_CLIENT_LOCAL_ADDR_DEFAULT NULL /* INADDR(6)_ANY */
|
||||
#define MGCP_CLIENT_LOCAL_PORT_DEFAULT 2727
|
||||
#define MGCP_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1"
|
||||
#define MGCP_CLIENT_REMOTE_PORT_DEFAULT 2427
|
||||
@@ -75,7 +75,7 @@ struct mgcp_response {
|
||||
char *body;
|
||||
struct mgcp_response_head head;
|
||||
uint16_t audio_port;
|
||||
char audio_ip[INET_ADDRSTRLEN];
|
||||
char audio_ip[INET6_ADDRSTRLEN];
|
||||
unsigned int ptime;
|
||||
enum mgcp_codecs codecs[MGCP_MAX_CODECS];
|
||||
unsigned int codecs_len;
|
||||
@@ -133,7 +133,7 @@ int mgcp_client_connect(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);
|
||||
uint32_t mgcp_client_remote_addr_n(struct mgcp_client *mgcp) OSMO_DEPRECATED("deprecated, returns 0");
|
||||
|
||||
const char *mgcp_client_endpoint_domain(const struct mgcp_client *mgcp);
|
||||
const char *mgcp_client_rtpbridge_wildcard(const struct mgcp_client *mgcp);
|
||||
|
@@ -8,14 +8,14 @@
|
||||
* (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[INET_ADDRSTRLEN];
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
|
||||
/*! RTP connection IP-Port (optional) */
|
||||
uint16_t port;
|
||||
|
@@ -6,7 +6,6 @@
|
||||
|
||||
struct mgcp_client {
|
||||
struct mgcp_client_conf actual;
|
||||
uint32_t remote_addr;
|
||||
struct osmo_wqueue wq;
|
||||
mgcp_trans_id_t next_trans_id;
|
||||
struct llist_head responses_pending;
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/byteswap.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <osmocom/core/sockaddr_str.h>
|
||||
|
||||
#include <osmocom/mgcp_client/mgcp_client.h>
|
||||
#include <osmocom/mgcp_client/mgcp_client_internal.h>
|
||||
@@ -370,22 +371,37 @@ static int mgcp_parse_audio_ptime_rtpmap(struct mgcp_response *r, const char *li
|
||||
/* Parse a line like "c=IN IP4 10.11.12.13" */
|
||||
static int mgcp_parse_audio_ip(struct mgcp_response *r, const char *line)
|
||||
{
|
||||
struct in_addr ip_test;
|
||||
struct in6_addr ip_test;
|
||||
bool is_ipv6;
|
||||
|
||||
if (strlen(line) < 16)
|
||||
if (strncmp("c=IN IP", line, 7) != 0)
|
||||
goto response_parse_failure;
|
||||
|
||||
/* The current implementation strictly supports IPV4 only ! */
|
||||
if (memcmp("c=IN IP4 ", line, 9) != 0)
|
||||
line += 7;
|
||||
if (*line == '6')
|
||||
is_ipv6 = true;
|
||||
else if (*line == '4')
|
||||
is_ipv6 = false;
|
||||
else
|
||||
goto response_parse_failure;
|
||||
|
||||
/* Extract IP-Address */
|
||||
osmo_strlcpy(r->audio_ip, line + 9, sizeof(r->audio_ip));
|
||||
|
||||
/* Check IP-Address */
|
||||
if (inet_aton(r->audio_ip, &ip_test) == 0)
|
||||
line++;
|
||||
if (*line != ' ')
|
||||
goto response_parse_failure;
|
||||
line++;
|
||||
|
||||
/* Extract and check IP-Address */
|
||||
if (is_ipv6) {
|
||||
/* 45 = INET6_ADDRSTRLEN -1 */
|
||||
if (sscanf(line, "%45s", r->audio_ip) != 1)
|
||||
goto response_parse_failure;
|
||||
if (inet_pton(AF_INET6, r->audio_ip, &ip_test) != 1)
|
||||
goto response_parse_failure;
|
||||
} else {
|
||||
/* 15 = INET_ADDRSTRLEN -1 */
|
||||
if (sscanf(line, "%15s", r->audio_ip) != 1)
|
||||
goto response_parse_failure;
|
||||
if (inet_pton(AF_INET, r->audio_ip, &ip_test) != 1)
|
||||
goto response_parse_failure;
|
||||
}
|
||||
return 0;
|
||||
|
||||
response_parse_failure:
|
||||
@@ -778,7 +794,7 @@ static int init_socket(struct mgcp_client *mgcp)
|
||||
|
||||
/* Initalize socket with the currently configured port
|
||||
* number */
|
||||
rc = osmo_sock_init2_ofd(&wq->bfd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, mgcp->actual.local_addr,
|
||||
rc = osmo_sock_init2_ofd(&wq->bfd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, mgcp->actual.local_addr,
|
||||
mgcp->actual.local_port, mgcp->actual.remote_addr, mgcp->actual.remote_port,
|
||||
OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT);
|
||||
if (rc > 0)
|
||||
@@ -807,7 +823,6 @@ static int init_socket(struct mgcp_client *mgcp)
|
||||
* \returns 0 on success, -EINVAL on error. */
|
||||
int mgcp_client_connect(struct mgcp_client *mgcp)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
struct osmo_wqueue *wq;
|
||||
int rc;
|
||||
|
||||
@@ -817,6 +832,11 @@ int mgcp_client_connect(struct mgcp_client *mgcp)
|
||||
}
|
||||
|
||||
wq = &mgcp->wq;
|
||||
osmo_wqueue_init(wq, 1024);
|
||||
wq->read_cb = mgcp_do_read;
|
||||
wq->write_cb = mgcp_do_write;
|
||||
|
||||
osmo_fd_setup(&wq->bfd, -1, OSMO_FD_READ, osmo_wqueue_bfd_cb, mgcp, 0);
|
||||
|
||||
rc = init_socket(mgcp);
|
||||
if (rc < 0) {
|
||||
@@ -827,14 +847,6 @@ int mgcp_client_connect(struct mgcp_client *mgcp)
|
||||
goto error_close_fd;
|
||||
}
|
||||
|
||||
inet_aton(mgcp->actual.remote_addr, &addr.sin_addr);
|
||||
mgcp->remote_addr = htonl(addr.sin_addr.s_addr);
|
||||
|
||||
osmo_wqueue_init(wq, 1024);
|
||||
wq->bfd.when = OSMO_FD_READ;
|
||||
wq->bfd.data = mgcp;
|
||||
wq->read_cb = mgcp_do_read;
|
||||
wq->write_cb = mgcp_do_write;
|
||||
|
||||
LOGP(DLMGCP, LOGL_INFO, "MGCP GW connection: %s\n", osmo_sock_get_name2(wq->bfd.fd));
|
||||
|
||||
@@ -861,12 +873,13 @@ uint16_t mgcp_client_remote_port(struct mgcp_client *mgcp)
|
||||
return mgcp->actual.remote_port;
|
||||
}
|
||||
|
||||
/*! Get the IP-Aaddress of the associated MGW as its numeric representation.
|
||||
/*! Get the IP-Address of the associated MGW as its numeric representation.
|
||||
* DEPRECATED, DON'T USE.
|
||||
* \param[in] mgcp MGCP client descriptor.
|
||||
* \returns IP-Address as 32 bit integer (network byte order) */
|
||||
uint32_t mgcp_client_remote_addr_n(struct mgcp_client *mgcp)
|
||||
{
|
||||
return mgcp->remote_addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* To compose endpoint names, usually for CRCX, use this as domain name.
|
||||
@@ -1121,7 +1134,8 @@ static int add_sdp(struct msgb *msg, struct mgcp_msg *mgcp_msg, struct mgcp_clie
|
||||
{
|
||||
unsigned int i;
|
||||
int rc = 0;
|
||||
char local_ip[INET_ADDRSTRLEN];
|
||||
char local_ip[INET6_ADDRSTRLEN];
|
||||
int local_ip_family, audio_ip_family;
|
||||
const char *codec;
|
||||
unsigned int pt;
|
||||
|
||||
@@ -1138,10 +1152,21 @@ static int add_sdp(struct msgb *msg, struct mgcp_msg *mgcp_msg, struct mgcp_clie
|
||||
msgb_free(msg);
|
||||
return -2;
|
||||
}
|
||||
local_ip_family = osmo_ip_str_type(local_ip);
|
||||
if (local_ip_family == AF_UNSPEC) {
|
||||
msgb_free(msg);
|
||||
return -2;
|
||||
}
|
||||
audio_ip_family = osmo_ip_str_type(mgcp_msg->audio_ip);
|
||||
if (audio_ip_family == AF_UNSPEC) {
|
||||
msgb_free(msg);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Add owner/creator (SDP) */
|
||||
rc += msgb_printf(msg, "o=- %x 23 IN IP4 %s\r\n",
|
||||
mgcp_msg->call_id, local_ip);
|
||||
rc += msgb_printf(msg, "o=- %x 23 IN IP%c %s\r\n", mgcp_msg->call_id,
|
||||
local_ip_family == AF_INET6 ? '6' : '4',
|
||||
local_ip);
|
||||
|
||||
/* Add session name (none) */
|
||||
rc += msgb_printf(msg, "s=-\r\n");
|
||||
@@ -1159,7 +1184,9 @@ static int add_sdp(struct msgb *msg, struct mgcp_msg *mgcp_msg, struct mgcp_clie
|
||||
msgb_free(msg);
|
||||
return -2;
|
||||
}
|
||||
rc += msgb_printf(msg, "c=IN IP4 %s\r\n", mgcp_msg->audio_ip);
|
||||
rc += msgb_printf(msg, "c=IN IP%c %s\r\n",
|
||||
audio_ip_family == AF_INET6 ? '6' : '4',
|
||||
mgcp_msg->audio_ip);
|
||||
|
||||
/* Add time description, active time (SDP) */
|
||||
rc += msgb_printf(msg, "t=0 0\r\n");
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/core/byteswap.h>
|
||||
#include <osmocom/core/tdef.h>
|
||||
#include <osmocom/core/sockaddr_str.h>
|
||||
|
||||
#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h>
|
||||
|
||||
@@ -235,8 +236,6 @@ static void fill_event_names()
|
||||
}
|
||||
}
|
||||
|
||||
/* T_defs is used to obtain an (Osmocom specific) T2427001: timeout for an MGCP response (note, 2427 corresponds to the
|
||||
* default MGCP port in osmo-mgw). */
|
||||
static __attribute__((constructor)) void osmo_mgcpc_ep_fsm_init()
|
||||
{
|
||||
OSMO_ASSERT(osmo_fsm_register(&osmo_mgcpc_ep_fsm) == 0);
|
||||
@@ -468,14 +467,12 @@ static void on_success(struct osmo_mgcpc_ep_ci *ci, void *data)
|
||||
|
||||
ci->pending = false;
|
||||
|
||||
rtp_info = data;
|
||||
|
||||
switch (ci->verb) {
|
||||
case MGCP_VERB_CRCX:
|
||||
/* If we sent a wildcarded endpoint name on CRCX, we need to store the resulting endpoint
|
||||
* name here. Also, we receive the MGW's RTP port information. */
|
||||
rtp_info = data;
|
||||
OSMO_ASSERT(rtp_info);
|
||||
ci->got_port_info = true;
|
||||
ci->rtp_info = *rtp_info;
|
||||
osmo_strlcpy(ci->mgcp_ci_str, mgcp_conn_get_ci(ci->mgcp_client_fi),
|
||||
sizeof(ci->mgcp_ci_str));
|
||||
if (rtp_info->endpoint[0]) {
|
||||
@@ -485,6 +482,15 @@ static void on_success(struct osmo_mgcpc_ep_ci *ci, void *data)
|
||||
return;
|
||||
}
|
||||
ci->ep->first_crcx_complete = true;
|
||||
OSMO_ASSERT(rtp_info);
|
||||
/* fall through */
|
||||
case MGCP_VERB_MDCX:
|
||||
/* Always update the received RTP ip/port information, since MGW
|
||||
* may provide new one after remote end params changed */
|
||||
if (rtp_info) {
|
||||
ci->got_port_info = true;
|
||||
ci->rtp_info = *rtp_info;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -517,17 +523,33 @@ const struct mgcp_conn_peer *osmo_mgcpc_ep_ci_get_rtp_info(const struct osmo_mgc
|
||||
bool osmo_mgcpc_ep_ci_get_crcx_info_to_sockaddr(const struct osmo_mgcpc_ep_ci *ci, struct sockaddr_storage *dest)
|
||||
{
|
||||
const struct mgcp_conn_peer *rtp_info;
|
||||
int family;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
rtp_info = osmo_mgcpc_ep_ci_get_rtp_info(ci);
|
||||
if (!rtp_info)
|
||||
return false;
|
||||
|
||||
sin = (struct sockaddr_in *)dest;
|
||||
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr.s_addr = inet_addr(rtp_info->addr);
|
||||
sin->sin_port = osmo_ntohs(rtp_info->port);
|
||||
family = osmo_ip_str_type(rtp_info->addr);
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
sin = (struct sockaddr_in *)dest;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_port = osmo_ntohs(rtp_info->port);
|
||||
if (inet_pton(AF_INET, rtp_info->addr, &sin->sin_addr) != 1)
|
||||
return false;
|
||||
break;
|
||||
case AF_INET6:
|
||||
sin6 = (struct sockaddr_in6 *)dest;
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = osmo_ntohs(rtp_info->port);
|
||||
if (inet_pton(AF_INET6, rtp_info->addr, &sin6->sin6_addr) != 1)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -547,7 +569,7 @@ bool osmo_mgcpc_ep_ci_get_crcx_info_to_osmux_cid(const struct osmo_mgcpc_ep_ci *
|
||||
}
|
||||
|
||||
static const struct osmo_tdef_state_timeout osmo_mgcpc_ep_fsm_timeouts[32] = {
|
||||
[OSMO_MGCPC_EP_ST_WAIT_MGW_RESPONSE] = { .T=2427001 },
|
||||
[OSMO_MGCPC_EP_ST_WAIT_MGW_RESPONSE] = { .T=-2427 },
|
||||
};
|
||||
|
||||
/* Transition to a state, using the T timer defined in assignment_fsm_timeouts.
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <osmocom/core/byteswap.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/sockaddr_str.h>
|
||||
|
||||
/* Context information, this is attached to the priv pointer of the FSM and
|
||||
* is also handed back when dispatcheing events to the parent FSM. This is
|
||||
@@ -522,8 +523,8 @@ static void fsm_cleanup_cb(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause ca
|
||||
* connection. This is not the normal case. The user should always use
|
||||
* mgcp_conn_delete() to instruct the FSM to perform a graceful exit */
|
||||
if (strlen(mgcp_ctx->conn_id)) {
|
||||
LOGPFSML(fi, LOGL_ERROR,
|
||||
"MGW/DLCX: abrupt FSM termination with connections still present, sending unconditional DLCX...\n");
|
||||
LOGPFSML(fi, LOGL_NOTICE,
|
||||
"MGW/DLCX: FSM termination with connections still present, sending unconditional DLCX...\n");
|
||||
msg = make_dlcx_msg(mgcp_ctx);
|
||||
if (!msg)
|
||||
LOGPFSML(fi, LOGL_ERROR, "MGW/DLCX: Error composing DLCX message\n");
|
||||
@@ -607,14 +608,16 @@ struct osmo_fsm_inst *mgcp_conn_create(struct mgcp_client *mgcp, struct osmo_fsm
|
||||
{
|
||||
struct mgcp_ctx *mgcp_ctx;
|
||||
struct osmo_fsm_inst *fi;
|
||||
struct in_addr ip_test;
|
||||
struct in6_addr ip_test;
|
||||
|
||||
|
||||
OSMO_ASSERT(parent_fi);
|
||||
OSMO_ASSERT(mgcp);
|
||||
OSMO_ASSERT(conn_peer);
|
||||
|
||||
/* Check if IP/Port information in conn info makes sense */
|
||||
if (conn_peer->port && inet_aton(conn_peer->addr, &ip_test) == 0)
|
||||
if (conn_peer->port && inet_pton(osmo_ip_str_type(conn_peer->addr),
|
||||
conn_peer->addr, &ip_test) != 1)
|
||||
return NULL;
|
||||
|
||||
/* Allocate and configure a new fsm instance */
|
||||
@@ -644,7 +647,7 @@ int mgcp_conn_modify(struct osmo_fsm_inst *fi, uint32_t parent_evt, struct mgcp_
|
||||
{
|
||||
OSMO_ASSERT(fi);
|
||||
struct mgcp_ctx *mgcp_ctx = fi->priv;
|
||||
struct in_addr ip_test;
|
||||
struct in6_addr ip_test;
|
||||
|
||||
OSMO_ASSERT(mgcp_ctx);
|
||||
OSMO_ASSERT(conn_peer);
|
||||
@@ -668,8 +671,8 @@ int mgcp_conn_modify(struct osmo_fsm_inst *fi, uint32_t parent_evt, struct mgcp_
|
||||
LOGPFSML(fi, LOGL_ERROR, "Cannot MDCX, port == 0\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (inet_aton(conn_peer->addr, &ip_test) == 0) {
|
||||
LOGPFSML(fi, LOGL_ERROR, "Cannot MDCX, IP address == 0.0.0.0\n");
|
||||
if (inet_pton(osmo_ip_str_type(conn_peer->addr), conn_peer->addr, &ip_test) != 1) {
|
||||
LOGPFSML(fi, LOGL_ERROR, "Cannot MDCX, IP address %s\n", conn_peer->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@@ -36,9 +36,10 @@ void *global_mgcp_client_ctx = NULL;
|
||||
struct mgcp_client_conf *global_mgcp_client_conf = NULL;
|
||||
|
||||
DEFUN(cfg_mgw_local_ip, cfg_mgw_local_ip_cmd,
|
||||
"mgw local-ip A.B.C.D",
|
||||
"mgw local-ip " VTY_IPV46_CMD,
|
||||
MGW_STR "local bind to connect to MGW from\n"
|
||||
"local bind IP address\n")
|
||||
"local bind IPv4 address\n"
|
||||
"local bind IPv6 address\n")
|
||||
{
|
||||
if (!global_mgcp_client_conf)
|
||||
return CMD_ERR_NOTHING_TODO;
|
||||
@@ -69,9 +70,10 @@ ALIAS_DEPRECATED(cfg_mgw_local_port, cfg_mgcpgw_local_port_cmd,
|
||||
"local bind port\n")
|
||||
|
||||
DEFUN(cfg_mgw_remote_ip, cfg_mgw_remote_ip_cmd,
|
||||
"mgw remote-ip A.B.C.D",
|
||||
"mgw remote-ip " VTY_IPV46_CMD,
|
||||
MGW_STR "remote IP address to reach the MGW at\n"
|
||||
"remote IP address\n")
|
||||
"remote IPv4 address\n"
|
||||
"remote IPv6 address\n")
|
||||
{
|
||||
if (!global_mgcp_client_conf)
|
||||
return CMD_ERR_NOTHING_TODO;
|
||||
@@ -188,21 +190,21 @@ void mgcp_client_vty_init(void *talloc_ctx, int node, struct mgcp_client_conf *c
|
||||
global_mgcp_client_ctx = talloc_ctx;
|
||||
global_mgcp_client_conf = conf;
|
||||
|
||||
install_element(node, &cfg_mgw_local_ip_cmd);
|
||||
install_element(node, &cfg_mgw_local_port_cmd);
|
||||
install_element(node, &cfg_mgw_remote_ip_cmd);
|
||||
install_element(node, &cfg_mgw_remote_port_cmd);
|
||||
install_element(node, &cfg_mgw_endpoint_range_cmd);
|
||||
install_element(node, &cfg_mgw_rtp_bts_base_port_cmd);
|
||||
install_element(node, &cfg_mgw_endpoint_domain_name_cmd);
|
||||
install_lib_element(node, &cfg_mgw_local_ip_cmd);
|
||||
install_lib_element(node, &cfg_mgw_local_port_cmd);
|
||||
install_lib_element(node, &cfg_mgw_remote_ip_cmd);
|
||||
install_lib_element(node, &cfg_mgw_remote_port_cmd);
|
||||
install_lib_element(node, &cfg_mgw_endpoint_range_cmd);
|
||||
install_lib_element(node, &cfg_mgw_rtp_bts_base_port_cmd);
|
||||
install_lib_element(node, &cfg_mgw_endpoint_domain_name_cmd);
|
||||
|
||||
/* deprecated 'mgcpgw' commands */
|
||||
install_element(node, &cfg_mgcpgw_local_ip_cmd);
|
||||
install_element(node, &cfg_mgcpgw_local_port_cmd);
|
||||
install_element(node, &cfg_mgcpgw_remote_ip_cmd);
|
||||
install_element(node, &cfg_mgcpgw_remote_port_cmd);
|
||||
install_element(node, &cfg_mgcpgw_endpoint_range_cmd);
|
||||
install_element(node, &cfg_mgcpgw_rtp_bts_base_port_cmd);
|
||||
install_lib_element(node, &cfg_mgcpgw_local_ip_cmd);
|
||||
install_lib_element(node, &cfg_mgcpgw_local_port_cmd);
|
||||
install_lib_element(node, &cfg_mgcpgw_remote_ip_cmd);
|
||||
install_lib_element(node, &cfg_mgcpgw_remote_port_cmd);
|
||||
install_lib_element(node, &cfg_mgcpgw_endpoint_range_cmd);
|
||||
install_lib_element(node, &cfg_mgcpgw_rtp_bts_base_port_cmd);
|
||||
|
||||
osmo_fsm_vty_add_cmds();
|
||||
}
|
||||
|
@@ -199,7 +199,7 @@ struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
|
||||
/* Initialize watchdog */
|
||||
osmo_timer_setup(&conn->watchdog, mgcp_conn_watchdog_cb, conn);
|
||||
mgcp_conn_watchdog_kick(conn);
|
||||
llist_add(&conn->entry, &endp->conns);
|
||||
mgcp_endp_add_conn(endp, conn);
|
||||
|
||||
return conn;
|
||||
}
|
||||
@@ -289,12 +289,6 @@ void mgcp_conn_free(struct mgcp_endpoint *endp, const char *id)
|
||||
if (!conn)
|
||||
return;
|
||||
|
||||
/* Run endpoint cleanup action. By this we inform the endpoint about
|
||||
* the removal of the connection and allow it to clean up its inner
|
||||
* state accordingly */
|
||||
if (endp->type->cleanup_cb)
|
||||
endp->type->cleanup_cb(endp, conn);
|
||||
|
||||
switch (conn->type) {
|
||||
case MGCP_CONN_TYPE_RTP:
|
||||
aggregate_rtp_conn_stats(endp, &conn->u.rtp);
|
||||
@@ -308,7 +302,8 @@ void mgcp_conn_free(struct mgcp_endpoint *endp, const char *id)
|
||||
}
|
||||
|
||||
osmo_timer_del(&conn->watchdog);
|
||||
llist_del(&conn->entry);
|
||||
mgcp_endp_remove_conn(endp, conn);
|
||||
/* WARN: endp may have be freed after call to mgcp_endp_remove_conn */
|
||||
talloc_free(conn);
|
||||
}
|
||||
|
||||
@@ -349,6 +344,7 @@ void mgcp_conn_free_all(struct mgcp_endpoint *endp)
|
||||
char *mgcp_conn_dump(struct mgcp_conn *conn)
|
||||
{
|
||||
static char str[sizeof(conn->name)+sizeof(conn->id)+256];
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (!conn) {
|
||||
snprintf(str, sizeof(str), "(null connection)");
|
||||
@@ -362,7 +358,7 @@ char *mgcp_conn_dump(struct mgcp_conn *conn)
|
||||
"rtp:%u rtcp:%u)",
|
||||
conn->name,
|
||||
conn->id,
|
||||
inet_ntoa(conn->u.rtp.end.addr),
|
||||
osmo_sockaddr_ntop(&conn->u.rtp.end.addr.u.sa, ipbuf),
|
||||
ntohs(conn->u.rtp.end.rtp_port),
|
||||
ntohs(conn->u.rtp.end.rtcp_port));
|
||||
break;
|
||||
|
@@ -361,11 +361,7 @@ static void e1_recv_cb(struct e1inp_ts *ts, struct msgb *msg)
|
||||
e1_send(ts, trunk);
|
||||
}
|
||||
|
||||
/*! Find an endpoint by its name on a specified trunk.
|
||||
* \param[in] trunk trunk configuration.
|
||||
* \param[in] ts_nr E1 timeslot number.
|
||||
* \returns -EINVAL on failure, 0 on success. */
|
||||
int mgcp_e1_init(struct mgcp_trunk *trunk, uint8_t ts_nr)
|
||||
static int e1_init(struct mgcp_trunk *trunk, uint8_t ts_nr)
|
||||
{
|
||||
/*! Each timeslot needs only to be configured once. The Timeslot then
|
||||
* stays open and permanently receives data. It is then up to the
|
||||
@@ -385,26 +381,25 @@ int mgcp_e1_init(struct mgcp_trunk *trunk, uint8_t ts_nr)
|
||||
}
|
||||
|
||||
/* Get E1 line */
|
||||
if (!trunk->e1.line) {
|
||||
e1_line = e1inp_line_find(trunk->e1.vty_line_nr);
|
||||
if (!e1_line) {
|
||||
LOGPTRUNK(trunk, DE1, LOGL_DEBUG, "no such E1 line %u - check VTY config!\n",
|
||||
trunk->e1.vty_line_nr);
|
||||
return -EINVAL;
|
||||
}
|
||||
e1inp_line_bind_ops(e1_line, &dummy_e1_line_ops);
|
||||
} else
|
||||
e1_line = trunk->e1.line;
|
||||
if (!e1_line)
|
||||
e1_line = e1inp_line_find(trunk->e1.vty_line_nr);
|
||||
if (!e1_line) {
|
||||
LOGPTRUNK(trunk, DE1, LOGL_DEBUG, "no such E1 line %u - check VTY config!\n",
|
||||
trunk->e1.vty_line_nr);
|
||||
return -EINVAL;
|
||||
}
|
||||
e1inp_line_bind_ops(e1_line, &dummy_e1_line_ops);
|
||||
|
||||
/* Configure E1 timeslot */
|
||||
rc = e1inp_ts_config_raw(&e1_line->ts[ts_nr - 1], e1_line, e1_recv_cb);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
LOGPTRUNK(trunk, DE1, LOGL_ERROR, "failed to put E1 timeslot %u in raw mode.\n", ts_nr);
|
||||
return -EINVAL;
|
||||
e1inp_line_update(e1_line);
|
||||
if (rc < 0)
|
||||
}
|
||||
rc = e1inp_line_update(e1_line);
|
||||
if (rc < 0) {
|
||||
LOGPTRUNK(trunk, DE1, LOGL_ERROR, "failed to update E1 timeslot %u.\n", ts_nr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LOGPTRUNK(trunk, DE1, LOGL_DEBUG, "E1 timeslot %u set up successfully.\n", ts_nr);
|
||||
trunk->e1.ts_in_use[ts_nr - 1] = true;
|
||||
@@ -518,7 +513,7 @@ int mgcp_e1_endp_equip(struct mgcp_endpoint *endp, uint8_t ts, uint8_t ss, uint8
|
||||
endp->e1.last_amr_ft = AMR_4_75;
|
||||
|
||||
/* Set up E1 line / timeslot */
|
||||
rc = mgcp_e1_init(endp->trunk, ts);
|
||||
rc = e1_init(endp->trunk, ts);
|
||||
if (rc != 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
@@ -27,9 +27,9 @@
|
||||
#include <osmocom/mgcp/mgcp_endp.h>
|
||||
#include <osmocom/mgcp/mgcp_trunk.h>
|
||||
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
#include <osmocom/mgcp/mgcp_e1.h>
|
||||
|
||||
#define E1_TIMESLOTS 32
|
||||
#define E1_RATE_MAX 64
|
||||
#define E1_OFFS_MAX 8
|
||||
|
||||
@@ -375,7 +375,7 @@ static uint8_t e1_ts_nr_from_epname(const char *epname)
|
||||
if (strncmp(token, "s-", 2) == 0) {
|
||||
errno = 0;
|
||||
res = strtoul(token + 2, NULL, 10);
|
||||
if (errno == ERANGE || res > E1_TIMESLOTS)
|
||||
if (errno == ERANGE || res > NUM_E1_TS)
|
||||
return 0xff;
|
||||
return (uint8_t) res;
|
||||
}
|
||||
@@ -641,8 +641,7 @@ int mgcp_endp_claim(struct mgcp_endpoint *endp, const char *callid)
|
||||
OSMO_ASSERT(false);
|
||||
}
|
||||
|
||||
/* Make sure the endpoint is released when claiming the endpoint
|
||||
* failes. */
|
||||
/* Make sure the endpoint is released when claiming the endpoint fails. */
|
||||
if (rc < 0)
|
||||
mgcp_endp_release(endp);
|
||||
|
||||
@@ -666,3 +665,20 @@ void mgcp_endp_update(struct mgcp_endpoint *endp)
|
||||
OSMO_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
void mgcp_endp_add_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn)
|
||||
{
|
||||
llist_add(&conn->entry, &endp->conns);
|
||||
}
|
||||
|
||||
void mgcp_endp_remove_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn)
|
||||
{
|
||||
/* Run endpoint cleanup action. By this we inform the endpoint about
|
||||
* the removal of the connection and allow it to clean up its inner
|
||||
* state accordingly */
|
||||
if (endp->type->cleanup_cb)
|
||||
endp->type->cleanup_cb(endp, conn);
|
||||
llist_del(&conn->entry);
|
||||
if (llist_empty(&endp->conns))
|
||||
mgcp_endp_release(endp);
|
||||
}
|
||||
|
@@ -107,7 +107,7 @@ int mgcp_parse_conn_mode(const char *mode, struct mgcp_endpoint *endp,
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Special handling für RTP connections */
|
||||
/* Special handling for RTP connections */
|
||||
if (conn->type == MGCP_CONN_TYPE_RTP) {
|
||||
conn->u.rtp.end.output_enabled =
|
||||
conn->mode & MGCP_CONN_SEND_ONLY ? 1 : 0;
|
||||
@@ -245,7 +245,7 @@ int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line)
|
||||
/*! Check if the specified callid seems plausible.
|
||||
* \param[in] endp pointer to endpoint
|
||||
* \param{in] callid to verify
|
||||
* \returns 1 when callid seems plausible, 0 on error */
|
||||
* \returns 0 when callid seems plausible, -1 on error */
|
||||
int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid)
|
||||
{
|
||||
/*! This function compares the supplied callid with the called that is
|
||||
|
@@ -77,6 +77,16 @@ static void rtpconn_rate_ctr_inc(struct mgcp_conn_rtp *conn_rtp, struct mgcp_end
|
||||
|
||||
static int rx_rtp(struct msgb *msg);
|
||||
|
||||
static bool addr_is_any(struct osmo_sockaddr *osa) {
|
||||
if (osa->u.sa.sa_family == AF_INET6) {
|
||||
struct in6_addr ip6_any = IN6ADDR_ANY_INIT;
|
||||
return memcmp(&osa->u.sin6.sin6_addr,
|
||||
&ip6_any, sizeof(ip6_any)) == 0;
|
||||
} else {
|
||||
return osa->u.sin.sin_addr.s_addr == 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*! Determine the local rtp bind IP-address.
|
||||
* \param[out] addr caller provided memory to store the resulting IP-Address.
|
||||
* \param[in] endp mgcp endpoint, that holds a copy of the VTY parameters.
|
||||
@@ -89,39 +99,52 @@ void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn)
|
||||
{
|
||||
|
||||
struct mgcp_endpoint *endp;
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
int rc;
|
||||
endp = conn->conn->endp;
|
||||
bool rem_addr_set = !addr_is_any(&conn->end.addr);
|
||||
char *bind_addr;
|
||||
|
||||
/* Try probing the local IP-Address */
|
||||
if (endp->cfg->net_ports.bind_addr_probe && conn->end.addr.s_addr != 0) {
|
||||
rc = osmo_sock_local_ip(addr, inet_ntoa(conn->end.addr));
|
||||
if (endp->cfg->net_ports.bind_addr_probe && rem_addr_set) {
|
||||
rc = osmo_sock_local_ip(addr, osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf));
|
||||
if (rc < 0)
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
|
||||
"local interface auto detection failed, using configured addresses...\n");
|
||||
else {
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
|
||||
"selected local rtp bind ip %s by probing using remote ip %s\n",
|
||||
addr, inet_ntoa(conn->end.addr));
|
||||
addr, osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Select from preconfigured IP-Addresses. We don't have bind_addr for Osmux (yet?). */
|
||||
if (endp->cfg->net_ports.bind_addr) {
|
||||
if (rem_addr_set) {
|
||||
/* Check there is a bind IP for the RTP traffic configured,
|
||||
* if so, use that IP-Address */
|
||||
osmo_strlcpy(addr, endp->cfg->net_ports.bind_addr, INET_ADDRSTRLEN);
|
||||
bind_addr = conn->end.addr.u.sa.sa_family == AF_INET6 ?
|
||||
endp->cfg->net_ports.bind_addr_v6 :
|
||||
endp->cfg->net_ports.bind_addr_v4;
|
||||
} else {
|
||||
/* Choose any of the bind addresses, preferring v6 over v4 */
|
||||
bind_addr = endp->cfg->net_ports.bind_addr_v6;
|
||||
if (!bind_addr)
|
||||
bind_addr = endp->cfg->net_ports.bind_addr_v4;
|
||||
}
|
||||
if (bind_addr) {
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
|
||||
"using configured rtp bind ip as local bind ip %s\n",
|
||||
addr);
|
||||
bind_addr);
|
||||
} else {
|
||||
/* No specific bind IP is configured for the RTP traffic, so
|
||||
* assume the IP where we listen for incoming MGCP messages
|
||||
* as bind IP */
|
||||
osmo_strlcpy(addr, endp->cfg->source_addr, INET_ADDRSTRLEN);
|
||||
bind_addr = endp->cfg->source_addr;
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
|
||||
"using mgcp bind ip as local rtp bind ip: %s\n", addr);
|
||||
"using mgcp bind ip as local rtp bind ip: %s\n", bind_addr);
|
||||
}
|
||||
osmo_strlcpy(addr, bind_addr, INET6_ADDRSTRLEN);
|
||||
}
|
||||
|
||||
/* This does not need to be a precision timestamp and
|
||||
@@ -154,19 +177,26 @@ static uint32_t get_current_ts(unsigned codec_rate)
|
||||
* \param[in] buf buffer that holds the data to be send.
|
||||
* \param[in] len length of the data to be sent.
|
||||
* \returns bytes sent, -1 on error. */
|
||||
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len)
|
||||
int mgcp_udp_send(int fd, struct osmo_sockaddr *addr, int port, char *buf, int len)
|
||||
{
|
||||
struct sockaddr_in out;
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
size_t addr_len;
|
||||
bool is_ipv6 = addr->u.sa.sa_family == AF_INET6;
|
||||
|
||||
LOGP(DRTP, LOGL_DEBUG,
|
||||
"sending %i bytes length packet to %s:%u ...\n",
|
||||
len, inet_ntoa(*addr), ntohs(port));
|
||||
"sending %i bytes length packet to %s:%u ...\n", len,
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
ntohs(port));
|
||||
|
||||
out.sin_family = AF_INET;
|
||||
out.sin_port = port;
|
||||
memcpy(&out.sin_addr, addr, sizeof(*addr));
|
||||
if (is_ipv6) {
|
||||
addr->u.sin6.sin6_port = port;
|
||||
addr_len = sizeof(addr->u.sin6);
|
||||
} else {
|
||||
addr->u.sin.sin_port = port;
|
||||
addr_len = sizeof(addr->u.sin);
|
||||
}
|
||||
|
||||
return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out));
|
||||
return sendto(fd, buf, len, 0, &addr->u.sa, addr_len);
|
||||
}
|
||||
|
||||
/*! send RTP dummy packet (to keep NAT connection open).
|
||||
@@ -229,12 +259,13 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
|
||||
struct mgcp_rtp_state *state,
|
||||
struct mgcp_rtp_stream_state *sstate,
|
||||
struct mgcp_rtp_end *rtp_end,
|
||||
struct sockaddr_in *addr,
|
||||
struct osmo_sockaddr *addr,
|
||||
uint16_t seq, uint32_t timestamp,
|
||||
const char *text, int32_t * tsdelta_out)
|
||||
{
|
||||
int32_t tsdelta;
|
||||
int32_t timestamp_error;
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
/* Not fully intialized, skip */
|
||||
if (sstate->last_tsdelta == 0 && timestamp == sstate->last_timestamp)
|
||||
@@ -251,8 +282,9 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
|
||||
"from %s:%d\n",
|
||||
text, seq,
|
||||
state->patch.timestamp_offset, state->patch.seq_offset,
|
||||
sstate->ssrc, timestamp, inet_ntoa(addr->sin_addr),
|
||||
ntohs(addr->sin_port));
|
||||
sstate->ssrc, timestamp,
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -267,9 +299,9 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
|
||||
"The %s timestamp delta is %d "
|
||||
"on SSRC: %u timestamp: %u "
|
||||
"from %s:%d\n",
|
||||
text, tsdelta,
|
||||
sstate->ssrc, timestamp,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
text, tsdelta, sstate->ssrc, timestamp,
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -281,7 +313,8 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
|
||||
"on SSRC: %u timestamp: %u from %s:%d\n",
|
||||
text, sstate->last_tsdelta, tsdelta,
|
||||
sstate->ssrc, timestamp,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +336,8 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
|
||||
(int16_t)(seq - sstate->last_seq),
|
||||
(int32_t)(timestamp - sstate->last_timestamp),
|
||||
tsdelta,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa),
|
||||
state->packet_duration);
|
||||
}
|
||||
return 1;
|
||||
@@ -313,12 +347,13 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
|
||||
static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
|
||||
struct mgcp_rtp_state *state,
|
||||
struct mgcp_rtp_end *rtp_end,
|
||||
struct sockaddr_in *addr,
|
||||
struct osmo_sockaddr *addr,
|
||||
int16_t delta_seq, uint32_t in_timestamp)
|
||||
{
|
||||
int32_t tsdelta = state->packet_duration;
|
||||
int timestamp_offset;
|
||||
uint32_t out_timestamp;
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (tsdelta == 0) {
|
||||
tsdelta = state->out_stream.last_tsdelta;
|
||||
@@ -327,7 +362,8 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
|
||||
"A fixed packet duration is not available, "
|
||||
"using last output timestamp delta instead: %d "
|
||||
"from %s:%d\n", tsdelta,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
} else {
|
||||
tsdelta = rtp_end->codec->rate * 20 / 1000;
|
||||
LOGPENDP(endp, DRTP, LOGL_NOTICE,
|
||||
@@ -335,7 +371,8 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
|
||||
"are not available, "
|
||||
"using fixed 20ms instead: %d "
|
||||
"from %s:%d\n", tsdelta,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,13 +381,13 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
|
||||
|
||||
if (state->patch.timestamp_offset != timestamp_offset) {
|
||||
state->patch.timestamp_offset = timestamp_offset;
|
||||
|
||||
LOGPENDP(endp, DRTP, LOGL_NOTICE,
|
||||
"Timestamp offset change on SSRC: %u "
|
||||
"SeqNo delta: %d, TS offset: %d, "
|
||||
"from %s:%d\n", state->in_stream.ssrc,
|
||||
delta_seq, state->patch.timestamp_offset,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
}
|
||||
|
||||
return timestamp_offset;
|
||||
@@ -360,9 +397,10 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
|
||||
static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
|
||||
struct mgcp_rtp_state *state,
|
||||
struct mgcp_rtp_end *rtp_end,
|
||||
struct sockaddr_in *addr,
|
||||
struct osmo_sockaddr *addr,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
int ts_error = 0;
|
||||
int ts_check = 0;
|
||||
int ptime = state->packet_duration;
|
||||
@@ -375,14 +413,14 @@ static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
|
||||
/* If there is an alignment error, we have to compensate it */
|
||||
if (ts_error) {
|
||||
state->patch.timestamp_offset += ptime - ts_error;
|
||||
|
||||
LOGPENDP(endp, DRTP, LOGL_NOTICE,
|
||||
"Corrected timestamp alignment error of %d on SSRC: %u "
|
||||
"new TS offset: %d, "
|
||||
"from %s:%d\n",
|
||||
ts_error, state->in_stream.ssrc,
|
||||
state->patch.timestamp_offset, inet_ntoa(addr->sin_addr),
|
||||
ntohs(addr->sin_port));
|
||||
state->patch.timestamp_offset,
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
}
|
||||
|
||||
/* Check we really managed to compensate the timestamp
|
||||
@@ -521,8 +559,9 @@ static int mgcp_patch_pt(struct mgcp_conn_rtp *conn_src,
|
||||
void mgcp_patch_and_count(struct mgcp_endpoint *endp,
|
||||
struct mgcp_rtp_state *state,
|
||||
struct mgcp_rtp_end *rtp_end,
|
||||
struct sockaddr_in *addr, struct msgb *msg)
|
||||
struct osmo_sockaddr *addr, struct msgb *msg)
|
||||
{
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
uint32_t arrival_time;
|
||||
int32_t transit;
|
||||
uint16_t seq;
|
||||
@@ -560,7 +599,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
|
||||
"pkt-duration: %d, from %s:%d\n",
|
||||
state->in_stream.ssrc,
|
||||
state->patch.seq_offset, state->packet_duration,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
if (state->packet_duration == 0) {
|
||||
state->packet_duration =
|
||||
rtp_end->codec->rate * 20 / 1000;
|
||||
@@ -568,14 +608,16 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
|
||||
"fixed packet duration is not available, "
|
||||
"using fixed 20ms instead: %d from %s:%d\n",
|
||||
state->packet_duration,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
}
|
||||
} else if (state->in_stream.ssrc != ssrc) {
|
||||
LOGPENDP(endp, DRTP, LOGL_NOTICE,
|
||||
"SSRC changed: %u -> %u "
|
||||
"from %s:%d\n",
|
||||
state->in_stream.ssrc, rtp_hdr->ssrc,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
|
||||
state->in_stream.ssrc = ssrc;
|
||||
if (rtp_end->force_constant_ssrc) {
|
||||
@@ -604,7 +646,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
|
||||
"SeqNo offset: %d, TS offset: %d "
|
||||
"from %s:%d\n", state->in_stream.ssrc,
|
||||
state->patch.seq_offset, state->patch.timestamp_offset,
|
||||
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
}
|
||||
|
||||
state->in_stream.last_tsdelta = 0;
|
||||
@@ -825,7 +868,7 @@ static void gen_rtp_header(struct msgb *msg, struct mgcp_rtp_end *rtp_end,
|
||||
* \param[in] conn_src associated source connection.
|
||||
* \param[in] conn_dst associated destination connection.
|
||||
* \returns 0 on success, -1 on ERROR. */
|
||||
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
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)
|
||||
{
|
||||
@@ -836,6 +879,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
struct mgcp_trunk *trunk = endp->trunk;
|
||||
struct mgcp_rtp_end *rtp_end;
|
||||
struct mgcp_rtp_state *rtp_state;
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
char *dest_name;
|
||||
int rc;
|
||||
int len;
|
||||
@@ -849,10 +893,6 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
LOGPENDP(endp, DRTP, LOGL_DEBUG, "delivering RTCP packet...\n");
|
||||
}
|
||||
|
||||
LOGPENDP(endp, DRTP, LOGL_DEBUG, "loop:%d, mode:%d%s\n",
|
||||
trunk->audio_loop, conn_src->conn->mode,
|
||||
conn_src->conn->mode == MGCP_CONN_LOOPBACK ? " (loopback)" : "");
|
||||
|
||||
/* FIXME: It is legal that the payload type on the egress connection is
|
||||
* different from the payload type that has been negotiated on the
|
||||
* ingress connection. Essentially the codecs are the same so we can
|
||||
@@ -886,7 +926,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
"output disabled, drop to %s %s "
|
||||
"rtp_port:%u rtcp_port:%u\n",
|
||||
dest_name,
|
||||
inet_ntoa(rtp_end->addr),
|
||||
osmo_sockaddr_ntop(&rtp_end->addr.u.sa, ipbuf),
|
||||
ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
|
||||
);
|
||||
} else if (is_rtp) {
|
||||
@@ -932,7 +972,8 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
LOGPENDP(endp, DRTP, LOGL_DEBUG,
|
||||
"process/send to %s %s "
|
||||
"rtp_port:%u rtcp_port:%u\n",
|
||||
dest_name, inet_ntoa(rtp_end->addr),
|
||||
dest_name,
|
||||
osmo_sockaddr_ntop(&rtp_end->addr.u.sa, ipbuf),
|
||||
ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
|
||||
);
|
||||
|
||||
@@ -975,7 +1016,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
} else if (!trunk->omit_rtcp) {
|
||||
LOGPENDP(endp, DRTP, LOGL_DEBUG,
|
||||
"send to %s %s rtp_port:%u rtcp_port:%u\n",
|
||||
dest_name, inet_ntoa(rtp_end->addr),
|
||||
dest_name, osmo_sockaddr_ntop(&rtp_end->addr.u.sa, ipbuf),
|
||||
ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
|
||||
);
|
||||
|
||||
@@ -995,10 +1036,11 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
|
||||
/* Check if the origin (addr) matches the address/port data of the RTP
|
||||
* connections. */
|
||||
static int check_rtp_origin(struct mgcp_conn_rtp *conn,
|
||||
struct sockaddr_in *addr)
|
||||
static int check_rtp_origin(struct mgcp_conn_rtp *conn, struct osmo_sockaddr *addr)
|
||||
{
|
||||
if (conn->end.addr.s_addr == 0) {
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (addr_is_any(&conn->end.addr)) {
|
||||
switch (conn->conn->mode) {
|
||||
case MGCP_CONN_LOOPBACK:
|
||||
/* HACK: for IuUP, we want to reply with an IuUP Initialization ACK upon the first RTP
|
||||
@@ -1010,7 +1052,8 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
|
||||
* MGCP port is in loopback mode, allow looping back the packet to any source. */
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
|
||||
"In loopback mode and remote address not set:"
|
||||
" allowing data from address: %s\n", inet_ntoa(addr->sin_addr));
|
||||
" allowing data from address: %s\n",
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf));
|
||||
return 0;
|
||||
|
||||
default:
|
||||
@@ -1019,18 +1062,25 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
|
||||
* confuse humans with expected errors. */
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_INFO,
|
||||
"Rx RTP from %s, but remote address not set:"
|
||||
" dropping early media\n", inet_ntoa(addr->sin_addr));
|
||||
" dropping early media\n",
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: Check if the inbound RTP data comes from the same host to
|
||||
* which we send our outgoing RTP traffic. */
|
||||
if (conn->end.addr.s_addr != addr->sin_addr.s_addr) {
|
||||
if (conn->end.addr.u.sa.sa_family != addr->u.sa.sa_family ||
|
||||
(conn->end.addr.u.sa.sa_family == AF_INET &&
|
||||
conn->end.addr.u.sin.sin_addr.s_addr != addr->u.sin.sin_addr.s_addr) ||
|
||||
(conn->end.addr.u.sa.sa_family == AF_INET6 &&
|
||||
memcmp(&conn->end.addr.u.sin6.sin6_addr, &addr->u.sin6.sin6_addr,
|
||||
sizeof(struct in6_addr)))) {
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
|
||||
"data from wrong address: %s, ", inet_ntoa(addr->sin_addr));
|
||||
"data from wrong address: %s, ",
|
||||
osmo_sockaddr_ntop(&addr->u.sa, ipbuf));
|
||||
LOGPC(DRTP, LOGL_ERROR, "expected: %s\n",
|
||||
inet_ntoa(conn->end.addr));
|
||||
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf));
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_ERROR, "packet tossed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1039,10 +1089,11 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
|
||||
* the same as the remote port where we transmit outgoing RTP traffic
|
||||
* to (set by MDCX). We use this to check the origin of the data for
|
||||
* plausibility. */
|
||||
if (conn->end.rtp_port != addr->sin_port &&
|
||||
conn->end.rtcp_port != addr->sin_port) {
|
||||
if (ntohs(conn->end.rtp_port) != osmo_sockaddr_port(&addr->u.sa) &&
|
||||
ntohs(conn->end.rtcp_port) != osmo_sockaddr_port(&addr->u.sa)) {
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
|
||||
"data from wrong source port: %d, ", ntohs(addr->sin_port));
|
||||
"data from wrong source port: %d, ",
|
||||
osmo_sockaddr_port(&addr->u.sa));
|
||||
LOGPC(DRTP, LOGL_ERROR,
|
||||
"expected: %d for RTP or %d for RTCP\n",
|
||||
ntohs(conn->end.rtp_port), ntohs(conn->end.rtcp_port));
|
||||
@@ -1057,26 +1108,29 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
|
||||
* makes sense */
|
||||
static int check_rtp_destin(struct mgcp_conn_rtp *conn)
|
||||
{
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
bool ip_is_any = addr_is_any(&conn->end.addr);
|
||||
|
||||
/* Note: it is legal to create a connection but never setting a port
|
||||
* and IP-address for outgoing data. */
|
||||
if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0 && conn->end.rtp_port == 0) {
|
||||
if (ip_is_any && conn->end.rtp_port == 0) {
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
|
||||
"destination IP-address and rtp port is (not yet) known (%s:%u)\n",
|
||||
inet_ntoa(conn->end.addr), conn->end.rtp_port);
|
||||
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf), conn->end.rtp_port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0) {
|
||||
if (ip_is_any) {
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
|
||||
"destination IP-address is invalid (%s:%u)\n",
|
||||
inet_ntoa(conn->end.addr), conn->end.rtp_port);
|
||||
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf), conn->end.rtp_port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->end.rtp_port == 0) {
|
||||
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
|
||||
"destination rtp port is invalid (%s:%u)\n",
|
||||
inet_ntoa(conn->end.addr), conn->end.rtp_port);
|
||||
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf), conn->end.rtp_port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1147,7 +1201,6 @@ static int mgcp_send_rtp(struct mgcp_conn_rtp *conn_dst, struct msgb *msg)
|
||||
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
|
||||
enum rtp_proto proto = mc->proto;
|
||||
struct mgcp_conn_rtp *conn_src = mc->conn_src;
|
||||
struct sockaddr_in *from_addr = mc->from_addr;
|
||||
struct mgcp_endpoint *endp = conn_src->conn->endp;
|
||||
|
||||
LOGPENDP(endp, DRTP, LOGL_DEBUG, "destin conn:%s\n",
|
||||
@@ -1167,7 +1220,7 @@ static int mgcp_send_rtp(struct mgcp_conn_rtp *conn_dst, struct msgb *msg)
|
||||
"endpoint type is MGCP_RTP_DEFAULT, "
|
||||
"using mgcp_send() to forward data directly\n");
|
||||
return mgcp_send(endp, proto == MGCP_PROTO_RTP,
|
||||
from_addr, msg, conn_src, conn_dst);
|
||||
mc->from_addr, msg, conn_src, conn_dst);
|
||||
case MGCP_OSMUX_BSC_NAT:
|
||||
case MGCP_OSMUX_BSC:
|
||||
LOGPENDP(endp, DRTP, LOGL_DEBUG,
|
||||
@@ -1197,7 +1250,7 @@ int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg)
|
||||
struct mgcp_conn_rtp *conn_src = mc->conn_src;
|
||||
struct mgcp_conn *conn = conn_src->conn;
|
||||
struct mgcp_conn *conn_dst;
|
||||
struct sockaddr_in *from_addr = mc->from_addr;
|
||||
struct osmo_sockaddr *from_addr = mc->from_addr;
|
||||
|
||||
/*! NOTE: This callback function implements the endpoint specific
|
||||
* dispatch behaviour of an rtp bridge/proxy endpoint. It is assumed
|
||||
@@ -1216,8 +1269,19 @@ int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg)
|
||||
* address data from the UDP packet header to patch the
|
||||
* outgoing address in connection on the fly */
|
||||
if (conn->u.rtp.end.rtp_port == 0) {
|
||||
conn->u.rtp.end.addr = from_addr->sin_addr;
|
||||
conn->u.rtp.end.rtp_port = from_addr->sin_port;
|
||||
OSMO_ASSERT(conn->u.rtp.end.addr.u.sa.sa_family == from_addr->u.sa.sa_family);
|
||||
switch (from_addr->u.sa.sa_family) {
|
||||
case AF_INET:
|
||||
conn->u.rtp.end.addr.u.sin.sin_addr = from_addr->u.sin.sin_addr;
|
||||
conn->u.rtp.end.rtp_port = from_addr->u.sin.sin_port;
|
||||
break;
|
||||
case AF_INET6:
|
||||
conn->u.rtp.end.addr.u.sin6.sin6_addr = from_addr->u.sin6.sin6_addr;
|
||||
conn->u.rtp.end.rtp_port = from_addr->u.sin6.sin6_port;
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(false);
|
||||
}
|
||||
}
|
||||
return mgcp_send_rtp(conn_src, msg);
|
||||
}
|
||||
@@ -1266,7 +1330,7 @@ int mgcp_dispatch_e1_bridge_cb(struct msgb *msg)
|
||||
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
|
||||
struct mgcp_conn_rtp *conn_src = mc->conn_src;
|
||||
struct mgcp_conn *conn = conn_src->conn;
|
||||
struct sockaddr_in *from_addr = mc->from_addr;
|
||||
struct osmo_sockaddr *from_addr = mc->from_addr;
|
||||
|
||||
/* Check if the connection is in loopback mode, if yes, just send the
|
||||
* incoming data back to the origin */
|
||||
@@ -1276,8 +1340,19 @@ int mgcp_dispatch_e1_bridge_cb(struct msgb *msg)
|
||||
* address data from the UDP packet header to patch the
|
||||
* outgoing address in connection on the fly */
|
||||
if (conn->u.rtp.end.rtp_port == 0) {
|
||||
conn->u.rtp.end.addr = from_addr->sin_addr;
|
||||
conn->u.rtp.end.rtp_port = from_addr->sin_port;
|
||||
OSMO_ASSERT(conn->u.rtp.end.addr.u.sa.sa_family == from_addr->u.sa.sa_family);
|
||||
switch (from_addr->u.sa.sa_family) {
|
||||
case AF_INET:
|
||||
conn->u.rtp.end.addr.u.sin.sin_addr = from_addr->u.sin.sin_addr;
|
||||
conn->u.rtp.end.rtp_port = from_addr->u.sin.sin_port;
|
||||
break;
|
||||
case AF_INET6:
|
||||
conn->u.rtp.end.addr.u.sin6.sin6_addr = from_addr->u.sin6.sin6_addr;
|
||||
conn->u.rtp.end.rtp_port = from_addr->u.sin6.sin6_port;
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(false);
|
||||
}
|
||||
}
|
||||
return mgcp_send_rtp(conn_src, msg);
|
||||
}
|
||||
@@ -1300,7 +1375,8 @@ void mgcp_cleanup_rtp_bridge_cb(struct mgcp_endpoint *endp, struct mgcp_conn *co
|
||||
* connections present when one connection is removed from the
|
||||
* endpoint. */
|
||||
llist_for_each_entry(conn_cleanup, &endp->conns, entry) {
|
||||
conn_cleanup->priv = NULL;
|
||||
if (conn_cleanup->priv == conn)
|
||||
conn_cleanup->priv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1331,8 +1407,9 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
|
||||
|
||||
struct mgcp_conn_rtp *conn_src;
|
||||
struct mgcp_endpoint *endp;
|
||||
struct sockaddr_in addr;
|
||||
struct osmo_sockaddr addr;
|
||||
socklen_t slen = sizeof(addr);
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
int ret;
|
||||
enum rtp_proto proto;
|
||||
struct osmo_rtp_msg_ctx *mc;
|
||||
@@ -1346,7 +1423,7 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
|
||||
|
||||
proto = (fd == &conn_src->end.rtp)? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
|
||||
|
||||
ret = recvfrom(fd->fd, msgb_data(msg), msg->data_len, 0, (struct sockaddr *)&addr, &slen);
|
||||
ret = recvfrom(fd->fd, msgb_data(msg), msg->data_len, 0, (struct sockaddr *)&addr.u.sa, &slen);
|
||||
|
||||
if (ret <= 0) {
|
||||
LOG_CONN_RTP(conn_src, LOGL_ERROR, "recvfrom error: %s\n", strerror(errno));
|
||||
@@ -1358,7 +1435,8 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
|
||||
|
||||
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "%s: rx %u bytes from %s:%u\n",
|
||||
proto == MGCP_PROTO_RTP ? "RTP" : "RTPC",
|
||||
msgb_length(msg), inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
||||
msgb_length(msg), osmo_sockaddr_ntop(&addr.u.sa, ipbuf),
|
||||
osmo_sockaddr_port(&addr.u.sa));
|
||||
|
||||
if ((proto == MGCP_PROTO_RTP && check_rtp(conn_src, msg))
|
||||
|| (proto == MGCP_PROTO_RTCP && check_rtcp(conn_src, msg))) {
|
||||
@@ -1383,7 +1461,10 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
|
||||
};
|
||||
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "msg ctx: %d %p %s\n",
|
||||
mc->proto, mc->conn_src,
|
||||
osmo_hexdump((void*)mc->from_addr, sizeof(struct sockaddr_in)));
|
||||
osmo_hexdump((void*)mc->from_addr,
|
||||
mc->from_addr->u.sa.sa_family == AF_INET6 ?
|
||||
sizeof(struct sockaddr_in6) :
|
||||
sizeof(struct sockaddr_in)));
|
||||
|
||||
/* Increment RX statistics */
|
||||
rate_ctr_inc(&conn_src->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR]);
|
||||
@@ -1404,7 +1485,7 @@ static int rx_rtp(struct msgb *msg)
|
||||
{
|
||||
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
|
||||
struct mgcp_conn_rtp *conn_src = mc->conn_src;
|
||||
struct sockaddr_in *from_addr = mc->from_addr;
|
||||
struct osmo_sockaddr *from_addr = mc->from_addr;
|
||||
struct mgcp_conn *conn = conn_src->conn;
|
||||
struct mgcp_trunk *trunk = conn->endp->trunk;
|
||||
|
||||
@@ -1456,7 +1537,7 @@ int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP, source_addr, port,
|
||||
rc = osmo_sock_init2(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, source_addr, port,
|
||||
NULL, 0, OSMO_SOCK_F_BIND);
|
||||
if (rc < 0) {
|
||||
LOGP(DRTP, LOGL_ERROR, "failed to bind UDP port (%s:%i).\n",
|
||||
@@ -1496,7 +1577,6 @@ static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
|
||||
mgcp_set_ip_tos(rtp_end->rtp.fd, cfg->endp_dscp);
|
||||
mgcp_set_ip_tos(rtp_end->rtcp.fd, cfg->endp_dscp);
|
||||
|
||||
rtp_end->rtp.when = OSMO_FD_READ;
|
||||
if (osmo_fd_register(&rtp_end->rtp) != 0) {
|
||||
LOGPENDP(endp, DRTP, LOGL_ERROR,
|
||||
"failed to register RTP port %d\n",
|
||||
@@ -1504,7 +1584,6 @@ static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
|
||||
goto cleanup2;
|
||||
}
|
||||
|
||||
rtp_end->rtcp.when = OSMO_FD_READ;
|
||||
if (osmo_fd_register(&rtp_end->rtcp) != 0) {
|
||||
LOGPENDP(endp, DRTP, LOGL_ERROR,
|
||||
"failed to register RTCP port %d\n",
|
||||
@@ -1536,7 +1615,6 @@ int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
|
||||
{
|
||||
char name[512];
|
||||
struct mgcp_rtp_end *end;
|
||||
char local_ip_addr[INET_ADDRSTRLEN];
|
||||
|
||||
snprintf(name, sizeof(name), "%s-%s", conn->conn->name, conn->conn->id);
|
||||
end = &conn->end;
|
||||
@@ -1554,14 +1632,10 @@ int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
|
||||
}
|
||||
|
||||
end->local_port = rtp_port;
|
||||
end->rtp.cb = rtp_data_net;
|
||||
end->rtp.data = conn;
|
||||
end->rtcp.data = conn;
|
||||
end->rtcp.cb = rtp_data_net;
|
||||
osmo_fd_setup(&end->rtp, -1, OSMO_FD_READ, rtp_data_net, conn, 0);
|
||||
osmo_fd_setup(&end->rtcp, -1, OSMO_FD_READ, rtp_data_net, conn, 0);
|
||||
|
||||
mgcp_get_local_addr(local_ip_addr, conn);
|
||||
|
||||
return bind_rtp(endp->cfg, local_ip_addr, end, endp);
|
||||
return bind_rtp(endp->cfg, conn->end.local_addr, end, endp);
|
||||
}
|
||||
|
||||
/*! free allocated RTP and RTCP ports.
|
||||
|
@@ -35,6 +35,7 @@ static LLIST_HEAD(osmux_handle_list);
|
||||
|
||||
struct osmux_handle {
|
||||
struct llist_head head;
|
||||
struct mgcp_conn_rtp *conn;
|
||||
struct osmux_in_handle *in;
|
||||
struct in_addr rem_addr;
|
||||
int rem_port; /* network byte order */
|
||||
@@ -47,14 +48,17 @@ static void *osmux;
|
||||
static void osmux_deliver_cb(struct msgb *batch_msg, void *data)
|
||||
{
|
||||
struct osmux_handle *handle = data;
|
||||
struct sockaddr_in out = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = handle->rem_port,
|
||||
};
|
||||
struct mgcp_conn_rtp *conn = handle->conn;
|
||||
|
||||
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));
|
||||
if (conn->end.output_enabled) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -109,13 +113,15 @@ static void osmux_handle_put(struct osmux_in_handle *in)
|
||||
|
||||
/* Allocate free OSMUX handle */
|
||||
static struct osmux_handle *
|
||||
osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
|
||||
osmux_handle_alloc(struct mgcp_conn_rtp *conn, struct in_addr *addr, int rem_port)
|
||||
{
|
||||
struct osmux_handle *h;
|
||||
struct mgcp_config *cfg = conn->conn->endp->cfg;
|
||||
|
||||
h = talloc_zero(osmux, struct osmux_handle);
|
||||
if (!h)
|
||||
return NULL;
|
||||
h->conn = conn;
|
||||
h->rem_addr = *addr;
|
||||
h->rem_port = rem_port;
|
||||
h->refcnt++;
|
||||
@@ -148,15 +154,20 @@ osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
|
||||
/* Lookup existing handle for a specified address, if the handle can not be
|
||||
* found, the function will automatically allocate one */
|
||||
static struct osmux_in_handle *
|
||||
osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
|
||||
osmux_handle_lookup(struct mgcp_conn_rtp *conn, struct osmo_sockaddr *addr, int rem_port)
|
||||
{
|
||||
struct osmux_handle *h;
|
||||
|
||||
h = osmux_handle_find_get(addr, rem_port);
|
||||
if (addr->u.sa.sa_family != AF_INET) {
|
||||
LOGP(DLMGCP, LOGL_DEBUG, "IPv6 not supported in osmux yet!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
h = osmux_handle_find_get(&addr->u.sin.sin_addr, rem_port);
|
||||
if (h != NULL)
|
||||
return h->in;
|
||||
|
||||
h = osmux_handle_alloc(cfg, addr, rem_port);
|
||||
h = osmux_handle_alloc(conn, &addr->u.sin.sin_addr, rem_port);
|
||||
if (h == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -236,7 +247,7 @@ static void scheduled_from_osmux_tx_rtp_cb(struct msgb *msg, void *data)
|
||||
{
|
||||
struct mgcp_conn_rtp *conn = data;
|
||||
struct mgcp_endpoint *endp = conn->conn->endp;
|
||||
struct sockaddr_in addr = { /* FIXME: do we know the source address?? */ };
|
||||
struct osmo_sockaddr addr = { /* FIXME: do we know the source address?? */ };
|
||||
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
|
||||
*mc = (struct osmo_rtp_msg_ctx){
|
||||
.proto = MGCP_PROTO_RTP,
|
||||
@@ -275,6 +286,8 @@ static struct msgb *osmux_recv(struct osmo_fd *ofd, struct sockaddr_in *addr)
|
||||
static int endp_osmux_state_check(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
|
||||
bool sending)
|
||||
{
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
switch(conn->osmux.state) {
|
||||
case OSMUX_STATE_ACTIVATING:
|
||||
if (osmux_enable_conn(endp, conn, &conn->end.addr, conn->end.rtp_port) < 0) {
|
||||
@@ -287,7 +300,8 @@ static int endp_osmux_state_check(struct mgcp_endpoint *endp, struct mgcp_conn_r
|
||||
LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR,
|
||||
"Osmux %s CID %u towards %s:%u is now enabled\n",
|
||||
sending ? "sent" : "received",
|
||||
conn->osmux.cid, inet_ntoa(conn->end.addr),
|
||||
conn->osmux.cid,
|
||||
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf),
|
||||
ntohs(conn->end.rtp_port));
|
||||
return 0;
|
||||
case OSMUX_STATE_ENABLED:
|
||||
@@ -376,6 +390,8 @@ static int osmux_read_fd_cb(struct osmo_fd *ofd, unsigned int what)
|
||||
goto out;
|
||||
}
|
||||
|
||||
mgcp_conn_watchdog_kick(conn_src->conn);
|
||||
|
||||
/*conn_dst = mgcp_find_dst_conn(conn_src->conn);
|
||||
if (!conn_dst) {
|
||||
LOGP(DLMGCP, LOGL_ERROR,
|
||||
@@ -400,8 +416,7 @@ int osmux_init(int role, struct mgcp_config *cfg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
osmux_fd.cb = osmux_read_fd_cb;
|
||||
osmux_fd.data = cfg;
|
||||
osmo_fd_setup(&osmux_fd, -1, OSMO_FD_READ, osmux_read_fd_cb, cfg, 0);
|
||||
|
||||
ret = mgcp_create_bind(cfg->osmux_addr, &osmux_fd, cfg->osmux_port);
|
||||
if (ret < 0) {
|
||||
@@ -410,7 +425,6 @@ int osmux_init(int role, struct mgcp_config *cfg)
|
||||
return ret;
|
||||
}
|
||||
mgcp_set_ip_tos(osmux_fd.fd, cfg->endp_dscp);
|
||||
osmux_fd.when |= OSMO_FD_READ;
|
||||
|
||||
ret = osmo_fd_register(&osmux_fd);
|
||||
if (ret < 0) {
|
||||
@@ -433,7 +447,7 @@ int osmux_init(int role, struct mgcp_config *cfg)
|
||||
* \param[in] port portnumber of the remote OSMUX endpoint (in network byte order)
|
||||
* \returns 0 on success, -1 on ERROR */
|
||||
int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
|
||||
struct in_addr *addr, uint16_t port)
|
||||
struct osmo_sockaddr *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
|
||||
@@ -444,7 +458,7 @@ int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
|
||||
* overlapping RTP SSRC traveling to the BTSes behind the BSC,
|
||||
* similarly, for flows traveling to the MSC.
|
||||
*/
|
||||
struct in_addr addr_unset = {};
|
||||
struct in6_addr addr_unset = {};
|
||||
static const uint32_t rtp_ssrc_winlen = UINT32_MAX / (OSMUX_CID_MAX + 1);
|
||||
uint16_t osmux_dummy = endp->cfg->osmux_dummy;
|
||||
|
||||
@@ -457,13 +471,16 @@ int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
|
||||
}
|
||||
|
||||
/* Wait until we have the connection information from MDCX */
|
||||
if (memcmp(&conn->end.addr, &addr_unset, sizeof(addr_unset)) == 0) {
|
||||
if (memcmp(&conn->end.addr, &addr_unset,
|
||||
conn->end.addr.u.sa.sa_family == AF_INET6 ?
|
||||
sizeof(struct in6_addr) :
|
||||
sizeof(struct in_addr)) == 0) {
|
||||
LOGPCONN(conn->conn, DLMGCP, LOGL_INFO,
|
||||
"Osmux remote address/port still unknown\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn->osmux.in = osmux_handle_lookup(endp->cfg, addr, port);
|
||||
conn->osmux.in = osmux_handle_lookup(conn, addr, port);
|
||||
if (!conn->osmux.in) {
|
||||
LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR,
|
||||
"Cannot allocate input osmux handle for conn:%s\n",
|
||||
@@ -559,6 +576,7 @@ int conn_osmux_allocate_cid(struct mgcp_conn_rtp *conn, int osmux_cid)
|
||||
* \returns bytes sent, -1 on error */
|
||||
int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
|
||||
{
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
struct osmux_hdr *osmuxh;
|
||||
int buf_len;
|
||||
struct in_addr addr_unset = {};
|
||||
@@ -588,7 +606,8 @@ int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
|
||||
|
||||
LOGPCONN(conn->conn, DLMGCP, LOGL_DEBUG,
|
||||
"sending OSMUX dummy load to %s:%u CID %u\n",
|
||||
inet_ntoa(conn->end.addr), ntohs(conn->end.rtp_port), conn->osmux.cid);
|
||||
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf),
|
||||
ntohs(conn->end.rtp_port), conn->osmux.cid);
|
||||
|
||||
return mgcp_udp_send(osmux_fd.fd, &conn->end.addr,
|
||||
conn->end.rtp_port, (char*)osmuxh, buf_len);
|
||||
|
@@ -223,24 +223,22 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
|
||||
const char *trans_id,
|
||||
bool add_conn_params)
|
||||
{
|
||||
/* TODO: we may want to define another local_ip_osmux var to us for
|
||||
OSMUX connections. Perhaps adding a new internal API to get it based
|
||||
on conn type */
|
||||
const char *addr = endp->cfg->local_ip;
|
||||
/* cfg->local_ip allows overwritting the announced IP address with
|
||||
* regards to the one we actually bind to. Useful in behind-NAT
|
||||
* scenarios.
|
||||
* TODO: we may want to define another local_ip_osmux var to
|
||||
* us for OSMUX connections. Perhaps adding a new internal API to get it
|
||||
* based on conn type.
|
||||
*/
|
||||
const char *addr = endp->cfg->local_ip ? : conn->end.local_addr;
|
||||
struct msgb *sdp;
|
||||
int rc;
|
||||
struct msgb *result;
|
||||
char local_ip_addr[INET_ADDRSTRLEN];
|
||||
|
||||
sdp = msgb_alloc_headroom(4096, 128, "sdp record");
|
||||
if (!sdp)
|
||||
return NULL;
|
||||
|
||||
if (!addr) {
|
||||
mgcp_get_local_addr(local_ip_addr, conn);
|
||||
addr = local_ip_addr;
|
||||
}
|
||||
|
||||
/* Attach optional connection parameters */
|
||||
if (add_conn_params) {
|
||||
rc = add_params(sdp, endp, conn);
|
||||
@@ -526,6 +524,7 @@ static int set_local_cx_options(void *ctx, struct mgcp_lco *lco,
|
||||
{
|
||||
char *lco_id;
|
||||
char codec[17];
|
||||
char nt[17];
|
||||
int len;
|
||||
|
||||
if (!options)
|
||||
@@ -552,7 +551,7 @@ static int set_local_cx_options(void *ctx, struct mgcp_lco *lco,
|
||||
lco->pkt_period_max = lco->pkt_period_min;
|
||||
break;
|
||||
case 'a':
|
||||
/* FIXME: LCO also supports the negotiation of more then one codec.
|
||||
/* FIXME: LCO also supports the negotiation of more than one codec.
|
||||
* (e.g. a:PCMU;G726-32) But this implementation only supports a single
|
||||
* codec only. */
|
||||
if (sscanf(lco_id + 1, ":%16[^,]", codec) == 1) {
|
||||
@@ -564,6 +563,10 @@ static int set_local_cx_options(void *ctx, struct mgcp_lco *lco,
|
||||
osmo_str_toupper_buf(lco->codec, len + 1, codec);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (lco_id[1] == 't' && sscanf(lco_id + 2, ":%16[^,]", nt) == 1)
|
||||
break;
|
||||
/* else: fall throught to print notice log */
|
||||
default:
|
||||
LOGP(DLMGCP, LOGL_NOTICE,
|
||||
"LCO: unhandled option: '%c'/%d in \"%s\"\n",
|
||||
@@ -709,7 +712,7 @@ static bool parse_x_osmo_ign(struct mgcp_endpoint *endp, char *line)
|
||||
{
|
||||
char *saveptr = NULL;
|
||||
|
||||
if (strncmp(line, MGCP_X_OSMO_IGN_HEADER, strlen(MGCP_X_OSMO_IGN_HEADER)))
|
||||
if (strncasecmp(line, MGCP_X_OSMO_IGN_HEADER, strlen(MGCP_X_OSMO_IGN_HEADER)))
|
||||
return false;
|
||||
line += strlen(MGCP_X_OSMO_IGN_HEADER);
|
||||
|
||||
@@ -746,8 +749,11 @@ static struct msgb *handle_create_con(struct mgcp_parse_data *p)
|
||||
int rc;
|
||||
|
||||
LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "CRCX: creating new connection ...\n");
|
||||
|
||||
if (!mgcp_endp_avail(endp)) {
|
||||
rate_ctr_inc(&rate_ctrs->ctr[MGCP_CRCX_FAIL_AVAIL]);
|
||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||
"CRCX: selected endpoint not available!\n");
|
||||
return create_err_response(NULL, 501, "CRCX", p->trans);
|
||||
}
|
||||
|
||||
@@ -940,6 +946,9 @@ mgcp_header_done:
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* Find a local address for conn based on policy and initial SDP remote
|
||||
information, then find a free port for it */
|
||||
mgcp_get_local_addr(conn->end.local_addr, conn);
|
||||
if (allocate_port(endp, conn) != 0) {
|
||||
rate_ctr_inc(&rate_ctrs->ctr[MGCP_CRCX_FAIL_BIND_PORT]);
|
||||
goto error2;
|
||||
@@ -1002,6 +1011,7 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
|
||||
{
|
||||
struct mgcp_endpoint *endp = p->endp;
|
||||
struct rate_ctr_group *rate_ctrs = endp->trunk->ratectr.mgcp_mdcx_ctr_group;
|
||||
char new_local_addr[INET6_ADDRSTRLEN];
|
||||
int error_code = 500;
|
||||
int silent = 0;
|
||||
int have_sdp = 0;
|
||||
@@ -1017,6 +1027,8 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
|
||||
|
||||
if (!mgcp_endp_avail(endp)) {
|
||||
rate_ctr_inc(&rate_ctrs->ctr[MGCP_MDCX_FAIL_AVAIL]);
|
||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||
"MDCX: selected endpoint not available!\n");
|
||||
return create_err_response(NULL, 501, "MDCX", p->trans);
|
||||
}
|
||||
|
||||
@@ -1164,6 +1176,20 @@ mgcp_header_done:
|
||||
that conn. */
|
||||
}
|
||||
|
||||
/* MDCX may have provided a new remote address, which means we may need
|
||||
to update our announced IP addr and re-bind our local end. This can
|
||||
happen for instance if MGW initially provided an IPv4 during CRCX
|
||||
ACK, and now MDCX tells us the remote has an IPv6 address. */
|
||||
mgcp_get_local_addr(new_local_addr, conn);
|
||||
if (strcmp(new_local_addr, conn->end.local_addr)) {
|
||||
osmo_strlcpy(conn->end.local_addr, new_local_addr, sizeof(conn->end.local_addr));
|
||||
mgcp_free_rtp_port(&conn->end);
|
||||
if (allocate_port(endp, conn) != 0) {
|
||||
rate_ctr_inc(&rate_ctrs->ctr[MGCP_CRCX_FAIL_BIND_PORT]);
|
||||
goto error3;
|
||||
}
|
||||
}
|
||||
|
||||
if (setup_rtp_processing(endp, conn) != 0) {
|
||||
rate_ctr_inc(&rate_ctrs->ctr[MGCP_MDCX_FAIL_START_RTP]);
|
||||
goto error3;
|
||||
@@ -1243,6 +1269,8 @@ static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
|
||||
|
||||
if (!mgcp_endp_avail(endp)) {
|
||||
rate_ctr_inc(&rate_ctrs->ctr[MGCP_DLCX_FAIL_AVAIL]);
|
||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||
"DLCX: selected endpoint not available!\n");
|
||||
return create_err_response(NULL, 501, "DLCX", p->trans);
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,9 @@
|
||||
*/
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <osmocom/core/sockaddr_str.h>
|
||||
|
||||
#include <osmocom/mgcp/mgcp.h>
|
||||
#include <osmocom/mgcp/osmux.h>
|
||||
#include <osmocom/mgcp/mgcp_conn.h>
|
||||
@@ -259,6 +262,42 @@ error:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
static int audio_ip_from_sdp(struct osmo_sockaddr *dst_addr, char *sdp)
|
||||
{
|
||||
bool is_ipv6;
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
if (strncmp("c=IN IP", sdp, 7) != 0)
|
||||
return -1;
|
||||
sdp += 7;
|
||||
if (*sdp == '6')
|
||||
is_ipv6 = true;
|
||||
else if (*sdp == '4')
|
||||
is_ipv6 = false;
|
||||
else
|
||||
return -1;
|
||||
sdp++;
|
||||
if (*sdp != ' ')
|
||||
return -1;
|
||||
sdp++;
|
||||
if (is_ipv6) {
|
||||
/* 45 = INET6_ADDRSTRLEN -1 */
|
||||
if (sscanf(sdp, "%45s", ipbuf) != 1)
|
||||
return -1;
|
||||
if (inet_pton(AF_INET6, ipbuf, &dst_addr->u.sin6.sin6_addr) != 1)
|
||||
return -1;
|
||||
dst_addr->u.sa.sa_family = AF_INET6;
|
||||
} else {
|
||||
/* 15 = INET_ADDRSTRLEN -1 */
|
||||
if (sscanf(sdp, "%15s", ipbuf) != 1)
|
||||
return -1;
|
||||
if (inet_pton(AF_INET, ipbuf, &dst_addr->u.sin.sin_addr) != 1)
|
||||
return -1;
|
||||
dst_addr->u.sa.sa_family = AF_INET;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Pick optional fmtp parameters by payload type, if there are no fmtp
|
||||
* parameters, a nullpointer is returned */
|
||||
static struct mgcp_codec_param *param_by_pt(int pt, struct sdp_fmtp_param *fmtp_params, unsigned int fmtp_params_len)
|
||||
@@ -289,6 +328,7 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
|
||||
struct sdp_fmtp_param fmtp_params[MGCP_MAX_CODECS];
|
||||
unsigned int fmtp_used = 0;
|
||||
struct mgcp_codec_param *codec_param;
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
char *line;
|
||||
unsigned int i;
|
||||
void *tmp_ctx = talloc_new(NULL);
|
||||
@@ -298,7 +338,6 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
|
||||
int ptime, ptime2 = 0;
|
||||
char audio_name[64];
|
||||
int port, rc;
|
||||
char ipv4[16];
|
||||
|
||||
OSMO_ASSERT(endp);
|
||||
OSMO_ASSERT(conn);
|
||||
@@ -355,10 +394,8 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
|
||||
codecs_used = rc;
|
||||
break;
|
||||
case 'c':
|
||||
|
||||
if (sscanf(line, "c=IN IP4 %15s", ipv4) == 1) {
|
||||
inet_aton(ipv4, &rtp->addr);
|
||||
}
|
||||
if (audio_ip_from_sdp(&rtp->addr, line) < 0)
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
if (p->endp)
|
||||
@@ -393,7 +430,7 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
|
||||
|
||||
LOGPCONN(conn->conn, DLMGCP, LOGL_NOTICE,
|
||||
"Got media info via SDP: port:%d, addr:%s, duration:%d, payload-types:",
|
||||
ntohs(rtp->rtp_port), inet_ntoa(rtp->addr),
|
||||
ntohs(rtp->rtp_port), osmo_sockaddr_ntop(&rtp->addr.u.sa, ipbuf),
|
||||
rtp->packet_duration_ms);
|
||||
if (codecs_used == 0)
|
||||
LOGPC(DLMGCP, LOGL_NOTICE, "none");
|
||||
@@ -529,6 +566,7 @@ int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
|
||||
int local_port;
|
||||
struct sdp_fmtp_param fmtp_params[1];
|
||||
unsigned int fmtp_params_len = 0;
|
||||
bool addr_is_v6;
|
||||
|
||||
OSMO_ASSERT(endp);
|
||||
OSMO_ASSERT(conn);
|
||||
@@ -543,12 +581,16 @@ int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
|
||||
audio_name = codec->audio_name;
|
||||
payload_type = codec->payload_type;
|
||||
|
||||
addr_is_v6 = osmo_ip_str_type(addr) == AF_INET6;
|
||||
|
||||
rc = msgb_printf(sdp,
|
||||
"v=0\r\n"
|
||||
"o=- %s 23 IN IP4 %s\r\n"
|
||||
"o=- %s 23 IN IP%c %s\r\n"
|
||||
"s=-\r\n"
|
||||
"c=IN IP4 %s\r\n"
|
||||
"t=0 0\r\n", conn->conn->id, addr, addr);
|
||||
"c=IN IP%c %s\r\n"
|
||||
"t=0 0\r\n", conn->conn->id,
|
||||
addr_is_v6 ? '6' : '4', addr,
|
||||
addr_is_v6 ? '6' : '4', addr);
|
||||
|
||||
if (rc < 0)
|
||||
goto buffer_too_small;
|
||||
|
@@ -50,7 +50,7 @@ struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_typ
|
||||
|
||||
trunk->audio_send_ptime = 1;
|
||||
trunk->audio_send_name = 1;
|
||||
trunk->v.vty_number_endpoints = 32;
|
||||
trunk->v.vty_number_endpoints = 512;
|
||||
trunk->omit_rtcp = 0;
|
||||
|
||||
mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
|
||||
@@ -190,7 +190,7 @@ int e1_trunk_nr_from_epname(const char *epname)
|
||||
|
||||
errno = 0;
|
||||
trunk_nr = strtoul(epname + prefix_len, &str_trunk_nr_end, 10);
|
||||
if (errno == ERANGE || trunk_nr > 64 || trunk_nr == 0
|
||||
if (errno == ERANGE || trunk_nr > 64
|
||||
|| epname + prefix_len == str_trunk_nr_end
|
||||
|| str_trunk_nr_end[0] != '/')
|
||||
return -EINVAL;
|
||||
@@ -217,7 +217,7 @@ struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char
|
||||
}
|
||||
|
||||
trunk_nr = e1_trunk_nr_from_epname(epname);
|
||||
if (trunk_nr > 0)
|
||||
if (trunk_nr >= 0)
|
||||
return mgcp_trunk_by_num(cfg, MGCP_TRUNK_E1, trunk_nr);
|
||||
|
||||
/* Earlier versions of osmo-mgw were accepting endpoint names
|
||||
|
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/sockaddr_str.h>
|
||||
#include <osmocom/vty/misc.h>
|
||||
#include <osmocom/mgcp/mgcp.h>
|
||||
#include <osmocom/mgcp/mgcp_common.h>
|
||||
@@ -41,6 +42,7 @@
|
||||
#define RTP_KEEPALIVE_STR "Send dummy UDP packet to net RTP destination\n"
|
||||
#define RTP_TS101318_RFC5993_CONV_STR "Convert GSM-HR from TS101318 to RFC5993 and vice versa\n"
|
||||
|
||||
#define X(x) (1 << x)
|
||||
|
||||
static struct mgcp_config *g_cfg = NULL;
|
||||
|
||||
@@ -70,9 +72,12 @@ static int config_write_mgcp(struct vty *vty)
|
||||
vty_out(vty, " rtp port-range %u %u%s",
|
||||
g_cfg->net_ports.range_start, g_cfg->net_ports.range_end,
|
||||
VTY_NEWLINE);
|
||||
if (g_cfg->net_ports.bind_addr)
|
||||
if (g_cfg->net_ports.bind_addr_v4)
|
||||
vty_out(vty, " rtp bind-ip %s%s",
|
||||
g_cfg->net_ports.bind_addr, VTY_NEWLINE);
|
||||
g_cfg->net_ports.bind_addr_v4, VTY_NEWLINE);
|
||||
if (g_cfg->net_ports.bind_addr_v6)
|
||||
vty_out(vty, " rtp bind-ip-v6 %s%s",
|
||||
g_cfg->net_ports.bind_addr_v6, VTY_NEWLINE);
|
||||
if (g_cfg->net_ports.bind_addr_probe)
|
||||
vty_out(vty, " rtp ip-probing%s", VTY_NEWLINE);
|
||||
else
|
||||
@@ -111,7 +116,6 @@ static int config_write_mgcp(struct vty *vty)
|
||||
trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
|
||||
vty_out(vty, " %ssdp audio-payload send-name%s",
|
||||
trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
|
||||
vty_out(vty, " loop %u%s", ! !trunk->audio_loop, VTY_NEWLINE);
|
||||
vty_out(vty, " number endpoints %u%s",
|
||||
trunk->v.vty_number_endpoints, VTY_NEWLINE);
|
||||
vty_out(vty, " %sallow-transcoding%s",
|
||||
@@ -405,11 +409,14 @@ DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_local_ip,
|
||||
cfg_mgcp_local_ip_cmd,
|
||||
"local ip A.B.C.D",
|
||||
"Local options for the SDP record\n"
|
||||
IP_STR "IPv4 Address to use in SDP record\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_local_ip,
|
||||
cfg_mgcp_local_ip_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"local ip " VTY_IPV46_CMD,
|
||||
"Local options for the SDP record\n"
|
||||
IP_STR
|
||||
"IPv4 Address to use in SDP record\n"
|
||||
"IPv6 Address to use in SDP record\n")
|
||||
{
|
||||
osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
@@ -418,7 +425,10 @@ DEFUN(cfg_mgcp_local_ip,
|
||||
#define BIND_STR "Listen/Bind related socket option\n"
|
||||
DEFUN(cfg_mgcp_bind_ip,
|
||||
cfg_mgcp_bind_ip_cmd,
|
||||
"bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
|
||||
"bind ip " VTY_IPV46_CMD,
|
||||
BIND_STR IP_STR
|
||||
"IPv4 Address to bind to\n"
|
||||
"IPv6 Address to bind to\n")
|
||||
{
|
||||
osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
@@ -434,14 +444,13 @@ DEFUN(cfg_mgcp_bind_port,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_bind_early,
|
||||
cfg_mgcp_bind_early_cmd,
|
||||
"bind early (0|1)",
|
||||
BIND_STR
|
||||
"Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
|
||||
DEFUN_DEPRECATED(cfg_mgcp_bind_early,
|
||||
cfg_mgcp_bind_early_cmd,
|
||||
"bind early (0|1)",
|
||||
BIND_STR
|
||||
"Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
|
||||
{
|
||||
vty_out(vty, "bind early is deprecated, remove it from the config.\n");
|
||||
return CMD_WARNING;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define RTP_STR "RTP configuration\n"
|
||||
@@ -492,12 +501,14 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
|
||||
RTP_STR "Range of ports to use for the NET side\n"
|
||||
RANGE_START_STR RANGE_END_STR)
|
||||
|
||||
DEFUN(cfg_mgcp_rtp_bind_ip,
|
||||
cfg_mgcp_rtp_bind_ip_cmd,
|
||||
"rtp bind-ip A.B.C.D",
|
||||
RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_rtp_bind_ip,
|
||||
cfg_mgcp_rtp_bind_ip_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp bind-ip A.B.C.D",
|
||||
RTP_STR "Bind endpoints facing the Network\n"
|
||||
"IPv4 Address to bind to\n")
|
||||
{
|
||||
osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
|
||||
osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr_v4, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
|
||||
@@ -505,14 +516,15 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
|
||||
"rtp net-bind-ip A.B.C.D",
|
||||
RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
|
||||
|
||||
DEFUN(cfg_mgcp_rtp_no_bind_ip,
|
||||
cfg_mgcp_rtp_no_bind_ip_cmd,
|
||||
"no rtp bind-ip",
|
||||
NO_STR RTP_STR "Bind endpoints facing the Network\n"
|
||||
"Address to bind to\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_rtp_no_bind_ip,
|
||||
cfg_mgcp_rtp_no_bind_ip_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp bind-ip",
|
||||
NO_STR RTP_STR "Bind endpoints facing the Network\n"
|
||||
"Address to bind to\n")
|
||||
{
|
||||
talloc_free(g_cfg->net_ports.bind_addr);
|
||||
g_cfg->net_ports.bind_addr = NULL;
|
||||
talloc_free(g_cfg->net_ports.bind_addr_v4);
|
||||
g_cfg->net_ports.bind_addr_v4 = NULL;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
|
||||
@@ -521,29 +533,55 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
|
||||
NO_STR RTP_STR "Bind endpoints facing the Network\n"
|
||||
"Address to bind to\n")
|
||||
|
||||
DEFUN(cfg_mgcp_rtp_net_bind_ip_probing,
|
||||
cfg_mgcp_rtp_net_bind_ip_probing_cmd,
|
||||
"rtp ip-probing",
|
||||
RTP_STR "automatic rtp bind ip selection\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_rtp_bind_ip_v6,
|
||||
cfg_mgcp_rtp_bind_ip_v6_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp bind-ip-v6 " VTY_IPV6_CMD,
|
||||
RTP_STR "Bind endpoints facing the Network\n"
|
||||
"IPv6 Address to bind to\n")
|
||||
{
|
||||
osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr_v6, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN_USRATTR(cfg_mgcp_rtp_no_bind_ip_v6,
|
||||
cfg_mgcp_rtp_no_bind_ip_v6_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp bind-ip-v6",
|
||||
NO_STR RTP_STR "Bind endpoints facing the Network\n"
|
||||
"Address to bind to\n")
|
||||
{
|
||||
talloc_free(g_cfg->net_ports.bind_addr_v6);
|
||||
g_cfg->net_ports.bind_addr_v6 = NULL;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN_USRATTR(cfg_mgcp_rtp_net_bind_ip_probing,
|
||||
cfg_mgcp_rtp_net_bind_ip_probing_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp ip-probing",
|
||||
RTP_STR "automatic rtp bind ip selection\n")
|
||||
{
|
||||
g_cfg->net_ports.bind_addr_probe = true;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_rtp_no_net_bind_ip_probing,
|
||||
cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
|
||||
"no rtp ip-probing",
|
||||
NO_STR RTP_STR "no automatic rtp bind ip selection\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_rtp_no_net_bind_ip_probing,
|
||||
cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp ip-probing",
|
||||
NO_STR RTP_STR "no automatic rtp bind ip selection\n")
|
||||
{
|
||||
g_cfg->net_ports.bind_addr_probe = false;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_rtp_ip_dscp,
|
||||
cfg_mgcp_rtp_ip_dscp_cmd,
|
||||
"rtp ip-dscp <0-255>",
|
||||
RTP_STR
|
||||
"Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_rtp_ip_dscp,
|
||||
cfg_mgcp_rtp_ip_dscp_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp ip-dscp <0-255>",
|
||||
RTP_STR
|
||||
"Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
|
||||
{
|
||||
int dscp = atoi(argv[0]);
|
||||
g_cfg->endp_dscp = dscp;
|
||||
@@ -555,29 +593,32 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
|
||||
RTP_STR
|
||||
"Apply IP_TOS to the audio stream\n" "The DSCP value\n")
|
||||
#define FORCE_PTIME_STR "Force a fixed ptime for packets sent"
|
||||
DEFUN(cfg_mgcp_rtp_force_ptime,
|
||||
cfg_mgcp_rtp_force_ptime_cmd,
|
||||
"rtp force-ptime (10|20|40)",
|
||||
RTP_STR FORCE_PTIME_STR
|
||||
"The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_rtp_force_ptime,
|
||||
cfg_mgcp_rtp_force_ptime_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp force-ptime (10|20|40)",
|
||||
RTP_STR FORCE_PTIME_STR
|
||||
"The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
|
||||
{
|
||||
g_cfg->force_ptime = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_rtp_force_ptime,
|
||||
cfg_mgcp_no_rtp_force_ptime_cmd,
|
||||
"no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
|
||||
DEFUN_USRATTR(cfg_mgcp_no_rtp_force_ptime,
|
||||
cfg_mgcp_no_rtp_force_ptime_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
|
||||
{
|
||||
g_cfg->force_ptime = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_sdp_fmtp_extra,
|
||||
cfg_mgcp_sdp_fmtp_extra_cmd,
|
||||
"sdp audio fmtp-extra .NAME",
|
||||
"Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
|
||||
"Extra Information\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_sdp_fmtp_extra,
|
||||
cfg_mgcp_sdp_fmtp_extra_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"sdp audio fmtp-extra .NAME",
|
||||
"Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
|
||||
"Extra Information\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -590,9 +631,10 @@ DEFUN(cfg_mgcp_sdp_fmtp_extra,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_allow_transcoding,
|
||||
cfg_mgcp_allow_transcoding_cmd,
|
||||
"allow-transcoding", "Allow transcoding\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_allow_transcoding,
|
||||
cfg_mgcp_allow_transcoding_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"allow-transcoding", "Allow transcoding\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -600,9 +642,10 @@ DEFUN(cfg_mgcp_allow_transcoding,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_allow_transcoding,
|
||||
cfg_mgcp_no_allow_transcoding_cmd,
|
||||
"no allow-transcoding", NO_STR "Allow transcoding\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_no_allow_transcoding,
|
||||
cfg_mgcp_no_allow_transcoding_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no allow-transcoding", NO_STR "Allow transcoding\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -637,10 +680,11 @@ ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
|
||||
"sdp audio payload name NAME",
|
||||
SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
|
||||
|
||||
DEFUN(cfg_mgcp_sdp_payload_send_ptime,
|
||||
cfg_mgcp_sdp_payload_send_ptime_cmd,
|
||||
"sdp audio-payload send-ptime",
|
||||
SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_sdp_payload_send_ptime,
|
||||
cfg_mgcp_sdp_payload_send_ptime_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"sdp audio-payload send-ptime",
|
||||
SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -648,10 +692,11 @@ DEFUN(cfg_mgcp_sdp_payload_send_ptime,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
|
||||
cfg_mgcp_no_sdp_payload_send_ptime_cmd,
|
||||
"no sdp audio-payload send-ptime",
|
||||
NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_no_sdp_payload_send_ptime,
|
||||
cfg_mgcp_no_sdp_payload_send_ptime_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no sdp audio-payload send-ptime",
|
||||
NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -659,10 +704,11 @@ DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_sdp_payload_send_name,
|
||||
cfg_mgcp_sdp_payload_send_name_cmd,
|
||||
"sdp audio-payload send-name",
|
||||
SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_sdp_payload_send_name,
|
||||
cfg_mgcp_sdp_payload_send_name_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"sdp audio-payload send-name",
|
||||
SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -670,10 +716,11 @@ DEFUN(cfg_mgcp_sdp_payload_send_name,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_sdp_payload_send_name,
|
||||
cfg_mgcp_no_sdp_payload_send_name_cmd,
|
||||
"no sdp audio-payload send-name",
|
||||
NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_no_sdp_payload_send_name,
|
||||
cfg_mgcp_no_sdp_payload_send_name_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no sdp audio-payload send-name",
|
||||
NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -681,26 +728,20 @@ DEFUN(cfg_mgcp_no_sdp_payload_send_name,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_loop,
|
||||
cfg_mgcp_loop_cmd,
|
||||
"loop (0|1)",
|
||||
"Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
|
||||
DEFUN_DEPRECATED(cfg_mgcp_loop,
|
||||
cfg_mgcp_loop_cmd,
|
||||
"loop (0|1)",
|
||||
"Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
if (g_cfg->osmux) {
|
||||
vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
trunk->audio_loop = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_force_realloc,
|
||||
cfg_mgcp_force_realloc_cmd,
|
||||
"force-realloc (0|1)",
|
||||
"Force endpoint reallocation when the endpoint is still seized\n"
|
||||
"Don't force reallocation\n" "force reallocation\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_force_realloc,
|
||||
cfg_mgcp_force_realloc_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"force-realloc (0|1)",
|
||||
"Force endpoint reallocation when the endpoint is still seized\n"
|
||||
"Don't force reallocation\n" "force reallocation\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -708,11 +749,12 @@ DEFUN(cfg_mgcp_force_realloc,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_rtp_accept_all,
|
||||
cfg_mgcp_rtp_accept_all_cmd,
|
||||
"rtp-accept-all (0|1)",
|
||||
"Accept all RTP packets, even when the originating IP/Port does not match\n"
|
||||
"enable filter\n" "disable filter\n")
|
||||
DEFUN_ATTR(cfg_mgcp_rtp_accept_all,
|
||||
cfg_mgcp_rtp_accept_all_cmd,
|
||||
"rtp-accept-all (0|1)",
|
||||
"Accept all RTP packets, even when the originating IP/Port does not match\n"
|
||||
"enable filter\n" "disable filter\n",
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -731,15 +773,21 @@ DEFUN(cfg_mgcp_number_endp,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_omit_rtcp, cfg_mgcp_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
|
||||
DEFUN_ATTR(cfg_mgcp_omit_rtcp,
|
||||
cfg_mgcp_omit_rtcp_cmd,
|
||||
"rtcp-omit", RTCP_OMIT_STR,
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
trunk->omit_rtcp = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_omit_rtcp,
|
||||
cfg_mgcp_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
|
||||
DEFUN_ATTR(cfg_mgcp_no_omit_rtcp,
|
||||
cfg_mgcp_no_omit_rtcp_cmd,
|
||||
"no rtcp-omit",
|
||||
NO_STR RTCP_OMIT_STR,
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -747,9 +795,10 @@ DEFUN(cfg_mgcp_no_omit_rtcp,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_patch_rtp_ssrc,
|
||||
cfg_mgcp_patch_rtp_ssrc_cmd,
|
||||
"rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_patch_rtp_ssrc,
|
||||
cfg_mgcp_patch_rtp_ssrc_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -757,9 +806,10 @@ DEFUN(cfg_mgcp_patch_rtp_ssrc,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
|
||||
cfg_mgcp_no_patch_rtp_ssrc_cmd,
|
||||
"no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_no_patch_rtp_ssrc,
|
||||
cfg_mgcp_no_patch_rtp_ssrc_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -767,9 +817,10 @@ DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_patch_rtp_ts,
|
||||
cfg_mgcp_patch_rtp_ts_cmd,
|
||||
"rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_patch_rtp_ts,
|
||||
cfg_mgcp_patch_rtp_ts_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -777,9 +828,10 @@ DEFUN(cfg_mgcp_patch_rtp_ts,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_patch_rtp_ts,
|
||||
cfg_mgcp_no_patch_rtp_ts_cmd,
|
||||
"no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
|
||||
DEFUN_USRATTR(cfg_mgcp_no_patch_rtp_ts,
|
||||
cfg_mgcp_no_patch_rtp_ts_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -787,9 +839,10 @@ DEFUN(cfg_mgcp_no_patch_rtp_ts,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_patch_rtp_rfc5993hr,
|
||||
cfg_mgcp_patch_rtp_rfc5993hr_cmd,
|
||||
"rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
|
||||
DEFUN_USRATTR(cfg_mgcp_patch_rtp_rfc5993hr,
|
||||
cfg_mgcp_patch_rtp_rfc5993hr_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -797,9 +850,10 @@ DEFUN(cfg_mgcp_patch_rtp_rfc5993hr,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_patch_rtp_rfc5993hr,
|
||||
cfg_mgcp_no_patch_rtp_rfc5993hr_cmd,
|
||||
"no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
|
||||
DEFUN_USRATTR(cfg_mgcp_no_patch_rtp_rfc5993hr,
|
||||
cfg_mgcp_no_patch_rtp_rfc5993hr_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -807,8 +861,10 @@ DEFUN(cfg_mgcp_no_patch_rtp_rfc5993hr,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_patch_rtp,
|
||||
cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
|
||||
DEFUN_USRATTR(cfg_mgcp_no_patch_rtp,
|
||||
cfg_mgcp_no_patch_rtp_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp-patch", NO_STR RTP_PATCH_STR)
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -818,10 +874,11 @@ DEFUN(cfg_mgcp_no_patch_rtp,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_rtp_keepalive,
|
||||
cfg_mgcp_rtp_keepalive_cmd,
|
||||
"rtp keep-alive <1-120>",
|
||||
RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n")
|
||||
DEFUN_ATTR(cfg_mgcp_rtp_keepalive,
|
||||
cfg_mgcp_rtp_keepalive_cmd,
|
||||
"rtp keep-alive <1-120>",
|
||||
RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n",
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -829,10 +886,11 @@ DEFUN(cfg_mgcp_rtp_keepalive,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_rtp_keepalive_once,
|
||||
cfg_mgcp_rtp_keepalive_once_cmd,
|
||||
"rtp keep-alive once",
|
||||
RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
|
||||
DEFUN_ATTR(cfg_mgcp_rtp_keepalive_once,
|
||||
cfg_mgcp_rtp_keepalive_once_cmd,
|
||||
"rtp keep-alive once",
|
||||
RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n",
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -840,9 +898,10 @@ DEFUN(cfg_mgcp_rtp_keepalive_once,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_rtp_keepalive,
|
||||
cfg_mgcp_no_rtp_keepalive_cmd,
|
||||
"no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
|
||||
DEFUN_ATTR(cfg_mgcp_no_rtp_keepalive,
|
||||
cfg_mgcp_no_rtp_keepalive_cmd,
|
||||
"no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR,
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
|
||||
OSMO_ASSERT(trunk);
|
||||
@@ -850,11 +909,13 @@ DEFUN(cfg_mgcp_no_rtp_keepalive,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define CALL_AGENT_STR "Callagent information\n"
|
||||
#define CALL_AGENT_STR "Call agent information\n"
|
||||
DEFUN(cfg_mgcp_agent_addr,
|
||||
cfg_mgcp_agent_addr_cmd,
|
||||
"call-agent ip A.B.C.D",
|
||||
CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
|
||||
"call-agent ip " VTY_IPV46_CMD,
|
||||
CALL_AGENT_STR IP_STR
|
||||
"IPv4 Address of the call agent\n"
|
||||
"IPv6 Address of the call agent\n")
|
||||
{
|
||||
osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
@@ -866,16 +927,11 @@ ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
|
||||
"IPv4 Address of the callagent\n")
|
||||
|
||||
DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
|
||||
"trunk <1-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
|
||||
"trunk <0-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk;
|
||||
int index = atoi(argv[0]);
|
||||
|
||||
/* Due to historical reasons, the trunk id number 0 is reserved for the
|
||||
* virtual trunk. This trunk is configured with separate VTY
|
||||
* parameters, so we restrict the access to trunks with id numbers
|
||||
* greater than 0. */
|
||||
|
||||
trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_E1, index);
|
||||
if (!trunk) {
|
||||
trunk = mgcp_trunk_alloc(g_cfg, MGCP_TRUNK_E1, index);
|
||||
@@ -919,7 +975,6 @@ static int config_write_trunk(struct vty *vty)
|
||||
trunk->keepalive_interval, VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
|
||||
vty_out(vty, " loop %d%s", trunk->audio_loop, VTY_NEWLINE);
|
||||
vty_out(vty, " force-realloc %d%s",
|
||||
trunk->force_realloc, VTY_NEWLINE);
|
||||
vty_out(vty, " rtp-accept-all %d%s",
|
||||
@@ -951,11 +1006,12 @@ static int config_write_trunk(struct vty *vty)
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_sdp_fmtp_extra,
|
||||
cfg_trunk_sdp_fmtp_extra_cmd,
|
||||
"sdp audio fmtp-extra .NAME",
|
||||
"Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
|
||||
"Extra Information\n")
|
||||
DEFUN_USRATTR(cfg_trunk_sdp_fmtp_extra,
|
||||
cfg_trunk_sdp_fmtp_extra_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"sdp audio fmtp-extra .NAME",
|
||||
"Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
|
||||
"Extra Information\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
char *txt = argv_concat(argv, argc, 0);
|
||||
@@ -991,132 +1047,142 @@ ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
|
||||
"sdp audio payload name NAME",
|
||||
SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
|
||||
|
||||
DEFUN(cfg_trunk_loop,
|
||||
cfg_trunk_loop_cmd,
|
||||
"loop (0|1)",
|
||||
"Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
|
||||
DEFUN_DEPRECATED(cfg_trunk_loop,
|
||||
cfg_trunk_loop_cmd,
|
||||
"loop (0|1)",
|
||||
"Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
|
||||
if (g_cfg->osmux) {
|
||||
vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
trunk->audio_loop = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_sdp_payload_send_ptime,
|
||||
cfg_trunk_sdp_payload_send_ptime_cmd,
|
||||
"sdp audio-payload send-ptime",
|
||||
SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
|
||||
DEFUN_USRATTR(cfg_trunk_sdp_payload_send_ptime,
|
||||
cfg_trunk_sdp_payload_send_ptime_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"sdp audio-payload send-ptime",
|
||||
SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->audio_send_ptime = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
|
||||
cfg_trunk_no_sdp_payload_send_ptime_cmd,
|
||||
"no sdp audio-payload send-ptime",
|
||||
NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
|
||||
DEFUN_USRATTR(cfg_trunk_no_sdp_payload_send_ptime,
|
||||
cfg_trunk_no_sdp_payload_send_ptime_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no sdp audio-payload send-ptime",
|
||||
NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->audio_send_ptime = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_sdp_payload_send_name,
|
||||
cfg_trunk_sdp_payload_send_name_cmd,
|
||||
"sdp audio-payload send-name",
|
||||
SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
|
||||
DEFUN_USRATTR(cfg_trunk_sdp_payload_send_name,
|
||||
cfg_trunk_sdp_payload_send_name_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"sdp audio-payload send-name",
|
||||
SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->audio_send_name = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_sdp_payload_send_name,
|
||||
cfg_trunk_no_sdp_payload_send_name_cmd,
|
||||
"no sdp audio-payload send-name",
|
||||
NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
|
||||
DEFUN_USRATTR(cfg_trunk_no_sdp_payload_send_name,
|
||||
cfg_trunk_no_sdp_payload_send_name_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no sdp audio-payload send-name",
|
||||
NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->audio_send_name = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_omit_rtcp, cfg_trunk_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
|
||||
DEFUN_ATTR(cfg_trunk_omit_rtcp,
|
||||
cfg_trunk_omit_rtcp_cmd,
|
||||
"rtcp-omit", RTCP_OMIT_STR,
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->omit_rtcp = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_omit_rtcp,
|
||||
cfg_trunk_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
|
||||
DEFUN_ATTR(cfg_trunk_no_omit_rtcp,
|
||||
cfg_trunk_no_omit_rtcp_cmd,
|
||||
"no rtcp-omit", NO_STR RTCP_OMIT_STR,
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->omit_rtcp = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_patch_rtp_ssrc,
|
||||
cfg_trunk_patch_rtp_ssrc_cmd,
|
||||
"rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
|
||||
DEFUN_USRATTR(cfg_trunk_patch_rtp_ssrc,
|
||||
cfg_trunk_patch_rtp_ssrc_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->force_constant_ssrc = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_patch_rtp_ssrc,
|
||||
cfg_trunk_no_patch_rtp_ssrc_cmd,
|
||||
"no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
|
||||
DEFUN_USRATTR(cfg_trunk_no_patch_rtp_ssrc,
|
||||
cfg_trunk_no_patch_rtp_ssrc_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->force_constant_ssrc = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_patch_rtp_ts,
|
||||
cfg_trunk_patch_rtp_ts_cmd,
|
||||
"rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
|
||||
DEFUN_USRATTR(cfg_trunk_patch_rtp_ts,
|
||||
cfg_trunk_patch_rtp_ts_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->force_aligned_timing = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_patch_rtp_ts,
|
||||
cfg_trunk_no_patch_rtp_ts_cmd,
|
||||
"no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
|
||||
DEFUN_USRATTR(cfg_trunk_no_patch_rtp_ts,
|
||||
cfg_trunk_no_patch_rtp_ts_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->force_aligned_timing = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_patch_rtp_rfc5993hr,
|
||||
cfg_trunk_patch_rtp_rfc5993hr_cmd,
|
||||
"rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
|
||||
DEFUN_USRATTR(cfg_trunk_patch_rtp_rfc5993hr,
|
||||
cfg_trunk_patch_rtp_rfc5993hr_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->rfc5993_hr_convert = true;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_patch_rtp_rfc5993hr,
|
||||
cfg_trunk_no_patch_rtp_rfc5993hr_cmd,
|
||||
"no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
|
||||
DEFUN_USRATTR(cfg_trunk_no_patch_rtp_rfc5993hr,
|
||||
cfg_trunk_no_patch_rtp_rfc5993hr_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->rfc5993_hr_convert = false;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_patch_rtp,
|
||||
cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
|
||||
DEFUN_USRATTR(cfg_trunk_no_patch_rtp,
|
||||
cfg_trunk_no_patch_rtp_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no rtp-patch", NO_STR RTP_PATCH_STR)
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->force_constant_ssrc = 0;
|
||||
@@ -1125,47 +1191,52 @@ DEFUN(cfg_trunk_no_patch_rtp,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_rtp_keepalive,
|
||||
cfg_trunk_rtp_keepalive_cmd,
|
||||
"rtp keep-alive <1-120>",
|
||||
RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n")
|
||||
DEFUN_ATTR(cfg_trunk_rtp_keepalive,
|
||||
cfg_trunk_rtp_keepalive_cmd,
|
||||
"rtp keep-alive <1-120>",
|
||||
RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n",
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_rtp_keepalive_once,
|
||||
cfg_trunk_rtp_keepalive_once_cmd,
|
||||
"rtp keep-alive once",
|
||||
RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
|
||||
DEFUN_ATTR(cfg_trunk_rtp_keepalive_once,
|
||||
cfg_trunk_rtp_keepalive_once_cmd,
|
||||
"rtp keep-alive once",
|
||||
RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n",
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_rtp_keepalive,
|
||||
cfg_trunk_no_rtp_keepalive_cmd,
|
||||
"no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
|
||||
DEFUN_ATTR(cfg_trunk_no_rtp_keepalive,
|
||||
cfg_trunk_no_rtp_keepalive_cmd,
|
||||
"no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR,
|
||||
CMD_ATTR_IMMEDIATE)
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
mgcp_trunk_set_keepalive(trunk, 0);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_allow_transcoding,
|
||||
cfg_trunk_allow_transcoding_cmd,
|
||||
"allow-transcoding", "Allow transcoding\n")
|
||||
DEFUN_USRATTR(cfg_trunk_allow_transcoding,
|
||||
cfg_trunk_allow_transcoding_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"allow-transcoding", "Allow transcoding\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->no_audio_transcoding = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_allow_transcoding,
|
||||
cfg_trunk_no_allow_transcoding_cmd,
|
||||
"no allow-transcoding", NO_STR "Allow transcoding\n")
|
||||
DEFUN_USRATTR(cfg_trunk_no_allow_transcoding,
|
||||
cfg_trunk_no_allow_transcoding_cmd,
|
||||
X(MGW_CMD_ATTR_NEWCONN),
|
||||
"no allow-transcoding", NO_STR "Allow transcoding\n")
|
||||
{
|
||||
struct mgcp_trunk *trunk = vty->index;
|
||||
trunk->no_audio_transcoding = 1;
|
||||
@@ -1241,13 +1312,15 @@ DEFUN(loop_conn,
|
||||
|
||||
DEFUN(tap_rtp,
|
||||
tap_rtp_cmd,
|
||||
"tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
|
||||
"tap-rtp <0-64> ENDPOINT CONN (in|out) " VTY_IPV46_CMD " <0-65534>",
|
||||
"Forward data on endpoint to a different system\n" "Trunk number\n"
|
||||
"The endpoint in hex\n"
|
||||
"The connection id in hex\n"
|
||||
"Forward incoming data\n"
|
||||
"Forward leaving data\n"
|
||||
"destination IP of the data\n" "destination port\n")
|
||||
"Destination IPv4 of the data\n"
|
||||
"Destination IPv6 of the data\n"
|
||||
"Destination port\n")
|
||||
{
|
||||
struct mgcp_rtp_tap *tap;
|
||||
struct mgcp_trunk *trunk;
|
||||
@@ -1295,8 +1368,22 @@ DEFUN(tap_rtp,
|
||||
}
|
||||
|
||||
memset(&tap->forward, 0, sizeof(tap->forward));
|
||||
inet_aton(argv[4], &tap->forward.sin_addr);
|
||||
tap->forward.sin_port = htons(atoi(argv[5]));
|
||||
|
||||
tap->forward.u.sa.sa_family = osmo_ip_str_type(argv[4]);
|
||||
switch (tap->forward.u.sa.sa_family) {
|
||||
case AF_INET:
|
||||
if (inet_pton(AF_INET, argv[4], &tap->forward.u.sin.sin_addr) != 1)
|
||||
return CMD_WARNING;
|
||||
tap->forward.u.sin.sin_port = htons(atoi(argv[5]));
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (inet_pton(AF_INET6, argv[4], &tap->forward.u.sin6.sin6_addr) != 1)
|
||||
return CMD_WARNING;
|
||||
tap->forward.u.sin6.sin6_port = htons(atoi(argv[5]));
|
||||
break;
|
||||
default:
|
||||
return CMD_WARNING;
|
||||
}
|
||||
tap->enabled = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@@ -1401,18 +1488,16 @@ DEFUN(cfg_mgcp_osmux,
|
||||
else if (strcmp(argv[0], "only") == 0)
|
||||
g_cfg->osmux = OSMUX_USAGE_ONLY;
|
||||
|
||||
if (trunk->audio_loop) {
|
||||
vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_osmux_ip,
|
||||
cfg_mgcp_osmux_ip_cmd,
|
||||
"osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
|
||||
"osmux bind-ip " VTY_IPV46_CMD,
|
||||
OSMUX_STR IP_STR
|
||||
"IPv4 Address to bind to\n"
|
||||
"IPv6 Address to bind to\n")
|
||||
{
|
||||
osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
@@ -1503,8 +1588,10 @@ int mgcp_vty_init(void)
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_port_range_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_v6_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_v6_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_probing_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_probing_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
|
||||
|
@@ -60,6 +60,8 @@
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/stats.h>
|
||||
#include <osmocom/vty/misc.h>
|
||||
#include <osmocom/vty/cpu_sched_vty.h>
|
||||
|
||||
#include <osmocom/abis/abis.h>
|
||||
|
||||
#include "../../bscconfig.h"
|
||||
@@ -91,7 +93,7 @@ const char *osmomgw_copyright =
|
||||
static char *config_file = "osmo-mgw.cfg";
|
||||
|
||||
/* used by msgb and mgcp */
|
||||
void *tall_bsc_ctx = NULL;
|
||||
void *tall_mgw_ctx = NULL;
|
||||
|
||||
static void print_help()
|
||||
{
|
||||
@@ -139,7 +141,7 @@ static void handle_options(int argc, char **argv)
|
||||
exit(2);
|
||||
}
|
||||
case 'c':
|
||||
config_file = talloc_strdup(tall_bsc_ctx, optarg);
|
||||
config_file = talloc_strdup(tall_mgw_ctx, optarg);
|
||||
break;
|
||||
case 's':
|
||||
log_set_use_color(osmo_stderr_target, 0);
|
||||
@@ -177,7 +179,7 @@ static int mgcp_rsip_cb(struct mgcp_trunk *trunk)
|
||||
|
||||
static int read_call_agent(struct osmo_fd *fd, unsigned int what)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
struct osmo_sockaddr addr;
|
||||
socklen_t slen = sizeof(addr);
|
||||
struct msgb *msg;
|
||||
struct msgb *resp;
|
||||
@@ -203,7 +205,7 @@ static int read_call_agent(struct osmo_fd *fd, unsigned int what)
|
||||
msgb_reset(msg);
|
||||
|
||||
if (resp) {
|
||||
sendto(cfg->gw_fd.bfd.fd, resp->l2h, msgb_l2len(resp), 0, (struct sockaddr *) &addr, sizeof(addr));
|
||||
sendto(cfg->gw_fd.bfd.fd, resp->l2h, msgb_l2len(resp), 0, &addr.u.sa, sizeof(addr));
|
||||
msgb_free(resp);
|
||||
}
|
||||
|
||||
@@ -290,20 +292,24 @@ int main(int argc, char **argv)
|
||||
unsigned int flags;
|
||||
int rc;
|
||||
|
||||
tall_bsc_ctx = talloc_named_const(NULL, 1, "mgcp-callagent");
|
||||
vty_info.tall_ctx = tall_bsc_ctx;
|
||||
tall_mgw_ctx = talloc_named_const(NULL, 1, "mgcp-callagent");
|
||||
vty_info.tall_ctx = tall_mgw_ctx;
|
||||
|
||||
msgb_talloc_ctx_init(tall_bsc_ctx, 0);
|
||||
msgb_talloc_ctx_init(tall_mgw_ctx, 0);
|
||||
|
||||
osmo_init_ignore_signals();
|
||||
osmo_init_logging2(tall_bsc_ctx, &log_info);
|
||||
libosmo_abis_init(tall_bsc_ctx);
|
||||
osmo_init_logging2(tall_mgw_ctx, &log_info);
|
||||
libosmo_abis_init(tall_mgw_ctx);
|
||||
|
||||
cfg = mgcp_config_alloc();
|
||||
if (!cfg)
|
||||
return -1;
|
||||
|
||||
vty_info.copyright = osmomgw_copyright;
|
||||
vty_info.usr_attr_desc[MGW_CMD_ATTR_NEWCONN] = \
|
||||
"This command applies when a new connection is created";
|
||||
vty_info.usr_attr_letters[MGW_CMD_ATTR_NEWCONN] = 'n';
|
||||
|
||||
vty_init(&vty_info);
|
||||
logging_vty_add_cmds();
|
||||
osmo_talloc_vty_add_cmds();
|
||||
@@ -311,18 +317,19 @@ int main(int argc, char **argv)
|
||||
mgcp_vty_init();
|
||||
ctrl_vty_init(cfg);
|
||||
e1inp_vty_init();
|
||||
osmo_cpu_sched_vty_init(tall_mgw_ctx);
|
||||
|
||||
handle_options(argc, argv);
|
||||
|
||||
rate_ctr_init(tall_bsc_ctx);
|
||||
osmo_stats_init(tall_bsc_ctx);
|
||||
rate_ctr_init(tall_mgw_ctx);
|
||||
osmo_stats_init(tall_mgw_ctx);
|
||||
|
||||
rc = mgcp_parse_config(config_file, cfg, MGCP_BSC);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* start telnet after reading config for vty_get_bind_addr() */
|
||||
rc = telnet_init_dynif(tall_bsc_ctx, NULL,
|
||||
rc = telnet_init_dynif(tall_mgw_ctx, NULL,
|
||||
vty_get_bind_addr(), OSMO_VTY_PORT_MGW);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@@ -342,7 +349,7 @@ int main(int argc, char **argv)
|
||||
if (cfg->call_agent_addr)
|
||||
flags |= OSMO_SOCK_F_CONNECT;
|
||||
|
||||
rc = osmo_sock_init2_ofd(&cfg->gw_fd.bfd, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
|
||||
rc = osmo_sock_init2_ofd(&cfg->gw_fd.bfd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
|
||||
cfg->source_addr, cfg->source_port,
|
||||
cfg->call_agent_addr, cfg->call_agent_addr ? 2727 : 0, flags);
|
||||
if (rc < 0) {
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <dlfcn.h>
|
||||
@@ -1262,7 +1263,7 @@ struct rtp_packet_info test_rtp_packets1[] = {
|
||||
void mgcp_patch_and_count(struct mgcp_endpoint *endp,
|
||||
struct mgcp_rtp_state *state,
|
||||
struct mgcp_rtp_end *rtp_end,
|
||||
struct sockaddr_in *addr, struct msgb *msg);
|
||||
struct osmo_sockaddr *addr, struct msgb *msg);
|
||||
|
||||
static void test_packet_error_detection(int patch_ssrc, int patch_ts)
|
||||
{
|
||||
@@ -1274,7 +1275,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
|
||||
struct mgcp_config cfg = {0};
|
||||
struct mgcp_rtp_state state;
|
||||
struct mgcp_rtp_end *rtp;
|
||||
struct sockaddr_in addr = { 0 };
|
||||
struct osmo_sockaddr addr = { 0 };
|
||||
uint32_t last_ssrc = 0;
|
||||
uint32_t last_timestamp = 0;
|
||||
uint32_t last_seqno = 0;
|
||||
@@ -1486,7 +1487,8 @@ static void test_multilple_codec(void)
|
||||
OSMO_ASSERT(conn->end.rtp_port == htons(16434));
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
inet_aton("8.8.8.8", &addr);
|
||||
OSMO_ASSERT(conn->end.addr.s_addr == addr.s_addr);
|
||||
OSMO_ASSERT(conn->end.addr.u.sa.sa_family == AF_INET);
|
||||
OSMO_ASSERT(conn->end.addr.u.sin.sin_addr.s_addr == addr.s_addr);
|
||||
|
||||
/* Check what happens without that flag */
|
||||
|
||||
@@ -2124,6 +2126,8 @@ void test_e1_trunk_nr_from_epname()
|
||||
/* Note: e1_trunk_nr_from_epname does not check the text
|
||||
* after the E1 trunk number, after the delimiter
|
||||
* character "/" arbitrary text may follow. */
|
||||
trunk_nr = e1_trunk_nr_from_epname("ds/e1-0/s-1/su16-0");
|
||||
OSMO_ASSERT(trunk_nr == 0);
|
||||
trunk_nr = e1_trunk_nr_from_epname("ds/e1-1/s-1/su16-0");
|
||||
OSMO_ASSERT(trunk_nr == 1);
|
||||
trunk_nr = e1_trunk_nr_from_epname("ds/e1-2/s-2/su16-0");
|
||||
@@ -2141,8 +2145,6 @@ void test_e1_trunk_nr_from_epname()
|
||||
* trunk number exceeds the valid range or the trunk prefix
|
||||
* is wrong. Also when the delimiter character "/" at the
|
||||
* end of the trunk is wrong the parsing should fail. */
|
||||
trunk_nr = e1_trunk_nr_from_epname("ds/e1-0/s-1/su16-0");
|
||||
OSMO_ASSERT(trunk_nr == -EINVAL);
|
||||
trunk_nr = e1_trunk_nr_from_epname("ds/e1-65/s-1/su16-0");
|
||||
OSMO_ASSERT(trunk_nr == -EINVAL);
|
||||
trunk_nr = e1_trunk_nr_from_epname("ds/e1--1/s-1/su16-0");
|
||||
|
@@ -294,11 +294,23 @@ void test_mgcp_msg(void)
|
||||
MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
|
||||
MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
|
||||
memset(audio_ip_overflow, 'X', sizeof(audio_ip_overflow));
|
||||
audio_ip_overflow[1] = '.';
|
||||
audio_ip_overflow[sizeof(audio_ip_overflow) - 1] = '\0';
|
||||
mgcp_msg.audio_ip = audio_ip_overflow;
|
||||
msg = mgcp_msg_gen(mgcp, &mgcp_msg);
|
||||
OSMO_ASSERT(msg == NULL);
|
||||
|
||||
printf("IPv6 test:\n");
|
||||
mgcp_msg.verb = MGCP_VERB_MDCX;
|
||||
mgcp_msg.presence =
|
||||
(MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
|
||||
MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
|
||||
MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
|
||||
mgcp_msg.audio_ip = "2001:db8:1::ab9:c0a8:102";
|
||||
mgcp->actual.remote_addr = "::1";
|
||||
msg = mgcp_msg_gen(mgcp, &mgcp_msg);
|
||||
printf("%s\n", (char *)msg->data);
|
||||
|
||||
printf("\n");
|
||||
msgb_free(msg);
|
||||
}
|
||||
@@ -413,6 +425,66 @@ static struct sdp_section_start_test sdp_section_start_tests[] = {
|
||||
"m=audio 23\r\n",
|
||||
.expect_rc = 0,
|
||||
},
|
||||
{
|
||||
.body = "some mgcp header data\r\nand header params"
|
||||
"\r\n\r\n"
|
||||
"c=IN IP4 1.2.3.4\r\n",
|
||||
.expect_params = {
|
||||
.audio_ip = "1.2.3.4",
|
||||
},
|
||||
.expect_rc = 0,
|
||||
},
|
||||
{
|
||||
.body = "some mgcp header data\r\nand header params"
|
||||
"\r\n\r\n"
|
||||
"c=IN IP6 2001:db8:1::ab9:c0a8:102\r\n",
|
||||
.expect_params = {
|
||||
.audio_ip = "2001:db8:1::ab9:c0a8:102",
|
||||
},
|
||||
.expect_rc = 0,
|
||||
},
|
||||
{
|
||||
.body = "some mgcp header data\r\nand header params"
|
||||
"\r\n\r\n"
|
||||
"c=IN IP6 1.2.3.4\r\n",
|
||||
.expect_rc = -22,
|
||||
},
|
||||
{
|
||||
.body = "some mgcp header data\r\nand header params"
|
||||
"\r\n\r\n"
|
||||
"c=IN IP4 ::1\r\n",
|
||||
.expect_rc = -22,
|
||||
},
|
||||
{
|
||||
.body = "some mgcp header data\r\nand header params"
|
||||
"\r\n\r\n"
|
||||
"c=IN IP4 notanip\r\n",
|
||||
.expect_rc = -22,
|
||||
},
|
||||
{
|
||||
.body = "some mgcp header data\r\nand header params"
|
||||
"\r\n\r\n"
|
||||
"c=IN IP4 1.2.3.4.5.6\r\n",
|
||||
.expect_rc = -22,
|
||||
},
|
||||
{
|
||||
.body = "some mgcp header data\r\nand header params"
|
||||
"\r\n\r\n"
|
||||
"c=IN IP4 1.2 .3\r\n",
|
||||
.expect_rc = -22,
|
||||
},
|
||||
{
|
||||
.body = "some mgcp header data\r\nand header params"
|
||||
"\r\n\r\n"
|
||||
"c=IN IP4 1.2 .3\r\n",
|
||||
.expect_rc = -22,
|
||||
},
|
||||
{
|
||||
.body = "some mgcp header data\r\nand header params"
|
||||
"\r\n\r\n"
|
||||
"c=IN IP4 \r\n",
|
||||
.expect_rc = -22,
|
||||
},
|
||||
};
|
||||
|
||||
void test_sdp_section_start()
|
||||
@@ -443,7 +515,12 @@ void test_sdp_section_start()
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stderr, "got audio_port=%u\n", t->expect_params.audio_port);
|
||||
fprintf(stderr, "got audio_ip=\"%s\"\n", r->audio_ip);
|
||||
if (strcmp(r->audio_ip, t->expect_params.audio_ip)) {
|
||||
fprintf(stderr, "FAIL: Expected audio_ip=\"%s\"\n", t->expect_params.audio_ip);
|
||||
failures++;
|
||||
}
|
||||
fprintf(stderr, "got audio_port=%u\n", r->audio_port);
|
||||
if (r->audio_port != t->expect_params.audio_port) {
|
||||
fprintf(stderr, "FAIL: Expected audio_port=%u\n", t->expect_params.audio_port);
|
||||
failures++;
|
||||
|
@@ -19,55 +19,112 @@ test_sdp_section_start() test [0]:
|
||||
body: ""
|
||||
DLMGCP MGCP response contains no SDP parameters
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=0
|
||||
|
||||
test_sdp_section_start() test [1]:
|
||||
body: "\n\n"
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=0
|
||||
|
||||
test_sdp_section_start() test [2]:
|
||||
body: "\r\n\r\n"
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=0
|
||||
|
||||
test_sdp_section_start() test [3]:
|
||||
body: "\n\r\n\r"
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=0
|
||||
|
||||
test_sdp_section_start() test [4]:
|
||||
body: "some mgcp header data\r\nand header params\n\nm=audio 23\r\n"
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=23
|
||||
|
||||
test_sdp_section_start() test [5]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nm=audio 23\r\n"
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=23
|
||||
|
||||
test_sdp_section_start() test [6]:
|
||||
body: "some mgcp header data\r\nand header params\n\r\n\rm=audio 23\r\n"
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=23
|
||||
|
||||
test_sdp_section_start() test [7]:
|
||||
body: "some mgcp header data\r\nand header params\n\r\nm=audio 23\r\n"
|
||||
DLMGCP MGCP response contains no SDP parameters
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=0
|
||||
|
||||
test_sdp_section_start() test [8]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\rm=audio 23\r\n"
|
||||
DLMGCP MGCP response contains no SDP parameters
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=0
|
||||
|
||||
test_sdp_section_start() test [9]:
|
||||
body: "some mgcp header data\r\nand header params\n\r\rm=audio 23\r\n"
|
||||
DLMGCP MGCP response contains no SDP parameters
|
||||
got rc=0
|
||||
got audio_ip=""
|
||||
got audio_port=0
|
||||
|
||||
test_sdp_section_start() test [10]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 1.2.3.4\r\n"
|
||||
got rc=0
|
||||
got audio_ip="1.2.3.4"
|
||||
got audio_port=0
|
||||
|
||||
test_sdp_section_start() test [11]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP6 2001:db8:1::ab9:c0a8:102\r\n"
|
||||
got rc=0
|
||||
got audio_ip="2001:db8:1::ab9:c0a8:102"
|
||||
got audio_port=0
|
||||
|
||||
test_sdp_section_start() test [12]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP6 1.2.3.4\r\n"
|
||||
DLMGCP Failed to parse MGCP response header (audio ip)
|
||||
got rc=-22
|
||||
|
||||
test_sdp_section_start() test [13]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 ::1\r\n"
|
||||
DLMGCP Failed to parse MGCP response header (audio ip)
|
||||
got rc=-22
|
||||
|
||||
test_sdp_section_start() test [14]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 notanip\r\n"
|
||||
DLMGCP Failed to parse MGCP response header (audio ip)
|
||||
got rc=-22
|
||||
|
||||
test_sdp_section_start() test [15]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 1.2.3.4.5.6\r\n"
|
||||
DLMGCP Failed to parse MGCP response header (audio ip)
|
||||
got rc=-22
|
||||
|
||||
test_sdp_section_start() test [16]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 1.2 .3\r\n"
|
||||
DLMGCP Failed to parse MGCP response header (audio ip)
|
||||
got rc=-22
|
||||
|
||||
test_sdp_section_start() test [17]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 1.2 .3\r\n"
|
||||
DLMGCP Failed to parse MGCP response header (audio ip)
|
||||
got rc=-22
|
||||
|
||||
test_sdp_section_start() test [18]:
|
||||
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 \r\n"
|
||||
DLMGCP Failed to parse MGCP response header (audio ip)
|
||||
got rc=-22
|
||||
DLMGCP ptmap contains illegal mapping: codec=113 maps to pt=2
|
||||
DLMGCP ptmap contains illegal mapping: codec=0 maps to pt=100
|
||||
DLMGCP ptmap contains illegal mapping: codec=113 maps to pt=2
|
||||
|
@@ -109,6 +109,20 @@ M: sendrecv
|
||||
X-Osmux: 2
|
||||
|
||||
Overfolow test:
|
||||
IPv6 test:
|
||||
MDCX 19 23@mgw MGCP 1.0
|
||||
C: 2f
|
||||
I: 11
|
||||
M: sendrecv
|
||||
|
||||
v=0
|
||||
o=- 2f 23 IN IP6 ::1
|
||||
s=-
|
||||
c=IN IP6 2001:db8:1::ab9:c0a8:102
|
||||
t=0 0
|
||||
m=audio 1234 RTP/AVP 3
|
||||
a=ptime:20
|
||||
|
||||
|
||||
|
||||
test_mgcp_client_cancel():
|
||||
@@ -149,6 +163,24 @@ test_sdp_section_start() test [7]:
|
||||
test_sdp_section_start() test [8]:
|
||||
|
||||
test_sdp_section_start() test [9]:
|
||||
|
||||
test_sdp_section_start() test [10]:
|
||||
|
||||
test_sdp_section_start() test [11]:
|
||||
|
||||
test_sdp_section_start() test [12]:
|
||||
|
||||
test_sdp_section_start() test [13]:
|
||||
|
||||
test_sdp_section_start() test [14]:
|
||||
|
||||
test_sdp_section_start() test [15]:
|
||||
|
||||
test_sdp_section_start() test [16]:
|
||||
|
||||
test_sdp_section_start() test [17]:
|
||||
|
||||
test_sdp_section_start() test [18]:
|
||||
110 => 96
|
||||
111 => 97
|
||||
112 => 98
|
||||
|
Reference in New Issue
Block a user