mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 13:03:33 +00:00
Compare commits
48 Commits
1.2.1
...
lynxis/34c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb57b9b3a1 | ||
|
|
e35eeae8e0 | ||
|
|
abbb6b9088 | ||
|
|
3f35a3708a | ||
|
|
33eafe050b | ||
|
|
1d1b98f4a4 | ||
|
|
a0ac30faa5 | ||
|
|
49e3d5a9c9 | ||
|
|
3338135ead | ||
|
|
5dbfc78aff | ||
|
|
7bc5552512 | ||
|
|
a330b864e5 | ||
|
|
7df419b434 | ||
|
|
7cedfd753b | ||
|
|
23b8e29835 | ||
|
|
1c3287f1db | ||
|
|
922ae9a5bf | ||
|
|
189d6bf4d4 | ||
|
|
c8f37cb4d6 | ||
|
|
c0dcc3c60c | ||
|
|
230e4fc270 | ||
|
|
ead2f60f73 | ||
|
|
f8bfbe8b14 | ||
|
|
ffd75e420c | ||
|
|
01d24a3281 | ||
|
|
0be3ce66c0 | ||
|
|
fcd0655176 | ||
|
|
48454983c4 | ||
|
|
9a3543a8d4 | ||
|
|
465446b4b4 | ||
|
|
b597b4fc9d | ||
|
|
d20910c655 | ||
|
|
677f4ad968 | ||
|
|
7c20c9de5a | ||
|
|
839fc954d0 | ||
|
|
d164b05655 | ||
|
|
a896f9cdeb | ||
|
|
1b0cf6fa1c | ||
|
|
9bf7c53779 | ||
|
|
6be0fdb5e4 | ||
|
|
641c4d47b9 | ||
|
|
c1b9fa158e | ||
|
|
6a421f1b6f | ||
|
|
f1889d8640 | ||
|
|
2982e42d93 | ||
|
|
ddf1f9d7d5 | ||
|
|
653c4ff354 | ||
|
|
4efce88a62 |
@@ -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
|
||||
13
configure.ac
13
configure.ac
@@ -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"])
|
||||
|
||||
11
contrib/systemd/osmo-mgw.service
Normal file
11
contrib/systemd/osmo-mgw.service
Normal 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
|
||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,9 +1,3 @@
|
||||
osmo-mgw (1.2.1) unstable; urgency=medium
|
||||
[ Harald Welte ]
|
||||
* debian: fix osmo-mgw, it should depend on libosmo-mgcp1, not 0
|
||||
|
||||
-- Harald Welte <laforge@gnumonks.org> Fri, 13 Apr 2018 08:43:29 +0200
|
||||
|
||||
osmo-mgw (1.2.0) unstable; urgency=medium
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
|
||||
1
debian/osmo-mgw.service
vendored
Symbolic link
1
debian/osmo-mgw.service
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../contrib/systemd/osmo-mgw.service
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user