<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc2629 version 1.2.3 -->

<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
]>

<?rfc toc="yes"?>
<?rfc sortrefs="yes"?>
<?rfc symrefs="yes"?>

<rfc ipr="trust200902" docName="draft-tiesel-taps-socketintents-bsdsockets-00" category="info">

  <front>
    <title abbrev="Socket Intents for BSD Sockets">A Socket Intents Prototype for the BSD Socket API – Experiences, Lessons Learned and Considerations</title>

    <author initials="P.S." surname="Tiesel" fullname="Philipp S. Tiesel">
      <organization>Berlin Institute of Technology</organization>
      <address>
        <postal>
          <street>Marchstr. 23</street>
          <city>Berlin</city>
          <country>Germany</country>
        </postal>
        <email>philipp@inet.tu-berlin.de</email>
      </address>
    </author>
    <author initials="T." surname="Enghardt" fullname="Theresa Enghardt">
      <organization>Berlin Institute of Technology</organization>
      <address>
        <postal>
          <street>Marchstr. 23</street>
          <city>Berlin</city>
          <country>Germany</country>
        </postal>
        <email>theresa@inet.tu-berlin.de</email>
      </address>
    </author>

    <date year="2017" month="July" day="03"/>

    <area>Transport</area>
    <workgroup>TAPS Working Group</workgroup>
    <keyword>Internet-Draft</keyword>

    <abstract>


<t>This document describes a prototype implementation of
Socket Intents <xref target="I-D.tiesel-taps-socketintents"/> for the
BSD Socket API as an illustrative example
how Socket Intents could be implemented.
It described the experiences made with the prototype
and lessons learned from trying to extend the BSD Socket API.</t>



    </abstract>


  </front>

  <middle>


<section anchor="introduction" title="Introduction">

<t>With the proliferation of devices that have multiple paths to the
internet and an increasing number of transport protocols available, the number
of transport options to serve a communication unit explodes.
Implementing a heuristic or strategy for choosing from this
overwhelming set of transport options by each application puts a huge
burden on the application developer.
Thus, the decisions regarding all transport options mentioned so far
should be supported and, if requested by the application, automated
within the transport layer.</t>

<t>Socket Intents <xref target="I-D.tiesel-taps-socketintents"/> allow an application
to express what it knows, assumes, expects or wants to prioritize
regarding its own network communication.
This information can than be used by the OS to perform destination
selection, path selection and transport protocol stack instance
selection.</t>

<t>Our Socket Intents prototype for the BSD Socket API is a first
attempt to automate transport option selection within the OS.
It is primarily targeted at path and destination address selection and
tries to be as close as possible to the semantics of the BSD Socket API.
The prototype mostly excludes the problem of transport protocol stack
instance selection, which is more closely discussed in
<xref target="I-D.tiesel-taps-communitgrany"/>.</t>

<t>We implemented the prototype as a wrapper for the BSD Socket API
that communicates to a central Multiple Access Manager that makes the
actual decisions and can optimize across applications.
The whole implementation was done in about 15k lines of C code.
The code is available at <eref target="https://github.com/fg-inet/socket-intents/">Github</eref>
under BSD License.</t>

<t>This document describes our Socket Intents prototype for the
BSD Socket API.
It details important aspects of the implementation and the API
variants we developed over time based on lessons learned. Finally, it
summarizes these lessons and points out why the BSD Socket API is not
particularly well suited to integrate automated transport protocol stack
instance selection. Furthermore, it describes the limitations for destination
address and path selection within the BSD Socket API.</t>

</section>
<section anchor="prototype-architecture" title="Prototype Architecture">

<t>The Socket Intents prototype consists of the following components, also
shown in <xref target="prototypearch"/>:</t>

<t><list style="symbols">
  <t>The Socket Intents API, a BSD Socket API wrapper for applications to
use, including a representation of the actual Socket Intents.</t>
  <t>The Socket Intents Library which implements the Socket Intents API.
It sends requests to the Multiple Access Manager, e.g. before
establishing a connection, and gets back a response regarding what
interface to use.</t>
  <t>The Multiple Access Manager (MAM), a daemon which gets informed about
all application requests and has knowledge of the available network
interfaces.</t>
  <t>The Policy, a dynamically loaded library hosted by the MAM. It
chooses which of the available interfaces to use based on the
available knowledge about them and the Socket Intents.</t>
  <t>Data collectors that that reside inside the MAM and that provide
information like bandwidth usage, smoothed RTT estimate and RSSI for wireless links to the policy.</t>
</list></t>

<figure title="Components of the Socket Intents Prototype" anchor="prototypearch"><artwork align="center"><![CDATA[
+------------------------+
|      Application       |
|                        |                   +-------------------+
+-{ Socket Intents API }-+  (MAM Request)    |  Multiple Access  |
|                        | ----------------> |      Manager      |
|     Socket Intents     |  (MAM Response)   | +---------------+ |
|        Library         | <---------------- | |    Policy     | |
+------------------------+                   | +---------------+ |
|      BSD Sockets       |                   | |Data Collectors| |
+------------------------+                   +-+---------------+-+
]]></artwork></figure>

</section>
<section anchor="multiple-access-manager" title="Multiple Access Manager">

<t>The Multiple Access Manager (MAM) is the central transport option
selection instance on a host.
It is realized as a daemon that runs in userspace and receives<vspace />
requests from each application that uses the Socket Intents Library.</t>

<t>The MAM hosts the Policy, which is the actual decision making 
component, e.g., deciding which source address and therefore which 
source interface to use.
Upon events, such as an application requesting to resolve a name or to
connect a socket (see <xref target="apivar"/> for details), the Socket Intents
Library issues a MAM request and the MAM invokes a callback to the
policy – see <xref target="policy"/> for details - which can either communicate
its decision right away or defer its decision, e.g., when it has to 
wait for the results of name resolution.
The results and decisions are communicated back to the Socket
Intents Library through the MAM response, where they are applied to the
actual socket, see also <xref target="prototypearch"/>.</t>

<t>To support the policy, the MAM maintains a list of IP prefixes that are
configured on the local interfaces and available for outgoing
communications.
As destination address selection and path selection are highly 
dependent on each other, the MAM integrates DNS resolution and maintains 
separate resolver configurations per prefix (see <xref target="ANRW17-MH"/> for
further discussion on multiple PvDs and DNS resolution).
Furthermore, the MAM includes data collectors which periodically gather
statistics on the available paths, see <xref target="pmeasure"/> for details.</t>

<section anchor="policy" title="Policy">

<t>In the Socket Intents prototype, the Policy to select among the
available transport options is hosted by the MAM, see <xref target="prototypearch"/>.
We implement different interchangeable policies as dynamically loaded
libraries.
In our current implementation, only one policy can be active at a
given time.
When launching the MAM, the user has to choose a policy and supply a
policy configuration, which can contain arbitrary data.</t>

<t>Examples of policy configuration include:</t>

<t><list style="symbols">
  <t>A list of IP prefixes configured on local interfaces to consider as source for the communication</t>
  <t>Name server(s) to use for each of the IP prefixes</t>
  <t>Preferences to instrument the policy</t>
</list></t>

<t>The policy is initialized with this configuration and then waits for the
callback of an incoming MAM request.</t>

<t>Upon a callback, the policy can use information from the MAM request,
such as Socket Intents, and information available within the MAM, such
as recently measured path characteristics (see <xref target="pmeasure"/>), to make
decisions.</t>

<t>Policy decisions can include:</t>

<t><list style="symbols">
  <t>The source address(es) used for name resolution</t>
  <t>How to order the results of name resolution (i.e., preferring certain
IP addresses over others)</t>
  <t>Picking an IP protocol version</t>
  <t>Picking a transport protocol</t>
  <t>Setting socket options (e.g., disable TCP Nagle)</t>
  <t>Choosing a source address for the outgoing communication</t>
  <t>Reusing a socket from a given socket set (only for the API variant
described in <xref target="socketconnectapi"/>)</t>
</list></t>

<t>Note that in our current implementation, the policy is a piece of code 
which can in principle execute arbitrary instructions.
We assume this is acceptable for an experimental platform but would prefer
an abstract description like a domain-specific language for a 
production system.</t>

</section>
<section anchor="pmeasure" title="Path characteristics data collectors">

<t>The data collectors are implemented as a component of the MAM, within a
callback that is executed periodically, e.g., every 100 ms. When this
callback is invoked, the MAM passively gathers statistics about the
current usage and properties of the available local interfaces and
stores them in per-interface or per-network prefix data structures.</t>

<t>Measured properties include:</t>

<t><list style="symbols">
  <t>Minimum Smoothed Round Trip Time (SRTT) of current TCP connections
using a network prefix, as an estimate for last-mile latency</t>
  <t>Transmitted and received bytes per second over an interface within the
last callback period, as an estimate for current utilization</t>
  <t>Smoothed transmitted and received bytes per second over an
interface, as an estimate for recent utilization</t>
  <t>Maximum transmitted and received bytes per second over an interface
within the last 5 minutes, as an estimate for maximum available bandwidth</t>
  <t>On 802.11 interfaces, the Received Signal Strength Indicator (RSSI) of
the last received frame on that interface, as an estimate for
reception strength</t>
  <t>On 802.11 interfaces, the modulation rate of the last received and the
last transmitted unicast data frame on that interface, as an estimate
for the available data transmission rate on the first hop</t>
</list></t>

<t>When a policy callback is invoked, the policy can use the latest
measured properties to guide its decisions, see <xref target="policy"/>.</t>

<t>Note that we do not perform active measurements from within the MAM to
avoid overhead.</t>

</section>
</section>
<section anchor="socket-intents-representation" title="Socket Intents Representation">

<t>As described in <xref target="I-D.tiesel-taps-socketintents"/>, Socket Intents are
pieces of information about upcoming traffic. An application can share
the information that it has available through the Socket Intents API.</t>

<t>In our implementation, Socket Intents are represented as socket
options for get/setsockopt on its own socket option level (SOL_INTENTS).</t>

<t>For some of the API variants, we had to introduce socket option lists,
i.e., data structures that can hold multiple socket options and
therefore multiple Socket Intents.</t>

<t>Which of these variants is actually used depends on the API variant,
see <xref target="apivar"/>.</t>

</section>
<section anchor="apivar" title="The Socket Intents API Variants">

<t>The Socket Intents API is a wrapper around the BSD Socket API. It sends
requests to the Multiple Access Manager (MAM) at certain events, e.g.,
before a connection is established, and applies the suggestions that it
gets from the MAM, e.g., to bind to a certain local interface or to set
a certain socket option.</t>

<t>There exist different variants of this API, see <xref target="apivar"/>, that
try to fit different concepts:</t>

<t><list style="symbols">
  <t>The Classic API with muacc_context, see <xref target="muacccontextapi"/>, was
attempting to stick as close as possible to the call sequence of
BSD Sockets.</t>
  <t>The second variant of the classic API does all transport option
selection in <spanx style="verb">getaddrinfo</spanx>, see <xref target="getaddrinfoapi"/>.
This variant tries to simplify the implementation without deriving
too much from the usage of BSD Sockets.
It minimizes the changes to the BSD Socket API, but adds
additional overhead to the application.</t>
  <t>The <spanx style="verb">socketconnect</spanx> API, see <xref target="socketconnectapi"/>, tries to automate
as much functionality as possible and adds support for automating
connection caching.
It replaces the usual sequence of BSD Socket API calls with a
single call.</t>
</list></t>

<section anchor="muacccontextapi" title="Classic API / muacc_context">

<t>In the first variant, we add a parameter called <spanx style="verb">muacc_context</spanx> to
the BSD Socket API calls and to getaddrinfo.
This parameter holds properties provided by the socket calls and
retains them across function calls to enable automation of the
connection properties by our Socket Intents Prototype.
The shadow data structures behind the <spanx style="verb">muacc_context</spanx> parameter are
initialized by API wrapper at the time of the first call (which we
assume to be muacc_getaddrinfo most of the time) with most of its
fields empty.
Then within each call to our modified Socket API, it is filled with
data.</t>

<t>Properties include:</t>

<t><list style="symbols">
  <t>Socket file descriptor</t>
  <t>API calls that were already performed on this context</t>
  <t>domain, type, and protocol of the socket</t>
  <t>remote hostname</t>
  <t>remote address</t>
  <t>hints for resolving the remote address</t>
  <t>local address to bind to that the application requested</t>
  <t>local address to bind to that the MAM suggested</t>
  <t>current socket options that were set</t>
  <t>socket options suggested by MAM</t>
</list></t>

<section anchor="muaccgetaddrinfo" title="muacc_getaddrinfo()">

<t>This function resolves a host name or service to an addrinfo data
structure, usually containing an IP address or port.
Internally, the Socket Intents
prototype sends a <spanx style="verb">getaddrinfo</spanx> request to the MAM, which should do the
name resolution.
It can, e.g., resolve the name over multiple available interfaces at
the same time, and then order the results according to a policy
decision, or only return results obtained over a specific interface.</t>

<t>SIGNATURE:</t>

<t>int muacc_getaddrinfo(muacc_context_t *ctx, const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function is mostly called with an empty context, which is then filled within the function.</t>
  <t hangText='hostname:'>
  Remote host name to be resolved</t>
  <t hangText='servname:'>
  Remote service to be resolved</t>
  <t hangText='hints:'>
  Hints for resolving the name</t>
  <t hangText='res:'>
  Data structure for result of name resolution</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or an error code as provided by getaddrinfo().</t>

</section>
<section anchor="muaccsocket" title="muacc_socket()">

<t>This function creates a socket file descriptor just like the regular socket call.</t>

<t>SIGNATURE:</t>

<t>int muacc_socket(muacc_context_t *ctx, int domain, int type, int protocol)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function is mostly called after muacc_getaddrinfo(), since domain, type, and protocol can depend on the type of resolved address.</t>
  <t hangText='domain:'>
  Domain of the socket</t>
  <t hangText='type:'>
  Type of the socket</t>
  <t hangText='protocol:'>
  Protocol of the socket</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns a file descriptor of the new socket on success, or -1 on failure.</t>

</section>
<section anchor="muaccsetsockopt" title="muacc_setsockopt()">

<t>This call allows to set socket options (including Socket Intents).
For Socket Intents, this function can be called on a valid
<spanx style="verb">muacc_context</spanx> and an invalided file descriptor (-1) to provide
assertional hints to <spanx style="verb">muacc_getaddrinfo()</spanx>.</t>

<t>SIGNATURE:</t>

<t>int muacc_setsockopt(muacc_context_t *ctx, int socket, int level, int option_name, const void *option_value, socklen_t option_len)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function is mostly called to set Intents as socket options within the context.</t>
  <t hangText='socket:'>
  Socket file descriptor</t>
  <t hangText='level:'>
  Level of the socket option to set</t>
  <t hangText='option_name:'>
  Name of the socket option to set</t>
  <t hangText='option_value:'>
  Value of the socket option to set</t>
  <t hangText='option_len:'>
  Length of the socket option to set</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or -1 on failure.</t>

</section>
<section anchor="muaccconnect" title="muacc_connect()">

<t>Like the regular connect call, but also binds to the source address
selected by the Socket Intents Policy and applies socket options
suggested by the Socket Intents Policy.</t>

<t>SIGNATURE:</t>

<t>int muacc_connect(muacc_context_t *ctx, int socket, const struct sockaddr *address, socklen_t address_len)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function is mostly called after all Socket Intents for this connection have been set via muacc_setsockopt().</t>
  <t hangText='socket:'>
  Socket file descriptor</t>
  <t hangText='address:'>
  Remote address to connect to</t>
  <t hangText='address_len:'>
  Length of the remote address</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or -1 on failure.</t>

</section>
<section anchor="muaccclose" title="muacc_close()">

<t>Like regular close, but also cleans up state held in shadow structures
behind <spanx style="verb">muacc_context</spanx></t>

<t>SIGNATURE:</t>

<t>int muacc_close(muacc_context_t *ctx, int socket)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function deinitializes and releases the context.</t>
  <t hangText='socket:'>
  Socket file descriptor</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or -1 on failure.</t>

</section>
</section>
<section anchor="getaddrinfoapi" title="Classic API / getaddrinfo">

<t>In this variant, Socket Intents are passed directly to <spanx style="verb">getaddrinfo()</spanx> 
as part of the <spanx style="verb">hints</spanx> parameter. 
The name resolution is done by the MAM, which makes all decisions and
stores them in the “result” data structure as list of options ordered 
by preference.
Subsequently, applications can use this information for calls to the
unmodified BSD Socket API or other APIs.
We provide helpers to apply all socket options from the “result” 
data structure.</t>

<t>All relevant infos are stored in our addrinfo struct (see <xref target="muacc_addrinfo"/>)</t>

<t>SIGNATURE:</t>

<t>int muacc_ai_getaddrinfo(const char * hostname, const char * service,
const struct muacc_addrinfo * hints, struct muacc_addrinfo ** result)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='hostname:'>
  Remote host name to be resolved</t>
  <t hangText='service:'>
  Remote service to be resolved</t>
  <t hangText='hints:'>
  Hints for resolving the name. Contents include family, socket type, protocol, socket options (including Socket Intents for this socket/connection), local address to bind to.</t>
  <t hangText='result:'>
  Data structure for result of name resolution</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or an error code as provided by getaddrinfo().</t>

<figure title="Definition of the muacc_addrinfo struct" anchor="muacc_addrinfo"><artwork type="C" align="center"><![CDATA[
/** Extended version of the standard library's struct addrinfo
 *
 * This is used both as hint and as result from the
 * muacc_ai_getaddrinfo * function. This structure
 * differs from struct addrinfo only in the three members
 * ai_bindaddrlen, ai_bindaddr and ai_socketopt.
 */
struct muacc_addrinfo {
    int ai_flags;
    int ai_family;
    int ai_socktype;
    int ai_protocol;

    /** Not included in struct addrinfo. Purpose:
      * 1. If the structure is given to muacc_ai_getaddrinfo
      *    as hints, you set socket intents that influence MAM's
      *    source and destination as well as transport protocol
      *    selection
      * 2. The recommended socket options MAM will be returned
      *    through this attribute.
      */
    struct socketopt *ai_sockopts;

    int ai_addrlen;
    struct sockaddr *ai_addr;
    char *ai_canonname;

    /** Not included in struct addrinfo.
      * Length of ai_bindaddr.
      */
    int ai_bindaddrlen;
    /** Not included in struct addrinfo.
      * Contains the address, which the MAM recommends us to bind to.
      */
    struct sockaddr *ai_bindaddr;

    struct muacc_addrinfo *ai_next;
};
]]></artwork></figure>

<t><xref target="getaddrinfo_api_example"/> shows an example usage of the classic API with most functionality in getaddrinfo.</t>

</section>
<section anchor="socketconnectapi" title="Socketconnect API">

<t>In this API variant, we move the functionality of resolving a hostname
and connecting to the resulting address into one function called
<spanx style="verb">socketconnect()</spanx>. 
This API makes it possible to call socketconnect not only for
each connection, but also to multiplex messages across multiple
existing sockets.</t>

<t>This function returns a file descriptor of a connected socket for
the application to use.
This socket can either be a newly created one or a
socket that existed previously and is now being reused.
Furthermore, a socket can belong to a socket set of sockets with common
destination and service.
These sockets may, e.g., be bound to different local addresses, but are
treated as interchangeable by the API implementation.
So if the application passes a socket file descriptor to this function,
it may get back a different file descriptor to a socket from the same
set, e.g., to use the connection over a different local interface for
its following communication.</t>

<t>SIGNATURE:</t>

<t>int socketconnect(int *socket, const char *host, size_t hostlen, const char *serv, size_t servlen, struct socketopt *sockopts, int domain, int type, int proto)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='socket:'>
  Existing socket file descriptor as representant to a socket set, “-1” to create a new socket, or “0” to automatically try to find a suitable socket set</t>
  <t hangText='host:'>
  Remote hostname to be resolved</t>
  <t hangText='hostlen:'>
  Length of remote hostname</t>
  <t hangText='serv:'>
  Remote service or port</t>
  <t hangText='servlen:'>
  Length of remote service</t>
  <t hangText='socketopts:'>
  List of socket options, including Socket Intents</t>
  <t hangText='domain:'>
  Domain of the socket</t>
  <t hangText='type:'>
  Type of the socket</t>
  <t hangText='proto:'>
  Protocol of the socket</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success if socket is from an existing socket set, 1 on success if socket was newly created, or -1 on fail.</t>

<t><xref target="socketconnect_api_example"/> shows an example usage of the Socketconnect API.</t>

</section>
</section>
<section anchor="api-implementation-experiences-lessons-learned" title="API Implementation Experiences &amp; Lessons Learned">

<t>While designing and implementing the different parts of the system as
described in this document, we faced several challenges.
In the Multiple Access Manager discovering the currently available 
paths and statistics about their performance turned out to be quite
complex and had to be implemented in a partially platform-dependent way.
However, the most challenging parts were the Socket Intents API and
Library, on which we focus in the following sections.</t>

<section anchor="namereslink" title="The Missing Link to Name Resolution">

<t>Transport option selection is most useful if crucial information, such as Socket
Intents or other socket options, is available as early as possible, i.e., for
name resolution. The primary problem here is the order of the function calls
that are involved in name resolution, destination selection, protocol, and path
selection, and how they are linked.</t>

<t>In the classic BSD Socket API, most functions either take a socket file
descriptor as argument or return it, and thus link different function calls to
the same flow. However, <spanx style="verb">getaddrinfo()</spanx> is not linked to a socket file
descriptor, and it is typically called before the socket is created. At this
point, it is not yet possible to set a socket option, because the socket does
not exist yet.</t>

<t>Consequently, across BSD Socket API calls, several choices are being made
before it is possible to set a Socket Intent: A call to <spanx style="verb">getaddrinfo()</spanx> returns
a linked list of <spanx style="verb">addrinfo</spanx> structs, where each entry contains an <spanx style="verb">ai_family</spanx>
(IP version), the pair of <spanx style="verb">ai_socktype</spanx> and <spanx style="verb">ai_protocol</spanx> (transport protocol),
and a <spanx style="verb">sockaddr</spanx> struct containing an IP address and port to connect to. Then
a socket of the given family, type, and protocol is created. Only after this
has been done, socket options can be set on the socket, but at this point
destination, IP version, and transport protocol are already fixed.
Before calling <spanx style="verb">connect()</spanx>, only the path to be used (i.e., the local address
to bind to) can still be chosen, but the available paths and which one to
prefer may be constrained by the choice of destination.</t>

<t>The three variants described in <xref target="apivar"/> work around this problem in
different ways:</t>

<t><list style="symbols">
  <t>The approach in <xref target="getaddrinfoapi"/> places the whole
automation of transport option selection into the <spanx style="verb">getaddrinfo()</spanx>
function.
The results are returned in an extended <spanx style="verb">addrinfo</spanx> struct and have to be
applied manually by the application, including binding to a source address
representing the selected path and applying all socket options provided in a
list, for each connection attempt.</t>
  <t>The approach in <xref target="muacccontextapi"/> adds a context to all socket- and
name resolution-related API calls.</t>
  <t>The approach in <xref target="socketconnectapi"/> puts all functionality into
one call.</t>
</list></t>

<t>All of these approaches add the missing link between name resolution and the
other parts of the API, but add a lot of state keeping either to the API, which
the application developer has to manage, or to the Socket Intents library.</t>

</section>
<section anchor="fdharm" title="File Descriptors Considered Harmful">

<t>When using BSD sockets, file descriptors are the abstraction for network flows.
Depending on the transport protocol used, their semantics changes and these
file handles represent streams (SOCK_STREAM), associations (SOCK_DRAM) or
network interfaces (SOCK_RAW). This does not provide a unified API, but is
merely an artifact of squeezing networking into the “Everything is a file”
UNIX philosophy.</t>

<t>File descriptors make no good abstraction for automated protocol stack
instance selection as applications have to adopt to changed semantics,
e.g., whether message boundaries are preserved, depending on the
transport protocol chosen.</t>

<t>File descriptors make no good abstraction for destination instance
selection and path selection either.
Once a socket has been created, its protocol stack instance is fixed, so
selecting a path by binding to a local address and connecting to a destination
instance is now only possible using this protocol stack instance. If such a
connection attempt fails, it is possible to retry using another path and
destination, but changing the protocol stack instance requires creating a new
socket with a different file descriptor.</t>

<t>For further discussion of other asynchronous I/O weirdness with file
descriptors see end of <xref target="async-api"/>.</t>

</section>
<section anchor="async-api" title="Asynchronous API Anarchy">

<t>Network I/O is asynchronous, but asynchronous I/O within the POSIX
filesystem API is hard to use. There are at least three different
asynchronous I/O APIs for each operating system.</t>

<t>To implement asynchronous I/O for our Socket Intents prototype, we
wrapped one of the asynchronous I/O APIs that is available on most
platforms: <spanx style="verb">select()</spanx>.
To make Socket Intents accessible to more applications and on more
platforms, a production-grade system would need to wrap all
asynchronous I/O APIs and implement most of the socket creation logic,
path selection and connection logic within these wrappers.
However, mixing asynchronous I/O and multithreading may lead to
unintuitive behavior, e.g., calling our prototype’s select() from
different threads could lead to anything from deadlocks to busy waiting.</t>

<t>Another issue is that we use Unix domain sockets to communicate between
our Multiple Access Manager and the Socket Intents API library called
by the application, so we need to make sure that the application does
not block on communication with the Multiple Access Manager.</t>

<t>Also the problems with using file descriptors get even worse.
If a Socket API call should return immediately, it needs to provide the
application with a reference to a flow that has not yet been fully set
up, i.e., a reference to a “future” socket.
An implementation of such an asynchronous API has to return an
unconnected socket file descriptor, on which the application then
calls, e.g., <spanx style="verb">select()</spanx>, and starts using it once it becomes readable
and writable.
If the destination, path and transport protocol have not been chosen
yet at this point, the file descriptor returned by the implementation
might not yet have the final family and transport protocol.
When the implementation later creates the final socket of the right
type, it can re-bind it to the file-id of the originally returned
file descriptor using <spanx style="verb">dup2</spanx>.
This procedure can easily lead to time-of-check to time-of-use confusion.
To make things even worse, the application can copy the “future” file
descriptor using <spanx style="verb">dup</spanx>, which is rarely useful for sockets, but in
combination with file descriptors used as “future” it leads to unexpected
behavior.</t>

</section>
<section anchor="here-be-dragons-hiding-in-shadow-structures" title="Here Be Dragons hiding in Shadow Structures">

<t>The API variants described in <xref target="socketconnectapi"/> and <xref target="muacccontextapi"/>
need to keep a lot of state in shadow structures that cannot be passed
between the Socket API calls otherwise.
This state needs to be cleaned up when the last copy of the file
descriptor is closed or the last socket held for reuse has timed out.
In addition, access to these shadow structures has to be thread-safe.</t>

<t>Implementing both has turned out to be extremely error-prone and there
is a high amount of unspecified behavior and platform-dependent
extensions in the system library. These issues guarantee that an
implementation of transport option selection that nicely integrates with
BSD Sockets will come with lots of limitations and will not be portable
across POSIX-compliant operating systems.</t>

</section>
</section>
<section anchor="conclusion" title="Conclusion">

<t>Adding transport option selection to BSD Sockets is hard, as the API
calls are not designed to defer making and applying choices to a moment
where all information needed for transport option selection is
available.</t>

<t>After all, if limiting transport option selection to the granularity
BSD Sockets typically provide today (TCP connections and
UDP associations), the API variant described in <xref target="getaddrinfoapi"/>
seems to be a good compromise, even if it forces the application to try
all candidates itself (either in a sequential or partial parallel
fashion).
This option is easily deployable, but does not include automation of 
techniques like connection caching or HTTP pipelining.</t>

<t>The most versatile API variant described in <xref target="socketconnectapi"/> 
implements connection caching on the transport layer. 
This comes at the cost of heavily modifying existing applications.
If feasible, given the unnecessary complexity of the file I/O 
integration of BSD sockets, it seems easier to move to a totally 
different system like <xref target="I-D.trammell-taps-post-sockets"/>.</t>

</section>
<section anchor="acknowledgments" title="Acknowledgments">

<t>Thanks to Tobias Kaiser <eref target="mailto:mail@tb-kaiser.de">mail@tb-kaiser.de</eref> for drafting and
implementing the API variant described in <xref target="getaddrinfoapi"/>
as part of his BA thesis.</t>

</section>


  </middle>

  <back>


    <references title='Informative References'>





<reference  anchor="RFC2119" target='http://www.rfc-editor.org/info/rfc2119'>
<front>
<title>Key words for use in RFCs to Indicate Requirement Levels</title>
<author initials='S.' surname='Bradner' fullname='S. Bradner'><organization /></author>
<date year='1997' month='March' />
<abstract><t>In many standards track documents several words are used to signify the requirements in the specification.  These words are often capitalized. This document defines these words as they should be interpreted in IETF documents.  This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t></abstract>
</front>
<seriesInfo name='BCP' value='14'/>
<seriesInfo name='RFC' value='2119'/>
<seriesInfo name='DOI' value='10.17487/RFC2119'/>
</reference>



<reference  anchor="RFC6824" target='http://www.rfc-editor.org/info/rfc6824'>
<front>
<title>TCP Extensions for Multipath Operation with Multiple Addresses</title>
<author initials='A.' surname='Ford' fullname='A. Ford'><organization /></author>
<author initials='C.' surname='Raiciu' fullname='C. Raiciu'><organization /></author>
<author initials='M.' surname='Handley' fullname='M. Handley'><organization /></author>
<author initials='O.' surname='Bonaventure' fullname='O. Bonaventure'><organization /></author>
<date year='2013' month='January' />
<abstract><t>TCP/IP communication is currently restricted to a single path per connection, yet multiple paths often exist between peers.  The simultaneous use of these multiple paths for a TCP/IP session would improve resource usage within the network and, thus, improve user experience through higher throughput and improved resilience to network failure.</t><t>Multipath TCP provides the ability to simultaneously use multiple paths between peers.  This document presents a set of extensions to traditional TCP to support multipath operation.  The protocol offers the same type of service to applications as TCP (i.e., reliable bytestream), and it provides the components necessary to establish and use multiple TCP flows across potentially disjoint paths.  This  document defines an Experimental Protocol for the Internet community.</t></abstract>
</front>
<seriesInfo name='RFC' value='6824'/>
<seriesInfo name='DOI' value='10.17487/RFC6824'/>
</reference>



<reference  anchor="RFC7413" target='http://www.rfc-editor.org/info/rfc7413'>
<front>
<title>TCP Fast Open</title>
<author initials='Y.' surname='Cheng' fullname='Y. Cheng'><organization /></author>
<author initials='J.' surname='Chu' fullname='J. Chu'><organization /></author>
<author initials='S.' surname='Radhakrishnan' fullname='S. Radhakrishnan'><organization /></author>
<author initials='A.' surname='Jain' fullname='A. Jain'><organization /></author>
<date year='2014' month='December' />
<abstract><t>This document describes an experimental TCP mechanism called TCP Fast Open (TFO).  TFO allows data to be carried in the SYN and SYN-ACK packets and consumed by the receiving end during the initial connection handshake, and saves up to one full round-trip time (RTT) compared to the standard TCP, which requires a three-way handshake (3WHS) to complete before data can be exchanged.  However, TFO deviates from the standard TCP semantics, since the data in the SYN could be replayed to an application in some rare circumstances.  Applications should not use TFO unless they can tolerate this issue, as detailed in the Applicability section.</t></abstract>
</front>
<seriesInfo name='RFC' value='7413'/>
<seriesInfo name='DOI' value='10.17487/RFC7413'/>
</reference>



<reference  anchor="RFC7556" target='http://www.rfc-editor.org/info/rfc7556'>
<front>
<title>Multiple Provisioning Domain Architecture</title>
<author initials='D.' surname='Anipko' fullname='D. Anipko' role='editor'><organization /></author>
<date year='2015' month='June' />
<abstract><t>This document is a product of the work of the Multiple Interfaces Architecture Design team.  It outlines a solution framework for some of the issues experienced by nodes that can be attached to multiple networks simultaneously.  The framework defines the concept of a Provisioning Domain (PvD), which is a consistent set of network configuration information.  PvD-aware nodes learn PvD-specific information from the networks they are attached to and/or other sources.  PvDs are used to enable separation and configuration consistency in the presence of multiple concurrent connections.</t></abstract>
</front>
<seriesInfo name='RFC' value='7556'/>
<seriesInfo name='DOI' value='10.17487/RFC7556'/>
</reference>



<reference anchor="I-D.tiesel-taps-socketintents">
<front>
<title>Socket Intents</title>

<author initials='P' surname='Tiesel' fullname='Philipp Tiesel'>
    <organization />
</author>

<author initials='T' surname='Enghardt' fullname='Theresa Enghardt'>
    <organization />
</author>

<date month='June' day='15' year='2017' />

<abstract><t>This document outlines an API-independent concept that allows applications to share their knowledge about upcoming communication and express their performance preferences in a portable and abstract way: Socket Intents.  Socket Intents express what an application knows, assumes, expects or wants to prioritize regarding its own network communication.  The information provided by Socket Intents should be taken into account by the network stack in a best-effort way.  Socket Intent can be used to stem against the complexity and make use of multiple provisioning domains as well as new transport protocols and features available to a larger user base by expressing the applications intents in an abstract and portable way.</t></abstract>

</front>

<seriesInfo name='Internet-Draft' value='draft-tiesel-taps-socketintents-00' />
<format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-tiesel-taps-socketintents-00.txt' />
</reference>



<reference anchor="I-D.tiesel-taps-communitgrany">
<front>
<title>Communication Units Granularity Considerations for Multi-Path Aware Transport Selection</title>

<author initials='P' surname='Tiesel' fullname='Philipp Tiesel'>
    <organization />
</author>

<author initials='T' surname='Enghardt' fullname='Theresa Enghardt'>
    <organization />
</author>

<date month='June' day='27' year='2017' />

<abstract><t>This document provides an abstract framework to reason about the composition of multi-path aware systems in a protocol-independent fashion.  It discusses basic mechanisms that are used in multi-path systems and their applicability to different granularities of communication units.  This document is targeted as consideration basis for automation of destination, path and transport protocol selection within the transport layer.</t></abstract>

</front>

<seriesInfo name='Internet-Draft' value='draft-tiesel-taps-communitgrany-00' />
<format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-tiesel-taps-communitgrany-00.txt' />
</reference>



<reference anchor="I-D.trammell-taps-post-sockets">
<front>
<title>Post Sockets, An Abstract Programming Interface for the Transport Layer</title>

<author initials='B' surname='Trammell' fullname='Brian Trammell'>
    <organization />
</author>

<author initials='C' surname='Perkins' fullname='Colin Perkins'>
    <organization />
</author>

<author initials='T' surname='Pauly' fullname='Tommy Pauly'>
    <organization />
</author>

<author initials='M' surname='Kuehlewind' fullname='Mirja Kuehlewind'>
    <organization />
</author>

<date month='March' day='8' year='2017' />

<abstract><t>This document describes Post Sockets, an asynchronous abstract programming interface for the atomic transmission of messages in an inherently multipath environment.  Post replaces connections with long-lived associations between endpoints, with the possibility to cache cryptographic state in order to reduce amortized connection latency.  We present this abstract interface as an illustration of what is possible with present developments in transport protocols when freed from the strictures of the current sockets API.</t></abstract>

</front>

<seriesInfo name='Internet-Draft' value='draft-trammell-taps-post-sockets-00' />
<format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-trammell-taps-post-sockets-00.txt' />
</reference>

<reference anchor="ANRW17-MH" >
  <front>
    <title>Multi-Homed on a Single Link</title>
    <author initials="P." surname="Tiesel" fullname="Philipp S. Tiesel">
      <organization></organization>
    </author>
    <author initials="B." surname="May" fullname="Bernd May">
      <organization></organization>
    </author>
    <author initials="A." surname="Feldmann" fullname="Anja Feldmann">
      <organization></organization>
    </author>
    <date year="2016"/>
  </front>
  <seriesInfo name="Proceedings of the 2016 workshop on Applied Networking Research Workshop - ANRW 16" value=""/>
  <seriesInfo name="DOI" value="10.1145/2959424.2959434"/>
</reference>




    </references>


<section anchor="api-usage-examples" title="API Usage Examples">

<section anchor="classic_api_example" title="Usage Example of the Classic / muacc_context API">

<t>In this example, a client application sets up a connection to a remote host and sends data
to it. It specifies two Socket Intents on this connection: The Category of Bulk
Transfer and the File Size of 1 MB.</t>

<figure><artwork type="C"><![CDATA[
#define LENGTH_OF_DATA 1048576

// Create and initialize a context to retain information across function
// calls
muacc_context_t ctx;
muacc_init_context(&ctx);

int socket = -1;

struct addrinfo *result = NULL;

// Initialize a buffer of data to send later.
char buf[LENGTH_OF_DATA];
memset(&buf, 0, LENGTH_OF_DATA);

// Set Socket Intents for this connection. Note that the "socket" is
// still invalid, but it does not yet need to exist at this time. The
// Socket Intents prototype just sets the Intent within the
// muacc_context data structure.

enum intent_category category = INTENT_BULKTRANSFER;
muacc_setsockopt(&ctx, socket, SOL_INTENTS,
    INTENT_CATEGORY, &category, sizeof(enum intent_category));

int filesize = LENGTH_OF_DATA;
muacc_setsockopt(&ctx, socket, SOL_INTENTS,
    INTENT_FILESIZE, &filesize, sizeof(int));


// Resolve a host name. This involves a request to the MAM, which can
// automatically choose a suitable local interface or other parameters
// for the DNS request and set other parameters, such as preferred
// address family or transport protocol.
muacc_getaddrinfo(&ctx, "example.org", NULL, NULL, &result);

// Create the socket with the address family, type, and protocol
// obtained by getaddrinfo.
socket = muacc_socket(&ctx, result->ai_family, result->ai_socktype,
    result->ai_protocol);

// Connect the socket to the remote endpoint as determined by
// getaddrinfo.  This involves another request to MAM, which may at this
// point, e.g., choose to bind the socket to a local IP address before
// connecting it.
muacc_connect(&ctx, socket, result->ai_addr, result->ai_addrlen);

// Send data to the remote host over the socket.
write(socket, &buf, LENGTH_OF_DATA);

// Close the socket. This de-initializes any data that was stored within
// the muacc_context.
muacc_close(&ctx, socket);

]]></artwork></figure>

</section>
<section anchor="getaddrinfo_api_example" title="Usage Example of the Classic / getaddrinfo API">

<t>As in <xref target="classic_api_example"/>, the application sets the Intents “Category” and “File Size”.</t>

<figure><artwork type="C"><![CDATA[
#define LENGTH_OF_DATA 1048576

// Define Intents to be set later
enum intent_category category = INTENT_BULKTRANSFER;
int filesize = LENGTH_OF_DATA;

struct socketopt intents = { .level = SOL_INTENTS,
    .optname = INTENT_CATEGORY, .optval = &category, .next = NULL};
struct socketopt filesize_intent = { .level = SOL_INTENTS,
    .optname = INTENT_FILESIZE, .optval = &filesize, .next = NULL};

intents.next = &filesize_intent;

// Initialize a buffer of data to send later.
char buf[LENGTH_OF_DATA];
memset(&buf, 0, LENGTH_OF_DATA);

struct muacc_addrinfo intent_hints = { .ai_flags = 0,
    .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, .ai_protocol = 0,
    .ai_sockopts = &intents, .ai_addr = NULL, .ai_addrlen = 0,
    .ai_bindaddr = NULL, .ai_bindaddrlen = 0, .ai_next = NULL };

struct muacc_addrinfo *result = NULL;

muacc_ai_getaddrinfo("example.org", NULL, &intent_hints,
    &result);

// Create and connect the socket, using the information obtained through
// getaddrinfo
int fd;
fd = socket(result->ai_family, result->ai_socktype,
    result->ai_protocol);
muacc_ai_simple_connect(fd, result);

// Send data to the remote host over the socket, then close it.
write(fd, &buf, LENGTH_OF_DATA);
close(fd);

muacc_ai_freeaddrinfo(result);

]]></artwork></figure>

</section>
<section anchor="socketconnect_api_example" title="Usage Example of the Socketconnect API">

<t>As in <xref target="classic_api_example"/>, the application sets the Intents “Category” and “File Size”.
As we provide <spanx style="verb">-1</spanx> as socket, no we do not reuse existing connections.</t>

<figure><artwork type="C"><![CDATA[
#define LENGTH_OF_DATA 1048576

// Define Intents to be set later
enum intent_category category = INTENT_BULKTRANSFER;
int filesize = LENGTH_OF_DATA;

struct socketopt intents = { .level = SOL_INTENTS,
    .optname = INTENT_CATEGORY, .optval = &category, .next = NULL};
struct socketopt filesize_intent = { .level = SOL_INTENTS,
    .optname = INTENT_FILESIZE, .optval = &filesize, .next = NULL};

intents.next = &filesize_intent;

// Initialize a buffer of data to send later.
char buf[LENGTH_OF_DATA];
memset(&buf, 0, LENGTH_OF_DATA);

int socket = -1;

// Get a socket that is connected to the given host and service,
// with the given Intents
socketconnect(&socket, "example.org", 11, "80", 2, &intents, AF_INET,
    SOCK_STREAM, 0);

// Send data to the remote host over the socket.
write(socket, &buf, LENGTH_OF_DATA);

// Close the socket and tear down the data structure kept for it
// in the library
socketclose(socket);
]]></artwork></figure>

</section>
</section>


  </back>

<!-- ##markdown-source:
H4sIADlaWlkAA+196XLcRpbu/3yKDCrCTclVJVFt90KNO4aWZJvR2oKk23Nv
R4cIFrKqMKoCagCUKFqtjnmHecP7JPd855xMZAIoSvLMnesfo+iliCWXk2ff
MJ1OTVu0a3dsT+x5NX/jWntatq5sG/uqrtqqvdk6u6hq266c/fb8iX/o5NWp
/T///h/26butqwtXzl0zsc9c01RlQ/+f1aXLbVbm9jFdKHJXZ21Bv0x2dVW7
t8f9uTBDN3pj8mpeZhtaVV5ni3baFq5x62mbbZtpw48U8uL0qsnlQjNdZ61r
WpPT/x3bhw+Ofj99QP/5rZnThWVV3xzbolxUxhTb+ti29a5pHz548McHD01W
u+zYXtRZ2WyrujXXVf1mWVe7LV08eXVuf6K/i3Jpv8c188bd0AP5Ma+dttlO
n2CNxjQt7fd1tq5Kmv/GNWZbHNu/ttV8YhsatnYLAlFzs8GPvxmT7dpVVR8b
OzWW/hVlc2xfzez5zF7wbvmqAOHVqlgX223vXlUvs7L4mQF7bL919booaVEN
neeudbZa2As3X5XVulre8AsNrcG1x/Z5Vs9X9MfMPvwt35gX7Y0fQS5Uu7IF
xL539SYr5XW3yYr1sd3KYv65oK3P2t30il+b5S7ZycXMPi2Xq6zO22gjFytX
uyZLb/1/2kcraxnZhykrerot3rpjwhbCmfCXtWffPX54dPRH/fm7Pzz8Sn/+
/quj3/qfX3/9O/w8nT6Z7cXcsQfm1WazK4t2Sah4Ex6os83GrfWRbdW0OhAP
cfLi7CfC9Oc/HNsnL09nRw9mR0dffX3/4R+//uNXD7+a8f//9itjzHQ6tdkV
QSubE65erIrGEpHtNrQWm7tmXhdXrrGZ3QaqLzbbtcN9Phk6B9Mj2vfvb93h
hw+ecZge48hootIW6/UO6wForXuXYTqzqq77vIEOcZ3bq2hBLp+Z027ZOTMn
13Eiu8lyZ6+LdsV3wpYMGNJamdRamdSirjbEDm5A4W1Fw9Cs+Qi7mykQN0We
00INLa+u8t0cwDHfRP/ouZ+iqdfFQrkfUDl3bwussF1lrV1ltPPNbt0WtDG7
zdpVgyUAYoUyF+ahAFY5Jy7VYJHlbkO4isFaz7Jki/NqTYB9S9idXa3dhBcg
D5vk4WrLvBhTNa6mJWRWMW8u6wQOAp7rikBMoPZwx+yZXbldXRB1zolyLR+g
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
Eg8FZnxBfR2lXGJy/xeGmNEAfYkAAA==

-->

</rfc>

