移动app

This commit is contained in:
2023-09-24 17:55:19 +08:00
parent 736c5376e0
commit 59f7e39791
735 changed files with 80523 additions and 57 deletions

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lld</groupId>
<artifactId>im-system</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>im-codec</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- netty -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.35.Final</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<!-- common -->
<dependency>
<groupId>com.lld</groupId>
<artifactId>common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,43 @@
package com.lld.im.codec;
import com.alibaba.fastjson.JSONObject;
import com.lld.im.codec.proto.Message;
import com.lld.im.codec.proto.MessageHeader;
import com.lld.im.codec.utils.ByteBufToMessageUtils;
import com.sun.org.apache.bcel.internal.generic.NEW;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;
/**
* @description: 消息解码类
* @author: lld
* @version: 1.0
*/
public class MessageDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx,
ByteBuf in, List<Object> out) throws Exception {
//请求头(指令
// 版本
// clientType
// 消息解析类型
// appId
// imei长度
// bodylen+ imei号 + 请求体
if(in.readableBytes() < 28){
return;
}
Message message = ByteBufToMessageUtils.transition(in);
if(message == null){
return;
}
out.add(message);
}
}

View File

@@ -0,0 +1,27 @@
package com.lld.im.codec;
import com.alibaba.fastjson.JSONObject;
import com.lld.im.codec.proto.MessagePack;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
/**
* @author: Chackylee
* @description: 消息编码类私有协议规则前4位表示长度接着command4位后面是数据
**/
public class MessageEncoder extends MessageToByteEncoder {
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
if(msg instanceof MessagePack){
MessagePack msgBody = (MessagePack) msg;
String s = JSONObject.toJSONString(msgBody.getData());
byte[] bytes = s.getBytes();
out.writeInt(msgBody.getCommand());
out.writeInt(bytes.length);
out.writeBytes(bytes);
}
}
}

View File

@@ -0,0 +1,32 @@
package com.lld.im.codec;
import com.lld.im.codec.proto.Message;
import com.lld.im.codec.utils.ByteBufToMessageUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import java.util.List;
/**
* @description:
* @author: lld
* @version: 1.0
*/
public class WebSocketMessageDecoder extends MessageToMessageDecoder<BinaryWebSocketFrame> {
@Override
protected void decode(ChannelHandlerContext ctx, BinaryWebSocketFrame msg, List<Object> out) throws Exception {
System.out.println("ws解码器收到信息");
ByteBuf content = msg.content();
if (content.readableBytes() < 28) {
return;
}
Message message = ByteBufToMessageUtils.transition(content);
if(message == null){
return;
}
out.add(message);
}
}

View File

@@ -0,0 +1,40 @@
package com.lld.im.codec;
import com.alibaba.fastjson.JSONObject;
import com.lld.im.codec.proto.MessagePack;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* @author: Chackylee
* @description:
**/
public class WebSocketMessageEncoder extends MessageToMessageEncoder<MessagePack> {
private static Logger log = LoggerFactory.getLogger(WebSocketMessageEncoder.class);
@Override
protected void encode(ChannelHandlerContext ctx, MessagePack msg, List<Object> out) {
try {
String s = JSONObject.toJSONString(msg);
ByteBuf byteBuf = Unpooled.directBuffer(8+s.length());
byte[] bytes = s.getBytes();
byteBuf.writeInt(msg.getCommand());
byteBuf.writeInt(bytes.length);
byteBuf.writeBytes(bytes);
out.add(new BinaryWebSocketFrame(byteBuf));
}catch (Exception e){
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,146 @@
package com.lld.im.codec.config;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author: Chackylee
* @description:
**/
@Data
public class BootstrapConfig {
private TcpConfig lim;
@Data
public static class TcpConfig {
private Integer tcpPort;// tcp 绑定的端口号
private Integer webSocketPort; // webSocket 绑定的端口号
private boolean enableWebSocket; //是否启用webSocket
private Integer bossThreadSize; // boss线程 默认=1
private Integer workThreadSize; //work线程
private Long heartBeatTime; //心跳超时时间 单位毫秒
private Integer loginModel;
/**
* redis配置
*/
private RedisConfig redis;
/**
* rabbitmq配置
*/
private Rabbitmq rabbitmq;
/**
* zk配置
*/
private ZkConfig zkConfig;
/**
* brokerId
*/
private Integer brokerId;
private String logicUrl;
}
@Data
public static class ZkConfig {
/**
* zk连接地址
*/
private String zkAddr;
/**
* zk连接超时时间
*/
private Integer zkConnectTimeOut;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RedisConfig {
/**
* 单机模式single 哨兵模式sentinel 集群模式cluster
*/
private String mode;
/**
* 数据库
*/
private Integer database;
/**
* 密码
*/
private String password;
/**
* 超时时间
*/
private Integer timeout;
/**
* 最小空闲数
*/
private Integer poolMinIdle;
/**
* 连接超时时间(毫秒)
*/
private Integer poolConnTimeout;
/**
* 连接池大小
*/
private Integer poolSize;
/**
* redis单机配置
*/
private RedisSingle single;
}
/**
* redis单机配置
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RedisSingle {
/**
* 地址
*/
private String address;
}
/**
* rabbitmq哨兵模式配置
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Rabbitmq {
private String host;
private Integer port;
private String virtualHost;
private String userName;
private String password;
}
}

View File

@@ -0,0 +1,15 @@
package com.lld.im.codec.pack;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class LoginPack {
private String userId;
}

View File

@@ -0,0 +1,15 @@
package com.lld.im.codec.pack.conversation;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class DeleteConversationPack {
private String conversationId;
}

View File

@@ -0,0 +1,23 @@
package com.lld.im.codec.pack.conversation;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class UpdateConversationPack {
private String conversationId;
private Integer isMute;
private Integer isTop;
private Integer conversationType;
private Long sequence;
}

View File

@@ -0,0 +1,16 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 用户添加黑名单以后tcp通知数据包
**/
@Data
public class AddFriendBlackPack {
private String fromId;
private String toId;
private Long sequence;
}

View File

@@ -0,0 +1,22 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
import java.util.List;
/**
* @author: Chackylee
* @description: 好友分组添加成员通知包
**/
@Data
public class AddFriendGroupMemberPack {
public String fromId;
private String groupName;
private List<String> toIds;
/** 序列号*/
private Long sequence;
}

View File

@@ -0,0 +1,17 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 用户创建好友分组通知包
**/
@Data
public class AddFriendGroupPack {
public String fromId;
private String groupName;
/** 序列号*/
private Long sequence;
}

View File

@@ -0,0 +1,28 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 添加好友通知报文
**/
@Data
public class AddFriendPack {
private String fromId;
/**
* 备注
*/
private String remark;
private String toId;
/**
* 好友来源
*/
private String addSource;
/**
* 添加好友时的描述信息(用于打招呼)
*/
private String addWording;
private Long sequence;
}

View File

@@ -0,0 +1,18 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 审批好友申请通知报文
**/
@Data
public class ApproverFriendRequestPack {
private Long id;
//1同意 2拒绝
private Integer status;
private Long sequence;
}

View File

@@ -0,0 +1,14 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 删除黑名单通知报文
**/
@Data
public class DeleteAllFriendPack {
private String fromId;
}

View File

@@ -0,0 +1,17 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 删除黑名单通知报文
**/
@Data
public class DeleteBlackPack {
private String fromId;
private String toId;
private Long sequence;
}

View File

@@ -0,0 +1,22 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
import java.util.List;
/**
* @author: Chackylee
* @description: 删除好友分组成员通知报文
**/
@Data
public class DeleteFriendGroupMemberPack {
public String fromId;
private String groupName;
private List<String> toIds;
/** 序列号*/
private Long sequence;
}

View File

@@ -0,0 +1,17 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 删除好友分组通知报文
**/
@Data
public class DeleteFriendGroupPack {
public String fromId;
private String groupName;
/** 序列号*/
private Long sequence;
}

View File

@@ -0,0 +1,17 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 删除好友通知报文
**/
@Data
public class DeleteFriendPack {
private String fromId;
private String toId;
private Long sequence;
}

View File

@@ -0,0 +1,15 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 已读好友申请通知报文
**/
@Data
public class ReadAllFriendRequestPack {
private String fromId;
private Long sequence;
}

View File

@@ -0,0 +1,20 @@
package com.lld.im.codec.pack.friendship;
import lombok.Data;
/**
* @author: Chackylee
* @description: 修改好友通知报文
**/
@Data
public class UpdateFriendPack {
public String fromId;
private String toId;
private String remark;
private Long sequence;
}

View File

@@ -0,0 +1,18 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
import java.util.List;
/**
* @author: Chackylee
* @description: 群内添加群成员通知报文
**/
@Data
public class AddGroupMemberPack {
private String groupId;
private List<String> members;
}

View File

@@ -0,0 +1,48 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
/**
* @author: Chackylee
* @description: 创建群组通知报文
**/
@Data
public class CreateGroupPack {
private String groupId;
private Integer appId;
//群主id
private String ownerId;
//群类型 1私有群类似微信 2公开群(类似qq
private Integer groupType;
private String groupName;
private Integer mute;// 是否全员禁言0 不禁言1 全员禁言。
// 申请加群选项包括如下几种:
// 0 表示禁止任何人申请加入
// 1 表示需要群主或管理员审批
// 2 表示允许无需审批自由加入群组
private Integer applyJoinType;
private Integer privateChat; //是否禁止私聊0 允许群成员发起私聊1 不允许群成员发起私聊。
private String introduction;//群简介
private String notification;//群公告
private String photo;//群头像
private Integer status;//群状态 0正常 1解散
private Long sequence;
private Long createTime;
private String extra;
}

View File

@@ -0,0 +1,16 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
/**
* @author: Chackylee
* @description: 解散群通知报文
**/
@Data
public class DestroyGroupPack {
private String groupId;
private Long sequence;
}

View File

@@ -0,0 +1,18 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
/**
* @author: Chackylee
* @description: 群成员禁言通知报文
**/
@Data
public class GroupMemberSpeakPack {
private String groupId;
private String memberId;
private Long speakDate;
}

View File

@@ -0,0 +1,37 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
/**
* @author: Chackylee
* @description: 群聊消息分发报文
**/
@Data
public class GroupMessagePack {
//客户端传的messageId
private String messageId;
private String messageKey;
private String fromId;
private String groupId;
private int messageRandom;
private long messageTime;
private long messageSequence;
private String messageBody;
/**
* 这个字段缺省或者为 0 表示需要计数,为 1 表示本条消息不需要计数,即右上角图标数字不增加
*/
private int badgeMode;
private Long messageLifeTime;
private Integer appId;
}

View File

@@ -0,0 +1,14 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
/**
* @author: Chackylee
* @description: 禁言群tcp通知
**/
@Data
public class MuteGroupPack {
private String groupId;
}

View File

@@ -0,0 +1,16 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
/**
* @author: Chackylee
* @description: 踢人出群通知报文
**/
@Data
public class RemoveGroupMemberPack {
private String groupId;
private String member;
}

View File

@@ -0,0 +1,16 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
/**
* @author: Chackylee
* @description: 转让群主通知报文
**/
@Data
public class TransferGroupPack {
private String groupId;
private String ownerId;
}

View File

@@ -0,0 +1,29 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
/**
* @author: Chackylee
* @description: 修改群信息通知报文
**/
@Data
public class UpdateGroupInfoPack {
private String groupId;
private String groupName;
private Integer mute;// 是否全员禁言0 不禁言1 全员禁言。
private Integer joinType;//加入群权限0 所有人可以加入1 群成员可以拉人2 群管理员或群组可以拉人。
private String introduction;//群简介
private String notification;//群公告
private String photo;//群头像
private Integer maxMemberCount;//群成员上限
private Long sequence;
}

View File

@@ -0,0 +1,19 @@
package com.lld.im.codec.pack.group;
import lombok.Data;
/**
* @author: Chackylee
* @description: 修改群成员通知报文
**/
@Data
public class UpdateGroupMemberPack {
private String groupId;
private String memberId;
private String alias;
private String extra;
}

View File

@@ -0,0 +1,25 @@
package com.lld.im.codec.pack.message;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class ChatMessageAck {
private String messageId;
private Long messageSequence;
public ChatMessageAck(String messageId) {
this.messageId = messageId;
}
public ChatMessageAck(String messageId,Long messageSequence) {
this.messageId = messageId;
this.messageSequence = messageSequence;
}
}

View File

@@ -0,0 +1,22 @@
package com.lld.im.codec.pack.message;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class MessageReadedPack {
private long messageSequence;
private String fromId;
private String groupId;
private String toId;
private Integer conversationType;
}

View File

@@ -0,0 +1,22 @@
package com.lld.im.codec.pack.message;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class MessageReciveServerAckPack {
private Long messageKey;
private String fromId;
private String toId;
private Long messageSequence;
private Boolean serverSend;
}

View File

@@ -0,0 +1,21 @@
package com.lld.im.codec.pack.message;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author: Chackylee
* @description: 撤回消息通知报文
**/
@Data
@NoArgsConstructor
public class RecallMessageNotifyPack {
private String fromId;
private String toId;
private Long messageKey;
private Long messageSequence;
}

View File

@@ -0,0 +1,15 @@
package com.lld.im.codec.pack.user;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class LoginAckPack {
private String userId;
}

View File

@@ -0,0 +1,22 @@
package com.lld.im.codec.pack.user;
import com.lld.im.common.model.UserSession;
import lombok.Data;
import java.util.List;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class UserCustomStatusChangeNotifyPack {
private String customText;
private Integer customStatus;
private String userId;
}

View File

@@ -0,0 +1,32 @@
package com.lld.im.codec.pack.user;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class UserModifyPack {
// 用户id
private String userId;
// 用户名称
private String nickName;
private String password;
// 头像
private String photo;
// 性别
private String userSex;
// 个性签名
private String selfSignature;
// 加好友验证类型Friend_AllowType 1需要验证
private Integer friendAllowType;
}

View File

@@ -0,0 +1,25 @@
package com.lld.im.codec.pack.user;
import com.lld.im.common.model.UserSession;
import lombok.Data;
import sun.dc.pr.PRError;
import java.util.List;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class UserStatusChangeNotifyPack {
private Integer appId;
private String userId;
private Integer status;
private List<UserSession> client;
}

View File

@@ -0,0 +1,24 @@
package com.lld.im.codec.proto;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class Message {
private MessageHeader messageHeader;
private Object messagePack;
@Override
public String toString() {
return "Message{" +
"messageHeader=" + messageHeader +
", messagePack=" + messagePack +
'}';
}
}

View File

@@ -0,0 +1,39 @@
package com.lld.im.codec.proto;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class MessageHeader {
//消息操作指令 十六进制 一个消息的开始通常以0x开头
//4字节
private Integer command;
//4字节 版本号
private Integer version;
//4字节 端类型
private Integer clientType;
/**
* 应用ID
*/
// 4字节 appId
private Integer appId;
/**
* 数据解析类型 和具体业务无关后续根据解析类型解析data数据 0x0:Json,0x1:ProtoBuf,0x2:Xml,默认:0x0
*/
//4字节 解析类型
private Integer messageType = 0x0;
//4字节 imel长度
private Integer imeiLength;
//4字节 包体长度
private int length;
//imei号
private String imei;
}

View File

@@ -0,0 +1,48 @@
package com.lld.im.codec.proto;
import lombok.Data;
import java.io.Serializable;
/**
* @author: Chackylee
* @description: 消息服务发送给tcp的包体,tcp再根据改包体解析成Message发给客户端
**/
@Data
public class MessagePack<T> implements Serializable {
private String userId;
private Integer appId;
/**
* 接收方
*/
private String toId;
/**
* 客户端标识
*/
private int clientType;
/**
* 消息ID
*/
private String messageId;
/**
* 客户端设备唯一标识
*/
private String imei;
private Integer command;
/**
* 业务数据对象,如果是聊天消息则不需要解析直接透传
*/
private T data;
// /** 用户签名*/
// private String userSign;
}

View File

@@ -0,0 +1,84 @@
package com.lld.im.codec.utils;
import com.alibaba.fastjson.JSONObject;
import com.lld.im.codec.proto.Message;
import com.lld.im.codec.proto.MessageHeader;
import io.netty.buffer.ByteBuf;
/**
* @author: rowger
* @description: 将ByteBuf转化为Message实体根据私有协议转换
* 私有协议规则,
* 4位表示Command表示消息的开始
* 4位表示version
* 4位表示clientType
* 4位表示messageType
* 4位表示appId
* 4位表示imei长度
* imei
* 4位表示数据长度
* data
* 后续将解码方式加到数据头根据不同的解码方式解码如pbjson现在用json字符串
* @version: 1.0
*/
public class ByteBufToMessageUtils {
public static Message transition(ByteBuf in){
/** 获取command*/
int command = in.readInt();
/** 获取version*/
int version = in.readInt();
/** 获取clientType*/
int clientType = in.readInt();
/** 获取clientType*/
int messageType = in.readInt();
/** 获取appId*/
int appId = in.readInt();
/** 获取imeiLength*/
int imeiLength = in.readInt();
/** 获取bodyLen*/
int bodyLen = in.readInt();
if(in.readableBytes() < bodyLen + imeiLength){
in.resetReaderIndex();
return null;
}
byte [] imeiData = new byte[imeiLength];
in.readBytes(imeiData);
String imei = new String(imeiData);
byte [] bodyData = new byte[bodyLen];
in.readBytes(bodyData);
MessageHeader messageHeader = new MessageHeader();
messageHeader.setAppId(appId);
messageHeader.setClientType(clientType);
messageHeader.setCommand(command);
messageHeader.setLength(bodyLen);
messageHeader.setVersion(version);
messageHeader.setMessageType(messageType);
messageHeader.setImei(imei);
Message message = new Message();
message.setMessageHeader(messageHeader);
if(messageType == 0x0){
String body = new String(bodyData);
JSONObject parse = (JSONObject) JSONObject.parse(body);
message.setMessagePack(parse);
}
in.markReaderIndex();
return message;
}
}