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

📄 receiveimpacket.java

📁 LUMAQQ源代码 JAVA 地球人都知道
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
 * 13. 尾部
 * 
 * 如果是好友属性改变通知
 * 1. 头部
 * 2. 发送者QQ号,4字节,一般是10000
 * 3. 接收者QQ号,4字节
 * 4. 包序号(并非我们发送时候的序号,因为这个是4字节,可能是服务器端得总序号)
 * 5. 发送者IP,如果是服务器转发的,那么ip就是服务器ip, 4字节
 * 6. 发送者端口,如果是服务器转发的,那么就是服务器的端口,2字节
 * 7. 消息类型,2字节,0x001E
 * 8. 好友QQ号,4字节
 * 9. 好友属性,4字节
 * 10. 未知的16字节
 * 11. 尾部
 * </pre>
 * 
 * @see NormalIM
 * @see NormalIMHeader
 * @see ReceiveIMHeader
 * @see ClusterIM
 * @see FileTransferArgs
 * @see FileInfo
 * @see TempSessionIM
 * @see SMS
 * @see QQLive
 * 
 * @author luma
 */
@DocumentalPacket
@PacketName("接收消息包")
@RelatedPacket({ReceiveIMReplyPacket.class})
@LinkedEvent({QQ_RECEIVE_DUPLICATED_IM,
	QQ_RECEIVE_NORMAL_IM,
	QQ_REQUEST_SEND_FILE,
	QQ_REJECT_SEND_FILE,
	QQ_ACCEPT_SEND_FILE,
	QQ_NOTIFY_FILE_TRANSFER_ARGS,
	QQ_REQUEST_ME_CONNECT,
	QQ_CANCEL_SEND_FILE,
	QQ_UNKNOWN_TYPE_IM,
	QQ_KICKED_OUT_BY_SYSTEM,
	QQ_RECEIVE_SYS_MESSAGE,
	QQ_RECEIVE_CLUSTER_IM,
	QQ_RECEIVE_TEMP_CLUSTER_IM,
	QQ_RECEIVE_UNKNOWN_CLUSTER_IM,
	QQ_RECEIVE_SMS,
	QQ_RECEIVE_TEMP_SESSION_IM,
	QQ_I_AM_ADDED_TO_CLUSTER,
	QQ_I_AM_REMOVED_FROM_CLUSTER,
	QQ_REQUEST_JOIN_CLUSTER_APPROVED,
	QQ_REQUEST_JOIN_CLUSTER_REJECTED,
	QQ_REQUEST_JOIN_CLUSTER,
	QQ_ADMIN_ENTITLED,
	QQ_ADMIN_WITHDRAWED,
	QQ_FRIEND_SIGNATURE_CHANGED,
	QQ_RECEIVE_DISK_NOTIFICATION,
	QQ_RECEIVE_QQLIVE,
	QQ_RECEIVE_MEMBER_LOGIN_HINT,
	QQ_FRIEND_PROPERTY_CHANGED,
	QQ_FRIEND_CUSTOM_HEAD_CHANGED})
public class ReceiveIMPacket extends BasicInPacket {	
	// 用于发送确认
    public byte[] reply;
    // 为true时表示收到的消息是空的
    public boolean empty; 
    // 整个包的头
    public ReceiveIMHeader header;
    
    // 仅用于普通消息时
    public NormalIMHeader normalHeader;
    public NormalIM normalIM;
    
    // 仅用于系统通知时
    public byte systemMessageType;
    public String sysMessage;
    
    // 仅用于文件传输时
    public FileInfo fileInfo;
    public FileTransferArgs fileArgs;
    public byte transferType;
    
    // 仅用于群普通消息时
    public ClusterIM clusterIM;
    
    // 仅用于其他类型群消息
    public int externalId;
    public byte clusterType;
    public int sender;
    public String message;
    
    // 用于群通知时
    public byte role;
    public byte opCode;
    public int memberQQ;
    
    // 用户个性签名通知
    public int signatureOwner;
    public int modifiedTime;
    public String signature;
    
    // 用于手机短信消息
    public SMS sms;
    
    // 临时会话消息
    public TempSessionIM tempSessionIM;
    
    // QQ直播消息
    public QQLive qqlive;
    
    // 自定义头像变化通知
    public List<CustomHead> headChanges;
    
    // 用户属性变化
    public UserPropertyChange propertyChange;
    
    /**
     * 构造函数
     * @param buf 缓冲区
     * @param length 包长度
     * @throws PacketParseException 解析错误
     */
    public ReceiveIMPacket(ByteBuffer buf, int length, QQUser user) throws PacketParseException {
        super(buf, length, user);
    }   
    
    /* (non-Javadoc)
     * @see edu.tsinghua.lumaqq.qq.packets.InPacket#getPacketName()
     */
	@Override
    public String getPacketName() {
        return "Receive IM Packet";
    }

    /* (non-Javadoc)
     * @see edu.tsinghua.lumaqq.qq.packets.InPacket#parseBody(java.nio.ByteBuffer)
     */
	@Override
    protected void parseBody(ByteBuffer buf) throws PacketParseException {
        empty = false;
        // 检查消息长度,至少要有16字节,因为我们需要前16字节做为确认发回
        if(buf.remaining() < 16)
            throw new PacketParseException("收到的消息太短,抛弃该消息");  
	    // 得到前16个字节用作回复
	    reply = new byte[16];
	    buf.get(reply);
	    // 读取消息头
	    buf.rewind();
	    header = new ReceiveIMHeader();
	    header.readBean(buf);
        // 检查输入流可用字节
        if(!buf.hasRemaining()) {
            empty = true;
            return;
        }
	    // 判断消息类型
        int len = 0;
        switch(header.type) {
		    case QQ.QQ_RECV_IM_FRIEND:
		    case QQ.QQ_RECV_IM_STRANGER:
		        /* 是从好友或者陌生人处发来的消息 */			        
		        parseNormalIM(buf);
		    	break;
		    case QQ.QQ_RECV_IM_TEMP_SESSION:
		    	tempSessionIM = new TempSessionIM();
		    	tempSessionIM.readBean(buf);
		    	break;
		    case QQ.QQ_RECV_IM_SYS_MESSAGE:
		        /* 是系统消息 */
		        parseSystemMessage(buf);
		    	break;
		    case QQ.QQ_RECV_IM_CLUSTER:
		    	/* 群消息 */
		        parseClusterIM(buf);
		    	break;
		    case QQ.QQ_RECV_IM_TEMP_CLUSTER:
		        /* 临时群消息 */
		        parseTempClusterIM(buf);
		    	break;
		    case QQ.QQ_RECV_IM_UNKNOWN_CLUSTER:
		        parseUnknownClusterIM(buf);
		    	break;
		    case QQ.QQ_RECV_IM_BIND_USER:
		    	sms = new SMS();
		    	sms.readBindUserSMS(buf);
		    	break;
		    case QQ.QQ_RECV_IM_MOBILE_QQ:
		    	sms = new SMS();
		    	sms.readMobileQQSMS(buf);
		    	break;
		    case QQ.QQ_RECV_IM_MOBILE_QQ_2:
		    	sms = new SMS();
		    	sms.readMobileQQ2SMS(buf);
		    	break;
		    case QQ.QQ_RECV_IM_MOBILE:
		    	sms = new SMS();
		    	sms.readMobileSMS(buf);
		    	break;
		    case QQ.QQ_RECV_IM_CREATE_CLUSTER:
		    case QQ.QQ_RECV_IM_ADDED_TO_CLUSTER:
		    case QQ.QQ_RECV_IM_DELETED_FROM_CLUSTER:
		    	externalId = buf.getInt();
		    	clusterType = buf.get();
		    	sender = buf.getInt();
		    	break;
		    case QQ.QQ_RECV_IM_APPROVE_JOIN_CLUSTER:
		    case QQ.QQ_RECV_IM_REJECT_JOIN_CLUSTER:
		    case QQ.QQ_RECV_IM_REQUEST_JOIN_CLUSTER:
		    	externalId = buf.getInt();
		    	clusterType = buf.get();
		    	sender = buf.getInt();
		    	len = buf.get() & 0xFF;
		    	byte[] b = new byte[len];
		    	buf.get(b);
		    	message = Util.getString(b);
		    	break;
		    case QQ.QQ_RECV_IM_CLUSTER_NOTIFICATION:
		    	externalId = buf.getInt();
		    	clusterType = buf.get();
		    	opCode = buf.get();
		    	memberQQ = buf.getInt();
		    	role = buf.get();
		    	sender = externalId;
		    	break;
		    case QQ.QQ_RECV_IM_SIGNATURE_CHANGE:
		    	signatureOwner = buf.getInt();
		    	modifiedTime = buf.getInt();
		    	len = buf.get() & 0xFF;
		    	signature = Util.getString(buf, len);
		    	break;
		    case QQ.QQ_RECV_IM_QQLIVE:
		    	// QQLive message
		    	qqlive = new QQLive();
		    	qqlive.readBean(buf);
		    	break;
		    case QQ.QQ_RECV_IM_MEMBER_LOGIN_HINT:
		    	buf.get();
		    	break;
		    case QQ.QQ_RECV_IM_CUSTOM_HEAD_CHANGE:
		    	int count = buf.get() & 0xFF;
		    	if(count > 0) {
		    		headChanges = new ArrayList<CustomHead>();
		    		while(buf.hasRemaining()) {
		    			CustomHead change = new CustomHead();
		    			change.readBean(buf);
		    			headChanges.add(change);
		    		}
		    	}
		    	break;
		    case QQ.QQ_RECV_IM_PROPERTY_CHANGE:
		    	propertyChange = new UserPropertyChange();
		    	propertyChange.readBean(buf);
		    	break;
		    default:
		        // 其他类型的消息我们现在没有办法处理,忽略
		        break;     
        }
    }

	/**
     * @param buf
     */
    private void parseUnknownClusterIM(ByteBuffer buf) {
		clusterIM = new ClusterIM(QQ.QQ_RECV_IM_UNKNOWN_CLUSTER);
		clusterIM.readBean(buf);
    }

    /**
	 * 解析临时组消息
	 * 
     * @param buf
     */
    private void parseTempClusterIM(ByteBuffer buf) {
		clusterIM = new ClusterIM(QQ.QQ_RECV_IM_TEMP_CLUSTER);
		clusterIM.readBean(buf);
    }    

    /**
	 * 解析群普通消息
	 */
	private void parseClusterIM(ByteBuffer buf) {
		clusterIM = new ClusterIM(QQ.QQ_RECV_IM_CLUSTER);
		clusterIM.readBean(buf);
	}

	/**
	 * 解析系统消息
	 */
	private void parseSystemMessage(ByteBuffer buf) {
	    // 系统消息类型
	    systemMessageType = buf.get();
	    // 系统消息长度
	    int len = buf.get() & 0xFF;
	    // 系统消息
        sysMessage = Util.getString(buf, len);
	}

	/**
	 * 解析普通消息
	 */
	private void parseNormalIM(ByteBuffer buf) throws PacketParseException {
        try {
            // 读入普通消息头
            normalHeader = new NormalIMHeader();
            normalHeader.readBean(buf);
            // 判断普通消息类型
            if(normalHeader.type == QQ.QQ_IM_TYPE_TEXT) {
                normalIM = new NormalIM();
                normalIM.readBean(buf);			            
            } else if(normalHeader.type == QQ.QQ_IM_TYPE_UDP_REQUEST 
            		|| normalHeader.type == QQ.QQ_IM_TYPE_TCP_REQUEST){
            	fileArgs = new FileTransferArgs();
            	fileArgs.readBean(buf);
            	fileInfo = new FileInfo();
            	fileInfo.readBean(buf);
            } else if(normalHeader.type == QQ.QQ_IM_TYPE_ACCEPT_UDP_REQUEST
            		|| normalHeader.type == QQ.QQ_IM_TYPE_NOTIFY_IP) {
            	fileArgs = new FileTransferArgs();
            	fileArgs.readBean(buf);
            } 
            log.debug("收到的普通消息类型为:" + Util.getNormalIMTypeString(normalHeader.type));
        } catch (Exception e) {
            throw new PacketParseException(e.getMessage());
        }
	}
	
	/**
	 * @return
	 * 		消息种类
	 */
	public int getMessageCategory() {
		switch(header.type) {
			case QQ.QQ_RECV_IM_SYS_MESSAGE:
				return QQ.QQ_IM_FROM_SYS;
			case QQ.QQ_RECV_IM_FRIEND:
			case QQ.QQ_RECV_IM_STRANGER:
				return QQ.QQ_IM_FROM_USER;
			case QQ.QQ_RECV_IM_TEMP_SESSION:
				return QQ.QQ_IM_FROM_TEMP_SESSION;
			case QQ.QQ_RECV_IM_CLUSTER:
			case QQ.QQ_RECV_IM_TEMP_CLUSTER:
			case QQ.QQ_RECV_IM_UNKNOWN_CLUSTER:
				return QQ.QQ_IM_FROM_CLUSTER;
			case QQ.QQ_RECV_IM_BIND_USER:
			case QQ.QQ_RECV_IM_MOBILE_QQ:
			case QQ.QQ_RECV_IM_MOBILE_QQ_2:
			case QQ.QQ_RECV_IM_MOBILE:
				return QQ.QQ_IM_FROM_SMS;
			default:
				return QQ.QQ_IM_FROM_SYS;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -