mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
feat(net,gui): real internet access -- redirects, HTTPS guard, netcheck, and a live ONLINE indicator
The stack could already reach the real internet once the UDP-checksum and
scheduler fixes landed; this makes it work on real-world URLs and gives the
desktop a first-class "is the internet up?" answer.
HTTP client
- Follows 3xx redirects (Location header, absolute or relative) up to five
hops, so a bare host that 301s to a path or a canonical host resolves to
actual content. Verified: `webget google.com/` follows the 301 to
www.google.com and returns its HTTP 200 homepage.
- Refuses https:// targets -- at the initial URL and on redirect -- with a
clear message instead of speaking plaintext to port 443 and timing out.
- Split the URL parser out so both the initial request and redirect targets
go through the same path; added a case-insensitive header finder.
netcheck (CLI)
One command that walks the whole chain -- link, address, gateway ping, DNS,
and a real HTTP fetch -- and reports each PASS/FAIL, ending in ONLINE or
DEGRADED. The one-shot answer to "is the internet working?".
Network Monitor (GUI)
A live Internet: ONLINE/OFFLINE badge with the resolved IP, HTTP status and
latency. It auto-probes once on open and re-checks on the Check button, all
through the async HTTP worker so the window never blocks.
Verified against the real internet through QEMU's NAT: DNS resolved
example.com to a live Cloudflare address; `netcheck` passed all five layers
(Internet: ONLINE); the GUI badge showed "ONLINE 104.20.23.154 HTTP 200 240
ms"; redirect following and the HTTPS refusal both behaved. Builds clean on
x86_64, aarch64 and armv8i.
Known limit: no TLS, so HTTPS URLs are reported rather than fetched -- plain
HTTP only.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
This commit is contained in:
1 parent
dd4922767a
commit
f6e4511047
4 files changed
+308
-33
No files matched your search
+78
-2
@@ -26,6 +26,7 @@
|
||||
#include <net/tcp.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/socket.h>
|
||||
#include <net/http_client.h>
|
||||
#include <drivers/e1000.h>
|
||||
|
||||
#define NETMON_HISTORY 64
|
||||
@@ -46,8 +47,57 @@ typedef struct {
|
||||
bool primed; // a baseline reading has been taken
|
||||
|
||||
int scroll; // first connection row shown
|
||||
|
||||
// Internet reachability probe (async, via the HTTP worker).
|
||||
http_fetch_t* probe;
|
||||
int inet_state; // 0 unknown, 1 checking, 2 online, 3 offline
|
||||
char inet_detail[72];
|
||||
bool auto_checked;
|
||||
} netmon_data_t;
|
||||
|
||||
#define INET_UNKNOWN 0
|
||||
#define INET_CHECKING 1
|
||||
#define INET_ONLINE 2
|
||||
#define INET_OFFLINE 3
|
||||
|
||||
#define NETMON_PROBE_HOST "example.com/" // a plain-HTTP host to reach for
|
||||
|
||||
// Advance the reachability probe: collect a finished result, or note that one
|
||||
// is still in flight. Runs every paint; the fetch itself is on the worker.
|
||||
static void netmon_poll_probe(netmon_data_t* nd) {
|
||||
if (!nd->probe) return;
|
||||
|
||||
int st = nd->probe->state;
|
||||
if (st == HTTP_STATE_RUNNING) { nd->inet_state = INET_CHECKING; return; }
|
||||
|
||||
if (st == HTTP_STATE_DONE && nd->probe->status_code > 0) {
|
||||
char ipx[16];
|
||||
ip_to_str(nd->probe->ip, ipx);
|
||||
nd->inet_state = INET_ONLINE;
|
||||
snprintf(nd->inet_detail, sizeof(nd->inet_detail), "%s HTTP %d %u ms",
|
||||
ipx, nd->probe->status_code, nd->probe->elapsed_ms);
|
||||
} else {
|
||||
nd->inet_state = INET_OFFLINE;
|
||||
snprintf(nd->inet_detail, sizeof(nd->inet_detail), "%s",
|
||||
st == HTTP_STATE_ERROR ? nd->probe->err : "no response");
|
||||
}
|
||||
|
||||
http_fetch_release(nd->probe);
|
||||
nd->probe = NULL;
|
||||
}
|
||||
|
||||
static void netmon_start_probe(netmon_data_t* nd) {
|
||||
if (nd->probe) return; // one in flight already
|
||||
nd->probe = http_fetch_start(NETMON_PROBE_HOST, 4096);
|
||||
if (nd->probe) {
|
||||
nd->inet_state = INET_CHECKING;
|
||||
} else {
|
||||
// The single worker slot is busy (e.g. the Web app is fetching).
|
||||
nd->inet_state = INET_UNKNOWN;
|
||||
snprintf(nd->inet_detail, sizeof(nd->inet_detail), "worker busy, try again");
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Sampling
|
||||
// ===========================================================================
|
||||
@@ -217,8 +267,32 @@ static void netmon_paint(gui_window_t* win) {
|
||||
(unsigned)tcp_get_connections_count(), tcp_get_listener_count());
|
||||
gui_label_aligned(0, row + 12, w - 12, buf, GUI_THEME_TEXT_MUTED, GUI_ALIGN_RIGHT);
|
||||
|
||||
// --- internet reachability -------------------------------------------
|
||||
// Kick off one probe automatically the first time the window paints, then
|
||||
// let the user re-check on demand. The fetch runs on the worker thread, so
|
||||
// this stays responsive while a check is in flight.
|
||||
if (!nd->auto_checked) { nd->auto_checked = true; netmon_start_probe(nd); }
|
||||
netmon_poll_probe(nd);
|
||||
|
||||
int irow = row + 28;
|
||||
static const char* const inet_labels[] = { "UNKNOWN", "checking...", "ONLINE", "OFFLINE" };
|
||||
uint32_t inet_col = (nd->inet_state == INET_ONLINE) ? GUI_THEME_SUCCESS
|
||||
: (nd->inet_state == INET_OFFLINE) ? GUI_THEME_DANGER
|
||||
: (nd->inet_state == INET_CHECKING)? GUI_THEME_WARNING
|
||||
: GUI_THEME_TEXT_DIM;
|
||||
gui_label(10, irow, "Internet:", GUI_THEME_TEXT_MUTED);
|
||||
gui_badge(84, irow - 1, inet_labels[nd->inet_state],
|
||||
inet_col, GUI_COLOR_BLACK);
|
||||
if (nd->inet_detail[0]) {
|
||||
gui_label(150, irow, nd->inet_detail, GUI_THEME_TEXT_DIM);
|
||||
}
|
||||
if (gui_button(5, w - 82, irow - 3, 72, 18,
|
||||
nd->probe ? "checking" : "Check")) {
|
||||
netmon_start_probe(nd);
|
||||
}
|
||||
|
||||
// --- connection table -------------------------------------------------
|
||||
int tbl_y = row + 30;
|
||||
int tbl_y = row + 46;
|
||||
gui_separator(10, tbl_y - 4, w - 20);
|
||||
gui_label_bold(10, tbl_y, "PROTO LOCAL", GUI_THEME_TEXT_DIM);
|
||||
gui_label(w / 2 + 6, tbl_y, "REMOTE", GUI_THEME_TEXT_DIM);
|
||||
@@ -306,7 +380,9 @@ static void netmon_event(gui_window_t* win, const gui_event_t* ev) {
|
||||
gui_widget_feed_event(win, ev);
|
||||
|
||||
if (ev->type == GUI_EVENT_CLOSE && win->user_data) {
|
||||
kfree(win->user_data);
|
||||
netmon_data_t* nd = (netmon_data_t*)win->user_data;
|
||||
if (nd->probe) http_fetch_release(nd->probe); // safe mid-fetch
|
||||
kfree(nd);
|
||||
win->user_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user