==> src/http.c <==1/* ui.rs's "6 http" section, ported. */
2#include "mesh/top_ui_http.h"
3
4#include "tui/utf8.h"
5
6#include <stdlib.h>
7#include <string.h>
8
9const char *mt_http_target(mt_frame *f, const mt_machine *m) {
10 const char *colon = strrchr(m->endpoint, ':');
11 const char *ep_host = colon ? tui_arena_strndup(f->a, m->endpoint, (size_t)(colon - m->endpoint)) : m->endpoint;
12 char bound[193] = "";
13 if (m->has_snap) mt_snapshot_host_str(&m->snap, MESH_S_HTTP_ADDR, 64, bound);
14 const char *c = strrchr(bound, ':');
15 if (!c) return MT_FMT(f, "%s:%u", ep_host, MESH_HTTP_PORT);
16 size_t il = (size_t)(c - bound);
17 if ((il == 7 && memcmp(bound, "0.0.0.0", 7) == 0) || (il == 4 && memcmp(bound, "[::]", 4) == 0)) return MT_FMT(f, "%s:%s", ep_host, c + 1);
18 return tui_arena_strdup(f->a, bound);
19}
20
21static void count_line(void *ctx, const char *line, size_t len) {
22 (void)line;
23 (void)len;
24 ++*(size_t *)ctx;
25}
26
27void mt_draw_http(mt_frame *f, tui_rect area, const mt_app *app) {
28 const mt_machine *m = mt_app_focused(app);
29 tui_color color;
30 tui_line title = mt_machine_title(f, m, true, "http: GET served by the GPU", &color);
31 tui_block block = mt_panel(f, title, color);
32 tui_rect inner = tui_block_inner(&block, area);
33 mt_block(f, &block, area);
34 tui_rect r[3];
35 tui_vsplit(inner, 3, (tui_constraint[]){TUI_LENGTH(4), TUI_LENGTH(3), TUI_FILL(1)}, r);
36 const char *path = *app->http_input ? app->http_input : "/";
37 const char *curl = MT_FMT(f, "curl -s http://%s%s", mt_http_target(f, m), path);
38 const mt_section *h = mt_machine_program(m, "http");
39 mt_lines lines = {0};
40 if (m->has_snap && h) {
41 const mt_snapshot *s = &m->snap;
42 char last[193];
43 mt_snapshot_host_str(s, MESH_S_LAST_HTTP, 64, last);
44 mt_lines_push(f, &lines,
45 MT_LINE(f, mt_label("served by GPU "), mt_val(MT_FMT(f, "%u", mt_section_view_u32(h, MESH_HTTP_HV_SERVED))),
46 mt_label(" relayed by meshd "), mt_val(MT_FMT(f, "%u", mt_snapshot_host_u32(s, MESH_S_HTTP_REQUESTS))),
47 mt_label(" last code "), mt_val(MT_FMT(f, "%u", mt_section_view_u32(h, MESH_HTTP_HV_LAST_CODE))),
48 mt_label(" http "), mt_styled(mt_section_state_name(h), mt_state_style(h))));
49 mt_lines_push(f, &lines, MT_LINE(f, mt_label("last request "), mt_fgs(tui_arena_strdup(f->a, last), MT_ACCENT)));
50 mt_lines_push(f, &lines, MT_LINE(f, mt_label("try "), mt_fgs(curl, MT_WARN)));
51 } else if (m->has_snap) {
52 mt_lines_push(f, &lines, tui_line_span(f->a, mt_styled(MT_FMT(f, " http is not loaded on %s ", mt_name(f, m)), mt_fg_bg_bold(MT_BG, MT_WARN))));
53 } else {
54 mt_lines_push(f, &lines, tui_line_span(f->a, mt_fgs(MT_FMT(f, "no snapshot (%s)", m->status), MT_WARN)));
55 }
56 mt_par(f, mt_text(f, &lines), r[0]);
57
58 tui_block ib = mt_panel(f, tui_line_span(f->a, mt_label(" path (Enter sends `http <path>`) ")), MT_ACCENT);
59 tui_paragraph ip = tui_paragraph_new(
60 tui_text_line(f->a, MT_LINE(f, mt_fgs("GET ", MT_DIM), mt_fgb(tui_arena_strdup(f->a, app->http_input), MT_FG), mt_fgs("█", MT_ACCENT))));
61 ip.block = &ib;
62 tui_paragraph_render(f->a, &ip, r[1], f->buf);
63
64 const char *body;
65 if (m->has_http_resp) {
66 size_t ln;
67 char *lossy = tui_utf8_lossy(m->http_resp, m->http_resp_len, &ln);
68 /* .replace("\r\n", "\n") */
69 char *o = tui_arena_alloc(f->a, ln + 1);
70 size_t k = 0;
71 for (size_t i = 0; i < ln; i++) {
72 if (lossy[i] == '\r' && i + 1 < ln && lossy[i + 1] == '\n') continue;
73 o[k++] = lossy[i];
74 }
75 o[k] = 0;
76 free(lossy);
77 body = o;
78 } else {
79 body = "(no response yet: press Enter)";
80 }
81 size_t total = 0;
82 tui_str_lines(body, count_line, &total);
83 tui_block rb = mt_panel(f, tui_line_span(f->a, mt_label(MT_FMT(f, " response %zu lines scroll %u ", total, app->http_scroll))), MT_FAINT);
84 tui_paragraph rp = tui_paragraph_new(tui_text_from_str(f->a, body));
85 rp.wrap = TUI_WRAP_KEEP;
86 rp.scroll_y = app->http_scroll;
87 rp.block = &rb;
88 tui_paragraph_render(f->a, &rp, r[2], f->buf);
89}