📄 cwtpinitiator.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 java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;
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.CWTPSegmResult;
import net.sourceforge.jwap.wtp.pdu.EWTPCorruptPDUException;
/**
* This class implements a WTP state machine of one transaction according
* to the WTP specification by the WAP Forum. It uses CWTPManagement to send
* the PDUs. CWTPManagement receives PDUs from the remote, decodes them and
* calls #process(CWTPPDU pdu) of the corresponding tranaction (this class).
* <p>
* To be informed of thrown service primitives by this layer, you should
* implement the interface IWTPUpperLayer and give it with the constructor.
* </p><p>
* To construct a service primitive to be processed by this WTP-socket,
* use objects of the class CWTPEvent, that implement service primitives.
* </p><p>
* To Use a whole WAP Stack besides you need the WSP layer, implemented
* in package mmsjua.wap.wsp.
* </p><p>
* <b>Notice</b>, that development is actually in progress.
* Most features are implemented but only for Initiator, not for a responder!
* (for a definition of these terms refer to the spec, section 3.2.)
* </p><p>
* <b>Section descriptions</b> used in this class refer to
* WTP Specification WAP-224-WTP-20010710-a
* by the <a href="http://www.wapforum.org">WAP Forum</a>
* </p>
*
*/
public class CWTPInitiator implements IWTPTransaction {
private static final byte STATE_NULL = 0x00;
private static final byte STATE_RESULT_WAIT = 0x01;
private static final byte STATE_RESULT_RESP_WAIT = 0x02;
private static final byte STATE_WAIT_TIMEOUT = 0x03;
private static final byte STATE_WAIT_ACK = 0x04;
private static final String[] states = {
"NULL", "RESULT WAIT", "RESULT RESP WAIT", "WAIT TIMEOUT", "WAIT ACK"
};
protected static Logger logger = Logger.getLogger(CWTPInitiator.class);
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 = -1;
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;
/**
* 7.14.3
* While segmentation each segment has to be acknowledged. This timer
* waits before resending a segment.
*/
private javax.swing.Timer s_timer;
private int s = 5000;
private CWTPPDU segment;
private int segment_sended = 1;
private final int segment_sended_max = 4;
/**
* 9.4.2
* re-transmission counter
* acknowledgement expireation counter
*/
private int rcr = 0;
private int aec = 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;
/**
* next segment to send while in STATE_WAIT_ACK
*/
private int segmentIndex = 0;
private ByteArrayOutputStream segdata;
private int segend;
private short seglast;
private int segTID;
//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 CWTPInitiator(CWTPSocket wtp_Socket, IWTPUpperLayer upper_Layer,
CWTPEvent initPacket, boolean ackType, byte classType) {
init(wtp_Socket, upper_Layer, ackType, classType);
sendTID = CWTPInitiator.generateNewTID();
rcvTID = sendTID - 32768; // rcvTID = sendTID XOR 0x8000
// process the init service primitive
try {
process(initPacket);
} catch (EWTPAbortedException e) {
logger.warn("Event 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;
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_RESULT_RESP_WAIT) {
// check acknowledgement counter
if (!uack) { // if user acknowledgement is turned off
// unfortunately I do not remember why I have coded this branch like this.
logger.error("acknowledgement timer: exceeded " +
(aec + 1) + " time(s) --> cancel");
CWTPAck send = new CWTPAck(sendTID);
wtpSocket.send(send);
w_timer.restart();
setState(STATE_WAIT_TIMEOUT);
} else if (aec < AEC_MAX) {
if(logger.isDebugEnabled()) {
logger.debug("acknowledgement timer: exceeded " +
(aec + 1) + " time(s).");
}
aec++;
a_timer.restart();
setState(STATE_RESULT_RESP_WAIT);
} else if (aec == AEC_MAX) {
//abort if acknowledgement counter exceeds the maximum
logger.error("acknowledgement timer: exceeded " +
(aec + 1) + " time(s) --> cancel");
CWTPAbort send = new CWTPAbort(sendTID);
send.setAbortReason(CWTPAbort.ABORT_REASON_NORESPONSE);
wtpSocket.send(send);
close(CWTPAbort.ABORT_REASON_NORESPONSE);
aec = 0;
setState(STATE_NULL);
}
}
}
});
// 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_WAIT) {
// check retransmission counter
if (rcr < RCR_MAX) {
/** @todo Ack(TIDok) already sent? Page 53 */
if(logger.isDebugEnabled()) {
logger.debug("retransmission timer: exceeded " +
(rcr + 1) + " time(s) --> re-send");
}
rcr++;
r_timer.restart();
// re-send recent Invoke
sentPDU.setRID(true);
wtpSocket.send(sentPDU);
setState(STATE_RESULT_WAIT);
} else if (rcr == RCR_MAX) {
logger.error("retransmission timer: exceeded " +
(rcr + 1) + " time(s) --> cancel");
// abort
close(CWTPAbort.ABORT_REASON_UNKNOWN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -