edu.tsinghua.lumaqq.qq.packets.PacketHelper.java Source code

Java tutorial

Introduction

Here is the source code for edu.tsinghua.lumaqq.qq.packets.PacketHelper.java

Source

/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 notXX
*                    luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.qq.packets;

import java.nio.ByteBuffer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.beans.QQUser;

/**
 * @author notXX
 * @author luma
 */
public final class PacketHelper {
    // Log
    static Log log = LogFactory.getLog(PacketHelper.class);
    // ?parser
    private IParser parser;

    private static final int PARSER_COUNT = 3;
    private int[] family;
    private IParser[] parsers;

    public PacketHelper(int supportedFamily) {
        family = new int[] { QQ.QQ_PROTOCOL_FAMILY_BASIC, QQ.QQ_PROTOCOL_FAMILY_03, QQ.QQ_PROTOCOL_FAMILY_05, };
        parsers = new IParser[] {
                (supportedFamily * QQ.QQ_PROTOCOL_FAMILY_BASIC) != 0 ? new BasicFamilyParser() : null,
                (supportedFamily * QQ.QQ_PROTOCOL_FAMILY_03) != 0 ? new _03FamilyParser() : null,
                (supportedFamily * QQ.QQ_PROTOCOL_FAMILY_05) != 0 ? new _05FamilyParser() : null, };
    }

    /**
     * ?
     * 
     * @param in
     *       ?
     * @return
     *       OutPacketnull
     */
    public OutPacket retrieveSent(InPacket in) {
        for (int i = 0; i < PARSER_COUNT; i++) {
            if (in.getFamily() == family[i]) {
                PacketHistory history = parsers[i].getHistory();
                if (history == null)
                    return null;
                else
                    return history.retrieveSent(in);
            }
        }
        return null;
    }

    /**
     * 
     * 
     * @param out
     */
    public void putSent(OutPacket out) {
        for (int i = 0; i < PARSER_COUNT; i++) {
            if (out.getFamily() == family[i]) {
                PacketHistory history = parsers[i].getHistory();
                if (history != null)
                    history.putSent(out);
                break;
            }
        }
    }

    /**
     * ???hash
     * ?packethashpackethashCode?
     * packet????hash??
     * 
     * @param packet
     *       ?
     * @param add
     *       true?hash??
     * @return
     *       true??false
     * 
     * @see Packet#hashCode()
     * @see Packet#equals(Object);
     */
    public boolean isReplied(OutPacket packet, boolean add) {
        for (int i = 0; i < PARSER_COUNT; i++) {
            if (packet.getFamily() == family[i]) {
                PacketHistory history = parsers[i].getHistory();
                if (history != null)
                    return history.check(packet, add);
                else
                    return false;
            }
        }
        return false;
    }

    /**
     * ???
     * 
     * @param packet
     *       InPacket?
     * @return
     *       true??
     */
    public boolean isDuplicated(InPacket packet) {
        for (int i = 0; i < PARSER_COUNT; i++) {
            if (packet.getFamily() == family[i]) {
                return parsers[i].isDuplicate(packet);
            }
        }
        return false;
    }

    /**
     * ByteBuffer??InPacket?buf???limit
     * ????bufpositionlength?
     * 
     * @param supportedFamily
     *       ????
     * @param buf 
     *       ByteBuffer
     * @param debug
     *       true????
     * @return InPacket
     *       ???null
     * @throws PacketParseException
     *       ??
     */
    public InPacket parseIn(int supportedFamily, ByteBuffer buf, QQUser user, boolean debug)
            throws PacketParseException {
        if (!findParser(supportedFamily, buf))
            return null;
        return parseIn(buf, parser.getLength(buf), user, debug);
    }

    /**
     * ?bufparser
     * 
     * @param supportedFamily 
     *       ????
     * @param buf
     *       ByteBuffer
     * @return
     *       truefalse
     */
    private boolean findParser(int supportedFamily, ByteBuffer buf) {
        if (parser == null) {
            for (int i = 0; i < PARSER_COUNT; i++) {
                if ((supportedFamily & family[i]) != 0) {
                    if (parsers[i].accept(buf)) {
                        parser = parsers[i];
                        break;
                    }
                }
            }
        }
        return parser != null;
    }

    /**
     * ByteBuffer??InPacket?buf???length
     * ???bufposition?length?
     * 
     * @param buf
     *             ByteBuffer
     * @param type
     *             
     * @param length
     *             
     * @param debug
     * @return InPacket
     * @throws PacketParseException
     *                ??
     */
    private InPacket parseIn(ByteBuffer buf, int length, QQUser user, boolean debug) throws PacketParseException {
        // ???
        int offset = buf.position();

        // ?
        try {
            InPacket ret = parser.parseIncoming(buf, length, user);
            boolean duplicated = isDuplicated(ret);
            boolean needReply = parser.isDuplicatedNeedReply(ret);
            if (duplicated && !needReply && !debug)
                return null;
            else {
                ret.setDuplicated(duplicated);
                return ret;
            }
        } catch (PacketParseException e) {
            throw e;
        } finally {
            buf.position(offset + length);
            parser = null;
        }
    }

    /**
     * ByteBuffer??InPacket?buf???limit
     * ????bufpositionlength?
     * 
     * @param buf
     * @param type
     * @return
     * @throws PacketParseException
     */
    public OutPacket parseOut(int supportedFamily, ByteBuffer buf, QQUser user) throws PacketParseException {
        if (!findParser(supportedFamily, buf))
            return null;
        return parseOut(buf, parser.getLength(buf), user);
    }

    /**
    * ByteBuffer??InPacket?buf???limit
    * ????bufpositionlength?
    * 
     * @param buf
     * @param length
     * @param debug
     * @return
     * @throws PacketParseException
     */
    private OutPacket parseOut(ByteBuffer buf, int length, QQUser user) throws PacketParseException {
        int pos = buf.position();
        try {
            OutPacket ret = parser.parseOutcoming(buf, length, user);
            return ret;
        } catch (PacketParseException e) {
            throw e;
        } finally {
            buf.position(pos + length);
            parser = null;
        }
    }

    /**
     * position???parser
     * ??
     * 
     * @param relocateFamily
     *       ?????
     * @param buf
     *       
     * @return
     *       true???false??
     */
    public boolean relocate(int relocateFamily, ByteBuffer buf) {
        int offset = buf.position();
        for (int i = 0; i < PARSER_COUNT; i++) {
            if ((relocateFamily & family[i]) != 0) {
                int relocated = parsers[i].relocate(buf);
                if (relocated > offset) {
                    buf.position(relocated);
                    return true;
                } else
                    return false;
            }
        }
        return false;
    }
}