Home | History | Annotate | Line # | Download | only in ddd
      1  1.1  christos Report on the Conclusions of the QUIC DDD Process
      2  1.1  christos =================================================
      3  1.1  christos 
      4  1.1  christos The [QUIC Demo-Driven Design process](README.md) was undertaken to meet the OMC
      5  1.1  christos requirement to develop a QUIC API that required only minimal changes to existing
      6  1.1  christos applications to be able to adapt their code to use QUIC. The demo-driven design
      7  1.1  christos process developed a set of representative demos modelling a variety of common
      8  1.1  christos OpenSSL usage patterns based on analysis of a broad spectrum of open source
      9  1.1  christos software projects using OpenSSL.
     10  1.1  christos 
     11  1.1  christos As part of this process, a set of proposed diffs were produced. These proposed
     12  1.1  christos diffs were the expected changes which would be needed to the baseline demos to
     13  1.1  christos support QUIC based on theoretical analysis of the minimum requirements to be
     14  1.1  christos able to support QUIC. This analysis concluded that the changes needed to
     15  1.1  christos applications could be kept very small in many circumstances, with only minimal
     16  1.1  christos diff sizes to the baseline demos.
     17  1.1  christos 
     18  1.1  christos Following the development of QUIC MVP, these demos have been revisited and the
     19  1.1  christos correspondence of our actual final API and usage patterns with the planned diffs
     20  1.1  christos have been reviewed.
     21  1.1  christos 
     22  1.1  christos This document discusses the planned changes and the actual changes for each demo
     23  1.1  christos and draws conclusions on the level of disparity.
     24  1.1  christos 
     25  1.1  christos Since tracking a set of diffs separately is unwieldy, both the planned and
     26  1.1  christos unplanned changes have been folded into the original baseline demo files guarded
     27  1.1  christos with `#ifdef USE_QUIC`. Viewing these files therefore is informative to
     28  1.1  christos application writers as it provides a clear view of what is different when using
     29  1.1  christos QUIC. (The originally planned changes, and the final changes, are added in
     30  1.1  christos separate, clearly-labelled commits; to view the originally planned changes only,
     31  1.1  christos view the commit history for a given demo file.)
     32  1.1  christos 
     33  1.1  christos ddd-01-conn-blocking
     34  1.1  christos --------------------
     35  1.1  christos 
     36  1.1  christos This demo exists to demonstrate the simplest possible usage of OpenSSL, whether
     37  1.1  christos with TLS or QUIC.
     38  1.1  christos 
     39  1.1  christos ### Originally planned changes
     40  1.1  christos 
     41  1.1  christos The originally planned change to enable applications for QUIC amounted to just a
     42  1.1  christos single line:
     43  1.1  christos 
     44  1.1  christos ```diff
     45  1.1  christos +    ctx = SSL_CTX_new(QUIC_client_method());
     46  1.1  christos -    ctx = SSL_CTX_new(TLS_client_method());
     47  1.1  christos ```
     48  1.1  christos 
     49  1.1  christos ### Actual changes
     50  1.1  christos 
     51  1.1  christos The following additional changes needed to be made:
     52  1.1  christos 
     53  1.1  christos - `QUIC_client_method` was renamed to `OSSL_QUIC_client_method` for namespacing
     54  1.1  christos   reasons.
     55  1.1  christos 
     56  1.1  christos - A call to `SSL_set_alpn_protos` to configure ALPN was added. This is necessary
     57  1.1  christos   because QUIC mandates the use of ALPN, and this was not noted during the
     58  1.1  christos   DDD process.
     59  1.1  christos 
     60  1.1  christos ddd-02-conn-nonblocking
     61  1.1  christos -----------------------
     62  1.1  christos 
     63  1.1  christos This demo exists to demonstrate simple non-blocking usage. As with
     64  1.1  christos ddd-01-conn-blocking, the name resolution process is managed by `BIO_s_connect`.
     65  1.1  christos 
     66  1.1  christos It also arbitrarily adds a `BIO_f_buffer` pushed onto the BIO stack
     67  1.1  christos as this is a common application usage pattern.
     68  1.1  christos 
     69  1.1  christos ### Originally planned changes
     70  1.1  christos 
     71  1.1  christos The originally planned changes to enable applications for QUIC amounted to:
     72  1.1  christos 
     73  1.1  christos - Change of method (as for ddd-01-conn-blocking);
     74  1.1  christos 
     75  1.1  christos - Use of a `BIO_f_dgram_buffer` BIO method instead of a `BIO_f_buffer`;
     76  1.1  christos 
     77  1.1  christos - Use of a `BIO_get_poll_fd` function to get the FD to poll rather than
     78  1.1  christos   `BIO_get_fd`;
     79  1.1  christos 
     80  1.1  christos - A change to how the `POLLIN`/`POLLOUT`/`POLLERR` flags to pass to poll(2)
     81  1.1  christos   need to be determined.
     82  1.1  christos 
     83  1.1  christos - Additional functions in application code to determine event handling
     84  1.1  christos   timeouts related to QUIC (`get_conn_pump_timeout`) and to pump
     85  1.1  christos   the QUIC event loop (`pump`).
     86  1.1  christos 
     87  1.1  christos - Timeout computation code which involves merging and comparing different
     88  1.1  christos   timeouts and calling `pump` as needed, based on deadlines reported
     89  1.1  christos   by libssl.
     90  1.1  christos 
     91  1.1  christos Note that some of these changes are unnecessary when using the thread assisted
     92  1.1  christos mode (see the variant ddd-02-conn-nonblocking-threads below).
     93  1.1  christos 
     94  1.1  christos ### Actual changes
     95  1.1  christos 
     96  1.1  christos The following additional changes needed to be made:
     97  1.1  christos 
     98  1.1  christos - Change of method name (as for ddd-01-conn-blocking);
     99  1.1  christos 
    100  1.1  christos - Use of ALPN (as for ddd-01-conn-blocking);
    101  1.1  christos 
    102  1.1  christos - The strategy for how to expose pollable OS resource handles
    103  1.1  christos   to applications to determine I/O readiness has changed substantially since the
    104  1.1  christos   original DDD process. As such, applications now use `BIO_get_rpoll_descriptor`
    105  1.1  christos   and `BIO_get_wpoll_descriptor` to determine I/O readiness, rather than the
    106  1.1  christos   originally hypothesised `SSL_get_poll_fd`.
    107  1.1  christos 
    108  1.1  christos - The strategy for how to determine when to poll for `POLLIN`, when to
    109  1.1  christos   poll for `POLLOUT`, etc. has changed since the original DDD process.
    110  1.1  christos   This information is now exposed via `SSL_net_read_desired` and
    111  1.1  christos   `SSL_net_write_desired`.
    112  1.1  christos 
    113  1.1  christos - The API to expose the event handling deadline for the QUIC engine
    114  1.1  christos   has evolved since the original DDD process. The new API
    115  1.1  christos   `SSL_get_event_timeout` is used, rather than the originally hypothesised
    116  1.1  christos   `BIO_get_timeout`/`SSL_get_timeout`.
    117  1.1  christos 
    118  1.1  christos - The API to perform QUIC event processing has been renamed to be
    119  1.1  christos   more descriptive. It is now called `SSL_handle_events` rather than
    120  1.1  christos   the originally hypothesised `BIO_pump`/`SSL_pump`.
    121  1.1  christos 
    122  1.1  christos The following changes were foreseen to be necessary, but turned out to actually
    123  1.1  christos not be necessary:
    124  1.1  christos 
    125  1.1  christos - The need to change code which pushes a `BIO_f_buffer()` after an SSL BIO
    126  1.1  christos   was foreseen as use of buffering on the network side is unworkable with
    127  1.1  christos   QUIC. This turned out not to be necessary since we can just reject the
    128  1.1  christos   BIO_push() call. The buffer should still be freed eventually when the
    129  1.1  christos   SSL BIO is freed. The buffer is not used and is unnecessary, so it is
    130  1.1  christos   still desirable for applications to remove this code.
    131  1.1  christos 
    132  1.1  christos ddd-02-conn-nonblocking-threads
    133  1.1  christos -------------------------------
    134  1.1  christos 
    135  1.1  christos This is a variant of the ddd-02-conn-nonblocking demo. The base is the same, but
    136  1.1  christos the changes made are different. The use of thread-assisted mode, in which an
    137  1.1  christos internal assist thread is used to perform QUIC event handling, enables an
    138  1.1  christos application to make fewer changes than are needed in the ddd-02-conn-nonblocking
    139  1.1  christos demo.
    140  1.1  christos 
    141  1.1  christos ### Originally planned changes
    142  1.1  christos 
    143  1.1  christos The originally planned changes to enable applications for QUIC amounted to:
    144  1.1  christos 
    145  1.1  christos - Change of method, this time using method `QUIC_client_thread_method` rather
    146  1.1  christos   than `QUIC_client_method`;
    147  1.1  christos 
    148  1.1  christos - Use of a `BIO_get_poll_fd` function to get the FD to poll rather than
    149  1.1  christos   `BIO_get_fd`;
    150  1.1  christos 
    151  1.1  christos - A change to how the `POLLIN`/`POLLOUT`/`POLLERR` flags to pass to poll(2)
    152  1.1  christos   need to be determined.
    153  1.1  christos 
    154  1.1  christos   Note that this is a substantially smaller list of changes than for
    155  1.1  christos   ddd-02-conn-nonblocking.
    156  1.1  christos 
    157  1.1  christos ### Actual changes
    158  1.1  christos 
    159  1.1  christos The following additional changes needed to be made:
    160  1.1  christos 
    161  1.1  christos - Change of method name (`QUIC_client_thread_method` was renamed to
    162  1.1  christos   `OSSL_QUIC_client_thread_method` for namespacing reasons);
    163  1.1  christos 
    164  1.1  christos - Use of ALPN (as for ddd-01-conn-blocking);
    165  1.1  christos 
    166  1.1  christos - Use of `BIO_get_rpoll_descriptor` rather than `BIO_get_poll_fd` (as for
    167  1.1  christos   ddd-02-conn-nonblocking).
    168  1.1  christos 
    169  1.1  christos - Use of `SSL_net_read_desired` and `SSL_net_write_desired` (as for
    170  1.1  christos   ddd-02-conn-nonblocking).
    171  1.1  christos 
    172  1.1  christos ddd-03-fd-blocking
    173  1.1  christos ------------------
    174  1.1  christos 
    175  1.1  christos This demo is similar to ddd-01-conn-blocking but uses a file descriptor passed
    176  1.1  christos directly by the application rather than BIO_s_connect.
    177  1.1  christos 
    178  1.1  christos ### Originally planned changes
    179  1.1  christos 
    180  1.1  christos - Change of method (as for ddd-01-conn-blocking);
    181  1.1  christos 
    182  1.1  christos - The arguments to the `socket(2)` call are changed from `(AF_INET, SOCK_STREAM,
    183  1.1  christos   IPPROTO_TCP)` to `(AF_INET, SOCK_DGRAM, IPPROTO_UDP)`.
    184  1.1  christos 
    185  1.1  christos ### Actual changes
    186  1.1  christos 
    187  1.1  christos The following additional changes needed to be made:
    188  1.1  christos 
    189  1.1  christos - Change of method name (as for ddd-01-conn-blocking);
    190  1.1  christos 
    191  1.1  christos - Use of ALPN (as for ddd-01-conn-blocking).
    192  1.1  christos 
    193  1.1  christos ddd-04-fd-nonblocking
    194  1.1  christos ---------------------
    195  1.1  christos 
    196  1.1  christos This demo is similar to ddd-01-conn-nonblocking but uses a file descriptor
    197  1.1  christos passed directly by the application rather than BIO_s_connect.
    198  1.1  christos 
    199  1.1  christos ### Originally planned changes
    200  1.1  christos 
    201  1.1  christos - Change of method (as for ddd-01-conn-blocking);
    202  1.1  christos 
    203  1.1  christos - The arguments to the `socket(2)` call are changed from `(AF_INET, SOCK_STREAM,
    204  1.1  christos   IPPROTO_TCP)` to `(AF_INET, SOCK_DGRAM, IPPROTO_UDP)`;
    205  1.1  christos 
    206  1.1  christos - A change to how the `POLLIN`/`POLLOUT`/`POLLERR` flags to pass to poll(2)
    207  1.1  christos   need to be determined.
    208  1.1  christos 
    209  1.1  christos - Additional functions in application code to determine event handling
    210  1.1  christos   timeouts related to QUIC (`get_conn_pump_timeout`) and to pump
    211  1.1  christos   the QUIC event loop (`pump`).
    212  1.1  christos 
    213  1.1  christos - Timeout computation code which involves merging and comparing different
    214  1.1  christos   timeouts and calling `pump` as needed, based on deadlines reported
    215  1.1  christos   by libssl.
    216  1.1  christos 
    217  1.1  christos ### Actual changes
    218  1.1  christos 
    219  1.1  christos The following additional changes needed to be made:
    220  1.1  christos 
    221  1.1  christos - Change of method name (as for ddd-01-conn-blocking);
    222  1.1  christos 
    223  1.1  christos - Use of ALPN (as for ddd-01-conn-blocking);
    224  1.1  christos 
    225  1.1  christos - `SSL_get_timeout` replaced with `SSL_get_event_timeout` (as for
    226  1.1  christos   ddd-02-conn-nonblocking);
    227  1.1  christos 
    228  1.1  christos - `SSL_pump` renamed to `SSL_handle_events` (as for ddd-02-conn-nonblocking);
    229  1.1  christos 
    230  1.1  christos - The strategy for how to determine when to poll for `POLLIN`, when to
    231  1.1  christos   poll for `POLLOUT`, etc. has changed since the original DDD process.
    232  1.1  christos   This information is now exposed via `SSL_net_read_desired` and
    233  1.1  christos   `SSL_net_write_desired` (as for ddd-02-conn-nonblocking).
    234  1.1  christos 
    235  1.1  christos ddd-05-mem-nonblocking
    236  1.1  christos ----------------------
    237  1.1  christos 
    238  1.1  christos This demo is more elaborate. It uses memory buffers created and managed by an
    239  1.1  christos application as an intermediary between libssl and the network, which is a common
    240  1.1  christos usage pattern for applications. Managing this pattern for QUIC is more elaborate
    241  1.1  christos since datagram semantics on the network channel need to be maintained.
    242  1.1  christos 
    243  1.1  christos ### Originally planned changes
    244  1.1  christos 
    245  1.1  christos - Change of method (as for ddd-01-conn-blocking);
    246  1.1  christos 
    247  1.1  christos - Call to `BIO_new_bio_pair` is changed to `BIO_new_dgram_pair`, which
    248  1.1  christos   provides a bidirectional memory buffer BIO with datagram semantics.
    249  1.1  christos 
    250  1.1  christos - A change to how the `POLLIN`/`POLLOUT`/`POLLERR` flags to pass to poll(2)
    251  1.1  christos   need to be determined.
    252  1.1  christos 
    253  1.1  christos - Potential changes to buffer sizes used by applications to buffer
    254  1.1  christos   datagrams, if those buffers are smaller than 1472 bytes.
    255  1.1  christos 
    256  1.1  christos - The arguments to the `socket(2)` call are changed from `(AF_INET, SOCK_STREAM,
    257  1.1  christos   IPPROTO_TCP)` to `(AF_INET, SOCK_DGRAM, IPPROTO_UDP)`;
    258  1.1  christos 
    259  1.1  christos ### Actual changes
    260  1.1  christos 
    261  1.1  christos The following additional changes needed to be made:
    262  1.1  christos 
    263  1.1  christos - Change of method name (as for ddd-01-conn-blocking);
    264  1.1  christos 
    265  1.1  christos - Use of ALPN (as for ddd-01-conn-blocking);
    266  1.1  christos 
    267  1.1  christos - The API to construct a `BIO_s_dgram_pair` ended up being named
    268  1.1  christos   `BIO_new_bio_dgram_pair` rather than `BIO_new_dgram_pair`;
    269  1.1  christos 
    270  1.1  christos - Use of `SSL_net_read_desired` and `SSL_net_write_desired` (as for
    271  1.1  christos   ddd-02-conn-nonblocking).
    272  1.1  christos 
    273  1.1  christos ddd-06-mem-uv
    274  1.1  christos -------------
    275  1.1  christos 
    276  1.1  christos This demo is the most elaborate of the set. It uses a real-world asynchronous
    277  1.1  christos I/O reactor, namely libuv (the engine used by Node.js). In doing so it seeks to
    278  1.1  christos demonstrate and prove the viability of our API design with a real-world
    279  1.1  christos asynchronous I/O system. It operates wholly in non-blocking mode and uses memory
    280  1.1  christos buffers on either side of the QUIC stack to feed data to and from the
    281  1.1  christos application and the network.
    282  1.1  christos 
    283  1.1  christos ### Originally planned changes
    284  1.1  christos 
    285  1.1  christos - Change of method (as for ddd-01-conn-blocking);
    286  1.1  christos 
    287  1.1  christos - Various changes to use of libuv needed to switch to using UDP;
    288  1.1  christos 
    289  1.1  christos - Additional use of libuv to configure a timer event;
    290  1.1  christos 
    291  1.1  christos - Call to `BIO_new_bio_pair` is changed to `BIO_new_dgram_pair`
    292  1.1  christos   (as for ddd-05-mem-nonblocking);
    293  1.1  christos 
    294  1.1  christos - Some reordering of code required by the design of libuv.
    295  1.1  christos 
    296  1.1  christos ### Actual changes
    297  1.1  christos 
    298  1.1  christos The following additional changes needed to be made:
    299  1.1  christos 
    300  1.1  christos - Change of method name (as for ddd-01-conn-blocking);
    301  1.1  christos 
    302  1.1  christos - Use of ALPN (as for ddd-01-conn-blocking);
    303  1.1  christos 
    304  1.1  christos - `BIO_new_dgram_pair` renamed to `BIO_new_bio_dgram_pair` (as for
    305  1.1  christos   ddd-05-mem-nonblocking);
    306  1.1  christos 
    307  1.1  christos - `SSL_get_timeout` replaced with `SSL_get_event_timeout` (as for
    308  1.1  christos   ddd-02-conn-nonblocking);
    309  1.1  christos 
    310  1.1  christos - `SSL_pump` renamed to `SSL_handle_events` (as for ddd-02-conn-nonblocking);
    311  1.1  christos 
    312  1.1  christos - Fixes to use of libuv based on a corrected understanding
    313  1.1  christos   of its operation, and changes that necessarily ensue.
    314  1.1  christos 
    315  1.1  christos Conclusions
    316  1.1  christos -----------
    317  1.1  christos 
    318  1.1  christos The DDD process has successfully delivered on the objective of delivering a QUIC
    319  1.1  christos API which can be used with only minimal API changes. The additional changes on
    320  1.1  christos top of those originally planned which were required to successfully execute the
    321  1.1  christos demos using QUIC were highly limited in scope and mostly constituted only minor
    322  1.1  christos changes. The sum total of the changes required for each demo (both planned and
    323  1.1  christos additional), as denoted in each DDD demo file under `#ifdef USE_QUIC` guards,
    324  1.1  christos are both minimal and limited in scope.
    325  1.1  christos 
    326  1.1  christos Minimal and limited are distinct criteria. If inexorable technical
    327  1.1  christos requirements dictate, an enormous set of changes to an application could be
    328  1.1  christos considered minimal. The changes required to representative applications, as
    329  1.1  christos demonstrated by the DDD demos, are not merely minimal but also limited.
    330  1.1  christos 
    331  1.1  christos For example, while the extent of these necessary changes varies by the
    332  1.1  christos sophistication of each demo and the kind of application usage pattern it
    333  1.1  christos represents, some demos in particular demonstrate exceptionally small changesets;
    334  1.1  christos for example, ddd-01-conn-blocking and ddd-02-conn-nonblocking-threads, with
    335  1.1  christos ddd-01-conn-blocking literally being enabled by a single line change assuming
    336  1.1  christos ALPN is already configured.
    337  1.1  christos 
    338  1.1  christos This report concludes the DDD process for the single-stream QUIC client API
    339  1.1  christos design process, which sought to validate our API design and API ease of use for
    340  1.1  christos existing applications seeking to adopt QUIC.
    341