versions for a single original application message or even multiple
original messages to be exchanged as a part of a single OCP
transaction. For example, a single original e-mail message may need
to be transformed into several e-mail messages, with one 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,
transaction, or connection by sending an appropriate OCP message.
Usually, the callout server 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
In addition to messages carrying application data, OCP agents may
also exchange messages related to their configuration, state,
transport connections, application connections, etc. A callout
server may remove itself from the application message processing
loop. A single OPES processor can communicate with many callout
servers and vice versa. Though many OCP exchange patterns do not
follow a classic client-server model, it is possible to think of an
OPES processor as an "OCP client" and of a callout server as an "OCP
server". The OPES architecture document [RFC3835] describes
configuration possibilities.
The following informal rules illustrate relationships between
connections, transactions, OCP messages, and application messages:
o An OCP agent may communicate with multiple OCP agents. This is
outside the scope of this specification.
o 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.
o 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).
o 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).
o 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.
o 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.
o 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 lead to states in which an OCP agent is not receiving
required messages from the other OCP agent. OCP Core defines no
messages to address such situations. In the absence of 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 such 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 assumed usually to take place over TCP/IP
connections on the Internet (though no default TCP port is assigned
to OCP in this specification). This does not preclude OCP from being
implemented 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 and message-order-preserving
transport. Any protocol with these properties can be used; the
mapping of OCP message structures onto the transport data units of
the protocol in question is outside the scope of this specification.
OCP Core is application agnostic. OCP messages can carry
application-specific information 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 OPES
processor and callout server. Some messages require responses (one
could call such messages "requests"); some can only be used in
response to other messages ("responses"); some may be sent without
solicitation; 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 accompany the above ABNF:
o 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 above ABNF.
o All protocol elements are case sensitive unless it is specified
otherwise. In particular, message names and parameter names are
case sensitive.
o Sizes are interpreted as decimal values and cannot have leading
zeros.
o Sizes do not exceed 2147483647.
o 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.
o Empty quoted values are encoded as a 4-octet sequence "0:".
o 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.
o 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 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
OCP syntax provides for compact representation of short control
messages and required parameters while allowing for parameter
extensions. Below are examples of short control messages. The
required CRLF sequence at the end of each line is not shown
explicitly (see section 3.2).
PQ;
TS 1 2;
DWM 22;
DWP 22 16;
x-doit "5:xyzzy";
The above examples contain atomic anonymous parameter values, such as
number and string constants. OCP messages sometimes use more
complicated parameters such as item lists or structures with named
values. As both messages below illustrate, structures and lists can
be nested:
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 are possible with a named
parameters approach, as illustrated by the following example. The
DWM (section 11.17) message in the example has two anonymous
parameters (the last one being an extension) and two named parameters
(the last one being an extension).
DWM 1 3
Size-Request: 16384
X-Need-Info: "26:twenty six octet extension";
Finally, any message may have a payload part. For example, the Data
Use Mine (DUM) message below carries 8865 octets of raw data.
DUM 1 13
Modp: 75
\r\n
8865:... 8865 octets of raw data ...;
3.4. Message Names
Most OCP messages defined in this specification have short names,
formed by abbreviating or compressing a longer but human-friendlier
message title. Short names without a central registration system
(such as this specification or the IANA registry) are likely to cause
conflicts. Informal protocol extensions should avoid short names.
To emphasize what is already defined by message syntax,
implementations cannot assume that all message names are very short.
4. Transactions
An OCP transaction is a logical sequence of OCP messages processing a
single original application message. The result of the processing
may be zero or more application messages, adapted from the original.
A typical transaction consists of two message flows: a flow from the
OPES processor to the callout server (sending the original
application message), and a flow from the callout server to the OPES
processor (sending adapted application messages). The number of
application messages produced by the callout server and whether the
callout server actually modifies the original application message may
depend on the requested callout service and other factors. The OPES
processor or the callout server can terminate the transaction by
sending a corresponding message to the other side.
An OCP transaction starts with a Transaction Start (TS) message sent
by the OPES processor. A transaction ends with the first Transaction
End (TE) message sent or received, explicit or implied. A TE message
can be sent by either side. Zero or more OCP messages associated
with the transaction can be exchanged in between. The figure below
illustrates a possible message sequence (prefix "P" stands for the
OPES processor; prefix "S" stands for the callout server). Some
message details are omitted.
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 specification contains many criteria for valid OCP messages and
their parts, including syntax rules, semantics requirements, and
relationship to agents state. In this context, "Invalid input" means
messages or message parts that violate at least one of the normative
rules. A message with an invalid part is, by definition, invalid.
If OCP agent resources are exhausted while parsing or interpreting a
message, the agent MUST treat the corresponding OCP message as
invalid.
Unless 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 a connection scope. A terminating agent MUST
use the result status code of 400 and MAY specify termination cause
information in the result status reason parameter (see section
10.10). If an OCP agent is unable to determine the scope of an
invalid message it received, the agent MUST treat the message as
having connection scope.
OCP usually deals with optional but invasive application message
manipulations for which correctness ought to be valued above
robustness. For example, a failure to insert or remove certain
optional web page content is usually far less disturbing than
corrupting (making unusable) the host page while performing that
insertion or removal. Most OPES adaptations are high level in
nature, which makes it impossible to assess correctness of the
adaptations automatically, especially if "robustness guesses" are
involved.
6. Negotiation
The negotiation mechanism allows OCP agents to agree on the mutually
acceptable set of features, including optional and
application-specific behavior and OCP extensions. For example,
transport encryption, data format, and support for a new message can
be negotiated. Negotiation implies intent for a behavioral change.
For a related mechanism allowing an agent to query capabilities of
its counterpart without changing the counterpart’s behavior, see the
Ability Query (AQ) and Ability Answer (AA) message definitions.
Most negotiations require at least one round trip time delay. In
rare cases when the other side’s response is not required
immediately, negotiation delay can be eliminated, with an inherent
risk of an overly optimistic assumption about the negotiation
response.
A detected violation of negotiation rules leads to OCP connection
termination. This design reduces the number of negotiation scenarios
resulting in a deadlock when one of the agents is not compliant.
Two core negotiation primitives are supported: negotiation offer and
negotiation response. A Negotiation Offer (NO) message allows an
agent to specify a set of features from which the responder has to
select at most one feature that it prefers. The selection is sent by
using a Negotiation Response (NR) message. If the response is
positive, both sides assume that the selected feature is in effect
immediately (see section 11.19 for details). If the response is
negative, no behavioral changes are assumed. In either case, further
offers may follow.
Negotiating OCP agents have to take into account prior negotiated
(i.e., already enabled) features. OCP agents MUST NOT make and MUST
reject offers that would lead to a conflict with already negotiated
features. For example, an agent cannot offer an HTTP application
profile for a connection that already has an SMTP application profile
enabled, as there would 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
for changing an encryption scheme on the fly).
Negotiation Offer (NO) messages may be sent by either agent. OCP
extensions documenting negotiation MAY assign the initiator role to
one of the agents, depending on the feature being negotiated. For
example, negotiation of transport security feature should be
initiated by OPES processors to avoid situations where both agents
wait for the other to make an offer.
As either agent may make an offer, two "concurrent" offers may be
made at the same time, by the two communicating agents. Unmanaged
concurrent offers may lead to a negotiation deadlock. By giving OPES
processor a priority, offer-handling rules (section 11.18) ensure
that only one offer per OCP connection is honored at a time, and that
the other concurrent offers are ignored by both agents.
6.1. Negotiation Phase
A Negotiation Phase is a mechanism ensuring that both agents have a
chance to negotiate all features they require before proceeding
further. Negotiation Phases have OCP connection scope and do not
overlap. For each OCP agent, the Negotiation Phase starts with the
first Negotiation Offer (NO) message received or the first
Negotiation Response (NR) message sent, provided the message is not a
part of an existing Phase. For each OCP agent, Negotiation Phase
ends with the first Negotiation Response (NR) message (sent or
received), after which the agent expects no more negotiations. Agent
expectation rules are defined later in this section.
During a Negotiation Phase, an OCP agent MUST NOT send messages other
than the following "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).
Multiple Negotiation Phases may happen during the lifespan of a
single OCP connection. An agent may attempt to start a new
Negotiation Phase immediately after the old Phase is over, but it is
possible that the other agent will send messages other than
"Negotiation Phase messages" before receiving the new Negotiation
Offer (NO). The agent that starts a Phase has to be prepared to
handle those messages while its offer is reaching the recipient.
An OPES processor MUST make a negotiation offer immediately after
sending a Connection Start (CS) message. If the OPES processor has
nothing to negotiate, the processor 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. Thus, these
bootstrapping requirements are unlikely to result in any extra work.
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. Moreover, if there
is a possibility that the agent may need to continue the Negotiation
Phase, the agent must send a true "Offer-Pending" parameter.
6.2. Negotiation Examples
Below is an example of the simplest negotiation possible. The OPES
processor is offering nothing and is predictably receiving a
rejection. Note that the NR message terminates the Negotiation Phase
in this case because neither of the messages contains a true
"Offer-Pending" value:
P: NO ();
S: NR;
The next example illustrates how a callout server can force
negotiation of a feature that an OPES processor has not negotiated.
Note that the server sets the "Offer-Pending" parameter to true when
responding to the processor Negotiation Offer (NO) message. The
processor chooses 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 seeks to stop the above negotiations after sending a
true "Offer-Pending" value, its only option would be send an empty
negotiation offer (see the first example above). If the server does
nothing instead, the OPES processor would wait for the server and
would eventually time out the connection.
The following example shows a dialog with a callout server that
insists on enabling two imaginary features: strong transport
encryption and volatile storage for responses. The server is
designed not to exchange sensitive messages until both features are
enabled. Naturally, the volatile storage feature has to be
negotiated securely. The OPES processor supports one of the strong
encryption mechanisms but prefers not to offer (to volunteer support
for) strong encryption, perhaps for performance reasons. The server
has to send a true "Offer-Pending" parameter to get a chance to offer
strong encryption (which is successfully negotiated in this case).
Any messages sent by either agent after the (only) successful NR
response are encrypted with "strongB" encryption scheme. The OPES
processor does not understand the volatile storage feature, and 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" }
;
The following example from [OPES-HTTP] illustrates 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
Many adaptations do not require any data modifications (e.g., message
logging or blocking). Some adaptations modify only a small portion
of application message content (e.g., HTTP cookies filtering or ad
insertion). Yet, in many cases, the callout service has to see
complete data. By default, unmodified data would first travel from
the OPES processor to the callout server and then back. The "data
preservation" optimization in OCP helps eliminate the return trip if
both OCP agents cooperate. Such cooperation is optional: OCP agents
MAY support data preservation optimization.
To avoid sending back unmodified data, a callout service has to know
that the OPES processor has a copy of the data. As data sizes can be
very large and the callout service may not know in advance whether it
will be able to use the processor copy, it is not possible to require
the processor to keep a copy of the entire original data. Instead,
it is expected that a processor may keep some portion of the data,