[*] 日常优化

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

View File

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

View File

@@ -28,9 +28,9 @@ import lombok.extern.slf4j.Slf4j;
@Manager @Manager
public class ProtocolManager { public class ProtocolManager {
private final ClientManager clientManager; private final ClientManager clientManager;
private final SecurityService securityService; private final SecurityService securityService;
private final ApplicationContext applicationContext; private final ApplicationContext applicationContext;
private final PlatformErrorProtocol platformErrorProtocol; private final PlatformErrorProtocol platformErrorProtocol;
/** /**
@@ -38,102 +38,107 @@ public class ProtocolManager {
*/ */
private final Map<String, Protocol> protocolMapping; private final Map<String, Protocol> protocolMapping;
public ProtocolManager(ClientManager clientManager, SecurityService securityService, ApplicationContext applicationContext, PlatformErrorProtocol platformErrorProtocol) { public ProtocolManager(
this.clientManager = clientManager; ClientManager clientManager,
this.securityService = securityService; SecurityService securityService,
this.applicationContext = applicationContext; ApplicationContext applicationContext,
PlatformErrorProtocol platformErrorProtocol
) {
this.clientManager = clientManager;
this.securityService = securityService;
this.applicationContext = applicationContext;
this.platformErrorProtocol = platformErrorProtocol; this.platformErrorProtocol = platformErrorProtocol;
this.protocolMapping = new ConcurrentHashMap<>(); this.protocolMapping = new ConcurrentHashMap<>();
} }
/** /**
* 加载信令映射 * 加载信令映射
*/ */
public void init() { public void init() {
this.applicationContext.getBeansOfType(Protocol.class).entrySet().stream() this.applicationContext.getBeansOfType(Protocol.class).entrySet().stream()
.sorted((a, z) -> a.getValue().signal().compareTo(z.getValue().signal())) .sorted((a, z) -> a.getValue().signal().compareTo(z.getValue().signal()))
.forEach(e -> { .forEach(e -> {
final String key = e.getKey(); final String key = e.getKey();
final Protocol value = e.getValue(); final Protocol value = e.getValue();
final String name = value.name(); final String name = value.name();
final String signal = value.signal(); final String signal = value.signal();
if(this.protocolMapping.containsKey(signal)) { if(this.protocolMapping.containsKey(signal)) {
throw MessageCodeException.of("存在重复信令协议:" + signal); throw MessageCodeException.of("存在重复信令协议:" + signal);
} }
if(log.isDebugEnabled()) { if(log.isDebugEnabled()) {
log.debug("注册信令协议:{} - {} - {}", String.format("%-36s", signal), String.format("%-36s", key), name); log.debug("注册信令协议:{} - {} - {}", String.format("%-36s", signal), String.format("%-36s", key), name);
} }
this.protocolMapping.put(signal, value); this.protocolMapping.put(signal, value);
}); });
log.info("当前注册信令数量:{}", this.protocolMapping.size()); log.info("当前注册信令数量:{}", this.protocolMapping.size());
} }
/** /**
* @param signal 信令标识 * @param signal 信令标识
* *
* @return 信令 * @return 信令
*/ */
public Protocol protocol(String signal) { public Protocol protocol(String signal) {
return this.protocolMapping.get(signal); return this.protocolMapping.get(signal);
} }
/** /**
* 执行信令消息 * 执行信令消息
* *
* @param content 信令消息 * @param content 信令消息
* @param instance 终端实例 * @param instance 终端实例
*/ */
public void execute(String content, AutoCloseable instance) { public void execute(String content, AutoCloseable instance) {
final Client client = this.clientManager.getClients(instance); final Client client = this.clientManager.getClients(instance);
if(client == null) { if(client == null) {
log.warn("信令终端无效:{}-{}", instance, content); log.warn("信令终端无效:{}-{}", instance, content);
return; return;
} }
// 验证请求 // 验证请求
final Message message = JSONUtils.toJava(content, Message.class); final Message message = JSONUtils.toJava(content, Message.class);
if(message == null) { if(message == null) {
log.warn("信令消息格式错误(解析失败):{}", content); log.warn("信令消息格式错误(解析失败):{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(解析失败)")); client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(解析失败)"));
return; return;
} }
final Header header = message.getHeader(); final Header header = message.getHeader();
if(header == null) { if(header == null) {
log.warn("信令消息格式错误(没有头部):{}", content); log.warn("信令消息格式错误(没有头部):{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(没有头部)")); client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(没有头部)"));
return; return;
} }
final String v = header.getV(); final String v = header.getV();
final Long id = header.getId(); final Long id = header.getId();
final String signal = header.getSignal(); final String signal = header.getSignal();
// 设置缓存ID // 设置缓存ID
this.platformErrorProtocol.set(id); this.platformErrorProtocol.set(id);
if(v == null || id == null || signal == null) { if(v == null || id == null || signal == null) {
log.warn("信令消息格式错误(缺失头部关键参数):{}", content); log.warn("信令消息格式错误(缺失头部关键参数):{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(缺失头部关键参数)")); client.push(this.platformErrorProtocol.build(MessageCode.CODE_1002, "信令消息格式错误(缺失头部关键参数)"));
return; return;
} }
// 开始处理协议 // 开始处理协议
final Protocol protocol = this.protocolMapping.get(signal); final Protocol protocol = this.protocolMapping.get(signal);
if(protocol == null) { if(protocol == null) {
log.warn("不支持的信令协议:{}", content); log.warn("不支持的信令协议:{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_3415, "不支持的信令协议:" + signal)); client.push(this.platformErrorProtocol.build(MessageCode.CODE_3415, "不支持的信令协议:" + signal));
return; return;
} }
if(log.isDebugEnabled()) { if(log.isDebugEnabled()) {
log.debug("执行信令消息:{} - {}", client.getClientId(), content); log.debug("执行信令消息:{} - {}", client.getClientId(), content);
} }
if(protocol instanceof ClientRegisterProtocol) { if(protocol instanceof ClientRegisterProtocol) {
protocol.execute(client, message); protocol.execute(client, message);
} else if(this.securityService.authenticate(client, message, protocol)) { } else if(this.securityService.authenticate(client, message, protocol)) {
if(client.response(id, message)) { if(client.response(id, message)) {
// 响应消息不做其他处理 // 响应消息不做其他处理
} else { } else {
protocol.execute(client, message); protocol.execute(client, message);
} }
} else { } else {
log.warn("终端没有授权:{}", content); log.warn("终端没有授权:{}", content);
client.push(this.platformErrorProtocol.build(MessageCode.CODE_3401, "终端没有授权")); 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 { public abstract class ProtocolRoomAdapter extends ProtocolClientAdapter {
protected ProtocolRoomAdapter(String name, String signal) { protected ProtocolRoomAdapter(String name, String signal) {
super(name, signal); super(name, signal);
} }
@Override @Override
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) { 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 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) { if(room == null) {
throw MessageCodeException.of("无效房间:" + roomId); throw MessageCodeException.of("无效房间:" + roomId);
} }
@@ -32,30 +32,30 @@ public abstract class ProtocolRoomAdapter extends ProtocolClientAdapter {
throw MessageCodeException.of("终端没有房间权限:" + clientId); throw MessageCodeException.of("终端没有房间权限:" + clientId);
} }
this.execute(clientId, clientType, room, client, room.getMediaClient(), message, body); this.execute(clientId, clientType, room, client, room.getMediaClient(), message, body);
} }
/** /**
* @param room 房间 * @param room 房间
* @param client 终端 * @param client 终端
* *
* @return 是否认证 * @return 是否认证
*/ */
protected boolean authenticate(Room room, Client client) { protected boolean authenticate(Room room, Client client) {
return room.authenticate(client); return room.authenticate(client);
} }
/** /**
* 处理终端房间信令 * 处理终端房间信令
* *
* @param clientId 终端标识 * @param clientId 终端标识
* @param clientType 终端类型 * @param clientType 终端类型
* @param room 房间 * @param room 房间
* @param client 终端 * @param client 终端
* @param mediaClient 媒体服务终端 * @param mediaClient 媒体服务终端
* @param message 消息 * @param message 信令消息
* @param body 消息主体 * @param body 消息主体
*/ */
public void execute(String clientId, ClientType clientType, Room room, Client client, Client mediaClient, Message message, Map<String, Object> 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 { public abstract class ProtocolSessionAdapter extends ProtocolClientAdapter {
protected ProtocolSessionAdapter(String name, String signal) { protected ProtocolSessionAdapter(String name, String signal) {
super(name, signal); super(name, signal);
} }
@Override @Override
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) { 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 String sessionId = MapUtils.get(body, Constant.SESSION_ID);
final Session session = this.sessionManager.get(sessionId); final Session session = this.sessionManager.get(sessionId);
if(session == null) { if(session == null) {
throw MessageCodeException.of("无效会话:" + sessionId); throw MessageCodeException.of("无效会话:" + sessionId);
} }
this.execute(clientId, clientType, session, client, message, body); this.execute(clientId, clientType, session, client, message, body);
} }
/** /**
* 处理终端会话信令 * 处理终端会话信令
* *
* @param clientId 终端标识 * @param clientId 终端标识
* @param clientType 终端类型 * @param clientType 终端类型
* @param session 会话 * @param session 会话
* @param client 终端 * @param client 终端
* @param message 消息 * @param message 信令消息
* @param body 消息主体 * @param body 消息主体
*/ */
public void execute(String clientId, ClientType clientType, Session session, Client client, Message message, Map<String, Object> 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 { public interface SecurityService {
/** /**
* 认证 * 认证
* 优先使用`UsernamePasswordService`其次使用配置帐号密码 * 优先使用`UsernamePasswordService`其次使用配置帐号密码
* *
* @param username 用户名称 * @param username 用户名称
* @param password 用户密码 * @param password 用户密码
* *
* @return 是否成功 * @return 是否成功
* *
* @see UsernamePasswordService * @see UsernamePasswordService
*/ */
boolean authenticate(String username, String password); boolean authenticate(String username, String password);
/** /**
* 鉴权 * 鉴权
* *
* @param client 终端 * @param client 终端
* @param message 信令 * @param message 信令消息
* @param protocol 协议 * @param protocol 协议
* *
* @return 是否成功 * @return 是否成功
*/ */
boolean authenticate(Client client, Message message, Protocol protocol); 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 { public class SecurityServiceImpl implements SecurityService {
private final SecurityProperties securityProperties; private final SecurityProperties securityProperties;
private final UsernamePasswordService usernamePasswordService; private final UsernamePasswordService usernamePasswordService;
public SecurityServiceImpl(SecurityProperties securityProperties, UsernamePasswordService usernamePasswordService) { public SecurityServiceImpl(SecurityProperties securityProperties, UsernamePasswordService usernamePasswordService) {
this.securityProperties = securityProperties; this.securityProperties = securityProperties;
this.usernamePasswordService = usernamePasswordService; this.usernamePasswordService = usernamePasswordService;
} }
@Override @Override
public boolean authenticate(String username, String password) { public boolean authenticate(String username, String password) {
if(Boolean.FALSE.equals(this.securityProperties.getEnabled())) { if(Boolean.FALSE.equals(this.securityProperties.getEnabled())) {
return true; return true;
} }
if(this.usernamePasswordService == null) { if(this.usernamePasswordService == null) {
return return
StringUtils.equals(this.securityProperties.getUsername(), username) && StringUtils.equals(this.securityProperties.getUsername(), username) &&
StringUtils.equals(this.securityProperties.getPassword(), password); StringUtils.equals(this.securityProperties.getPassword(), password);
} else { } else {
return this.usernamePasswordService.authenticate(username, password); return this.usernamePasswordService.authenticate(username, password);
} }
} }
@Override @Override
public boolean authenticate(Client client, Message message, Protocol protocol) { public boolean authenticate(Client client, Message message, Protocol protocol) {
return client.authorized() && protocol.authenticate(message); return client.authorized() && protocol.authenticate(message);
} }
} }

View File

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

View File

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