Remove dead code left over from NITB split
There still is a lot of dead code that we inherited from the NITB days, let's remove more of it. libtrau will be re-introduced as part of osmo-mgw later. Change-Id: I8e0af56a158f25a4f1384d667c03eb20e72df5b8
This commit is contained in:
parent
f8dc526207
commit
d9956d91ba
|
@ -145,7 +145,6 @@ AC_OUTPUT(
|
|||
include/osmocom/Makefile
|
||||
include/osmocom/bsc/Makefile
|
||||
src/Makefile
|
||||
src/libtrau/Makefile
|
||||
src/libbsc/Makefile
|
||||
src/libcommon/Makefile
|
||||
src/libfilter/Makefile
|
||||
|
@ -161,7 +160,6 @@ AC_OUTPUT(
|
|||
tests/bsc-nat/Makefile
|
||||
tests/bsc-nat-trie/Makefile
|
||||
tests/abis/Makefile
|
||||
tests/trau/Makefile
|
||||
tests/subscr/Makefile
|
||||
tests/nanobts_omlattr/Makefile
|
||||
tests/bssap/Makefile
|
||||
|
|
|
@ -4,7 +4,6 @@ noinst_HEADERS = \
|
|||
abis_om2000.h \
|
||||
abis_rsl.h \
|
||||
arfcn_range_encode.h \
|
||||
auth.h \
|
||||
bsc_msc.h \
|
||||
bsc_msg_filter.h \
|
||||
bsc_nat.h \
|
||||
|
@ -18,7 +17,6 @@ noinst_HEADERS = \
|
|||
common.h \
|
||||
common_bsc.h \
|
||||
common_cs.h \
|
||||
crc24.h \
|
||||
ctrl.h \
|
||||
debug.h \
|
||||
e1_config.h \
|
||||
|
@ -26,16 +24,12 @@ noinst_HEADERS = \
|
|||
gsm_04_80.h \
|
||||
gsm_data.h \
|
||||
gsm_data_shared.h \
|
||||
gsm_subscriber.h \
|
||||
handover.h \
|
||||
handover_decision.h \
|
||||
ipaccess.h \
|
||||
meas_feed.h \
|
||||
meas_rep.h \
|
||||
misdn.h \
|
||||
mncc.h \
|
||||
mncc_int.h \
|
||||
msc_ifaces.h \
|
||||
nat_rewrite_trie.h \
|
||||
network_listen.h \
|
||||
openbscdefines.h \
|
||||
|
@ -52,15 +46,9 @@ noinst_HEADERS = \
|
|||
rest_octets.h \
|
||||
rrlp.h \
|
||||
rs232.h \
|
||||
rtp_proxy.h \
|
||||
signal.h \
|
||||
silent_call.h \
|
||||
sms_queue.h \
|
||||
socket.h \
|
||||
system_information.h \
|
||||
transaction.h \
|
||||
trau_mux.h \
|
||||
trau_upqueue.h \
|
||||
ussd.h \
|
||||
vty.h \
|
||||
bsc_api.h \
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef _AUTH_H
|
||||
#define _AUTH_H
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
struct gsm_auth_tuple;
|
||||
|
||||
enum auth_action {
|
||||
AUTH_ERROR = -1, /* Internal error */
|
||||
AUTH_NOT_AVAIL = 0, /* No auth tuple available */
|
||||
AUTH_DO_AUTH_THEN_CIPH = 1, /* Firsth authenticate, then cipher */
|
||||
AUTH_DO_CIPH = 2, /* Only ciphering */
|
||||
AUTH_DO_AUTH = 3, /* Only authentication, no ciphering */
|
||||
};
|
||||
|
||||
extern const struct value_string auth_action_names[];
|
||||
static inline const char *auth_action_str(enum auth_action a)
|
||||
{
|
||||
return get_value_string(auth_action_names, a);
|
||||
}
|
||||
|
||||
#endif /* _AUTH_H */
|
|
@ -6,7 +6,7 @@
|
|||
struct msgb;
|
||||
|
||||
/* start and stop network */
|
||||
extern int bsc_network_alloc(mncc_recv_cb_t mncc_recv);
|
||||
extern int bsc_network_alloc(void);
|
||||
extern int bsc_network_configure(const char *cfg_file);
|
||||
extern int bsc_shutdown_net(struct gsm_network *net);
|
||||
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
|
||||
struct gsm_subscriber_connection;
|
||||
|
||||
/* Find an allocated channel for a specified subscriber */
|
||||
struct gsm_subscriber_connection *connection_for_subscr(struct vlr_subscr *vsub);
|
||||
|
||||
/* Allocate a logical channel (SDCCH, TCH, ...) */
|
||||
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type, int allow_bigger);
|
||||
|
||||
|
|
|
@ -5,5 +5,4 @@
|
|||
|
||||
struct gsm_network *bsc_network_init(void *ctx,
|
||||
uint16_t country_code,
|
||||
uint16_t network_code,
|
||||
mncc_recv_cb_t mncc_recv);
|
||||
uint16_t network_code);
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
struct msgb;
|
||||
struct gsm_network;
|
||||
|
||||
typedef int (*mncc_recv_cb_t)(struct gsm_network *, struct msgb *);
|
||||
|
||||
struct vty;
|
||||
|
||||
#define MAX_A5_KEY_LEN (128/8)
|
||||
|
@ -20,8 +18,7 @@ struct gsm_encr {
|
|||
|
||||
struct gsm_network *gsm_network_init(void *ctx,
|
||||
uint16_t country_code,
|
||||
uint16_t network_code,
|
||||
mncc_recv_cb_t mncc_recv);
|
||||
uint16_t network_code);
|
||||
|
||||
int common_cs_vty_init(struct gsm_network *network,
|
||||
int (* config_write_net )(struct vty *));
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef _CRC24_H
|
||||
#define _CRC24_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define INIT_CRC24 0xffffff
|
||||
|
||||
uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len);
|
||||
|
||||
#endif
|
|
@ -24,11 +24,9 @@
|
|||
|
||||
#define OBSC_NM_W_ACK_CB(__msgb) (__msgb)->cb[3]
|
||||
|
||||
struct mncc_sock_state;
|
||||
struct gsm_subscriber_group;
|
||||
struct bsc_subscr;
|
||||
struct vlr_instance;
|
||||
struct vlr_subscr;
|
||||
struct gprs_ra_id;
|
||||
|
||||
#define OBSC_LINKID_CB(__msgb) (__msgb)->cb[3]
|
||||
|
@ -107,42 +105,15 @@ struct gsm_subscriber_connection {
|
|||
/* global linked list of subscriber_connections */
|
||||
struct llist_head entry;
|
||||
|
||||
/* usage count. If this drops to zero, we start the release
|
||||
* towards A/Iu */
|
||||
uint32_t use_count;
|
||||
|
||||
/* The MS has opened the conn with a CM Service Request, and we shall
|
||||
* keep it open for an actual request (or until timeout). */
|
||||
bool received_cm_service_request;
|
||||
|
||||
/* libbsc subscriber information (if available) */
|
||||
struct bsc_subscr *bsub;
|
||||
|
||||
/* libmsc/libvlr subscriber information (if available) */
|
||||
struct vlr_subscr *vsub;
|
||||
|
||||
/* LU expiration handling */
|
||||
uint8_t expire_timer_stopped;
|
||||
/* SMS helpers for libmsc */
|
||||
uint8_t next_rp_ref;
|
||||
|
||||
struct osmo_fsm_inst *conn_fsm;
|
||||
|
||||
/* Are we part of a special "silent" call */
|
||||
int silent_call;
|
||||
|
||||
/* MNCC rtp bridge markers */
|
||||
int mncc_rtp_bridge;
|
||||
int mncc_rtp_create_pending;
|
||||
int mncc_rtp_connect_pending;
|
||||
|
||||
/* bsc structures */
|
||||
struct osmo_bsc_sccp_con *sccp_con; /* BSC */
|
||||
|
||||
/* back pointers */
|
||||
struct gsm_network *network;
|
||||
|
||||
bool in_release;
|
||||
struct gsm_lchan *lchan; /* BSC */
|
||||
struct gsm_lchan *ho_lchan; /* BSC */
|
||||
struct gsm_bts *bts; /* BSC */
|
||||
|
@ -151,9 +122,6 @@ struct gsm_subscriber_connection {
|
|||
struct osmo_timer_list T10; /* BSC */
|
||||
struct gsm_lchan *secondary_lchan; /* BSC */
|
||||
|
||||
/* connected via 2G or 3G? */
|
||||
enum ran_type via_ran;
|
||||
|
||||
struct gsm_classmark classmark;
|
||||
|
||||
uint16_t lac;
|
||||
|
@ -336,10 +304,6 @@ struct gsm_network {
|
|||
struct rate_ctr_group *bsc_ctrs;
|
||||
struct osmo_counter *active_calls;
|
||||
|
||||
/* layer 4 */
|
||||
struct mncc_sock_state *mncc_state;
|
||||
mncc_recv_cb_t mncc_recv;
|
||||
struct llist_head upqueue;
|
||||
/*
|
||||
* TODO: Move the trans_list into the subscriber connection and
|
||||
* create a pending list for MT transactions. These exist before
|
||||
|
@ -381,8 +345,6 @@ struct gsm_network {
|
|||
/* MSC data in case we are a true BSC */
|
||||
struct osmo_bsc_data *bsc_data;
|
||||
|
||||
struct gsm_sms_queue *sms_queue;
|
||||
|
||||
/* control interface */
|
||||
struct ctrl_handle *ctrl;
|
||||
|
||||
|
@ -451,7 +413,6 @@ struct gsm_sms_addr {
|
|||
|
||||
struct gsm_sms {
|
||||
unsigned long long id;
|
||||
struct vlr_subscr *receiver;
|
||||
struct gsm_sms_addr src, dst;
|
||||
enum gsm_sms_source_id source;
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
struct osmo_bsc_data;
|
||||
|
||||
struct osmo_bsc_sccp_con;
|
||||
struct gsm_sms_queue;
|
||||
|
||||
/* RRLP mode of operation */
|
||||
enum rrlp_mode {
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
#ifndef _GSM_SUBSCR_H
|
||||
#define _GSM_SUBSCR_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
|
||||
#define GSM_NAME_LENGTH 160
|
||||
|
||||
#define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */
|
||||
#define GSM_MIN_EXTEN 20000
|
||||
#define GSM_MAX_EXTEN 49999
|
||||
|
||||
#define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001
|
||||
/* gprs_sgsn.h defines additional flags including and above bit 16 (0x10000) */
|
||||
|
||||
#define GSM_SUBSCRIBER_NO_EXPIRATION 0x0
|
||||
|
||||
enum gsm_subscriber_field {
|
||||
GSM_SUBSCRIBER_IMSI,
|
||||
GSM_SUBSCRIBER_TMSI,
|
||||
GSM_SUBSCRIBER_EXTENSION,
|
||||
GSM_SUBSCRIBER_ID,
|
||||
};
|
||||
|
||||
enum gsm_subscriber_update_reason {
|
||||
GSM_SUBSCRIBER_UPDATE_ATTACHED,
|
||||
GSM_SUBSCRIBER_UPDATE_DETACHED,
|
||||
GSM_SUBSCRIBER_UPDATE_EQUIPMENT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct for pending channel requests. This is managed in the
|
||||
* llist_head requests of each subscriber. The reference counting
|
||||
* should work in such a way that a subscriber with a pending request
|
||||
* remains in memory.
|
||||
*/
|
||||
struct subscr_request {
|
||||
struct llist_head entry;
|
||||
|
||||
/* human readable label to be able to log pending request kinds */
|
||||
const char *label;
|
||||
|
||||
/* the callback data */
|
||||
gsm_cbfn *cbfn;
|
||||
void *param;
|
||||
};
|
||||
|
||||
int subscr_update(struct vlr_subscr *vsub, int reason);
|
||||
|
||||
/*
|
||||
* Paging handling with authentication
|
||||
*/
|
||||
struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub,
|
||||
gsm_cbfn *cbfn, void *param,
|
||||
const char *label);
|
||||
|
||||
void subscr_remove_request(struct subscr_request *req);
|
||||
int subscr_rx_paging_response(struct msgb *msg,
|
||||
struct gsm_subscriber_connection *conn);
|
||||
|
||||
int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
|
||||
struct msgb *msg, void *data, void *param);
|
||||
|
||||
#endif /* _GSM_SUBSCR_H */
|
|
@ -2,11 +2,13 @@
|
|||
#define _IPACCESS_H
|
||||
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
#include "gsm_subscriber.h"
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/protocol/ipaccess.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
struct gsm_bts;
|
||||
struct gsm_bts_trx;
|
||||
|
||||
struct ipac_msgt_sccp_state {
|
||||
uint8_t src_ref[3];
|
||||
uint8_t dst_ref[3];
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
|
||||
* 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
|
||||
|
||||
/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
*
|
||||
* 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 _MNCC_H
|
||||
#define _MNCC_H
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/mncc.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct gsm_network;
|
||||
struct msgb;
|
||||
|
||||
|
||||
/* One end of a call */
|
||||
struct gsm_call {
|
||||
struct llist_head entry;
|
||||
|
||||
/* network handle */
|
||||
void *net;
|
||||
|
||||
/* the 'local' transaction */
|
||||
uint32_t callref;
|
||||
/* the 'remote' transaction */
|
||||
uint32_t remote_ref;
|
||||
};
|
||||
|
||||
#define MNCC_SETUP_REQ 0x0101
|
||||
#define MNCC_SETUP_IND 0x0102
|
||||
#define MNCC_SETUP_RSP 0x0103
|
||||
#define MNCC_SETUP_CNF 0x0104
|
||||
#define MNCC_SETUP_COMPL_REQ 0x0105
|
||||
#define MNCC_SETUP_COMPL_IND 0x0106
|
||||
/* MNCC_REJ_* is perfomed via MNCC_REL_* */
|
||||
#define MNCC_CALL_CONF_IND 0x0107
|
||||
#define MNCC_CALL_PROC_REQ 0x0108
|
||||
#define MNCC_PROGRESS_REQ 0x0109
|
||||
#define MNCC_ALERT_REQ 0x010a
|
||||
#define MNCC_ALERT_IND 0x010b
|
||||
#define MNCC_NOTIFY_REQ 0x010c
|
||||
#define MNCC_NOTIFY_IND 0x010d
|
||||
#define MNCC_DISC_REQ 0x010e
|
||||
#define MNCC_DISC_IND 0x010f
|
||||
#define MNCC_REL_REQ 0x0110
|
||||
#define MNCC_REL_IND 0x0111
|
||||
#define MNCC_REL_CNF 0x0112
|
||||
#define MNCC_FACILITY_REQ 0x0113
|
||||
#define MNCC_FACILITY_IND 0x0114
|
||||
#define MNCC_START_DTMF_IND 0x0115
|
||||
#define MNCC_START_DTMF_RSP 0x0116
|
||||
#define MNCC_START_DTMF_REJ 0x0117
|
||||
#define MNCC_STOP_DTMF_IND 0x0118
|
||||
#define MNCC_STOP_DTMF_RSP 0x0119
|
||||
#define MNCC_MODIFY_REQ 0x011a
|
||||
#define MNCC_MODIFY_IND 0x011b
|
||||
#define MNCC_MODIFY_RSP 0x011c
|
||||
#define MNCC_MODIFY_CNF 0x011d
|
||||
#define MNCC_MODIFY_REJ 0x011e
|
||||
#define MNCC_HOLD_IND 0x011f
|
||||
#define MNCC_HOLD_CNF 0x0120
|
||||
#define MNCC_HOLD_REJ 0x0121
|
||||
#define MNCC_RETRIEVE_IND 0x0122
|
||||
#define MNCC_RETRIEVE_CNF 0x0123
|
||||
#define MNCC_RETRIEVE_REJ 0x0124
|
||||
#define MNCC_USERINFO_REQ 0x0125
|
||||
#define MNCC_USERINFO_IND 0x0126
|
||||
#define MNCC_REJ_REQ 0x0127
|
||||
#define MNCC_REJ_IND 0x0128
|
||||
|
||||
#define MNCC_BRIDGE 0x0200
|
||||
#define MNCC_FRAME_RECV 0x0201
|
||||
#define MNCC_FRAME_DROP 0x0202
|
||||
#define MNCC_LCHAN_MODIFY 0x0203
|
||||
#define MNCC_RTP_CREATE 0x0204
|
||||
#define MNCC_RTP_CONNECT 0x0205
|
||||
#define MNCC_RTP_FREE 0x0206
|
||||
|
||||
#define GSM_TCHF_FRAME 0x0300
|
||||
#define GSM_TCHF_FRAME_EFR 0x0301
|
||||
#define GSM_TCHH_FRAME 0x0302
|
||||
#define GSM_TCH_FRAME_AMR 0x0303
|
||||
#define GSM_BAD_FRAME 0x03ff
|
||||
|
||||
#define MNCC_SOCKET_HELLO 0x0400
|
||||
|
||||
#define GSM_MAX_FACILITY 128
|
||||
#define GSM_MAX_SSVERSION 128
|
||||
#define GSM_MAX_USERUSER 128
|
||||
|
||||
#define MNCC_F_BEARER_CAP 0x0001
|
||||
#define MNCC_F_CALLED 0x0002
|
||||
#define MNCC_F_CALLING 0x0004
|
||||
#define MNCC_F_REDIRECTING 0x0008
|
||||
#define MNCC_F_CONNECTED 0x0010
|
||||
#define MNCC_F_CAUSE 0x0020
|
||||
#define MNCC_F_USERUSER 0x0040
|
||||
#define MNCC_F_PROGRESS 0x0080
|
||||
#define MNCC_F_EMERGENCY 0x0100
|
||||
#define MNCC_F_FACILITY 0x0200
|
||||
#define MNCC_F_SSVERSION 0x0400
|
||||
#define MNCC_F_CCCAP 0x0800
|
||||
#define MNCC_F_KEYPAD 0x1000
|
||||
#define MNCC_F_SIGNAL 0x2000
|
||||
|
||||
struct gsm_mncc {
|
||||
/* context based information */
|
||||
uint32_t msg_type;
|
||||
uint32_t callref;
|
||||
|
||||
/* which fields are present */
|
||||
uint32_t fields;
|
||||
|
||||
/* data derived informations (MNCC_F_ based) */
|
||||
struct gsm_mncc_bearer_cap bearer_cap;
|
||||
struct gsm_mncc_number called;
|
||||
struct gsm_mncc_number calling;
|
||||
struct gsm_mncc_number redirecting;
|
||||
struct gsm_mncc_number connected;
|
||||
struct gsm_mncc_cause cause;
|
||||
struct gsm_mncc_progress progress;
|
||||
struct gsm_mncc_useruser useruser;
|
||||
struct gsm_mncc_facility facility;
|
||||
struct gsm_mncc_cccap cccap;
|
||||
struct gsm_mncc_ssversion ssversion;
|
||||
struct {
|
||||
int sup;
|
||||
int inv;
|
||||
} clir;
|
||||
int signal;
|
||||
|
||||
/* data derived information, not MNCC_F based */
|
||||
int keypad;
|
||||
int more;
|
||||
int notify; /* 0..127 */
|
||||
int emergency;
|
||||
char imsi[16];
|
||||
};
|
||||
|
||||
struct gsm_data_frame {
|
||||
uint32_t msg_type;
|
||||
uint32_t callref;
|
||||
unsigned char data[0];
|
||||
};
|
||||
|
||||
#define MNCC_SOCK_VERSION 5
|
||||
struct gsm_mncc_hello {
|
||||
uint32_t msg_type;
|
||||
uint32_t version;
|
||||
|
||||
/* send the sizes of the structs */
|
||||
uint32_t mncc_size;
|
||||
uint32_t data_frame_size;
|
||||
|
||||
/* send some offsets */
|
||||
uint32_t called_offset;
|
||||
uint32_t signal_offset;
|
||||
uint32_t emergency_offset;
|
||||
};
|
||||
|
||||
struct gsm_mncc_rtp {
|
||||
uint32_t msg_type;
|
||||
uint32_t callref;
|
||||
uint32_t ip;
|
||||
uint16_t port;
|
||||
uint32_t payload_type;
|
||||
uint32_t payload_msg_type;
|
||||
};
|
||||
|
||||
struct gsm_mncc_bridge {
|
||||
uint32_t msg_type;
|
||||
uint32_t callref[2];
|
||||
};
|
||||
|
||||
const char *get_mncc_name(int value);
|
||||
void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
|
||||
void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
|
||||
|
||||
/* input from CC code into mncc_builtin */
|
||||
int int_mncc_recv(struct gsm_network *net, struct msgb *msg);
|
||||
|
||||
/* input from CC code into mncc_sock */
|
||||
int mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg);
|
||||
|
||||
int mncc_sock_init(struct gsm_network *net, const char *sock_path);
|
||||
|
||||
#define mncc_is_data_frame(msg_type) \
|
||||
(msg_type == GSM_TCHF_FRAME \
|
||||
|| msg_type == GSM_TCHF_FRAME_EFR \
|
||||
|| msg_type == GSM_TCHH_FRAME \
|
||||
|| msg_type == GSM_TCH_FRAME_AMR \
|
||||
|| msg_type == GSM_BAD_FRAME)
|
||||
|
||||
|
||||
#endif
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef _MNCC_INT_H
|
||||
#define _MNCC_INT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct mncc_int {
|
||||
uint8_t def_codec[2];
|
||||
};
|
||||
|
||||
extern struct mncc_int mncc_int;
|
||||
|
||||
uint8_t mncc_codec_for_mode(int lchan_type);
|
||||
|
||||
#endif
|
|
@ -1,42 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
|
||||
/* These are the interfaces of the MSC layer towards (from?) the BSC and RNC,
|
||||
* i.e. in the direction towards the mobile device (MS aka UE).
|
||||
*
|
||||
* 2G will use the A-interface,
|
||||
* 3G aka UMTS will use the Iu-interface (for the MSC, it's IuCS).
|
||||
*
|
||||
* To allow linking parts of the MSC code without having to include entire
|
||||
* infrastructures of external libraries, the core transmitting and receiving
|
||||
* functions are left unimplemented. For example, a unit test does not need to
|
||||
* link against external ASN1 libraries if it is never going to encode actual
|
||||
* outgoing messages. It is up to each building scope to implement real world
|
||||
* functions or to plug mere dummy implementations.
|
||||
*
|
||||
* For example, msc_tx_dtap(conn, msg), depending on conn->via_iface, will call
|
||||
* either iu_tx() or a_tx() [note: at time of writing, the A-interface is not
|
||||
* yet implemented]. When you try to link against libmsc, you will find that
|
||||
* the compiler complains about an undefined reference to iu_tx(). If you,
|
||||
* however, link against libiu as well as the osmo-iuh libs (etc.), iu_tx() is
|
||||
* available. A unit test may instead simply implement a dummy iu_tx() function
|
||||
* and not link against osmo-iuh, see tests/libiudummy/.
|
||||
*/
|
||||
|
||||
/* Each main linkage must implement this function (see comment above). */
|
||||
extern int iu_tx(struct msgb *msg, uint8_t sapi);
|
||||
|
||||
int msc_tx_dtap(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg);
|
||||
|
||||
int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn);
|
||||
int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
|
||||
enum gsm48_reject_value value);
|
||||
|
||||
int msc_tx_common_id(struct gsm_subscriber_connection *conn);
|
||||
int msc_call_assignment(struct gsm_trans *trans);
|
||||
int msc_call_bridge(struct gsm_trans *trans1, struct gsm_trans *trans2);
|
||||
void msc_call_release(struct gsm_trans *trans);
|
||||
int msc_call_connect(struct gsm_trans *trans, uint16_t port, uint32_t ip);
|
|
@ -1,95 +0,0 @@
|
|||
#ifndef _RTP_PROXY_H
|
||||
#define _RTP_PROXY_H
|
||||
|
||||
/* RTP proxy handling for ip.access nanoBTS */
|
||||
|
||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
* 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 <netinet/in.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/select.h>
|
||||
|
||||
#include <osmocom/bsc/mncc.h>
|
||||
|
||||
#define RTP_PT_GSM_FULL 3
|
||||
#define RTP_PT_GSM_HALF 96
|
||||
#define RTP_PT_GSM_EFR 97
|
||||
#define RTP_PT_AMR 98
|
||||
#define RTP_LEN_GSM_FULL 33
|
||||
#define RTP_LEN_GSM_HALF 15
|
||||
#define RTP_LEN_GSM_EFR 31
|
||||
#define RTP_GSM_DURATION 160
|
||||
|
||||
enum rtp_rx_action {
|
||||
RTP_NONE,
|
||||
RTP_PROXY,
|
||||
RTP_RECV_UPSTREAM,
|
||||
};
|
||||
|
||||
enum rtp_tx_action {
|
||||
RTP_SEND_NONE,
|
||||
RTP_SEND_DOWNSTREAM,
|
||||
};
|
||||
|
||||
struct rtp_sub_socket {
|
||||
struct sockaddr_in sin_local;
|
||||
struct sockaddr_in sin_remote;
|
||||
|
||||
struct osmo_fd bfd;
|
||||
/* linked list of to-be-transmitted msgb's */
|
||||
struct llist_head tx_queue;
|
||||
};
|
||||
|
||||
struct rtp_socket {
|
||||
struct llist_head list;
|
||||
|
||||
struct rtp_sub_socket rtp;
|
||||
struct rtp_sub_socket rtcp;
|
||||
|
||||
/* what should we do on receive? */
|
||||
enum rtp_rx_action rx_action;
|
||||
union {
|
||||
struct {
|
||||
struct rtp_socket *other_sock;
|
||||
} proxy;
|
||||
struct {
|
||||
struct gsm_network *net;
|
||||
uint32_t callref;
|
||||
} receive;
|
||||
};
|
||||
enum rtp_tx_action tx_action;
|
||||
struct {
|
||||
uint16_t sequence;
|
||||
uint32_t timestamp;
|
||||
uint32_t ssrc;
|
||||
struct timeval last_tv;
|
||||
} transmit;
|
||||
};
|
||||
|
||||
struct rtp_socket *rtp_socket_create(void);
|
||||
int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip);
|
||||
int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port);
|
||||
int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other);
|
||||
int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net, uint32_t callref);
|
||||
int rtp_socket_free(struct rtp_socket *rs);
|
||||
int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame);
|
||||
|
||||
#endif /* _RTP_PROXY_H */
|
|
@ -34,19 +34,15 @@
|
|||
*/
|
||||
enum signal_subsystems {
|
||||
SS_PAGING,
|
||||
SS_SMS,
|
||||
SS_ABISIP,
|
||||
SS_NM,
|
||||
SS_LCHAN,
|
||||
SS_SUBSCR,
|
||||
SS_SCALL,
|
||||
SS_CHALLOC,
|
||||
SS_IPAC_NWL,
|
||||
SS_RF,
|
||||
SS_MSC,
|
||||
SS_HO,
|
||||
SS_CCCH,
|
||||
SS_SGSN,
|
||||
};
|
||||
|
||||
/* SS_PAGING signals */
|
||||
|
@ -55,15 +51,6 @@ enum signal_paging {
|
|||
S_PAGING_EXPIRED,
|
||||
};
|
||||
|
||||
/* SS_SMS signals */
|
||||
enum signal_sms {
|
||||
S_SMS_SUBMITTED, /* A SMS has been successfully submitted to us */
|
||||
S_SMS_DELIVERED, /* A SMS has been successfully delivered to a MS */
|
||||
S_SMS_SMMA, /* A MS tells us it has more space available */
|
||||
S_SMS_MEM_EXCEEDED, /* A MS tells us it has no more space available */
|
||||
S_SMS_UNKNOWN_ERROR, /* A MS tells us it has an error */
|
||||
};
|
||||
|
||||
/* SS_ABISIP signals */
|
||||
enum signal_abisip {
|
||||
S_ABISIP_CRCX_ACK,
|
||||
|
@ -108,20 +95,6 @@ enum signal_challoc {
|
|||
S_CHALLOC_FREED, /* lchan has been successfully freed */
|
||||
};
|
||||
|
||||
/* SS_SUBSCR signals */
|
||||
enum signal_subscr {
|
||||
S_SUBSCR_ATTACHED,
|
||||
S_SUBSCR_DETACHED,
|
||||
S_SUBSCR_IDENTITY, /* we've received some identity information */
|
||||
};
|
||||
|
||||
/* SS_SCALL signals */
|
||||
enum signal_scall {
|
||||
S_SCALL_SUCCESS,
|
||||
S_SCALL_EXPIRED,
|
||||
S_SCALL_DETACHED,
|
||||
};
|
||||
|
||||
/* SS_IPAC_NWL signals */
|
||||
enum signal_ipaccess {
|
||||
S_IPAC_NWL_COMPLETE,
|
||||
|
@ -138,21 +111,6 @@ enum signal_rf {
|
|||
S_RF_GRACE,
|
||||
};
|
||||
|
||||
struct paging_signal_data {
|
||||
struct vlr_subscr *vsub;
|
||||
struct gsm_bts *bts;
|
||||
|
||||
int paging_result;
|
||||
|
||||
/* NULL in case the paging didn't work */
|
||||
struct gsm_subscriber_connection *conn;
|
||||
};
|
||||
|
||||
struct scall_signal_data {
|
||||
struct gsm_subscriber_connection *conn;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct ipacc_ack_signal_data {
|
||||
struct gsm_bts_trx *trx;
|
||||
uint8_t msg_type;
|
||||
|
@ -197,15 +155,6 @@ struct rf_signal_data {
|
|||
struct gsm_network *net;
|
||||
};
|
||||
|
||||
struct sms_signal_data {
|
||||
/* The transaction where this occured */
|
||||
struct gsm_trans *trans;
|
||||
/* Can be NULL for SMMA */
|
||||
struct gsm_sms *sms;
|
||||
/* int paging result. Only the ones with > 0 */
|
||||
int paging_result;
|
||||
};
|
||||
|
||||
struct lchan_signal_data {
|
||||
/* The lchan the signal happened on */
|
||||
struct gsm_lchan *lchan;
|
||||
|
@ -239,22 +188,4 @@ struct ccch_signal_data {
|
|||
uint16_t rach_access_count;
|
||||
};
|
||||
|
||||
/* GPRS SGSN signals SS_SGSN */
|
||||
enum signal_sgsn {
|
||||
S_SGSN_ATTACH,
|
||||
S_SGSN_DETACH,
|
||||
S_SGSN_UPDATE,
|
||||
S_SGSN_PDP_ACT,
|
||||
S_SGSN_PDP_DEACT,
|
||||
S_SGSN_PDP_TERMINATE,
|
||||
S_SGSN_PDP_FREE,
|
||||
S_SGSN_MM_FREE,
|
||||
};
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
struct sgsn_signal_data {
|
||||
struct sgsn_mm_ctx *mm;
|
||||
struct sgsn_pdp_ctx *pdp; /* non-NULL for PDP_ACT, PDP_DEACT, PDP_FREE */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef _SILENT_CALL_H
|
||||
#define _SILENT_CALL_H
|
||||
|
||||
struct gsm_subscriber_connection;
|
||||
|
||||
extern int gsm_silent_call_start(struct vlr_subscr *vsub,
|
||||
void *data, int type);
|
||||
extern int gsm_silent_call_stop(struct vlr_subscr *vsub);
|
||||
|
||||
#if 0
|
||||
extern int silent_call_rx(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
extern int silent_call_reroute(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
#endif
|
||||
|
||||
#endif /* _SILENT_CALL_H */
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
int smpp_openbsc_alloc_init(void *ctx);
|
||||
int smpp_openbsc_start(struct gsm_network *net);
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef SMS_QUEUE_H
|
||||
#define SMS_QUEUE_H
|
||||
|
||||
struct gsm_network;
|
||||
struct gsm_sms_queue;
|
||||
struct vty;
|
||||
|
||||
int sms_queue_start(struct gsm_network *, int in_flight);
|
||||
int sms_queue_trigger(struct gsm_sms_queue *);
|
||||
|
||||
/* vty helper functions */
|
||||
int sms_queue_stats(struct gsm_sms_queue *, struct vty* vty);
|
||||
int sms_queue_set_max_pending(struct gsm_sms_queue *, int max);
|
||||
int sms_queue_set_max_failure(struct gsm_sms_queue *, int fail);
|
||||
int sms_queue_clear(struct gsm_sms_queue *);
|
||||
|
||||
#endif
|
|
@ -1,102 +0,0 @@
|
|||
#ifndef _TRANSACT_H
|
||||
#define _TRANSACT_H
|
||||
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/bsc/mncc.h>
|
||||
#include <osmocom/gsm/gsm0411_smc.h>
|
||||
#include <osmocom/gsm/gsm0411_smr.h>
|
||||
|
||||
enum bridge_state {
|
||||
BRIDGE_STATE_NONE,
|
||||
BRIDGE_STATE_LOOPBACK_PENDING,
|
||||
BRIDGE_STATE_LOOPBACK_ESTABLISHED,
|
||||
BRIDGE_STATE_BRIDGE_PENDING,
|
||||
BRIDGE_STATE_BRIDGE_ESTABLISHED,
|
||||
};
|
||||
|
||||
/* One transaction */
|
||||
struct gsm_trans {
|
||||
/* Entry in list of all transactions */
|
||||
struct llist_head entry;
|
||||
|
||||
/* Back pointer to the network struct */
|
||||
struct gsm_network *net;
|
||||
|
||||
/* The protocol within which we live */
|
||||
uint8_t protocol;
|
||||
|
||||
/* The current transaction ID */
|
||||
uint8_t transaction_id;
|
||||
|
||||
/* To whom we belong, unique identifier of remote MM entity */
|
||||
struct vlr_subscr *vsub;
|
||||
|
||||
/* The associated connection we are using to transmit messages */
|
||||
struct gsm_subscriber_connection *conn;
|
||||
|
||||
/* reference from MNCC or other application */
|
||||
uint32_t callref;
|
||||
|
||||
/* if traffic channel receive was requested */
|
||||
int tch_recv;
|
||||
|
||||
/* is thats one paging? */
|
||||
struct subscr_request *paging_request;
|
||||
|
||||
/* bearer capabilities (rate and codec) */
|
||||
struct gsm_mncc_bearer_cap bearer_cap;
|
||||
|
||||
/* status of the assignment, true when done */
|
||||
bool assignment_done;
|
||||
|
||||
/* if true, TCH_RTP_CREATE is sent after the
|
||||
* assignment is done */
|
||||
bool tch_rtp_create;
|
||||
|
||||
union {
|
||||
struct {
|
||||
|
||||
/* current call state */
|
||||
int state;
|
||||
|
||||
/* current timer and message queue */
|
||||
int Tcurrent; /* current CC timer */
|
||||
int T308_second; /* used to send release again */
|
||||
struct osmo_timer_list timer;
|
||||
struct gsm_mncc msg; /* stores setup/disconnect/release message */
|
||||
} cc;
|
||||
struct {
|
||||
struct gsm411_smc_inst smc_inst;
|
||||
struct gsm411_smr_inst smr_inst;
|
||||
|
||||
struct gsm_sms *sms;
|
||||
} sms;
|
||||
};
|
||||
|
||||
struct {
|
||||
struct gsm_trans *peer;
|
||||
enum bridge_state state;
|
||||
} bridge;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct gsm_trans *trans_find_by_id(struct gsm_subscriber_connection *conn,
|
||||
uint8_t proto, uint8_t trans_id);
|
||||
struct gsm_trans *trans_find_by_callref(struct gsm_network *net,
|
||||
uint32_t callref);
|
||||
|
||||
struct gsm_trans *trans_alloc(struct gsm_network *net,
|
||||
struct vlr_subscr *vsub,
|
||||
uint8_t protocol, uint8_t trans_id,
|
||||
uint32_t callref);
|
||||
void trans_free(struct gsm_trans *trans);
|
||||
|
||||
int trans_assign_trans_id(struct gsm_network *net, struct vlr_subscr *vsub,
|
||||
uint8_t protocol, uint8_t ti_flag);
|
||||
struct gsm_trans *trans_has_conn(const struct gsm_subscriber_connection *conn);
|
||||
void trans_conn_closed(struct gsm_subscriber_connection *conn);
|
||||
|
||||
#endif
|
|
@ -1,70 +0,0 @@
|
|||
/* Simple TRAU frame reflector to route voice calls */
|
||||
|
||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* The "TRAU mux map" defines which particular 16kbit sub-slot (in which E1
|
||||
* timeslot on which E1 interface) should be directly muxed to which other
|
||||
* sub-slot. Entries in the mux map are always bi-directional.
|
||||
*
|
||||
* The idea of all this is to directly switch voice channels in the BSC
|
||||
* from one phone to another. We do this right now since we don't support
|
||||
* any external interface for voice channels, and in the future as an
|
||||
* optimization to routing them externally.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/mncc.h>
|
||||
|
||||
struct decoded_trau_frame;
|
||||
|
||||
/* map a TRAU mux map entry */
|
||||
int trau_mux_map(const struct gsm_e1_subslot *src,
|
||||
const struct gsm_e1_subslot *dst);
|
||||
int trau_mux_map_lchan(const struct gsm_lchan *src,
|
||||
const struct gsm_lchan *dst);
|
||||
|
||||
/* unmap a TRAU mux map entry */
|
||||
int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref);
|
||||
|
||||
/* we get called by subchan_demux */
|
||||
int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
|
||||
const uint8_t *trau_bits, int num_bits);
|
||||
|
||||
/* add a trau receiver */
|
||||
int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref);
|
||||
|
||||
/* send trau from application */
|
||||
int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame);
|
||||
|
||||
/* switch trau muxer to new lchan */
|
||||
int switch_trau_mux(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan);
|
||||
|
||||
/* callback invoked if we receive TRAU frames */
|
||||
int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len, void *_priv);
|
||||
|
||||
/* TRAU frame transcoding */
|
||||
struct msgb *trau_decode_fr(uint32_t callref,
|
||||
const struct decoded_trau_frame *tf);
|
||||
struct msgb *trau_decode_efr(uint32_t callref,
|
||||
const struct decoded_trau_frame *tf);
|
||||
void trau_encode_fr(struct decoded_trau_frame *tf,
|
||||
const unsigned char *data);
|
||||
void trau_encode_efr(struct decoded_trau_frame *tf,
|
||||
const unsigned char *data);
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef _TRAU_UPQUEUE_H
|
||||
#define _TRAU_UPQUEUE_H
|
||||
|
||||
void trau_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
|
||||
|
||||
#endif /* _TRAU_UPQUEUE_H */
|
||||
|
|
@ -24,7 +24,6 @@ SUBDIRS = \
|
|||
libcommon \
|
||||
libcommon-cs \
|
||||
libbsc \
|
||||
libtrau \
|
||||
libfilter \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ bin_PROGRAMS = \
|
|||
|
||||
abisip_find_LDADD = \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(OSMO_LIBS) \
|
||||
$(NULL)
|
||||
|
@ -49,7 +48,6 @@ ipaccess_config_SOURCES = \
|
|||
ipaccess_config_LDADD = \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(OSMO_LIBS) \
|
||||
$(NULL)
|
||||
|
@ -60,7 +58,6 @@ ipaccess_proxy_SOURCES = \
|
|||
|
||||
ipaccess_proxy_LDADD = \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(OSMO_LIBS) \
|
||||
$(NULL)
|
||||
|
|
|
@ -978,7 +978,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
libosmo_abis_init(tall_ctx_config);
|
||||
|
||||
bsc_gsmnet = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
|
||||
bsc_gsmnet = bsc_network_init(tall_bsc_ctx, 1, 1);
|
||||
if (!bsc_gsmnet)
|
||||
exit(1);
|
||||
|
||||
|
|
|
@ -40,8 +40,6 @@
|
|||
#include <osmocom/bsc/paging.h>
|
||||
#include <osmocom/bsc/signal.h>
|
||||
#include <osmocom/bsc/meas_rep.h>
|
||||
#include <osmocom/bsc/rtp_proxy.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
#include <osmocom/gsm/rsl.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
|
@ -51,6 +49,11 @@
|
|||
#define RSL_ALLOC_SIZE 1024
|
||||
#define RSL_ALLOC_HEADROOM 128
|
||||
|
||||
#define RTP_PT_GSM_FULL 3
|
||||
#define RTP_PT_GSM_HALF 96
|
||||
#define RTP_PT_GSM_EFR 97
|
||||
#define RTP_PT_AMR 98
|
||||
|
||||
enum sacch_deact {
|
||||
SACCH_NONE,
|
||||
SACCH_DEACTIVATE,
|
||||
|
@ -160,9 +163,6 @@ static struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
|||
LOGP(DRSL, LOGL_ERROR, "%s %smismatching chan_nr=0x%02x\n",
|
||||
gsm_ts_and_pchan_name(lchan->ts), log_name, chan_nr);
|
||||
|
||||
if (lchan->conn)
|
||||
log_set_context(LOG_CTX_VLR_SUBSCR, lchan->conn->vsub);
|
||||
|
||||
return lchan;
|
||||
}
|
||||
|
||||
|
@ -2422,20 +2422,6 @@ int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
|
|||
return abis_rsl_sendmsg(msg);
|
||||
}
|
||||
|
||||
/* tell BTS to connect RTP stream to our local RTP socket */
|
||||
int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
|
||||
int rc;
|
||||
|
||||
rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
|
||||
ntohs(rs->rtp.sin_local.sin_port),
|
||||
/* FIXME: use RTP payload of bound socket, not BTS*/
|
||||
lchan->abis_ip.rtp_payload2);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
|
||||
{
|
||||
struct msgb *msg = rsl_msgb_alloc();
|
||||
|
|
|
@ -24,13 +24,11 @@
|
|||
#include <osmocom/bsc/bsc_api.h>
|
||||
#include <osmocom/bsc/bsc_rll.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/bsc/signal.h>
|
||||
#include <osmocom/bsc/abis_rsl.h>
|
||||
#include <osmocom/bsc/chan_alloc.h>
|
||||
#include <osmocom/bsc/handover.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/bsc/trau_mux.h>
|
||||
#include <osmocom/bsc/gsm_04_08_utils.h>
|
||||
#include <osmocom/bsc/bsc_subscriber.h>
|
||||
|
||||
|
@ -263,7 +261,6 @@ struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_lchan *lcha
|
|||
conn->network = net;
|
||||
conn->lchan = lchan;
|
||||
conn->bts = lchan->ts->trx->bts;
|
||||
conn->via_ran = RAN_GERAN_A;
|
||||
conn->lac = conn->bts->location_area_code;
|
||||
lchan->conn = conn;
|
||||
llist_add_tail(&conn->entry, &net->subscr_conns);
|
||||
|
@ -278,11 +275,6 @@ void bsc_subscr_con_free(struct gsm_subscriber_connection *conn)
|
|||
if (conn->network->bsc_api->conn_cleanup)
|
||||
conn->network->bsc_api->conn_cleanup(conn);
|
||||
|
||||
if (conn->vsub) {
|
||||
LOGP(DNM, LOGL_ERROR, "conn->vsub should have been cleared.\n");
|
||||
conn->vsub = NULL;
|
||||
}
|
||||
|
||||
if (conn->ho_lchan) {
|
||||
LOGP(DNM, LOGL_ERROR, "The ho_lchan should have been cleared.\n");
|
||||
conn->ho_lchan->conn = NULL;
|
||||
|
@ -453,10 +445,6 @@ static void handle_ass_compl(struct gsm_subscriber_connection *conn,
|
|||
return;
|
||||
}
|
||||
|
||||
/* switch TRAU muxer for E1 based BTS from one channel to another */
|
||||
if (is_e1_bts(conn->bts))
|
||||
switch_trau_mux(conn->lchan, conn->secondary_lchan);
|
||||
|
||||
/* swap channels */
|
||||
osmo_timer_del(&conn->T10);
|
||||
|
||||
|
|
|
@ -529,10 +529,10 @@ static int bootstrap_bts(struct gsm_bts *bts)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bsc_network_alloc(mncc_recv_cb_t mncc_recv)
|
||||
int bsc_network_alloc(void)
|
||||
{
|
||||
/* initialize our data structures */
|
||||
bsc_gsmnet = bsc_network_init(tall_bsc_ctx, 1, 1, mncc_recv);
|
||||
bsc_gsmnet = bsc_network_init(tall_bsc_ctx, 1, 1);
|
||||
if (!bsc_gsmnet)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -25,12 +25,10 @@
|
|||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/bsc/chan_alloc.h>
|
||||
#include <osmocom/bsc/abis_nm.h>
|
||||
#include <osmocom/bsc/abis_rsl.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/bsc/rtp_proxy.h>
|
||||
#include <osmocom/bsc/signal.h>
|
||||
#include <osmocom/bsc/gsm_04_08_utils.h>
|
||||
|
||||
|
@ -392,13 +390,6 @@ void lchan_free(struct gsm_lchan *lchan)
|
|||
osmo_signal_dispatch(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, &sig);
|
||||
}
|
||||
|
||||
if (lchan->abis_ip.rtp_socket) {
|
||||
LOGP(DRLL, LOGL_ERROR, "%s RTP Proxy Socket remained open.\n",
|
||||
gsm_lchan_name(lchan));
|
||||
rtp_socket_free(lchan->abis_ip.rtp_socket);
|
||||
lchan->abis_ip.rtp_socket = NULL;
|
||||
}
|
||||
|
||||
/* stop the timer */
|
||||
osmo_timer_del(&lchan->T3101);
|
||||
|
||||
|
@ -449,11 +440,6 @@ void lchan_reset(struct gsm_lchan *lchan)
|
|||
|
||||
lchan->type = GSM_LCHAN_NONE;
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
|
||||
|
||||
if (lchan->abis_ip.rtp_socket) {
|
||||
rtp_socket_free(lchan->abis_ip.rtp_socket);
|
||||
lchan->abis_ip.rtp_socket = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Drive the release process of the lchan */
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
#include <osmocom/abis/trau_frame.h>
|
||||
#include <osmocom/bsc/trau_mux.h>
|
||||
#include <osmocom/bsc/misdn.h>
|
||||
#include <osmocom/abis/ipaccess.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
|
@ -45,7 +43,6 @@ int e1_reconfig_ts(struct gsm_bts_trx_ts *ts)
|
|||
{
|
||||
struct gsm_e1_subslot *e1_link = &ts->e1_link;
|
||||
struct e1inp_line *line;
|
||||
struct e1inp_ts *e1_ts;
|
||||
|
||||
DEBUGP(DLMI, "e1_reconfig_ts(%u,%u,%u)\n", ts->trx->bts->nr, ts->trx->nr, ts->nr);
|
||||
|
||||
|
@ -63,12 +60,6 @@ int e1_reconfig_ts(struct gsm_bts_trx_ts *ts)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (ts_is_tch(ts)) {
|
||||
e1_ts = &line->ts[e1_link->e1_ts-1];
|
||||
e1inp_ts_config_trau(e1_ts, line, subch_cb);
|
||||
subch_demux_activate(&e1_ts->trau.demux, e1_link->e1_ts_ss);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include <osmocom/bsc/abis_rsl.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/bsc/transaction.h>
|
||||
#include <osmocom/bsc/paging.h>
|
||||
#include <osmocom/bsc/signal.h>
|
||||
#include <osmocom/bsc/bsc_api.h>
|
||||
|
|
|
@ -32,13 +32,10 @@
|
|||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/bsc/abis_rsl.h>
|
||||
#include <osmocom/bsc/chan_alloc.h>
|
||||
#include <osmocom/bsc/signal.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/bsc/transaction.h>
|
||||
#include <osmocom/bsc/trau_mux.h>
|
||||
#include <osmocom/bsc/bsc_subscriber.h>
|
||||
#include <osmocom/bsc/gsm_04_08_utils.h>
|
||||
|
||||
|
@ -271,10 +268,6 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
|
|||
|
||||
osmo_timer_del(&ho->T3103);
|
||||
|
||||
/* switch TRAU muxer for E1 based BTS from one channel to another */
|
||||
if (is_e1_bts(new_lchan->conn->bts))
|
||||
switch_trau_mux(ho->old_lchan, new_lchan);
|
||||
|
||||
/* Replace the ho lchan with the primary one */
|
||||
if (ho->old_lchan != new_lchan->conn->lchan)
|
||||
LOGP(DHO, LOGL_ERROR, "Primary lchan changed during handover.\n");
|
||||
|
|
|
@ -24,12 +24,11 @@
|
|||
|
||||
struct gsm_network *bsc_network_init(void *ctx,
|
||||
uint16_t country_code,
|
||||
uint16_t network_code,
|
||||
mncc_recv_cb_t mncc_recv)
|
||||
uint16_t network_code)
|
||||
{
|
||||
struct gsm_network *net;
|
||||
|
||||
net = gsm_network_init(ctx, country_code, network_code, mncc_recv);
|
||||
net = gsm_network_init(ctx, country_code, network_code);
|
||||
|
||||
net->bsc_data = talloc_zero(net, struct osmo_bsc_data);
|
||||
if (!net->bsc_data) {
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include <osmocom/bsc/common_cs.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/gsm_04_08_utils.h>
|
||||
|
||||
|
@ -39,8 +38,7 @@
|
|||
*/
|
||||
struct gsm_network *gsm_network_init(void *ctx,
|
||||
uint16_t country_code,
|
||||
uint16_t network_code,
|
||||
mncc_recv_cb_t mncc_recv)
|
||||
uint16_t network_code)
|
||||
{
|
||||
struct gsm_network *net;
|
||||
|
||||
|
@ -55,7 +53,6 @@ struct gsm_network *gsm_network_init(void *ctx,
|
|||
net->t3212 = 5;
|
||||
|
||||
INIT_LLIST_HEAD(&net->trans_list);
|
||||
INIT_LLIST_HEAD(&net->upqueue);
|
||||
INIT_LLIST_HEAD(&net->subscr_conns);
|
||||
|
||||
net->bsc_subscribers = talloc_zero(net, struct llist_head);
|
||||
|
@ -63,8 +60,6 @@ struct gsm_network *gsm_network_init(void *ctx,
|
|||
|
||||
net->active_calls = osmo_counter_alloc("msc.active_calls");
|
||||
|
||||
net->mncc_recv = mncc_recv;
|
||||
|
||||
net->dyn_ts_allow_tch_f = true;
|
||||
|
||||
INIT_LLIST_HEAD(&net->a.bscs);
|
||||
|
@ -128,16 +123,3 @@ int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
|
|||
return gsm48_extract_mi(classmark2_lv, length - classmark_offset,
|
||||
mi_string, mi_type);
|
||||
}
|
||||
|
||||
uint8_t sms_next_rp_msg_ref(uint8_t *next_rp_ref)
|
||||
{
|
||||
const uint8_t rp_msg_ref = *next_rp_ref;
|
||||
/*
|
||||
* This should wrap as the valid range is 0 to 255. We only
|
||||
* transfer one SMS at a time so we don't need to check if
|
||||
* the id has been already assigned.
|
||||
*/
|
||||
*next_rp_ref += 1;
|
||||
|
||||
return rp_msg_ref;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <osmocom/bsc/vty.h>
|
||||
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
|
||||
struct cmd_node net_node = {
|
||||
GSMNET_NODE,
|
||||
|
|
|
@ -25,5 +25,4 @@ libcommon_a_SOURCES = \
|
|||
gsm_data_shared.c \
|
||||
socket.c \
|
||||
talloc_ctx.c \
|
||||
gsm_subscriber_base.c \
|
||||
$(NULL)
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <osmocom/bsc/vty.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/bsc/bsc_nat.h>
|
||||
#include <osmocom/bsc/abis_om2000.h>
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/* The concept of a subscriber as seen by the BSC */
|
||||
|
||||
/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010 by On-Waves
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
|
||||
LLIST_HEAD(active_subscribers);
|
||||
void *tall_subscr_ctx;
|
||||
|
|
@ -32,8 +32,6 @@ extern void *tall_paging_ctx;
|
|||
extern void *tall_sigh_ctx;
|
||||
extern void *tall_tqe_ctx;
|
||||
extern void *tall_trans_ctx;
|
||||
extern void *tall_map_ctx;
|
||||
extern void *tall_upq_ctx;
|
||||
extern void *tall_ctr_ctx;
|
||||
|
||||
void talloc_ctx_init(void *ctx_root)
|
||||
|
@ -49,7 +47,5 @@ void talloc_ctx_init(void *ctx_root)
|
|||
tall_sigh_ctx = talloc_named_const(ctx_root, 0, "signal_handler");
|
||||
tall_tqe_ctx = talloc_named_const(ctx_root, 0, "subch_txq_entry");
|
||||
tall_trans_ctx = talloc_named_const(ctx_root, 0, "transaction");
|
||||
tall_map_ctx = talloc_named_const(ctx_root, 0, "trau_map_entry");
|
||||
tall_upq_ctx = talloc_named_const(ctx_root, 0, "trau_upq_entry");
|
||||
tall_ctr_ctx = talloc_named_const(ctx_root, 0, "counter");
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_builddir) \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOVTY_CFLAGS) \
|
||||
$(LIBOSMOABIS_CFLAGS) \
|
||||
$(LIBOSMONETIF_CFLAGS) \
|
||||
$(COVERAGE_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
AM_LDFLAGS = \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBOSMOABIS_LIBS) \
|
||||
$(COVERAGE_LDFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
noinst_LIBRARIES = \
|
||||
libtrau.a \
|
||||
$(NULL)
|
||||
|
||||
libtrau_a_SOURCES = \
|
||||
rtp_proxy.c \
|
||||
trau_mux.c \
|
||||
trau_upqueue.c \
|
||||
$(NULL)
|
|
@ -1,764 +0,0 @@
|
|||
/* RTP proxy handling for ip.access nanoBTS */
|
||||
|
||||
/* (C) 2009-2013 by Harald Welte <laforge@gnumonks.org>
|
||||
* 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 <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h> /* gettimeofday() */
|
||||
#include <unistd.h> /* get..() */
|
||||
#include <time.h> /* clock() */
|
||||
#include <sys/utsname.h> /* uname() */
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/bsc/rtp_proxy.h>
|
||||
#include <osmocom/bsc/mncc.h>
|
||||
#include <osmocom/bsc/trau_upqueue.h>
|
||||
|
||||
#include <osmocom/netif/rtp.h>
|
||||
|
||||
/* attempt to determine byte order */
|
||||
#include <sys/param.h>
|
||||
#include <limits.h>
|
||||
|
||||
static LLIST_HEAD(rtp_sockets);
|
||||
|
||||
/* should we mangle the CNAME inside SDES of RTCP packets? We disable
|
||||
* this by default, as it seems to be not needed */
|
||||
static int mangle_rtcp_cname = 0;
|
||||
|
||||
enum rtp_bfd_priv {
|
||||
RTP_PRIV_NONE,
|
||||
RTP_PRIV_RTP,
|
||||
RTP_PRIV_RTCP
|
||||
};
|
||||
|
||||
#define RTP_ALLOC_SIZE 1500
|
||||
|
||||
#define RTCP_TYPE_SDES 202
|
||||
|
||||
#define RTCP_IE_CNAME 1
|
||||
|
||||
|
||||
#define RTP_VERSION 2
|
||||
|
||||
/* 33 for FR, all other codecs have smaller size */
|
||||
#define MAX_RTP_PAYLOAD_LEN 33
|
||||
|
||||
/* decode an rtp frame and create a new buffer with payload */
|
||||
static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
|
||||
{
|
||||
struct msgb *new_msg;
|
||||
struct gsm_data_frame *frame;
|
||||
struct rtp_hdr *rtph = (struct rtp_hdr *)msg->data;
|
||||
struct rtp_x_hdr *rtpxh;
|
||||
uint8_t *payload, *payload_out;
|
||||
int payload_len;
|
||||
int msg_type;
|
||||
int x_len;
|
||||
|
||||
if (msg->len < 12) {
|
||||
DEBUGPC(DLMUX, "received RTP frame too short (len = %d)\n",
|
||||
msg->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rtph->version != RTP_VERSION) {
|
||||
DEBUGPC(DLMUX, "received RTP version %d not supported.\n",
|
||||
rtph->version);
|
||||
return -EINVAL;
|
||||
}
|
||||
payload = msg->data + sizeof(struct rtp_hdr) + (rtph->csrc_count << 2);
|
||||
payload_len = msg->len - sizeof(struct rtp_hdr) - (rtph->csrc_count << 2);
|
||||
if (payload_len < 0) {
|
||||
DEBUGPC(DLMUX, "received RTP frame too short (len = %d, "
|
||||
"csrc count = %d)\n", msg->len, rtph->csrc_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rtph->extension) {
|
||||
if (payload_len < sizeof(struct rtp_x_hdr)) {
|
||||
DEBUGPC(DLMUX, "received RTP frame too short for "
|
||||
"extension header\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
rtpxh = (struct rtp_x_hdr *)payload;
|
||||
x_len = ntohs(rtpxh->length) * 4 + sizeof(struct rtp_x_hdr);
|
||||
payload += x_len;
|
||||
payload_len -= x_len;
|
||||
if (payload_len < 0) {
|
||||
DEBUGPC(DLMUX, "received RTP frame too short, "
|
||||
"extension header exceeds frame length\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (rtph->padding) {
|
||||
if (payload_len < 1) {
|
||||
DEBUGPC(DLMUX, "received RTP frame too short for "
|
||||
"padding length\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
payload_len -= payload[payload_len - 1];
|
||||
if (payload_len < 0) {
|
||||
DEBUGPC(DLMUX, "received RTP frame with padding "
|
||||
"greater than payload\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (rtph->payload_type) {
|
||||
case RTP_PT_GSM_FULL:
|
||||
msg_type = GSM_TCHF_FRAME;
|
||||
if (payload_len != RTP_LEN_GSM_FULL) {
|
||||
DEBUGPC(DLMUX, "received RTP full rate frame with "
|
||||
"payload length != %d (len = %d)\n",
|
||||
RTP_LEN_GSM_FULL, payload_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case RTP_PT_GSM_EFR:
|
||||
msg_type = GSM_TCHF_FRAME_EFR;
|
||||
if (payload_len != RTP_LEN_GSM_EFR) {
|
||||
DEBUGPC(DLMUX, "received RTP extended full rate frame "
|
||||
"with payload length != %d (len = %d)\n",
|
||||
RTP_LEN_GSM_EFR, payload_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case RTP_PT_GSM_HALF:
|
||||
msg_type = GSM_TCHH_FRAME;
|
||||
if (payload_len != RTP_LEN_GSM_HALF) {
|
||||
DEBUGPC(DLMUX, "received RTP half rate frame with "
|
||||
"payload length != %d (len = %d)\n",
|
||||
RTP_LEN_GSM_HALF, payload_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case RTP_PT_AMR:
|
||||
msg_type = GSM_TCH_FRAME_AMR;
|
||||
break;
|
||||
default:
|
||||
DEBUGPC(DLMUX, "received RTP frame with unknown payload "
|
||||
"type %d\n", rtph->payload_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (payload_len > MAX_RTP_PAYLOAD_LEN ||
|
||||
(rtph->payload_type == RTP_PT_AMR &&
|
||||
payload_len > MAX_RTP_PAYLOAD_LEN - 1)) {
|
||||
DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
|
||||
payload_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* always allocate for the maximum possible size to avoid
|
||||
* fragmentation */
|
||||
new_msg = msgb_alloc(sizeof(struct gsm_data_frame) +
|
||||
MAX_RTP_PAYLOAD_LEN+1, "GSM-DATA (TCH)");
|
||||
|
||||
if (!new_msg)
|
||||
return -ENOMEM;
|
||||
frame = (struct gsm_data_frame *) msgb_put(new_msg, sizeof(struct gsm_data_frame));
|
||||
frame->msg_type = msg_type;
|
||||
frame->callref = callref;
|
||||
if (rtph->payload_type == RTP_PT_AMR) {
|
||||
/* for FR/HR/EFR the length is implicit. In AMR, we
|
||||
* need to make it explicit by using the first byte of
|
||||
* the data[] buffer as length byte */
|
||||
uint8_t *data0 = msgb_put(new_msg, 1);
|
||||
*data0 = payload_len;
|
||||
}
|
||||
payload_out = msgb_put(new_msg, payload_len);
|
||||
memcpy(payload_out, payload, payload_len);
|
||||
|
||||
*data = new_msg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief encode and send a rtp frame
|
||||
* \param[in] rs RTP socket through which we shall send
|
||||
* \param[in] frame GSM RTP frame to be sent
|
||||
*/
|
||||
int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
|
||||
{
|
||||
struct rtp_sub_socket *rss = &rs->rtp;
|
||||
struct msgb *msg;
|
||||
struct rtp_hdr *rtph;
|
||||
uint8_t *payload;
|
||||
int payload_type;
|
||||
int payload_len;
|
||||
int duration; /* in samples */
|
||||
int is_bfi = 0;
|
||||
|
||||
if (rs->tx_action != RTP_SEND_DOWNSTREAM) {
|
||||
/* initialize sequences */
|
||||
rs->tx_action = RTP_SEND_DOWNSTREAM;
|
||||
rs->transmit.ssrc = rand();
|
||||
rs->transmit.sequence = random();
|
||||
rs->transmit.timestamp = random();
|
||||
}
|
||||
|
||||
switch (frame->msg_type) {
|
||||
case GSM_TCHF_FRAME:
|
||||
payload_type = RTP_PT_GSM_FULL;
|
||||
payload_len = RTP_LEN_GSM_FULL;
|
||||
duration = RTP_GSM_DURATION;
|
||||
break;
|
||||
case GSM_TCHF_FRAME_EFR:
|
||||
payload_type = RTP_PT_GSM_EFR;
|
||||
payload_len = RTP_LEN_GSM_EFR;
|
||||
duration = RTP_GSM_DURATION;
|
||||
break;
|
||||
case GSM_TCHH_FRAME:
|
||||
payload_type = RTP_PT_GSM_HALF;
|
||||
payload_len = RTP_LEN_GSM_HALF;
|
||||
duration = RTP_GSM_DURATION;
|
||||
break;
|
||||
case GSM_TCH_FRAME_AMR:
|
||||
payload_type = RTP_PT_AMR;
|
||||
payload_len = frame->data[0];
|
||||
duration = RTP_GSM_DURATION;
|
||||
break;
|
||||
case GSM_BAD_FRAME:
|
||||
payload_type = 0;
|
||||
payload_len = 0;
|
||||
duration = RTP_GSM_DURATION;
|
||||
is_bfi = 1;
|
||||
break;
|
||||
default:
|
||||
DEBUGPC(DLMUX, "unsupported message type %d\n",
|
||||
frame->msg_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (payload_len > MAX_RTP_PAYLOAD_LEN) {
|
||||
DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
|
||||
payload_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_bfi) {
|
||||
/* In case of a bad frame, just count and drop packet. */
|
||||
rs->transmit.timestamp += duration;
|
||||
rs->transmit.sequence++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len, "RTP-GSM");
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
rtph = (struct rtp_hdr *) msgb_put(msg, sizeof(struct rtp_hdr));
|
||||
rtph->version = RTP_VERSION;
|
||||
rtph->padding = 0;
|
||||
rtph->extension = 0;
|
||||
rtph->csrc_count = 0;
|
||||
rtph->marker = 0;
|
||||
rtph->payload_type = payload_type;
|
||||
rtph->sequence = htons(rs->transmit.sequence++);
|
||||
rtph->timestamp = htonl(rs->transmit.timestamp);
|
||||
rs->transmit.timestamp += duration;
|
||||
rtph->ssrc = htonl(rs->transmit.ssrc);
|
||||
|
||||
payload = msgb_put(msg, payload_len);
|
||||
if (frame->msg_type == GSM_TCH_FRAME_AMR)
|
||||
memcpy(payload, frame->data + 1, payload_len);
|
||||
else
|
||||
memcpy(payload, frame->data, payload_len);
|
||||
msgb_enqueue(&rss->tx_queue, msg);
|
||||
rss->bfd.when |= BSC_FD_WRITE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* iterate over all chunks in one RTCP message, look for CNAME IEs and
|
||||
* replace all of those with 'new_cname' */
|
||||
static int rtcp_sdes_cname_mangle(struct msgb *msg, struct rtcp_hdr *rh,
|
||||
uint16_t *rtcp_len, const char *new_cname)
|
||||
{
|
||||
uint8_t *rtcp_end;
|
||||
uint8_t *cur = (uint8_t *) rh;
|
||||
uint8_t tag, len = 0;
|
||||
|
||||
rtcp_end = cur + *rtcp_len;
|
||||
/* move cur to end of RTP header */
|
||||
cur += sizeof(*rh);
|
||||
|
||||
/* iterate over Chunks */
|
||||
while (cur+4 < rtcp_end) {
|
||||
/* skip four bytes SSRC/CSRC */
|
||||
cur += 4;
|
||||
|
||||
/* iterate over IE's inside the chunk */
|
||||
while (cur+1 < rtcp_end) {
|
||||
tag = *cur++;
|
||||
if (tag == 0) {
|
||||
/* end of chunk, skip additional zero */
|
||||
while ((*cur++ == 0) && (cur < rtcp_end)) { }
|
||||
break;
|
||||
}
|
||||
len = *cur++;
|
||||
|
||||
if (tag == RTCP_IE_CNAME) {
|
||||
/* we've found the CNAME, lets mangle it */
|
||||
if (len < strlen(new_cname)) {
|
||||
/* we need to make more space */
|
||||
int increase = strlen(new_cname) - len;
|
||||
|
||||
msgb_push(msg, increase);
|
||||
memmove(cur+len+increase, cur+len,
|
||||
rtcp_end - (cur+len));
|
||||
/* FIXME: we have to respect RTCP
|
||||
* padding/alignment rules! */
|
||||
len += increase;
|
||||
*(cur-1) += increase;
|
||||
rtcp_end += increase;
|
||||
*rtcp_len += increase;
|
||||
}
|
||||
/* copy new CNAME into message */
|
||||
memcpy(cur, new_cname, strlen(new_cname));
|
||||
/* FIXME: zero the padding in case new CNAME
|
||||
* is smaller than old one !!! */
|
||||
}
|
||||
cur += len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtcp_mangle(struct msgb *msg, struct rtp_socket *rs)
|
||||
{
|
||||
struct rtp_sub_socket *rss = &rs->rtcp;
|
||||
struct rtcp_hdr *rtph;
|
||||
uint16_t old_len;
|
||||
int rc;
|
||||
|
||||
if (!mangle_rtcp_cname)
|
||||
return 0;
|
||||
|
||||
printf("RTCP\n");
|
||||
/* iterate over list of RTCP messages */
|
||||
rtph = (struct rtcp_hdr *)msg->data;
|
||||
while ((void *)rtph + sizeof(*rtph) <= (void *)msg->data + msg->len) {
|
||||
old_len = (ntohs(rtph->length) + 1) * 4;
|
||||
if ((void *)rtph + old_len > (void *)msg->data + msg->len) {
|
||||
DEBUGPC(DLMUX, "received RTCP packet too short for "
|
||||
"length element\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rtph->type == RTCP_TYPE_SDES) {
|
||||
char new_cname[255];
|
||||
osmo_strlcpy(new_cname,
|
||||
inet_ntoa(rss->sin_local.sin_addr),
|
||||
sizeof(new_cname));
|
||||
rc = rtcp_sdes_cname_mangle(msg, rtph, &old_len,
|
||||
new_cname);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
rtph = (void *)rtph + old_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read from incoming RTP/RTCP socket */
|
||||
static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss)
|
||||
{
|
||||
int rc;
|
||||
struct msgb *msg = msgb_alloc(RTP_ALLOC_SIZE, "RTP/RTCP");
|
||||
struct msgb *new_msg;
|
||||
struct rtp_sub_socket *other_rss;
|
||||
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = read(rss->bfd.fd, msg->data, RTP_ALLOC_SIZE);
|
||||
if (rc == 0) {
|
||||
rss->bfd.when &= ~BSC_FD_READ;
|
||||
goto out_free;
|
||||
} else if (rc < 0) {
|
||||
/* Ignore "connection refused". this happens, If we open the
|
||||
* socket faster than the remote side. */
|
||||
if (errno == ECONNREFUSED)
|
||||
goto out_free;
|
||||
DEBUGPC(DLMUX, "Read of RTP socket (%p) failed (errno %d, "
|
||||
"%s)\n", rs, errno, strerror(errno));
|
||||
rss->bfd.when &= ~BSC_FD_READ;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
msgb_put(msg, rc);
|
||||
|
||||
switch (rs->rx_action) {
|
||||
case RTP_PROXY:
|
||||
if (!rs->proxy.other_sock) {
|
||||
rc = -EIO;
|
||||
goto out_free;
|
||||
}
|
||||
if (rss->bfd.priv_nr == RTP_PRIV_RTP)
|
||||
other_rss = &rs->proxy.other_sock->rtp;
|
||||
else if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
|
||||
other_rss = &rs->proxy.other_sock->rtcp;
|
||||
/* modify RTCP SDES CNAME */
|
||||
rc = rtcp_mangle(msg, rs);
|
||||
if (rc < 0)
|
||||
goto out_free;
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
msgb_enqueue(&other_rss->tx_queue, msg);
|
||||
other_rss->bfd.when |= BSC_FD_WRITE;
|
||||
break;
|
||||
|
||||
case RTP_RECV_UPSTREAM:
|
||||
if (!rs->receive.callref || !rs->receive.net) {
|
||||
rc = -EIO;
|
||||
goto out_free;
|
||||
}
|
||||
if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
|
||||
if (!mangle_rtcp_cname) {
|
||||
msgb_free(msg);
|
||||
break;
|
||||
}
|
||||
/* modify RTCP SDES CNAME */
|
||||
rc = rtcp_mangle(msg, rs);
|
||||
if (rc < 0)
|
||||
goto out_free;
|
||||
msgb_enqueue(&rss->tx_queue, msg);
|
||||
rss->bfd.when |= BSC_FD_WRITE;
|
||||
break;
|
||||
}
|
||||
if (rss->bfd.priv_nr != RTP_PRIV_RTP) {
|
||||
rc = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
rc = rtp_decode(msg, rs->receive.callref, &new_msg);
|
||||
if (rc < 0)
|
||||
goto out_free;
|
||||
msgb_free(msg);
|
||||
trau_tx_to_mncc(rs->receive.net, new_msg);
|
||||
break;
|
||||
|
||||
case RTP_NONE: /* if socket exists, but disabled by app */
|
||||
msgb_free(msg);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
msgb_free(msg);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* \brief write from tx_queue to RTP/RTCP socket */
|
||||
static int rtp_socket_write(struct rtp_socket *rs, struct rtp_sub_socket *rss)
|
||||
{
|
||||
struct msgb *msg;
|
||||
int written;
|
||||
|
||||
msg = msgb_dequeue(&rss->tx_queue);
|
||||
if (!msg) {
|
||||
rss->bfd.when &= ~BSC_FD_WRITE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
written = write(rss->bfd.fd, msg->data, msg->len);
|
||||
if (written < msg->len) {
|
||||
LOGP(DLMIB, LOGL_ERROR, "short write");
|
||||
msgb_free(msg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
msgb_free(msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief callback for the select.c:bfd_* layer */
|
||||
static int rtp_bfd_cb(struct osmo_fd *bfd, unsigned int flags)
|
||||
{
|
||||
struct rtp_socket *rs = bfd->data;
|
||||
struct rtp_sub_socket *rss;
|
||||
|
||||
switch (bfd->priv_nr) {
|
||||
case RTP_PRIV_RTP:
|
||||
rss = &rs->rtp;
|
||||
break;
|
||||
case RTP_PRIV_RTCP:
|
||||
rss = &rs->rtcp;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (flags & BSC_FD_READ)
|
||||
rtp_socket_read(rs, rss);
|
||||
|
||||
if (flags & BSC_FD_WRITE)
|
||||
rtp_socket_write(rs, rss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief initialize one rtp sub-socket */
|
||||
static void init_rss(struct rtp_sub_socket *rss,
|
||||
struct rtp_socket *rs, int fd, int priv_nr)
|
||||
{
|
||||
/* initialize bfd */
|
||||
rss->bfd.fd = fd;
|
||||
rss->bfd.data = rs;
|
||||
rss->bfd.priv_nr = priv_nr;
|
||||
rss->bfd.cb = rtp_bfd_cb;
|
||||
}
|
||||
|
||||
/*! \brief create a new RTP/RTCP socket and bind it */
|
||||
struct rtp_socket *rtp_socket_create(void)
|
||||
{
|
||||
int rc;
|
||||
struct rtp_socket *rs;
|
||||
|
||||
DEBUGP(DLMUX, "rtp_socket_create(): ");
|
||||
|
||||
rs = talloc_zero(tall_bsc_ctx, struct rtp_socket);
|
||||
if (!rs)
|
||||
return NULL;
|
||||
|
||||
INIT_LLIST_HEAD(&rs->rtp.tx_queue);
|
||||
INIT_LLIST_HEAD(&rs->rtcp.tx_queue);
|
||||
|
||||
rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (rc < 0)
|
||||
goto out_free;
|
||||
|
||||
init_rss(&rs->rtp, rs, rc, RTP_PRIV_RTP);
|
||||
rc = osmo_fd_register(&rs->rtp.bfd);
|
||||
if (rc < 0)
|
||||
goto out_rtp_socket;
|
||||
|
||||
rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (rc < 0)
|
||||
goto out_rtp_bfd;
|
||||
|
||||
init_rss(&rs->rtcp, rs, rc, RTP_PRIV_RTCP);
|
||||
rc = osmo_fd_register(&rs->rtcp.bfd);
|
||||
if (rc < 0)
|
||||
goto out_rtcp_socket;
|
||||
|
||||
DEBUGPC(DLMUX, "success\n");
|
||||
|
||||
rc = rtp_socket_bind(rs, INADDR_ANY);
|
||||
if (rc < 0)
|
||||
goto out_rtcp_bfd;
|
||||
|
||||
return rs;
|
||||
|
||||
out_rtcp_bfd:
|
||||
osmo_fd_unregister(&rs->rtcp.bfd);
|
||||
out_rtcp_socket:
|
||||
close(rs->rtcp.bfd.fd);
|
||||
out_rtp_bfd:
|
||||
osmo_fd_unregister(&rs->rtp.bfd);
|
||||
out_rtp_socket:
|
||||
close(rs->rtp.bfd.fd);
|
||||
out_free:
|
||||
talloc_free(rs);
|
||||
DEBUGPC(DLMUX, "failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int rtp_sub_socket_bind(struct rtp_sub_socket *rss, uint32_t ip,
|
||||
uint16_t port)
|
||||
{
|
||||
int rc;
|
||||
socklen_t alen = sizeof(rss->sin_local);
|
||||
|
||||
rss->sin_local.sin_family = AF_INET;
|
||||
rss->sin_local.sin_addr.s_addr = htonl(ip);
|
||||
rss->sin_local.sin_port = htons(port);
|
||||
rss->bfd.when |= BSC_FD_READ;
|
||||
|
||||
rc = bind(rss->bfd.fd, (struct sockaddr *)&rss->sin_local,
|
||||
sizeof(rss->sin_local));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* retrieve the address we actually bound to, in case we
|
||||
* passed INADDR_ANY as IP address */
|
||||
return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local,
|
||||
&alen);
|
||||
}
|
||||
|
||||
#define RTP_PORT_BASE 30000
|
||||
static unsigned int next_udp_port = RTP_PORT_BASE;
|
||||
|
||||
/*! \brief bind a RTP socket to a specific local address
|
||||
* \param[in] rs RTP socket to be bound
|
||||
* \param[in] ip local IP address to which socket is to be bound
|
||||
*/
|
||||
int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip)
|
||||
{
|
||||
int rc = -EIO;
|
||||
struct in_addr ia;
|
||||
|
||||
ia.s_addr = htonl(ip);
|
||||
DEBUGP(DLMUX, "rtp_socket_bind(rs=%p, IP=%s): ", rs,
|
||||
inet_ntoa(ia));
|
||||
|
||||
/* try to bind to a consecutive pair of ports */
|
||||
for (next_udp_port = next_udp_port % 0xffff;
|
||||
next_udp_port < 0xffff; next_udp_port += 2) {
|
||||
rc = rtp_sub_socket_bind(&rs->rtp, ip, next_udp_port);
|
||||
if (rc != 0)
|
||||
continue;
|
||||
|
||||
rc = rtp_sub_socket_bind(&rs->rtcp, ip, next_udp_port+1);
|
||||
if (rc == 0)
|
||||
break;
|
||||
}
|
||||
if (rc < 0) {
|
||||
DEBUGPC(DLMUX, "failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
ia.s_addr = rs->rtp.sin_local.sin_addr.s_addr;
|
||||
DEBUGPC(DLMUX, "BOUND_IP=%s, BOUND_PORT=%u\n",
|
||||
inet_ntoa(ia), ntohs(rs->rtp.sin_local.sin_port));
|
||||
return ntohs(rs->rtp.sin_local.sin_port);
|
||||
}
|
||||
|
||||
static int rtp_sub_socket_connect(struct rtp_sub_socket *rss,
|
||||
uint32_t ip, uint16_t port)
|
||||
{
|
||||
int rc;
|
||||
socklen_t alen = sizeof(rss->sin_local);
|
||||
|
||||
rss->sin_remote.sin_family = AF_INET;
|
||||
rss->sin_remote.sin_addr.s_addr = htonl(ip);
|
||||
rss->sin_remote.sin_port = htons(port);
|
||||
|
||||
rc = connect(rss->bfd.fd, (struct sockaddr *) &rss->sin_remote,
|
||||
sizeof(rss->sin_remote));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local,
|
||||
&alen);
|
||||
}
|
||||
|
||||
/*! \brief 'connect' a RTP socket to a remote peer
|
||||
* \param[in] rs RTP socket to be connected
|
||||
* \param[in] ip remote IP address to which to connect
|
||||
* \param[in] port remote UDP port number to which to connect
|
||||
*/
|
||||
int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port)
|
||||
{
|
||||
int rc;
|
||||
struct in_addr ia;
|
||||
|
||||
ia.s_addr = htonl(ip);
|
||||
DEBUGP(DLMUX, "rtp_socket_connect(rs=%p, ip=%s, port=%u)\n",
|
||||
rs, inet_ntoa(ia), port);
|
||||
|
||||
rc = rtp_sub_socket_connect(&rs->rtp, ip, port);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return rtp_sub_socket_connect(&rs->rtcp, ip, port+1);
|
||||
}
|
||||
|
||||
/*! \brief bind two RTP/RTCP sockets together in the proxy
|
||||
* \param[in] this First RTP socket
|
||||
* \param[in] other Second RTP socket
|
||||
*/
|
||||
int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other)
|
||||
{
|
||||
DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, other=%p)\n",
|
||||
this, other);
|
||||
|
||||
this->rx_action = RTP_PROXY;
|
||||
this->proxy.other_sock = other;
|
||||
|
||||
other->rx_action = RTP_PROXY;
|
||||
other->proxy.other_sock = this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief bind RTP/RTCP socket to application, disabling proxy
|
||||
* \param[in] this RTP socket
|
||||
* \param[in] net gsm_network argument to trau_tx_to_mncc()
|
||||
* \param[in] callref callref argument to trau_tx_to_mncc()
|
||||
*/
|
||||
int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net,
|
||||
uint32_t callref)
|
||||
{
|
||||
DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, callref=%u)\n",
|
||||
this, callref);
|
||||
|
||||
if (callref) {
|
||||
this->rx_action = RTP_RECV_UPSTREAM;
|
||||
this->receive.net = net;
|
||||
this->receive.callref = callref;
|
||||
} else
|
||||
this->rx_action = RTP_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_tx_queue(struct rtp_sub_socket *rss)
|
||||
{
|
||||
struct msgb *msg;
|
||||
|
||||
while ((msg = msgb_dequeue(&rss->tx_queue)))
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
/*! \brief Free/release a previously allocated RTP socket
|
||||
* \param[in[] rs RTP/RTCP socket to be released
|
||||
*/
|
||||
int rtp_socket_free(struct rtp_socket *rs)
|
||||
{
|
||||
DEBUGP(DLMUX, "rtp_socket_free(rs=%p)\n", rs);
|
||||
|
||||
/* make sure we don't leave references dangling to us */
|
||||
if (rs->rx_action == RTP_PROXY &&
|
||||
rs->proxy.other_sock)
|
||||
rs->proxy.other_sock->proxy.other_sock = NULL;
|
||||
|
||||
osmo_fd_unregister(&rs->rtp.bfd);
|
||||
close(rs->rtp.bfd.fd);
|
||||
free_tx_queue(&rs->rtp);
|
||||
|
||||
osmo_fd_unregister(&rs->rtcp.bfd);
|
||||
close(rs->rtcp.bfd.fd);
|
||||
free_tx_queue(&rs->rtcp);
|
||||
|
||||
talloc_free(rs);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,547 +0,0 @@
|
|||
/* Simple TRAU frame reflector to route voice calls */
|
||||
|
||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/abis/trau_frame.h>
|
||||
#include <osmocom/bsc/trau_mux.h>
|
||||
#include <osmocom/abis/subchan_demux.h>
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/bsc/trau_upqueue.h>
|
||||
#include <osmocom/core/crcgen.h>
|
||||
#include <osmocom/bsc/transaction.h>
|
||||
|
||||
/* this corresponds to the bit-lengths of the individual codec
|
||||
* parameters as indicated in Table 1.1 of TS 06.10 */
|
||||
static const uint8_t gsm_fr_map[] = {
|
||||
6, 6, 5, 5, 4, 4, 3, 3,
|
||||
7, 2, 2, 6, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 7, 2, 2, 6, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 7, 2, 2, 6, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 7, 2, 2, 6, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* EFR TRAU parity
|
||||
*
|
||||
* g(x) = x^3 + x^1 + 1
|
||||
*/
|
||||
static const struct osmo_crc8gen_code gsm0860_efr_crc3 = {
|
||||
.bits = 3,
|
||||
.poly = 0x3,
|
||||
.init = 0x0,
|
||||
.remainder = 0x7,
|
||||
};
|
||||
|
||||
/* EFR parity bits */
|
||||
static inline void efr_parity_bits_1(ubit_t *check_bits, const ubit_t *d_bits)
|
||||
{
|
||||
memcpy(check_bits + 0 , d_bits + 0, 22);
|
||||
memcpy(check_bits + 22 , d_bits + 24, 3);
|
||||
check_bits[25] = d_bits[28];
|
||||
}
|
||||
|
||||
static inline void efr_parity_bits_2(ubit_t *check_bits, const ubit_t *d_bits)
|
||||
{
|
||||
memcpy(check_bits + 0 , d_bits + 42, 10);
|
||||
memcpy(check_bits + 10 , d_bits + 90, 2);
|
||||
}
|
||||
|
||||
static inline void efr_parity_bits_3(ubit_t *check_bits, const ubit_t *d_bits)
|
||||
{
|
||||
memcpy(check_bits + 0 , d_bits + 98, 5);
|
||||
check_bits[5] = d_bits[104];
|
||||
memcpy(check_bits + 6 , d_bits + 143, 2);
|
||||
}
|
||||
|
||||
static inline void efr_parity_bits_4(ubit_t *check_bits, const ubit_t *d_bits)
|
||||
{
|
||||
memcpy(check_bits + 0 , d_bits + 151, 10);
|
||||
memcpy(check_bits + 10 , d_bits + 199, 2);
|
||||
}
|
||||
|
||||
static inline void efr_parity_bits_5(ubit_t *check_bits, const ubit_t *d_bits)
|
||||
{
|
||||
memcpy(check_bits + 0 , d_bits + 207, 5);
|
||||
check_bits[5] = d_bits[213];
|
||||
memcpy(check_bits + 6 , d_bits + 252, 2);
|
||||
}
|
||||
|
||||
struct map_entry {
|
||||
struct llist_head list;
|
||||
struct gsm_e1_subslot src, dst;
|
||||
};
|
||||
|
||||
struct upqueue_entry {
|
||||
struct llist_head list;
|
||||
struct gsm_network *net;
|
||||
struct gsm_e1_subslot src;
|
||||
uint32_t callref;
|
||||
};
|
||||
|
||||
static LLIST_HEAD(ss_map);
|
||||
static LLIST_HEAD(ss_upqueue);
|
||||
|
||||
void *tall_map_ctx, *tall_upq_ctx;
|
||||
|
||||
/* map one particular subslot to another subslot */
|
||||
int trau_mux_map(const struct gsm_e1_subslot *src,
|
||||
const struct gsm_e1_subslot *dst)
|
||||
{
|
||||
struct map_entry *me;
|
||||
|
||||
me = talloc(tall_map_ctx, struct map_entry);
|
||||
if (!me) {
|
||||
LOGP(DLMIB, LOGL_FATAL, "Out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGP(DCC, "Setting up TRAU mux map between (e1=%u,ts=%u,ss=%u) "
|
||||
"and (e1=%u,ts=%u,ss=%u)\n",
|
||||
src->e1_nr, src->e1_ts, src->e1_ts_ss,
|
||||
dst->e1_nr, dst->e1_ts, dst->e1_ts_ss);
|
||||
|
||||
/* make sure to get rid of any stale old mappings */
|
||||
trau_mux_unmap(src, 0);
|
||||
trau_mux_unmap(dst, 0);
|
||||
|
||||
memcpy(&me->src, src, sizeof(me->src));
|
||||
memcpy(&me->dst, dst, sizeof(me->dst));
|
||||
llist_add(&me->list, &ss_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trau_mux_map_lchan(const struct gsm_lchan *src,
|
||||
const struct gsm_lchan *dst)
|
||||
{
|
||||
struct gsm_e1_subslot *src_ss, *dst_ss;
|
||||
|
||||
src_ss = &src->ts->e1_link;
|
||||
dst_ss = &dst->ts->e1_link;
|
||||
|
||||
return trau_mux_map(src_ss, dst_ss);
|
||||
}
|
||||
|
||||
|
||||
/* unmap one particular subslot from another subslot */
|
||||
int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref)
|
||||
{
|
||||
struct map_entry *me, *me2;
|
||||
struct upqueue_entry *ue, *ue2;
|
||||
|
||||
if (ss)
|
||||
llist_for_each_entry_safe(me, me2, &ss_map, list) {
|
||||
if (!memcmp(&me->src, ss, sizeof(*ss)) ||
|
||||
!memcmp(&me->dst, ss, sizeof(*ss))) {
|
||||
llist_del(&me->list);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
llist_for_each_entry_safe(ue, ue2, &ss_upqueue, list) {
|
||||
if (ue->callref == callref) {
|
||||
llist_del(&ue->list);
|
||||
return 0;
|
||||
}
|
||||
if (ss && !memcmp(&ue->src, ss, sizeof(*ss))) {
|
||||
llist_del(&ue->list);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* look-up an enty in the TRAU mux map */
|
||||
static struct gsm_e1_subslot *
|
||||
lookup_trau_mux_map(const struct gsm_e1_subslot *src)
|
||||
{
|
||||
struct map_entry *me;
|
||||
|
||||
llist_for_each_entry(me, &ss_map, list) {
|
||||
if (!memcmp(&me->src, src, sizeof(*src)))
|
||||
return &me->dst;
|
||||
if (!memcmp(&me->dst, src, sizeof(*src)))
|
||||
return &me->src;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look-up an enty in the TRAU upqueue */
|
||||
struct upqueue_entry *
|
||||
lookup_trau_upqueue(const struct gsm_e1_subslot *src)
|
||||
{
|
||||
struct upqueue_entry *ue;
|
||||
|
||||
llist_for_each_entry(ue, &ss_upqueue, list) {
|
||||
if (!memcmp(&ue->src, src, sizeof(*src)))
|
||||
return ue;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const uint8_t c_bits_check_fr[] = { 0, 0, 0, 1, 0 };
|
||||
static const uint8_t c_bits_check_efr[] = { 1, 1, 0, 1, 0 };
|
||||
|
||||
struct msgb *trau_decode_fr(uint32_t callref,
|
||||
const struct decoded_trau_frame *tf)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct gsm_data_frame *frame;
|
||||
unsigned char *data;
|
||||
int i, j, k, l, o;
|
||||
|
||||
msg = msgb_alloc(sizeof(struct gsm_data_frame) + 33,
|
||||
"GSM-DATA");
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
frame = (struct gsm_data_frame *)msg->data;
|
||||
memset(frame, 0, sizeof(struct gsm_data_frame));
|
||||
data = frame->data;
|
||||
data[0] = 0xd << 4;
|
||||
/* reassemble d-bits */
|
||||
i = 0; /* counts bits */
|
||||
j = 4; /* counts output bits */
|
||||
k = gsm_fr_map[0]-1; /* current number bit in element */
|
||||
l = 0; /* counts element bits */
|
||||
o = 0; /* offset input bits */
|
||||
while (i < 260) {
|
||||
data[j/8] |= (tf->d_bits[k+o] << (7-(j%8)));
|
||||
/* to avoid out-of-bounds access in gsm_fr_map[++l] */
|
||||
if (i == 259)
|
||||
break;
|
||||
if (--k < 0) {
|
||||
o += gsm_fr_map[l];
|
||||
k = gsm_fr_map[++l]-1;
|
||||
}
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
if (tf->c_bits[11]) /* BFI */
|
||||
frame->msg_type = GSM_BAD_FRAME;
|
||||
else
|
||||
frame->msg_type = GSM_TCHF_FRAME;
|
||||
frame->callref = callref;
|
||||
msgb_put(msg, sizeof(struct gsm_data_frame) + 33);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
struct msgb *trau_decode_efr(uint32_t callref,
|
||||
const struct decoded_trau_frame *tf)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct gsm_data_frame *frame;
|
||||
unsigned char *data;
|
||||
int i, j, rc;
|
||||
ubit_t check_bits[26];
|
||||
|
||||
msg = msgb_alloc(sizeof(struct gsm_data_frame) + 31,
|
||||
"GSM-DATA");
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
frame = (struct gsm_data_frame *)msg->data;
|
||||
memset(frame, 0, sizeof(struct gsm_data_frame));
|
||||
frame->msg_type = GSM_TCHF_FRAME_EFR;
|
||||
frame->callref = callref;
|
||||
msgb_put(msg, sizeof(struct gsm_data_frame) + 31);
|
||||
|
||||
if (tf->c_bits[11]) /* BFI */
|
||||
goto bad_frame;
|
||||
|
||||
data = frame->data;
|
||||
data[0] = 0xc << 4;
|
||||
/* reassemble d-bits */
|
||||
for (i = 1, j = 4; i < 39; i++, j++)
|
||||
data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
|
||||
efr_parity_bits_1(check_bits, tf->d_bits);
|
||||
rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 26,
|
||||
tf->d_bits + 39);
|
||||
if (rc)
|
||||
goto bad_frame;
|
||||
for (i = 42, j = 42; i < 95; i++, j++)
|
||||
data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
|
||||
efr_parity_bits_2(check_bits, tf->d_bits);
|
||||
rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
|
||||
tf->d_bits + 95);
|
||||
if (rc)
|
||||
goto bad_frame;
|
||||
for (i = 98, j = 95; i < 148; i++, j++)
|
||||
data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
|
||||
efr_parity_bits_3(check_bits, tf->d_bits);
|
||||
rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
|
||||
tf->d_bits + 148);
|
||||
if (rc)
|
||||
goto bad_frame;
|
||||
for (i = 151, j = 145; i < 204; i++, j++)
|
||||
data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
|
||||
efr_parity_bits_4(check_bits, tf->d_bits);
|
||||
rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
|
||||
tf->d_bits + 204);
|
||||
if (rc)
|
||||
goto bad_frame;
|
||||
for (i = 207, j = 198; i < 257; i++, j++)
|
||||
data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
|
||||
efr_parity_bits_5(check_bits, tf->d_bits);
|
||||
rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
|
||||
tf->d_bits + 257);
|
||||
if (rc)
|
||||
goto bad_frame;
|
||||
|
||||
return msg;
|
||||
|
||||
bad_frame:
|
||||
frame->msg_type = GSM_BAD_FRAME;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* we get called by subchan_demux */
|
||||
int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
|
||||
const uint8_t *trau_bits, int num_bits)
|
||||
{
|
||||
struct decoded_trau_frame tf;
|
||||
uint8_t trau_bits_out[TRAU_FRAME_BITS];
|
||||
struct gsm_e1_subslot *dst_e1_ss = lookup_trau_mux_map(src_e1_ss);
|
||||
struct subch_mux *mx;
|
||||
struct upqueue_entry *ue;
|
||||
int rc;
|
||||
|
||||
/* decode TRAU, change it to downlink, re-encode */
|
||||
rc = decode_trau_frame(&tf, trau_bits);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!dst_e1_ss) {
|
||||
struct msgb *msg = NULL;
|
||||
/* frame shall be sent to upqueue */
|
||||
if (!(ue = lookup_trau_upqueue(src_e1_ss)))
|
||||
return -EINVAL;
|
||||
if (!ue->callref)
|
||||
return -EINVAL;
|
||||
if (!memcmp(tf.c_bits, c_bits_check_fr, 5))
|
||||
msg = trau_decode_fr(ue->callref, &tf);
|
||||
else if (!memcmp(tf.c_bits, c_bits_check_efr, 5))
|
||||
msg = trau_decode_efr(ue->callref, &tf);
|
||||
else {
|
||||
DEBUGPC(DLMUX, "illegal trau (C1-C5) %s\n",
|
||||
osmo_hexdump(tf.c_bits, 5));
|
||||
DEBUGPC(DLMUX, "test trau (C1-C5) %s\n",
|
||||
osmo_hexdump(c_bits_check_efr, 5));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
trau_tx_to_mncc(ue->net, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
mx = e1inp_get_mux(dst_e1_ss->e1_nr, dst_e1_ss->e1_ts);
|
||||
if (!mx)
|
||||
return -EINVAL;
|
||||
|
||||
trau_frame_up2down(&tf);
|
||||
encode_trau_frame(trau_bits_out, &tf);
|
||||
|
||||
/* and send it to the muxer */
|
||||
return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
|
||||
TRAU_FRAME_BITS);
|
||||
}
|
||||
|
||||
/* callback when a TRAU frame was received */
|
||||
int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len,
|
||||
void *_priv)
|
||||
{
|
||||
struct e1inp_ts *e1i_ts = _priv;
|
||||
struct gsm_e1_subslot src_ss;
|
||||
|
||||
src_ss.e1_nr = e1i_ts->line->num;
|
||||
src_ss.e1_ts = e1i_ts->num;
|
||||
src_ss.e1_ts_ss = ch;
|
||||
|
||||
return trau_mux_input(&src_ss, data, len);
|
||||
}
|
||||
|
||||
/* add receiver instance for lchan and callref */
|
||||
int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref)
|
||||
{
|
||||
struct gsm_e1_subslot *src_ss;
|
||||
struct upqueue_entry *ue;
|
||||
|
||||
ue = talloc(tall_upq_ctx, struct upqueue_entry);
|
||||
if (!ue)
|
||||
return -ENOMEM;
|
||||
|
||||
src_ss = &lchan->ts->e1_link;
|
||||
|
||||
DEBUGP(DCC, "Setting up TRAU receiver (e1=%u,ts=%u,ss=%u) "
|
||||
"and (callref 0x%x)\n",
|
||||
src_ss->e1_nr, src_ss->e1_ts, src_ss->e1_ts_ss,
|
||||
callref);
|
||||
|
||||
/* make sure to get rid of any stale old mappings */
|
||||
trau_mux_unmap(src_ss, callref);
|
||||
|
||||
memcpy(&ue->src, src_ss, sizeof(ue->src));
|
||||
ue->net = lchan->ts->trx->bts->network;
|
||||
ue->callref = callref;
|
||||
llist_add(&ue->list, &ss_upqueue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void trau_encode_fr(struct decoded_trau_frame *tf,
|
||||
const unsigned char *data)
|
||||
{
|
||||
int i, j, k, l, o;
|
||||
|
||||
/* set c-bits and t-bits */
|
||||
tf->c_bits[0] = 1;
|
||||
tf->c_bits[1] = 1;
|
||||
tf->c_bits[2] = 1;
|
||||
tf->c_bits[3] = 0;
|
||||
tf->c_bits[4] = 0;
|
||||
memset(&tf->c_bits[5], 0, 6);
|
||||
memset(&tf->c_bits[11], 1, 10);
|
||||
memset(&tf->t_bits[0], 1, 4);
|
||||
/* reassemble d-bits */
|
||||
i = 0; /* counts bits */
|
||||
j = 4; /* counts input bits */
|
||||
k = gsm_fr_map[0]-1; /* current number bit in element */
|
||||
l = 0; /* counts element bits */
|
||||
o = 0; /* offset output bits */
|
||||
while (i < 260) {
|
||||
tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1;
|
||||
/* to avoid out-of-bounds access in gsm_fr_map[++l] */
|
||||
if (i == 259)
|
||||
break;
|
||||
if (--k < 0) {
|
||||
o += gsm_fr_map[l];
|
||||
k = gsm_fr_map[++l]-1;
|
||||
}
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
void trau_encode_efr(struct decoded_trau_frame *tf,
|
||||
const unsigned char *data)
|
||||
{
|
||||
int i, j;
|
||||
ubit_t check_bits[26];
|
||||
|
||||
/* set c-bits and t-bits */
|
||||
tf->c_bits[0] = 1;
|
||||
tf->c_bits[1] = 1;
|
||||
tf->c_bits[2] = 0;
|
||||
tf->c_bits[3] = 1;
|
||||
tf->c_bits[4] = 0;
|
||||
memset(&tf->c_bits[5], 0, 6);
|
||||
memset(&tf->c_bits[11], 1, 10);
|
||||
memset(&tf->t_bits[0], 1, 4);
|
||||
/* reassemble d-bits */
|
||||
tf->d_bits[0] = 1;
|
||||
for (i = 1, j = 4; i < 39; i++, j++)
|
||||
tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
|
||||
efr_parity_bits_1(check_bits, tf->d_bits);
|
||||
osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 26,
|
||||
tf->d_bits + 39);
|
||||
for (i = 42, j = 42; i < 95; i++, j++)
|
||||
tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
|
||||
efr_parity_bits_2(check_bits, tf->d_bits);
|
||||
osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
|
||||
tf->d_bits + 95);
|
||||
for (i = 98, j = 95; i < 148; i++, j++)
|
||||
tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
|
||||
efr_parity_bits_3(check_bits, tf->d_bits);
|
||||
osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
|
||||
tf->d_bits + 148);
|
||||
for (i = 151, j = 145; i < 204; i++, j++)
|
||||
tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
|
||||
efr_parity_bits_4(check_bits, tf->d_bits);
|
||||
osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
|
||||
tf->d_bits + 204);
|
||||
for (i = 207, j = 198; i < 257; i++, j++)
|
||||
tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
|
||||
efr_parity_bits_5(check_bits, tf->d_bits);
|
||||
osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
|
||||
tf->d_bits + 257);
|
||||
}
|
||||
|
||||
int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame)
|
||||
{
|
||||
uint8_t trau_bits_out[TRAU_FRAME_BITS];
|
||||
struct gsm_e1_subslot *dst_e1_ss = &lchan->ts->e1_link;
|
||||
struct subch_mux *mx;
|
||||
struct decoded_trau_frame tf;
|
||||
|
||||
mx = e1inp_get_mux(dst_e1_ss->e1_nr, dst_e1_ss->e1_ts);
|
||||
if (!mx)
|
||||
return -EINVAL;
|
||||
|
||||
switch (frame->msg_type) {
|
||||
case GSM_TCHF_FRAME:
|
||||
trau_encode_fr(&tf, frame->data);
|
||||
break;
|
||||
case GSM_TCHF_FRAME_EFR:
|
||||
trau_encode_efr(&tf, frame->data);
|
||||
break;
|
||||
default:
|
||||
DEBUGPC(DLMUX, "unsupported message type %d\n",
|
||||
frame->msg_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
encode_trau_frame(trau_bits_out, &tf);
|
||||
|
||||
/* and send it to the muxer */
|
||||
return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
|
||||
TRAU_FRAME_BITS);
|
||||
}
|
||||
|
||||
/* switch trau muxer to new lchan */
|
||||
int switch_trau_mux(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan)
|
||||
{
|
||||
struct gsm_network *net = old_lchan->ts->trx->bts->network;
|
||||
struct gsm_trans *trans;
|
||||
|
||||
/* look up transaction with TCH frame receive enabled */
|
||||
llist_for_each_entry(trans, &net->trans_list, entry) {
|
||||
if (trans->conn && trans->conn->lchan == old_lchan && trans->tch_recv) {
|
||||
/* switch */
|
||||
trau_recv_lchan(new_lchan, trans->callref);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/* trau_upqueue.c - Pass msgb's up the chain */
|
||||
|
||||
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/bsc/mncc.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
|
||||
void trau_tx_to_mncc(struct gsm_network *net, struct msgb *msg)
|
||||
{
|
||||
net->mncc_recv(net, msg);
|
||||
}
|
|
@ -40,12 +40,10 @@ osmo_bsc_SOURCES = \
|
|||
osmo_bsc_ctrl.c \
|
||||
$(NULL)
|
||||
|
||||
# once again since TRAU uses CC symbol :(
|
||||
osmo_bsc_LDADD = \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOSCCP_LIBS) \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <osmocom/bsc/osmo_bsc.h>
|
||||
#include <osmocom/bsc/bsc_msc_data.h>
|
||||
#include <osmocom/bsc/gsm_04_80.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/bsc/bsc_subscriber.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/bsc/paging.h>
|
||||
|
|
|
@ -201,7 +201,7 @@ int main(int argc, char **argv)
|
|||
osmo_stats_init(tall_bsc_ctx);
|
||||
|
||||
/* Allocate global gsm_network struct */
|
||||
rc = bsc_network_alloc(NULL);
|
||||
rc = bsc_network_alloc();
|
||||
if (rc) {
|
||||
fprintf(stderr, "Allocation failed. exiting.\n");
|
||||
exit(1);
|
||||
|
|
|
@ -42,7 +42,6 @@ osmo_bsc_nat_LDADD = \
|
|||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOSCCP_LIBS) \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <osmocom/bsc/bsc_nat.h>
|
||||
#include <osmocom/bsc/bsc_nat_sccp.h>
|
||||
#include <osmocom/bsc/ipaccess.h>
|
||||
|
|
|
@ -49,7 +49,6 @@ bs11_config_SOURCES = \
|
|||
bs11_config_LDADD = \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
|
|
|
@ -897,7 +897,7 @@ int main(int argc, char **argv)
|
|||
handle_options(argc, argv);
|
||||
bts_model_bs11_init();
|
||||
|
||||
gsmnet = bsc_network_init(tall_bs11cfg_ctx, 1, 1, NULL);
|
||||
gsmnet = bsc_network_init(tall_bs11cfg_ctx, 1, 1);
|
||||
if (!gsmnet) {
|
||||
fprintf(stderr, "Unable to allocate gsm network\n");
|
||||
exit(1);
|
||||
|
|
|
@ -3,7 +3,6 @@ SUBDIRS = \
|
|||
gsm0408 \
|
||||
channel \
|
||||
abis \
|
||||
trau \
|
||||
subscr \
|
||||
nanobts_omlattr \
|
||||
bsc-nat \
|
||||
|
|
|
@ -28,7 +28,6 @@ abis_test_LDADD = \
|
|||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOABIS_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
|
|
|
@ -11,7 +11,6 @@ noinst_PROGRAMS = bsc_nat_trie_test
|
|||
bsc_nat_trie_test_SOURCES = bsc_nat_trie_test.c \
|
||||
$(top_srcdir)/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c
|
||||
bsc_nat_trie_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -lrt \
|
||||
$(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) \
|
||||
|
|
|
@ -46,7 +46,6 @@ bsc_nat_test_LDADD = \
|
|||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
|
|
|
@ -34,7 +34,6 @@ bsc_test_SOURCES = \
|
|||
bsc_test_LDADD = \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <osmocom/bsc/osmo_bsc.h>
|
||||
#include <osmocom/bsc/bsc_msc_data.h>
|
||||
#include <osmocom/bsc/gsm_04_80.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/backtrace.h>
|
||||
|
|
|
@ -36,7 +36,6 @@ bssap_test_LDADD = \
|
|||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBOSMOABIS_LIBS) \
|
||||
|
|
|
@ -82,7 +82,7 @@ void test_cell_identifier()
|
|||
struct gsm_network *net;
|
||||
struct bsc_msc_data *msc;
|
||||
|
||||
net = bsc_network_init(NULL, 1, 1, NULL);
|
||||
net = bsc_network_init(NULL, 1, 1);
|
||||
net->bsc_data->rf_ctrl = talloc_zero(NULL, struct osmo_bsc_rf);
|
||||
net->bsc_data->rf_ctrl->policy = S_RF_ON;
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <osmocom/bsc/common_bsc.h>
|
||||
#include <osmocom/bsc/abis_rsl.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
|
||||
void test_bts_debug_print(void)
|
||||
{
|
||||
|
@ -39,7 +38,7 @@ void test_bts_debug_print(void)
|
|||
printf("Testing the lchan printing:");
|
||||
|
||||
/* Create a dummy network */
|
||||
network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
|
||||
network = bsc_network_init(tall_bsc_ctx, 1, 1);
|
||||
if (!network)
|
||||
exit(1);
|
||||
/* Add a BTS with some reasonanbly non-zero id */
|
||||
|
|
|
@ -25,7 +25,6 @@ gsm0408_test_SOURCES = \
|
|||
gsm0408_test_LDADD = \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocom/bsc/common_bsc.h>
|
||||
#include <osmocom/bsc/gsm_subscriber.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/gsm_data_shared.h>
|
||||
#include <osmocom/bsc/debug.h>
|
||||
#include <osmocom/bsc/arfcn_range_encode.h>
|
||||
|
@ -715,7 +715,7 @@ int main(int argc, char **argv)
|
|||
osmo_init_logging(&log_info);
|
||||
log_set_log_level(osmo_stderr_target, LOGL_INFO);
|
||||
|
||||
net = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
|
||||
net = bsc_network_init(tall_bsc_ctx, 1, 1);
|
||||
if (!net) {
|
||||
printf("Network init failure.\n");
|
||||
return EXIT_FAILURE;
|
||||
|
|
|
@ -24,7 +24,6 @@ nanobts_omlattr_test_SOURCES = \
|
|||
|
||||
nanobts_omlattr_test_LDADD = \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
|
|
|
@ -33,7 +33,6 @@ bsc_subscr_test_SOURCES = \
|
|||
bsc_subscr_test_LDADD = \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOABIS_LIBS) \
|
||||
|
|
|
@ -39,12 +39,6 @@ cat $abs_srcdir/bsc/bsc_test.ok > expout
|
|||
AT_CHECK([$abs_top_builddir/tests/bsc/bsc_test], [], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([trau])
|
||||
AT_KEYWORDS([trau])
|
||||
cat $abs_srcdir/trau/trau_test.ok > expout
|
||||
AT_CHECK([$abs_top_builddir/tests/trau/trau_test], [], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([nanobts_omlattr])
|
||||
AT_KEYWORDS([nanobts_omlattr])
|
||||
cat $abs_srcdir/nanobts_omlattr/nanobts_omlattr_test.ok > expout
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-ggdb3 \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(LIBOSMOABIS_CFLAGS) \
|
||||
$(LIBSMPP34_CFLAGS) \
|
||||
$(COVERAGE_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
AM_LDFLAGS = \
|
||||
$(COVERAGE_LDFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = \
|
||||
trau_test.ok \
|
||||
$(NULL)
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
trau_test \
|
||||
$(NULL)
|
||||
|
||||
trau_test_SOURCES = \
|
||||
trau_test.c \
|
||||
$(NULL)
|
||||
|
||||
trau_test_LDADD = \
|
||||
$(top_builddir)/src/libbsc/libbsc.a \
|
||||
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
|
||||
$(top_builddir)/src/libtrau/libtrau.a \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOABIS_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBSMPP34_LIBS) \
|
||||
$(LIBOSMOVTY_LIBS) \
|
||||
$(LIBRARY_DL) \
|
||||
$(NULL)
|
|
@ -1,84 +0,0 @@
|
|||
/* (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/abis/trau_frame.h>
|
||||
#include <osmocom/bsc/trau_mux.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void test_trau_fr_efr(unsigned char *data)
|
||||
{
|
||||
struct decoded_trau_frame tf;
|
||||
struct msgb *msg;
|
||||
struct gsm_data_frame *frame;
|
||||
|
||||
printf("Testing TRAU FR transcoding.\n");
|
||||
data[0] = 0xd0;
|
||||
trau_encode_fr(&tf, data);
|
||||
tf.c_bits[11] = 0; /* clear BFI */
|
||||
msg = trau_decode_fr(1, &tf);
|
||||
OSMO_ASSERT(msg != NULL);
|
||||
frame = (struct gsm_data_frame *)msg->data;
|
||||
OSMO_ASSERT(frame->msg_type == GSM_TCHF_FRAME);
|
||||
OSMO_ASSERT(!memcmp(frame->data, data, 33));
|
||||
msgb_free(msg);
|
||||
|
||||
printf("Testing TRAU EFR transcoding.\n");
|
||||
data[0] = 0xc0;
|
||||
trau_encode_efr(&tf, data);
|
||||
OSMO_ASSERT(tf.d_bits[0] == 1); /* spare bit must be 1 */
|
||||
tf.c_bits[11] = 0; /* clear BFI */
|
||||
msg = trau_decode_efr(1, &tf);
|
||||
OSMO_ASSERT(msg != NULL);
|
||||
frame = (struct gsm_data_frame *)msg->data;
|
||||
OSMO_ASSERT(frame->msg_type == GSM_TCHF_FRAME_EFR);
|
||||
OSMO_ASSERT(!memcmp(frame->data, data, 31));
|
||||
|
||||
printf("Testing TRAU EFR decoding with CRC error.\n");
|
||||
tf.d_bits[0] = 0; /* spare bit must be included */
|
||||
msg = trau_decode_efr(1, &tf);
|
||||
OSMO_ASSERT(msg != NULL);
|
||||
frame = (struct gsm_data_frame *)msg->data;
|
||||
OSMO_ASSERT(frame->msg_type == GSM_BAD_FRAME);
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned char data[33];
|
||||
int i;
|
||||
|
||||
msgb_talloc_ctx_init(NULL, 0);
|
||||
|
||||
memset(data, 0x00, sizeof(data));
|
||||
test_trau_fr_efr(data);
|
||||
memset(data, 0xff, sizeof(data));
|
||||
test_trau_fr_efr(data);
|
||||
srandom(42);
|
||||
for (i = 0; i < sizeof(data); i++)
|
||||
data[i] = random();
|
||||
test_trau_fr_efr(data);
|
||||
printf("Done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* stubs */
|
||||
void vty_out() {}
|
|
@ -1,10 +0,0 @@
|
|||
Testing TRAU FR transcoding.
|
||||
Testing TRAU EFR transcoding.
|
||||
Testing TRAU EFR decoding with CRC error.
|
||||
Testing TRAU FR transcoding.
|
||||
Testing TRAU EFR transcoding.
|
||||
Testing TRAU EFR decoding with CRC error.
|
||||
Testing TRAU FR transcoding.
|
||||
Testing TRAU EFR transcoding.
|
||||
Testing TRAU EFR decoding with CRC error.
|
||||
Done
|
Loading…
Reference in New Issue