Skip to content

Commit c604703

Browse files
committed
check update
1 parent 1f20e21 commit c604703

File tree

11 files changed

+4998
-21
lines changed

11 files changed

+4998
-21
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@conet.project/conet-proxy",
33

4-
"version": "1.0.2",
4+
"version": "1.1.0",
55

66
"license": "UNLICENSED",
77
"files": [

src/localServer/localServer.ts

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,93 @@ import * as openpgp from 'openpgp'
1414
import os from 'node:os'
1515
import CONET_Guardian_NodeInfo_ABI from './CONET_Guardian_NodeInfo_ABI.json'
1616
import {runUpdater, readUpdateInfo} from './updateProcess'
17+
import allNodes from './nodes.json'
1718
import fs from 'node:fs'
1819
import {LayerMinus} from './layerMinus'
1920

21+
2022
const ver = '0.1.5'
2123

24+
const deleteNodeFromList = (node: nodes_info) => {
25+
const index = allNodes.findIndex(n => n.ip_addr === node.ip_addr)
26+
if (index > -1) {
27+
allNodes.splice(index, 1)
28+
}
29+
}
30+
31+
export const postToEndpoint = async <T = any> (
32+
url: string,
33+
post: boolean,
34+
jsonData?: any,
35+
timeoutMs = 5 * 1000
36+
): Promise<"" | boolean | T> => {
37+
const ac = new AbortController();
38+
39+
40+
try {
41+
const timer = setTimeout(() => ac.abort('TimeoutError'), timeoutMs);
42+
const res = await fetch(url, {
43+
method: post ? "POST" : "GET",
44+
headers:
45+
post && jsonData !== undefined
46+
? { "Content-Type": "application/json;charset=UTF-8" }
47+
: undefined,
48+
body: post ? (jsonData ? JSON.stringify(jsonData) : "") : undefined,
49+
signal: ac.signal,
50+
});
51+
52+
// 200 → resolve(false)
53+
if (res.status < 200 || res.status >= 300) {
54+
return false;
55+
}
56+
clearTimeout(timer);
57+
const text = await res.text();
58+
if (!text.length) {
59+
return "";
60+
}
61+
62+
// 优先依据 Content-Type
63+
const ct = (res.headers.get("Content-Type") || "").toLowerCase();
64+
if (ct.includes("application/json") || ct.includes("+json")) {
65+
return JSON.parse(text) as T;
66+
}
67+
68+
// 回落:尝试 JSON 解析;失败时保持原规则(POST→"",GET→true)
69+
try {
70+
return JSON.parse(text) as T;
71+
} catch {
72+
return (post ? "" : true) as any;
73+
}
74+
} catch (err) {
75+
// AbortError/网络错误 → reject
76+
throw err;
77+
}
78+
}
79+
80+
81+
const testNode = (node: nodes_info): Promise<boolean> => new Promise (async executor => {
82+
try {
83+
const url = `http://${node.ip_addr}`
84+
await postToEndpoint(url, false, false, 1000)
85+
// 只有在“计入结果”的时候才判断是否够数
86+
executor(true)
87+
} catch (e) {
88+
// 失败再次测试
89+
deleteNodeFromList(node)
90+
executor(false)
91+
}
92+
})
93+
94+
const getRandomNode = async () => {
95+
const index = Math.floor(Math.random() * allNodes.length)
96+
const node = allNodes[index]
97+
const isWorking = await testNode(node)
98+
if (!isWorking) {
99+
return await getRandomNode ()
100+
}
101+
return node
102+
103+
}
22104
const getLocalNetworkIpaddress = () => {
23105
const interfaceAll = os.networkInterfaces()
24106
let ipv4: string[] = []
@@ -179,7 +261,7 @@ const startSilentPass = (vpnObj: Native_StartVPNObj, currentVer: UpdateInfo, rea
179261
const layerMinus = new LayerMinus(vpnObj.entryNodes, vpnObj.exitNode, vpnObj.privateKey)
180262
_proxyServer = new ProxyServer(3002, layerMinus)
181263
_proxyServer.start()
182-
runUpdater(vpnObj.entryNodes, currentVer, reactFolder, restart)
264+
//runUpdater(vpnObj.entryNodes, currentVer, reactFolder, restart)
183265
return _proxyServer
184266
}
185267

@@ -223,6 +305,15 @@ type filterRule = {
223305
}
224306

225307

308+
const checkUpdateProcess = async (currentVer: UpdateInfo, reactFolder: string, restart: () => Promise<void>) => {
309+
const node = await getRandomNode()
310+
await runUpdater(node, currentVer, reactFolder, restart)
311+
setTimeout(() => {
312+
checkUpdateProcess (currentVer, reactFolder, restart)
313+
}, 1000 * 60 * 10)
314+
}
315+
316+
226317
export class Daemon {
227318
private logsPool: proxyLogs[] = []
228319

@@ -279,7 +370,10 @@ export class Daemon {
279370
if (!this.currentVer) {
280371
staticFolder = defaultPath
281372
logger(Colors.red(`updatedPath ERROR, go back to defaultPath ${defaultPath}`))
282-
}
373+
} else {
374+
// start check update process
375+
checkUpdateProcess ( this.currentVer, this.reactBuildFolder, this.restart)
376+
}
283377

284378
// --- 关键逻辑结束 ---
285379

@@ -563,6 +657,8 @@ export class Daemon {
563657
{ 'Serving files from': staticFolder }
564658
])
565659
})
660+
661+
566662
}
567663

568664
// 将 restart 方法改为箭头函数属性

src/localServer/nodes.json

Lines changed: 4736 additions & 0 deletions
Large diffs are not rendered by default.

src/localServer/updateProcess.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ const getRandomNode = (nodes: nodes_info[]): nodes_info => {
103103
* @param folderPath 要检查的文件夹根路径
104104
* @returns 如果验证通过则返回 true,否则返回 false
105105
*/
106-
const validateUpdateContents = async (folderPath: string, ver: string, nodes: nodes_info[]): Promise<boolean> => {
106+
const validateUpdateContents = async (folderPath: string, ver: string, randomNode: nodes_info): Promise<boolean> => {
107107
logger('🔍 开始验证和修复更新内容...')
108108
const manifestPath = join(folderPath, 'asset-manifest.json')
109109

@@ -112,7 +112,6 @@ const validateUpdateContents = async (folderPath: string, ver: string, nodes: no
112112
if (!fs.existsSync(manifestPath)) {
113113
logger('🔴 验证失败: 关键文件 asset-manifest.json 未找到!')
114114
// 如果清单都不存在,可以尝试下载它本身
115-
const randomNode = getRandomNode(nodes)
116115
const manifestUrl = `http://${randomNode.ip_addr}/silentpass-rpc/asset-manifest.json`
117116
logger(`尝试下载缺失的 asset-manifest.json from ${manifestUrl}`)
118117
await downloadSingleFileHttp(manifestUrl, manifestPath)
@@ -138,7 +137,6 @@ const validateUpdateContents = async (folderPath: string, ver: string, nodes: no
138137
if (!fs.existsSync(fullPath)) {
139138
logger(`🟡 文件缺失: ${localFilePath}。准备下载...`)
140139

141-
const randomNode = getRandomNode(nodes)
142140
const downloadUrl = `http://${randomNode.ip_addr}/silentpass-rpc/${localFilePath}`
143141

144142
// 将下载任务的 Promise 添加到数组中
@@ -255,15 +253,14 @@ export const readUpdateInfo = async (staticFolder: string, ver: string): Promise
255253
/**
256254
* 主更新函数
257255
*/
258-
export const runUpdater = async (nodes: nodes_info[], currentVer: UpdateInfo, reactFolder: string, restart: () => Promise<void> ) => {
256+
export const runUpdater = async (selectedNode: nodes_info, currentVer: UpdateInfo, reactFolder: string, restart: () => Promise<void> ) => {
259257

260258

261-
logger('🚀 开始执行动态节点更新程序...')
259+
logger(`🚀 开始执行动态节点更新程序... local version = ${currentVer.ver}`)
262260

263261
try {
264262
tempUpdatePath = join(reactFolder, `conet-update-${Date.now()}`)
265263

266-
const selectedNode = getRandomNode(nodes)
267264
logger(`✅ 节点列表获取成功!已随机选择节点: ${selectedNode.ip_addr} (位于 ${selectedNode.region})`);
268265

269266
// --- 步骤 2: 使用选定节点的 IP 获取更新信息 ---
@@ -313,7 +310,7 @@ export const runUpdater = async (nodes: nodes_info[], currentVer: UpdateInfo, re
313310
logger(`🎉 成功下载并解压文件到 ${tempUpdatePath}`)
314311

315312
// 2. 验证内容
316-
if (!(await validateUpdateContents(tempUpdatePath, updateInfo.ver, nodes))) {
313+
if (!(await validateUpdateContents(tempUpdatePath, updateInfo.ver, selectedNode))) {
317314
throw new Error('下载的内容无效或不完整,已终止更新。')
318315
}
319316

@@ -373,3 +370,5 @@ function isNewerVersion(oldVer: string, newVer: string): boolean {
373370
return false // 如果版本号完全相同,则不是更新的版本
374371
}
375372

373+
374+

src/localServer/workers/asset-manifest.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"files": {
33
"main.css": "/static/css/main.0cb9cf36.css",
4-
"main.js": "/static/js/main.e7a80705.js",
4+
"main.js": "/static/js/main.5142b55d.js",
55
"static/js/453.a5cbc0be.chunk.js": "/static/js/453.a5cbc0be.chunk.js",
66
"static/media/GC.svg": "/static/media/GC.32c345f58a5986b6be47a893faa2ccfc.svg",
77
"static/media/sp-token.svg": "/static/media/sp-token.cc8bab92d2fc3d4bed2b9a9a85731b6e.svg",
@@ -42,11 +42,11 @@
4242
"static/media/home-icon-blue.svg": "/static/media/home-icon-blue.df38257e8df35d5d6d3197cc84871954.svg",
4343
"static/media/home-icon-grey.svg": "/static/media/home-icon-grey.7c0953e4572ebe8dd813c4a3cd870b10.svg",
4444
"main.0cb9cf36.css.map": "/static/css/main.0cb9cf36.css.map",
45-
"main.e7a80705.js.map": "/static/js/main.e7a80705.js.map",
45+
"main.5142b55d.js.map": "/static/js/main.5142b55d.js.map",
4646
"453.a5cbc0be.chunk.js.map": "/static/js/453.a5cbc0be.chunk.js.map"
4747
},
4848
"entrypoints": [
4949
"static/css/main.0cb9cf36.css",
50-
"static/js/main.e7a80705.js"
50+
"static/js/main.5142b55d.js"
5151
]
5252
}

0 commit comments

Comments
 (0)