nx_ipp_submit.nx source
↩ module page · 112 lines · 5860 B
1// nx_ipp_submit.nx -- build IPP job-submission requests (Validate-Job / Print-Job) -- R-RASTER-1.
2//
3// Validate-Job (op 0x0004): asks the printer "would you accept this job?" and prints NOTHING -- the SAFE
4// way to prove the submission path live (no paper, no toner). Returns successful-ok if it would accept.
5// Print-Job (op 0x0002): the real thing -- the document data (e.g. our URF page) rides in the HTTP body
6// immediately after the IPP request's end-of-attributes-tag (RFC 8011 sec 4.2.1).
7//
8// Operation attributes (order matters per RFC 8011: charset first, natural-language second):
9// attributes-charset, attributes-natural-language, printer-uri, requesting-user-name, job-name,
10// document-format. All built with the verified R0 codec.
11//
12// NEVER-BRICK (#26): pure request builder; no syscalls, no firmware writes. Sovereign (imports nx_ipp_codec).
13// genealogy_id: project-printer-management-ipp-sclass-2026-06-20 ; license_tier: ORIGINAL
14
15import "nx_ipp_codec.nx"
16
17func nx_sub_puti(buf: *u8, off: i64, v: i64) -> i64 {
18 var o: i64 = off
19 if v == 0 { buf[o] = 48 as u8; return o + 1 }
20 var m: i64 = v
21 let tmp: *u8 = sys_mmap(24)
22 var k: i64 = 0
23 while m > 0 { tmp[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
24 var i: i64 = k - 1
25 while i >= 0 { buf[o] = tmp[i]; o = o + 1; i = i - 1 }
26 return o
27}
28
29// build ipp://a.b.c.d<path> into uri (NUL-terminated). Returns length.
30func nx_sub_uri(uri: *u8, a: i64, b: i64, c: i64, d: i64, path: *u8) -> i64 {
31 var o: i64 = 0
32 var i: i64 = 0
33 let pre: *u8 = "ipp://"
34 while pre[i] != (0 as u8) { uri[o] = pre[i]; o = o + 1; i = i + 1 }
35 o = nx_sub_puti(uri, o, a); uri[o] = 46 as u8; o = o + 1
36 o = nx_sub_puti(uri, o, b); uri[o] = 46 as u8; o = o + 1
37 o = nx_sub_puti(uri, o, c); uri[o] = 46 as u8; o = o + 1
38 o = nx_sub_puti(uri, o, d)
39 var j: i64 = 0
40 while path[j] != (0 as u8) { uri[o] = path[j]; o = o + 1; j = j + 1 }
41 uri[o] = 0 as u8
42 return o
43}
44
45// shared operation-attributes group. Returns advanced offset (group written, NOT ended).
46func nx_sub_op_attrs(req: *u8, off: i64, a: i64, b: i64, c: i64, d: i64,
47 path: *u8, user: *u8, jobname: *u8, docfmt: *u8) -> i64 {
48 var o: i64 = nx_ipp_group(req, off, NX_IPP_GRP_OPERATION)
49 o = nx_ipp_attr(req, o, NX_IPP_VT_CHARSET, "attributes-charset", 18, "utf-8", 5)
50 o = nx_ipp_attr(req, o, NX_IPP_VT_NATLANG, "attributes-natural-language", 27, "en", 2)
51 let uri: *u8 = sys_mmap(256)
52 let ulen: i64 = nx_sub_uri(uri, a, b, c, d, path)
53 o = nx_ipp_attr(req, o, NX_IPP_VT_URI, "printer-uri", 11, uri, ulen)
54 o = nx_ipp_attr(req, o, NX_IPP_VT_NAME, "requesting-user-name", 20, user, nx_ipp_strlen(user))
55 o = nx_ipp_attr(req, o, NX_IPP_VT_NAME, "job-name", 8, jobname, nx_ipp_strlen(jobname))
56 o = nx_ipp_attr(req, o, NX_IPP_VT_MIMETYPE, "document-format", 15, docfmt, nx_ipp_strlen(docfmt))
57 return o
58}
59
60// Validate-Job request (no document data). Returns total IPP request length.
61func nx_ipp_build_validate_job(req: *u8, a: i64, b: i64, c: i64, d: i64,
62 path: *u8, user: *u8, jobname: *u8, docfmt: *u8) -> i64 {
63 var o: i64 = nx_ipp_begin(req, 1, 1, NX_IPP_OP_VALIDATE_JOB, 2)
64 o = nx_sub_op_attrs(req, o, a, b, c, d, path, user, jobname, docfmt)
65 o = nx_ipp_end(req, o)
66 return o
67}
68
69// Get-Job-Attributes request (op 0x0009) for a job-id -- used to poll job-state. Returns request length.
70func nx_ipp_build_get_job_attrs(req: *u8, a: i64, b: i64, c: i64, d: i64,
71 path: *u8, user: *u8, jobid: i64) -> i64 {
72 var o: i64 = nx_ipp_begin(req, 1, 1, NX_IPP_OP_GET_JOB_ATTRIBUTES, 4)
73 o = nx_ipp_group(req, o, NX_IPP_GRP_OPERATION)
74 o = nx_ipp_attr(req, o, NX_IPP_VT_CHARSET, "attributes-charset", 18, "utf-8", 5)
75 o = nx_ipp_attr(req, o, NX_IPP_VT_NATLANG, "attributes-natural-language", 27, "en", 2)
76 let uri: *u8 = sys_mmap(256)
77 let ulen: i64 = nx_sub_uri(uri, a, b, c, d, path)
78 o = nx_ipp_attr(req, o, NX_IPP_VT_URI, "printer-uri", 11, uri, ulen)
79 o = nx_ipp_attr_int(req, o, NX_IPP_VT_INTEGER, "job-id", 6, jobid)
80 o = nx_ipp_attr(req, o, NX_IPP_VT_NAME, "requesting-user-name", 20, user, nx_ipp_strlen(user))
81 o = nx_ipp_end(req, o)
82 return o
83}
84
85// Print-Job request HEADER (the IPP part). The caller appends document data after the returned length.
86func nx_ipp_build_print_job(req: *u8, a: i64, b: i64, c: i64, d: i64,
87 path: *u8, user: *u8, jobname: *u8, docfmt: *u8) -> i64 {
88 var o: i64 = nx_ipp_begin(req, 1, 1, NX_IPP_OP_PRINT_JOB, 3)
89 o = nx_sub_op_attrs(req, o, a, b, c, d, path, user, jobname, docfmt)
90 o = nx_ipp_end(req, o)
91 return o
92}
93
94// job-attributes group (RFC 8011 sec 5.2): the job-template attribute `sides` selects one/two-sided output.
95// "two-sided-long-edge" = duplex, which HALVES the sheet count vs the vendor-default "one-sided". Returns offset.
96func nx_sub_job_attrs_sides(req: *u8, off: i64, sides: *u8, slen: i64) -> i64 {
97 var o: i64 = nx_ipp_group(req, off, NX_IPP_GRP_JOB)
98 o = nx_ipp_attr(req, o, NX_IPP_VT_KEYWORD, "sides", 5, sides, slen)
99 return o
100}
101
102// Print-Job request HEADER carrying an explicit `sides` job attribute (e.g. two-sided-long-edge for duplex).
103// ADDITIVE: the original nx_ipp_build_print_job (no job-attrs -> the printer's default) is unchanged (#19).
104func nx_ipp_build_print_job_sides(req: *u8, a: i64, b: i64, c: i64, d: i64,
105 path: *u8, user: *u8, jobname: *u8, docfmt: *u8,
106 sides: *u8, slen: i64) -> i64 {
107 var o: i64 = nx_ipp_begin(req, 1, 1, NX_IPP_OP_PRINT_JOB, 3)
108 o = nx_sub_op_attrs(req, o, a, b, c, d, path, user, jobname, docfmt)
109 o = nx_sub_job_attrs_sides(req, o, sides, slen)
110 o = nx_ipp_end(req, o)
111 return o
112}