code wiki / (root) / nx_mcp_route.nx

nx_mcp_route.nx source

↩ module page · 127 lines · 4718 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.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}