[+] 整体架构调整

生产者接入完成
媒体作为信令服务的终端注册
This commit is contained in:
acgist
2023-02-25 13:31:57 +08:00
parent 6358255458
commit 129c36ed80
156 changed files with 3659 additions and 2817 deletions

View File

@@ -1,13 +1,17 @@
package com.acgist.taoyao.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.acgist.taoyao.boot.config.SecurityProperties;
import com.acgist.taoyao.boot.config.TaoyaoProperties;
import com.acgist.taoyao.interceptor.SecurityInterceptor;
import com.acgist.taoyao.interceptor.SlowInterceptor;
import com.acgist.taoyao.signal.service.SecurityService;
import com.acgist.taoyao.signal.service.UsernamePasswordService;
import com.acgist.taoyao.signal.service.impl.SecurityServiceImpl;
/**
@@ -15,26 +19,29 @@ import com.acgist.taoyao.signal.service.impl.SecurityServiceImpl;
*
* @author acgist
*/
@Configuration
@AutoConfiguration
public class TaoyaoAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SlowInterceptor slowInterceptor() {
return new SlowInterceptor();
public SlowInterceptor slowInterceptor(TaoyaoProperties taoyaoProperties) {
return new SlowInterceptor(taoyaoProperties);
}
@Bean
@ConditionalOnMissingBean
public SecurityService securityService() {
return new SecurityServiceImpl();
public SecurityService securityService(
SecurityProperties securityProperties,
@Autowired(required = false) UsernamePasswordService usernamePasswordService
) {
return new SecurityServiceImpl(securityProperties, usernamePasswordService);
}
@Bean
@ConditionalOnProperty(prefix = "taoyao.security", name = "enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnMissingBean
public SecurityInterceptor securityInterceptor() {
return new SecurityInterceptor();
public SecurityInterceptor securityInterceptor(SecurityService securityService, SecurityProperties securityProperties) {
return new SecurityInterceptor(securityService, securityProperties);
}
}

View File

@@ -1,6 +1,5 @@
package com.acgist.taoyao.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -24,13 +23,16 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@RestController
@RequestMapping("/config")
public class ConfigController {
@Autowired
private MediaProperties mediaProperties;
@Autowired
private WebrtcProperties webrtcProperties;
private final MediaProperties mediaProperties;
private final WebrtcProperties webrtcProperties;
@Operation(summary = "媒体配置", description = "媒体配置")
public ConfigController(MediaProperties mediaProperties, WebrtcProperties webrtcProperties) {
this.mediaProperties = mediaProperties;
this.webrtcProperties = webrtcProperties;
}
@Operation(summary = "媒体配置", description = "媒体配置")
@GetMapping("/media")
@ApiResponse(content = @Content(schema = @Schema(implementation = MediaProperties.class)))
public Message media() {

View File

@@ -1,14 +1,16 @@
package com.acgist.taoyao.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.acgist.taoyao.boot.model.Message;
import com.acgist.taoyao.signal.protocol.media.MediaRebootProtocol;
import com.acgist.taoyao.signal.protocol.media.MediaShutdownProtocol;
import com.acgist.taoyao.signal.protocol.control.ControlBellProtocol;
import com.acgist.taoyao.signal.protocol.control.ControlPhotographProtocol;
import com.acgist.taoyao.signal.protocol.control.ControlPtzProtocol;
import com.acgist.taoyao.signal.protocol.control.ControlRecordProtocol;
import com.acgist.taoyao.signal.protocol.platform.PlatformRebootProtocol;
import com.acgist.taoyao.signal.protocol.platform.PlatformShutdownProtocol;
import com.acgist.taoyao.signal.protocol.system.SystemRebootProtocol;
@@ -16,6 +18,7 @@ import com.acgist.taoyao.signal.protocol.system.SystemShutdownProtocol;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
/**
* 控制
@@ -23,37 +26,68 @@ import io.swagger.v3.oas.annotations.tags.Tag;
* @author acgist
*/
@Tag(name = "控制", description = "控制管理")
@Validated
@RestController
@RequestMapping("/control")
public class ControlController {
@Autowired
private MediaRebootProtocol mediaRebootProtocol;
@Autowired
private MediaShutdownProtocol mediaShutdownProtocol;
@Autowired
private SystemRebootProtocol systemRebootProtocol;
@Autowired
private SystemShutdownProtocol systemShutdownProtocol;
@Autowired
private PlatformRebootProtocol platformRebootProtocol;
@Autowired
private PlatformShutdownProtocol platformShutdownProtocol;
private final ControlPtzProtocol controlPtzProtocol;
private final ControlBellProtocol controlBellProtocol;
private final SystemRebootProtocol systemRebootProtocol;
private final ControlRecordProtocol controlRecordProtocol;
private final SystemShutdownProtocol systemShutdownProtocol;
private final PlatformRebootProtocol platformRebootProtocol;
private final PlatformShutdownProtocol platformShutdownProtocol;
private final ControlPhotographProtocol controlPhotographProtocol;
@Operation(summary = "重启媒体", description = "重启媒体")
@GetMapping("/media/reboot/{mediaId}")
public Message mediaReboot(@PathVariable String mediaId) {
this.mediaRebootProtocol.execute(mediaId);
return Message.success();
}
@Operation(summary = "关闭媒体", description = "关闭媒体")
@GetMapping("/media/shutdown/{mediaId}")
public Message mediaShutdown(@PathVariable String mediaId) {
this.mediaShutdownProtocol.execute(mediaId);
return Message.success();
public ControlController(
ControlPtzProtocol controlPtzProtocol, ControlBellProtocol controlBellProtocol,
SystemRebootProtocol systemRebootProtocol, ControlRecordProtocol controlRecordProtocol,
SystemShutdownProtocol systemShutdownProtocol, PlatformRebootProtocol platformRebootProtocol,
PlatformShutdownProtocol platformShutdownProtocol, ControlPhotographProtocol controlPhotographProtocol
) {
this.controlPtzProtocol = controlPtzProtocol;
this.controlBellProtocol = controlBellProtocol;
this.systemRebootProtocol = systemRebootProtocol;
this.controlRecordProtocol = controlRecordProtocol;
this.systemShutdownProtocol = systemShutdownProtocol;
this.platformRebootProtocol = platformRebootProtocol;
this.platformShutdownProtocol = platformShutdownProtocol;
this.controlPhotographProtocol = controlPhotographProtocol;
}
@Operation(summary = "PTZ", description = "PTZ")
@GetMapping("/ptz/{clientId}")
public Message ptz(
@NotNull(message = "PTZ类型不能为空") ControlPtzProtocol.Type type,
@NotNull(message = "PTZ参数不能为空") Double value,
@PathVariable String clientId
) {
this.controlPtzProtocol.execute(type, value, clientId);
return Message.success();
}
@Operation(summary = "响铃", description = "响铃")
@GetMapping("/bell/{clientId}")
public Message bell(@PathVariable String clientId) {
this.controlBellProtocol.execute(clientId);
return Message.success();
}
@Operation(summary = "录像", description = "录像")
@GetMapping("/record/{clientId}")
public Message record(@PathVariable String clientId) {
this.controlRecordProtocol.execute(clientId);
return Message.success();
}
@Operation(summary = "拍照", description = "拍照")
@GetMapping("/photograph/{clientId}")
public Message photograph(@PathVariable String clientId) {
this.controlPhotographProtocol.execute(clientId);
return Message.success();
}
@Operation(summary = "重启系统", description = "重启系统")
@GetMapping("/system/reboot")
public Message systemReboot() {

View File

@@ -4,7 +4,6 @@ import java.util.Base64;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.util.AntPathMatcher;
@@ -25,12 +24,16 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SecurityInterceptor extends InterceptorAdapter {
@Autowired
private SecurityService securityService;
@Autowired
private SecurityProperties securityProperties;
private final SecurityService securityService;
private final SecurityProperties securityProperties;
public SecurityInterceptor(SecurityService securityService, SecurityProperties securityProperties) {
this.securityService = securityService;
this.securityProperties = securityProperties;
log.info("安全拦截密码:{}", securityProperties.getPassword());
}
/**
/**
* 地址匹配
*/
private final AntPathMatcher matcher = new AntPathMatcher();

View File

@@ -1,7 +1,5 @@
package com.acgist.taoyao.interceptor;
import org.springframework.beans.factory.annotation.Autowired;
import com.acgist.taoyao.boot.config.TaoyaoProperties;
import com.acgist.taoyao.boot.interceptor.InterceptorAdapter;
@@ -17,10 +15,13 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SlowInterceptor extends InterceptorAdapter {
@Autowired
private TaoyaoProperties taoyaoProperties;
private final TaoyaoProperties taoyaoProperties;
/**
public SlowInterceptor(TaoyaoProperties taoyaoProperties) {
this.taoyaoProperties = taoyaoProperties;
}
/**
* 请求开始时间
*/
private final ThreadLocal<Long> local = new ThreadLocal<>();

View File

@@ -3,18 +3,24 @@ package com.acgist.taoyao.listener;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.context.ApplicationListener;
import lombok.extern.slf4j.Slf4j;
/**
* 配置JDK HTTPClient域名校验问题
* 去年今日此门中
* 人面桃花相映红
*
* 注意SpringApplicationRunListeners里面同步执行
*
* @author acgist
*/
public class HTTPClientListener implements ApplicationListener<ApplicationStartingEvent> {
@Slf4j
public class QnjrcmzListener implements ApplicationListener<ApplicationStartingEvent> {
@Override
public void onApplicationEvent(ApplicationStartingEvent event) {
synchronized (HTTPClientListener.class) {
synchronized (QnjrcmzListener.class) {
log.debug("配置忽略证书域名校验");
// 配置JDK HTTPClient域名校验问题
System.getProperties().setProperty("jdk.internal.httpclient.disableHostnameVerification", Boolean.TRUE.toString());
}
}

View File

@@ -0,0 +1,29 @@
package com.acgist.taoyao.listener;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import com.acgist.taoyao.boot.annotation.Listener;
import com.acgist.taoyao.boot.config.TaoyaoProperties;
import lombok.extern.slf4j.Slf4j;
/**
* 人面不知何处去
* 桃花依旧笑春风
*
* @author acgist
*/
@Slf4j
@Listener
public class ThyjxcfListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
synchronized (ThyjxcfListener.class) {
final TaoyaoProperties taoyaoProperties = event.getApplicationContext().getBean(TaoyaoProperties.class);
log.info("项目启动成功:{}", taoyaoProperties.getName());
}
}
}

View File

@@ -10,6 +10,7 @@ public class TaoyaoApplication {
public static void main(String[] args) {
SpringApplication.run(TaoyaoApplication.class, args);
// System.exit(SpringApplication.exit(SpringApplication.run(TaoyaoApplication.class, args)));
}
}

View File

@@ -1 +1 @@
org.springframework.context.ApplicationListener=com.acgist.taoyao.listener.HTTPClientListener
org.springframework.context.ApplicationListener=com.acgist.taoyao.listener.QnjrcmzListener

View File

@@ -1,14 +1,10 @@
taoyao:
media:
media-server-list:
- media-id: media-local-a
enabled: false
rewrite-ip: true
# host: 192.168.1.110
host: 192.168.8.110
port: 9443
schema: wss
username: taoyao
password: taoyao
security:
permit: /v3/api-docs/**,/swagger-ui/**,/swagger-ui.html,/,/error,/index.html,/favicon.ico
permit:
- /
- /error
- /index.html
- /favicon.ico
- /v3/api-docs/**
- /swagger-ui/**
- /swagger-ui.html

View File

@@ -1,4 +1,6 @@
taoyao:
security:
password: ${random.uuid}
script:
enabled: false

View File

@@ -19,6 +19,8 @@ server:
# servlet:
# context-path: /taoyao
spring:
# main:
# lazy-initialization: true
profiles:
active: dev
application:
@@ -51,7 +53,6 @@ taoyao:
name: 桃夭信令服务
version: 1.0.0
description: 桃夭WebRTC信令服务
ip-mask: 24
timeout: 5000
id:
index: 0
@@ -99,24 +100,6 @@ taoyao:
bitrate: 800
frame-rate: 16
resolution: 720*480
# 媒体服务配置
media-server-list:
- media-id: media-local-a
enabled: true
rewrite-ip: true
host: 127.0.0.1
port: 9443
schema: wss
username: taoyao
password: taoyao
- media-id: media-local-z
enabled: true
rewrite-ip: true
host: 127.0.0.1
port: 9443
schema: wss
username: taoyao
password: taoyao
# Socket信令
socket:
enabled: true
@@ -151,18 +134,31 @@ taoyao:
security:
enabled: true
realm: taoyao
permit: /,/error,/index.html,/favicon.ico
permit:
- /
- /error
- /index.html
- /favicon.ico
username: taoyao
password: taoyao
# 定时任务
scheduled:
media: 0 * * * * ?
client: 0 * * * * ?
# 地址重写
ip-rewrite:
enabled: true
prefix: 24
rule:
- prefix: 24
network: 192.168.1.0
target-host:
- prefix: 24
network: 192.168.8.0
target-host:
# 脚本配置
script:
enabled: true
media-reboot: pm2 restart taoyao-client-media
media-shutdown: pm2 stop taoyao-client-media
system-reboot: reboot
system-shutdown: shutdown now
platform-reboot: systemctl restart taoyao-signal-server

View File

@@ -25,6 +25,7 @@ class IdServiceTest {
void testId() {
final long id = this.idService.buildId();
log.info("生成ID{}", id);
log.info("生成ID{}", String.valueOf(id).length());
}
@Test

View File

@@ -1,77 +0,0 @@
package com.acgist.taoyao.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.acgist.taoyao.annotation.TaoyaoTest;
import com.acgist.taoyao.boot.service.IpService;
import com.acgist.taoyao.main.TaoyaoApplication;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@TaoyaoTest(classes = TaoyaoApplication.class)
public class IpServiceTest {
@Autowired
private IpService ipService;
@Test
public void testDomain() throws UnknownHostException {
InetAddress byName = InetAddress.getByName("www.acgist.com");
System.out.println(byName);
System.out.println(byName.getHostAddress());
System.out.println(byName.getHostName());
System.out.println(byName.isAnyLocalAddress());
System.out.println(byName.isLoopbackAddress());
System.out.println(byName.isLinkLocalAddress());
System.out.println(byName.isMulticastAddress());
System.out.println(byName.isSiteLocalAddress());
}
@Test
public void testSubnetIp() {
assertTrue(this.ipService.subnetIp("192.168.8.1", "192.168.8.100"));
assertTrue(this.ipService.subnetIp("192.168.100.1", "192.168.100.100"));
assertFalse(this.ipService.subnetIp("192.168.1.1", "192.168.8.100"));
assertFalse(this.ipService.subnetIp("192.168.80.1", "192.168.8.100"));
assertTrue(this.ipService.subnetIp("fe80::9ff9:2da9:9759:17e9", "fe80::9ff9:2da9:9759:17e9"));
assertTrue(this.ipService.subnetIp("fe80::9ff9:2da9:9759:17ee", "fe80::9ff9:2da9:9759:17e9"));
assertFalse(this.ipService.subnetIp("fe81::9ff9:2da9:9759:17e9", "fe80::9ff9:2da9:9759:17e9"));
assertFalse(this.ipService.subnetIp("fe81::9ff9:2da9:9759:17ee", "fe80::9ff9:2da9:9759:17e9"));
}
@Test
public void testRewriteIp() {
assertEquals("192.168.1.0", this.ipService.rewriteIp("0.0.0.0", "192.168.1.1"));
assertEquals("192.168.1.10", this.ipService.rewriteIp("0.0.0.0", "192.168.1.1", "192.168.8.10"));
assertEquals("192.168.1.100", this.ipService.rewriteIp("192.168.8.100", "192.168.1.1"));
assertEquals("192.168.10.100", this.ipService.rewriteIp("192.168.8.100", "192.168.10.1"));
}
@Test
public void testCost() {
long a = System.currentTimeMillis();
for (int index = 0; index < 100000; index++) {
assertTrue(this.ipService.subnetIp("192.168.100.1", "192.168.100.100"));
assertFalse(this.ipService.subnetIp("192.168.1.1", "192.168.8.100"));
}
long z = System.currentTimeMillis();
log.info("耗时:{}", z - a);
a = System.currentTimeMillis();
for (int index = 0; index < 100000; index++) {
assertEquals("192.168.1.100", this.ipService.rewriteIp("192.168.8.100", "192.168.1.1"));
assertEquals("192.168.10.100", this.ipService.rewriteIp("192.168.8.100", "192.168.10.1"));
}
z = System.currentTimeMillis();
log.info("耗时:{}", z - a);
}
}