Added support of mISDN to direct bridge feature
Now it is possible to directly bridge: - GSM with SIP - GSM with ISDN - SIP with ISDN
This commit is contained in:
parent
58afedec93
commit
d6866316df
111
appbridge.cpp
111
appbridge.cpp
|
@ -78,55 +78,6 @@ void EndpointAppBridge::trace_header(const char *name, int direction)
|
|||
msgtext);
|
||||
}
|
||||
|
||||
/* hunts for the given interface
|
||||
* it does not need to have an mISDNport instance */
|
||||
struct interface *EndpointAppBridge::hunt_interface(char *ifname)
|
||||
{
|
||||
struct interface *interface;
|
||||
int there_is_an_external = 0;
|
||||
|
||||
interface = interface_first;
|
||||
|
||||
/* first find the given interface or, if not given, one with no extension */
|
||||
checknext:
|
||||
if (!interface) {
|
||||
if (!there_is_an_external && !(ifname && ifname[0])) {
|
||||
trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
|
||||
add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
|
||||
end_trace();
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* check for given interface */
|
||||
if (ifname && ifname[0]) {
|
||||
if (!strcasecmp(interface->name, ifname)) {
|
||||
/* found explicit interface */
|
||||
trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", ifname);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (interface->external) {
|
||||
there_is_an_external = 1;
|
||||
/* found non extension */
|
||||
trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", interface->name);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
}
|
||||
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
foundif:
|
||||
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
||||
/* port MESSAGE_SETUP */
|
||||
void EndpointAppBridge::port_setup(struct port_list *portlist, int message_type, union parameter *param)
|
||||
{
|
||||
|
@ -138,6 +89,7 @@ void EndpointAppBridge::port_setup(struct port_list *portlist, int message_type,
|
|||
unsigned int bridge_id;
|
||||
unsigned int source_port_id = portlist->port_id;
|
||||
char portname[64];
|
||||
int cause = 47;
|
||||
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from='%s' to='%s'\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
|
||||
|
||||
|
@ -156,10 +108,10 @@ void EndpointAppBridge::port_setup(struct port_list *portlist, int message_type,
|
|||
interface_in = interface_in->next;
|
||||
}
|
||||
if (!interface_in) {
|
||||
fail:
|
||||
PERROR("Cannot find source interface %s.\n", param->setup.callerinfo.interface);
|
||||
fail:
|
||||
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
|
||||
message->param.disconnectinfo.cause = 47;
|
||||
message->param.disconnectinfo.cause = cause;
|
||||
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
|
||||
message_put(message);
|
||||
|
||||
|
@ -186,18 +138,69 @@ fail:
|
|||
#ifdef WITH_SIP
|
||||
if (interface_out->sip) {
|
||||
port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface_out);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#ifdef WITH_GSM_BS
|
||||
if (interface_out->gsm_bs) {
|
||||
port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface_out);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#ifdef WITH_GSM_MS
|
||||
if (interface_out->gsm_ms) {
|
||||
port = new Pgsm_bs(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface_out);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef WITH_MISDN
|
||||
struct mISDNport *mISDNport;
|
||||
char *ifname = interface_out->name;
|
||||
int channel = 0;
|
||||
struct admin_list *admin;
|
||||
int earlyb;
|
||||
int mode = B_MODE_TRANSPARENT;
|
||||
|
||||
/* hunt for mISDNport and create Port */
|
||||
mISDNport = hunt_port(ifname, &channel);
|
||||
if (!mISDNport) {
|
||||
trace_header("INTERFACE (busy)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", ifname);
|
||||
end_trace();
|
||||
cause = 33;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
|
||||
#ifdef WITH_SS5
|
||||
if (mISDNport->ss5)
|
||||
port = ss5_hunt_line(mISDNport);
|
||||
else
|
||||
#endif
|
||||
if (mISDNport->ifport->remote) {
|
||||
admin = admin_first;
|
||||
while(admin) {
|
||||
if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
|
||||
break;
|
||||
admin = admin->next;
|
||||
}
|
||||
if (!admin) {
|
||||
trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
|
||||
add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
|
||||
end_trace();
|
||||
cause = 27;
|
||||
goto fail;
|
||||
}
|
||||
port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
|
||||
} else
|
||||
port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
|
||||
earlyb = mISDNport->earlyb;
|
||||
#else
|
||||
trace_header("INTERFACE (has no function)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", ifname);
|
||||
end_trace();
|
||||
cause = 31;
|
||||
goto fail
|
||||
#endif
|
||||
}
|
||||
if (!port)
|
||||
FATAL("Remote interface, but not supported???\n");
|
||||
portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, interface_out->is_earlyb == IS_YES);
|
||||
|
|
|
@ -26,7 +26,6 @@ class EndpointAppBridge : public EndpointApp
|
|||
void port_release(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void port_other(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void ea_message_port(unsigned int port_id, int message, union parameter *param);
|
||||
struct interface *hunt_interface(char *ifname);
|
||||
|
||||
void trace_header(const char *name, int direction);
|
||||
};
|
||||
|
|
300
apppbx.cpp
300
apppbx.cpp
|
@ -584,306 +584,6 @@ void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
|
|||
}
|
||||
}
|
||||
|
||||
/* hunts for the given interface
|
||||
* it does not need to have an mISDNport instance */
|
||||
struct interface *EndpointAppPBX::hunt_interface(char *ifname)
|
||||
{
|
||||
struct interface *interface;
|
||||
int there_is_an_external = 0;
|
||||
|
||||
interface = interface_first;
|
||||
|
||||
/* first find the given interface or, if not given, one with no extension */
|
||||
checknext:
|
||||
if (!interface) {
|
||||
if (!there_is_an_external && !(ifname && ifname[0])) {
|
||||
trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
|
||||
add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
|
||||
end_trace();
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* check for given interface */
|
||||
if (ifname && ifname[0]) {
|
||||
if (!strcasecmp(interface->name, ifname)) {
|
||||
/* found explicit interface */
|
||||
trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", ifname);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
} else {
|
||||
if (interface->external) {
|
||||
there_is_an_external = 1;
|
||||
/* found non extension */
|
||||
trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", interface->name);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
}
|
||||
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
foundif:
|
||||
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_MISDN
|
||||
/*
|
||||
* hunts an mISDNport that is available for an outgoing call
|
||||
* if no ifname was given, any interface that is not an extension
|
||||
* will be searched.
|
||||
*/
|
||||
struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
|
||||
{
|
||||
struct interface *interface;
|
||||
struct interface_port *ifport, *ifport_start;
|
||||
struct select_channel *selchannel;
|
||||
struct mISDNport *mISDNport;
|
||||
int index, i;
|
||||
int there_is_an_external = 0;
|
||||
|
||||
interface = interface_first;
|
||||
|
||||
/* first find the given interface or, if not given, one with no extension */
|
||||
checknext:
|
||||
if (!interface) {
|
||||
if (!there_is_an_external && !(ifname && ifname[0])) {
|
||||
trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
|
||||
add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
|
||||
end_trace();
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* check for given interface */
|
||||
if (ifname && ifname[0]) {
|
||||
if (!strcasecmp(interface->name, ifname)) {
|
||||
/* found explicit interface */
|
||||
trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", ifname);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (interface->external) {
|
||||
there_is_an_external = 1;
|
||||
/* found non extension */
|
||||
trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", interface->name);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
}
|
||||
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
foundif:
|
||||
|
||||
/* see if interface has ports */
|
||||
if (!interface->ifport) {
|
||||
/* no ports */
|
||||
trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", interface->name);
|
||||
end_trace();
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
}
|
||||
|
||||
/* select port by algorithm */
|
||||
ifport_start = interface->ifport;
|
||||
index = 0;
|
||||
if (interface->hunt == HUNT_ROUNDROBIN) {
|
||||
while(ifport_start->next && index<interface->hunt_next) {
|
||||
ifport_start = ifport_start->next;
|
||||
index++;
|
||||
}
|
||||
trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport_start->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
}
|
||||
|
||||
/* loop ports */
|
||||
ifport = ifport_start;
|
||||
nextport:
|
||||
|
||||
/* see if port is available */
|
||||
if (!ifport->mISDNport) {
|
||||
trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
goto portbusy;
|
||||
}
|
||||
mISDNport = ifport->mISDNport;
|
||||
|
||||
/* see if port is administratively blocked */
|
||||
if (ifport->block) {
|
||||
trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
goto portbusy;
|
||||
}
|
||||
|
||||
/* see if link is up on PTP*/
|
||||
if (mISDNport->l2hold && mISDNport->l2link<1) {
|
||||
trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
goto portbusy;
|
||||
}
|
||||
|
||||
/* check for channel form selection list */
|
||||
*channel = 0;
|
||||
#ifdef WITH_SS5
|
||||
if (mISDNport->ss5) {
|
||||
class Pss5 *port;
|
||||
port = ss5_hunt_line(mISDNport);
|
||||
if (port) {
|
||||
*channel = port->p_m_b_channel;
|
||||
trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", *channel);
|
||||
end_trace();
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
selchannel = ifport->out_channel;
|
||||
while(selchannel) {
|
||||
switch(selchannel->channel) {
|
||||
case CHANNEL_FREE: /* free channel */
|
||||
if (mISDNport->b_reserved >= mISDNport->b_num)
|
||||
break; /* all channel in use or reserverd */
|
||||
/* find channel */
|
||||
i = 0;
|
||||
while(i < mISDNport->b_num) {
|
||||
if (mISDNport->b_port[i] == NULL) {
|
||||
*channel = i+1+(i>=15);
|
||||
trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", *channel);
|
||||
end_trace();
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (*channel)
|
||||
break;
|
||||
trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
break;
|
||||
|
||||
case CHANNEL_ANY: /* don't ask for channel */
|
||||
if (mISDNport->b_reserved >= mISDNport->b_num) {
|
||||
trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("total", NULL, "%d", mISDNport->b_num);
|
||||
add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
|
||||
end_trace();
|
||||
break; /* all channel in use or reserverd */
|
||||
}
|
||||
trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
*channel = CHANNEL_ANY;
|
||||
break;
|
||||
|
||||
case CHANNEL_NO: /* call waiting */
|
||||
trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
*channel = CHANNEL_NO;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (selchannel->channel<1 || selchannel->channel==16) {
|
||||
trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", selchannel->channel);
|
||||
end_trace();
|
||||
break; /* invalid channels */
|
||||
}
|
||||
i = selchannel->channel-1-(selchannel->channel>=17);
|
||||
if (i >= mISDNport->b_num) {
|
||||
trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", selchannel->channel);
|
||||
add_trace("channels", NULL, "%d", mISDNport->b_num);
|
||||
end_trace();
|
||||
break; /* channel not in port */
|
||||
}
|
||||
if (mISDNport->b_port[i] == NULL) {
|
||||
*channel = selchannel->channel;
|
||||
trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", *channel);
|
||||
end_trace();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (*channel)
|
||||
break; /* found channel */
|
||||
selchannel = selchannel->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* if channel was found, return mISDNport and channel */
|
||||
if (*channel) {
|
||||
/* setting next port to start next time */
|
||||
if (interface->hunt == HUNT_ROUNDROBIN) {
|
||||
index++;
|
||||
if (!ifport->next)
|
||||
index = 0;
|
||||
interface->hunt_next = index;
|
||||
}
|
||||
|
||||
return(mISDNport);
|
||||
}
|
||||
|
||||
trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
|
||||
portbusy:
|
||||
/* go next port, until all ports are checked */
|
||||
index++;
|
||||
ifport = ifport->next;
|
||||
if (!ifport) {
|
||||
index = 0;
|
||||
ifport = interface->ifport;
|
||||
}
|
||||
if (ifport != ifport_start)
|
||||
goto nextport;
|
||||
|
||||
if (!ifname) {
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
}
|
||||
|
||||
return(NULL); /* no port found */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* outgoing setup to port(s)
|
||||
* ports will be created and a setup is sent if everything is ok. otherwhise
|
||||
|
|
2
apppbx.h
2
apppbx.h
|
@ -236,8 +236,6 @@ class EndpointAppPBX : public EndpointApp
|
|||
void keypad_function(char digit);
|
||||
void set_tone(struct port_list *portlist, const char *tone);
|
||||
void out_setup(int cfnr);
|
||||
struct mISDNport *hunt_port(char *ifname, int *channel);
|
||||
struct interface *hunt_interface(char *ifname);
|
||||
char *apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name);
|
||||
void auth(int job, int bit_num);
|
||||
|
||||
|
|
305
endpointapp.cpp
305
endpointapp.cpp
|
@ -64,3 +64,308 @@ class EndpointApp *new_endpointapp(class Endpoint *epoint, int origin, int type)
|
|||
|
||||
return app;
|
||||
}
|
||||
|
||||
#ifdef WITH_MISDN
|
||||
/*
|
||||
* hunts an mISDNport that is available for an outgoing call
|
||||
* if no ifname was given, any interface that is not an extension
|
||||
* will be searched.
|
||||
*/
|
||||
struct mISDNport *EndpointApp::hunt_port(char *ifname, int *channel)
|
||||
{
|
||||
struct interface *interface;
|
||||
struct interface_port *ifport, *ifport_start;
|
||||
struct select_channel *selchannel;
|
||||
struct mISDNport *mISDNport;
|
||||
int index, i;
|
||||
int there_is_an_external = 0;
|
||||
|
||||
interface = interface_first;
|
||||
|
||||
/* first find the given interface or, if not given, one with no extension */
|
||||
checknext:
|
||||
if (!interface) {
|
||||
if (!there_is_an_external && !(ifname && ifname[0])) {
|
||||
trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
|
||||
add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
|
||||
end_trace();
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* check for given interface */
|
||||
if (ifname && ifname[0]) {
|
||||
if (!strcasecmp(interface->name, ifname)) {
|
||||
/* found explicit interface */
|
||||
trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", ifname);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (interface->external) {
|
||||
there_is_an_external = 1;
|
||||
/* found non extension */
|
||||
trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", interface->name);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
}
|
||||
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
foundif:
|
||||
|
||||
/* see if interface has ports */
|
||||
if (!interface->ifport) {
|
||||
/* no ports */
|
||||
trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", interface->name);
|
||||
end_trace();
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
}
|
||||
|
||||
/* select port by algorithm */
|
||||
ifport_start = interface->ifport;
|
||||
index = 0;
|
||||
if (interface->hunt == HUNT_ROUNDROBIN) {
|
||||
while(ifport_start->next && index<interface->hunt_next) {
|
||||
ifport_start = ifport_start->next;
|
||||
index++;
|
||||
}
|
||||
trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport_start->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
}
|
||||
|
||||
/* loop ports */
|
||||
ifport = ifport_start;
|
||||
nextport:
|
||||
|
||||
/* see if port is available */
|
||||
if (!ifport->mISDNport) {
|
||||
trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
goto portbusy;
|
||||
}
|
||||
mISDNport = ifport->mISDNport;
|
||||
|
||||
/* see if port is administratively blocked */
|
||||
if (ifport->block) {
|
||||
trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
goto portbusy;
|
||||
}
|
||||
|
||||
/* see if link is up on PTP*/
|
||||
if (mISDNport->l2hold && mISDNport->l2link<1) {
|
||||
trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
goto portbusy;
|
||||
}
|
||||
|
||||
/* check for channel form selection list */
|
||||
*channel = 0;
|
||||
#ifdef WITH_SS5
|
||||
if (mISDNport->ss5) {
|
||||
class Pss5 *port;
|
||||
port = ss5_hunt_line(mISDNport);
|
||||
if (port) {
|
||||
*channel = port->p_m_b_channel;
|
||||
trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", *channel);
|
||||
end_trace();
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
selchannel = ifport->out_channel;
|
||||
while(selchannel) {
|
||||
switch(selchannel->channel) {
|
||||
case CHANNEL_FREE: /* free channel */
|
||||
if (mISDNport->b_reserved >= mISDNport->b_num)
|
||||
break; /* all channel in use or reserverd */
|
||||
/* find channel */
|
||||
i = 0;
|
||||
while(i < mISDNport->b_num) {
|
||||
if (mISDNport->b_port[i] == NULL) {
|
||||
*channel = i+1+(i>=15);
|
||||
trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", *channel);
|
||||
end_trace();
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (*channel)
|
||||
break;
|
||||
trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
break;
|
||||
|
||||
case CHANNEL_ANY: /* don't ask for channel */
|
||||
if (mISDNport->b_reserved >= mISDNport->b_num) {
|
||||
trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("total", NULL, "%d", mISDNport->b_num);
|
||||
add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
|
||||
end_trace();
|
||||
break; /* all channel in use or reserverd */
|
||||
}
|
||||
trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
*channel = CHANNEL_ANY;
|
||||
break;
|
||||
|
||||
case CHANNEL_NO: /* call waiting */
|
||||
trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
*channel = CHANNEL_NO;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (selchannel->channel<1 || selchannel->channel==16) {
|
||||
trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", selchannel->channel);
|
||||
end_trace();
|
||||
break; /* invalid channels */
|
||||
}
|
||||
i = selchannel->channel-1-(selchannel->channel>=17);
|
||||
if (i >= mISDNport->b_num) {
|
||||
trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", selchannel->channel);
|
||||
add_trace("channels", NULL, "%d", mISDNport->b_num);
|
||||
end_trace();
|
||||
break; /* channel not in port */
|
||||
}
|
||||
if (mISDNport->b_port[i] == NULL) {
|
||||
*channel = selchannel->channel;
|
||||
trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
add_trace("channel", NULL, "%d", *channel);
|
||||
end_trace();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (*channel)
|
||||
break; /* found channel */
|
||||
selchannel = selchannel->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* if channel was found, return mISDNport and channel */
|
||||
if (*channel) {
|
||||
/* setting next port to start next time */
|
||||
if (interface->hunt == HUNT_ROUNDROBIN) {
|
||||
index++;
|
||||
if (!ifport->next)
|
||||
index = 0;
|
||||
interface->hunt_next = index;
|
||||
}
|
||||
|
||||
return(mISDNport);
|
||||
}
|
||||
|
||||
trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
|
||||
add_trace("port", NULL, "%d", ifport->portnum);
|
||||
add_trace("position", NULL, "%d", index);
|
||||
end_trace();
|
||||
|
||||
portbusy:
|
||||
/* go next port, until all ports are checked */
|
||||
index++;
|
||||
ifport = ifport->next;
|
||||
if (!ifport) {
|
||||
index = 0;
|
||||
ifport = interface->ifport;
|
||||
}
|
||||
if (ifport != ifport_start)
|
||||
goto nextport;
|
||||
|
||||
if (!ifname) {
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
}
|
||||
|
||||
return(NULL); /* no port found */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* hunts for the given interface
|
||||
* it does not need to have an mISDNport instance */
|
||||
struct interface *EndpointApp::hunt_interface(char *ifname)
|
||||
{
|
||||
struct interface *interface;
|
||||
int there_is_an_external = 0;
|
||||
|
||||
interface = interface_first;
|
||||
|
||||
/* first find the given interface or, if not given, one with no extension */
|
||||
checknext:
|
||||
if (!interface) {
|
||||
if (!there_is_an_external && !(ifname && ifname[0])) {
|
||||
trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
|
||||
add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
|
||||
end_trace();
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* check for given interface */
|
||||
if (ifname && ifname[0]) {
|
||||
if (!strcasecmp(interface->name, ifname)) {
|
||||
/* found explicit interface */
|
||||
trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", ifname);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
} else {
|
||||
if (interface->external) {
|
||||
there_is_an_external = 1;
|
||||
/* found non extension */
|
||||
trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", interface->name);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
}
|
||||
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
foundif:
|
||||
|
||||
return interface;
|
||||
}
|
||||
|
||||
/* must be overloaded by specific app */
|
||||
void EndpointApp::trace_header(const char *name, int direction)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -23,6 +23,12 @@ class EndpointApp
|
|||
class Endpoint *ea_endpoint;
|
||||
virtual void ea_message_port(unsigned int port_id, int message, union parameter *param);
|
||||
virtual void ea_message_join(unsigned int join_id, int message, union parameter *param);
|
||||
virtual void trace_header(const char *name, int direction);
|
||||
|
||||
#ifdef WITH_MISDN
|
||||
struct mISDNport *hunt_port(char *ifname, int *channel);
|
||||
#endif
|
||||
struct interface *hunt_interface(char *ifname);
|
||||
};
|
||||
|
||||
class EndpointApp *new_endpointapp(class Endpoint *epoint, int origin, int type);
|
||||
|
|
Loading…
Reference in New Issue