code wiki / (root) / nx_ipp_submit.nx

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}