Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 112 additions & 36 deletions app.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -158,37 +158,6 @@ def get_mock_process_kernel_map():
"cron": ["kernel/time/timer.c", "kernel/sched/clock.c"]
}

def get_nginx_open_files():
"""Get open files for nginx process"""
try:
nginx_files = []
for proc in psutil.process_iter(["pid", "name"]):
if proc.info["name"] == "nginx":
try:
files = proc.open_files()
for file in files:
if file.path and os.path.exists(file.path):
nginx_files.append({
"path": file.path,
"fd": file.fd,
"pid": proc.info["pid"]
})
except (psutil.AccessDenied, psutil.NoSuchProcess):
continue
return get_mock_nginx_files()
except Exception as e:
print(f"Error getting nginx files: {e}")
return get_mock_nginx_files()

def get_mock_nginx_files():
"""Mock data for nginx open files"""
return [
{"path": "/etc/nginx/nginx.conf", "fd": 0, "pid": 123},
{"path": "/var/log/nginx/access.log", "fd": 1, "pid": 123},
{"path": "/var/log/nginx/error.log", "fd": 2, "pid": 123},
{"path": "/var/www/html/index.html", "fd": 3, "pid": 123},
{"path": "/etc/nginx/sites-enabled/default", "fd": 4, "pid": 123}
]
# API Endpoints

@app.route('/')
Expand Down Expand Up @@ -249,6 +218,63 @@ def health_check():
})

# Static files handling
@app.route('/static/<path:filename>')
def static_files(filename):
"""Serve static files"""
return send_from_directory(app.config['STATIC_FOLDER'], filename)

# Error handling
# Active connections functions
# Nginx files functions
def get_nginx_open_files():
"""Get open files for Nginx process"""
try:
import psutil
nginx_processes = []
for proc in psutil.process_iter(["pid", "name", "open_files"]):
try:
if proc.info["name"] and "nginx" in proc.info["name"].lower():
nginx_processes.append(proc.info["pid"])
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue

if nginx_processes:
# Get open files for first nginx process
proc = psutil.Process(nginx_processes[0])
open_files = proc.open_files()

# Filter and format file paths
files = []
for file in open_files:
if file.path:
# Extract relative path from full path
if "/etc/nginx/" in file.path:
rel_path = file.path.split("/etc/nginx/")[-1]
files.append({"path": f"nginx/{rel_path}", "type": "config"})
elif "/var/log/nginx/" in file.path:
rel_path = file.path.split("/var/log/nginx/")[-1]
files.append({"path": f"nginx/logs/{rel_path}", "type": "log"})
else:
files.append({"path": file.path, "type": "other"})

return files[:10] # Limit to 10 files
else:
return get_mock_nginx_files()

except Exception as e:
print(f"Error getting nginx files: {e}")
return get_mock_nginx_files()

def get_mock_nginx_files():
"""Mock data for nginx files"""
return [
{"path": "nginx/nginx.conf", "type": "config"},
{"path": "nginx/sites-enabled/default", "type": "config"},
{"path": "nginx/conf.d/default.conf", "type": "config"},
{"path": "nginx/logs/access.log", "type": "log"},
{"path": "nginx/logs/error.log", "type": "log"}
]

@app.route("/api/nginx-files")
def nginx_files():
"""API for nginx open files"""
Expand All @@ -257,12 +283,60 @@ def nginx_files():
return jsonify({"files": files})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/static/<path:filename>')
def static_files(filename):
"""Serve static files"""
return send_from_directory(app.config['STATIC_FOLDER'], filename)
def get_active_connections():
"""Get active network connections"""
try:
connections = []
# Get TCP connections
with open("/proc/net/tcp", "r") as f:
lines = f.readlines()[1:] # Skip header
for line in lines:
parts = line.strip().split()
if len(parts) >= 4:
local_addr = parts[1]
remote_addr = parts[2]
state = parts[3]

# Convert hex addresses to readable format
local_ip = ".".join([str(int(local_addr.split(":")[0][i:i+2], 16)) for i in range(0, 8, 2)])
local_port = int(local_addr.split(":")[1], 16)

if remote_addr != "00000000:0000": # Not listening
remote_ip = ".".join([str(int(remote_addr.split(":")[0][i:i+2], 16)) for i in range(0, 8, 2)])
remote_port = int(remote_addr.split(":")[1], 16)

connections.append({
"local": f"{local_ip}:{local_port}",
"remote": f"{remote_ip}:{remote_port}",
"state": state,
"type": "TCP"
})

# Limit to first 20 connections for display
return connections[:20]

except Exception as e:
print(f"Error getting active connections: {e}")
return get_mock_active_connections()

# Error handling
def get_mock_active_connections():
"""Mock data for active connections"""
return [
{"local": "127.0.0.1:22", "remote": "192.168.1.100:54321", "state": "01", "type": "TCP"},
{"local": "0.0.0.0:80", "remote": "10.0.0.50:12345", "state": "01", "type": "TCP"},
{"local": "127.0.0.1:3306", "remote": "172.16.0.10:65432", "state": "01", "type": "TCP"},
{"local": "0.0.0.0:443", "remote": "203.0.113.0:54321", "state": "01", "type": "TCP"},
{"local": "127.0.0.1:5001", "remote": "192.168.1.101:12345", "state": "01", "type": "TCP"}
]

@app.route("/api/active-connections")
def active_connections():
"""API for active network connections"""
try:
connections = get_active_connections()
return jsonify({"connections": connections})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.errorhandler(404)
def not_found(error):
return jsonify({'error': 'Not found'}), 404
Expand All @@ -282,6 +356,7 @@ def internal_error(error):
print(f" - {Config.API_PREFIX}/syscalls-realtime")
print(f" - {Config.API_PREFIX}/kernel-data")
print(f" - {Config.API_PREFIX}/process-kernel-map")
print(f" - {Config.API_PREFIX}/nginx-files")
print(f" - /health")

app.run(
Expand All @@ -290,3 +365,4 @@ def internal_error(error):
debug=Config.DEBUG,
threaded=True
)

1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

<!-- Scripts -->
<script src="/static/js/syscalls.js"></script>
<script src="/static/js/active-connections.js"></script>
<script src="/static/js/main.js?v=30"></script>
</body>
</html>
124 changes: 124 additions & 0 deletions static/js/active-connections.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Module for working with active network connections
class ActiveConnectionsManager {
constructor() {
console.log("ActiveConnectionsManager: constructor called");
this.currentConnections = [];
this.updateInterval = null;
this.updateCallback = null;
}

// Update active connections data
async updateConnectionsTable() {
try {
console.log("ActiveConnectionsManager: updateConnectionsTable called");
const response = await fetch('/api/active-connections');
const data = await response.json();

console.log("API response:", data);

if (data.connections) {
console.log("Total connections:", data.connections.length);

// Filter out local connections (127.0.0.1, 0.0.0.0)
this.currentConnections = data.connections.filter(conn => {
const localIP = conn.local.split(':')[0];
return true; // Temporarily show all connections
});

console.log("Filtered connections:", this.currentConnections.length);

this.renderConnectionsTable();

// Call callback if set
if (this.updateCallback) {
this.updateCallback(data);
}
}
} catch (error) {
console.error('Error getting active connections:', error);
this.useFallbackData();
}
}

// Fallback data
useFallbackData() {
this.currentConnections = [
{local: '192.168.1.100:22', remote: '10.0.0.50:54321', state: '01', type: 'TCP'},
{local: '203.0.113.0:80', remote: '172.16.0.10:12345', state: '01', type: 'TCP'},
{local: '198.51.100.0:443', remote: '192.168.1.101:65432', state: '01', type: 'TCP'},
{local: '203.0.113.0:8080', remote: '10.0.0.100:54321', state: '01', type: 'TCP'},
{local: '198.51.100.0:3306', remote: '172.16.0.20:12345', state: '01', type: 'TCP'}
];
this.renderConnectionsTable();
}

// Render active connections table below system calls
renderConnectionsTable() {
const svg = d3.select('svg');

// Clear old elements
svg.selectAll('.connection-box, .connection-text').remove();

// Calculate starting Y position (below system calls)
const startY = 35 + 10 * 30 + 20; // 10 system calls * 30px + 20px gap

// Create new elements for active connections
this.currentConnections.forEach((connection, i) => {
const displayText = `${connection.local} → ${connection.remote}`;

svg.append('rect')
.attr('x', 30)
.attr('y', startY + i * 30)
.attr('width', 230)
.attr('height', 22)
.attr('class', 'item-box connection-box');

svg.append('text')
.attr('x', 38)
.attr('y', startY + 15 + i * 30)
.text(displayText)
.attr('class', 'socket-text connection-text');
});
}

// Start auto update
startAutoUpdate(intervalMs = 3000) {
console.log("ActiveConnectionsManager: startAutoUpdate called");
this.updateConnectionsTable();
this.updateInterval = setInterval(() => {
this.updateConnectionsTable();
}, intervalMs);
}

// Stop auto update
stopAutoUpdate() {
if (this.updateInterval) {
clearInterval(this.updateInterval);
this.updateInterval = null;
}
}

// Set update callback
setUpdateCallback(callback) {
this.updateCallback = callback;
}

// Get current data
getCurrentConnections() {
return this.currentConnections;
}

// Restore state
restoreState() {
if (this.currentConnections.length > 0) {
this.renderConnectionsTable();
} else {
this.updateConnectionsTable();
}
}
}

// Export for use in other modules
if (typeof module !== 'undefined' && module.exports) {
module.exports = ActiveConnectionsManager;
}
Empty file modified static/js/bezier_curves.js
100644 → 100755
Empty file.
7 changes: 7 additions & 0 deletions static/js/main.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ function initApp() {
// Initialize system calls manager
syscallsManager = new SyscallsManager();

// Initialize active connections manager
const connectionsManager = new ActiveConnectionsManager();
connectionsManager.startAutoUpdate(3000);

window.nginxFilesManager = new NginxFilesManager();
// Draw main interface
draw();
Expand All @@ -205,6 +209,9 @@ function setupEventListeners() {
if (syscallsManager) {
syscallsManager.stopAutoUpdate();
}
if (connectionsManager) {
connectionsManager.stopAutoUpdate();
}
});
}

Expand Down
Empty file modified static/js/nginx_files.js
100644 → 100755
Empty file.
6 changes: 4 additions & 2 deletions static/js/syscalls.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class SyscallsManager {
// Update system calls data
async updateSyscallsTable() {
try {
const response = await fetch('/api/syscalls-realtime');
const response = await fetch("/api/syscalls-realtime");
const data = await response.json();

if (data.syscalls) {
Expand All @@ -22,7 +22,7 @@ class SyscallsManager {
}
}
} catch (error) {
console.error('Error getting system calls:', error);
console.error('Error getting active connections:', error);
this.useFallbackData();
}
}
Expand Down Expand Up @@ -68,6 +68,8 @@ class SyscallsManager {
.text(displayText)
.attr("class", "socket-text syscall-text");
});
// Display active connections below system calls
// this.displayActiveConnections();
}

// Start auto update
Expand Down