[asterisk-commits] mattf: branch mattf/bug13495 r163158 - /team/mattf/bug13495/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Dec 11 11:31:35 CST 2008
Author: mattf
Date: Thu Dec 11 11:31:34 2008
New Revision: 163158
URL: http://svn.digium.com/view/asterisk?view=rev&rev=163158
Log:
Using this as development branch until we get ANSI support tested. Starting on ISUP masquerade and clustering support, initial check in of this code.
Modified:
team/mattf/bug13495/channels/chan_dahdi.c
Modified: team/mattf/bug13495/channels/chan_dahdi.c
URL: http://svn.digium.com/view/asterisk/team/mattf/bug13495/channels/chan_dahdi.c?view=diff&rev=163158&r1=163157&r2=163158
==============================================================================
--- team/mattf/bug13495/channels/chan_dahdi.c (original)
+++ team/mattf/bug13495/channels/chan_dahdi.c Thu Dec 11 11:31:34 2008
@@ -389,18 +389,22 @@
#define SS7_BLOCKED_MAINTENANCE (1 << 0)
#define SS7_BLOCKED_HARDWARE (1 << 1)
+#define SS7_MAX_SLAVES 100
+
struct dahdi_ss7 {
pthread_t master; /*!< Thread of master */
ast_mutex_t lock;
- int fds[NUM_DCHANS];
+ int fds[NUM_DCHANS + SS7_MAX_SLAVES];
int numsigchans;
int linkstate[NUM_DCHANS];
int numchans;
int type;
+
enum {
LINKSET_STATE_DOWN = 0,
LINKSET_STATE_UP
} state;
+
char called_nai; /*!< Called Nature of Address Indicator */
char calling_nai; /*!< Calling Nature of Address Indicator */
char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
@@ -413,6 +417,23 @@
int flags; /*!< Linkset flags */
int ss7type;
};
+
+struct slave_channel {
+ int linksetnum;
+ int startcic;
+ int endcic;
+ unsigned int opc;
+ char addr[64];
+};
+
+struct slave_chan_server {
+ int fd;
+
+ pthread_t master;
+ struct slave_channel slave_channel[SS7_MAX_SLAVES];
+ int numslaves;
+
+} slave_chan_server;
static struct dahdi_ss7 linksets[NUM_SPANS];
@@ -981,6 +1002,93 @@
#endif
#ifdef HAVE_SS7
+
+#define SS7_SLAVE_SERVER_PORT 7777
+
+static struct dahdi_ss7 * ss7_resolve_linkset(int linkset);
+
+static void * ss7_slave_server(void * data)
+{
+ struct sockaddr_in my_addr, slave_addr;
+ int slave_sock;
+ int i;
+ unsigned int len;
+
+ if ((slave_chan_server.fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ ast_log(LOG_ERROR, "Unable to open socket for SS7 slave server\n");
+ return NULL;
+ }
+
+ memset(&my_addr, 0, sizeof(my_addr));
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_port = htons(SS7_SLAVE_SERVER_PORT);
+ my_addr.sin_addr.s_addr = htons(INADDR_ANY);
+
+ if (bind(slave_chan_server.fd, (struct sockaddr *) &my_addr, sizeof(my_addr))) {
+ ast_log(LOG_ERROR, "Unable to bind to port %d in SS7 slave server\n", 7777);
+ close(slave_chan_server.fd);
+ return NULL;
+ }
+
+ if (listen(slave_chan_server.fd, SS7_MAX_SLAVES) == -1) {
+ ast_log(LOG_ERROR, "Unable to set max slaves on listen for SS7 slave server\n");
+ close(slave_chan_server.fd);
+ return NULL;
+ }
+
+ while (1) {
+do_accept:
+ if ((slave_sock = accept(slave_chan_server.fd, (struct sockaddr *) &slave_addr, &len)) == -1) {
+ ast_log(LOG_ERROR, "Error in accept: %s\n", strerror(errno));
+ continue;
+ }
+
+ for (i = 0; i < slave_chan_server.numslaves; i++) {
+ if (!strcasecmp(ast_inet_ntoa(slave_addr.sin_addr), slave_chan_server.slave_channel[i].addr)) {
+ struct dahdi_ss7 *ss7 = ss7_resolve_linkset(slave_chan_server.slave_channel[i].linksetnum);
+
+ ast_log(LOG_NOTICE, "Accepting SS7 slave connection from host %s\n", ast_inet_ntoa(slave_addr.sin_addr));
+
+ ast_mutex_lock(&ss7->lock);
+
+ isup_masquerade_add_route(ss7->ss7, slave_sock,
+ slave_chan_server.slave_channel[i].startcic,
+ slave_chan_server.slave_channel[i].endcic,
+ slave_chan_server.slave_channel[i].opc);
+
+ ss7->fds[ss7->numsigchans++] = slave_sock;
+ /* XXX */
+ ast_mutex_unlock(&ss7->lock);
+ goto do_accept;
+ }
+ }
+
+ /* If we get here, it is an unrecognized host trying to register */
+ ast_log(LOG_WARNING, "Unrecognized host %s tried to register with SS7 slave server\n", ast_inet_ntoa(slave_addr.sin_addr));
+ close(slave_sock);
+ }
+}
+
+static void ss7_add_slave_to_server(const char *addr)
+{
+ if (slave_chan_server.numslaves >= SS7_MAX_SLAVES) {
+ ast_log(LOG_ERROR, "Max slave channels reached (%d)\n", MAX_SLAVES);
+ return;
+ }
+
+ sscanf(addr, "%s,%d,%d-%d",
+ slave_chan_server.slave_channel[slave_chan_server.numslaves].addr,
+ &slave_chan_server.slave_channel[slave_chan_server.numslaves].opc,
+ &slave_chan_server.slave_channel[slave_chan_server.numslaves].startcic,
+ &slave_chan_server.slave_channel[slave_chan_server.numslaves].endcic);
+
+
+ slave_chan_server.slave_channel[slave_chan_server.numslaves].linksetnum = cur_linkset;
+ slave_chan_server.numslaves++;
+
+ return;
+}
+
static int ss7_find_alloc_call(struct dahdi_pvt *p);
static int ss7_do_rsc(struct dahdi_pvt *p);
@@ -10341,10 +10449,10 @@
}
break;
case MTP2_LINK_UP:
- ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
+ ast_verbose("MTP2 link up\n");
break;
case MTP2_LINK_DOWN:
- ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
+ ast_log(LOG_WARNING, "MTP2 link down\n");
break;
case ISUP_EVENT_CPG:
chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
@@ -14060,7 +14168,7 @@
}
#ifdef HAVE_SS7
-static int linkset_addsigchan(int sigchan)
+static int linkset_addsigchan(const char *sigchanstr)
{
struct dahdi_ss7 *link;
int res;
@@ -14068,7 +14176,20 @@
struct dahdi_params p;
struct dahdi_bufferinfo bi;
struct dahdi_spaninfo si;
-
+ char mysigstr[128];
+ char *tech = "DAHDI";
+ char *addr;
+
+ ast_copy_string(mysigstr, sigchanstr, sizeof(mysigstr));
+
+ addr = strchr(mysigstr, '/');
+
+ if (addr) {
+ *addr++ = 0;
+ tech = mysigstr;
+ } else {
+ addr = mysigstr;
+ }
link = ss7_resolve_linkset(cur_linkset);
if (!link) {
@@ -14099,7 +14220,7 @@
} else
ss7_set_pc(link->ss7, cur_pointcode);
- if (sigchan < 0) {
+ if (ast_strlen_zero(addr)) {
ast_log(LOG_ERROR, "Invalid sigchan!\n");
return -1;
} else {
@@ -14107,62 +14228,86 @@
ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
return -1;
}
+
curfd = link->numsigchans;
- link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
- if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
- ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
- return -1;
- }
- res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
- if (res) {
- dahdi_close_ss7_fd(link, curfd);
- ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
- return -1;
- }
- if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
- dahdi_close_ss7_fd(link, curfd);
- ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
- return -1;
- }
-
- bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
- bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
- bi.numbufs = 32;
- bi.bufsize = 512;
-
- if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
- ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
- dahdi_close_ss7_fd(link, curfd);
- return -1;
- }
-
- if (cur_adjpointcode < 0) {
- ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
- return -1;
- }
-
- if (p.sigtype == DAHDI_SIG_MTP2)
- ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd], cur_slc, cur_adjpointcode);
- else
- ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd], cur_slc, cur_adjpointcode);
+ if (!strcasecmp("DAHDI", tech)) {
+ int sigchan = atoi(addr);
+
+ link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
+ if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
+ ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
+ return -1;
+ }
+ res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
+ if (res) {
+ dahdi_close_ss7_fd(link, curfd);
+ ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
+ return -1;
+ }
+ if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
+ dahdi_close_ss7_fd(link, curfd);
+ ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
+ return -1;
+ }
+
+ bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
+ bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
+ bi.numbufs = 32;
+ bi.bufsize = 512;
+
+ if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
+ ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
+ dahdi_close_ss7_fd(link, curfd);
+ return -1;
+ }
+
+ if (cur_adjpointcode < 0) {
+ ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
+ return -1;
+ }
+
+ if (p.sigtype == DAHDI_SIG_MTP2)
+ ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd], cur_slc, cur_adjpointcode);
+ else
+ ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd], cur_slc, cur_adjpointcode);
+
+ memset(&si, 0, sizeof(si));
+ res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
+ if (res) {
+ dahdi_close_ss7_fd(link, curfd);
+ ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
+ }
+
+ if (!si.alarms) {
+ link->linkstate[curfd] = LINKSTATE_DOWN;
+ ss7_link_noalarm(link->ss7, link->fds[curfd]);
+ } else {
+ link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
+ ss7_link_alarm(link->ss7, link->fds[curfd]);
+ }
+ } else if (!strcasecmp("tcp", tech)) {
+ struct sockaddr_in my_addr;
+
+ if ((link->fds[curfd] = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ ast_log(LOG_ERROR, "Unable to open socket for SS7 slave server\n");
+ return -1;
+ }
+
+ memset(&my_addr, 0, sizeof(my_addr));
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_port = htons(SS7_SLAVE_SERVER_PORT);
+ my_addr.sin_addr.s_addr = inet_addr(addr);
+
+ if (connect(link->fds[curfd], &my_addr, sizeof(my_addr)) == -1) {
+ ast_log(LOG_ERROR, "Unable to make initial connection. Retrying later\n");
+ }
+
+ ss7_add_link(link->ss7, SS7_TRANSPORT_TCP, link->fds[curfd], cur_slc, cur_adjpointcode);
+ }
link->numsigchans++;
- memset(&si, 0, sizeof(si));
- res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
- if (res) {
- dahdi_close_ss7_fd(link, curfd);
- ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
- }
-
- if (!si.alarms) {
- link->linkstate[curfd] = LINKSTATE_DOWN;
- ss7_link_noalarm(link->ss7, link->fds[curfd]);
- } else {
- link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
- ss7_link_alarm(link->ss7, link->fds[curfd]);
- }
}
if (cur_defaultdpc < 0) {
@@ -16209,6 +16354,8 @@
ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
} else if (!strcasecmp(v->name, "ss7_networkroutedprefix")) {
ast_copy_string(confp->ss7.networkroutedprefix, v->value, sizeof(confp->ss7.networkroutedprefix));
+ } else if (!strcasecmp(v->name, "ss7_slave_channel")) {
+ ss7_add_slave_to_server(v->value);
} else if (!strcasecmp(v->name, "ss7_called_nai")) {
if (!strcasecmp(v->value, "national")) {
confp->ss7.called_nai = SS7_NAI_NATIONAL;
@@ -16234,9 +16381,8 @@
ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "sigchan")) {
- int sigchan, res;
- sigchan = atoi(v->value);
- res = linkset_addsigchan(sigchan);
+ int res;
+ res = linkset_addsigchan(v->value);
if (res < 0)
return -1;
@@ -16689,6 +16835,13 @@
ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
}
}
+
+ if (slave_chan_server.numslaves) {
+ if (ast_pthread_create(&slave_chan_server.master, NULL, ss7_slave_server, NULL)) {
+ ast_log(LOG_ERROR, "Unable to start SS7 slave chan server\n");
+ } else
+ ast_verb(2, "Starting SS7 slave channel server\n");
+ }
}
#endif
/* And start the monitor for the first time */
More information about the asterisk-commits
mailing list