Draft: draft-trammell-taps-interface

Commentary: These commits separate Endpoint into LocalEndpoint and RemoteEndpoint types , and update the rest of the documents to match . 
 Since the previous comment was on a now - hidden commit : I agree that a raw Endpoint that is n't Remote or Local may not be used in any of the externally - facing APIs to create a Connection . From an API standpoint , it 's fine to require a specific type of the general class . All I 'm arguing is that in our list of concepts and definitions , we need to define that there is a basic concept of an Endpoint , that is n't necessarily local or remote , since local and remote only become relevant in the context of a connection , or some communication . Having a definition of Remote and Local Endpoints without ever saying what an endpoint is ( or duplicating the definitions , saying Local : See the generic parts of Remote ) seems unnecessary . Also , from an implementation standpoint , the Endpoint really is n't as trivial as you 're saying . It 's not just a matter of displaying . Since we do n't use sockaddrs in the exposure of the address form of endpoint , the Endpoint does the following : Can create hostname / address from a string , which automatically parses into a hostname , IPv4 , or IPv6 address . If the IPv6 address is a mapped v4 address , it parses that out . Create port with a string or number ( " http " or " 80 " ) Extract address byte encoding for use in forming packets Extract port in either network or host byte order Extract IP address family Do subnet or DNS name segment matching and comparisons between endpoints ( are these two in the same slash # ) Allow definition of custom endpoint subclasses that can resolve into standard types All of these operations are useful for both local and remote endpoints , such as when you are filling out or parsing headers within the protocol stack . If as an implementation , I was told to make the LocalEndpoint and RemoteEndpoint completely different classes in a strongly typed language , I would need to redefine all of these ? If they 're not subclasses of the same Endpoint generic class , at least they both implement the template / protocol of an Endpoint so we can re - use some logic . To that end , defining the concept of Endpoint first , then explaining Remote and Local Endpoint , still makes sense in the architecture . 
 I 'd say that what you described about the use of endpoint should probably be noted in the implementation draft . I 'm still not sure if  should be noted in the architecture because it 's not an architectural concept but rather an implementation issue , but I think I 'm okay to define it for sake of having a good definition we can refer to . I 'm still wondering if we generate new remotes in the resolution step or if we store all we know about one actual endpoint in the same remote . If we get multiple IP addresses for the same URL , is that multiple hosts serving the same content , or one entity that is presumably distributed over multiple physical ( frontend ) host , or one host having multiple addresses . My answer would be , as we do n't know the actually setup , we should keep all information we learned based on the initial input provided for the Remote within that Remote object . I guess this goes all back to the ( StackEvo ) question : what is an endpoint ? So maybe good to have a definition ... 
 i 'm holding off on my big editorial pass until this lands ... 
 I think that while the concept is most critical for the implementation , it still affects the application developer that uses the API . If , as a developer , I want to create a Remote or Local Endpoint , I need to know how to specify my address / hostname / port ( which needs to be common types between the two ) . We also have application level tests that do things like create a listener , extract the local endpoint , and then create a connection back to ourselves over loopback , using the the local as a remote . It would be strange if that was n't possible . Mainly , I 'm just arguing we should define the existence of a generic " address / hostname / service " blob from the start for clarity . Removing the definition of the base endpoint concept did n't make the remote or local endpoints stronger definition ; it just removed clarifying text that 's general to both . 
 on reflection , putting endpoint into the architecture seems okay , but I 'm still unconvinced we need it in the API . Or , at least , before we add Endpoint to the API , we need to more clearly understand the range of different endpoint types to really see what 's common between them . I wonder if things like , e.g. , LocalEndpoints obtained via a TURN server , break some of the assumptions of commonality . I was thinking that would return a list of objects . Maybe they should reference what they were resolved from , but I do n't think we have any way of knowing whether they refer to the same host or not . 
 I agree on the point for the API document . I do n't think we need to have the generic endpoint there for now , as long as the architecture explains the relationship . With regards to resolution , our implementation takes an endpoint , and resolves it into a set of endpoints ( of a different type , generally ; used for bonjour service -hostname , hostname -address , v4 address -NAT64 translated v6 address , etc ) . We 've found it useful for the endpoint to track the " parent " endpoint it was derived from , mainly so that when protocols that care about the original hostnames need to access them ( like TLS for cert validation , or SOCKS for figuring out the original hostname to request to the proxy ) , it 's available . Also useful for doing per - domain policy evaluation for flows . 
 ack - will try to write this up tomorrow ( today was a write - off due to lecturing ... ) 
 Looks good !
Paragraph (version A):
The Local Endpoint MUST be specified if the Preconnection is used to
Listen() for incoming connections, but is OPTIONAL if it is used to
Initiate() connections.  The Remote Endpoint MUST be specified in the
Preconnection is used to Initiate() connections, but is OPTIONAL if
it is used to Listen() for incoming connections.
Paragraph (version B):
The LocalEndpoint MUST be specified if the Preconnection is used to
Listen() for incoming connections, but is OPTIONAL if it is used to
Initiate() connections.  The RemoteEndpoint MUST be specified in the
Preconnection is used to Initiate() connections, but is OPTIONAL if
it is used to Listen() for incoming connections.
Paragraph (version B):
The transport services API uses the LocalEndpoint and RemoteEndpoint
types to refer to the endpoints of a transport connection.  Subtypes
of these represent various different types of endpoint identifiers,
such as IP addresses, DNS names, and interface names, as well as port
numbers and service names.
Paragraph (version A):
The transport services API resolves names internally, when Initiate()
is called to transform a Preconnection object into a Connection.  The
API does not need an explicit name resolution method, although it may
be useful to provide one for reasons unrelated to transport.
Paragraph (version B):
Multiple endpoint identifiers can be specified for each LocalEndpoint
and RemoteEndoint.  For example, a LocalEndpoint could be configured
with two interface names, or a RemoteEndpoint could be specified via
both IPv4 and IPv6 addresses.  The multiple identifiers refer to the
same endpoint.
Paragraph (version B):
The transport services API will resolve names internally, when the
Initiate(), Listen(), or Rendezvous() method is called establish a
connection.  The API does not need the application to resolve names,
and premature name resolution can damage performance by limiting the
scope for alternate path discovery during connection establishment.
The Resolve() method is, however, provided to resolve a LocalEndpoint
or a RemoteEndpoint in cases where this is required, for example with
some NAT traversal protocols (see rendezvous).
Paragraph (version A):
Transport Preferences drive protocol selection and path selection on
connection establishment.  Not all transport protocols work on all
paths.  Thus, transport protocol selection is tied to path selection,
which may involve choosing between multiple local interfaces that are
connected to different access networks.
Paragraph (version B):
Transport Preferences drive protocol selection and path selection on
connection establishment.  Since there could be paths over which some
transport protocols are unable to operate, or remote endpoints that
support only specific network addresses or transports, transport
protocol selection is necessarily tied to path selection.  This may
involve choosing between multiple local interfaces that are connected
to different access networks.
Paragraph (version A):
Suggest a timeout to the peer: This boolean property specifies
whether an application considers it useful to propose a timeout
until the connection is assumed to be lost.  This property applies
to Connections and Connection Groups.  This is not a strict
requirement.  The default is to have this option.
Paragraph (version B):
Suggest a timeout to the RemoteEndpoint: This boolean property
specifies whether an application considers it useful to propose a
timeout until the connection is assumed to be lost.  This property
applies to Connections and Connection Groups.  This is not a
strict requirement.  The default is to have this option.
Paragraph (version A):
Protocol Properties represent the configuration of a transport
protocol once it has been selected.  A transport protocol may not
support all Protocol Properties, depending on the available transport
features.  As with Transport Preferences (transport-prefs), Protocol
Properties are specified on the Preconnection object, and are using
during initiation of a Connection to help the system choose an
appropriate transport.  The system will only actually set those
protocol properties that are actually supported by the chosen
transport protocol.  These properties all apply to Connections and
Connection groups.  The default settings of these properties depends
on the chosen protocol and on the system configuration.
Paragraph (version A):
Set timeout for aborting Connection: This numeric property
specifies how long to wait before aborting a Connection attempt.
It is given in seconds.
Paragraph (version A):
Set timeout to suggest to the peer: This numeric property
specifies the timeout to propose to the peer.  It is given in
seconds.
Paragraph (version B):
Set timeout to suggest to the RemoteEndpoint: This numeric
property specifies the timeout to propose to the RemoteEndpoint.
It is given in seconds.
Paragraph (version A):
Pre-shared keying material: Used to install pre-shared keying
material established out-of-band.  Each pre-shared keying material
is associated with some identity that typically identifies its use
or has some protocol-specific meaning to peers.
Paragraph (version A):
Trust verification callback: Invoked when a peer's trust must be
validated before the handshake protocol can proceed.
Paragraph (version B):
Pre-shared keying material: Used to install pre-shared keying
material established out-of-band.  Each pre-shared keying material
is associated with some identity that typically identifies its use
or has some protocol-specific meaning to the RemoteEndpoint.
Paragraph (version B):
Trust verification callback: Invoked when a RemoteEndpoint's trust
must be validated before the handshake protocol can proceed.
Paragraph (version A):
Before calling Initiate, the caller must have populated a
Preconnection object with local and remote endpoint specifiers, as
well as all parameters necessary for candidate selection.  After
calling Initiate, no further parameters may be bound to the
Connection.  The Initiate() call consumes the Preconnection and
creates a Connection object.  A Preconnection can only be initiated
once.
Paragraph (version A):
Once Initiate is called, the candidate Protocol Stack(s) may cause
one or more transport-layer connections to be created to the
specified remote endpoint.  The caller may immediately begin sending
Content on the Connection (see sending) after calling Initate, though
it may wait for one of the following events before doing so.
Paragraph (version B):
Before calling Initiate, the caller must have populated a
Preconnection object with a RemoteEndpoint specifier, optionally a
LocalEndpoint specifier (if not specified, the system will attempt to
determine a suitable LocalEndpoint), as well as all parameters
necessary for candidate selection.  After calling Initiate, no
further parameters may be bound to the Connection.  The Initiate()
call consumes the Preconnection and creates a Connection object.  A
Preconnection can only be initiated once.
Paragraph (version B):
Once Initiate is called, the candidate Protocol Stack(s) may cause
one or more candidate transport-layer connections to be created to
the specified remote endpoint.  The caller may immediately begin
sending Content on the Connection (see sending) after calling
Initate(); note that any idempotent data sent while the Connection is
being established may be sent multiple times or on multiple
candidates.
Paragraph (version A):
An InitiateError occurs either when the set of local and remote
specifiers and transport and cryptographic parameters cannot be
fulfilled on a connection for initiation (e.g. the set of available
Paths and/or Protocol Stacks meeting the constraints is empty), when
the remote specifier cannot be resolved, or when no transport-layer
connection can be established to the remote endpoint (e.g.  because
the remote endpoint is not accepting connections, or the application
is prohibited from opening a connection by the operating system).
Paragraph (version B):
An InitiateError occurs either when the set of transport and
cryptographic parameters cannot be fulfilled on a connection for
initiation (e.g. the set of available Paths and/or Protocol Stacks
meeting the constraints is empty) or reconciled with the local and/or
remote endpoints; when the remote specifier cannot be resolved; or
when no transport-layer connection can be established to the remote
endpoint (e.g. because the remote endpoint is not accepting
connections, or the application is prohibited from opening a
connection by the operating system).
Paragraph (version A):
Before calling Listen, the caller must have initialized the
Preconnection during the pre-establishment phase with local endpoint
specifiers, as well as all parameters necessary for Protocol Stack
selection.  The Listen() action consumes the Preconnection.  Once
Listen() has been called, no further parameters may be bound to the
Preconnection, and no subsequent establishment call may be made on
the Preconnection.
Paragraph (version A):
The ConnectionReceived event occurs when a remote endpoint has
established a transport-layer connection to this Preconnection or
when the remote endpoint has sent its first Content, causing a new
Connection to be created.  The resulting Connection is contained
within the ConnectionReceived event, and is ready to use as soon as
it is passed to the application via the event.
Paragraph (version A):
A ListenError occurs either when the set of local specifier,
transport and cryptographic parameters cannot be fulfilled for
listening, when the local specifier cannot be resolved, or when the
application is prohibited from listening by the operating system.
Paragraph (version A):
An RendezvousError occurs when...
Paragraph (version B):
Before calling Listen, the caller must have initialized the
Preconnection during the pre-establishment phase with a LocalEndpoint
specifier, as well as all parameters necessary for Protocol Stack
selection.  A RemoteEndpoint may optionally be specified, to
constrain what connections are accepted.  The Listen() action
consumes the Preconnection.  Once Listen() has been called, no
further parameters may be bound to the Preconnection, and no
subsequent establishment call may be made on the Preconnection.
Paragraph (version B):
The ConnectionReceived event occurs when a RemoteEndpoint has
established a transport-layer connection to this Preconnection (for
connection-oriented transport protocols), or when the first Content
has been received from the RemoteEndpoint (for connectionless
protocols), causing a new Connection to be created.  The resulting
Connection is contained within the ConnectionReceived event, and is
ready to use as soon as it is passed to the application via the
event.
Paragraph (version B):
A ListenError occurs either when the Preconnection cannot be
fulfilled for listening, when the LocalEndpoint (or RemoteEndpoint,
if specified) cannot be resolved, or when the application is
prohibited from listening by policy.
Paragraph (version B):
The Preconnection object must be specified with both a LocalEndpoint
and a RemoteEndpoint, and also the transport and security parameters
needed for protocol stack selection.  The Rendezvous() action causes
the Preconnection to listen on the LocalEndpoint for an incoming
connection from the RemoteEndpoint, while simultaneously trying to
establish a connection from the LocalEndpoint to the RemoteEndpoint.
This corresponds to a TCP simultaneous open, for example.
Paragraph (version B):
The Rendezvous() action consumes the Preconnection.  Once
Rendezvous() has been called, no further parameters may be bound to
the Preconnection, and no subsequent establishment call may be made
on the Preconnection.
Paragraph (version B):
The RendezvousDone<> event occurs when a connection is established
with the RemoteEndpoint.  For connection-oriented transports, this
occurs when the transport-layer connection is established; for
connectionless transports, it occurs when the first Content is
received from the RemoteEndpoint.  The resulting Connection is
contained within the RendezvousDone<> event, and is ready to use as
soon as it is passed to the application via the event.
Paragraph (version B):
An RendezvousError occurs either when the Preconnection cannot be
fulfilled for listening, when the LocalEndpoint or RemoteEndpoint
cannot be resolved, when no transport-layer connection can be
established to the RemoteEndpoint, or when the application is
prohibited from rendezvous by policy.
Paragraph (version B):
The Resolve() call returns a list of Preconnection objects, that
represent the concrete addresses, local and server reflexive, on
which a Rendezvous() for the Preconnection will listen for incoming
connections.  This list can be passed to a peer via a signalling
protocol, such as SIP or WebRTC, to configure the remote.
Paragraph (version A):
There is only one Protocol Property that is not entangled, i.e. it is
a separate per-Connection Property for individual Connections in the
group: a priority.  This priority, which can be represented as a non-
negative integer or float, expresses a desired share of the
Connection Group's available network capacity, such that an ideal
transport system implementation would assign the Connection the
capacity share P x C/sum_P, where P = priority, C = total available
capacity and sum_P = sum of all priority values that are used for the
Connections in the same Connection Group.  The priority setting is
purely advisory; no guarantees are given.
Paragraph (version B):
There is only one Protocol Property that is not entangled, i.e., it
is a separate per-Connection Property for individual Connections in
the group: a priority.  This priority, which can be represented as a
non-negative integer or float, expresses a desired share of the
Connection Group's available network capacity, such that an ideal
transport system implementation would assign the Connection the
capacity share P x C/sum_P, where P = priority, C = total available
capacity and sum_P = sum of all priority values that are used for the
Connections in the same Connection Group.  The priority setting is
purely advisory; no guarantees are given.
Paragraph (version A):
The Sent event occurs when a previous Send action has completed, i.e.
when the data derived from the Content has been passed down or
through the underlying Protocol Stack and is no longer the
responsibility of the implementation of this interface.  The exact
disposition of Content when the Sent event occurs is specific to the
implementation and the constraints on the Protocol Stacks implied by
the Connection's transport parameters.  The Sent event contains an
implementation-specific reference to the Content to which it applies.
Paragraph (version B):
The Sent event occurs when a previous Send action has completed,
i.e., when the data derived from the Content has been passed down or
through the underlying Protocol Stack and is no longer the
responsibility of the implementation of this interface.  The exact
disposition of Content when the Sent event occurs is specific to the
implementation and the constraints on the Protocol Stacks implied by
the Connection's transport parameters.  The Sent event contains an
implementation-specific reference to the Content to which it applies.
Paragraph (version A):
As with sending, the type of the Content to be passed is dependent on
the implementation, and on the constraints on the Protocol Stacks
implied by the Connection's transport parameters.  The Content may
also contain metadata from protocols in the Protocol Stack for
logging and debugging purposes.  In particular, when this information
is available, the value of the Explicit Congestion Notification (ECN)
field is contained in such metadata.
Paragraph (version B):
As with sending, the type of the Content to be passed is dependent on
the implementation, and on the constraints on the Protocol Stacks
implied by the Connection's transport parameters.  The Content may
also contain metadata from protocols in the Protocol Stack; which
metadata is available is Protocol Stack dependent.  In particular,
when this information is available, the value of the Explicit
Congestion Notification (ECN) field is contained in such metadata.
This information can be used for logging and debugging purposes, and
for building applications which need access to information about the
transport internals for their own operation.
Paragraph (version A):
For preserving message boundaries over stream transports, this
interface provides receiver-side deframing.  This facility is based
on the observation that, since many of our current application
protocols evolved over TCP, which does not provide message boundary
preservation, and since many of these protocols require message
boundaries to function, each application layer protocol has defined
its own framing.  A Deframer allows an application to push this
deframing down into the interface, in order to transform an octet
stream into a sequence of Content.
Paragraph (version B):
For preserving message boundaries over stream transports, this
interface provides receiver-side de-framing.  This facility is based
on the observation that, since many of our current application
protocols evolved over TCP, which does not provide message boundary
preservation, and since many of these protocols require message
boundaries to function, each application layer protocol has defined
its own framing.  A Deframer allows an application to push this de-
framing down into the interface, in order to transform an octet
stream into a sequence of Content.
Paragraph (version A):
The status of the Connection, which can be one of the following:
Pre-Establishment, Establishment in progress, Established,
Listening, Rendezvous in progress, Closed.
Paragraph (version A):
Close terminates a Connection after satisfying all the requirements
that were specified regarding the delivery of Content that the
application has already given to the transport system.  For example,
if reliable delivery was requested for Content handed over before
calling Close, the transport system will ensure that such Content is
indeed delivered.  If the peer still has data to send, it cannot be
received after this call.
Paragraph (version A):
The Closed event can inform the application that the peer has closed
the Connection; however, there is no guarantee that a remote close
will be signaled.
Paragraph (version B):
Close terminates a Connection after satisfying all the requirements
that were specified regarding the delivery of Content that the
application has already given to the transport system.  For example,
if reliable delivery was requested for Content handed over before
calling Close, the transport system will ensure that such Content is
indeed delivered.  If the RemoteEndpoint still has data to send, it
cannot be received after this call.
Paragraph (version B):
The Closed event can inform the application that the RemoteEndpoint
has closed the Connection; however, there is no guarantee that a
remote close will be signaled.