📄 r2caschannel.java
字号:
if (ani != null)
return ani;
if (linestate != ICALL) {
ani = "";
return ani;
}
EVT evt;
StringBuffer anibuf = new StringBuffer();
int anil = 0;
try {
beginService();
voiceDev.r2_sendb(Voice.SIGA_5, r2tone);
getANI:
while (true) {
evt = serviceWaitEvent(R2InterDigit);
if (evt == null) {
// Timeout in incomming dial
abortIcall("Ani timeout");
}
if (evt.type == EVT.TDX_CST
&& evt.cstevt == EVT.DE_TONEON) {
r2tone = evt.cstdata;
anil++;
switch(r2tone) {
case Voice.SIGI_1:
anibuf.append('1');
break;
case Voice.SIGI_2:
anibuf.append('2');
break;
case Voice.SIGI_3:
anibuf.append('3');
break;
case Voice.SIGI_4:
anibuf.append('4');
break;
case Voice.SIGI_5:
anibuf.append('5');
break;
case Voice.SIGI_6:
anibuf.append('6');
break;
case Voice.SIGI_7:
anibuf.append('7');
break;
case Voice.SIGI_8:
anibuf.append('8');
break;
case Voice.SIGI_9:
anibuf.append('9');
break;
case Voice.SIGI_10:
anibuf.append('0');
break;
case Voice.SIGI_12: // ANI rq denied
case Voice.SIGI_15: // ANI rq finished
break getANI;
default:
// Unexpected forward signal
abortIcall("Ani unexpected " + evt);
}
voiceDev.r2_sendb(Voice.SIGA_5, r2tone);
} else if (evt.type == EVT.TDX_CST &&
evt.cstevt == EVT.DE_TONEOFF) {
// Ignore, forward off
} else if (evt.type == EVT.TDX_PLAYTONE) {
// Ignore, backward completed
} else {
abortIcall("Ani unexpected " + evt);
}
}
ani = anibuf.toString();// .substring(1); // includes category
} finally {
endService();
}
return ani;
}
// abort ICALL (ani/accept) due to protocol error
private void abortIcall(String error) {
EVT evt;
System.err.println("Icall: " + error);
setState(OOS);
voiceDev.stop();
voiceDev.r2_fdisable();
voiceDev.r2_sendbp(Voice.SIGA_4);
ani = ""; // prevent late request of ANI
do {
evt = serviceWaitEvent();
} while (!ra && evt.type != EVT.TDX_PLAYTONE);
if (call != null) call.drop();
clear();
throw new HangUpException();
}
int pulses() {
return pulses;
}
synchronized void clear() {
if (linestate == RESET)
return;
if (ani == null) ani = ""; // Prevent late ANI request
super.clear();
int fromState = linestate;
linestate = RESET; // No need for flush to throw an event
voiceDev.stop();
voiceDev.r2_fdisable();
voiceDev.r2_bdisable();
voiceDev.clear();
dtiDev.listen(voiceDev);
voiceDev.listen(dtiDev);
flush();
pulses = 0;
ani = "";
switch(fromState) {
case IDLE:
case RESET:
break;
case RINGS:
if (ringer != null) ringer.interrupt();
case RSEIZED:
case ICALL:
// dropping in advance ?
if (ra)
// They dropped
dtiDev.setsig(xa = true, xb = false);
// else
// We drop. But lets wait...
break;
case IN:
// dropping...
if (ra)
// They dropped
dtiDev.setsig(xa = true, xb = false);
else
// We drop.
dtiDev.setsig(xa = true, xb);
break;
case OFFH:
// Wait for seizure conf
break;
case DIAL:
case DIALOK:
case OUT:
case INIT:
dtiDev.setsig(xa = true, xb = false);
break;
}
if (serviceThread == null) {
serviceThread = new Thread(group, this, dtiDev.name + "/" + voiceDev.name + " service");
serviceThread.start();
}
}
/**
* service()
* Our line state service fn
* Run in channel thread (like a interrupt time handler :-)
* Can "eat" the event if it should not get into "user space"
* or even change it by returning null or other event
*/
protected EVT service(EVT evt) {
if (dtiDev.source(evt)) {
switch(evt.type) {
case EVT.DTEV_SIG:
ra = (evt.data & A)!= 0;
rb = (evt.data & B)!= 0;
if (linestate == INIT) {
evt = null;
break;
}
if ((evt.data & CA) != 0) {
if (ra) {
if (setA()) evt = null;
} else {
if (clrA()) evt = null;
}
} else if ((evt.data & CB) != 0) {
if (rb) {
if (setB()) evt = null;
} else {
if (clrB()) evt = null;
}
} else if ((evt.data & WINK) != 0) {
pulses++;
return null;
}
break;
case EVT.DTEV_E1ERRC:
switch(linestate) {
case IN:
case OUT:
if (call != null) call.drop();
clear();
throw new HangUpException();
}
break;
}
} else if (voiceDev.source(evt)) {
if (evt.type == EVT.TDX_PLAYTONE) {
if (linestate == RINGS) {
if (ringPhase) {
voiceDev.playtone(ring, stdTPT);
ringPhase = false;
ringsSent++;
} else {
voiceDev.playtone(ringSilence, stdTPT);
ringPhase = true;
}
return null;
}
}
}
return evt;
}
/**
* setA()
* logic to apply to A bit going high.
* Returns true if event was serviced, i.e., should not be passed along
*/
private boolean setA() {
switch(linestate) {
case RESET:
// They drop after us in incoming ?
dtiDev.setsig(xa = true, xb = false);
break;
case IDLE: // should not happen...
case RSEIZED: // premature abort, handled elsewhere
setState(OOS);
break;
case RINGS: // abort
if (ringer != null) ringer.interrupt();
// PASSTHROUGH
case ICALL: // late abort
linestate = IN; // prevent ring cycle loop (if RINGS)
// prevent late ani request (if ICALL)
// PASSTHROUGH
case IN:
// Incoming hang up
if (call != null) call.drop();
clear();
throw new HangUpException();
case OUT:
// Remote "forced" clearing...
if (call != null) call.drop();
clear();
throw new HangUpException();
}
return true;
}
/**
* clrA()
* logic to apply to A bit going low.
* Returns true if event was serviced, i.e., should not be passed along
*/
private boolean clrA() {
switch(linestate) {
case RESET:
if (rb)
break;
// Fall through if we are in guard time...
case IDLE:
// answer ?
dtiDev.setsig(xa = true, xb = true);
linestate = RSEIZED;
setState(INCOMING);
return false;
case OFFH:
// Simultaneous seizure...
linestate = ERROR;
case DIAL:
// XXX Answer before R2 finished ???
return false;
case DIALOK:
// Answer
linestate = OUT;
pulses++;
if (call != null) call.connect();
return false;
}
return true;
}
/**
* setB()
* logic to apply to B bit going high.
* Returns true if event was serviced, i.e., should not be passed along
*/
private boolean setB() {
switch(linestate) {
case IDLE:
// Line blocked ?
linestate = RESET;
setState(OOS);
return false; // Let serviceChannel know we are not idle anymore
case RESET:
// late seizure conf ?
setState(OOS); // just in case
dtiDev.setsig(xa = true, xb = false);
break;
case OFFH:
// seizure conf
linestate = DIAL;
return false;
}
return true;
}
/**
* clrB()
* logic to apply to B bit going low.
* Returns true if event was serviced, i.e., should not be passed along
*/
private boolean clrB() {
switch (linestate) {
case RESET:
// WAIT for serviceChannel to set it idle... 9/9/01
// if (ra) linestate = IDLE;
// setState(FREE);
return true;
case OFFH:
case DIAL:
case DIALOK:
setState(OOS);
if (call != null) call.drop();
clear();
throw new ChannelException("Abort");
}
return false;
}
//{{DECLARE_CONTROLS
//}}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -