RFC 4037

Open Pluggable Edge Services (OPES) Callout Protocol (OCP) Core

๐Ÿ“… published March 2005, from ietf

RFC 4037: Open Pluggable Edge Services (OPES) Callout Protocol (OCP) Core ๐ŸŽ€

Okay bestie, let's get into RFC 4037 ๐Ÿ’… First the paperwork ๐Ÿ“‹ It's titled Open Pluggable Edge Services (OPES) Callout Protocol (OCP) Core, written by A. Rousskov from The Measurement Factory, filed as a Standards Track document, and dated March 2005 ๐Ÿฆ‹ The header doesn't list anything it obsoletes or updates, so there's no drama there โœจ

Status of This Memo ๐Ÿ“ฃ

Okay so this document is an Internet standards track protocol spec for the Internet community, and it's basically asking everyone to talk about it and suggest improvements ๐Ÿ’ฌ If you want to know where this protocol stands in standardization, check the current edition of "Internet Official Protocol Standards" (STD 1) ๐Ÿ“š And the distribution of this memo is unlimited, so share away ๐Ÿ’–

Copyright (C) The Internet Society (2005).

Abstract ๐ŸŒธ

Okay this part is the big-picture tea โ˜• This document defines the core of the Open Pluggable Edge Services (OPES) Callout Protocol (OCP). OCP is how application messages get passed along from other communication protocols. An OPES intermediary sends the original application messages to a callout server, and the callout server sends adapted application messages back to the processor ๐Ÿ” It was built with typical adaptation jobs in mind, like virus and spam management, language and format translation, message anonymization, or advertisement manipulation ๐Ÿ™ˆ The OCP Core is the part that's application-agnostic, meaning it holds the mechanisms you need for efficient support of those typical adaptations. It's giving foundation energy ๐Ÿงฑโœจ

Table of Contents ๐Ÿ“‘

   1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  3
       1.1.  Scope  . . . . . . . . . . . . . . . . . . . . . . . . .  4
       1.2.  OPES Document Map  . . . . . . . . . . . . . . . . . . .  5
       1.3.  Terminology  . . . . . . . . . . . . . . . . . . . . . .  6
   2.  Overall Operation  . . . . . . . . . . . . . . . . . . . . . .  7
       2.1.  Initialization . . . . . . . . . . . . . . . . . . . . .  7
       2.2.  Original Dataflow  . . . . . . . . . . . . . . . . . . .  8
       2.3.  Adapted Dataflow . . . . . . . . . . . . . . . . . . . .  8
       2.4.  Multiple Application Messages  . . . . . . . . . . . . .  9
       2.5.  Termination  . . . . . . . . . . . . . . . . . . . . . .  9
       2.6.  Message Exchange Patterns  . . . . . . . . . . . . . . .  9
       2.7.  Timeouts . . . . . . . . . . . . . . . . . . . . . . . . 10
       2.8.  Environment  . . . . . . . . . . . . . . . . . . . . . . 11
   3.  Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

       3.1.  Message Format . . . . . . . . . . . . . . . . . . . . . 12
       3.2.  Message Rendering  . . . . . . . . . . . . . . . . . . . 13
       3.3.  Message Examples . . . . . . . . . . . . . . . . . . . . 14
       3.4.  Message Names  . . . . . . . . . . . . . . . . . . . . . 15
   4.  Transactions . . . . . . . . . . . . . . . . . . . . . . . . . 15
   5.  Invalid Input  . . . . . . . . . . . . . . . . . . . . . . . . 16
   6.  Negotiation  . . . . . . . . . . . . . . . . . . . . . . . . . 16
       6.1.  Negotiation Phase  . . . . . . . . . . . . . . . . . . . 17
       6.2.  Negotiation Examples . . . . . . . . . . . . . . . . . . 18
   7.  'Data Preservation' Optimization . . . . . . . . . . . . . . . 20
   8.  'Premature Dataflow Termination' Optimizations . . . . . . . . 21
       8.1.  Original Dataflow  . . . . . . . . . . . . . . . . . . . 22
       8.2.  Adapted Dataflow . . . . . . . . . . . . . . . . . . . . 23
       8.3.  Getting Out of the Loop  . . . . . . . . . . . . . . . . 24
   9.  Protocol Element Type Declaration Mnemonic (PETDM) . . . . . . 25
       9.1     Optional Parameters  . . . . . . . . . . . . . . . . . 27
   10. Message Parameter Types  . . . . . . . . . . . . . . . . . . . 28
       10.1.   uri. . . . . . . . . . . . . . . . . . . . . . . . . . 28
       10.2.   uni. . . . . . . . . . . . . . . . . . . . . . . . . . 28
       10.3.   size . . . . . . . . . . . . . . . . . . . . . . . . . 29
       10.4.   offset . . . . . . . . . . . . . . . . . . . . . . . . 29
       10.5.   percent  . . . . . . . . . . . . . . . . . . . . . . . 29
       10.6.   boolean. . . . . . . . . . . . . . . . . . . . . . . . 30
       10.7.   xid .  . . . . . . . . . . . . . . . . . . . . . . . . 30
       10.8.   sg-id. . . . . . . . . . . . . . . . . . . . . . . . . 30
       10.9.   modp. . . . . . . . . . . . . . . . . . . . . . . . .  30
       10.10.  result. . . . . . . . . . . . . . . . . . . . . . . .  30
       10.11.  feature . . . . . . . . . . . . . . . . . . . . . . .  32
       10.12.  features. . . . . . . . . . . . . . . . . . . . . . .  32
       10.13.  service . . . . . . . . . . . . . . . . . . . . . . .  32
       10.14.  services. . . . . . . . . . . . . . . . . . . . . . .  33
       10.15.  Dataflow Specializations. . . . . . . . . . . . . . .  33
   11. Message Definitions . . . . . . . . . . . . . . . . . . . . .  33
       11.1.   Connection Start (CS) . . . . . . . . . . . . . . . .  34
       11.2.   Connection End (CE) . . . . . . . . . . . . . . . . .  35
       11.3.   Service Group Created (SGC) . . . . . . . . . . . . .  35
       11.4.   Service Group Destroyed (SGD) . . . . . . . . . . . .  36
       11.5.   Transaction Start (TS). . . . . . . . . . . . . . . .  36
       11.6.   Transaction End (TE). . . . . . . . . . . . . . . . .  36
       11.7.   Application Message Start (AMS) . . . . . . . . . . .  37
       11.8.   Application Message End (AME) . . . . . . . . . . . .  37
       11.9.   Data Use Mine (DUM) . . . . . . . . . . . . . . . . .  38
       11.10.  Data Use Yours (DUY). . . . . . . . . . . . . . . . .  39
       11.11.  Data Preservation Interest (DPI). . . . . . . . . . .  39
       11.12.  Want Stop Receiving Data (DWSR) . . . . . . . . . . .  40
       11.13.  Want Stop Sending Data (DWSS) . . . . . . . . . . . .  41
       11.14.  Stop Sending Data (DSS) . . . . . . . . . . . . . . .  41
       11.15.  Want Data Paused (DWP). . . . . . . . . . . . . . . .  42
       11.16.  Paused My Data (DPM). . . . . . . . . . . . . . . . .  43
       11.17.  Want More Data (DWM). . . . . . . . . . . . . . . . .  43
       11.18.  Negotiation Offer (NO). . . . . . . . . . . . . . . .  44
       11.19.  Negotiation Response (NR) . . . . . . . . . . . . . .  45
       11.20.  Ability Query (AQ). . . . . . . . . . . . . . . . . .  46
       11.21.  Ability Answer (AA) . . . . . . . . . . . . . . . . .  46
       11.22.  Progress Query (PQ) . . . . . . . . . . . . . . . . .  47
       11.23.  Progress Answer (PA). . . . . . . . . . . . . . . . .  47
       11.24.  Progress Report (PR). . . . . . . . . . . . . . . . .  48
   12. IAB Considerations  . . . . . . . . . . . . . . . . . . . . .  48
   13. Security Considerations . . . . . . . . . . . . . . . . . . .  48
   14. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  50
   15. Compliance  . . . . . . . . . . . . . . . . . . . . . . . . .  50
       15.1.  Extending OCP Core . . . . . . . . . . . . . . . . . .  51
   A.  Message Summary . . . . . . . . . . . . . . . . . . . . . . .  52
   B.  State Summary   . . . . . . . . . . . . . . . . . . . . . . .  53
   C.  Acknowledgements  . . . . . . . . . . . . . . . . . . . . . .  54
   16. References  . . . . . . . . . . . . . . . . . . . . . . . . .  54
       16.1.  Normative References . . . . . . . . . . . . . . . . .  54
       16.2.  Informative References . . . . . . . . . . . . . . . .  54
   Author's Address. . . . . . . . . . . . . . . . . . . . . . . . .  55
   Full Copyright Statement. . . . . . . . . . . . . . . . . . . . .  56

1. Introduction ๐Ÿฆ‹

Okay so the Open Pluggable Edge Services (OPES) architecture [RFC3835] is all about cooperative application services, called OPES services ๐Ÿค These happen between a data provider, a data consumer, and zero or more OPES processors. The services analyze application-level messages going between the data provider and the data consumer, and they might even transform them ๐Ÿ”ง

The OPES processor can hand off the work of running a service by talking to callout servers ๐Ÿ“ž As [RFC3836] describes, an OPES processor invokes and talks to services on a callout server using an OPES callout protocol (OCP) ๐Ÿ’Œ This document defines the core of that protocol, which we call "OCP Core" ๐Ÿ’œ

The OCP Core spec covers general, application-independent protocol mechanisms ๐ŸŒˆ Separate documents handle the application-specific bits of OCP. For example, "HTTP Adaptation with OPES" [OPES-HTTP] explains, in part, how HTTP messages and HTTP meta-information can be carried over OCP ๐ŸŒธ

Section 1.2 gives you a quick tour of the whole OPES document collection, including the documents on OPES use cases and security threats ๐Ÿงš

1.1. Scope

okay so the OCP Core spec is the bit that explains how OCP agents behave and what OCP extensions have to do ๐Ÿ’… It does NOT get into the rules for specific application protocols that are being adapted. Those belong somewhere else, bestie ๐ŸŽ€

An OPES processor is basically an application proxy. It either proxies one application protocol or converts from one application protocol to another ๐Ÿฆ‹ At the same time, the processor can be an OCP client too, using OCP to get proxied messages adapted at callout servers. So it's super tempting to assume the processor takes the application messages it's proxying, sends them over OCP to callout servers, and then puts the adapted results back on the wire โœจ But that assumption means OCP is applied directly to the application messages, and that isn't always what's happening ๐Ÿ™ˆ

      OPES processor scope                         callout server scope
      +-----------------+                           +-----------------+
      | pre-processing  |         OCP scope         |                 |
      |            +- - - - - - - - - - - - - - - - - - -+            |
      | iteration  |     <== ( application data ) ==>    | adaptation |
      |            +- - - - - - - - - - - - - - - - - - -+            |
      | post-processing |                           |                 |
      +-----------------+                           +-----------------+

An OPES processor can preprocess (or postprocess) proxied application messages before (or after) they get adapted at callout servers ๐ŸŒธ For example, a processor might take an HTTP response it's proxying and pass it along as-is, together with metadata about the matching HTTP connection. Another processor might take an HTTP response, pull out the body, and pass that body along with the content-encoding metadata ๐Ÿ’œ And to get adaptation done, the OPES processor might run several callout services, iterating over several callout servers ๐Ÿ”ฅ All that preprocessing, postprocessing, and iterating means you can't count on any specific relationship between the application messages being proxied and the application messages being sent to a callout service. Also, the specific adaptation actions at the callout server are totally outside OCP Core scope ๐Ÿ™…โ€โ™€๏ธ

This spec doesn't define or require any specific relationship between the application messages the OPES processor proxies and the application messages it swaps with a callout server over OCP โœจ The processor usually sets up some mapping between those application messages, but what it actually does is beyond OCP scope. So basically, this spec isn't concerned with the OPES processor as an application proxy or as an iterator of callout services ๐Ÿ’… OCP Core is all about communication between one OPES processor and one callout server, period ๐ŸŽ€

Also, an OPES processor gets to choose which proxied application messages (or info about them) go over OCP ๐Ÿฆ‹ Literally any of these is allowed: all proxied messages on all proxied connections (if connections are even defined for that application protocol), everything on some connections, selected proxied messages, or nothing at all. OPES processor and callout server state related to proxied protocols can be relayed over OCP as application message metadata too ๐Ÿงš

1.2. OPES Document Map

okay this doc is part of a big family of OPES specs from the IETF OPES Working Group ๐ŸŒˆ You kind of need to know the overall OPES approach and typical scenarios to understand any single OPES doc on its own, so this section is basically an index to help you find any "missing" info ๐Ÿซถ

  • "OPES Use Cases and Deployment Scenarios" [RFC3752] describes a set of services and applications that count as in scope for OPES. They were used as motivation and guidance when designing the OPES architecture โœจ
  • The OPES architecture and common terminology are described in "An Architecture for Open Pluggable Edge Services (OPES)" [RFC3835] ๐Ÿ’–
  • "Policy, Authorization, and Enforcement Requirements of OPES" [RFC3838] lays out requirements and assumptions for the policy framework, but it doesn't pick concrete authorization and enforcement methods ๐Ÿ”ฅ
  • "Security Threats and Risks for OPES" [RFC3837] gives the OPES risk analysis, without recommending specific solutions ๐Ÿ˜ญ
  • "OPES Treatment of IAB Considerations" [RFC3914] covers all the architecture-level considerations the IETF Internet Architecture Board (IAB) raised when the OPES WG was chartered ๐Ÿ‘‘
  • At the heart of the OPES architecture are the OPES processor and the callout server. They're two network elements that talk to each other through an OPES Callout Protocol (OCP) ๐Ÿฆ‹ The requirements for that protocol are discussed in "Requirements for OPES Callout Protocols" [RFC3836] โœจ
  • This document specifies an application agnostic protocol core for communication between an OPES processor and a callout server ๐Ÿ’…
  • "OPES Entities and End Points Communications" [RFC3897] specifies generic tracing and bypass mechanisms for OPES ๐ŸŽ€
  • The OCP Core and communications docs are independent from the application protocol being adapted by OPES entities ๐ŸŒธ Their generic mechanisms have to be complemented by application-specific profiles. "HTTP Adaptation with OPES" [OPES-HTTP] is one of those application profiles, for HTTP. It specifies how the application-agnostic OPES mechanisms get used and augmented so HTTP messages can be adapted ๐Ÿ’œ
  • Finally, "P: Message Processing Language" [OPES-RULES] defines a language for specifying which OPES adaptations (e.g., translation) must be applied to which application messages (e.g., e-mail from bob@example.com). The P language is meant for configuring application proxies (OPES processors) ๐Ÿงš

1.3. Terminology

bestie, this part matters ๐Ÿซถ The keywords "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]. When they're used with their normative meanings, these keywords will be all uppercase. Lowercase versions of these words are just normal prose, with no normative implications ๐Ÿ”ฅ

Here's the deal with the vocab: the OPES processor works with messages from application protocols and may relay info about those application messages to a callout server. OCP is also an application protocol ๐ŸŒˆ So protocol elements like "message", "connection", or "transaction" exist in OCP and in other application protocols too. In this spec, any reference to elements from application protocols other than OCP gets an explicit "application" qualifier. References without the "application" qualifier refer to OCP elements โœจ

  • OCP message: A basic unit of communication between an OPES processor and a callout server. The message is a sequence of octets formatted according to syntax rules (section 3.1). Message semantics are defined in section 11. ๐Ÿ’–
  • application message: An entity defined by negotiation between the OPES processor and the callout server. Usually the negotiated definition matches the definition from an application protocol (e.g., the [RFC2616] definition of an HTTP message) ๐Ÿฆ‹
  • application message data: An opaque sequence of octets representing a complete or partial application message. OCP Core doesn't distinguish application message structures (if there are any). Application message data may be empty ๐ŸŒธ
  • data: Same as application message data ๐Ÿ’…
  • original: Refers to an application message flowing from the OPES processor to a callout server ๐ŸŽ€
  • adapted: Refers to an application message flowing from an OPES callout server to the OPES processor ๐Ÿงš
  • adaptation: Any kind of access by a callout server, including modification, generation, and copying. For example, translating or logging an SMTP message is adaptation of that application message ๐Ÿ”ฅ
  • agent: The actor for a given communication protocol. The OPES processor and callout server are OCP agents. An agent can be referred to as a sender or receiver, depending on what it's doing in a particular context ๐Ÿ‘‘
  • immediate: Performing the specified action before reacting to new incoming messages or sending any new messages unrelated to the specified action โœจ
  • OCP extension: A specification that extends or adjusts this document for adaptation of an application protocol (a.k.a. application profile; e.g., [OPES-HTTP]), new OCP functionality (e.g., transport encryption and authentication), and/or a new OCP Core version ๐Ÿ’œ

2. Overall Operation โœจ

the OPES processor can use the OPES callout protocol (OCP) to talk to callout servers ๐Ÿฆ‹ Adaptation using callout services is sometimes called "bump in the wire" architecture ๐Ÿ’…

2.1. Initialization

the OPES processor sets up transport connections with callout servers so it can swap application messages with them over OCP ๐ŸŒธ Once a transport-layer connection (usually TCP/IP) is up, the communicating OCP agents exchange Connection Start (CS) messages ๐Ÿ’– After that, OCP features can be negotiated between the processor and the callout server (see section 6). For example, OCP agents might negotiate transport encryption and application message definition ๐Ÿงš

Once enough settings are negotiated, the OCP agents can start exchanging application messages โœจ

OCP Core provides negotiation and other mechanisms so agents can encrypt OCP connections and authenticate each other ๐Ÿ” OCP Core doesn't require OCP connection encryption or agent authentication ๐Ÿ™…โ€โ™€๏ธ Application profiles and other OCP extensions may document and/or require these and other security mechanisms. OCP is expected to be used, partly, in closed environments where trust and privacy are established by means outside OCP ๐Ÿซถ Implementations are expected to demand the security features they need through the OCP Core negotiation mechanism, depending on agent configuration and environment ๐Ÿ‘‘

2.2. Original Dataflow

when the OPES processor wants to adapt an application message, it sends a Transaction Start (TS) message to kick off an OCP transaction dedicated to that application message ๐Ÿฆ‹ Then the processor sends an Application Message Start (AMS) message to get the callout server ready for the application data that's coming next โœจ Once the application message scope is set up, application data can be sent to the callout server using Data Use Mine (DUM) and related OCP message(s) ๐Ÿ”ฅ All of these messages make up the original dataflow ๐Ÿ’–

2.3. Adapted Dataflow

okay so the callout server gets the data and metadata that the OPES processor sends over (that's the original dataflow ๐ŸŒธ). It reads the metadata and adapts the data as it comes in ๐Ÿ’…. Usually the server builds its own version of the metadata and replies to the OPES processor with an Application Message Start (AMS) message โœจ. The adapted application message data can go next, using Data Use Mine (DUM) OCP message(s) ๐Ÿฆ‹. Then the application message gets announced as "completed" or "closed" with an Application Message End (AME) message. The transaction can be closed with a Transaction End (TE) message too ๐Ÿ’–. All of these messages make up the adapted data flow.

       +---------------+                             +-------+
       |     OPES      | == (original data flow) ==> |callout|
       |   processor   | <== (adapted data flow) === |server |
       +---------------+                             +-------+

The OPES processor receives the adapted application message that the callout server sent back ๐Ÿซถ. What the OPES processor does next with that message is outside the scope of this specification ๐Ÿ™ˆ.

2.4. Multiple Application Messages

OCP Core only gives you a transactions interface for swapping one original application message and one adapted application message ๐Ÿ’…. Some application protocols need several adapted versions of a single original message, or several original messages inside one OCP transaction ๐Ÿ‘‘. Picture one original e-mail that has to turn into several e-mails, with a custom message for each recipient ๐Ÿ’Œ.

OCP extensions MAY document mechanisms for exchanging multiple original and/or multiple adapted application messages within a single OCP transaction โœจ.

2.5. Termination

Either OCP agent can terminate application message delivery, a transaction, or a connection by sending an appropriate OCP message ๐Ÿ›‘. Usually it's the callout server that terminates adapted application message delivery and the transaction. Premature and abnormal terminations at arbitrary times are supported ๐Ÿ’€. The termination message includes a result description ๐Ÿ“.

2.6. Message Exchange Patterns

Besides messages carrying application data, OCP agents can also exchange messages about their configuration, state, transport connections, application connections, and so on ๐Ÿ’œ. A callout server may remove itself from the application message processing loop ๐Ÿฆ‹. One OPES processor can talk to many callout servers, and vice versa ๐Ÿ‘ฏ. Lots of OCP exchange patterns don't follow a classic client-server model, but it helps to think of an OPES processor as an "OCP client" and a callout server as an "OCP server" ๐ŸŽ€. The OPES architecture document [RFC3835] describes configuration possibilities.

The following informal rules show how connections, transactions, OCP messages, and application messages relate to each other ๐Ÿ”ฅ:

  • An OCP agent may communicate with multiple OCP agents. This is outside the scope of this specification.
  • An OPES processor may have multiple concurrent OCP connections to a callout server. Communication over multiple OCP connections is outside the scope of this specification.
  • A connection may carry multiple concurrent transactions. A transaction is always associated with a single connection (i.e., a transaction cannot span multiple concurrent connections).
  • A connection may carry at most one message at a time, including control messages and transaction-related messages. A message is always associated with a single connection (i.e., a message cannot span multiple concurrent connections).
  • A transaction is a sequence of messages related to application of a given set of callout services to a single application message.
    • A sequence of transaction messages from an OPES processor to a callout server is called original flow. A sequence of transaction messages from a callout server to an OPES processor is called adapted flow. The two flows may overlap in time.
  • In OCP Core, a transaction is associated with a single original and a single adapted application message. OCP Core extensions may extend transaction scope to more application messages.
  • An application message (adapted or original) is transferred by using a sequence of OCP messages.

2.7. Timeouts

OCP violations, resource limits, external dependencies, and other factors may leave an OCP agent stuck waiting for messages the other OCP agent isn't sending ๐Ÿ˜ญ. OCP Core doesn't define any messages to deal with such situations. Without any extension mechanism, OCP agents must implement timeouts for OCP operations ๐Ÿ’…. An OCP agent MUST forcefully terminate any OCP connection, negotiation, transaction, etc. that is not making progress. This rule covers both dead- and livelock situations ๐Ÿ’€.

In their implementation, OCP agents MAY rely on transport-level or other external timeouts if those external timeouts are guaranteed to happen for a given OCP operation ๐Ÿงš. Depending on the OCP operation, an agent may benefit from "pinging" the other side with a Progress Query (PQ) message before terminating an OCP transaction or connection ๐ŸŒˆ. The latter is especially useful for adaptations that may take a long time at the callout server before producing any adapted data.

2.8. Environment

OCP communication is usually assumed to take place over TCP/IP connections on the Internet, though no default TCP port is assigned to OCP in this specification ๐ŸŒ. That doesn't stop OCP from running on top of other transport protocols or on other networks ๐Ÿฆ‹. High-level transport protocols such as BEEP [RFC3080] may be used. OCP Core requires a reliable, message-order-preserving transport. Any protocol with those properties can be used; mapping OCP message structures onto the transport data units of that protocol is outside the scope of this specification ๐Ÿ’–.

OCP Core is application agnostic, meaning it doesn't care what the application is ๐Ÿ™ˆ. OCP messages can carry application-specific information either as a payload or as application-specific message parameters โœจ.

OCP Core overhead in terms of extra traffic on the wire is about 100 - 200 octets per small application message. Pipelining, preview, data preservation, and early termination optimizations, as well as as-is encapsulation of application data, make fast exchange of application messages possible ๐Ÿš€.

3. Messages โœจ

As defined in section 1.3, an OCP message is a basic unit of communication between an OPES processor and a callout server ๐Ÿ’Œ. A message is a sequence of octets formatted according to syntax rules (section 3.1). Message semantics is defined in section 11. Messages are transmitted on top of OCP transport ๐Ÿงš.

OCP messages deal with transport, transaction management, and application data exchange between a single OPES processor and a single callout server ๐ŸŽ€. Some messages can be emitted only by an OPES processor, some only by a callout server, and some by both ๐Ÿซถ. Some messages require responses (you could call these "requests"). Some can only be used in response to other messages ("responses"). Some may be sent without being asked for, and some may not require a response ๐Ÿฆ‹.

3.1. Message Format

An OCP message consists of a message name, followed by optional parameters and a payload ๐Ÿ’…. The exact message syntax is defined by the following Augmented Backus-Naur Form (ABNF) [RFC2234]:

message = name [SP anonym-parameters]
          [CRLF named-parameters CRLF]
          [CRLF payload CRLF]
          ";" CRLF

anonym-parameters = value *(SP value)               ; space-separated
named-parameters  = named-value *(CRLF named-value) ; CRLF-separated
list-items        = value *("," value)              ; comma-separated

payload = data

named-value = name ":" SP value

value     = structure / list / atom
structure = "{" [anonym-parameters] [CRLF named-parameters CRLF] "}"
list      = "(" [ list-items ] ")"
atom      = bare-value / quoted-value

name = ALPHA *safe-OCTET
bare-value = 1*safe-OCTET
quoted-value = DQUOTE data DQUOTE
data = size ":" *OCTET                   ; exactly size octets

safe-OCTET = ALPHA / DIGIT / "-" / "_"
size = dec-number                        ; 0-2147483647
dec-number = 1*DIGIT                     ; no leading zeros or signs

Several normative rules come with the ABNF above ๐Ÿง :

  • There is no "implied linear space" (LWS) rule. LWS rules are common to MIME-based grammars but are not used here. The whitespace syntax is restricted to what is explicitly allowed by the ABNF above.
  • All protocol elements are case sensitive unless it is specified otherwise. In particular, message names and parameter names are case sensitive.
  • Sizes are interpreted as decimal values and cannot have leading zeros.
  • Sizes do not exceed 2147483647.
  • The size attribute in a quoted-value encoding specifies the exact number of octets following the column (':') separator. If size octets are not followed by a quote ('"') character, the encoding is syntactically invalid.
  • Empty quoted values are encoded as a 4-octet sequence "0:".
  • Any bare value can be encoded as a quoted value. A quoted value is interpreted after the encoding is removed. For example, number 1234 can be encoded as four octets 1234 or as eight octets "4:1234", yielding exactly the same meaning.
  • Unicode UTF-8 is the default encoding. Note that ASCII is a UTF-8 subset, and that the syntax prohibits non-ASCII characters outside of the "data" element.

Messages violating formatting rules are, by definition, invalid. See section 5 for rules governing processing of invalid messages ๐Ÿ™…โ€โ™€๏ธ.

3.2. Message Rendering

OCP message samples in this specification and its extensions may not be typeset to depict minor syntactical details of OCP message format ๐Ÿ“. Specifically, SP and CRLF characters are not shown explicitly. No rendering of an OCP message can be used to infer message format. The message format definition above is the only normative source for all implementations ๐Ÿ’œ.

On occasion, an OCP message line exceeds the text width allowed by this specification format. A backslash (\), a "soft line break" character, is used to emphasize a protocol-violating presentation-only linebreak. Bare backslashes are prohibited by OCP syntax. Similarly, an "\r\n" string is sometimes used to emphasize the presence of a CRLF sequence, usually before OCP message payload. Normally, the visible end of line corresponds to the CRLF sequence on the wire ๐ŸŒธ.

The next section (section 3.3) contains specific OCP message examples, some of which illustrate the above rendering techniques โœจ.

3.3. Message Examples โœจ

okay so OCP syntax is literally so compact for short control messages ๐Ÿฅน you get the required parameters and you can still add extensions later. The required CRLF at the end of each line isn't shown here (see section 3.2), so just imagine it's there ๐ŸŽ€

PQ;
TS 1 2;
DWM 22;
DWP 22 16;
x-doit "5:xyzzy";

The examples above only use atomic anonymous parameter values, like number and string constants. OCP messages sometimes get more complicated, with item lists or structures that have named values. Both of these messages show that structures and lists can be nested, and it's giving matryoshka doll ๐Ÿช†

NO ({"32:http://www.iana.org/assignments/opes/ocp/tls"});
NO ({"54:http://www.iana.org/assignments/opes/ocp/http/response"
Optional-Parts: (request-header)
},{"54:http://www.iana.org/assignments/opes/ocp/http/response"
Optional-Parts: (request-header,request-body)
Transfer-Encodings: (chunked)
});

Optional parameters and extensions work with a named parameters approach too ๐Ÿฆ‹ In this one, the DWM message (section 11.17) has two anonymous parameters (the last one is an extension) and two named parameters (the last one is also an extension).

DWM 1 3
Size-Request: 16384
X-Need-Info: "26:twenty six octet extension";

And finally, any message can have a payload part ๐Ÿ’… The Data Use Mine (DUM) message below carries 8865 octets of raw data, which is a lot of data bestie ๐Ÿ˜ญ

DUM 1 13
Modp: 75
\r\n
8865:... 8865 octets of raw data ...;

3.4. Message Names

most OCP messages in this spec have short names ๐Ÿ“ They're made by shortening a longer, more human-friendly title. Short names that don't have a central registration system (like this spec or the IANA registry) are likely to cause conflicts, so informal protocol extensions should avoid short names ๐Ÿ™ˆ To make it clear that message syntax is what defines them, implementations cannot assume that every message name is very short. no shortcuts, no cap ๐Ÿงš

4. Transactions ๐ŸŒธ

An OCP transaction is a logical sequence of OCP messages that processes a single original application message. The processing can produce zero or more application messages, adapted from the original. A typical transaction has two message flows: one from the OPES processor to the callout server (sending the original application message), and one from the callout server back to the OPES processor (sending adapted application messages). How many application messages the callout server makes, and whether it actually changes the original application message, can depend on the requested callout service and other factors โœจ Either the OPES processor or the callout server can end the transaction by sending a matching message to the other side.

An OCP transaction starts with a Transaction Start (TS) message sent by the OPES processor. It ends with the first Transaction End (TE) message that's sent or received, whether that's explicit or implied, and either side can send a TE message. Zero or more OCP messages tied to the transaction can get exchanged in between ๐Ÿซถ The figure below shows one possible message sequence (the prefix "P" is for the OPES processor and the prefix "S" is for the callout server). Some message details are left out.

P: TS 10;
P: AMS 10 1;
   ... processor sending application data to the callout server
S: AMS 10 2;
   ... callout server sending application data to the processor
   ... processor sending application data to the callout server
P: AME 10 1 result;
S: AME 10 2 result;
P: TE 10 result;

5. Invalid Input ๐Ÿ’€

This spec has a lot of criteria for valid OCP messages and their parts, covering syntax rules, semantics requirements, and how things relate to agent state. In this context, "Invalid input" means messages or message parts that break at least one of the normative rules ๐Ÿ˜ค A message with an invalid part is, by definition, invalid. If OCP agent resources run out while an agent is parsing or interpreting a message, the agent MUST treat the corresponding OCP message as invalid.

Unless it's explicitly allowed to do otherwise, an OCP agent MUST terminate the transaction if it receives an invalid message with transaction scope, and MUST terminate the connection if it receives an invalid message with connection scope ๐Ÿšซ A terminating agent MUST use the result status code of 400, and it MAY specify termination cause information in the result status reason parameter (see section 10.10) ๐Ÿ’… If an OCP agent can't figure out the scope of an invalid message it received, the agent MUST treat the message as having connection scope. safety first bestie ๐Ÿซ 

OCP usually deals with optional but invasive application message manipulations, where correctness matters more than robustness ๐Ÿ”ฅ Failing to insert or remove some optional web page content is usually way less disturbing than corrupting (making unusable) the host page during that insertion or removal. Most OPES adaptations are high level, which makes it impossible to check whether they're correct automatically, especially if "robustness guesses" are involved.

6. Negotiation ๐Ÿฆ‹

The negotiation mechanism lets OCP agents agree on a mutually acceptable set of features. That covers optional and application-specific behavior, plus OCP extensions. For example, transport encryption, data format, and support for a new message can all be negotiated โœจ Negotiation implies intent to change behavior. If you want an agent to ask its counterpart about capabilities without changing that counterpart's behavior, that's a different mechanism: see the Ability Query (AQ) and Ability Answer (AA) message definitions.

Most negotiations need at least one round trip time of delay. In rare cases when the other side's response isn't needed immediately, the negotiation delay can be removed, with an inherent risk of an overly optimistic assumption about the negotiation response ๐Ÿ˜ฌ

A detected violation of the negotiation rules leads to OCP connection termination. This design cuts down on the number of negotiation scenarios that end in a deadlock when one of the agents isn't compliant ๐Ÿ™ƒ

Two core negotiation primitives are supported: negotiation offer and negotiation response. A Negotiation Offer (NO) message lets an agent specify a set of features, and the responder has to select at most one feature it prefers. The selection is sent using a Negotiation Response (NR) message. If the response is positive, both sides assume the selected feature is in effect immediately (see section 11.19 for details). If the response is negative, no behavioral changes are assumed. Either way, more offers may follow ๐ŸŒˆ

Negotiating OCP agents have to take into account features that were already negotiated (in other words, already enabled) ๐Ÿ‘‘ OCP agents MUST NOT make offers that would conflict with already negotiated features, and they MUST reject such offers. For example, an agent can't offer an HTTP application profile for a connection that already has an SMTP application profile enabled, since there'd be no way to resolve the conflict for a given transaction ๐Ÿ’€ Similarly, once TLSv1 connection encryption is negotiated, an agent must not offer and must reject offers for SSLv2 connection encryption (unless a negotiated feature explicitly allows changing the encryption scheme on the fly).

Either agent can send Negotiation Offer (NO) messages. OCP extensions that document negotiation MAY assign the initiator role to one of the agents, depending on the feature being negotiated ๐Ÿงš For example, negotiation of a transport security feature should be initiated by OPES processors, so you don't end up with both agents waiting around for the other one to make an offer ๐Ÿ™ˆ

Since either agent may make an offer, two "concurrent" offers can happen at the same time from the two communicating agents. Unmanaged concurrent offers may lead to a negotiation deadlock ๐Ÿ˜ญ By giving the OPES processor priority, the offer-handling rules (section 11.18) make sure that only one offer per OCP connection is honored at a time, and that the other concurrent offers get ignored by both agents. priority queue energy ๐Ÿ‘‘

6.1. Negotiation Phase ๐ŸŽ€

A Negotiation Phase is a mechanism that makes sure both agents get a chance to negotiate all the features they need before going any further ๐Ÿ’– Negotiation Phases have OCP connection scope and they don't overlap. For each OCP agent, a Negotiation Phase starts with the first Negotiation Offer (NO) message received or the first Negotiation Response (NR) message sent, as long as that message isn't already part of an existing Phase. For each OCP agent, the Negotiation Phase ends with the first Negotiation Response (NR) message (sent or received), after which the agent doesn't expect any more negotiations. The agent expectation rules are defined later in this section โœจ

During a Negotiation Phase, an OCP agent MUST NOT send messages other than these "Negotiation Phase messages": Negotiation Offer (NO), Negotiation Response (NR), Ability Query (AQ), Ability Answer (AA), Progress Query (PQ), Progress Answer (PA), Progress Report (PR), and Connection End (CE). no sneaking in other messages ๐Ÿคซ

Multiple Negotiation Phases can happen during the lifespan of a single OCP connection. An agent may try to start a new Negotiation Phase right after the old one is over, but the other agent might send messages that aren't "Negotiation Phase messages" before it receives the new Negotiation Offer (NO). So the agent that starts a Phase has to be ready to handle those messages while its offer is on the way ๐ŸŒธ

An OPES processor MUST make a negotiation offer immediately after sending a Connection Start (CS) message. If the OPES processor has nothing to negotiate, it MUST send a Negotiation Offer (NO) message with an empty features list. These two rules bootstrap the first Negotiation Phase ๐Ÿš€ Agents are expected to negotiate at least the application profile for OCP Core, so these bootstrapping requirements are unlikely to create any extra work, which is very iconic of them ๐Ÿ’…

Once a Negotiation Phase starts, an agent MUST expect further negotiations if and only if the last NO sent or the last NR received contained a true "Offer-Pending" parameter value. Informally, an agent can keep the phase open by sending true "Offer-Pending" parameters with negotiation offers or responses ๐Ÿฆ‹ And if there's any chance the agent may need to keep the Negotiation Phase going, the agent must send a true "Offer-Pending" parameter. it's giving planning ahead ๐Ÿซถ

6.2. Negotiation Examples โœจ

Okay so here's the simplest negotiation ever ๐Ÿ™ˆ The OPES processor offers nothing and, shocker, gets a rejection. Note that the NR message ends the Negotiation Phase here because neither message has a true "Offer-Pending" value ๐Ÿ’…

P: NO ();
S: NR;

Next up, a callout server forcing a feature the OPES processor never asked for ๐Ÿ‘€ The server sets "Offer-Pending" to true when it answers the processor's Negotiation Offer (NO) message, and the processor decides to accept the feature ๐Ÿซถ

P: NO ();
S: NR
   Offer-Pending: true
   ;
S: NO ({"22:ocp://feature/example/"})
   Offer-Pending: false
   ;
P: NR {"22:ocp://feature/example/"};

If the server wants to stop these negotiations after sending a true "Offer-Pending" value, its only option is to send an empty negotiation offer (see the first example). If it just does nothing, the OPES processor sits there waiting for the server and eventually times out the connection ๐Ÿ’€

The next one is a dialog with a callout server that is very insistent ๐Ÿ˜ค It wants two imaginary features enabled: strong transport encryption and volatile storage for responses. The server won't exchange sensitive messages until both are on, and volatile storage has to be negotiated securely, obviously. The OPES processor supports one of the strong encryption mechanisms but prefers not to offer it (not volunteer support for it), maybe for performance reasons. So the server has to send a true "Offer-Pending" parameter to get a chance to offer strong encryption, which works out in this case ๐ŸŽ€ After the (only) successful NR response, every message from either agent is encrypted with the "strongB" encryption scheme. The OPES processor doesn't understand the volatile storage feature, so the last negotiation fails (over a strongly encrypted transport connection) ๐Ÿ˜ญ

P: NO ({"29:ocp://example/encryption/weak"})
   ;
S: NR
   Offer-Pending: true
   ;
S: NO ({"32:ocp://example/encryption/strongA"},\
   {"32:ocp://example/encryption/strongB"})
   Offer-Pending: true
   ;
P: NR {"32:ocp://example/encryption/strongB"}
   ;
... all traffic below is encrypted using strongB ...

S: NO ({"31:ocp://example/storage/volatile"})
   Offer-Pending: false
   ;
P: NR
   Unknowns: ({"31:ocp://example/storage/volatile"})
   ;
S: CSE { 400 "33:lack of VolStore protocol support" }
   ;

Last one, straight from [OPES-HTTP], showing a successful HTTP application profile negotiation ๐ŸŒธ

P: NO ({"54:http://www.iana.org/assignments/opes/ocp/http/response"
   Aux-Parts: (request-header,request-body)
   })
   SG: 5;
S: NR {"54:http://www.iana.org/assignments/opes/ocp/http/response"
   Aux-Parts: (request-header)
   Pause-At-Body: 30
   Wont-Send-Body: 2147483647
   Content-Encodings: (gzip)
   }
   SG: 5;

7. 'Data Preservation' Optimization ๐Ÿงš

Lots of adaptations don't need to touch the data at all, like message logging or blocking ๐Ÿ’– Some only change a tiny bit of the content, like cookie filtering or ad insertion. But a lot of the time the callout service has to see the complete data. By default, unmodified data would travel from the OPES processor to the callout server and then all the way back ๐Ÿ˜ฉ The "data preservation" optimization in OCP helps kill that return trip if both OCP agents cooperate. And that cooperation is optional: OCP agents MAY support the data preservation optimization ๐Ÿซถ

For the callout service to skip sending data back, it has to know the OPES processor still has a copy. Data can be huge, though, and the callout service may not know ahead of time whether it'll even be able to use that copy. So it's not possible to require the processor to keep the entire original data. Instead, a processor may keep some portion of the data, depending on its settings and state ๐Ÿฆ‹

When an OPES processor commits to keeping a chunk, it announces the decision and the chunk parameters through a Kept parameter in a Data Use Mine (DUM) message ๐Ÿ“ฃ The callout server MAY "use" that chunk by sending a Data Use Yours (DUY) message that refers to the preserved chunk. That OCP message has no payload, so the return trip is gone โœจ

Here's the tricky part ๐Ÿ‘€ The processor doesn't know how original data maps to adapted data, so the processor MUST keep the announced-as-preserved chunk until the end of the corresponding transaction. The only exception is when the callout server explicitly says the chunk isn't needed anymore. Because of that, the processor can't assume a chunk is done just because the callout server sent a Data Use Yours (DUY) message, or adapted data with, say, the same offset as the preserved chunk ๐Ÿ™…โ€โ™€๏ธ

For simplicity, preserved data is always one contiguous chunk of original data, described by an (offset, size) pair using a "Kept" parameter of a Data Use Mine (DUM) message. An OPES processor may volunteer to increase the size of the kept data. And an OPES processor may increase the offset if the callout server indicated that the kept data is no longer needed ๐Ÿ’…

Both agents can benefit from data reuse, but only the processor has to allocate storage for it. The callout server doesn't ๐Ÿ˜ค On the flip side, the callout server is the one responsible for releasing the processor from its data preservation commitments. There's no simple way to fix that conflict of interest at the protocol level ๐Ÿ’€ Some processors may allocate a small buffer and stop preserving data once it's full, which works great for callout services that can reuse or drop kept data quickly. Another strategy is sizing the buffer based on historical reuse stats ๐Ÿ“Š To make this cooperation work better, callout servers are strongly encouraged to tell processors about unwanted data right away. A callout server that decides not to send Data Use Yours (DUY) messages (for specific data ranges, or at all) SHOULD immediately inform the OPES processor of that decision with the matching Data Preservation Interest (DPI) message(s) or other mechanisms ๐ŸŽ€


8. 'Premature Dataflow Termination' Optimizations ๐Ÿฆ‹

Plenty of callout services only adapt a small part of a huge message, and they'd honestly rather not be in the loop once that's done ๐Ÿ™Œ Some don't want to modify anything and would prefer not to send data back at all, even if the OPES processor doesn't support data preservation (Section 7). Here's the catch: if a callout server ends the dataflow early all on its own, the OCP transaction gets killed with an error ๐Ÿ’€ So the two agents have to cooperate to make early termination error-free ๐Ÿซถ

This section documents two mechanisms for ending original or adapted dataflow early. Used together, they let the callout server leave the processing loop completely ๐Ÿ‘‘

8.1. Original Dataflow ๐ŸŒˆ

Sometimes a callout server just doesn't care about the rest of the original dataflow ๐Ÿ™„ Take a simple access blocking or "this site is temporary down" service. It has to send an adapted (generated) application message, but it would rather not receive original data from the OPES processor at all.

OCP Core supports ending original dataflow early with the Want Stop Receiving Data (DWSR) message. If a callout server doesn't want any more original data (beyond a certain size), it sends a DWSR message. The OPES processor that gets a DWSR message ends the original dataflow by sending an Application Message End (AME) message with a 206 (partial) status code ๐Ÿ’–

Here's a typical sequence. The downward lines between the two dataflows show the transmission delay, which gives each agent time to send more OCP messages while it waits for the other side to react ๐Ÿงš

OPES                 Callout
Processor            Server
    DUM>             <DUM
    DUM>             <DWSR  <-- Server is ready to stop receiving
    ...        _____/<DUM   <-- Server continues as usual
    DUM>______/      <DUM
    AME>             ...    <-- Processor stops sending original data
        \_____       <DUM
              \______<DUM
                     <DUM   <-- Server continues to send adapted data
                     ...
                     <AME

This mechanism has no effect on the adapted dataflow. Getting an Application Message End (AME) message with a 206 (partial) result status code from the OPES processor doesn't add any special requirements for ending the adapted dataflow. But heads up: once the original dataflow has been ended early, you can't end the adapted dataflow early too (see section 8.3) ๐Ÿ™ˆ

8.2. Adapted Dataflow โœจ

okay so sometimes a callout service wants to bounce before the whole application message has been sent ๐Ÿฆ‹ like a logging-only callout service that needs every single app message but would rather NOT send copies back to the OPES processor ๐Ÿ“ (lowkey iconic behavior tbh)

OCP Core handles this early exit with two messages, Want Stop Sending Data (DWSS) and Stop Sending Data (DSS) ๐Ÿ’Œ. A callout service that wants to stop sending data sends a DWSS message to ask the OPES processor for permission to stop. While it waits for that permission, the server just keeps doing its usual thing ๐Ÿ’…

When an OPES processor gets a Want Stop Sending Data message, it responds with a Stop Sending Data (DSS) message ๐Ÿซถ After that, it can either pause and wait for the callout server to finish the adapted dataflow, or keep sending original data while making a copy of it. Once the server ends the adapted dataflow, the processor is responsible for using the original data (whether it was sent already or paused after the DSS) instead of the adapted data โœจ

When the callout server gets a DSS message, it terminates the adapted dataflow. The exact requirements and corner cases live in the Stop Sending Data (DSS) message definition, so go check there for the fine print ๐Ÿ“–

Here's a typical sequence of events. It includes a possible pause in the original dataflow while the OPES processor waits for the adapted dataflow to end. The downward lines connecting the two dataflows show the transmission delay, which lets more OCP messages get sent while an agent waits for the other agent to react ๐ŸŒธ

OPES                 Callout
Processor            Server
    DUM>             <DUM
    DUM>             <DWSS    <-- Server is ready to stop sending
    ...        _____/<DUM     <-- Server continues as usual,
    DUM>______/      <DUM         waiting for DSS
    DSS>             ...
        \_____       <DUM
  possible    \______<DUM
  org-dataflow       <AME 206 <-- Server terminates adapted dataflow
  pause        _____/             upon receiving the DSS message
        ______/
    DUM>                      <-- Processor resumes original dataflow
    DUM>                          to the server and starts using
    ...                           original data without adapting it
    AME>

Okay, the tricky part ๐Ÿฅบ Keeping the adapted dataflow alive is not trivial, because the OPES processor depends on the callout server to supply adapted data (modified or not) so it can build the adapted application message. If the callout server wants to quit its job, extra care is needed so the OPES processor can still construct the complete application message. Logically, this is the same as swapping one callout server for another callout server that does not modify anything, right in the middle of an OCP transaction ๐Ÿ”„

Apart from a possible pause in the original dataflow, this mechanism has no effect on the original dataflow. Getting an Application Message End (AME) message with a 206 (partial) result status code from the callout server doesn't add any special requirements for ending the original dataflow ๐Ÿ’–

8.3. Getting Out of the Loop ๐Ÿšช

Some adaptation services work on the prefixes of application messages, and they don't want to stay in the adaptation loop once their job is done ๐Ÿงš For example, an ad insertion service that already did its thing by modifying the first fragment of a web "page" has no reason to keep receiving original data or doing more adaptations. The 'Getting Out of the Loop' optimization lets a callout server leave the application message processing loop completely ๐Ÿ‘‘

The "Getting Out of the Loop" optimization works by terminating the adapted dataflow (section 8.2) first, and then terminating the original dataflow (section 8.1). The order matters A LOT ๐Ÿ˜ญ

If the original dataflow gets terminated first, the OPES processor won't allow the adapted dataflow to be terminated early. It wouldn't be able to rebuild the rest of the adapted application message, because it wouldn't know which suffix of the remaining original data should follow the adapted parts. The mapping between original and adapted octets is only known to the callout service ๐Ÿ™ˆ

An OPES processor that received a DWSS message followed by a DWSR message MUST NOT send an AME message with a 206 (partial) status code before sending a DSS message.

Informally, this rule means that a callout server that wants out of the loop quickly should send a DWSS message immediately followed by a DWSR message ๐Ÿƒโ€โ™€๏ธ The server doesn't have to wait for the OPES processor's permission to end the adapted dataflow before asking the processor to end the original dataflow โœจ


9. Protocol Element Type Declaration Mnemonic (PETDM) ๐ŸŽ€

A protocol element type is a named set of syntax and semantics rules ๐Ÿ“œ This section defines a simple, formal declaration mnemonic for protocol element types, called PETDM ๐Ÿ’œ PETDM is simple so type declarations stay easy in this specification, and it's formal so implementations interoperate better ๐Ÿซถ PETDM supports two kinds of protocol elements: message parameter values and messages.

All OCP Core parameter and message types are declared using PETDM. OCP extensions SHOULD use PETDM when they declare new types ๐Ÿ’…

Atom, list, structure, and message are the four base types ๐Ÿง Their syntax and semantics rules are defined in section 3.1. You can extend base types with new semantics by using the declaration templates below, and the new semantics rules get attached to each declaration in prose ๐Ÿ“

Text inside angle brackets "<>" is a template placeholder, to be swapped with actual type names or parameter name tokens. Square brackets "[]" wrap optional elements, like structure members or message payload ๐ŸŒˆ

Declaring a new atomic type:

<new-type-name>: extends atom;

Declaring a new list with old-type-name items:

<new-type-name>: extends list of <old-type-name>;

Unless it's explicitly noted otherwise, empty lists are valid and have the semantics of an absent parameter value ๐Ÿ™Œ

Declaring a new structure with members:

<new-type-name>: extends structure with {
        <old-type-nameA> <old-type-nameB> [<old-type-nameC>] ...;
        <member-name1>: <old-type-name1>;
        <member-name2>: <old-type-name2>;
        [<member-name3>: <old-type-name3>];
        ...
};

The new structure can have anonymous members and named members, and neither group has to exist. It's always possible for extensions to add more members to old structures without changing type semantics, because compliant agents ignore unrecognized members ๐Ÿฆ‹

Declaring a new message with parameters:

<new-type-name>: extends message with {
        <old-type-nameA> <old-type-nameB> [<old-type-nameC>] ...;
        <parameter-name1>: <old-type-name1>;
        <parameter-name2>: <old-type-name2>;
        [<parameter-name3>: <old-type-name3>];
        ...
};

The new type name becomes the message name. Just like when a structure is extended, the new message can have anonymous parameters and named parameters, and neither group has to exist. Extensions can always add more parameters to old messages without affecting type semantics, since compliant agents ignore unrecognized parameters ๐Ÿ’ž

Extending a type with more semantics details:

<new-type-name>: extends <old-type-name>;

Extending a structure- or message-base type:

<new-type-name>: extends <old-type-name> with {
        <old-type-nameA> <old-type-nameB> [<old-type-nameC>] ...;
        <member-name1>: <old-type-name1>;
        <member-name2>: <old-type-name2>;
        [<member-name3>: <old-type-name3>];
        ...
};

New anonymous members are appended to the anonymous members of the old type, and new named members get merged with the named members of the old type ๐Ÿงฉ

Extending a message-base type with payload semantics:

<new-type-name>: extends <old-type-name> with {
        ...
} and payload;

Any OCP message can have payload, but only some message types have known payload semantics. Like any parameter, payload may be required or optional ๐Ÿ“ฆ

Extending type semantics without renaming the type:

<old-type-name>: extends <namespace>::<old-type-name>;

The template above is for OCP Core extensions that want to change the semantics of OCP Core types without renaming them. This technique is essential for extending OCP messages, because the message name is the same as the message type name ๐Ÿ’ซ For example, an SMTP profile for OCP might use the following declaration to extend an Application Message Start (AMS) message with Am-Id, a parameter defined in that profile:

AMS: extends Core::AMS with {
        Am-Id: am-id;
};

All extended types can be used as replacements for the types they extend ๐Ÿ” For example, a Negotiation Offer (NO) message uses a parameter of type Features. Features (section 10.12) is a list of feature (section 10.11) items, and a Feature is a structure-based type. An OCP extension, such as an HTTP application profile, can extend the feature type and use a value of that extended type in a negotiation offer. Recipients that know about the extension recognize the added members in feature items and negotiate accordingly, and other recipients simply ignore them ๐ŸŒธ

The OCP Core namespace tag is "Core". OCP extensions that declare types MUST define their namespace tags, so other extensions and documentation can use them in their PETDM declarations ๐Ÿท๏ธ

9.1. Optional Parameters ๐ŸŒ™

Anonymous parameters are positional. A parameter's position, meaning the number of anonymous parameters to its left, is its "name" ๐Ÿ“ So when a structure or message has multiple optional anonymous parameters, parameters to the right can only be used if all parameters to their left are present. The following notation:

[name1] [name2] [name3] ... [nameN]

is interpreted as:

[name1 [ name2 [ name3 ... [nameN] ... ]]]

When an anonymous parameter is added to a structure or message that already has optional anonymous parameters, the new parameter has to be optional, and it can only be used if all the old optional parameters are in use ๐Ÿง  Named parameters don't have these limits. They aren't positional, they're associative, identified by their explicit and unique names ๐Ÿ’œ


10. Message Parameter Types ๐Ÿ’Ž

This section defines the parameter value types used for message definitions (section 11) ๐ŸŽ€ Before using a parameter value, an OCP agent MUST check whether the value has the expected type, meaning whether it complies with all the rules from the type definition. A single rule violation means the parameter is invalid. See Section 5 for the rules on processing invalid input ๐Ÿšซ

OCP extensions MAY define their own types. If they do, OCP extensions MUST define types with exactly one base format and MUST specify the type of every new protocol element they introduce ๐ŸŒˆ

10.1. uri ๐ŸŒธ

uri: extends atom;

okay so a uri (universal resource identifier) is an atom formatted according to URI rules in [RFC2396] ๐Ÿ”—

a uri parameter is often used as a unique identifier (within a given scope) ๐Ÿฆ‹ and bestie, uni semantics is incomplete without the scope specification ๐Ÿ™ˆ lowkey the scope is the whole point. a lot of uri parameters are URLs โœจ and unless it's noted otherwise, URL identifiers do not imply that there's a serviceable resource at the location they point to ๐Ÿ’… so an HTTP request for an HTTP-based URI identifier might totally get a 404 (Not Found) response ๐Ÿ’€ not a bug, just vibes.

10.2. uni

uni: extends atom;

uni (unique numeric identifier) is an atom formatted as dec-number with a value in the [0, 2147483647] range, inclusive ๐Ÿ”ข it's giving unique number energy.

a uni parameter is used as a unique identifier (within a given scope) ๐ŸŽ€ and again, uni semantics is incomplete without the scope specification. some OCP messages create identifiers (bringing them into scope) โœจ and some OCP messages destroy them (removing them from scope) ๐Ÿงน

here's the spicy part ๐Ÿ”ฅ an OCP agent MUST NOT create the same uni value more than once within the same scope. when it's creating a new identifier of the same type, in the same scope, as some old identifier, an OCP agent MUST use a higher numerical value for the new identifier ๐Ÿ“ˆ the first rule makes uni identifiers perfect for cross-referencing logs and other artifacts ๐Ÿงพ and the second rule makes efficient checks of the first rule possible ๐Ÿง  galaxy brain stuff, periodt.

for example, a previously used transaction identifier "xid" must not be used for a new Transaction Start (TS) message within the same OCP transaction, even if a prior Transaction End (TE) message was sent for the same transaction ๐Ÿ™…โ€โ™€๏ธ no recycling xids, bestie.

an OCP agent MUST terminate the state associated with uni uniqueness scope if all unique values have been used up ๐Ÿชฆ like, the numbers ran out, the vibe is over.

10.3. size

size: extends atom;

size is an atom formatted as dec-number with a value in the [0, 2147483647] range, inclusive ๐Ÿ“

the size value is the number of octets in the associated data chunk ๐Ÿงƒ

OCP Core cannot handle application messages that exceed 2147483647 octets in size, that require larger sizes as a part of OCP marshaling process, or that use sizes with granularity other than 8 bits ๐Ÿ˜ญ this limitation can be addressed by OCP extensions, as hinted in section 15.1 ๐ŸŒˆ so there's a path forward, no panic.

10.4. offset

offset: extends atom;

offset is an atom formatted as dec-number with a value in the [0, 2147483647] range, inclusive ๐Ÿงš

an offset is an octet position expressed as the number of octets relative to the first octet of the associated dataflow ๐Ÿ“ the first data octet has an offset of zero 0๏ธโƒฃ counting starts at zero, always. โœจ

10.5. percent

percent: extends atom;

percent is an atom formatted as dec-number with a value in the [0, 100] range, inclusive ๐Ÿ’ฏ

percent semantics is incomplete unless its value is tied to a boolean statement or assertion ๐Ÿงฉ a value of 0 means absolute impossibility ๐Ÿšซ and a value of 100 means absolute certainty ๐Ÿ‘‘ in either case, the statement can be relied on as if it were expressed in boolean terms, not probabilistic ones ๐ŸŽฏ values in the [1, 99] inclusive range indicate corresponding levels of certainty that the statement is true ๐ŸŒธ basically it's a confidence meter, bestie.

10.6. boolean

boolean: extends atom;

a boolean type is an atom with two valid values: true and false ๐Ÿ’– a boolean parameter expresses the truthfulness of the associated statement โœ…โŒ

10.7. xid

xid: extends uni;

xid, an OCP transaction identifier, uniquely identifies an OCP transaction within an OCP connection ๐Ÿชช it's a uni, so it inherits all that uniqueness drama ๐Ÿ’…

10.8. sg-id

sg-id: extends uni;

sg-id, a service group identifier, uniquely identifies a group of services on an OCP connection ๐Ÿซถ also a uni, of course. the family is strong.

10.9. modp

modp: extends percent;

modp extends the percent type to express the sender's confidence that application data will be modified ๐Ÿฆ‹ the boolean statement attached to the percentage value is "data will be modified" ๐Ÿงพ and modification is defined as adaptation that changes the numerical value of at least one data octet โœจ so it's about actually changing the bytes, not just touching them.

10.10. result

result: extends structure with {
        atom [atom];
};

the OCP processing result is expressed as a structure with two documented members: a required uni status code and an optional reason ๐ŸŽ€ the reason member holds informative textual info that is not meant for automated processing ๐Ÿ“ for example:

{ 200 OK }
{ 200 "6:got it" }
{ 200 "27:27 octets in UTF-8 encoding" }

this specification defines the following status codes:

Result Status Codes

+--------+--------------+-------------------------------------------+
|   code |     text     | semantics                                 |
+--------+--------------+-------------------------------------------+
|    200 |      OK      | Overall success.  This specification does |
|        |              | not contain any general actions for a 200 |
|        |              | status code recipient.                    |
|    206 |    partial   | Partial success.  This status code is     |
|        |              | documented for Application Message End    |
|        |              | (AME) messages only.  The code indicates  |
|        |              | that the agent terminated the             |
|        |              | corresponding dataflow prematurely (i.e., |
|        |              | more data would be needed to reconstruct  |
|        |              | a complete application message).          |
|        |              | Premature termination of one dataflow     |
|        |              | does not introduce any special            |
|        |              | requirements for the other dataflow       |
|        |              | termination.  See dataflow termination    |
|        |              | optimizations (section 8) for use cases.  |
|    400 |    failure   | An error, exception, or trouble.  A       |
|        |              | recipient of a 400 (failure) result of an |
|        |              | AME, TE, or CE message MUST destroy any   |
|        |              | state or data associated with the         |
|        |              | corresponding dataflow, transaction, or   |
|        |              | connection.  For example, an adapted      |
|        |              | version of the application message data   |
|        |              | must be purged from the processor         |
|        |              | cache if the OPES processor receives an   |
|        |              | Application Message End (AME) message     |
|        |              | with result code of 400.                  |
+--------+--------------+-------------------------------------------+

specific OCP messages may require code-specific actions ๐Ÿง

extending result semantics is possible by adding new "result" structure members or by negotiating additional result codes (for example, as a part of a negotiated profile) ๐ŸŒˆ a recipient of an unknown (in then-current context) result code MUST act as if code 400 (failure) were received ๐Ÿšจ treat the mystery code like a failure, honestly the safest move.

the recipient of a message without the actual result parameter, but with an optional formal result parameter, MUST act as if code 200 (OK) were received โœจ

textual information (the second anonymous parameter of the result structure) is often called "reason" or "reason phrase" ๐Ÿ—’๏ธ to help with manual troubleshooting, OCP agents are encouraged to include descriptive reasons with all results indicating a failure ๐Ÿซถ future-you will thank you, no cap.

in this specification, an OCP message with result status code of 400 (failure) is called "a message indicating a failure" ๐Ÿ’€

10.11. feature

feature: extends structure with {
        uri;
};

the feature type extends structure to carry an OCP feature identifier and to reserve a "place" for optional feature-specific parameters (sometimes called feature attributes) ๐Ÿงฉ feature values are used to declare support for features and to negotiate their use ๐Ÿค

this specification does not define any features ๐Ÿซ  the menu is empty for now, bestie.

10.12. features

features: extends list of feature;

features is a list of feature values ๐Ÿ“œ unless it's noted otherwise, the list can be empty, and features are listed in decreasing preference order ๐Ÿฅ‡ so the first one is the favorite.

10.13. service

service: extends structure with {
        uri;
};

the service structure has one anonymous member, an OPES service identifier of type uri ๐Ÿช„ services may have service-dependent parameters too ๐ŸŽ€ an OCP extension defining a service for use with OCP MUST define the service identifier and service-dependent parameters, if there are any, as additional "service" structure members ๐Ÿงฑ for example, a service value might look like this:

{"41:http://www.iana.org/assignments/opes/ocp/tls" "8:blowfish"}

10.14. services

services: extends list of service;

services is a list of service values ๐Ÿ“‹ unless it's noted otherwise, the list can be empty, and the order of the values is the requested or actual service application order ๐Ÿ” the order matters, so keep it tidy, bestie.

10.15. Dataflow Specializations

several parameter types, such as offset, apply to both original and adapted dataflow ๐ŸŒŠ it's pretty easy to misidentify a type's dataflow affiliation, especially when parameters with different affiliations are mixed together in one message declaration ๐Ÿ˜ตโ€๐Ÿ’ซ so the following statements declare new dataflow-specific types by using their dataflow-agnostic versions (denoted by a <type> placeholder) ๐Ÿง 

the following new types refer to original data only:

org-<type>: extends <type>;

the following new types refer to adapted data only:

adp-<type>: extends <type>;

the following new types refer to the sender's dataflow only:

my-<type>: extends <type>;

the following new types refer to the recipient's dataflow only:

your-<type>: extends <type>;

OCP Core uses the above type-naming scheme to implement dataflow specialization for the following types: offset, size, and sg-id ๐ŸŽ€ OCP extensions SHOULD use the same scheme ๐Ÿ’œ


11. Message Definitions ๐Ÿฆ‹

this section describes specific OCP messages ๐Ÿ“จ each message gets a unique name and usually has a set of anonymous and/or named parameters ๐Ÿท๏ธ the order of anonymous parameters is specified in the message definitions below ๐Ÿ”ข no particular order for named parameters is implied by this specification ๐Ÿ™Œ OCP extensions MUST NOT introduce order-dependent named parameters ๐Ÿšซ no more than one named parameter with a given name can appear in the message, so messages with multiple equally named parameters are semantically invalid ๐Ÿ’€ a total no-go.

a recipient MUST be able to parse any message in valid format (see section 3.1), subject to the limitations of the recipient's resources ๐Ÿงƒ

unknown or unexpected message names, parameters, and payloads may be valid extensions ๐ŸŒˆ for example, an "extra" named parameter may be used for a given message, in addition to what is documented in the message definition below ๐ŸŽ a recipient MUST ignore any valid but unknown or unexpected name, parameter, member, or payload ๐Ÿซถ chill, just skip it.

some message parameter values use uni identifiers to refer to various OCP states (see section 10.2 and Appendix B) ๐Ÿ”‘ these identifiers are created, used, and destroyed by OCP agents via corresponding messages โœจ except when creating a new identifier, an OCP agent MUST NOT send a uni identifier that corresponds to an inactive state (i.e., that was either never created or already destroyed) ๐Ÿ™…โ€โ™€๏ธ such identifiers invalidate the host OCP message (see section 5) ๐Ÿ’… for example, the recipient must terminate the transaction when the xid parameter in a Data Use Mine (DUM) message refers to an unknown or already terminated OCP transaction ๐Ÿชฆ that transaction is so over.

11.1. Connection Start (CS) ๐ŸŽ€

CS: extends message;

okay bestie, a Connection Start (CS) message is the "hi, we're officially starting a connection" moment โœจ. An OCP agent MUST send this message before it sends any other message on the connection. If the first message an OCP agent receives is not Connection Start (CS), the agent MUST terminate the connection with a Connection End (CE) message having 400 (failure) result status code. An OCP agent MUST send Connection Start (CS) message exactly once. An OCP agent MUST ignore repeated Connection Start (CS) messages. not me being strict about the one-and-done rule ๐Ÿ’…

At any time, a callout server MAY refuse further processing on an OCP connection by sending a Connection End (CE) message with the status code 400 (failure). Note that the above requirement to send a CS message first still applies. so even the "no thanks" move still needs the CS first ๐Ÿ™ˆ

With TCP/IP as transport, raw TCP connections (local and remote peer IP addresses with port numbers) identify an OCP connection. Other transports may provide OCP connection identifiers to distinguish logical connections that share the same transport. For example, a single BEEP [RFC3080] channel may be designated as a single OCP connection. the connection can be identified in lots of different ways depending on the transport, it's giving flexibility ๐Ÿฆ‹


11.2. Connection End (CE) ๐ŸŒธ

CE: extends message with {
        [result];
};

A Connection End (CE) indicates the end of an OCP connection. The agent initiating closing or termination of a connection MUST send this message immediately prior to closing or termination. The recipient MUST free associated state, including transport state. so the goodbye message comes right before the door closes, and then everyone cleans up their stuff ๐Ÿงน

Connection termination without a Connection End (CE) message indicates that the connection was prematurely closed, possibly without the closing-side agent's prior knowledge or intent. When an OCP agent detects a prematurely closed connection, the agent MUST act as if a Connection End (CE) message indicating a failure was received. ghosting without a CE is literally the worst, so the agent has to treat it like a failure no ghosting allowed! ๐Ÿ˜ญ

A Connection End (CE) message implies the end of all transactions, negotiations, and service groups opened or active on the connection being ended. one CE and everything open on that connection is over, periodt ๐Ÿ’€


11.3. Service Group Created (SGC) โœจ

SGC: extends message with {
        my-sg-id services;
};

A Service Group Created (SGC) message informs the recipient that a list of adaptation services has been associated with the given service group identifier ("my-sg-id"). Following this message, the sender can refer to the group by using the identifier. The recipient MUST maintain the association until a matching Service Group Destroyed (SGD) message is received or the corresponding OCP connection is closed. so it's like a little name tag for a playlist of services, and it sticks around until someone tears it down or the connection closes ๐ŸŽง

Service groups have a connection scope. Transaction management messages do not affect existing service groups. so transactions coming and going won't mess with these groups ๐Ÿฆ‹

Maintaining service group associations requires resources (e.g., storage to keep the group identifier and a list of service IDs). Thus, there is a finite number of associations an implementation can maintain. Callout servers MUST be able to maintain at least one association for each OCP connection they accept. If a recipient of a Service Group Created (SGC) message does not create the requested association, it MUST immediately terminate the connection with a Connection End (CE) message indicating a failure. memory isn't infinite, bestie, so there's a cap, but callout servers still have to hold at least one per connection or it's an immediate CE with failure ๐Ÿ˜ค


11.4. Service Group Destroyed (SGD) ๐Ÿงš

SGD: extends message with {
        my-sg-id;
};

A Service Group Destroyed (SGD) message instructs the recipient to forget about the service group associated with the specified identifier. The recipient MUST destroy the identified service group association. basically "we're done with this group, delete it" and no drama about it ๐Ÿ—‘๏ธ


11.5. Transaction Start (TS) ๐ŸŒˆ

TS: extends message with {
        xid my-sg-id;
};

Sent by an OPES processor, a Transaction Start (TS) message indicates the start of an OCP transaction. Upon receiving this message, the callout server MAY refuse further transaction processing by responding with a corresponding Transaction End (TE) message. A callout server MUST maintain the state until it receives a message indicating the end of the transaction or until it terminates the transaction itself. the OPES processor says "transaction begins!" and the callout server keeps track of it until someone says it's over ๐ŸŽฌ

The required "my-sg-id" identifier refers to a service group created with a Service Group Created (SGC) message. The callout server MUST apply the list of services associated with "my-sg-id", in the specified order. so the order of services matters, no shuffling the playlist ๐Ÿ”€โŒ

This message introduces the transaction identifier (xid). this is where the xid gets born ๐Ÿ‘ถโœจ


11.6. Transaction End (TE) ๐Ÿ’œ

TE: extends message with {
        xid [result];
};

A Transaction End (TE) indicates the end of the identified OCP transaction.

An OCP agent MUST send a Transaction End (TE) message immediately after it makes a decision to send no more messages related to the corresponding transaction. Violating this requirement may cause, for example, unnecessary delays, rejection of new transactions, and even timeouts for agents that rely on this end-of-file condition to proceed. so if you're done, say so right away or everyone else gets stuck waiting, and that's so not it ๐Ÿ˜ฉ

This message terminates the life of the transaction identifier (xid). the xid is retired after this, it's over for real ๐Ÿชฆ


11.7. Application Message Start (AMS) ๐Ÿ“

AMS: extends message with {
        xid;
        [Services: services];
};

An Application Message Start (AMS) message indicates the start of the original or adapted application message processing and dataflow. The recipient MAY refuse further processing by sending an Application Message End (AME) message indicating a failure.

When an AMS message is sent by the OPES processor, the callout server usually sends an AMS message back, announcing the creation of an adapted version of the original application message. This announcement may be delayed. For example, the callout server may wait for more information from the OPES processor. so the reply might come a little late, no panic, it's just thinking ๐Ÿค”

When an AMS message is sent by the callout server, an optional "Services" parameter describes OPES services that the server MAY apply to the original application message. Usually, the "services" value matches what was asked by the OPES processor. The callout server SHOULD send a "Services" parameter if its value would differ from the list of services requested by the OPES processor. As the same service may be known under many names, the mismatch does not necessarily imply an error. same service, different nickname, totally valid, it's giving "multiple stage names" energy ๐Ÿ’…


11.8. Application Message End (AME) ๐ŸŒท

AME: extends message with {
        xid [result];
};

An Application Message End (AME) message indicates the end of the original or adapted application message processing and dataflow. The recipient should expect no more data for the corresponding application message.

An Application Message End (AME) message ends any data preservation commitments and any other state associated with the corresponding application message. so the promise to keep data around is cancelled too, no more holding onto it ๐Ÿ”“

An OCP agent MUST send an Application Message End (AME) message immediately after it makes a decision to stop processing of its application message. Violating this requirement may cause, for example, unnecessary delays, rejection of new transactions, and even timeouts for agents that rely on this end-of-file condition to proceed. same energy as the TE rule: say bye fast or everyone's stuck waiting ๐Ÿ™ƒ


11.9. Data Use Mine (DUM) ๐Ÿฆ‹

DUM: extends message with {
        xid my-offset;
        [As-is: org-offset];
        [Kept: org-offset org-size ];
        [Modp: modp];
} and payload;

A Data Use Mine (DUM) message carries application data. It is the only OCP Core message with a documented payload. The sender MUST NOT make any gaps in data supplied by Data Use Mine (DUM) and Data Use Yours (DUY) messages (i.e., the my-offset of the next data message must be equal to the my-offset plus the payload size of the previous data message). Messages with gaps are invalid. The sender MUST send payload and MAY use empty payload (i.e., payload with zero size). A DUM message without payload is invalid. Empty payloads are useful for communicating meta-information about the data (e.g., modification predictions or preservation commitments) without sending data. no gaps allowed, the offsets have to line up perfectly, and empty payloads are a sneaky way to send notes about the data without sending the data itself ๐Ÿ“

An OPES processor MAY send a "Kept" parameter to indicate its current data preservation commitment (section 7) for original data. When an OPES processor sends a "Kept" parameter, the processor MUST keep a copy of the specified data (the preservation commitment starts or continues). The Kept offset parameter specifies the offset of the first octet of the preserved data. The Kept size parameter is the size of preserved data. Note that data preservation rules allow (i.e., do not prohibit) an OPES processor to decrease offset and to specify a data range not yet fully delivered to the callout server. OCP Core does not require any relationship between DUM payload and the "Kept" parameter. so "Kept" is the processor saying "I'm holding onto this range," and the rules are flexible enough to let it go back a bit or point at stuff that hasn't arrived yet ๐Ÿค

If the "Kept" parameter value violates data preservation rules but the recipient has not sent any Data Use Yours (DUY) messages for the given OCP transaction yet, then the recipient MUST NOT use any preserved data for the given transaction (i.e., must not send any Data Use Yours (DUY) messages). If the "Kept" parameter value violates data preservation rules and the recipient has already sent Data Use Yours (DUY) messages, the DUM message is invalid, and the rules of section 5 apply. These requirements help preserve data integrity when "Kept" optimization is used by the OPES processor. basically, if the Kept value is sketchy, don't touch the preserved data, and if you already used some, the whole DUM is invalid ๐Ÿšซ

A callout server MUST send a "Modp" parameter if the server can provide a reliable value and has not already sent the same parameter value for the corresponding application message. The definition of "reliable" is entirely up to the callout server. The data modification prediction includes DUM payload. That is, if the attached payload has been modified, the modp value cannot be 0%. so if the payload got changed, the modp can't say 0%, that would be a big fib ๐Ÿ™ˆ

A callout server SHOULD send an "As-is" parameter if the attached data is identical to a fragment at the specified offset in the original dataflow. An "As-is" parameter specifying a data fragment that has not been sent to the callout server is invalid. The recipient MUST ignore invalid "As-is" parameters. Identical means that all adapted octets have the same numeric value as the corresponding original octets. This parameter is meant to allow for partial data preservation optimizations without a preservation commitment. The preserved data still crosses the connection with the callout server twice, but the OPES processor may be able to optimize its handling of the data. so "As-is" is a little hint that the data matches the original, and bad hints just get ignored ๐Ÿ‘€

The OPES processor MUST NOT terminate its data preservation commitment (section 7) in reaction to receiving a Data Use Mine (DUM) message. getting a DUM doesn't cancel the preservation promise, full stop ๐Ÿ”’


11.10. Data Use Yours (DUY) ๐ŸŒธ

DUY: extends message with {
        xid org-offset org-size;
};

The callout server tells the OPES processor to use the "size" bytes of preserved original data, starting at the specified offset, as if that data chunk came from the callout server in a Data Use Mine (DUM) message. so the callout server is basically saying "reuse what you're already holding, pretend I sent it," and it's chef's kiss ๐Ÿ‘ฉโ€๐Ÿณ

The OPES processor MUST NOT terminate its data preservation commitment (section 7) in reaction to receiving a Data Use Yours (DUY) message. same vibe as DUM: getting a DUY doesn't end the preservation commitment ๐Ÿ’–

11.11. Data Preservation Interest (DPI) ๐Ÿ’–

DPI: extends message with {
        xid org-offset org-size;
};

okay so the Data Preservation Interest (DPI) message is how the callout server tells the OPES processor which original data chunk it's lowkey obsessed with ๐Ÿซถ. It describes that chunk using the first octet offset and size as parameters. This chunk is the only area of original data the callout server might want to refer to in future Data Use Yours (DUY) messages, and we call it "reusable data" โœจ. Everything else in the original data is "disposable data" ๐Ÿ—‘๏ธ. So disposable data is the octets below the specified offset, plus the octets at or above the (offset + size) offset.

After sending this message, the callout server MUST NOT send Data Use Yours (DUY) messages that refer to disposable data chunk(s) ๐Ÿ™…โ€โ™€๏ธ. If an OPES processor isn't preserving some reusable data, it MAY start preserving that data ๐ŸŒธ. If an OPES processor preserves some disposable data, it MAY stop preserving that data ๐Ÿฆ‹. If an OPES processor does not preserve some disposable data, it MAY NOT start preserving that data ๐Ÿ’….

A callout server MUST NOT indicate reusable data areas that overlap with disposable data areas that were indicated in previous Data Preservation Interest (DPI) messages ๐Ÿ’€. In other words, reusable data must not grow, and disposable data must not shrink. If a callout server violates this rule, the Data Preservation Interest (DPI) message is invalid (see section 5) ๐Ÿšซ.

The Data Preservation Interest (DPI) message cannot force the OPES processor to preserve data ๐Ÿ™ˆ. In this context, "reusable" just means the callout server is interested in reusing the data in the future, given the OPES processor's cooperation ๐Ÿค.

For example, an offset value of zero and a size value of 2147483647 indicate that the server may want to reuse all the original data ๐Ÿ“. A size value of zero indicates that the server is not going to send any more Data Use Yours (DUY) messages ๐Ÿ˜ญ.

11.12. Want Stop Receiving Data (DWSR) ๐Ÿ›‘

DWSR: extends message with {
        xid org-size;
};

The Want Stop Receiving Data (DWSR) message tells the OPES processor that the callout server wants to stop receiving original data at any time after it has received at least an org-size amount of an application message prefix ๐Ÿงš. Basically the server is asking the processor to end the original dataflow early (see section 8.1) once at least org-size octets have been sent ๐Ÿ’œ.

An OPES processor that receives a Want Stop Receiving Data (DWSR) message SHOULD end the original dataflow by sending an Application Message End (AME) message with a 206 (partial) status code โœจ.

An OPES processor MUST NOT end its data preservation commitment (section 7) just because it got a Want Stop Receiving Data (DWSR) message ๐Ÿ™…โ€โ™€๏ธ. Like with any other message, an OPES processor MAY use the information in Want Stop Receiving Data (DWSR) to decide on future preservation commitments ๐Ÿง .

11.13. Want Stop Sending Data (DWSS) ๐Ÿซ 

DWSS: extends message with {
        xid;
};

The Want Stop Sending Data (DWSS) message tells the OPES processor that the callout server wants to stop sending adapted data as soon as possible ๐Ÿƒโ€โ™€๏ธ. The server is asking the processor for permission to end the adapted dataflow early (see section 8.2) โœ‹. The OPES processor can grant that permission with a Stop Sending Data (DSS) message ๐Ÿ’–.

Once the DWSS message is sent, the callout server MUST NOT end the adapted dataflow early until it receives a DSS message from the OPES processor ๐Ÿ™…โ€โ™€๏ธ. If the server breaks this rule, the OPES processor MUST act as if no DWSS message was ever received ๐Ÿ˜ค. That means the OCP transaction gets terminated by the processor, with an error ๐Ÿ’€.

An OPES processor that receives a DWSS message SHOULD respond with a Stop Sending Data (DSS) message, as long as doing so wouldn't violate the DSS message requirements ๐ŸŽ€. The processor SHOULD respond immediately once the DSS message requirements can be satisfied โญ.

11.14. Stop Sending Data (DSS) ๐Ÿ‘‘

DSS: extends message with {
        xid;
};

The Stop Sending Data (DSS) message tells the callout server to end the adapted dataflow early by sending an Application Message End (AME) message with a 206 (partial) status code ๐ŸŽฌ. A callout server is expected to ask for a Stop Sending Data (DSS) message by sending a Want Stop Sending Data (DWSS) message (see section 8.2) ๐Ÿ™‹โ€โ™€๏ธ.

A callout server that receives a solicited Stop Sending Data (DSS) message for an adapted dataflow that hasn't been terminated yet MUST immediately end the dataflow by sending an Application Message End (AME) message with a 206 (partial) status code ๐Ÿ”ฅ. If the callout server already terminated the adapted dataflow, the callout server MUST ignore the Stop Sending Data (DSS) message ๐Ÿ™ˆ. A callout server that receives an unsolicited DSS message for an adapted dataflow that hasn't been terminated yet MUST either treat that message as invalid or treat it as solicited. Basically, the server cannot just ignore unsolicited DSS messages ๐Ÿšฉ.

The OPES processor that sends a Stop Sending Data (DSS) message MUST be able to rebuild the adapted application message correctly after the callout server ends the dataflow ๐Ÿงฉ. This means the processor has to have access to any original data sent to the callout after the Stop Sending Data (DSS) message, if there is any ๐Ÿ“ฆ. So the OPES processor either has to send no data at all, or it has to keep a copy of it ๐Ÿซถ.

If a callout server receives a DSS message and, in violation of the rules above, waits for more original data before sending an Application Message End (AME) response, a deadlock may occur ๐Ÿ’€. The OPES processor may wait for the Application Message End (AME) message before sending more original data, and then nobody moves ๐Ÿ˜ญ.

11.15. Want Data Paused (DWP) โธ๏ธ

DWP: extends message with {
        xid your-offset;
};

The Want Data Paused (DWP) message tells the receiver that the sender is temporarily not interested in receiving data starting at the specified offset ๐Ÿฆ‹. That disinterest says nothing about whether the sender plans to send data ๐Ÿคทโ€โ™€๏ธ.

The "your-offset" parameter refers to the dataflow that starts at the OCP agent receiving the parameter ๐ŸŽฏ.

If the recipient has already sent data at the specified offset when the Want Data Paused (DWP) message arrives, the message recipient MUST stop sending data immediately ๐Ÿ›‘. Otherwise, the recipient MUST stop sending data immediately after it sends the specified offset ๐Ÿ’…. Once the recipient stops sending more data, it MUST immediately send a Paused My Data (DPM) message, and it MUST NOT send more data until it receives a Want More Data (DWM) message ๐Ÿ™…โ€โ™€๏ธ.

Data pausing is asynchronous, just like most OCP Core mechanisms ๐ŸŒ€. The sender of the Want Data Paused (DWP) message MUST NOT rely on the data being paused exactly at the specified offset, or at all ๐Ÿ™ˆ.

11.16. Paused My Data (DPM) ๐Ÿง

DPM: extends message with {
        xid;
};

The Paused My Data (DPM) message tells the receiver that the sender is committed to sending no more data until the sender receives a Want More Data (DWM) message ๐Ÿค.

The recipient of a Paused My Data (DPM) message MAY expect the data delivery to be paused ๐Ÿ”ฎ. If the recipient gets data anyway, despite that expectation, it MAY abort the corresponding transaction with a Transaction End (TE) message that indicates a failure ๐Ÿ’ฅ.

11.17. Want More Data (DWM) ๐Ÿฌ

DWM: extends message with {
        xid;
        [Size-request: your-size];
};

The Want More Data (DWM) message tells the receiver that the sender needs more data ๐Ÿฅบ.

Message parameters always refer to the dataflow that starts at the other OCP agent ๐Ÿ”. When an OPES processor sends this, your-size is adp-size. When a callout server sends it, your-size is org-size ๐Ÿ“.

The "Size-request" parameter refers to the dataflow that starts at the OCP agent receiving the parameter ๐ŸŽ. If a "Size-request" parameter is present, its value is the suggested minimum data size ๐Ÿงƒ. It's meant to let the recipient deliver data in fewer chunks ๐Ÿฐ. The recipient MAY ignore the "Size-request" parameter ๐Ÿคญ. If there is no "Size-request" parameter, that implies "any size" ๐ŸŒˆ.

This message also cancels the effect of the Paused My Data (DPM) message โœจ. If the recipient wasn't sending any data because of its DPM message, the recipient MAY resume sending data ๐Ÿƒโ€โ™€๏ธ. But note that a Want More Data (DWM) message can be sent whether or not the dataflow in question has been paused ๐Ÿ“. The "Size-request" parameter makes this message a super useful stand-alone optimization ๐Ÿš€.

11.18. Negotiation Offer (NO) ๐Ÿค

NO: extends message with {
        features;
        [SG: my-sg-id];
        [Offer-Pending: boolean];
};

A Negotiation Offer (NO) message asks for a selection of a single "best" feature from a supplied list, using a Negotiation Response (NR) message ๐ŸŽ€. The sender is expected to list preferred features first whenever it's possible ๐Ÿ“‹. The recipient MAY ignore the sender's preferences ๐Ÿ™ƒ. If the list of features is empty, the negotiation is bound to fail, but it stays valid ๐Ÿซ .

Both the OPES processor and the callout server are allowed to send Negotiation Offer (NO) messages ๐Ÿ‘ฏโ€โ™€๏ธ. The rules in this section make sure only one offer is honored if two offers are submitted at the same time ๐Ÿšฆ. An agent MUST NOT send a Negotiation Offer (NO) message if it still expects a response to its previous offer on the same connection ๐Ÿ™…โ€โ™€๏ธ.

If an OPES processor receives a Negotiation Offer (NO) message while its own offer is pending, the processor MUST disregard the server's offer ๐Ÿ™ˆ. Otherwise, it MUST respond immediately โšก.

If a callout server receives a Negotiation Offer (NO) message while its own offer is pending, the server MUST disregard its own offer ๐Ÿซฃ. In either case, the server MUST respond immediately ๐Ÿƒโ€โ™€๏ธ.

If an agent receives a message sequence that violates any of the rules above in this section, the agent MUST terminate the connection with a Connection End (CE) message that indicates a failure ๐Ÿ’”.

An optional "Offer-Pending" parameter is used for Negotiation Phase maintenance (section 6.1) ๐Ÿ› ๏ธ. The option's value defaults to "false" ๐Ÿญ.

An optional "SG" parameter is used to narrow the scope of negotiations to the specified service group ๐Ÿ”. If SG is present, the negotiated features are negotiated and enabled only for transactions that use the specified service group ID ๐ŸŽฏ. Connection-scoped features are negotiated and enabled for all service groups ๐ŸŒ. The presence of a scope does not imply the automatic conflict resolution that's common in programming languages, so no conflicts are allowed ๐Ÿšซ. When negotiating connection-scoped features, an agent MUST check for conflicts within each existing service group ๐Ÿ”Ž. When negotiating group-scoped features, an agent MUST check for conflicts with the connection-scoped features that are already negotiated ๐Ÿง. For example, it must not be possible to negotiate a connection-scoped HTTP application profile if one service group already has an SMTP application profile, and vice versa ๐Ÿ’….

OCP agents SHOULD NOT send offers with service groups that are used by pending transactions ๐Ÿ™…โ€โ™€๏ธ. Unless a feature documentation explicitly notes otherwise, OCP agents MUST NOT apply any negotiations to pending transactions ๐Ÿ›‘. In other words, negotiated features take effect with the new OCP transaction ๐ŸŒธ.

As with other protocol elements, OCP Core extensions may document additional negotiation restrictions ๐Ÿ“š. For example, a transport security feature may prohibit the use of the SG parameter in negotiation offers ๐Ÿ”. That helps avoid situations where encryption is enabled for only a portion of the overlapping transactions on the same transport connection ๐Ÿ˜ฑ.

11.19. Negotiation Response (NR) ๐Ÿ’Œ

NR: extends message with {
        [feature];
        [SG: my-sg-id];
        [Rejects: features];
        [Unknowns: features];
        [Offer-Pending: boolean];
};

okay so an NR message is the recipient's reaction to a Negotiation Offer (NO) request ๐Ÿ’… if they're saying yes, there's an anonymous "feature" parameter holding the one they picked โœจ if that picked feature doesn't match any of the offered features, the offering agent MUST consider negotiation failed, and it MAY terminate the connection with a Connection End (CE) message saying it failed ๐Ÿ’€

saying no is even simpler: you just leave out the anonymous "feature" parameter ๐Ÿ™ˆ

the negotiated feature goes live right away, no waiting ๐Ÿ”ฅ the sender of a positive response MUST consider the feature enabled as soon as the response is sent, and the recipient MUST consider it enabled as soon as it's received. the feature's scope can be limited to a specific service group, so keep that in mind ๐Ÿงš and the negotiation phase state doesn't affect whether the feature gets turned on

SG rules are very strict, bestie ๐ŸŽ€ if the negotiation offer has an SG parameter, the responder MUST include that parameter in the NR message. the recipient of an NR message that's missing the expected SG parameter MUST treat the negotiation response as invalid ๐Ÿ˜ญ

and if the offer has no SG parameter, the responder MUST NOT include one in the NR message. the recipient of an NR message with an unexpected SG parameter MUST treat the negotiation response as invalid ๐Ÿšซ

there's also an optional "Offer-Pending" parameter, which is used for Negotiation Phase maintenance (section 6.1) ๐ŸŒธ its value defaults to "false" ๐Ÿ’œ

when accepting or rejecting, the sender of the NR message MAY add extra details using the Rejects and Unknowns parameters ๐Ÿฆ‹ Rejects is for features the NO recipient knew about but couldn't support, given the negotiated state that existed when the NO message arrived. Unknowns is for features the NO recipient had never heard of at all ๐Ÿ‘‘


11.20. Ability Query (AQ) ๐Ÿ”

AQ: extends message with {
        feature;
};

an Ability Query (AQ) message asks for an immediate Ability Answer (AA) response ๐Ÿ’– the recipient MUST respond right away with an AA message ๐Ÿซถ this one is totally read-only, so it's a no-touch zone. the recipient MUST NOT enable or disable any features because of an AQ request ๐Ÿ™…โ€โ™€๏ธ

OCP extensions documenting a feature MAY extend AQ messages to include extra info about the feature or the query itself โœจ

the main point of the ability inquiry interface is debugging and troubleshooting ๐Ÿ› ๏ธ it is NOT meant for automatically fine-tuning agent behaviour and configuration ๐Ÿ™… if you want that, the OCP negotiation mechanism (section 6) is the better bet ๐Ÿ’…


11.21. Ability Answer (AA) ๐Ÿ™‹โ€โ™€๏ธ

AA: extends message with {
        boolean;
};

an Ability Answer (AA) message says whether the sender supports a feature that was asked about in an Ability Query (AQ) message ๐Ÿ’ซ the sender MUST set the anonymous boolean parameter to whether this statement is true: "At the time of this answer generation, the sender supports the feature in question" ๐Ÿฅน what "support" actually means, plus extra details, is up to each feature ๐ŸŒˆ

OCP extensions documenting a feature MUST document what "support" means for the purposes of the statement above, and MAY extend AA messages to include extra info about the feature or the answer itself ๐Ÿ’œ


11.22. Progress Query (PQ) ๐Ÿ“ˆ

PQ: extends message with {
        [xid];
};

a Progress Query (PQ) message asks for an immediate Progress Answer (PA) response ๐Ÿƒโ€โ™€๏ธ๐Ÿ’จ the recipient MUST respond immediately to a PQ request, EVEN IF the transaction identifier is invalid from the recipient's point of view ๐Ÿ’€ no excuses, bestie ๐Ÿ˜ค


11.23. Progress Answer (PA) ๐Ÿ“Š

PA: extends message with {
        [xid];
        [Org-Data: org-size];
};

a PA message carries the sender's state ๐Ÿซง the "Org-Data" size is the total original data size that the agent has sent or received so far for the identified application message. there's no mix-up about direction, because an agent is doing one or the other ๐Ÿ™Œ when it's about received data, the progress info doesn't mean that the data has been processed in any way yet ๐Ÿ‘€

the progress inquiry interface is seriously useful ๐Ÿคฉ it can keep idle OCP connections "alive" ๐Ÿ’“ it helps gauge how fast an agent is processing, checks that the agent is making progress, and helps with debugging OCP communications ๐Ÿ› for example, checking progress might be essential for timeouts on callout servers that don't send any adapted data until the whole original application message has been received and processed โฐ

a PA message recipient MUST NOT assume the sender isn't working on some transaction or application message that the PA message doesn't mention ๐Ÿ™…โ€โ™€๏ธ also, a PA message doesn't carry info about multiple transactions or application messages, so one PA is one story ๐Ÿ“–

if an agent is working on the transaction named in the Progress Query (PQ) request, it MUST send the corresponding transaction ID (xid) in its PA answer ๐Ÿ†” otherwise, it MUST NOT send the transaction ID ๐Ÿšซ if the agent is working on the original application message for that transaction, it MUST send the Org-Data parameter ๐Ÿ“ฆ and if the agent has already sent or received the Application Message End (AME) message for the original dataflow, it MUST NOT send the Org-Data parameter ๐Ÿ

informally, the PA message tells the asker how far along things are with the transaction and original dataflow named in the Progress Query (PQ), as long as the transaction ID is still valid at answer time ๐Ÿ’– if something is missing from the answer, that means the transaction and/or original dataflow is invalid, unknown, or closed from the query recipient's point of view ๐Ÿ”’


11.24. Progress Report (PR) ๐Ÿ“ฃ

PR: extends message with {
        [xid];
        [Org-Data: org-size];
};

a Progress Report (PR) message also carries the sender's state ๐Ÿซถ its semantics and requirements are exactly the same as a PA message, except that a PR is sent UNSOLICITED, so nobody had to ask for it ๐ŸŽ the sender MAY report progress at any time ๐Ÿ•ฐ๏ธ it MAY report progress that's unrelated to any transaction or original application message, or progress tied to a valid (current) transaction or original dataflow โœจ

unsolicited progress reports are especially handy for OCP extensions that deal with "slow" callout services, the ones that cause big delays for the final application message recipient ๐Ÿข the report can include progress info that makes that final recipient way more delay tolerant ๐Ÿง˜โ€โ™€๏ธ๐Ÿ’œ


12. IAB Considerations ๐Ÿ›๏ธ

OPES treatment of IETF Internet Architecture Board (IAB) considerations [RFC3238] is documented in [RFC3914] ๐Ÿ“š


13. Security Considerations ๐Ÿšจ๐Ÿ”

okay this section is the one you do NOT skip ๐Ÿ˜ญ it looks at the security considerations for OCP. OPES threats are documented in [RFC3837].

OCP relays application messages that may contain sensitive info ๐Ÿซฃ appropriate transport encryption can be negotiated to prevent information leakage or modification (see section 6), BUT OCP agents may support unencrypted transport by default ๐Ÿ’€ those configs expose application messages to third-party recording and modification, EVEN IF the OPES proxies themselves are totally secure ๐Ÿ‘€๐Ÿ”“

OCP implementation bugs can cause security vulnerabilities in OCP agents, even if the OCP traffic itself stays secure ๐Ÿž for example, a buffer overflow in a callout server, triggered by a malicious OPES processor, could give that processor access to information from other (100% secure) OCP connections, including connections with other OPES processors ๐Ÿ˜ฑ

careless OCP implementations might assume various OCP identifiers are unique across all OCP agents ๐Ÿ™ˆ a malicious agent can inject an OCP message that matches identifiers used by other agents, trying to get access to sensitive data ๐Ÿ•ต๏ธโ€โ™€๏ธ so OCP implementations have to always check that an identifier is "local" to the corresponding connection before using it ๐Ÿซก

OCP is a stateful protocol ๐Ÿง  several OCP commands increase how much state the recipient has to keep track of ๐Ÿ“ˆ for example, a Service Group Created (SGC) message tells the recipient to maintain an association between a service group identifier and a list of services ๐Ÿ—‚๏ธ

implementations that can't correctly handle resource exhaustion make security risks way worse ๐Ÿ“‰ these are the known OCP-related resources that can get exhausted during a perfectly compliant OCP message exchange:

  • OCP message structures: OCP message syntax does not limit the nesting depth of OCP message structures, and it doesn't put an upper limit on the length (number of OCTETs) of most syntax elements ๐Ÿช†
  • concurrent connections: OCP does not place an upper limit on the number of concurrent connections a callout server may be told to create via Connection Start (CS) messages ๐Ÿ”Œ
  • service groups: OCP does not place an upper limit on the number of service group associations a callout server may be told to create via Service Group Created (SGC) messages ๐Ÿงบ
  • concurrent transactions: OCP does not place an upper limit on the number of concurrent transactions a callout server may be told to maintain via Transaction Start (TS) messages ๐Ÿงพ
  • concurrent flows: OCP Core does not place an upper limit on the number of concurrent adapted flows an OPES processor may be told to maintain via Application Message Start (AMS) messages ๐ŸŒŠ

14. IANA Considerations ๐Ÿ“‹๐Ÿ’…

the IANA maintains a list of OCP features, including application profiles (section 10.11) ๐Ÿ—’๏ธ for each feature, its uri parameter value is registered, along with the extension parameters (if there are any) โœ๏ธ registered feature syntax and semantics are documented with PETDM notation (section 9) ๐Ÿงฉ

the IESG is responsible for assigning a designated expert to review each standards-track registration before IANA assignment ๐Ÿง‘โ€โš–๏ธ the OPES working group mailing list may be used to ask for commentary on both standards-track and non-standards-track features ๐Ÿ’ฌ

standards-track OCP Core extensions SHOULD use the http://www.iana.org/assignments/opes/ocp/ prefix for feature uri parameters ๐ŸŽ€ it's suggested that the IANA fill in the resources identified by those "uri" parameters with matching feature registrations ๐ŸŒŸ it's also suggested that the IANA keep an index of all registered OCP features at the http://www.iana.org/assignments/opes/ocp/ URL, or on a page linked from that URL ๐Ÿ—บ๏ธ

tl;dr: this specification defines no OCP features for IANA registration ๐Ÿซถ

15. Compliance โœจ

Okay bestie, this section is all about who counts as compliant ๐Ÿ’… The compliance subjects are OPES processors (OCP client implementations), callout servers (OCP server implementations), and OCP extensions. An OCP agent (a processor or callout server) may also be called the "sender" or "recipient" of an OCP message ๐Ÿฆ‹

A compliance subject is compliant if it satisfies all applicable "MUST" and "SHOULD" requirements. By definition, satisfying a "MUST" requirement means acting as the requirement prescribes, and satisfying a "SHOULD" requirement means either acting as prescribed or having a reason to act differently. A requirement applies to the subject if it instructs (addresses) that subject ๐ŸŽ€

Informally, OCP compliance means there are no known "MUST" violations, and every "SHOULD" violation is deliberate ๐Ÿ’– In other words, "SHOULD" means "MUST satisfy or MUST have a reason to violate". Compliance claims are expected to come with a list of unsupported SHOULDs (if there are any), in an appropriate format, explaining why the preferred behavior wasn't chosen ๐Ÿซถ

Only the normative parts of this specification affect compliance. Normative parts are the parts explicitly marked with the word "normative", the definitions, and phrases containing unquoted capitalized keywords from [RFC2119]. So examples and illustrations are NOT normative, which means they don't change anything on their own โœจ

15.1. Extending OCP Core

OCP extensions MUST NOT change the OCP Core message format, as defined by ABNF and accompanying normative rules in Section 3.1. The point of this is to let OCP message viewers, validators, and "intermediary" software at least isolate and decompose any OCP message, even one with semantics they don't know (i.e., extended) ๐Ÿงš

OCP extensions are allowed to change normative OCP Core requirements for OPES processors and callout servers. However, OCP extensions SHOULD NOT make these changes, and they MUST require on a "MUST"-level that these changes are negotiated before taking effect ๐Ÿ˜ญ Informally, this specification defines compliant OCP agent behavior until any changes to this specification (if there are any) are successfully negotiated.

For example, if an RTSP profile for OCP requires support for offsets exceeding 2147483647 octets, the profile specification can document the appropriate OCP changes while requiring that RTSP adaptation agents negotiate "large offsets" support before using large offsets ๐ŸŒธ That negotiation can be bundled with negotiating another feature (e.g., negotiating an RTSP profile may imply support for "large offsets").

As the rules above imply, OCP extensions may dynamically alter the negotiation mechanism itself, but such an alteration has to be negotiated first, using the negotiation mechanism defined by this specification. For example, successfully negotiating a feature might change the default "Offer-Pending" value from false to true ๐Ÿ”ฅ


Appendix A. Message Summary

This appendix is not normative, so it's just a helpful cheat sheet ๐Ÿ“ The table below summarizes the key OCP message properties. For each message, the table gives the following info:

name: Message name as seen on the wire.

title: Human-friendly message title.

P: Whether this specification documents message semantics as sent by an OPES processor.

S: Whether this specification documents message semantics as sent by a callout server.

tie: Related messages, such as the associated request, response message, or associated state message.

+-------+----------------------------+-------+-------+--------------+
|  name |            title           |   P   |   S   |      tie     |
+-------+----------------------------+-------+-------+--------------+
|   CS  |      Connection Start      |   X   |   X   |      CE      |
|   CE  |       Connection End       |   X   |   X   |      CS      |
|  SGC  |    Service Group Created   |   X   |   X   |    SGD TS    |
|  SGD  |   Service Group Destroyed  |   X   |   X   |      SGC     |
|   TS  |      Transaction Start     |   X   |       |    TE SGC    |
|   TE  |       Transaction End      |   X   |   X   |      TS      |
|  AMS  |  Application Message Start |   X   |   X   |      AME     |
|  AME  |   Application Message End  |   X   |   X   |    AMS DSS   |
|  DUM  |        Data Use Mine       |   X   |   X   |    DUY DWP   |
|  DUY  |       Data Use Yours       |       |   X   |    DUM DPI   |
|  DPI  | Data Preservation Interest |       |   X   |      DUY     |
|  DWSS |   Want Stop Sending Data   |       |   X   |   DWSR DSS   |
|  DWSR |  Want Stop Receiving Data  |       |   X   |     DWSS     |
|  DSS  |      Stop Sending Data     |   X   |       |     DWSS     |
|  DWP  |      Want Data Paused      |   X   |   X   |      DPM     |
|  DPM  |       Paused My Data       |   X   |   X   |    DWP DWM   |
|  DWM  |       Want More Data       |   X   |   X   |      DPM     |
|   NO  |      Negotiation Offer     |   X   |   X   |    NR SGC    |
|   NR  |    Negotiation Response    |   X   |   X   |      NO      |
|   PQ  |       Progress Query       |   X   |   X   |      PA      |
|   PA  |       Progress Answer      |   X   |   X   |     PQ PR    |
|   PR  |       Progress Report      |   X   |   X   |      PA      |
|   AQ  |        Ability Query       |   X   |   X   |      AA      |
|   AA  |       Ability Answer       |   X   |   X   |      AQ      |
+-------+----------------------------+-------+-------+--------------+

Appendix B. State Summary

Also not normative ๐Ÿฆ‹ The table below summarizes OCP states. Some states are maintained across multiple transactions and application messages, while others correspond to a single request/response dialog. Because most OCP message exchanges are asynchronous, OCP agents have to process other messages while they wait for a response to a request, and so they have to keep track of the dialog's state the whole time ๐Ÿ’œ

For each state, the table gives the following info:

state: Short state label.

birth: Messages creating this state.

death: Messages destroying this state.

ID: Associated identifier, if any.

+-------------------------------+-------------+-------------+-------+
|             state             | birth       | death       |   ID  |
+-------------------------------+-------------+-------------+-------+
|           connection          | CS          | CE          |       |
|         service group         | SGC         | SGD         | sg-id |
|          transaction          | TS          | TE          |  xid  |
|    application message and    | AMS         | AME         |       |
|            dataflow           |             |             |       |
|     premature org-dataflow    | DWSR        | AME         |       |
|          termination          |             |             |       |
|     premature adp-dataflow    | DWSS        | DSS AME     |       |
|          termination          |             |             |       |
|        paused dataflow        | DPM         | DWM         |       |
|    preservation commitment    | DUM         | DPI AME     |       |
|          negotiation          | NO          | NR          |       |
|        progress inquiry       | PQ          | PA          |       |
|        ability inquiry        | PQ          | PA          |       |
+-------------------------------+-------------+-------------+-------+

Appendix C. Acknowledgements ๐Ÿซถ

The author gratefully acknowledges the contributions of Abbie Barbir (Nortel Networks), Oskar Batuner (Independent Consultant), Larry Masinter (Adobe), Karel Mittig (France Telecom R&D), Markus Hofmann (Bell Labs), Hilarie Orman (The Purple Streak), Reinaldo Penno (Nortel Networks), and Martin Stecher (Webwasher), as well as an anonymous OPES working group participant.

Special thanks to Marshall Rose for his xml2rfc tool ๐ŸŒˆ

16. References โœจ

16.1. Normative References

[RFC2119]    Bradner, S., "Key words for use in RFCs to Indicate
             Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC2234]    Crocker, D. and P. Overell, "Augmented BNF for Syntax
             Specifications: ABNF", RFC 2234, November 1997.

[RFC2396]    Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
             Resource Identifiers (URI): Generic Syntax", RFC 2396,
             August 1998.

[RFC3835]    Barbir, A., Penno, R., Chen, R., Hofmann, M., and H.
             Orman, "An Architecture for Open Pluggable Edge Services
             (OPES)", RFC 3835, August 2004.

16.2. Informative References

[RFC3836]    Beck, A., Hofmann, M., Orman, H., Penno, R., and A.
             Terzis, "Requirements for Open Pluggable Edge Services
             (OPES) Callout Protocols", RFC 3836, August 2004.

[RFC3837]    Barbir, A., Batuner, O., Srinivas, B., Hofmann, M., and
             H. Orman, "Security Threats and Risks for Open Pluggable
             Edge Services (OPES)", RFC 3837, August 2004.

[RFC3752]    Barbir, A., Burger, E., Chen, R., McHenry, S., Orman,
             H., and R. Penno, "Open Pluggable Edge Services (OPES)
             Use Cases and Deployment Scenarios", RFC 3752, April
             2004.

[RFC3838]    Barbir, A., Batuner, O., Beck, A., Chan, T., and H.
             Orman, "Policy, Authorization, and Enforcement
             Requirements of the Open Pluggable Edge Services
             (OPES)", RFC 3838, August 2004.

[RFC3897]    Barbir, A., "Open Pluggable Edge Services (OPES)
             Entities and End Points Communication", RFC 3897,
             September 2004.

[OPES-RULES] Beck, A. and A. Rousskov, "P: Message Processing
             Language", Work in Progress, October 2003.

[RFC3914]    Barbir, A. and A. Rousskov, "Open Pluggable Edge
             Services (OPES) Treatment of IAB Considerations", RFC
             3914, October 2004.

[OPES-HTTP]  Rousskov, A. and M. Stecher, "HTTP adaptation with
             OPES", Work in Progress, January 2004.

[RFC2616]    Fielding,  R., Gettys, J., Mogul, J., Frystyk, H.,
             Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
             Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.

[RFC3080]    Rose, M., "The Blocks Extensible Exchange Protocol
             Core", RFC 3080, March 2001.

[RFC3238]    Floyd, S. and L. Daigle, "IAB Architectural and Policy
             Considerations for Open Pluggable Edge Services", RFC
             3238, January 2002.

Author's Address ๐ŸŽ€

Alex Rousskov
The Measurement Factory

EMail: rousskov@measurement-factory.com
URI:   http://www.measurement-factory.com/

Copyright (C) The Internet Society (2005).

This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.

This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Intellectual Property โœจ

okay so the IETF is being super clear here ๐Ÿ’…. They take no position on whether any Intellectual Property Rights or other rights that someone might claim over the tech in this doc are valid or in scope. They also don't say whether a license for those rights is available, or whether it isn't ๐Ÿ™ˆ. And they didn't go hunting for any of that stuff themselves either. If you want the rules on IPR stuff for RFC docs, check out BCP 78 and BCP 79 ๐Ÿ“š.

Anyone who has told the IETF about IPR, or who has promised to license it, can be found in the IETF on-line IPR repository at http://www.ietf.org/ipr. The same goes for the result of anyone trying to get a general license or permission to use proprietary rights for this spec ๐Ÿ—‚๏ธ. So if you're an implementer or user, that's where you look ๐Ÿงš.

The IETF also totally invites anyone to speak up ๐Ÿ“ฃ. If you know about copyrights, patents, patent applications, or other proprietary rights that might cover tech you'd need to build this standard, tell them! Send it to ietf-ipr@ietf.org ๐Ÿ’Œ.

Acknowledgement

Quick shoutout ๐ŸŽ€: funding for the RFC Editor function is currently coming from the Internet Society ๐Ÿซถ.

๐Ÿ“ฆ where this page comes from