Compare commits

...

4 Commits

Author SHA1 Message Date
lejianwen
a771b1e9b0 fix(webclient): remove console.log when query online by new 2024-12-21 21:49:03 +08:00
lejianwen
7750f9c54d chore(changelog): up build.yml to add changelog 2024-12-21 21:39:11 +08:00
lejianwen
b2d24ee67b docs(webclient): up readme 2024-12-21 21:31:54 +08:00
lejianwen
589a2a5123 feat(webclient): add new query_online function
There may be a loss of performance
Therefore, it is not enabled by default
2024-12-21 21:15:06 +08:00
7 changed files with 184 additions and 86 deletions

View File

@@ -55,6 +55,8 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go environment - name: Set up Go environment
uses: actions/setup-go@v4 uses: actions/setup-go@v4
@@ -121,6 +123,12 @@ jobs:
name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }} name: rustdesk-api-${{ matrix.job.goos }}-${{ matrix.job.platform }}
path: | path: |
${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}} ${{ matrix.job.goos}}-${{ matrix.job.platform }}.${{matrix.job.file_ext}}
- name: Generate Changelog
run: npx changelogithub # or changelogithub@0.12 if ensure the stable result
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Upload to GitHub Release - name: Upload to GitHub Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:

View File

@@ -210,38 +210,39 @@ proxy:
### 环境变量 ### 环境变量
变量名前缀是`RUSTDESK_API`,环境变量如果存在将覆盖配置文件中的配置 变量名前缀是`RUSTDESK_API`,环境变量如果存在将覆盖配置文件中的配置
| 变量名 | 说明 | 示例 | | 变量名 | 说明 | 示例 |
|------------------------------------|---------------------------------------------------------|------------------------------| |---------------------------------------------------|---------------------------------------------------------|------------------------------|
| TZ | 时区 | Asia/Shanghai | | TZ | 时区 | Asia/Shanghai |
| RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` | | RUSTDESK_API_LANG | 语言 | `en`,`zh-CN` |
| RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 | | RUSTDESK_API_APP_WEB_CLIENT | 是否启用web-client; 1:启用,0:不启用; 默认启用 | 1 |
| RUSTDESK_API_APP_REGISTER | 是否开启注册; `true`, `false` 默认`false` | `false` | | RUSTDESK_API_APP_REGISTER | 是否开启注册; `true`, `false` 默认`false` | `false` |
| RUSTDESK_API_APP_SHOW_SWAGGER | 是否可见swagger文档;`1`显示,`0`不显示,默认`0`不显示 | `1` | | RUSTDESK_API_APP_SHOW_SWAGGER | 是否可见swagger文档;`1`显示,`0`不显示,默认`0`不显示 | `1` |
| -----ADMIN配置----- | ---------- | ---------- | | -----ADMIN配置----- | ---------- | ---------- |
| RUSTDESK_API_ADMIN_TITLE | 后台标题 | `RustDesk Api Admin` | | RUSTDESK_API_ADMIN_TITLE | 后台标题 | `RustDesk Api Admin` |
| RUSTDESK_API_ADMIN_HELLO | 后台欢迎语,可以使用`html` | | | RUSTDESK_API_ADMIN_HELLO | 后台欢迎语,可以使用`html` | |
| RUSTDESK_API_ADMIN_HELLO_FILE | 后台欢迎语文件,如果内容多,使用文件更方便。<br>会覆盖`RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` | | RUSTDESK_API_ADMIN_HELLO_FILE | 后台欢迎语文件,如果内容多,使用文件更方便。<br>会覆盖`RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
| -----GIN配置----- | ---------- | ---------- | | -----GIN配置----- | ---------- | ---------- |
| RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 | | RUSTDESK_API_GIN_TRUST_PROXY | 信任的代理IP列表以`,`分割,默认信任所有 | 192.168.1.2,192.168.1.3 |
| -----------GORM配置---------------- | ------------------------------------ | --------------------------- | | -----------GORM配置---------------- | ------------------------------------ | --------------------------- |
| RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql默认sqlite | sqlite | | RUSTDESK_API_GORM_TYPE | 数据库类型sqlite或者mysql默认sqlite | sqlite |
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 | | RUSTDESK_API_GORM_MAX_IDLE_CONNS | 数据库最大空闲连接数 | 10 |
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 | | RUSTDESK_API_GORM_MAX_OPEN_CONNS | 数据库最大打开连接数 | 100 |
| RUSTDESK_API_RUSTDESK_PERSONAL | 是否启用个人版API 1:启用,0:不启用; 默认启用 | 1 | | RUSTDESK_API_RUSTDESK_PERSONAL | 是否启用个人版API 1:启用,0:不启用; 默认启用 | 1 |
| -----MYSQL配置----- | ---------- | ---------- | | -----MYSQL配置----- | ---------- | ---------- |
| RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root | | RUSTDESK_API_MYSQL_USERNAME | mysql用户名 | root |
| RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 | | RUSTDESK_API_MYSQL_PASSWORD | mysql密码 | 111111 |
| RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 | | RUSTDESK_API_MYSQL_ADDR | mysql地址 | 192.168.1.66:3306 |
| RUSTDESK_API_MYSQL_DBNAME | mysql数据库名 | rustdesk | | RUSTDESK_API_MYSQL_DBNAME | mysql数据库名 | rustdesk |
| -----RUSTDESK配置----- | --------------- | ---------- | | -----RUSTDESK配置----- | --------------- | ---------- |
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk的id服务器地址 | 192.168.1.66:21116 | | RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk的id服务器地址 | 192.168.1.66:21116 |
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk的relay服务器地址 | 192.168.1.66:21117 | | RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk的relay服务器地址 | 192.168.1.66:21117 |
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 | | RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk的api服务器地址 | http://192.168.1.66:21114 |
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 | | RUSTDESK_API_RUSTDESK_KEY | Rustdesk的key | 123456789 |
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk存放key的文件 | `./conf/data/id_ed25519.pub` | | RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk存放key的文件 | `./conf/data/id_ed25519.pub` |
| ----PROXY配置----- | --------------- | ---------- | | RUSTDESK_API_RUSTDESK_WEBCLIENT_MAGIC_QUERYONLINE | Web client v2 中是否启用新的在线状态查询方法; `1`:启用,`0`:不启用,默认不启用 | `0` |
| RUSTDESK_API_PROXY_ENABLE | 是否启用代理:`false`, `true` | `false` | | ----PROXY配置----- | --------------- | ---------- |
| RUSTDESK_API_PROXY_HOST | 代理地址 | `http://127.0.0.1:1080` | | RUSTDESK_API_PROXY_ENABLE | 是否启用代理:`false`, `true` | `false` |
| RUSTDESK_API_PROXY_HOST | 代理地址 | `http://127.0.0.1:1080` |
### 运行 ### 运行

View File

@@ -213,38 +213,39 @@ proxy:
### Environment Variables ### Environment Variables
The prefix for variable names is `RUSTDESK_API`. If environment variables exist, they will override the configurations in the configuration file. The prefix for variable names is `RUSTDESK_API`. If environment variables exist, they will override the configurations in the configuration file.
| Variable Name | Description | Example | | Variable Name | Description | Example |
|------------------------------------|-------------------------------------------------------------------------|-------------------------------| |-----------------------------------------------------|--------------------------------------------------------------------------------------------------------------|-------------------------------|
| TZ | timezone | Asia/Shanghai | | TZ | timezone | Asia/Shanghai |
| RUSTDESK_API_LANG | Language | `en`,`zh-CN` | | RUSTDESK_API_LANG | Language | `en`,`zh-CN` |
| RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, default: 1 | 1 | | RUSTDESK_API_APP_WEB_CLIENT | web client on/off; 1: on, 0 off, default: 1 | 1 |
| RUSTDESK_API_APP_REGISTER | register enable; `true`, `false`; default:`false` | `false` | | RUSTDESK_API_APP_REGISTER | register enable; `true`, `false`; default:`false` | `false` |
| RUSTDESK_API_APP_SHOW_SWAGGER | swagger visible; 1: yes, 0: no; default: 0 | `0` | | RUSTDESK_API_APP_SHOW_SWAGGER | swagger visible; 1: yes, 0: no; default: 0 | `0` |
| ----- ADMIN Configuration----- | ---------- | ---------- | | ----- ADMIN Configuration----- | ---------- | ---------- |
| RUSTDESK_API_ADMIN_TITLE | Admin Title | `RustDesk Api Admin` | | RUSTDESK_API_ADMIN_TITLE | Admin Title | `RustDesk Api Admin` |
| RUSTDESK_API_ADMIN_HELLO | Admin welcome message, you can use `html` | | | RUSTDESK_API_ADMIN_HELLO | Admin welcome message, you can use `html` | |
| RUSTDESK_API_ADMIN_HELLO_FILE | Admin welcome message file,<br>will override `RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` | | RUSTDESK_API_ADMIN_HELLO_FILE | Admin welcome message file,<br>will override `RUSTDESK_API_ADMIN_HELLO` | `./conf/admin/hello.html` |
| ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- | | ----- GIN Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 | | RUSTDESK_API_GIN_TRUST_PROXY | Trusted proxy IPs, separated by commas. | 192.168.1.2,192.168.1.3 |
| ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- | | ----- GORM Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite | | RUSTDESK_API_GORM_TYPE | Database type (`sqlite` or `mysql`). Default is `sqlite`. | sqlite |
| RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 | | RUSTDESK_API_GORM_MAX_IDLE_CONNS | Maximum idle connections | 10 |
| RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 | | RUSTDESK_API_GORM_MAX_OPEN_CONNS | Maximum open connections | 100 |
| RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 | | RUSTDESK_API_RUSTDESK_PERSONAL | Open Personal Api 1:Enable,0:Disable | 1 |
| ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- | | ----- MYSQL Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_MYSQL_USERNAME | MySQL username | root | | RUSTDESK_API_MYSQL_USERNAME | MySQL username | root |
| RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 | | RUSTDESK_API_MYSQL_PASSWORD | MySQL password | 111111 |
| RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 | | RUSTDESK_API_MYSQL_ADDR | MySQL address | 192.168.1.66:3306 |
| RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk | | RUSTDESK_API_MYSQL_DBNAME | MySQL database name | rustdesk |
| ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- | | ----- RUSTDESK Configuration ----- | --------------------------------------- | ----------------------------- |
| RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 | | RUSTDESK_API_RUSTDESK_ID_SERVER | Rustdesk ID server address | 192.168.1.66:21116 |
| RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 | | RUSTDESK_API_RUSTDESK_RELAY_SERVER | Rustdesk relay server address | 192.168.1.66:21117 |
| RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 | | RUSTDESK_API_RUSTDESK_API_SERVER | Rustdesk API server address | http://192.168.1.66:21114 |
| RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 | | RUSTDESK_API_RUSTDESK_KEY | Rustdesk key | 123456789 |
| RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk存放key的文件 | `./conf/data/id_ed25519.pub` | | RUSTDESK_API_RUSTDESK_KEY_FILE | Rustdesk key file | `./conf/data/id_ed25519.pub` |
| ---- PROXY ----- | --------------- | ---------- | | RUSTDESK_API_RUSTDESK_WEBCLIENT_MAGIC_QUERYONLINE | New online query method is enabled in the web client v2; '1': Enabled, '0': Disabled, not enabled by default | `0` |
| RUSTDESK_API_PROXY_ENABLE | proxy_enable :`false`, `true` | `false` | | ---- PROXY ----- | --------------- | ---------- |
| RUSTDESK_API_PROXY_HOST | proxy_host | `http://127.0.0.1:1080` | | RUSTDESK_API_PROXY_ENABLE | proxy_enable :`false`, `true` | `false` |
| RUSTDESK_API_PROXY_HOST | proxy_host | `http://127.0.0.1:1080` |
### Installation Steps ### Installation Steps

View File

@@ -28,6 +28,7 @@ rustdesk:
key: "" key: ""
key-file: "./conf/data/id_ed25519.pub" key-file: "./conf/data/id_ed25519.pub"
personal: 1 personal: 1
webclient-magic-queryonline: 0
logger: logger:
path: "./runtime/log.txt" path: "./runtime/log.txt"
level: "warn" #trace,debug,info,warn,error,fatal level: "warn" #trace,debug,info,warn,error,fatal

View File

@@ -11,6 +11,8 @@ type Rustdesk struct {
Key string `mapstructure:"key"` Key string `mapstructure:"key"`
KeyFile string `mapstructure:"key-file"` KeyFile string `mapstructure:"key-file"`
Personal int `mapstructure:"personal"` Personal int `mapstructure:"personal"`
//webclient-magic-queryonline
WebclientMagicQueryonline int `mapstructure:"webclient-magic-queryonline"`
} }
func LoadKeyFile(rustdesk *Rustdesk) { func LoadKeyFile(rustdesk *Rustdesk) {

View File

@@ -3,6 +3,7 @@ package web
import ( import (
"Gwen/global" "Gwen/global"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"strconv"
) )
type Index struct { type Index struct {
@@ -14,11 +15,13 @@ func (i *Index) Index(c *gin.Context) {
func (i *Index) ConfigJs(c *gin.Context) { func (i *Index) ConfigJs(c *gin.Context) {
apiServer := global.Config.Rustdesk.ApiServer apiServer := global.Config.Rustdesk.ApiServer
magicQueryonline := strconv.Itoa(global.Config.Rustdesk.WebclientMagicQueryonline)
tmp := ` tmp := `
localStorage.setItem('api-server', "` + apiServer + `") localStorage.setItem('api-server', "` + apiServer + `")
const ws2_prefix = 'wc-' const ws2_prefix = 'wc-'
localStorage.setItem(ws2_prefix+'api-server', "` + apiServer + `") localStorage.setItem(ws2_prefix+'api-server', "` + apiServer + `")
`
window.webclient_magic_queryonline = ` + magicQueryonline + ``
c.String(200, tmp) c.String(200, tmp)
} }

View File

@@ -11112,6 +11112,71 @@ function nt(u, e) {
ye("callback_query_onlines", {onlines: u.join(","), offlines: e.join(",")}) ye("callback_query_onlines", {onlines: u.join(","), offlines: e.join(",")})
} }
const onlineCache = {}
// Query onlines
async function myQueryOnline(id) {
const last_online = onlineCache[id]
if (last_online && new Date().getTime() - last_online < 20 * 1000) {
return true
}
// 映射 方便后期更新
const maps = {
uri: P4(),
ws: j4,
conn_type: ne.DEFAULT_CONN,
nat_type: pt.SYMMETRIC,
token: Pt(),
version: se,
licence_key: Io(),
rendezvousPunchHoleRequest: Ku,
rendezvousPunchHoleResponse_Failure: Z0
}
const s = new maps.ws(maps.uri, !0, "rendezvous");
await s.open();
const punch_hole_request = maps.rendezvousPunchHoleRequest.fromPartial({
id: id,
licence_key: maps.licence_key,
conn_type: maps.conn_type,
nat_type: maps.nat_type,
token: maps.token,
version: maps.version
});
s.sendRendezvous({punch_hole_request: punch_hole_request});
const msg = await s.next();
s.close();
let online = false
const phr = msg.punch_hole_response, rr = msg.relay_response;
if (phr) {
online = true
if (phr != null && phr.other_failure) {
online = false
return online
}
if (phr.failure != maps.rendezvousPunchHoleResponse_Failure.UNRECOGNIZED) switch (phr == null ? void 0 : phr.failure) {
case maps.rendezvousPunchHoleResponse_Failure.ID_NOT_EXIST:
case maps.rendezvousPunchHoleResponse_Failure.OFFLINE:
case maps.rendezvousPunchHoleResponse_Failure.LICENSE_MISMATCH:
case maps.rendezvousPunchHoleResponse_Failure.LICENSE_OVERUSE:
online = false
break
}
} else if (rr) {
online = true
if (!rr.version) {
online = false
return online
}
}
if (online) {
onlineCache[id] = new Date().getTime()
} else if (onlineCache[id]) {
delete onlineCache[id]
}
return online
}
async function wn(u) { async function wn(u) {
let e = []; let e = [];
try { try {
@@ -11121,28 +11186,45 @@ async function wn(u) {
return return
} }
if (e.length === 0) return; if (e.length === 0) return;
const i = bn(), o = new j4(i, !0, "query onlines");
try { if (window.webclient_magic_queryonline) {
await o.open(); const onlines = []
const a = Ju.fromPartial({id: N4(), peers: e}); const offlines = []
o.sendRendezvous({online_request: a}) for (let i = 0; i < e.length; i++) {
} catch (a) { let online = await myQueryOnline(e[i])
console.error("Failed to query onlines, ", a), nt([], e), o.close(); if (online) {
return onlines.push(e[i])
} } else {
for (let a = 0; a < 2; a++) { offlines.push(e[i])
const t = await Ro(o, 3e3); }
if (!t || (t == null ? void 0 : t.key_exchange) || (t == null ? void 0 : t.online_response) === void 0) continue;
const s = t.online_response.states;
let l = [], E = [];
for (let c = 0; c < e.length; c++) {
const C = 1 << 7 - c % 8;
(s[Math.floor(c / 8)] & C) === C ? l.push(e[c]) : E.push(e[c])
} }
nt(l, E), o.close(); nt(onlines, offlines)
return } else {
const i = bn(), o = new j4(i, !0, "query onlines");
try {
await o.open();
const a = Ju.fromPartial({id: N4(), peers: e});
o.sendRendezvous({online_request: a})
} catch (a) {
console.error("Failed to query onlines, ", a), nt([], e), o.close();
return
}
for (let a = 0; a < 2; a++) {
const t = await Ro(o, 3e3);
if (!t || (t == null ? void 0 : t.key_exchange) || (t == null ? void 0 : t.online_response) === void 0) continue;
const s = t.online_response.states;
let l = [], E = [];
for (let c = 0; c < e.length; c++) {
const C = 1 << 7 - c % 8;
(s[Math.floor(c / 8)] & C) === C ? l.push(e[c]) : E.push(e[c])
}
nt(l, E), o.close();
return
}
o.close(), console.error("Failed to query online states, no online response")
} }
o.close(), console.error("Failed to query online states, no online response")
} }
window.curConn = void 0; window.curConn = void 0;