mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-12-17 12:42:51 +08:00
Compare commits
12 Commits
1f6a2182be
...
v1.1.14-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2654ea9db | ||
|
|
8f8e415262 | ||
|
|
5ff624f7b2 | ||
|
|
e09243f1ec | ||
|
|
f5941c7eda | ||
|
|
3c2ebe602e | ||
|
|
2f64172ead | ||
|
|
a83206a346 | ||
|
|
46e769976f | ||
|
|
58c24b798e | ||
|
|
5cc31e5ba3 | ||
|
|
74fe9bebf5 |
2
.github/ISSUE_TEMPLATE/问题反馈.md
vendored
2
.github/ISSUE_TEMPLATE/问题反馈.md
vendored
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: 问题反馈
|
name: 问题反馈
|
||||||
about: Create a report to help us improve
|
about: 请在此提交问题报告,以便持续优化产品。
|
||||||
title: ''
|
title: ''
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: kunkundi
|
assignees: kunkundi
|
||||||
|
|||||||
28
.github/ISSUE_TEMPLATE/需求建议.md
vendored
Normal file
28
.github/ISSUE_TEMPLATE/需求建议.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
name: 需求建议
|
||||||
|
about: 请在此提交功能需求或改进建议,以便后续迭代参考。
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: kunkundi
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**功能/改进建议描述**
|
||||||
|
清晰简洁地描述希望新增的功能或改进的内容。
|
||||||
|
|
||||||
|
**使用场景 / 背景**
|
||||||
|
说明该功能或改进的使用场景,以及解决后带来的价值。
|
||||||
|
|
||||||
|
**预期效果**
|
||||||
|
描述你认为最理想的功能表现或改进效果。
|
||||||
|
|
||||||
|
**参考示例(可选)**
|
||||||
|
提供类似功能截图、参考链接或其他说明,帮助更好理解需求。
|
||||||
|
|
||||||
|
**优先级(可选)**
|
||||||
|
- [ ] 高
|
||||||
|
- [ ] 中
|
||||||
|
- [ ] 低
|
||||||
|
|
||||||
|
**补充信息(可选)**
|
||||||
|
其他相关信息或特殊要求。
|
||||||
175
README.md
175
README.md
@@ -169,7 +169,7 @@ xmake r -d crossdesk
|
|||||||
|
|
||||||
## 自托管服务器
|
## 自托管服务器
|
||||||
推荐使用Docker部署CrossDesk Server。
|
推荐使用Docker部署CrossDesk Server。
|
||||||
```
|
```bash
|
||||||
sudo docker run -d \
|
sudo docker run -d \
|
||||||
--name crossdesk_server \
|
--name crossdesk_server \
|
||||||
--network host \
|
--network host \
|
||||||
@@ -179,158 +179,69 @@ sudo docker run -d \
|
|||||||
-e COTURN_PORT=xxxx \
|
-e COTURN_PORT=xxxx \
|
||||||
-e MIN_PORT=xxxxx \
|
-e MIN_PORT=xxxxx \
|
||||||
-e MAX_PORT=xxxxx \
|
-e MAX_PORT=xxxxx \
|
||||||
-v /path/to/your/certs:/crossdesk-server/certs \
|
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||||
-v /path/to/your/db:/crossdesk-server/db \
|
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||||
-v /path/to/your/logs:/crossdesk-server/logs \
|
crossdesk/crossdesk-server:v1.1.3
|
||||||
crossdesk/crossdesk-server:v1.1.1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
上述命令中,用户需注意的参数如下:
|
上述命令中,用户需注意的参数如下:
|
||||||
|
|
||||||
|
**参数**
|
||||||
- EXTERNAL_IP:服务器公网 IP , 对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器地址**
|
- EXTERNAL_IP:服务器公网 IP , 对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器地址**
|
||||||
|
|
||||||
- INTERNAL_IP:服务器内网 IP
|
- INTERNAL_IP:服务器内网 IP
|
||||||
|
|
||||||
- CROSSDESK_SERVER_PORT:自托管服务使用的端口,对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器端口**
|
- CROSSDESK_SERVER_PORT:自托管服务使用的端口,对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器端口**
|
||||||
|
|
||||||
- COTURN_PORT: COTURN 服务使用的端口, 对应 CrossDesk 客户端**自托管服务器配置**中填写的**中继服务端口**
|
- COTURN_PORT: COTURN 服务使用的端口, 对应 CrossDesk 客户端**自托管服务器配置**中填写的**中继服务端口**
|
||||||
|
|
||||||
- MIN_PORT/MAX_PORT:COTURN 服务使用的端口范围,例如:MIN_PORT=50000, MAX_PORT=60000,范围可根据客户端数量调整。
|
- MIN_PORT/MAX_PORT:COTURN 服务使用的端口范围,例如:MIN_PORT=50000, MAX_PORT=60000,范围可根据客户端数量调整。
|
||||||
|
- `-v /var/lib/crossdesk:/var/lib/crossdesk`:持久化数据库和证书文件到宿主机
|
||||||
|
- `-v /var/log/crossdesk:/var/log/crossdesk`:持久化日志文件到宿主机
|
||||||
|
|
||||||
- /path/to/your/certs:证书文件目录
|
**示例**:
|
||||||
|
```bash
|
||||||
- /path/to/your/db:CrossDesk Server 设备管理数据库
|
sudo docker run -d \
|
||||||
|
--name crossdesk_server \
|
||||||
- /path/to/your/logs:日志目录
|
--network host \
|
||||||
|
-e EXTERNAL_IP=114.114.114.114 \
|
||||||
|
-e INTERNAL_IP=10.0.0.1 \
|
||||||
|
-e CROSSDESK_SERVER_PORT=9099 \
|
||||||
|
-e COTURN_PORT=3478 \
|
||||||
|
-e MIN_PORT=50000 \
|
||||||
|
-e MAX_PORT=60000 \
|
||||||
|
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||||
|
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||||
|
crossdesk/crossdesk-server:v1.1.3
|
||||||
|
```
|
||||||
|
|
||||||
**注意**:
|
**注意**:
|
||||||
- **/path/to/your/ 是示例路径,请替换为你自己的实际路径。挂载的目录必须事先创建好,否则容器会报错。**
|
- **服务器需开放端口:COTURN_PORT/udp,COTURN_PORT/tcp,MIN_PORT-MAX_PORT/udp,CROSSDESK_SERVER_PORT/tcp。**
|
||||||
- **服务器需开放端口:3478/udp,3478/tcp,MIN_PORT-MAX_PORT/udp,CROSSDESK_SERVER_PORT/tcp。**
|
- 如果不挂载 volume,容器删除后数据会丢失
|
||||||
|
- 证书文件会在首次启动时自动生成并持久化到宿主机的 `/var/lib/crossdesk/certs` 路径下
|
||||||
|
- 数据库文件会自动创建并持久化到宿主机的 `/var/lib/crossdesk/db/crossdesk-server.db` 路径下
|
||||||
|
- 日志文件会自动创建并持久化到宿主机的 `/var/log/crossdesk/` 路径下
|
||||||
|
|
||||||
## 证书文件
|
**权限注意**:如果 Docker 自动创建的目录权限不足(属于 root),容器内用户无法写入,会导致:
|
||||||
客户端需加载根证书文件,服务端需加载服务器私钥和服务器证书文件。
|
- 证书生成失败,容器启动脚本会报错退出
|
||||||
|
- 数据库目录创建失败,程序会抛出异常并崩溃
|
||||||
如果已有SSL证书的用户,可以忽略下面的证书生成步骤。
|
- 日志目录创建失败,日志文件无法写入(但程序可能继续运行)
|
||||||
|
|
||||||
对于无证书的用户,可使用下面的脚本自行生成证书文件:
|
**解决方案**:在启动容器前手动设置权限:
|
||||||
```
|
```bash
|
||||||
# 创建证书生成脚本
|
sudo mkdir -p /var/lib/crossdesk /var/log/crossdesk
|
||||||
vim generate_certs.sh
|
sudo chown -R $(id -u):$(id -g) /var/lib/crossdesk /var/log/crossdesk
|
||||||
```
|
|
||||||
拷贝到脚本中
|
|
||||||
```
|
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# 检查参数
|
|
||||||
if [ "$#" -ne 1 ]; then
|
|
||||||
echo "Usage: $0 <SERVER_IP>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
SERVER_IP="$1"
|
|
||||||
|
|
||||||
# 文件名
|
|
||||||
ROOT_KEY="crossdesk.cn_root.key"
|
|
||||||
ROOT_CERT="crossdesk.cn_root.crt"
|
|
||||||
SERVER_KEY="crossdesk.cn.key"
|
|
||||||
SERVER_CSR="crossdesk.cn.csr"
|
|
||||||
SERVER_CERT="crossdesk.cn_bundle.crt"
|
|
||||||
FULLCHAIN_CERT="crossdesk.cn_fullchain.crt"
|
|
||||||
|
|
||||||
# 证书主题
|
|
||||||
SUBJ="/C=CN/ST=Zhejiang/L=Hangzhou/O=CrossDesk/OU=CrossDesk/CN=$SERVER_IP"
|
|
||||||
|
|
||||||
# 1. 生成根证书
|
|
||||||
echo "Generating root private key..."
|
|
||||||
openssl genrsa -out "$ROOT_KEY" 4096
|
|
||||||
|
|
||||||
echo "Generating self-signed root certificate..."
|
|
||||||
openssl req -x509 -new -nodes -key "$ROOT_KEY" -sha256 -days 3650 -out "$ROOT_CERT" -subj "$SUBJ"
|
|
||||||
|
|
||||||
# 2. 生成服务器私钥
|
|
||||||
echo "Generating server private key..."
|
|
||||||
openssl genrsa -out "$SERVER_KEY" 2048
|
|
||||||
|
|
||||||
# 3. 生成服务器 CSR
|
|
||||||
echo "Generating server CSR..."
|
|
||||||
openssl req -new -key "$SERVER_KEY" -out "$SERVER_CSR" -subj "$SUBJ"
|
|
||||||
|
|
||||||
# 4. 生成临时 OpenSSL 配置文件,加入 SAN
|
|
||||||
SAN_CONF="san.cnf"
|
|
||||||
cat > $SAN_CONF <<EOL
|
|
||||||
[ req ]
|
|
||||||
default_bits = 2048
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
req_extensions = req_ext
|
|
||||||
prompt = no
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
C = CN
|
|
||||||
ST = Zhejiang
|
|
||||||
L = Hangzhou
|
|
||||||
O = CrossDesk
|
|
||||||
OU = CrossDesk
|
|
||||||
CN = $SERVER_IP
|
|
||||||
|
|
||||||
[ req_ext ]
|
|
||||||
subjectAltName = IP:$SERVER_IP
|
|
||||||
EOL
|
|
||||||
|
|
||||||
# 5. 用根证书签发服务器证书(包含 SAN)
|
|
||||||
echo "Signing server certificate with root certificate..."
|
|
||||||
openssl x509 -req -in "$SERVER_CSR" -CA "$ROOT_CERT" -CAkey "$ROOT_KEY" -CAcreateserial \
|
|
||||||
-out "$SERVER_CERT" -days 3650 -sha256 -extfile "$SAN_CONF" -extensions req_ext
|
|
||||||
|
|
||||||
# 6. 生成完整链证书
|
|
||||||
cat "$SERVER_CERT" "$ROOT_CERT" > "$FULLCHAIN_CERT"
|
|
||||||
|
|
||||||
# 7. 清理中间文件
|
|
||||||
rm -f "$ROOT_CERT.srl" "$SAN_CONF" "$ROOT_KEY" "$SERVER_CSR" "FULLCHAIN_CERT"
|
|
||||||
|
|
||||||
echo "Generation complete. Deployment files:"
|
|
||||||
echo " Client root certificate: $ROOT_CERT"
|
|
||||||
echo " Server private key: $SERVER_KEY"
|
|
||||||
echo " Server certificate: $SERVER_CERT"
|
|
||||||
```
|
|
||||||
执行
|
|
||||||
```
|
|
||||||
chmod +x generate_certs.sh
|
|
||||||
./generate_certs.sh 服务器公网IP
|
|
||||||
|
|
||||||
# 例如 ./generate_certs.sh 111.111.111.111
|
|
||||||
```
|
|
||||||
输出如下:
|
|
||||||
```
|
|
||||||
Generating root private key...
|
|
||||||
Generating self-signed root certificate...
|
|
||||||
Generating server private key...
|
|
||||||
Generating server CSR...
|
|
||||||
Signing server certificate with root certificate...
|
|
||||||
Certificate request self-signature ok
|
|
||||||
subject=C = CN, ST = Zhejiang, L = Hangzhou, O = CrossDesk, OU = CrossDesk, CN = xxx.xxx.xxx.xxx
|
|
||||||
cleaning up intermediate files...
|
|
||||||
Generation complete. Deployment files::
|
|
||||||
Client root certificate:: crossdesk.cn_root.crt
|
|
||||||
Server private key: crossdesk.cn.key
|
|
||||||
Server certificate: crossdesk.cn_bundle.crt
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 服务端
|
|
||||||
将 **crossdesk.cn.key** 和 **crossdesk.cn_bundle.crt** 放置到 **/path/to/your/certs** 目录下。
|
|
||||||
|
|
||||||
### 客户端
|
### 客户端
|
||||||
1. 点击右上角设置进入设置页面。<br>
|
1. 点击右上角设置进入设置页面。<br><br>
|
||||||
<img width="600" height="210" alt="image" src="https://github.com/user-attachments/assets/6431131d-b32a-4726-8783-6788f47baa3b" /><br><br>
|
<img width="600" height="210" alt="image" src="https://github.com/user-attachments/assets/6431131d-b32a-4726-8783-6788f47baa3b" /><br><br>
|
||||||
|
|
||||||
3. 点击点击**自托管服务器配置**。<br><br>
|
2. 点击点击`自托管服务器配置`按钮。<br><br>
|
||||||
<img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/24c761a3-1985-4d7e-84be-787383c2afb8" /><br><br>
|
<img width="600" height="140" alt="image" src="https://github.com/user-attachments/assets/24c761a3-1985-4d7e-84be-787383c2afb8" /><br><br>
|
||||||
|
|
||||||
5. 在**证书文件路径**选择框中找到 **crossdesk.cn_root.crt** 的存放路径,选中 **crossdesk.cn_root.crt**,点击确认。<br><br>
|
3. 输入`服务器地址`(**EXTERNAL_IP**)、`信令服务端口`(**CROSSDESK_SERVER_PORT**)、`中继服务端口`(**COTURN_PORT**)。<br><br>
|
||||||
<img width="600" height="220" alt="image" src="https://github.com/user-attachments/assets/4af7cd3a-c72e-44fb-b032-30e050019c2a" /><br><br>
|
<img width="600" height="200" alt="image" src="https://github.com/user-attachments/assets/9a32ddd5-37f8-4bee-9a51-eae295820f9a" /><br><br>
|
||||||
|
|
||||||
7. 勾选使用**自托管服务器配置**,点击确认配置生效。<br><br>
|
4. 后续如果自托管服务器被重置或因其他原因导致证书更换,可以点击`重置证书指纹`按钮重置客户端保存的证书指纹。<br><br>
|
||||||
<img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/1e455dc3-4087-4f37-a544-1ff9f8789383" /><br><br>
|
<img width="600" height="200" alt="image" src="https://github.com/user-attachments/assets/d9e423ab-0c2b-4fab-b132-4dc27462d704" /><br><br>
|
||||||
|
|
||||||
### Web 客户端
|
### Web 客户端
|
||||||
详情见项目 [CrossDesk Web Client](https://github.com/kunkundi/crossdesk-web-client)。
|
详情见项目 [CrossDesk Web Client](https://github.com/kunkundi/crossdesk-web-client)。
|
||||||
|
|||||||
178
README_EN.md
178
README_EN.md
@@ -187,158 +187,72 @@ sudo docker run -d \
|
|||||||
-e COTURN_PORT=xxxx \
|
-e COTURN_PORT=xxxx \
|
||||||
-e MIN_PORT=xxxxx \
|
-e MIN_PORT=xxxxx \
|
||||||
-e MAX_PORT=xxxxx \
|
-e MAX_PORT=xxxxx \
|
||||||
-v /path/to/your/certs:/crossdesk-server/certs \
|
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||||
-v /path/to/your/db:/crossdesk-server/db \
|
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||||
-v /path/to/your/logs:/crossdesk-server/logs \
|
crossdesk/crossdesk-server:v1.1.3
|
||||||
crossdesk/crossdesk-server:v1.1.1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The parameters you need to pay attention to are as follows:
|
The parameters you need to pay attention to are as follows:
|
||||||
|
|
||||||
- **EXTERNAL_IP**: The server's public IP, corresponding to the **Server Address** in the CrossDesk client **Self-Hosted Server Configuration**.
|
**Parameters**
|
||||||
|
- **EXTERNAL_IP**: The server’s public IP. This corresponds to **Server Address** in the CrossDesk client’s **Self-Hosted Server Configuration**.
|
||||||
|
- **INTERNAL_IP**: The server’s internal IP.
|
||||||
|
- **CROSSDESK_SERVER_PORT**: The port used by the self-hosted service. This corresponds to **Server Port** in the CrossDesk client’s **Self-Hosted Server Configuration**.
|
||||||
|
- **COTURN_PORT**: The port used by the COTURN service. This corresponds to **Relay Service Port** in the CrossDesk client’s **Self-Hosted Server Configuration**.
|
||||||
|
- **MIN_PORT / MAX_PORT**: The port range used by the COTURN service. Example: `MIN_PORT=50000`, `MAX_PORT=60000`. Adjust the range depending on the number of clients.
|
||||||
|
- `-v /var/lib/crossdesk:/var/lib/crossdesk`: Persists database and certificate files on the host machine.
|
||||||
|
- `-v /var/log/crossdesk:/var/log/crossdesk`: Persists log files on the host machine.
|
||||||
|
|
||||||
- **INTERNAL_IP**: The server's internal IP.
|
**Example**:
|
||||||
|
```bash
|
||||||
- **CROSSDESK_SERVER_PORT**: The port used by the self-hosted server, corresponding to the **Server Port** in the CrossDesk client **Self-Hosted Server Configuration**.
|
sudo docker run -d \
|
||||||
|
--name crossdesk_server \
|
||||||
- **COTURN_PORT**: The port used by Coturn, corresponding to the **Relay Server Port** in the CrossDesk client **Self-Hosted Server Configuration**.
|
--network host \
|
||||||
|
-e EXTERNAL_IP=114.114.114.114 \
|
||||||
- **MIN_PORT** and **MAX_PORT**: The range of ports used by the self-hosted server, corresponding to the **Minimum Port** and **Maximum Port** in the CrossDesk client **Self-Hosted Server Configuration**. Example: 50000-60000. It depends on the number of devices connected to the server.
|
-e INTERNAL_IP=10.0.0.1 \
|
||||||
|
-e CROSSDESK_SERVER_PORT=9099 \
|
||||||
- **/path/to/your/certs**: Directory for certificate files.
|
-e COTURN_PORT=3478 \
|
||||||
|
-e MIN_PORT=50000 \
|
||||||
- **/path/to/your/db**: CrossDesk Server device management database.
|
-e MAX_PORT=60000 \
|
||||||
|
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||||
- **/path/to/your/logs**: Log directory.
|
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||||
|
crossdesk/crossdesk-server:v1.1.3
|
||||||
**Note**:
|
|
||||||
- **/path/to/your/ is an example path; please replace it with your actual path. The mounted directories must be created in advance, otherwise the container will fail.**
|
|
||||||
- **The server must open the following ports: 3478/udp, 3478/tcp, 30000-60000/udp, CROSSDESK_SERVER_PORT/tcp.**
|
|
||||||
|
|
||||||
## Certificate Files
|
|
||||||
The client needs to load the root certificate, and the server needs to load the server private key and server certificate.
|
|
||||||
|
|
||||||
If you already have an SSL certificate, you can skip the following certificate generation steps.
|
|
||||||
|
|
||||||
For users without a certificate, you can use the script below to generate the certificate files:
|
|
||||||
```
|
```
|
||||||
# Create certificate generation script
|
|
||||||
vim generate_certs.sh
|
|
||||||
```
|
|
||||||
Copy the following into the script:
|
|
||||||
```
|
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Check arguments
|
**Notes**
|
||||||
if [ "$#" -ne 1 ]; then
|
- **The server must open the following ports: COTURN_PORT/udp, COTURN_PORT/tcp, MIN_PORT–MAX_PORT/udp, and CROSSDESK_SERVER_PORT/tcp.**
|
||||||
echo "Usage: $0 <SERVER_IP>"
|
- If you don’t mount volumes, all data will be lost when the container is removed.
|
||||||
exit 1
|
- Certificate files will be automatically generated on first startup and persisted to the host at `/var/lib/crossdesk/certs`.
|
||||||
fi
|
- The database file will be automatically created and stored at `/var/lib/crossdesk/db/crossdesk-server.db`.
|
||||||
|
- Log files will be created and stored at `/var/log/crossdesk/`.
|
||||||
|
|
||||||
SERVER_IP="$1"
|
**Permission Notice**
|
||||||
|
If the directories automatically created by Docker belong to root and have insufficient write permissions, the container user may not be able to write to them. This can cause:
|
||||||
|
- Certificate generation failure, leading to startup script errors and container exit.
|
||||||
|
- Database directory creation failure, causing the program to throw exceptions and crash.
|
||||||
|
- Log directory creation failure, preventing logs from being written (though the program may continue running).
|
||||||
|
|
||||||
# Filenames
|
**Solution:** Manually set permissions before starting the container:
|
||||||
ROOT_KEY="crossdesk.cn_root.key"
|
```bash
|
||||||
ROOT_CERT="crossdesk.cn_root.crt"
|
sudo mkdir -p /var/lib/crossdesk /var/log/crossdesk
|
||||||
SERVER_KEY="crossdesk.cn.key"
|
sudo chown -R $(id -u):$(id -g) /var/lib/crossdesk /var/log/crossdesk
|
||||||
SERVER_CSR="crossdesk.cn.csr"
|
|
||||||
SERVER_CERT="crossdesk.cn_bundle.crt"
|
|
||||||
FULLCHAIN_CERT="crossdesk.cn_fullchain.crt"
|
|
||||||
|
|
||||||
# Certificate subject
|
|
||||||
SUBJ="/C=CN/ST=Zhejiang/L=Hangzhou/O=CrossDesk/OU=CrossDesk/CN=$SERVER_IP"
|
|
||||||
|
|
||||||
# 1. Generate root certificate
|
|
||||||
echo "Generating root private key..."
|
|
||||||
openssl genrsa -out "$ROOT_KEY" 4096
|
|
||||||
|
|
||||||
echo "Generating self-signed root certificate..."
|
|
||||||
openssl req -x509 -new -nodes -key "$ROOT_KEY" -sha256 -days 3650 -out "$ROOT_CERT" -subj "$SUBJ"
|
|
||||||
|
|
||||||
# 2. Generate server private key
|
|
||||||
echo "Generating server private key..."
|
|
||||||
openssl genrsa -out "$SERVER_KEY" 2048
|
|
||||||
|
|
||||||
# 3. Generate server CSR
|
|
||||||
echo "Generating server CSR..."
|
|
||||||
openssl req -new -key "$SERVER_KEY" -out "$SERVER_CSR" -subj "$SUBJ"
|
|
||||||
|
|
||||||
# 4. Create temporary OpenSSL config file with SAN
|
|
||||||
SAN_CONF="san.cnf"
|
|
||||||
cat > $SAN_CONF <<EOL
|
|
||||||
[ req ]
|
|
||||||
default_bits = 2048
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
req_extensions = req_ext
|
|
||||||
prompt = no
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
C = CN
|
|
||||||
ST = Zhejiang
|
|
||||||
L = Hangzhou
|
|
||||||
O = CrossDesk
|
|
||||||
OU = CrossDesk
|
|
||||||
CN = $SERVER_IP
|
|
||||||
|
|
||||||
[ req_ext ]
|
|
||||||
subjectAltName = IP:$SERVER_IP
|
|
||||||
EOL
|
|
||||||
|
|
||||||
# 5. Sign server certificate with root certificate (including SAN)
|
|
||||||
echo "Signing server certificate with root certificate..."
|
|
||||||
openssl x509 -req -in "$SERVER_CSR" -CA "$ROOT_CERT" -CAkey "$ROOT_KEY" -CAcreateserial \
|
|
||||||
-out "$SERVER_CERT" -days 3650 -sha256 -extfile "$SAN_CONF" -extensions req_ext
|
|
||||||
|
|
||||||
# 6. Generate full chain certificate
|
|
||||||
cat "$SERVER_CERT" "$ROOT_CERT" > "$FULLCHAIN_CERT"
|
|
||||||
|
|
||||||
# 7. Clean up intermediate files
|
|
||||||
rm -f "$ROOT_CERT.srl" "$SAN_CONF" "$ROOT_KEY" "$SERVER_CSR" "FULLCHAIN_CERT"
|
|
||||||
|
|
||||||
echo "Generation complete. Deployment files:"
|
|
||||||
echo " Client root certificate: $ROOT_CERT"
|
|
||||||
echo " Server private key: $SERVER_KEY"
|
|
||||||
echo " Server certificate: $SERVER_CERT"
|
|
||||||
```
|
|
||||||
Execute:
|
|
||||||
```
|
|
||||||
chmod +x generate_certs.sh
|
|
||||||
./generate_certs.sh EXTERNAL_IP
|
|
||||||
|
|
||||||
# example ./generate_certs.sh 111.111.111.111
|
|
||||||
```
|
|
||||||
Expected output:
|
|
||||||
```
|
|
||||||
Generating root private key...
|
|
||||||
Generating self-signed root certificate...
|
|
||||||
Generating server private key...
|
|
||||||
Generating server CSR...
|
|
||||||
Signing server certificate with root certificate...
|
|
||||||
Certificate request self-signature ok
|
|
||||||
subject=C = CN, ST = Zhejiang, L = Hangzhou, O = CrossDesk, OU = CrossDesk, CN = xxx.xxx.xxx.xxx
|
|
||||||
cleaning up intermediate files...
|
|
||||||
Generation complete. Deployment files::
|
|
||||||
Client root certificate:: crossdesk.cn_root.crt
|
|
||||||
Server private key: crossdesk.cn.key
|
|
||||||
Server certificate: crossdesk.cn_bundle.crt
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Server Side
|
### Server Side
|
||||||
Place **crossdesk.cn.key** and **crossdesk.cn_bundle.crt** into the **/path/to/your/certs** directory.
|
Place **crossdesk.cn.key** and **crossdesk.cn_bundle.crt** into the **/path/to/your/certs** directory.
|
||||||
|
|
||||||
### Client Side
|
### Client Side
|
||||||
1. Click the settings icon in the top-right corner to enter the settings page.<br>
|
1. Click the settings icon in the top-right corner to enter the settings page.<br><br>
|
||||||
<img width="600" height="210" alt="image" src="https://github.com/user-attachments/assets/6431131d-b32a-4726-8783-6788f47baa3b" /><br><br>
|
<img width="600" height="210" alt="image" src="https://github.com/user-attachments/assets/6431131d-b32a-4726-8783-6788f47baa3b" /><br><br>
|
||||||
|
|
||||||
2. Click **Self-Hosted Server Configuration**.<br><br>
|
2. Click `Self-Hosted Server Configuration` button.<br><br>
|
||||||
<img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/24c761a3-1985-4d7e-84be-787383c2afb8" /><br><br>
|
<img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/24c761a3-1985-4d7e-84be-787383c2afb8" /><br><br>
|
||||||
|
|
||||||
3. In the **Certificate File Path** selection, locate and select the **crossdesk.cn_root.crt** file.<br><br>
|
3. Enter the `Server Address` (**EXTERNAL_IP**), `Signaling Service Port` (**CROSSDESK_SERVER_PORT**), and `Relay Service Port` (**COTURN_PORT**).<br><br>
|
||||||
<img width="600" height="220" alt="image" src="https://github.com/user-attachments/assets/4af7cd3a-c72e-44fb-b032-30e050019c2a" /><br><br>
|
<img width="600" height="200" alt="image" src="https://github.com/user-attachments/assets/9a32ddd5-37f8-4bee-9a51-eae295820f9a" /><br><br>
|
||||||
|
|
||||||
4. Check the option to use **Self-Hosted Server Configuration**.<br><br>
|
4. If the self-hosted server is later reset or the certificate is replaced for any reason, you can click the `Reset Certificate Fingerprint` button to clear the certificate fingerprint saved on the client.<br><br>
|
||||||
<img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/1e455dc3-4087-4f37-a544-1ff9f8789383" /><br><br>
|
<img width="600" height="200" alt="image" src="https://github.com/user-attachments/assets/d9e423ab-0c2b-4fab-b132-4dc27462d704" /><br><br>
|
||||||
|
|
||||||
### Web Client
|
### Web Client
|
||||||
See [CrossDesk Web Client](https://github.com/kunkundi/crossdesk-web-client)。
|
See [CrossDesk Web Client](https://github.com/kunkundi/crossdesk-web-client)。
|
||||||
|
|||||||
@@ -41,16 +41,101 @@ int ConfigCenter::Load() {
|
|||||||
|
|
||||||
enable_turn_ = ini_.GetBoolValue(section_, "enable_turn", enable_turn_);
|
enable_turn_ = ini_.GetBoolValue(section_, "enable_turn", enable_turn_);
|
||||||
enable_srtp_ = ini_.GetBoolValue(section_, "enable_srtp", enable_srtp_);
|
enable_srtp_ = ini_.GetBoolValue(section_, "enable_srtp", enable_srtp_);
|
||||||
signal_server_host_ = ini_.GetValue(section_, "signal_server_host",
|
|
||||||
signal_server_host_.c_str());
|
|
||||||
signal_server_port_ = static_cast<int>(
|
|
||||||
ini_.GetLongValue(section_, "signal_server_port", signal_server_port_));
|
|
||||||
coturn_server_port_ = static_cast<int>(
|
|
||||||
ini_.GetLongValue(section_, "coturn_server_port", coturn_server_port_));
|
|
||||||
cert_file_path_ =
|
|
||||||
ini_.GetValue(section_, "cert_file_path", cert_file_path_.c_str());
|
|
||||||
enable_self_hosted_ =
|
enable_self_hosted_ =
|
||||||
ini_.GetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
ini_.GetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
||||||
|
|
||||||
|
const char* signal_server_host_value =
|
||||||
|
ini_.GetValue(section_, "signal_server_host", nullptr);
|
||||||
|
if (signal_server_host_value != nullptr &&
|
||||||
|
strlen(signal_server_host_value) > 0) {
|
||||||
|
signal_server_host_ = signal_server_host_value;
|
||||||
|
} else {
|
||||||
|
signal_server_host_ = "";
|
||||||
|
}
|
||||||
|
const char* signal_server_port_value =
|
||||||
|
ini_.GetValue(section_, "signal_server_port", nullptr);
|
||||||
|
if (signal_server_port_value != nullptr &&
|
||||||
|
strlen(signal_server_port_value) > 0) {
|
||||||
|
signal_server_port_ =
|
||||||
|
static_cast<int>(ini_.GetLongValue(section_, "signal_server_port", 0));
|
||||||
|
} else {
|
||||||
|
signal_server_port_ = 0;
|
||||||
|
}
|
||||||
|
const char* coturn_server_port_value =
|
||||||
|
ini_.GetValue(section_, "coturn_server_port", nullptr);
|
||||||
|
if (coturn_server_port_value != nullptr &&
|
||||||
|
strlen(coturn_server_port_value) > 0) {
|
||||||
|
coturn_server_port_ =
|
||||||
|
static_cast<int>(ini_.GetLongValue(section_, "coturn_server_port", 0));
|
||||||
|
} else {
|
||||||
|
coturn_server_port_ = 0;
|
||||||
|
}
|
||||||
|
const char* cert_file_path_value =
|
||||||
|
ini_.GetValue(section_, "cert_file_path", nullptr);
|
||||||
|
if (cert_file_path_value != nullptr && strlen(cert_file_path_value) > 0) {
|
||||||
|
cert_file_path_ = cert_file_path_value;
|
||||||
|
} else {
|
||||||
|
cert_file_path_ = "";
|
||||||
|
}
|
||||||
|
const char* cert_fingerprint_value =
|
||||||
|
ini_.GetValue(section_, "cert_fingerprint", nullptr);
|
||||||
|
if (cert_fingerprint_value != nullptr && strlen(cert_fingerprint_value) > 0) {
|
||||||
|
cert_fingerprint_ = cert_fingerprint_value;
|
||||||
|
} else {
|
||||||
|
cert_fingerprint_ = "";
|
||||||
|
}
|
||||||
|
const char* cert_fingerprint_server_host_value =
|
||||||
|
ini_.GetValue(section_, "cert_fingerprint_server_host", nullptr);
|
||||||
|
if (cert_fingerprint_server_host_value != nullptr &&
|
||||||
|
strlen(cert_fingerprint_server_host_value) > 0) {
|
||||||
|
cert_fingerprint_server_host_ = cert_fingerprint_server_host_value;
|
||||||
|
} else {
|
||||||
|
cert_fingerprint_server_host_ = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* default_cert_fingerprint_value =
|
||||||
|
ini_.GetValue(section_, "default_cert_fingerprint", nullptr);
|
||||||
|
if (default_cert_fingerprint_value != nullptr &&
|
||||||
|
strlen(default_cert_fingerprint_value) > 0) {
|
||||||
|
default_cert_fingerprint_ = default_cert_fingerprint_value;
|
||||||
|
} else {
|
||||||
|
default_cert_fingerprint_ = "";
|
||||||
|
}
|
||||||
|
const char* default_cert_fingerprint_server_host_value =
|
||||||
|
ini_.GetValue(section_, "default_cert_fingerprint_server_host", nullptr);
|
||||||
|
if (default_cert_fingerprint_server_host_value != nullptr &&
|
||||||
|
strlen(default_cert_fingerprint_server_host_value) > 0) {
|
||||||
|
default_cert_fingerprint_server_host_ =
|
||||||
|
default_cert_fingerprint_server_host_value;
|
||||||
|
} else {
|
||||||
|
default_cert_fingerprint_server_host_ = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable_self_hosted_ && !cert_fingerprint_.empty() &&
|
||||||
|
!cert_fingerprint_server_host_.empty() &&
|
||||||
|
signal_server_host_ != cert_fingerprint_server_host_) {
|
||||||
|
LOG_INFO("Server IP changed from {} to {}, clearing old fingerprint",
|
||||||
|
cert_fingerprint_server_host_, signal_server_host_);
|
||||||
|
cert_fingerprint_.clear();
|
||||||
|
cert_fingerprint_server_host_.clear();
|
||||||
|
ini_.Delete(section_, "cert_fingerprint", false);
|
||||||
|
ini_.Delete(section_, "cert_fingerprint_server_host", false);
|
||||||
|
ini_.SaveFile(config_path_.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enable_self_hosted_ && !default_cert_fingerprint_.empty() &&
|
||||||
|
!default_cert_fingerprint_server_host_.empty() &&
|
||||||
|
signal_server_host_default_ != default_cert_fingerprint_server_host_) {
|
||||||
|
LOG_INFO(
|
||||||
|
"Default server IP changed from {} to {}, clearing old fingerprint",
|
||||||
|
default_cert_fingerprint_server_host_, signal_server_host_default_);
|
||||||
|
default_cert_fingerprint_.clear();
|
||||||
|
default_cert_fingerprint_server_host_.clear();
|
||||||
|
ini_.Delete(section_, "default_cert_fingerprint", false);
|
||||||
|
ini_.Delete(section_, "default_cert_fingerprint_server_host", false);
|
||||||
|
ini_.SaveFile(config_path_.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
enable_autostart_ =
|
enable_autostart_ =
|
||||||
ini_.GetBoolValue(section_, "enable_autostart", enable_autostart_);
|
ini_.GetBoolValue(section_, "enable_autostart", enable_autostart_);
|
||||||
enable_daemon_ = ini_.GetBoolValue(section_, "enable_daemon", enable_daemon_);
|
enable_daemon_ = ini_.GetBoolValue(section_, "enable_daemon", enable_daemon_);
|
||||||
@@ -71,11 +156,30 @@ int ConfigCenter::Save() {
|
|||||||
ini_.SetBoolValue(section_, "hardware_video_codec", hardware_video_codec_);
|
ini_.SetBoolValue(section_, "hardware_video_codec", hardware_video_codec_);
|
||||||
ini_.SetBoolValue(section_, "enable_turn", enable_turn_);
|
ini_.SetBoolValue(section_, "enable_turn", enable_turn_);
|
||||||
ini_.SetBoolValue(section_, "enable_srtp", enable_srtp_);
|
ini_.SetBoolValue(section_, "enable_srtp", enable_srtp_);
|
||||||
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
|
|
||||||
ini_.SetLongValue(section_, "signal_server_port",
|
|
||||||
static_cast<long>(signal_server_port_));
|
|
||||||
ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str());
|
|
||||||
ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
||||||
|
|
||||||
|
// only save when self hosted
|
||||||
|
if (enable_self_hosted_) {
|
||||||
|
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
|
||||||
|
ini_.SetLongValue(section_, "signal_server_port",
|
||||||
|
static_cast<long>(signal_server_port_));
|
||||||
|
ini_.SetLongValue(section_, "coturn_server_port",
|
||||||
|
static_cast<long>(coturn_server_port_));
|
||||||
|
ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str());
|
||||||
|
if (!cert_fingerprint_.empty()) {
|
||||||
|
ini_.SetValue(section_, "cert_fingerprint", cert_fingerprint_.c_str());
|
||||||
|
ini_.SetValue(section_, "cert_fingerprint_server_host",
|
||||||
|
cert_fingerprint_server_host_.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!default_cert_fingerprint_.empty()) {
|
||||||
|
ini_.SetValue(section_, "default_cert_fingerprint",
|
||||||
|
default_cert_fingerprint_.c_str());
|
||||||
|
ini_.SetValue(section_, "default_cert_fingerprint_server_host",
|
||||||
|
default_cert_fingerprint_server_host_.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
ini_.SetBoolValue(section_, "enable_autostart", enable_autostart_);
|
ini_.SetBoolValue(section_, "enable_autostart", enable_autostart_);
|
||||||
ini_.SetBoolValue(section_, "enable_daemon", enable_daemon_);
|
ini_.SetBoolValue(section_, "enable_daemon", enable_daemon_);
|
||||||
ini_.SetBoolValue(section_, "enable_minimize_to_tray",
|
ini_.SetBoolValue(section_, "enable_minimize_to_tray",
|
||||||
@@ -166,6 +270,15 @@ int ConfigCenter::SetSrtp(bool enable_srtp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ConfigCenter::SetServerHost(const std::string& signal_server_host) {
|
int ConfigCenter::SetServerHost(const std::string& signal_server_host) {
|
||||||
|
if (enable_self_hosted_ && !cert_fingerprint_.empty() &&
|
||||||
|
signal_server_host != signal_server_host_) {
|
||||||
|
LOG_INFO("Server IP changed from {} to {}, clearing old fingerprint",
|
||||||
|
signal_server_host_, signal_server_host);
|
||||||
|
cert_fingerprint_.clear();
|
||||||
|
cert_fingerprint_server_host_.clear();
|
||||||
|
ini_.Delete(section_, "cert_fingerprint", false);
|
||||||
|
ini_.Delete(section_, "cert_fingerprint_server_host", false);
|
||||||
|
}
|
||||||
signal_server_host_ = signal_server_host;
|
signal_server_host_ = signal_server_host;
|
||||||
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
|
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
|
||||||
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
@@ -207,9 +320,124 @@ int ConfigCenter::SetCertFilePath(const std::string& cert_file_path) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::SetCertFingerprint(const std::string& fingerprint) {
|
||||||
|
cert_fingerprint_ = fingerprint;
|
||||||
|
cert_fingerprint_server_host_ = signal_server_host_;
|
||||||
|
ini_.SetValue(section_, "cert_fingerprint", cert_fingerprint_.c_str());
|
||||||
|
ini_.SetValue(section_, "cert_fingerprint_server_host",
|
||||||
|
cert_fingerprint_server_host_.c_str());
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::SetDefaultCertFingerprint(const std::string& fingerprint) {
|
||||||
|
default_cert_fingerprint_ = fingerprint;
|
||||||
|
default_cert_fingerprint_server_host_ = signal_server_host_default_;
|
||||||
|
ini_.SetValue(section_, "default_cert_fingerprint",
|
||||||
|
default_cert_fingerprint_.c_str());
|
||||||
|
ini_.SetValue(section_, "default_cert_fingerprint_server_host",
|
||||||
|
default_cert_fingerprint_server_host_.c_str());
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::ClearCertFingerprint() {
|
||||||
|
cert_fingerprint_.clear();
|
||||||
|
cert_fingerprint_server_host_.clear();
|
||||||
|
ini_.Delete(section_, "cert_fingerprint", false);
|
||||||
|
ini_.Delete(section_, "cert_fingerprint_server_host", false);
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::ClearDefaultCertFingerprint() {
|
||||||
|
default_cert_fingerprint_.clear();
|
||||||
|
default_cert_fingerprint_server_host_.clear();
|
||||||
|
ini_.Delete(section_, "default_cert_fingerprint", false);
|
||||||
|
ini_.Delete(section_, "default_cert_fingerprint_server_host", false);
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ConfigCenter::SetSelfHosted(bool enable_self_hosted) {
|
int ConfigCenter::SetSelfHosted(bool enable_self_hosted) {
|
||||||
enable_self_hosted_ = enable_self_hosted;
|
enable_self_hosted_ = enable_self_hosted;
|
||||||
ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
||||||
|
|
||||||
|
// load from config if self hosted is enabled
|
||||||
|
if (enable_self_hosted_) {
|
||||||
|
const char* signal_server_host_value =
|
||||||
|
ini_.GetValue(section_, "signal_server_host", nullptr);
|
||||||
|
if (signal_server_host_value != nullptr &&
|
||||||
|
strlen(signal_server_host_value) > 0) {
|
||||||
|
signal_server_host_ = signal_server_host_value;
|
||||||
|
}
|
||||||
|
const char* signal_server_port_value =
|
||||||
|
ini_.GetValue(section_, "signal_server_port", nullptr);
|
||||||
|
if (signal_server_port_value != nullptr &&
|
||||||
|
strlen(signal_server_port_value) > 0) {
|
||||||
|
signal_server_port_ = static_cast<int>(
|
||||||
|
ini_.GetLongValue(section_, "signal_server_port", 0));
|
||||||
|
}
|
||||||
|
const char* coturn_server_port_value =
|
||||||
|
ini_.GetValue(section_, "coturn_server_port", nullptr);
|
||||||
|
if (coturn_server_port_value != nullptr &&
|
||||||
|
strlen(coturn_server_port_value) > 0) {
|
||||||
|
coturn_server_port_ = static_cast<int>(
|
||||||
|
ini_.GetLongValue(section_, "coturn_server_port", 0));
|
||||||
|
}
|
||||||
|
const char* cert_file_path_value =
|
||||||
|
ini_.GetValue(section_, "cert_file_path", nullptr);
|
||||||
|
if (cert_file_path_value != nullptr && strlen(cert_file_path_value) > 0) {
|
||||||
|
cert_file_path_ = cert_file_path_value;
|
||||||
|
}
|
||||||
|
const char* cert_fingerprint_value =
|
||||||
|
ini_.GetValue(section_, "cert_fingerprint", nullptr);
|
||||||
|
if (cert_fingerprint_value != nullptr &&
|
||||||
|
strlen(cert_fingerprint_value) > 0) {
|
||||||
|
cert_fingerprint_ = cert_fingerprint_value;
|
||||||
|
}
|
||||||
|
const char* cert_fingerprint_server_host_value =
|
||||||
|
ini_.GetValue(section_, "cert_fingerprint_server_host", nullptr);
|
||||||
|
if (cert_fingerprint_server_host_value != nullptr &&
|
||||||
|
strlen(cert_fingerprint_server_host_value) > 0) {
|
||||||
|
cert_fingerprint_server_host_ = cert_fingerprint_server_host_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cert_fingerprint_.empty() && !cert_fingerprint_server_host_.empty() &&
|
||||||
|
signal_server_host_ != cert_fingerprint_server_host_) {
|
||||||
|
LOG_INFO("Server IP changed from {} to {}, clearing old fingerprint",
|
||||||
|
cert_fingerprint_server_host_, signal_server_host_);
|
||||||
|
cert_fingerprint_.clear();
|
||||||
|
cert_fingerprint_server_host_.clear();
|
||||||
|
ini_.Delete(section_, "cert_fingerprint", false);
|
||||||
|
ini_.Delete(section_, "cert_fingerprint_server_host", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
|
||||||
|
ini_.SetLongValue(section_, "signal_server_port",
|
||||||
|
static_cast<long>(signal_server_port_));
|
||||||
|
ini_.SetLongValue(section_, "coturn_server_port",
|
||||||
|
static_cast<long>(coturn_server_port_));
|
||||||
|
ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str());
|
||||||
|
if (!cert_fingerprint_.empty()) {
|
||||||
|
ini_.SetValue(section_, "cert_fingerprint", cert_fingerprint_.c_str());
|
||||||
|
ini_.SetValue(section_, "cert_fingerprint_server_host",
|
||||||
|
cert_fingerprint_server_host_.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -297,6 +525,14 @@ int ConfigCenter::GetCoturnServerPort() const { return coturn_server_port_; }
|
|||||||
|
|
||||||
std::string ConfigCenter::GetCertFilePath() const { return cert_file_path_; }
|
std::string ConfigCenter::GetCertFilePath() const { return cert_file_path_; }
|
||||||
|
|
||||||
|
std::string ConfigCenter::GetCertFingerprint() const {
|
||||||
|
return cert_fingerprint_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ConfigCenter::GetDefaultCertFingerprint() const {
|
||||||
|
return default_cert_fingerprint_;
|
||||||
|
}
|
||||||
|
|
||||||
std::string ConfigCenter::GetDefaultServerHost() const {
|
std::string ConfigCenter::GetDefaultServerHost() const {
|
||||||
return signal_server_host_default_;
|
return signal_server_host_default_;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ class ConfigCenter {
|
|||||||
int SetServerPort(int signal_server_port);
|
int SetServerPort(int signal_server_port);
|
||||||
int SetCoturnServerPort(int coturn_server_port);
|
int SetCoturnServerPort(int coturn_server_port);
|
||||||
int SetCertFilePath(const std::string& cert_file_path);
|
int SetCertFilePath(const std::string& cert_file_path);
|
||||||
|
int SetCertFingerprint(const std::string& fingerprint);
|
||||||
|
int SetDefaultCertFingerprint(const std::string& fingerprint);
|
||||||
|
int ClearCertFingerprint();
|
||||||
|
int ClearDefaultCertFingerprint();
|
||||||
int SetSelfHosted(bool enable_self_hosted);
|
int SetSelfHosted(bool enable_self_hosted);
|
||||||
int SetMinimizeToTray(bool enable_minimize_to_tray);
|
int SetMinimizeToTray(bool enable_minimize_to_tray);
|
||||||
int SetAutostart(bool enable_autostart);
|
int SetAutostart(bool enable_autostart);
|
||||||
@@ -56,6 +60,8 @@ class ConfigCenter {
|
|||||||
int GetSignalServerPort() const;
|
int GetSignalServerPort() const;
|
||||||
int GetCoturnServerPort() const;
|
int GetCoturnServerPort() const;
|
||||||
std::string GetCertFilePath() const;
|
std::string GetCertFilePath() const;
|
||||||
|
std::string GetCertFingerprint() const;
|
||||||
|
std::string GetDefaultCertFingerprint() const;
|
||||||
std::string GetDefaultServerHost() const;
|
std::string GetDefaultServerHost() const;
|
||||||
int GetDefaultSignalServerPort() const;
|
int GetDefaultSignalServerPort() const;
|
||||||
int GetDefaultCoturnServerPort() const;
|
int GetDefaultCoturnServerPort() const;
|
||||||
@@ -70,7 +76,6 @@ class ConfigCenter {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string config_path_;
|
std::string config_path_;
|
||||||
std::string cert_file_path_;
|
|
||||||
CSimpleIniA ini_;
|
CSimpleIniA ini_;
|
||||||
const char* section_ = "Settings";
|
const char* section_ = "Settings";
|
||||||
|
|
||||||
@@ -81,13 +86,18 @@ class ConfigCenter {
|
|||||||
bool hardware_video_codec_ = false;
|
bool hardware_video_codec_ = false;
|
||||||
bool enable_turn_ = true;
|
bool enable_turn_ = true;
|
||||||
bool enable_srtp_ = false;
|
bool enable_srtp_ = false;
|
||||||
std::string signal_server_host_ = "api.crossdesk.cn";
|
std::string signal_server_host_ = "";
|
||||||
std::string signal_server_host_default_ = "api.crossdesk.cn";
|
std::string signal_server_host_default_ = "api.crossdesk.cn";
|
||||||
int signal_server_port_ = 9099;
|
int signal_server_port_ = 0;
|
||||||
int server_port_default_ = 9099;
|
int server_port_default_ = 9099;
|
||||||
int coturn_server_port_ = 3478;
|
int coturn_server_port_ = 0;
|
||||||
int coturn_server_port_default_ = 3478;
|
int coturn_server_port_default_ = 3478;
|
||||||
|
std::string cert_file_path_ = "";
|
||||||
std::string cert_file_path_default_ = "";
|
std::string cert_file_path_default_ = "";
|
||||||
|
std::string cert_fingerprint_ = "";
|
||||||
|
std::string cert_fingerprint_server_host_ = "";
|
||||||
|
std::string default_cert_fingerprint_ = "";
|
||||||
|
std::string default_cert_fingerprint_server_host_ = "";
|
||||||
bool enable_self_hosted_ = false;
|
bool enable_self_hosted_ = false;
|
||||||
bool enable_minimize_to_tray_ = false;
|
bool enable_minimize_to_tray_ = false;
|
||||||
bool enable_autostart_ = false;
|
bool enable_autostart_ = false;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -116,6 +116,9 @@ static std::vector<std::string> self_hosted_server_certificate_path = {
|
|||||||
reinterpret_cast<const char*>(u8"证书文件路径:"), "Certificate File Path:"};
|
reinterpret_cast<const char*>(u8"证书文件路径:"), "Certificate File Path:"};
|
||||||
static std::vector<std::string> select_a_file = {
|
static std::vector<std::string> select_a_file = {
|
||||||
reinterpret_cast<const char*>(u8"请选择文件"), "Please select a file"};
|
reinterpret_cast<const char*>(u8"请选择文件"), "Please select a file"};
|
||||||
|
static std::vector<std::string> reset_cert_fingerprint = {
|
||||||
|
reinterpret_cast<const char*>(u8"重置证书指纹"),
|
||||||
|
"Reset Certificate Fingerprint"};
|
||||||
static std::vector<std::string> ok = {reinterpret_cast<const char*>(u8"确认"),
|
static std::vector<std::string> ok = {reinterpret_cast<const char*>(u8"确认"),
|
||||||
"OK"};
|
"OK"};
|
||||||
static std::vector<std::string> cancel = {
|
static std::vector<std::string> cancel = {
|
||||||
|
|||||||
@@ -233,15 +233,41 @@ int Render::LocalWindow() {
|
|||||||
sizeof(password_saved_) - 1);
|
sizeof(password_saved_) - 1);
|
||||||
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
||||||
|
|
||||||
std::string client_id_with_password =
|
// if self hosted
|
||||||
std::string(client_id_) + "@" + password_saved_;
|
if (config_center_->IsSelfHosted()) {
|
||||||
strncpy(client_id_with_password_, client_id_with_password.c_str(),
|
std::string self_hosted_id_str;
|
||||||
sizeof(client_id_with_password_) - 1);
|
if (strlen(self_hosted_id_) > 0) {
|
||||||
client_id_with_password_[sizeof(client_id_with_password_) - 1] =
|
const char* at_pos = strchr(self_hosted_id_, '@');
|
||||||
'\0';
|
if (at_pos != nullptr) {
|
||||||
|
self_hosted_id_str =
|
||||||
|
std::string(self_hosted_id_, at_pos - self_hosted_id_);
|
||||||
|
} else {
|
||||||
|
self_hosted_id_str = self_hosted_id_;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self_hosted_id_str = client_id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string new_self_hosted_id =
|
||||||
|
self_hosted_id_str + "@" + password_saved_;
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
strncpy(self_hosted_id_, new_self_hosted_id.c_str(),
|
||||||
|
sizeof(self_hosted_id_) - 1);
|
||||||
|
self_hosted_id_[sizeof(self_hosted_id_) - 1] = '\0';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::string client_id_with_password =
|
||||||
|
std::string(client_id_) + "@" + password_saved_;
|
||||||
|
strncpy(client_id_with_password_, client_id_with_password.c_str(),
|
||||||
|
sizeof(client_id_with_password_) - 1);
|
||||||
|
client_id_with_password_[sizeof(client_id_with_password_) - 1] =
|
||||||
|
'\0';
|
||||||
|
}
|
||||||
|
|
||||||
SaveSettingsIntoCacheFile();
|
SaveSettingsIntoCacheFile();
|
||||||
|
|
||||||
|
memset(new_password_, 0, sizeof(new_password_));
|
||||||
|
|
||||||
LeaveConnection(peer_, client_id_);
|
LeaveConnection(peer_, client_id_);
|
||||||
DestroyPeer(&peer_);
|
DestroyPeer(&peer_);
|
||||||
focus_on_input_widget_ = true;
|
focus_on_input_widget_ = true;
|
||||||
|
|||||||
@@ -203,22 +203,41 @@ Render::~Render() {}
|
|||||||
|
|
||||||
int Render::SaveSettingsIntoCacheFile() {
|
int Render::SaveSettingsIntoCacheFile() {
|
||||||
cd_cache_mutex_.lock();
|
cd_cache_mutex_.lock();
|
||||||
std::ofstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
|
||||||
std::ios::binary);
|
std::ofstream cd_cache_v2_file(cache_path_ + "/secure_cache_v2.enc",
|
||||||
if (!cd_cache_file) {
|
std::ios::binary);
|
||||||
|
if (!cd_cache_v2_file) {
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&cd_cache_.client_id_with_password, 0,
|
memset(&cd_cache_v2_.client_id_with_password, 0,
|
||||||
sizeof(cd_cache_.client_id_with_password));
|
sizeof(cd_cache_v2_.client_id_with_password));
|
||||||
memcpy(cd_cache_.client_id_with_password, client_id_with_password_,
|
memcpy(cd_cache_v2_.client_id_with_password, client_id_with_password_,
|
||||||
sizeof(client_id_with_password_));
|
sizeof(client_id_with_password_));
|
||||||
memcpy(&cd_cache_.key, &aes128_key_, sizeof(aes128_key_));
|
memcpy(&cd_cache_v2_.key, &aes128_key_, sizeof(aes128_key_));
|
||||||
memcpy(&cd_cache_.iv, &aes128_iv_, sizeof(aes128_iv_));
|
memcpy(&cd_cache_v2_.iv, &aes128_iv_, sizeof(aes128_iv_));
|
||||||
|
|
||||||
|
memset(&cd_cache_v2_.self_hosted_id, 0, sizeof(cd_cache_v2_.self_hosted_id));
|
||||||
|
memcpy(cd_cache_v2_.self_hosted_id, self_hosted_id_, sizeof(self_hosted_id_));
|
||||||
|
|
||||||
|
cd_cache_v2_file.write(reinterpret_cast<char*>(&cd_cache_v2_),
|
||||||
|
sizeof(CDCacheV2));
|
||||||
|
cd_cache_v2_file.close();
|
||||||
|
|
||||||
|
std::ofstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
||||||
|
std::ios::binary);
|
||||||
|
if (cd_cache_file) {
|
||||||
|
memset(&cd_cache_.client_id_with_password, 0,
|
||||||
|
sizeof(cd_cache_.client_id_with_password));
|
||||||
|
memcpy(cd_cache_.client_id_with_password, client_id_with_password_,
|
||||||
|
sizeof(client_id_with_password_));
|
||||||
|
memcpy(&cd_cache_.key, &aes128_key_, sizeof(aes128_key_));
|
||||||
|
memcpy(&cd_cache_.iv, &aes128_iv_, sizeof(aes128_iv_));
|
||||||
|
cd_cache_file.write(reinterpret_cast<char*>(&cd_cache_), sizeof(CDCache));
|
||||||
|
cd_cache_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
cd_cache_file.write(reinterpret_cast<char*>(&cd_cache_), sizeof(CDCache));
|
|
||||||
cd_cache_file.close();
|
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -226,33 +245,81 @@ int Render::SaveSettingsIntoCacheFile() {
|
|||||||
|
|
||||||
int Render::LoadSettingsFromCacheFile() {
|
int Render::LoadSettingsFromCacheFile() {
|
||||||
cd_cache_mutex_.lock();
|
cd_cache_mutex_.lock();
|
||||||
std::ifstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
|
||||||
std::ios::binary);
|
std::ifstream cd_cache_v2_file(cache_path_ + "/secure_cache_v2.enc",
|
||||||
if (!cd_cache_file) {
|
std::ios::binary);
|
||||||
|
bool v2_file_exists = cd_cache_v2_file.good();
|
||||||
|
|
||||||
|
if (v2_file_exists) {
|
||||||
|
cd_cache_v2_file.read(reinterpret_cast<char*>(&cd_cache_v2_),
|
||||||
|
sizeof(CDCacheV2));
|
||||||
|
cd_cache_v2_file.close();
|
||||||
|
|
||||||
|
memset(&client_id_with_password_, 0, sizeof(client_id_with_password_));
|
||||||
|
memcpy(client_id_with_password_, cd_cache_v2_.client_id_with_password,
|
||||||
|
sizeof(client_id_with_password_));
|
||||||
|
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
memcpy(self_hosted_id_, cd_cache_v2_.self_hosted_id,
|
||||||
|
sizeof(self_hosted_id_));
|
||||||
|
|
||||||
|
memcpy(aes128_key_, cd_cache_v2_.key, sizeof(cd_cache_v2_.key));
|
||||||
|
memcpy(aes128_iv_, cd_cache_v2_.iv, sizeof(cd_cache_v2_.iv));
|
||||||
|
|
||||||
|
LOG_INFO("Load settings from v2 cache file");
|
||||||
|
} else {
|
||||||
|
std::ifstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
||||||
|
std::ios::binary);
|
||||||
|
if (!cd_cache_file) {
|
||||||
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
|
memset(password_saved_, 0, sizeof(password_saved_));
|
||||||
|
memset(aes128_key_, 0, sizeof(aes128_key_));
|
||||||
|
memset(aes128_iv_, 0, sizeof(aes128_iv_));
|
||||||
|
memset(self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
|
||||||
|
thumbnail_.reset();
|
||||||
|
thumbnail_ = std::make_shared<Thumbnail>(cache_path_ + "/thumbnails/");
|
||||||
|
thumbnail_->GetKeyAndIv(aes128_key_, aes128_iv_);
|
||||||
|
thumbnail_->DeleteAllFilesInDirectory();
|
||||||
|
|
||||||
|
SaveSettingsIntoCacheFile();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cd_cache_file.read(reinterpret_cast<char*>(&cd_cache_), sizeof(CDCache));
|
||||||
|
cd_cache_file.close();
|
||||||
|
|
||||||
|
memset(&cd_cache_v2_.client_id_with_password, 0,
|
||||||
|
sizeof(cd_cache_v2_.client_id_with_password));
|
||||||
|
memcpy(cd_cache_v2_.client_id_with_password,
|
||||||
|
cd_cache_.client_id_with_password,
|
||||||
|
sizeof(cd_cache_.client_id_with_password));
|
||||||
|
memcpy(&cd_cache_v2_.key, &cd_cache_.key, sizeof(cd_cache_.key));
|
||||||
|
memcpy(&cd_cache_v2_.iv, &cd_cache_.iv, sizeof(cd_cache_.iv));
|
||||||
|
|
||||||
|
memset(&cd_cache_v2_.self_hosted_id, 0,
|
||||||
|
sizeof(cd_cache_v2_.self_hosted_id));
|
||||||
|
|
||||||
|
memset(&client_id_with_password_, 0, sizeof(client_id_with_password_));
|
||||||
|
memcpy(client_id_with_password_, cd_cache_.client_id_with_password,
|
||||||
|
sizeof(client_id_with_password_));
|
||||||
|
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
|
||||||
|
memcpy(aes128_key_, cd_cache_.key, sizeof(cd_cache_.key));
|
||||||
|
memcpy(aes128_iv_, cd_cache_.iv, sizeof(cd_cache_.iv));
|
||||||
|
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
memset(password_saved_, 0, sizeof(password_saved_));
|
|
||||||
memset(aes128_key_, 0, sizeof(aes128_key_));
|
|
||||||
memset(aes128_iv_, 0, sizeof(aes128_iv_));
|
|
||||||
|
|
||||||
thumbnail_.reset();
|
|
||||||
thumbnail_ = std::make_shared<Thumbnail>(cache_path_ + "/thumbnails/");
|
|
||||||
thumbnail_->GetKeyAndIv(aes128_key_, aes128_iv_);
|
|
||||||
thumbnail_->DeleteAllFilesInDirectory();
|
|
||||||
|
|
||||||
SaveSettingsIntoCacheFile();
|
SaveSettingsIntoCacheFile();
|
||||||
|
cd_cache_mutex_.lock();
|
||||||
|
|
||||||
return -1;
|
LOG_INFO("Migrated settings from v1 to v2 cache file");
|
||||||
}
|
}
|
||||||
|
|
||||||
cd_cache_file.read(reinterpret_cast<char*>(&cd_cache_), sizeof(CDCache));
|
|
||||||
cd_cache_file.close();
|
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
memset(&client_id_with_password_, 0, sizeof(client_id_with_password_));
|
|
||||||
memcpy(client_id_with_password_, cd_cache_.client_id_with_password,
|
|
||||||
sizeof(client_id_with_password_));
|
|
||||||
|
|
||||||
if (strchr(client_id_with_password_, '@') != nullptr) {
|
if (strchr(client_id_with_password_, '@') != nullptr) {
|
||||||
std::string id, password;
|
std::string id, password;
|
||||||
const char* at_pos = strchr(client_id_with_password_, '@');
|
const char* at_pos = strchr(client_id_with_password_, '@');
|
||||||
@@ -273,9 +340,6 @@ int Render::LoadSettingsFromCacheFile() {
|
|||||||
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(aes128_key_, cd_cache_.key, sizeof(cd_cache_.key));
|
|
||||||
memcpy(aes128_iv_, cd_cache_.iv, sizeof(cd_cache_.iv));
|
|
||||||
|
|
||||||
thumbnail_.reset();
|
thumbnail_.reset();
|
||||||
thumbnail_ = std::make_shared<Thumbnail>(cache_path_ + "/thumbnails/",
|
thumbnail_ = std::make_shared<Thumbnail>(cache_path_ + "/thumbnails/",
|
||||||
aes128_key_, aes128_iv_);
|
aes128_key_, aes128_iv_);
|
||||||
@@ -473,32 +537,97 @@ int Render::CreateConnectionPeer() {
|
|||||||
std::string signal_server_ip;
|
std::string signal_server_ip;
|
||||||
int signal_server_port;
|
int signal_server_port;
|
||||||
int coturn_server_port;
|
int coturn_server_port;
|
||||||
std::string tls_cert_path;
|
std::string tls_cert_fingerprint;
|
||||||
|
|
||||||
if (config_center_->IsSelfHosted()) {
|
if (config_center_->IsSelfHosted()) {
|
||||||
signal_server_ip = config_center_->GetSignalServerHost();
|
signal_server_ip = config_center_->GetSignalServerHost();
|
||||||
signal_server_port = config_center_->GetSignalServerPort();
|
signal_server_port = config_center_->GetSignalServerPort();
|
||||||
coturn_server_port = config_center_->GetCoturnServerPort();
|
coturn_server_port = config_center_->GetCoturnServerPort();
|
||||||
tls_cert_path = config_center_->GetCertFilePath();
|
tls_cert_fingerprint = config_center_->GetCertFingerprint();
|
||||||
|
|
||||||
|
std::string current_self_hosted_ip = config_center_->GetSignalServerHost();
|
||||||
|
bool use_cached_id = false;
|
||||||
|
|
||||||
|
// Check secure_cache_v2.enc exists or not
|
||||||
|
std::ifstream v2_file(cache_path_ + "/secure_cache_v2.enc",
|
||||||
|
std::ios::binary);
|
||||||
|
if (v2_file.good()) {
|
||||||
|
CDCacheV2 temp_cache;
|
||||||
|
v2_file.read(reinterpret_cast<char*>(&temp_cache), sizeof(CDCacheV2));
|
||||||
|
v2_file.close();
|
||||||
|
|
||||||
|
if (strlen(temp_cache.self_hosted_id) > 0) {
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
strncpy(self_hosted_id_, temp_cache.self_hosted_id,
|
||||||
|
sizeof(self_hosted_id_) - 1);
|
||||||
|
self_hosted_id_[sizeof(self_hosted_id_) - 1] = '\0';
|
||||||
|
use_cached_id = true;
|
||||||
|
|
||||||
|
std::string id, password;
|
||||||
|
const char* at_pos = strchr(self_hosted_id_, '@');
|
||||||
|
if (at_pos == nullptr) {
|
||||||
|
id = self_hosted_id_;
|
||||||
|
password.clear();
|
||||||
|
} else {
|
||||||
|
id.assign(self_hosted_id_, at_pos - self_hosted_id_);
|
||||||
|
password = at_pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&client_id_, 0, sizeof(client_id_));
|
||||||
|
strncpy(client_id_, id.c_str(), sizeof(client_id_) - 1);
|
||||||
|
client_id_[sizeof(client_id_) - 1] = '\0';
|
||||||
|
|
||||||
|
memset(&password_saved_, 0, sizeof(password_saved_));
|
||||||
|
strncpy(password_saved_, password.c_str(), sizeof(password_saved_) - 1);
|
||||||
|
password_saved_[sizeof(password_saved_) - 1] = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memset(&self_hosted_id_, 0, sizeof(self_hosted_id_));
|
||||||
|
LOG_INFO(
|
||||||
|
"secure_cache_v2.enc not found, will use empty id to get new id from "
|
||||||
|
"server");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_cached_id && strlen(self_hosted_id_) > 0) {
|
||||||
|
memset(&self_hosted_user_id_, 0, sizeof(self_hosted_user_id_));
|
||||||
|
strncpy(self_hosted_user_id_, self_hosted_id_,
|
||||||
|
sizeof(self_hosted_user_id_) - 1);
|
||||||
|
self_hosted_user_id_[sizeof(self_hosted_user_id_) - 1] = '\0';
|
||||||
|
params_.user_id = self_hosted_user_id_;
|
||||||
|
} else {
|
||||||
|
memset(&self_hosted_user_id_, 0, sizeof(self_hosted_user_id_));
|
||||||
|
params_.user_id = self_hosted_user_id_;
|
||||||
|
LOG_INFO(
|
||||||
|
"Using empty id for self-hosted server, server will assign new id");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
signal_server_ip = config_center_->GetDefaultServerHost();
|
signal_server_ip = config_center_->GetDefaultServerHost();
|
||||||
signal_server_port = config_center_->GetDefaultSignalServerPort();
|
signal_server_port = config_center_->GetDefaultSignalServerPort();
|
||||||
coturn_server_port = config_center_->GetDefaultCoturnServerPort();
|
coturn_server_port = config_center_->GetDefaultCoturnServerPort();
|
||||||
tls_cert_path = config_center_->GetDefaultCertFilePath();
|
tls_cert_fingerprint = config_center_->GetDefaultCertFingerprint();
|
||||||
|
params_.user_id = client_id_with_password_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// self hosted server config
|
// self hosted server config
|
||||||
strncpy(signal_server_ip_self_, config_center_->GetSignalServerHost().c_str(),
|
strncpy(signal_server_ip_self_, config_center_->GetSignalServerHost().c_str(),
|
||||||
sizeof(signal_server_ip_self_) - 1);
|
sizeof(signal_server_ip_self_) - 1);
|
||||||
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
||||||
strncpy(signal_server_port_self_,
|
int signal_port = config_center_->GetSignalServerPort();
|
||||||
std::to_string(config_center_->GetSignalServerPort()).c_str(),
|
if (signal_port > 0) {
|
||||||
sizeof(signal_server_port_self_) - 1);
|
strncpy(signal_server_port_self_, std::to_string(signal_port).c_str(),
|
||||||
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
sizeof(signal_server_port_self_) - 1);
|
||||||
strncpy(coturn_server_port_self_,
|
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
||||||
std::to_string(config_center_->GetCoturnServerPort()).c_str(),
|
} else {
|
||||||
sizeof(coturn_server_port_self_) - 1);
|
signal_server_port_self_[0] = '\0';
|
||||||
coturn_server_port_self_[sizeof(coturn_server_port_self_) - 1] = '\0';
|
}
|
||||||
|
int coturn_port = config_center_->GetCoturnServerPort();
|
||||||
|
if (coturn_port > 0) {
|
||||||
|
strncpy(coturn_server_port_self_, std::to_string(coturn_port).c_str(),
|
||||||
|
sizeof(coturn_server_port_self_) - 1);
|
||||||
|
coturn_server_port_self_[sizeof(coturn_server_port_self_) - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
coturn_server_port_self_[0] = '\0';
|
||||||
|
}
|
||||||
tls_cert_path_self_ = config_center_->GetCertFilePath();
|
tls_cert_path_self_ = config_center_->GetCertFilePath();
|
||||||
|
|
||||||
// peer config
|
// peer config
|
||||||
@@ -520,9 +649,30 @@ int Render::CreateConnectionPeer() {
|
|||||||
strncpy((char*)params_.turn_server_password, "crossdeskpw",
|
strncpy((char*)params_.turn_server_password, "crossdeskpw",
|
||||||
sizeof(params_.turn_server_password) - 1);
|
sizeof(params_.turn_server_password) - 1);
|
||||||
params_.turn_server_password[sizeof(params_.turn_server_password) - 1] = '\0';
|
params_.turn_server_password[sizeof(params_.turn_server_password) - 1] = '\0';
|
||||||
strncpy(params_.tls_cert_path, tls_cert_path.c_str(),
|
strncpy(params_.tls_cert_fingerprint, tls_cert_fingerprint.c_str(),
|
||||||
sizeof(params_.tls_cert_path) - 1);
|
sizeof(params_.tls_cert_fingerprint) - 1);
|
||||||
params_.tls_cert_path[sizeof(params_.tls_cert_path) - 1] = '\0';
|
params_.tls_cert_fingerprint[sizeof(params_.tls_cert_fingerprint) - 1] = '\0';
|
||||||
|
|
||||||
|
if (config_center_->IsSelfHosted()) {
|
||||||
|
params_.on_cert_fingerprint = [](const char* fingerprint, void* user_data) {
|
||||||
|
Render* render = static_cast<Render*>(user_data);
|
||||||
|
if (render && render->config_center_) {
|
||||||
|
render->config_center_->SetCertFingerprint(fingerprint);
|
||||||
|
LOG_INFO("Saved self-hosted certificate fingerprint: {}", fingerprint);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
params_.fingerprint_user_data = this;
|
||||||
|
} else {
|
||||||
|
params_.on_cert_fingerprint = [](const char* fingerprint, void* user_data) {
|
||||||
|
Render* render = static_cast<Render*>(user_data);
|
||||||
|
if (render && render->config_center_) {
|
||||||
|
render->config_center_->SetDefaultCertFingerprint(fingerprint);
|
||||||
|
LOG_INFO("Saved default server certificate fingerprint: {}",
|
||||||
|
fingerprint);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
params_.fingerprint_user_data = this;
|
||||||
|
}
|
||||||
|
|
||||||
strncpy(params_.log_path, dll_log_path_.c_str(),
|
strncpy(params_.log_path, dll_log_path_.c_str(),
|
||||||
sizeof(params_.log_path) - 1);
|
sizeof(params_.log_path) - 1);
|
||||||
@@ -546,7 +696,6 @@ int Render::CreateConnectionPeer() {
|
|||||||
params_.on_connection_status = OnConnectionStatusCb;
|
params_.on_connection_status = OnConnectionStatusCb;
|
||||||
params_.net_status_report = NetStatusReport;
|
params_.net_status_report = NetStatusReport;
|
||||||
|
|
||||||
params_.user_id = client_id_with_password_;
|
|
||||||
params_.user_data = this;
|
params_.user_data = this;
|
||||||
|
|
||||||
peer_ = CreatePeer(¶ms_);
|
peer_ = CreatePeer(¶ms_);
|
||||||
@@ -1038,10 +1187,15 @@ int Render::Run() {
|
|||||||
config_center_->GetSignalServerHost().c_str(),
|
config_center_->GetSignalServerHost().c_str(),
|
||||||
sizeof(signal_server_ip_self_) - 1);
|
sizeof(signal_server_ip_self_) - 1);
|
||||||
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
||||||
strncpy(signal_server_port_self_,
|
int signal_port_init = config_center_->GetSignalServerPort();
|
||||||
std::to_string(config_center_->GetSignalServerPort()).c_str(),
|
if (signal_port_init > 0) {
|
||||||
sizeof(signal_server_port_self_) - 1);
|
strncpy(signal_server_port_self_,
|
||||||
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
std::to_string(signal_port_init).c_str(),
|
||||||
|
sizeof(signal_server_port_self_) - 1);
|
||||||
|
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
signal_server_port_self_[0] = '\0';
|
||||||
|
}
|
||||||
strncpy(cert_file_path_, cert_path_.c_str(), sizeof(cert_file_path_) - 1);
|
strncpy(cert_file_path_, cert_path_.c_str(), sizeof(cert_file_path_) - 1);
|
||||||
cert_file_path_[sizeof(cert_file_path_) - 1] = '\0';
|
cert_file_path_[sizeof(cert_file_path_) - 1] = '\0';
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -277,8 +277,25 @@ class Render {
|
|||||||
unsigned char iv[16];
|
unsigned char iv[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CDCacheV2 {
|
||||||
|
char client_id_with_password[17];
|
||||||
|
int language;
|
||||||
|
int video_quality;
|
||||||
|
int video_frame_rate;
|
||||||
|
int video_encode_format;
|
||||||
|
bool enable_hardware_video_codec;
|
||||||
|
bool enable_turn;
|
||||||
|
bool enable_srtp;
|
||||||
|
|
||||||
|
unsigned char key[16];
|
||||||
|
unsigned char iv[16];
|
||||||
|
|
||||||
|
char self_hosted_id[17];
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CDCache cd_cache_;
|
CDCache cd_cache_;
|
||||||
|
CDCacheV2 cd_cache_v2_;
|
||||||
std::mutex cd_cache_mutex_;
|
std::mutex cd_cache_mutex_;
|
||||||
std::unique_ptr<ConfigCenter> config_center_;
|
std::unique_ptr<ConfigCenter> config_center_;
|
||||||
ConfigCenter::LANGUAGE localization_language_ =
|
ConfigCenter::LANGUAGE localization_language_ =
|
||||||
@@ -470,6 +487,8 @@ class Render {
|
|||||||
char client_id_display_[12] = "";
|
char client_id_display_[12] = "";
|
||||||
char client_id_with_password_[17] = "";
|
char client_id_with_password_[17] = "";
|
||||||
char password_saved_[7] = "";
|
char password_saved_[7] = "";
|
||||||
|
char self_hosted_id_[17] = "";
|
||||||
|
char self_hosted_user_id_[17] = "";
|
||||||
int language_button_value_ = 0;
|
int language_button_value_ = 0;
|
||||||
int video_quality_button_value_ = 0;
|
int video_quality_button_value_ = 0;
|
||||||
int video_frame_rate_button_value_ = 1;
|
int video_frame_rate_button_value_ = 1;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "device_controller.h"
|
#include "device_controller.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
@@ -556,24 +557,93 @@ void Render::NetStatusReport(const char* client_id, size_t client_id_size,
|
|||||||
password = at_pos + 1;
|
password = at_pos + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&render->client_id_, 0, sizeof(render->client_id_));
|
bool is_self_hosted = render->config_center_->IsSelfHosted();
|
||||||
strncpy(render->client_id_, id.c_str(), sizeof(render->client_id_) - 1);
|
|
||||||
render->client_id_[sizeof(render->client_id_) - 1] = '\0';
|
|
||||||
|
|
||||||
memset(&render->password_saved_, 0, sizeof(render->password_saved_));
|
if (is_self_hosted) {
|
||||||
strncpy(render->password_saved_, password.c_str(),
|
memset(&render->client_id_, 0, sizeof(render->client_id_));
|
||||||
sizeof(render->password_saved_) - 1);
|
strncpy(render->client_id_, id.c_str(), sizeof(render->client_id_) - 1);
|
||||||
render->password_saved_[sizeof(render->password_saved_) - 1] = '\0';
|
render->client_id_[sizeof(render->client_id_) - 1] = '\0';
|
||||||
|
|
||||||
memset(&render->client_id_with_password_, 0,
|
memset(&render->password_saved_, 0, sizeof(render->password_saved_));
|
||||||
sizeof(render->client_id_with_password_));
|
strncpy(render->password_saved_, password.c_str(),
|
||||||
strncpy(render->client_id_with_password_, client_id,
|
sizeof(render->password_saved_) - 1);
|
||||||
sizeof(render->client_id_with_password_) - 1);
|
render->password_saved_[sizeof(render->password_saved_) - 1] = '\0';
|
||||||
render->client_id_with_password_[sizeof(render->client_id_with_password_) -
|
|
||||||
|
memset(&render->self_hosted_id_, 0, sizeof(render->self_hosted_id_));
|
||||||
|
strncpy(render->self_hosted_id_, client_id,
|
||||||
|
sizeof(render->self_hosted_id_) - 1);
|
||||||
|
render->self_hosted_id_[sizeof(render->self_hosted_id_) - 1] = '\0';
|
||||||
|
|
||||||
|
LOG_INFO("Use self-hosted client id [{}] and save to cache file", id);
|
||||||
|
|
||||||
|
render->cd_cache_mutex_.lock();
|
||||||
|
|
||||||
|
std::ifstream v2_file_read(render->cache_path_ + "/secure_cache_v2.enc",
|
||||||
|
std::ios::binary);
|
||||||
|
if (v2_file_read.good()) {
|
||||||
|
v2_file_read.read(reinterpret_cast<char*>(&render->cd_cache_v2_),
|
||||||
|
sizeof(CDCacheV2));
|
||||||
|
v2_file_read.close();
|
||||||
|
} else {
|
||||||
|
memset(&render->cd_cache_v2_, 0, sizeof(CDCacheV2));
|
||||||
|
memset(&render->cd_cache_v2_.client_id_with_password, 0,
|
||||||
|
sizeof(render->cd_cache_v2_.client_id_with_password));
|
||||||
|
strncpy(render->cd_cache_v2_.client_id_with_password,
|
||||||
|
render->client_id_with_password_,
|
||||||
|
sizeof(render->cd_cache_v2_.client_id_with_password));
|
||||||
|
memcpy(&render->cd_cache_v2_.key, &render->aes128_key_,
|
||||||
|
sizeof(render->cd_cache_v2_.key));
|
||||||
|
memcpy(&render->cd_cache_v2_.iv, &render->aes128_iv_,
|
||||||
|
sizeof(render->cd_cache_v2_.iv));
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&render->cd_cache_v2_.self_hosted_id, 0,
|
||||||
|
sizeof(render->cd_cache_v2_.self_hosted_id));
|
||||||
|
strncpy(render->cd_cache_v2_.self_hosted_id, client_id,
|
||||||
|
sizeof(render->cd_cache_v2_.self_hosted_id) - 1);
|
||||||
|
render->cd_cache_v2_
|
||||||
|
.self_hosted_id[sizeof(render->cd_cache_v2_.self_hosted_id) - 1] =
|
||||||
|
'\0';
|
||||||
|
|
||||||
|
memset(&render->cd_cache_v2_.client_id_with_password, 0,
|
||||||
|
sizeof(render->cd_cache_v2_.client_id_with_password));
|
||||||
|
strncpy(render->cd_cache_v2_.client_id_with_password,
|
||||||
|
render->client_id_with_password_,
|
||||||
|
sizeof(render->cd_cache_v2_.client_id_with_password));
|
||||||
|
memcpy(&render->cd_cache_v2_.key, &render->aes128_key_,
|
||||||
|
sizeof(render->cd_cache_v2_.key));
|
||||||
|
memcpy(&render->cd_cache_v2_.iv, &render->aes128_iv_,
|
||||||
|
sizeof(render->cd_cache_v2_.iv));
|
||||||
|
std::ofstream cd_cache_v2_file(
|
||||||
|
render->cache_path_ + "/secure_cache_v2.enc", std::ios::binary);
|
||||||
|
if (cd_cache_v2_file) {
|
||||||
|
cd_cache_v2_file.write(reinterpret_cast<char*>(&render->cd_cache_v2_),
|
||||||
|
sizeof(CDCacheV2));
|
||||||
|
cd_cache_v2_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
render->cd_cache_mutex_.unlock();
|
||||||
|
} else {
|
||||||
|
memset(&render->client_id_, 0, sizeof(render->client_id_));
|
||||||
|
strncpy(render->client_id_, id.c_str(), sizeof(render->client_id_) - 1);
|
||||||
|
render->client_id_[sizeof(render->client_id_) - 1] = '\0';
|
||||||
|
|
||||||
|
memset(&render->password_saved_, 0, sizeof(render->password_saved_));
|
||||||
|
strncpy(render->password_saved_, password.c_str(),
|
||||||
|
sizeof(render->password_saved_) - 1);
|
||||||
|
render->password_saved_[sizeof(render->password_saved_) - 1] = '\0';
|
||||||
|
|
||||||
|
memset(&render->client_id_with_password_, 0,
|
||||||
|
sizeof(render->client_id_with_password_));
|
||||||
|
strncpy(render->client_id_with_password_, client_id,
|
||||||
|
sizeof(render->client_id_with_password_) - 1);
|
||||||
|
render
|
||||||
|
->client_id_with_password_[sizeof(render->client_id_with_password_) -
|
||||||
1] = '\0';
|
1] = '\0';
|
||||||
|
|
||||||
LOG_INFO("Use client id [{}] and save id into cache file", id);
|
LOG_INFO("Use client id [{}] and save id into cache file", id);
|
||||||
render->SaveSettingsIntoCacheFile();
|
render->SaveSettingsIntoCacheFile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string remote_id(user_id, user_id_size);
|
std::string remote_id(user_id, user_id_size);
|
||||||
|
|||||||
@@ -141,9 +141,6 @@ int Render::SelfHostedServerWindow() {
|
|||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
{
|
{
|
||||||
static int settings_items_padding = title_bar_button_width_;
|
|
||||||
int settings_items_offset = 0;
|
|
||||||
|
|
||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f);
|
||||||
@@ -159,8 +156,6 @@ int Render::SelfHostedServerWindow() {
|
|||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text("%s", localization::self_hosted_server_address
|
ImGui::Text("%s", localization::self_hosted_server_address
|
||||||
[localization_language_index_]
|
[localization_language_index_]
|
||||||
@@ -171,7 +166,6 @@ int Render::SelfHostedServerWindow() {
|
|||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
||||||
|
|
||||||
ImGui::InputText("##signal_server_ip_self_", signal_server_ip_self_,
|
ImGui::InputText("##signal_server_ip_self_", signal_server_ip_self_,
|
||||||
@@ -182,8 +176,6 @@ int Render::SelfHostedServerWindow() {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
@@ -195,7 +187,6 @@ int Render::SelfHostedServerWindow() {
|
|||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
||||||
|
|
||||||
ImGui::InputText("##signal_server_port_self_", signal_server_port_self_,
|
ImGui::InputText("##signal_server_port_self_", signal_server_port_self_,
|
||||||
@@ -205,8 +196,6 @@ int Render::SelfHostedServerWindow() {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text("%s", localization::self_hosted_server_coturn_server_port
|
ImGui::Text("%s", localization::self_hosted_server_coturn_server_port
|
||||||
[localization_language_index_]
|
[localization_language_index_]
|
||||||
@@ -217,7 +206,6 @@ int Render::SelfHostedServerWindow() {
|
|||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
||||||
}
|
}
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
||||||
|
|
||||||
ImGui::InputText("##coturn_server_port_self_", coturn_server_port_self_,
|
ImGui::InputText("##coturn_server_port_self_", coturn_server_port_self_,
|
||||||
@@ -226,38 +214,44 @@ int Render::SelfHostedServerWindow() {
|
|||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
{
|
// {
|
||||||
settings_items_offset += settings_items_padding;
|
// ImGui::AlignTextToFramePadding();
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
// ImGui::Text(
|
||||||
ImGui::AlignTextToFramePadding();
|
// "%s",
|
||||||
ImGui::Text("%s", localization::self_hosted_server_certificate_path
|
// localization::reset_cert_fingerprint[localization_language_index_]
|
||||||
[localization_language_index_]
|
// .c_str());
|
||||||
.c_str());
|
// ImGui::SameLine();
|
||||||
ImGui::SameLine();
|
// if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
// ImGui::SetCursorPosX(title_bar_button_width_ * 2.5f);
|
||||||
ImGui::SetCursorPosX(title_bar_button_width_ * 2.5f);
|
// } else {
|
||||||
} else {
|
// ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
||||||
ImGui::SetCursorPosX(title_bar_button_width_ * 3.43f);
|
// }
|
||||||
}
|
// ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::SetNextItemWidth(title_bar_button_width_ * 3.8f);
|
|
||||||
|
|
||||||
ShowSimpleFileBrowser();
|
// ShowSimpleFileBrowser();
|
||||||
|
// }
|
||||||
|
{
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
if (ImGui::Button(localization::reset_cert_fingerprint
|
||||||
|
[localization_language_index_]
|
||||||
|
.c_str())) {
|
||||||
|
config_center_->ClearCertFingerprint();
|
||||||
|
LOG_INFO("Certificate fingerprint cleared by user");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream_window_inited_) {
|
if (stream_window_inited_) {
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(0.0f, title_bar_button_width_ * 0.25f));
|
||||||
|
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
ImGui::SetCursorPosX(title_bar_button_width_ * 2.32f);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 2.32f);
|
||||||
} else {
|
} else {
|
||||||
ImGui::SetCursorPosX(title_bar_button_width_ * 2.7f);
|
ImGui::SetCursorPosX(title_bar_button_width_ * 2.7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
settings_items_offset +=
|
|
||||||
settings_items_padding + title_bar_button_width_ * 0.3f;
|
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
// OK
|
// OK
|
||||||
@@ -291,16 +285,27 @@ int Render::SelfHostedServerWindow() {
|
|||||||
localization::cancel[localization_language_index_].c_str())) {
|
localization::cancel[localization_language_index_].c_str())) {
|
||||||
show_self_hosted_server_config_window_ = false;
|
show_self_hosted_server_config_window_ = false;
|
||||||
self_hosted_server_config_window_pos_reset_ = true;
|
self_hosted_server_config_window_pos_reset_ = true;
|
||||||
|
strncpy(signal_server_ip_self_,
|
||||||
strncpy(signal_server_ip_self_, signal_server_ip_,
|
config_center_->GetSignalServerHost().c_str(),
|
||||||
sizeof(signal_server_ip_self_) - 1);
|
sizeof(signal_server_ip_self_) - 1);
|
||||||
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
||||||
strncpy(signal_server_port_self_, signal_server_port_,
|
int signal_port = config_center_->GetSignalServerPort();
|
||||||
sizeof(signal_server_port_self_) - 1);
|
if (signal_port > 0) {
|
||||||
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
strncpy(signal_server_port_self_, std::to_string(signal_port).c_str(),
|
||||||
config_center_->SetServerHost(signal_server_ip_self_);
|
sizeof(signal_server_port_self_) - 1);
|
||||||
config_center_->SetServerPort(atoi(signal_server_port_self_));
|
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
||||||
tls_cert_path_self_.clear();
|
} else {
|
||||||
|
signal_server_port_self_[0] = '\0';
|
||||||
|
}
|
||||||
|
int coturn_port = config_center_->GetCoturnServerPort();
|
||||||
|
if (coturn_port > 0) {
|
||||||
|
strncpy(coturn_server_port_self_, std::to_string(coturn_port).c_str(),
|
||||||
|
sizeof(coturn_server_port_self_) - 1);
|
||||||
|
coturn_server_port_self_[sizeof(coturn_server_port_self_) - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
coturn_server_port_self_[0] = '\0';
|
||||||
|
}
|
||||||
|
tls_cert_path_self_ = config_center_->GetCertFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SetWindowFontScale(1.0f);
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
|||||||
Submodule submodules/minirtc updated: 0008123221...f9810444ee
Reference in New Issue
Block a user