Draft: draft-pauly-taps-arch

Commentary: Option for addressing : replace Content in the architecture with Message ( where appropriate ) ; use more general concepts like data in the background / design explanation , use Message in the concepts section , and refer to a Message 's content when we need to talk about the bytes specifically in this Message . 
 I am not hugely sold on the definition of /Content : A Content object/. I struggled in NEAT with the best word , and we eventually decided on /data block/. That 's not perfect , but it at least keeps away from the notion of content delivery networks , and various other uses of the word " Content " . Can we please reconsider this ? 
 Sure , we can reconsider . Data Block is one option ; we could also just do Data , but then the singular chunk is more awkward . Some test phrases : " a given Connection is ready to send and/or receive Content " " a given Connection is ready to send and/or receive Data Blocks " " a given Connection is ready to send and/or receive Data " Yeah , I do n't like making this seem like a Content Delivery Network , but when this does get applied to protocols like QUIC and HTTP/2 as a transport , then there are instances in which this is the Content portion of the Header / Content divide . Any other votes from the group ? 
 & lt;whispersmessage 
 I mean , message works nicely — other than the fact that it 's a bit awkward when describing incomplete message content . 
 Hard to come up with a good term for this one . In the test phrases above I think Data works quite well , but I am not sure it will in all situations . 
 I suggested " data block " or " data " , but I really would not have questioned " message " . 
 With our Socket Intents work , we started at " object " and finally came to " message " . A message can easily be spread across several PUDs for transmission . If re - assembly fails , we end up with partial messages . 
 One comment on the relationship between Message and Content : if we do Message as the main architecture concept ( which I 'm fine with to be clear ) , I can imagine that implementations or APIs can still refer to the " content of the message " as opposed to metadata about the message — for example , when I receive a UDP packet as a Message , the content is the interior payload of the datagram , but my metadata includes the ECN flags received on the packet . Does that sound good ? 
  me trhat would be fine ( ( ... we could people thinking about the content of messages , or content messages , etc - but at least we do n't have " content of content " etc ;-) ) ) 
 does this for Architecture ; we still need to make this change in API ( and make sure it carries forward into Implementation as necessary ) 
 Yes , needed for API as well . I already modified Implementation for this . 
 as you 're updating the API document with Message , make sure to make it clear that a single Send ( ) or Receive ( ) does not need to correspond in all cases to a complete Message , and that the Message 's content is passed or delivered , along with an indication of whether this Message is now complete . I 'm referencing this in the implementation for TCP and protocols with very long frames , so it needs to be reflected cleanly in the API too . 
 ACK . Not having to make the distinction was one of the nice things about " Content " , but we should be explicit about partials in the API anyway . 
 my current proposal for -00 is to acknowledge it both on send and receive , and to punt on the details as implementation - specific . 
 The details of what " complete " means for a Message is certainly implementation - determined ; as long as there 's a flag in the Send ( ) call , and in the Message Received callback , that 's fine . 
 So did changing the name from Content to Message now change the semantic of things ? I thought we were using the AFra - Bytestream concept from minset with the Framer as a convenience , but I do not understand how it maps to the partial messages ? 
 I hope not . I think it 's fine ( and good ! ) for the send call to have a flag , and for the receive call to have a flag - so an app CAN be informed about a complete message arriving , when the receiving transport system knows that it is indeed complete . However , the transport system does n't automatically guarantee to the sender that the receiver will be informed about the end of the message that the sender signifies with the flag . In other words : I had an issue with text in the postsockets document that talked about messages , which indicated a guarantee that these messages will be transferred as such . I do n't have an issue with flags in send and receive that MAY work ( but are not guaranteed to always work ) . 
 The flag for a Message being complete is purely local to an implementation : If you use TCP , or some long frames , you can send Message data and not be complete ; and you 'll only send a FIN , or whatever end - of - frame marker you have when you send data with the complete flag . If the frame needs length - value , it will wait until you mark complete . If you use UDP , if you do n't mark your Message as complete , the implementation would pend up data for the Message and wait til its complete before sending the datagram out . If you use TCP , or some long frames , when you receive , the complete flag indicates whether or not this was a FIN or the end of your frame . Since the Message could be gigabytes long , you ca n't just wait to deliver all at once sometimes . For UDP , Messages will be complete when received by default , but I can request to only receive two bytes at a time or something , and get delivered little chunks until the datagram is completely read . 
 But how do I send multiple messages over a TCP connection , this is the part I do not understand also from the implementation draft . I do not know what is underneath , so I send a bunch of messages on a connection and if it is TCP is gets sent as a stream of bytes and if it is SCTP it gets sent as a sequence of messages ? Or I am only allowed to send one message over a TCP connection ? 
 You ca n't send multiple Messages on a TCP stream without using a framing protocol on top of TCP ; you can , of course , send multiple pieces of Message content , and mark the final one as the Message being complete . There is only one sensible Message per direction in TCP . 
 As things are now , the application ca n't know that there is only TCP , and the transport system does n't know whether a framing protocol is used . So , when a message is complete , the sender must be allowed to say that it 's complete , whenever it wants . As you said this is local , and that should n't be a problem . When there is a framing protocol , there is no need for the transport system to convey " end of message " via TCP , so there is no problem if this is ignored . I find the logic of " one message = one TCP connection " disturbing . If I send 50 short messages , do I risk getting connections permanently opened and torn down because my " end of message " becomes a FIN ? That does n't sound like a good idea and it does n't make much sense to me ( e.g. , it wrecks congestion control ) . 
 No , you should not be sending 50 short messages on a single connection . That would cause a lot of havoc on the connection . This really is n't a problem if we 're looking at falling back between equivalent protocols . The protocols that will make sense to an application need to have equivalent contracts if they are n't rewriting any code . So , I can use the same code for TCP or TLS over TCP or a QUIC Stream etc , since those all look the same . But if I 'm writing discrete messages that are very short on a connection , I need a protocol that supports that — my use case here is IKE sending short messages either over UDP or over Length - Value frames on TCP ( RFC8229 ) . HTTP messages over TLS or QUIC or whatever also are equivalent . 
 I do n't see why 50 short messages on a single connection would cause a problem . It really should n't ! What if I 'm writing a game that only needs one connection and sends many small updates over it ? So if you implement IKE over the transport system , IKE is understood ( can be parsed ) from the receiver side data stream , even if you hand it over as individual data blocks - you do n't need to tell the receiver - side IKE instance where its message ends . Where 's the problem ? I do n't understand what this has to do with " end of message =  " and why anyone would need that . It does n't make sense to me and sounds like unnecessary trouble . 
 50 short messages is fine , if the protocol knows what a message is . And you could have a degenerate " framer " over TCP which does n't add any bytes to indicate length or framing and just puts the Message content down in bytes — essentially , ignore any completion markers . But it should also be possible to communicate over a stream or long message : " I was writing a long gigabyte message , and now I 'm done " . 
 Hm . Sure . And if an app wants to make absolutely sure this " gigabyte message , and now I 'm done " information reaches the other end , it can always use Close . 
 Yeah , that works for TCP , but say I have a framing protocol on top of TCP — HTTP for example , and I 'm doing pipelining of messages . I can still have mega - byte or giga - byte long messages that I send in multiple chunks on this Connection , and the completion bit tells the protocol when the HTTP request is done , and we need to start the headers for the next one . 
 Sure ! No problem in this case either 
 ... but there is text along these lines that does n't sound right to me in the implementation draft , section 5.1.1 . This : The effect of the application sending a Message is determined by the top - level protocol in the established Protocol Stack . That is , if the top - level protocol provides an abstraction of framed messages over a connection , the application will be able to send multiple Messages on that connection , even if the framing protocol is built on a byte - stream protocol like TCP . as if the top - level protocol is inside the transport system and that top - level protocol must provide framed messages , or else multiple messages can not be sent over a byte - stream protocol like TCP . However : it 's nice if there is a framing protocol like HTTP or whatever on top of your internal stack , but it should also be possible to send multiple messages just over TCP . This should n't be a problem as long as my receiver - side application can detect where messages begin and end . 
 I think that what you 're describing is the " degenerate framing protocol " that I referred to earlier — yes , we can let something just write on the stream , but either : You have actual boundaries that can be detected , in which case we call this a framing protocol ( may be very very simple ) You do n't have any on - the - wire detectable boundaries , in which case you can have a degenerate framer that just lays down the content of the Message without boundaries . You can do this , but it 's a bit silly . Or you can just treat the stream as one big message if you want . 
 When you say " can be detected , in which case we call this a framing protocol " , can that be outside the transport system or not ? My complaint is about the text sounding as if the framing protocol must be inside the transport system . With what I call an " Application - Framed Bytestream " , a sender - side application simply hands over messages , and as long as the receiver - side application ( all outside the transport system ! ) is able to detect them , these messages can go over e.g. SCTP , where they can arrive out - of - order , or TCP , where they will arrive in - order , without requiring any special intervention - it 's always the same receive call . You may receive your messages in parts but they are in - order " inside " ( of course ) and you ( the receiver - side app ) can detect where they end . 
 By " can be detected " , I meant " is represented in the on - the - wire format such that both the local and remote endpoints are explicitly communicating this message boundary " , like HTTP or SCTP . If you just lay the bytes out in TCP without any other encoding , you 're doing Message boundaries that only make sense to one end ( which can be okay , but is a bit degenerate ) . 
 perhaps we 're finally on the same page : yes I mean a case where only one end ( the sender side ) of the transport system knowing about the message boundaries in case of TCP , but the application on top knows the boundaries , on both the sender and receiver side . The point of my presentations and text about the " Application - Framed Bytestream " was that this is enough : you can do everything you want with this , you do n't actually need anything else . And it makes ideas like informing the receiver app about partial message reception unnecessary . The idea is that the receiver only accepts data blocks until it sees a message boundary that it knows about - then it has a complete message . 
 lgtm
Paragraph (version A):
Functionality that is common across multiple transport protocols
should be accessible through a unified set of API calls.  An
application should be able to implement logic for its basic use of
transport networking (establishing the transport, and sending and
receiving content) once, and expect that implementation to continue
to function as the transports change.
Paragraph (version B):
Functionality that is common across multiple transport protocols
should be accessible through a unified set of API calls.  An
application should be able to implement logic for its basic use of
transport networking (establishing the transport, and sending and
receiving data) once, and expect that implementation to continue to
function as the transports change.
Paragraph (version A):
A specialized feature may be required by an application only when
using a specific protocol, and not when using others.  For example,
if an application is using UDP, it may require control over the
checksum or fragmentation behavior for UDP; if it used a protocol to
frame its content over a byte stream like TCP, it would not need
these options.  In such cases, the API should expose the features in
such a way that they take effect when a particular protocol is
selected, but do not imply that only that protocol may be used if
there are equivalent options.
Paragraph (version A):
Other specialized features, however, may be strictly required by an
application and thus constrain the set of protocols that can be used.
For example, if an application requires encryption of its transport
content, only protocol stacks that include some transport security
protocol are eligible to be used.  A Transport Services API must
allow applications to define such requirements and constrain the
system's options.  Since such options are not part of the core,
common features, however, it should be simple for an application to
modify its set of constraints and change the set of allowable
protocol features without changing the core implementation.
Paragraph (version B):
A specialized feature may be required by an application only when
using a specific protocol, and not when using others.  For example,
if an application is using UDP, it may require control over the
checksum or fragmentation behavior for UDP; if it used a protocol to
frame its data over a byte stream like TCP, it would not need these
options.  In such cases, the API should expose the features in such a
way that they take effect when a particular protocol is selected, but
do not imply that only that protocol may be used if there are
equivalent options.
Paragraph (version B):
Other specialized features, however, may be strictly required by an
application and thus constrain the set of protocols that can be used.
For example, if an application requires encryption of its transport
data, only protocol stacks that include some transport security
protocol are eligible to be used.  A Transport Services API must
allow applications to define such requirements and constrain the
system's options.  Since such options are not part of the core,
common features, however, it should be simple for an application to
modify its set of constraints and change the set of allowable
protocol features without changing the core implementation.
Paragraph (version A):
Connection: A Connection object represents an active transport
protocol instance that can send and/or receive Content between a
Local Endpoint and a Remote Endpoint.  It holds state pertaining
to the underlying transport protocol instance and any ongoing data
transfer.  This represents, for example, an active connection in a
connection-oriented protocol such as TCP, or a fully-specified
5-tuple for a connectionless protocol such as UDP.
Paragraph (version B):
Connection: A Connection object represents an active transport
protocol instance that can send and/or receive Messages between a
Local Endpoint and a Remote Endpoint.  It holds state pertaining
to the underlying transport protocol instance and any ongoing data
transfer.  This represents, for example, an active connection in a
connection-oriented protocol such as TCP, or a fully-specified
5-tuple for a connectionless protocol such as UDP.
Paragraph (version A):
Initiate() is the primary action that an application can take to
create a Connection to a remote endpoint, and prepare any required
local or remote state to be able to send and/or receive content.
For some protocols, this may initiate a server-to-client style
handshake; for other protocols, this may just establish local
state; and for peer-to-peer protocols, this may begin the process
of a simultaneous open.  The Initiate() action consumes a
Preconnection object and creates a Connection object.  Resolution
of the remote endpoint identifier occurs during the Initiate()
call.
Paragraph (version B):
Initiate() is the primary action that an application can take to
create a Connection to a remote endpoint, and prepare any required
local or remote state to be able to send and/or receive Messages.
For some protocols, this may initiate a server-to-client style
handshake; for other protocols, this may just establish local
state; and for peer-to-peer protocols, this may begin the process
of a simultaneous open.  The Initiate() action consumes a
Preconnection object and creates a Connection object.  Resolution
of the remote endpoint identifier occurs during the Initiate()
call.
Paragraph (version A):
Content: A Content object is a unit of data that can be
represented as bytes that can be transferred between two endpoints
over a transport connection.  The bytes within a unit of Content
are assumed to be ordered within the unit itself.  That is, if an
application does not care about the order in which a peer receives
two distinct spans of bytes, those spans of bytes are considered
independent units of Content.  Content may or may not be usable if
incomplete or corrupted.  Boundaries of Content may or may not be
understood or transmitted by transport protocols.  That is, what
one application considers to be two units of Content sent on a
stream-based transport may be treated as a single unit of Content
by the application on the other side.
Paragraph (version A):
Send() is the action to transmit Content over a Connection to a
remote endpoint.  The interface to Send may include options
specific to how this Content is to be sent.  Status of the Send
operation may be delivered back to the application in an event
events.
Paragraph (version A):
Receive() is an action that indicates that the application is
ready to asynchronously accept Content over a Connection from a
Remote Endpoint, while the Content itself will be delivered in an
event events.  The interface to Receive may include options
specific to the Content that is to be delivered to the
application.
Paragraph (version B):
Message: A Message object is a unit of data that can be
represented as bytes that can be transferred between two endpoints
over a transport connection.  The bytes within a Message are
assumed to be ordered within the unit itself.  That is, if an
application does not care about the order in which a peer receives
two distinct spans of bytes, those spans of bytes are considered
independent Messages.  Messages may or may not be usable if
incomplete or corrupted.  Boundaries of a Message may or may not
be understood or transmitted by transport protocols.  That is,
what one application considers to be two Messages sent on a
stream-based transport may be treated as a single Message by the
application on the other side.
Paragraph (version B):
Send() is the action to transmit a Message or partial Message over
a Connection to a Remote Endpoint.  The interface to Send may
include options specific to how the Message's content is to be
sent.  Status of the Send operation may be delivered back to the
application in an event events.
Paragraph (version B):
Receive() is an action that indicates that the application is
ready to asynchronously accept a Message over a Connection from a
Remote Endpoint, while the Message content itself will be
delivered in an event events.  The interface to Receive may
include options specific to the Message that is to be delivered to
the application.
Paragraph (version A):
Connection Ready: A Connection Ready event signals to an
application that a given Connection is ready to send and/or
receive Content.  If the Connection relies on handshakes to
establish state between peers, then it is assumed that these steps
have been taken.
Paragraph (version A):
Connection Finished: A Connection Finished event signals to an
application that a given Connection is no longer usable for
sending or receiving Content.  This should deliver an error to the
application that describes the nature of the termination.
Paragraph (version A):
Content Received: A Content Received event delivers received
content to the application, based on a Receive action.  This may
include an error if the Receive action cannot be satisfied due to
the Connection being closed.
Paragraph (version A):
Content Sent: A Content Sent event notifies the application of the
status of its Send action.  This may be an error if the Content
cannot be sent, or an indication that Content has been processed
by the protocol stack.
Paragraph (version B):
Connection Ready: A Connection Ready event signals to an
application that a given Connection is ready to send and/or
receive Messages.  If the Connection relies on handshakes to
establish state between peers, then it is assumed that these steps
have been taken.
Paragraph (version B):
Connection Finished: A Connection Finished event signals to an
application that a given Connection is no longer usable for
sending or receiving Messages.  This should deliver an error to
the application that describes the nature of the termination.
Paragraph (version B):
Message Received: A Message Received event delivers received
Message content to the application, based on a Receive action.
This may include an error if the Receive action cannot be
satisfied due to the Connection being closed.
Paragraph (version B):
Message Sent: A Message Sent event notifies the application of the
status of its Send action.  This may be an error if the Message
cannot be sent, or an indication that Message has been processed
by the protocol stack.
Paragraph (version A):
Protocol Instance: A Protocol Instance is a single instance of one
protocol, including any state it has necessary to establish
connectivity or send and receive content.
Paragraph (version A):
Protocol Stack: A Protocol Stack is a set of Protocol Instances
(including relevant application, security, transport, or Internet
protocols) that are used together to establish connectivity or
send and receive content.  A single stack may be simple (a single
transport protocol instance over IP), or complex (multiple
application protocol streams going through a single security and
transport protocol, over IP; or, a multi-path transport protocol
over multiple transport sub-flows).
Paragraph (version B):
Protocol Instance: A Protocol Instance is a single instance of one
protocol, including any state it has necessary to establish
connectivity or send and receive Messages.
Paragraph (version B):
Protocol Stack: A Protocol Stack is a set of Protocol Instances
(including relevant application, security, transport, or Internet
protocols) that are used together to establish connectivity or
send and receive Messages.  A single stack may be simple (a single
transport protocol instance over IP), or complex (multiple
application protocol streams going through a single security and
transport protocol, over IP; or, a multi-path transport protocol
over multiple transport sub-flows).