mirror of https://github.com/sipwise/sems.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
558 lines
26 KiB
558 lines
26 KiB
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <termios.h>
|
|
#include <pthread.h>
|
|
#include <sys/time.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#include "log.h"
|
|
#include "AmSession.h"
|
|
|
|
#include "globals.h"
|
|
#include "mISDNStack.h"
|
|
#include "mISDNChannel.h"
|
|
#include "mISDNNames.h"
|
|
|
|
using namespace mISDN;
|
|
|
|
mISDNStack* mISDNStack::_instance=NULL;
|
|
|
|
mISDNStack* mISDNStack::instance()
|
|
{
|
|
if(!_instance) {
|
|
DBG("mISDNStack::instance spawning new\n");
|
|
_instance = new mISDNStack();
|
|
if(_instance->init() != OK){
|
|
delete _instance;
|
|
_instance = 0;
|
|
} else {
|
|
DBG("mISDNStack::instance start\n");
|
|
_instance->start();
|
|
init_flip_bits();
|
|
}
|
|
}
|
|
return _instance;
|
|
}
|
|
mISDNChannel* mISDNStack::NewCR(mISDNport *port,mISDN::iframe_t *frame) {
|
|
std::map<int,mISDNChannel*>::iterator iter=CR_map.find(frame->dinfo);;
|
|
if(iter==CR_map.end()) {
|
|
mISDNChannel* chan=NULL;
|
|
DBG("This is new CR, spawning new object\n");
|
|
chan = new mISDNChannel(port);
|
|
CR_map[frame->dinfo]=chan;
|
|
chan->m_CR=frame->dinfo;
|
|
DBG("pointer to chan is %p\n",chan);
|
|
return chan;
|
|
} else {
|
|
DBG("got previous CR porinter is %p\n",iter->second);
|
|
return iter->second;
|
|
}
|
|
}
|
|
|
|
mISDNChannel* mISDNStack::FindCR(mISDN::iframe_t *frame) {
|
|
std::map<int,mISDNChannel*>::iterator iter=CR_map.find(frame->dinfo);;
|
|
if(iter!=CR_map.end()) {
|
|
// DBG("got previous CR porinter is %p\n",iter->second);
|
|
return iter->second;
|
|
} else {
|
|
ERROR("CR 0x%08x not found in CR_map\n",frame->dinfo);
|
|
return NULL;
|
|
}
|
|
}
|
|
mISDNChannel* mISDNStack::FindBC(mISDN::iframe_t *frame) {
|
|
std::map<int,mISDNChannel*>::iterator iter=BC_map.find(frame->addr&STACK_ID_MASK);;
|
|
if(iter!=BC_map.end()) {
|
|
// DBG("got previous BC porinter is %p\n",iter->second);
|
|
return iter->second;
|
|
} else {
|
|
ERROR("BC address 0x%08x not found in BC_map\n",frame->addr);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
int mISDNStack::placeCall(const AmSipRequest &req, GWSession *session, const std::string &tonumber, const std::string &fromnumber) {
|
|
//we will have code to choose right port here.
|
|
mISDNChannel *chan = new mISDNChannel(); //(device);
|
|
if(chan==NULL) {
|
|
ERROR("Cant allocate new mISDNChannel\n");
|
|
return FAIL;
|
|
}
|
|
session->setOtherLeg(chan);
|
|
chan->setSession(session);
|
|
DBG("calling ((mISDNChannel*)m_pstndevice)->placeCall(m_req, tonumber, fromnumber);\n");
|
|
return chan->placeCall(req, tonumber, fromnumber);
|
|
}
|
|
|
|
|
|
int mISDNStack::GetPortInfo() {
|
|
int err;
|
|
int i, num_cards, p;
|
|
int useable, nt, pri;
|
|
unsigned char buff[1025];
|
|
iframe_t *frm = (iframe_t *)buff;
|
|
stack_info_t *stinf;
|
|
int device;
|
|
|
|
if ((device = mISDN_open()) < 0) {
|
|
ERROR("mISDNStack::mISDNStack: mISDN_open() failed: ret=%d errno=%d (%s) Check for mISDN modules and device.\n", device, errno, strerror(errno));
|
|
return FAIL;
|
|
}
|
|
DBG("mISDNStack::mISDNStack: mISDN_open %d\n",device);
|
|
/* get number of stacks */
|
|
i = 1;
|
|
num_cards = mISDN_get_stack_count(device);
|
|
if (num_cards <= 0) {
|
|
ERROR("Found no card. Please be sure to load card drivers.\n");
|
|
return FAIL;
|
|
}
|
|
|
|
/* loop the number of cards and get their info */
|
|
while(i <= num_cards) {
|
|
err = mISDN_get_stack_info(device, i, buff, sizeof(buff));
|
|
if (err <= 0) { ERROR("mISDN_get_stack_info() failed: port=%d err=%d\n", i, err); break; }
|
|
stinf = (stack_info_t *)&frm->data.p;
|
|
nt = pri = 0;
|
|
useable = 1;
|
|
switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK) {
|
|
case ISDN_PID_L0_TE_S0: INFO("Port %2d: TE-mode BRI S/T interface line (for phone lines)\n",i); break;
|
|
case ISDN_PID_L0_NT_S0: nt = 1; INFO("Port %2d: NT-mode BRI S/T interface port (for phones)\n",i); break;
|
|
case ISDN_PID_L0_TE_E1: pri = 1; INFO("Port %2d: TE-mode PRI E1 interface line (for phone lines)\n",i); break;
|
|
case ISDN_PID_L0_NT_E1: nt = 1;pri = 1; INFO("Port %2d: NT-mode PRI E1 interface port (for phones)\n",i); break;
|
|
default: useable = 0; ERROR("unknown type 0x%08x\n",stinf->pid.protocol[0]);
|
|
}
|
|
if (nt) {
|
|
if (stinf->pid.protocol[1] == 0) { useable = 0; INFO(" -> Missing layer 1 NT-mode protocol.\n"); }
|
|
p = 2; while(p <= MAX_LAYER_NR) { if (stinf->pid.protocol[p]) {useable = 0; INFO(" -> Layer %d protocol 0x%08x is detected, but not allowed for NT.\n", p, stinf->pid.protocol[p]); } p++; }
|
|
if (useable) {
|
|
if (pri) INFO(" -> Interface is Point-To-Point (PRI).\n");
|
|
else INFO(" -> Interface can be Poin-To-Point/Multipoint.\n");
|
|
}
|
|
} else {
|
|
if (stinf->pid.protocol[1] == 0) { useable = 0; INFO(" -> Missing layer 1 protocol.\n"); }
|
|
if (stinf->pid.protocol[2] == 0) { useable = 0; INFO(" -> Missing layer 2 protocol.\n"); }
|
|
if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP) { INFO(" -> Interface is Poin-To-Point.\n"); }
|
|
if (stinf->pid.protocol[3] == 0) { useable = 0; INFO(" -> Missing layer 3 protocol.\n"); }
|
|
else { switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK) {
|
|
case ISDN_PID_L3_DSS1USER: INFO(" -> Protocol: DSS1 (Euro ISDN)\n"); break;
|
|
default: useable = 0; INFO(" -> Protocol: unknown protocol 0x%08x\n",stinf->pid.protocol[3]);
|
|
}
|
|
}
|
|
p = 4; while(p <= MAX_LAYER_NR) { if (stinf->pid.protocol[p]) { useable = 0; INFO(" -> Layer %d protocol 0x%08x is detected, but not allowed for TE.\n", p, stinf->pid.protocol[p]); } p++; }
|
|
INFO(" -> childcnt: %d\n",stinf->childcnt);
|
|
}
|
|
if (!useable) ERROR(" * Port %2d NOT useable. (maybe somethind is using it already?)\n",i);
|
|
i++;
|
|
}
|
|
/* close mISDN */
|
|
if ((err = mISDN_close(device))) {
|
|
ERROR("mISDN_close() failed: err=%d '%s'\n", err, strerror(err));
|
|
return FAIL;
|
|
}
|
|
return OK;
|
|
}
|
|
mISDNStack::mISDNStack() : m_mISDNdevice(0),m_entity(0) {
|
|
mISDNport_first=NULL;
|
|
}
|
|
|
|
mISDNStack::~mISDNStack() {
|
|
}
|
|
|
|
int mISDNStack::init() {
|
|
unsigned char buff[1025];
|
|
iframe_t *frm = (iframe_t *)buff;
|
|
int ret;
|
|
struct mISDNport *mISDNport, **mISDNportp;
|
|
int i, cnt,port;
|
|
int pri, ports;
|
|
int nt, ptp;
|
|
//net_stack_t *nst;
|
|
//manager_t *mgr;
|
|
layer_info_t li;
|
|
stack_info_t *stinf;
|
|
|
|
|
|
if ((m_mISDNdevice = mISDN_open()) < 0) { ERROR("mISDNStack::init: mISDN_open() failed: ret=%d errno=%d (%s) Check for mISDN modules and device.\n", m_mISDNdevice, errno, strerror(errno)); return FAIL; }
|
|
DBG("mISDNStack::init: mISDN_opened %d\n",m_mISDNdevice);
|
|
/* create entity for layer 3 TE-mode */
|
|
mISDN_write_frame(m_mISDNdevice, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
|
|
ret = mISDN_read_frame(m_mISDNdevice, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
|
|
if (ret < (int)mISDN_HEADER_LEN) { ERROR("Cannot request MGR_NEWENTITY from mISDN. header too small.\n");return FAIL; }
|
|
m_entity = frm->dinfo & 0xffff;
|
|
if (!m_entity) { ERROR("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.\n"); return FAIL; }
|
|
DBG("our entity for l3-processes is 0x%08x.\n", m_entity);
|
|
m_crcount=1; //entity and crcount is used to generate uniqe addr for outgoing calls
|
|
|
|
cnt = mISDN_get_stack_count(m_mISDNdevice);
|
|
if(cnt<=0) { ERROR("no devices\n"); return FAIL;}
|
|
for(port=1;port<=cnt;port++) {
|
|
pri = ports = nt = 0;
|
|
ret = mISDN_get_stack_info(m_mISDNdevice, port, buff, sizeof(buff));
|
|
if (ret < 0) { ERROR("Cannot get stack info for port %d (ret=%d)\n", port, ret); }
|
|
stinf = (stack_info_t *)&frm->data.p;
|
|
switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK) {
|
|
case ISDN_PID_L0_TE_S0: DBG("TE-mode BRI S/T interface line\n"); pri = 0; nt = 0; break;
|
|
case ISDN_PID_L0_NT_S0: DBG("NT-mode BRI S/T interface port\n"); pri = 0; nt = 1; break;
|
|
case ISDN_PID_L0_TE_E1: DBG("TE-mode PRI E1 interface line\n"); pri = 1; nt = 0; break;
|
|
case ISDN_PID_L0_NT_E1: DBG("LT-mode PRI E1 interface port\n"); pri = 1; nt = 1; break;
|
|
default:
|
|
ERROR("unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
|
|
}
|
|
if (nt) {
|
|
DBG("Port %d (nt) proto1=0x%08x proto2=0x%08x\n",port, stinf->pid.protocol[1],stinf->pid.protocol[2]);
|
|
if (stinf->pid.protocol[1] == 0) { ERROR("Given port %d: Missing layer 1 NT-mode protocol.\n", port); }
|
|
if (stinf->pid.protocol[2]) { ERROR("Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for NT.\n", port, stinf->pid.protocol[2]); }
|
|
ERROR("NT mode not supported yet\n");
|
|
return FAIL;
|
|
} else { //(te)
|
|
DBG("Port %d (te) proto1=0x%08x proto2=0x%08x proto3=0x%08x proto4=0x%08x (nul proto4 is good here)\n",port, stinf->pid.protocol[1],stinf->pid.protocol[2],stinf->pid.protocol[3],stinf->pid.protocol[4]);
|
|
if (stinf->pid.protocol[1] == 0) { ERROR("Given port %d: Missing layer 1 protocol.\n", port);}
|
|
if (stinf->pid.protocol[2] == 0) { ERROR("Given port %d: Missing layer 2 protocol.\n", port);}
|
|
if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP) { ptp=1;DBG("Port %d is point-to-point.\n",port); } else { ptp=0;}
|
|
if (stinf->pid.protocol[3] == 0) { ERROR("Given port %d: Missing layer 3 protocol.\n", port);}
|
|
else {
|
|
switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK) {
|
|
case ISDN_PID_L3_DSS1USER: break;
|
|
default:
|
|
ERROR("Given port %d: own protocol 0x%08x", port,stinf->pid.protocol[3]);
|
|
}
|
|
}
|
|
if (stinf->pid.protocol[4]) { ERROR("Given port %d: Layer 4 protocol not allowed.\n", port); }
|
|
}
|
|
/* add mISDNport structure */
|
|
mISDNportp = &mISDNport_first;
|
|
while(*mISDNportp)
|
|
mISDNportp = &((*mISDNportp)->next);
|
|
mISDNport = (struct mISDNport *)malloc(sizeof(struct mISDNport));
|
|
*mISDNportp = mISDNport;
|
|
|
|
/* allocate ressources of port */
|
|
mISDNport->d_stid = stinf->id;
|
|
DBG("d_stid = 0x%x.\n", mISDNport->d_stid);
|
|
/* create layer intance */
|
|
memset(&li, 0, sizeof(li));
|
|
strcpy(&li.name[0], "te l4");
|
|
li.object_id = -1;
|
|
li.extentions = 0;
|
|
// li.pid.protocol[4] = ISDN_PID_L4_CAPI20;
|
|
li.pid.protocol[4] = ISDN_PID_L4_B_USER;
|
|
li.pid.layermask = ISDN_LAYER(4);
|
|
li.st = mISDNport->d_stid;
|
|
DBG("setting mISDN_new_layer on port %d, li.st=0x%08x \n",port,li.st);
|
|
ret = mISDN_new_layer(m_mISDNdevice, &li);
|
|
if (ret) { ERROR("Cannot add layer4 of port %d (ret %d)\n", port, ret);
|
|
// mISDNport_close(mISDNport);
|
|
return FAIL;
|
|
}
|
|
mISDNport->upper_id = li.id;
|
|
ret = mISDN_register_layer(m_mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
|
|
if (ret) { ERROR("Cannot register layer4 of port %d\n", port);
|
|
// mISDNport_close(mISDNport);
|
|
return FAIL;
|
|
}
|
|
mISDNport->lower_id = mISDN_get_layerid(m_mISDNdevice, mISDNport->d_stid, 3);
|
|
if (mISDNport->lower_id < 0) { ERROR("Cannot get layer(%d) id of port %d\n", nt?1:3, port);
|
|
// mISDNport_close(mISDNport);
|
|
return FAIL;
|
|
}
|
|
mISDNport->upper_id = mISDN_get_layerid(m_mISDNdevice, mISDNport->d_stid, 4);
|
|
if (mISDNport->upper_id < 0) { ERROR("Cannot get layer4 id of port %d\n", port);
|
|
// mISDNport_close(mISDNport);
|
|
return FAIL;
|
|
}
|
|
DBG("Layer 4 of port %d added (0x%08x) lower_id=0x%08x.\n", port,mISDNport->upper_id,mISDNport->lower_id);
|
|
|
|
mISDNport->b_num = stinf->childcnt;
|
|
mISDNport->portnum = port;
|
|
mISDNport->ntmode = nt;
|
|
mISDNport->pri = pri;
|
|
mISDNport->ptp = ptp;
|
|
DBG("Port has %d b-channels.\n", mISDNport->b_num);
|
|
i = 0;
|
|
while(i < mISDNport->b_num) {
|
|
mISDNport->b_stid[i] = stinf->child[i];
|
|
DBG("b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
|
|
i++;
|
|
}
|
|
/* if te-mode, query state link */
|
|
// if (!mISDNport->ntmode) {
|
|
iframe_t act;
|
|
/* L2 */
|
|
act.prim = MGR_SHORTSTATUS | REQUEST;
|
|
act.addr = mISDNport->upper_id | MSG_BROADCAST;
|
|
act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
|
|
act.len = 0;
|
|
DBG("sending MGR_SHORTSTATUS request for port %d addr=0x%08x.\n", port,act.addr);
|
|
mISDN_write(m_mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
|
|
// }
|
|
act.prim = PH_ACTIVATE| REQUEST;
|
|
act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
|
|
act.dinfo = 0;
|
|
act.len = 0;
|
|
DBG("sending PH_ACTIVATE request (l1 up) for port %d addr=0x%08x.\n", port,act.addr);
|
|
mISDN_write(m_mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
|
|
/* if ptp AND te-mode, pull up the link */
|
|
// if (mISDNport->ptp && !mISDNport->ntmode) {
|
|
// iframe_t act;
|
|
/* L2 */
|
|
act.prim = DL_ESTABLISH | REQUEST;
|
|
// act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 4 | FLG_MSG_DOWN;
|
|
act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
|
|
act.dinfo = 0;
|
|
act.len = 0;
|
|
DBG("sending DL_ESTABLISH request (l2 up) for port %d addr=0x%08x.\n", port,act.addr);
|
|
mISDN_write(m_mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
|
|
// }
|
|
/* initially, we assume that the link is down, exept for nt-ptmp */
|
|
mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
void mISDNStack::on_stop(void) {
|
|
unsigned char buff[1025];
|
|
DBG("mISDNStack::on_stop\n");
|
|
if (m_mISDNdevice >= 0) {
|
|
mISDN_write_frame(m_mISDNdevice, buff, 0, MGR_DELENTITY | REQUEST, m_entity, 0, NULL, TIMEOUT_1SEC);
|
|
mISDN_close(m_mISDNdevice); m_mISDNdevice = -1;
|
|
DBG("mISDN device closed.\n");
|
|
}
|
|
}
|
|
|
|
int mISDNStack::GenerateCR() {
|
|
int cr;
|
|
//llock()
|
|
if (m_crcount++ > 0x7fff)
|
|
m_crcount = 0x0001;
|
|
cr=(m_entity<<16) | m_crcount;
|
|
//unlock();
|
|
return cr;
|
|
}
|
|
|
|
|
|
|
|
void mISDNStack::run()
|
|
{
|
|
DBG("running mISDNStack::run...\n");
|
|
char msg_buf[MAX_MSG_SIZE];
|
|
int msg_buf_s;
|
|
iframe_t* frame;
|
|
mISDNport *port;
|
|
mISDNChannel* channel;
|
|
|
|
while(true){
|
|
// DBG("tick\n");
|
|
msg_buf_s = mISDN_read(m_mISDNdevice,&msg_buf,MAX_MSG_SIZE, TIMEOUT_10SEC);;
|
|
if(msg_buf_s == -1){
|
|
switch(errno){
|
|
case EINTR:
|
|
case EAGAIN:
|
|
continue;
|
|
default: break;
|
|
};
|
|
ERROR("running mISDNStack::run Error in mISDN_read %s\n",strerror(errno));
|
|
break;
|
|
}
|
|
if(msg_buf_s == 0){/*DBG("got 0, cotinuing\n");*/ continue; }
|
|
|
|
frame=(iframe_t*)msg_buf;
|
|
if (frame->dinfo==(signed long)0xffffffff && frame->prim==(PH_DATA|CONFIRM)) {
|
|
ERROR("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
|
|
}
|
|
// DBG("Got something msg_buf_s=%d prim=0x%08x addr=0x%08x dinfo=0x%08x\n",msg_buf_s,frame->prim,frame->addr,frame->dinfo);
|
|
port = mISDNport_first;
|
|
while(port) {
|
|
if ((frame->addr&MASTER_ID_MASK) == (unsigned int)(port->upper_id&MASTER_ID_MASK))
|
|
break;
|
|
port = port->next;
|
|
}
|
|
if (!port) {
|
|
ERROR("message belongs to no mISDNport: prim(0x%x) addr(0x%x) msg->len(%d)\n", frame->prim, frame->addr, msg_buf_s);
|
|
continue;
|
|
}
|
|
if (frame->addr&FLG_CHILD_STACK) { /* child stack */
|
|
/* b-channel data and messages */
|
|
// DBG("processing child stack for %s (%d) prim(0x%x) addr(0x%x) dinfo=0x%x msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr,frame->dinfo, msg_buf_s);
|
|
channel=FindBC(frame);
|
|
if(channel==NULL) {
|
|
DBG("b-channel is not associated to an ISDNPort (address 0x%x), ignoring.\n", frame->addr);
|
|
continue;
|
|
}
|
|
if(channel->bchan_event(msg_buf,msg_buf_s)!=OK)
|
|
ERROR("Error processing bchan_event in channel object\n");
|
|
continue;
|
|
} else { /* d-message */
|
|
//next two are debug packet dumps uncomment if needed
|
|
l1l2l3_trace_header(port, frame->addr, frame->prim, 1);
|
|
if(msg_buf_s>16) DBG("IE: %s",mISDNStack::dumpIE(msg_buf,msg_buf_s).c_str());
|
|
/* general messages not(yet) related to CR */
|
|
switch(frame->prim) {
|
|
case CC_NEW_CR | INDICATION:
|
|
DBG("CC_NEW_CR | INDICATION for %s (%d) \n",port->name, port->portnum);
|
|
channel=NewCR(port,frame);
|
|
continue; break;
|
|
case CC_NEW_CR | CONFIRM:
|
|
DBG("CC_NEW_CR | CONFIRM for %s (%d) Is this possible?\n",port->name, port->portnum);
|
|
continue; break;
|
|
case CC_RELEASE_CR | INDICATION:
|
|
DBG("CC_RELEASE_CR | INDICATION for %s (%d) \n",port->name, port->portnum);
|
|
channel=FindCR(frame);
|
|
if(channel!=NULL) {
|
|
DBG("should delete channel=%p but we will leave it to have media procesor happy just unregister CR from map\n",channel);
|
|
channel->unregister_CR();
|
|
// delete(channel);
|
|
} else ERROR("Channel not found for CC_RELEASE_CR | INDICATION %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);
|
|
continue; break;
|
|
case CC_RELEASE_CR | CONFIRM:
|
|
DBG("CC_RELEASE_CR | CONFIRM for %s (%d) Is this possible?\n",port->name, port->portnum);
|
|
continue; break;
|
|
case MGR_SHORTSTATUS | INDICATION:
|
|
case MGR_SHORTSTATUS | CONFIRM:
|
|
DBG("MGR_SHORTSTATUS ind or confirm for %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);
|
|
switch(frame->dinfo) {
|
|
case SSTATUS_L1_ACTIVATED: port->l1link = 1;DBG("MGR_SHORTSTATUS->SSTATUS_L1_ACTIVATED for %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);break;
|
|
case SSTATUS_L1_DEACTIVATED: port->l1link = 0;DBG("MGR_SHORTSTATUS->SSTATUS_L1_DEACTIVATED for %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);break;
|
|
case SSTATUS_L2_ESTABLISHED: port->l2link = 1;DBG("MGR_SHORTSTATUS->SSTATUS_L2_ESTABLISHED for %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);break;
|
|
case SSTATUS_L2_RELEASED: port->l2link = 0;DBG("MGR_SHORTSTATUS->SSTATUS_L2_RELEASED for %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);break;
|
|
}
|
|
continue; break;
|
|
case PH_ACTIVATE | CONFIRM:
|
|
case PH_ACTIVATE | INDICATION:
|
|
DBG("PH_ACTIVATE ind or confirm for %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);
|
|
port->l1link = 1;
|
|
continue; break;
|
|
case PH_DEACTIVATE | CONFIRM:
|
|
case PH_DEACTIVATE | INDICATION:
|
|
DBG("PH_DEACTIVATE ind or confirm for %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);
|
|
port->l1link = 0;
|
|
continue; break;
|
|
case PH_CONTROL | CONFIRM:
|
|
case PH_CONTROL | INDICATION:
|
|
DBG("Received PH_CONTROL for port %d (%s).\n", port->portnum, port->name);
|
|
continue; break;
|
|
case DL_ESTABLISH | INDICATION:
|
|
case DL_ESTABLISH | CONFIRM:
|
|
DBG("DL_ESTABLISH ind or confirm for %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);
|
|
port->l2link = 1;
|
|
continue; break;
|
|
case DL_RELEASE | INDICATION:
|
|
case DL_RELEASE | CONFIRM:
|
|
DBG("DL_RELEASE ind or confirm for %s (%d) prim(0x%x) addr(0x%x) msg->len(%d) \n",port->name, port->portnum, frame->prim, frame->addr, msg_buf_s);
|
|
port->l2link = 0;
|
|
continue; break;
|
|
default:
|
|
DBG("GOT d-msg from %s port %d prim 0x%x dinfo 0x%x addr 0x%x\n", (port->ntmode)?"NT":"TE", port->portnum, frame->prim, frame->dinfo, frame->addr);
|
|
}
|
|
/* d-message */
|
|
if (port->ntmode) {
|
|
ERROR("NT mode not supported yet\n");
|
|
continue;
|
|
} else {
|
|
/* l3-data is sent to channel object for processing */
|
|
channel=FindCR(frame);
|
|
if(channel==NULL) {
|
|
ERROR("Cant find channel for message\n");
|
|
continue;
|
|
}
|
|
if(channel->processMsg(msg_buf,msg_buf_s)!=OK)
|
|
ERROR("Error processing msg in channel object\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////
|
|
void mISDNStack::l1l2l3_trace_header(struct mISDNport *mISDNport, int port, unsigned long prim, int direction)
|
|
{
|
|
|
|
string msgtext;
|
|
msgtext.assign(mISDNNames::Message(prim&0xffffff00));
|
|
msgtext.append(mISDNNames::isdn_prim[prim&0x00000003]);
|
|
|
|
/* add direction */
|
|
if (direction && (prim&0xffffff00)!=CC_NEW_CR && (prim&0xffffff00)!=CC_RELEASE_CR) {
|
|
if (mISDNport) {
|
|
if (mISDNport->ntmode) { if (direction == DIRECTION_OUT) msgtext.append(" N->U"); else msgtext.append(" N<-U"); }
|
|
else { if (direction == DIRECTION_OUT) msgtext.append(" U->N"); else msgtext.append(" U<-N"); }
|
|
}
|
|
}
|
|
DBG("prim=0x%08lx port=0x%08x %s\n",prim,port, msgtext.c_str());
|
|
}
|
|
|
|
#define QI_DUMP(_x_,_y_) sprintf(x," %25s off=0x%04x ridx=0x%04x res1=0x%04x cs_flg=0x%04x",_y_,qi->_x_.off,qi->_x_.ridx,qi->_x_.res1,qi->_x_.cs_flg);ret.append(x);\
|
|
if(qi->_x_.off>0) {sprintf(x," 0x%02hhx 0x%02hhx 0x%02hhx 0x%02hhx\n",\
|
|
y[qi->_x_.off],\
|
|
y[qi->_x_.off+1],\
|
|
y[qi->_x_.off+2],\
|
|
y[qi->_x_.off+3]\
|
|
);ret.append(x);} else ret.append(" \n");
|
|
|
|
std::string mISDNStack::dumpIE(char *buf,int len) {
|
|
Q931_info_t* qi;
|
|
ie_info_t *ie;
|
|
char buf2[MAX_MSG_SIZE];
|
|
u16 *arr;
|
|
char *p,*x,*y;
|
|
std::string ret,tmp_a,tmp_b;
|
|
int j;
|
|
size_t i;
|
|
|
|
qi = (Q931_info_t*)(buf + mISDN_HEADER_LEN);
|
|
x =(char*)&buf2;
|
|
arr=(u16 *)qi;
|
|
ie=&(qi->bearer_capability);
|
|
p=(char*)qi;
|
|
y=p;
|
|
y+=L3_EXTRA_SIZE;
|
|
sprintf(x,"type=0x%02hhx crlen=0x%02hhx cr=0x%04x\n",qi->type,qi->crlen,qi->cr);ret.append(x);
|
|
for(i=0;i<37;i++) {
|
|
if(ie[i].off>0) {
|
|
sprintf(x," %25s off=0x%04x ridx=0x%04x res1=0x%04x cs_flg=0x%04x",mISDNNames::IE_Names[i],ie[i].off,ie[i].ridx,ie[i].res1,ie[i].cs_flg);ret.append(x);
|
|
tmp_a.assign("");tmp_b.assign(" ");
|
|
for(j=0;j<y[ie[i].off+1];j++) {
|
|
sprintf(x," 0x%02hhx",y[ie[i].off+2+j]);tmp_a.append(x);
|
|
sprintf(x,"%c",(y[ie[i].off+2+j]>32)?y[ie[i].off+2+j]:'.');tmp_b.append(x);
|
|
}
|
|
ret.append(tmp_a);ret.append(tmp_b);ret.append("\n");
|
|
if((ie[i].repeated>0) || (ie[i].ridx>0)) {
|
|
QI_DUMP(ext[i].ie,"extinfo ")
|
|
sprintf(x," extinfo[%d]: cs.codeset=0x%04x cs.locked=0x%04x cs.res1=0x%04x cs.len=0x%04x | v.codeset=0x%04x v.res1=0x%04x v.val=0x%04x\n",
|
|
i,qi->ext[i].cs.codeset,qi->ext[i].cs.locked,qi->ext[i].cs.res1,qi->ext[i].cs.len,
|
|
qi->ext[i].v.codeset,qi->ext[i].v.res1,qi->ext[i].v.val);
|
|
ret.append(x);
|
|
}
|
|
}
|
|
}
|
|
ret.append("=========================\n");
|
|
for(i=0;i<=(len-mISDN_HEADER_LEN)/2;i++) {
|
|
sprintf(x," 0x%04x (%c %c),",arr[i],
|
|
(p[2*i]>=32)?p[2*i]:'.',
|
|
((p[2*i+1])>=32)?p[2*i+1]:'.');
|
|
ret.append(x);
|
|
}
|
|
ret.append("\n");
|
|
if(len>(mISDN_HEADER_LEN+L3_EXTRA_SIZE)) {
|
|
ret.append("tail:");
|
|
for(i=0;i<=(len-(mISDN_HEADER_LEN+L3_EXTRA_SIZE));i++) {
|
|
sprintf(x," 0x%02hhx (%c),",y[i],(y[i]>32)?y[i]:'.');ret.append(x);
|
|
}
|
|
ret.append("\n");
|
|
} else ret.append("no tail\n");
|
|
|
|
|
|
return ret;
|
|
}
|
|
|
|
/** EMACS **
|
|
* Local variables:
|
|
* mode: c++
|
|
* c-basic-offset: 4
|
|
* End:
|
|
*/
|