Status Window
This commit is contained in:
172
background.js
172
background.js
@@ -12,6 +12,17 @@ var serverSocketId = null;
|
||||
var isListening = false;
|
||||
var isInitialized = false; // Prevent double initialization
|
||||
var handlersSetup = false; // Prevent duplicate event listeners
|
||||
var appWindow = null; // Keep app window reference to prevent suspension
|
||||
|
||||
// Connection statistics
|
||||
var stats = {
|
||||
totalConnections: 0,
|
||||
activeConnections: 0,
|
||||
bytesReceived: 0,
|
||||
bytesSent: 0,
|
||||
startTime: Date.now(),
|
||||
connections: {} // socketId -> { connectTime, bytesReceived, bytesSent }
|
||||
};
|
||||
|
||||
// SOCKS5 Connection States
|
||||
var ConnectionState = {
|
||||
@@ -78,7 +89,18 @@ function initConnection(socketId) {
|
||||
buffer: new Uint8Array(0),
|
||||
destinationSocketId: null
|
||||
};
|
||||
|
||||
// Track statistics
|
||||
stats.totalConnections++;
|
||||
stats.activeConnections++;
|
||||
stats.connections[socketId] = {
|
||||
connectTime: Date.now(),
|
||||
bytesReceived: 0,
|
||||
bytesSent: 0
|
||||
};
|
||||
|
||||
console.log('[SOCKS] Initialized connection ' + socketId);
|
||||
sendStatusToWindow();
|
||||
}
|
||||
|
||||
function removeConnection(socketId) {
|
||||
@@ -90,7 +112,15 @@ function removeConnection(socketId) {
|
||||
} catch(e) {}
|
||||
}
|
||||
delete connections[socketId];
|
||||
|
||||
// Update statistics
|
||||
if (stats.connections[socketId]) {
|
||||
delete stats.connections[socketId];
|
||||
}
|
||||
stats.activeConnections--;
|
||||
|
||||
console.log('[SOCKS] Removed connection ' + socketId);
|
||||
sendStatusToWindow();
|
||||
}
|
||||
|
||||
function handleSocksData(clientSocketId, data) {
|
||||
@@ -102,11 +132,25 @@ function handleSocksData(clientSocketId, data) {
|
||||
|
||||
// If we're in tunnel mode, forward data to destination
|
||||
if (conn.state === ConnectionState.TUNNEL && conn.destinationSocketId) {
|
||||
console.log('[Tunnel] Client -> Destination: ' + data.byteLength + ' bytes');
|
||||
var byteLength = data.byteLength;
|
||||
console.log('[Tunnel] Client -> Destination: ' + byteLength + ' bytes');
|
||||
|
||||
// Track statistics
|
||||
stats.bytesReceived += byteLength;
|
||||
if (stats.connections[clientSocketId]) {
|
||||
stats.connections[clientSocketId].bytesReceived += byteLength;
|
||||
}
|
||||
|
||||
chrome.sockets.tcp.send(conn.destinationSocketId, data, function(sendInfo) {
|
||||
if (sendInfo.resultCode < 0) {
|
||||
console.error('[Tunnel] Failed to send to destination: ' + sendInfo.resultCode);
|
||||
closeConnection(clientSocketId);
|
||||
return;
|
||||
}
|
||||
// Track sent bytes
|
||||
stats.bytesSent += byteLength;
|
||||
if (stats.connections[clientSocketId]) {
|
||||
stats.connections[clientSocketId].bytesSent += byteLength;
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -343,7 +387,14 @@ function handleDestinationData(destSocketId, data) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[Tunnel] Destination -> Client: ' + data.byteLength + ' bytes');
|
||||
var byteLength = data.byteLength;
|
||||
console.log('[Tunnel] Destination -> Client: ' + byteLength + ' bytes');
|
||||
|
||||
// Track statistics
|
||||
stats.bytesReceived += byteLength;
|
||||
if (stats.connections[clientSocketId]) {
|
||||
stats.connections[clientSocketId].bytesReceived += byteLength;
|
||||
}
|
||||
|
||||
// Pause destination to prevent event spam while sending
|
||||
chrome.sockets.tcp.setPaused(destSocketId, true);
|
||||
@@ -356,6 +407,12 @@ function handleDestinationData(destSocketId, data) {
|
||||
console.error('[Tunnel] Failed to send to client: ' + sendInfo.resultCode);
|
||||
// Close both connections
|
||||
closeConnection(clientSocketId);
|
||||
return;
|
||||
}
|
||||
// Track sent bytes
|
||||
stats.bytesSent += byteLength;
|
||||
if (stats.connections[clientSocketId]) {
|
||||
stats.connections[clientSocketId].bytesSent += byteLength;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -462,8 +519,51 @@ function initializeProxy() {
|
||||
chrome.app.runtime.onLaunched.addListener(function() {
|
||||
console.log('[Hammer] App launched');
|
||||
initializeProxy();
|
||||
createAppWindow();
|
||||
});
|
||||
|
||||
// Create a minimal app window to prevent Chrome from suspending the app
|
||||
function createAppWindow() {
|
||||
// Only create if we don't already have one
|
||||
if (appWindow) {
|
||||
try {
|
||||
appWindow.focus();
|
||||
return;
|
||||
} catch(e) {
|
||||
appWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
chrome.app.window.create('window.html', {
|
||||
'outerBounds': {
|
||||
'width': 400,
|
||||
'height': 500,
|
||||
'minWidth': 300,
|
||||
'minHeight': 400
|
||||
},
|
||||
'resizable': true,
|
||||
'alwaysOnTop': false
|
||||
}, function(createdWindow) {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error('[Hammer] Failed to create window:', chrome.runtime.lastError);
|
||||
return;
|
||||
}
|
||||
appWindow = createdWindow;
|
||||
console.log('[Hammer] App window created - prevents suspension');
|
||||
|
||||
// Re-create window if closed
|
||||
appWindow.onClosed.addListener(function() {
|
||||
console.log('[Hammer] Window closed, recreating in 2 seconds...');
|
||||
appWindow = null;
|
||||
setTimeout(function() {
|
||||
if (!appWindow) {
|
||||
createAppWindow();
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Chrome App lifecycle - restart when app is restarted
|
||||
chrome.app.runtime.onRestarted.addListener(function() {
|
||||
console.log('[Hammer] App restarted');
|
||||
@@ -500,6 +600,13 @@ chrome.app.window.onClosed.addListener(function() {
|
||||
// Also initialize on startup (for apps that are already running)
|
||||
initializeProxy();
|
||||
|
||||
// Create window on startup to prevent suspension
|
||||
setTimeout(function() {
|
||||
if (!appWindow) {
|
||||
createAppWindow();
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// ============================================================================
|
||||
// KEEP-ALIVE MECHANISM
|
||||
// ============================================================================
|
||||
@@ -512,6 +619,9 @@ chrome.alarms.onAlarm.addListener(function(alarm) {
|
||||
// Heartbeat: log activity to keep the app alive
|
||||
console.log('[Hammer] Heartbeat - Proxy is ' + (isListening ? 'active' : 'inactive'));
|
||||
|
||||
// Send status to window
|
||||
sendStatusToWindow();
|
||||
|
||||
// Check if server is still listening, restart if needed
|
||||
if (!isListening && !isInitialized) {
|
||||
console.log('[Hammer] Server not listening, reinitializing...');
|
||||
@@ -523,6 +633,64 @@ chrome.alarms.onAlarm.addListener(function(alarm) {
|
||||
}
|
||||
});
|
||||
|
||||
// Send status to app window
|
||||
function sendStatusToWindow() {
|
||||
// Format bytes for display
|
||||
function formatBytes(bytes) {
|
||||
if (bytes < 1024) return bytes + ' B';
|
||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
|
||||
return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
|
||||
}
|
||||
|
||||
// Format duration for display
|
||||
function formatDuration(ms) {
|
||||
var seconds = Math.floor(ms / 1000);
|
||||
var minutes = Math.floor(seconds / 60);
|
||||
var hours = Math.floor(minutes / 60);
|
||||
if (hours > 0) return hours + 'h ' + (minutes % 60) + 'm';
|
||||
if (minutes > 0) return minutes + 'm ' + (seconds % 60) + 's';
|
||||
return seconds + 's';
|
||||
}
|
||||
|
||||
// Calculate connection durations
|
||||
var connectionDurations = [];
|
||||
for (var socketId in stats.connections) {
|
||||
var conn = stats.connections[socketId];
|
||||
var duration = Date.now() - conn.connectTime;
|
||||
connectionDurations.push(formatDuration(duration));
|
||||
}
|
||||
|
||||
chrome.runtime.sendMessage({
|
||||
type: 'status',
|
||||
active: isListening,
|
||||
stats: {
|
||||
totalConnections: stats.totalConnections,
|
||||
activeConnections: stats.activeConnections,
|
||||
bytesReceived: formatBytes(stats.bytesReceived),
|
||||
bytesSent: formatBytes(stats.bytesSent),
|
||||
uptime: formatDuration(Date.now() - stats.startTime),
|
||||
connectionDurations: connectionDurations
|
||||
}
|
||||
});
|
||||
chrome.runtime.sendMessage({
|
||||
type: 'heartbeat'
|
||||
});
|
||||
}
|
||||
|
||||
// Listen for status requests from window
|
||||
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
|
||||
if (message.type === 'getStatus') {
|
||||
sendResponse({
|
||||
type: 'status',
|
||||
active: isListening,
|
||||
stats: {
|
||||
totalConnections: stats.totalConnections,
|
||||
activeConnections: stats.activeConnections
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handle when app is suspended and resumed
|
||||
chrome.runtime.onSuspend.addListener(function() {
|
||||
console.log('[Hammer] App being suspended...');
|
||||
|
||||
Reference in New Issue
Block a user