mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-02-24 18:41:57 +00:00
635 lines
18 KiB
C
635 lines
18 KiB
C
|
/*
|
||
|
* 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>
|
||
|
*
|
||
|
*
|
||
|
* mod_wanchan.c -- WANPIPE PRI Channel Module
|
||
|
*
|
||
|
*/
|
||
|
#include <switch.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/time.h>
|
||
|
#include <sys/queue.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <unistd.h>
|
||
|
#include <ctype.h>
|
||
|
#include <string.h>
|
||
|
#include <libsangoma.h>
|
||
|
#include <sangoma_pri.h>
|
||
|
|
||
|
static const char modname[] = "mod_wanchan";
|
||
|
#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;
|
||
|
|
||
|
#define PACKET_LEN 160
|
||
|
#define DEFAULT_BYTES_PER_FRAME 160
|
||
|
|
||
|
static struct {
|
||
|
int debug;
|
||
|
int panic;
|
||
|
int span;
|
||
|
int dchan;
|
||
|
int node;
|
||
|
int pswitch;
|
||
|
int bytes_per_frame;
|
||
|
char *dialplan;
|
||
|
} globals;
|
||
|
|
||
|
|
||
|
|
||
|
struct private_object {
|
||
|
unsigned int flags; /* FLAGS */
|
||
|
struct switch_frame frame; /* Frame for Writing */
|
||
|
unsigned char databuf[1024];
|
||
|
struct sangoma_pri *spri;
|
||
|
pri_event ring_event;
|
||
|
pri_event hangup_event;
|
||
|
sangoma_api_hdr_t hdrframe;
|
||
|
switch_caller_profile *caller_profile;
|
||
|
int socket;
|
||
|
int callno;
|
||
|
int cause;
|
||
|
};
|
||
|
|
||
|
struct channel_map {
|
||
|
switch_core_session *map[36];
|
||
|
};
|
||
|
|
||
|
|
||
|
static void set_global_dialplan(char *dialplan)
|
||
|
{
|
||
|
if (globals.dialplan) {
|
||
|
free(globals.dialplan);
|
||
|
globals.dialplan = NULL;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static void set_global_dialplan(char *dialplan);
|
||
|
static int str2node(char *node);
|
||
|
static int str2switch(char *swtype);
|
||
|
static switch_status wanchan_on_init(switch_core_session *session);
|
||
|
static switch_status wanchan_on_hangup(switch_core_session *session);
|
||
|
static switch_status wanchan_on_loopback(switch_core_session *session);
|
||
|
static switch_status wanchan_on_transmit(switch_core_session *session);
|
||
|
static switch_status wanchan_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session);
|
||
|
static switch_status wanchan_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags);
|
||
|
static switch_status wanchan_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags);
|
||
|
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);
|
||
|
static int check_flags(struct sangoma_pri *spri);
|
||
|
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);
|
||
|
static void *pri_thread_run(switch_thread *thread, void *obj);
|
||
|
static int config_wanpipe(int reload);
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
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.
|
||
|
*/
|
||
|
static switch_status wanchan_on_init(switch_core_session *session)
|
||
|
{
|
||
|
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);
|
||
|
|
||
|
tech_pvt->frame.data = tech_pvt->databuf;
|
||
|
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANCHAN INIT\n");
|
||
|
|
||
|
|
||
|
/* Move Channel's State Machine to RING */
|
||
|
switch_channel_set_state(channel, CS_RING);
|
||
|
return SWITCH_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static switch_status wanchan_on_ring(switch_core_session *session)
|
||
|
{
|
||
|
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);
|
||
|
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANCHAN RING\n");
|
||
|
|
||
|
return SWITCH_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static switch_status wanchan_on_hangup(switch_core_session *session)
|
||
|
{
|
||
|
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_socket_close(&tech_pvt->socket);
|
||
|
|
||
|
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, tech_pvt->hangup_event.hangup.call ? tech_pvt->hangup_event.hangup.call : tech_pvt->ring_event.ring.call);
|
||
|
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANCHAN HANGUP\n");
|
||
|
return SWITCH_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static switch_status wanchan_on_loopback(switch_core_session *session)
|
||
|
{
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANCHAN LOOPBACK\n");
|
||
|
return SWITCH_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static switch_status wanchan_on_transmit(switch_core_session *session)
|
||
|
{
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANCHAN TRANSMIT\n");
|
||
|
return SWITCH_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static switch_status wanchan_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session)
|
||
|
{
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "NOT IMPLEMENTED\n");
|
||
|
|
||
|
return SWITCH_STATUS_GENERR;
|
||
|
}
|
||
|
|
||
|
static switch_status wanchan_answer_channel(switch_core_session *session)
|
||
|
{
|
||
|
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);
|
||
|
|
||
|
pri_answer(tech_pvt->spri->pri, tech_pvt->ring_event.ring.call, 0, 1);
|
||
|
|
||
|
return SWITCH_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static switch_status wanchan_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags)
|
||
|
{
|
||
|
struct private_object *tech_pvt;
|
||
|
switch_channel *channel = NULL;
|
||
|
void *bp;
|
||
|
int bytes = 0, res = 0;
|
||
|
|
||
|
channel = switch_core_session_get_channel(session);
|
||
|
assert(channel != NULL);
|
||
|
|
||
|
tech_pvt = switch_core_session_get_private(session);
|
||
|
assert(tech_pvt != NULL);
|
||
|
|
||
|
bp = tech_pvt->databuf;
|
||
|
|
||
|
*frame = NULL;
|
||
|
memset(tech_pvt->databuf, 0, sizeof(tech_pvt->databuf));
|
||
|
while (bytes < globals.bytes_per_frame) {
|
||
|
if ((res = switch_socket_waitfor(tech_pvt->socket, timeout, POLLIN|POLLERR)) < 0) {
|
||
|
return SWITCH_STATUS_GENERR;
|
||
|
} else if (res == 0) {
|
||
|
tech_pvt->frame.datalen = 0;
|
||
|
return SWITCH_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
if ((res = sangoma_readmsg_socket(
|
||
|
tech_pvt->socket,
|
||
|
&tech_pvt->hdrframe,
|
||
|
sizeof(tech_pvt->hdrframe),
|
||
|
bp,
|
||
|
sizeof(tech_pvt->databuf) - bytes, 0)) < 0) {
|
||
|
if (errno == EBUSY) {
|
||
|
continue;
|
||
|
} else {
|
||
|
return SWITCH_STATUS_GENERR;
|
||
|
}
|
||
|
}
|
||
|
bytes += res;
|
||
|
bp += bytes;
|
||
|
}
|
||
|
tech_pvt->frame.datalen = bytes;
|
||
|
|
||
|
*frame = &tech_pvt->frame;
|
||
|
return SWITCH_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static switch_status wanchan_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags)
|
||
|
{
|
||
|
struct private_object *tech_pvt;
|
||
|
switch_channel *channel = NULL;
|
||
|
int res = 0;
|
||
|
int bytes = frame->datalen;
|
||
|
void *bp = frame->data;
|
||
|
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);
|
||
|
|
||
|
while (bytes > 0) {
|
||
|
switch_socket_waitfor(tech_pvt->socket, -1, POLLOUT | POLLERR | POLLHUP);
|
||
|
res = sangoma_sendmsg_socket(
|
||
|
tech_pvt->socket,
|
||
|
&tech_pvt->hdrframe,
|
||
|
sizeof(tech_pvt->hdrframe),
|
||
|
bp,
|
||
|
PACKET_LEN, 0);
|
||
|
if (res < 0) {
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Bad Write frame len %d write %d bytes returned %d errno %d!\n", frame->datalen, PACKET_LEN, res, errno);
|
||
|
if (errno == EBUSY) {
|
||
|
continue;
|
||
|
}
|
||
|
status = SWITCH_STATUS_GENERR;
|
||
|
break;
|
||
|
} else {
|
||
|
bytes -= res;
|
||
|
bp += res;
|
||
|
res = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
static const switch_io_routines wanchan_io_routines*/ {
|
||
|
/*.outgoing_channel*/ wanchan_outgoing_channel,
|
||
|
/*.answer_channel*/ wanchan_answer_channel,
|
||
|
/*.read_frame*/ wanchan_read_frame,
|
||
|
/*.write_frame*/ wanchan_write_frame
|
||
|
};
|
||
|
|
||
|
static const switch_event_handler_table wanchan_event_handlers = {
|
||
|
/*.on_init*/ wanchan_on_init,
|
||
|
/*.on_ring*/ wanchan_on_ring,
|
||
|
/*.on_execute*/ NULL,
|
||
|
/*.on_hangup*/ wanchan_on_hangup,
|
||
|
/*.on_loopback*/ wanchan_on_loopback,
|
||
|
/*.on_transmit*/ wanchan_on_transmit
|
||
|
};
|
||
|
|
||
|
static const switch_endpoint_interface wanchan_endpoint_interface = {
|
||
|
/*.interface_name*/ "wanchan",
|
||
|
/*.io_routines*/ &wanchan_io_routines,
|
||
|
/*.event_handlers*/ &wanchan_event_handlers,
|
||
|
/*.private*/ NULL,
|
||
|
/*.next*/ NULL
|
||
|
};
|
||
|
|
||
|
static const switch_loadable_module_interface wanchan_module_interface = {
|
||
|
/*.module_name*/ modname,
|
||
|
/*.endpoint_interface*/ &wanchan_endpoint_interface,
|
||
|
/*.timer_interface*/ NULL,
|
||
|
/*.dialplan_interface*/ NULL,
|
||
|
/*.codec_interface*/ NULL,
|
||
|
/*.application_interface*/ NULL
|
||
|
};
|
||
|
|
||
|
Public switch_status switch_module_load(const switch_loadable_module_interface **interface, chanr *filename) {
|
||
|
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
/* connect my internal structure to the blank pointer passed to me */
|
||
|
*interface = &wanchan_module_interface;
|
||
|
|
||
|
/* indicate that the module should continue to be loaded */
|
||
|
return SWITCH_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* Event Handlers */
|
||
|
|
||
|
static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
||
|
{
|
||
|
struct channel_map *chanmap;
|
||
|
switch_core_session *session;
|
||
|
struct private_object *tech_pvt;
|
||
|
|
||
|
chanmap = spri->private;
|
||
|
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);
|
||
|
|
||
|
tech_pvt->cause = event->hangup.cause;
|
||
|
memcpy(&tech_pvt->hangup_event, event, sizeof(*event));
|
||
|
|
||
|
switch_channel_set_state(channel, CS_HANGUP);
|
||
|
}
|
||
|
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"-- Hanging up channel %d\n", event->hangup.channel);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
||
|
{
|
||
|
char name[128];
|
||
|
switch_core_session *session;
|
||
|
switch_channel *channel;
|
||
|
struct channel_map *chanmap;
|
||
|
|
||
|
|
||
|
|
||
|
chanmap = spri->private;
|
||
|
if (chanmap->map[event->ring.channel]) {
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"--Duplicate Ring on channel %d (ignored)\n", event->ring.channel);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"-- Ring on channel %d (from %s to %s)\n", event->ring.channel, event->ring.callingnum, event->ring.callednum);
|
||
|
|
||
|
sprintf(name, "w%dg%d", globals.span, event->ring.channel);
|
||
|
if ((session = switch_core_session_request(&wanchan_endpoint_interface, NULL))) {
|
||
|
struct private_object *tech_pvt;
|
||
|
int fd;
|
||
|
char ani2str[4] = "";
|
||
|
//wanpipe_tdm_api_t tdm_api;
|
||
|
|
||
|
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);
|
||
|
} else {
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
|
||
|
switch_core_session_destroy(&session);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (event->ring.ani2 >= 0) {
|
||
|
snprintf(ani2str, 5, "%.2d", event->ring.ani2);
|
||
|
}
|
||
|
|
||
|
if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
|
||
|
globals.dialplan,
|
||
|
"wanchan fixme",
|
||
|
event->ring.callingnum,
|
||
|
event->ring.callingani,
|
||
|
switch_strlen_zero(ani2str) ? NULL : ani2str,
|
||
|
event->ring.callednum))) {
|
||
|
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;
|
||
|
|
||
|
memcpy(&tech_pvt->ring_event, event, sizeof(*event));
|
||
|
|
||
|
tech_pvt->callno = event->ring.channel;
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
||
|
{
|
||
|
int fd;
|
||
|
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"-- Restarting channel %d\n", event->restart.channel);
|
||
|
|
||
|
if ((fd = sangoma_create_socket_intr(spri->span, event->restart.channel)) < 0) {
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"Can't open fd!\n");
|
||
|
} else {
|
||
|
close(fd);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event)
|
||
|
{
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"Caught Event %d (%s)\n", event_type, sangoma_pri_event_str(event_type));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void *pri_thread_run(switch_thread *thread, void *obj)
|
||
|
{
|
||
|
struct sangoma_pri *spri = obj;
|
||
|
struct channel_map chanmap;
|
||
|
|
||
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_ANY, on_anything);
|
||
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_RING, on_ring);
|
||
|
SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_HANGUP_REQ, on_hangup);
|
||
|
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;
|
||
|
spri->private = &chanmap;
|
||
|
sangoma_run_pri(spri);
|
||
|
|
||
|
free(spri);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int config_wanpipe(int reload)
|
||
|
{
|
||
|
switch_config cfg;
|
||
|
char *var, *val;
|
||
|
int count = 0;
|
||
|
struct sangoma_pri *spri;
|
||
|
char *cf = "wanchan.conf";
|
||
|
|
||
|
globals.bytes_per_frame = DEFAULT_BYTES_PER_FRAME;
|
||
|
|
||
|
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);
|
||
|
} else if (!strcmp(var, "span")) {
|
||
|
globals.span = atoi(val);
|
||
|
} else if (!strcmp(var, "dchan")) {
|
||
|
globals.dchan = atoi(val);
|
||
|
} else if (!strcmp(var, "node")) {
|
||
|
globals.node = str2node(val);
|
||
|
} else if (!strcmp(var, "switch")) {
|
||
|
globals.pswitch = str2switch(val);
|
||
|
} else if (!strcmp(var, "bpf")) {
|
||
|
globals.bytes_per_frame = atoi(val);
|
||
|
} else if (!strcmp(var, "dialplan")) {
|
||
|
set_global_dialplan(val);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch_config_close_file(&cfg);
|
||
|
|
||
|
if (!globals.dialplan) {
|
||
|
set_global_dialplan("default");
|
||
|
}
|
||
|
|
||
|
if ((spri=switch_core_alloc(module_pool, sizeof(*spri)))) {
|
||
|
memset(spri, 0, sizeof(*spri));
|
||
|
sangoma_init_pri(spri,
|
||
|
globals.span,
|
||
|
globals.dchan,
|
||
|
23,
|
||
|
globals.pswitch,
|
||
|
globals.node,
|
||
|
globals.debug);
|
||
|
|
||
|
pri_thread_run(NULL, spri);
|
||
|
|
||
|
} else {
|
||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "error!\n");
|
||
|
}
|
||
|
|
||
|
return count;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
Public switch_status switch_module_runtime(void)
|
||
|
{
|
||
|
config_wanpipe(0);
|
||
|
return SWITCH_STATUS_TERM;
|
||
|
}
|
||
|
|