[*] 日常优化

This commit is contained in:
acgist
2023-08-12 09:12:16 +08:00
parent d65fe5b27f
commit 4b63339947
9 changed files with 414 additions and 409 deletions

View File

@@ -19,90 +19,90 @@ import com.acgist.taoyao.signal.event.ApplicationEventAdapter;
* @author acgist
*/
public interface Protocol {
/**
* @return 信令名称
*/
String name();
/**
* @return 信令标识
*/
String signal();
/**
* 鉴权
*
* @param message 信令消息
*
* @return 是否成功
*/
default boolean authenticate(Message message) {
return true;
}
/**
* 处理终端信令
*
* @param client 终端
* @param message 信令消息
*/
void execute(Client client, Message message);
/**
* @return 信令名称
*/
String name();
/**
* @return 信令标识
*/
String signal();
/**
* 鉴权
*
* @param message 信令消息
*
* @return 是否成功
*/
default boolean authenticate(Message message) {
return true;
}
/**
* 处理终端信令
*
* @param client 终端
* @param message 信令消息
*/
void execute(Client client, Message message);
/**
* 发布事件
*
* @param <E> 事件类型
*
* @param event 事件
*/
<E extends ApplicationEventAdapter> void publishEvent(E event);
/**
* @return 信令消息
*/
Message build();
/**
* @param body 消息主体
*
* @return 信令消息
*/
Message build(Object body);
/**
* @param messageCode 状态编码
* @param body 消息主体
*
* @return 信令消息
*/
Message build(MessageCode messageCode, Object body);
/**
* @param message 状态描述
* @param body 消息主体
*
* @return 信令消息
*/
Message build(String message, Object body);
/**
* @param messageCode 状态编码
* @param message 状态描述
* @param body 消息主体
*
* @return 信令消息
*/
Message build(MessageCode messageCode, String message, Object body);
/**
* @param id 消息标识
* @param messageCode 状态编码
* @param message 状态描述
* @param body 消息主体
*
* @return 信令消息
*/
Message build(Long id, MessageCode messageCode, String message, Object body);
/**
* 发布事件
*
* @param <E> 事件类型
*
* @param event 事件
*/
<E extends ApplicationEventAdapter> void publishEvent(E event);
/**
* @return 信令消息
*/
Message build();
/**
* @param body 消息主体
*
* @return 信令消息
*/
Message build(Object body);
/**
* @param messageCode 状态编码
* @param body 消息主体
*
* @return 信令消息
*/
Message build(MessageCode messageCode, Object body);
/**
* @param message 状态描述
* @param body 消息主体
*
* @return 信令消息
*/
Message build(String message, Object body);
/**
* @param messageCode 状态编码
* @param message 状态描述
* @param body 消息主体
*
* @return 信令消息
*/
Message build(MessageCode messageCode, String message, Object body);
/**
* @param id 消息标识
* @param messageCode 状态编码
* @param message 状态描述
* @param body 消息主体
*
* @return 信令消息
*/
Message build(Long id, MessageCode messageCode, String message, Object body);
}

View File

@@ -26,127 +26,127 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class ProtocolAdapter implements Protocol {
@Autowired
protected IdService idService;
@Autowired
protected RoomManager roomManager;
@Autowired
protected ClientManager clientManager;
@Autowired
protected SessionManager sessionManager;
@Autowired
protected TaoyaoProperties taoyaoProperties;
@Autowired
protected ApplicationContext applicationContext;
/**
* 信令名称
*/
protected final String name;
/**
* 信令标识
*/
protected final String signal;
@Autowired
protected IdService idService;
@Autowired
protected RoomManager roomManager;
@Autowired
protected ClientManager clientManager;
@Autowired
protected SessionManager sessionManager;
@Autowired
protected TaoyaoProperties taoyaoProperties;
@Autowired
protected ApplicationContext applicationContext;
/**
* 信令名称
*/
protected final String name;
/**
* 信令标识
*/
protected final String signal;
protected ProtocolAdapter(String name, String signal) {
this.name = name;
this.signal = signal;
}
@Override
public String name() {
return this.name;
}
@Override
public String signal() {
return this.signal;
}
@Override
public <E extends ApplicationEventAdapter> void publishEvent(E event) {
this.applicationContext.publishEvent(event);
}
@Override
public Message build() {
return this.build(null, null, null, null);
}
@Override
public Message build(Object body) {
return this.build(null, null, null, body);
}
@Override
public Message build(MessageCode messageCode, Object body) {
return this.build(null, messageCode, null, body);
}
@Override
public Message build(String message, Object body) {
return this.build(null, null, message, body);
}
@Override
public Message build(MessageCode messageCode, String message, Object body) {
return this.build(null, messageCode, message, body);
}
@Override
public Message build(Long id, MessageCode messageCode, String message, Object body) {
// 消息标识
if(id == null) {
id = this.idService.buildId();
}
// 设置主体
if(body == null) {
body = Map.of();
}
// 消息头部
final Header header = Header.builder()
.v(this.taoyaoProperties.getVersion())
.id(id)
.signal(this.signal)
.build();
final Message build = Message.builder().build();
// 设置状态编码、状态描述:默认成功
build.setCode(messageCode == null ? MessageCode.CODE_0000 : messageCode, message);
// 设置消息头部
build.setHeader(header);
// 设置消息主体
build.setBody(body);
return build;
}
/**
* 精简消息主体
*
* @param body 消息主体
* @param keys 清理键
*/
protected void pure(Map<String, Object> body, String ... keys) {
if(ArrayUtils.isEmpty(keys)) {
return;
}
for (String key : keys) {
protected ProtocolAdapter(String name, String signal) {
this.name = name;
this.signal = signal;
}
@Override
public String name() {
return this.name;
}
@Override
public String signal() {
return this.signal;
}
@Override
public <E extends ApplicationEventAdapter> void publishEvent(E event) {
this.applicationContext.publishEvent(event);
}
@Override
public Message build() {
return this.build(null, null, null, null);
}
@Override
public Message build(Object body) {
return this.build(null, null, null, body);
}
@Override
public Message build(MessageCode messageCode, Object body) {
return this.build(null, messageCode, null, body);
}
@Override
public Message build(String message, Object body) {
return this.build(null, null, message, body);
}
@Override
public Message build(MessageCode messageCode, String message, Object body) {
return this.build(null, messageCode, message, body);
}
@Override
public Message build(Long id, MessageCode messageCode, String message, Object body) {
// 消息标识
if(id == null) {
id = this.idService.buildId();
}
// 设置主体
if(body == null) {
body = Map.of();
}
// 消息头部
final Header header = Header.builder()
.v(this.taoyaoProperties.getVersion())
.id(id)
.signal(this.signal)
.build();
final Message build = Message.builder().build();
// 设置状态编码、状态描述:默认成功
build.setCode(messageCode == null ? MessageCode.CODE_0000 : messageCode, message);
// 设置消息头部
build.setHeader(header);
// 设置消息主体
build.setBody(body);
return build;
}
/**
* 精简消息主体
*
* @param body 消息主体
* @param keys 清理键
*/
protected void pure(Map<String, Object> body, String ... keys) {
if(ArrayUtils.isEmpty(keys)) {
return;
}
for (String key : keys) {
body.remove(key);
}
}
/**
* @param args 参数
*/
protected void logNoAdapter(Object ... args) {
if(log.isDebugEnabled()) {
final StringBuilder builder = new StringBuilder(this.name);
builder.append("没有适配信令消息:");
for (final Object object : args) {
builder.append(object).append(" ");
}
builder.setLength(builder.length() - 1);
log.debug(builder.toString());
}
}
}
/**
* @param args 参数
*/
protected void logNoAdapter(Object ... args) {
if(log.isDebugEnabled()) {
final StringBuilder builder = new StringBuilder(this.name);
builder.append("没有适配信令消息:");
for (final Object object : args) {
builder.append(object).append(" ");
}
builder.setLength(builder.length() - 1);
log.debug(builder.toString());
}
}
}

View File

@@ -28,9 +28,9 @@ import lombok.extern.slf4j.Slf4j;
@Manager
public class ProtocolManager {
private final ClientManager clientManager;
private final SecurityService securityService;
private final ApplicationContext applicationContext;
private final ClientManager clientManager;
private final SecurityService securityService;
private final ApplicationContext applicationContext;
private final PlatformErrorProtocol platformErrorProtocol;
/**
@@ -38,102 +38,107 @@ public class ProtocolManager {
*/
private final Map<String, Protocol> protocolMapping;
public ProtocolManager(ClientManager clientManager, SecurityService securityService, ApplicationContext applicationContext, PlatformErrorProtocol platformErrorProtocol) {
this.clientManager = clientManager;
this.securityService = securityService;
this.applicationContext = applicationContext;
public ProtocolManager(
ClientManager clientManager,
SecurityService securityService,
ApplicationContext applicationContext,
PlatformErrorProtocol platformErrorProtocol
) {
this.clientManager = clientManager;
this.securityService = securityService;
this.applicationContext = applicationContext;
this.platformErrorProtocol = platformErrorProtocol;
this.protocolMapping = new ConcurrentHashMap<>();
this.protocolMapping = new ConcurrentHashMap<>();
}
/**
* 加载信令映射
*/
public void init() {
this.applicationContext.getBeansOfType(Protocol.class).entrySet().stream()
.sorted((a, z) -> a.getValue().signal().compareTo(z.getValue().signal()))
.forEach(e -> {
final String key = e.getKey();
final Protocol value = e.getValue();
final String name = value.name();
final String signal = value.signal();
if(this.protocolMapping.containsKey(signal)) {
throw MessageCodeException.of("存在重复信令协议:" + signal);
}
if(log.isDebugEnabled()) {
log.debug("注册信令协议:{} - {} - {}", String.format("%-36s", signal), String.format("%-36s", key), name);
}
this.protocolMapping.put(signal, value);
});
log.info("当前注册信令数量:{}", this.protocolMapping.size());
}
/**
* @param signal 信令标识
*
* @return 信令
*/
public Protocol protocol(String signal) {
return this.protocolMapping.get(signal);
}
/**
* 执行信令消息
*
* @param content 信令消息
* @param instance 终端实例
*/
public void execute(String content, AutoCloseable instance) {
final Client client = this.clientManager.getClients(instance);
if(client == null) {
log.warn("信令终端无效:{}-{}", instance, content);
return;
}
// 验证请求
final Message message = JSONUtils.toJava(content, Message.class);
if(message == null) {
log.warn("信令消息格式错误(解析失败):{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(解析失败)"));
return;
}
final Header header = message.getHeader();
if(header == null) {
log.warn("信令消息格式错误(没有头部):{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(没有头部)"));
return;
}
final String v = header.getV();
final Long id = header.getId();
final String signal = header.getSignal();
// 设置缓存ID
this.platformErrorProtocol.set(id);
if(v == null || id == null || signal == null) {
log.warn("信令消息格式错误(缺失头部关键参数):{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(缺失头部关键参数)"));
return;
}
// 开始处理协议
final Protocol protocol = this.protocolMapping.get(signal);
if(protocol == null) {
log.warn("不支持的信令协议:{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_3415, "不支持的信令协议:" + signal));
return;
}
if(log.isDebugEnabled()) {
log.debug("执行信令消息:{} - {}", client.getClientId(), content);
}
if(protocol instanceof ClientRegisterProtocol) {
protocol.execute(client, message);
} else if(this.securityService.authenticate(client, message, protocol)) {
if(client.response(id, message)) {
// 响应消息不做其他处理
} else {
protocol.execute(client, message);
}
} else {
log.warn("终端没有授权:{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_3401, "终端没有授权"));
}
}
/**
* 加载信令映射
*/
public void init() {
this.applicationContext.getBeansOfType(Protocol.class).entrySet().stream()
.sorted((a, z) -> a.getValue().signal().compareTo(z.getValue().signal()))
.forEach(e -> {
final String key = e.getKey();
final Protocol value = e.getValue();
final String name = value.name();
final String signal = value.signal();
if(this.protocolMapping.containsKey(signal)) {
throw MessageCodeException.of("存在重复信令协议:" + signal);
}
if(log.isDebugEnabled()) {
log.debug("注册信令协议:{} - {} - {}", String.format("%-36s", signal), String.format("%-36s", key), name);
}
this.protocolMapping.put(signal, value);
});
log.info("当前注册信令数量:{}", this.protocolMapping.size());
}
/**
* @param signal 信令标识
*
* @return 信令
*/
public Protocol protocol(String signal) {
return this.protocolMapping.get(signal);
}
/**
* 执行信令消息
*
* @param content 信令消息
* @param instance 终端实例
*/
public void execute(String content, AutoCloseable instance) {
final Client client = this.clientManager.getClients(instance);
if(client == null) {
log.warn("信令终端无效:{}-{}", instance, content);
return;
}
// 验证请求
final Message message = JSONUtils.toJava(content, Message.class);
if(message == null) {
log.warn("信令消息格式错误(解析失败):{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(解析失败)"));
return;
}
final Header header = message.getHeader();
if(header == null) {
log.warn("信令消息格式错误(没有头部):{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(没有头部)"));
return;
}
final String v = header.getV();
final Long id = header.getId();
final String signal = header.getSignal();
// 设置缓存ID
this.platformErrorProtocol.set(id);
if(v == null || id == null || signal == null) {
log.warn("信令消息格式错误(缺失头部关键参数):{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(缺失头部关键参数)"));
return;
}
// 开始处理协议
final Protocol protocol = this.protocolMapping.get(signal);
if(protocol == null) {
log.warn("不支持的信令协议:{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_3415, "不支持的信令协议:" + signal));
return;
}
if(log.isDebugEnabled()) {
log.debug("执行信令消息:{} - {}", client.getClientId(), content);
}
if(protocol instanceof ClientRegisterProtocol) {
protocol.execute(client, message);
} else if(this.securityService.authenticate(client, message, protocol)) {
if(client.response(id, message)) {
// 响应消息不做其他处理
} else {
protocol.execute(client, message);
}
} else {
log.warn("终端没有授权:{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_3401, "终端没有授权"));
}
}
}

View File

@@ -17,14 +17,14 @@ import com.acgist.taoyao.signal.party.room.Room;
*/
public abstract class ProtocolRoomAdapter extends ProtocolClientAdapter {
protected ProtocolRoomAdapter(String name, String signal) {
super(name, signal);
}
@Override
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) {
protected ProtocolRoomAdapter(String name, String signal) {
super(name, signal);
}
@Override
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, Constant.ROOM_ID);
final Room room = this.roomManager.getRoom(roomId);
final Room room = this.roomManager.getRoom(roomId);
if(room == null) {
throw MessageCodeException.of("无效房间:" + roomId);
}
@@ -32,30 +32,30 @@ public abstract class ProtocolRoomAdapter extends ProtocolClientAdapter {
throw MessageCodeException.of("终端没有房间权限:" + clientId);
}
this.execute(clientId, clientType, room, client, room.getMediaClient(), message, body);
}
/**
* @param room 房间
* @param client 终端
*
* @return 是否认证
*/
protected boolean authenticate(Room room, Client client) {
return room.authenticate(client);
}
/**
* 处理终端房间信令
*
* @param clientId 终端标识
* @param clientType 终端类型
* @param room 房间
* @param client 终端
* @param mediaClient 媒体服务终端
* @param message 消息
* @param body 消息主体
*/
public void execute(String clientId, ClientType clientType, Room room, Client client, Client mediaClient, Message message, Map<String, Object> body) {
}
}
/**
* @param room 房间
* @param client 终端
*
* @return 是否认证
*/
protected boolean authenticate(Room room, Client client) {
return room.authenticate(client);
}
/**
* 处理终端房间信令
*
* @param clientId 终端标识
* @param clientType 终端类型
* @param room 房间
* @param client 终端
* @param mediaClient 媒体服务终端
* @param message 信令消息
* @param body 消息主体
*/
public void execute(String clientId, ClientType clientType, Room room, Client client, Client mediaClient, Message message, Map<String, Object> body) {
}
}

View File

@@ -17,31 +17,31 @@ import com.acgist.taoyao.signal.party.session.Session;
*/
public abstract class ProtocolSessionAdapter extends ProtocolClientAdapter {
protected ProtocolSessionAdapter(String name, String signal) {
super(name, signal);
}
@Override
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) {
protected ProtocolSessionAdapter(String name, String signal) {
super(name, signal);
}
@Override
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) {
final String sessionId = MapUtils.get(body, Constant.SESSION_ID);
final Session session = this.sessionManager.get(sessionId);
if(session == null) {
throw MessageCodeException.of("无效会话:" + sessionId);
}
this.execute(clientId, clientType, session, client, message, body);
}
/**
* 处理终端会话信令
*
* @param clientId 终端标识
* @param clientType 终端类型
* @param session 会话
* @param client 终端
* @param message 消息
* @param body 消息主体
*/
public void execute(String clientId, ClientType clientType, Session session, Client client, Message message, Map<String, Object> body) {
}
}
/**
* 处理终端会话信令
*
* @param clientId 终端标识
* @param clientType 终端类型
* @param session 会话
* @param client 终端
* @param message 信令消息
* @param body 消息主体
*/
public void execute(String clientId, ClientType clientType, Session session, Client client, Message message, Map<String, Object> body) {
}
}

View File

@@ -11,28 +11,28 @@ import com.acgist.taoyao.signal.protocol.Protocol;
*/
public interface SecurityService {
/**
* 认证
* 优先使用`UsernamePasswordService`其次使用配置帐号密码
*
* @param username 用户名称
* @param password 用户密码
*
* @return 是否成功
*
* @see UsernamePasswordService
*/
boolean authenticate(String username, String password);
/**
* 鉴权
*
* @param client 终端
* @param message 信令
* @param protocol 协议
*
* @return 是否成功
*/
boolean authenticate(Client client, Message message, Protocol protocol);
/**
* 认证
* 优先使用`UsernamePasswordService`其次使用配置帐号密码
*
* @param username 用户名称
* @param password 用户密码
*
* @return 是否成功
*
* @see UsernamePasswordService
*/
boolean authenticate(String username, String password);
/**
* 鉴权
*
* @param client 终端
* @param message 信令消息
* @param protocol 协议
*
* @return 是否成功
*/
boolean authenticate(Client client, Message message, Protocol protocol);
}

View File

@@ -11,31 +11,31 @@ import com.acgist.taoyao.signal.service.UsernamePasswordService;
public class SecurityServiceImpl implements SecurityService {
private final SecurityProperties securityProperties;
private final UsernamePasswordService usernamePasswordService;
public SecurityServiceImpl(SecurityProperties securityProperties, UsernamePasswordService usernamePasswordService) {
this.securityProperties = securityProperties;
private final SecurityProperties securityProperties;
private final UsernamePasswordService usernamePasswordService;
public SecurityServiceImpl(SecurityProperties securityProperties, UsernamePasswordService usernamePasswordService) {
this.securityProperties = securityProperties;
this.usernamePasswordService = usernamePasswordService;
}
@Override
public boolean authenticate(String username, String password) {
if(Boolean.FALSE.equals(this.securityProperties.getEnabled())) {
return true;
}
if(this.usernamePasswordService == null) {
return
StringUtils.equals(this.securityProperties.getUsername(), username) &&
StringUtils.equals(this.securityProperties.getPassword(), password);
} else {
return this.usernamePasswordService.authenticate(username, password);
}
}
@Override
public boolean authenticate(Client client, Message message, Protocol protocol) {
return client.authorized() && protocol.authenticate(message);
}
public boolean authenticate(String username, String password) {
if(Boolean.FALSE.equals(this.securityProperties.getEnabled())) {
return true;
}
if(this.usernamePasswordService == null) {
return
StringUtils.equals(this.securityProperties.getUsername(), username) &&
StringUtils.equals(this.securityProperties.getPassword(), password);
} else {
return this.usernamePasswordService.authenticate(username, password);
}
}
@Override
public boolean authenticate(Client client, Message message, Protocol protocol) {
return client.authorized() && protocol.authenticate(message);
}
}

View File

@@ -26,9 +26,9 @@ public class CipherUtils {
}
/**
* @param mode 模式
* @param mode 模式
* @param encrypt 算法
* @param secret 密钥
* @param secret 密钥
*
* @return 加密工具
*/
@@ -37,8 +37,8 @@ public class CipherUtils {
return null;
}
try {
final String algo = encrypt.getAlgo();
final String name = encrypt.name();
final String algo = encrypt.getAlgo();
final String name = encrypt.name();
final Cipher cipher = Cipher.getInstance(algo);
cipher.init(mode, new SecretKeySpec(Base64.getMimeDecoder().decode(secret), name));
return cipher;

View File

@@ -1,4 +1,4 @@
com.acgist.taoyao.signal.configuration.ScriptAutoConfiguration
com.acgist.taoyao.signal.configuration.SignalAutoConfiguration
com.acgist.taoyao.signal.configuration.SocketSignalAutoConfiguration
com.acgist.taoyao.signal.configuration.WebSocketSignalAutoConfiguration
com.acgist.taoyao.signal.configuration.WebSocketSignalAutoConfiguration