1a74702c6SGeorge Wang# Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. 27edaabaaSDmitri TikhonovLSQUIC APIs 37edaabaaSDmitri Tikhonov=========== 47edaabaaSDmitri Tikhonov 57edaabaaSDmitri TikhonovLSQUIC exposes the following object types to the user: 67edaabaaSDmitri Tikhonov 77edaabaaSDmitri Tikhonov - Engine Settings (struct lsquic_engine_settings) 87edaabaaSDmitri Tikhonov - Stream Interface (struct lsquic_stream_if) 97edaabaaSDmitri Tikhonov - Engine API (struct lsquic_engine_api) 107edaabaaSDmitri Tikhonov - Engine 117edaabaaSDmitri Tikhonov - Connection 127edaabaaSDmitri Tikhonov - Stream 137edaabaaSDmitri Tikhonov 147edaabaaSDmitri TikhonovThe first three -- engine settings, engine APIs, and stream interface -- 157edaabaaSDmitri Tikhonovare used to instantiate the engine. After engine is instantiated, the 167edaabaaSDmitri Tikhonovuser code need only concern itself with engine, connections, and streams. 177edaabaaSDmitri Tikhonov 187edaabaaSDmitri Tikhonov 197edaabaaSDmitri TikhonovEngine Settings 207edaabaaSDmitri Tikhonov--------------- 217edaabaaSDmitri Tikhonov 227edaabaaSDmitri TikhonovEngine settings is the struct lsquic_engine_settings. It contains various 237edaabaaSDmitri TikhonovQUIC settings and LSQUIC parameters. The usual way to use it is to initialize 247edaabaaSDmitri Tikhonovit to default values using lsquic_engine_init_settings(), modify any values 257edaabaaSDmitri Tikhonovif necessary, and pass it as parameter to lsquic_engine_new(). 267edaabaaSDmitri Tikhonov 277edaabaaSDmitri TikhonovQUIC settings are specified by the following members: 287edaabaaSDmitri Tikhonov 297edaabaaSDmitri Tikhonov lsquic_engine_settings QUIC 307edaabaaSDmitri Tikhonov member parameter 317edaabaaSDmitri Tikhonov ---------------------- --------- 327edaabaaSDmitri Tikhonov es_cfcw CFCW 337edaabaaSDmitri Tikhonov es_sfcw SFCW 347edaabaaSDmitri Tikhonov es_max_streams_in MIDS 357edaabaaSDmitri Tikhonov es_ua UAID 367edaabaaSDmitri Tikhonov es_versions VER 377edaabaaSDmitri Tikhonov es_idle_conn_to ICSL 387edaabaaSDmitri Tikhonov es_silent_close SCLS 397edaabaaSDmitri Tikhonov es_support_srej COPT/SREJ 407edaabaaSDmitri Tikhonov es_support_nstp COPT/NSTP 417edaabaaSDmitri Tikhonov es_support_tcid0 TCID 427edaabaaSDmitri Tikhonov 437edaabaaSDmitri TikhonovThe following parameters affect run-time behavior: 447edaabaaSDmitri Tikhonov 457edaabaaSDmitri Tikhonov es_rw_once Important: affects event dispatch 467edaabaaSDmitri Tikhonov es_handshake_to 477edaabaaSDmitri Tikhonov es_support_push 487edaabaaSDmitri Tikhonov es_pace_packets 497edaabaaSDmitri Tikhonov 507edaabaaSDmitri TikhonovOther noteworthy settings: 517edaabaaSDmitri Tikhonov 527edaabaaSDmitri Tikhonov es_max_header_list_size 537edaabaaSDmitri Tikhonov es_progress_check 547edaabaaSDmitri Tikhonov 557edaabaaSDmitri TikhonovTo be sure your settings are good (in other words, passing this struct won't 567edaabaaSDmitri Tikhonovtrip up the engine constructor), use lsquic_engine_check_settings(). 577edaabaaSDmitri Tikhonov 587edaabaaSDmitri Tikhonov 597edaabaaSDmitri TikhonovStream Interface 607edaabaaSDmitri Tikhonov---------------- 617edaabaaSDmitri Tikhonov 627edaabaaSDmitri TikhonovThe stream interface, lsquic_stream_if, specifies callbacks LSQUIC engine 637edaabaaSDmitri Tikhonovwill call for connections and streams. 647edaabaaSDmitri Tikhonov 657edaabaaSDmitri TikhonovThe following callbacks should be specified for connection: 667edaabaaSDmitri Tikhonov 677edaabaaSDmitri Tikhonov on_new_conn This is called when connection is created. 687edaabaaSDmitri Tikhonov 697edaabaaSDmitri Tikhonov on_goaway_received This function is called when we receive GOAWAY 707edaabaaSDmitri Tikhonov frame from peer. This callback is optional. 717edaabaaSDmitri Tikhonov 727edaabaaSDmitri Tikhonov on_conn_closed Connection is closed: all streams have been 737edaabaaSDmitri Tikhonov destroyed. 747edaabaaSDmitri Tikhonov 757edaabaaSDmitri TikhonovThe streams have four callbacks: 767edaabaaSDmitri Tikhonov 777edaabaaSDmitri Tikhonov on_new_stream Stream has been created. 787edaabaaSDmitri Tikhonov 797edaabaaSDmitri Tikhonov on_read Stream can be read from (see Events). 807edaabaaSDmitri Tikhonov 817edaabaaSDmitri Tikhonov on_write Stream can be written to (see Events). 827edaabaaSDmitri Tikhonov 837edaabaaSDmitri Tikhonov on_close Stream has been closed. 847edaabaaSDmitri Tikhonov 857edaabaaSDmitri TikhonovFor both connections and streams, the "on new" callback return value can 867ee41525SDmitri Tikhonovbe used to specify user-supplied data. This data pointer is optional and 877edaabaaSDmitri Tikhonovcan be NULL. It can also refer to the same data for the connection and 887edaabaaSDmitri Tikhonovits streams. "on close" callbacks should be used to free user-supplied 897edaabaaSDmitri Tikhonovdata. 907edaabaaSDmitri Tikhonov 917edaabaaSDmitri Tikhonov 927edaabaaSDmitri TikhonovEngine API 937edaabaaSDmitri Tikhonov---------- 947edaabaaSDmitri Tikhonov 957edaabaaSDmitri TikhonovThe engine API, struct lsquic_engine_api, is a combination structure to 967edaabaaSDmitri Tikhonovmake calling lsquic_engine_new() manageable. It holds references to 977edaabaaSDmitri Tikhonovstruct lsquic_engine_settings and struct lsquic_stream_if, as well as: 987edaabaaSDmitri Tikhonov 997edaabaaSDmitri Tikhonov - Interface for sending outgoing packets, ea_packets_out 1007edaabaaSDmitri Tikhonov - Interface for allocating memory for outgoing packet buffers 1017edaabaaSDmitri Tikhonov (optional). 1025392f7a3SLiteSpeed Tech - Interface for share memory hash, ea_shi 1035392f7a3SLiteSpeed Tech - Optional interface for reporting connections whose handshake 1045392f7a3SLiteSpeed Tech did not complete (ea_bad_handshake) 1057edaabaaSDmitri Tikhonov 1067edaabaaSDmitri Tikhonovea_packets_out is a pointer to a function of type lsquic_packets_out_f. 1077edaabaaSDmitri TikhonovThe engine calls this function when it is appropriate to send out packets 1087edaabaaSDmitri Tikhonovfor one or more connections, which it gives to the function in a batch. 1097edaabaaSDmitri TikhonovThis batch is an array of struct lsquic_out_spec. 1107edaabaaSDmitri Tikhonov 1117edaabaaSDmitri Tikhonov 1127edaabaaSDmitri TikhonovEngine 1137edaabaaSDmitri Tikhonov------ 1147edaabaaSDmitri Tikhonov 1157edaabaaSDmitri TikhonovThe engine is instantiated using lsquic_engine_new(). The first parameter 1167edaabaaSDmitri Tikhonovis a list flags and the second parameter is the reference to the engine 1177edaabaaSDmitri Tikhonovapi. The engine settings are specified, they are copied; changing 1187edaabaaSDmitri Tikhonovthe setting after the engine has been created will not affect engine's 1197edaabaaSDmitri Tikhonovbehavior. If the settings are not specified, the engine will use default 1207edaabaaSDmitri Tikhonovsettings created by lsquic_engine_init_settings(). 1217edaabaaSDmitri Tikhonov 1227edaabaaSDmitri TikhonovOnce the engine is instantiated, there are four main ways to use it to 1237edaabaaSDmitri Tikhonovdrive QUIC connections: 1247edaabaaSDmitri Tikhonov 1257edaabaaSDmitri Tikhonov 1. Create a connection using lsquic_engine_connect(). 1267edaabaaSDmitri Tikhonov 2. Feed it incoming packets using lsquic_engine_packet_in() function. 1277edaabaaSDmitri Tikhonov 3. Process connections using one of the connection queue functions 1287edaabaaSDmitri Tikhonov (see Connection Queues). 1297edaabaaSDmitri Tikhonov 4. Accept outgoing packets for sending (and send them!) using 1307edaabaaSDmitri Tikhonov ea_packets_out callback. 1317edaabaaSDmitri Tikhonov 1327edaabaaSDmitri Tikhonov 133e8bd737dSDmitri TikhonovConnection Management 134e8bd737dSDmitri Tikhonov--------------------- 1357edaabaaSDmitri Tikhonov 1367ee41525SDmitri TikhonovA connection needs to be processed once in a while. It needs to be 137e8bd737dSDmitri Tikhonovprocessed when one of the following is true: 138e8bd737dSDmitri Tikhonov 139e8bd737dSDmitri Tikhonov - There are incoming packets; 140e8bd737dSDmitri Tikhonov - A stream is both readable by the user code and the user code wants 141e8bd737dSDmitri Tikhonov to read from it; 142e8bd737dSDmitri Tikhonov - A stream is both writeable by the user code and the user code wants 143e8bd737dSDmitri Tikhonov to write to it; 144e8bd737dSDmitri Tikhonov - User has written to stream outside of on_write() callbacks (that is 145e8bd737dSDmitri Tikhonov allowed) and now there are packets ready to be sent; 146e8bd737dSDmitri Tikhonov - A timer (pacer, retransmission, idle, etc) has expired; 147e8bd737dSDmitri Tikhonov - A control frame needs to be sent out; 148e8bd737dSDmitri Tikhonov - A stream needs to be serviced or created. 149e8bd737dSDmitri Tikhonov 150e8bd737dSDmitri TikhonovEach of these use cases is handled by a single function: 151e8bd737dSDmitri Tikhonov 152e8bd737dSDmitri Tikhonov lsquic_engine_process_conns() 153e8bd737dSDmitri Tikhonov 154e8bd737dSDmitri TikhonovThe connections to which the conditions above apply are processed (or 155e8bd737dSDmitri Tikhonov"ticked") in the least recently ticked order. After calling this function, 156e8bd737dSDmitri Tikhonovyou can see when is the next time a connection needs to be processed using 157e8bd737dSDmitri Tikhonov 158e8bd737dSDmitri Tikhonov lsquic_engine_earliest_adv_tick() 159e8bd737dSDmitri Tikhonov 160e8bd737dSDmitri TikhonovBased on this value, next event can be scheduled (in the event loop of 161e8bd737dSDmitri Tikhonovyour choice). 1627edaabaaSDmitri Tikhonov 1637edaabaaSDmitri TikhonovConnection 1647edaabaaSDmitri Tikhonov---------- 1657edaabaaSDmitri Tikhonov 1667edaabaaSDmitri TikhonovA connection is created using lsquic_engine_connect(). When on_new_conn() 1677edaabaaSDmitri Tikhonovis called, the client code should call lsquic_conn_make_stream() one or 1687edaabaaSDmitri Tikhonovmore times. One new stream will be created for each one of those calls. 1697edaabaaSDmitri Tikhonov 1707edaabaaSDmitri TikhonovSeveral auxiliary functions are available: 1717edaabaaSDmitri Tikhonov 1727edaabaaSDmitri Tikhonov - lsquic_conn_id() 1737edaabaaSDmitri Tikhonov - lsquic_conn_going_away() 1747edaabaaSDmitri Tikhonov - lsquic_conn_get_peer_ctx() 1757edaabaaSDmitri Tikhonov - lsquic_conn_get_stream_by_id() 1767edaabaaSDmitri Tikhonov - lsquic_conn_get_ctx() 1777edaabaaSDmitri Tikhonov 1787edaabaaSDmitri Tikhonov 1797edaabaaSDmitri TikhonovStream 1807edaabaaSDmitri Tikhonov------ 1817edaabaaSDmitri Tikhonov 1827edaabaaSDmitri TikhonovLSQUIC stream hides QUIC and HTTP/2 framing complexities from the user. 1837edaabaaSDmitri TikhonovWhat it presents is a way to send HTTP headers and, optionally, body to 1847edaabaaSDmitri Tikhonovpeer. On read side, the user gets what looks like HTTP/1.1 stream. 1857edaabaaSDmitri Tikhonov 1867edaabaaSDmitri TikhonovExpected usage for client is to express the desire to write to stream 1877edaabaaSDmitri Tikhonovusing lsquic_stream_wantwrite() call. Once on_write() is called: 1887edaabaaSDmitri Tikhonov 1897edaabaaSDmitri Tikhonov 1. Write headers using lsquic_stream_send_headers() 1907edaabaaSDmitri Tikhonov 2. Optionally write payload body using of of lsquic_stream_write(), 1917edaabaaSDmitri Tikhonov lsquic_stream_writev(), or lsquic_stream_writef(). 1927edaabaaSDmitri Tikhonov 1937edaabaaSDmitri TikhonovThat done, shutdown write side using lsquic_stream_shutdown(), unregister 1947edaabaaSDmitri Tikhonovfor write events and register for read events using lsquic_stream_wantread(). 1957edaabaaSDmitri Tikhonov 1967edaabaaSDmitri TikhonovRead and parse HTTP/1.1 stream from on_read() callback until end-of-stream 1977edaabaaSDmitri Tikhonovor an error is encountered. 1987edaabaaSDmitri Tikhonov 1997edaabaaSDmitri TikhonovThen unregister the read event and shutdown the read side. The stream will 2007edaabaaSDmitri Tikhonovbe closed after that at some point and on_close() callback will be called, 2017edaabaaSDmitri Tikhonovat which point resources can be freed. (Internally, the stream object is 2027edaabaaSDmitri Tikhonovnot destroyed until either all the packets carrying its data are ACKed or 2037edaabaaSDmitri Tikhonovthe connection is destroyed). 2047edaabaaSDmitri Tikhonov 2057edaabaaSDmitri Tikhonovon_read() and on_write() callbacks are dispatched differently based on the 2067edaabaaSDmitri Tikhonovvalue of es_rw_once: 2077edaabaaSDmitri Tikhonov 2087edaabaaSDmitri TikhonovIf es_rw_once is false, then the callbacks are dispatched in a loop until 2097edaabaaSDmitri Tikhonovthe user unregisters the event or the stream becomes unreadable (or 2107edaabaaSDmitri Tikhonovunwriteable). 2117edaabaaSDmitri Tikhonov 2127edaabaaSDmitri TikhonovIf es_rw_once is true, on_read() and on_write() are called once "per tick". 2137edaabaaSDmitri TikhonovIt is the up to the user to read and write enough data. 2147edaabaaSDmitri Tikhonov 2157edaabaaSDmitri Tikhonov 2167edaabaaSDmitri TikhonovEvents 2177edaabaaSDmitri Tikhonov------ 2187edaabaaSDmitri Tikhonov 2197edaabaaSDmitri TikhonovStream events are persistent: once call lsquic_stream_wantwrite() or 2207edaabaaSDmitri Tikhonovlsquic_stream_wantread(), the event stays active until turned off. 2217edaabaaSDmitri Tikhonov 2227edaabaaSDmitri TikhonovNote that when an error is encountered (such as a stream reset), the 2237edaabaaSDmitri Tikhonovstream becomes readable and writeable: this allows user code to collect 2247edaabaaSDmitri Tikhonovthe error. 2257edaabaaSDmitri Tikhonov 2267edaabaaSDmitri Tikhonov 2277edaabaaSDmitri TikhonovVersions 2287edaabaaSDmitri Tikhonov-------- 2297edaabaaSDmitri Tikhonov 2307edaabaaSDmitri TikhonovQUIC version are listed in enum lsquic_version. To specify a list of 2317edaabaaSDmitri Tikhonovversions, they are usually placed in a bitmask, e.g. es_versions. 232