stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll - stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close - utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP), add deferred drain in both Phase J and L - stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39, exchange ed25519_pubkey in both handshake directions - etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb - chat_sync.c: fix lk->conn NULL dereference for TCP links - test_stcp.c: update stcp_server_create/stcp_client_connect callsites - tools/chat_tcp_test: change transport udp→tcp
This commit is contained in:
1 parent
a3783b5f55
commit
38c9f229bc
1272 files changed
+968388
-1
No files matched your search
@@ -0,0 +1,87 @@
|
||||
#include "json_flat.h"
|
||||
#include <string.h>
|
||||
|
||||
#define SKIP_WS(p, end) while ((p) < (end) && (*(p) == ' ' || *(p) == '\t' || *(p) == '\n' || *(p) == '\r')) (p)++
|
||||
#define CHECK(p, end) if ((p) >= (end)) return -1
|
||||
|
||||
static int json_read_string(const char** pp, const char* end, char* out, size_t out_sz) {
|
||||
const char* p = *pp;
|
||||
CHECK(p, end);
|
||||
if (*p != '"') return -1; p++;
|
||||
size_t n = 0;
|
||||
while (p < end && *p != '"') {
|
||||
char ch = *p;
|
||||
if (*p == '\\') { p++; CHECK(p, end);
|
||||
switch (*p) {
|
||||
case '"': ch = '"'; break;
|
||||
case '\\': ch = '\\'; break;
|
||||
case '/': ch = '/'; break;
|
||||
case 'n': ch = '\n'; break;
|
||||
case 'r': ch = '\r'; break;
|
||||
case 't': ch = '\t'; break;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
if (out && n < out_sz - 1) out[n++] = ch;
|
||||
p++;
|
||||
}
|
||||
CHECK(p, end); /* closing quote */
|
||||
p++;
|
||||
if (out && n < out_sz) out[n] = '\0';
|
||||
else if (out && out_sz > 0) out[out_sz - 1] = '\0';
|
||||
*pp = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_parse_pair(const char** pp, const char* end,
|
||||
json_flat_cb cb, void* arg) {
|
||||
const char* p = *pp;
|
||||
SKIP_WS(p, end); CHECK(p, end);
|
||||
if (*p == '}') { *pp = p; return 0; }
|
||||
|
||||
char key[128], val[256];
|
||||
if (json_read_string(&p, end, key, sizeof(key)) != 0) return -1;
|
||||
SKIP_WS(p, end); CHECK(p, end);
|
||||
if (*p != ':') return -1; p++;
|
||||
SKIP_WS(p, end); CHECK(p, end);
|
||||
if (json_read_string(&p, end, val, sizeof(val)) != 0) return -1;
|
||||
|
||||
if (cb && cb(key, val, arg) != 0) { *pp = p; return 1; }
|
||||
|
||||
SKIP_WS(p, end); CHECK(p, end);
|
||||
if (*p == ',') p++;
|
||||
|
||||
*pp = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int json_flat_parse(const char* json, json_flat_cb cb, void* arg) {
|
||||
if (!json) return -1;
|
||||
const char* p = json, *end = json + strlen(json);
|
||||
SKIP_WS(p, end); CHECK(p, end);
|
||||
if (*p != '{') return -1; p++;
|
||||
|
||||
for (;;) {
|
||||
int rc = json_parse_pair(&p, end, cb, arg);
|
||||
if (rc < 0) return -1;
|
||||
if (rc > 0) return 0; /* callback stopped */
|
||||
SKIP_WS(p, end); CHECK(p, end);
|
||||
if (*p == '}') return 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct get_ctx { const char* key; char* out; size_t sz; int found; };
|
||||
|
||||
static int get_cb(const char* k, const char* v, void* arg) {
|
||||
struct get_ctx* g = (struct get_ctx*)arg;
|
||||
if (strcmp(k, g->key) == 0) { if (g->out) { size_t vl = strlen(v);
|
||||
size_t cp = vl < g->sz - 1 ? vl : g->sz - 1; memcpy(g->out, v, cp); g->out[cp] = '\0'; }
|
||||
g->found = 1; return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int json_flat_get(const char* json, const char* key, char* value_out, size_t value_sz) {
|
||||
struct get_ctx g = { key, value_out, value_sz, 0 };
|
||||
if (json_flat_parse(json, get_cb, &g) != 0) return -1;
|
||||
return g.found ? 0 : -1;
|
||||
}
|
||||
Reference in new issue
Block a user