⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cwtpinitiator.java

📁 WAP Gateway source code in JAVA:WAP网关的java源码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/**
 * 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 + -