📄 cwtpresponder.java
字号:
/**
* JWAP - A Java Implementation of the WAP Protocols
* Copyright (C) 2001-2004 Niko Bender
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package net.sourceforge.jwap.wtp;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import net.sourceforge.jwap.util.Logger;
import net.sourceforge.jwap.wtp.pdu.CWTPAbort;
import net.sourceforge.jwap.wtp.pdu.CWTPAck;
import net.sourceforge.jwap.wtp.pdu.CWTPInvoke;
import net.sourceforge.jwap.wtp.pdu.CWTPPDU;
import net.sourceforge.jwap.wtp.pdu.CWTPResult;
import net.sourceforge.jwap.wtp.pdu.EWTPCorruptPDUException;
public class CWTPResponder implements IWTPTransaction{
private static final byte STATE_LISTEN = 0x00;
private static final byte STATE_TIDOK_WAIT = 0x01;
private static final byte STATE_INVOKE_RESP_WAIT = 0x02;
private static final byte STATE_RESULT_WAIT = 0x03;
private static final byte STATE_RESULT_RESP_WAIT = 0x04;
private static final byte STATE_WAIT_TIMEOUT = 0x05;
private static final String[] states = {"LISTEN",
"TIDOK WAIT",
"INVOKE RESP WAIT",
"RESULT WAIT",
"RESLUT RESP WAIT",
"WAIT TIMEOUT"};
static Logger logger = Logger.getLogger(CWTPResponder.class);
private byte state = 0x00;
// which session does this transaction belong to?
private IWTPUpperLayer upperLayer;
// used to send and receive
private CWTPSocket wtpSocket;
// is this transaction aborted?
private boolean aborted = false;
private short abortCode;
/**
* 5.3.1.7
* Class Type 1, 2 or 3
*/
private byte classType;
/**
* 9.4.1
* ack interval
* this sets a bound for the amount of time to wait before sending an acknowledgement.
*/
private javax.swing.Timer a_timer;
private int a = 5000;
/**
* 9.4.1
* retry interval
* This sets a bound for the amount of time to wait before re-transmitting a PDU.
*/
private javax.swing.Timer r_timer;
private int r = 10000;
/**
* 9.4.1
* wait timeout interval (only class 2 initiator and class 1 responder)
* This sets a bound for the amount of time to wait before state information
* about a transaction is released.
*/
private javax.swing.Timer w_timer;
private int w = 5000;
/**
* 9.4.2
* re-transmission counter
* acknowledgement expireation counter
*/
private int rcr = 0;
private int aec = 0;
public static final int RCR_MAX = 3;
public static final int AEC_MAX = 3;
/**
* 9.4.3
* counter to generate unique TIDs
* uint16
*/
private static int genTID = 0;
/**
* uint16
*/
private int sendTID;
private int rcvTID;
private int lastTID;
/**
* recently sent PDU - hold it for retransmission
*/
private CWTPPDU sentPDU;
private boolean holdOn = false;
private boolean uack = false;
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//XXXXXXXXXXXXXXXXXXXXXXX CONSTRUCTOR XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/**
* Constructs a CWTPSocket using a DatagramSocket (UDP).
* Even implementing all parameters belonging to according to
* TR-Invoke service primitive (section 5.3.1),
* which are not temporary for one transaction.
* This socket can be used several times by service primitives.
* After all it has to be closed by calling <code>close()</code>
*
* @see #close(short)
* @param to destination address (section 5.3.1.3)
* @param port destination port (section 5.3.1.4)
* @param ackType Ack Type (section 5.3.1.5)
* @param classType Class Type (0, 1 or 2) (section 5.3.1.8)
* @throws IllegalArgumentException
* @throws SocketException
*/
public CWTPResponder(CWTPSocket wtp_Socket,
IWTPUpperLayer upper_Layer,
CWTPInvoke initPDU,
boolean ackType,
byte classtype
){
init(wtp_Socket, upperLayer, ackType, classtype);
rcvTID = initPDU.getTID();
sendTID = rcvTID - 32768; // sendTID = rcvTID XOR 0x8000
// process the invoke pdu
try{
process(initPDU);
} catch (EWTPAbortedException e){
logger.error("PDU processing aborted", e);
}
}
private void init(CWTPSocket wtp_Socket,
IWTPUpperLayer upper_Layer,
boolean ackType,
byte classtype
) throws IllegalArgumentException {
this.upperLayer = upper_Layer;
this.wtpSocket = wtp_Socket;
wtpSocket.addTransaction(this);
uack = ackType;
setClassType(classtype);
// initialize timer and add actionListener
// see declaration of a_timer above
a_timer = new javax.swing.Timer(a,
new ActionListener() {
public void actionPerformed(ActionEvent e) {
a_timer.stop();
if (state == STATE_INVOKE_RESP_WAIT){
// check acknowledgement counter
if (aec < AEC_MAX){
logger.debug("acknowledgement timer abgelaufen: aec < AEC_MAX");
aec++;
a_timer.restart();
setState(STATE_RESULT_RESP_WAIT);
} else if (aec == AEC_MAX){
//abort if acknowledgement counter exceeds the maximum
logger.debug("acknowledgement timer abgelaufen: aec == AEC_MAX");
CWTPAbort send = new CWTPAbort(sendTID);
send.setAbortReason(CWTPAbort.ABORT_REASON_NORESPONSE);
wtpSocket.send(send);
close(CWTPAbort.ABORT_REASON_NORESPONSE);
aec = 0;
upperLayer.tr_abort(CWTPAbort.ABORT_REASON_NORESPONSE);
setState(STATE_LISTEN);
} else if (!uack && classType == CLASS_TYPE_1){
logger.debug("acknowledgement timer abgelaufen: uack == false classtype 1");
CWTPAck send = new CWTPAck(sendTID);
wtpSocket.send(send);
w_timer.restart();
setState(STATE_WAIT_TIMEOUT);
} else if (!uack && classType == CLASS_TYPE_2){
logger.debug("acknowledgement timer abgelaufen: uack == false classtype 2");
CWTPAck ack = new CWTPAck(sendTID);
wtpSocket.send(ack);
setState(STATE_RESULT_WAIT);
}
}
else if (state == STATE_RESULT_WAIT){
logger.debug("acknowledgement timer abgelaufen.");
CWTPAck ack = new CWTPAck(sendTID);
wtpSocket.send(ack);
setState(STATE_RESULT_WAIT);
}
}
}
);
// see declaration of r_timer above
r_timer = new javax.swing.Timer(r,
new ActionListener() {
public void actionPerformed(ActionEvent e) {
r_timer.stop();
if (state == STATE_RESULT_RESP_WAIT){
// check retransmission counter
if (rcr < RCR_MAX){
logger.debug("retransmission timer "+ rcr
+ " mal abgelaufen. Re-sending Result.");
rcr++;
r_timer.restart();
// re-send recent Result
wtpSocket.send(sentPDU);
setState(STATE_RESULT_RESP_WAIT);
} else if (rcr == RCR_MAX){
logger.debug("retransmission timer " + rcr
+ " mal abgelaufen. Abbruch!");
// abort
close(CWTPAbort.ABORT_REASON_UNKNOWN);
upperLayer.tr_abort(CWTPAbort.ABORT_REASON_UNKNOWN);
rcr = 0;
setState(STATE_LISTEN);
}
}
}
}
);
// see declaration of w_timer above
w_timer = new javax.swing.Timer(w,
new ActionListener() {
public void actionPerformed(ActionEvent e) {
w_timer.stop();
if (state == STATE_WAIT_TIMEOUT){
logger.debug("wait timeout");
setState(STATE_LISTEN);
close((short)0x00);
}
}
}
);
}
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/**
* Invoked by the run()-Method of the Management-Entity CWTPManagement.
* Processes given protocol data units
* according to state machine described in section 9.5
* <b>Notice:</b> Only WTP Initiator is implemented!
*
* @param pdu the pdu to be processed in the state machine
*/
public synchronized void process(CWTPPDU pdu) throws EWTPAbortedException{
if (aborted){
throw new EWTPAbortedException(abortCode);
}
switch (state){
///////////////////// STATE LISTEN ///////////////////////////////////////
case 0x00:
// invoke pdu in state listen
if(pdu.getPDUType() == CWTPPDU.PDU_TYPE_INVOKE){
if (this.classType == IWTPTransaction.CLASS_TYPE_1 ||
this.classType == IWTPTransaction.CLASS_TYPE_2){
if (true/** @todo is tid ok? */){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -