RFC 8010

Internet Printing Protocol/1.1: Encoding and Transport

πŸ“… published January 2017, from ietf

RFC 8010: Internet Printing Protocol/1.1: Encoding and Transport πŸ–¨οΈβœ¨

  • Authors: M. Sweet (Apple Inc.) and I. McDonald (High North, Inc.) πŸ§‘β€πŸ’»
  • Category: Standards Track πŸ‘‘
  • Date: January 2017 πŸ“…
  • ISSN: 2070-1721
  • Obsoletes: RFC 2910 and RFC 3382 πŸ’…
  • Updates: none listed in the header

Abstract

Okay bestie, so IPP (the Internet Printing Protocol) is an application-level protocol for distributed printing that runs on Internet tools and technologies. πŸ–¨οΈ This doc lays out the rules for encoding IPP operations, attributes, and values into the Internet MIME media type called "application/ipp". It also covers the rules for transporting a message body whose Content-Type is "application/ipp" over HTTP and/or HTTPS. πŸ¦‹ The data model and operation semantics live in "Internet Printing Protocol/1.1: Model and Semantics" (RFC 8011), so go check that one for the what-it-means part.

This document obsoletes RFCs 2910 and 3382. πŸ’œ


Status of This Memo ✨

This is an Internet Standards Track document. 🌸

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has gotten public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check Section 2 of RFC 7841. πŸ“š

Want the current status of this document, any errata, or a way to send feedback? Head to http://www.rfc-editor.org/info/rfc8010. πŸ”—


Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved. ©️

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stand on the date of publication. Please review these carefully, because they spell out your rights and restrictions for this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in the Simplified BSD License. 🫢


Table of Contents πŸ—ΊοΈ

1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
2.  Conventions Used in This Document . . . . . . . . . . . . . .   5
  2.1.  Requirements Language . . . . . . . . . . . . . . . . . .   5
  2.2.  Printing Terminology  . . . . . . . . . . . . . . . . . .   5
  2.3.  Abbreviations . . . . . . . . . . . . . . . . . . . . . .   6
3.  Encoding of the Operation Layer . . . . . . . . . . . . . . .   6
  3.1.  Picture of the Encoding . . . . . . . . . . . . . . . . .   8
    3.1.1.  Request and Response  . . . . . . . . . . . . . . . .   8
    3.1.2.  Attribute Group . . . . . . . . . . . . . . . . . . .   9
    3.1.3.  Attribute . . . . . . . . . . . . . . . . . . . . . .   9
    3.1.4.  Attribute-with-one-value  . . . . . . . . . . . . . .  10
    3.1.5.  Additional-value  . . . . . . . . . . . . . . . . . .  11
    3.1.6.  Collection Attribute  . . . . . . . . . . . . . . . .  12
    3.1.7.  Member Attributes . . . . . . . . . . . . . . . . . .  13
    3.1.8.  Alternative Picture of the Encoding of a Request or a
            Response  . . . . . . . . . . . . . . . . . . . . . .  14
  3.2.  Syntax of Encoding  . . . . . . . . . . . . . . . . . . .  15
  3.3.  Attribute-group . . . . . . . . . . . . . . . . . . . . .  16
  3.4.  Required Parameters . . . . . . . . . . . . . . . . . . .  18
    3.4.1.  "version-number"  . . . . . . . . . . . . . . . . . .  18
    3.4.2.  "operation-id"  . . . . . . . . . . . . . . . . . . .  18
    3.4.3.  "status-code" . . . . . . . . . . . . . . . . . . . .  19
    3.4.4.  "request-id"  . . . . . . . . . . . . . . . . . . . .  19
  3.5.  Tags  . . . . . . . . . . . . . . . . . . . . . . . . . .  19
    3.5.1.  "delimiter-tag" Values  . . . . . . . . . . . . . . .  19
    3.5.2.  "value-tag" Values  . . . . . . . . . . . . . . . . .  20
  3.6.  "name-length" . . . . . . . . . . . . . . . . . . . . . .  23
  3.7.  (Attribute) "name"  . . . . . . . . . . . . . . . . . . .  23
  3.8.  "value-length"  . . . . . . . . . . . . . . . . . . . . .  23
  3.9.  (Attribute) "value" . . . . . . . . . . . . . . . . . . .  24
  3.10. Data  . . . . . . . . . . . . . . . . . . . . . . . . . .  25

4.  Encoding of Transport Layer . . . . . . . . . . . . . . . . .  26
  4.1.  Printer URI, Job URI, and Job ID  . . . . . . . . . . . .  26
5.  IPP URI Schemes . . . . . . . . . . . . . . . . . . . . . . .  28
6.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .  29
7.  Internationalization Considerations . . . . . . . . . . . . .  31
8.  Security Considerations . . . . . . . . . . . . . . . . . . .  31
  8.1.  Security Conformance Requirements . . . . . . . . . . . .  31
    8.1.1.  Digest Authentication . . . . . . . . . . . . . . . .  32
    8.1.2.  Transport Layer Security (TLS)  . . . . . . . . . . .  32
  8.2.  Using IPP with TLS  . . . . . . . . . . . . . . . . . . .  33
9.  Interoperability with Other IPP Versions  . . . . . . . . . .  33
  9.1.  The "version-number" Parameter  . . . . . . . . . . . . .  34
  9.2.  Security and URI Schemes  . . . . . . . . . . . . . . . .  34
10. Changes since RFC 2910  . . . . . . . . . . . . . . . . . . .  35
11. References  . . . . . . . . . . . . . . . . . . . . . . . . .  36
  11.1.  Normative References . . . . . . . . . . . . . . . . . .  36
  11.2.  Informative References . . . . . . . . . . . . . . . . .  38
Appendix A.  Protocol Examples  . . . . . . . . . . . . . . . . .  40
  A.1.  Print-Job Request . . . . . . . . . . . . . . . . . . . .  40
  A.2.  Print-Job Response (Successful) . . . . . . . . . . . . .  41
  A.3.  Print-Job Response (Failure)  . . . . . . . . . . . . . .  42
  A.4.  Print-Job Response (Success with Attributes Ignored)  . .  43
  A.5.  Print-URI Request . . . . . . . . . . . . . . . . . . . .  45
  A.6.  Create-Job Request  . . . . . . . . . . . . . . . . . . .  46
  A.7.  Create-Job Request with Collection Attributes . . . . . .  46
  A.8.  Get-Jobs Request  . . . . . . . . . . . . . . . . . . . .  48
  A.9.  Get-Jobs Response . . . . . . . . . . . . . . . . . . . .  49
Acknowledgements  . . . . . . . . . . . . . . . . . . . . . . . .  51
Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  51

1. Introduction 🌷

Okay so this doc has the rules for encoding IPP operations, and it describes two layers: the transport layer and the operation layer. πŸŽ€

The transport layer is an HTTP request and response. Every IPP implementation supports HTTP/1.1, and the relevant parts of it are described in these RFCs:

  • Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing [RFC7230]
  • Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content [RFC7231]
  • Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests [RFC7232]
  • Hypertext Transfer Protocol (HTTP/1.1): Caching [RFC7234]
  • Hypertext Transfer Protocol (HTTP/1.1): Authentication [RFC7235]
  • The 'Basic' HTTP Authentication Scheme [RFC7617]
  • HTTP Digest Access Authentication [RFC7616]

IPP implementations can also support HTTP/2, which is described in these RFCs:

  • Hypertext Transfer Protocol Version 2 (HTTP/2) [RFC7540]
  • HPACK - Header Compression for HTTP/2 [RFC7541]

This document specifies the HTTP headers that an IPP implementation supports. 🧚

The operation layer is a message body inside an HTTP request or response. The "Internet Printing Protocol/1.1: Model and Semantics" document [RFC8011] and its later extensions (collectively called the IPP Model) define what that message body means and which values are supported. πŸ’… This document is the one that specifies how an IPP request and response message gets encoded. πŸ¦‹


2. Conventions Used in This Document πŸ“–

2.1. Requirements Language πŸ”‘

Okay, the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. Read those carefully, they're the whole vibe check for what's mandatory and what's optional. πŸ’–

2.2. Printing Terminology πŸ–¨οΈ

Here's the cast of characters:

  • Client: The initiator of outgoing IPP session requests and the sender of outgoing IPP operation requests (Hypertext Transfer Protocol -- HTTP/1.1 [RFC7230] User Agent). πŸ“€
  • Document: An object that a Printer creates and manages, holding description, processing, and status information. A Document object can have attached data, and it's bound to a single Job. πŸ“„
  • 'ipp' URI: An IPP URI as defined in [RFC3510]. πŸ”—
  • 'ipps' URI: An IPPS URI as defined in [RFC7472]. πŸ”
  • Job: An object that a Printer creates and manages, holding description, processing, and status information. A Job also contains zero or more Document objects. 🧾
  • Logical Device: A print server, software service, or gateway that processes Jobs and either forwards or stores the processed Job, or uses one or more Physical Devices to render output. 🏒
  • Model: The semantics of operations, attributes, values, and status-codes used in the Internet Printing Protocol, as defined in the Internet Printing Protocol/1.1: Model and Semantics document [RFC8011] and its later extensions. 🧠
  • Output Device: A single Logical or Physical Device. ✨
  • Physical Device: A hardware implementation of an endpoint device, for example a marking engine, a fax modem, and so on. πŸ–¨οΈ
  • Printer: The listener for incoming IPP session requests and the receiver of incoming IPP operation requests (Hypertext Transfer Protocol -- HTTP/1.1 [RFC7230] Server). It represents one or more Physical Devices or a Logical Device. πŸ†

2.3. Abbreviations πŸ”€

Here's the alphabet soup, bestie:

  • ABNF: Augmented Backus-Naur Form [RFC5234] 🧩
  • ASCII: American Standard Code for Information Interchange [RFC20] πŸ” 
  • HTTP: Hypertext Transfer Protocol [RFC7230] 🌐
  • HTTPS: HTTP over TLS [RFC2818] πŸ”’
  • IANA: Internet Assigned Numbers Authority πŸ—‚οΈ
  • IEEE: Institute of Electrical and Electronics Engineers ⚑
  • IESG: Internet Engineering Steering Group πŸ‘‘
  • IPP: Internet Printing Protocol (this document and [PWG5100.12]) πŸ–¨οΈπŸ’œ
  • ISTO: IEEE Industry Standards and Technology Organization πŸ›οΈ
  • LPD: Line Printer Daemon Protocol [RFC1179] πŸ¦•
  • PWG: IEEE-ISTO Printer Working Group πŸ§‘β€πŸ€β€πŸ§‘
  • RFC: Request for Comments πŸ“
  • TCP: Transmission Control Protocol [RFC793] 🚚
  • TLS: Transport Layer Security [RFC5246] πŸ›‘οΈ
  • URI: Uniform Resource Identifier [RFC3986] πŸ“
  • URL: Uniform Resource Locator [RFC3986] πŸ—ΊοΈ
  • UTF-8: Unicode Transformation Format - 8-bit [RFC3629] 🌈

3. Encoding of the Operation Layer ✨

okay so the operation layer is the message body part of the HTTP request or response, and it MUST contain a single IPP operation request or IPP operation response πŸ’Œ. Each request or response is a sequence of values and attribute groups. Attribute groups are sequences of attributes, and each attribute is a name and a value. Names and values are ultimately sequences of octets 🧚.

The whole encoding is built out of octets, which are the most primitive type πŸŽ€. Three important types sit on top of octets: integers, character strings, and octet strings, and most of the other data types are built from those three 🌸.

Every character string in this encoding MUST be a sequence of characters where the characters are associated with some charset [RFC2978] and some natural language 🌈. A character string MUST be in "reading order", so the first character in the value (according to reading order) is the first character in the encoding πŸ“–. A character string whose charset is US-ASCII and whose natural language is US English is from now on called a US-ASCII-STRING πŸ‡ΊπŸ‡Έ. A character string whose charset and natural language are specified in a request or response, as described in the Model, is from now on called a LOCALIZED-STRING πŸ’œ.

An octet string MUST be in "Model order", so the first octet in the value (according to the Model order) is the first octet in the encoding πŸ¦‹. Every integer in this encoding MUST be encoded as a signed integer using two's-complement binary encoding with big-endian format. This is also known as "network order" or "most significant byte first" πŸ”₯. The number of octets for an integer MUST be 1, 2, or 4, depending on how it's used in the protocol πŸ“.

Here's how the integer sizes shake out:

  • A one-octet integer, called a SIGNED-BYTE, is used for the version-number and tag fields 🍬.
  • A two-byte integer, called a SIGNED-SHORT, is used for the operation-id, status-code, and length fields ✨.
  • A four-byte integer, called a SIGNED-INTEGER, is used for value fields and the request-id πŸ’….

The next two sections explain the encoding of the operation layer in two different ways:

  • informally, through pictures and description πŸ–ΌοΈ
  • formally, through Augmented Backus-Naur Form (ABNF), as specified by RFC 5234 [RFC5234] 🧠

An operation request or response MUST use the encoding described in these two sections. No skipping, bestie 🫢.

3.1. Picture of the Encoding

3.1.1. Request and Response

An operation request or response is encoded like this πŸ‘€:

-----------------------------------------------
|                  version-number             |   2 bytes  - required
-----------------------------------------------
|               operation-id (request)        |
|                      or                     |   2 bytes  - required
|               status-code (response)        |
-----------------------------------------------
|                   request-id                |   4 bytes  - required
-----------------------------------------------
|                 attribute-group             |   n bytes - 0 or more
-----------------------------------------------
|              end-of-attributes-tag          |   1 byte   - required
-----------------------------------------------
|                     data                    |   q bytes  - optional
-----------------------------------------------

                       Figure 1: IPP Message Format

The first three fields in that diagram hold the values of attributes described in Section 4.1.1 of the Model and Semantics document [RFC8011]. Cute, right? They're like the VIP section of the message πŸ‘‘.

The fourth field is the "attribute-group" field, and it can show up 0 or more times 🌷. Each "attribute-group" field represents one group of attributes, like an Operation Attributes group or a Job Attributes group (see the Model) 🍰. The Model is the one that says which attribute groups are required, and what order they go in, for each operation request and response πŸ“‹.

The "end-of-attributes-tag" field is always present, even when the "data" field isn't πŸ›‘. The Model is the source of truth for whether the "data" field is present for each operation request and response πŸ’–.

3.1.2. Attribute Group

Each "attribute-group" field is encoded like this ✨:

-----------------------------------------------
|           begin-attribute-group-tag         |  1 byte
----------------------------------------------------------
|                   attribute                 |  p bytes |- 0 or more
----------------------------------------------------------

                    Figure 2: Attribute Group Encoding

An "attribute-group" field contains zero or more "attribute" fields 🧺.

Also, fun fact: the "begin-attribute-group-tag" field and the "end-of-attributes-tag" field are both called "delimiter-tags" 🚧.

3.1.3. Attribute

An "attribute" field is encoded like this πŸ¦‹:

-----------------------------------------------
|          attribute-with-one-value           |  q bytes
----------------------------------------------------------
|             additional-value                |  r bytes |- 0 or more
----------------------------------------------------------

                       Figure 3: Attribute Encoding

So here's the deal. When an attribute is single valued (like "copies" with a value of 10), or multi-valued with just one value (like "sides-supported" with only the value 'one-sided'), it's encoded with just an "attribute-with-one-value" field πŸ’…. When an attribute is multi-valued with n values (like "sides-supported" with the values 'one-sided' and 'two-sided-long-edge'), it's encoded with an "attribute-with-one-value" field followed by n-1 "additional-value" fields πŸŽ€. Main character energy for the first value, supporting cast for the rest 🌟.

3.1.4. Attribute-with-one-value

Each "attribute-with-one-value" field is encoded like this πŸ“¦:

-----------------------------------------------
|                   value-tag                 |   1 byte
-----------------------------------------------
|               name-length  (value is u)     |   2 bytes
-----------------------------------------------
|                     name                    |   u bytes
-----------------------------------------------
|              value-length  (value is v)     |   2 bytes
-----------------------------------------------
|                     value                   |   v bytes
-----------------------------------------------

                 Figure 4: Single Value Attribute Encoding

An "attribute-with-one-value" field has five subfields, and I'm obsessed with how neatly they line up 😭:

  • The "value-tag" field specifies the attribute syntax. For example, 0x44 is the attribute syntax 'keyword' πŸ”‘.
  • The "name-length" field specifies the length of the "name" field in bytes. That's u in the diagram above, or 15 for the name "sides-supported" πŸ“.
  • The "name" field contains the textual name of the attribute, like "sides-supported" 🏷️.
  • The "value-length" field specifies the length of the "value" field in bytes. That's v in the diagram, or 9 for the (keyword) value 'one-sided' 🍭.
  • The "value" field contains the value of the attribute, like the textual value 'one-sided' πŸ’œ.

3.1.5. Additional-value

Each "additional-value" field is encoded like this 🌈:

-----------------------------------------------
|                   value-tag                 |   1 byte
-----------------------------------------------
|            name-length  (value is 0x0000)   |   2 bytes
-----------------------------------------------
|              value-length (value is w)      |   2 bytes
-----------------------------------------------
|                     value                   |   w bytes
-----------------------------------------------

               Figure 5: Additional Attribute Value Encoding

An "additional-value" has four subfields 🫧:

  • The "value-tag" field specifies the attribute syntax. For example, 0x44 is the attribute syntax 'keyword' πŸ”‘.
  • The "name-length" field is always 0, and that's how it signals that this is an "additional-value". So here's the trick: a "name-length" of 0 means "additional-value", and a "name-length" that isn't 0 means "attribute-with-one-value" πŸ•΅οΈβ€β™€οΈ.
  • The "value-length" field specifies the length of the "value" field in bytes. That's w in the diagram, or 19 for the (keyword) value 'two-sided-long-edge' πŸ“.
  • The "value" field contains the value of the attribute, like the textual value 'two-sided-long-edge' πŸ“.

3.1.6. Collection Attribute

Collection attributes create a named group that holds related "member" attributes πŸ—‚οΈ. The "attribute-with-one-value" field for a collection attribute is encoded like this 🧩:

-----------------------------------------------
|          value-tag (value is 0x34)          |   1 byte
-----------------------------------------------
|          name-length (value is u)           |   2 bytes
-----------------------------------------------
|                     name                    |   u bytes
-----------------------------------------------
|        value-length (value is 0x0000)       |   2 bytes
-----------------------------------------------------------
|               member-attribute              |   q bytes |-0 or more
-----------------------------------------------------------
|        end-value-tag (value is 0x37)        |   1 byte
-----------------------------------------------
|      end-name-length (value is 0x0000)      |   2 bytes
-----------------------------------------------
|      end-value-length (value is 0x0000)     |   2 bytes
-----------------------------------------------

                  Figure 6: Collection Attribute Encoding

A collection attribute has eight subfields, and honestly, the bookends are giving πŸŽ€:

  • The "value-tag" field specifies the start attribute syntax: 0x34 is the attribute syntax 'begCollection' 🌸.
  • The "name-length" field specifies the length of the "name" field in bytes. That's u in the diagram, or 9 for the name "media-col". Additional collection attribute values use a name length of 0x0000 πŸ™ˆ.
  • The "name" field contains the textual name of the attribute, like "media-col" πŸ’–.
  • The "value-length" field specifies a length of 0x0000 πŸ«₯.
  • The "member-attribute" field contains member attributes, encoded as defined in Section 3.1.7 πŸ§šβ€β™€οΈ.
  • The "end-value-tag" field specifies the end attribute syntax: 0x37 is the attribute syntax 'endCollection' 🏁.
  • The "end-name-length" field specifies a length of 0x0000 πŸŒ™.
  • The "end-value-length" field specifies a length of 0x0000 ✨.

3.1.7. Member Attributes πŸŽ€

okay so member attributes are the little pieces that live inside a collection 🧚 each one gets encoded like this, no cap:

   -----------------------------------------------
   |          value-tag (value is 0x4a)          |   1 byte
   -----------------------------------------------
   |        name-length (value is 0x0000)        |   2 bytes
   -----------------------------------------------
   |          value-length (value is w)          |   2 bytes
   -----------------------------------------------
   |             value (member-name)             |   w bytes
   -----------------------------------------------
   |               member-value-tag              |   1 byte
   -----------------------------------------------
   |        name-length (value is 0x0000)        |   2 bytes
   -----------------------------------------------
   |      member-value-length (value is x)       |   2 bytes
   -----------------------------------------------
   |                member-value                 |   x bytes
   -----------------------------------------------

                    Figure 7: Member Attribute Encoding

A member-attribute is made of eight subfields πŸ’… here's the tea on each one:

  • The value-tag field specifies 0x4a for the attribute syntax memberAttrName.
  • The name-length field has the value of 0 in order to signify that it is a member-attribute contained in the collection.
  • The value-length field specifies the length of the value field in bytes, e.g., w in the above diagram or 10 for the member attribute name 'media-type'. Additional member attribute values are specified using a value length of 0.
  • The value field contains the name of the member attribute, e.g., the textual value 'media-type'.
  • The member-value-tag field specifies the attribute syntax for the member attribute, e.g., 0x44 for the attribute syntax keyword.
  • The second name-length field has the value of 0 in order to signify that it is a member-attribute contained in the collection.
  • The member-value-length field specifies the length of the member attribute value, e.g., x in the above diagram or 10 for the value 'stationery'.
  • The member-value field contains the value of the attribute, e.g., the textual value 'stationery'.

3.1.8. Alternative Picture of the Encoding of a Request or a Response πŸ¦‹

ok this one is for the parser girlies πŸ€“ if you're reading the message based on each tag value, the encoding looks like this:

   -----------------------------------------------
   |                  version-number             |   2 bytes  - required
   -----------------------------------------------
   |               operation-id (request)        |
   |                      or                     |   2 bytes  - required
   |               status-code (response)        |
   -----------------------------------------------
   |                   request-id                |   4 bytes  - required
   -----------------------------------------------------------
   |        tag (delimiter-tag or value-tag)     |   1 byte  |
   -----------------------------------------------           |-0 or more
   |           empty or rest of attribute        |   x bytes |
   -----------------------------------------------------------
   |              end-of-attributes-tag          |   1 byte   - required
   -----------------------------------------------
   |                     data                    |   y bytes  - optional
   -----------------------------------------------

                  Figure 8: Encoding Based on Value Tags

And here's what the parser should expect to see after each type of tag πŸ‘€:

  • begin-attribute-group-tag: expect zero or more attribute fields
  • value-tag: expect the remainder of an attribute-with-one-value or an additional-value
  • end-of-attributes-tag: expect that attribute fields are complete and there is optional data

3.2. Syntax of Encoding 🌈

the ABNF [RFC5234] syntax for an IPP message is shown in Figure 9, and it's giving very precise 🧐

   ipp-message  = ipp-request / ipp-response
   ipp-request  = version-number operation-id request-id
                  *attribute-group end-of-attributes-tag data
   ipp-response = version-number status-code request-id
                  *attribute-group end-of-attributes-tag  data

   version-number       = major-version-number minor-version-number
   major-version-number = SIGNED-BYTE
   minor-version-number = SIGNED-BYTE

   operation-id = SIGNED-SHORT     ; mapping from model
   status-code  = SIGNED-SHORT     ; mapping from model
   request-id   = SIGNED-INTEGER   ; whose value is > 0

   attribute-group          = begin-attribute-group-tag *attribute
   attribute                = attribute-with-one-value *additional-value
   attribute-with-one-value = value-tag name-length name
                              value-length value
   additional-value         = value-tag zero-name-length
                              value-length value

   name-length  = SIGNED-SHORT     ; number of octets of 'name'
   name         = LALPHA *( LALPHA / DIGIT / "-" / "_" / "." )
   value-length = SIGNED-SHORT     ; number of octets of 'value'
   value        = OCTET-STRING
   data         = OCTET-STRING

   zero-name-length          = %x00.00           ; name-length of 0
   value-tag                 = %x10-ff           ; see Section 3.5.2
   begin-attribute-group-tag = %x00-02 / %x04-0f ; see Section 3.5.1
   end-of-attributes-tag     = %x03              ; tag of 3
                                                 ; see Section 3.5.1

   SIGNED-BYTE    = BYTE
   SIGNED-SHORT   = 2BYTE
   SIGNED-INTEGER = 4BYTE
   DIGIT          = %x30-39        ; "0" to "9"
   LALPHA         = %x61-7A        ; "a" to "z"
   BYTE           = %x00-ff
   OCTET-STRING   = *BYTE

                   Figure 9: ABNF of IPP Message Format

Figure 10 defines some extra terms that get referenced in this doc, and it also gives us an alternate way of grouping the delimiter tags ✨

   delimiter-tag = begin-attribute-group-tag /   ; see Section 3.5.1
             end-of-attributes-tag
   begin-attribute-group-tag = %x00 / operation-attributes-tag /
      job-attributes-tag / printer-attributes-tag /
      unsupported-attributes-tag / future-group-tags
   operation-attributes-tag   = %x01             ; tag of 1
   job-attributes-tag         = %x02             ; tag of 2
   end-of-attributes-tag      = %x03             ; tag of 3
   printer-attributes-tag     = %x04             ; tag of 4
   unsupported-attributes-tag = %x05             ; tag of 5
   future-group-tags          = %x06-0f          ; future extensions

                 Figure 10: ABNF for Attribute Group Tags

3.3. Attribute-group πŸ’–

each attribute-group field MUST be encoded with the begin-attribute-group-tag field, followed by zero or more attribute subfields. no skipping that step, bestie 🫢

Table 1 maps the Model group name to the value of the begin-attribute-group-tag field πŸ“

   +----------------+--------------------------------------------------+
   | Model Document | "begin-attribute-group-tag" field values         |
   | Group          |                                                  |
   +----------------+--------------------------------------------------+
   | Operation      | "operations-attributes-tag"                      |
   | Attributes     |                                                  |
   +----------------+--------------------------------------------------+
   | Job Template   | "job-attributes-tag"                             |
   | Attributes     |                                                  |
   +----------------+--------------------------------------------------+
   | Job Object     | "job-attributes-tag"                             |
   | Attributes     |                                                  |
   +----------------+--------------------------------------------------+
   | Unsupported    | "unsupported-attributes-tag"                     |
   | Attributes     |                                                  |
   +----------------+--------------------------------------------------+
   | Requested      | (Get-Job-Attributes) "job-attributes-tag"        |
   | Attributes     |                                                  |
   +----------------+--------------------------------------------------+
   | Requested      | (Get-Printer-Attributes)"printer-attributes-tag" |
   | Attributes     |                                                  |
   +----------------+--------------------------------------------------+
   | Document       | in a special position at the end of the message  |
   | Content        | as described in Section 3.1.1.                   |
   +----------------+--------------------------------------------------+

                           Table 1: Group Values

For every operation request and response, the Model decides which attribute groups are required and which are optional, plus the order they go in πŸ“‹ same goes for attributes inside each group: the Model says which are required and which are optional, and in what order.

okay now the empty group situation πŸ™ˆ when the Model requires an attribute group and that group has zero attributes, a request or response SHOULD still encode the group with its begin-attribute-group-tag field followed by zero attribute fields. example: if the Client asks for a single unsupported attribute with Get-Printer-Attributes, the Printer MUST return no attribute fields, and it SHOULD return a begin-attribute-group-tag field for the Printer Attributes group. the Unsupported Attributes group is NOT like that, though πŸ™…β€β™€οΈ according to the Model, the Unsupported Attributes group SHOULD be present only if it contains at least one attribute.

a receiver of a request MUST be able to treat the following as equivalent empty attribute groups, so don't panic πŸ’œ

a. A begin-attribute-group-tag field with zero following attribute fields.

b. A missing, but expected, begin-attribute-group-tag field.

and when the Model needs a sequence of an unknown number of attribute groups, all of the same type, the encoding MUST contain one begin-attribute-group-tag field for each attribute group, even if an attribute-group field has zero attribute subfields. for example, Get-Jobs might return zero attributes for some Jobs and not others πŸ§ƒ a begin-attribute-group-tag followed by zero attribute fields tells the recipient "yep, there's a Job in the queue, we just don't have any info on it except that it's queued" 🎟️

3.4. Required Parameters πŸ‘‘

some operation elements are called parameters in the Model 🫧 they MUST be encoded in a special position, and they MUST NOT show up as operation attributes. the subsections below cover them.

3.4.1. "version-number" 🌸

the version-number field is a major and minor version-number, and each one is a SIGNED-BYTE πŸ’… the major version-number is the first byte of the encoding, and the minor version-number is the second byte. the protocol described in [RFC8011] has a major version-number of 1 (0x01) and a minor version-number of 1 (0x01), so the ABNF for these two bytes is %x01.01, periodt ✨

Note: check out Section 9 for more on the version-number field and IPP version numbers πŸ¦‹

3.4.2. "operation-id" πŸ’

the operation-id field holds an operation-id value as defined in the Model 🧠 it's encoded as a SIGNED-SHORT and lives in the third and fourth bytes of the encoding of an operation request πŸŽ€

3.4.3. "status-code" πŸ’–

Okay bestie, the "status-code" field holds the status-code value from the Model ✨ It's encoded as a SIGNED-SHORT and lives in the third and fourth bytes of an operation response encoding πŸŽ€

If an IPP status-code is returned, then the HTTP status-code MUST be 200 (OK). πŸ’… With any other HTTP status-code value, the HTTP response MUST NOT contain an IPP message body, so no IPP status-code comes back at all πŸ™ˆ

3.4.4. "request-id" πŸ¦‹

The "request-id" field is the request-id value from the Model πŸ’œ It's encoded as a SIGNED-INTEGER and sits in the fifth through eighth bytes of the encoding 🌸

3.5. Tags 🌈

Tags come in two flavours, and I'm obsessed with how they split the work 😭

  • delimiter tags: delimit major sections of the protocol, namely attribute groups and data
  • value tags: specify the type of each attribute value

Tags are part of the IANA IPP registry [IANA-IPP] πŸ“š

3.5.1. "delimiter-tag" Values πŸ‘‘

Table 2 lists the values for the delimiter tags defined in this document. These are registered, along with tags from other documents, in the "Attribute Group Tags" registry 🧚

            +-----------------+------------------------------+
            | Tag Value (Hex) | Meaning                      |
            +-----------------+------------------------------+
            | 0x00            | Reserved                     |
            | 0x01            | "operation-attributes-tag"   |
            | 0x02            | "job-attributes-tag"         |
            | 0x03            | "end-of-attributes-tag"      |
            | 0x04            | "printer-attributes-tag"     |
            | 0x05            | "unsupported-attributes-tag" |
            +-----------------+------------------------------+

                      Table 2: "delimiter-tag" Values

When a "begin-attribute-group-tag" field shows up, it means that zero or more of the following attributes, up to the next group tag, belong to the attribute group named by that tag's value ✨ For example, if "begin-attribute-group-tag" is 0x01, the attributes that follow are members of the Operations Attributes group πŸŽ€

The "end-of-attributes-tag" (value 0x03) MUST occur exactly once in an operation and MUST be the last "delimiter-tag" 😀 If the operation has a document-data group, the Document data in that group follows the "end-of-attributes-tag" 🫢

The order and presence of "attribute-group" fields (whose beginning is marked by the "begin-attribute-group-tag" subfield) for each operation request and each operation response MUST be that defined in the Model πŸ’…

A Printer MUST treat a "delimiter-tag" (values from 0x00 through 0x0f) differently from a "value-tag" (values from 0x10 through 0xff), so the Printer knows there's a whole attribute group instead of a single value πŸ”₯

3.5.2. "value-tag" Values πŸ“

The remaining tables cover the "value-tag" field, which is the first octet of an attribute πŸ’œ The "value-tag" field tells you the type of the attribute's value, and that's the whole plot 🌈

Table 3 lists the "out-of-band" values for the "value-tag" field defined in this document. These are registered, along with tags from other documents, in the "Out-of-Band Attribute Value Tags" registry πŸ¦‹

                     +-----------------+-------------+
                     | Tag Value (Hex) | Meaning     |
                     +-----------------+-------------+
                     | 0x10            | unsupported |
                     | 0x12            | unknown     |
                     | 0x13            | no-value    |
                     +-----------------+-------------+

                        Table 3: Out-of-Band Values

Table 4 lists the integer values defined here for the "value-tag" field. They're registered in the "Attribute Syntaxes" registry 🌸

   +----------------+--------------------------------------------------+
   | Tag Value      | Meaning                                          |
   | (Hex)          |                                                  |
   +----------------+--------------------------------------------------+
   | 0x20           | Unassigned integer data type (see IANA IPP       |
   |                | registry)                                        |
   | 0x21           | integer                                          |
   | 0x22           | boolean                                          |
   | 0x23           | enum                                             |
   | 0x24-0x2f      | Unassigned integer data types (see IANA IPP      |
   |                | registry)                                        |
   +----------------+--------------------------------------------------+

                           Table 4: Integer Tags

Table 5 lists the octetString values defined here for the "value-tag" field, also registered in the "Attribute Syntaxes" registry 🧚

   +---------------+---------------------------------------------------+
   | Tag Value     | Meaning                                           |
   | (Hex)         |                                                   |
   +---------------+---------------------------------------------------+
   | 0x30          | octetString with an unspecified format            |
   | 0x31          | dateTime                                          |
   | 0x32          | resolution                                        |
   | 0x33          | rangeOfInteger                                    |
   | 0x34          | begCollection                                     |
   | 0x35          | textWithLanguage                                  |
   | 0x36          | nameWithLanguage                                  |
   | 0x37          | endCollection                                     |
   | 0x38-0x3f     | Unassigned octetString data types (see IANA IPP   |
   |               | registry)                                         |
   +---------------+---------------------------------------------------+

                         Table 5: octetString Tags

Table 6 lists the character-string values defined here for the "value-tag" field, registered in the "Attribute Syntaxes" registry too πŸ’–

   +---------------+---------------------------------------------------+
   | Tag Value     | Meaning                                           |
   | (Hex)         |                                                   |
   +---------------+---------------------------------------------------+
   | 0x40          | Unassigned character-string data type (see IANA   |
   |               | IPP registry)                                     |
   | 0x41          | textWithoutLanguage                               |
   | 0x42          | nameWithoutLanguage                               |
   | 0x43          | Unassigned character-string data type (see IANA   |
   |               | IPP registry)                                     |
   | 0x44          | keyword                                           |
   | 0x45          | uri                                               |
   | 0x46          | uriScheme                                         |
   | 0x47          | charset                                           |
   | 0x48          | naturalLanguage                                   |
   | 0x49          | mimeMediaType                                     |
   | 0x4a          | memberAttrName                                    |
   | 0x4b-0x5f     | Unassigned character-string data types (see IANA  |
   |               | IPP registry)                                     |
   +---------------+---------------------------------------------------+

                           Table 6: String Tags
Note: An attribute value always has a type, and that type is explicitly specified by its tag. One such tag value is "nameWithoutLanguage". An attribute's name has an implicit type, which is keyword. πŸ”₯

The values 0x60-0xff are reserved for future type definitions in Standards Track documents πŸ‘‘

The tag 0x7f is reserved for extending types beyond the 255 values a single byte can hold 🌈 A tag value of 0x7f MUST signify that the first four bytes of the value field are interpreted as the tag value. Bonus: this future extension doesn't affect parsers that don't know about it, because the tag is treated like any other unknown tag 🫢 The value length says how long the value is, and the parser handles that value atomically. Values from 0x00000000 to 0x3fffffff are reserved for definition in future Standards Track documents. The values 0x40000000 to 0x7fffffff are reserved for vendor extensions πŸ¦‹

3.6. "name-length" πŸ’…

The "name-length" field is a SIGNED-SHORT that gives the number of octets in the immediately following "name" field. The value of this field doesn't count the two bytes of the "name-length" field itself πŸŽ€ For example, if the "name" field contains 'sides', the value of this field is 5 ✨

If a "name-length" field has a value of zero, the following "name" field is empty, and the following value is treated as an additional value for the attribute encoded in the nearest preceding "attribute-with-one-value" field πŸ™ˆ Within an attribute group, if two or more attributes have the same name, the attribute group is malformed (see [RFC8011]) 😭 The zero-length name is the only mechanism for multi-valued attributes πŸ’œ

3.7. (Attribute) "name" 🌸

The "name" field holds the name of an attribute, and the Model is the one that specifies those names 🧚

3.8. "value-length" πŸ’–

The "value-length" field is a SIGNED-SHORT that specifies the number of octets in the immediately following "value" field. The value of this field doesn't count the two bytes of the "value-length" field πŸ¦‹ For example, if the "value" field contains the keyword (string) value 'one-sided', the value of this field is 9 πŸ“

For any of the types represented by binary signed integers, the sender MUST encode the value in exactly four octets πŸ”₯

For any of the types represented by binary signed bytes, e.g., the boolean type, the sender MUST encode the value in exactly one octet πŸ’…

For any of the types represented by character strings, the sender MUST encode the value with all the characters of the string and without any padding characters 🫢

For "out-of-band" values for the "value-tag" field defined in this document, such as 'unsupported', the "value-length" MUST be 0 and the "value" empty πŸ™ˆ The "value" has no meaning when the "value-tag" has one of these "out-of-band" values. For future "out-of-band" "value-tag" fields, the same rule holds unless the definition explicitly states that the "value-length" MAY be non-zero and the "value" non-empty 🌈

3.9. (Attribute) "value" πŸ’–

okay so the syntax types (the ones the "value-tag" field points at) and most of the nitty-gritty about how attribute values get represented are all defined in the Model 🧚. Table 7 is like a cheat sheet that adds to the Model and defines every Model syntax type using the five basic types from Section 3 ✨. The five types are US-ASCII-STRING, LOCALIZED-STRING, SIGNED-INTEGER, SIGNED-SHORT, SIGNED-BYTE, and OCTET-STRING.

+----------------------+--------------------------------------------+
| Syntax of Attribute  | Encoding                                   |
| Value                |                                            |
+----------------------+--------------------------------------------+
| textWithoutLanguage, | LOCALIZED-STRING                           |
| nameWithoutLanguage  |                                            |
+----------------------+--------------------------------------------+
| textWithLanguage     | OCTET-STRING consisting of four fields: a  |
|                      | SIGNED-SHORT, which is the number of       |
|                      | octets in the following field; a value of  |
|                      | type natural-language; a SIGNED-SHORT,     |
|                      | which is the number of octets in the       |
|                      | following field; and a value of type       |
|                      | textWithoutLanguage.  The length of a      |
|                      | textWithLanguage value MUST be 4 + the     |
|                      | value of field a + the value of field c.   |
+----------------------+--------------------------------------------+
| nameWithLanguage     | OCTET-STRING consisting of four fields: a  |
|                      | SIGNED-SHORT, which is the number of       |
|                      | octets in the following field; a value of  |
|                      | type natural-language; a SIGNED-SHORT,     |
|                      | which is the number of octets in the       |
|                      | following field; and a value of type       |
|                      | nameWithoutLanguage.  The length of a      |
|                      | nameWithLanguage value MUST be 4 + the     |
|                      | value of field a + the value of field c.   |
+----------------------+--------------------------------------------+
| charset,             | US-ASCII-STRING                            |
| naturalLanguage,     |                                            |
| mimeMediaType,       |                                            |
| keyword, uri, and    |                                            |
| uriScheme            |                                            |
+----------------------+--------------------------------------------+
| boolean              | SIGNED-BYTE where 0x00 is 'false' and 0x01 |
|                      | is 'true'                                  |
+----------------------+--------------------------------------------+
| integer and enum     | a SIGNED-INTEGER                           |
+----------------------+--------------------------------------------+
| dateTime             | OCTET-STRING consisting of eleven octets   |
|                      | whose contents are defined by              |
|                      | "DateAndTime" in RFC 2579 [RFC2579]        |
+----------------------+--------------------------------------------+
| resolution           | OCTET-STRING consisting of nine octets of  |
|                      | two SIGNED-INTEGERs followed by a SIGNED-  |
|                      | BYTE.  The first SIGNED-INTEGER contains   |
|                      | the value of cross-feed direction          |
|                      | resolution.  The second SIGNED-INTEGER     |
|                      | contains the value of feed direction       |
|                      | resolution.  The SIGNED-BYTE contains the  |
|                      | units value.                               |
+----------------------+--------------------------------------------+
| rangeOfInteger       | Eight octets consisting of two SIGNED-     |
|                      | INTEGERs.  The first SIGNED-INTEGER        |
|                      | contains the lower bound and the second    |
|                      | SIGNED-INTEGER contains the upper bound.   |
+----------------------+--------------------------------------------+
| 1setOf X             | Encoding according to the rules for an     |
|                      | attribute with more than one value.  Each  |
|                      | value X is encoded according to the rules  |
|                      | for encoding its type.                     |
+----------------------+--------------------------------------------+
| octetString          | OCTET-STRING                               |
+----------------------+--------------------------------------------+
| collection           | Encoding as defined in Section 3.1.6.      |
+----------------------+--------------------------------------------+

Table 7: Attribute Value Encoding

whatever syntax type an attribute value has is what decides its encoding, and it's also what sets the value of its "value-tag" πŸŽ€ ngl, it's the whole chain reaction πŸ¦‹

3.10. Data πŸ“

the "data" field MUST include any data required by the operation. no skipping it, bestie 🫢

4. Encoding of Transport Layer 🚚

okay the transport layer is where things get real πŸ”₯ HTTP/1.1 [RFC7230] is the REQUIRED transport layer for this protocol, full stop πŸ’… HTTP/2 [RFC7540] is an OPTIONAL transport layer for this protocol, so it's a bonus, not a must ✨

the operation layer was designed assuming the transport layer is carrying these two things:

  • the target URI for the operation; and
  • the total length of the data in the operation layer, either as a single length or as a sequence of chunks each with a length.

Printer implementations MUST support HTTP over the IANA-assigned well-known port 631 (the IPP default port), although a Printer implementation can support HTTP over some other port as well 🌸

each HTTP operation MUST use the POST method, where the request-target is the object target of the operation. and the "Content-Type" of the message body in each request and response MUST be "application/ipp" πŸ’œ the message body MUST contain the operation layer and MUST have the syntax described in Section 3.2, "Syntax of Encoding". A Client implementation MUST adhere to the rules for a Client described for HTTP [RFC7230]. A Printer (server) implementation MUST adhere to the rules for an origin server described for HTTP [RFC7230]. main character energy, the rules are super clear πŸ‘‘

An IPP server sends a response for each request that it receives. If an IPP server detects an error, it MAY send a response before it has read the entire request. If the HTTP layer of the IPP server completes processing the HTTP headers successfully, it MAY send an intermediate response, such as "100 Continue", with no IPP data before sending the IPP response. A Client MUST expect such a variety of responses from an IPP server πŸ¦‹ for further info on HTTP, go check the HTTP documents [RFC7230], iykyk 🧚

An HTTP/1.1 server MUST support chunking for IPP requests, and an IPP Client MUST support chunking for IPP responses according to HTTP/1.1 [RFC7230] 🌈

4.1. Printer URI, Job URI, and Job ID πŸͺͺ

All Printer and Job objects are identified by a Uniform Resource Identifier (URI) [RFC3986] so that they can be persistently and unambiguously referenced. Jobs can also be identified by a combination of Printer URI and Job ID ✨

some operation elements are encoded twice: once as the request-target on the HTTP request-line, and a second time as a REQUIRED operation attribute in the application/ipp entity. these attributes are the target for the operation and are called "printer-uri" and "job-uri" πŸŽ€

Note: The target URI is included twice in an operation referencing the same IPP object, but the two URIs can be different. For example, the HTTP request-target can be relative while the IPP request URI is absolute. πŸ™ˆ

HTTP allows Clients to generate and send a relative URI rather than an absolute URI. A relative URI identifies a resource with the scope of the HTTP server but does not include scheme, host, or port. the following statements characterize how URIs are used in the mapping of IPP onto HTTP πŸ’–

  1. Although potentially redundant, a Client MUST supply the target of the operation both as an operation attribute and as a URI at the HTTP layer. The rationale for this decision is to maintain a consistent set of rules for mapping "application/ipp" to possibly many communication layers, even where URIs are not used as the addressing mechanism in the transport layer.
  2. Even though these two URIs might not be literally identical (one being relative and the other being absolute), they MUST both reference the same IPP object.
  3. The URI in the HTTP layer is either relative or absolute and is used by the HTTP server to route the HTTP request to the correct resource relative to that HTTP server.
  4. Once the HTTP server resource begins to process the HTTP request, it can get the reference to the appropriate IPP Printer object from either the HTTP URI (using to the context of the HTTP server for relative URIs) or from the URI within the operation request; the choice is up to the implementation. 🧚
  5. HTTP URIs can be relative or absolute, but the target URI in the IPP operation attribute MUST be an absolute URI. πŸ’…

5. IPP URI Schemes ✨

okay so the IPP URI schemes are 'ipp' [RFC3510] and 'ipps' [RFC7472] πŸ¦‹ and bestie, Clients and Printers MUST support the ipp-URI value in these IPP attributes:

  • Job attributes:
    • job-uri
    • job-printer-uri
  • Printer attributes:
    • printer-uri-supported
  • Operation attributes:
    • job-uri
    • printer-uri

each of these attributes identifies a Printer or Job πŸ–¨οΈ the ipp-URI and ipps-URI are meant to be the value of the attributes in this list. all of them have a syntax type of 'uri', BUT there are other 'uri' attributes that don't use the 'ipp' scheme, like "job-more-info" πŸ™ˆ so don't assume every URI is an ipp one, periodt.

If a Printer registers its URI with a directory service, the Printer MUST register an ipp-URI or ipps-URI. no exceptions, it's giving rule πŸ’…

When a Client sends a request, it MUST convert a target ipp-URI to a target http-URL (or ipps-URI to a target https-URI) for the HTTP layer. the steps are:

  1. change the 'ipp' scheme to 'http' or 'ipps' scheme to 'https'; and
  2. add an explicit port 631 if the ipp-URL or ipps-URL does not contain an explicit port. note that port 631 is the IANA-assigned well-known port for the 'ipp' and 'ipps' schemes 🌸

the Client MUST use the target http-URL or https-URL in both the HTTP request-line and HTTP headers, as specified by HTTP [RFC7230]. but the Client MUST use the target ipp-URI or ipps-URI for the value of the "printer-uri" or "job-uri" operation attribute within the application/ipp body of the request. the server MUST use the ipp-URI or ipps-URI for the value of the "printer-uri", "job-uri", or "printer-uri-supported" attributes within the application/ipp body of the response. so the HTTP part gets the http vibes, and the IPP body keeps the ipp vibes πŸŽ€

here's an example. when an IPP Client sends a request directly (no proxy) to the ipp-URI ipp://printer.example.com/ipp/print/myqueue, it opens a TCP connection to port 631 (the IPP implicit port) on the host printer.example.com and sends this:

POST /ipp/print/myqueue HTTP/1.1
Host: printer.example.com:631
Content-type: application/ipp
Transfer-Encoding: chunked
...
"printer-uri" 'ipp://printer.example.com/ipp/print/myqueue'
       (encoded in application/ipp message body)
...

                 Figure 11: Direct IPP Request

and now the proxy version 🧚 same request, but this time it goes through myproxy.example.com. the Client opens a TCP connection to the proxy port 8080 on the proxy host myproxy.example.com and sends this:

POST http://printer.example.com:631/ipp/print/myqueue HTTP/1.1
Host: printer.example.com:631
Content-type: application/ipp
Transfer-Encoding: chunked
...
"printer-uri" 'ipp://printer.example.com/ipp/print/myqueue'
       (encoded in application/ipp message body)
...

                Figure 12: Proxied IPP Request

the proxy then connects to the IPP origin server with headers that are the same as the "no-proxy" example above. it's the same energy, just with a middleman πŸ’œ


6. IANA Considerations

okay the IANA-PRINTER-MIB [RFC3805] has been updated to reference this document. the current version is available from <http://www.iana.org> 🌈

see the IANA Considerations in the document "Internet Printing Protocol/1.1: Model and Semantics" [RFC8011] for info on IANA considerations for IPP extensions. IANA has also updated the existing 'application/ipp' media type registration (whose contents are defined in Section 3 "Encoding of the Operation Layer") with the following info:

Type name: application

Subtype name: ipp

Required parameters: N/A

Optional parameters: N/A

Encoding considerations: IPP requests/responses MAY contain long
lines and ALWAYS contain binary data (for example, attribute value
lengths).

Security considerations: IPP requests/responses do not introduce any
security risks not already inherent in the underlying transport
protocols.  Protocol mixed-version interworking rules in [RFC8011] as
well as protocol-encoding rules in this document are complete and
unambiguous.  See also the security considerations in this document
and [RFC8011].

Interoperability considerations: IPP requests (generated by Clients)
and responses (generated by servers) MUST comply with all conformance
requirements imposed by the normative specifications [RFC8011] and
this document.  Protocol-encoding rules specified in RFC 8010 are
comprehensive so that interoperability between conforming
implementations is guaranteed (although support for specific optional
features is not ensured).  Both the "charset" and "natural-language"
of all IPP attribute values that are a LOCALIZED-STRING are explicit
within IPP requests/responses (without recourse to any external
information in HTTP, SMTP, or other message transport headers).

Published specifications: RFCs 8010 and 8011

Applications that use this media type: Internet Printing Protocol
(IPP) print clients and print servers that communicate using HTTP/
HTTPS or other transport protocols.  Messages of type "application/
ipp" are self-contained and transport independent, including
"charset" and "natural-language" context for any LOCALIZED-STRING
value.

Fragment identifier considerations: N/A
Additional information:

   Deprecated alias names for this type: N/A
   Magic number(s): N/A
   File extension(s): N/A
   Macintosh file type code(s): N/A

Person & email address to contact for further information:

   ISTO PWG IPP Workgroup <ipp@pwg.org>

Intended usage: COMMON

Restrictions on usage: N/A

Author: ISTO PWG IPP Workgroup <ipp@pwg.org>

Change controller: ISTO PWG IPP Workgroup <ipp@pwg.org>

Provisional registration? (standards tree only): No

7. Internationalization Considerations

see the section on "Internationalization Considerations" in the document "Internet Printing Protocol/1.1: Model and Semantics" [RFC8011] for the i18n details. this document adds no additional issues 🌍✨


8. Security Considerations πŸ”

okay this one is SERIOUS bestie, so grab your snacks πŸ“ the IPP Model and Semantics document [RFC8011] talks about the high-level security requirements: Client Authentication, Server Authentication, and Operation Privacy.

  • Client Authentication is how the Client proves its identity to the server in a secure way.
  • Server Authentication is how the server proves its identity to the Client in a secure way.
  • Operation Privacy is a mechanism for protecting operations from eavesdropping. no snooping allowed πŸ‘€

Message Integrity is covered in the document "Internet Printing Protocol (IPP) over HTTPS Transport Binding and the 'ipps' URI Scheme" [RFC7472] 🫢

8.1. Security Conformance Requirements

this section defines the security requirements for IPP Clients and IPP objects. the rules are lowkey strict, so read carefully πŸ’–

8.1.1. Digest Authentication

IPP Clients and Printers SHOULD support Digest Authentication [RFC7616]. Use of the Message Integrity feature (qop="auth-int") is OPTIONAL.

Note: previous versions of this spec required support for the MD5 algorithms. however, [RFC7616] makes SHA2-256 mandatory to implement and deprecates MD5, only allowing its use for backwards compatibility reasons. so IPP implementations that support Digest Authentication MUST support SHA2-256 and SHOULD support MD5 for backwards compatibility. the glow-up is real 🌸

Note: the reason that IPP Clients and Printers SHOULD (rather than MUST) support Digest Authentication is that there's a certain class of Output Devices where it doesn't make sense. specifically, a low-end device with limited ROM space and low paper throughput may not need Client Authentication. this class of device typically forces firmware designers to make trade-offs between protocols and functionality to land on the lowest-cost solution possible. the designer has to weigh not just the size of the code, but also the testing, maintenance, usefulness, and time-to-market impact for each feature delivered to the customer. forcing these low-end devices to provide security just to claim IPP/1.1 conformance wouldn't make business sense 🧾 print devices with high-volume throughput and available ROM space will typically support Client Authentication that safeguards the device from unauthorized access, because these devices are prone to a high loss of consumables and paper if unauthorized access happens πŸ’Έ

8.1.2. Transport Layer Security (TLS)

IPP Clients and Printers SHOULD support Transport Layer Security (TLS) [RFC5246] [RFC7525] for Server Authentication and Operation Privacy. IPP Printers MAY also support TLS for Client Authentication. IPP Clients and Printers MAY support Basic Authentication [RFC7617] for User Authentication if the channel is secure, e.g., IPP over HTTPS [RFC7472]. but IPP Clients and Printers SHOULD NOT support Basic Authentication over insecure channels. yikes, no cap πŸ™…β€β™€οΈ

the IPP Model and Semantics document [RFC8011] defines two Printer attributes ("uri-authentication-supported" and "uri-security-supported") that the Client can use to discover a Printer's security policy. that document also outlines IPP-specific security considerations and is the primary reference for security implications with regard to IPP itself πŸ”

Note: because previous versions of this spec did not require TLS support, this version can't require it for IPP/1.1. however, printing often involves a great deal of sensitive or private info (medical reports, performance reviews, banking information, etc.), and network monitoring is pervasive ([RFC7258]). so implementors are strongly encouraged to include TLS support. this is literally the main character moment πŸ˜­πŸ”’

Note: because IPP Printers typically use self-signed X.509 certificates, IPP Clients SHOULD support Trust On First Use (defined in [RFC7435]) in addition to traditional X.509 certificate validation πŸ¦‹

8.2. Using IPP with TLS

IPP uses the "Upgrading to TLS Within HTTP/1.1" mechanism [RFC2817] for 'ipp' URIs. the Client requests a secure TLS connection by using the HTTP Upgrade header, and the server agrees in the HTTP response. the switch to TLS happens either because the server grants the Client's request to upgrade, or because a server asks to switch to TLS in its response. secure communication begins with a server's response to switch to TLS πŸ”βœ¨

IPP uses the "HTTPS: HTTP over TLS" mechanism [RFC2818] for 'ipps' URIs. the Client and server negotiate a secure TLS connection immediately and unconditionally. no waiting, no maybe πŸ’…


9. Interoperability with Other IPP Versions 🌈

it's beyond the scope of this specification to mandate conformance with versions of IPP other than 1.1. BUT IPP was deliberately designed to make supporting other versions easy, which is so smart 🧠 IPP objects (Printers, Jobs, etc.) SHOULD:

  • understand any valid request whose major version-number is greater than 0; and
  • respond appropriately with a response containing the same version-number parameter value the Client used in the request (if the Client-supplied version-number is supported), or the highest version-number supported by the Printer (if the Client-supplied version-number is not supported).

IPP Clients SHOULD:

  • understand any valid response whose major version-number is greater than 0.

9.1. The "version-number" Parameter ✨

okay so this one is all about the "version-number" parameter πŸŽ€ (peep Section 3.3 if you want the backstory). here are the rules:

  1. Clients MUST send requests with the highest supported value, like 1.1, 2.0, etc. πŸ”₯ If they get a server-error-version-not-supported error back, they SHOULD try supplying alternate version numbers. For example, if a Client sends an IPP/2.0 request that gets rejected with server-error-version-not-supported and an IPP/1.1 "version-number", it SHOULD retry by sending an IPP/1.1 request πŸ¦‹
  2. IPP objects (Printers, Jobs, etc.) MUST accept requests with a '1.1' value πŸ’– (or reject the request for reasons other than 'server-error-version-not-supported') πŸ’…
  3. IPP objects SHOULD either accept requests whose major version is greater than 0 or reject them with the 'server-error-version-not-supported' status-code 🌸 See Section 4.1.8 of [RFC8011].
  4. In any case, security MUST NOT be compromised when a Client supplies a lower "version-number" parameter in a request 🫢 For example, if an IPP/2.0 conforming Printer accepts version '1.1' requests and is set up to enforce Digest Authentication, it MUST do the same for a version '1.1' request. no shortcuts, bestie 😭

9.2. Security and URI Schemes πŸ”

this section is about how security, the "version-number" parameter, and the URI scheme in target attributes and responses all vibe together ✨

  1. When a Client supplies a request, the "printer-uri" or "job-uri" target operation attribute MUST have the same scheme as one of the values of the "printer-uri-supported" Printer attribute πŸ’œ
  2. When the Printer returns the "job-printer-uri" or "job-uri" Job Description attributes, it SHOULD return the same scheme ('ipp', 'ipps', etc.) that the Client supplied in the "printer-uri" or "job-uri" target operation attributes in the Get-Job-Attributes or Get-Jobs request 🧚 It's the one the Client used in that query, not the scheme from when the Job was created. However, when a Client asks for Job attributes with Get-Job-Attributes or Get-Jobs, what the Printer hands back depends on: (1) the security in effect when the Job was created, (2) the security in effect in the query request, and (3) the security policy in force. it's giving layers πŸ“
  3. The Printer MUST enforce its security and privacy policies based on the owner of the IPP object and on the URI scheme and/or credentials the Client supplies in the current request πŸ‘‘

10. Changes since RFC 2910 🌈

okay here's the glow-up list. these are all the changes since RFC 2910 was published:

  • Added references to current IPP extension specifications πŸ’–
  • Added optional support for HTTP/2 πŸ¦‹
  • Added collection attribute syntax from RFC 3382 πŸŽ€
  • Fixed typographical errors πŸ’…
  • Now reference TLS/1.2 and no longer mandate the TLS/1.0 MTI ciphersuites πŸ”₯
  • Updated all references 🌸
  • Updated document organization to follow current style ✨
  • Updated example ipp: URIs to follow guidelines in RFC 7472 🧚
  • Updated version compatibility for all versions of IPP πŸ’œ
  • Updated HTTP Digest Authentication to optional for Clients 🫢
  • Removed references to (Experimental) IPP/1.0 and usage of http:/https: URLs πŸ’€

11. References πŸ“š

11.1. Normative References

11.2. Informative References


Appendix A. Protocol Examples 🧚

A.1. Print-Job Request ✨

okay so this is a Print-Job request with "job-name", "copies", and "sides" all specified πŸ–¨οΈ. The ipp-attribute-fidelity attribute is set to 'true', which means the whole print request fails if "copies" or "sides" isn't supported, or if their values aren't supported. it's giving strict bestie energy πŸ’…

Octets                         Symbolic Value       Protocol field

0x0101                         1.1                  version-number
0x0002                         Print-Job            operation-id
0x00000001                     1                    request-id
0x01                           start operation-     operation-
                               attributes           attributes-tag
0x47                           charset type         value-tag
0x0012                                              name-length
attributes-charset             attributes-charset   name
0x0005                                              value-length
utf-8                          UTF-8                value
0x48                           natural-language     value-tag
                               type
0x001b                                              name-length
attributes-natural-language    attributes-natural-  name
                               language
0x0005                                              value-length
en-us                          en-US                value
0x45                           uri type             value-tag
0x000b                                              name-length
printer-uri                    printer-uri          name
0x002c                                              value-length
ipp://printer.example.com/ipp/ printer pinetree     value
print/pinetree
0x42                           nameWithoutLanguage  value-tag
                               type
0x0008                                              name-length
job-name                       job-name             name
0x0006                                              value-length
foobar                         foobar               value
0x22                           boolean type         value-tag
0x0016                                              name-length
ipp-attribute-fidelity         ipp-attribute-       name
                               fidelity
0x0001                                              value-length
0x01                           true                 value
0x02                           start job-attributes job-attributes-

                                                    tag
0x21                           integer type         value-tag
0x0006                                              name-length
copies                         copies               name
0x0004                                              value-length
0x00000014                     20                   value
0x44                           keyword type         value-tag
0x0005                                              name-length
sides                          sides                name
0x0013                                              value-length
two-sided-long-edge            two-sided-long-edge  value
0x03                           end-of-attributes    end-of-
                                                    attributes-tag
%!PDF...                       <PDF Document>       data

A.2. Print-Job Response (Successful) πŸŽ€

here's the successful Print-Job response to that previous request πŸ₯³. the Printer supported both "copies" and "sides" along with their supplied values, so the status-code comes back as 'successful-ok' ✨

Octets                           Symbolic Value     Protocol field

0x0101                           1.1                version-number
0x0000                           successful-ok      status-code
0x00000001                       1                  request-id
0x01                             start operation-   operation-
                                 attributes         attributes-tag
0x47                             charset type       value-tag
0x0012                                              name-length
attributes-charset               attributes-charset name
0x0005                                              value-length
utf-8                            UTF-8              value
0x48                             natural-language   value-tag
                                 type
0x001b                                              name-length
attributes-natural-language      attributes-        name
                                 natural-language
0x0005                                              value-length
en-us                            en-US              value
0x41                             textWithoutLanguag value-tag
                                 e type
0x000e                                              name-length
status-message                   status-message     name
0x000d                                              value-length
successful-ok                    successful-ok      value
0x02                             start job-         job-attributes-
                                 attributes         tag
0x21                             integer            value-tag
0x0006                                              name-length
job-id                           job-id             name
0x0004                                              value-length
147                              147                value
0x45                             uri type           value-tag
0x0007                                              name-length
job-uri                          job-uri            name
0x0030                                              value-length
ipp://printer.example.com/ipp/pr job 147 on         value
int/pinetree/147                 pinetree
0x23                             enum type          value-tag
0x0009                                              name-length
job-state                        job-state          name
0x0004                                              value-length
0x0003                           pending            value
0x03                             end-of-attributes  end-of-
                                                    attributes-tag

A.3. Print-Job Response (Failure) πŸ’€

and now the flop era 😭. this is the unsuccessful Print-Job response to that same request. it fails because the Printer doesn't support the "sides" attribute, and because the value '20' for "copies" isn't supported either. so no Job gets created, and neither a "job-id" nor a "job-uri" operation attribute comes back πŸ™ˆ. the error code is 'client-error-attributes-or-values-not-supported' (0x040b) πŸ’œ

Octets                      Symbolic Value              Protocol
                                                        field

0x0101                      1.1                         version-
                                                        number
0x040b                      client-error-attributes-or- status-code
                            values-not-supported
0x00000001                  1                           request-id
0x01                        start operation-attributes  operation-
                                                        attributes
                                                        tag
0x47                        charset type                value-tag
0x0012                                                  name-length
attributes-charset          attributes-charset          name
0x0005                                                  value-length
utf-8                       UTF-8                       value
0x48                        natural-language type       value-tag
0x001b                                                  name-length
attributes-natural-language attributes-natural-language name
0x0005                                                  value-length
en-us                       en-US                       value
0x41                        textWithoutLanguage type    value-tag
0x000e                                                  name-length
status-message              status-message              name
0x002f                                                  value-length
client-error-attributes-or- client-error-attributes-or- value
values-not-supported        values-not-supported
0x05                        start unsupported-          unsupported-
                            attributes                  attributes
                                                        tag
0x21                        integer type                value-tag
0x0006                                                  name-length
copies                      copies                      name
0x0004                                                  value-length
0x00000014                  20                          value
0x10                        unsupported (type)          value-tag
0x0005                                                  name-length
sides                       sides                       name
0x0000                                                  value-length
0x03                        end-of-attributes           end-of-
                                                        attributes-
                                                        tag

A.4. Print-Job Response (Success with Attributes Ignored) πŸŽ€

okay so this one is giving "it worked, but not exactly how you asked" πŸ’… It's a successful Print-Job response to a request like the last one, except this time "ipp-attribute-fidelity" is 'false' 🫢 The print request still succeeds even though the Printer supports neither the "sides" attribute nor the value '20' for "copies" 😭 So a Job gets created, and you get back both a "job-id" and a "job-uri" operation attribute πŸ¦‹ The unsupported attributes show up in an Unsupported Attributes group too. The error code is 'successful-ok-ignored-or-substituted-attributes' (0x0001) ✨

Octets                     Symbolic Value              Protocol field

0x0101                     1.1                         version-number
0x0001                     successful-ok-ignored-or-   status-code
                           substituted-attributes
0x00000001                 1                           request-id
0x01                       start operation-attributes  operation-
                                                       attributes-tag
0x47                       charset type                value-tag
0x0012                                                 name-length
attributes-charset         attributes-charset          name
0x0005                                                 value-length
utf-8                      UTF-8                       value
0x48                       natural-language type       value-tag
0x001b                                                 name-length
attributes-natural-        attributes-natural-language name
language
0x0005                                                 value-length
en-us                      en-US                       value
0x41                       textWithoutLanguage type    value-tag
0x000e                                                 name-length
status-message             status-message              name
0x002f                                                 value-length
successful-ok-ignored-or-  successful-ok-ignored-or-   value
substituted-attributes     substituted-attributes
0x05                       start unsupported-          unsupported-
                           attributes                  attributes tag
0x21                       integer type                value-tag
0x0006                                                 name-length
copies                     copies                      name
0x0004                                                 value-length
0x00000014                 20                          value
0x10                       unsupported  (type)         value-tag
0x0005                                                 name-length
sides                      sides                       name
0x0000                                                 value-length
0x02                       start job-attributes        job-
                                                       attributes-tag
0x21                       integer                     value-tag
0x0006                                                 name-length
job-id                     job-id                      name
0x0004                                                 value-length
147                        147                         value
0x45                       uri type                    value-tag
0x0007                                                 name-length
job-uri                    job-uri                     name
0x0030                                                 value-length
ipp://printer.example.com/ job 147 on pinetree         value
ipp/print/pinetree/147
0x23                       enum  type                  value-tag
0x0009                                                 name-length
job-state                  job-state                   name
0x0004                                                 value-length
0x0003                     pending                     value
0x03                       end-of-attributes           end-of-
                                                       attributes-tag

A.5. Print-URI Request 🌈

okay, the Print-URI request is so cute 🧚 This example sends the "copies" and "job-name" parameters along with the request ✨

Octets                         Symbolic Value       Protocol field

0x0101                         1.1                  version-number
0x0003                         Print-URI            operation-id
0x00000001                     1                    request-id
0x01                           start operation-     operation-
                               attributes           attributes-tag
0x47                           charset type         value-tag
0x0012                                              name-length
attributes-charset             attributes-charset   name
0x0005                                              value-length
utf-8                          UTF-8                value
0x48                           natural-language     value-tag
                               type
0x001b                                              name-length
attributes-natural-language    attributes-natural-  name
                               language
0x0005                                              value-length
en-us                          en-US                value
0x45                           uri type             value-tag
0x000b                                              name-length
printer-uri                    printer-uri          name
0x002c                                              value-length
ipp://printer.example.com/ipp/ printer pinetree     value
print/pinetree
0x45                           uri type             value-tag
0x000c                                              name-length
document-uri                   document-uri         name
0x0019                                              value-length
ftp://foo.example.com/foo      ftp://foo.example.co value
                               m/foo
0x42                           nameWithoutLanguage  value-tag
                               type
0x0008                                              name-length
job-name                       job-name             name
0x0006                                              value-length
foobar                         foobar               value
0x02                           start job-attributes job-attributes-
                                                    tag
0x21                           integer type         value-tag
0x0006                                              name-length
copies                         copies               name
0x0004                                              value-length
0x00000001                     1                    value
0x03                           end-of-attributes    end-of-
                                                    attributes-tag

A.6. Create-Job Request πŸ¦‹

this one is the minimalist era 🫢 It's a Create-Job request with no parameters and no attributes, just the bare minimum πŸ’–

Octets                         Symbolic Value       Protocol field

0x0101                         1.1                  version-number
0x0005                         Create-Job           operation-id
0x00000001                     1                    request-id
0x01                           start operation-     operation-
                               attributes           attributes-tag
0x47                           charset type         value-tag
0x0012                                              name-length
attributes-charset             attributes-charset   name
0x0005                                              value-length
utf-8                          UTF-8                value
0x48                           natural-language     value-tag
                               type
0x001b                                              name-length
attributes-natural-language    attributes-natural-  name
                               language
0x0005                                              value-length
en-us                          en-US                value
0x45                           uri type             value-tag
0x000b                                              name-length
printer-uri                    printer-uri          name
0x002c                                              value-length
ipp://printer.example.com/ipp/ printer pinetree     value
print/pinetree
0x03                           end-of-attributes    end-of-
                                                    attributes-tag

A.7. Create-Job Request with Collection Attributes ✨

okay so this one is where things get spicy 🌢️ we're sending a Create-Job request that carries the media-col collection attribute [PWG5100.3], and its value is media-size={x-dimension=21000 y-dimension=29700} media-type='stationery' πŸ“„ the collection is basically a little box of named members sitting inside one attribute, and the bytes show exactly how that box gets packed up πŸŽ€

   Octets                         Symbolic Value       Protocol field

   0x0101                         1.1                  version-number
   0x0005                         Create-Job           operation-id
   0x00000001                     1                    request-id
   0x01                           start operation-     operation-
                                  attributes           attributes-tag
   0x47                           charset type         value-tag
   0x0012                                              name-length
   attributes-charset             attributes-charset   name
   0x0005                                              value-length
   utf-8                          UTF-8                value
   0x48                           natural-language     value-tag
                                  type
   0x001b                                              name-length
   attributes-natural-language    attributes-natural-  name
                                  language
   0x0005                                              value-length
   en-us                          en-US                value
   0x45                           uri type             value-tag
   0x000b                                              name-length
   printer-uri                    printer-uri          name
   0x002c                                              value-length
   ipp://printer.example.com/ipp/ printer pinetree     value
   print/pinetree
   0x34                           begCollection        value-tag
   0x0009                         9                    name-length
   media-col                      media-col            name
   0x0000                         0                    value-length
   0x4a                           memberAttrName       value-tag
   0x0000                         0                    name-length
   0x000a                         10                   value-length
   media-size                     media-size           value (member-
                                                       name)
   0x34                           begCollection        member-value-tag
   0x0000                         0                    name-length
   0x0000                         0                    member-value-
                                                       length
   0x4a                           memberAttrName       value-tag
   0x0000                         0                    name-length
   0x000b                         11                   value-length
   x-dimension                    x-dimension          value (member-
                                                       name)
   0x21                           integer              member-value-tag
   0x0000                         0                    name-length
   0x0004                         4                    member-value-
                                                       length
   0x00005208                     21000                member-value
   0x4a                           memberAttrName       value-tag
   0x0000                         0                    name-length
   0x000b                         11                   value-length
   y-dimension                    y-dimension          value (member-
                                                       name)

   0x21                           integer              member-value-tag
   0x0000                         0                    name-length
   0x0004                         4                    member-value-
                                                       length
   0x00007404                     29700                member-value
   0x37                           endCollection        end-value-tag
   0x0000                         0                    end-name-length
   0x0000                         0                    end-value-length
   0x4a                           memberAttrName       value-tag
   0x0000                         0                    name-length
   0x000a                         10                   value-length
   media-type                     media-type           value (member-
                                                       name)
   0x44                           keyword              member-value-tag
   0x0000                         0                    name-length
   0x000a                         10                   member-value-
                                                       length
   stationery                     stationery           member-value
   0x37                           endCollection        end-value-tag
   0x0000                         0                    end-name-length
   0x0000                         0                    end-value-length
   0x03                           end-of-attributes    end-of-
                                                       attributes-tag

A.8. Get-Jobs Request 🧚

this one is a chill vibe 🌸 it's a Get-Jobs request that has parameters but no attributes, so there's no collection drama here, just a clean little ask πŸ’… the limit is 50, and we're requesting job-id, job-name, and document-format back

    Octets                         Symbolic Value       Protocol field

    0x0101                         1.1                  version-number
    0x000a                         Get-Jobs             operation-id
    0x0000007b                     123                  request-id
    0x01                           start operation-     operation-
                                   attributes           attributes-tag
    0x47                           charset type         value-tag
    0x0012                                              name-length
    attributes-charset             attributes-charset   name
    0x0005                                              value-length
    utf-8                          UTF-8                value
    0x48                           natural-language     value-tag
                                   type
    0x001b                                              name-length
    attributes-natural-language    attributes-natural-  name
                                   language
    0x0005                                              value-length
    en-us                          en-US                value
    0x45                           uri type             value-tag
    0x000b                                              name-length
    printer-uri                    printer-uri          name
    0x002c                                              value-length
    ipp://printer.example.com/ipp/ printer pinetree     value
    print/pinetree
    0x21                           integer type         value-tag
    0x0005                                              name-length
    limit                          limit                name
    0x0004                                              value-length
    0x00000032                     50                   value
    0x44                           keyword type         value-tag
    0x0014                                              name-length
    requested-attributes           requested-attributes name
    0x0006                                              value-length
    job-id                         job-id               value
    0x44                           keyword type         value-tag
    0x0000                         additional value     name-length
    0x0008                                              value-length
    job-name                       job-name             value
    0x44                           keyword type         value-tag
    0x0000                         additional value     name-length
    0x000f                                              value-length
    document-format                document-format      value
    0x03                           end-of-attributes    end-of-
                                                        attributes-tag

A.9. Get-Jobs Response πŸŽ€

ok the response to that last request is where we get to see the Printer's answer πŸ‘‘ this one comes back with three Jobs, but the Printer keeps the second Job's details to itself (because of security reasons πŸ”’) so you'll notice that object is just an empty start with no details inside

   Octets                  Symbolic Value          Protocol field

   0x0101                  1.1                     version-number
   0x0000                  successful-ok           status-code
   0x0000007b              123                     request-id (echoed
                                                   back)
   0x01                    start operation-        operation-attributes-
                           attributes              tag
   0x47                    charset type            value-tag
   0x0012                                          name-length
   attributes-charset      attributes-charset      name
   0x0005                                          value-length
   utf-8                   UTF-8                   value
   0x48                    natural-language type   value-tag
   0x001b                                          name-length
   attributes-natural-     attributes-natural-     name
   language                language
   0x0005                                          value-length
   en-us                   en-US                   value
   0x41                    textWithoutLanguage     value-tag
                           type
   0x000e                                          name-length
   status-message          status-message          name
   0x000d                                          value-length
   successful-ok           successful-ok           value
   0x02                    start job-attributes    job-attributes-tag
                           (1st  object)
   0x21                    integer type            value-tag
   0x0006                                          name-length
   job-id                  job-id                  name
   0x0004                                          value-length
   147                     147                     value
   0x36                    nameWithLanguage        value-tag
   0x0008                                          name-length
   job-name                job-name                name
   0x000c                                          value-length
   0x0005                                          sub-value-length
   fr-ca                   fr-CA                   value
   0x0003                                          sub-value-length
   fou                     fou                     name
   0x02                    start job-attributes    job-attributes-tag
                           (2nd object)
   0x02                    start job-attributes    job-attributes-tag
                           (3rd object)
   0x21                    integer type            value-tag
   0x0006                                          name-length
   job-id                  job-id                  name
   0x0004                                          value-length
   148                     149                     value
   0x36                    nameWithLanguage        value-tag
   0x0008                                          name-length
   job-name                job-name                name
   0x0012                                          value-length
   0x0005                                          sub-value-length
   de-CH                   de-CH                   value
   0x0009                                          sub-value-length
   isch guet               isch guet               name
   0x03                    end-of-attributes       end-of-attributes-tag

Acknowledgements 🫢

okay bestie, the authors wanted to give a massive shoutout to the people who helped build the original IPP/1.1 specs πŸ’– that's Sylvan Butler, Roger deBry, Tom Hastings, Robert Herriot (the original editor of RFC 2910 πŸ™Œ), Paul Moore, Kirk Ocke, Randy Turner, John Wenn, and Peter Zehler. the whole squad deserves flowers πŸ’βœ¨

Authors' Addresses πŸ¦‹

these are the two authors who wrote this one, so here's where you can find them πŸ’…

Michael Sweet Apple Inc. 1 Infinite Loop MS 111-HOMC Cupertino, CA 95014 United States of America

Email: msweet@apple.com

Ira McDonald High North, Inc. PO Box 221 Grand Marais, MI 49839 United States of America

Phone: +1 906-494-2434 Email: blueroofmusic@gmail.com

that's the whole doc, babe 🌈✨ you made it through all 11 parts πŸ‘‘

πŸ“¦ where this page comes from