Compare commits

...

48 Commits

Author SHA1 Message Date
Alexander Couzens
eb57b9b3a1 add mgcp rtp log
Change-Id: I42bbd803e7b0a2f1c4c4ad75561e5d3f8f80fa97
2018-01-03 00:37:38 +01:00
Harald Welte
e35eeae8e0 Return proper MGCP Error codes, as per spec
Change-Id: I55db8351422ff951516fefa6a29e87086b7ab74b
Closes: OS#2657, OS#2656
2017-12-28 14:00:42 +01:00
Harald Welte
abbb6b9088 centralize handling of common errors like "endpoint not found"
Previously we
* did not distinguish between the cause of errors in mgcp_header_parse
* common errors were not handled in mgcp_handle_message() but in
  individual per-verb functions

Let's centralize the handling of generating error responses and remove
that burden from the individual per-verb handler functions.

Change-Id: I463b27306e10ae3b021583ed102977e7299e5e66
2017-12-28 14:00:37 +01:00
Harald Welte
3f35a3708a mgcp_internal.h: document more struct members with comments
Change-Id: Idfba05de37d354f9485030f37dfc9c780eff7b35
2017-12-28 03:17:10 +01:00
Harald Welte
33eafe050b mgcp_msg: We must parse endpoint numbers as hex, not decimal!
The MGCP client uses hex numbers, while the server side parses it
as decimal. This results in the first 10 calls succeeding, but from
0x0a onwards it of course fails :/

Change-Id: I006f5f5325f0a5069d02fec8912a38d943cfc552
Closes: OS#2784
2017-12-28 03:17:10 +01:00
Harald Welte
1d1b98f4a4 libosmo-mgcp: Cosmetic spelling fixes in comments
Change-Id: Ic0469c2a4d69b55a6a90653ad7ea1ad89a34e4bc
2017-12-25 10:10:29 +01:00
Harald Welte
a0ac30faa5 mgcp_rtp_end: Group statistics members into 'stats' sub-struct
Change-Id: I4e0ecdcd9a75fe08abc55b730780c01617f3d4af
2017-12-25 10:10:29 +01:00
Harald Welte
49e3d5a9c9 mgcp_rtp_state: grup 'stats' members into sub-structure
Change-Id: I92a1bead01c6b85bf237b6edf64a1b76b9e97c78
2017-12-25 10:10:29 +01:00
Harald Welte
3338135ead strct mgcp_rtp_state: Group + document struct members related to patching
Change-Id: I403ddcafe0a11290103bb017568cfacaf5c04412
2017-12-25 10:10:29 +01:00
Philipp Maier
5dbfc78aff network: use originating RTP packet address for loopback
When a connection is created in loopback mode all incoming
packets should be reflected back to their origin. If the
user did not supply a destination address with the CRCX
command all incoming packets will be tossed because no
destination address is officially known yet.

If there is no destination address set and the connection
is in loopback mode. Then use the originating address of
the incoming packet as destination address.

Change-Id: I3d1abe56d016e28c97f60635eb574679d36e2c52
2017-12-12 16:27:14 +01:00
Philipp Maier
7bc5552512 mcgp_client: mgcp_msg_gen(): add checks to verify params
mgcp_msg_gen() does not check the contents of the prameters that
are handed over with the struct. This may lead to invalid mgcp
messages sent to the MGW, which can be difficult to debug.

Add some additional checks to make a possible problem
noticeable in an early stage.

- verify that the endpoint is not a nullstring
- verify that the connection id is not a nullstring
- verify that the ip-address is not a nullstring
- verify that the port number is a value greater 0

Change-Id: I15c464c4bcdf6e524f68acc62f44186dd7ad19a7
2017-12-10 23:22:14 +01:00
Philipp Maier
a330b864e5 mgcp_test: fix possible double free
Change-Id: I2d044382c0bb66e190400e3397449c3f2387359a
2017-12-04 17:34:11 +01:00
Philipp Maier
7df419b434 mgcp_test: add returncode check
The returncode of get_conn_id_from_response() is unchecked, which
is intentional since some of the test messages will intentionally cause
this function to fail (the response does not inclde a connection
identifier). This means it makes no sense to assert this function
to a fixed value.

In order to spot regressions better print a log message depending
on the return code.

Change-Id: I9bce9ca39b7751b557374b7ab57c6c9005bcdb7d
Fixes: Coverity CID#180534
2017-12-04 17:34:11 +01:00
Philipp Maier
7cedfd753b mgcp_test: fix nullpointer dereference
Change-Id: Ic2ee79eaaca2fada673baf6ff4c226aa16c26269
Fixes: Coverity CID#180536
2017-12-04 17:33:59 +01:00
Philipp Maier
23b8e29835 mgcp_test: fix wrong strcmp() parameters
The CRCX string parameter lacks the quotes and the result of
the function call is not checked against zero. Also the
return code of get_conn_id_from_response() is not asserted.

Fixes: Coverity CID#180534

Change-Id: If4f3ed2c3572da196160569a9705b7a302b700a9
2017-12-04 16:51:40 +01:00
Philipp Maier
1c3287f1db conn: remove assertions
the assertions in the code that handles the connection
lists introduce a lot of unnecessary bloat.

Change-Id: I7badc729e97b76701abbce6a73a1ad1e46d3fee0
2017-12-04 16:04:10 +01:00
Philipp Maier
922ae9a5bf client: use string as connection identifier
The test that tests the cancelation of a pending mgcp message
uses an integer as connection identifier, which leads to a
segfault since connection identifiers are represented as strings.

Use a string as connection identifier.

Change-Id: I395a23c1828cf216031d69d481ad35dd458ee7d4
2017-12-04 16:04:10 +01:00
Neels Hofmeyr
189d6bf4d4 mgcp_client_test makefile: add update_exp target
Change-Id: I8cda082c46ab5734873cbb39b313037d86777589
2017-12-03 22:47:38 +00:00
Neels Hofmeyr
c8f37cb4d6 mgcp_client: add transaction cleanup
So far, if an MGCP message is sent, the transaction gets enqueued, but there is
no way to end the transaction other than receiving a valid reply. So, if the
caller decides that the transaction timed out and tears down the priv pointer
passed to mgcp_client_tx, and if then a late reply arrives, the callback will
dereference the invalid priv pointer and cause a segfault. Hence it is possible
to crash an mgcp_client program by sending a late response.

Furthermore, if no reply ever arrives, we would keep the pending response in
the list forever, amounting to a "memory leak".

Add mgcp_client_cancel() to discard a pending transaction. The caller can now
decide to discard a pending response when it sees fit (e.g. the caller's
timeout expired). This needs to be added to OsmoMSC and OsmoBSC.

Add mgcp_msg_trans_id() to provide an obvious way to obtain the transaction id
from a generated MGCP message.

No public API is broken; but refine the negative return code from
mgcp_client_rx(): return -ENOENT if no such transaction ID is found, and still
-1 if decoding failed. This is mainly for mgcp_client_test.

Implement a test for mgcp_client_cancel() in mgcp_client_test.c.

Tweak internal mgcp_client_response_pending_get() to take only the transaction
id as argument instead of the entire mgcp message struct.

Found-by: dexter
Related: OS#2695 OS#2696
Change-Id: I16811e168a46a82a05943252a737b3434143f4bd
2017-12-03 22:47:01 +00:00
Neels Hofmeyr
c0dcc3c60c Revert "mgcp_client: don't configure "bts base"" until osmo-msc is ready
OsmoMSC is in the odd situation that it is already using the new 
libosmo-mgcp-client, which is targeted at osmo-mgw, to configure talking to the
old osmo-bsc_mgcp. By removing the bts_base, we break current OsmoMSC.

Removing bts_base makes sense, but let's revert this until OsmoMSC is ready
after merging Ieea9630358b3963261fa1993cf1f3b563ff23538 (which moves the 
osmo-msc over to osmo-mgw).

This reverts commit 0be3ce66c0.

Change-Id: Ibce214c2bfc35623097abbb647619426ef3dcc94
2017-12-02 18:37:18 +00:00
Philipp Maier
230e4fc270 cosmetic: clearly mark endpoint numbers as hex
The log prints the endpoint numbers as hexadecimal numbers, but
it does not prefix them with "0x".

Add "0x" prefixes to all endpoint number outputs in the log

Change-Id: I284627de02cd140a894445375e9152ff007a71e6
2017-12-01 11:58:24 +00:00
Philipp Maier
ead2f60f73 cosmetic: fix sourcecode formatting
Change-Id: I1a4eda30986e07237bb7b496704f36f03d25a149
2017-12-01 11:58:24 +00:00
Philipp Maier
f8bfbe8b14 client: use osmo_strlcpy instead of strncpy
simplify \nul termination of the ip_addr string

Change-Id: I94e3815f45d08e0d40faf41e580547de937c4ce8
2017-12-01 11:58:24 +00:00
Philipp Maier
ffd75e420c libosmo-mgcp: Connection Identifiers are allocated by MGW, not CA
The MGCP connection identifier is allocated by the MGW while processing
the CRCX, see RFC3435 2.1.3.2:. Including/Accepting a connection
identifier in CRCX is "forbidden" as per RFC3435 Section 3.2.2.

So the MGW side must *reject* a CRCX message with 'I' parameter, and
allocate a connection identifier which is subsequently returned in the
response.

Closes: OS#2648
Change-Id: Iab6a6038e7610c62f34e642cd49c93d11151252c
2017-12-01 11:58:24 +00:00
Philipp Maier
01d24a3281 MGCP: Connection Identifiers are hex strings
The MGCP spec in RFC3435 is quite clear: Connection Identifiers are
hexadecimal strings of up to 32 characters. We should not print and
parse them as integers on either client or server.

Change the internal uint32_t representation of connection identifiers
to a string representation in the client and also in the server.

Closes: OS#2649
Change-Id: I0531a1b670d00cec50078423a2868207135b2436
2017-12-01 11:58:23 +00:00
Neels Hofmeyr
0be3ce66c0 mgcp_client: don't configure "bts base"
There should not be any BTS base port to be configured at an MGCP client.

Possibly this is related to the legacy behavior of libosmo-legacy-mgcp, and
certainly has no place in libosmo-mgcp-client.

Further changes may be needed to follow up on removal of the BTS base port
concept, at least drop it from the VTY for now.

Change-Id: I36e46208d7b75611e5ade3c74d8e1c25870de511
2017-11-30 12:18:57 +01:00
Philipp Maier
fcd0655176 vty: do not change number_endpoints at runtime
The variable number_endpoints is used as a length indicator
for the array that contains the trunk endpoints at all times.
When osmo-mgw is startet up, the variable is set and osmo-mgw
will allocate the memory for the endpoints. However, it is
still possible to manipulate the variable via the telnet
interface. When the value is increased osmo-mgw might start
using unallocated memory at some point.

Store subsequent changes of number_enspoints in a separate
variable in order to write them to the config file. The
changes will then take effect after a restart.

Closes: OS#2632
Change-Id: I3994af016fb96427263edbba05f560743f85fdd4
2017-11-27 14:38:29 +00:00
Philipp Maier
48454983c4 vty: simplify endpoint allocation
mgcp_parse_config() uses a helper function allocate_trunk() to
perform the trunk allocation. This helper function only calls
mgcp_endpoints_allocate() and checks the return code.

Call mgcp_endpoints_allocate() directly from mgcp_parse_config()

Change-Id: Iefdc5b905d76d2cd97f26584261fe5cbefb699cf
2017-11-27 11:01:43 +01:00
Philipp Maier
9a3543a8d4 cosmetic: use correct VTY port number constant
osmo-mgw currently uses VTY port number constant of osmo-bsc_mgwp,
however, libosmore now offers a constant specifically for osmo_mgw,
which has the same value, but is intended to be used by osmo-mgw

use the new port number constant for osmo-mgw

Closes: OS#2628
Change-Id: I63c3b300cc9287d1755a3f2c5b5ade7fc6398f6e
Depends: libosmocore I1770787e697906322ce5815fcaadba06c01ddee9
2017-11-24 12:40:51 +01:00
Neels Hofmeyr
465446b4b4 mgcp_test: sanitize: free msgb_ctx
Ensure that all msgb were cleaned up, then free the overall msgb_ctx, in order
to not leave any memory leaks the sanitizer build complains about.

Change-Id: I53373023a6c3f490d6d6cb1c283db5dfb915882c
2017-11-22 02:59:03 +01:00
Neels Hofmeyr
b597b4fc9d mgcp_test: test_no_cycle: sanitize: free endp
Release endpoint to avoid sanitizer errors.

Change-Id: I78d16ffc435c0f967fe99c6e38dde829b6fa0dc9
2017-11-22 02:58:27 +01:00
Neels Hofmeyr
d20910c655 mgcp_test: test_packet_error_detection: sanitize: free all conns
Don't leave any memory leaks a sanitizer build will complain about.

Change-Id: I6823653d5efcebaed40471123d21a9321cf633fd
2017-11-18 21:27:55 +01:00
Neels Hofmeyr
677f4ad968 legacy_mgcp: mgcp_test: sanitize: free msgb_ctx
Ensure that all msgb were cleaned up, then free the overall msgb_ctx, in order
to not leave any memory leaks the sanitizer build complains about.

Change-Id: I84e0ac7f0928f04ffddd7da18200466841589c25
2017-11-18 21:26:27 +01:00
Neels Hofmeyr
7c20c9de5a add --enable-sanitize config option
Change-Id: I2693238c5c8d914cf3ff7721511e7b4b56e413d2
2017-11-18 10:17:39 +00:00
Harald Welte
839fc954d0 osmo-mgw: Fix copyright notice
The copyright statement and contribution notices were copied 1:1
from OpenBSC, which is of course not correct for OsmoMGW.

Change-Id: I6143becdd0da589451efcbda530a78f655b7ce0b
2017-11-17 20:58:22 +01:00
Harald Welte
d164b05655 osmo-mgw: Config file is osmo-mgw.cfg, and not mgcp.cfg
Change-Id: I16016684ee5bd6d82a8867d4b2be108b6d718291
2017-11-17 15:41:24 +01:00
Harald Welte
a896f9cdeb osmo-mgw: Update copyright statement
sysmocom (specifically Philipp) was doing all the new osmo-mgw
development, but that is not yet reflected in the Copyright statement
for some reason.  Let's fix it.

Change-Id: I4cad29daaabec1caec1bd09088414e59fa15a17e
2017-11-17 15:08:41 +01:00
Harald Welte
1b0cf6fa1c Fix possible buffer overflow in mgcp_conn_dump()
mgcp_conn.c: In function ‘mgcp_conn_dump’:
mgcp_conn.c:248:30: warning: ‘/rtp, id:’ directive output may be truncated writing 9 bytes into a region of size between 0 and 255 [-Wformat-truncation=]
   snprintf(str, sizeof(str), "(%s/rtp, id:%u, ip:%s, "
                              ^~~~~~~~~~~~~~~~~~~~~~~~~
mgcp_conn.c:248:30: note: directive argument in the range [0, 65535]
mgcp_conn.c:248:30: note: directive argument in the range [0, 65535]
mgcp_conn.c:248:3: note: ‘snprintf’ output 32 or more bytes (assuming 295) into a destination of size 256
   snprintf(str, sizeof(str), "(%s/rtp, id:%u, ip:%s, "

as mgcp_conn->name can already be up to 256 bytes, a total buffer size
of 256 is insufficient!

Change-Id: I5d48132b1358d19fe72e3901117737b09a42c69c
2017-11-17 14:28:46 +01:00
Harald Welte
9bf7c53779 cosmetic: fix whitespaces; we use tabs for indentation
Change-Id: I547f650bcda369ea399c5171a3541a96862d978b
2017-11-17 14:18:24 +01:00
Alexander Couzens
6be0fdb5e4 debian: include systemd service osmo-mgw.service
Change-Id: Ic298b836620b3497734aed89b92c4f22a9071f0d
2017-11-16 15:54:55 +00:00
Alexander Couzens
641c4d47b9 debian/control: correct library dependency of osmo-mgw against libosmo-mgcp1
When the library version was bump, the dependency of osmo-mgw
was forgotten.

Change-Id: I3eeafa3c294d9ec71a72fb2833fe3b2bdef05a50
Fixes: e7d27aeae1 ("Tag/Release Version 1.2.0")
2017-11-16 15:54:54 +00:00
Neels Hofmeyr
c1b9fa158e MGCP endpoints: parse as decimal, not hex
Parse the endpoint index from the MGCP messages as base-10, not 16.

If osmo-mgw parses the endpoint IDs as base-16 numbers while OsmoMSC and
OsmoBSC pass in decimal endpoint numbers, the consequence is, for example:

- I configure 32 endpoints in osmo-mgw,
- I tell OsmoBSC to use endpoint range 1-32,
- At some point OsmoBSC may pass in, say, "30@mgw",
- "30" is parsed base-16 and ends up being endpoint index 48, instead of 32,
- OsmoMGW sees that 48 > number_endpoints and barfs.

Related: OS#2633
Change-Id: Ic18608ff23303c1564548a86d5f6bfa539fe555e
2017-11-15 23:02:05 +00:00
Philipp Maier
6a421f1b6f doc: update sample config file
The current example configuration is out of date.

Add a recent configuration file

Change-Id: Iad2034ce4c68bb8b70cb72d3978d2a0f685bbe19
2017-11-12 14:22:23 +00:00
Philipp Maier
f1889d8640 cosmetic: remove prefix "net" from rtp related vty commands
There the prefix "net" is a leftover from the time when
there was a bts and a net side. Now we do not distinguish
anymore between the two.

remove prefix "net"

Change-Id: Id627e2ef6f725979ed52a585ca09686e1a049adf
2017-11-12 14:22:22 +00:00
Philipp Maier
2982e42d93 cosmetic: guard dead osmux vty code with ifdef
Since currently osmux is not available we decided to lock down the
respective VTY command with an early return CMD_WARNING, making
the code after this line unreachable.

Guard the dead code with an ifdef

Fixes: Coverity CID#178648
Change-Id: I2ad9579453f52fe129cf120801a2efa19a26304e
2017-11-10 21:32:35 +00:00
Philipp Maier
ddf1f9d7d5 osmux: fix nullpointer dereference
in point_lookup() the connection pointer is determined using
mgcp_conn_get_rtp() this function may return 0. At the moment
there are no nullpointer checks implemented

Add checks to test for nullpointer.

Fixes: Coverity CID#178662
Change-Id: If9a3c1ac002bc8adc90ca1c1c3dd1db4feea07ac
2017-11-10 21:30:19 +00:00
Neels Hofmeyr
653c4ff354 fix segfault: DLCX for unknown endpoint: dont try to log NULL endpoint
Change-Id: Ib127fd81a2d68f51c470ff77ef0822bdb4829de4
2017-11-10 16:23:36 +01:00
Pau Espin Pedrol
4efce88a62 contrib: Add osmo-mgw systemd service
Change-Id: Ic89815dc4ef8dff8a9d8541b61212ab8d4837712
2017-11-10 10:31:39 +00:00
32 changed files with 1662 additions and 632 deletions

View File

@@ -23,4 +23,7 @@
# If any interfaces have been added since the last public release, a++;
# If any interfaces have been removed or changed since the last public release, a=0.
#
#library what description / commit summary line
#library what description / commit summary line
libosmo-mgcp API/ABI change parse and represent connection identifiers as hex strings
libosmo-mgcp API/ABI change connection identifiers are assigned by the server, not CA
libosmo-mgcp-client API/ABI change parse and store connection identifier in response

View File

@@ -40,9 +40,22 @@ AC_SUBST(LIBRARY_DL)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.10.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.10.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.10.0)
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.1.0)
AC_ARG_ENABLE(sanitize,
[AS_HELP_STRING(
[--enable-sanitize],
[Compile with address sanitizer enabled],
)],
[sanitize=$enableval], [sanitize="no"])
if test x"$sanitize" = x"yes"
then
CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
fi
# Enable/disable transcoding within osmo-bsc_mgcp?
AC_ARG_ENABLE([mgcp-transcoding], [AS_HELP_STRING([--enable-mgcp-transcoding], [Build the MGCP gateway with internal transcoding enabled.])],
[osmo_ac_mgcp_transcoding="$enableval"],[osmo_ac_mgcp_transcoding="no"])

View File

@@ -0,0 +1,11 @@
[Unit]
Description=Osmocom Media Gateway (MGW)
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/osmo-mgw -s -c /etc/osmocom/osmo-mgw.cfg
RestartSec=2
[Install]
WantedBy=multi-user.target

2
debian/control vendored
View File

@@ -16,7 +16,7 @@ Homepage: https://osmocom.org/projects/osmo-mgw
Package: osmo-mgw
Architecture: any
Multi-Arch: foreign
Depends: libosmo-mgcp0, ${misc:Depends}, ${shlibs:Depends}
Depends: libosmo-mgcp1, ${misc:Depends}, ${shlibs:Depends}
Description: OsmoMGW: Osmocom's Media Gateway for 2G and 3G circuit-switched mobile networks
Package: libosmo-mgcp1

1
debian/osmo-mgw.service vendored Symbolic link
View File

@@ -0,0 +1 @@
../contrib/systemd/osmo-mgw.service

View File

@@ -2,12 +2,17 @@
! MGCP configuration example
!
mgcp
!local ip 10.23.24.2
!bts ip 10.24.24.1
!bind ip 10.23.24.1
bind port 2427
rtp force-ptime 20
sdp audio payload number 98
sdp audio payload name AMR/8000
number endpoints 31
no rtcp-omit
bind ip 127.0.0.1
rtp port-range 4002 16000
rtp bind-ip 10.9.1.122
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

View File

@@ -105,12 +105,12 @@ struct mgcp_port_range {
};
/* There are up to three modes in which the keep-alive dummy packet can be
* sent. The beviour is controlled viw the keepalive_interval member of the
* sent. The behaviour is controlled via the keepalive_interval member of the
* trunk config. If that member is set to 0 (MGCP_KEEPALIVE_NEVER) no dummy-
* packet is sent at all and the timer that sends regular dummy packets
* is no longer scheduled. If the keepalive_interval is set to -1, only
* one dummy packet is sent when an CRCX or an MDCX is performed. No timer
* is scheduled. For all vales greater 0, the a timer is scheduled and the
* is scheduled. For all vales greater 0, the timer is scheduled and the
* value is used as interval. See also mgcp_keepalive_timer_cb(),
* handle_modify_con(), and handle_create_con() */
#define MGCP_KEEPALIVE_ONCE (-1)
@@ -151,6 +151,7 @@ struct mgcp_trunk_config {
int rtp_accept_all;
unsigned int number_endpoints;
int vty_number_endpoints;
struct mgcp_endpoint *endpoints;
};

View File

@@ -68,4 +68,8 @@ static inline int mgcp_msg_terminate_nul(struct msgb *msg)
return 0;
}
/* String length of Connection Identifiers
* (see also RFC3435 2.1.3.2 Names of Connections) */
#define MGCP_CONN_ID_LENGTH 32+1
#endif

View File

@@ -28,12 +28,11 @@
#include <inttypes.h>
struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
uint32_t id, enum mgcp_conn_type type,
char *name);
struct mgcp_conn *mgcp_conn_get(struct mgcp_endpoint *endp, uint32_t id);
enum mgcp_conn_type type, char *name);
struct mgcp_conn *mgcp_conn_get(struct mgcp_endpoint *endp, const char *id);
struct mgcp_conn_rtp *mgcp_conn_get_rtp(struct mgcp_endpoint *endp,
uint32_t id);
void mgcp_conn_free(struct mgcp_endpoint *endp, uint32_t id);
const char *id);
void mgcp_conn_free(struct mgcp_endpoint *endp, const char *id);
void mgcp_conn_free_oldest(struct mgcp_endpoint *endp);
void mgcp_conn_free_all(struct mgcp_endpoint *endp);
char *mgcp_conn_dump(struct mgcp_conn *conn);

View File

@@ -30,8 +30,10 @@
#define CI_UNUSED 0
#define CONN_ID_BTS 0
#define CONN_ID_NET 1
/* FIXME: This this is only needed to compile the currently
* broken OSMUX support. Remove when fixed */
#define CONN_ID_BTS "0"
#define CONN_ID_NET "1"
enum mgcp_trunk_type {
MGCP_TRUNK_VIRTUAL,
@@ -48,27 +50,37 @@ struct mgcp_rtp_stream_state {
};
struct mgcp_rtp_state {
/* has this state structure been initialized? */
int initialized;
int patch_ssrc;
uint32_t orig_ssrc;
struct {
/* are we patching the SSRC value? */
int patch_ssrc;
/* original SSRC (to which we shall patch any different SSRC) */
uint32_t orig_ssrc;
/* offset to apply on the sequence number */
int seq_offset;
/* offset to apply on the timestamp number */
int32_t timestamp_offset;
} patch;
int seq_offset;
int32_t timestamp_offset;
/* duration of a packet (FIXME: in which unit?) */
uint32_t packet_duration;
struct mgcp_rtp_stream_state in_stream;
struct mgcp_rtp_stream_state out_stream;
/* jitter and packet loss calculation */
int stats_initialized;
uint16_t stats_base_seq;
uint16_t stats_max_seq;
uint32_t stats_ssrc;
uint32_t stats_jitter;
int32_t stats_transit;
int stats_cycles;
struct {
int initialized;
uint16_t base_seq;
uint16_t max_seq;
uint32_t ssrc;
uint32_t jitter;
int32_t transit;
int cycles;
} stats;
bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
};
@@ -83,13 +95,18 @@ struct mgcp_rtp_codec {
char *subtype_name;
};
/* 'mgcp_rtp_end': basically a wrapper around the RTP+RTCP ports */
struct mgcp_rtp_end {
/* statistics */
unsigned int packets_rx;
unsigned int octets_rx;
unsigned int packets_tx;
unsigned int octets_tx;
unsigned int dropped_packets;
struct {
unsigned int packets_rx;
unsigned int octets_rx;
unsigned int packets_tx;
unsigned int octets_tx;
unsigned int dropped_packets;
} stats;
/* local IP address of the RTP socket */
struct in_addr addr;
/* in network byte order */
@@ -103,23 +120,30 @@ struct mgcp_rtp_end {
int frames_per_packet;
uint32_t packet_duration_ms;
char *fmtp_extra;
/* are we transmitting packets (1) or dropping (0) outbound packets */
int output_enabled;
/* FIXME: This parameter can be set + printed, but is nowhere used! */
int force_output_ptime;
/* RTP patching */
int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
/* should we perform align_rtp_timestamp_offset() (1) or not (0) */
int force_aligned_timing;
/* FIXME: not used anymore, used to be [external] transcoding related */
void *rtp_process_data;
/* Each end has a separate socket for RTP and RTCP */
struct osmo_fd rtp;
struct osmo_fd rtcp;
/* local UDP port number of the RTP socket; RTCP is +1 */
int local_port;
};
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;
};
@@ -155,7 +179,7 @@ struct mgcp_conn_rtp {
/* Sequence bits */
struct mgcp_rtp_state state;
/* taps for the rtp connection */
/* taps for the rtp connection; one per direction */
struct mgcp_rtp_tap tap_in;
struct mgcp_rtp_tap tap_out;
@@ -202,8 +226,8 @@ struct mgcp_conn {
/*!< copy of the mode to restore the original setting (VTY) */
enum mgcp_connection_mode mode_orig;
/*!< connection id to identify the conntion */
uint32_t id;
/*!< connection id to identify the connection */
char id[MGCP_CONN_ID_LENGTH];
/*!< human readable name (vty, logging) */
char name[256];
@@ -249,7 +273,6 @@ struct mgcp_parse_data {
struct mgcp_endpoint *endp;
char *trans;
char *save;
int found;
};
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,

View File

@@ -43,7 +43,7 @@ int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line);
int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid);
int mgcp_verify_ci(struct mgcp_endpoint *endp, const char *ci);
int mgcp_verify_ci(struct mgcp_endpoint *endp, const char *conn_id);
char *mgcp_strline(char *str, char **saveptr);
@@ -54,5 +54,3 @@ char *mgcp_strline(char *str, char **saveptr);
#define for_each_non_empty_line(line, save)\
for (line = strtok_r(NULL, "\r\n", &save); line;\
line = strtok_r(NULL, "\r\n", &save))
int mgcp_parse_ci(uint32_t *conn_id, const char *ci);

View File

@@ -27,9 +27,10 @@ struct mgcp_client_conf {
typedef unsigned int mgcp_trans_id_t;
struct mgcp_response_head {
int response_code;
mgcp_trans_id_t trans_id;
const char *comment;
int response_code;
mgcp_trans_id_t trans_id;
const char *comment;
char conn_id[MGCP_CONN_ID_LENGTH];
};
struct mgcp_response {
@@ -63,9 +64,9 @@ struct mgcp_msg {
uint32_t presence;
char endpoint[MGCP_ENDPOINT_MAXLEN];
unsigned int call_id;
uint32_t conn_id;
uint16_t audio_port;
char *audio_ip;
char *conn_id;
uint16_t audio_port;
char *audio_ip;
enum mgcp_connection_mode conn_mode;
};
@@ -92,6 +93,7 @@ int mgcp_response_parse_params(struct mgcp_response *r);
int mgcp_client_tx(struct mgcp_client *mgcp, struct msgb *msg,
mgcp_response_cb_t response_cb, void *priv);
int mgcp_client_cancel(struct mgcp_client *mgcp, mgcp_trans_id_t trans_id);
enum mgcp_connection_mode;
@@ -110,6 +112,7 @@ struct msgb *mgcp_msg_dlcx(struct mgcp_client *mgcp, uint16_t rtp_endpoint,
OSMO_DEPRECATED("Use mgcp_msg_gen() instead");
struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg);
mgcp_trans_id_t mgcp_msg_trans_id(struct msgb *msg);
extern const struct value_string mgcp_client_connection_mode_strs[];
static inline const char *mgcp_client_cmode_name(enum mgcp_connection_mode mode)

View File

@@ -372,8 +372,8 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
display_mgcp_message(msg->l2h, msgb_l2len(msg), "Received message");
/* attempt to treat it as a response */
if (sscanf((const char *)&msg->l2h[0], "%3d %*s", &code) == 1) {
/* attempt to treat it as a response */
if (sscanf((const char *)&msg->l2h[0], "%3d %*s", &code) == 1) {
LOGP(DLMGCP, LOGL_DEBUG, "Response: Code: %d\n", code);
return NULL;
}

View File

@@ -133,7 +133,7 @@ static int mgcp_response_parse_head(struct mgcp_response *r, struct msgb *msg)
r->body = (char *)msg->data;
if (sscanf(r->body, "%3d %u %n",
if (sscanf(r->body, "%3d %u %n",
&r->head.response_code, &r->head.trans_id,
&comment_pos) != 2)
goto response_parse_failure;
@@ -176,7 +176,7 @@ static bool mgcp_line_is_valid(const char *line)
/* Parse a line like "m=audio 16002 RTP/AVP 98" */
static int mgcp_parse_audio_port(struct mgcp_response *r, const char *line)
{
if (sscanf(line, "m=audio %hu",
if (sscanf(line, "m=audio %hu",
&r->audio_port) != 1)
goto response_parse_failure;
@@ -201,8 +201,7 @@ static int mgcp_parse_audio_ip(struct mgcp_response *r, const char *line)
goto response_parse_failure;
/* Extract IP-Address */
strncpy(r->audio_ip, line + 9, sizeof(r->audio_ip));
r->audio_ip[sizeof(r->audio_ip) - 1] = '\0';
osmo_strlcpy(r->audio_ip, line + 9, sizeof(r->audio_ip));
/* Check IP-Address */
if (inet_aton(r->audio_ip, &ip_test) == 0)
@@ -258,15 +257,65 @@ int mgcp_response_parse_params(struct mgcp_response *r)
return 0;
}
/* Parse a line like "I: 0cedfd5a19542d197af9afe5231f1d61" */
static int mgcp_parse_conn_id(struct mgcp_response *r, const char *line)
{
if (strlen(line) < 4)
goto response_parse_failure;
if (memcmp("I: ", line, 3) != 0)
goto response_parse_failure;
osmo_strlcpy(r->head.conn_id, line + 3, sizeof(r->head.conn_id));
return 0;
response_parse_failure:
LOGP(DLMGCP, LOGL_ERROR,
"Failed to parse MGCP response (connectionIdentifier)\n");
return -EINVAL;
}
/* Parse MGCP parameters of the response */
static int parse_head_params(struct mgcp_response *r)
{
char *line;
int rc = 0;
OSMO_ASSERT(r->body);
char *data = r->body;
char *data_end = strstr(r->body, "\n\n");
/* Protect SDP body, for_each_non_empty_line() will
* only parse until it hits \0 mark. */
if (data_end)
*data_end = '\0';
for_each_non_empty_line(line, data) {
switch (line[0]) {
case 'I':
rc = mgcp_parse_conn_id(r, line);
if (rc)
goto exit;
break;
default:
/* skip unhandled parameters */
break;
}
}
exit:
/* Restore original state */
if (data_end)
*data_end = '\n';
return rc;
}
static struct mgcp_response_pending *mgcp_client_response_pending_get(
struct mgcp_client *mgcp,
struct mgcp_response *r)
mgcp_trans_id_t trans_id)
{
struct mgcp_response_pending *pending;
if (!r)
return NULL;
llist_for_each_entry(pending, &mgcp->responses_pending, entry) {
if (pending->trans_id == r->head.trans_id) {
if (pending->trans_id == trans_id) {
llist_del(&pending->entry);
return pending;
}
@@ -288,16 +337,22 @@ int mgcp_client_rx(struct mgcp_client *mgcp, struct msgb *msg)
rc = mgcp_response_parse_head(&r, msg);
if (rc) {
LOGP(DLMGCP, LOGL_ERROR, "Cannot parse MGCP response\n");
LOGP(DLMGCP, LOGL_ERROR, "Cannot parse MGCP response (head)\n");
return -1;
}
pending = mgcp_client_response_pending_get(mgcp, &r);
rc = parse_head_params(&r);
if (rc) {
LOGP(DLMGCP, LOGL_ERROR, "Cannot parse MGCP response (head parameters)\n");
return -1;
}
pending = mgcp_client_response_pending_get(mgcp, r.head.trans_id);
if (!pending) {
LOGP(DLMGCP, LOGL_ERROR,
"Cannot find matching MGCP transaction for trans_id %d\n",
r.head.trans_id);
return -1;
return -ENOENT;
}
mgcp_client_handle_response(mgcp, pending, &r);
@@ -325,7 +380,7 @@ static int mgcp_do_read(struct osmo_fd *fd)
LOGP(DLMGCP, LOGL_ERROR, "Too much data: %d\n", ret);
msgb_free(msg);
return -1;
}
}
msg->l2h = msgb_put(msg, ret);
ret = mgcp_client_rx(mgcp, msg);
@@ -340,7 +395,7 @@ static int mgcp_do_write(struct osmo_fd *fd, struct msgb *msg)
unsigned int l = msg->len < sizeof(strbuf) ? msg->len : sizeof(strbuf);
unsigned int i;
strncpy(strbuf, (const char*)msg->data, l);
osmo_strlcpy(strbuf, (const char*)msg->data, l);
for (i = 0; i < sizeof(strbuf); i++) {
if (strbuf[i] == '\n' || strbuf[i] == '\r') {
strbuf[i] = '\0';
@@ -503,7 +558,10 @@ struct mgcp_response_pending * mgcp_client_pending_add(
* response_cb. NOTE: the response_cb still needs to call
* mgcp_response_parse_params(response) to get the parsed parameters -- to
* potentially save some CPU cycles, only the head line has been parsed when
* the response_cb is invoked. */
* the response_cb is invoked.
* Before the priv pointer becomes invalid, e.g. due to transaction timeout,
* mgcp_client_cancel() needs to be called for this transaction.
*/
int mgcp_client_tx(struct mgcp_client *mgcp, struct msgb *msg,
mgcp_response_cb_t response_cb, void *priv)
{
@@ -546,6 +604,32 @@ mgcp_tx_error:
return -1;
}
/* Cancel a pending transaction.
* Should a priv pointer passed to mgcp_client_tx() become invalid, this function must be called. In
* practical terms, if the caller of mgcp_client_tx() wishes to tear down a transaction without having
* received a response this function must be called. The trans_id can be obtained by calling
* mgcp_msg_trans_id() on the msgb produced by mgcp_msg_gen().
*/
int mgcp_client_cancel(struct mgcp_client *mgcp, mgcp_trans_id_t trans_id)
{
struct mgcp_response_pending *pending = mgcp_client_response_pending_get(mgcp, trans_id);
if (!pending) {
/* INFO is sufficient, it is not harmful to cancel a transaction twice. */
LOGP(DLMGCP, LOGL_INFO, "Cannot cancel, no such transaction: %u\n", trans_id);
return -ENOENT;
}
LOGP(DLMGCP, LOGL_INFO, "Canceled transaction %u\n", trans_id);
talloc_free(pending);
return 0;
/* We don't really need to clean up the wqueue: In all sane cases, the msgb has already been sent
* out and is no longer in the wqueue. If it still is in the wqueue, then sending MGCP messages
* per se is broken and the program should notice so by a full wqueue. Even if this was called
* before we had a chance to send out the message and it is still going to be sent, we will just
* ignore the reply to it later. Removing a msgb from the wqueue here would just introduce more
* bug surface in terms of failing to update wqueue API's counters or some such.
*/
}
static struct msgb *mgcp_msg_from_buf(mgcp_trans_id_t trans_id,
const char *buf, int len)
{
@@ -650,7 +734,6 @@ struct msgb *mgcp_msg_dlcx(struct mgcp_client *mgcp, uint16_t rtp_endpoint,
#define MGCP_CRCX_MANDATORY (MGCP_MSG_PRESENCE_ENDPOINT | \
MGCP_MSG_PRESENCE_CALL_ID | \
MGCP_MSG_PRESENCE_CONN_ID | \
MGCP_MSG_PRESENCE_CONN_MODE)
#define MGCP_MDCX_MANDATORY (MGCP_MSG_PRESENCE_ENDPOINT | \
MGCP_MSG_PRESENCE_CONN_ID)
@@ -706,8 +789,15 @@ struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg)
}
/* Add endpoint name */
if (mgcp_msg->presence & MGCP_MSG_PRESENCE_ENDPOINT)
if (mgcp_msg->presence & MGCP_MSG_PRESENCE_ENDPOINT) {
if (strlen(mgcp_msg->endpoint) <= 0) {
LOGP(DLMGCP, LOGL_ERROR,
"Empty endpoint name, can not generate MGCP message\n");
msgb_free(msg);
return NULL;
}
rc += msgb_printf(msg, " %s", mgcp_msg->endpoint);
}
/* Add protocol version */
rc += msgb_printf(msg, " MGCP 1.0\r\n");
@@ -717,12 +807,18 @@ struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg)
rc += msgb_printf(msg, "C: %x\r\n", mgcp_msg->call_id);
/* Add connection id */
if (mgcp_msg->presence & MGCP_MSG_PRESENCE_CONN_ID)
rc += msgb_printf(msg, "I: %u\r\n", mgcp_msg->conn_id);
if (mgcp_msg->presence & MGCP_MSG_PRESENCE_CONN_ID) {
if (strlen(mgcp_msg->conn_id) <= 0) {
LOGP(DLMGCP, LOGL_ERROR,
"Empty connection id, can not generate MGCP message\n");
msgb_free(msg);
return NULL;
}
rc += msgb_printf(msg, "I: %s\r\n", mgcp_msg->conn_id);
}
/* Add local connection options */
if (mgcp_msg->presence & MGCP_MSG_PRESENCE_CONN_ID
&& mgcp_msg->verb == MGCP_VERB_CRCX)
if (mgcp_msg->verb == MGCP_VERB_CRCX)
rc += msgb_printf(msg, "L: p:20, a:AMR, nt:IN\r\n");
/* Add mode */
@@ -734,6 +830,18 @@ struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg)
/* Add RTP address and port (SDP) */
if (mgcp_msg->presence & MGCP_MSG_PRESENCE_AUDIO_IP
&& mgcp_msg->presence & MGCP_MSG_PRESENCE_AUDIO_PORT) {
if (mgcp_msg->audio_port == 0) {
LOGP(DLMGCP, LOGL_ERROR,
"Invalid port number, can not generate MGCP message\n");
msgb_free(msg);
return NULL;
}
if (strlen(mgcp_msg->audio_ip) <= 0) {
LOGP(DLMGCP, LOGL_ERROR,
"Empty ip address, can not generate MGCP message\n");
msgb_free(msg);
return NULL;
}
rc += msgb_printf(msg, "\r\n");
rc += msgb_printf(msg, "c=IN IP4 %s\r\n", mgcp_msg->audio_ip);
rc +=
@@ -751,6 +859,12 @@ struct msgb *mgcp_msg_gen(struct mgcp_client *mgcp, struct mgcp_msg *mgcp_msg)
return msg;
}
/* Retrieve the MGCP transaction ID from a msgb generated by mgcp_msg_gen() */
mgcp_trans_id_t mgcp_msg_trans_id(struct msgb *msg)
{
return (mgcp_trans_id_t)msg->cb[MSGB_CB_MGCP_TRANS_ID];
}
struct mgcp_client_conf *mgcp_client_conf_actual(struct mgcp_client *mgcp)
{
return &mgcp->actual;

View File

@@ -7,6 +7,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
-Wall \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \
$(LIBOSMOVTY_CFLAGS) \
$(LIBOSMONETIF_CFLAGS) \
$(COVERAGE_CFLAGS) \
@@ -14,6 +15,7 @@ AM_CFLAGS = \
AM_LDFLAGS = \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \
$(LIBOSMOVTY_LIBS) \
$(LIBOSMONETIF_LIBS) \
$(COVERAGE_LDFLAGS) \

View File

@@ -25,6 +25,47 @@
#include <osmocom/mgcp/mgcp_internal.h>
#include <osmocom/mgcp/mgcp_common.h>
#include <osmocom/mgcp/mgcp_ep.h>
#include <osmocom/gsm/gsm_utils.h>
#include <ctype.h>
/* Allocate a new connection identifier. According to RFC3435, they must
* be unique only within the scope of the endpoint. (Caller must provide
* memory for id) */
static int mgcp_alloc_id(struct mgcp_endpoint *endp, char *id)
{
int i;
int k;
int rc;
uint8_t id_bin[16];
char *id_hex;
/* Generate a connection id that is unique for the current endpoint.
* Technically a counter would be sufficient, but in order to
* be able to find a specific connection in large logfiles and to
* prevent unintentional connections we assign the connection
* identifiers randomly from a reasonable large number space */
for (i = 0; i < 32; i++) {
rc = osmo_get_rand_id(id_bin, sizeof(id_bin));
if (rc < 0)
return rc;
id_hex = osmo_hexdump_nospc(id_bin, sizeof(id_bin));
for (k = 0; k < strlen(id_hex); k++)
id_hex[k] = toupper(id_hex[k]);
/* ensure that the generated conn_id is unique
* for this endpoint */
if (!mgcp_conn_get_rtp(endp, id_hex)) {
osmo_strlcpy(id, id_hex, MGCP_CONN_ID_LENGTH);
return 0;
}
}
LOGP(DLMGCP, LOGL_ERROR, "endpoint:0x%x, unable to generate a unique connectionIdentifier\n",
ENDPOINT_NUMBER(endp));
return -1;
}
/* Reset codec state and free memory */
static void mgcp_rtp_codec_reset(struct mgcp_rtp_codec *codec)
@@ -52,12 +93,7 @@ static void mgcp_rtp_conn_reset(struct mgcp_conn_rtp *conn)
end->rtp.fd = -1;
end->rtcp.fd = -1;
end->local_port = 0;
end->packets_rx = 0;
end->octets_rx = 0;
end->packets_tx = 0;
end->octets_tx = 0;
end->dropped_packets = 0;
memset(&end->stats, 0, sizeof(end->stats));
end->rtp_port = end->rtcp_port = 0;
talloc_free(end->fmtp_extra);
end->fmtp_extra = NULL;
@@ -78,22 +114,15 @@ static void mgcp_rtp_conn_reset(struct mgcp_conn_rtp *conn)
* \param[in] type connection type (e.g. MGCP_CONN_TYPE_RTP)
* \returns pointer to allocated connection, NULL on error */
struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
uint32_t id, enum mgcp_conn_type type,
char *name)
enum mgcp_conn_type type, char *name)
{
struct mgcp_conn *conn;
OSMO_ASSERT(endp);
OSMO_ASSERT(endp->conns.next != NULL && endp->conns.prev != NULL);
OSMO_ASSERT(strlen(name) < sizeof(conn->name));
int rc;
/* Do not allow more then two connections */
if (llist_count(&endp->conns) >= endp->type->max_conns)
return NULL;
/* Prevent duplicate connection IDs */
if (mgcp_conn_get(endp, id))
return NULL;
/* Create new connection and add it to the list */
conn = talloc_zero(ctx, struct mgcp_conn);
if (!conn)
@@ -102,9 +131,13 @@ struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
conn->type = type;
conn->mode = MGCP_CONN_NONE;
conn->mode_orig = MGCP_CONN_NONE;
conn->id = id;
conn->u.rtp.conn = conn;
strcpy(conn->name, name);
osmo_strlcpy(conn->name, name, sizeof(conn->name));
rc = mgcp_alloc_id(endp, conn->id);
if (rc < 0) {
talloc_free(conn);
return NULL;
}
switch (type) {
case MGCP_CONN_TYPE_RTP:
@@ -126,15 +159,12 @@ struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
* \param[in] endp associated endpoint
* \param[in] id identification number of the connection
* \returns pointer to allocated connection, NULL if not found */
struct mgcp_conn *mgcp_conn_get(struct mgcp_endpoint *endp, uint32_t id)
struct mgcp_conn *mgcp_conn_get(struct mgcp_endpoint *endp, const char *id)
{
OSMO_ASSERT(endp);
OSMO_ASSERT(endp->conns.next != NULL && endp->conns.prev != NULL);
struct mgcp_conn *conn;
llist_for_each_entry(conn, &endp->conns, entry) {
if (conn->id == id)
if (strncmp(conn->id, id, sizeof(conn->id)) == 0)
return conn;
}
@@ -145,11 +175,9 @@ struct mgcp_conn *mgcp_conn_get(struct mgcp_endpoint *endp, uint32_t id)
* \param[in] endp associated endpoint
* \param[in] id identification number of the connection
* \returns pointer to allocated connection, NULL if not found */
struct mgcp_conn_rtp *mgcp_conn_get_rtp(struct mgcp_endpoint *endp, uint32_t id)
struct mgcp_conn_rtp *mgcp_conn_get_rtp(struct mgcp_endpoint *endp,
const char *id)
{
OSMO_ASSERT(endp);
OSMO_ASSERT(endp->conns.next != NULL && endp->conns.prev != NULL);
struct mgcp_conn *conn;
conn = mgcp_conn_get(endp, id);
@@ -165,11 +193,8 @@ struct mgcp_conn_rtp *mgcp_conn_get_rtp(struct mgcp_endpoint *endp, uint32_t id)
/*! free a connection by its ID.
* \param[in] endp associated endpoint
* \param[in] id identification number of the connection */
void mgcp_conn_free(struct mgcp_endpoint *endp, uint32_t id)
void mgcp_conn_free(struct mgcp_endpoint *endp, const char *id)
{
OSMO_ASSERT(endp);
OSMO_ASSERT(endp->conns.next != NULL && endp->conns.prev != NULL);
struct mgcp_conn *conn;
conn = mgcp_conn_get(endp, id);
@@ -197,9 +222,6 @@ void mgcp_conn_free(struct mgcp_endpoint *endp, uint32_t id)
* \param[in] endp associated endpoint */
void mgcp_conn_free_oldest(struct mgcp_endpoint *endp)
{
OSMO_ASSERT(endp);
OSMO_ASSERT(endp->conns.next != NULL && endp->conns.prev != NULL);
struct mgcp_conn *conn;
if (llist_empty(&endp->conns))
@@ -216,9 +238,6 @@ void mgcp_conn_free_oldest(struct mgcp_endpoint *endp)
* \param[in] endp associated endpoint */
void mgcp_conn_free_all(struct mgcp_endpoint *endp)
{
OSMO_ASSERT(endp);
OSMO_ASSERT(endp->conns.next != NULL && endp->conns.prev != NULL);
struct mgcp_conn *conn;
struct mgcp_conn *conn_tmp;
@@ -230,12 +249,12 @@ void mgcp_conn_free_all(struct mgcp_endpoint *endp)
return;
}
/*! dump basic connection information to human readble string.
/*! dump basic connection information to human readable string.
* \param[in] conn to dump
* \returns human readble string */
* \returns human readable string */
char *mgcp_conn_dump(struct mgcp_conn *conn)
{
static char str[256];
static char str[sizeof(conn->name)+sizeof(conn->id)+256];
if (!conn) {
snprintf(str, sizeof(str), "(null connection)");
@@ -245,7 +264,7 @@ char *mgcp_conn_dump(struct mgcp_conn *conn)
switch (conn->type) {
case MGCP_CONN_TYPE_RTP:
/* Dump RTP connection */
snprintf(str, sizeof(str), "(%s/rtp, id:%u, ip:%s, "
snprintf(str, sizeof(str), "(%s/rtp, id:0x%s, ip:%s, "
"rtp:%u rtcp:%u)",
conn->name,
conn->id,

View File

@@ -82,7 +82,7 @@ int mgcp_parse_conn_mode(const char *mode, struct mgcp_endpoint *endp,
if (!mode) {
LOGP(DLMGCP, LOGL_ERROR,
"endpoint:%x missing connection mode\n",
"endpoint:0x%x missing connection mode\n",
ENDPOINT_NUMBER(endp));
return -1;
}
@@ -101,7 +101,7 @@ int mgcp_parse_conn_mode(const char *mode, struct mgcp_endpoint *endp,
conn->mode = MGCP_CONN_LOOPBACK;
else {
LOGP(DLMGCP, LOGL_ERROR,
"endpoint:%x unknown connection mode: '%s'\n",
"endpoint:0x%x unknown connection mode: '%s'\n",
ENDPOINT_NUMBER(endp), mode);
ret = -1;
}
@@ -113,16 +113,16 @@ int mgcp_parse_conn_mode(const char *mode, struct mgcp_endpoint *endp,
}
LOGP(DLMGCP, LOGL_DEBUG,
"endpoint:%x conn:%s\n",
"endpoint:0x%x conn:%s\n",
ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn));
LOGP(DLMGCP, LOGL_DEBUG,
"endpoint:%x connection mode '%s' %d\n",
"endpoint:0x%x connection mode '%s' %d\n",
ENDPOINT_NUMBER(endp), mode, conn->mode);
/* Special handling für RTP connections */
if (conn->type == MGCP_CONN_TYPE_RTP) {
LOGP(DLMGCP, LOGL_DEBUG, "endpoint:%x output_enabled %d\n",
LOGP(DLMGCP, LOGL_DEBUG, "endpoint:0x%x output_enabled %d\n",
ENDPOINT_NUMBER(endp), conn->u.rtp.end.output_enabled);
}
@@ -230,21 +230,21 @@ int mgcp_parse_header(struct mgcp_parse_data *pdata, char *data)
if (!pdata->endp) {
LOGP(DLMGCP, LOGL_ERROR,
"Unable to find Endpoint `%s'\n", elem);
return -1;
return -500;
}
break;
case 2:
if (strcmp("MGCP", elem)) {
LOGP(DLMGCP, LOGL_ERROR,
"MGCP header parsing error\n");
return -1;
return -510;
}
break;
case 3:
if (strcmp("1.0", elem)) {
LOGP(DLMGCP, LOGL_ERROR, "MGCP version `%s' "
"not supported\n", elem);
return -1;
return -528;
}
break;
}
@@ -255,7 +255,7 @@ int mgcp_parse_header(struct mgcp_parse_data *pdata, char *data)
LOGP(DLMGCP, LOGL_ERROR, "MGCP status line too short.\n");
pdata->trans = "000000";
pdata->endp = NULL;
return -1;
return -510;
}
return 0;
@@ -318,7 +318,7 @@ int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid)
if (strcmp(endp->callid, callid) != 0) {
LOGP(DLMGCP, LOGL_ERROR,
"endpoint:%x CallIDs does not match '%s' != '%s'\n",
"endpoint:0x%x CallIDs does not match '%s' != '%s'\n",
ENDPOINT_NUMBER(endp), endp->callid, callid);
return -1;
}
@@ -330,21 +330,39 @@ int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid)
* \param[in] endp pointer to endpoint
* \param{in] connection id to verify
* \returns 1 when connection id seems plausible, 0 on error */
int mgcp_verify_ci(struct mgcp_endpoint *endp, const char *ci)
int mgcp_verify_ci(struct mgcp_endpoint *endp, const char *conn_id)
{
uint32_t id;
if (!endp)
/* Check for null identifiers */
if (!conn_id) {
LOGP(DLMGCP, LOGL_ERROR,
"endpoint:0x%x invalid ConnectionIdentifier (missing)\n",
ENDPOINT_NUMBER(endp));
return -1;
}
id = strtoul(ci, NULL, 10);
/* Check for empty connection identifiers */
if (strlen(conn_id) == 0) {
LOGP(DLMGCP, LOGL_ERROR,
"endpoint:0x%x invalid ConnectionIdentifier (empty)\n",
ENDPOINT_NUMBER(endp));
return -1;
}
if (mgcp_conn_get(endp, id))
/* Check for over long connection identifiers */
if (strlen(conn_id) > MGCP_CONN_ID_LENGTH) {
LOGP(DLMGCP, LOGL_ERROR,
"endpoint:0x%x invalid ConnectionIdentifier (too long) 0x%s\n",
ENDPOINT_NUMBER(endp), conn_id);
return -1;
}
/* Check if connection exists */
if (mgcp_conn_get(endp, conn_id))
return 0;
LOGP(DLMGCP, LOGL_ERROR,
"endpoint:%x No connection found under ConnectionIdentifier %u\n",
ENDPOINT_NUMBER(endp), id);
"endpoint:0x%x no connection found under ConnectionIdentifier 0x%s\n",
ENDPOINT_NUMBER(endp), conn_id);
return -1;
}
@@ -386,20 +404,3 @@ char *mgcp_strline(char *str, char **saveptr)
return result;
}
/*! Parse CI from a given string.
* \param[out] caller provided memory to store the result
* \param{in] string containing the connection id
* \returns 0 on success, -1 on error */
int mgcp_parse_ci(uint32_t *conn_id, const char *ci)
{
OSMO_ASSERT(conn_id);
if (!ci)
return -1;
*conn_id = strtoul(ci, NULL, 10);
return 0;
}

View File

@@ -73,11 +73,11 @@ void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn)
rc = osmo_sock_local_ip(addr, inet_ntoa(conn->end.addr));
if (rc < 0)
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x CI:%i local interface auto detection failed, using configured addresses...\n",
"endpoint:0x%x CI:%s local interface auto detection failed, using configured addresses...\n",
ENDPOINT_NUMBER(endp), conn->conn->id);
else {
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x CI:%i selected local rtp bind ip %s by probing using remote ip %s\n",
"endpoint:0x%x CI:%s selected local rtp bind ip %s by probing using remote ip %s\n",
ENDPOINT_NUMBER(endp), conn->conn->id, addr,
inet_ntoa(conn->end.addr));
return;
@@ -88,17 +88,17 @@ void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn)
if (endp->cfg->net_ports.bind_addr) {
/* Check there is a bind IP for the RTP traffic configured,
* if so, use that IP-Address */
strncpy(addr, endp->cfg->net_ports.bind_addr, INET_ADDRSTRLEN);
osmo_strlcpy(addr, endp->cfg->net_ports.bind_addr, INET_ADDRSTRLEN);
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x CI:%i using configured rtp bind ip as local bind ip %s\n",
"endpoint:0x%x CI:%s using configured rtp bind ip as local bind ip %s\n",
ENDPOINT_NUMBER(endp), conn->conn->id, 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 */
strncpy(addr, endp->cfg->source_addr, INET_ADDRSTRLEN);
osmo_strlcpy(addr, endp->cfg->source_addr, INET_ADDRSTRLEN);
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x CI:%i using mgcp bind ip as local rtp bind ip: %s\n",
"endpoint:0x%x CI:%s using mgcp bind ip as local rtp bind ip: %s\n",
ENDPOINT_NUMBER(endp), conn->conn->id, addr);
}
}
@@ -162,8 +162,8 @@ int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
OSMO_ASSERT(conn);
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x sending dummy packet...\n", ENDPOINT_NUMBER(endp));
LOGP(DRTP, LOGL_DEBUG, "endpoint:%x conn:%s\n",
"endpoint:0x%x sending dummy packet...\n", ENDPOINT_NUMBER(endp));
LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x conn:%s\n",
ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn->conn));
rc = mgcp_udp_send(conn->end.rtp.fd, &conn->end.addr,
@@ -184,8 +184,9 @@ int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
failed:
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x Failed to send dummy %s packet.\n",
ENDPOINT_NUMBER(endp), was_rtcp ? "RTCP" : "RTP");
"endpoint:0x%x Failed to send dummy %s packet. 0x%x %d.\n",
ENDPOINT_NUMBER(endp), was_rtcp ? "RTCP" : "RTP", conn->end.addr, conn->end.rtcp_port);
LOGP(DRTP, LOGL_ERROR, "endpoint: 0x%x : dump %s", ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn->conn));
return -1;
}
@@ -231,7 +232,7 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
"on 0x%x SSRC: %u timestamp: %u "
"from %s:%d\n",
text, seq,
state->timestamp_offset, state->seq_offset,
state->patch.timestamp_offset, state->patch.seq_offset,
ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
}
@@ -325,15 +326,15 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
out_timestamp = state->out_stream.last_timestamp + delta_seq * tsdelta;
timestamp_offset = out_timestamp - in_timestamp;
if (state->timestamp_offset != timestamp_offset) {
state->timestamp_offset = timestamp_offset;
if (state->patch.timestamp_offset != timestamp_offset) {
state->patch.timestamp_offset = timestamp_offset;
LOGP(DRTP, LOGL_NOTICE,
"Timestamp offset change on 0x%x SSRC: %u "
"SeqNo delta: %d, TS offset: %d, "
"from %s:%d\n",
ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
delta_seq, state->timestamp_offset,
delta_seq, state->patch.timestamp_offset,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
}
@@ -354,11 +355,11 @@ static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
/* Align according to: T + Toffs - Tlast = k * Tptime */
ts_error = ts_alignment_error(&state->out_stream, ptime,
timestamp + state->timestamp_offset);
timestamp + state->patch.timestamp_offset);
/* If there is an alignment error, we have to compensate it */
if (ts_error) {
state->timestamp_offset += ptime - ts_error;
state->patch.timestamp_offset += ptime - ts_error;
LOGP(DRTP, LOGL_NOTICE,
"Corrected timestamp alignment error of %d on 0x%x SSRC: %u "
@@ -366,16 +367,16 @@ static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
"from %s:%d\n",
ts_error,
ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
state->timestamp_offset, inet_ntoa(addr->sin_addr),
state->patch.timestamp_offset, inet_ntoa(addr->sin_addr),
ntohs(addr->sin_port));
}
/* Check we really managed to compensate the timestamp
* offset. There should not be any remaining error, failing
* here would point to a serous problem with the alingnment
* error computation fuction */
* here would point to a serous problem with the alignment
* error computation function */
ts_check = ts_alignment_error(&state->out_stream, ptime,
timestamp + state->timestamp_offset);
timestamp + state->patch.timestamp_offset);
OSMO_ASSERT(ts_check == 0);
/* Return alignment error before compensation */
@@ -387,13 +388,13 @@ static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
* \param[in] destination RTP end
* \param[in,out] pointer to buffer with voice data
* \param[in] voice data length
* \param[in] maxmimum size of caller provided voice data buffer
* \param[in] maximum size of caller provided voice data buffer
* \returns ignores input parameters, return always 0 */
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp,
struct mgcp_rtp_end *dst_end,
char *data, int *len, int buf_size)
{
LOGP(DRTP, LOGL_DEBUG, "endpoint:%x transcoding disabled\n",
LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x transcoding disabled\n",
ENDPOINT_NUMBER(endp));
return 0;
}
@@ -407,7 +408,7 @@ int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
struct mgcp_rtp_end *dst_end,
struct mgcp_rtp_end *src_end)
{
LOGP(DRTP, LOGL_DEBUG, "endpoint:%x transcoding disabled\n",
LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x transcoding disabled\n",
ENDPOINT_NUMBER(endp));
return 0;
}
@@ -419,7 +420,7 @@ void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
struct mgcp_conn_rtp *conn)
{
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x conn:%s using format defaults\n",
"endpoint:0x%x conn:%s using format defaults\n",
ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn->conn));
*payload_type = conn->end.codec.payload_type;
@@ -434,14 +435,14 @@ void mgcp_rtp_annex_count(struct mgcp_endpoint *endp,
int32_t d;
/* initialize or re-initialize */
if (!state->stats_initialized || state->stats_ssrc != ssrc) {
state->stats_initialized = 1;
state->stats_base_seq = seq;
state->stats_max_seq = seq - 1;
state->stats_ssrc = ssrc;
state->stats_jitter = 0;
state->stats_transit = transit;
state->stats_cycles = 0;
if (!state->stats.initialized || state->stats.ssrc != ssrc) {
state->stats.initialized = 1;
state->stats.base_seq = seq;
state->stats.max_seq = seq - 1;
state->stats.ssrc = ssrc;
state->stats.jitter = 0;
state->stats.transit = transit;
state->stats.cycles = 0;
} else {
uint16_t udelta;
@@ -452,10 +453,10 @@ void mgcp_rtp_annex_count(struct mgcp_endpoint *endp,
* It can't wrap during the initialization so let's
* skip it here. The Appendix A probably doesn't have
* this issue because of the probation. */
udelta = seq - state->stats_max_seq;
udelta = seq - state->stats.max_seq;
if (udelta < RTP_MAX_DROPOUT) {
if (seq < state->stats_max_seq)
state->stats_cycles += RTP_SEQ_MOD;
if (seq < state->stats.max_seq)
state->stats.cycles += RTP_SEQ_MOD;
} else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) {
LOGP(DRTP, LOGL_NOTICE,
"RTP seqno made a very large jump on 0x%x delta: %u\n",
@@ -467,12 +468,12 @@ void mgcp_rtp_annex_count(struct mgcp_endpoint *endp,
* taken closer to the read function. This was taken from the
* Appendix A of RFC 3550. Timestamp and arrival_time have a 1/rate
* resolution. */
d = transit - state->stats_transit;
state->stats_transit = transit;
d = transit - state->stats.transit;
state->stats.transit = transit;
if (d < 0)
d = -d;
state->stats_jitter += d - ((state->stats_jitter + 8) >> 4);
state->stats_max_seq = seq;
state->stats.jitter += d - ((state->stats.jitter + 8) >> 4);
state->stats.max_seq = seq;
}
/* The RFC 3550 Appendix A assumes there are multiple sources but
@@ -508,7 +509,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
if (!state->initialized) {
state->initialized = 1;
state->in_stream.last_seq = seq - 1;
state->in_stream.ssrc = state->orig_ssrc = ssrc;
state->in_stream.ssrc = state->patch.orig_ssrc = ssrc;
state->in_stream.last_tsdelta = 0;
state->packet_duration =
mgcp_rtp_packet_duration(endp, rtp_end);
@@ -516,23 +517,23 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
state->out_stream.last_timestamp = timestamp;
state->out_stream.ssrc = ssrc - 1; /* force output SSRC change */
LOGP(DRTP, LOGL_INFO,
"endpoint:%x initializing stream, SSRC: %u timestamp: %u "
"endpoint:0x%x initializing stream, SSRC: %u timestamp: %u "
"pkt-duration: %d, from %s:%d\n",
ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
state->seq_offset, state->packet_duration,
state->patch.seq_offset, state->packet_duration,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
if (state->packet_duration == 0) {
state->packet_duration =
rtp_end->codec.rate * 20 / 1000;
LOGP(DRTP, LOGL_NOTICE,
"endpoint:%x fixed packet duration is not available, "
"endpoint:0x%x fixed packet duration is not available, "
"using fixed 20ms instead: %d from %s:%d\n",
ENDPOINT_NUMBER(endp), state->packet_duration,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
}
} else if (state->in_stream.ssrc != ssrc) {
LOGP(DRTP, LOGL_NOTICE,
"endpoint:%x SSRC changed: %u -> %u "
"endpoint:0x%x SSRC changed: %u -> %u "
"from %s:%d\n",
ENDPOINT_NUMBER(endp),
state->in_stream.ssrc, rtp_hdr->ssrc,
@@ -543,7 +544,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
int16_t delta_seq;
/* Always increment seqno by 1 */
state->seq_offset =
state->patch.seq_offset =
(state->out_stream.last_seq + 1) - seq;
/* Estimate number of packets that would have been sent */
@@ -555,17 +556,17 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
adjust_rtp_timestamp_offset(endp, state, rtp_end, addr,
delta_seq, timestamp);
state->patch_ssrc = 1;
ssrc = state->orig_ssrc;
state->patch.patch_ssrc = 1;
ssrc = state->patch.orig_ssrc;
if (rtp_end->force_constant_ssrc != -1)
rtp_end->force_constant_ssrc -= 1;
LOGP(DRTP, LOGL_NOTICE,
"endpoint:%x SSRC patching enabled, SSRC: %u "
"endpoint:0x%x SSRC patching enabled, SSRC: %u "
"SeqNo offset: %d, TS offset: %d "
"from %s:%d\n",
ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
state->seq_offset, state->timestamp_offset,
state->patch.seq_offset, state->patch.timestamp_offset,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
}
@@ -576,8 +577,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
addr, seq, timestamp, "input",
&state->in_stream.last_tsdelta);
if (state->patch_ssrc)
ssrc = state->orig_ssrc;
if (state->patch.patch_ssrc)
ssrc = state->patch.orig_ssrc;
}
/* Save before patching */
@@ -592,15 +593,15 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
timestamp);
/* Store the updated SSRC back to the packet */
if (state->patch_ssrc)
if (state->patch.patch_ssrc)
rtp_hdr->ssrc = htonl(ssrc);
/* Apply the offset and store it back to the packet.
* This won't change anything if the offset is 0, so the conditional is
* omitted. */
seq += state->seq_offset;
seq += state->patch.seq_offset;
rtp_hdr->sequence = htons(seq);
timestamp += state->timestamp_offset;
timestamp += state->patch.timestamp_offset;
rtp_hdr->timestamp = htonl(timestamp);
/* Check again, whether the timestamps are still valid */
@@ -619,7 +620,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
#if 0
DEBUGP(DRTP,
"endpoint:%x payload hdr payload %u -> endp payload %u\n",
"endpoint:0x%x payload hdr payload %u -> endp payload %u\n",
ENDPOINT_NUMBER(endp), rtp_hdr->payload_type, payload);
rtp_hdr->payload_type = payload;
#endif
@@ -670,16 +671,16 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
if (is_rtp) {
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x delivering RTP packet...\n",
"endpoint:0x%x delivering RTP packet...\n",
ENDPOINT_NUMBER(endp));
} else {
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x delivering RTCP packet...\n",
"endpoint:0x%x delivering RTCP packet...\n",
ENDPOINT_NUMBER(endp));
}
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x loop:%d, mode:%d ",
"endpoint:0x%x loop:%d, mode:%d ",
ENDPOINT_NUMBER(endp), tcfg->audio_loop, conn_src->conn->mode);
if (conn_src->conn->mode == MGCP_CONN_LOOPBACK)
LOGPC(DRTP, LOGL_DEBUG, "(loopback)\n");
@@ -693,9 +694,9 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
dest_name = conn_dst->conn->name;
if (!rtp_end->output_enabled) {
rtp_end->dropped_packets += 1;
rtp_end->stats.dropped_packets += 1;
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x output disabled, drop to %s %s "
"endpoint:0x%x output disabled, drop to %s %s "
"rtp_port:%u rtcp_port:%u\n",
ENDPOINT_NUMBER(endp),
dest_name,
@@ -718,7 +719,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
mgcp_patch_and_count(endp, rtp_state, rtp_end,
addr, buf, buflen);
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x process/send to %s %s "
"endpoint:0x%x process/send to %s %s "
"rtp_port:%u rtcp_port:%u\n",
ENDPOINT_NUMBER(endp), dest_name,
inet_ntoa(rtp_end->addr), ntohs(rtp_end->rtp_port),
@@ -748,8 +749,8 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
if (len <= 0)
return len;
conn_dst->end.packets_tx += 1;
conn_dst->end.octets_tx += len;
conn_dst->end.stats.packets_tx += 1;
conn_dst->end.stats.octets_tx += len;
nbytes += len;
buflen = cont;
@@ -757,7 +758,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
return nbytes;
} else if (!tcfg->omit_rtcp) {
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x send to %s %s rtp_port:%u rtcp_port:%u\n",
"endpoint:0x%x send to %s %s rtp_port:%u rtcp_port:%u\n",
ENDPOINT_NUMBER(endp),
dest_name,
inet_ntoa(rtp_end->addr),
@@ -768,8 +769,8 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
&rtp_end->addr,
rtp_end->rtcp_port, buf, len);
conn_dst->end.packets_tx += 1;
conn_dst->end.octets_tx += len;
conn_dst->end.stats.packets_tx += 1;
conn_dst->end.stats.octets_tx += len;
return len;
}
@@ -804,13 +805,13 @@ static int receive_from(struct mgcp_endpoint *endp, int fd,
if (rc < 0) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x failed to receive packet, errno: %d/%s\n",
"endpoint:0x%x failed to receive packet, errno: %d/%s\n",
ENDPOINT_NUMBER(endp), errno, strerror(errno));
return -1;
}
if (tossed) {
LOGP(DRTP, LOGL_ERROR, "endpoint:%x packet tossed\n",
LOGP(DRTP, LOGL_ERROR, "endpoint:0x%x packet tossed\n",
ENDPOINT_NUMBER(endp));
}
@@ -830,11 +831,11 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
if (memcmp(&addr->sin_addr, &conn->end.addr, sizeof(addr->sin_addr))
!= 0) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x data from wrong address: %s, ",
"endpoint:0x%x data from wrong address: %s, ",
ENDPOINT_NUMBER(endp), inet_ntoa(addr->sin_addr));
LOGPC(DRTP, LOGL_ERROR, "expected: %s\n",
inet_ntoa(conn->end.addr));
LOGP(DRTP, LOGL_ERROR, "endpoint:%x packet tossed\n",
LOGP(DRTP, LOGL_ERROR, "endpoint:0x%x packet tossed\n",
ENDPOINT_NUMBER(endp));
return -1;
}
@@ -846,12 +847,12 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
if (conn->end.rtp_port != addr->sin_port &&
conn->end.rtcp_port != addr->sin_port) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x data from wrong source port: %d, ",
"endpoint:0x%x data from wrong source port: %d, ",
ENDPOINT_NUMBER(endp), ntohs(addr->sin_port));
LOGPC(DRTP, LOGL_ERROR,
"expected: %d for RTP or %d for RTCP\n",
ntohs(conn->end.rtp_port), ntohs(conn->end.rtcp_port));
LOGP(DRTP, LOGL_ERROR, "endpoint:%x packet tossed\n",
LOGP(DRTP, LOGL_ERROR, "endpoint:0x%x packet tossed\n",
ENDPOINT_NUMBER(endp));
return -1;
}
@@ -868,14 +869,14 @@ static int check_rtp_destin(struct mgcp_conn_rtp *conn)
if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x destination IP-address is invalid\n",
"endpoint:0x%x destination IP-address is invalid\n",
ENDPOINT_NUMBER(endp));
return -1;
}
if (conn->end.rtp_port == 0) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x destination rtp port is invalid\n",
"endpoint:0x%x destination rtp port is invalid\n",
ENDPOINT_NUMBER(endp));
return -1;
}
@@ -897,7 +898,7 @@ static int mgcp_recv(int *proto, struct sockaddr_in *addr, char *buf,
endp = conn->conn->endp;
tcfg = endp->tcfg;
LOGP(DRTP, LOGL_DEBUG, "endpoint:%x receiving RTP/RTCP packet...\n",
LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x receiving RTP/RTCP packet...\n",
ENDPOINT_NUMBER(endp));
rc = receive_from(endp, fd->fd, addr, buf, buf_size);
@@ -905,11 +906,11 @@ static int mgcp_recv(int *proto, struct sockaddr_in *addr, char *buf,
return -1;
*proto = fd == &conn->end.rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
LOGP(DRTP, LOGL_DEBUG, "endpoint:%x ", ENDPOINT_NUMBER(endp));
LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x ", ENDPOINT_NUMBER(endp));
LOGPC(DRTP, LOGL_DEBUG, "receiveing from %s %s %d\n",
conn->conn->name, inet_ntoa(addr->sin_addr),
ntohs(addr->sin_port));
LOGP(DRTP, LOGL_DEBUG, "endpoint:%x conn:%s\n", ENDPOINT_NUMBER(endp),
LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x conn:%s\n", ENDPOINT_NUMBER(endp),
mgcp_conn_dump(conn->conn));
/* Check if the origin of the RTP packet seems plausible */
@@ -921,16 +922,16 @@ static int mgcp_recv(int *proto, struct sockaddr_in *addr, char *buf,
/* Filter out dummy message */
if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) {
LOGP(DRTP, LOGL_NOTICE,
"endpoint:%x dummy message received\n",
"endpoint:0x%x dummy message received\n",
ENDPOINT_NUMBER(endp));
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x packet tossed\n", ENDPOINT_NUMBER(endp));
"endpoint:0x%x packet tossed\n", ENDPOINT_NUMBER(endp));
return 0;
}
/* Increment RX statistics */
conn->end.packets_rx += 1;
conn->end.octets_rx += rc;
conn->end.stats.packets_rx += 1;
conn->end.stats.octets_rx += rc;
/* Forward a copy of the RTP data to a debug ip/port */
forward_data(fd->fd, &conn->tap_in, buf, rc);
@@ -948,7 +949,7 @@ static int mgcp_send_rtp(int proto, struct sockaddr_in *addr, char *buf,
struct mgcp_endpoint *endp;
endp = conn_src->conn->endp;
LOGP(DRTP, LOGL_DEBUG, "endpoint:%x destin conn:%s\n",
LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x destin conn:%s\n",
ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn_dst->conn));
/* Before we try to deliver the packet, we check if the destination
@@ -962,7 +963,7 @@ static int mgcp_send_rtp(int proto, struct sockaddr_in *addr, char *buf,
switch (conn_dst->type) {
case MGCP_RTP_DEFAULT:
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x endpoint type is MGCP_RTP_DEFAULT, "
"endpoint:0x%x endpoint type is MGCP_RTP_DEFAULT, "
"using mgcp_send() to forward data directly\n",
ENDPOINT_NUMBER(endp));
return mgcp_send(endp, proto == MGCP_PROTO_RTP,
@@ -970,7 +971,7 @@ static int mgcp_send_rtp(int proto, struct sockaddr_in *addr, char *buf,
case MGCP_OSMUX_BSC_NAT:
case MGCP_OSMUX_BSC:
LOGP(DRTP, LOGL_DEBUG,
"endpoint:%x endpoint type is MGCP_OSMUX_BSC_NAT, "
"endpoint:0x%x endpoint type is MGCP_OSMUX_BSC_NAT, "
"using osmux_xfrm_to_osmux() to forward data through OSMUX\n",
ENDPOINT_NUMBER(endp));
return osmux_xfrm_to_osmux(buf, buf_size, conn_dst);
@@ -980,7 +981,7 @@ static int mgcp_send_rtp(int proto, struct sockaddr_in *addr, char *buf,
* be discarded, this should not happen, normally the MGCP type
* should be properly set */
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x bad MGCP type -- data discarded!\n",
"endpoint:0x%x bad MGCP type -- data discarded!\n",
ENDPOINT_NUMBER(endp));
return -1;
@@ -1025,7 +1026,7 @@ int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr, char *buf,
/* There is no destination conn, stop here */
if (!conn_dst) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x unable to find destination conn\n",
"endpoint:0x%x unable to find destination conn\n",
ENDPOINT_NUMBER(endp));
return -1;
}
@@ -1033,7 +1034,7 @@ int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr, char *buf,
/* The destination conn is not an RTP connection */
if (conn_dst->type != MGCP_CONN_TYPE_RTP) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x unable to find suitable destination conn\n",
"endpoint:0x%x unable to find suitable destination conn\n",
ENDPOINT_NUMBER(endp));
return -1;
}
@@ -1067,7 +1068,7 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
endp = conn_src->conn->endp;
OSMO_ASSERT(endp);
LOGP(DRTP, LOGL_DEBUG, "endpoint:%x source conn:%s\n",
LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x source conn:%s\n",
ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn_src->conn));
/* Receive packet */
@@ -1077,7 +1078,16 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
/* Check if the connection is in loopback mode, if yes, just send the
* incoming data back to the origin */
if (conn_src->conn->mode == MGCP_CONN_LOOPBACK) {
/* When we are in loopback mode, we loop back all incoming
* packets back to their origin. We will use the originating
* address data from the UDP packet header to patch the
* outgoing address in connection on the fly */
if (conn_src->end.rtp_port == 0) {
conn_src->end.addr = addr.sin_addr;
conn_src->end.rtp_port = addr.sin_port;
}
return mgcp_send_rtp(proto, &addr, buf,
len, conn_src, conn_src);
}
@@ -1158,7 +1168,7 @@ static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
if (mgcp_create_bind(source_addr, &rtp_end->rtp,
rtp_end->local_port) != 0) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x failed to create RTP port: %s:%d\n", endpno,
"endpoint:0x%x failed to create RTP port: %s:%d\n", endpno,
source_addr, rtp_end->local_port);
goto cleanup0;
}
@@ -1166,7 +1176,7 @@ static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
if (mgcp_create_bind(source_addr, &rtp_end->rtcp,
rtp_end->local_port + 1) != 0) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x failed to create RTCP port: %s:%d\n", endpno,
"endpoint:0x%x failed to create RTCP port: %s:%d\n", endpno,
source_addr, rtp_end->local_port + 1);
goto cleanup1;
}
@@ -1178,7 +1188,7 @@ static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
rtp_end->rtp.when = BSC_FD_READ;
if (osmo_fd_register(&rtp_end->rtp) != 0) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x failed to register RTP port %d\n", endpno,
"endpoint:0x%x failed to register RTP port %d\n", endpno,
rtp_end->local_port);
goto cleanup2;
}
@@ -1186,7 +1196,7 @@ static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
rtp_end->rtcp.when = BSC_FD_READ;
if (osmo_fd_register(&rtp_end->rtcp) != 0) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x failed to register RTCP port %d\n", endpno,
"endpoint:0x%x failed to register RTCP port %d\n", endpno,
rtp_end->local_port + 1);
goto cleanup3;
}
@@ -1217,12 +1227,12 @@ int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
struct mgcp_rtp_end *end;
char local_ip_addr[INET_ADDRSTRLEN];
snprintf(name, sizeof(name), "%s-%u", conn->conn->name, conn->conn->id);
snprintf(name, sizeof(name), "%s-%s", conn->conn->name, conn->conn->id);
end = &conn->end;
if (end->rtp.fd != -1 || end->rtcp.fd != -1) {
LOGP(DRTP, LOGL_ERROR,
"endpoint:%x %u was already bound on conn:%s\n",
"endpoint:0x%x %u was already bound on conn:%s\n",
ENDPOINT_NUMBER(endp), rtp_port,
mgcp_conn_dump(conn->conn));

View File

@@ -142,7 +142,7 @@ 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
* foud a the function will automatically allocate one */
* 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)
{
@@ -207,12 +207,18 @@ endpoint_lookup(struct mgcp_config *cfg, int cid,
case MGCP_DEST_NET:
/* FIXME: Get rid of CONN_ID_XXX! */
conn_net = mgcp_conn_get_rtp(endp, CONN_ID_NET);
this = &conn_net->end.addr;
if (conn_net)
this = &conn_net->end.addr;
else
this = NULL;
break;
case MGCP_DEST_BTS:
/* FIXME: Get rid of CONN_ID_XXX! */
conn_bts = mgcp_conn_get_rtp(endp, CONN_ID_BTS);
this = &conn_bts->end.addr;
if (conn_bts)
this = &conn_bts->end.addr;
else
this = NULL;
break;
default:
/* Should not ever happen */
@@ -222,7 +228,8 @@ endpoint_lookup(struct mgcp_config *cfg, int cid,
/* FIXME: Get rid of CONN_ID_XXX! */
conn_net = mgcp_conn_get_rtp(endp, CONN_ID_NET);
if (conn_net->osmux.cid == cid && this->s_addr == from_addr->s_addr)
if (conn_net && this && conn_net->osmux.cid == cid
&& this->s_addr == from_addr->s_addr)
return endp;
}
@@ -248,8 +255,8 @@ static void scheduled_tx_net_cb(struct msgb *msg, void *data)
.sin_port = conn_net->end.rtp_port,
};
conn_bts->end.octets_tx += msg->len;
conn_bts->end.packets_tx++;
conn_bts->end.stats.octets_tx += msg->len;
conn_bts->end.stats.packets_tx++;
/* Send RTP data to NET */
/* FIXME: Get rid of conn_bts and conn_net! */
@@ -275,8 +282,8 @@ static void scheduled_tx_bts_cb(struct msgb *msg, void *data)
.sin_port = conn_bts->end.rtp_port,
};
conn_net->end.octets_tx += msg->len;
conn_net->end.packets_tx++;
conn_net->end.stats.octets_tx += msg->len;
conn_net->end.stats.packets_tx++;
/* Send RTP data to BTS */
/* FIXME: Get rid of conn_bts and conn_net! */
@@ -566,7 +573,7 @@ void osmux_disable_conn(struct mgcp_conn_rtp *conn)
if (conn->osmux.state != OSMUX_STATE_ENABLED)
return;
LOGP(DLMGCP, LOGL_INFO, "Releasing connection %u using Osmux CID %u\n",
LOGP(DLMGCP, LOGL_INFO, "Releasing connection %s using Osmux CID %u\n",
conn->conn->id, conn->osmux.cid);
osmux_xfrm_input_close_circuit(conn->osmux.in, conn->osmux.cid);
conn->osmux.state = OSMUX_STATE_DISABLED;

View File

@@ -221,7 +221,7 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
osmux_extension[0] = '\0';
}
rc = msgb_printf(sdp, "I: %u%s\n\n", conn->conn->id, osmux_extension);
rc = msgb_printf(sdp, "I: %s%s\n\n", conn->conn->id, osmux_extension);
if (rc < 0)
goto error;
@@ -252,7 +252,7 @@ static void send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
{
struct mgcp_parse_data pdata;
int i, code, handled = 0;
int rc, i, code, handled = 0;
struct msgb *resp = NULL;
char *data;
@@ -280,13 +280,19 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
memset(&pdata, 0, sizeof(pdata));
pdata.cfg = cfg;
data = mgcp_strline((char *)msg->l3h, &pdata.save);
pdata.found = mgcp_parse_header(&pdata, data);
rc = mgcp_parse_header(&pdata, data);
if (pdata.endp && pdata.trans
&& pdata.endp->last_trans
&& strcmp(pdata.endp->last_trans, pdata.trans) == 0) {
return do_retransmission(pdata.endp);
}
/* check for general parser failure */
if (rc < 0) {
LOGP(DLMGCP, LOGL_NOTICE, "%s: failed to find the endpoint\n", msg->l2h);
return create_err_response(NULL, -rc, (const char *) msg->l2h, pdata.trans);
}
for (i = 0; i < ARRAY_SIZE(mgcp_requests); ++i) {
if (strncmp
(mgcp_requests[i].name, (const char *)&msg->l2h[0],
@@ -308,19 +314,13 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
static struct msgb *handle_audit_endpoint(struct mgcp_parse_data *p)
{
LOGP(DLMGCP, LOGL_NOTICE, "AUEP: auditing endpoint ...\n");
if (p->found != 0) {
LOGP(DLMGCP, LOGL_ERROR,
"AUEP: failed to find the endpoint.\n");
return create_err_response(NULL, 500, "AUEP", p->trans);
} else
return create_ok_response(p->endp, 200, "AUEP", p->trans);
return create_ok_response(p->endp, 200, "AUEP", p->trans);
}
/* Try to find a free port by attemting to bind on it. Also handle the
/* Try to find a free port by attempting to bind on it. Also handle the
* counter that points on the next free port. Since we have a pointer
* to the next free port, binding should work on the first attemt,
* neverless, try at least the next 200 ports before giving up */
* to the next free port, binding should work on the first attempt,
* nevertheless, try at least the next 200 ports before giving up */
static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
{
int i;
@@ -356,7 +356,7 @@ static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
}
/* Set the LCO from a string (see RFC 3435).
* The string is stored in the 'string' field. A NULL string is handled excatlyy
* The string is stored in the 'string' field. A NULL string is handled exactly
* like an empty string, the 'string' field is never NULL after this function
* has been called. */
static void set_local_cx_options(void *ctx, struct mgcp_lco *lco,
@@ -443,19 +443,15 @@ static struct msgb *handle_create_con(struct mgcp_parse_data *p)
const char *local_options = NULL;
const char *callid = NULL;
const char *ci = NULL;
const char *mode = NULL;
char *line;
int have_sdp = 0, osmux_cid = -1;
struct mgcp_conn_rtp *conn = NULL;
uint32_t conn_id;
struct mgcp_conn *_conn = NULL;
char conn_name[512];
LOGP(DLMGCP, LOGL_NOTICE, "CRCX: creating new connection ...\n");
if (p->found != 0)
return create_err_response(NULL, 510, "CRCX", p->trans);
/* parse CallID C: and LocalParameters L: */
for_each_line(line, p->save) {
if (!mgcp_check_param(endp, line))
@@ -469,7 +465,10 @@ static struct msgb *handle_create_con(struct mgcp_parse_data *p)
callid = (const char *)line + 3;
break;
case 'I':
ci = (const char *)line + 3;
/* It is illegal to send a connection identifier
* together with a CRCX, the MGW will assign the
* connection identifier by itself on CRCX */
return create_err_response(NULL, 523, "CRCX", p->trans);
break;
case 'M':
mode = (const char *)line + 3;
@@ -501,21 +500,14 @@ mgcp_header_done:
LOGP(DLMGCP, LOGL_ERROR,
"CRCX: endpoint:%x insufficient parameters, missing callid\n",
ENDPOINT_NUMBER(endp));
return create_err_response(endp, 400, "CRCX", p->trans);
return create_err_response(endp, 516, "CRCX", p->trans);
}
if (!mode) {
LOGP(DLMGCP, LOGL_ERROR,
"CRCX: endpoint:%x insufficient parameters, missing mode\n",
ENDPOINT_NUMBER(endp));
return create_err_response(endp, 400, "CRCX", p->trans);
}
if (!ci) {
LOGP(DLMGCP, LOGL_ERROR,
"CRCX: endpoint:%x insufficient parameters, missing connection id\n",
ENDPOINT_NUMBER(endp));
return create_err_response(endp, 400, "CRCX", p->trans);
return create_err_response(endp, 517, "CRCX", p->trans);
}
/* Check if we are able to accept the creation of another connection */
@@ -531,7 +523,7 @@ mgcp_header_done:
} else {
/* There is no more room for a connection, leave
* everything as it is and return with an error */
return create_err_response(endp, 400, "CRCX", p->trans);
return create_err_response(endp, 540, "CRCX", p->trans);
}
}
@@ -539,7 +531,7 @@ mgcp_header_done:
* callids match up so that we are sure that this is our call */
if (endp->callid && mgcp_verify_call_id(endp, callid)) {
LOGP(DLMGCP, LOGL_ERROR,
"CRCX: endpoint:%x allready seized by other call (%s)\n",
"CRCX: endpoint:0x%x allready seized by other call (%s)\n",
ENDPOINT_NUMBER(endp), endp->callid);
if (tcfg->force_realloc)
/* This is not our call, toss everything by releasing
@@ -553,7 +545,7 @@ mgcp_header_done:
}
/* Set the callid, creation of another connection will only be possible
* when the callid matches up. (Connections are distinuished by their
* when the callid matches up. (Connections are distinguished by their
* connection ids) */
endp->callid = talloc_strdup(tcfg->endpoints, callid);
@@ -561,39 +553,17 @@ mgcp_header_done:
set_local_cx_options(endp->tcfg->endpoints, &endp->local_options,
local_options);
if (mgcp_parse_ci(&conn_id, ci)) {
snprintf(conn_name, sizeof(conn_name), "%s", callid);
_conn = mgcp_conn_alloc(NULL, endp, MGCP_CONN_TYPE_RTP, conn_name);
if (!_conn) {
LOGP(DLMGCP, LOGL_ERROR,
"CRCX: endpoint:%x insufficient parameters, missing ci (connectionIdentifier)\n",
ENDPOINT_NUMBER(endp));
return create_err_response(endp, 400, "CRCX", p->trans);
}
/* Only accept another connection when the connection ID is different. */
if (mgcp_conn_get_rtp(endp, conn_id)) {
LOGP(DLMGCP, LOGL_ERROR,
"CRCX: endpoint:%x there is already a connection with id %u present!\n",
conn_id, ENDPOINT_NUMBER(endp));
if (tcfg->force_realloc) {
/* Ignore the existing connection by just freeing it */
mgcp_conn_free(endp, conn_id);
} else {
/* There is already a connection with that ID present,
* leave everything as it is and return with an error. */
return create_err_response(endp, 400, "CRCX", p->trans);
}
}
snprintf(conn_name, sizeof(conn_name), "%s-%u", callid, conn_id);
mgcp_conn_alloc(NULL, endp, conn_id, MGCP_CONN_TYPE_RTP,
conn_name);
conn = mgcp_conn_get_rtp(endp, conn_id);
if (!conn) {
LOGP(DLMGCP, LOGL_ERROR,
"CRCX: endpoint:%x unable to allocate RTP connection\n",
"CRCX: endpoint:0x%x unable to allocate RTP connection\n",
ENDPOINT_NUMBER(endp));
goto error2;
}
conn = mgcp_conn_get_rtp(endp, _conn->id);
OSMO_ASSERT(conn);
if (mgcp_parse_conn_mode(mode, endp, conn->conn) != 0) {
error_code = 517;
@@ -608,7 +578,7 @@ mgcp_header_done:
conn->osmux.state = OSMUX_STATE_NEGOTIATING;
} else if (endp->cfg->osmux == OSMUX_USAGE_ONLY) {
LOGP(DLMGCP, LOGL_ERROR,
"CRCX: endpoint:%x osmux only and no osmux offered\n",
"CRCX: endpoint:0x%x osmux only and no osmux offered\n",
ENDPOINT_NUMBER(endp));
goto error2;
}
@@ -635,7 +605,7 @@ mgcp_header_done:
if (setup_rtp_processing(endp, conn) != 0) {
LOGP(DLMGCP, LOGL_ERROR,
"CRCX: endpoint:%x could not start RTP processing!\n",
"CRCX: endpoint:0x%x could not start RTP processing!\n",
ENDPOINT_NUMBER(endp));
goto error2;
}
@@ -648,7 +618,7 @@ mgcp_header_done:
switch (rc) {
case MGCP_POLICY_REJECT:
LOGP(DLMGCP, LOGL_NOTICE,
"CRCX: endpoint:%x CRCX rejected by policy\n",
"CRCX: endpoint:0x%x CRCX rejected by policy\n",
ENDPOINT_NUMBER(endp));
mgcp_release_endp(endp);
return create_err_response(endp, 400, "CRCX", p->trans);
@@ -664,7 +634,7 @@ mgcp_header_done:
}
LOGP(DLMGCP, LOGL_DEBUG,
"CRCX: endpoint:%x Creating connection: CI: %u port: %u\n",
"CRCX: endpoint:0x%x Creating connection: CI: %s port: %u\n",
ENDPOINT_NUMBER(endp), conn->conn->id, conn->end.local_port);
if (p->cfg->change_cb)
p->cfg->change_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX);
@@ -676,13 +646,13 @@ mgcp_header_done:
send_dummy(endp, conn);
LOGP(DLMGCP, LOGL_NOTICE,
"CRCX: endpoint:%x connection successfully created\n",
"CRCX: endpoint:0x%x connection successfully created\n",
ENDPOINT_NUMBER(endp));
return create_response_with_sdp(endp, conn, "CRCX", p->trans);
error2:
mgcp_release_endp(endp);
LOGP(DLMGCP, LOGL_NOTICE,
"CRCX: endpoint:%x unable to create connection resource error\n",
"CRCX: endpoint:0x%x unable to create connection resource error\n",
ENDPOINT_NUMBER(endp));
return create_err_response(endp, error_code, "CRCX", p->trans);
}
@@ -695,20 +665,16 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
int silent = 0;
int have_sdp = 0;
char *line;
const char *ci = NULL;
const char *local_options = NULL;
const char *mode = NULL;
struct mgcp_conn_rtp *conn = NULL;
uint32_t conn_id;
const char *conn_id = NULL;
LOGP(DLMGCP, LOGL_NOTICE, "MDCX: modifying existing connection ...\n");
if (p->found != 0)
return create_err_response(NULL, 510, "MDCX", p->trans);
if (llist_count(&endp->conns) <= 0) {
LOGP(DLMGCP, LOGL_ERROR,
"MDCX: endpoint:%x endpoint is not holding a connection.\n",
"MDCX: endpoint:0x%x endpoint is not holding a connection.\n",
ENDPOINT_NUMBER(endp));
return create_err_response(endp, 400, "MDCX", p->trans);
}
@@ -719,13 +685,17 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
switch (line[0]) {
case 'C':
if (mgcp_verify_call_id(endp, line + 3) != 0)
if (mgcp_verify_call_id(endp, line + 3) != 0) {
error_code = 516;
goto error3;
}
break;
case 'I':
ci = (const char *)line + 3;
if (mgcp_verify_ci(endp, ci) != 0)
conn_id = (const char *)line + 3;
if (mgcp_verify_ci(endp, conn_id) != 0) {
error_code = 515;
goto error3;
}
break;
case 'L':
local_options = (const char *)line + 3;
@@ -742,18 +712,18 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
break;
default:
LOGP(DLMGCP, LOGL_NOTICE,
"MDCX: endpoint:%x Unhandled MGCP option: '%c'/%d\n",
"MDCX: endpoint:0x%x Unhandled MGCP option: '%c'/%d\n",
ENDPOINT_NUMBER(endp), line[0], line[0]);
break;
}
}
mgcp_header_done:
if (mgcp_parse_ci(&conn_id, ci)) {
if (!conn_id) {
LOGP(DLMGCP, LOGL_ERROR,
"MDCX: endpoint:%x insufficient parameters, missing ci (connectionIdentifier)\n",
"MDCX: endpoint:0x%x insufficient parameters, missing ci (connectionIdentifier)\n",
ENDPOINT_NUMBER(endp));
return create_err_response(endp, 400, "MDCX", p->trans);
return create_err_response(endp, 515, "MDCX", p->trans);
}
conn = mgcp_conn_get_rtp(endp, conn_id);
@@ -790,7 +760,7 @@ mgcp_header_done:
switch (rc) {
case MGCP_POLICY_REJECT:
LOGP(DLMGCP, LOGL_NOTICE,
"MDCX: endpoint:%x rejected by policy\n",
"MDCX: endpoint:0x%x rejected by policy\n",
ENDPOINT_NUMBER(endp));
if (silent)
goto out_silent;
@@ -799,7 +769,7 @@ mgcp_header_done:
case MGCP_POLICY_DEFER:
/* stop processing */
LOGP(DLMGCP, LOGL_DEBUG,
"MDCX: endpoint:%x defered by policy\n",
"MDCX: endpoint:0x%x defered by policy\n",
ENDPOINT_NUMBER(endp));
return NULL;
break;
@@ -813,7 +783,7 @@ mgcp_header_done:
/* modify */
LOGP(DLMGCP, LOGL_DEBUG,
"MDCX: endpoint:%x modified conn:%s\n",
"MDCX: endpoint:0x%x modified conn:%s\n",
ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn->conn));
if (p->cfg->change_cb)
p->cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp),
@@ -829,14 +799,14 @@ mgcp_header_done:
goto out_silent;
LOGP(DLMGCP, LOGL_NOTICE,
"MDCX: endpoint:%x connection successfully modified\n",
"MDCX: endpoint:0x%x connection successfully modified\n",
ENDPOINT_NUMBER(endp));
return create_response_with_sdp(endp, conn, "MDCX", p->trans);
error3:
return create_err_response(endp, error_code, "MDCX", p->trans);
out_silent:
LOGP(DLMGCP, LOGL_DEBUG, "MDCX: endpoint:%x silent exit\n",
LOGP(DLMGCP, LOGL_DEBUG, "MDCX: endpoint:0x%x silent exit\n",
ENDPOINT_NUMBER(endp));
return NULL;
}
@@ -849,22 +819,18 @@ static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
int silent = 0;
char *line;
char stats[1048];
const char *ci = NULL;
const char *conn_id = NULL;
struct mgcp_conn_rtp *conn = NULL;
uint32_t conn_id;
LOGP(DLMGCP, LOGL_NOTICE,
"DLCX: endpoint:%x deleting connection ...\n",
"DLCX: endpoint:0x%x deleting connection ...\n",
ENDPOINT_NUMBER(endp));
if (p->found != 0)
return create_err_response(NULL, error_code, "DLCX", p->trans);
if (llist_count(&endp->conns) <= 0) {
LOGP(DLMGCP, LOGL_ERROR,
"DLCX: endpoint:%x endpoint is not holding a connection.\n",
"DLCX: endpoint:0x%x endpoint is not holding a connection.\n",
ENDPOINT_NUMBER(endp));
return create_err_response(endp, 400, "DLCX", p->trans);
return create_err_response(endp, 515, "DLCX", p->trans);
}
for_each_line(line, p->save) {
@@ -873,20 +839,24 @@ static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
switch (line[0]) {
case 'C':
if (mgcp_verify_call_id(endp, line + 3) != 0)
if (mgcp_verify_call_id(endp, line + 3) != 0) {
error_code = 516;
goto error3;
}
break;
case 'I':
ci = (const char *)line + 3;
if (mgcp_verify_ci(endp, ci) != 0)
conn_id = (const char *)line + 3;
if (mgcp_verify_ci(endp, conn_id) != 0) {
error_code = 515;
goto error3;
}
break;
case 'Z':
silent = strcmp("noanswer", line + 3) == 0;
break;
default:
LOGP(DLMGCP, LOGL_NOTICE,
"DLCX: endpoint:%x Unhandled MGCP option: '%c'/%d\n",
"DLCX: endpoint:0x%x Unhandled MGCP option: '%c'/%d\n",
ENDPOINT_NUMBER(endp), line[0], line[0]);
break;
}
@@ -900,7 +870,7 @@ static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
switch (rc) {
case MGCP_POLICY_REJECT:
LOGP(DLMGCP, LOGL_NOTICE,
"DLCX: endpoint:%x rejected by policy\n",
"DLCX: endpoint:0x%x rejected by policy\n",
ENDPOINT_NUMBER(endp));
if (silent)
goto out_silent;
@@ -919,9 +889,9 @@ static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
/* When no connection id is supplied, we will interpret this as a
* wildcarded DLCX and drop all connections at once. (See also
* RFC3435 Section F.7) */
if (!ci) {
if (!conn_id) {
LOGP(DLMGCP, LOGL_NOTICE,
"DLCX: endpoint:%x missing ci (connectionIdentifier), will remove all connections at once\n",
"DLCX: endpoint:0x%x missing ci (connectionIdentifier), will remove all connections at once\n",
ENDPOINT_NUMBER(endp));
mgcp_release_endp(endp);
@@ -932,14 +902,6 @@ static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
return create_ok_response(endp, 200, "DLCX", p->trans);
}
/* Parse the connection id */
if (mgcp_parse_ci(&conn_id, ci)) {
LOGP(DLMGCP, LOGL_ERROR,
"DLCX: endpoint:%x insufficient parameters, invalid ci (connectionIdentifier)\n",
ENDPOINT_NUMBER(endp));
return create_err_response(endp, 400, "DLCX", p->trans);
}
/* Find the connection */
conn = mgcp_conn_get_rtp(endp, conn_id);
if (!conn)
@@ -949,11 +911,11 @@ static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
mgcp_format_stats(stats, sizeof(stats), conn->conn);
/* delete connection */
LOGP(DLMGCP, LOGL_DEBUG, "DLCX: endpoint:%x deleting conn:%s\n",
LOGP(DLMGCP, LOGL_DEBUG, "DLCX: endpoint:0x%x deleting conn:%s\n",
ENDPOINT_NUMBER(endp), mgcp_conn_dump(conn->conn));
mgcp_conn_free(endp, conn_id);
LOGP(DLMGCP, LOGL_NOTICE,
"DLCX: endpoint:%x connection successfully deleted\n",
"DLCX: endpoint:0x%x connection successfully deleted\n",
ENDPOINT_NUMBER(endp));
/* When all connections are closed, the endpoint will be released
@@ -961,7 +923,7 @@ static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
if (llist_count(&endp->conns) <= 0) {
mgcp_release_endp(endp);
LOGP(DLMGCP, LOGL_DEBUG,
"DLCX: endpoint:%x endpoint released\n",
"DLCX: endpoint:0x%x endpoint released\n",
ENDPOINT_NUMBER(endp));
}
@@ -977,7 +939,7 @@ error3:
return create_err_response(endp, error_code, "DLCX", p->trans);
out_silent:
LOGP(DLMGCP, LOGL_DEBUG, "DLCX: endpoint:%x silent exit\n",
LOGP(DLMGCP, LOGL_DEBUG, "DLCX: endpoint:0x%x silent exit\n",
ENDPOINT_NUMBER(endp));
return NULL;
}
@@ -995,12 +957,6 @@ static struct msgb *handle_rsip(struct mgcp_parse_data *p)
LOGP(DLMGCP, LOGL_NOTICE, "RSIP: resetting all endpoints ...\n");
if (p->found != 0) {
LOGP(DLMGCP, LOGL_ERROR,
"RSIP: failed to find the endpoint.\n");
return NULL;
}
if (p->cfg->reset_cb)
p->cfg->reset_cb(p->endp->tcfg);
return NULL;
@@ -1026,9 +982,6 @@ static struct msgb *handle_noti_req(struct mgcp_parse_data *p)
LOGP(DLMGCP, LOGL_NOTICE, "RQNT: processing request for notification ...\n");
if (p->found != 0)
return create_err_response(NULL, 400, "RQNT", p->trans);
for_each_line(line, p->save) {
switch (line[0]) {
case 'S':
@@ -1050,7 +1003,7 @@ static struct msgb *handle_noti_req(struct mgcp_parse_data *p)
}
/* Connection keepalive timer, will take care that dummy packets are send
* regulary, so that NAT connections stay open */
* regularly, so that NAT connections stay open */
static void mgcp_keepalive_timer_cb(void *_tcfg)
{
struct mgcp_trunk_config *tcfg = _tcfg;
@@ -1170,7 +1123,7 @@ struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int nr)
trunk->audio_payload = 126;
trunk->audio_send_ptime = 1;
trunk->audio_send_name = 1;
trunk->number_endpoints = 33;
trunk->vty_number_endpoints = 33;
trunk->omit_rtcp = 0;
mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
llist_add_tail(&trunk->entry, &cfg->trunks);
@@ -1202,12 +1155,12 @@ int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg)
tcfg->endpoints = _talloc_zero_array(tcfg->cfg,
sizeof(struct mgcp_endpoint),
tcfg->number_endpoints,
tcfg->vty_number_endpoints,
"endpoints");
if (!tcfg->endpoints)
return -1;
for (i = 0; i < tcfg->number_endpoints; ++i) {
for (i = 0; i < tcfg->vty_number_endpoints; ++i) {
INIT_LLIST_HEAD(&tcfg->endpoints[i].conns);
tcfg->endpoints[i].cfg = tcfg->cfg;
tcfg->endpoints[i].tcfg = tcfg;
@@ -1217,17 +1170,18 @@ int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg)
tcfg->endpoints[i].type = &ep_typeset.rtp;
}
tcfg->number_endpoints = tcfg->vty_number_endpoints;
return 0;
}
/*! relase endpoint, all open connections are closed.
/*! release endpoint, all open connections are closed.
* \param[in] endp endpoint to release */
void mgcp_release_endp(struct mgcp_endpoint *endp)
{
LOGP(DLMGCP, LOGL_DEBUG, "Releasing endpoint:%x\n",
LOGP(DLMGCP, LOGL_DEBUG, "Releasing endpoint:0x%x\n",
ENDPOINT_NUMBER(endp));
/* Normally this function should only be called wehen
/* Normally this function should only be called when
* all connections have been removed already. In case
* that there are still connections open (e.g. when
* RSIP is executed), free them all at once. */

View File

@@ -365,7 +365,7 @@ int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
rc = msgb_printf(sdp,
"v=0\r\n"
"o=- %u 23 IN IP4 %s\r\n"
"o=- %s 23 IN IP4 %s\r\n"
"s=-\r\n"
"c=IN IP4 %s\r\n"
"t=0 0\r\n", conn->conn->id, addr, addr);

View File

@@ -30,10 +30,10 @@ void calc_loss(struct mgcp_rtp_state *state,
struct mgcp_rtp_end *end, uint32_t *expected,
int *loss)
{
*expected = state->stats_cycles + state->stats_max_seq;
*expected = *expected - state->stats_base_seq + 1;
*expected = state->stats.cycles + state->stats.max_seq;
*expected = *expected - state->stats.base_seq + 1;
if (!state->stats_initialized) {
if (!state->stats.initialized) {
*expected = 0;
*loss = 0;
return;
@@ -43,8 +43,8 @@ void calc_loss(struct mgcp_rtp_state *state,
* Make sure the sign is correct and use the biggest
* positive/negative number that fits.
*/
*loss = *expected - end->packets_rx;
if (*expected < end->packets_rx) {
*loss = *expected - end->stats.packets_rx;
if (*expected < end->stats.packets_rx) {
if (*loss > 0)
*loss = INT_MIN;
} else {
@@ -56,9 +56,9 @@ void calc_loss(struct mgcp_rtp_state *state,
/* Helper function for mgcp_format_stats_rtp() to calculate jitter */
uint32_t calc_jitter(struct mgcp_rtp_state *state)
{
if (!state->stats_initialized)
if (!state->stats.initialized)
return 0;
return state->stats_jitter >> 4;
return state->stats.jitter >> 4;
}
/* Generate statistics for an RTP connection */
@@ -74,8 +74,8 @@ static void mgcp_format_stats_rtp(char *str, size_t str_len,
nchars = snprintf(str, str_len,
"\r\nP: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
conn->end.packets_tx, conn->end.octets_tx,
conn->end.packets_rx, conn->end.octets_rx,
conn->end.stats.packets_tx, conn->end.stats.octets_tx,
conn->end.stats.packets_rx, conn->end.stats.octets_rx,
ploss, jitter);
if (nchars < 0 || nchars >= str_len)
goto truncate;

View File

@@ -67,11 +67,11 @@ static int config_write_mgcp(struct vty *vty)
vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
vty_out(vty, " rtp net-range %u %u%s",
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)
vty_out(vty, " rtp net-bind-ip %s%s",
vty_out(vty, " rtp bind-ip %s%s",
g_cfg->net_ports.bind_addr, VTY_NEWLINE);
if (g_cfg->net_ports.bind_addr_probe)
vty_out(vty, " rtp ip-probing%s", VTY_NEWLINE);
@@ -115,7 +115,7 @@ static int config_write_mgcp(struct vty *vty)
g_cfg->trunk.audio_send_name ? "" : "no ", VTY_NEWLINE);
vty_out(vty, " loop %u%s", ! !g_cfg->trunk.audio_loop, VTY_NEWLINE);
vty_out(vty, " number endpoints %u%s",
g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
g_cfg->trunk.vty_number_endpoints - 1, VTY_NEWLINE);
vty_out(vty, " %sallow-transcoding%s",
g_cfg->trunk.no_audio_transcoding ? "no " : "", VTY_NEWLINE);
if (g_cfg->call_agent_addr)
@@ -167,7 +167,7 @@ static void dump_rtp_end(struct vty *vty, struct mgcp_rtp_state *state,
" Output-Enabled: %d Force-PTIME: %d%s",
state->in_stream.err_ts_counter,
state->out_stream.err_ts_counter, VTY_NEWLINE,
end->dropped_packets, VTY_NEWLINE,
end->stats.dropped_packets, VTY_NEWLINE,
codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE,
codec->frame_duration_num, codec->frame_duration_den,
VTY_NEWLINE, end->frames_per_packet, end->packet_duration_ms,
@@ -292,28 +292,37 @@ static void parse_range(struct mgcp_port_range *range, const char **argv)
#define RANGE_START_STR "Start of the range of ports\n"
#define RANGE_END_STR "End of the range of ports\n"
DEFUN(cfg_mgcp_rtp_net_range,
cfg_mgcp_rtp_net_range_cmd,
"rtp net-range <0-65534> <0-65534>",
DEFUN(cfg_mgcp_rtp_port_range,
cfg_mgcp_rtp_port_range_cmd,
"rtp port-range <0-65534> <0-65534>",
RTP_STR "Range of ports to use for the NET side\n"
RANGE_START_STR RANGE_END_STR)
{
parse_range(&g_cfg->net_ports, argv);
return CMD_SUCCESS;
}
ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
cfg_mgcp_rtp_net_range_cmd,
"rtp net-range <0-65534> <0-65534>",
RTP_STR "Range of ports to use for the NET side\n"
RANGE_START_STR RANGE_END_STR)
DEFUN(cfg_mgcp_rtp_net_bind_ip,
cfg_mgcp_rtp_net_bind_ip_cmd,
"rtp net-bind-ip A.B.C.D",
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")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
return CMD_SUCCESS;
}
ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
cfg_mgcp_rtp_net_bind_ip_cmd,
"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_net_bind_ip,
cfg_mgcp_rtp_no_net_bind_ip_cmd,
"no rtp net-bind-ip",
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")
{
@@ -321,6 +330,11 @@ DEFUN(cfg_mgcp_rtp_no_net_bind_ip,
g_cfg->net_ports.bind_addr = NULL;
return CMD_SUCCESS;
}
ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
cfg_mgcp_rtp_no_net_bind_ip_cmd,
"no rtp net-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,
@@ -510,7 +524,7 @@ DEFUN(cfg_mgcp_number_endp,
"Number options\n" "Endpoints available\n" "Number endpoints\n")
{
/* + 1 as we start counting at one */
g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
g_cfg->trunk.vty_number_endpoints = atoi(argv[0]) + 1;
return CMD_SUCCESS;
}
@@ -956,7 +970,7 @@ DEFUN(tap_rtp,
struct mgcp_trunk_config *trunk;
struct mgcp_endpoint *endp;
struct mgcp_conn_rtp *conn;
uint32_t conn_id;
const char *conn_id = NULL;
trunk = find_trunk(g_cfg, atoi(argv[0]));
if (!trunk) {
@@ -980,11 +994,11 @@ DEFUN(tap_rtp,
endp = &trunk->endpoints[endp_no];
conn_id = strtoul(argv[2], NULL, 10);
conn_id = argv[2];
conn = mgcp_conn_get_rtp(endp, conn_id);
if (!conn) {
vty_out(vty, "Conn ID %s/%d is invalid.%s",
argv[2], conn_id, VTY_NEWLINE);
vty_out(vty, "Conn ID %s is invalid.%s",
conn_id, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1102,7 +1116,7 @@ DEFUN(cfg_mgcp_osmux,
* allow to turn it on yet. */
vty_out(vty, "OSMUX currently unavailable in this software version.%s", VTY_NEWLINE);
return CMD_WARNING;
#if 0
if (strcmp(argv[0], "on") == 0)
g_cfg->osmux = OSMUX_USAGE_ON;
else if (strcmp(argv[0], "only") == 0)
@@ -1114,6 +1128,7 @@ DEFUN(cfg_mgcp_osmux,
}
return CMD_SUCCESS;
#endif
}
DEFUN(cfg_mgcp_osmux_ip,
@@ -1181,8 +1196,11 @@ int mgcp_vty_init(void)
install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
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_no_net_bind_ip_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_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);
@@ -1251,18 +1269,6 @@ int mgcp_vty_init(void)
return 0;
}
static int allocate_trunk(struct mgcp_trunk_config *trunk)
{
if (mgcp_endpoints_allocate(trunk) != 0) {
LOGP(DLMGCP, LOGL_ERROR,
"Failed to allocate %d endpoints on trunk %d.\n",
trunk->number_endpoints, trunk->trunk_nr);
return -1;
}
return 0;
}
int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
enum mgcp_role role)
{
@@ -1286,17 +1292,18 @@ int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
return -1;
}
if (allocate_trunk(&g_cfg->trunk) != 0) {
if (mgcp_endpoints_allocate(&g_cfg->trunk) != 0) {
LOGP(DLMGCP, LOGL_ERROR,
"Failed to initialize the virtual trunk.\n");
"Failed to initialize the virtual trunk (%d endpoints)\n",
g_cfg->trunk.number_endpoints);
return -1;
}
llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
if (allocate_trunk(trunk) != 0) {
if (mgcp_endpoints_allocate(trunk) != 0) {
LOGP(DLMGCP, LOGL_ERROR,
"Failed to initialize E1 trunk %d.\n",
trunk->trunk_nr);
"Failed to initialize trunk %d (%d endpoints)\n",
trunk->trunk_nr, trunk->number_endpoints);
return -1;
}
}

View File

@@ -189,33 +189,33 @@ static int read_call_agent(struct osmo_fd *fd, unsigned int what)
int mgcp_vty_is_config_node(struct vty *vty, int node)
{
switch (node) {
case CONFIG_NODE:
return 0;
switch (node) {
case CONFIG_NODE:
return 0;
default:
return 1;
}
default:
return 1;
}
}
int mgcp_vty_go_parent(struct vty *vty)
{
switch (vty->node) {
case TRUNK_NODE:
vty->node = MGCP_NODE;
vty->index = NULL;
break;
case MGCP_NODE:
default:
if (mgcp_vty_is_config_node(vty, vty->node))
vty->node = CONFIG_NODE;
else
vty->node = ENABLE_NODE;
switch (vty->node) {
case TRUNK_NODE:
vty->node = MGCP_NODE;
vty->index = NULL;
break;
case MGCP_NODE:
default:
if (mgcp_vty_is_config_node(vty, vty->node))
vty->node = CONFIG_NODE;
else
vty->node = ENABLE_NODE;
vty->index = NULL;
}
vty->index = NULL;
}
return vty->node;
return vty->node;
}
@@ -231,8 +231,8 @@ static const struct log_info_cat log_categories[] = {
};
const struct log_info log_info = {
.cat = log_categories,
.num_cat = ARRAY_SIZE(log_categories),
.cat = log_categories,
.num_cat = ARRAY_SIZE(log_categories),
};
int main(int argc, char **argv)
@@ -282,8 +282,8 @@ int main(int argc, char **argv)
/* set some callbacks */
cfg->reset_cb = mgcp_rsip_cb;
/* we need to bind a socket */
if (rc == 0) {
/* we need to bind a socket */
if (rc == 0) {
cfg->gw_fd.bfd.when = BSC_FD_READ;
cfg->gw_fd.bfd.cb = read_call_agent;
cfg->gw_fd.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);

View File

@@ -4,6 +4,7 @@
/*
* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2011 by On-Waves
* (C) 2017 by sysmocom - s.f.m.c. GmbH, Author: Philipp Maier
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -63,16 +64,16 @@ static struct mgcp_trunk_config *reset_trunk;
static int reset_endpoints = 0;
static int daemonize = 0;
const char *openbsc_copyright =
const char *osmomgw_copyright =
"Copyright (C) 2009-2010 Holger Freyther and On-Waves\r\n"
"Copyright (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>\r\n"
"Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\r\n"
"Dieter Spaar, Andreas Eversberg, Harald Welte\r\n\r\n"
"Contributions by Pablo Neira Ayuso, Jacob Erlbeck, Neels Hofmeyr\r\n"
"Philipp Maier\r\n\r\n"
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
"This is free software: you are free to change and redistribute it.\r\n"
"There is NO WARRANTY, to the extent permitted by law.\r\n";
static char *config_file = "mgcp.cfg";
static char *config_file = "osmo-mgw.cfg";
/* used by msgb and mgcp */
void *tall_bsc_ctx = NULL;
@@ -195,33 +196,33 @@ static int read_call_agent(struct osmo_fd *fd, unsigned int what)
int mgcp_vty_is_config_node(struct vty *vty, int node)
{
switch (node) {
case CONFIG_NODE:
return 0;
switch (node) {
case CONFIG_NODE:
return 0;
default:
return 1;
}
default:
return 1;
}
}
int mgcp_vty_go_parent(struct vty *vty)
{
switch (vty->node) {
case TRUNK_NODE:
vty->node = MGCP_NODE;
vty->index = NULL;
break;
case MGCP_NODE:
default:
if (mgcp_vty_is_config_node(vty, vty->node))
vty->node = CONFIG_NODE;
else
vty->node = ENABLE_NODE;
switch (vty->node) {
case TRUNK_NODE:
vty->node = MGCP_NODE;
vty->index = NULL;
break;
case MGCP_NODE:
default:
if (mgcp_vty_is_config_node(vty, vty->node))
vty->node = CONFIG_NODE;
else
vty->node = ENABLE_NODE;
vty->index = NULL;
}
vty->index = NULL;
}
return vty->node;
return vty->node;
}
@@ -243,8 +244,8 @@ static const struct log_info_cat log_categories[] = {
};
const struct log_info log_info = {
.cat = log_categories,
.num_cat = ARRAY_SIZE(log_categories),
.cat = log_categories,
.num_cat = ARRAY_SIZE(log_categories),
};
int main(int argc, char **argv)
@@ -262,7 +263,7 @@ int main(int argc, char **argv)
if (!cfg)
return -1;
vty_info.copyright = openbsc_copyright;
vty_info.copyright = osmomgw_copyright;
vty_init(&vty_info);
logging_vty_add_cmds(NULL);
osmo_stats_vty_add_cmds(&log_info);
@@ -279,7 +280,7 @@ int main(int argc, char **argv)
/* start telnet after reading config for vty_get_bind_addr() */
rc = telnet_init_dynif(tall_bsc_ctx, NULL,
vty_get_bind_addr(), OSMO_VTY_PORT_BSC_MGCP);
vty_get_bind_addr(), OSMO_VTY_PORT_MGW);
if (rc < 0)
return rc;
@@ -287,8 +288,8 @@ int main(int argc, char **argv)
* mgcp-command "RSIP" (Reset in Progress) is received */
cfg->reset_cb = mgcp_rsip_cb;
/* we need to bind a socket */
if (rc == 0) {
/* we need to bind a socket */
if (rc == 0) {
cfg->gw_fd.bfd.when = BSC_FD_READ;
cfg->gw_fd.bfd.cb = read_call_agent;
cfg->gw_fd.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);

View File

@@ -1212,7 +1212,7 @@ const struct log_info log_info = {
int main(int argc, char **argv)
{
msgb_talloc_ctx_init(NULL, 0);
void *msgb_ctx = msgb_talloc_ctx_init(NULL, 0);
osmo_init_logging(&log_info);
test_strline();
@@ -1231,6 +1231,9 @@ int main(int argc, char **argv)
test_no_name();
test_osmux_cid();
OSMO_ASSERT(talloc_total_size(msgb_ctx) == 0);
OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
talloc_free(msgb_ctx);
printf("Done\n");
return EXIT_SUCCESS;
}

View File

@@ -76,33 +76,33 @@ static void test_strline(void)
#define SHORT_RET "510 000000 FAIL\r\n"
#define MDCX_WRONG_EP "MDCX 18983213 ds/e1-3/1@172.16.6.66 MGCP 1.0\r\n"
#define MDCX_ERR_RET "510 18983213 FAIL\r\n"
#define MDCX_ERR_RET "500 18983213 FAIL\r\n"
#define MDCX_UNALLOCATED "MDCX 18983214 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n"
#define MDCX_RET "400 18983214 FAIL\r\n"
#define MDCX3 \
"MDCX 18983215 1@mgw MGCP 1.0\r\n" \
"I: 1\n"
"I: %s\n"
#define MDCX3_RET \
"200 18983215 OK\r\n" \
"I: 1\n" \
"I: %s\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
"m=audio 16002 RTP/AVP 128\r\n" \
"a=rtpmap:128 GSM-EFR/8000\r\n" \
"m=audio 16002 RTP/AVP 97\r\n" \
"a=rtpmap:97 GSM-EFR/8000\r\n" \
"a=ptime:40\r\n"
#define MDCX3A_RET \
"200 18983215 OK\r\n" \
"I: 1\n" \
"I: %s\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
@@ -112,15 +112,15 @@ static void test_strline(void)
#define MDCX3_FMTP_RET \
"200 18983215 OK\r\n" \
"I: 1\n" \
"I: %s\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
"m=audio 16006 RTP/AVP 128\r\n" \
"a=rtpmap:128 GSM-EFR/8000\r\n" \
"m=audio 16006 RTP/AVP 97\r\n" \
"a=rtpmap:97 GSM-EFR/8000\r\n" \
"a=fmtp:126 0/1/2\r\n" \
"a=ptime:40\r\n"
@@ -128,11 +128,11 @@ static void test_strline(void)
"MDCX 18983216 1@mgw MGCP 1.0\r\n" \
"M: sendrecv\r" \
"C: 2\r\n" \
"I: 1\r\n" \
"I: %s\r\n" \
"L: p:20, a:AMR, nt:IN\r\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
"m=audio 4441 RTP/AVP 99\r\n" \
@@ -141,10 +141,10 @@ static void test_strline(void)
#define MDCX4_RET(Ident) \
"200 " Ident " OK\r\n" \
"I: 1\n" \
"I: %s\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
@@ -154,10 +154,10 @@ static void test_strline(void)
#define MDCX4_RO_RET(Ident) \
"200 " Ident " OK\r\n" \
"I: 1\n" \
"I: %s\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
@@ -169,11 +169,11 @@ static void test_strline(void)
"MDCX 18983217 1@mgw MGCP 1.0\r\n" \
"M: sendrecv\r" \
"C: 2\r\n" \
"I: 1\r\n" \
"I: %s\r\n" \
"L: p:20-40, a:AMR, nt:IN\r\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
"m=audio 4441 RTP/AVP 99\r\n" \
@@ -184,11 +184,11 @@ static void test_strline(void)
"MDCX 18983218 1@mgw MGCP 1.0\r\n" \
"M: sendrecv\r" \
"C: 2\r\n" \
"I: 1\r\n" \
"I: %s\r\n" \
"L: p:20-20, a:AMR, nt:IN\r\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
"m=audio 4441 RTP/AVP 99\r\n" \
@@ -199,11 +199,11 @@ static void test_strline(void)
"MDCX 18983219 1@mgw MGCP 1.0\r\n" \
"M: sendrecv\r" \
"C: 2\r\n" \
"I: 1\r\n" \
"I: %s\r\n" \
"L: a:AMR, nt:IN\r\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
"m=audio 4441 RTP/AVP 99\r\n" \
@@ -214,11 +214,11 @@ static void test_strline(void)
"MDCX 18983220 1@mgw MGCP 1.0\r\n" \
"M: sendonly\r" \
"C: 2\r\n" \
"I: 1\r\n" \
"I: %s\r\n" \
"L: p:20, a:AMR, nt:IN\r\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
"m=audio 4441 RTP/AVP 99\r\n" \
@@ -229,7 +229,7 @@ static void test_strline(void)
"MDCX 18983221 1@mgw MGCP 1.0\r\n" \
"M: recvonly\r" \
"C: 2\r\n" \
"I: 1\r\n" \
"I: %s\r\n" \
"L: p:20, a:AMR, nt:IN\r\n"
#define SHORT2 "CRCX 1"
@@ -242,7 +242,6 @@ static void test_strline(void)
"CRCX 2 1@mgw MGCP 1.0\r\n" \
"M: recvonly\r\n" \
"C: 2\r\n" \
"I: 1\r\n" \
"L: p:20\r\n" \
"\r\n" \
"v=0\r\n" \
@@ -253,10 +252,10 @@ static void test_strline(void)
#define CRCX_RET \
"200 2 OK\r\n" \
"I: 1\n" \
"I: %s\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
@@ -266,10 +265,10 @@ static void test_strline(void)
#define CRCX_RET_NO_RTPMAP \
"200 2 OK\r\n" \
"I: 1\n" \
"I: %s\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
@@ -278,10 +277,10 @@ static void test_strline(void)
#define CRCX_FMTP_RET \
"200 2 OK\r\n" \
"I: 1\n" \
"I: %s\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
@@ -294,7 +293,6 @@ static void test_strline(void)
"CRCX 2 1@mgw MGCP 1.0\r" \
"M: recvonly\r" \
"C: 2\r\n" \
"I: 1\n" \
"\n" \
"v=0\r" \
"c=IN IP4 123.12.12.123\r" \
@@ -303,10 +301,10 @@ static void test_strline(void)
#define CRCX_ZYN_RET \
"200 2 OK\r\n" \
"I: 1\n" \
"I: %s\n" \
"\n" \
"v=0\r\n" \
"o=- 1 23 IN IP4 0.0.0.0\r\n" \
"o=- %s 23 IN IP4 0.0.0.0\r\n" \
"s=-\r\n" \
"c=IN IP4 0.0.0.0\r\n" \
"t=0 0\r\n" \
@@ -316,7 +314,7 @@ static void test_strline(void)
#define DLCX \
"DLCX 7 1@mgw MGCP 1.0\r\n" \
"I: 1\r\n" \
"I: %s\r\n" \
"C: 2\r\n"
#define DLCX_RET \
@@ -343,7 +341,6 @@ static void test_strline(void)
#define CRCX_MULT_1 \
"CRCX 2 1@mgw MGCP 1.0\r\n" \
"I: 4711\r\n" \
"M: recvonly\r\n" \
"C: 2\r\n" \
"X\r\n" \
@@ -358,7 +355,6 @@ static void test_strline(void)
#define CRCX_MULT_2 \
"CRCX 2 2@mgw MGCP 1.0\r\n" \
"I: 90210\r\n" \
"M: recvonly\r\n" \
"C: 2\r\n" \
"X\r\n" \
@@ -374,7 +370,6 @@ static void test_strline(void)
#define CRCX_MULT_3 \
"CRCX 2 3@mgw MGCP 1.0\r\n" \
"I: 0815\r\n" \
"M: recvonly\r\n" \
"C: 2\r\n" \
"X\r\n" \
@@ -390,7 +385,6 @@ static void test_strline(void)
#define CRCX_MULT_4 \
"CRCX 2 4@mgw MGCP 1.0\r\n" \
"I: 32168\r\n" \
"M: recvonly\r\n" \
"C: 2\r\n" \
"X\r\n" \
@@ -407,7 +401,6 @@ static void test_strline(void)
#define CRCX_MULT_GSM_EXACT \
"CRCX 259260421 5@mgw MGCP 1.0\r\n" \
"C: 1355c6041e\r\n" \
"I: 3\r\n" \
"L: p:20, a:GSM, nt:IN\r\n" \
"M: recvonly\r\n" \
"\r\n" \
@@ -432,7 +425,7 @@ static void test_strline(void)
#define MDCX_NAT_DUMMY \
"MDCX 23 5@mgw MGCP 1.0\r\n" \
"C: 1355c6041e\r\n" \
"I: 3\r\n" \
"I: %s\r\n" \
"\r\n" \
"c=IN IP4 8.8.8.8\r\n" \
"m=audio 16434 RTP/AVP 255\r\n"
@@ -482,12 +475,20 @@ static const struct mgcp_test retransmit[] = {
{"DLCX", DLCX, DLCX_RET},
};
static struct msgb *create_msg(const char *str)
static struct msgb *create_msg(const char *str, const char *conn_id)
{
struct msgb *msg;
int len;
printf("creating message from statically defined input:\n");
printf("---------8<---------\n%s\n---------8<---------\n", str);
msg = msgb_alloc_headroom(4096, 128, "MGCP msg");
int len = sprintf((char *)msg->data, "%s", str);
if (conn_id && strlen(conn_id))
len = sprintf((char *)msg->data, str, conn_id, conn_id);
else
len = sprintf((char *)msg->data, "%s", str);
msg->l2h = msgb_put(msg, len);
return msg;
}
@@ -554,20 +555,97 @@ static void test_values(void)
MGCP_CONN_RECV_SEND);
}
/* Extract a connection ID from a response (CRCX) */
static int get_conn_id_from_response(uint8_t *resp, char *conn_id,
unsigned int conn_id_len)
{
char *conn_id_ptr;
int i;
conn_id_ptr = strstr((char *)resp, "I: ");
if (!conn_id_ptr)
return -EINVAL;
memset(conn_id, 0, conn_id_len);
memcpy(conn_id, conn_id_ptr + 3, 32);
for (i = 0; i < conn_id_len; i++) {
if (conn_id[i] == '\n' || conn_id[i] == '\r')
conn_id[i] = '\0';
}
/* A valid conn_id must at least contain one digit, and must
* not exceed a length of 32 digits */
OSMO_ASSERT(strlen(conn_id) <= 32);
OSMO_ASSERT(strlen(conn_id) > 0);
return 0;
}
/* Check response, automatically patch connection ID if needed */
static int check_response(uint8_t *resp, const char *exp_resp)
{
char exp_resp_patched[4096];
const char *exp_resp_ptr;
char conn_id[256];
printf("checking response:\n");
/* If the expected response is intened to be patched
* (%s placeholder inside) we will patch it with the
* connection identifier we just received from the
* real response. This is necessary because the CI
* is generated by the mgcp code on CRCX and we can
* not know it in advance */
if (strstr(exp_resp, "%s")) {
if (get_conn_id_from_response(resp, conn_id, sizeof(conn_id)) ==
0) {
sprintf(exp_resp_patched, exp_resp, conn_id, conn_id);
exp_resp_ptr = exp_resp_patched;
printf
("using message with patched conn_id for comparison\n");
} else {
printf
("patching conn_id failed, using message as statically defined for comparison\n");
exp_resp_ptr = exp_resp;
}
} else {
printf("using message as statically defined for comparison\n");
exp_resp_ptr = exp_resp;
}
if (strcmp((char *)resp, exp_resp_ptr) != 0) {
printf("Unexpected response, please check!\n");
printf
("Got:\n---------8<---------\n%s\n---------8<---------\n\n",
resp);
printf
("Expected:\n---------8<---------\n%s\n---------8<---------\n",
exp_resp_ptr);
return -EINVAL;
}
printf("Response matches our expectations.\n");
return 0;
}
static void test_messages(void)
{
struct mgcp_config *cfg;
struct mgcp_endpoint *endp;
int i;
struct mgcp_conn_rtp *conn = NULL;
char last_conn_id[256];
int rc;
cfg = mgcp_config_alloc();
cfg->trunk.number_endpoints = 64;
cfg->trunk.vty_number_endpoints = 64;
mgcp_endpoints_allocate(&cfg->trunk);
cfg->policy_cb = mgcp_test_policy_cb;
memset(last_conn_id, 0, sizeof(last_conn_id));
mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
for (i = 0; i < ARRAY_SIZE(tests); i++) {
@@ -575,6 +653,7 @@ static void test_messages(void)
struct msgb *inp;
struct msgb *msg;
printf("\n================================================\n");
printf("Testing %s\n", t->name);
last_endpoint = -1;
@@ -583,7 +662,7 @@ static void test_messages(void)
osmo_talloc_replace_string(cfg, &cfg->trunk.audio_fmtp_extra,
t->extra_fmtp);
inp = create_msg(t->req);
inp = create_msg(t->req, last_conn_id);
msg = mgcp_handle_message(cfg, inp);
msgb_free(inp);
if (!t->exp_resp) {
@@ -592,12 +671,22 @@ static void test_messages(void)
(char *)msg->data);
OSMO_ASSERT(false);
}
} else if (strcmp((char *)msg->data, t->exp_resp) != 0) {
printf("%s failed.\nExpected:\n%s\nGot:\n%s\n",
t->name, t->exp_resp, (char *) msg->data);
} else if (check_response(msg->data, t->exp_resp) != 0) {
printf("%s failed.\n", t->name);
OSMO_ASSERT(false);
}
msgb_free(msg);
if (msg) {
rc = get_conn_id_from_response(msg->data, last_conn_id,
sizeof(last_conn_id));
if (rc)
printf("(response contains a connection id)\n");
else
printf("(response does not contain a connection id)\n");
}
if (msg)
msgb_free(msg);
if (dummy_packets)
printf("Dummy packets: %d\n", dummy_packets);
@@ -605,7 +694,7 @@ static void test_messages(void)
if (last_endpoint != -1) {
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, 1);
conn = mgcp_conn_get_rtp(endp, "1");
if (conn) {
OSMO_ASSERT(conn);
@@ -657,7 +746,7 @@ static void test_messages(void)
}
/* Check detected payload type */
if (t->ptype != PTYPE_IGNORE) {
if (conn && t->ptype != PTYPE_IGNORE) {
OSMO_ASSERT(last_endpoint != -1);
endp = &cfg->trunk.endpoints[last_endpoint];
@@ -682,12 +771,16 @@ static void test_retransmission(void)
{
struct mgcp_config *cfg;
int i;
char last_conn_id[256];
int rc;
cfg = mgcp_config_alloc();
cfg->trunk.number_endpoints = 64;
cfg->trunk.vty_number_endpoints = 64;
mgcp_endpoints_allocate(&cfg->trunk);
memset(last_conn_id, 0, sizeof(last_conn_id));
mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
for (i = 0; i < ARRAY_SIZE(retransmit); i++) {
@@ -695,24 +788,33 @@ static void test_retransmission(void)
struct msgb *inp;
struct msgb *msg;
printf("\n================================================\n");
printf("Testing %s\n", t->name);
inp = create_msg(t->req);
inp = create_msg(t->req, last_conn_id);
msg = mgcp_handle_message(cfg, inp);
msgb_free(inp);
if (strcmp((char *)msg->data, t->exp_resp) != 0) {
if (msg && check_response(msg->data, t->exp_resp) != 0) {
printf("%s failed '%s'\n", t->name, (char *)msg->data);
OSMO_ASSERT(false);
}
msgb_free(msg);
if (msg && strcmp(t->name, "CRCX") == 0) {
rc = get_conn_id_from_response(msg->data, last_conn_id,
sizeof(last_conn_id));
OSMO_ASSERT(rc == 0);
}
if (msg)
msgb_free(msg);
/* Retransmit... */
printf("Re-transmitting %s\n", t->name);
inp = create_msg(t->req);
inp = create_msg(t->req, last_conn_id);
msg = mgcp_handle_message(cfg, inp);
msgb_free(inp);
if (strcmp((char *)msg->data, t->exp_resp) != 0) {
if (check_response(msg->data, t->exp_resp) != 0) {
printf("%s failed '%s'\n", t->name, (char *)msg->data);
OSMO_ASSERT(false);
}
@@ -733,21 +835,26 @@ static void test_rqnt_cb(void)
{
struct mgcp_config *cfg;
struct msgb *inp, *msg;
char conn_id[256];
cfg = mgcp_config_alloc();
cfg->rqnt_cb = rqnt_cb;
cfg->trunk.number_endpoints = 64;
cfg->trunk.vty_number_endpoints = 64;
mgcp_endpoints_allocate(&cfg->trunk);
mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
inp = create_msg(CRCX);
msgb_free(mgcp_handle_message(cfg, inp));
inp = create_msg(CRCX, NULL);
msg = mgcp_handle_message(cfg, inp);
OSMO_ASSERT(msg);
OSMO_ASSERT(get_conn_id_from_response(msg->data, conn_id,
sizeof(conn_id)) == 0);
msgb_free(msg);
msgb_free(inp);
/* send the RQNT and check for the CB */
inp = create_msg(RQNT);
inp = create_msg(RQNT, conn_id);
msg = mgcp_handle_message(cfg, inp);
if (strncmp((const char *)msg->l2h, "200", 3) != 0) {
printf("FAILED: message is not 200. '%s'\n", msg->l2h);
@@ -762,7 +869,7 @@ static void test_rqnt_cb(void)
msgb_free(msg);
msgb_free(inp);
inp = create_msg(DLCX);
inp = create_msg(DLCX, conn_id);
msgb_free(mgcp_handle_message(cfg, inp));
msgb_free(inp);
talloc_free(cfg);
@@ -809,12 +916,12 @@ static void test_packet_loss_calc(void)
memset(&state, 0, sizeof(state));
memset(&rtp, 0, sizeof(rtp));
state.stats_initialized = 1;
state.stats_base_seq = pl_test_dat[i].base_seq;
state.stats_max_seq = pl_test_dat[i].max_seq;
state.stats_cycles = pl_test_dat[i].cycles;
state.stats.initialized = 1;
state.stats.base_seq = pl_test_dat[i].base_seq;
state.stats.max_seq = pl_test_dat[i].max_seq;
state.stats.cycles = pl_test_dat[i].cycles;
rtp.packets_rx = pl_test_dat[i].packets;
rtp.stats.packets_rx = pl_test_dat[i].packets;
calc_loss(&state, &rtp, &expected, &loss);
if (loss != pl_test_dat[i].loss
@@ -865,7 +972,7 @@ static void test_mgcp_stats(void)
int loss;
int rc;
msg = create_msg(DLCX_RET);
msg = create_msg(DLCX_RET, NULL);
rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter);
printf("Parsing result: %d\n", rc);
if (bps != 0 || bos != 0 || pr != 0 || _or != 0 || loss != 0
@@ -875,7 +982,7 @@ static void test_mgcp_stats(void)
msg =
create_msg
("250 7 OK\r\nP: PS=10, OS=20, PR=30, OR=40, PL=-3, JI=40\r\n");
("250 7 OK\r\nP: PS=10, OS=20, PR=30, OR=40, PL=-3, JI=40\r\n", NULL);
rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter);
printf("Parsing result: %d\n", rc);
if (bps != 10 || bos != 20 || pr != 30 || _or != 40 || loss != -3
@@ -1014,6 +1121,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
int last_in_ts_err_cnt = 0;
int last_out_ts_err_cnt = 0;
struct mgcp_conn_rtp *conn = NULL;
struct mgcp_conn *_conn = NULL;
printf("Testing packet error detection%s%s.\n",
patch_ssrc ? ", patch SSRC" : "",
@@ -1025,7 +1133,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
endp.type = &ep_typeset.rtp;
trunk.number_endpoints = 1;
trunk.vty_number_endpoints = 1;
trunk.endpoints = &endp;
trunk.force_constant_ssrc = patch_ssrc;
trunk.force_aligned_timing = patch_ts;
@@ -1033,9 +1141,10 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
endp.tcfg = &trunk;
INIT_LLIST_HEAD(&endp.conns);
mgcp_conn_alloc(NULL, &endp, 4711, MGCP_CONN_TYPE_RTP,
"test-connection");
conn = mgcp_conn_get_rtp(&endp, 4711);
_conn = mgcp_conn_alloc(NULL, &endp, MGCP_CONN_TYPE_RTP,
"test-connection");
OSMO_ASSERT(_conn);
conn = mgcp_conn_get_rtp(&endp, _conn->id);
OSMO_ASSERT(conn);
rtp = &conn->end;
@@ -1074,7 +1183,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
state.out_stream.err_ts_counter - last_out_ts_err_cnt);
printf("Stats: Jitter = %u, Transit = %d\n",
calc_jitter(&state), state.stats_transit);
calc_jitter(&state), state.stats.transit);
last_in_ts_err_cnt = state.in_stream.err_ts_counter;
last_out_ts_err_cnt = state.out_stream.err_ts_counter;
@@ -1083,6 +1192,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
}
force_monotonic_time_us = -1;
mgcp_conn_free_all(&endp);
}
static void test_multilple_codec(void)
@@ -1092,96 +1202,107 @@ static void test_multilple_codec(void)
struct msgb *inp, *resp;
struct in_addr addr;
struct mgcp_conn_rtp *conn = NULL;
char conn_id[256];
printf("Testing multiple payload types\n");
cfg = mgcp_config_alloc();
cfg->trunk.number_endpoints = 64;
cfg->trunk.vty_number_endpoints = 64;
mgcp_endpoints_allocate(&cfg->trunk);
cfg->policy_cb = mgcp_test_policy_cb;
mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
/* Allocate endpoint 1@mgw with two codecs */
last_endpoint = -1;
inp = create_msg(CRCX_MULT_1);
inp = create_msg(CRCX_MULT_1, NULL);
resp = mgcp_handle_message(cfg, inp);
OSMO_ASSERT(get_conn_id_from_response(resp->data, conn_id,
sizeof(conn_id)) == 0);
msgb_free(inp);
msgb_free(resp);
OSMO_ASSERT(last_endpoint == 1);
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, 4711);
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
OSMO_ASSERT(conn->end.codec.payload_type == 18);
OSMO_ASSERT(conn->end.alt_codec.payload_type == 97);
/* Allocate 2@mgw with three codecs, last one ignored */
last_endpoint = -1;
inp = create_msg(CRCX_MULT_2);
inp = create_msg(CRCX_MULT_2, NULL);
resp = mgcp_handle_message(cfg, inp);
OSMO_ASSERT(get_conn_id_from_response(resp->data, conn_id,
sizeof(conn_id)) == 0);
msgb_free(inp);
msgb_free(resp);
OSMO_ASSERT(last_endpoint == 2);
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, 90210);
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
OSMO_ASSERT(conn->end.codec.payload_type == 18);
OSMO_ASSERT(conn->end.alt_codec.payload_type == 97);
/* Allocate 3@mgw with no codecs, check for PT == -1 */
last_endpoint = -1;
inp = create_msg(CRCX_MULT_3);
inp = create_msg(CRCX_MULT_3, NULL);
resp = mgcp_handle_message(cfg, inp);
OSMO_ASSERT(get_conn_id_from_response(resp->data, conn_id,
sizeof(conn_id)) == 0);
msgb_free(inp);
msgb_free(resp);
OSMO_ASSERT(last_endpoint == 3);
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, 815);
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
OSMO_ASSERT(conn->end.codec.payload_type == -1);
OSMO_ASSERT(conn->end.alt_codec.payload_type == -1);
/* Allocate 4@mgw with a single codec */
last_endpoint = -1;
inp = create_msg(CRCX_MULT_4);
inp = create_msg(CRCX_MULT_4, NULL);
resp = mgcp_handle_message(cfg, inp);
OSMO_ASSERT(get_conn_id_from_response(resp->data, conn_id,
sizeof(conn_id)) == 0);
msgb_free(inp);
msgb_free(resp);
OSMO_ASSERT(last_endpoint == 4);
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, 32168);
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
OSMO_ASSERT(conn->end.codec.payload_type == 18);
OSMO_ASSERT(conn->end.alt_codec.payload_type == -1);
/* Allocate 5@mgw at select GSM.. */
last_endpoint = -1;
inp = create_msg(CRCX_MULT_GSM_EXACT);
inp = create_msg(CRCX_MULT_GSM_EXACT, NULL);
talloc_free(cfg->trunk.audio_name);
cfg->trunk.audio_name = "GSM/8000";
cfg->trunk.no_audio_transcoding = 1;
resp = mgcp_handle_message(cfg, inp);
OSMO_ASSERT(get_conn_id_from_response(resp->data, conn_id,
sizeof(conn_id)) == 0);
msgb_free(inp);
msgb_free(resp);
OSMO_ASSERT(last_endpoint == 5);
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, 3);
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
OSMO_ASSERT(conn->end.codec.payload_type == 3);
OSMO_ASSERT(conn->end.alt_codec.payload_type == -1);
inp = create_msg(MDCX_NAT_DUMMY);
inp = create_msg(MDCX_NAT_DUMMY, conn_id);
last_endpoint = -1;
resp = mgcp_handle_message(cfg, inp);
msgb_free(inp);
msgb_free(resp);
OSMO_ASSERT(last_endpoint == 5);
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, 3);
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
OSMO_ASSERT(conn->end.codec.payload_type == 3);
OSMO_ASSERT(conn->end.alt_codec.payload_type == -1);
@@ -1198,19 +1319,21 @@ static void test_multilple_codec(void)
talloc_free(endp->last_response);
talloc_free(endp->last_trans);
endp->last_response = endp->last_trans = NULL;
conn = mgcp_conn_get_rtp(endp, 3);
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(!conn);
last_endpoint = -1;
inp = create_msg(CRCX_MULT_GSM_EXACT);
inp = create_msg(CRCX_MULT_GSM_EXACT, NULL);
cfg->trunk.no_audio_transcoding = 0;
resp = mgcp_handle_message(cfg, inp);
OSMO_ASSERT(get_conn_id_from_response(resp->data, conn_id,
sizeof(conn_id)) == 0);
msgb_free(inp);
msgb_free(resp);
OSMO_ASSERT(last_endpoint == 5);
endp = &cfg->trunk.endpoints[last_endpoint];
conn = mgcp_conn_get_rtp(endp, 3);
conn = mgcp_conn_get_rtp(endp, conn_id);
OSMO_ASSERT(conn);
OSMO_ASSERT(conn->end.codec.payload_type == 255);
OSMO_ASSERT(conn->end.alt_codec.payload_type == 0);
@@ -1223,44 +1346,47 @@ static void test_no_cycle(void)
struct mgcp_config *cfg;
struct mgcp_endpoint *endp;
struct mgcp_conn_rtp *conn = NULL;
struct mgcp_conn *_conn = NULL;
printf("Testing no sequence flow on initial packet\n");
cfg = mgcp_config_alloc();
cfg->trunk.number_endpoints = 64;
cfg->trunk.vty_number_endpoints = 64;
mgcp_endpoints_allocate(&cfg->trunk);
endp = &cfg->trunk.endpoints[1];
mgcp_conn_alloc(NULL, endp, 4711, MGCP_CONN_TYPE_RTP,
"test-connection");
conn = mgcp_conn_get_rtp(endp, 4711);
_conn = mgcp_conn_alloc(NULL, endp, MGCP_CONN_TYPE_RTP,
"test-connection");
OSMO_ASSERT(_conn);
conn = mgcp_conn_get_rtp(endp, _conn->id);
OSMO_ASSERT(conn);
OSMO_ASSERT(conn->state.stats_initialized == 0);
OSMO_ASSERT(conn->state.stats.initialized == 0);
mgcp_rtp_annex_count(endp, &conn->state, 0, 0, 2342);
OSMO_ASSERT(conn->state.stats_initialized == 1);
OSMO_ASSERT(conn->state.stats_cycles == 0);
OSMO_ASSERT(conn->state.stats_max_seq == 0);
OSMO_ASSERT(conn->state.stats.initialized == 1);
OSMO_ASSERT(conn->state.stats.cycles == 0);
OSMO_ASSERT(conn->state.stats.max_seq == 0);
mgcp_rtp_annex_count(endp, &conn->state, 1, 0, 2342);
OSMO_ASSERT(conn->state.stats_initialized == 1);
OSMO_ASSERT(conn->state.stats_cycles == 0);
OSMO_ASSERT(conn->state.stats_max_seq == 1);
OSMO_ASSERT(conn->state.stats.initialized == 1);
OSMO_ASSERT(conn->state.stats.cycles == 0);
OSMO_ASSERT(conn->state.stats.max_seq == 1);
/* now jump.. */
mgcp_rtp_annex_count(endp, &conn->state, UINT16_MAX, 0, 2342);
OSMO_ASSERT(conn->state.stats_initialized == 1);
OSMO_ASSERT(conn->state.stats_cycles == 0);
OSMO_ASSERT(conn->state.stats_max_seq == UINT16_MAX);
OSMO_ASSERT(conn->state.stats.initialized == 1);
OSMO_ASSERT(conn->state.stats.cycles == 0);
OSMO_ASSERT(conn->state.stats.max_seq == UINT16_MAX);
/* and wrap */
mgcp_rtp_annex_count(endp, &conn->state, 0, 0, 2342);
OSMO_ASSERT(conn->state.stats_initialized == 1);
OSMO_ASSERT(conn->state.stats_cycles == UINT16_MAX + 1);
OSMO_ASSERT(conn->state.stats_max_seq == 0);
OSMO_ASSERT(conn->state.stats.initialized == 1);
OSMO_ASSERT(conn->state.stats.cycles == UINT16_MAX + 1);
OSMO_ASSERT(conn->state.stats.max_seq == 0);
mgcp_release_endp(endp);
talloc_free(cfg);
}
@@ -1272,7 +1398,7 @@ static void test_no_name(void)
printf("Testing no rtpmap name\n");
cfg = mgcp_config_alloc();
cfg->trunk.number_endpoints = 64;
cfg->trunk.vty_number_endpoints = 64;
cfg->trunk.audio_send_name = 0;
mgcp_endpoints_allocate(&cfg->trunk);
@@ -1280,9 +1406,10 @@ static void test_no_name(void)
mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
inp = create_msg(CRCX);
inp = create_msg(CRCX, NULL);
msg = mgcp_handle_message(cfg, inp);
if (strcmp((char *)msg->data, CRCX_RET_NO_RTPMAP) != 0) {
if (check_response(msg->data, CRCX_RET_NO_RTPMAP) != 0) {
printf("FAILED: there should not be a RTPMAP: %s\n",
(char *)msg->data);
OSMO_ASSERT(false);
@@ -1329,7 +1456,7 @@ const struct log_info log_info = {
int main(int argc, char **argv)
{
msgb_talloc_ctx_init(NULL, 0);
void *msgb_ctx = msgb_talloc_ctx_init(NULL, 0);
osmo_init_logging(&log_info);
test_strline();
@@ -1348,6 +1475,9 @@ int main(int argc, char **argv)
test_no_name();
test_osmux_cid();
OSMO_ASSERT(talloc_total_size(msgb_ctx) == 0);
OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
talloc_free(msgb_ctx);
printf("Done\n");
return EXIT_SUCCESS;
}

View File

@@ -11,87 +11,574 @@ line: 'mixed (4 lines)'
line: ''
line: ''
line: ''
================================================
Testing AUEP1
creating message from statically defined input:
---------8<---------
AUEP 158663169 ds/e1-1/2@172.16.6.66 MGCP 1.0
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing AUEP2
creating message from statically defined input:
---------8<---------
AUEP 18983213 ds/e1-2/1@172.16.6.66 MGCP 1.0
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing MDCX1
creating message from statically defined input:
---------8<---------
MDCX 18983213 ds/e1-3/1@172.16.6.66 MGCP 1.0
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing MDCX2
creating message from statically defined input:
---------8<---------
MDCX 18983214 ds/e1-1/2@172.16.6.66 MGCP 1.0
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing CRCX
creating message from statically defined input:
---------8<---------
CRCX 2 1@mgw MGCP 1.0
M: recvonly
C: 2
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP 97
a=rtpmap:97 GSM-EFR/8000
a=ptime:40
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
(response does not contain a connection id)
Dummy packets: 2
Detected packet duration: 40
Requested packetetization period: 20-20
Connection mode: 1: RECV
================================================
Testing MDCX3
creating message from statically defined input:
---------8<---------
MDCX 18983215 1@mgw MGCP 1.0
I: %s
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
(response does not contain a connection id)
Dummy packets: 2
Detected packet duration: 40
Requested packetization period not set
Connection mode: 1: RECV
================================================
Testing MDCX4
creating message from statically defined input:
---------8<---------
MDCX 18983216 1@mgw MGCP 1.0
M: sendrecv
C: 2
I: %s
L: p:20, a:AMR, nt:IN
v=0
o=- %s 23 IN IP4 0.0.0.0
c=IN IP4 0.0.0.0
t=0 0
m=audio 4441 RTP/AVP 99
a=rtpmap:99 AMR/8000
a=ptime:40
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
(response does not contain a connection id)
Detected packet duration: 40
Requested packetetization period: 20-20
Connection mode: 3: SEND RECV
Dummy packets: 2
================================================
Testing MDCX4_PT1
creating message from statically defined input:
---------8<---------
MDCX 18983217 1@mgw MGCP 1.0
M: sendrecv
C: 2
I: %s
L: p:20-40, a:AMR, nt:IN
v=0
o=- %s 23 IN IP4 0.0.0.0
c=IN IP4 0.0.0.0
t=0 0
m=audio 4441 RTP/AVP 99
a=rtpmap:99 AMR/8000
a=ptime:40
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
Detected packet duration: 40
Requested packetetization period: 20-40
Connection mode: 3: SEND RECV
(response does not contain a connection id)
Dummy packets: 2
================================================
Testing MDCX4_PT2
creating message from statically defined input:
---------8<---------
MDCX 18983218 1@mgw MGCP 1.0
M: sendrecv
C: 2
I: %s
L: p:20-20, a:AMR, nt:IN
v=0
o=- %s 23 IN IP4 0.0.0.0
c=IN IP4 0.0.0.0
t=0 0
m=audio 4441 RTP/AVP 99
a=rtpmap:99 AMR/8000
a=ptime:40
---------8<---------
checking response:
using message with patched conn_id for comparison
Detected packet duration: 40
Requested packetetization period: 20-20
Connection mode: 3: SEND RECV
Response matches our expectations.
(response does not contain a connection id)
Dummy packets: 2
================================================
Testing MDCX4_PT3
creating message from statically defined input:
---------8<---------
MDCX 18983219 1@mgw MGCP 1.0
M: sendrecv
C: 2
I: %s
L: a:AMR, nt:IN
v=0
o=- %s 23 IN IP4 0.0.0.0
c=IN IP4 0.0.0.0
t=0 0
m=audio 4441 RTP/AVP 99
a=rtpmap:99 AMR/8000
a=ptime:40
---------8<---------
checking response:
Detected packet duration: 40
Requested packetization period not set
Connection mode: 3: SEND RECV
using message with patched conn_id for comparison
Response matches our expectations.
(response does not contain a connection id)
Detected packet duration: 40
Requested packetetization period: 20-20
Connection mode: 2: SEND
Dummy packets: 2
================================================
Testing MDCX4_SO
creating message from statically defined input:
---------8<---------
MDCX 18983220 1@mgw MGCP 1.0
M: sendonly
C: 2
I: %s
L: p:20, a:AMR, nt:IN
v=0
o=- %s 23 IN IP4 0.0.0.0
c=IN IP4 0.0.0.0
t=0 0
m=audio 4441 RTP/AVP 99
a=rtpmap:99 AMR/8000
a=ptime:40
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
(response does not contain a connection id)
================================================
Testing MDCX4_RO
creating message from statically defined input:
---------8<---------
MDCX 18983221 1@mgw MGCP 1.0
M: recvonly
C: 2
I: %s
L: p:20, a:AMR, nt:IN
Detected packet duration: 40
Requested packetetization period: 20-20
Connection mode: 1: RECV
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
(response does not contain a connection id)
Dummy packets: 2
================================================
Testing DLCX
creating message from statically defined input:
---------8<---------
DLCX 7 1@mgw MGCP 1.0
I: %s
C: 2
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing CRCX_ZYN
creating message from statically defined input:
---------8<---------
CRCX 2 1@mgw MGCP 1.0
M: recvonly
C: 2
Detected packet duration: 20
Requested packetization period not set
Connection mode: 1: RECV
v=0
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP 97
a=rtpmap:97 GSM-EFR/8000
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
(response does not contain a connection id)
Dummy packets: 2
================================================
Testing EMPTY
creating message from statically defined input:
---------8<---------
---------8<---------
================================================
Testing SHORT1
creating message from statically defined input:
---------8<---------
CRCX
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing SHORT2
creating message from statically defined input:
---------8<---------
CRCX 1
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing SHORT3
creating message from statically defined input:
---------8<---------
CRCX 1 1@mgw
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing SHORT4
creating message from statically defined input:
---------8<---------
CRCX 1 1@mgw MGCP
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing RQNT1
creating message from statically defined input:
---------8<---------
RQNT 186908780 1@mgw MGCP 1.0
X: B244F267488
S: D/9
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing RQNT2
creating message from statically defined input:
---------8<---------
RQNT 186908781 1@mgw MGCP 1.0
X: ADD4F26746F
R: D/[0-9#*](N), G/ft, fxr/t38
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing DLCX
creating message from statically defined input:
---------8<---------
DLCX 7 1@mgw MGCP 1.0
I: %s
C: 2
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing CRCX
creating message from statically defined input:
---------8<---------
CRCX 2 1@mgw MGCP 1.0
M: recvonly
C: 2
L: p:20
v=0
Detected packet duration: 40
Requested packetetization period: 20-20
Connection mode: 1: RECV
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP 97
a=rtpmap:97 GSM-EFR/8000
a=ptime:40
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
(response does not contain a connection id)
Dummy packets: 2
================================================
Testing MDCX3
Detected packet duration: 40
Requested packetization period not set
Connection mode: 1: RECV
creating message from statically defined input:
---------8<---------
MDCX 18983215 1@mgw MGCP 1.0
I: %s
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
(response does not contain a connection id)
Dummy packets: 2
================================================
Testing DLCX
creating message from statically defined input:
---------8<---------
DLCX 7 1@mgw MGCP 1.0
I: %s
C: 2
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
(response contains a connection id)
================================================
Testing CRCX
creating message from statically defined input:
---------8<---------
CRCX 2 1@mgw MGCP 1.0
M: recvonly
C: 2
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP 97
a=rtpmap:97 GSM-EFR/8000
a=ptime:40
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
Re-transmitting CRCX
creating message from statically defined input:
---------8<---------
CRCX 2 1@mgw MGCP 1.0
M: recvonly
C: 2
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP 97
a=rtpmap:97 GSM-EFR/8000
a=ptime:40
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
================================================
Testing RQNT1
creating message from statically defined input:
---------8<---------
RQNT 186908780 1@mgw MGCP 1.0
X: B244F267488
S: D/9
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
Re-transmitting RQNT1
creating message from statically defined input:
---------8<---------
RQNT 186908780 1@mgw MGCP 1.0
X: B244F267488
S: D/9
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
================================================
Testing RQNT2
creating message from statically defined input:
---------8<---------
RQNT 186908781 1@mgw MGCP 1.0
X: ADD4F26746F
R: D/[0-9#*](N), G/ft, fxr/t38
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
Re-transmitting RQNT2
creating message from statically defined input:
---------8<---------
RQNT 186908781 1@mgw MGCP 1.0
X: ADD4F26746F
R: D/[0-9#*](N), G/ft, fxr/t38
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
================================================
Testing MDCX3
creating message from statically defined input:
---------8<---------
MDCX 18983215 1@mgw MGCP 1.0
I: %s
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
Re-transmitting MDCX3
creating message from statically defined input:
---------8<---------
MDCX 18983215 1@mgw MGCP 1.0
I: %s
---------8<---------
checking response:
using message with patched conn_id for comparison
Response matches our expectations.
================================================
Testing DLCX
creating message from statically defined input:
---------8<---------
DLCX 7 1@mgw MGCP 1.0
I: %s
C: 2
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
Re-transmitting DLCX
creating message from statically defined input:
---------8<---------
DLCX 7 1@mgw MGCP 1.0
I: %s
C: 2
---------8<---------
checking response:
using message as statically defined for comparison
Response matches our expectations.
Testing packet loss calculation.
creating message from statically defined input:
---------8<---------
CRCX 2 1@mgw MGCP 1.0
M: recvonly
C: 2
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP 97
a=rtpmap:97 GSM-EFR/8000
a=ptime:40
---------8<---------
creating message from statically defined input:
---------8<---------
RQNT 186908780 1@mgw MGCP 1.0
X: B244F267488
S: D/9
---------8<---------
creating message from statically defined input:
---------8<---------
DLCX 7 1@mgw MGCP 1.0
I: %s
C: 2
---------8<---------
Testing stat parsing
creating message from statically defined input:
---------8<---------
250 7 OK
P: PS=0, OS=0, PR=0, OR=0, PL=0, JI=0
X-Osmo-CP: EC TI=0, TO=0
@@ -466,6 +953,156 @@ In TS: 160320, dTS: 160, Seq: 1002
Stats: Jitter = 22, Transit = -32888
In TS: 36888, dTS: 160, Seq: 25
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 21, Transit = -32888
In TS: 160000, dTS: 0, Seq: 1000
Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -144000
In TS: 160160, dTS: 160, Seq: 1001
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -144000
In TS: 160320, dTS: 160, Seq: 1002
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -144000
Testing multiple payload types
creating message from statically defined input:
---------8<---------
CRCX 2 1@mgw MGCP 1.0
M: recvonly
C: 2
X
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP 18 97
a=rtpmap:18 G729/8000
a=rtpmap:97 GSM-EFR/8000
a=ptime:40
---------8<---------
creating message from statically defined input:
---------8<---------
CRCX 2 2@mgw MGCP 1.0
M: recvonly
C: 2
X
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP 18 97 101
a=rtpmap:18 G729/8000
a=rtpmap:97 GSM-EFR/8000
a=rtpmap:101 FOO/8000
a=ptime:40
---------8<---------
creating message from statically defined input:
---------8<---------
CRCX 2 3@mgw MGCP 1.0
M: recvonly
C: 2
X
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP
a=rtpmap:18 G729/8000
a=rtpmap:97 GSM-EFR/8000
a=rtpmap:101 FOO/8000
a=ptime:40
---------8<---------
creating message from statically defined input:
---------8<---------
CRCX 2 4@mgw MGCP 1.0
M: recvonly
C: 2
X
L: p:20
v=0
c=IN IP4 123.12.12.123
m=audio 5904 RTP/AVP 18
a=rtpmap:18 G729/8000
a=rtpmap:97 GSM-EFR/8000
a=rtpmap:101 FOO/8000
a=ptime:40
---------8<---------
creating message from statically defined input:
---------8<---------
CRCX 259260421 5@mgw MGCP 1.0
C: 1355c6041e
L: p:20, a:GSM, nt:IN
M: recvonly
v=0
o=- 1439038275 1439038275 IN IP4 192.168.181.247
s=-
c=IN IP4 192.168.181.247
t=0 0
m=audio 29084 RTP/AVP 255 0 8 3 18 4 96 97 101
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:3 gsm/8000
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:4 G723/8000
a=rtpmap:96 iLBC/8000
a=fmtp:96 mode=20
a=rtpmap:97 iLBC/8000
a=fmtp:97 mode=30
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=recvonly
---------8<---------
creating message from statically defined input:
---------8<---------
MDCX 23 5@mgw MGCP 1.0
C: 1355c6041e
I: %s
c=IN IP4 8.8.8.8
m=audio 16434 RTP/AVP 255
---------8<---------
creating message from statically defined input:
---------8<---------
CRCX 259260421 5@mgw MGCP 1.0
C: 1355c6041e
L: p:20, a:GSM, nt:IN
M: recvonly
v=0
o=- 1439038275 1439038275 IN IP4 192.168.181.247
s=-
c=IN IP4 192.168.181.247
t=0 0
m=audio 29084 RTP/AVP 255 0 8 3 18 4 96 97 101
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:3 gsm/8000
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:4 G723/8000
a=rtpmap:96 iLBC/8000
a=fmtp:96 mode=20
a=rtpmap:97 iLBC/8000
a=fmtp:97 mode=30
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=recvonly
---------8<---------
Testing no sequence flow on initial packet
Testing no rtpmap name
creating message from statically defined input:
---------8<---------
CRCX 2 1@mgw MGCP 1.0
M: recvonly
C: 2
L: p:20

View File

@@ -37,3 +37,6 @@ mgcp_client_test_LDADD = \
$(LIBRARY_DL) \
$(LIBOSMONETIF_LIBS) \
$(NULL)
update_exp:
$(builddir)/mgcp_client_test >$(srcdir)/mgcp_client_test.ok 2>$(srcdir)/mgcp_client_test.err

View File

@@ -24,6 +24,7 @@
#include <osmocom/core/application.h>
#include <osmocom/mgcp_client/mgcp_client.h>
#include <osmocom/mgcp_client/mgcp_client_internal.h>
#include <errno.h>
void *ctx;
@@ -46,14 +47,14 @@ static struct msgb *mgcp_from_str(const char *head, const char *params)
l = strlen(head);
msg->l2h = msgb_put(msg, l);
data = (char*)msgb_l2(msg);
strncpy(data, head, l);
osmo_strlcpy(data, head, l);
data = (char*)msgb_put(msg, 1);
*data = '\n';
l = strlen(params);
data = (char*)msgb_put(msg, l);
strncpy(data, params, l);
osmo_strlcpy(data, params, l);
return msg;
}
@@ -66,14 +67,14 @@ static struct msgb *from_str(const char *str)
char *data;
msg->l2h = msgb_put(msg, l);
data = (char*)msgb_l2(msg);
strncpy(data, str, l);
osmo_strlcpy(data, str, l);
return msg;
}
static struct mgcp_client_conf conf;
struct mgcp_client *mgcp = NULL;
static void reply_to(mgcp_trans_id_t trans_id, int code, const char *comment,
static int reply_to(mgcp_trans_id_t trans_id, int code, const char *comment,
int conn_id, const char *params)
{
static char compose[4096 - 128];
@@ -87,7 +88,7 @@ static void reply_to(mgcp_trans_id_t trans_id, int code, const char *comment,
printf("composed response:\n-----\n%s\n-----\n",
compose);
mgcp_client_rx(mgcp, from_str(compose));
return mgcp_client_rx(mgcp, from_str(compose));
}
void test_response_cb(struct mgcp_response *response, void *priv)
@@ -162,7 +163,7 @@ void test_mgcp_msg(void)
.endpoint = "23@mgw",
.audio_port = 1234,
.call_id = 47,
.conn_id = 11,
.conn_id = "11",
.conn_mode = MGCP_CONN_RECV_SEND
};
@@ -225,6 +226,51 @@ void test_mgcp_msg(void)
msgb_free(msg);
}
void test_mgcp_client_cancel()
{
mgcp_trans_id_t trans_id;
struct msgb *msg;
struct mgcp_msg mgcp_msg = {
.verb = MGCP_VERB_CRCX,
.audio_ip = "192.168.100.23",
.endpoint = "23@mgw",
.audio_port = 1234,
.call_id = 47,
.conn_id = "11",
.conn_mode = MGCP_CONN_RECV_SEND,
.presence = (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID
| MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE),
};
printf("\n%s():\n", __func__);
fprintf(stderr, "\n%s():\n", __func__);
if (mgcp)
talloc_free(mgcp);
mgcp = mgcp_client_init(ctx, &conf);
msg = mgcp_msg_gen(mgcp, &mgcp_msg);
trans_id = mgcp_msg_trans_id(msg);
fprintf(stderr, "- composed msg with trans_id=%u\n", trans_id);
fprintf(stderr, "- not in queue yet, cannot cancel yet\n");
OSMO_ASSERT(mgcp_client_cancel(mgcp, trans_id) == -ENOENT);
fprintf(stderr, "- enqueue\n");
dummy_mgcp_send(msg);
fprintf(stderr, "- cancel succeeds\n");
OSMO_ASSERT(mgcp_client_cancel(mgcp, trans_id) == 0);
fprintf(stderr, "- late response gets discarded\n");
OSMO_ASSERT(reply_to(trans_id, 200, "OK", 1, "v=0\r\n") == -ENOENT);
fprintf(stderr, "- canceling again does nothing\n");
OSMO_ASSERT(mgcp_client_cancel(mgcp, trans_id) == -ENOENT);
fprintf(stderr, "%s() done\n", __func__);
}
static const struct log_info_cat log_categories[] = {
};
@@ -244,10 +290,13 @@ int main(int argc, char **argv)
log_set_use_color(osmo_stderr_target, 0);
log_set_print_category(osmo_stderr_target, 1);
log_set_category_filter(osmo_stderr_target, DLMGCP, 1, LOGL_DEBUG);
mgcp_client_conf_init(&conf);
test_crcx();
test_mgcp_msg();
test_mgcp_client_cancel();
printf("Done\n");
fprintf(stderr, "Done\n");

View File

@@ -1,2 +1,15 @@
DLMGCP message buffer to small, can not generate MGCP message
test_mgcp_client_cancel():
- composed msg with trans_id=1
- not in queue yet, cannot cancel yet
DLMGCP Cannot cancel, no such transaction: 1
- enqueue
- cancel succeeds
DLMGCP Canceled transaction 1
- late response gets discarded
DLMGCP Cannot find matching MGCP transaction for trans_id 1
- canceling again does nothing
DLMGCP Cannot cancel, no such transaction: 1
test_mgcp_client_cancel() done
Done

View File

@@ -59,4 +59,23 @@ RSIP 5 23@mgw MGCP 1.0
Overfolow test:
test_mgcp_client_cancel():
composed:
-----
CRCX 1 23@mgw MGCP 1.0
C: 2f
I: 11
L: p:20, a:AMR, nt:IN
M: sendrecv
-----
composed response:
-----
200 1 OK
I: 1
v=0
-----
Done