Java tutorial
/* * 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; } }