cdp-tunnel 2.1.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/index.js +15 -0
- package/extension-new/core/state.js +1 -1
- package/extension-new/core/websocket.js +30 -5
- package/package.json +1 -1
- package/server/proxy-server.js +12 -1
package/cli/index.js
CHANGED
|
@@ -104,6 +104,9 @@ function checkChromeExtension() {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
function getExtensionPath() {
|
|
107
|
+
if (process.env.CDP_TUNNEL_DEV_EXT) {
|
|
108
|
+
return process.env.CDP_TUNNEL_DEV_EXT;
|
|
109
|
+
}
|
|
107
110
|
const cliDir = __dirname;
|
|
108
111
|
return path.join(cliDir, '..', 'extension-new');
|
|
109
112
|
}
|
|
@@ -181,6 +184,18 @@ function startServer(port, watchdog, autoRestart) {
|
|
|
181
184
|
console.log(' 重启次数: ' + restartTimestamps.length + '/' + MAX_RESTARTS + ' (60秒内)');
|
|
182
185
|
console.log('');
|
|
183
186
|
|
|
187
|
+
// Kill any leftover process occupying the port before restarting
|
|
188
|
+
try {
|
|
189
|
+
const result = execSync(`lsof -ti:${port} 2>/dev/null || true`).toString().trim();
|
|
190
|
+
if (result) {
|
|
191
|
+
const pids = result.split('\n').filter(p => p && parseInt(p) !== process.pid);
|
|
192
|
+
pids.forEach(p => { try { process.kill(parseInt(p), 'SIGKILL'); } catch {} });
|
|
193
|
+
if (pids.length > 0) {
|
|
194
|
+
log('gray', ' 已清理占用端口 ' + port + ' 的残留进程: ' + pids.join(', '));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
} catch {}
|
|
198
|
+
|
|
184
199
|
setTimeout(() => startServer(port, true, autoRestart), 3000);
|
|
185
200
|
});
|
|
186
201
|
|
|
@@ -285,7 +285,7 @@ var State = (function() {
|
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
var cdpGroups = groups.filter(function(g) {
|
|
288
|
-
return g.title && g.title.indexOf('CDP-') === 0;
|
|
288
|
+
return g.title && (g.title.indexOf('CDP-') === 0 || g.title.indexOf('CDP #') === 0);
|
|
289
289
|
});
|
|
290
290
|
|
|
291
291
|
if (cdpGroups.length === 0) {
|
|
@@ -316,6 +316,7 @@ var WebSocketManager = (function() {
|
|
|
316
316
|
|
|
317
317
|
function closeTabsByClientId(clientId, resolve) {
|
|
318
318
|
var attachedTabs = State.getAttachedTabIds();
|
|
319
|
+
var groupId = State.getGroupIdForClient(clientId);
|
|
319
320
|
var tabsToClose = [];
|
|
320
321
|
|
|
321
322
|
attachedTabs.forEach(function(tabId) {
|
|
@@ -329,10 +330,35 @@ var WebSocketManager = (function() {
|
|
|
329
330
|
resolve();
|
|
330
331
|
return;
|
|
331
332
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
333
|
+
|
|
334
|
+
if (groupId) {
|
|
335
|
+
chrome.tabs.query({ groupId: groupId }, function(groupTabs) {
|
|
336
|
+
if (chrome.runtime.lastError || !groupTabs) {
|
|
337
|
+
resolve();
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
var groupTabIds = new Set(groupTabs.map(function(t) { return t.id; }));
|
|
341
|
+
var safeToClose = tabsToClose.filter(function(tabId) {
|
|
342
|
+
return groupTabIds.has(tabId);
|
|
343
|
+
});
|
|
344
|
+
var unsafeCount = tabsToClose.length - safeToClose.length;
|
|
345
|
+
if (unsafeCount > 0) {
|
|
346
|
+
Logger.info('[WS] Protecting ' + unsafeCount + ' tabs outside group from deletion');
|
|
347
|
+
}
|
|
348
|
+
doCloseTabs(safeToClose, clientId, resolve);
|
|
349
|
+
});
|
|
350
|
+
} else {
|
|
351
|
+
doCloseTabs(tabsToClose, clientId, resolve);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function doCloseTabs(tabIds, clientId, resolve) {
|
|
356
|
+
if (tabIds.length === 0) {
|
|
357
|
+
resolve();
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
Logger.info('[WS] Closing ' + tabIds.length + ' attached tabs for clientId:', clientId);
|
|
361
|
+
tabIds.forEach(function(tabId) {
|
|
336
362
|
chrome.tabs.remove(tabId, function() {
|
|
337
363
|
if (chrome.runtime.lastError) {
|
|
338
364
|
Logger.info('[WS] Tab already closed:', tabId);
|
|
@@ -341,7 +367,6 @@ var WebSocketManager = (function() {
|
|
|
341
367
|
chrome.debugger.detach({ tabId: tabId }).catch(function() {});
|
|
342
368
|
State.removeAttachedTab(tabId);
|
|
343
369
|
});
|
|
344
|
-
|
|
345
370
|
resolve();
|
|
346
371
|
}
|
|
347
372
|
|
package/package.json
CHANGED
package/server/proxy-server.js
CHANGED
|
@@ -22,6 +22,7 @@ const PORT = CONFIG.PORT;
|
|
|
22
22
|
const CONFIG_DIR = path.join(os.homedir(), '.cdp-tunnel');
|
|
23
23
|
const EXTENSION_STATE_FILE = path.join(CONFIG_DIR, 'extension-state.json');
|
|
24
24
|
const PLUGIN_EVER_CONNECTED_FILE = path.join(CONFIG_DIR, 'plugin-ever-connected');
|
|
25
|
+
const SERVER_START_TIME = Date.now();
|
|
25
26
|
|
|
26
27
|
let lastChromeRestartAttempt = 0;
|
|
27
28
|
const CHROME_RESTART_COOLDOWN = CONFIG.CHROME_RESTART_COOLDOWN;
|
|
@@ -739,7 +740,7 @@ function handlePluginConnection(ws, clientInfo) {
|
|
|
739
740
|
type: 'connected',
|
|
740
741
|
role: 'plugin',
|
|
741
742
|
id: id,
|
|
742
|
-
fresh:
|
|
743
|
+
fresh: (Date.now() - SERVER_START_TIME) < 5000,
|
|
743
744
|
timestamp: Date.now()
|
|
744
745
|
}));
|
|
745
746
|
}
|
|
@@ -1513,4 +1514,14 @@ process.on('SIGTERM', () => {
|
|
|
1513
1514
|
process.exit(0);
|
|
1514
1515
|
});
|
|
1515
1516
|
|
|
1517
|
+
server.on('error', (err) => {
|
|
1518
|
+
if (err.code === 'EADDRINUSE') {
|
|
1519
|
+
console.error(`[FATAL] Port ${PORT} is already in use. Is another cdp-tunnel running?`);
|
|
1520
|
+
console.error(` Run "cdp-tunnel stop" first, or kill the process on port ${PORT}.`);
|
|
1521
|
+
process.exit(2);
|
|
1522
|
+
}
|
|
1523
|
+
console.error('[FATAL] Server error:', err.message);
|
|
1524
|
+
process.exit(1);
|
|
1525
|
+
});
|
|
1526
|
+
|
|
1516
1527
|
server.listen(PORT, '0.0.0.0');
|