236 lines
6.9 KiB
C
236 lines
6.9 KiB
C
|
|
#include <pthread.h>
|
|
#include <osmocom/core/timer.h>
|
|
#include <osmocom/core/select.h>
|
|
#include <osmocom/cc/endpoint.h>
|
|
#include <osmocom/cc/helper.h>
|
|
#include "../libsample/sample.h"
|
|
#include "../libjitter/jitter.h"
|
|
#include "../libph_socket/ph_socket.h"
|
|
#include "tones.h"
|
|
|
|
#define B_MODE_TRANSPARENT 0
|
|
#define B_MODE_HDLC 1
|
|
|
|
#define B_STATE_IDLE 0 /* not open */
|
|
#define B_STATE_ACTIVATING 1 /* DL_ESTABLISH sent */
|
|
#define B_STATE_ACTIVE 2 /* channel active */
|
|
#define B_STATE_DEACTIVATING 3 /* DL_RELEASE sent */
|
|
|
|
#define B_EVENT_USE 0 /* activate bchannel */
|
|
#define B_EVENT_ACTIVATED 1 /* DL_ESTABLISH received */
|
|
#define B_EVENT_DROP 2 /* deactivate bchannel */
|
|
#define B_EVENT_DEACTIVATED 3 /* DL_RELEASE received */
|
|
#define B_EVENT_TIMEOUT 4 /* timeout happed during (de)activation */
|
|
|
|
#define TONES_TYPE_AMERICAN 1
|
|
#define TONES_TYPE_GERMAN 2
|
|
#define TONES_TYPE_OLDGERMAN 3
|
|
|
|
#define DIRECTION_ORIGINATOR 0
|
|
#define DIRECTION_TERMINATOR 1
|
|
|
|
enum isdn_state {
|
|
ISDN_STATE_IDLE = 0, /* no call */
|
|
ISDN_STATE_IN_SETUP, /* incoming connection */
|
|
ISDN_STATE_OUT_SETUP, /* outgoing connection */
|
|
ISDN_STATE_IN_OVERLAP, /* more informatiopn needed */
|
|
ISDN_STATE_OUT_OVERLAP, /* more informatiopn needed */
|
|
ISDN_STATE_IN_PROCEEDING,/* call is proceeding */
|
|
ISDN_STATE_OUT_PROCEEDING,/* call is proceeding */
|
|
ISDN_STATE_IN_ALERTING, /* call is ringing */
|
|
ISDN_STATE_OUT_ALERTING,/* call is ringing */
|
|
ISDN_STATE_IN_CONNECTING,/* wait for ack after answer */
|
|
ISDN_STATE_OUT_CONNECTING,/* wait for ack after answer */
|
|
ISDN_STATE_CONNECT, /* call is connected and transmission is enabled */
|
|
ISDN_STATE_IN_DISCONNECT,/* incoming disconnected */
|
|
ISDN_STATE_OUT_DISCONNECT,/* outgoing disconnected */
|
|
ISDN_STATE_OUT_RELEASE, /* call released */
|
|
ISDN_STATE_SUSPENDED, /* call suspended */
|
|
};
|
|
|
|
struct isdn;
|
|
|
|
struct b_timer_inst {
|
|
struct isdn *isdn_ep;
|
|
int index;
|
|
};
|
|
|
|
struct msn_list {
|
|
struct msn_list *next;
|
|
char msn[0];
|
|
};
|
|
|
|
struct select_channel {
|
|
struct select_channel *next;
|
|
int channel;
|
|
};
|
|
|
|
struct isdn;
|
|
|
|
struct isdn_b_sock {
|
|
int index;
|
|
struct isdn *isdn_ep;
|
|
struct osmo_fd ofd;
|
|
};
|
|
|
|
struct call_list;
|
|
|
|
typedef struct isdn {
|
|
struct call_list *call_list;
|
|
struct msn_list *msn_list;
|
|
|
|
/* settings */
|
|
char law;
|
|
struct select_channel *out_channel; /* list of outgoing channels to select */
|
|
struct select_channel *in_channel; /* the same for incoming channels */
|
|
int out_channel_exclusive; /* force channel */
|
|
int serving_location; /* who we serve when sending causes towards interface */
|
|
const char *timeouts;
|
|
int tx_delay;
|
|
int local_tones;
|
|
/* metering/AOC-D/AOC-S */
|
|
int aocd;
|
|
int aocs;
|
|
|
|
/* osmo-cc */
|
|
struct osmo_cc_endpoint cc_ep;
|
|
|
|
/* mISDN */
|
|
char *portname;
|
|
int portnum;
|
|
int ntmode;
|
|
int ptp;
|
|
int pri;
|
|
int l1hold;
|
|
int l2hold;
|
|
int l2sock;
|
|
void *l2inst;
|
|
ph_socket_t *ph_socket;
|
|
pthread_mutex_t upqueue_lock;
|
|
struct mqueue upqueue;
|
|
int upqueue_initialized;
|
|
int upqueue_pipe[2];
|
|
struct osmo_fd upqueue_ofd;
|
|
struct mlayer3 *ml3;
|
|
int los, ais, rdi, slip_rx, slip_tx;
|
|
int l1link; /* current state */
|
|
int l2link; /* current state */
|
|
struct osmo_timer_list l2establish_timer;
|
|
int b_num;
|
|
int b_reserved;
|
|
int b_mode[128];
|
|
int b_state[128];
|
|
struct isdn_b_sock b_sock[128];
|
|
struct call_list *b_call[128];
|
|
struct osmo_timer_list b_timer[128];
|
|
struct b_timer_inst b_timer_inst[128];
|
|
uint8_t b_buffer[128][160];
|
|
int b_buffer_pos[128];
|
|
unsigned char l2mask[16]; /* 128 bits for each tei */
|
|
|
|
/* bridging */
|
|
int bridge_possible;
|
|
int bridge_cardnum;
|
|
int bridge_portnum;
|
|
|
|
/* clock for tone on hold */
|
|
struct osmo_timer_list clock_timer;
|
|
double last_time_clock;
|
|
} isdn_t;
|
|
|
|
typedef struct call_list {
|
|
struct call_list *next;
|
|
isdn_t *isdn_ep;
|
|
|
|
/* mISDN states */
|
|
uint32_t l3_pid;
|
|
uint16_t l3_ces;
|
|
|
|
/* tone states */
|
|
struct isdn_tone isdn_tone;
|
|
|
|
/* osmo-cc states */
|
|
uint32_t cc_callref;
|
|
osmo_cc_session_t *cc_session;
|
|
osmo_cc_session_codec_t *codec;
|
|
const char *sdp;
|
|
char codec_law;
|
|
int codec_negotiated;
|
|
int audio_path;
|
|
|
|
/* bchannel states */
|
|
int b_index;
|
|
int b_channel;
|
|
int b_exclusive;
|
|
int b_reserve;
|
|
int b_mode;
|
|
int b_transmitting;
|
|
double b_rx_time;
|
|
|
|
/* call states */
|
|
int direction; /* originator or terminator of call */
|
|
enum isdn_state state;
|
|
int any_dialing; /* if any digit was dialed, we track this for dial tone */
|
|
int channel_negotiated;
|
|
int send_local_tones; /* using locally generated tones, because upper layer does not provide them */
|
|
int send_remote_tones; /* using remote tones, as we received a progress indicator 1 or 8 from upper layer */
|
|
int proceeding_sent;
|
|
int sending_complete; /* send proceeding when osmo-cc requests overlap */
|
|
int setup_comp_req_channel_assignment; /* must assign channel on setup comp req */
|
|
uint8_t collect_cause, collect_location;
|
|
int hold; /* if call is on hold */
|
|
int conference_3pty; /* if call is the active call in a 3pty conference */
|
|
int park_len;
|
|
uint8_t park_callid[8];
|
|
/* metering/AOC-D/AOC-S */
|
|
struct osmo_timer_list aocd_unit_timer;
|
|
int aocd_unit_timer_started;
|
|
int metering_info_received;
|
|
uint16_t metering_connect_units;
|
|
uint16_t metering_unit_period_decisecs;
|
|
uint16_t metering_total_units;
|
|
|
|
/* bridge states */
|
|
int can_bridge; /* last state sent to the server */
|
|
int bridge_enabled; /* last state received by the server */
|
|
int bridge_bank_tx;
|
|
int bridge_slot_tx;
|
|
int bridge_bank_rx;
|
|
int bridge_slot_rx;
|
|
|
|
/* jitter buffer for tx and 3pty call */
|
|
jitter_t tx_dejitter;
|
|
jitter_t conf_dejitter;
|
|
|
|
} call_t;
|
|
|
|
/* channel selection */
|
|
int hunt_bchannel_in(isdn_t *isdn_ep, int channel, int exclusive);
|
|
int hunt_bchannel_out(isdn_t *isdn_ep, int *channel, int *exclusive);
|
|
int open_bchannel_in(call_t *call, int channel, int exclusive);
|
|
int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive);
|
|
|
|
/* isdn instance */
|
|
isdn_t *isdn_create(void);
|
|
void isdn_destroy(isdn_t *isdn_ep);
|
|
int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int local_tones, int serving_location, int aocd, int aocs);
|
|
int isdn_open(isdn_t *isdn_ep);
|
|
void isdn_close(isdn_t *isdn_ep);
|
|
void isdn_add_msn(isdn_t *isdn_ep, const char *msn);
|
|
|
|
/* call instance */
|
|
call_t *call_create(isdn_t *isdn_ep, int direction, int channel, int exclusive, int mode);
|
|
void call_create_jitter(call_t *call, int data);
|
|
void call_destroy(call_t *call);
|
|
|
|
/* channel allocation and handling */
|
|
void bchannel_tone(call_t *call, int tone);
|
|
void bchannel_bridge(call_t *call, int pcm_bridge, int rx_slot, int tx_slot, int rx_bank, int tx_bank);
|
|
void bchannel_event(isdn_t *isdn_ep, int index, int event);
|
|
int seize_bchannel(call_t *call, int channel, int exclusive);
|
|
void drop_bchannel(call_t *call);
|
|
void rtp_receive(struct osmo_cc_session_codec *codec, uint8_t marker, uint16_t sequence_number, uint32_t timestamp, uint32_t ssrc, uint8_t *data, int len);
|
|
void enable_hold_clock(isdn_t *isdn_ep);
|
|
|