Rewire build and includes to libosmo-legacy-mgcp. Drop osmo-bsc_mgcp and related python tests, now found in osmo-mgw.git. libosmo-legacy-mgcp is installed from osmo-mgw, hence add the dependency to jenkins.sh (so far using the pre_release branch). Change-Id: Ic99d681759edce11564da62500c2aac5cf5fffe2changes/92/3492/9
parent
c2df7e84a7
commit
979cd26f35
@ -1,300 +0,0 @@ |
||||
/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */ |
||||
|
||||
/*
|
||||
* (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org> |
||||
* (C) 2009-2012 by On-Waves |
||||
* All Rights Reserved |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as published by |
||||
* the Free Software Foundation; either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
*/ |
||||
|
||||
#ifndef OPENBSC_MGCP_H |
||||
#define OPENBSC_MGCP_H |
||||
|
||||
#include <osmocom/core/msgb.h> |
||||
#include <osmocom/core/write_queue.h> |
||||
#include <osmocom/core/timer.h> |
||||
|
||||
#include "debug.h" |
||||
|
||||
#include <arpa/inet.h> |
||||
#include <sys/types.h> |
||||
#include <sys/socket.h> |
||||
#include <netinet/in.h> |
||||
|
||||
#define RTP_PORT_DEFAULT 4000 |
||||
#define RTP_PORT_NET_DEFAULT 16000 |
||||
|
||||
/**
|
||||
* Calculate the RTP audio port for the given multiplex |
||||
* and the direction. This allows a semi static endpoint |
||||
* to port calculation removing the need for the BSC |
||||
* and the MediaGateway to communicate. |
||||
* |
||||
* Port usage explained: |
||||
* base + (multiplex * 2) + 0 == local port to wait for network packets |
||||
* base + (multiplex * 2) + 1 == local port for rtcp |
||||
* |
||||
* The above port will receive packets from the BTS that need |
||||
* to be patched and forwarded to the network. |
||||
* The above port will receive packets from the network that |
||||
* need to be patched and forwarded to the BTS. |
||||
* |
||||
* We assume to have a static BTS IP address so we can differentiate |
||||
* network and BTS. |
||||
* |
||||
*/ |
||||
static inline int rtp_calculate_port(int multiplex, int base) |
||||
{ |
||||
return base + (multiplex * 2); |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* Handling of MGCP Endpoints and the MGCP Config |
||||
*/ |
||||
struct mgcp_endpoint; |
||||
struct mgcp_config; |
||||
struct mgcp_trunk_config; |
||||
struct mgcp_rtp_end; |
||||
|
||||
#define MGCP_ENDP_CRCX 1 |
||||
#define MGCP_ENDP_DLCX 2 |
||||
#define MGCP_ENDP_MDCX 3 |
||||
|
||||
/*
|
||||
* what to do with the msg? |
||||
* - continue as usual? |
||||
* - reject and send a failure code? |
||||
* - defer? do not send anything |
||||
*/ |
||||
#define MGCP_POLICY_CONT 4 |
||||
#define MGCP_POLICY_REJECT 5 |
||||
#define MGCP_POLICY_DEFER 6 |
||||
|
||||
typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint); |
||||
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state); |
||||
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id); |
||||
typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg); |
||||
typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone); |
||||
|
||||
/**
|
||||
* Return: |
||||
* < 0 in case no audio was processed |
||||
* >= 0 in case audio was processed. The remaining payload |
||||
* length will be returned. |
||||
*/ |
||||
typedef int (*mgcp_processing)(struct mgcp_endpoint *endp, |
||||
struct mgcp_rtp_end *dst_end, |
||||
char *data, int *len, int buf_size); |
||||
typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp, |
||||
struct mgcp_rtp_end *dst_end, |
||||
struct mgcp_rtp_end *src_end); |
||||
|
||||
typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp, |
||||
int *payload_type, |
||||
const char**subtype_name, |
||||
const char**fmtp_extra); |
||||
|
||||
#define PORT_ALLOC_STATIC 0 |
||||
#define PORT_ALLOC_DYNAMIC 1 |
||||
|
||||
/**
|
||||
* This holds information on how to allocate ports |
||||
*/ |
||||
struct mgcp_port_range { |
||||
int mode; |
||||
|
||||
/* addr or NULL to fall-back to default */ |
||||
char *bind_addr; |
||||
|
||||
/* pre-allocated from a base? */ |
||||
int base_port; |
||||
|
||||
/* dynamically allocated */ |
||||
int range_start; |
||||
int range_end; |
||||
int last_port; |
||||
}; |
||||
|
||||
#define MGCP_KEEPALIVE_ONCE (-1) |
||||
|
||||
struct mgcp_trunk_config { |
||||
struct llist_head entry; |
||||
|
||||
struct mgcp_config *cfg; |
||||
|
||||
int trunk_nr; |
||||
int trunk_type; |
||||
|
||||
char *audio_fmtp_extra; |
||||
char *audio_name; |
||||
int audio_payload; |
||||
int audio_send_ptime; |
||||
int audio_send_name; |
||||
int audio_loop; |
||||
|
||||
int no_audio_transcoding; |
||||
|
||||
int omit_rtcp; |
||||
int keepalive_interval; |
||||
|
||||
/* RTP patching */ |
||||
int force_constant_ssrc; /* 0: don't, 1: once */ |
||||
int force_aligned_timing; |
||||
|
||||
/* spec handling */ |
||||
int force_realloc; |
||||
|
||||
/* timer */ |
||||
struct osmo_timer_list keepalive_timer; |
||||
|
||||
unsigned int number_endpoints; |
||||
struct mgcp_endpoint *endpoints; |
||||
}; |
||||
|
||||
enum mgcp_role { |
||||
MGCP_BSC = 0, |
||||
MGCP_BSC_NAT, |
||||
}; |
||||
|
||||
enum mgcp_connection_mode { |
||||
MGCP_CONN_NONE = 0, |
||||
MGCP_CONN_RECV_ONLY = 1, |
||||
MGCP_CONN_SEND_ONLY = 2, |
||||
MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY, |
||||
MGCP_CONN_LOOPBACK = 4 | MGCP_CONN_RECV_SEND, |
||||
}; |
||||
|
||||
extern const struct value_string mgcp_connection_mode_strs[]; |
||||
|
||||
static inline const char *mgcp_cmode_name(enum mgcp_connection_mode mode) |
||||
{ |
||||
return get_value_string(mgcp_connection_mode_strs, mode); |
||||
} |
||||
|
||||
struct mgcp_config { |
||||
int source_port; |
||||
char *local_ip; |
||||
char *source_addr; |
||||
char *bts_ip; |
||||
char *call_agent_addr; |
||||
|
||||
struct in_addr bts_in; |
||||
|
||||
/* transcoder handling */ |
||||
char *transcoder_ip; |
||||
struct in_addr transcoder_in; |
||||
int transcoder_remote_base; |
||||
|
||||
/* RTP processing */ |
||||
mgcp_processing rtp_processing_cb; |
||||
mgcp_processing_setup setup_rtp_processing_cb; |
||||
|
||||
mgcp_get_format get_net_downlink_format_cb; |
||||
|
||||
struct osmo_wqueue gw_fd; |
||||
|
||||
struct mgcp_port_range bts_ports; |
||||
struct mgcp_port_range net_ports; |
||||
struct mgcp_port_range transcoder_ports; |
||||
int endp_dscp; |
||||
|
||||
int bts_force_ptime; |
||||
|
||||
mgcp_change change_cb; |
||||
mgcp_policy policy_cb; |
||||
mgcp_reset reset_cb; |
||||
mgcp_realloc realloc_cb; |
||||
mgcp_rqnt rqnt_cb; |
||||
void *data; |
||||
|
||||
uint32_t last_call_id; |
||||
|
||||
/* trunk handling */ |
||||
struct mgcp_trunk_config trunk; |
||||
struct llist_head trunks; |
||||
|
||||
/* only used for start with a static configuration */ |
||||
int last_net_port; |
||||
int last_bts_port; |
||||
|
||||
enum mgcp_role role; |
||||
|
||||
/* osmux translator: 0 means disabled, 1 means enabled */ |
||||
int osmux; |
||||
/* addr to bind the server to */ |
||||
char *osmux_addr; |
||||
/* The BSC-NAT may ask for enabling osmux on demand. This tells us if
|
||||
* the osmux socket is already initialized. |
||||
*/ |
||||
int osmux_init; |
||||
/* osmux batch factor: from 1 to 4 maximum */ |
||||
int osmux_batch; |
||||
/* osmux batch size (in bytes) */ |
||||
int osmux_batch_size; |
||||
/* osmux port */ |
||||
uint16_t osmux_port; |
||||
/* Pad circuit with dummy messages until we see the first voice
|
||||
* message. |
||||
*/ |
||||
uint16_t osmux_dummy; |
||||
}; |
||||
|
||||
/* config management */ |
||||
struct mgcp_config *mgcp_config_alloc(void); |
||||
int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg, |
||||
enum mgcp_role role); |
||||
int mgcp_vty_init(void); |
||||
int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg); |
||||
void mgcp_release_endp(struct mgcp_endpoint *endp); |
||||
void mgcp_initialize_endp(struct mgcp_endpoint *endp); |
||||
int mgcp_reset_transcoder(struct mgcp_config *cfg); |
||||
void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size); |
||||
int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter); |
||||
|
||||
void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval); |
||||
|
||||
/*
|
||||
* format helper functions |
||||
*/ |
||||
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg); |
||||
|
||||
/* adc helper */ |
||||
static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot) |
||||
{ |
||||
if (timeslot == 0) { |
||||
LOGP(DMGCP, LOGL_ERROR, "Timeslot should not be 0\n"); |
||||
timeslot = 255; |
||||
} |
||||
|
||||
return timeslot + (32 * multiplex); |
||||
} |
||||
|
||||
static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot) |
||||
{ |
||||
*multiplex = endpoint / 32; |
||||
*timeslot = endpoint % 32; |
||||
} |
||||
|
||||
int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint); |
||||
int mgcp_send_reset_all(struct mgcp_config *cfg); |
||||
|
||||
|
||||
int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port); |
||||
int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp, struct sockaddr_in *addr, char *buf, int rc); |
||||
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len); |
||||
|
||||
#endif |
@ -1,337 +0,0 @@ |
||||
/* MGCP Private Data */ |
||||
|
||||
/*
|
||||
* (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org> |
||||
* (C) 2009-2012 by On-Waves |
||||
* All Rights Reserved |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as published by |
||||
* the Free Software Foundation; either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <osmocom/core/select.h> |
||||
|
||||
#define CI_UNUSED 0 |
||||
|
||||
enum mgcp_trunk_type { |
||||
MGCP_TRUNK_VIRTUAL, |
||||
MGCP_TRUNK_E1, |
||||
}; |
||||
|
||||
struct mgcp_rtp_stream_state { |
||||
uint32_t ssrc; |
||||
uint16_t last_seq; |
||||
uint32_t last_timestamp; |
||||
uint32_t err_ts_counter; |
||||
int32_t last_tsdelta; |
||||
uint32_t last_arrival_time; |
||||
}; |
||||
|
||||
struct mgcp_rtp_state { |
||||
int initialized; |
||||
int patch_ssrc; |
||||
|
||||
uint32_t orig_ssrc; |
||||
|
||||
int seq_offset; |
||||
|
||||
int32_t timestamp_offset; |
||||
uint32_t packet_duration; |
||||
|
||||
struct mgcp_rtp_stream_state in_stream; |
||||
struct mgcp_rtp_stream_state out_stream; |
||||
|
||||
/* jitter and packet loss calculation */ |
||||
int stats_initialized; |
||||
uint16_t stats_base_seq; |
||||
uint16_t stats_max_seq; |
||||
uint32_t stats_ssrc; |
||||
uint32_t stats_jitter; |
||||
int32_t stats_transit; |
||||
int stats_cycles; |
||||
bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */ |
||||
}; |
||||
|
||||
struct mgcp_rtp_codec { |
||||
uint32_t rate; |
||||
int channels; |
||||
uint32_t frame_duration_num; |
||||
uint32_t frame_duration_den; |
||||
|
||||
int payload_type; |
||||
char *audio_name; |
||||
char *subtype_name; |
||||
}; |
||||
|
||||
struct mgcp_rtp_end { |
||||
/* statistics */ |
||||
unsigned int packets; |
||||
unsigned int octets; |
||||
unsigned int dropped_packets; |
||||
struct in_addr addr; |
||||
|
||||
/* in network byte order */ |
||||
int rtp_port, rtcp_port; |
||||
|
||||
/* audio codec information */ |
||||
struct mgcp_rtp_codec codec; |
||||
struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */ |
||||
|
||||
/* per endpoint data */ |
||||
int frames_per_packet; |
||||
uint32_t packet_duration_ms; |
||||
char *fmtp_extra; |
||||
int output_enabled; |
||||
int force_output_ptime; |
||||
|
||||
/* RTP patching */ |
||||
int force_constant_ssrc; /* -1: always, 0: don't, 1: once */ |
||||
int force_aligned_timing; |
||||
void *rtp_process_data; |
||||
|
||||
/*
|
||||
* Each end has a socket... |
||||
*/ |
||||
struct osmo_fd rtp; |
||||
struct osmo_fd rtcp; |
||||
|
||||
int local_port; |
||||
int local_alloc; |
||||
}; |
||||
|
||||
enum { |
||||
MGCP_TAP_BTS_IN, |
||||
MGCP_TAP_BTS_OUT, |
||||
MGCP_TAP_NET_IN, |
||||
MGCP_TAP_NET_OUT, |
||||
|
||||
/* last element */ |
||||
MGCP_TAP_COUNT |
||||
}; |
||||
|
||||
struct mgcp_rtp_tap { |
||||
int enabled; |
||||
struct sockaddr_in forward; |
||||
}; |
||||
|
||||
struct mgcp_lco { |
||||
char *string; |
||||
char *codec; |
||||
int pkt_period_min; /* time in ms */ |
||||
int pkt_period_max; /* time in ms */ |
||||
}; |
||||
|
||||
enum mgcp_type { |
||||
MGCP_RTP_DEFAULT = 0, |
||||
MGCP_RTP_TRANSCODED, |
||||
MGCP_OSMUX_BSC, |
||||
MGCP_OSMUX_BSC_NAT, |
||||
}; |
||||
|
||||
#include <openbsc/osmux.h> |
||||
|
||||
struct mgcp_endpoint { |
||||
int allocated; |
||||
uint32_t ci; |
||||
char *callid; |
||||
struct mgcp_lco local_options; |
||||
int conn_mode; |
||||
int orig_mode; |
||||
|
||||
/* backpointer */ |
||||
struct mgcp_config *cfg; |
||||
struct mgcp_trunk_config *tcfg; |
||||
|
||||
/* port status for bts/net */ |
||||
struct mgcp_rtp_end bts_end; |
||||
struct mgcp_rtp_end net_end; |
||||
|
||||
/*
|
||||
* For transcoding we will send from the local_port |
||||
* of trans_bts and it will arrive at trans_net from |
||||
* where we will forward it to the network. |
||||
*/ |
||||
struct mgcp_rtp_end trans_bts; |
||||
struct mgcp_rtp_end trans_net; |
||||
enum mgcp_type type; |
||||
|
||||
/* sequence bits */ |
||||
struct mgcp_rtp_state net_state; |
||||
struct mgcp_rtp_state bts_state; |
||||
|
||||
/* fields for re-transmission */ |
||||
char *last_trans; |
||||
char *last_response; |
||||
|
||||
/* tap for the endpoint */ |
||||
struct mgcp_rtp_tap taps[MGCP_TAP_COUNT]; |
||||
|
||||
struct { |
||||
/* Osmux state: disabled, activating, active */ |
||||
enum osmux_state state; |
||||
/* Allocated Osmux circuit ID for this endpoint */ |
||||
int allocated_cid; |
||||
/* Used Osmux circuit ID for this endpoint */ |
||||
uint8_t cid; |
||||
/* handle to batch messages */ |
||||
struct osmux_in_handle *in; |
||||
/* handle to unbatch messages */ |
||||
struct osmux_out_handle out; |
||||
/* statistics */ |
||||
struct { |
||||
uint32_t chunks; |
||||
uint32_t octets; |
||||
} stats; |
||||
} osmux; |
||||
}; |
||||
|
||||
#define for_each_line(line, save) \ |
||||
for (line = strline_r(NULL, &save); line;\
|
||||
line = strline_r(NULL, &save)) |
||||
|
||||
static inline char *strline_r(char *str, char **saveptr) |
||||
{ |
||||
char *result; |
||||
|
||||
if (str) |
||||
*saveptr = str; |
||||
|
||||
result = *saveptr; |
||||
|
||||
if (*saveptr != NULL) { |
||||
*saveptr = strpbrk(*saveptr, "\r\n"); |
||||
|
||||
if (*saveptr != NULL) { |
||||
char *eos = *saveptr; |
||||
|
||||
if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n') |
||||
(*saveptr)++; |
||||
(*saveptr)++; |
||||
if ((*saveptr)[0] == '\0') |
||||
*saveptr = NULL; |
||||
|
||||
*eos = '\0'; |
||||
} |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
|
||||
|
||||
#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints)) |
||||
|
||||
/**
|
||||
* Internal structure while parsing a request |
||||
*/ |
||||
struct mgcp_parse_data { |
||||
struct mgcp_config *cfg; |
||||
struct mgcp_endpoint *endp; |
||||
char *trans; |
||||
char *save; |
||||
int found; |
||||
}; |
||||
|
||||
int mgcp_send_dummy(struct mgcp_endpoint *endp); |
||||
int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port); |
||||
int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port); |
||||
int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port); |
||||
int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port); |
||||
int mgcp_free_rtp_port(struct mgcp_rtp_end *end); |
||||
|
||||
/* For transcoding we need to manage an in and an output that are connected */ |
||||
static inline int endp_back_channel(int endpoint) |
||||
{ |
||||
return endpoint + 60; |
||||
} |
||||
|
||||
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index); |
||||
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index); |
||||
|
||||
void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change, |
||||
struct mgcp_rtp_end *rtp); |
||||
uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp, |
||||
struct mgcp_rtp_end *rtp); |
||||
|
||||
void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *, |
||||
uint32_t *expected, int *loss); |
||||
uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *); |
||||
|
||||
/* payload processing default functions */ |
||||
int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end, |
||||
char *data, int *len, int buf_size); |
||||
|
||||
int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp, |
||||
struct mgcp_rtp_end *dst_end, |
||||
struct mgcp_rtp_end *src_end); |
||||
|
||||
void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp, |
||||
int *payload_type, |
||||
const char**subtype_name, |
||||
const char**fmtp_extra); |
||||
|
||||
/* internal RTP Annex A counting */ |
||||
void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state, |
||||
const uint16_t seq, const int32_t transit, |
||||
const uint32_t ssrc); |
||||
|
||||
int mgcp_set_ip_tos(int fd, int tos); |
||||
|
||||
enum { |
||||
MGCP_DEST_NET = 0, |
||||
MGCP_DEST_BTS, |
||||
}; |
||||
|
||||
|
||||
#define MGCP_DUMMY_LOAD 0x23 |
||||
|
||||
|
||||
/**
|
||||
* SDP related information |
||||
*/ |
||||
/* Assume audio frame length of 20ms */ |
||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20 |
||||
#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000 |
||||
#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20 |
||||
#define DEFAULT_RTP_AUDIO_DEFAULT_RATE 8000 |
||||
#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1 |
||||
|
||||
#define PTYPE_UNDEFINED (-1) |
||||
int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p); |
||||
int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec, |
||||
int payload_type, const char *audio_name); |
||||
|
||||
|
||||
/**
|
||||
* Internal network related |
||||
*/ |
||||
static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp) |
||||
{ |
||||
if (endp->cfg->net_ports.bind_addr) |
||||
return endp->cfg->net_ports.bind_addr; |
||||
return endp->cfg->source_addr; |
||||
} |
||||
|
||||
static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp) |
||||
{ |
||||
if (endp->cfg->bts_ports.bind_addr) |
||||
return endp->cfg->bts_ports.bind_addr; |
||||
return endp->cfg->source_addr; |
||||
} |
||||
|
||||
int mgcp_msg_terminate_nul(struct msgb *msg); |
@ -1,90 +0,0 @@ |
||||
/*
|
||||
* (C) 2014 by On-Waves |
||||
* All Rights Reserved |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as published by |
||||
* the Free Software Foundation; either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
*/ |
||||
#ifndef OPENBSC_MGCP_TRANSCODE_H |
||||
#define OPENBSC_MGCP_TRANSCODE_H |
||||
|
||||
#include "bscconfig.h" |
||||
|
||||
#include <gsm.h> |
||||
#ifdef HAVE_BCG729 |
||||
#include <bcg729/decoder.h> |
||||
#include <bcg729/encoder.h> |
||||
#endif |
||||
|
||||
enum audio_format { |
||||
AF_INVALID, |
||||
AF_S16, |
||||
AF_L16, |
||||
AF_GSM, |
||||
AF_G729, |
||||
AF_PCMA, |
||||
AF_PCMU |
||||
}; |
||||
|
||||
|
||||
struct mgcp_process_rtp_state { |
||||
/* decoding */ |
||||
enum audio_format src_fmt; |
||||
union { |
||||
gsm gsm_handle; |
||||
#ifdef HAVE_BCG729 |
||||
bcg729DecoderChannelContextStruct *g729_dec; |
||||
#endif |
||||
} src; |
||||
size_t src_frame_size; |
||||
size_t src_samples_per_frame; |
||||
|
||||
/* processing */ |
||||
|
||||
/* encoding */ |
||||
enum audio_format dst_fmt; |
||||
union { |
||||
gsm gsm_handle; |
||||
#ifdef HAVE_BCG729 |
||||
bcg729EncoderChannelContextStruct *g729_enc; |
||||
#endif |
||||
} dst; |
||||
size_t dst_frame_size; |
||||
size_t dst_samples_per_frame; |
||||
int dst_packet_duration; |
||||
|
||||
int is_running; |
||||
uint16_t next_seq; |
||||
uint32_t next_time; |
||||
int16_t samples[10*160]; |
||||
size_t sample_cnt; |
||||
size_t sample_offs; |
||||
}; |
||||
|
||||
|
||||
int mgcp_transcoding_setup(struct mgcp_endpoint *endp, |
||||
struct mgcp_rtp_end *dst_end, |
||||
struct mgcp_rtp_end *src_end); |
||||
|
||||
void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp, |
||||
int *payload_type, |
||||
const char**audio_name, |
||||
const char**fmtp_extra); |
||||
|
||||
int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp, |
||||
struct mgcp_rtp_end *dst_end, |
||||
char *data, int *len, int buf_size); |
||||
|
||||
int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst); |
||||
#endif /* OPENBSC_MGCP_TRANSCODE_H */ |
@ -1,111 +0,0 @@ |
||||
#pragma once |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include <osmocom/core/linuxlist.h> |
||||
#include <osmocom/core/write_queue.h> |
||||
|
||||
enum mgcp_connection_mode; |
||||
|
||||
struct msgb; |
||||
struct vty; |
||||
|
||||
#define MGCPGW_CLIENT_LOCAL_ADDR_DEFAULT "0.0.0.0" |
||||
#define MGCPGW_CLIENT_LOCAL_PORT_DEFAULT 0 |
||||
#define MGCPGW_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1" |
||||
#define MGCPGW_CLIENT_REMOTE_PORT_DEFAULT 2427 |
||||
|
||||
#define MSGB_CB_MGCP_TRANS_ID 0 |
||||
|
||||
typedef unsigned int mgcp_trans_id_t; |
||||
|
||||
struct mgcpgw_client_conf { |
||||
const char *local_addr; |
||||
int local_port; |
||||
const char *remote_addr; |
||||
int remote_port; |
||||
uint16_t first_endpoint; |
||||
uint16_t last_endpoint; |
||||
uint16_t bts_base; |
||||
}; |
||||
|
||||
struct mgcp_response_head { |
||||
int response_code; |
||||
mgcp_trans_id_t trans_id; |
||||
const char *comment; |
||||
}; |
||||
|
||||
struct mgcp_response { |
||||
char *body; |
||||
struct mgcp_response_head head; |
||||
uint16_t audio_port; |
||||
}; |
||||
|
||||
struct mgcpgw_client { |
||||
struct mgcpgw_client_conf actual; |
||||
uint32_t remote_addr; |
||||
struct osmo_wqueue wq; |
||||
mgcp_trans_id_t next_trans_id; |
||||
struct llist_head responses_pending; |
||||
struct llist_head inuse_endpoints; |
||||
}; |
||||
|
||||
struct mgcp_inuse_endpoint { |
||||
struct llist_head entry; |
||||
uint16_t id; |
||||
}; |
||||
|
||||
/* Invoked when an MGCP response is received or sending failed. When the
|
||||
* response is passed as NULL, this indicates failure during transmission. */ |
||||
typedef void (* mgcp_response_cb_t )(struct mgcp_response *response, void *priv); |
||||
|
||||
struct mgcp_response_pending { |
||||
struct llist_head entry; |
||||
|
||||
mgcp_trans_id_t trans_id; |
||||
mgcp_response_cb_t response_cb; |
||||
void *priv; |
||||
}; |
||||
|
||||
|
||||
void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf); |
||||
|
||||
struct mgcpgw_client *mgcpgw_client_init(void *ctx, |
||||
struct mgcpgw_client_conf *conf); |
||||
int mgcpgw_client_connect(struct mgcpgw_client *mgcp); |
||||
|
||||
const char *mgcpgw_client_remote_addr_str(struct mgcpgw_client *mgcp); |
||||
uint16_t mgcpgw_client_remote_port(struct mgcpgw_client *mgcp); |
||||
uint32_t mgcpgw_client_remote_addr_n(struct mgcpgw_client *mgcp); |
||||
|
||||
/* Find and seize an unsused endpoint id */ |
||||
int mgcpgw_client_next_endpoint(struct mgcpgw_client *client); |
||||
|
||||
/* Release a seized endpoint id to make it available again for other calls */ |
||||
void mgcpgw_client_release_endpoint(uint16_t id, struct mgcpgw_client *client); |
||||
|
||||
int mgcp_response_parse_params(struct mgcp_response *r); |
||||
|
||||
int mgcpgw_client_tx(struct mgcpgw_client *mgcp, struct msgb *msg, |
||||
mgcp_response_cb_t response_cb, void *priv); |
||||
|
||||
struct msgb *mgcp_msg_crcx(struct mgcpgw_client *mgcp, |
||||
uint16_t rtp_endpoint, unsigned int call_id, |
||||
enum mgcp_connection_mode mode); |
||||
|
||||
struct msgb *mgcp_msg_mdcx(struct mgcpgw_client *mgcp, |
||||
uint16_t rtp_endpoint, const char *rtp_conn_addr, |
||||
uint16_t rtp_port, enum mgcp_connection_mode mode); |
||||
|
||||
struct msgb *mgcp_msg_dlcx(struct mgcpgw_client *mgcp, uint16_t rtp_endpoint, |
||||
unsigned int call_id); |
||||
|
||||
void mgcpgw_client_vty_init(int node, struct mgcpgw_client_conf *conf); |
||||
int mgcpgw_client_config_write(struct vty *vty, const char *indent); |
||||
|
||||
struct mgcp_response_pending * mgcpgw_client_pending_add( |
||||
struct mgcpgw_client *mgcp, |
||||
mgcp_trans_id_t trans_id, |
||||
mgcp_response_cb_t response_cb, |
||||
void *priv); |
||||
int mgcpgw_client_rx(struct mgcpgw_client *mgcp, struct msgb *msg); |
@ -1,46 +0,0 @@ |
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_builddir) \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOVTY_CFLAGS) \
|
||||
$(LIBOSMONETIF_CFLAGS) \
|
||||
$(COVERAGE_CFLAGS) \
|
||||
$(LIBBCG729_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
AM_LDFLAGS = \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBOSMONETIF_LIBS) \
|
||||
$(COVERAGE_LDFLAGS) \
|
||||
$(LIBBCG729_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
noinst_LIBRARIES = \
|
||||
libmgcp.a \
|
||||
$(NULL)
|
||||
|
||||
noinst_HEADERS = \
|
||||
g711common.h \
|
||||
$(NULL)
|
||||
|
||||
libmgcp_a_SOURCES = \
|
||||
mgcp_common.c \
|
||||
mgcp_protocol.c \
|
||||
mgcp_network.c \
|
||||
mgcp_vty.c \
|
||||
mgcp_osmux.c \
|
||||
mgcp_sdp.c \
|
||||
mgcpgw_client.c \
|
||||
mgcpgw_client_vty.c \
|
||||
$(NULL)
|
||||
if BUILD_MGCP_TRANSCODING |
||||
libmgcp_a_SOURCES += \
|
||||
mgcp_transcode.c \
|
||||
$(NULL)
|
||||
endif |
@ -1,187 +0,0 @@ |
||||
/*
|
||||
* PCM - A-Law conversion |
||||
* Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> |
||||
* |
||||
* Wrapper for linphone Codec class by Simon Morlat <simon.morlat@linphone.org> |
||||
* |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation; either version 2 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
*/ |
||||
|
||||
static inline int val_seg(int val) |
||||
{ |
||||
int r = 0; |
||||
val >>= 7; /*7 = 4 + 3*/ |
||||
if (val & 0xf0) { |
||||
val >>= 4; |
||||
r += 4; |
||||
} |
||||
if (val & 0x0c) { |
||||
val >>= 2; |
||||
r += 2; |
||||
} |
||||
if (val & 0x02) |
||||
r += 1; |
||||
return r; |
||||
} |
||||
|
||||
/*
|
||||
* s16_to_alaw() - Convert a 16-bit linear PCM value to 8-bit A-law |
||||
* |
||||
* s16_to_alaw() accepts an 16-bit integer and encodes it as A-law data. |
||||
* |
||||
* Linear Input Code Compressed Code |
||||
* ------------------------ --------------- |
||||
* 0000000wxyza 000wxyz |
||||
* 0000001wxyza 001wxyz |
||||
* 000001wxyzab 010wxyz |
||||
* 00001wxyzabc 011wxyz |
||||
* 0001wxyzabcd 100wxyz |
||||
* 001wxyzabcde 101wxyz |
||||
* 01wxyzabcdef 110wxyz |
||||
* 1wxyzabcdefg 111wxyz |
||||
* |
||||
* For further information see John C. Bellamy's Digital Telephony, 1982, |
||||
* John Wiley & Sons, pps 98-111 and 472-476. |
||||
* G711 is designed for 13 bits input signal, this function add extra shifting to take this into account. |
||||
*/ |
||||
|
||||
static inline unsigned char s16_to_alaw(int pcm_val) |
||||
{ |
||||
int mask; |
||||
int seg; |
||||
unsigned char aval; |
||||
|
||||
if (pcm_val >= 0) { |
||||
mask = 0xD5; |
||||
} else { |
||||
mask = 0x55; |
||||
pcm_val = -pcm_val; |
||||
if (pcm_val > 0x7fff) |
||||
pcm_val = 0x7fff; |
||||
} |
||||
|
||||
if (pcm_val < 256) /*256 = 32 << 3*/ |
||||
aval = pcm_val >> 4; /*4 = 1 + 3*/ |
||||
else { |
||||
/* Convert the scaled magnitude to segment number. */ |
||||
seg = val_seg(pcm_val); |
||||
aval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f); |
||||
} |
||||
return aval ^ mask; |
||||
} |
||||
|
||||
/*
|
||||
* alaw_to_s16() - Convert an A-law value to 16-bit linear PCM |
||||
* |
||||
*/ |
||||
static inline int alaw_to_s16(unsigned char a_val) |
||||
{ |
||||
int t; |
||||
int seg; |
||||
|
||||
a_val ^= 0x55; |
||||
t = a_val & 0x7f; |
||||
if (t < 16) |
||||
t = (t << 4) + 8; |
||||
else { |
||||
seg = (t >> 4) & 0x07; |
||||
t = ((t & 0x0f) << 4) + 0x108; |
||||
t <<= seg -1; |
||||
} |
||||
return ((a_val & 0x80) ? t : -t); |
||||
} |
||||
/*
|
||||
* s16_to_ulaw() - Convert a linear PCM value to u-law |
||||
* |
||||
* In order to simplify the encoding process, the original linear magnitude |
||||
* is biased by adding 33 which shifts the encoding range from (0 - 8158) to |
||||
* (33 - 8191). The result can be seen in the following encoding table: |
||||
* |
||||
* Biased Linear Input Code Compressed Code |
||||
* ------------------------ --------------- |
||||
* 00000001wxyza 000wxyz |
||||
* 0000001wxyzab 001wxyz |
||||
* 000001wxyzabc 010wxyz |
||||
* 00001wxyzabcd 011wxyz |
||||
* 0001wxyzabcde 100wxyz |
||||
* 001wxyzabcdef 101wxyz |
||||
* 01wxyzabcdefg 110wxyz |
||||
* 1wxyzabcdefgh 111wxyz |
||||
* |
||||
* Each biased linear code has a leading 1 which identifies the segment |
||||
* number. The value of the segment number is equal to 7 minus the number |
||||
* of leading 0's. The quantization interval is directly available as the |
||||
* four bits wxyz. * The trailing bits (a - h) are ignored. |
||||
* |
||||
* Ordinarily the complement of the resulting code word is used for |
||||
* transmission, and so the code word is complemented before it is returned. |
||||
* |
||||
* For further information see John C. Bellamy's Digital Telephony, 1982, |
||||
* John Wiley & Sons, pps 98-111 and 472-476. |
||||
*/ |
||||
|
||||
static inline unsigned char s16_to_ulaw(int pcm_val) /* 2's complement (16-bit range) */ |
||||
{ |
||||
int mask; |
||||
int seg; |
||||
unsigned char uval; |
||||
|
||||
if (pcm_val < 0) { |
||||
pcm_val = 0x84 - pcm_val; |
||||
mask = 0x7f; |
||||
} else { |
||||
pcm_val += 0x84; |
||||
mask = 0xff; |
||||
} |
||||
if (pcm_val > 0x7fff) |
||||
pcm_val = 0x7fff; |
||||
|
||||
/* Convert the scaled magnitude to segment number. */ |
||||
seg = val_seg(pcm_val); |
||||
|
||||
/*
|
||||
* Combine the sign, segment, quantization bits; |
||||
* and complement the code word. |
||||
*/ |
||||
uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f); |
||||
return uval ^ mask; |
||||
} |
||||
|
||||
/*
|
||||
* ulaw_to_s16() - Convert a u-law value to 16-bit linear PCM |
||||
* |
||||
* First, a biased linear code is derived from the code word. An unbiased |
||||
* output can then be obtained by subtracting 33 from the biased code. |
||||
* |
||||
* Note that this function expects to be passed the complement of the |
||||
* original code word. This is in keeping with ISDN conventions. |
||||
*/ |
||||
static inline int ulaw_to_s16(unsigned char u_val) |
||||
{ |
||||
int t; |
||||
|
||||
/* Complement to obtain normal u-law value. */ |
||||
u_val = ~u_val; |
||||
|
||||
/*
|
||||
* Extract and bias the quantization bits. Then |
||||
* shift up by the segment number and subtract out the bias. |
||||
*/ |
||||
t = ((u_val & 0x0f) << 3) + 0x84; |
||||
t <<= (u_val & 0x70) >> 4; |
||||
|
||||
return ((u_val & 0x80) ? (0x84 - t) : (t - 0x84)); |
||||
} |
@ -1,54 +0,0 @@ |
||||
/* Media Gateway Control Protocol Media Gateway: RFC 3435 */ |
||||
/* Implementations useful both for the MGCP GW as well as MGCP GW clients */ |
||||
|
||||
/*
|
||||
* (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de> |
||||
* All Rights Reserved |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as published by |
||||
* the Free Software Foundation; either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
*/ |
||||
|
||||
#include <errno.h> |
||||
|
||||
#include <osmocom/core/utils.h> |
||||
#include <openbsc/mgcp.h> |
||||
|
||||
const struct value_string mgcp_connection_mode_strs[] = { |
||||
{ MGCP_CONN_NONE, "none" }, |
||||
{ MGCP_CONN_RECV_SEND, "sendrecv" }, |
||||
{ MGCP_CONN_SEND_ONLY, "sendonly" }, |
||||
{ MGCP_CONN_RECV_ONLY, "recvonly" }, |
||||
{ MGCP_CONN_LOOPBACK, "loopback" }, |
||||
{ 0, NULL } |
||||
}; |
||||
|
||||
/* Ensure that the msg->l2h is NUL terminated. */ |
||||
int mgcp_msg_terminate_nul(struct msgb *msg) |
||||
{ |
||||
unsigned char *tail = msg->l2h + msgb_l2len(msg); /* char after l2 data */ |
||||
if (tail[-1] == '\0') |
||||
/* nothing to do */; |
||||
else if (msgb_tailroom(msg) > 0) |
||||
tail[0] = '\0'; |
||||
else if (tail[-1] == '\r' || tail[-1] == '\n') |
||||
tail[-1] = '\0'; |
||||
else { |
||||
LOGP(DMGCP, LOGL_ERROR, "Cannot NUL terminate MGCP message: " |
||||
"Length: %d, Buffer size: %d\n", |
||||
msgb_l2len(msg), msg->data_len); |
||||
return -ENOTSUP; |
||||
} |
||||
return 0; |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,583 +0,0 @@ |
||||
/*
|
||||
* (C) 2012-2013 by Pablo Neira Ayuso <pablo@gnumonks.org> |
||||
* (C) 2012-2013 by On Waves ehf <http://www.on-waves.com>
|
||||
* All rights not specifically granted under this license are reserved. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify it |
||||
* under the terms of the GNU Affero General Public License as published by the |
||||
* Free Software Foundation; either version 3 of the License, or (at your |
||||
* option) any later version. |
||||
*/ |
||||
|
||||
#include <stdio.h> /* for printf */ |
||||
#include <string.h> /* for memcpy */ |
||||
#include <stdlib.h> /* for abs */ |
||||
#include <inttypes.h> /* for PRIu64 */ |
||||
#include <netinet/in.h> |
||||
#include <osmocom/core/msgb.h> |
||||
#include <osmocom/core/talloc.h> |
||||
|
||||
#include <osmocom/netif/osmux.h> |
||||
#include <osmocom/netif/rtp.h> |
||||
|
||||
#include <openbsc/mgcp.h> |
||||
#include <openbsc/mgcp_internal.h> |
||||
#include <openbsc/osmux.h> |
||||
|
||||
static struct osmo_fd osmux_fd; |
||||
|
||||
static LLIST_HEAD(osmux_handle_list); |
||||
|
||||
struct osmux_handle { |
||||
struct llist_head head; |
||||
struct osmux_in_handle *in; |
||||
struct in_addr rem_addr; |
||||
int rem_port; |
||||
int refcnt; |
||||
}; |
||||
|
||||
static void *osmux; |
||||
|
||||
static void osmux_deliver(struct msgb *batch_msg, void *data) |
||||
{ |
||||
struct osmux_handle *handle = data; |
||||
struct sockaddr_in out = { |
||||
.sin_family = AF_INET, |
||||
.sin_port = handle->rem_port, |
||||
}; |
||||
|
||||
memcpy(&out.sin_addr, &handle->rem_addr, sizeof(handle->rem_addr)); |
||||
sendto(osmux_fd.fd, batch_msg->data, batch_msg->len, 0, |
||||
(struct sockaddr *)&out, sizeof(out)); |
||||
msgb_free(batch_msg); |
||||
} |
||||
|
||||
static struct osmux_handle * |
||||
osmux_handle_find_get(struct in_addr *addr, int rem_port) |
||||
{ |
||||
struct osmux_handle *h; |
||||
|
||||
/* Lookup for existing OSMUX handle for this destination address. */ |
||||
llist_for_each_entry(h, &osmux_handle_list, head) { |
||||
if (memcmp(&h->rem_addr, addr, sizeof(struct in_addr)) == 0 && |
||||
h->rem_port == rem_port) { |
||||
LOGP(DMGCP, LOGL_DEBUG, "using existing OSMUX handle " |
||||
"for addr=%s:%d\n", |
||||
inet_ntoa(*addr), ntohs(rem_port)); |
||||
h->refcnt++; |
||||
return h; |
||||
} |
||||
} |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
static void osmux_handle_put(struct osmux_in_handle *in) |
||||
{ |
||||
struct osmux_handle *h; |
||||
|
||||
/* Lookup for existing OSMUX handle for this destination address. */ |
||||
llist_for_each_entry(h, &osmux_handle_list, head) { |
||||
if (h->in == in) { |
||||
if (--h->refcnt == 0) { |
||||
LOGP(DMGCP, LOGL_INFO, |
||||
"Releasing unused osmux handle for %s:%d\n", |
||||
inet_ntoa(h->rem_addr), |
||||
ntohs(h->rem_port)); |
||||
LOGP(DMGCP, LOGL_INFO, "Stats: " |
||||
"input RTP msgs: %u bytes: %"PRIu64" " |
||||
"output osmux msgs: %u bytes: %"PRIu64"\n", |
||||
in->stats.input_rtp_msgs, |
||||
in->stats.input_rtp_bytes, |
||||
in->stats.output_osmux_msgs, |
||||
in->stats.output_osmux_bytes); |
||||
llist_del(&h->head); |
||||
osmux_xfrm_input_fini(h->in); |
||||
talloc_free(h); |
||||
} |
||||
return |