nx_mcp_route_json_t160.nx source
↩ module page · 127 lines · 4729 B
1// Credential routing is explicit configuration; the remote capability verifier remains authoritative.
2import "nx_value_parse_json.nx"
3import "_hdl_build/nx_json_lib_route_t160.nx"
4
5// IDs retain their JSON type. Compare decoded strings by explicit length,
6// and integer source spans rather than potentially overflowed machine values.
7func mr_id_equal(a: *NxValue, b: *NxValue) -> i64 {
8 if a == (0 as *NxValue) { return 0 }
9 if b == (0 as *NxValue) { return 0 }
10 if a.kind != b.kind { return 0 }
11 if a.kind == NX_VAL_STRING {
12 let ab: *u8 = sys_mmap(a.str_len+1)
13 let bb: *u8 = sys_mmap(b.str_len+1)
14 let an: i64 = jx_decode_span(a.str_ptr,a.str_len,ab,a.str_len+1)
15 let bn: i64 = jx_decode_span(b.str_ptr,b.str_len,bb,b.str_len+1)
16 var equal: i64 = 1
17 if an < 0 { equal = 0 }
18 if an != bn { equal = 0 }
19 if equal != 0 {
20 var i: i64 = 0
21 while i < an { if ab[i] != bb[i] { equal = 0 }; i = i + 1 }
22 }
23 sys_munmap(ab,a.str_len+1); sys_munmap(bb,b.str_len+1)
24 return equal
25 }
26 if a.kind != NX_VAL_INT { return 0 }
27 if a.str_len != b.str_len { return 0 }
28 var i: i64 = 0
29 while i < a.str_len { if a.str_ptr[i] != b.str_ptr[i] { return 0 }; i = i + 1 }
30 return 1
31}
32
33func mr_response_matches(request: *u8, request_n: i64, response: *u8, response_n: i64) -> i64 {
34 var verdict: i64 = 0
35 let req: *NxValue = nx_value_parse_json(request,request_n,&verdict)
36 if verdict != NX_VAL_PARSE_OK { return 0 }
37 let res: *NxValue = nx_value_parse_json(response,response_n,&verdict)
38 if verdict != NX_VAL_PARSE_OK { return 0 }
39 var bad: i64 = 0
40 let rid: *NxValue = mr_member(req,"id" as *u8,&bad)
41 let sid: *NxValue = mr_member(res,"id" as *u8,&bad)
42 if bad != 0 { return 0 }
43 return mr_id_equal(rid,sid)
44}
45
46func mr_equal(a: *u8, an: i64, b: *u8) -> i64 {
47 var i: i64 = 0
48 while i < an {
49 if b[i] == (0 as u8) { return 0 }
50 if a[i] != b[i] { return 0 }
51 i = i + 1
52 }
53 if b[i] != (0 as u8) { return 0 }
54 return 1
55}
56
57func mr_len(s: *u8) -> i64 {
58 var n: i64 = 0
59 while s[n] != (0 as u8) { n = n + 1 }
60 return n
61}
62
63// The current value parser returns raw string spans. Reject escaped selector keys
64// rather than let its interpretation differ from the server's decoded key lookup.
65func mr_member(v: *NxValue, key: *u8, bad: *i64) -> *NxValue {
66 if v == (0 as *NxValue) { *bad = 1; return 0 as *NxValue }
67 if v.kind != NX_VAL_OBJECT { *bad = 1; return 0 as *NxValue }
68 var found: *NxValue = 0 as *NxValue
69 var i: i64 = 0
70 while i < v.n_items {
71 var j: i64 = 0
72 while j < v.key_lens_ptr[i] {
73 let c: i64 = v.keys_ptr[i][j] as i64
74 if c == 92 { *bad = 1 }
75 if c < 32 { *bad = 1 }
76 j = j + 1
77 }
78 if mr_equal(v.keys_ptr[i], v.key_lens_ptr[i], key) == 1 {
79 if found != (0 as *NxValue) { *bad = 1 }
80 found = v.items_ptr[i]
81 }
82 i = i + 1
83 }
84 return found
85}
86
87func mr_config(argc: i64, argv: *i64, first: i64) -> i64 {
88 if argc < first { return 0 }
89 if (argc - first) % 2 != 0 { return 0 }
90 var i: i64 = first
91 while i < argc {
92 if mr_len(argv[i] as *u8) == 0 { return 0 }
93 if mr_len(argv[i + 1] as *u8) == 0 { return 0 }
94 var j: i64 = first
95 while j < i {
96 if mr_equal(argv[i] as *u8, mr_len(argv[i] as *u8), argv[j] as *u8) == 1 { return 0 }
97 j = j + 2
98 }
99 i = i + 2
100 }
101 return 1
102}
103
104// Return the selected argv slot, or -1 for an ambiguous/unsupported envelope.
105// Parse allocations belong to the existing short-lived request worker.
106func mr_select(body: *u8, n: i64, argc: i64, argv: *i64, first: i64, default_slot: i64) -> i64 {
107 var verdict: i64 = 0
108 let root: *NxValue = nx_value_parse_json(body, n, &verdict)
109 if verdict != NX_VAL_PARSE_OK { return 0 - 1 }
110 var bad: i64 = 0
111 let method: *NxValue = mr_member(root, "method" as *u8, &bad)
112 if bad != 0 { return 0 - 1 }
113 if method == (0 as *NxValue) { return default_slot }
114 if method.kind != NX_VAL_STRING { return 0 - 1 }
115 if mr_equal(method.str_ptr, method.str_len, "tools/call" as *u8) == 0 { return default_slot }
116 let params: *NxValue = mr_member(root, "params" as *u8, &bad)
117 let name: *NxValue = mr_member(params, "name" as *u8, &bad)
118 if bad != 0 { return 0 - 1 }
119 if name == (0 as *NxValue) { return 0 - 1 }
120 if name.kind != NX_VAL_STRING { return 0 - 1 }
121 var i: i64 = first
122 while i < argc {
123 if mr_equal(name.str_ptr, name.str_len, argv[i] as *u8) == 1 { return i + 1 }
124 i = i + 2
125 }
126 return default_slot
127}