2006-02-22 17:16:47 +00:00
|
|
|
/*
|
2006-01-03 22:13:59 +00:00
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
* Version: MPL 1.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
*
|
2006-01-13 14:23:34 +00:00
|
|
|
* mod_wanpipe.c -- WANPIPE PRI Channel Module
|
2006-01-03 22:13:59 +00:00
|
|
|
*
|
|
|
|
*/
|
2006-02-22 16:47:07 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
#include <switch.h>
|
|
|
|
#include <libsangoma.h>
|
|
|
|
#include <sangoma_pri.h>
|
2006-02-22 16:47:07 +00:00
|
|
|
#include <libteletone.h>
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
static const char modname[] = "mod_wanpipe";
|
2006-01-03 22:13:59 +00:00
|
|
|
#define STRLEN 15
|
|
|
|
|
|
|
|
static switch_memory_pool *module_pool;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
PFLAG_ANSWER = (1 << 0),
|
|
|
|
PFLAG_HANGUP = (1 << 1),
|
|
|
|
} PFLAGS;
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
PPFLAG_RING = (1 << 0),
|
|
|
|
} PPFLAGS;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
TFLAG_MEDIA = (1 << 0),
|
|
|
|
TFLAG_INBOUND = (1 << 1),
|
|
|
|
TFLAG_OUTBOUND = (1 << 2),
|
|
|
|
TFLAG_INCOMING = (1 << 3),
|
|
|
|
TFLAG_PARSE_INCOMING = (1 << 4),
|
|
|
|
TFLAG_ACTIVATE = (1 << 5),
|
|
|
|
TFLAG_DTMF = (1 << 6),
|
|
|
|
TFLAG_DESTROY = (1 << 7),
|
|
|
|
TFLAG_ABORT = (1 << 8),
|
|
|
|
TFLAG_SWITCH = (1 << 9),
|
|
|
|
} TFLAGS;
|
|
|
|
|
2006-02-24 19:11:49 +00:00
|
|
|
|
2006-02-22 15:20:46 +00:00
|
|
|
#define DEFAULT_MTU 160
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
static struct {
|
|
|
|
int debug;
|
|
|
|
int panic;
|
2006-02-22 15:20:46 +00:00
|
|
|
int mtu;
|
2006-02-22 18:32:15 +00:00
|
|
|
int dtmf_on;
|
|
|
|
int dtmf_off;
|
2006-02-23 22:41:08 +00:00
|
|
|
int supress_dtmf_tone;
|
2006-02-24 16:47:22 +00:00
|
|
|
int configured_spans;
|
2006-02-12 20:38:24 +00:00
|
|
|
char *dialplan;
|
|
|
|
} globals;
|
|
|
|
|
|
|
|
struct wanpipe_pri_span {
|
2006-01-03 22:13:59 +00:00
|
|
|
int span;
|
|
|
|
int dchan;
|
2006-02-12 20:38:24 +00:00
|
|
|
unsigned int bchans;
|
2006-01-03 22:13:59 +00:00
|
|
|
int node;
|
2006-02-22 15:20:46 +00:00
|
|
|
int mtu;
|
2006-01-03 22:13:59 +00:00
|
|
|
int pswitch;
|
|
|
|
char *dialplan;
|
2006-02-12 20:38:24 +00:00
|
|
|
unsigned int l1;
|
|
|
|
unsigned int dp;
|
|
|
|
struct sangoma_pri spri;
|
|
|
|
};
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
#define MAX_SPANS 128
|
|
|
|
static struct wanpipe_pri_span *SPANS[MAX_SPANS];
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
struct private_object {
|
2006-01-20 15:05:05 +00:00
|
|
|
unsigned int flags; /* FLAGS */
|
2006-02-10 22:26:00 +00:00
|
|
|
switch_frame read_frame; /* Frame for Writing */
|
|
|
|
switch_core_session *session;
|
|
|
|
switch_codec read_codec;
|
|
|
|
switch_codec write_codec;
|
2006-01-14 16:44:52 +00:00
|
|
|
unsigned char databuf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
|
2006-01-03 22:13:59 +00:00
|
|
|
struct sangoma_pri *spri;
|
|
|
|
sangoma_api_hdr_t hdrframe;
|
|
|
|
switch_caller_profile *caller_profile;
|
|
|
|
int socket;
|
|
|
|
int callno;
|
2006-02-22 18:32:15 +00:00
|
|
|
int span;
|
2006-01-03 22:13:59 +00:00
|
|
|
int cause;
|
2006-02-10 22:26:00 +00:00
|
|
|
q931_call *call;
|
2006-02-22 18:32:15 +00:00
|
|
|
teletone_dtmf_detect_state_t dtmf_detect;
|
2006-02-22 16:47:07 +00:00
|
|
|
teletone_generation_session_t tone_session;
|
|
|
|
switch_buffer *dtmf_buffer;
|
2006-01-03 22:13:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct channel_map {
|
|
|
|
switch_core_session *map[36];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void set_global_dialplan(char *dialplan)
|
|
|
|
{
|
|
|
|
if (globals.dialplan) {
|
|
|
|
free(globals.dialplan);
|
|
|
|
globals.dialplan = NULL;
|
|
|
|
}
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
globals.dialplan = strdup(dialplan);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int str2node(char *node)
|
|
|
|
{
|
|
|
|
if (!strcasecmp(node, "cpe"))
|
|
|
|
return PRI_CPE;
|
|
|
|
if (!strcasecmp(node, "network"))
|
|
|
|
return PRI_NETWORK;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int str2switch(char *swtype)
|
|
|
|
{
|
|
|
|
if (!strcasecmp(swtype, "ni2"))
|
|
|
|
return PRI_SWITCH_NI2;
|
|
|
|
if (!strcasecmp(swtype, "dms100"))
|
|
|
|
return PRI_SWITCH_DMS100;
|
|
|
|
if (!strcasecmp(swtype, "lucent5e"))
|
|
|
|
return PRI_SWITCH_LUCENT5E;
|
|
|
|
if (!strcasecmp(swtype, "att4ess"))
|
|
|
|
return PRI_SWITCH_ATT4ESS;
|
|
|
|
if (!strcasecmp(swtype, "euroisdn"))
|
|
|
|
return PRI_SWITCH_EUROISDN_E1;
|
|
|
|
if (!strcasecmp(swtype, "gr303eoc"))
|
|
|
|
return PRI_SWITCH_GR303_EOC;
|
|
|
|
if (!strcasecmp(swtype, "gr303tmc"))
|
|
|
|
return PRI_SWITCH_GR303_TMC;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
|
|
|
|
static int str2l1(char *l1)
|
|
|
|
{
|
|
|
|
if (!strcasecmp(l1, "alaw"))
|
|
|
|
return PRI_LAYER_1_ALAW;
|
|
|
|
|
|
|
|
return PRI_LAYER_1_ULAW;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int str2dp(char *dp)
|
|
|
|
{
|
|
|
|
if (!strcasecmp(dp, "international"))
|
|
|
|
return PRI_INTERNATIONAL_ISDN;
|
|
|
|
if (!strcasecmp(dp, "national"))
|
|
|
|
return PRI_NATIONAL_ISDN;
|
|
|
|
if (!strcasecmp(dp, "local"))
|
|
|
|
return PRI_LOCAL_ISDN;
|
|
|
|
if (!strcasecmp(dp, "private"))
|
|
|
|
return PRI_PRIVATE;
|
|
|
|
if (!strcasecmp(dp, "unknown"))
|
|
|
|
return PRI_UNKNOWN;
|
|
|
|
|
|
|
|
return PRI_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
static const switch_endpoint_interface wanpipe_endpoint_interface;
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
static void set_global_dialplan(char *dialplan);
|
|
|
|
static int str2node(char *node);
|
|
|
|
static int str2switch(char *swtype);
|
2006-01-13 14:23:34 +00:00
|
|
|
static switch_status wanpipe_on_init(switch_core_session *session);
|
|
|
|
static switch_status wanpipe_on_hangup(switch_core_session *session);
|
|
|
|
static switch_status wanpipe_on_loopback(switch_core_session *session);
|
|
|
|
static switch_status wanpipe_on_transmit(switch_core_session *session);
|
2006-01-20 15:05:05 +00:00
|
|
|
static switch_status wanpipe_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
|
|
|
|
switch_core_session **new_session);
|
|
|
|
static switch_status wanpipe_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
|
|
|
|
switch_io_flag flags, int stream_id);
|
|
|
|
static switch_status wanpipe_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
|
|
|
|
switch_io_flag flags, int stream_id);
|
2006-02-10 22:26:00 +00:00
|
|
|
static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event);
|
|
|
|
static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event);
|
|
|
|
static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event);
|
2006-01-03 22:13:59 +00:00
|
|
|
static int check_flags(struct sangoma_pri *spri);
|
2006-02-10 22:26:00 +00:00
|
|
|
static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event);
|
|
|
|
static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event);
|
2006-01-03 22:13:59 +00:00
|
|
|
static void *pri_thread_run(switch_thread *thread, void *obj);
|
2006-02-24 19:11:49 +00:00
|
|
|
static switch_status config_wanpipe(int reload);
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
State methods they get called when the state changes to the specific state
|
|
|
|
returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
|
|
|
|
so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
|
|
|
|
*/
|
2006-01-13 14:23:34 +00:00
|
|
|
static switch_status wanpipe_on_init(switch_core_session *session)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
switch_channel *channel = NULL;
|
2006-02-10 22:26:00 +00:00
|
|
|
wanpipe_tdm_api_t tdm_api;
|
|
|
|
int err = 0;
|
2006-02-24 19:11:49 +00:00
|
|
|
int mtu_mru;
|
2006-02-10 22:26:00 +00:00
|
|
|
unsigned int rate = 8000;
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
assert(tech_pvt != NULL);
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
tech_pvt->read_frame.data = tech_pvt->databuf;
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-02-24 19:11:49 +00:00
|
|
|
err = sangoma_tdm_set_codec(tech_pvt->socket, &tdm_api, WP_SLINEAR);
|
|
|
|
mtu_mru = sangoma_tdm_get_usr_mtu_mru(tech_pvt->socket, &tdm_api);
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANPIPE INIT MTU is %d\n", mtu_mru);
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-24 19:11:49 +00:00
|
|
|
if (mtu_mru != globals.mtu) {
|
|
|
|
sangoma_tdm_set_usr_period(tech_pvt->socket, &tdm_api, (globals.mtu / 8) / 2);
|
|
|
|
mtu_mru = sangoma_tdm_get_usr_mtu_mru(tech_pvt->socket, &tdm_api);
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "ADJUSTED MTU is %d\n", mtu_mru);
|
|
|
|
}
|
2006-02-10 22:26:00 +00:00
|
|
|
|
|
|
|
if (switch_core_codec_init
|
|
|
|
(&tech_pvt->read_codec, "L16", rate, 20, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
|
|
|
|
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s Cannot set read codec\n", switch_channel_get_name(channel));
|
|
|
|
switch_channel_hangup(channel);
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_core_codec_init
|
|
|
|
(&tech_pvt->write_codec, "L16", rate, 20, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
|
|
|
|
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s Cannot set read codec\n", switch_channel_get_name(channel));
|
|
|
|
switch_channel_hangup(channel);
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
tech_pvt->read_frame.rate = rate;
|
|
|
|
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
|
|
|
|
switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
|
|
|
|
switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-02-22 18:32:15 +00:00
|
|
|
|
|
|
|
/* Setup artificial DTMF stuff */
|
|
|
|
memset(&tech_pvt->tone_session, 0, sizeof(tech_pvt->tone_session));
|
2006-02-22 16:47:07 +00:00
|
|
|
teletone_init_session(&tech_pvt->tone_session, 1024, NULL, NULL);
|
|
|
|
|
2006-02-22 18:32:15 +00:00
|
|
|
if (globals.debug) {
|
2006-02-22 16:47:07 +00:00
|
|
|
tech_pvt->tone_session.debug = globals.debug;
|
|
|
|
tech_pvt->tone_session.debug_stream = stdout;
|
|
|
|
}
|
|
|
|
|
|
|
|
tech_pvt->tone_session.rate = rate;
|
2006-02-22 18:32:15 +00:00
|
|
|
tech_pvt->tone_session.duration = globals.dtmf_on * (tech_pvt->tone_session.rate / 1000);
|
|
|
|
tech_pvt->tone_session.wait = globals.dtmf_off * (tech_pvt->tone_session.rate / 1000);
|
2006-02-22 16:47:07 +00:00
|
|
|
|
2006-02-22 18:32:15 +00:00
|
|
|
teletone_dtmf_detect_init (&tech_pvt->dtmf_detect, rate);
|
|
|
|
|
2006-02-22 16:47:07 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
/* Move Channel's State Machine to RING */
|
|
|
|
switch_channel_set_state(channel, CS_RING);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
static switch_status wanpipe_on_ring(switch_core_session *session)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
switch_channel *channel = NULL;
|
|
|
|
struct private_object *tech_pvt = NULL;
|
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
assert(tech_pvt != NULL);
|
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANPIPE RING\n");
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
|
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
static switch_status wanpipe_on_hangup(switch_core_session *session)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
switch_channel *channel = NULL;
|
2006-02-10 22:26:00 +00:00
|
|
|
struct channel_map *chanmap;
|
|
|
|
|
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
assert(tech_pvt != NULL);
|
|
|
|
|
2006-02-26 04:52:34 +00:00
|
|
|
chanmap = tech_pvt->spri->private_info;
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
sangoma_socket_close(&tech_pvt->socket);
|
|
|
|
|
|
|
|
switch_core_codec_destroy(&tech_pvt->read_codec);
|
|
|
|
switch_core_codec_destroy(&tech_pvt->write_codec);
|
|
|
|
|
|
|
|
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANPIPE HANGUP\n");
|
|
|
|
|
|
|
|
pri_hangup(tech_pvt->spri->pri, tech_pvt->call, tech_pvt->cause);
|
|
|
|
pri_destroycall(tech_pvt->spri->pri, tech_pvt->call);
|
|
|
|
|
|
|
|
if (chanmap->map[tech_pvt->callno]) {
|
|
|
|
chanmap->map[tech_pvt->callno] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-01-20 15:05:05 +00:00
|
|
|
pri_hangup(tech_pvt->spri->pri,
|
|
|
|
tech_pvt->hangup_event.hangup.call ? tech_pvt->hangup_event.hangup.call : tech_pvt->ring_event.ring.call,
|
|
|
|
tech_pvt->cause);
|
|
|
|
pri_destroycall(tech_pvt->spri->pri,
|
2006-02-10 22:26:00 +00:00
|
|
|
tech_pvt->hangup_event.hangup.call ? tech_pvt->hangup_event.hangup.call : tech_pvt->ring_event.ring.call);
|
|
|
|
*/
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-02-22 16:47:07 +00:00
|
|
|
teletone_destroy_session(&tech_pvt->tone_session);
|
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
static switch_status wanpipe_on_loopback(switch_core_session *session)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
2006-01-13 14:23:34 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANPIPE LOOPBACK\n");
|
2006-01-03 22:13:59 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
static switch_status wanpipe_on_transmit(switch_core_session *session)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
2006-01-13 14:23:34 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANPIPE TRANSMIT\n");
|
2006-01-03 22:13:59 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
static switch_status wanpipe_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
|
|
|
|
switch_core_session **new_session)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
2006-02-24 16:47:22 +00:00
|
|
|
if (!globals.configured_spans) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error No Spans Configured.\n");
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
if ((*new_session = switch_core_session_request(&wanpipe_endpoint_interface, NULL))) {
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
switch_channel *channel;
|
|
|
|
|
|
|
|
switch_core_session_add_stream(*new_session, NULL);
|
|
|
|
if ((tech_pvt =
|
|
|
|
(struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) {
|
|
|
|
memset(tech_pvt, 0, sizeof(*tech_pvt));
|
|
|
|
channel = switch_core_session_get_channel(*new_session);
|
|
|
|
switch_core_session_set_private(*new_session, tech_pvt);
|
|
|
|
tech_pvt->session = *new_session;
|
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
|
|
|
|
switch_core_session_destroy(new_session);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outbound_profile) {
|
|
|
|
char name[128];
|
|
|
|
switch_caller_profile *caller_profile;
|
2006-02-12 20:38:24 +00:00
|
|
|
struct sangoma_pri *spri;
|
|
|
|
int span = 0, autospan = 0, autochan = 0;
|
|
|
|
char *num, *p;
|
|
|
|
int channo = 0;
|
|
|
|
struct channel_map *chanmap = NULL;
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
|
2006-02-12 20:38:24 +00:00
|
|
|
num = caller_profile->destination_number;
|
|
|
|
if ((p = strchr(num, '/'))) {
|
|
|
|
*p++ = '\0';
|
|
|
|
if (*num != 'a') {
|
|
|
|
span = atoi(num);
|
|
|
|
} else {
|
|
|
|
span = 1;
|
|
|
|
autospan = 1;
|
|
|
|
}
|
|
|
|
num = p;
|
|
|
|
if ((p = strchr(num, '/'))) {
|
|
|
|
*p++ = '\0';
|
|
|
|
if (*num == 'a') {
|
|
|
|
autochan = 1;
|
|
|
|
} else if (*num == 'A') {
|
|
|
|
autochan = -1;
|
|
|
|
} else {
|
|
|
|
channo = atoi(num);
|
|
|
|
}
|
|
|
|
caller_profile->destination_number = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2006-02-22 02:50:33 +00:00
|
|
|
|
|
|
|
snprintf(name, sizeof(name), "WanPipe/%s-%04x", caller_profile->destination_number, rand() & 0xffff);
|
|
|
|
switch_channel_set_name(channel, name);
|
2006-02-10 22:26:00 +00:00
|
|
|
switch_channel_set_caller_profile(channel, caller_profile);
|
|
|
|
tech_pvt->caller_profile = caller_profile;
|
2006-02-22 02:50:33 +00:00
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
do {
|
|
|
|
if ((spri = &SPANS[span]->spri)) {
|
2006-02-26 04:52:34 +00:00
|
|
|
chanmap = spri->private_info;
|
2006-02-12 20:38:24 +00:00
|
|
|
if (channo == 0) {
|
|
|
|
if (autochan > 0) {
|
|
|
|
for(channo = 1; channo < SANGOMA_MAX_CHAN_PER_SPAN; channo++) {
|
|
|
|
if ((SPANS[span]->bchans & (1 << channo)) && !chanmap->map[channo]) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Choosing channel %d\n", channo);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (autochan < 0) {
|
|
|
|
for(channo = SANGOMA_MAX_CHAN_PER_SPAN; channo > 0; channo--) {
|
|
|
|
if ((SPANS[span]->bchans & (1 << channo)) && !chanmap->map[channo]) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Choosing channel %d\n", channo);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (channo <= 0 || channo == (SANGOMA_MAX_CHAN_PER_SPAN)) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Free Channels!\n");
|
|
|
|
channo = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (channo) {
|
2006-02-10 22:26:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-02-12 20:38:24 +00:00
|
|
|
} while(autospan && span < MAX_SPANS && !spri && !channo);
|
|
|
|
|
|
|
|
|
|
|
|
if (!spri || channo == 0 || channo == (SANGOMA_MAX_CHAN_PER_SPAN)) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Free Channels!\n");
|
|
|
|
switch_core_session_destroy(new_session);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spri && (tech_pvt->call = pri_new_call(spri->pri))) {
|
|
|
|
struct pri_sr *sr;
|
2006-02-10 22:26:00 +00:00
|
|
|
|
|
|
|
sr = pri_sr_new();
|
2006-02-12 20:38:24 +00:00
|
|
|
pri_sr_set_channel(sr, channo, 0, 0);
|
|
|
|
pri_sr_set_bearer(sr, 0, SPANS[span]->l1);
|
|
|
|
pri_sr_set_called(sr, caller_profile->destination_number, SPANS[span]->dp, 1);
|
2006-02-10 22:26:00 +00:00
|
|
|
pri_sr_set_caller(sr,
|
|
|
|
caller_profile->caller_id_number,
|
|
|
|
caller_profile->caller_id_name,
|
2006-02-12 20:38:24 +00:00
|
|
|
SPANS[span]->dp,
|
2006-02-10 22:26:00 +00:00
|
|
|
PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN);
|
|
|
|
pri_sr_set_redirecting(sr,
|
|
|
|
caller_profile->caller_id_number,
|
2006-02-12 20:38:24 +00:00
|
|
|
SPANS[span]->dp,
|
2006-02-10 22:26:00 +00:00
|
|
|
PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN,
|
|
|
|
PRI_REDIR_UNCONDITIONAL);
|
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
if (pri_setup(spri->pri, tech_pvt->call , sr)) {
|
2006-02-10 22:26:00 +00:00
|
|
|
switch_core_session_destroy(new_session);
|
|
|
|
pri_sr_free(sr);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
2006-02-12 20:38:24 +00:00
|
|
|
if ((tech_pvt->socket = sangoma_create_socket_intr(spri->span, channo)) < 0) {
|
2006-02-10 22:26:00 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open fd!\n");
|
|
|
|
switch_core_session_destroy(new_session);
|
|
|
|
pri_sr_free(sr);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
pri_sr_free(sr);
|
2006-02-12 20:38:24 +00:00
|
|
|
chanmap->map[channo] = *new_session;
|
|
|
|
tech_pvt->spri = spri;
|
2006-02-10 22:26:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Doh! no caller profile\n");
|
|
|
|
switch_core_session_destroy(new_session);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_channel_set_flag(channel, CF_OUTBOUND);
|
|
|
|
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
|
|
|
|
switch_channel_set_state(channel, CS_INIT);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
static switch_status wanpipe_answer_channel(switch_core_session *session)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
switch_channel *channel = NULL;
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
assert(tech_pvt != NULL);
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
if (switch_test_flag(tech_pvt, TFLAG_INBOUND)) {
|
|
|
|
pri_answer(tech_pvt->spri->pri, tech_pvt->call, 0, 1);
|
|
|
|
}
|
2006-01-03 22:13:59 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
static switch_status wanpipe_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
|
|
|
|
switch_io_flag flags, int stream_id)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
switch_channel *channel = NULL;
|
|
|
|
void *bp;
|
|
|
|
int bytes = 0, res = 0;
|
2006-02-22 18:32:15 +00:00
|
|
|
char digit_str[80];
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
assert(tech_pvt != NULL);
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
if (tech_pvt->socket <= 0) {
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
bp = tech_pvt->databuf;
|
|
|
|
|
|
|
|
*frame = NULL;
|
|
|
|
memset(tech_pvt->databuf, 0, sizeof(tech_pvt->databuf));
|
2006-02-22 15:20:46 +00:00
|
|
|
while (bytes < globals.mtu) {
|
2006-02-10 22:26:00 +00:00
|
|
|
if ((res = sangoma_socket_waitfor(tech_pvt->socket, timeout, POLLIN | POLLERR)) < 0) {
|
2006-01-03 22:13:59 +00:00
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
} else if (res == 0) {
|
2006-02-10 22:26:00 +00:00
|
|
|
tech_pvt->read_frame.datalen = 0;
|
2006-01-03 22:13:59 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
if ((res = sangoma_readmsg_socket(tech_pvt->socket,
|
2006-01-03 22:13:59 +00:00
|
|
|
&tech_pvt->hdrframe,
|
2006-01-20 15:05:05 +00:00
|
|
|
sizeof(tech_pvt->hdrframe), bp, sizeof(tech_pvt->databuf) - bytes, 0)) < 0) {
|
2006-01-03 22:13:59 +00:00
|
|
|
if (errno == EBUSY) {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bytes += res;
|
|
|
|
bp += bytes;
|
|
|
|
}
|
2006-02-10 22:26:00 +00:00
|
|
|
tech_pvt->read_frame.datalen = bytes;
|
2006-02-22 18:32:15 +00:00
|
|
|
tech_pvt->read_frame.samples = bytes / 2;
|
|
|
|
|
|
|
|
res = teletone_dtmf_detect (&tech_pvt->dtmf_detect, tech_pvt->read_frame.data, tech_pvt->read_frame.samples);
|
|
|
|
res = teletone_dtmf_get(&tech_pvt->dtmf_detect, digit_str, sizeof(digit_str));
|
|
|
|
|
|
|
|
if(digit_str[0]) {
|
|
|
|
switch_channel_queue_dtmf(channel, digit_str);
|
|
|
|
if (globals.debug) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "DTMF DETECTED: [%s]\n", digit_str);
|
|
|
|
}
|
2006-02-23 22:41:08 +00:00
|
|
|
if (globals.supress_dtmf_tone) {
|
|
|
|
memset(tech_pvt->read_frame.data, 0, tech_pvt->read_frame.datalen);
|
|
|
|
}
|
2006-02-22 18:32:15 +00:00
|
|
|
}
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
*frame = &tech_pvt->read_frame;
|
2006-01-03 22:13:59 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
static switch_status wanpipe_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
|
|
|
|
switch_io_flag flags, int stream_id)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
switch_channel *channel = NULL;
|
|
|
|
int res = 0;
|
|
|
|
int bytes = frame->datalen;
|
|
|
|
void *bp = frame->data;
|
2006-02-22 18:32:15 +00:00
|
|
|
unsigned char dtmf[1024];
|
|
|
|
int inuse, bread, bwrote = 0;
|
2006-01-03 22:13:59 +00:00
|
|
|
switch_status status = SWITCH_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
assert(tech_pvt != NULL);
|
|
|
|
|
2006-02-22 18:32:15 +00:00
|
|
|
while (tech_pvt->dtmf_buffer && bwrote < frame->datalen && bytes > 0 && (inuse = switch_buffer_inuse(tech_pvt->dtmf_buffer)) > 0) {
|
2006-02-24 19:11:49 +00:00
|
|
|
if ((bread = switch_buffer_read(tech_pvt->dtmf_buffer, dtmf, globals.mtu)) < globals.mtu) {
|
|
|
|
while (bread < globals.mtu) {
|
2006-02-22 18:32:15 +00:00
|
|
|
dtmf[bread++] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sangoma_socket_waitfor(tech_pvt->socket, -1, POLLOUT | POLLERR | POLLHUP);
|
|
|
|
res = sangoma_sendmsg_socket(tech_pvt->socket,
|
|
|
|
&tech_pvt->hdrframe, sizeof(tech_pvt->hdrframe), dtmf, bread, 0);
|
|
|
|
if (res < 0) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE,
|
|
|
|
"Bad Write %d bytes returned %d (%s)!\n", bread,
|
|
|
|
res, strerror(errno));
|
|
|
|
if (errno == EBUSY) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Write Failed!\n");
|
|
|
|
status = SWITCH_STATUS_GENERR;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
bytes -= res;
|
|
|
|
bwrote += res;
|
|
|
|
bp += res;
|
|
|
|
res = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
while (bytes > 0) {
|
2006-02-10 22:26:00 +00:00
|
|
|
sangoma_socket_waitfor(tech_pvt->socket, -1, POLLOUT | POLLERR | POLLHUP);
|
2006-01-20 15:05:05 +00:00
|
|
|
res = sangoma_sendmsg_socket(tech_pvt->socket,
|
2006-02-24 19:11:49 +00:00
|
|
|
&tech_pvt->hdrframe, sizeof(tech_pvt->hdrframe), bp, globals.mtu, 0);
|
2006-01-03 22:13:59 +00:00
|
|
|
if (res < 0) {
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE,
|
2006-02-22 15:20:46 +00:00
|
|
|
"Bad Write frame len %d write %d bytes returned %d (%s)!\n", frame->datalen,
|
2006-02-24 19:11:49 +00:00
|
|
|
globals.mtu, res, strerror(errno));
|
2006-01-03 22:13:59 +00:00
|
|
|
if (errno == EBUSY) {
|
|
|
|
continue;
|
|
|
|
}
|
2006-02-22 15:20:46 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Write Failed!\n");
|
2006-01-03 22:13:59 +00:00
|
|
|
status = SWITCH_STATUS_GENERR;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
bytes -= res;
|
|
|
|
bp += res;
|
|
|
|
res = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2006-02-22 16:47:07 +00:00
|
|
|
static switch_status wanpipe_send_dtmf(switch_core_session *session, char *digits)
|
|
|
|
{
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
switch_channel *channel = NULL;
|
|
|
|
switch_status status = SWITCH_STATUS_SUCCESS;
|
|
|
|
int wrote = 0;
|
|
|
|
char *cur = NULL;
|
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
assert(tech_pvt != NULL);
|
|
|
|
|
|
|
|
if (!tech_pvt->dtmf_buffer) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Allocate DTMF Buffer....");
|
2006-02-22 18:32:15 +00:00
|
|
|
if (switch_buffer_create(switch_core_session_get_pool(session), &tech_pvt->dtmf_buffer, 3192) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "FAILURE!\n");
|
2006-02-22 16:47:07 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
} else {
|
2006-02-22 18:32:15 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "SUCCESS!\n");
|
2006-02-22 16:47:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (cur = digits; *cur; cur++) {
|
|
|
|
if ((wrote = teletone_mux_tones(&tech_pvt->tone_session, &tech_pvt->tone_session.TONES[(int)*cur]))) {
|
|
|
|
switch_buffer_write(tech_pvt->dtmf_buffer, tech_pvt->tone_session.buffer, wrote * 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static switch_status wanpipe_receive_message(switch_core_session *session, switch_core_session_message *msg)
|
|
|
|
{
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static switch_status wanpipe_kill_channel(switch_core_session *session, int sig)
|
|
|
|
{
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
switch_channel *channel = NULL;
|
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
assert(tech_pvt != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
switch_clear_flag(tech_pvt, TFLAG_MEDIA);
|
|
|
|
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
static const switch_io_routines wanpipe_io_routines = {
|
2006-01-20 15:05:05 +00:00
|
|
|
/*.outgoing_channel */ wanpipe_outgoing_channel,
|
2006-02-10 22:26:00 +00:00
|
|
|
/*.answer_channel */ wanpipe_answer_channel,
|
|
|
|
/*.read_frame */ wanpipe_read_frame,
|
2006-02-22 16:47:07 +00:00
|
|
|
/*.write_frame */ wanpipe_write_frame,
|
|
|
|
/*.kill_channel */ wanpipe_kill_channel,
|
|
|
|
/*.waitfor_read */ NULL,
|
|
|
|
/*.waitfor_read */ NULL,
|
|
|
|
/*.send_dtmf*/ wanpipe_send_dtmf,
|
|
|
|
/*.receive_message*/ wanpipe_receive_message
|
2006-01-03 22:13:59 +00:00
|
|
|
};
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
static const switch_state_handler_table wanpipe_state_handlers = {
|
2006-01-20 15:05:05 +00:00
|
|
|
/*.on_init */ wanpipe_on_init,
|
|
|
|
/*.on_ring */ wanpipe_on_ring,
|
|
|
|
/*.on_execute */ NULL,
|
|
|
|
/*.on_hangup */ wanpipe_on_hangup,
|
|
|
|
/*.on_loopback */ wanpipe_on_loopback,
|
|
|
|
/*.on_transmit */ wanpipe_on_transmit
|
2006-01-03 22:13:59 +00:00
|
|
|
};
|
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
static const switch_endpoint_interface wanpipe_endpoint_interface = {
|
2006-01-20 15:05:05 +00:00
|
|
|
/*.interface_name */ "wanpipe",
|
|
|
|
/*.io_routines */ &wanpipe_io_routines,
|
2006-02-10 22:26:00 +00:00
|
|
|
/*.state_handlers */ &wanpipe_state_handlers,
|
2006-01-20 15:05:05 +00:00
|
|
|
/*.private */ NULL,
|
|
|
|
/*.next */ NULL
|
2006-01-03 22:13:59 +00:00
|
|
|
};
|
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
static const switch_loadable_module_interface wanpipe_module_interface = {
|
2006-01-20 15:05:05 +00:00
|
|
|
/*.module_name */ modname,
|
|
|
|
/*.endpoint_interface */ &wanpipe_endpoint_interface,
|
|
|
|
/*.timer_interface */ NULL,
|
|
|
|
/*.dialplan_interface */ NULL,
|
|
|
|
/*.codec_interface */ NULL,
|
|
|
|
/*.application_interface */ NULL
|
2006-01-03 22:13:59 +00:00
|
|
|
};
|
|
|
|
|
2006-02-24 19:11:49 +00:00
|
|
|
static void s_pri_error(struct pri *pri, char *s)
|
|
|
|
{
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void s_pri_message(struct pri *pri, char *s)
|
|
|
|
{
|
|
|
|
s_pri_error(pri, s);
|
|
|
|
}
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
|
2006-01-20 15:05:05 +00:00
|
|
|
{
|
2006-02-24 19:11:49 +00:00
|
|
|
switch_status status = SWITCH_STATUS_SUCCESS;
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
memset(SPANS, 0, sizeof(SPANS));
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OH OH no pool\n");
|
|
|
|
return SWITCH_STATUS_TERM;
|
|
|
|
}
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
/* start the pri's */
|
2006-02-24 19:11:49 +00:00
|
|
|
if ((status = config_wanpipe(0) != SWITCH_STATUS_SUCCESS)) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
pri_set_error(s_pri_error);
|
|
|
|
pri_set_message(s_pri_message);
|
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
/* connect my internal structure to the blank pointer passed to me */
|
2006-01-13 14:23:34 +00:00
|
|
|
*interface = &wanpipe_module_interface;
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
/* indicate that the module should continue to be loaded */
|
2006-02-24 19:11:49 +00:00
|
|
|
return status;
|
2006-01-03 22:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
/*event Handlers */
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "number is: %s\n", event->ring.callednum);
|
|
|
|
if (strlen(event->ring.callednum) > 3) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "final number is: %s\n", event->ring.callednum);
|
|
|
|
pri_answer(spri->pri, event->ring.call, 0, 1);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
struct channel_map *chanmap;
|
|
|
|
switch_core_session *session;
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
|
2006-02-26 04:52:34 +00:00
|
|
|
chanmap = spri->private_info;
|
2006-01-03 22:13:59 +00:00
|
|
|
if ((session = chanmap->map[event->hangup.channel])) {
|
|
|
|
switch_channel *channel = NULL;
|
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
assert(tech_pvt != NULL);
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
if (!tech_pvt->call) {
|
|
|
|
tech_pvt->call = event->hangup.call;
|
|
|
|
}
|
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
tech_pvt->cause = event->hangup.cause;
|
|
|
|
|
|
|
|
switch_channel_set_state(channel, CS_HANGUP);
|
2006-02-10 22:26:00 +00:00
|
|
|
chanmap->map[event->hangup.channel] = NULL;
|
2006-01-03 22:13:59 +00:00
|
|
|
}
|
2006-01-20 15:05:05 +00:00
|
|
|
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Hanging up channel %d\n", event->hangup.channel);
|
2006-01-03 22:13:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
static int on_answer(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
|
|
|
{
|
|
|
|
switch_core_session *session;
|
|
|
|
switch_channel *channel;
|
|
|
|
struct channel_map *chanmap;
|
|
|
|
|
2006-02-26 04:52:34 +00:00
|
|
|
chanmap = spri->private_info;
|
2006-02-10 22:26:00 +00:00
|
|
|
|
|
|
|
if ((session = chanmap->map[event->answer.channel])) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Answer on channel %d\n", event->answer.channel);
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
switch_channel_answer(channel);
|
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Answer on channel %d but it's not in use?\n", event->answer.channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-22 02:50:33 +00:00
|
|
|
|
|
|
|
static int on_proceed(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
|
|
|
{
|
|
|
|
switch_core_session *session;
|
|
|
|
switch_channel *channel;
|
|
|
|
struct channel_map *chanmap;
|
|
|
|
|
2006-02-26 04:52:34 +00:00
|
|
|
chanmap = spri->private_info;
|
2006-02-22 02:50:33 +00:00
|
|
|
|
|
|
|
if ((session = chanmap->map[event->proceeding.channel])) {
|
|
|
|
switch_caller_profile *originator;
|
|
|
|
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Proceeding on channel %d\n", event->proceeding.channel);
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
if ((originator = switch_channel_get_originator_caller_profile(channel))) {
|
|
|
|
switch_core_session_message msg;
|
|
|
|
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Passing progress to Originator %s\n", originator->chan_name);
|
|
|
|
|
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_PROGRESS;
|
|
|
|
msg.from = switch_channel_get_name(channel);
|
|
|
|
|
|
|
|
switch_core_session_message_send(originator->uuid, &msg);
|
|
|
|
|
|
|
|
switch_channel_set_flag(channel, CF_EARLY_MEDIA);
|
|
|
|
}
|
|
|
|
|
|
|
|
//switch_channel_answer(channel);
|
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Proceeding on channel %d but it's not in use?\n", event->proceeding.channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-22 15:20:46 +00:00
|
|
|
#if 0
|
2006-02-10 22:26:00 +00:00
|
|
|
static int on_ringing(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
|
|
|
{
|
|
|
|
switch_core_session *session;
|
|
|
|
switch_channel *channel;
|
|
|
|
struct channel_map *chanmap;
|
|
|
|
struct private_object *tech_pvt;
|
|
|
|
|
2006-02-26 04:52:34 +00:00
|
|
|
chanmap = spri->private_info;
|
2006-02-10 22:26:00 +00:00
|
|
|
|
|
|
|
if ((session = chanmap->map[event->ringing.channel])) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Ringing on channel %d\n", event->ringing.channel);
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
|
|
|
pri_proceeding(spri->pri, event->ringing.call, event->ringing.channel, 0);
|
|
|
|
pri_acknowledge(spri->pri, event->ringing.call, event->ringing.channel, 0);
|
|
|
|
|
|
|
|
tech_pvt = switch_core_session_get_private(session);
|
|
|
|
if (!tech_pvt->call) {
|
|
|
|
tech_pvt->call = event->ringing.call;
|
|
|
|
}
|
|
|
|
tech_pvt->callno = event->ring.channel;
|
2006-02-22 18:32:15 +00:00
|
|
|
tech_pvt->span = spri->span;
|
2006-02-10 22:26:00 +00:00
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Ringing on channel %d but it's not in use?\n", event->ringing.channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2006-02-22 15:20:46 +00:00
|
|
|
#endif
|
2006-02-10 22:26:00 +00:00
|
|
|
|
|
|
|
static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
char name[128];
|
|
|
|
switch_core_session *session;
|
|
|
|
switch_channel *channel;
|
|
|
|
struct channel_map *chanmap;
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-02-26 04:52:34 +00:00
|
|
|
chanmap = spri->private_info;
|
2006-01-03 22:13:59 +00:00
|
|
|
if (chanmap->map[event->ring.channel]) {
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "--Duplicate Ring on channel %d (ignored)\n",
|
|
|
|
event->ring.channel);
|
2006-01-03 22:13:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Ring on channel %d (from %s to %s)\n", event->ring.channel,
|
|
|
|
event->ring.callingnum, event->ring.callednum);
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
|
|
|
|
pri_proceeding(spri->pri, event->ring.call, event->ring.channel, 0);
|
|
|
|
pri_acknowledge(spri->pri, event->ring.call, event->ring.channel, 0);
|
|
|
|
|
2006-01-13 14:23:34 +00:00
|
|
|
if ((session = switch_core_session_request(&wanpipe_endpoint_interface, NULL))) {
|
2006-01-03 22:13:59 +00:00
|
|
|
struct private_object *tech_pvt;
|
|
|
|
int fd;
|
|
|
|
char ani2str[4] = "";
|
|
|
|
//wanpipe_tdm_api_t tdm_api;
|
|
|
|
|
2006-01-09 18:40:56 +00:00
|
|
|
switch_core_session_add_stream(session, NULL);
|
2006-01-03 22:13:59 +00:00
|
|
|
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(session, sizeof(struct private_object)))) {
|
|
|
|
memset(tech_pvt, 0, sizeof(*tech_pvt));
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
switch_core_session_set_private(session, tech_pvt);
|
2006-02-12 20:38:24 +00:00
|
|
|
sprintf(name, "w%dg%d", spri->span, event->ring.channel);
|
2006-02-10 22:26:00 +00:00
|
|
|
switch_channel_set_name(channel, name);
|
2006-02-22 02:50:33 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
|
|
|
|
switch_core_session_destroy(&session);
|
|
|
|
return 0;
|
|
|
|
}
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
if (event->ring.ani2 >= 0) {
|
|
|
|
snprintf(ani2str, 5, "%.2d", event->ring.ani2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
|
2006-01-20 15:05:05 +00:00
|
|
|
globals.dialplan,
|
|
|
|
"wanpipe fixme",
|
|
|
|
event->ring.callingnum,
|
|
|
|
event->ring.callingani,
|
|
|
|
switch_strlen_zero(ani2str) ? NULL : ani2str,
|
2006-02-10 22:26:00 +00:00
|
|
|
NULL,
|
2006-01-20 15:05:05 +00:00
|
|
|
event->ring.callednum))) {
|
2006-01-03 22:13:59 +00:00
|
|
|
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_set_flag(tech_pvt, TFLAG_INBOUND);
|
|
|
|
tech_pvt->spri = spri;
|
|
|
|
tech_pvt->cause = -1;
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
if (!tech_pvt->call) {
|
|
|
|
tech_pvt->call = event->ring.call;
|
|
|
|
}
|
2006-02-22 18:32:15 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
tech_pvt->callno = event->ring.channel;
|
2006-02-22 18:32:15 +00:00
|
|
|
tech_pvt->span = spri->span;
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
if ((fd = sangoma_create_socket_intr(spri->span, event->ring.channel)) < 0) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open fd!\n");
|
|
|
|
}
|
|
|
|
//sangoma_tdm_set_hw_period(fd, &tdm_api, 480);
|
|
|
|
|
|
|
|
tech_pvt->socket = fd;
|
|
|
|
chanmap->map[event->ring.channel] = session;
|
|
|
|
|
|
|
|
switch_channel_set_state(channel, CS_INIT);
|
|
|
|
switch_core_session_thread_launch(session);
|
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Cannot Create new Inbound Channel!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int check_flags(struct sangoma_pri *spri)
|
|
|
|
{
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
int fd;
|
2006-02-10 22:26:00 +00:00
|
|
|
switch_core_session *session;
|
|
|
|
struct channel_map *chanmap;
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Restarting channel %d\n", event->restart.channel);
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-26 04:52:34 +00:00
|
|
|
chanmap = spri->private_info;
|
2006-02-10 22:26:00 +00:00
|
|
|
|
|
|
|
if ((session = chanmap->map[event->restart.channel])) {
|
|
|
|
switch_channel *channel;
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hanging Up %s\n", switch_channel_get_name(channel));
|
|
|
|
switch_channel_hangup(channel);
|
|
|
|
}
|
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
if ((fd = sangoma_create_socket_intr(spri->span, event->restart.channel)) < 0) {
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open fd!\n");
|
2006-01-03 22:13:59 +00:00
|
|
|
} else {
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-10 22:26:00 +00:00
|
|
|
static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Caught Event %d (%s)\n", event_type,
|
|
|
|
sangoma_pri_event_str(event_type));
|
2006-01-03 22:13:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void *pri_thread_run(switch_thread *thread, void *obj)
|
|
|
|
{
|
|
|
|
struct sangoma_pri *spri = obj;
|
|
|
|
struct channel_map chanmap;
|
2006-02-22 15:20:46 +00:00
|
|
|
|
2006-02-14 16:42:26 +00:00
|
|
|
switch_event *s_event;
|
2006-01-03 22:13:59 +00:00
|
|
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_ANY, on_anything);
|
|
|
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_RING, on_ring);
|
2006-02-22 15:20:46 +00:00
|
|
|
//SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_RINGING, on_ringing);
|
2006-02-10 22:26:00 +00:00
|
|
|
//SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_SETUP_ACK, on_ringing);
|
2006-02-22 02:50:33 +00:00
|
|
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_PROCEEDING, on_proceed);
|
2006-02-10 22:26:00 +00:00
|
|
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_ANSWER, on_answer);
|
2006-01-03 22:13:59 +00:00
|
|
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_HANGUP_REQ, on_hangup);
|
2006-02-22 02:50:33 +00:00
|
|
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_HANGUP, on_hangup);
|
2006-01-03 22:13:59 +00:00
|
|
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_INFO_RECEIVED, on_info);
|
|
|
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_RESTART, on_restart);
|
|
|
|
|
|
|
|
spri->on_loop = check_flags;
|
2006-02-26 04:52:34 +00:00
|
|
|
spri->private_info = &chanmap;
|
2006-02-14 16:42:26 +00:00
|
|
|
|
|
|
|
if (switch_event_create(&s_event, SWITCH_EVENT_PUBLISH) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_pri._tcp");
|
|
|
|
switch_event_fire(&s_event);
|
|
|
|
}
|
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
sangoma_run_pri(spri);
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
free(spri);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
static void pri_thread_launch(struct sangoma_pri *spri)
|
|
|
|
{
|
|
|
|
switch_thread *thread;
|
|
|
|
switch_threadattr_t *thd_attr = NULL;
|
|
|
|
|
|
|
|
switch_threadattr_create(&thd_attr, module_pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
|
|
|
switch_thread_create(&thread, thd_attr, pri_thread_run, spri, module_pool);
|
|
|
|
|
|
|
|
}
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-24 19:11:49 +00:00
|
|
|
static switch_status config_wanpipe(int reload)
|
2006-01-03 22:13:59 +00:00
|
|
|
{
|
|
|
|
switch_config cfg;
|
|
|
|
char *var, *val;
|
|
|
|
int count = 0;
|
2006-01-13 14:23:34 +00:00
|
|
|
char *cf = "wanpipe.conf";
|
2006-02-12 20:38:24 +00:00
|
|
|
int current_span = 0;
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-22 15:20:46 +00:00
|
|
|
globals.mtu = DEFAULT_MTU;
|
2006-02-22 18:32:15 +00:00
|
|
|
globals.dtmf_on = 150;
|
|
|
|
globals.dtmf_off = 50;
|
2006-01-03 22:13:59 +00:00
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
if (!switch_config_open_file(&cfg, cf)) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "open of %s failed\n", cf);
|
|
|
|
return SWITCH_STATUS_TERM;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (switch_config_next_pair(&cfg, &var, &val)) {
|
|
|
|
if (!strcasecmp(cfg.category, "settings")) {
|
|
|
|
if (!strcmp(var, "debug")) {
|
|
|
|
globals.debug = atoi(val);
|
2006-02-22 15:20:46 +00:00
|
|
|
} else if (!strcmp(var, "mtu")) {
|
|
|
|
globals.mtu = atoi(val);
|
2006-02-22 18:32:15 +00:00
|
|
|
} else if (!strcmp(var, "dtmf_on")) {
|
|
|
|
globals.dtmf_on = atoi(val);
|
|
|
|
} else if (!strcmp(var, "dtmf_off")) {
|
|
|
|
globals.dtmf_off = atoi(val);
|
2006-02-23 22:41:08 +00:00
|
|
|
} else if (!strcmp(var, "supress_dtmf_tone")) {
|
|
|
|
globals.supress_dtmf_tone = switch_true(val);
|
2006-02-12 20:38:24 +00:00
|
|
|
}
|
|
|
|
} else if (!strcasecmp(cfg.category, "span")) {
|
|
|
|
if (!strcmp(var, "span")) {
|
|
|
|
current_span = atoi(val);
|
|
|
|
if (current_span <= 0 || current_span > MAX_SPANS) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid SPAN!\n");
|
|
|
|
current_span = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!SPANS[current_span]) {
|
|
|
|
if (!(SPANS[current_span] = switch_core_alloc(module_pool, sizeof(*SPANS[current_span])))) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "MEMORY ERROR\n");
|
|
|
|
break;;
|
|
|
|
}
|
|
|
|
SPANS[current_span]->span = current_span;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (!current_span) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid option %s when no span defined.\n", var);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(var, "dchan")) {
|
|
|
|
SPANS[current_span]->dchan = atoi(val);
|
|
|
|
} else if (!strcmp(var, "bchan")) {
|
|
|
|
char from[128];
|
|
|
|
char *to;
|
|
|
|
switch_copy_string(from, val, sizeof(from));
|
|
|
|
if ((to = strchr(from, '-'))) {
|
|
|
|
int fromi, toi, x = 0;
|
|
|
|
*to++ = '\0';
|
|
|
|
fromi = atoi(from);
|
|
|
|
toi = atoi(to);
|
|
|
|
if (fromi > 0 && toi > 0 && fromi < toi && fromi < MAX_SPANS && toi < MAX_SPANS) {
|
|
|
|
for(x = fromi; x <= toi; x++) {
|
|
|
|
SPANS[current_span]->bchans |= (1 << x);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid bchan range!\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int i = atoi(val);
|
|
|
|
if (i > 0 && i < 31) {
|
|
|
|
SPANS[current_span]->bchans |= (1 << i);
|
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid bchan!\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (!strcmp(var, "node")) {
|
|
|
|
SPANS[current_span]->node = str2node(val);
|
|
|
|
} else if (!strcmp(var, "switch")) {
|
|
|
|
SPANS[current_span]->pswitch = str2switch(val);
|
|
|
|
} else if (!strcmp(var, "dp")) {
|
|
|
|
SPANS[current_span]->dp = str2dp(val);
|
|
|
|
} else if (!strcmp(var, "l1")) {
|
|
|
|
SPANS[current_span]->l1 = str2l1(val);
|
|
|
|
} else if (!strcmp(var, "dialplan")) {
|
|
|
|
set_global_dialplan(val);
|
2006-02-22 15:20:46 +00:00
|
|
|
} else if (!strcmp(var, "mtu")) {
|
|
|
|
int mtu = atoi(val);
|
|
|
|
|
|
|
|
if (mtu >= 10 && mtu < 960) {
|
|
|
|
SPANS[current_span]->mtu = mtu;
|
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid MTU (%s)!\n", val);
|
|
|
|
}
|
2006-02-12 20:38:24 +00:00
|
|
|
}
|
2006-01-20 15:05:05 +00:00
|
|
|
}
|
2006-01-03 22:13:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_config_close_file(&cfg);
|
|
|
|
|
|
|
|
if (!globals.dialplan) {
|
|
|
|
set_global_dialplan("default");
|
|
|
|
}
|
|
|
|
|
2006-02-22 15:20:46 +00:00
|
|
|
|
2006-02-24 16:47:22 +00:00
|
|
|
globals.configured_spans = 0;
|
2006-02-12 20:38:24 +00:00
|
|
|
for(current_span = 1; current_span < MAX_SPANS; current_span++) {
|
|
|
|
if (SPANS[current_span]) {
|
2006-02-21 19:36:51 +00:00
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
if (!SPANS[current_span]->l1) {
|
|
|
|
SPANS[current_span]->l1 = PRI_LAYER_1_ULAW;
|
|
|
|
}
|
2006-02-21 19:36:51 +00:00
|
|
|
if (sangoma_init_pri(&SPANS[current_span]->spri,
|
|
|
|
current_span,
|
|
|
|
SPANS[current_span]->dchan,
|
|
|
|
SPANS[current_span]->pswitch,
|
|
|
|
SPANS[current_span]->node,
|
|
|
|
globals.debug)) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Cannot launch span %d\n", current_span);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Launch span %d\n", current_span);
|
2006-02-12 20:38:24 +00:00
|
|
|
pri_thread_launch(&SPANS[current_span]->spri);
|
2006-02-24 16:47:22 +00:00
|
|
|
globals.configured_spans++;
|
2006-02-12 20:38:24 +00:00
|
|
|
}
|
|
|
|
}
|
2006-01-20 15:05:05 +00:00
|
|
|
|
|
|
|
|
2006-01-03 22:13:59 +00:00
|
|
|
|
|
|
|
return count;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-12 20:38:24 +00:00
|
|
|
|