git-svn-id: http://svn.openzap.org/svn/openzap/trunk@416 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
Anthony Minessale 2008-02-29 00:21:04 +00:00
parent 5e56f09d92
commit 1d3f79cddc
11 changed files with 633 additions and 45 deletions

View File

@ -29,7 +29,7 @@
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
CFLAGS=@COMP_VENDOR_CFLAGS@
CFLAGS=@COMP_VENDOR_CFLAGS@ @DEFS@
SRC=src
SOURCES=\
$(SRC)/hashtable.c \
@ -68,6 +68,7 @@ $(SRC)/isdn/5ESSStateTE.c \
$(SRC)/isdn/Q932mes.c \
$(SRC)/zap_zt.c \
$(SRC)/zap_wanpipe.c \
$(SRC)/ss7_boost_client.c \
$(SRC)/zap_ss7_boost.c
OBJS=\
@ -107,6 +108,7 @@ $(SRC)/isdn/5ESSStateTE.o \
$(SRC)/isdn/Q932mes.o \
$(SRC)/zap_zt.o \
$(SRC)/zap_wanpipe.o \
$(SRC)/ss7_boost_client.o \
$(SRC)/zap_ss7_boost.o
HEADERS= $(SRC)/include/fsk.h \

View File

@ -44,6 +44,9 @@ sun)
COMP_VENDOR_CFLAGS="-std=c99 -Wall -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes"
;;
esac
AC_CHECK_HEADERS([netinet/sctp.h])
# Enable debugging
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug],[build with debug information])],[enable_debug="$enable_debug"],[enable_debug="yes"])

View File

@ -33,6 +33,7 @@
#include "openzap.h"
#include "zap_analog.h"
#include "zap_isdn.h"
#include "zap_ss7_boost.h"
#ifndef __FUNCTION__
#define __FUNCTION__ __SWITCH_FUNC__
@ -807,7 +808,8 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
char name[128];
zap_status_t status;
int direction = ZAP_TOP_DOWN;
zap_caller_data_t caller_data = {{ 0 }};
if (!outbound_profile) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n");
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
@ -846,10 +848,14 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
chan_id = 0;
}
zap_set_string(caller_data.ani, dest);
zap_set_string(caller_data.cid_name, outbound_profile->caller_id_name);
zap_set_string(caller_data.cid_num, outbound_profile->caller_id_number);
if (chan_id) {
status = zap_channel_open(span_id, chan_id, &zchan);
} else {
status = zap_channel_open_any(span_id, direction, &zchan);
status = zap_channel_open_any(span_id, direction, &caller_data, &zchan);
}
if (status != ZAP_SUCCESS) {
@ -875,9 +881,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
snprintf(name, sizeof(name), "OPENZAP/%s", dest);
switch_channel_set_name(channel, name);
zap_set_string(zchan->caller_data.ani, dest);
zap_set_string(zchan->caller_data.cid_name, outbound_profile->caller_id_name);
zap_set_string(zchan->caller_data.cid_num, outbound_profile->caller_id_number);
zchan->caller_data = caller_data;
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile;
@ -1535,6 +1539,7 @@ static switch_status_t load_config(void)
if (!id) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
continue;
}
span_id = atoi(id);
@ -1561,6 +1566,70 @@ static switch_status_t load_config(void)
}
}
if ((spans = switch_xml_child(cfg, "boost_spans"))) {
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
char *id = (char *) switch_xml_attr_soft(myspan, "id");
char *context = "default";
char *dialplan = "XML";
uint32_t span_id = 0;
zap_span_t *span = NULL;
char *tonegroup = NULL;
char *local_ip = NULL;
int local_port = 0;
char *remote_ip = NULL;
int remote_port = 0;
for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "tonegroup")) {
tonegroup = val;
} else if (!strcasecmp(var, "local-ip")) {
local_ip = val;
} else if (!strcasecmp(var, "local-port")) {
local_port = atoi(val);
} else if (!strcasecmp(var, "remote-ip")) {
remote_ip = val;
} else if (!strcasecmp(var, "remote-port")) {
remote_port = atoi(val);
} else if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "dialplan")) {
dialplan = val;
}
}
if (!(id && local_ip && local_port && remote_ip && remote_port) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param\n");
continue;
}
span_id = atoi(id);
if (!tonegroup) {
tonegroup = "us";
}
if (zap_span_find(span_id, &span) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_ERROR, "Error finding OpenZAP span %d\n", span_id);
continue;
}
if (zap_ss7_boost_configure_span(span, local_ip, local_port, remote_ip, remote_port, on_isdn_signal) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_ERROR, "Error starting OpenZAP span %d error: %s\n", span_id, span->last_error);
continue;
}
SPAN_CONFIG[span->span_id].span = span;
switch_copy_string(SPAN_CONFIG[span->span_id].context, context, sizeof(SPAN_CONFIG[span->span_id].context));
switch_copy_string(SPAN_CONFIG[span->span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span->span_id].dialplan));
zap_ss7_boost_start(span);
}
}
switch_xml_free(xml);

View File

@ -150,7 +150,9 @@
#define assert(_Expression) ((void)(_Expression))
#endif
#define ZAP_MAX_CHANNELS_SPAN 513
#define ZAP_MAX_CHANNELS_PHYSICAL_SPAN 32
#define ZAP_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN 16
#define ZAP_MAX_CHANNELS_SPAN ZAP_MAX_CHANNELS_PHYSICAL_SPAN * ZAP_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN
#define ZAP_MAX_SPANS_INTERFACE 33
#define GOTO_STATUS(label,st) status = st; goto label ;
@ -506,7 +508,7 @@ zap_status_t zap_span_set_event_callback(zap_span_t *span, zio_event_cb_t event_
zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zio_event_cb_t event_callback);
zap_status_t zap_channel_open(uint32_t span_id, uint32_t chan_id, zap_channel_t **zchan);
zap_status_t zap_channel_open_chan(zap_channel_t *zchan);
zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, zap_channel_t **zchan);
zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, const zap_caller_data_t *caller_data, zap_channel_t **zchan);
zap_status_t zap_channel_close(zap_channel_t **zchan);
zap_status_t zap_channel_done(zap_channel_t *zchan);
zap_status_t zap_channel_use(zap_channel_t *zchan);

View File

@ -44,7 +44,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef SS7BC_USE_SCTP
#ifdef HAVE_NETINET_SCTP_H
#include <netinet/sctp.h>
#endif
#include <arpa/inet.h>
@ -77,13 +77,13 @@
typedef t_sigboost ss7bc_event_t;
typedef uint32_t ss7bc_event_id_t;
typedef struct smg_ip_cfg
typedef struct ss7bc_ip_cfg
{
char local_ip[25];
int local_port;
char remote_ip[25];
int remote_port;
}smg_ip_cfg_t;
}ss7bc_ip_cfg_t;
struct ss7bc_connection {
zap_socket_t socket;
@ -99,7 +99,7 @@ struct ss7bc_connection {
unsigned int rxseq;
unsigned int txwindow;
unsigned int rxseq_reset;
smg_ip_cfg_t cfg;
ss7bc_ip_cfg_t cfg;
};
typedef enum {
@ -111,7 +111,7 @@ typedef struct ss7bc_connection ss7bc_connection_t;
/* disable nagle's algorythm */
static inline void sctp_no_nagle(int socket)
{
#ifdef SS7BC_USE_SCTP
#ifdef HAVE_NETINET_SCTP_H
int flag = 1;
setsockopt(socket, IPPROTO_SCTP, SCTP_NODELAY, (char *) &flag, sizeof(int));
#endif
@ -123,8 +123,9 @@ ss7bc_event_t *ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration);
ss7bc_event_t *ss7bc_connection_readp(ss7bc_connection_t *mcon, int iteration);
int ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event);
void ss7bc_event_init(ss7bc_event_t *event, ss7bc_event_id_t event_id, int chan, int span);
void ss7bc_call_init(ss7bc_event_t *event, char *calling, char *called, int setup_id);
char *ss7bc_event_id_name(uint32_t event_id);
void ss7bc_call_init(ss7bc_event_t *event, const char *calling, const char *called, int setup_id);
const char *ss7bc_event_id_name(uint32_t event_id);
int ss7bc_exec_command(ss7bc_connection_t *mcon, int span, int chan, int id, int cmd, int cause);
#endif

View File

@ -33,21 +33,19 @@
#ifndef ZAP_SS7_BOOST_H
#define ZAP_SS7_BOOST_H
#include "ss7_boost_client.h"
#include "openzap.h"
typedef enum {
ZAP_SS7_BOOST_RUNNING = (1 << 0)
} zap_isdn_flag_t;
} zap_ss7_boost_flag_t;
struct zap_ss7_boost_data {
const char *local_ip;
int local_port;
const char *remote_ip;
int remote_port;
typedef struct zap_ss7_boost_data {
ss7bc_connection_t mcon;
ss7bc_connection_t pcon;
zio_signal_cb_t signal_cb;
uint32_t flags;
};
typedef struct zap_ss7_boost_data zap_ss7_boost_data_t;
} zap_ss7_boost_data_t;
zap_status_t zap_ss7_boost_start(zap_span_t *span);
zap_status_t zap_ss7_boost_init(void);

View File

@ -336,8 +336,9 @@ typedef struct zap_channel zap_channel_t;
typedef struct zap_event zap_event_t;
typedef struct zap_sigmsg zap_sigmsg_t;
typedef struct zap_span zap_span_t;
typedef struct zap_caller_data zap_caller_data_t;
#define ZIO_CHANNEL_REQUEST_ARGS (zap_span_t *span, zap_direction_t direction, zap_channel_t **zchan)
#define ZIO_CHANNEL_REQUEST_ARGS (zap_span_t *span, zap_direction_t direction, const zap_caller_data_t *caller_data, zap_channel_t **zchan)
#define ZIO_CHANNEL_OUTGOING_CALL_ARGS (zap_channel_t *zchan)
#define ZIO_SPAN_POLL_EVENT_ARGS (zap_span_t *span, uint32_t ms)
#define ZIO_SPAN_NEXT_EVENT_ARGS (zap_span_t *span, zap_event_t **event)

View File

@ -43,7 +43,7 @@ extern int gethostbyname_r (__const char *__restrict __name,
struct ss7bc_map {
uint32_t event_id;
char *name;
const char *name;
};
static struct ss7bc_map ss7bc_table[] = {
@ -72,7 +72,7 @@ static int create_conn_socket(ss7bc_connection_t *mcon, char *local_ip, int loca
memset(&mcon->remote_hp, 0, sizeof(mcon->remote_hp));
memset(&mcon->local_hp, 0, sizeof(mcon->local_hp));
#ifdef SS7BC_USE_SCTP
#ifdef HAVE_NETINET_SCTP_H
mcon->socket = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
#else
mcon->socket = socket(AF_INET, SOCK_DGRAM, 0);
@ -96,7 +96,7 @@ static int create_conn_socket(ss7bc_connection_t *mcon, char *local_ip, int loca
memcpy((char *) &mcon->local_addr.sin_addr.s_addr, mcon->local_hp.h_addr_list[0], mcon->local_hp.h_length);
mcon->local_addr.sin_port = htons(local_port);
#ifdef SS7BC_USE_SCTP
#ifdef HAVE_NETINET_SCTP_H
setsockopt(mcon->socket, IPPROTO_SCTP, SCTP_NODELAY,
(char *)&flag, sizeof(int));
#endif
@ -107,7 +107,7 @@ static int create_conn_socket(ss7bc_connection_t *mcon, char *local_ip, int loca
close(mcon->socket);
mcon->socket = -1;
} else {
#ifdef SS7BC_USE_SCTP
#ifdef HAVE_NETINET_SCTP_H
rc=listen(mcon->socket,100);
if (rc) {
close(mcon->socket);
@ -123,9 +123,11 @@ static int create_conn_socket(ss7bc_connection_t *mcon, char *local_ip, int loca
int ss7bc_connection_close(ss7bc_connection_t *mcon)
{
close(mcon->socket);
mcon->socket = -1;
if (mcon->socket > -1) {
close(mcon->socket);
}
memset(mcon, 0, sizeof(*mcon));
mcon->socket = -1;
return 0;
}
@ -136,6 +138,41 @@ int ss7bc_connection_open(ss7bc_connection_t *mcon, char *local_ip, int local_po
return mcon->socket;
}
int ss7bc_exec_command(ss7bc_connection_t *mcon, int span, int chan, int id, int cmd, int cause)
{
ss7bc_event_t oevent;
int retry = 5;
ss7bc_event_init(&oevent, cmd, chan, span);
oevent.release_cause = cause;
if (id >= 0) {
oevent.call_setup_id = id;
}
isup_exec_cmd_retry:
if (ss7bc_connection_write(mcon, &oevent) <= 0){
--retry;
if (retry <= 0) {
zap_log(ZAP_LOG_WARNING,
"Critical System Error: Failed to tx on ISUP socket: %s\n",
strerror(errno));
return -1;
} else {
zap_log(ZAP_LOG_WARNING,
"System Warning: Failed to tx on ISUP socket: %s :retry %i\n",
strerror(errno),retry);
}
goto isup_exec_cmd_retry;
}
return 0;
}
ss7bc_event_t *ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration)
{
unsigned int fromlen = sizeof(struct sockaddr_in);
@ -360,7 +397,7 @@ int ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event)
return err;
}
void ss7bc_call_init(ss7bc_event_t *event, char *calling, char *called, int setup_id)
void ss7bc_call_init(ss7bc_event_t *event, const char *calling, const char *called, int setup_id)
{
memset(event, 0, sizeof(ss7bc_event_t));
event->event_id = SIGBOOST_EVENT_CALL_START;
@ -387,10 +424,10 @@ void ss7bc_event_init(ss7bc_event_t *event, ss7bc_event_id_t event_id, int chan,
event->span = span;
}
char *ss7bc_event_id_name(uint32_t event_id)
const char *ss7bc_event_id_name(uint32_t event_id)
{
unsigned int x;
char *ret = NULL;
const char *ret = NULL;
for (x = 0 ; x < sizeof(ss7bc_table)/sizeof(struct ss7bc_map); x++) {
if (ss7bc_table[x].event_id == event_id) {

View File

@ -37,6 +37,7 @@
#endif
#include "openzap.h"
#include "zap_isdn.h"
#include "zap_ss7_boost.h"
#include <stdarg.h>
#ifdef WIN32
#include <io.h>
@ -342,7 +343,7 @@ zap_status_t zap_span_close_all(void)
span = &globals.spans[i];
if (zap_test_flag(span, ZAP_SPAN_CONFIGURED)) {
for(j = 0; j < span->chan_count; j++) {
zap_channel_destroy(&span->channels[i]);
zap_channel_destroy(&span->channels[j]);
}
}
}
@ -679,7 +680,7 @@ zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t sta
return ok ? ZAP_SUCCESS : ZAP_FAIL;
}
zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, zap_channel_t **zchan)
zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, const zap_caller_data_t *caller_data, zap_channel_t **zchan)
{
zap_status_t status = ZAP_FAIL;
zap_channel_t *check;
@ -690,7 +691,7 @@ zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, z
zap_mutex_lock(globals.mutex);
if (span_id && globals.spans[span_id].channel_request) {
status = globals.spans[span_id].channel_request(&globals.spans[span_id], direction, zchan);
status = globals.spans[span_id].channel_request(&globals.spans[span_id], direction, caller_data, zchan);
goto done;
}
@ -1949,6 +1950,7 @@ zap_status_t zap_global_init(void)
time_init();
zap_isdn_init();
zap_ss7_boost_init();
memset(&interfaces, 0, sizeof(interfaces));
globals.interface_hash = create_hashtable(16, zap_hash_hashfromstring, zap_hash_equalkeys);

View File

@ -35,30 +35,493 @@
#include "ss7_boost_client.h"
#include "zap_ss7_boost.h"
typedef uint16_t ss7_boost_request_id_t;
typedef enum {
BST_FREE,
BST_WAITING,
BST_READY,
BST_FAIL
} ss7_boost_request_status_t;
typedef struct {
ss7_boost_request_status_t status;
ss7bc_event_t event;
zap_span_t *span;
zap_channel_t *zchan;
} ss7_boost_request_t;
static ss7_boost_request_id_t current_request = 0;
static ss7_boost_request_t OUTBOUND_REQUESTS[ZAP_MAX_CHANNELS_SPAN] = {{ 0 }};
static zap_mutex_t *request_mutex = NULL;
static zap_mutex_t *signal_mutex = NULL;
static ss7_boost_request_id_t next_request_id(void)
{
ss7_boost_request_id_t r;
zap_mutex_lock(request_mutex);
if (current_request == ZAP_MAX_CHANNELS_SPAN) {
current_request = 0;
}
r = current_request++;
zap_mutex_unlock(request_mutex);
return r + 1;
}
static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event)
{
int i;
zap_channel_t *zchan = NULL;
for(i = 0; i < span->chan_count; i++) {
if (span->channels[i].physical_span_id == event->span+1 && span->channels[i].physical_chan_id == event->chan+1) {
zchan = &span->channels[i];
break;
}
}
return zchan;
}
static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request)
{
zap_ss7_boost_data_t *ss7_boost_data = span->signal_data;
zap_status_t status = ZAP_SUCCESS;
ss7_boost_request_id_t r = next_request_id();
ss7bc_event_t event = {0};
int sanity = 60000;
ss7bc_call_init(&event, caller_data->cid_num, caller_data->ani, r);
OUTBOUND_REQUESTS[r].status = BST_WAITING;
OUTBOUND_REQUESTS[r].span = span;
if (ss7bc_connection_write(&ss7_boost_data->mcon, &event) <= 0) {
zap_log(ZAP_LOG_CRIT, "Failed to tx on ISUP socket [%s]\n", strerror(errno));
status = ZAP_FAIL;
goto done;
}
while(OUTBOUND_REQUESTS[r].status == BST_WAITING) {
zap_sleep(1);
if (!--sanity) {
status = ZAP_FAIL;
goto done;
}
}
if (OUTBOUND_REQUESTS[r].status == BST_READY) {
*zchan = OUTBOUND_REQUESTS[r].zchan;
}
done:
OUTBOUND_REQUESTS[r].status = BST_FREE;
return status;
}
static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(ss7_boost_outgoing_call)
{
zap_status_t status = ZAP_SUCCESS;
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DIALING);
return status;
}
static void handle_call_start_ack(ss7bc_connection_t *mcon, ss7bc_event_t *event)
{
zap_channel_t *zchan;
OUTBOUND_REQUESTS[event->call_setup_id].event = *event;
if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event))) {
OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY;
if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_ERROR, "OPEN ERROR [%s]\n", zchan->last_error);
} else {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DIALING);
OUTBOUND_REQUESTS[event->call_setup_id].zchan = zchan;
return;
}
}
ss7bc_exec_command(mcon,
event->span,
event->chan,
event->call_setup_id,
SIGBOOST_EVENT_CALL_STOPPED,
0);
OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL;
}
static void handle_call_start_nack(ss7bc_connection_t *mcon, ss7bc_event_t *event)
{
OUTBOUND_REQUESTS[event->call_setup_id].event = *event;
OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL;
ss7bc_exec_command(mcon,
event->span,
event->chan,
event->call_setup_id,
SIGBOOST_EVENT_CALL_START_NACK_ACK,
0);
}
static void handle_call_stop(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event)
{
zap_channel_t *zchan;
if ((zchan = find_zchan(span, event))) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_TERMINATING);
} else {
ss7bc_exec_command(mcon,
event->span,
event->chan,
0,
SIGBOOST_EVENT_CALL_STOPPED,
0);
}
}
static void handle_call_answer(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event)
{
zap_channel_t *zchan;
if ((zchan = find_zchan(span, event))) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_UP);
} else {
ss7bc_exec_command(mcon,
event->span,
event->chan,
0,
SIGBOOST_EVENT_CALL_STOPPED,
0);
}
}
static void handle_call_start(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event)
{
zap_channel_t *zchan;
if ((zchan = find_zchan(span, event))) {
ss7bc_exec_command(mcon,
event->span,
event->chan,
0,
SIGBOOST_EVENT_CALL_START_ACK,
0);
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING);
} else {
ss7bc_exec_command(mcon,
event->span,
event->chan,
0,
SIGBOOST_EVENT_CALL_START_NACK,
0);
}
}
static void handle_heartbeat(ss7bc_connection_t *mcon, ss7bc_event_t *event)
{
int err = ss7bc_connection_write(mcon, event);
if (err <= 0) {
zap_log(ZAP_LOG_CRIT, "Failed to tx on ISUP socket [%s]: %s\n", strerror(errno));
}
return;
}
static void handle_restart_ack(ss7bc_connection_t *mcon, ss7bc_event_t *event)
{
mcon->rxseq_reset = 0;
}
static int parse_ss7_event(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event)
{
zap_mutex_lock(signal_mutex);
zap_log(ZAP_LOG_DEBUG,
"RX EVENT: %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i Cd=[%s] Ci=[%s]\n",
ss7bc_event_id_name(event->event_id),
event->event_id,
event->span+1,
event->chan+1,
event->release_cause,
event->call_setup_id,
event->fseqno,
(event->called_number_digits_count ? (char *) event->called_number_digits : "N/A"),
(event->calling_number_digits_count ? (char *) event->calling_number_digits : "N/A")
);
switch(event->event_id) {
case SIGBOOST_EVENT_CALL_START:
handle_call_start(span, mcon, event);
break;
case SIGBOOST_EVENT_CALL_STOPPED:
handle_call_stop(span, mcon, event);
break;
case SIGBOOST_EVENT_CALL_START_ACK:
handle_call_start_ack(mcon, event);
break;
case SIGBOOST_EVENT_CALL_START_NACK:
handle_call_start_nack(mcon, event);
break;
case SIGBOOST_EVENT_CALL_ANSWERED:
handle_call_answer(span, mcon, event);
break;
case SIGBOOST_EVENT_HEARTBEAT:
handle_heartbeat(mcon, event);
break;
case SIGBOOST_EVENT_CALL_START_NACK_ACK:
//handle_call_start_nack_ack(event);
break;
case SIGBOOST_EVENT_CALL_STOPPED_ACK:
//handle_call_stop_ack(event);
break;
case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
//handle_call_loop_start(event);
break;
case SIGBOOST_EVENT_REMOVE_CHECK_LOOP:
//handle_call_stop(event);
break;
case SIGBOOST_EVENT_SYSTEM_RESTART_ACK:
handle_restart_ack(mcon,event);
break;
case SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE:
//handle_gap_abate(event);
break;
default:
zap_log(ZAP_LOG_WARNING, "No handler implemented for [%s]\n", ss7bc_event_id_name(event->event_id));
break;
}
zap_mutex_unlock(signal_mutex);
return 0;
}
static __inline__ void state_advance(zap_channel_t *zchan)
{
zap_ss7_boost_data_t *ss7_boost_data = zchan->span->signal_data;
ss7bc_connection_t *mcon = &ss7_boost_data->mcon;
zap_sigmsg_t sig;
zap_status_t status;
zap_log(ZAP_LOG_ERROR, "%d:%d STATE [%s]\n",
zchan->span_id, zchan->chan_id, zap_channel_state2str(zchan->state));
memset(&sig, 0, sizeof(sig));
sig.chan_id = zchan->chan_id;
sig.span_id = zchan->span_id;
sig.channel = zchan;
switch (zchan->state) {
case ZAP_CHANNEL_STATE_DOWN:
{
zap_channel_done(zchan);
}
break;
case ZAP_CHANNEL_STATE_PROGRESS:
{
if (zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) {
sig.event_id = ZAP_SIGEVENT_PROGRESS;
if ((status = ss7_boost_data->signal_cb(&sig) != ZAP_SUCCESS)) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
} else {
//send progress
}
}
break;
case ZAP_CHANNEL_STATE_RING:
{
if (!zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) {
sig.event_id = ZAP_SIGEVENT_START;
if ((status = ss7_boost_data->signal_cb(&sig) != ZAP_SUCCESS)) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
}
}
break;
case ZAP_CHANNEL_STATE_RESTART:
{
if (zchan->last_state > ZAP_CHANNEL_STATE_HANGUP) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
}
break;
case ZAP_CHANNEL_STATE_PROGRESS_MEDIA:
{
if (zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) {
sig.event_id = ZAP_SIGEVENT_PROGRESS_MEDIA;
if ((status = ss7_boost_data->signal_cb(&sig) != ZAP_SUCCESS)) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
} else {
// send alerting
}
}
break;
case ZAP_CHANNEL_STATE_UP:
{
if (zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) {
sig.event_id = ZAP_SIGEVENT_UP;
if ((status = ss7_boost_data->signal_cb(&sig) != ZAP_SUCCESS)) {
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
}
} else {
// send connect
}
}
break;
case ZAP_CHANNEL_STATE_DIALING:
{
}
break;
case ZAP_CHANNEL_STATE_HANGUP:
{
ss7bc_exec_command(mcon,
zchan->physical_span_id-1,
zchan->physical_chan_id-1,
0,
SIGBOOST_EVENT_CALL_STOPPED,
0);
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
}
break;
case ZAP_CHANNEL_STATE_TERMINATING:
{
sig.event_id = ZAP_SIGEVENT_STOP;
status = ss7_boost_data->signal_cb(&sig);
}
default:
break;
}
}
static __inline__ void check_state(zap_span_t *span)
{
if (zap_test_flag(span, ZAP_SPAN_STATE_CHANGE)) {
uint32_t j;
for(j = 1; j <= span->chan_count; j++) {
if (zap_test_flag((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE)) {
zap_mutex_lock(signal_mutex);
state_advance(&span->channels[j]);
zap_mutex_unlock(signal_mutex);
zap_clear_flag_locked((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE);
}
}
zap_clear_flag_locked(span, ZAP_SPAN_STATE_CHANGE);
}
}
static void *zap_ss7_boost_run(zap_thread_t *me, void *obj)
{
zap_span_t *span = (zap_span_t *) obj;
zap_ss7_boost_data_t *ss7_boost_data = span->signal_data;
ss7bc_connection_t *mcon, *pcon;
ss7_boost_data->pcon = ss7_boost_data->mcon;
if (ss7bc_connection_open(&ss7_boost_data->mcon,
ss7_boost_data->mcon.cfg.local_ip,
ss7_boost_data->mcon.cfg.local_port,
ss7_boost_data->mcon.cfg.remote_ip,
ss7_boost_data->mcon.cfg.remote_port) < 0) {
zap_log(ZAP_LOG_DEBUG, "Error: Opening MCON Socket [%d] %s\n", ss7_boost_data->mcon.socket, strerror(errno));
goto end;
}
if (ss7bc_connection_open(&ss7_boost_data->pcon,
ss7_boost_data->pcon.cfg.local_ip,
++ss7_boost_data->pcon.cfg.local_port,
ss7_boost_data->pcon.cfg.remote_ip,
ss7_boost_data->pcon.cfg.remote_port) < 0) {
zap_log(ZAP_LOG_DEBUG, "Error: Opening PCON Socket [%d] %s\n", ss7_boost_data->pcon.socket, strerror(errno));
goto end;
}
mcon = &ss7_boost_data->mcon;
pcon = &ss7_boost_data->pcon;
mcon->rxseq_reset = 1;
ss7bc_exec_command(mcon,
0,
0,
-1,
SIGBOOST_EVENT_SYSTEM_RESTART,
0);
while (zap_running() && zap_test_flag(ss7_boost_data, ZAP_SS7_BOOST_RUNNING)) {
break;
fd_set rfds, efds;
struct timeval tv = { 0, 100000 };
int max, activity, i = 0;
ss7bc_event_t *event = NULL;
FD_ZERO(&rfds);
FD_ZERO(&efds);
FD_SET(mcon->socket, &rfds);
FD_SET(mcon->socket, &efds);
FD_SET(pcon->socket, &rfds);
FD_SET(pcon->socket, &efds);
max = ((pcon->socket > mcon->socket) ? pcon->socket : mcon->socket) + 1;
if ((activity = select(max, &rfds, NULL, &efds, &tv)) < 0) {
goto error;
}
if (!activity) {
continue;
}
if (FD_ISSET(pcon->socket, &efds) || FD_ISSET(mcon->socket, &efds)) {
goto error;
}
if (FD_ISSET(pcon->socket, &rfds)) {
if ((event = ss7bc_connection_readp(pcon, i))) {
parse_ss7_event(span, pcon, event);
}
}
if (FD_ISSET(mcon->socket, &rfds)) {
if ((event = ss7bc_connection_read(mcon, i))) {
parse_ss7_event(span, mcon, event);
}
}
check_state(span);
}
goto end;
error:
zap_log(ZAP_LOG_CRIT, "Socket Error!\n");
end:
ss7bc_connection_close(&ss7_boost_data->mcon);
ss7bc_connection_close(&ss7_boost_data->pcon);
zap_clear_flag(ss7_boost_data, ZAP_SS7_BOOST_RUNNING);
zap_log(ZAP_LOG_DEBUG, "SS7_BOOST thread ended.\n");
@ -67,6 +530,9 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj)
zap_status_t zap_ss7_boost_init(void)
{
zap_mutex_create(&request_mutex);
zap_mutex_create(&signal_mutex);
return ZAP_SUCCESS;
}
@ -84,14 +550,18 @@ zap_status_t zap_ss7_boost_configure_span(zap_span_t *span,
{
zap_ss7_boost_data_t *ss7_boost_data = NULL;
if (!local_ip && local_port && remote_ip && remote_port && sig_cb) {
return ZAP_FAIL;
}
ss7_boost_data = malloc(sizeof(*ss7_boost_data));
assert(ss7_boost_data);
memset(ss7_boost_data, 0, sizeof(*ss7_boost_data));
ss7_boost_data->local_ip = local_ip;
ss7_boost_data->local_port = local_port;
ss7_boost_data->remote_ip = remote_ip;
ss7_boost_data->remote_port = remote_port;
zap_set_string(ss7_boost_data->mcon.cfg.local_ip, local_ip);
ss7_boost_data->mcon.cfg.local_port = local_port;
zap_set_string(ss7_boost_data->mcon.cfg.remote_ip, remote_ip);
ss7_boost_data->mcon.cfg.remote_port = remote_port;
ss7_boost_data->signal_cb = sig_cb;
span->signal_data = ss7_boost_data;

View File

@ -358,13 +358,14 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
sockfd = tdmv_api_open_span_chan(spanno, x);
if (sockfd != WP_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
wanpipe_tdm_api_t tdm_api;
zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d\n", spanno, x, chan->span_id, chan->chan_id, sockfd);
chan->physical_span_id = spanno;
chan->physical_chan_id = x;
chan->rate = 8000;
if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) {
wanpipe_tdm_api_t tdm_api;
#if 1
if (type == ZAP_CHAN_TYPE_FXO) {
@ -390,8 +391,9 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
wp_tdm_cmd_exec(chan, &tdm_api);
}
if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO || type == ZAP_CHAN_TYPE_B) {
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_HW_CODING;
wp_tdm_cmd_exec(chan, &tdm_api);
if (tdm_api.wp_tdm_cmd.hw_tdm_coding) {
@ -400,6 +402,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
chan->native_codec = chan->effective_codec = ZAP_CODEC_ULAW;
}
}
if (!zap_strlen_zero(name)) {
zap_copy_string(chan->chan_name, name, sizeof(chan->chan_name));
}