From e668670da80478886afe6fca901b4be4ec8c1488 Mon Sep 17 00:00:00 2001
From: acgist <289547414@qq.com>
Date: Fri, 11 Nov 2022 07:59:36 +0800
Subject: [PATCH] =?UTF-8?q?[*]=20=E7=BB=9F=E4=B8=80=E6=B6=88=E6=81=AF?=
=?UTF-8?q?=E6=A8=A1=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
LICENSE | 2 +-
README.md | 12 +-
pom.xml | 25 +--
.../boot/config/BootAutoConfiguration.java | 8 +
.../taoyao/boot/config/FormatStyle.java | 133 ------------
.../taoyao/boot/config/WebrtcProperties.java | 21 +-
.../controller/TaoyaoControllerAdvice.java | 2 +-
.../controller/TaoyaoErrorController.java | 2 +-
.../boot/interceptor/SecurityInterceptor.java | 11 +-
.../com/acgist/taoyao/boot/model}/Header.java | 22 +-
.../com/acgist/taoyao/boot/model/Message.java | 176 ++++++++-------
.../acgist/taoyao/boot/service/IdService.java | 6 +-
.../boot/service/impl/IdServiceImpl.java | 43 +++-
.../acgist/taoyao/boot/utils/DateUtils.java | 125 ++++++++++-
.../acgist/taoyao/boot/utils/ErrorUtils.java | 39 +++-
.../taoyao/boot/utils/ExceptionUtils.java | 43 ----
.../acgist/taoyao/boot/utils/JSONUtils.java | 6 +-
taoyao-client/pom.xml | 30 ---
taoyao-nat/README.md | 3 +
taoyao-nat/pom.xml | 2 +-
taoyao-server/LICENSE | 201 ++++++++++++++++++
taoyao-server/pom.xml | 4 -
.../src/main/resources/application.yml | 9 +-
taoyao-signal/README.md | 43 ++++
.../config/SignalAutoConfiguration.java | 17 +-
.../com/acgist/taoyao/signal/event/Event.java | 15 --
.../taoyao/signal/event/EventAdapter.java | 10 -
.../signal/event/client/RegisterEvent.java | 25 ++-
.../listener/ApplicationListenerAdapter.java | 21 ++
.../listener/client/RegisterListener.java | 38 ++++
.../acgist/taoyao/signal/message/Message.java | 41 ----
.../taoyao/signal/protocol/Protocol.java | 29 +++
.../signal/protocol/ProtocolAdapter.java | 46 +++-
.../protocol/ProtocolBodyMapAdapter.java | 44 ++++
.../protocol/ProtocolBodyObjectAdapter.java | 55 +++++
.../signal/protocol/ProtocolManager.java | 86 +++++++-
.../signal/protocol/client/CloseProtocol.java | 33 +++
.../protocol/client/OfflineProtocol.java | 10 +
.../protocol/client/OnlineProtocol.java | 32 +++
.../protocol/client/RegisterProtocol.java | 54 +++++
.../signal/protocol/system/ErrorProtocol.java | 32 +++
.../taoyao/signal/session/ClientSession.java | 66 ++++++
.../signal/session/ClientSessionAdapter.java | 88 ++++++++
.../signal/session/ClientSessionManager.java | 129 +++++++++++
.../signal/session/ClientSessionStatus.java | 12 ++
.../acgist/taoyao/signal/session/Session.java | 5 -
.../taoyao/signal/session/SessionAdapter.java | 5 -
.../taoyao/signal/session/SessionManager.java | 162 --------------
.../{TaoyaoSocket.java => SocketSignal.java} | 2 +-
.../session/websocket/SessionWrapper.java | 72 -------
.../session/websocket/TaoyaoWebSocket.java | 60 ------
.../session/websocket/WebSocketSession.java | 37 ++++
.../session/websocket/WebSocketSignal.java | 94 ++++++++
taoyao-webrtc/pom.xml | 2 +-
.../pom.xml | 12 +-
taoyao-webrtc/taoyao-webrtc-mcu/pom.xml | 2 +-
taoyao-webrtc/taoyao-webrtc-sfu/pom.xml | 2 +-
57 files changed, 1542 insertions(+), 764 deletions(-)
delete mode 100644 taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/FormatStyle.java
rename {taoyao-signal/src/main/java/com/acgist/taoyao/signal/message => taoyao-boot/src/main/java/com/acgist/taoyao/boot/model}/Header.java (73%)
delete mode 100644 taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/ExceptionUtils.java
delete mode 100644 taoyao-client/pom.xml
create mode 100644 taoyao-nat/README.md
create mode 100644 taoyao-server/LICENSE
create mode 100644 taoyao-signal/README.md
delete mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/Event.java
delete mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/EventAdapter.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/listener/ApplicationListenerAdapter.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/listener/client/RegisterListener.java
delete mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/message/Message.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolBodyMapAdapter.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolBodyObjectAdapter.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/CloseProtocol.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/OfflineProtocol.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/OnlineProtocol.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/RegisterProtocol.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/system/ErrorProtocol.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSession.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionAdapter.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionManager.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionStatus.java
delete mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/Session.java
delete mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/SessionAdapter.java
delete mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/SessionManager.java
rename taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/socket/{TaoyaoSocket.java => SocketSignal.java} (77%)
delete mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/SessionWrapper.java
delete mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/TaoyaoWebSocket.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/WebSocketSession.java
create mode 100644 taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/WebSocketSignal.java
rename taoyao-webrtc/{taoyao-webrtc-mix => taoyao-webrtc-jni}/pom.xml (65%)
diff --git a/LICENSE b/LICENSE
index 261eeb9..6e6a6b0 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright [yyyy] [name of copyright owner]
+ Copyright [2022] [acgist]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/README.md b/README.md
index b8a31ea..d12a075 100644
--- a/README.md
+++ b/README.md
@@ -7,18 +7,17 @@
|模块|名称|描述|
|:--|:--|:--|
|taoyao|桃夭|桃之夭夭灼灼其华|
-|taoyao-nat|内网穿透|STUN/TURN暂不实现(请用公共服务或者搭建coturn服务)|
+|taoyao-nat|内网穿透|STUN/TURN|
|taoyao-boot|基础|启动模块|
|taoyao-live|直播|直播、连麦|
|taoyao-media|媒体|录制、视频(美颜、AI识别)、音频(混音、变声)|
-|taoyao-client|终端|帐号(移动端|浏览器)、摄像头|
|taoyao-signal|信令|信令服务|
|taoyao-server|服务|启动服务|
|taoyao-meeting|会议|会议模式、广播模式、单人对讲|
|taoyao-webrtc|WebRTC模块||
+|taoyao-webrtc-jni|WebRTC JNI|WebRTC本地接口|
|taoyao-webrtc-sfu|WebRTC SFU架构实现||
|taoyao-webrtc-mcu|WebRTC MCU架构实现||
-|taoyao-webrtc-mix|WebRTC混合|MCU/SFU混合媒体服务|
|taoyao-webrtc-mesh|WebRTC MESH架构实现||
## STUN/TURN公共服务
@@ -33,7 +32,8 @@ stun:stun.stunprotocol.org:3478
## 终端
-帐号(移动端|浏览器)可以管理媒体,摄像头只能被动管理。
+帐号(移动端|浏览器)
+摄像头
### 功能
@@ -55,6 +55,8 @@ stun:stun.stunprotocol.org:3478
恢复推流
掉线重连
+## 信令
+
### 信息
IP
@@ -68,8 +70,6 @@ MAC
## 会议
-##
-
## 证书
```
diff --git a/pom.xml b/pom.xml
index 79fb815..a44aa27 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,7 +39,6 @@
taoyao-boot
taoyao-live
taoyao-media
- taoyao-client
taoyao-signal
taoyao-webrtc
taoyao-server
@@ -123,11 +122,6 @@
taoyao-media
${project.version}
-
- com.acgist
- taoyao-client
- ${project.version}
-
com.acgist
taoyao-signal
@@ -148,6 +142,11 @@
taoyao-webrtc
${project.version}
+
+ com.acgist
+ taoyao-webrtc-jni
+ ${project.version}
+
com.acgist
taoyao-webrtc-sfu
@@ -158,11 +157,6 @@
taoyao-webrtc-mcu
${project.version}
-
- com.acgist
- taoyao-webrtc-mix
- ${project.version}
-
com.acgist
taoyao-webrtc-mesh
@@ -226,15 +220,6 @@
false
-
-
- ./
- false
- META-INF/
-
- LICENSE
-
-
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/BootAutoConfiguration.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/BootAutoConfiguration.java
index 8535328..7cd6d34 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/BootAutoConfiguration.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/BootAutoConfiguration.java
@@ -51,6 +51,8 @@ import com.acgist.taoyao.boot.controller.TaoyaoControllerAdvice;
import com.acgist.taoyao.boot.controller.TaoyaoErrorController;
import com.acgist.taoyao.boot.interceptor.SecurityInterceptor;
import com.acgist.taoyao.boot.model.MessageCode;
+import com.acgist.taoyao.boot.service.IdService;
+import com.acgist.taoyao.boot.service.impl.IdServiceImpl;
import com.acgist.taoyao.boot.utils.ErrorUtils;
import com.acgist.taoyao.boot.utils.FileUtils;
import com.acgist.taoyao.boot.utils.JSONUtils;
@@ -80,6 +82,12 @@ public class BootAutoConfiguration {
@Autowired
private ApplicationContext context;
+ @Bean
+ @ConditionalOnMissingBean
+ public IdService idService() {
+ return new IdServiceImpl();
+ }
+
@Bean
@Primary
@ConditionalOnMissingBean
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/FormatStyle.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/FormatStyle.java
deleted file mode 100644
index 4b1187c..0000000
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/FormatStyle.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package com.acgist.taoyao.boot.config;
-
-import java.time.format.DateTimeFormatter;
-
-import lombok.Getter;
-
-/**
- * 格式
- *
- * @author acgist
- */
-public interface FormatStyle {
-
- /**
- * 默认日期格式
- */
- public static final String YYYY_MM_DD_HH24_MM_SS = "yyyy-MM-dd HH:mm:ss";
-
- /**
- * 日期时间
- *
- * @author acgist
- */
- @Getter
- public static enum DateTimeStyle {
-
- // YYYY
- YYYYMMDD_HH24_MM("yyyyMMdd HH:mm"),
- YYYY_MM_DD_HH24_MM("yyyy-MM-dd HH:mm"),
- YYYYMMDDHH24MMSS("yyyyMMddHHmmss"),
- YYYYMMDDHH24MMSSSSS("yyyyMMddHHmmssSSS"),
- YYYYMMDD_HH24_MM_SS("yyyyMMdd HH:mm:ss"),
- YYYYMMDD_HH24_MM_SS_SSS("yyyyMMdd HH:mm:ss.SSS"),
- YYYY_MM_DD_HH24_MM_SS("yyyy-MM-dd HH:mm:ss"),
- YYYY_MM_DD_HH24_MM_SS_SSS("yyyy-MM-dd HH:mm:ss.SSS"),
- // YY
- YYMMDD_HH24_MM("yyMMdd HH:mm"),
- YY_MM_DD_HH24_MM("yy-MM-dd HH:mm"),
- YYMMDDHH24MMSS("yyMMddHHmmss"),
- YYMMDDHH24MMSSSSS("yyMMddHHmmssSSS"),
- YYMMDD_HH24_MM_SS("yyMMdd HH:mm:ss"),
- YYMMDD_HH24_MM_SS_SSS("yyMMdd HH:mm:ss.SSS"),
- YY_MM_DD_HH24_MM_SS("yy-MM-dd HH:mm:ss"),
- YY_MM_DD_HH24_MM_SS_SSS("yy-MM-dd HH:mm:ss.SSS"),
- // ISO
- YY_MM_DD_HH24_MM_SS_ISO("yy-MM-dd'T'HH:mm:ss"),
- YY_MM_DD_HH24_MM_SS_SSS_ISO("yy-MM-dd'T'HH:mm:ss.SSS"),
- YYYY_MM_DD_HH24_MM_SS_ISO("yyyy-MM-dd'T'HH:mm:ss"),
- YYYY_MM_DD_HH24_MM_SS_SSS_ISO("yyyy-MM-dd'T'HH:mm:ss.SSS"),
- // UTC
- YY_MM_DD_HH24_MM_SS_UTC("yy-MM-dd'T'HH:mm:ss'Z'"),
- YY_MM_DD_HH24_MM_SS_SSS_UTC("yy-MM-dd'T'HH:mm:ss.SSS'Z'"),
- YYYY_MM_DD_HH24_MM_SS_UTC("yyyy-MM-dd'T'HH:mm:ss'Z'"),
- YYYY_MM_DD_HH24_MM_SS_SSS_UTC("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
-
- /**
- * 格式
- */
- private final String format;
- /**
- * 格式工具
- */
- private final DateTimeFormatter dateTimeFormatter;
-
- private DateTimeStyle(String format) {
- this.format = format;
- this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
- }
-
- }
-
- /**
- * 时间
- *
- * @author acgist
- */
- @Getter
- public static enum TimeStyle {
-
- HH24("HH"),
- HH24MM("HHmm"),
- HH24_MM("HH:mm"),
- HH24MMSS("HHmmss"),
- HH24_MM_SS("HH:mm:ss"),
- HH24MMSSSSS("HHmmssSSS"),
- HH24_MM_SS_SSS("HH:mm:ss.SSS");
-
- /**
- * 格式
- */
- private final String format;
- /**
- * 格式工具
- */
- private final DateTimeFormatter dateTimeFormatter;
-
- private TimeStyle(String format) {
- this.format = format;
- this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
- }
-
- }
-
- /**
- * 日期
- *
- * @author acgist
- */
- @Getter
- public static enum DateStyle {
-
- YYMMDD("yyMMdd"),
- YYYYMMDD("yyyyMMdd"),
- YY_MM_DD("yy-MM-dd"),
- YYYY_MM_DD("yyyy-MM-dd");
-
- /**
- * 格式
- */
- private String format;
- /**
- * 格式工具
- */
- private final DateTimeFormatter dateTimeFormatter;
-
- private DateStyle(String format) {
- this.format = format;
- this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
- }
-
- }
-
-}
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/WebrtcProperties.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/WebrtcProperties.java
index 898e258..25c3cd3 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/WebrtcProperties.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/WebrtcProperties.java
@@ -18,14 +18,23 @@ import lombok.Setter;
public class WebrtcProperties {
/**
- * 类型
+ * 架构类型
*
* @author acgist
*/
public enum Type {
+ /**
+ * SFU架构
+ */
SFU,
+ /**
+ * MCU架构
+ */
MCU,
+ /**
+ * MESH架构
+ */
MESH;
}
@@ -33,7 +42,15 @@ public class WebrtcProperties {
/**
* 类型
*/
- @Schema(name = "类型", description = "WebRTC媒体架构")
+ @Schema(name = "架构类型", description = "WebRTC架构类型")
private Type type;
+ /**
+ * stun服务器
+ */
+ private String[] stun;
+ /**
+ * turn服务器
+ */
+ private String[] turn;
}
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/controller/TaoyaoControllerAdvice.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/controller/TaoyaoControllerAdvice.java
index 5ad7448..29150fb 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/controller/TaoyaoControllerAdvice.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/controller/TaoyaoControllerAdvice.java
@@ -18,7 +18,7 @@ import com.acgist.taoyao.boot.utils.ErrorUtils;
public class TaoyaoControllerAdvice {
@ExceptionHandler(Exception.class)
- public Message exception(Exception e, HttpServletRequest request, HttpServletResponse response) {
+ public Message exception(Exception e, HttpServletRequest request, HttpServletResponse response) {
return ErrorUtils.message(e, request, response);
}
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/controller/TaoyaoErrorController.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/controller/TaoyaoErrorController.java
index d78981e..5b2a185 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/controller/TaoyaoErrorController.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/controller/TaoyaoErrorController.java
@@ -24,7 +24,7 @@ public class TaoyaoErrorController implements ErrorController {
@Operation(summary = "统一错误地址", description = "全局统一错误地址")
@RequestMapping(value = ErrorUtils.ERROR_PATH)
- public Message index(HttpServletRequest request, HttpServletResponse response) {
+ public Message index(HttpServletRequest request, HttpServletResponse response) {
return ErrorUtils.message(request, response);
}
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/interceptor/SecurityInterceptor.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/interceptor/SecurityInterceptor.java
index bf12cae..e5987e3 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/interceptor/SecurityInterceptor.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/interceptor/SecurityInterceptor.java
@@ -46,7 +46,7 @@ public class SecurityInterceptor implements HandlerInterceptor {
/**
* @param request 请求
*
- * @return 是否公共请求
+ * @return 是否许可请求
*/
private boolean permit(HttpServletRequest request) {
final String uri = request.getRequestURI();
@@ -54,8 +54,8 @@ public class SecurityInterceptor implements HandlerInterceptor {
return false;
}
for (String permit : this.securityProperties.getPermit()) {
- if(uri.startsWith(permit)) {
- log.debug("授权成功(公共请求):{}-{}", uri, permit);
+ if(StringUtils.startsWith(uri, permit)) {
+ log.debug("授权成功(许可请求):{}-{}", uri, permit);
return true;
}
}
@@ -73,11 +73,10 @@ public class SecurityInterceptor implements HandlerInterceptor {
if(StringUtils.isEmpty(authorization)) {
return false;
}
- final int index = authorization.indexOf(' ');
- if(index < 0 || !authorization.substring(0, index).equalsIgnoreCase(SecurityProperties.BASIC)) {
+ if(!StringUtils.startsWithIgnoreCase(authorization, SecurityProperties.BASIC)) {
return false;
}
- authorization = authorization.substring(index).strip();
+ authorization = authorization.substring(SecurityProperties.BASIC.length()).strip();
authorization = new String(Base64.getDecoder().decode(authorization));
if(!authorization.equals(this.securityProperties.getAuthorization())) {
return false;
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/message/Header.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/model/Header.java
similarity index 73%
rename from taoyao-signal/src/main/java/com/acgist/taoyao/signal/message/Header.java
rename to taoyao-boot/src/main/java/com/acgist/taoyao/boot/model/Header.java
index 930b3c5..0ad4867 100644
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/message/Header.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/model/Header.java
@@ -1,4 +1,4 @@
-package com.acgist.taoyao.signal.message;
+package com.acgist.taoyao.boot.model;
import java.io.Serializable;
@@ -23,16 +23,20 @@ public class Header implements Serializable {
private static final long serialVersionUID = 1L;
/**
- * 信令来源
+ * 信令版本
+ */
+ private String v;
+ /**
+ * 请求标识
+ */
+ private Long id;
+ /**
+ * 终端标识
*/
private String sn;
/**
- * 事件标识
+ * 协议标识
*/
- private String event;
- /**
- * 信令版本
- */
- private String version;
-
+ private Integer pid;
+
}
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/model/Message.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/model/Message.java
index 9979df6..ceeefd4 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/model/Message.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/model/Message.java
@@ -7,61 +7,88 @@ import org.apache.commons.lang3.StringUtils;
import com.acgist.taoyao.boot.utils.JSONUtils;
import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
import lombok.Getter;
+import lombok.NoArgsConstructor;
import lombok.Setter;
/**
- * 响应消息
+ * 消息
*
* @author acgist
- *
- * @param 消息类型
*/
@Getter
@Setter
-@Schema(name = "响应消息", description = "HTTP响应消息")
-public class Message implements Serializable {
+@Schema(name = "消息", description = "请求响应消息")
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class Message implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 响应编码
*/
- @Schema(name = "响应编码", description = "0000表示成功其他都是失败")
+ @Schema(name = "响应编码", description = "响应消息标识响应状态")
private String code;
/**
* 响应描述
*/
- @Schema(name = "响应描述", description = "响应编码描述")
+ @Schema(name = "响应描述", description = "响应消息描述响应编码")
private String message;
/**
- * 响应内容
+ * 请求响应头部
*/
- @Schema(name = "响应内容", description = "响应内容")
- private T body;
+ @Schema(name = "请求响应头部", description = "请求响应头部")
+ private Header header;
+ /**
+ * 请求响应主体
+ */
+ @Schema(name = "请求响应主体", description = "请求响应主体")
+ private Object body;
+
+ /**
+ * @param code 状态编码
+ *
+ * @return this
+ */
+ public Message setCode(MessageCode code) {
+ this.code = code.getCode();
+ this.message = code.getMessage();
+ return this;
+ }
+
+ /**
+ * @param code 状态编码
+ * @param message
+ *
+ * @return this
+ */
+ public Message setCode(MessageCode code, String message) {
+ if(StringUtils.isEmpty(message)) {
+ message = code.getMessage();
+ }
+ this.code = code.getCode();
+ this.message = message;
+ return this;
+ }
/**
- * 成功消息
- *
- * @param 消息类型
- *
* @return 成功消息
*/
- public static final Message success() {
+ public static final Message success() {
return success(null);
}
/**
- * 成功消息
- *
- * @param 消息类型
- *
- * @param body 消息内容
+ * @param body 主体
*
* @return 成功消息
*/
- public static final Message success(T body) {
- final Message message = new Message<>();
+ public static final Message success(Object body) {
+ final Message message = new Message();
message.code = MessageCode.CODE_0000.getCode();
message.message = MessageCode.CODE_0000.getMessage();
message.body = body;
@@ -69,94 +96,65 @@ public class Message implements Serializable {
}
/**
- * 错误消息
- *
- * @param 消息类型
- *
* @return 错误消息
*/
- public static final Message fail() {
- return fail(MessageCode.CODE_9999);
+ public static final Message fail() {
+ return fail(null, null, null);
}
/**
- * 错误消息
- *
- * @param 消息类型
- *
- * @param message 消息内容
+ * @param message 主体
*
* @return 错误消息
*/
- public static final Message fail(String message) {
- return fail(MessageCode.CODE_9999, message);
+ public static final Message fail(String message) {
+ return fail(null, message, null);
}
/**
- * 错误消息
- *
- * @param 消息类型
- *
- * @param code 错误编码
+ * @param code 响应编码
*
* @return 错误消息
*/
- public static final Message fail(MessageCode code) {
- return fail(code, null);
+ public static final Message fail(MessageCode code) {
+ return fail(code, null, null);
}
/**
- * 错误消息
- *
- * @param 消息类型
- *
- * @param code 错误编码
- * @param message 错误描述
+ * @param code 响应编码
+ * @param message 响应描述
*
* @return 错误消息
*/
- public static final Message fail(MessageCode code, String message) {
- final Message failMessage = new Message<>();
- failMessage.code = code.getCode();
- if (StringUtils.isEmpty(message)) {
- failMessage.message = code.getMessage();
- } else {
- failMessage.message = message;
+ public static final Message fail(MessageCode code, String message) {
+ return fail(code, message, null);
+ }
+
+ /**
+ * @param code 响应编码
+ * @param body 主体
+ *
+ * @return 错误消息
+ */
+ public static final Message fail(MessageCode code, Object body) {
+ return fail(code, null, body);
+ }
+
+ /**
+ * @param code 响应编码
+ * @param message 响应描述
+ * @param body 主体
+ *
+ * @return 错误消息
+ */
+ public static final Message fail(MessageCode code, String message, Object body) {
+ if(code == null) {
+ code = MessageCode.CODE_9999;
}
- return failMessage;
- }
-
- /**
- * 错误消息
- *
- * @param 消息类型
- *
- * @param code 错误编码
- * @param body 消息内容
- *
- * @return 错误消息
- */
- public static final Message fail(MessageCode code, T body) {
- final Message message = new Message<>();
- message.code = code.getCode();
- message.message = code.getMessage();
- message.body = body;
- return message;
- }
-
- /**
- * 错误消息
- *
- * @param 消息类型
- *
- * @param code 错误编码
- * @param message 错误描述
- * @param body 消息内容
- *
- * @return 错误消息
- */
- public static final Message fail(MessageCode code, String message, T body) {
- final Message failMessage = new Message<>();
+ if (StringUtils.isEmpty(message)) {
+ message = code.getMessage();
+ }
+ final Message failMessage = new Message();
failMessage.code = code.getCode();
failMessage.message = message;
failMessage.body = body;
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/service/IdService.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/service/IdService.java
index 4979457..f81a533 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/service/IdService.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/service/IdService.java
@@ -1,17 +1,17 @@
package com.acgist.taoyao.boot.service;
/**
- * ID生成
+ * ID
*
* @author acgist
*/
public interface IdService {
/**
- * 生成十八位的ID:YYMMddHHmmss + sn + xxxx
+ * 生成十九位的ID:YYMMddHHmmss(12) + sn(1) + xxxxxx(6)
*
* @return ID
*/
- Long id();
+ long id();
}
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/service/impl/IdServiceImpl.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/service/impl/IdServiceImpl.java
index 3a976f1..155e7ea 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/service/impl/IdServiceImpl.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/service/impl/IdServiceImpl.java
@@ -1,5 +1,46 @@
package com.acgist.taoyao.boot.service.impl;
-public class IdServiceImpl {
+import java.time.LocalDateTime;
+import org.springframework.beans.factory.annotation.Value;
+
+import com.acgist.taoyao.boot.service.IdService;
+
+public class IdServiceImpl implements IdService {
+
+ /**
+ * 机器序号
+ */
+ @Value("${taoyao.sn:0}")
+ private int sn = 9;
+ /**
+ * 当前索引
+ */
+ private int index;
+ /**
+ * 最大索引
+ */
+ private static final int MAX_INDEX = 999999;
+
+ @Override
+ public long id() {
+ synchronized (this) {
+ if (++this.index > MAX_INDEX) {
+ this.index = 0;
+ }
+ }
+ final LocalDateTime time = LocalDateTime.now();
+ return
+ 100000000000000000L * (time.getYear() % 100) +
+ 1000000000000000L * time.getMonthValue() +
+ 10000000000000L * time.getDayOfMonth() +
+ 100000000000L * time.getHour() +
+ 1000000000L * time.getMinute() +
+ 10000000L * time.getSecond() +
+ // 机器序号一位
+ 1000000L * this.sn +
+ // 每秒并发数量
+ this.index;
+ }
+
}
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/DateUtils.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/DateUtils.java
index e610143..650e04c 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/DateUtils.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/DateUtils.java
@@ -6,15 +6,13 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
-import com.acgist.taoyao.boot.config.FormatStyle.DateStyle;
-import com.acgist.taoyao.boot.config.FormatStyle.DateTimeStyle;
-import com.acgist.taoyao.boot.config.FormatStyle.TimeStyle;
-
+import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
/**
@@ -28,6 +26,125 @@ public final class DateUtils {
private DateUtils() {
}
+ /**
+ * 默认日期格式
+ */
+ public static final String YYYY_MM_DD_HH24_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+ /**
+ * 日期时间
+ *
+ * @author acgist
+ */
+ @Getter
+ public static enum DateTimeStyle {
+
+ // YYYY
+ YYYYMMDD_HH24_MM("yyyyMMdd HH:mm"),
+ YYYY_MM_DD_HH24_MM("yyyy-MM-dd HH:mm"),
+ YYYYMMDDHH24MMSS("yyyyMMddHHmmss"),
+ YYYYMMDDHH24MMSSSSS("yyyyMMddHHmmssSSS"),
+ YYYYMMDD_HH24_MM_SS("yyyyMMdd HH:mm:ss"),
+ YYYYMMDD_HH24_MM_SS_SSS("yyyyMMdd HH:mm:ss.SSS"),
+ YYYY_MM_DD_HH24_MM_SS("yyyy-MM-dd HH:mm:ss"),
+ YYYY_MM_DD_HH24_MM_SS_SSS("yyyy-MM-dd HH:mm:ss.SSS"),
+ // YY
+ YYMMDD_HH24_MM("yyMMdd HH:mm"),
+ YY_MM_DD_HH24_MM("yy-MM-dd HH:mm"),
+ YYMMDDHH24MMSS("yyMMddHHmmss"),
+ YYMMDDHH24MMSSSSS("yyMMddHHmmssSSS"),
+ YYMMDD_HH24_MM_SS("yyMMdd HH:mm:ss"),
+ YYMMDD_HH24_MM_SS_SSS("yyMMdd HH:mm:ss.SSS"),
+ YY_MM_DD_HH24_MM_SS("yy-MM-dd HH:mm:ss"),
+ YY_MM_DD_HH24_MM_SS_SSS("yy-MM-dd HH:mm:ss.SSS"),
+ // ISO
+ YY_MM_DD_HH24_MM_SS_ISO("yy-MM-dd'T'HH:mm:ss"),
+ YY_MM_DD_HH24_MM_SS_SSS_ISO("yy-MM-dd'T'HH:mm:ss.SSS"),
+ YYYY_MM_DD_HH24_MM_SS_ISO("yyyy-MM-dd'T'HH:mm:ss"),
+ YYYY_MM_DD_HH24_MM_SS_SSS_ISO("yyyy-MM-dd'T'HH:mm:ss.SSS"),
+ // UTC
+ YY_MM_DD_HH24_MM_SS_UTC("yy-MM-dd'T'HH:mm:ss'Z'"),
+ YY_MM_DD_HH24_MM_SS_SSS_UTC("yy-MM-dd'T'HH:mm:ss.SSS'Z'"),
+ YYYY_MM_DD_HH24_MM_SS_UTC("yyyy-MM-dd'T'HH:mm:ss'Z'"),
+ YYYY_MM_DD_HH24_MM_SS_SSS_UTC("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+
+ /**
+ * 格式
+ */
+ private final String format;
+ /**
+ * 格式工具
+ */
+ private final DateTimeFormatter dateTimeFormatter;
+
+ private DateTimeStyle(String format) {
+ this.format = format;
+ this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
+ }
+
+ }
+
+ /**
+ * 时间
+ *
+ * @author acgist
+ */
+ @Getter
+ public static enum TimeStyle {
+
+ HH24("HH"),
+ HH24MM("HHmm"),
+ HH24_MM("HH:mm"),
+ HH24MMSS("HHmmss"),
+ HH24_MM_SS("HH:mm:ss"),
+ HH24MMSSSSS("HHmmssSSS"),
+ HH24_MM_SS_SSS("HH:mm:ss.SSS");
+
+ /**
+ * 格式
+ */
+ private final String format;
+ /**
+ * 格式工具
+ */
+ private final DateTimeFormatter dateTimeFormatter;
+
+ private TimeStyle(String format) {
+ this.format = format;
+ this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
+ }
+
+ }
+
+ /**
+ * 日期
+ *
+ * @author acgist
+ */
+ @Getter
+ public static enum DateStyle {
+
+ YYMMDD("yyMMdd"),
+ YYYYMMDD("yyyyMMdd"),
+ YY_MM_DD("yy-MM-dd"),
+ YYYY_MM_DD("yyyy-MM-dd");
+
+ /**
+ * 格式
+ */
+ private String format;
+ /**
+ * 格式工具
+ */
+ private final DateTimeFormatter dateTimeFormatter;
+
+ private DateStyle(String format) {
+ this.format = format;
+ this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
+ }
+
+ }
+
/**
* 生成时间戳
*
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/ErrorUtils.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/ErrorUtils.java
index 355972a..d66bf26 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/ErrorUtils.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/ErrorUtils.java
@@ -76,7 +76,7 @@ public final class ErrorUtils {
*
* @return 错误信息
*/
- public static final Message message(HttpServletRequest request, HttpServletResponse response) {
+ public static final Message message(HttpServletRequest request, HttpServletResponse response) {
return message(null, request, response);
}
@@ -87,11 +87,11 @@ public final class ErrorUtils {
*
* @return 错误信息
*/
- public static final Message message(Throwable t, HttpServletRequest request, HttpServletResponse response) {
- final Message message;
+ public static final Message message(Throwable t, HttpServletRequest request, HttpServletResponse response) {
+ final Message message;
int status = globalStatus(request, response);
final Object globalError = t == null ? globalError(request) : t;
- final Object rootError = ExceptionUtils.root(globalError);
+ final Object rootError = rootException(globalError);
if(rootError instanceof MessageCodeException) {
// 自定义的异常
final MessageCodeException messageCodeException = (MessageCodeException) rootError;
@@ -220,4 +220,35 @@ public final class ErrorUtils {
return messageCode.getMessage();
}
+ /**
+ * @param t 异常
+ *
+ * @return 原始异常
+ *
+ * @see #rootException(Throwable)
+ */
+ public static final Object rootException(Object t) {
+ if(t instanceof Throwable) {
+ return rootException((Throwable) t);
+ }
+ return t;
+ }
+
+ /**
+ * @param t 异常
+ *
+ * @return 原始异常
+ */
+ public static final Throwable rootException(Throwable t) {
+ Throwable cause = t;
+ do {
+ // 直接返回状态编码异常
+ if(cause instanceof MessageCodeException) {
+ return cause;
+ }
+ } while(cause != null && (cause = cause.getCause()) != null);
+ // 返回原始异常
+ return t;
+ }
+
}
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/ExceptionUtils.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/ExceptionUtils.java
deleted file mode 100644
index 69e4f9b..0000000
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/ExceptionUtils.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.acgist.taoyao.boot.utils;
-
-import com.acgist.taoyao.boot.model.MessageCodeException;
-
-/**
- * 异常工具
- *
- * @author acgist
- */
-public class ExceptionUtils {
-
- /**
- * @param t 异常
- *
- * @return 原始异常
- *
- * @see #root(Throwable)
- */
- public static final Object root(Object t) {
- if(t instanceof Throwable) {
- return ExceptionUtils.root((Throwable) t);
- }
- return t;
- }
-
- /**
- * @param t 异常
- *
- * @return 原始异常
- */
- public static final Throwable root(Throwable t) {
- Throwable cause = t;
- do {
- // 直接返回状态编码异常
- if(cause instanceof MessageCodeException) {
- return cause;
- }
- } while(cause != null && (cause = cause.getCause()) != null);
- // 返回原始异常
- return t;
- }
-
-}
diff --git a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/JSONUtils.java b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/JSONUtils.java
index 3850417..0a3a49b 100644
--- a/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/JSONUtils.java
+++ b/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/JSONUtils.java
@@ -10,10 +10,10 @@ import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
-import com.acgist.taoyao.boot.config.FormatStyle.DateStyle;
-import com.acgist.taoyao.boot.config.FormatStyle.DateTimeStyle;
-import com.acgist.taoyao.boot.config.FormatStyle.TimeStyle;
import com.acgist.taoyao.boot.model.MessageCodeException;
+import com.acgist.taoyao.boot.utils.DateUtils.DateStyle;
+import com.acgist.taoyao.boot.utils.DateUtils.DateTimeStyle;
+import com.acgist.taoyao.boot.utils.DateUtils.TimeStyle;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
diff --git a/taoyao-client/pom.xml b/taoyao-client/pom.xml
deleted file mode 100644
index 1c71edc..0000000
--- a/taoyao-client/pom.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
- 4.0.0
-
-
- com.acgist
- taoyao
- 1.0.0
-
-
- taoyao-client
- jar
-
- taoyao-client
- 终端:帐号(移动端|浏览器)、摄像头
-
-
-
- com.acgist
- taoyao-boot
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
-
\ No newline at end of file
diff --git a/taoyao-nat/README.md b/taoyao-nat/README.md
new file mode 100644
index 0000000..6b4627f
--- /dev/null
+++ b/taoyao-nat/README.md
@@ -0,0 +1,3 @@
+# 内网穿透
+
+请用公共STUN/TURN服务或者自行搭建coturn服务。
diff --git a/taoyao-nat/pom.xml b/taoyao-nat/pom.xml
index f7d5045..c489356 100644
--- a/taoyao-nat/pom.xml
+++ b/taoyao-nat/pom.xml
@@ -14,7 +14,7 @@
jar
taoyao-net
- 内网穿透:STUN/TURN暂不实现(请用公共服务或者搭建coturn服务)
+ 内网穿透:STUN/TURN
diff --git a/taoyao-server/LICENSE b/taoyao-server/LICENSE
new file mode 100644
index 0000000..6e6a6b0
--- /dev/null
+++ b/taoyao-server/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [2022] [acgist]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/taoyao-server/pom.xml b/taoyao-server/pom.xml
index dd84c87..2027045 100644
--- a/taoyao-server/pom.xml
+++ b/taoyao-server/pom.xml
@@ -26,10 +26,6 @@
com.acgist
taoyao-live
-
- com.acgist
- taoyao-client
-
com.acgist
taoyao-signal
diff --git a/taoyao-server/src/main/resources/application.yml b/taoyao-server/src/main/resources/application.yml
index 5a82ead..0ed7da7 100644
--- a/taoyao-server/src/main/resources/application.yml
+++ b/taoyao-server/src/main/resources/application.yml
@@ -48,7 +48,14 @@ taoyao:
version: 1.0.0
description: WebRTC信令服务
webrtc:
- type:
+ type: SFU
+ stun:
+ - stun:stun1.l.google.com:19302
+ - stun:stun2.l.google.com:19302
+ - stun:stun3.l.google.com:19302
+ - stun:stun4.l.google.com:19302
+ - stun:stun.stunprotocol.org:3478
+ turn:
security:
realm: taoyao
permit: /v3/api-docs/,/swagger-ui/,/error
diff --git a/taoyao-signal/README.md b/taoyao-signal/README.md
new file mode 100644
index 0000000..b89b012
--- /dev/null
+++ b/taoyao-signal/README.md
@@ -0,0 +1,43 @@
+# 信令
+
+## 格式
+
+```
+{
+ "header": {
+ "v": "版本",
+ "id": 请求标识,
+ "sn": "设备标识"
+ "pid": 信令标识,
+ },
+ "code": "响应编码",
+ "message": "响应描述",
+ "body": {
+ // 信令参数
+ }
+}
+```
+
+## 系统信令(1000~1999|9999)
+
+### 异常信令(9999)
+
+## 设备信令(2000~2999)
+
+### 注册信令(2000)
+
+```
+{
+"username": "username",
+"password": "password"
+}
+```
+
+### 关闭信令(2001)
+
+### 上线信令(2002)
+
+### 下线信令(2003)
+
+## 房间信令(3000~3999)
+
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/config/SignalAutoConfiguration.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/config/SignalAutoConfiguration.java
index de89481..090ff50 100644
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/config/SignalAutoConfiguration.java
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/config/SignalAutoConfiguration.java
@@ -1,14 +1,11 @@
package com.acgist.taoyao.signal.config;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
-import com.acgist.taoyao.signal.protocol.ProtocolManager;
-import com.acgist.taoyao.signal.session.SessionManager;
-import com.acgist.taoyao.signal.session.websocket.TaoyaoWebSocket;
+import com.acgist.taoyao.signal.session.websocket.WebSocketSignal;
/**
* 信令配置
@@ -18,14 +15,10 @@ import com.acgist.taoyao.signal.session.websocket.TaoyaoWebSocket;
@Configuration
public class SignalAutoConfiguration {
- @Autowired
- private ProtocolManager eventManager;
- @Autowired
- private SessionManager sessionManager;
-
- @Autowired
- public TaoyaoWebSocket taoyaoWebSocket() {
- return new TaoyaoWebSocket(this.eventManager, this.sessionManager);
+ @Bean
+ @ConditionalOnMissingBean
+ public WebSocketSignal webSocketSignal() {
+ return new WebSocketSignal();
}
@Bean
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/Event.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/Event.java
deleted file mode 100644
index c831b01..0000000
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/Event.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.acgist.taoyao.signal.event;
-
-import com.acgist.taoyao.signal.protocol.Protocol;
-
-/**
- * 事件
- * 事件主要负责执行信令
- *
- * @author acgist
- *
- * @see Protocol
- */
-public interface Event {
-
-}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/EventAdapter.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/EventAdapter.java
deleted file mode 100644
index b2630d4..0000000
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/EventAdapter.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.acgist.taoyao.signal.event;
-
-/**
- * 注册事件
- *
- * @author acgist
- */
-public class EventAdapter {
-
-}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/client/RegisterEvent.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/client/RegisterEvent.java
index 9a2f7bd..fa2340b 100644
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/client/RegisterEvent.java
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/event/client/RegisterEvent.java
@@ -1,10 +1,31 @@
package com.acgist.taoyao.signal.event.client;
+import org.springframework.context.ApplicationEvent;
+
+import com.acgist.taoyao.signal.session.ClientSession;
+
+import lombok.Getter;
+import lombok.Setter;
+
/**
- * 注册事件
+ * 终端注册事件
*
* @author acgist
*/
-public class RegisterEvent {
+@Getter
+@Setter
+public class RegisterEvent extends ApplicationEvent {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 会话
+ */
+ private ClientSession session;
+
+ public RegisterEvent(ClientSession session) {
+ super(session);
+ this.session = session;
+ }
}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/listener/ApplicationListenerAdapter.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/listener/ApplicationListenerAdapter.java
new file mode 100644
index 0000000..fc5002f
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/listener/ApplicationListenerAdapter.java
@@ -0,0 +1,21 @@
+package com.acgist.taoyao.signal.listener;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+
+import com.acgist.taoyao.signal.session.ClientSessionManager;
+
+/**
+ * 事件监听
+ *
+ * @param 事件泛型
+ *
+ * @author acgist
+ */
+public abstract class ApplicationListenerAdapter implements ApplicationListener {
+
+ @Autowired
+ protected ClientSessionManager clientSessionManager;
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/listener/client/RegisterListener.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/listener/client/RegisterListener.java
new file mode 100644
index 0000000..4f8d365
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/listener/client/RegisterListener.java
@@ -0,0 +1,38 @@
+package com.acgist.taoyao.signal.listener.client;
+
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.signal.event.client.RegisterEvent;
+import com.acgist.taoyao.signal.listener.ApplicationListenerAdapter;
+import com.acgist.taoyao.signal.protocol.client.OnlineProtocol;
+import com.acgist.taoyao.signal.session.ClientSession;
+
+/**
+ * 终端注册监听
+ *
+ * @author acgist
+ */
+@Component
+public class RegisterListener extends ApplicationListenerAdapter {
+
+ @Autowired
+ private OnlineProtocol onlineProtocol;
+
+ @Async
+ @Override
+ public void onApplicationEvent(RegisterEvent event) {
+ final ClientSession session = event.getSession();
+ if(!session.authorized()) {
+ return;
+ }
+ final Message message = this.onlineProtocol.build();
+ message.setBody(Map.of("sn", session.sn()));
+ this.clientSessionManager.broadcast(message);
+ }
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/message/Message.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/message/Message.java
deleted file mode 100644
index 8012bac..0000000
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/message/Message.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.acgist.taoyao.signal.message;
-
-import java.io.Serializable;
-
-import com.acgist.taoyao.boot.utils.JSONUtils;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * 信令消息
- *
- * @author acgist
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class Message implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * 信令头部
- */
- private Header header;
- /**
- * 信令主体
- */
- private Object body;
-
- @Override
- public String toString() {
- return JSONUtils.toJSON(this);
- }
-
-}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/Protocol.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/Protocol.java
index 2792575..d4ec31a 100644
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/Protocol.java
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/Protocol.java
@@ -1,5 +1,10 @@
package com.acgist.taoyao.signal.protocol;
+import org.springframework.context.ApplicationEvent;
+
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.signal.session.ClientSession;
+
/**
* 信令协议
*
@@ -7,9 +12,33 @@ package com.acgist.taoyao.signal.protocol;
* 2000~2999:终端信令(注册、注销、终端列表)
* 3000~3999:直播信令
* 4000~4999:会议信令
+ * 9999:信令异常
*
* @author acgist
*/
public interface Protocol {
+
+ /**
+ * @return 信令协议标识
+ */
+ Integer protocol();
+ /**
+ * 处理信令消息
+ *
+ * @param sn 终端标识
+ * @param message 信令消息
+ * @param session 会话
+ *
+ * @return 事件
+ */
+ ApplicationEvent execute(String sn, Message message, ClientSession session);
+
+ /**
+ * 创建信令消息
+ *
+ * @return 信令消息
+ */
+ Message build();
+
}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolAdapter.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolAdapter.java
index 1b862e5..8a1f839 100644
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolAdapter.java
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolAdapter.java
@@ -1,5 +1,49 @@
package com.acgist.taoyao.signal.protocol;
-public class ProtocolAdapter {
+import org.springframework.beans.factory.annotation.Autowired;
+import com.acgist.taoyao.boot.config.TaoyaoProperties;
+import com.acgist.taoyao.boot.model.Header;
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.boot.service.IdService;
+
+/**
+ * 信令协议适配器
+ *
+ * @author acgist
+ */
+public abstract class ProtocolAdapter implements Protocol {
+
+ @Autowired
+ private IdService idService;
+ @Autowired
+ protected TaoyaoProperties taoyaoProperties;
+
+ /**
+ * 信令协议标识
+ */
+ protected final Integer protocol;
+
+ protected ProtocolAdapter(Integer protocol) {
+ this.protocol = protocol;
+ }
+
+ @Override
+ public Integer protocol() {
+ return this.protocol;
+ }
+
+ @Override
+ public Message build() {
+ final Header header = Header.builder()
+ .v(this.taoyaoProperties.getVersion())
+ .id(this.idService.id())
+ .pid(this.protocol)
+ .build();
+ final Message message = Message.builder()
+ .header(header)
+ .build();
+ return message;
+ }
+
}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolBodyMapAdapter.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolBodyMapAdapter.java
new file mode 100644
index 0000000..22fb3e6
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolBodyMapAdapter.java
@@ -0,0 +1,44 @@
+package com.acgist.taoyao.signal.protocol;
+
+import java.util.Map;
+
+import org.springframework.context.ApplicationEvent;
+
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.boot.model.MessageCodeException;
+import com.acgist.taoyao.signal.session.ClientSession;
+
+/**
+ * 信令协议Map主体适配器
+ *
+ * @author acgist
+ */
+public abstract class ProtocolBodyMapAdapter extends ProtocolAdapter {
+
+ protected ProtocolBodyMapAdapter(Integer protocol) {
+ super(protocol);
+ }
+
+ @Override
+ public ApplicationEvent execute(String sn, Message message, ClientSession session) {
+ final Object body = message.getBody();
+ if(body instanceof Map, ?> map) {
+ return this.execute(sn, map, message, session);
+ } else {
+ throw MessageCodeException.of("信令主体类型错误:" + message);
+ }
+ }
+
+ /**
+ * 处理信令消息
+ *
+ * @param sn 终端标识
+ * @param body 消息主体
+ * @param message 信令消息
+ * @param session 会话
+ *
+ * @return 事件
+ */
+ public abstract ApplicationEvent execute(String sn, Map, ?> body, Message message, ClientSession session);
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolBodyObjectAdapter.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolBodyObjectAdapter.java
new file mode 100644
index 0000000..c5388e5
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolBodyObjectAdapter.java
@@ -0,0 +1,55 @@
+package com.acgist.taoyao.signal.protocol;
+
+import java.util.Map;
+
+import org.springframework.cglib.beans.BeanMap;
+import org.springframework.context.ApplicationEvent;
+
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.boot.model.MessageCodeException;
+import com.acgist.taoyao.boot.utils.BeanUtils;
+import com.acgist.taoyao.signal.session.ClientSession;
+
+/**
+ * 信令协议对象主体适配器
+ *
+ * @author acgist
+ */
+public abstract class ProtocolBodyObjectAdapter extends ProtocolAdapter {
+
+ /**
+ * 对象类型
+ */
+ private final Class clazz;
+
+ protected ProtocolBodyObjectAdapter(Integer protocol, Class clazz) {
+ super(protocol);
+ this.clazz = clazz;
+ }
+
+ @Override
+ public ApplicationEvent execute(String sn, Message message, ClientSession session) {
+ final Object body = message.getBody();
+ if(body instanceof Map, ?> map) {
+ final T t = BeanUtils.newInstance(this.clazz);
+ final BeanMap beanMap = BeanMap.create(t);
+ beanMap.putAll(map);
+ return this.execute(sn, t, message, session);
+ } else {
+ throw MessageCodeException.of("信令主体类型错误:" + message);
+ }
+ }
+
+ /**
+ * 处理信令消息
+ *
+ * @param sn 终端标识
+ * @param body 消息主体
+ * @param message 信令消息
+ * @param session 会话
+ *
+ * @return 事件
+ */
+ public abstract ApplicationEvent execute(String sn, T body, Message message, ClientSession session);
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolManager.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolManager.java
index baccd61..661470f 100644
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolManager.java
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/ProtocolManager.java
@@ -1,20 +1,98 @@
package com.acgist.taoyao.signal.protocol;
-import javax.websocket.Session;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Service;
+import com.acgist.taoyao.boot.model.Header;
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.boot.model.MessageCodeException;
+import com.acgist.taoyao.boot.utils.JSONUtils;
+import com.acgist.taoyao.signal.protocol.client.RegisterProtocol;
+import com.acgist.taoyao.signal.session.ClientSession;
+import com.acgist.taoyao.signal.session.ClientSessionManager;
+
+import lombok.extern.slf4j.Slf4j;
+
/**
* 协议管理
*
* @author acgist
*/
+@Slf4j
@Service
public class ProtocolManager {
- public void execute(Session session, String message) {
- // TODO Auto-generated method stub
-
+ /**
+ * 协议映射
+ */
+ private Map protocolMapping = new ConcurrentHashMap<>();
+
+ @Autowired
+ private ApplicationContext context;
+ @Autowired
+ private ClientSessionManager clientSessionManager;
+
+ @PostConstruct
+ public void init() {
+ final Map map = this.context.getBeansOfType(Protocol.class);
+ map.forEach((k, v) -> {
+ final Integer protocol = v.protocol();
+ if(this.protocolMapping.containsKey(protocol)) {
+ throw MessageCodeException.of("存在重复信令协议:" + protocol);
+ }
+ log.info("注册信令协议:{}-{}", protocol, k);
+ this.protocolMapping.put(protocol, v);
+ });
+ }
+
+ /**
+ * 执行信令消息
+ *
+ * @param message 信令消息
+ * @param instance 会话实例
+ */
+ public void execute(String message, AutoCloseable instance) {
+ if(StringUtils.isEmpty(message)) {
+ log.warn("消息为空:{}", message);
+ return;
+ }
+ final Message value = JSONUtils.toJava(message, Message.class);
+ final Header header = value.getHeader();
+ if(header == null) {
+ log.warn("消息格式错误(没有头部):{}", message);
+ return;
+ }
+ final String sn = header.getSn();
+ final Integer pid = header.getPid();
+ if(sn == null || pid == null) {
+ log.warn("消息格式错误(没有SN或者PID):{}", message);
+ return;
+ }
+ final Protocol protocol = this.protocolMapping.get(pid);
+ if(protocol == null) {
+ log.warn("不支持的信令协议:{}", message);
+ return;
+ }
+ ApplicationEvent event = null;
+ final ClientSession session = this.clientSessionManager.session(instance);
+ if(session != null && protocol instanceof RegisterProtocol) {
+ event = protocol.execute(sn, value, session);
+ } else if(session != null) {
+ event = protocol.execute(sn, value, session);
+ } else {
+ log.warn("会话没有权限:{}", message);
+ }
+ if(event != null) {
+ this.context.publishEvent(event);
+ }
}
}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/CloseProtocol.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/CloseProtocol.java
new file mode 100644
index 0000000..7899054
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/CloseProtocol.java
@@ -0,0 +1,33 @@
+package com.acgist.taoyao.signal.protocol.client;
+
+import org.springframework.context.ApplicationEvent;
+import org.springframework.stereotype.Component;
+
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.signal.protocol.ProtocolAdapter;
+import com.acgist.taoyao.signal.session.ClientSession;
+
+/**
+ * 关闭信令协议
+ *
+ * @author acgist
+ */
+@Component
+public class CloseProtocol extends ProtocolAdapter {
+
+ /**
+ * 信令协议标识
+ */
+ public static final Integer PID = 2001;
+
+ public CloseProtocol() {
+ super(PID);
+ }
+
+ @Override
+ public ApplicationEvent execute(String sn, Message message, ClientSession session) {
+ // TODO
+ return null;
+ }
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/OfflineProtocol.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/OfflineProtocol.java
new file mode 100644
index 0000000..16ab85c
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/OfflineProtocol.java
@@ -0,0 +1,10 @@
+package com.acgist.taoyao.signal.protocol.client;
+
+public class OfflineProtocol {
+
+ /**
+ * 信令协议标识
+ */
+ public static final Integer PID = 2003;
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/OnlineProtocol.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/OnlineProtocol.java
new file mode 100644
index 0000000..0e911d0
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/OnlineProtocol.java
@@ -0,0 +1,32 @@
+package com.acgist.taoyao.signal.protocol.client;
+
+import org.springframework.context.ApplicationEvent;
+import org.springframework.stereotype.Component;
+
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.signal.protocol.ProtocolAdapter;
+import com.acgist.taoyao.signal.session.ClientSession;
+
+/**
+ * 上线信令协议
+ *
+ * @author acgist
+ */
+@Component
+public class OnlineProtocol extends ProtocolAdapter {
+
+ /**
+ * 信令协议标识
+ */
+ public static final Integer PID = 2002;
+
+ public OnlineProtocol() {
+ super(PID);
+ }
+
+ @Override
+ public ApplicationEvent execute(String sn, Message message, ClientSession session) {
+ return null;
+ }
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/RegisterProtocol.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/RegisterProtocol.java
new file mode 100644
index 0000000..ace1987
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/client/RegisterProtocol.java
@@ -0,0 +1,54 @@
+package com.acgist.taoyao.signal.protocol.client;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.stereotype.Component;
+
+import com.acgist.taoyao.boot.config.SecurityProperties;
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.boot.model.MessageCode;
+import com.acgist.taoyao.signal.event.client.RegisterEvent;
+import com.acgist.taoyao.signal.protocol.ProtocolBodyMapAdapter;
+import com.acgist.taoyao.signal.session.ClientSession;
+
+/**
+ * 注册信令协议
+ *
+ * @author acgist
+ */
+@Component
+public class RegisterProtocol extends ProtocolBodyMapAdapter {
+
+ /**
+ * 信令协议标识
+ */
+ public static final Integer PID = 2000;
+
+ @Autowired
+ private SecurityProperties securityProperties;
+
+ public RegisterProtocol() {
+ super(PID);
+ }
+
+ @Override
+ public ApplicationEvent execute(String sn, Map, ?> body, Message message, ClientSession session) {
+ final String username = (String) body.get("username");
+ final String password = (String) body.get("password");
+ if(
+ StringUtils.equals(this.securityProperties.getUsername(), username) &&
+ StringUtils.equals(this.securityProperties.getPassword(), password)
+ ) {
+ session.authorize(sn);
+ message.setCode(MessageCode.CODE_0000);
+ } else {
+ message.setCode(MessageCode.CODE_3401);
+ }
+ session.push(message);
+ return new RegisterEvent(session);
+ }
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/system/ErrorProtocol.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/system/ErrorProtocol.java
new file mode 100644
index 0000000..6449219
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/system/ErrorProtocol.java
@@ -0,0 +1,32 @@
+package com.acgist.taoyao.signal.protocol.system;
+
+import org.springframework.context.ApplicationEvent;
+import org.springframework.stereotype.Component;
+
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.signal.protocol.ProtocolAdapter;
+import com.acgist.taoyao.signal.session.ClientSession;
+
+/**
+ * 异常信令协议
+ *
+ * @author acgist
+ */
+@Component
+public class ErrorProtocol extends ProtocolAdapter {
+
+ /**
+ * 信令协议标识
+ */
+ public static final Integer PID = 9999;
+
+ public ErrorProtocol() {
+ super(PID);
+ }
+
+ @Override
+ public ApplicationEvent execute(String sn, Message message, ClientSession session) {
+ return null;
+ }
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSession.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSession.java
new file mode 100644
index 0000000..83a83c7
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSession.java
@@ -0,0 +1,66 @@
+package com.acgist.taoyao.signal.session;
+
+import com.acgist.taoyao.boot.model.Message;
+
+/**
+ * 会话
+ *
+ * @author acgist
+ *
+ * @param 会话类型
+ */
+public interface ClientSession extends AutoCloseable {
+
+ /**
+ * @return 终端标识
+ */
+ String sn();
+
+ /**
+ * 推送消息
+ *
+ * @param message 消息
+ */
+ void push(Message message);
+
+ /**
+ * @param timeout 超时时间
+ *
+ * @return 是否超时会话
+ */
+ boolean timeout(long timeout);
+
+ /**
+ * 设置授权
+ *
+ * @param sn 重点标识
+ */
+ void authorize(String sn);
+
+ /**
+ * @return 是否授权
+ */
+ boolean authorized();
+
+ /**
+ * @param sn 终端标识
+ *
+ * @return 终端标识是否匹配
+ */
+ boolean matchSn(String sn);
+
+ /**
+ * @param sn 终端标识
+ *
+ * @return 终端标识是否匹配失败
+ */
+ boolean matchNoneSn(String sn);
+
+ /**
+ * @param instance 会话实例
+ *
+ * @return 会话实例是否匹配
+ */
+ boolean matchInstance(M instance);
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionAdapter.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionAdapter.java
new file mode 100644
index 0000000..c3e5824
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionAdapter.java
@@ -0,0 +1,88 @@
+package com.acgist.taoyao.signal.session;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 会话适配器
+ *
+ * @author acgist
+ */
+public abstract class ClientSessionAdapter implements ClientSession {
+
+ /**
+ * 终端标识
+ */
+ protected String sn;
+ /**
+ * 进入时间
+ */
+ protected final long time;
+ /**
+ * 会话实例
+ */
+ protected final T instance;
+ /**
+ * 是否授权
+ */
+ protected boolean authorized;
+
+ protected ClientSessionAdapter(T instance) {
+ this.time = System.currentTimeMillis();
+ this.instance = instance;
+ this.authorized = false;
+ }
+
+ @Override
+ public String sn() {
+ return this.sn;
+ }
+
+ @Override
+ public boolean timeout(long timeout) {
+ return !(this.authorized && System.currentTimeMillis() - this.time <= timeout);
+ }
+
+ @Override
+ public void authorize(String sn) {
+ this.sn = sn;
+ this.authorized = true;
+ }
+
+ @Override
+ public boolean authorized() {
+ return this.authorized;
+ }
+
+ @Override
+ public boolean matchSn(String sn) {
+ return StringUtils.equals(sn, this.sn);
+ }
+
+ @Override
+ public boolean matchNoneSn(String sn) {
+ return !StringUtils.equals(sn, this.sn);
+ }
+
+ @Override
+ public boolean matchInstance(I instance) {
+ return instance == this.instance;
+ }
+
+ @Override
+ public void close() throws Exception {
+ try {
+ this.instance.close();
+ } finally {
+ // TODO:退出房间
+ // TODO:退出帐号
+ }
+ }
+
+ /**
+ * @return 会话实例
+ */
+ public T instance() {
+ return this.instance;
+ }
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionManager.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionManager.java
new file mode 100644
index 0000000..24a39e4
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionManager.java
@@ -0,0 +1,129 @@
+package com.acgist.taoyao.signal.session;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import com.acgist.taoyao.boot.config.TaoyaoProperties;
+import com.acgist.taoyao.boot.model.Message;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 会话管理
+ *
+ * @author acgist
+ */
+@Slf4j
+@Service
+public class ClientSessionManager {
+
+ @Autowired
+ private TaoyaoProperties taoyaoProperties;
+
+ /**
+ * 会话列表
+ */
+ private List sessions = new CopyOnWriteArrayList<>();
+
+ @Scheduled(cron = "${taoyao.scheduled.session:0 * * * * ?}")
+ public void scheduled() {
+ this.closeTimeoutSession();
+ }
+
+ /**
+ * @param session 会话
+ */
+ public void open(ClientSession session) {
+ this.sessions.add(session);
+ }
+
+ /**
+ * @param instance 会话实例
+ *
+ * @return 会话
+ */
+ public ClientSession session(AutoCloseable instance) {
+ return this.sessions.stream()
+ .filter(v -> v.matchInstance(instance))
+ .findFirst()
+ .orElse(null);
+ }
+
+ /**
+ * 单播消息
+ *
+ * @param to 接收终端
+ * @param message 消息
+ */
+ public void unicast(String to, Message message) {
+ this.sessions.stream().filter(v -> v.matchSn(to)).forEach(v -> {
+ message.getHeader().setSn(v.sn());
+ v.push(message);
+ });
+ }
+
+ /**
+ * 广播消息
+ *
+ * @param message 消息
+ */
+ public void broadcast(Message message) {
+ this.sessions.forEach(v -> {
+ message.getHeader().setSn(v.sn());
+ v.push(message);
+ });
+ }
+
+ /**
+ * 广播消息
+ *
+ * @param from 发送终端
+ * @param message 消息
+ */
+ public void broadcast(String from, Message message) {
+ this.sessions.stream().filter(v -> v.matchNoneSn(from)).forEach(v -> {
+ message.getHeader().setSn(v.sn());
+ v.push(message);
+ });
+ }
+
+ /**
+ * 关闭会话
+ *
+ * @param instance 会话实例
+ */
+ public void close(AutoCloseable instance) {
+ final ClientSession session = this.session(instance);
+ try {
+ if(session != null) {
+ session.close();
+ } else {
+ instance.close();
+ }
+ } catch (Exception e) {
+ log.error("关闭会话异常", e);
+ } finally {
+ if(session != null) {
+ this.sessions.remove(session);
+ }
+ }
+ }
+
+ /**
+ * 定时关闭超时会话
+ */
+ private void closeTimeoutSession() {
+ log.debug("定时关闭超时会话");
+ this.sessions.stream()
+ .filter(v -> v.timeout(this.taoyaoProperties.getTimeout()))
+ .forEach(v -> {
+ log.debug("关闭超时会话:{}", v);
+ this.close(v);
+ });
+ }
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionStatus.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionStatus.java
new file mode 100644
index 0000000..e9f78a5
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/ClientSessionStatus.java
@@ -0,0 +1,12 @@
+package com.acgist.taoyao.signal.session;
+
+/**
+ * 终端状态
+ *
+ * @author acgist
+ */
+public class ClientSessionStatus {
+
+
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/Session.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/Session.java
deleted file mode 100644
index 4133704..0000000
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/Session.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.acgist.taoyao.signal.session;
-
-public interface Session {
-
-}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/SessionAdapter.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/SessionAdapter.java
deleted file mode 100644
index 2f514a2..0000000
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/SessionAdapter.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.acgist.taoyao.signal.session;
-
-public class SessionAdapter {
-
-}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/SessionManager.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/SessionManager.java
deleted file mode 100644
index 1cc52bf..0000000
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/SessionManager.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package com.acgist.taoyao.signal.session;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import javax.websocket.Session;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Service;
-
-import com.acgist.taoyao.boot.config.TaoyaoProperties;
-import com.acgist.taoyao.signal.message.Message;
-import com.acgist.taoyao.signal.session.websocket.SessionWrapper;
-
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * 会话管理
- *
- * @author acgist
- */
-@Slf4j
-@Service
-public class SessionManager {
-
- @Autowired
- private TaoyaoProperties taoyaoProperties;
-
- /**
- * 没有授权会话
- */
- private Map unauthorized = new ConcurrentHashMap<>();
- /**
- * 授权会话列表
- */
- private List sessions = new CopyOnWriteArrayList<>();
-
- @Scheduled(cron = "${taoyao.scheduled.session:0 * * * * ?}")
- public void scheduled() {
- this.closeTimeoutSession();
- }
-
- /**
- * 存入没有授权会话,定时清除没有授权会话。
- *
- * @param session 会话
- */
- public void open(Session session) {
- this.unauthorized.put(session, System.currentTimeMillis());
- }
-
- /**
- * @param session 会话
- *
- * @return 会话包装器
- */
- public SessionWrapper getWrapper(Session session) {
- return this.sessions.stream()
- .filter(v -> v.matchSession(session))
- .findFirst()
- .orElse(null);
- }
-
- /**
- * 认证会话
- *
- * @param sn 终端标识
- * @param session 会话
- */
- public void authorized(String sn, Session session) {
- this.unauthorized.remove(session);
- final SessionWrapper wrapper = new SessionWrapper();
- wrapper.setSn(sn);
- wrapper.setSession(session);
- this.sessions.add(wrapper);
- }
-
- /**
- * 单播消息
- *
- * @param to 接收终端
- * @param message 消息
- */
- public void unicast(String to, Message message) {
- this.sessions.stream().filter(v -> v.matchSn(to)).forEach(v -> {
- message.getHeader().setSn(v.getSn());
- message.getHeader().setVersion(this.taoyaoProperties.getVersion());
- v.send(message);
- });
- }
-
- /**
- * 广播消息
- *
- * @param message 消息
- */
- public void broadcast(Message message) {
- this.sessions.forEach(v -> {
- message.getHeader().setSn(v.getSn());
- message.getHeader().setVersion(this.taoyaoProperties.getVersion());
- v.send(message);
- });
- }
-
- /**
- * 广播消息
- *
- * @param from 发送终端
- * @param message 消息
- */
- public void broadcast(String from, Message message) {
- this.sessions.stream().filter(v -> v.matchNoneSn(from)).forEach(v -> {
- message.getHeader().setSn(v.getSn());
- message.getHeader().setVersion(this.taoyaoProperties.getVersion());
- v.send(message);
- });
- }
-
- /**
- * 关闭会话
- *
- * @param session 会话
- */
- public void close(Session session) {
- final SessionWrapper wrapper = this.getWrapper(session);
- if(wrapper != null) {
- // TODO:退出房间
- // TODO:退出帐号
- // 移除
- this.sessions.remove(wrapper);
- }
- try {
- session.close();
- } catch (IOException e) {
- log.error("关闭会话异常", e);
- }
- }
-
- /**
- * 定时关闭超时会话
- */
- private void closeTimeoutSession() {
- log.debug("定时关闭超时会话");
- final Iterator> iterator = this.unauthorized.entrySet().iterator();
- while(iterator.hasNext()) {
- final Entry next = iterator.next();
- final Long last = next.getValue();
- final Session session = next.getKey();
- if(System.currentTimeMillis() - last > this.taoyaoProperties.getTimeout()) {
- log.debug("关闭超时会话:{}", session);
- this.close(session);
- }
- }
- }
-
-}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/socket/TaoyaoSocket.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/socket/SocketSignal.java
similarity index 77%
rename from taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/socket/TaoyaoSocket.java
rename to taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/socket/SocketSignal.java
index 10c2ec3..02f40d2 100644
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/socket/TaoyaoSocket.java
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/socket/SocketSignal.java
@@ -5,6 +5,6 @@ package com.acgist.taoyao.signal.session.socket;
*
* @author acgist
*/
-public class TaoyaoSocket {
+public class SocketSignal {
}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/SessionWrapper.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/SessionWrapper.java
deleted file mode 100644
index f347f3d..0000000
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/SessionWrapper.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.acgist.taoyao.signal.session.websocket;
-
-import java.io.IOException;
-
-import javax.websocket.Session;
-
-import com.acgist.taoyao.signal.message.Message;
-
-import lombok.Getter;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * 会话包装器
- *
- * @author acgist
- */
-@Slf4j
-@Getter
-@Setter
-public class SessionWrapper {
-
- /**
- * 终端帐号
- */
- private String sn;
- /**
- * 会话
- */
- private Session session;
-
- /**
- * 发送消息
- *
- * @param message 消息
- */
- public void send(Message message) {
- try {
- this.session.getBasicRemote().sendText(message.toString());
- } catch (IOException e) {
- log.error("WebSocket发送消息异常:{}", message, e);
- }
- }
-
- /**
- * @param sn 终端编号
- *
- * @return 是否匹配成功
- */
- public boolean matchSn(String sn) {
- return this.sn != null && this.sn.equals(sn);
- }
-
- /**
- * @param sn 终端编号
- *
- * @return 是否匹配失败
- */
- public boolean matchNoneSn(String sn) {
- return this.sn != null && !this.sn.equals(sn);
- }
-
- /**
- * @param session 会话
- *
- * @return 是否匹配成功
- */
- public boolean matchSession(Session session) {
- return this.session != null && this.session.equals(session);
- }
-
-}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/TaoyaoWebSocket.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/TaoyaoWebSocket.java
deleted file mode 100644
index ce2ace5..0000000
--- a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/TaoyaoWebSocket.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.acgist.taoyao.signal.session.websocket;
-
-import javax.websocket.OnClose;
-import javax.websocket.OnError;
-import javax.websocket.OnMessage;
-import javax.websocket.OnOpen;
-import javax.websocket.Session;
-import javax.websocket.server.ServerEndpoint;
-
-import com.acgist.taoyao.signal.protocol.ProtocolManager;
-import com.acgist.taoyao.signal.session.SessionManager;
-
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * WebSocket信令
- *
- * @author acgist
- */
-@Slf4j
-@ServerEndpoint(value = "/taoyao/websocket")
-public class TaoyaoWebSocket {
-
- private ProtocolManager eventManager;
- private SessionManager sessionManager;
-
- public TaoyaoWebSocket(ProtocolManager eventManager, SessionManager sessionManager) {
- this.eventManager = eventManager;
- this.sessionManager = sessionManager;
- }
-
- @OnOpen
- public void open(Session session) {
- log.debug("会话连接:{}", session);
- this.sessionManager.open(session);
- }
-
- @OnMessage
- public void message(Session session, String message) {
- log.debug("会话消息:{}-{}", session, message);
- try {
- this.eventManager.execute(session, message);
- } catch (Exception e) {
- log.error("处理会话消息异常", e);
- }
- }
-
- @OnClose
- public void close(Session session) {
- log.debug("会话关闭:{}", session);
- this.sessionManager.close(session);
- }
-
- @OnError
- public void error(Session session, Throwable e) {
- log.error("会话异常:{}", session, e);
- this.close(session);
- }
-
-}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/WebSocketSession.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/WebSocketSession.java
new file mode 100644
index 0000000..6212d29
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/WebSocketSession.java
@@ -0,0 +1,37 @@
+package com.acgist.taoyao.signal.session.websocket;
+
+import java.io.IOException;
+
+import javax.websocket.Session;
+
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.signal.session.ClientSessionAdapter;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * WebSocket会话
+ *
+ * @author acgist
+ */
+@Slf4j
+@Getter
+@Setter
+public class WebSocketSession extends ClientSessionAdapter {
+
+ public WebSocketSession(Session instance) {
+ super(instance);
+ }
+
+ @Override
+ public void push(Message message) {
+ try {
+ this.instance.getBasicRemote().sendText(message.toString());
+ } catch (IOException e) {
+ log.error("WebSocket发送消息异常:{}", message, e);
+ }
+ }
+
+}
diff --git a/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/WebSocketSignal.java b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/WebSocketSignal.java
new file mode 100644
index 0000000..3c9a2a9
--- /dev/null
+++ b/taoyao-signal/src/main/java/com/acgist/taoyao/signal/session/websocket/WebSocketSignal.java
@@ -0,0 +1,94 @@
+package com.acgist.taoyao.signal.session.websocket;
+
+import java.io.IOException;
+
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.ServerEndpoint;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.acgist.taoyao.boot.model.Message;
+import com.acgist.taoyao.signal.protocol.ProtocolManager;
+import com.acgist.taoyao.signal.protocol.system.ErrorProtocol;
+import com.acgist.taoyao.signal.session.ClientSessionManager;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * WebSocket信令
+ *
+ * @author acgist
+ */
+@Slf4j
+@ServerEndpoint(value = "/websocket.signal")
+public class WebSocketSignal {
+
+ private static ErrorProtocol errorProtocol;
+ private static ProtocolManager protocolManager;
+ private static ClientSessionManager clientSessionManager;
+
+ @OnOpen
+ public void open(Session session) {
+ log.debug("会话连接:{}", session);
+ WebSocketSignal.clientSessionManager.open(new WebSocketSession(session));
+ }
+
+ @OnMessage
+ public void message(Session session, String message) {
+ log.debug("会话消息:{}-{}", session, message);
+ try {
+ WebSocketSignal.protocolManager.execute(message, session);
+ } catch (Exception e) {
+ log.error("处理会话消息异常", e);
+ final Message errorMessage = WebSocketSignal.errorProtocol.build();
+ errorMessage.setBody(e.getMessage());
+ this.push(session, errorMessage);
+ }
+ }
+
+ @OnClose
+ public void close(Session session) {
+ log.debug("会话关闭:{}", session);
+ WebSocketSignal.clientSessionManager.close(session);
+ }
+
+ @OnError
+ public void error(Session session, Throwable e) {
+ log.error("会话异常:{}", session, e);
+ this.close(session);
+ }
+
+ /**
+ * 推送消息
+ *
+ * @param session 会话
+ * @param message 消息
+ */
+ private void push(Session session, Message message) {
+ try {
+ session.getBasicRemote().sendText(message.toString());
+ } catch (IOException e) {
+ log.error("推送消息异常:{}", message, e);
+ }
+ }
+
+ @Autowired
+ public void setErrorProtocol(ErrorProtocol errorProtocol) {
+ WebSocketSignal.errorProtocol = errorProtocol;
+ }
+
+ @Autowired
+ public void setProtocolManager(ProtocolManager protocolManager) {
+ WebSocketSignal.protocolManager = protocolManager;
+ }
+
+ @Autowired
+ public void setClientSessionManager(ClientSessionManager clientSessionManager) {
+ WebSocketSignal.clientSessionManager = clientSessionManager;
+ }
+
+}
diff --git a/taoyao-webrtc/pom.xml b/taoyao-webrtc/pom.xml
index a47ee55..7eb2e3d 100644
--- a/taoyao-webrtc/pom.xml
+++ b/taoyao-webrtc/pom.xml
@@ -17,9 +17,9 @@
WebRTC模块
+ taoyao-webrtc-jni
taoyao-webrtc-sfu
taoyao-webrtc-mcu
- taoyao-webrtc-mix
taoyao-webrtc-mesh
diff --git a/taoyao-webrtc/taoyao-webrtc-mix/pom.xml b/taoyao-webrtc/taoyao-webrtc-jni/pom.xml
similarity index 65%
rename from taoyao-webrtc/taoyao-webrtc-mix/pom.xml
rename to taoyao-webrtc/taoyao-webrtc-jni/pom.xml
index fabcb15..a81f0f8 100644
--- a/taoyao-webrtc/taoyao-webrtc-mix/pom.xml
+++ b/taoyao-webrtc/taoyao-webrtc-jni/pom.xml
@@ -10,19 +10,13 @@
1.0.0
- taoyao-webrtc-mix
+ taoyao-webrtc-jni
jar
- taoyao-webrtc-mix
- MCU/SFU混合媒体服务
+ taoyao-webrtc-jni
+ WebRTC JNI:WebRTC本地接口
-
\ No newline at end of file
diff --git a/taoyao-webrtc/taoyao-webrtc-mcu/pom.xml b/taoyao-webrtc/taoyao-webrtc-mcu/pom.xml
index aa188ec..47581d4 100644
--- a/taoyao-webrtc/taoyao-webrtc-mcu/pom.xml
+++ b/taoyao-webrtc/taoyao-webrtc-mcu/pom.xml
@@ -19,7 +19,7 @@
com.acgist
- taoyao-webrtc-mix
+ taoyao-webrtc-jni
diff --git a/taoyao-webrtc/taoyao-webrtc-sfu/pom.xml b/taoyao-webrtc/taoyao-webrtc-sfu/pom.xml
index 6976fa9..a3ad050 100644
--- a/taoyao-webrtc/taoyao-webrtc-sfu/pom.xml
+++ b/taoyao-webrtc/taoyao-webrtc-sfu/pom.xml
@@ -19,7 +19,7 @@
com.acgist
- taoyao-webrtc-mix
+ taoyao-webrtc-jni