├── .idea
├── artifacts
│ ├── webrtc_war.xml
│ └── webrtc_war_exploded.xml
├── compiler.xml
├── encodings.xml
├── libraries
│ ├── Maven__aopalliance_aopalliance_1_0.xml
│ ├── Maven__ch_qos_logback_logback_classic_1_1_2.xml
│ ├── Maven__ch_qos_logback_logback_core_1_1_2.xml
│ ├── Maven__com_google_guava_guava_20_0.xml
│ ├── Maven__com_thetransactioncompany_cors_filter_2_5.xml
│ ├── Maven__com_thetransactioncompany_java_property_utils_1_9_1.xml
│ ├── Maven__commons_collections_commons_collections_3_2_1.xml
│ ├── Maven__commons_logging_commons_logging_1_1_1.xml
│ ├── Maven__joda_time_joda_time_2_3.xml
│ ├── Maven__junit_junit_3_8_1.xml
│ ├── Maven__org_apache_commons_commons_lang3_3_5.xml
│ ├── Maven__org_apache_tomcat_tomcat_servlet_api_7_0_64.xml
│ ├── Maven__org_aspectj_aspectjrt_1_6_11.xml
│ ├── Maven__org_aspectj_aspectjweaver_1_7_3.xml
│ ├── Maven__org_codehaus_jackson_jackson_core_asl_1_9_12.xml
│ ├── Maven__org_codehaus_jackson_jackson_mapper_asl_1_9_12.xml
│ ├── Maven__org_hashids_hashids_1_0_1.xml
│ ├── Maven__org_json_json_20160810.xml
│ ├── Maven__org_slf4j_slf4j_api_1_7_6.xml
│ ├── Maven__org_springframework_spring_aop_4_0_0_RELEASE.xml
│ ├── Maven__org_springframework_spring_beans_4_0_0_RELEASE.xml
│ ├── Maven__org_springframework_spring_context_4_0_0_RELEASE.xml
│ ├── Maven__org_springframework_spring_core_4_0_0_RELEASE.xml
│ ├── Maven__org_springframework_spring_expression_4_0_0_RELEASE.xml
│ ├── Maven__org_springframework_spring_jdbc_4_0_0_RELEASE.xml
│ ├── Maven__org_springframework_spring_oxm_4_0_0_RELEASE.xml
│ ├── Maven__org_springframework_spring_test_4_0_0_RELEASE.xml
│ ├── Maven__org_springframework_spring_tx_4_0_0_RELEASE.xml
│ ├── Maven__org_springframework_spring_web_4_0_0_RELEASE.xml
│ └── Maven__org_springframework_spring_webmvc_4_0_0_RELEASE.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── doc
├── codeStructure.md
├── errorCode.md
└── protocol.md
├── image
├── build_war.png
├── change_jdk_1.png
├── change_jdk_2.png
├── check_jdk.png
├── config_cvm.png
├── cvm_image.png
├── cvm_info.png
├── new_cvm.png
├── postman.png
├── postman2.png
├── rav_config.png
├── rav_new.png
├── rav_open.png
├── restart_tomcat.png
├── upload_war.png
└── upload_war_2.png
├── pom.xml
├── src
└── main
│ ├── java
│ └── com
│ │ ├── tencent
│ │ └── qcloud
│ │ │ └── roomservice
│ │ │ └── webrtc
│ │ │ ├── common
│ │ │ ├── CORSFilter.java
│ │ │ └── Config.java
│ │ │ ├── controller
│ │ │ └── WebRTCRoom.java
│ │ │ ├── logic
│ │ │ ├── IMMgr.java
│ │ │ └── WebRTCRoomMgr.java
│ │ │ ├── pojo
│ │ │ ├── Member.java
│ │ │ ├── Request
│ │ │ │ ├── CreateRoomReq.java
│ │ │ │ ├── EnterRoomReq.java
│ │ │ │ ├── GetLoginInfoReq.java
│ │ │ │ ├── GetRoomListReq.java
│ │ │ │ ├── GetRoomMembersReq.java
│ │ │ │ ├── HeartBeatReq.java
│ │ │ │ └── QuitRoomReq.java
│ │ │ ├── Response
│ │ │ │ ├── BaseRsp.java
│ │ │ │ ├── CreateRoomRsp.java
│ │ │ │ ├── EnterRoomRsp.java
│ │ │ │ ├── GetLoginInfoRsp.java
│ │ │ │ ├── GetRoomListRsp.java
│ │ │ │ └── GetRoomMembersRsp.java
│ │ │ └── WebRTCRoom.java
│ │ │ ├── service
│ │ │ ├── WebRTCRoomService.java
│ │ │ └── impl
│ │ │ │ └── WebRTCRoomServiceImpl.java
│ │ │ └── utils
│ │ │ ├── RestTemplateConfig.java
│ │ │ └── Utils.java
│ │ └── tls
│ │ └── WebRTCSigApi.java
│ ├── resources
│ ├── applicationContext.xml
│ └── logback.xml
│ └── webapp
│ ├── WEB-INF
│ ├── dispatcher-servlet.xml
│ └── web.xml
│ └── index.jsp
└── webrtc.iml
/.idea/artifacts/webrtc_war.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/target
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/artifacts/webrtc_war_exploded.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/target/webrtc
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__aopalliance_aopalliance_1_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_1_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__ch_qos_logback_logback_core_1_1_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_guava_guava_20_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_thetransactioncompany_cors_filter_2_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_thetransactioncompany_java_property_utils_1_9_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_collections_commons_collections_3_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_logging_commons_logging_1_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__joda_time_joda_time_2_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__junit_junit_3_8_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_tomcat_servlet_api_7_0_64.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_aspectj_aspectjrt_1_6_11.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_aspectj_aspectjweaver_1_7_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_codehaus_jackson_jackson_core_asl_1_9_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_codehaus_jackson_jackson_mapper_asl_1_9_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hashids_hashids_1_0_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_json_json_20160810.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_aop_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_beans_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_context_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_core_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_expression_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_jdbc_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_oxm_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_test_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_tx_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_web_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_webmvc_4_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | true
20 | DEFINITION_ORDER
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | 1534313946657
139 |
140 |
141 | 1534313946657
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 | webrtc:war
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | Spring
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 | 1.8
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 | webrtc
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 | Maven: aopalliance:aopalliance:1.0
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 腾讯云音视频 WebRTC 解决方案服务端
2 | 当您测试体验完完 “WebRTC 互通”功能之后,想开发属于自己的“ WebRTC 互通”功能。这时需要部署属于自己账号体系的服务器。本文主要说明如何部署 WebRTC 服务器。
3 |
4 |
5 | ## 1 开通实时音视频服务
6 |
7 | #### step1: 申请开通实时音视频服务
8 | 进入 [实时音视频管理控制台](https://console.qcloud.com/rav),如果服务还没有开通,则会有如下提示:
9 | 
10 | 点击申请开通,之后会进入腾讯云人工审核阶段,审核通过后即可开通。
11 |
12 | #### step2: 创建实时音视频应用
13 | 实时音视频开通后,进入[【实时音视频管理控制台】](https://console.qcloud.com/rav) 创建实时音视频应用 :
14 | 
15 | 点击【**确定**】按钮即可。
16 |
17 | #### step3: 获取实时音视频配置信息
18 | 从实时音视频控制台获取`sdkAppID、accountType、privateKey`,后面配置服务器会用到:
19 | 
20 |
21 |
22 | ## 2 修改配置信息
23 | 后台使用 spring 框架搭建,开发环境是 IntelliJ IDEA,**java 环境要求使用1.8_52 或以上**。用 IntelliJ IDEA 导入工程源码,修改`\src\main\java\com\tencent\qcloud\roomservice\webrtc\common\Config.java` 中`sdkAppID、accountType、privateKey`等配置项。
24 |
25 | ```java
26 | public class Config {
27 |
28 | /**
29 | * 需要开通 实时音视频 服务
30 | * 有介绍appid 和 accType的获取方法。以及私钥文件的下载方法。
31 | */
32 | public class iLive {
33 | public final static long sdkAppID = 0;
34 |
35 | public final static String accountType = "0";
36 |
37 | /**
38 | * 派发userSig 和 privateMapKey 采用非对称加密算法RSA,用私钥生成签名。privateKey就是用于生成签名的私钥,私钥文件可以在互动直播控制台获取
39 | * 配置privateKey
40 | * 将private_key文件的内容按下面的方式填写到 privateKey字段。
41 | */
42 | public final static String privateKey = "-----BEGIN PRIVATE KEY-----\n" +
43 | "xxxx\n" +
44 | "xxxx\n" +
45 | "xxxx\n" +
46 | "-----END PRIVATE KEY-----";
47 | }
48 |
49 |
50 | /**
51 | * webrtc房间相关参数
52 | */
53 | public class WebRTCRoom {
54 | // 房间容量上限
55 | public final static int maxMembers = 4;
56 |
57 | // 心跳超时 单位秒
58 | public final static int heartBeatTimeout = 20;
59 | }
60 |
61 | }
62 | ```
63 |
64 | ## 3 服务器部署
65 |
66 | 以 CentOS 系统为例,描述部署过程。建议环境: CentOS + nginx + Apache Tomcat + java 。小程序和 IOS 都要求服务器支持 HTTPS 请求。
67 |
68 | ### 3.1 准备发布包
69 | 首先到 [IntelliJ IDEA 官网](https://www.jetbrains.com/idea/download/#section=windows) 下载 IntelliJ IDEA 工具,注意这里要选择 Ultimate 版 。因为只有 Ultimate 版本才拥有Java EE 相关插件以及功能。
70 | 
71 |
72 | 成功安装 IntelliJ IDEA,接着配置按照第 2 步讲述, 修改下配置信息。
73 |
74 | 修改好 Config.java 中的配置,然后选择 Build -> Build Artifacts 开始打包,打包完成后到输出路径拿到 webrtc.war 包。
75 |
76 | 
77 |
78 | ### 3.2 war包部署到服务器
79 |
80 | #### 1) 新建 CVM 主机
81 | 
82 |
83 | #### 2) 从服务市场选取镜像。
84 | 
85 |
86 | #### 3) 配置硬盘、网络、云主机访问密码,并且妥善保管好密码,然后设置安全组。
87 | 
88 |
89 | #### 4) 查看/切换 JDK 版本。
90 | 
91 |
92 | 
93 |
94 | #### 5) 使用 FileZilla 连接云服务器
95 | 因为需要上传文件到云服务器,建议使用 FileZilla 或者 FlashFXP 等可视化界面工具。
96 | 
97 |
98 | #### 6)将打包好的 webrtc.war 包上传 tomcat 的 webapps 目录下
99 | 
100 |
101 | #### 7) 通过 tomcat/bin 目录下的 startup.sh 脚本重新启动 tomcat。
102 | 
103 |
104 |
105 | ### 3.3 nginx 配置
106 | 如果您已经有**域名**以及域名对应的**SSL证书**存放在`/data/release/nginx/`目录下,请将下面配置内容中的
107 | - [1] 替换成您自己的域名
108 | - [2-1] 替换成SSL证书的crt文件名
109 | - [2-2] 替换成SSL证书的key文件名
110 |
111 | ```
112 | upstream app_weapp {
113 | server localhost:5757;
114 | keepalive 8;
115 | }
116 |
117 | #http请求转为 https请求
118 | server {
119 | listen 80;
120 | server_name [1];
121 |
122 | rewrite ^(.*)$ https://$server_name$1 permanent;
123 | }
124 |
125 | #https请求
126 | server {
127 | listen 443;
128 | server_name [1];
129 |
130 | ssl on;
131 |
132 | ssl_certificate /data/release/nginx/[2-1];
133 | ssl_certificate_key /data/release/nginx/[2-2];
134 | ssl_session_timeout 5m;
135 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
136 | ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
137 | ssl_session_cache shared:SSL:50m;
138 | ssl_prefer_server_ciphers on;
139 |
140 | # tomcat默认端口是8080,nginx 将请求转发给tomcat处理
141 | location / {
142 | proxy_pass http://127.0.0.1:8080;
143 | proxy_redirect off;
144 | proxy_set_header X-Real-IP $remote_addr;
145 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
146 | }
147 | }
148 | ```
149 |
150 | ### 3.4 运行服务
151 | 输入命令,启动Nginx服务。
152 | ```
153 | nginx -s reload
154 | ```
155 | 使用 Postman 通过 POST 方式访问接口,如果在返回的 json 数据带有**请求成功**字样,说明部署成功。
156 | 以获取登录信息为例,请求地址是` https://您自己的域名/webrtc/weapp/webrtc_room/get_login_info`
157 | 
158 |
159 | 如果你是本地测试,请求地址则是:`http://127.0.0.1:8080/weapp/webrtc_room/get_login_info`
160 | 
161 |
162 | ## 4 小程序和web端部署
163 | ### 4.1 小程序部署
164 |
165 | 下载 [小程序](https://github.com/TencentVideoCloudMLVBDev/RTCRoomDemo) 源码,将wxlite/config.js文件中的`webrtcServerUrl`修改成:
166 | ```
167 | https://您自己的域名/webrtc/weapp/webrtc_room
168 | ```
169 |
170 | ### 4.2 web端部署
171 |
172 | 下载 [web端](https://github.com/TencentVideoCloudMLVBDev/webrtc_pc) 源码,将component/WebRTCRoom.js文件中的`serverDomain`修改成:
173 | ```
174 | https://您自己的域名/webrtc/weapp/webrtc_room
175 | ```
176 |
177 | ## 5 开发者资源
178 | * [项目结构](https://github.com/TencentVideoCloudMLVBDev/webrtc_server_java/blob/master/doc/codeStructure.md) - 后台源码结构
179 | * [协议文档](https://github.com/TencentVideoCloudMLVBDev/webrtc_server_java/blob/master/doc/protocol.md) - 后台协议文档
180 | * [常见错误码](https://github.com/TencentVideoCloudMLVBDev/webrtc_server_java/blob/master/doc/errorCode.md) - 错误码文档
181 |
--------------------------------------------------------------------------------
/doc/codeStructure.md:
--------------------------------------------------------------------------------
1 | ## 项目结构
2 | ```
3 | roomserver
4 | ├── README.md //项目总体说明文档
5 | ├── doc
6 | │ ├── codeStructure.md //项目结构文档
7 | │ └── protocol.md //后台协议文档
8 | ├── pom.xml //maven 依赖配置文件
9 | ├── src //java源代码目录
10 | │ └── main
11 | │ ├── java
12 | │ │ └── com
13 | │ │ ├── tencent
14 | │ │ │ └── qcloud
15 | │ │ │ └── roomservice
16 | │ │ │ └── webrtc
17 | │ │ │ ├── common
18 | │ │ │ │ ├── CORSFilter.java //跨域设置类
19 | │ │ │ │ └── Config.java //后台配置,需要修改这里
20 | │ │ │ ├── controller
21 | │ │ │ │ └── WebRTCRoom.java //后台协议总入口
22 | │ │ │ ├── logic
23 | │ │ │ │ ├── IMMgr.java //云通信逻辑实现
24 | │ │ │ │ └── WebRTCRoomMgr.java //房间管理实现
25 | │ │ │ ├── pojo
26 | │ │ │ │ ├── Member.java //成员结构定义
27 | │ │ │ │ ├── Request
28 | │ │ │ │ │ ├── CreateRoomReq.java //建房请求定义
29 | │ │ │ │ │ ├── EnterRoomReq.java //进房请求定义
30 | │ │ │ │ │ ├── GetLoginInfoReq.java //getLoginInfo请求定义
31 | │ │ │ │ │ ├── GetRoomListReq.java //获取房间列表请求定义
32 | │ │ │ │ │ ├── GetRoomMembersReq.java //获取房间内成员请求定义
33 | │ │ │ │ │ ├── HeartBeatReq.java //心跳请求定义
34 | │ │ │ │ │ └── QuitRoomReq.java //退房请求定义
35 | │ │ │ │ ├── Response
36 | │ │ │ │ │ ├── BaseRsp.java //回包通用定义
37 | │ │ │ │ │ ├── CreateRoomRsp.java //建房回包定义
38 | │ │ │ │ │ ├── EnterRoomRsp.java //进房回包定义
39 | │ │ │ │ │ ├── GetLoginInfoRsp.java //getLoginInfo回包定义
40 | │ │ │ │ │ ├── GetRoomListRsp.java //获取房间列表回包定义
41 | │ │ │ │ │ └── GetRoomMembersRsp.java //获取房间成员回包定义
42 | │ │ │ │ └── WebRTCRoom.java //房间结构定义
43 | │ │ │ ├── service
44 | │ │ │ │ ├── WebRTCRoomService.java //房间管理服务service实现
45 | │ │ │ │ └── impl
46 | │ │ │ │ └── WebRTCRoomServiceImpl.java //房间管理服务service接口
47 | │ │ │ └── utils
48 | │ │ │ ├── RestTemplateConfig.java //http请求配置
49 | │ │ │ └── Utils.java //通用类
50 | │ │ └── tls
51 | │ │ └── WebRTCSigApi.java //计算UserSig和视频权限位的类
52 | │ ├── resources
53 | │ │ ├── applicationContext.xml //spring配置文件
54 | │ │ └── logback.xml //log配置文件
55 | │ └── webapp
56 | │ ├── WEB-INF
57 | │ │ ├── dispatcher-servlet.xml //spring配置文件
58 | │ │ └── web.xml //后台配置文件
59 | │ └── index.jsp
60 | └── webrtc.iml
61 | ```
62 | 后台使用spring框架搭建,开发环境是IntelliJ IDEA,java需要使用1.8
63 |
64 | `pom.xml` 是 maven 依赖配置文件。
65 |
66 | `WebRTCRoom.java` 是 服务器端 房间业务逻辑。
67 |
68 | `logic/IMMgr.java` 云通信相关的处理,主要功能有:
69 | ```
70 | getLoginInfo, // 获取sdkAppID、accountType、userSig票据等信息
71 | getPrivMapEncrypt, // 获取视频权限位
72 | ```
73 |
74 | `logic/WebRTCRoomMgr.java` 实时音视频房间管理模块,负责视频房间的创建,进房,退房,获取房间列表功能函数;另外也负责房间成员的心跳检查,对超时的成员进行删除处理。
75 |
--------------------------------------------------------------------------------
/doc/errorCode.md:
--------------------------------------------------------------------------------
1 | ## 常见错误码含义
2 |
3 | | 错误码 | 具体含义 |
4 | |---------|---------|
5 | | 415 | Unsupported Media Type。请求包体不是json格式 |
6 | | 400 | Bad Request。请求包体是json格式,但是字段不符合协议。在用postman调试后台接口的时候,body至少要填一对花括号{} |
7 | | 500 | Internal Server Error 服务器内部错误,根据具体的错误信息分析。一般是Config.java配置有问题或者java版本不合要求导致 |
8 |
--------------------------------------------------------------------------------
/doc/protocol.md:
--------------------------------------------------------------------------------
1 | # 后台协议设计
2 |
3 | * 接口命名采用c风格,举例 get_push_url
4 | * 请求方式POST,请求的body是Json格式。
5 |
6 | ## 接口说明
7 |
8 | ### get_login_info 获取sdkAppID、accountType、userID、userSig信息
9 |
10 | #### 参数说明
11 |
12 | | 参数名称 | 类型 | 是否必填 | 说明 |
13 | | ------ | ---------- | ---- | ------------------ |
14 | | userID | String | 是 | 用户id,可为空,为空则随机分配 |
15 |
16 | #### 返回结果说明
17 |
18 | | 属性名称 | 类型 | 说明 |
19 | | ------- | ---------- | ------ |
20 | | code | int | 返回码,0表示成功 |
21 | | message | String | 描述信息 |
22 | | sdkAppID | String | 互动直播的sdkAppID |
23 | | accountType | String | 互动直播的accountType |
24 | | userID | String | 用户id |
25 | | userSig | String | 用户签名 |
26 |
27 |
28 | ### create_room 创建房间
29 |
30 | #### 参数说明
31 |
32 | | 参数名称 | 类型 | 是否必填 | 说明 |
33 | | ------ | ---------- | ---- | ------------------ |
34 | | userID | String | 是 | 创建者用户id,不可为空 |
35 | | nickName | String | 否 | 创建者昵称,可为空 |
36 | | roomInfo | String | 是 | 房间名称 |
37 | | **roomType** | **String** | **否** | **请求加入的房间类型**,可以为空 |
38 |
39 | #### 返回结果说明
40 |
41 | | 属性名称 | 类型 | 说明 |
42 | | ------- | ---------- | ------ |
43 | | code | int | 返回码,0表示成功 |
44 | | message | String | 描述信息 |
45 | | roomID | String | 房间id |
46 | | roomInfo | String | 房间名 |
47 | | privateMapKey | String | 权限位 |
48 |
49 | ### enter_room 进入房间
50 |
51 | #### 参数说明
52 |
53 | | 参数名称 | 类型 | 是否必填 | 说明 |
54 | | ------ | ---------- | ---- | ------------------ |
55 | | userID | String | 是 | 请求加房的用户id |
56 | | nickName | String | 否 | 请求加房的用户昵称,可为空 |
57 | | roomID | String | 是 | 请求加入的房间id |
58 |
59 | #### 返回结果说明
60 |
61 | | 属性名称 | 类型 | 说明 |
62 | | ------- | ---------- | ------ |
63 | | code | int | 返回码,0表示成功 |
64 | | message | String | 描述信息 |
65 | | userID | String | 用户id |
66 | | roomID | String | 房间id |
67 | | privateMapKey | String | 权限位 |
68 |
69 | ### quit_room 退出房间
70 |
71 | #### 参数说明
72 |
73 | | 参数名称 | 类型 | 是否必填 | 说明 |
74 | | ------ | ---------- | ---- | ------------------ |
75 | | userID | String | 是 | 请求退出房间的用户id|
76 | | roomID | String | 是 | 请求退出的房间id|
77 |
78 | #### 返回结果说明
79 |
80 | | 属性名称 | 类型 | 说明 |
81 | | ------- | ---------- | ------ |
82 | | code | int | 返回码,0表示成功 |
83 | | message | String | 描述信息 |
84 |
85 | ### heartbeat 心跳,当终端心跳超时后踢出房间
86 |
87 | #### 参数说明
88 |
89 | | 参数名称 | 类型 | 是否必填 | 说明 |
90 | | ------ | ---------- | ---- | ------------------ |
91 | | userID | String | 是 | 用户id|
92 | | roomID | String | 是 | 房间id|
93 |
94 | #### 返回结果说明
95 |
96 | | 属性名称 | 类型 | 说明 |
97 | | ------- | ---------- | ------ |
98 | | code | int | 返回码,0表示成功 |
99 | | message | String | 描述信息 |
100 |
101 | ### get_room_list 获取webrtc房间列表
102 |
103 | #### 参数说明
104 |
105 | | 参数名称 | 类型 | 是否必填 | 说明 |
106 | | ------ | ---------- | ---- | ------------------ |
107 | | index | int | 是 | 起始位置|
108 | | count | int | 是 | 需要获取的记录条数|
109 | | **roomType** | **String** | **否** | **请求加入的房间类型**,可以为空 |
110 |
111 | #### 返回结果说明
112 |
113 | | 属性名称 | 类型 | 说明 |
114 | | ------- | ---------- | ------ |
115 | | code | int | 返回码,0表示成功 |
116 | | message | String | 描述信息 |
117 | | rooms | List | 房间列表 |
118 |
119 | #### Room 属性说明
120 |
121 | | 属性名称 | 类型 | 说明 |
122 | | ------- | ---------- | ------ |
123 | | roomID | String | 房间id |
124 | | roomInfo | String | 房间名称 |
125 |
126 | ### get_room_members 获取房间内成员列表
127 |
128 | #### 参数说明
129 |
130 | | 参数名称 | 类型 | 是否必填 | 说明 |
131 | | ------ | ---------- | ---- | ------------------ |
132 | | roomID | String | 房间id |
133 |
134 | #### 返回结果说明
135 |
136 | | 属性名称 | 类型 | 说明 |
137 | | ------- | ---------- | ------ |
138 | | code | int | 返回码,0表示成功 |
139 | | message | String | 描述信息 |
140 | | members | List | 成员列表 |
141 |
142 | #### Member 属性说明
143 |
144 | | 属性名称 | 类型 | 说明 |
145 | | ------- | ---------- | ------ |
146 | | userID | String | 用户id |
147 | | nickName | String | 用户昵称 |
148 |
149 |
--------------------------------------------------------------------------------
/image/build_war.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/build_war.png
--------------------------------------------------------------------------------
/image/change_jdk_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/change_jdk_1.png
--------------------------------------------------------------------------------
/image/change_jdk_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/change_jdk_2.png
--------------------------------------------------------------------------------
/image/check_jdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/check_jdk.png
--------------------------------------------------------------------------------
/image/config_cvm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/config_cvm.png
--------------------------------------------------------------------------------
/image/cvm_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/cvm_image.png
--------------------------------------------------------------------------------
/image/cvm_info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/cvm_info.png
--------------------------------------------------------------------------------
/image/new_cvm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/new_cvm.png
--------------------------------------------------------------------------------
/image/postman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/postman.png
--------------------------------------------------------------------------------
/image/postman2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/postman2.png
--------------------------------------------------------------------------------
/image/rav_config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/rav_config.png
--------------------------------------------------------------------------------
/image/rav_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/rav_new.png
--------------------------------------------------------------------------------
/image/rav_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/rav_open.png
--------------------------------------------------------------------------------
/image/restart_tomcat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/restart_tomcat.png
--------------------------------------------------------------------------------
/image/upload_war.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/upload_war.png
--------------------------------------------------------------------------------
/image/upload_war_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TencentVideoCloudMLVBDev/webrtc_server_java/c6ce64e3cc63f61a46a2021297f645899cc9a95f/image/upload_war_2.png
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.tencent.qcloud.roomservice.webrtc
5 | webrtc
6 | war
7 | 1.0-SNAPSHOT
8 | webrtc Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | UTF-8
13 | UTF-8
14 | UTF-8
15 |
16 |
17 | 4.0.0.RELEASE
18 | 3.4.1
19 | 1.3.0
20 |
21 |
22 |
23 | junit
24 | junit
25 | 3.8.1
26 | test
27 |
28 |
29 |
30 |
31 | org.apache.tomcat
32 | tomcat-servlet-api
33 | 7.0.64
34 |
35 |
36 |
37 |
38 | com.thetransactioncompany
39 | cors-filter
40 | 2.5
41 |
42 |
43 |
44 |
45 | org.springframework
46 | spring-webmvc
47 |
48 |
49 | ${org.spring.version}
50 |
51 |
52 |
53 | org.springframework
54 | spring-oxm
55 | ${org.spring.version}
56 |
57 |
58 | org.springframework
59 | spring-jdbc
60 | ${org.spring.version}
61 |
62 |
63 | org.springframework
64 | spring-tx
65 | ${org.spring.version}
66 |
67 |
68 | org.springframework
69 | spring-test
70 | ${org.spring.version}
71 |
72 |
73 |
74 | org.aspectj
75 | aspectjweaver
76 | 1.7.3
77 |
78 |
79 | org.aspectj
80 | aspectjrt
81 | 1.6.11
82 |
83 |
84 |
85 |
86 | org.codehaus.jackson
87 | jackson-mapper-asl
88 | 1.9.12
89 |
90 |
91 |
92 | org.json
93 | json
94 | 20160810
95 |
96 |
97 |
98 |
99 | ch.qos.logback
100 | logback-classic
101 | 1.1.2
102 | compile
103 |
104 |
105 | ch.qos.logback
106 | logback-core
107 | 1.1.2
108 | compile
109 |
110 |
111 |
112 |
113 | com.google.guava
114 | guava
115 | 20.0
116 |
117 |
118 |
119 |
120 | org.apache.commons
121 | commons-lang3
122 | 3.5
123 |
124 |
125 |
126 |
127 | commons-collections
128 | commons-collections
129 | 3.2.1
130 |
131 |
132 | joda-time
133 | joda-time
134 | 2.3
135 |
136 |
137 |
138 |
139 | org.hashids
140 | hashids
141 | 1.0.1
142 |
143 |
144 |
145 |
146 | webrtc
147 |
148 |
149 |
150 | org.mybatis.generator
151 | mybatis-generator-maven-plugin
152 | 1.3.2
153 |
154 | true
155 | true
156 |
157 |
158 |
159 |
161 |
162 | org.apache.maven.plugins
163 | maven-compiler-plugin
164 |
165 |
166 | 1.8
167 | 1.8
168 | UTF-8
169 |
170 |
171 |
173 |
174 | ${project.basedir}/src/main/webapp/WEB-INF/lib
175 |
176 |
177 |
178 |
179 |
180 | org.mybatis.generator
181 | mybatis-generator-maven-plugin
182 | 1.3.2
183 |
184 | true
185 | true
186 |
187 |
188 |
189 |
190 |
191 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/common/CORSFilter.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.common;
2 |
3 | import javax.servlet.*;
4 | import javax.servlet.http.HttpServletResponse;
5 | import java.io.IOException;
6 |
7 | public class CORSFilter implements Filter {
8 | @Override
9 | public void init(FilterConfig filterConfig) throws ServletException {
10 |
11 | }
12 |
13 | @Override
14 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
15 | HttpServletResponse response = (HttpServletResponse) servletResponse;
16 | response.setHeader("Access-Control-Allow-Origin", "*");
17 | response.setHeader("Access-Control-Allow-Methods", "POST, GET");
18 | response.setHeader("Access-Control-Max-Age", "3600");
19 | response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
20 | filterChain.doFilter(servletRequest, servletResponse);
21 | }
22 |
23 | @Override
24 | public void destroy() {
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/common/Config.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.common;
2 |
3 | public class Config {
4 |
5 | /**
6 | * 需要开通 实时音视频 服务
7 | * 参考 源码目录下《后台配置部署.md》中的云服务开通部分
8 | * 有介绍appid 和 accType的获取方法。以及私钥文件的下载方法。
9 | */
10 | public class iLive {
11 | public final static long sdkAppID = 0;
12 |
13 | public final static String accountType = "";
14 |
15 | /**
16 | * 派发userSig 和 privateMapKey 采用非对称加密算法RSA,用私钥生成签名。privateKey就是用于生成签名的私钥,私钥文件可以在实时音视频控制台获取
17 | * 配置privateKey
18 | * 将private_key文件的内容按下面的方式填写到 privateKey字段。
19 | */
20 | public final static String privateKey = "-----BEGIN PRIVATE KEY-----\n" +
21 | "\n" +
22 | "\n" +
23 | "\n" +
24 | "-----END PRIVATE KEY-----";
25 | }
26 |
27 |
28 | /**
29 | * webrtc房间相关参数
30 | */
31 | public class WebRTCRoom {
32 | // 房间容量上限
33 | public final static int maxMembers = 4;
34 |
35 | // 心跳超时 单位秒
36 | public final static int heartBeatTimeout = 20;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/controller/WebRTCRoom.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.controller;
2 |
3 | import com.tencent.qcloud.roomservice.webrtc.pojo.Request.*;
4 | import com.tencent.qcloud.roomservice.webrtc.pojo.Response.*;
5 | import com.tencent.qcloud.roomservice.webrtc.service.WebRTCRoomService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Controller;
8 | import org.springframework.web.bind.annotation.RequestBody;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.ResponseBody;
11 |
12 | /**
13 | * webrtc房间接口
14 | */
15 | @Controller
16 | @ResponseBody
17 | @RequestMapping("/weapp/webrtc_room")
18 | public class WebRTCRoom {
19 | @Autowired
20 | WebRTCRoomService webRTCRoomService;
21 |
22 | @ResponseBody
23 | @RequestMapping("get_login_info")
24 | public GetLoginInfoRsp get_login_info(@RequestBody GetLoginInfoReq req){
25 | return webRTCRoomService.getLoginInfo(req.getUserID());
26 | }
27 |
28 | @ResponseBody
29 | @RequestMapping("create_room")
30 | public CreateRoomRsp create_room(@RequestBody CreateRoomReq req){
31 | return webRTCRoomService.createRoom(req);
32 | }
33 |
34 | @ResponseBody
35 | @RequestMapping("enter_room")
36 | public EnterRoomRsp enter_room(@RequestBody EnterRoomReq req){
37 | return webRTCRoomService.enterRoom(req);
38 | }
39 |
40 | @ResponseBody
41 | @RequestMapping("quit_room")
42 | public BaseRsp quit_room(@RequestBody QuitRoomReq req){
43 | return webRTCRoomService.quitRoom(req);
44 | }
45 |
46 | @ResponseBody
47 | @RequestMapping("heartbeat")
48 | public BaseRsp heartbeat(@RequestBody HeartBeatReq req) {
49 | return webRTCRoomService.heartbeat(req);
50 | }
51 |
52 | @ResponseBody
53 | @RequestMapping("get_room_list")
54 | public GetRoomListRsp get_room_list(@RequestBody GetRoomListReq req) {
55 | return webRTCRoomService.getRoomList(req);
56 | }
57 |
58 | @ResponseBody
59 | @RequestMapping("get_room_members")
60 | public GetRoomMembersRsp get_room_members(@RequestBody GetRoomMembersReq req){
61 | return webRTCRoomService.getRoomMembers(req);
62 | }
63 | }
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/logic/IMMgr.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.logic;
2 |
3 | import com.tencent.qcloud.roomservice.webrtc.common.Config;
4 | import com.tencent.qcloud.roomservice.webrtc.pojo.Response.GetLoginInfoRsp;
5 | import com.tencent.qcloud.roomservice.webrtc.utils.Utils;
6 | import com.tls.WebRTCSigApi;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.stereotype.Component;
10 |
11 | import java.util.regex.Pattern;
12 |
13 | @Component
14 | public class IMMgr {
15 | private static Logger log= LoggerFactory.getLogger(IMMgr.class);
16 |
17 | public GetLoginInfoRsp getLoginInfo(String userID) {
18 | GetLoginInfoRsp rsp = new GetLoginInfoRsp();
19 |
20 | String pattern = "^[a-zA-Z][a-zA-Z0-9_]{3,23}$";
21 | if (userID.length() == 0) {
22 | userID = Utils.genUserIdByRandom();
23 | } else if (!Pattern.matches(pattern, userID)) {
24 | rsp.setCode(7);
25 | rsp.setMessage("请求失败,userID含有非法字符或者不符合规范");
26 | return rsp;
27 | }
28 |
29 | WebRTCSigApi api = new WebRTCSigApi();
30 | api.setSdkAppid((int) Config.iLive.sdkAppID);
31 | api.setPrivateKey(Config.iLive.privateKey);
32 | String userSig = api.genUserSig(userID, 60 * 60);
33 |
34 | rsp.setCode(0);
35 | rsp.setMessage("请求成功");
36 | rsp.setSdkAppID(Config.iLive.sdkAppID);
37 | rsp.setAccountType(Config.iLive.accountType);
38 | rsp.setUserID(userID);
39 | rsp.setUserSig(userSig);
40 |
41 | log.info("getLoginInfo, userID:" + userID);
42 |
43 | return rsp;
44 | }
45 |
46 | /**
47 | * 获取webrtcroom的权限位
48 | * @param userID
49 | * @return 权限位
50 | */
51 | public String getPrivMapEncrypt(String userID, String roomID) {
52 | WebRTCSigApi api = new WebRTCSigApi();
53 | api.setSdkAppid((int) Config.iLive.sdkAppID);
54 | api.setPrivateKey(Config.iLive.privateKey);
55 |
56 | String privMapEncrypt = api.genPrivMapEncrypt(userID, Integer.parseInt(roomID), 60 * 60);
57 |
58 | return privMapEncrypt;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/logic/WebRTCRoomMgr.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.logic;
2 |
3 | import com.tencent.qcloud.roomservice.webrtc.common.Config;
4 | import com.tencent.qcloud.roomservice.webrtc.pojo.Member;
5 | import com.tencent.qcloud.roomservice.webrtc.pojo.WebRTCRoom;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.beans.factory.InitializingBean;
9 | import org.springframework.stereotype.Component;
10 |
11 | import java.util.*;
12 | import java.util.concurrent.ConcurrentHashMap;
13 |
14 | @Component
15 | public class WebRTCRoomMgr implements InitializingBean {
16 | private ConcurrentHashMap webRTCRoomMap = new ConcurrentHashMap<>();
17 | private static Logger log = LoggerFactory.getLogger(WebRTCRoomMgr.class);
18 |
19 | private HeartTimer heartTimer = new HeartTimer();
20 | private Timer timer = null;
21 |
22 | @Override
23 | public void afterPropertiesSet() throws Exception {
24 | // 开启心跳检查定时器
25 | if (timer == null) {
26 | timer = new Timer();
27 | timer.schedule(heartTimer, 5 * 1000, 5 * 1000);
28 | }
29 | }
30 |
31 | public class HeartTimer extends TimerTask {
32 | @Override
33 | public void run() {
34 | onTimer();
35 | }
36 | }
37 |
38 | private void onTimer() {
39 | // 遍历房间每个成员,检查pusher的时间戳是否超过timeout
40 | long currentTS = System.currentTimeMillis()/1000;
41 | int timeout = Config.WebRTCRoom.heartBeatTimeout;
42 |
43 | for (WebRTCRoom room : webRTCRoomMap.values()) {
44 | Iterator> entries = room.getMembersMap().entrySet().iterator();
45 | while (entries.hasNext()) {
46 | Map.Entry entry = entries.next();
47 | if (currentTS - entry.getValue().getTimeStamp() > timeout) {
48 | entries.remove();
49 | }
50 | }
51 | }
52 | }
53 |
54 | /**
55 | * 获取房间列表
56 | */
57 | public ArrayList getList(int cnt, int index, String roomType) {
58 | ArrayList resultList = new ArrayList<>();
59 | int cursor = 0;
60 | int roomCnt = 0;
61 |
62 | //遍历
63 | for (WebRTCRoom value : webRTCRoomMap.values()) {
64 | if (roomCnt >= cnt)
65 | break;
66 |
67 | if (!value.getRoomType().equals(roomType)) {
68 | continue;
69 | }
70 |
71 | log.info("getRoomList roomID: " + value.getRoomID() + ", members count: " + value.getMembersCnt() + ", members list : " + value.getMembers() + ", roomType: " + roomType);
72 |
73 | if (value.getMembersCnt() != 0) {
74 | if (cursor >= index) {
75 | resultList.add(value);
76 | ++roomCnt;
77 | } else {
78 | ++cursor;
79 | continue;
80 | }
81 | } else {
82 | webRTCRoomMap.remove(value.getRoomID());
83 | }
84 | }
85 |
86 | return resultList;
87 | }
88 |
89 |
90 | /**
91 | * 创建房间
92 | */
93 | public void creatRoom(String roomID, String userID, String nickName, String roomInfo, String roomType) {
94 | WebRTCRoom webRTCRoom = new WebRTCRoom();
95 | webRTCRoom.setRoomID(roomID);
96 | webRTCRoom.setRoomInfo(roomInfo);
97 | webRTCRoom.addMember(userID, nickName);
98 | webRTCRoom.setRoomCreator(userID);
99 | webRTCRoom.setRoomType(roomType);
100 | log.info("creatRoom roomID: " + roomID + ", userID: " + userID + ", nickName: " + nickName + ", roomType: " + roomType);
101 | webRTCRoomMap.put(roomID, webRTCRoom);
102 | }
103 |
104 | /**
105 | * 房间是否存在
106 | */
107 | public boolean isRoomExist(String roomID) {
108 | return webRTCRoomMap.containsKey(roomID);
109 | }
110 |
111 | /**
112 | * 用户是否在房间中
113 | */
114 | public boolean isMemberExist(String roomID, String userID) {
115 | WebRTCRoom webRTCRoom = webRTCRoomMap.get(roomID);
116 | if (webRTCRoom != null) {
117 | return webRTCRoom.isMember(userID);
118 | }
119 | return false;
120 | }
121 |
122 |
123 | /**
124 | * 心跳更新
125 | */
126 | public void updateTimeStamp(String roomID, String userID) {
127 | WebRTCRoom webRTCRoom = webRTCRoomMap.get(roomID);
128 | if (webRTCRoom != null && webRTCRoom.isMember(userID)) {
129 | webRTCRoom.updateMember(userID);
130 | }
131 | }
132 |
133 | /**
134 | * 获取房间推流者人数
135 | */
136 | public int getMemberCnt(String roomID) {
137 | int count = 0;
138 | WebRTCRoom webRTCRoom = webRTCRoomMap.get(roomID);
139 | if (webRTCRoom != null) {
140 | count = webRTCRoom.getMembersCnt();
141 | }
142 | return count;
143 | }
144 |
145 | /**
146 | * 删除成员
147 | */
148 | public void delMember(String roomID, String userID) {
149 | WebRTCRoom webRTCRoom = webRTCRoomMap.get(roomID);
150 | if (webRTCRoom != null) {
151 | webRTCRoom.delMember(userID);
152 | log.info("delMember roomID: " + roomID + ", userID: " + userID);
153 |
154 | if (webRTCRoom.getMembersCnt() == 0) {
155 | webRTCRoomMap.remove(roomID);
156 | }
157 | }
158 | }
159 |
160 | public void addMember(String roomID, String userID, String nickName) {
161 | WebRTCRoom webRTCRoom = webRTCRoomMap.get(roomID);
162 | if (webRTCRoom != null) {
163 | webRTCRoom.addMember(userID, nickName);
164 | log.info("addMember roomID: " + roomID + ", userID: " + userID);
165 | }
166 | }
167 |
168 | public ArrayList getMembers(String roomID) {
169 | WebRTCRoom webRTCRoom = webRTCRoomMap.get(roomID);
170 | if (webRTCRoom != null) {
171 | return webRTCRoom.getMembers();
172 | }
173 | return null;
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Member.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo;
2 |
3 | import org.codehaus.jackson.annotate.JsonIgnore;
4 |
5 | public class Member {
6 | private String userID = "";
7 | private String nickName = "";
8 | private long timeStamp = 0;
9 |
10 | public String getUserID() {
11 | return userID;
12 | }
13 |
14 | public void setUserID(String userID) {
15 | this.userID = userID;
16 | }
17 |
18 | public String getNickName() {
19 | return nickName;
20 | }
21 |
22 | public void setNickName(String nickName) {
23 | this.nickName = nickName;
24 | }
25 |
26 | @JsonIgnore
27 | public long getTimeStamp() {
28 | return timeStamp;
29 | }
30 |
31 | public void setTimeStamp(long timeStamp) {
32 | this.timeStamp = timeStamp;
33 | }
34 |
35 | @Override
36 | public String toString() {
37 | return "userID=" + userID + ", nickName=" + nickName + ", timeStamp=" + timeStamp;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Request/CreateRoomReq.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Request;
2 |
3 | public class CreateRoomReq {
4 | private String userID = "";
5 | private String nickName = ""; //用户昵称
6 | private String roomInfo = "";
7 | private String roomType = ""; //房间类型,可以为空
8 |
9 | public String getUserID() {
10 | return userID;
11 | }
12 |
13 | public void setUserID(String userID) {
14 | this.userID = userID;
15 | }
16 |
17 | public String getRoomInfo() {
18 | return roomInfo;
19 | }
20 |
21 | public void setRoomInfo(String roomInfo) {
22 | this.roomInfo = roomInfo;
23 | }
24 |
25 | public String getNickName() {
26 | return nickName;
27 | }
28 |
29 | public void setNickName(String nickName) {
30 | this.nickName = nickName;
31 | }
32 |
33 | public String getRoomType() {
34 | return roomType;
35 | }
36 |
37 | public void setRoomType(String roomType) {
38 | this.roomType = roomType;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Request/EnterRoomReq.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Request;
2 |
3 | public class EnterRoomReq {
4 | private String userID = "";
5 | private String nickName = ""; //用户昵称
6 | private String roomID = "";
7 |
8 | public String getUserID() {
9 | return userID;
10 | }
11 |
12 | public void setUserID(String userID) {
13 | this.userID = userID;
14 | }
15 |
16 | public String getRoomID() {
17 | return roomID;
18 | }
19 |
20 | public void setRoomID(String roomID) {
21 | this.roomID = roomID;
22 | }
23 |
24 | public String getNickName() {
25 | return nickName;
26 | }
27 |
28 | public void setNickName(String nickName) {
29 | this.nickName = nickName;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Request/GetLoginInfoReq.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Request;
2 |
3 | public class GetLoginInfoReq {
4 | private String userID = "";
5 |
6 | public String getUserID() {
7 | return userID;
8 | }
9 |
10 | public void setUserID(String userID) {
11 | this.userID = userID;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Request/GetRoomListReq.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Request;
2 |
3 | public class GetRoomListReq {
4 | private int index = 0; // 起始位置
5 | private int count = 10; // 需要获取的记录条数
6 | private String roomType = ""; //房间类型,可以为空
7 |
8 | public int getIndex() {
9 | return index;
10 | }
11 |
12 | public void setIndex(int index) {
13 | this.index = index;
14 | }
15 |
16 | public int getCount() {
17 | return count;
18 | }
19 |
20 | public void setCount(int count) {
21 | this.count = count;
22 | }
23 |
24 | public String getRoomType() {
25 | return roomType;
26 | }
27 |
28 | public void setRoomType(String roomType) {
29 | this.roomType = roomType;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Request/GetRoomMembersReq.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Request;
2 |
3 | public class GetRoomMembersReq {
4 | private String roomID = "";
5 |
6 | public String getRoomID() {
7 | return roomID;
8 | }
9 |
10 | public void setRoomID(String roomID) {
11 | this.roomID = roomID;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Request/HeartBeatReq.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Request;
2 |
3 | public class HeartBeatReq {
4 | private String userID = "";
5 | private String roomID = "";
6 |
7 | public String getUserID() {
8 | return userID;
9 | }
10 |
11 | public void setUserID(String userID) {
12 | this.userID = userID;
13 | }
14 |
15 | public String getRoomID() {
16 | return roomID;
17 | }
18 |
19 | public void setRoomID(String roomID) {
20 | this.roomID = roomID;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Request/QuitRoomReq.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Request;
2 |
3 | public class QuitRoomReq {
4 | private String userID = "";
5 | private String roomID = "";
6 |
7 | public String getUserID() {
8 | return userID;
9 | }
10 |
11 | public void setUserID(String userID) {
12 | this.userID = userID;
13 | }
14 |
15 | public String getRoomID() {
16 | return roomID;
17 | }
18 |
19 | public void setRoomID(String roomID) {
20 | this.roomID = roomID;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Response/BaseRsp.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Response;
2 |
3 | public class BaseRsp {
4 | private int code = 0;
5 | private String message = "请求成功";
6 |
7 | public int getCode() {
8 | return code;
9 | }
10 |
11 | public void setCode(int code) {
12 | this.code = code;
13 | }
14 |
15 | public String getMessage() {
16 | return message;
17 | }
18 |
19 | public void setMessage(String message) {
20 | this.message = message;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Response/CreateRoomRsp.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Response;
2 |
3 | public class CreateRoomRsp extends BaseRsp {
4 | private String userID = ""; //用户id
5 | private String roomID = ""; // 房间id
6 | private String roomInfo = ""; // 房间名
7 | private String privateMapKey = ""; // 权限位
8 |
9 | public String getUserID() {
10 | return userID;
11 | }
12 |
13 | public void setUserID(String userID) {
14 | this.userID = userID;
15 | }
16 |
17 | public String getRoomID() {
18 | return roomID;
19 | }
20 |
21 | public void setRoomID(String roomID) {
22 | this.roomID = roomID;
23 | }
24 |
25 | public String getRoomInfo() {
26 | return roomInfo;
27 | }
28 |
29 | public void setRoomInfo(String roomInfo) {
30 | this.roomInfo = roomInfo;
31 | }
32 |
33 | public String getPrivateMapKey() {
34 | return privateMapKey;
35 | }
36 |
37 | public void setPrivateMapKey(String privateMapKey) {
38 | this.privateMapKey = privateMapKey;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Response/EnterRoomRsp.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Response;
2 |
3 | public class EnterRoomRsp extends BaseRsp {
4 | private String userID = ""; //用户id
5 | private String roomID = ""; // 房间id
6 | private String privateMapKey = ""; // 权限位
7 |
8 | public String getUserID() {
9 | return userID;
10 | }
11 |
12 | public void setUserID(String userID) {
13 | this.userID = userID;
14 | }
15 |
16 | public String getRoomID() {
17 | return roomID;
18 | }
19 |
20 | public void setRoomID(String roomID) {
21 | this.roomID = roomID;
22 | }
23 |
24 | public String getPrivateMapKey() {
25 | return privateMapKey;
26 | }
27 |
28 | public void setPrivateMapKey(String privateMapKey) {
29 | this.privateMapKey = privateMapKey;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Response/GetLoginInfoRsp.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Response;
2 |
3 | public class GetLoginInfoRsp extends BaseRsp {
4 | private long sdkAppID = 0;
5 | private String accountType = "";
6 | private String userID = "";
7 | private String userSig = "";
8 |
9 | public String getUserID() {
10 | return userID;
11 | }
12 |
13 | public void setUserID(String userID) {
14 | this.userID = userID;
15 | }
16 |
17 | public String getUserSig() {
18 | return userSig;
19 | }
20 |
21 | public void setUserSig(String userSig) {
22 | this.userSig = userSig;
23 | }
24 |
25 |
26 | public long getSdkAppID() {
27 | return sdkAppID;
28 | }
29 |
30 | public void setSdkAppID(long sdkAppID) {
31 | this.sdkAppID = sdkAppID;
32 | }
33 |
34 | public String getAccountType() {
35 | return accountType;
36 | }
37 |
38 | public void setAccountType(String accountType) {
39 | this.accountType = accountType;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Response/GetRoomListRsp.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Response;
2 |
3 | import com.tencent.qcloud.roomservice.webrtc.pojo.WebRTCRoom;
4 |
5 | import java.util.ArrayList;
6 |
7 | public class GetRoomListRsp extends BaseRsp {
8 | private ArrayList rooms;
9 |
10 | public ArrayList getRooms() {
11 | return rooms;
12 | }
13 |
14 | public void setRooms(ArrayList rooms) {
15 | this.rooms = rooms;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/Response/GetRoomMembersRsp.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo.Response;
2 |
3 | import com.tencent.qcloud.roomservice.webrtc.pojo.Member;
4 |
5 | import java.util.ArrayList;
6 |
7 | public class GetRoomMembersRsp extends BaseRsp {
8 | private ArrayList members = new ArrayList<>();
9 |
10 | public ArrayList getMembers() {
11 | return members;
12 | }
13 |
14 | public void setMembers(ArrayList members) {
15 | this.members = members;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/pojo/WebRTCRoom.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.pojo;
2 |
3 | import org.codehaus.jackson.annotate.JsonIgnore;
4 |
5 | import java.util.ArrayList;
6 | import java.util.concurrent.ConcurrentHashMap;
7 |
8 | public class WebRTCRoom {
9 | private String roomID = "";
10 | private String roomCreator = "";
11 | private String roomInfo = "";
12 | private String roomType = ""; //房间类型,可以为空
13 | private ConcurrentHashMap membersMap = new ConcurrentHashMap<>();
14 |
15 | public String getRoomID() {
16 | return roomID;
17 | }
18 |
19 | public void setRoomID(String roomID) {
20 | this.roomID = roomID;
21 | }
22 |
23 | public String getRoomInfo() {
24 | return roomInfo;
25 | }
26 |
27 | public void setRoomInfo(String roomInfo) {
28 | this.roomInfo = roomInfo;
29 | }
30 |
31 |
32 | @JsonIgnore
33 | public int getMembersCnt() {
34 | return membersMap.size();
35 | }
36 |
37 | @JsonIgnore
38 | public ConcurrentHashMap getMembersMap() {
39 | return this.membersMap;
40 | }
41 |
42 | @JsonIgnore
43 | public ArrayList getMembers() {
44 | ArrayList members = new ArrayList<>();
45 | for (Member member : this.membersMap.values()) {
46 | members.add(member);
47 | }
48 | return members;
49 | }
50 |
51 | public void addMember(String userID, String nickName) {
52 | Member member = new Member();
53 | member.setUserID(userID);
54 | member.setNickName(nickName);
55 | member.setTimeStamp(System.currentTimeMillis()/1000);
56 | this.membersMap.put(userID, member);
57 | }
58 |
59 | public void updateMember(String userID) {
60 | Member member = this.membersMap.get(userID);
61 | if (member != null) {
62 | member.setTimeStamp(System.currentTimeMillis()/1000);
63 | }
64 | }
65 |
66 | @JsonIgnore
67 | public boolean isMember(String userID) {
68 | return this.membersMap.containsKey(userID);
69 | }
70 |
71 | public void delMember(String userID) {
72 | this.membersMap.remove(userID);
73 | }
74 |
75 | public String getRoomCreator() {
76 | return roomCreator;
77 | }
78 |
79 | public void setRoomCreator(String roomCreator) {
80 | this.roomCreator = roomCreator;
81 | }
82 |
83 | @JsonIgnore
84 | public String getRoomType() {
85 | return roomType;
86 | }
87 |
88 | public void setRoomType(String roomType) {
89 | this.roomType = roomType;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/service/WebRTCRoomService.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.service;
2 |
3 | import com.tencent.qcloud.roomservice.webrtc.pojo.Request.*;
4 | import com.tencent.qcloud.roomservice.webrtc.pojo.Response.*;
5 |
6 | public interface WebRTCRoomService {
7 | GetLoginInfoRsp getLoginInfo(String userID);
8 | CreateRoomRsp createRoom(CreateRoomReq req);
9 | EnterRoomRsp enterRoom(EnterRoomReq req);
10 | BaseRsp quitRoom(QuitRoomReq req);
11 | BaseRsp heartbeat(HeartBeatReq req);
12 | GetRoomListRsp getRoomList(GetRoomListReq req);
13 | GetRoomMembersRsp getRoomMembers(GetRoomMembersReq roomID);
14 | }
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/service/impl/WebRTCRoomServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.service.impl;
2 |
3 | import com.tencent.qcloud.roomservice.webrtc.common.Config;
4 | import com.tencent.qcloud.roomservice.webrtc.logic.IMMgr;
5 | import com.tencent.qcloud.roomservice.webrtc.logic.WebRTCRoomMgr;
6 | import com.tencent.qcloud.roomservice.webrtc.pojo.Request.*;
7 | import com.tencent.qcloud.roomservice.webrtc.pojo.Response.*;
8 | import com.tencent.qcloud.roomservice.webrtc.service.WebRTCRoomService;
9 | import org.springframework.stereotype.Service;
10 |
11 | import javax.annotation.Resource;
12 | import java.util.regex.Pattern;
13 |
14 | @Service
15 | public class WebRTCRoomServiceImpl implements WebRTCRoomService {
16 | @Resource
17 | WebRTCRoomMgr webRTCRoomMgr;
18 |
19 | @Resource
20 | IMMgr imMgr;
21 |
22 | @Override
23 | public GetLoginInfoRsp getLoginInfo(String userID) {
24 | return imMgr.getLoginInfo(userID);
25 | }
26 |
27 | @Override
28 | public CreateRoomRsp createRoom(CreateRoomReq req) {
29 | CreateRoomRsp rsp = new CreateRoomRsp();
30 | String userID = req.getUserID();
31 | String nickName = req.getNickName();
32 | String roomInfo = req.getRoomInfo();
33 | String roomType = req.getRoomType();
34 |
35 | if (userID == null || userID.length() == 0 || roomInfo == null || roomInfo.length() == 0) {
36 | rsp.setCode(2);
37 | rsp.setMessage("请求失败,缺少参数");
38 | return rsp;
39 | }
40 |
41 | String pattern = "^[a-zA-Z][a-zA-Z0-9_]{3,23}$";
42 | if (!Pattern.matches(pattern, userID)) {
43 | rsp.setCode(7);
44 | rsp.setMessage("请求失败,userID含有非法字符或者不符合规范");
45 | return rsp;
46 | }
47 |
48 | if (roomInfo.length() > 1024) {
49 | rsp.setCode(11);
50 | rsp.setMessage("roomInfo 字符串长度不能超过1024字节");
51 | return rsp;
52 | }
53 |
54 | String roomID = String.valueOf(Math.abs((int)(System.currentTimeMillis())));
55 | // 获取一个可用的roomid
56 | while (webRTCRoomMgr.isRoomExist(roomID)) {
57 | roomID = String.valueOf(Math.abs((int)(System.currentTimeMillis())));
58 | }
59 |
60 | //先获取权限位
61 | String privateMapKey = imMgr.getPrivMapEncrypt(userID, roomID);
62 |
63 | if (privateMapKey.length() == 0) {
64 | rsp.setCode(3);
65 | rsp.setMessage("请求失败,权限位生成失败");
66 | return rsp;
67 | }
68 |
69 | // 再创建房间
70 | webRTCRoomMgr.creatRoom(roomID, userID, nickName, roomInfo, roomType);
71 | rsp.setUserID(userID);
72 | rsp.setRoomID(roomID);
73 | rsp.setRoomInfo(roomInfo);
74 | rsp.setPrivateMapKey(privateMapKey);
75 | return rsp;
76 | }
77 |
78 | @Override
79 | public EnterRoomRsp enterRoom(EnterRoomReq req) {
80 | EnterRoomRsp rsp = new EnterRoomRsp();
81 | String userID = req.getUserID();
82 | String nickName = req.getNickName();
83 | String roomID = req.getRoomID();
84 |
85 | if (userID == null || userID.length() == 0 || roomID == null || roomID.length() == 0) {
86 | rsp.setCode(2);
87 | rsp.setMessage("请求失败,缺少参数");
88 | return rsp;
89 | }
90 |
91 | String pattern = "^[a-zA-Z][a-zA-Z0-9_]{3,23}$";
92 | if (!Pattern.matches(pattern, userID)) {
93 | rsp.setCode(7);
94 | rsp.setMessage("请求失败,userID含有非法字符或者不符合规范");
95 | return rsp;
96 | }
97 |
98 | // 房间不存在
99 | if (!webRTCRoomMgr.isRoomExist(roomID)) {
100 | rsp.setCode(3);
101 | rsp.setMessage("请求失败,房间不存在");
102 | return rsp;
103 | }
104 |
105 | if (webRTCRoomMgr.getMemberCnt(roomID) >= Config.WebRTCRoom.maxMembers) {
106 | rsp.setCode(5001);
107 | rsp.setMessage("超出房间人数上限");
108 | return rsp;
109 | }
110 |
111 | //获取权限位
112 | String privateMapKey = imMgr.getPrivMapEncrypt(userID, roomID);
113 |
114 | if (privateMapKey.length() == 0) {
115 | rsp.setCode(3);
116 | rsp.setMessage("请求失败,权限位生成失败");
117 | return rsp;
118 | }
119 |
120 | webRTCRoomMgr.addMember(roomID, userID, nickName);
121 |
122 | rsp.setUserID(userID);
123 | rsp.setRoomID(roomID);
124 | rsp.setPrivateMapKey(privateMapKey);
125 | return rsp;
126 | }
127 |
128 | @Override
129 | public BaseRsp quitRoom(QuitRoomReq req) {
130 | BaseRsp rsp = new BaseRsp();
131 | String userID = req.getUserID();
132 | String roomID = req.getRoomID();
133 |
134 | if (userID == null || userID.length() == 0 || roomID == null || roomID.length() == 0) {
135 | rsp.setCode(2);
136 | rsp.setMessage("请求失败,缺少参数");
137 | return rsp;
138 | }
139 |
140 | // 房间不存在
141 | if (!webRTCRoomMgr.isRoomExist(roomID)) {
142 | rsp.setCode(3);
143 | rsp.setMessage("请求失败,房间不存在");
144 | return rsp;
145 | }
146 |
147 | // 删除成员
148 | webRTCRoomMgr.delMember(roomID, userID);
149 | return rsp;
150 | }
151 |
152 | @Override
153 | public BaseRsp heartbeat(HeartBeatReq req) {
154 | BaseRsp rsp = new BaseRsp();
155 | String userID = req.getUserID();
156 | String roomID = req.getRoomID();
157 |
158 | if (userID == null || userID.length() == 0 || roomID == null || roomID.length() == 0) {
159 | rsp.setCode(2);
160 | rsp.setMessage("请求失败,缺少参数");
161 | return rsp;
162 | }
163 |
164 | // 房间不存在
165 | if (!webRTCRoomMgr.isRoomExist(roomID)) {
166 | rsp.setCode(3);
167 | rsp.setMessage("请求失败,房间不存在");
168 | return rsp;
169 | }
170 |
171 | // 更新时间戳
172 | webRTCRoomMgr.updateTimeStamp(roomID, userID);
173 | return rsp;
174 | }
175 |
176 | @Override
177 | public GetRoomListRsp getRoomList(GetRoomListReq req) {
178 | GetRoomListRsp rsp = new GetRoomListRsp();
179 | rsp.setRooms(webRTCRoomMgr.getList(req.getCount(), req.getIndex(), req.getRoomType()));
180 | return rsp;
181 | }
182 |
183 | @Override
184 | public GetRoomMembersRsp getRoomMembers(GetRoomMembersReq req) {
185 | GetRoomMembersRsp rsp= new GetRoomMembersRsp();
186 | String roomID = req.getRoomID();
187 |
188 | if (roomID == null || roomID.length() == 0) {
189 | rsp.setCode(2);
190 | rsp.setMessage("请求失败,缺少参数");
191 | return rsp;
192 | }
193 |
194 | // 房间不存在
195 | if (!webRTCRoomMgr.isRoomExist(roomID)) {
196 | rsp.setCode(3);
197 | rsp.setMessage("请求失败,房间不存在");
198 | return rsp;
199 | }
200 |
201 | rsp.setMembers(webRTCRoomMgr.getMembers(roomID));
202 |
203 | return rsp;
204 | }
205 |
206 | }
207 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/utils/RestTemplateConfig.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.utils;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.http.client.ClientHttpRequestFactory;
6 | import org.springframework.http.client.SimpleClientHttpRequestFactory;
7 | import org.springframework.web.client.RestTemplate;
8 |
9 | @Configuration
10 | public class RestTemplateConfig {
11 | @Bean
12 | public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
13 | return new RestTemplate(factory);
14 | }
15 |
16 | @Bean
17 | public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
18 | SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
19 | factory.setReadTimeout(5000);// ms
20 | factory.setConnectTimeout(15000);// ms
21 | return factory;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/tencent/qcloud/roomservice/webrtc/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package com.tencent.qcloud.roomservice.webrtc.utils;
2 |
3 | import org.codehaus.jackson.map.ObjectMapper;
4 |
5 | import java.io.IOException;
6 | import java.io.StringWriter;
7 | import java.math.BigInteger;
8 | import java.security.MessageDigest;
9 | import java.security.NoSuchAlgorithmException;
10 | import java.util.UUID;
11 |
12 | public class Utils {
13 | public static String getMD5(String str) {
14 | try {
15 | MessageDigest md = MessageDigest.getInstance("MD5");
16 | md.update(str.getBytes());
17 | return byteArrayToHex(md.digest());
18 | } catch (NoSuchAlgorithmException e) {
19 | e.printStackTrace();
20 | }
21 | return "";
22 | }
23 |
24 | public static String byteArrayToHex(byte[] byteArray) {
25 | char[] hexDigits = {'0','1','2','3','4','5','6','7','8','9', 'a','b','c','d','e','f' };
26 | char[] resultCharArray =new char[byteArray.length * 2];
27 | int index = 0;
28 | for (byte b : byteArray) {
29 | resultCharArray[index++] = hexDigits[b>>>4 & 0xf];
30 | resultCharArray[index++] = hexDigits[b & 0xf];
31 | }
32 | return new String(resultCharArray);
33 | }
34 |
35 | public static String S4 () {
36 | return UUID.randomUUID().toString().substring(9, 13);
37 | }
38 |
39 | /**
40 | * 随机生成user_id
41 | */
42 | public static String genUserIdByRandom () {
43 | return "user_" + (S4() + S4() + "_" + S4());
44 | }
45 |
46 | /**
47 | * 随机生成room_id
48 | */
49 | public static String genRoomIdByRandom () {
50 | return "room_" + (S4() + S4() + "_" + S4());
51 | }
52 |
53 | public static String objectToString(Object obj){
54 | ObjectMapper mapper = new ObjectMapper();
55 | StringWriter writer = new StringWriter();
56 |
57 | try {
58 | mapper.writeValue(writer, obj);
59 | return writer.toString();
60 | } catch (IOException e) {
61 | e.printStackTrace();
62 | }
63 | return "{}";
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/tls/WebRTCSigApi.java:
--------------------------------------------------------------------------------
1 | package com.tls;
2 |
3 | import java.nio.charset.Charset;
4 | import java.security.KeyFactory;
5 | import java.security.PrivateKey;
6 | import java.security.PublicKey;
7 | import java.security.Signature;
8 | import java.security.spec.PKCS8EncodedKeySpec;
9 | import java.security.spec.X509EncodedKeySpec;
10 | import java.util.Arrays;
11 | import java.util.Base64;
12 | import java.util.zip.Deflater;
13 |
14 | public class WebRTCSigApi {
15 | private int mSdkAppid = 0;
16 | private PrivateKey mPrivateKey = null;
17 | private PublicKey mPublicKey = null;
18 |
19 | /**
20 | * 设置sdkappid
21 | * @param sdkappid
22 | */
23 | public void setSdkAppid(int sdkappid) {
24 | this.mSdkAppid = sdkappid;
25 | }
26 |
27 | /**
28 | * 设置私钥 如果要生成userSig和privMapEncrypt则需要私钥
29 | * @param privateKey 私钥文件内容
30 | */
31 | public void setPrivateKey(String privateKey) {
32 | String privateKeyPEM = privateKey.replace("-----BEGIN PRIVATE KEY-----", "")
33 | .replace("-----END PRIVATE KEY-----", "")
34 | .replace("\n", "");
35 | byte[] encodedKey = Base64.getDecoder().decode(privateKeyPEM.getBytes());
36 |
37 | try {
38 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
39 | KeyFactory keyFactory = KeyFactory.getInstance("EC");
40 | this.mPrivateKey = keyFactory.generatePrivate(keySpec);
41 | } catch (Exception e) {
42 | e.printStackTrace();
43 | }
44 | }
45 |
46 | /**
47 | * 设置公钥 如果要验证userSig和privMapEncrypt则需要公钥
48 | * @param publicKey 公钥文件内容
49 | */
50 | public void setPublicKey(String publicKey) {
51 | String publicKeyPEM = publicKey.replace("-----BEGIN PUBLIC KEY-----", "")
52 | .replace("-----END PUBLIC KEY-----", "")
53 | .replace("\n", "");
54 | byte[] encodedKey = Base64.getDecoder().decode(publicKeyPEM.getBytes());
55 |
56 | try {
57 | X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
58 | KeyFactory keyFactory = KeyFactory.getInstance("EC");
59 | this.mPublicKey = keyFactory.generatePublic(keySpec);
60 | } catch (Exception e) {
61 | e.printStackTrace();
62 | }
63 | }
64 |
65 | /**
66 | * ECDSA-SHA256签名
67 | * @param data 需要签名的数据
68 | * @return 签名
69 | */
70 | public byte[] sign(byte[] data) {
71 | try {
72 | Signature signer = Signature.getInstance("SHA256withECDSA");
73 | signer.initSign(this.mPrivateKey);
74 | signer.update(data);
75 | return signer.sign();
76 | } catch (Exception e) {
77 | e.printStackTrace();
78 | }
79 | return null;
80 | }
81 |
82 | /**
83 | * 验证ECDSA-SHA256签名
84 | * @param data 需要验证的数据原文
85 | * @param sig 需要验证的签名
86 | * @return true:验证成功 false:验证失败
87 | */
88 | public boolean verify(byte[] data, byte[] sig) {
89 | try {
90 | Signature signer = Signature.getInstance("SHA256withECDSA");
91 | signer.initVerify(this.mPublicKey);
92 | signer.update(data);
93 | return signer.verify(sig);
94 | } catch (Exception e) {
95 | e.printStackTrace();
96 | }
97 | return false;
98 | }
99 |
100 | /**
101 | * 用于url的base64encode
102 | * '+' => '*', '/' => '-', '=' => '_'
103 | * @param data 需要编码的数据
104 | * @return 编码后的base64数据
105 | */
106 | private byte[] base64UrlEncode(byte[] data) {
107 | byte[] encode = Base64.getEncoder().encode(data);
108 | for (int i = 0; i < encode.length; i++) {
109 | if (encode[i] == '+') {
110 | encode[i] = '*';
111 | } else if (encode[i] == '/') {
112 | encode[i] = '-';
113 | } else if (encode[i] == '=') {
114 | encode[i] = '_';
115 | }
116 | }
117 | return encode;
118 | }
119 |
120 | /**
121 | * 用于url的base64decode
122 | * '*' => '+', '-' => '/', '_' => '='
123 | * @param data 需要解码的数据
124 | * @return 解码后的数据
125 | */
126 | private byte[] base64UrlDecode(byte[] data) {
127 | byte[] encode = Arrays.copyOf(data, data.length);
128 | for (int i = 0; i < encode.length; i++) {
129 | if (encode[i] == '*') {
130 | encode[i] = '+';
131 | } else if (encode[i] == '-') {
132 | encode[i] = '/';
133 | } else if (encode[i] == '_') {
134 | encode[i] = '=';
135 | }
136 | }
137 | return encode;
138 | }
139 |
140 | /**
141 | * 生成userSig
142 | * @param userid 用户名
143 | * @param expire userSig有效期,建议为300秒
144 | * @return 生成的userSig
145 | */
146 | public String genUserSig(String userid, int expire) {
147 | String time = String.valueOf(System.currentTimeMillis()/1000);
148 | String serialString =
149 | "TLS.appid_at_3rd:" + 0 + "\n" +
150 | "TLS.account_type:" + 0 + "\n" +
151 | "TLS.identifier:" + userid + "\n" +
152 | "TLS.sdk_appid:" + this.mSdkAppid + "\n" +
153 | "TLS.time:" + time + "\n" +
154 | "TLS.expire_after:" + expire +"\n";
155 |
156 | byte[] signBytes = sign(serialString.getBytes(Charset.forName("UTF-8")));
157 | String sig = Base64.getEncoder().encodeToString(signBytes);
158 |
159 | String jsonString = "{"
160 | + "\"TLS.account_type\":\"" + 0 +"\","
161 | +"\"TLS.identifier\":\"" + userid +"\","
162 | +"\"TLS.appid_at_3rd\":\"" + 0 +"\","
163 | +"\"TLS.sdk_appid\":\"" + this.mSdkAppid +"\","
164 | +"\"TLS.expire_after\":\"" + expire +"\","
165 | +"\"TLS.sig\":\"" + sig +"\","
166 | +"\"TLS.time\":\"" + time +"\","
167 | +"\"TLS.version\": \"201512300000\""
168 | +"}";
169 |
170 | //compression
171 | Deflater compresser = new Deflater();
172 | compresser.setInput(jsonString.getBytes(Charset.forName("UTF-8")));
173 |
174 | compresser.finish();
175 | byte [] compressBytes = new byte [512];
176 | int compressBytesLength = compresser.deflate(compressBytes);
177 | compresser.end();
178 | String userSig = new String(base64UrlEncode(Arrays.copyOfRange(compressBytes, 0, compressBytesLength)));
179 |
180 | return userSig;
181 | }
182 |
183 | /**
184 | * 生成privMapEncrypt
185 | * @param userid 用户名
186 | * @param roomid 房间号
187 | * @param expire privMapEncrypt有效期,建议为300秒
188 | * @return 生成的privMapEncrypt
189 | */
190 | public String genPrivMapEncrypt(String userid, int roomid, int expire) {
191 | String time = String.valueOf(System.currentTimeMillis()/1000);
192 |
193 | //视频校验位需要用到的字段
194 | /*
195 | cVer unsigned char/1 版本号,填0
196 | wAccountLen unsigned short /2 第三方自己的帐号长度
197 | buffAccount wAccountLen 第三方自己的帐号字符
198 | dwSdkAppid unsigned int/4 sdkappid
199 | dwRoomId unsigned int/4 群组号码
200 | dwExpTime unsigned int/4 过期时间 (当前时间 + 有效期(单位:秒,建议300秒))
201 | dwPrivilegeMap unsigned int/4 权限位
202 | dwAccountType unsigned int/4 第三方帐号类型
203 | */
204 | int accountLength = userid.length();
205 | int offset = 0;
206 | byte[] bytes = new byte[1+2+accountLength+4+4+4+4+4];
207 | bytes[offset++] = 0;
208 | bytes[offset++] = (byte)((accountLength & 0xFF00) >> 8);
209 | bytes[offset++] = (byte)(accountLength & 0x00FF);
210 |
211 | for (; offset < 3 + accountLength; ++offset) {
212 | bytes[offset] = (byte)userid.charAt(offset - 3);
213 | }
214 | bytes[offset++] = (byte)((this.mSdkAppid & 0xFF000000) >> 24);
215 | bytes[offset++] = (byte)((this.mSdkAppid & 0x00FF0000) >> 16);
216 | bytes[offset++] = (byte)((this.mSdkAppid & 0x0000FF00) >> 8);
217 | bytes[offset++] = (byte)(this.mSdkAppid & 0x000000FF);
218 |
219 | long nRoomId = Long.valueOf(roomid);
220 | bytes[offset++] = (byte)((nRoomId & 0xFF000000) >> 24);
221 | bytes[offset++] = (byte)((nRoomId & 0x00FF0000) >> 16);
222 | bytes[offset++] = (byte)((nRoomId & 0x0000FF00) >> 8);
223 | bytes[offset++] = (byte)(nRoomId & 0x000000FF);
224 |
225 | long expiredTime = Long.valueOf(time) + expire;
226 | bytes[offset++] = (byte)((expiredTime & 0xFF000000) >> 24);
227 | bytes[offset++] = (byte)((expiredTime & 0x00FF0000) >> 16);
228 | bytes[offset++] = (byte)((expiredTime & 0x0000FF00) >> 8);
229 | bytes[offset++] = (byte)(expiredTime & 0x000000FF);
230 |
231 | bytes[offset++] = (byte)((255 & 0xFF000000) >> 24);
232 | bytes[offset++] = (byte)((255 & 0x00FF0000) >> 16);
233 | bytes[offset++] = (byte)((255 & 0x0000FF00) >> 8);
234 | bytes[offset++] = (byte)(255 & 0x000000FF);
235 |
236 | bytes[offset++] = (byte)((0 & 0xFF000000) >> 24);
237 | bytes[offset++] = (byte)((0 & 0x00FF0000) >> 16);
238 | bytes[offset++] = (byte)((0 & 0x0000FF00) >> 8);
239 | bytes[offset++] = (byte)(0 & 0x000000FF);
240 |
241 | String userbuf = Base64.getEncoder().encodeToString(bytes);
242 |
243 | String serialString =
244 | "TLS.appid_at_3rd:" + 0 + "\n" +
245 | "TLS.account_type:" + 0 + "\n" +
246 | "TLS.identifier:" + userid + "\n" +
247 | "TLS.sdk_appid:" + this.mSdkAppid + "\n" +
248 | "TLS.time:" + time + "\n" +
249 | "TLS.expire_after:" + expire +"\n" +
250 | "TLS.userbuf:" + userbuf + "\n";
251 |
252 | byte[] signBytes = sign(serialString.getBytes(Charset.forName("UTF-8")));
253 | String sig = Base64.getEncoder().encodeToString(signBytes);
254 |
255 | String jsonString = "{"
256 | +"\"TLS.appid_at_3rd\":\"" + 0 +"\","
257 | +"\"TLS.account_type\":\"" + 0 +"\","
258 | +"\"TLS.identifier\":\"" + userid +"\","
259 | +"\"TLS.sdk_appid\":\"" + this.mSdkAppid +"\","
260 | +"\"TLS.expire_after\":\"" + expire +"\","
261 | +"\"TLS.sig\":\"" + sig +"\","
262 | +"\"TLS.time\":\"" + time +"\","
263 | +"\"TLS.userbuf\":\"" + userbuf +"\","
264 | +"\"TLS.version\": \"201512300000\""
265 | +"}";
266 |
267 | //compression
268 | Deflater compresser = new Deflater();
269 | compresser.setInput(jsonString.getBytes(Charset.forName("UTF-8")));
270 |
271 | compresser.finish();
272 | byte [] compressBytes = new byte [512];
273 | int compressBytesLength = compresser.deflate(compressBytes);
274 | compresser.end();
275 | String privMapEncrypt = new String(base64UrlEncode(Arrays.copyOfRange(compressBytes, 0, compressBytesLength)));
276 |
277 | return privMapEncrypt;
278 | }
279 |
280 |
281 | public static void main(String[] args) {
282 | System.out.println("hello world");
283 |
284 | //云通信私钥字符串
285 | String privStr = "-----BEGIN PRIVATE KEY-----\n" +
286 | "\n" +
287 | "\n" +
288 | "\n" +
289 | "-----END PRIVATE KEY-----";
290 |
291 | //云通信公钥字符串
292 | String pubStr = "-----BEGIN PUBLIC KEY-----\n"+
293 | "\n"+
294 | "\n"+
295 | "-----END PUBLIC KEY-----";
296 |
297 | int sdkappid = 0; //云通信sdkappid
298 | String userid = "webrtc98"; //用户id
299 | int roomid = 1234; //房间id
300 |
301 |
302 | WebRTCSigApi api = new WebRTCSigApi();
303 | api.setSdkAppid(sdkappid);
304 | api.setPrivateKey(privStr);
305 | api.setPublicKey(pubStr);
306 |
307 | String userSig = api.genUserSig(userid, 300);
308 | String privMapEncrypt = api.genPrivMapEncrypt(userid, roomid, 300);
309 |
310 | System.out.println("userSig:\n" + userSig);
311 | System.out.println("privMapEncrypt:\n" + privMapEncrypt);
312 | }
313 |
314 | }
315 |
--------------------------------------------------------------------------------
/src/main/resources/applicationContext.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | UTF-8
5 |
6 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n
7 |
8 |
9 | DEBUG
10 |
11 |
12 |
13 |
14 | ${CATALINA_HOME}/logs/roomservice_webrtc_info.log
15 |
16 | ${CATALINA_HOME}/logs/roomservice_webrtc_info.log.%d{yyyy-MM-dd}.gz
17 | true
18 | 10
19 |
20 |
21 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n
22 |
23 |
24 | INFO
25 | ACCEPT
26 | DENY
27 |
28 |
29 |
30 |
31 | ${CATALINA_HOME}/logs/roomservice_webrtc_warn.log
32 |
33 | ${CATALINA_HOME}/logs/roomservice_webrtc_warn.log.%d{yyyy-MM-dd}.gz
34 | true
35 | 10
36 |
37 |
38 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n
39 |
40 |
41 | WARN
42 | ACCEPT
43 | DENY
44 |
45 |
46 |
47 |
48 |
49 | ${CATALINA_HOME}/logs/roomservice_webrtc_error.log
50 |
51 | ${CATALINA_HOME}/logs/roomservice_webrtc_error.log.%d{yyyy-MM-dd}.gz
52 | true
53 | 10
54 |
55 |
56 | [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n
57 |
58 |
59 | ERROR
60 | ACCEPT
61 | DENY
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/dispatcher-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | text/plain;charset=UTF-8
26 | text/html;charset=UTF-8
27 |
28 |
29 |
30 |
31 |
32 |
33 | application/json;charset=UTF-8
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 | Archetype Created Web Application
6 |
7 |
8 | CorsFilter
9 | com.tencent.qcloud.roomservice.webrtc.common.CORSFilter
10 |
11 |
12 | CorsFilter
13 | /*
14 |
15 |
16 |
17 |
18 |
19 | characterEncodingFilter
20 | org.springframework.web.filter.CharacterEncodingFilter
21 |
22 | encoding
23 | UTF-8
24 |
25 |
26 | forceEncoding
27 | true
28 |
29 |
30 |
31 | characterEncodingFilter
32 | /*
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.springframework.web.context.request.RequestContextListener
40 |
41 |
42 |
43 |
44 | org.springframework.web.context.ContextLoaderListener
45 |
46 |
47 | contextConfigLocation
48 |
49 | classpath:applicationContext.xml
50 |
51 |
52 |
53 |
54 |
55 | dispatcher
56 | org.springframework.web.servlet.DispatcherServlet
57 | 1
58 |
59 |
60 |
61 | dispatcher
62 | /
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------
/webrtc.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------