openssl-quic
名稱
openssl-quic - OpenSSL QUIC
說明
OpenSSL 3.2 及後續版本支援 QUIC 傳輸協定。目前僅支援用戶端連線。此手冊頁說明現有和新應用程式使用 QUIC 用戶端功能的方式。
QUIC 功能使用標準 SSL API。QUIC 連線以 SSL 物件表示,就像 TLS 連線一樣。現有應用程式只要對使用 libssl API 的部分做極小的變更,即可使用 QUIC 用戶端功能。若要使用 QUIC,請將 SSL 方法 OSSL_QUIC_client_method(3) 或 OSSL_QUIC_client_thread_method(3) 與 SSL_CTX_new(3) 搭配使用。
建立 QUIC 連線時,預設會以預設串流模式運作,目的是為了與現有的非 QUIC 應用程式使用模式相容。在此模式中,連線會有一個與其關聯的單一串流。在 QUIC 連線 SSL 物件上呼叫 SSL_read(3) 和 SSL_write(3) 會從該串流讀取和寫入資料。從 QUIC 的角度來看,串流是由用戶端或伺服器發起的,這取決於 SSL_read(3) 或 SSL_write(3) 先被呼叫。有關更多資訊,請參閱運作模式區段。
預設串流模式旨在與現有應用程式相容。建議使用 QUIC 的新應用程式停用預設串流模式,並使用多串流 API;有關更多資訊,請參閱運作模式區段和新應用程式的建議區段。
本手冊頁的其餘部分依序討論
預設串流模式與多串流模式;
現有 libssl API 的變更,這些變更是由 QUIC 相關的實作需求所驅動,現有應用程式應注意這些變更;
現有應用程式在採用 QUIC 時必須考量的面向,包括可能需要的變更。
新應用程式的建議使用方式。
新的 QUIC 專用 API。
運作模式
預設串流模式
QUIC 客户端連線可以使用預設串流模式或多串流模式。預設情況下,新建立的 QUIC 連線 SSL 物件會使用預設串流模式。
在預設串流模式中,會隱式建立一個串流並繫結到 QUIC 連線 SSL 物件;對 QUIC 連線 SSL 物件的 SSL_read(3) 和 SSL_write(3) 呼叫會預設運作並對應到該串流。
當使用預設串流模式時,任何可以在 QUIC 串流 SSL 物件上呼叫的 API 函數也可以在 QUIC 連線 SSL 物件上呼叫,這種情況下它會影響繫結到連線的預設串流。
QUIC 串流的身分,包括其串流 ID,會根據串流是由客户端啟動或伺服器啟動而有所不同。在預設串流模式中,如果客户端應用程式在對連線進行任何 SSL_write(3) 呼叫之前先呼叫 SSL_read(3),則假設應用程式協定使用伺服器啟動的串流,並且 SSL_read(3) 呼叫不會完成(如果已設定非封鎖模式,則會封鎖或適當地失敗),直到伺服器啟動一個串流。相反地,如果客户端應用程式在對連線進行任何 SSL_read(3) 呼叫之前先呼叫 SSL_write(3),則假設要使用客户端啟動的串流,並且會自動建立這樣的串流。
預設串流模式旨在協助與舊版應用程式的相容性。採用 QUIC 的新應用程式應使用下方說明的多串流模式,並避免使用預設串流功能。
可以使用 SSL_new_stream(3) 和 SSL_accept_stream(3) 在預設串流模式中使用其他串流;請注意,需要使用 SSL_set_incoming_stream_policy(3) 變更預設的傳入串流政策,才能在這種情況下使用 SSL_accept_stream(3)。但是,強烈建議使用其他串流的應用程式改用多串流模式。
在與 QUIC 連線 SSL 物件關聯預設串流之前呼叫 SSL_new_stream(3) 或 SSL_accept_stream(3) 會禁止未來建立預設串流。
多串流模式
採用 QUIC 的新應用程式的建議使用模式為多串流模式,其中沒有預設串流附加到 QUIC 連線 SSL 物件,並且嘗試對 QUIC 連線 SSL 物件呼叫 SSL_read(3) 和 SSL_write(3) 會失敗。相反地,應用程式會呼叫 SSL_new_stream(3) 或 SSL_accept_stream(3) 來建立個別串流 SSL 物件,以使用 SSL_read(3) 和 SSL_write(3) 傳送和接收應用程式資料。
若要使用多串流模式,請呼叫 SSL_set_default_stream_mode(3),並提供引數 SSL_DEFAULT_STREAM_MODE_NONE;此函式必須在啟動連線前呼叫。啟動連線後,預設串流模式無法變更。
當使用多串流模式(表示沒有預設串流與連線關聯)時,若在 QUIC 連線 SSL 物件上呼叫定義為在 QUIC 串流上運作的 API 函式,則呼叫會失敗。例如,SSL_write(3) 或 SSL_get_stream_id(3) 等呼叫會失敗。
現有 API 的變更
大多數的 SSL API,例如 SSL_read(3) 和 SSL_write(3),其功能與 TLS 連線相同,語意未變更,但有少數例外。現有 API 的語意變更如下
由於 QUIC 使用 UDP,SSL_set_bio(3)、SSL_set0_rbio(3) 和 SSL_set0_wbio(3) 的功能與之前相同,但現在必須接收具有資料報語意的 BIO。應用程式大致有四種選項可作為網路 BIO
BIO_s_datagram(3),建議大多數應用程式使用,取代 BIO_s_socket(3),並提供 UDP socket。
BIO_s_dgram_pair(3) 提供類似 BIO 配對的功能,但具有資料報語意,建議使用於現有應用程式,這些應用程式使用 BIO 配對或記憶體 BIO 來管理 libssl 與網路的通訊。
BIO_s_dgram_mem(3) 提供簡單的記憶體 BIO 類似介面,但具有資料報語意。與 BIO_s_dgram_pair(3) 不同,它是單向的。
應用程式也可以選擇實作自訂 BIO。必須支援新的 BIO_sendmmsg(3) 和 BIO_recvmmsg(3) API。
SSL_set_fd(3)、SSL_set_rfd(3) 和 SSL_set_wfd(3) 傳統上會實例化一個 BIO_s_socket(3)。對於 QUIC,這些函式會實例化一個 BIO_s_datagram(3)。這等同於實例化一個 BIO_s_datagram(3) 並使用 SSL_set0_rbio(3) 和 SSL_set0_wbio(3)。
傳統上,應用程式層級 I/O API(例如 SSL_read(3) 和 SSL_write(3))是否以封鎖模式運作,與底層網路 Socket 是否以封鎖模式設定直接相關。現在不再是這樣;應用程式必須使用 SSL_set_blocking_mode(3) 明確設定所需的應用程式層級封鎖模式。有關詳細資訊,請參閱 SSL_set_blocking_mode(3)。
網路層級 I/O 必須始終以非封鎖模式執行。應用程式仍可享受應用程式層級 I/O 函式(例如 SSL_read(3) 和 SSL_write(3))的封鎖語意,但提供給 QUIC 的底層網路 BIO(例如 BIO_s_datagram(3))必須以非封鎖模式設定。有關應用程式層級封鎖功能,請參閱 SSL_set_blocking_mode(3)。
BIO_new_ssl_connect(3) 已變更為在與 QUIC 搭配使用時自動使用 BIO_s_datagram(3),因此使用此函式的應用程式不需要變更其使用的 BIO。
BIO_new_buffer_ssl_connect(3) 無法與 QUIC 搭配使用,應用程式必須變更為使用 BIO_new_ssl_connect(3)。
SSL_shutdown(3) 在與 QUIC 連線的關閉方式方面有重大變更。特別是,應建議應用程式,符合 RFC 的完整 QUIC 關閉程序可能需要較長的時間。這可能不適合使用 QUIC 連線後應立即結束的短暫程序。此類應用程式可使用快速關閉模式。有關詳細資訊,請參閱 SSL_shutdown(3)。
SSL_want(3)、SSL_want_read(3) 和 SSL_want_write(3) 不再反映傳遞給 QUIC SSL 物件的網路 BIO 的 I/O 狀態,而是反映與 SSL 物件相關聯的 QUIC 串流的流量控制狀態。
在非封鎖模式下使用時,SSL_ERROR_WANT_READ 表示 QUIC 串流的接收部分目前沒有更多可讀取的資料,而 SSL_ERROR_WANT_WRITE 表示串流的內部緩衝區已滿。
若要判斷 QUIC 實作目前是否希望收到傳入網路資料報,請使用新的函式 SSL_net_read_desired(3);同樣地,若要判斷 QUIC 實作目前是否希望在可以傳輸網路資料報時收到通知,請使用新的函式 SSL_net_write_desired(3)。只有希望管理自己的事件迴圈的應用程式才需要使用這些函式;請參閱 應用程式驅動的事件迴圈 以進一步討論。
使用 QUIC 時,ALPN 的使用是強制性的。嘗試在未設定 ALPN 的情況下連線將會失敗。有關如何設定 ALPN 的資訊,請參閱 SSL_set_alpn_protos(3)。
QUIC 是以客戶端或伺服器模式運作,是由所使用的 SSL_METHOD 決定,而不是呼叫 SSL_set_connect_state(3) 或 SSL_set_accept_state(3) 來決定。在連線之前,不需要呼叫 SSL_set_connect_state(3) 或 SSL_set_accept_state(3),但如果呼叫其中任何一個,所呼叫的函式必須與所使用的 SSL_METHOD 相符。目前,只支援客戶端模式。
SSL_set_min_proto_version(3) 和 SSL_set_max_proto_version(3) API 未使用,傳遞給它們的值會被忽略,因為 OpenSSL QUIC 目前始終使用 TLS 1.3。
與 QUIC 搭配使用時,下列 libssl 功能不可用。
非同步功能
SSL_MODE_AUTO_RETRY
記錄區塊填補和分段 (SSL_set_block_padding(3) 等)
SRTP 功能
TLSv1.3 早期資料
TLS 下一個協定協商無法使用,並被 ALPN 取代,必須改用 ALPN。與 QUIC 搭配使用時,ALPN 的使用是強制性的。
握手後客戶端驗證不可用,因為 QUIC 禁止使用它。
QUIC 需要使用 TLSv1.3 或更新版本,因此僅與較舊 TLS 版本相關的功能不可用。
某些通常可供 TLSv1.3 使用的加密組不適用於 QUIC,例如 TLS_AES_128_CCM_8_SHA256。您的應用程式可能需要調整傳遞給 libssl 的可接受加密組清單。
目前不支援 CCM 模式。
與 QUIC 搭配使用時,下列 libssl 功能也不可用,但呼叫相關函式會被視為空操作
預先讀取 (SSL_set_read_ahead(3) 等)
現有應用程式的考量
現有應用程式尋求採用 QUIC 時,應套用以下清單來決定需要進行哪些變更
希望使用 QUIC 的應用程式必須使用 OSSL_QUIC_client_method(3) 或 OSSL_QUIC_client_thread_method(3) 作為其 SSL 方法。如需進一步瞭解這兩個方法之間的差異,請參閱執行緒輔助模式。
決定如何提供網路存取給 QUIC。決定下列哪些適用於您的應用程式
您的應用程式使用 BIO_s_socket(3) 建構 BIO,並傳遞給 SSL 物件以提供網路存取。
所需的變更:當使用 QUIC 時,變更您的應用程式以改用 BIO_s_datagram(3)。必須將 socket 設定為非封鎖模式。您可能需要或不需要使用 SSL_set1_initial_peer_addr(3) 來設定初始對等位址;有關詳細資訊,請參閱QUIC 特定 API區段。
您的應用程式使用 BIO_new_ssl_connect(3) 建構 BIO,並傳遞給 SSL 物件以提供網路存取。
所需的變更:不需要變更。系統會自動偵測 QUIC 的使用,並建立資料報 socket,而非一般 TCP socket。
您的應用程式使用此清單中的任何其他 I/O 策略,但將其與 BIO_f_buffer(3) 結合使用,例如使用 BIO_push(3)。
所需的變更:當使用 QUIC 時,停用 BIO_f_buffer(3) 的使用。此類緩衝區的使用與 QUIC 不相容,因為 QUIC 在與網路互動時需要資料報語意。
您的應用程式使用 BIO 對來讓 SSL 物件讀取和寫入網路流量至記憶體緩衝區。您的應用程式會以 libssl 不知道的方式自行管理緩衝資料的傳輸和接收。
所需的變更:從使用傳統 BIO 對切換為改用 BIO_s_dgram_pair(3),它具有必要的資料報語意。您需要修改您的應用程式,以使用 UDP socket 傳輸和接收,並在與 BIO_s_dgram_pair(3) 執行個體互動時使用資料報語意。
您的應用程式使用自訂 BIO 方法來提供網路存取給 SSL 物件。
必要的變更:自訂 BIO 必須重新建構,以具有資料報語意。必須實作 BIO_sendmmsg(3) 和 BIO_recvmmsg(3)。這些呼叫必須以非封鎖方式執行。如果需要,可選擇實作 BIO_get_rpoll_descriptor(3) 和 BIO_get_wpoll_descriptor(3) 方法。如果需要在 SSL API 層級封鎖語意,則必須實作這些方法。
應用程式必須明確設定是否要以封鎖模式使用 SSL API。傳統上,SSL 物件會根據底層網路 BIO 是否以封鎖或非封鎖模式執行,自動以封鎖或非封鎖模式執行。QUIC 需要使用非封鎖網路 BIO,因此應用程式必須使用新的 SSL_set_blocking_mode(3) API,在應用程式層級明確設定封鎖模式。預設模式為封鎖。如果應用程式希望在應用程式層級以非封鎖方式使用 SSL 物件 API,則必須新增呼叫 SSL_set_blocking_mode(3),以停用封鎖模式。
如果您的應用程式不選擇使用執行緒輔助模式,則必須確保定期對 SSL 物件呼叫 I/O 函數(例如 SSL_read(3) 或 SSL_write(3)),或新函數 SSL_handle_events(3)。如果 SSL 物件以封鎖模式使用,則對 I/O 函數的進行中封鎖呼叫會滿足此需求。這對於確保 QUIC 所需的計時器事件能及時處理是必要的。
大多數應用程式會定期呼叫 SSL_read(3) 或 SSL_write(3) 來服務 SSL 物件。如果應用程式不這麼做,則應確保定期呼叫 SSL_handle_events(3)。
SSL_get_event_timeout(3) 可用於判斷何時必須再次呼叫 SSL_handle_events(3)。
如果 SSL 物件與可輪詢的底層網路 BIO(例如 BIO_s_datagram(3))一起使用,則應用程式可以使用 SSL_get_rpoll_descriptor(3)、SSL_get_wpoll_descriptor(3) 來取得資源,這些資源可用於判斷何時應由於網路 I/O 而呼叫 SSL_handle_events(3)。
使用執行緒輔助模式的應用程式不必擔心此需求,因為 QUIC 實作會確保計時器事件能及時處理。有關詳細資訊,請參閱執行緒輔助模式。
請確保您對 SSL_want(3)、SSL_want_read(3) 和 SSL_want_write(3) 的使用反映在現有 API 的變更中所述的 API 變更。特別是,您應使用這些 API 來判斷 QUIC 串流接收或提供應用程式資料的能力,而不是判斷是否需要網路 I/O。
評估您的應用程式使用 SSL_shutdown(3) 的方式,並考量變更現有 API中所討論的變更。根據您的應用程式是要優先考量 RFC 相符性或快速關閉,請考慮改用新的 SSL_shutdown_ex(3) API。有關詳細資訊,請參閱QUIC 專用 API。
建議在新的應用程式中使用
建議在新的應用程式中使用的內容會根據三個獨立的設計決策而有所不同
應用程式是否會在應用程式層級使用封鎖或非封鎖 I/O(使用 SSL_set_blocking_mode(3) 設定)。
如果應用程式在應用程式層級執行非封鎖 I/O,它可以選擇管理自己的輪詢和事件迴圈;請參閱應用程式驅動的事件迴圈。
應用程式是否打算讓 QUIC 實作直接存取網路 socket(例如透過 BIO_s_datagram(3)),還是打算透過 BIO_s_dgram_pair(3) 或自訂 BIO 來緩衝傳輸和接收的資料報。
如果可能,建議使用前者,因為它可以降低網路延遲,讓 QUIC 能夠達到更高的效能和更精確的連線往返時間 (RTT) 估計。
是否會使用執行緒輔助模式(請參閱執行緒輔助模式)。
可以在 https://github.com/openssl/openssl/tree/master/doc/designs/ddd 找到在這些不同情況下使用 QUIC 的簡單示範。
想要實作 QUIC 專用通訊協定的應用程式應該注意QUIC 專用 API中所列出的 API,這些 API 提供存取 QUIC 專用功能。例如,SSL_stream_conclude(3) 可用於指出串流傳送部分的結束,而 SSL_shutdown_ex(3) 可用於在關閉連線時提供 QUIC 應用程式錯誤碼。
不論採用何種設計決策,建議新應用程式避免使用預設串流模式,並透過呼叫 SSL_set_default_stream_mode(3) 來使用多串流 API;有關詳細資訊,請參閱操作模式區段。
QUIC 特定 API
本區段詳述與 QUIC 直接或間接相關的新 API。有關每個 API 操作的詳細資訊,請參閱所引用的手冊頁面。
下列 SSL API 為新增功能,但與 QUIC 和 DTLS 都相關
- SSL_get_event_timeout(3)
-
如果有的話,決定 QUIC 實作應透過呼叫 SSL_handle_events(3)(或其他 I/O 函數,例如 SSL_read(3) 或 SSL_write(3))在何時再次喚醒。
這也可以搭配 DTLS 使用,並取代 DTLSv1_get_timeout(3) 以供新用途。
- SSL_handle_events(3)
-
這是一個非特定 I/O 操作,會盡力嘗試執行任何待處理的 I/O 或逾時處理。它可用於透過處理接收的網路流量、產生傳送的網路流量和處理任何逾時事件,來推動 QUIC 狀態機。SSL 物件上的大多數其他 I/O 函數,例如 SSL_read(3) 和 SSL_write(3),會隱含地對 SSL 物件執行事件處理,因此只有在不需要呼叫其他 I/O 函數時,才需要呼叫此函數。
這也可以搭配 DTLS 使用,並取代 DTLSv1_handle_timeout(3) 以供新用途。
下列 SSL API 為 QUIC 特定功能
- SSL_set_blocking_mode(3)、SSL_get_blocking_mode(3)
-
設定是否在應用程式層級使用封鎖語意。這會決定呼叫 SSL_read(3) 和 SSL_write(3) 等函數時是否會封鎖。
- SSL_get_rpoll_descriptor(3)、SSL_get_wpoll_descriptor(3)
-
這些函數有助於在非封鎖模式下執行操作。
當 SSL 物件與支援輪詢的底層網路讀取 BIO 搭配使用時,SSL_get_rpoll_descriptor(3) 會輸出一個作業系統資源,可用於同步網路可讀取事件,這些事件應會導致呼叫 SSL_handle_events(3)。 SSL_get_wpoll_descriptor(3) 以類似的方式適用於底層網路寫入 BIO。
只有當 SSL_net_read_desired(3) 和 SSL_net_write_desired(3) 分別傳回 1 時,才需要使用這些函數提供的輪詢描述符。
- SSL_net_read_desired(3)、SSL_net_write_desired(3)
-
這些函式有助於在非封鎖模式中執行,並分別與 SSL_get_rpoll_descriptor(3) 和 SSL_get_wpoll_descriptor(3) 搭配使用。它們會判斷各自的輪詢描述符是否目前與輪詢目的相關。
- SSL_set1_initial_peer_addr(3)
-
此函式可用於設定傳出 QUIC 連線的初始對等端位址。在一般情況下建立傳出 QUIC 連線時,必須使用此函式;不過,在某些情況下,可以自動偵測正確的初始對等端位址。有關詳細資訊,請參閱 SSL_set1_initial_peer_addr(3)。
- SSL_shutdown_ex(3)
-
此函式擴充 SSL_shutdown(3),允許指定應用程式錯誤碼。它也允許客戶端決定要多快執行關閉,可能會犧牲嚴格的 RFC 相容性。
- SSL_stream_conclude(3)
-
此函式允許應用程式指出 QUIC 串流傳送部分的正常結束。這對應於 QUIC RFC 中的 FIN 旗標。串流的接收部分仍然可以使用。
- SSL_stream_reset(3)
-
此函式允許應用程式指出串流傳送部分的非正常終止。這對應於 QUIC RFC 中的 RESET_STREAM 框架。
- SSL_get_stream_write_state(3) 和 SSL_get_stream_read_state(3)
-
此函式允許應用程式分別判斷串流傳送和接收部分的目前串流狀態。
- SSL_get_stream_write_error_code(3) 和 SSL_get_stream_read_error_code(3)
-
此函式允許應用程式判斷對等端發出的應用程式錯誤碼,該對等端已執行串流傳送或接收部分的非正常終止(如果有的話)。
- SSL_get_conn_close_info(3)
-
此函式允許應用程式判斷當本機或遠端端點終止 QUIC 連線時發出的錯誤碼。
- SSL_get0_connection(3)
-
從 QUIC 串流 SSL 物件取得 QUIC 連線 SSL 物件。
- SSL_is_connection(3)
-
如果 SSL 物件不是 QUIC 串流 SSL 物件,則傳回 1。
- SSL_get_stream_type(3)
-
提供有關附加到 SSL 物件的 QUIC 串流類型的資訊。
- SSL_get_stream_id(3)
-
傳回 QUIC 協定已與 QUIC 串流關聯的 QUIC 串流 ID。
- SSL_new_stream(3)
-
建立新的 QUIC 串流 SSL 物件,代表新的、本機發起的 QUIC 串流。
- SSL_accept_stream(3)
-
可能會產生新的 QUIC 串流 SSL 物件,代表新的遠端發起的 QUIC 串流,如果連線已設定為執行此動作,則會阻擋,直到有可用的串流為止。
- SSL_get_accept_stream_queue_len(3)
-
提供有關待處理的遠端發起串流數量的資訊。
- SSL_set_incoming_stream_policy(3)
-
設定如何處理遠端發起的串流。可使用傳入串流政策自動拒絕對等端建立的串流,或允許使用 SSL_accept_stream(3) 處理這些串流。
- SSL_set_default_stream_mode(3)
-
用於設定或停用預設串流模式;有關詳細資訊,請參閱操作模式區段。
下列 BIO API 並非 QUIC 專屬,但已新增以利於 QUIC 特定需求,且與其使用密切相關
- BIO_s_dgram_pair(3)
-
這是一種新的 BIO 方法,類似於傳統的 BIO 配對,但提供資料報語意。
- BIO_get_rpoll_descriptor(3)、BIO_get_wpoll_descriptor(3)
-
這是一種新的 BIO API,允許 BIO 公開輪詢描述符。此 API 用於實作對應的 SSL API SSL_get_rpoll_descriptor(3) 和 SSL_get_wpoll_descriptor(3)。
- BIO_sendmmsg(3)、BIO_recvmmsg(3)
-
這是一種新的 BIO API,可由實作資料報語意的 BIO 實作。它是由 BIO_s_datagram(3) 和 BIO_s_dgram_pair(3) 實作。QUIC 實作使用它來傳送和接收 UDP 資料報。
- BIO_dgram_set_no_trunc(3)、BIO_dgram_get_no_trunc(3)
-
預設情況下,BIO_s_dgram_pair(3) 的語意與使用資料報語意的 Berkeley socket 相當。這允許啟用替代模式,在該模式下,如果資料報過大,將不會靜默地截斷它們。
- BIO_dgram_set_caps(3)、BIO_dgram_get_caps(3)
-
這些函式用於允許 BIO_s_dgram_pair(3) 的一端使用者向 BIO_s_dgram_pair(3) 的另一端指示其功能。特別是,這允許應用程式通知 QUIC 實作是否準備處理傳輸資料報中的本地和/或對等位址,並在接收的資料報中提供適用的資訊。
- BIO_dgram_get_local_addr_cap(3)、BIO_dgram_set_local_addr_enable(3)、BIO_dgram_get_local_addr_enable(3)
-
本地定址支援是指具有資料報語意的 BIO 的能力,允許在傳輸時指定來源位址,並在接收時報告目的地位址。這些函式可用於確定 BIO 是否支援本地定址,以及是否可以在支援的情況下啟用本地定址支援。
- BIO_err_is_non_fatal(3)
-
這用於確定呼叫 BIO_sendmmsg(3) 或 BIO_recvmmsg(3) 時的錯誤是否本質上是短暫的,例如「會封鎖」錯誤。
執行緒輔助模式
可選的執行緒輔助模式可與 OSSL_QUIC_client_thread_method(3) 搭配使用。在此模式中,會自動建立背景執行緒。然後,OpenSSL QUIC 實作負責確保即使應用程式長時間未呼叫 SSL I/O 函式(例如 SSL_read(3) 或 SSL_write(3)),也會及時處理逾時事件。
所有必要的鎖定都會在內部自動處理,但公開 SSL API 的執行緒安全性保證不變。因此,如果應用程式希望同時使用公開 SSL API,則仍必須自行鎖定。
由於此方法依賴執行緒,因此在不支援執行緒或 OpenSSL 不支援執行緒的平台上無法使用。但是,它確實為應用程式提供了最簡單的使用模式。
實作可能會或可能不會使用共用執行緒或執行緒池來服務同一 SSL_CTX 中的多个 SSL 物件。
應用程式驅動事件迴圈
OpenSSL 的 QUIC 實作旨在協助應用程式以封鎖方式使用 SSL API,但同時也協助應用程式以非封鎖方式使用 SSL API,並直接管理自己的事件迴圈和輪詢。這在希望在應用程式的現有非封鎖 I/O 基礎架構上主機 OpenSSL 的 QUIC 實作時很有用。
這透過輪詢描述符的概念獲得支援;請參閱 BIO_get_rpoll_descriptor(3) 以取得詳細資料。廣義來說,BIO_POLL_DESCRIPTOR 是一種結構,表示某種可用於在 I/O 事件上同步化的作業系統資源。QUIC 實作提供一個基於底層網路 BIO 所提供的輪詢描述符的 BIO_POLL_DESCRIPTOR。這通常是作業系統的 socket 句柄,不過自訂 BIO 可以選擇實作自己的自訂輪詢描述符格式。
廣義來說,希望管理自己事件迴圈的應用程式應該以下列方式與 SSL 物件互動
它應該使用 SSL_set0_rbio(3) 和 SSL_set0_wbio(3),以非封鎖資料報語意將讀取和寫入 BIO 提供給 SSL 物件。這可以是抽象化網路 socket 的 BIO,例如 BIO_s_datagram(3),或是抽象化某種記憶體緩衝區的 BIO,例如 BIO_s_dgram_pair(3)。也可以使用自訂 BIO。
它應該透過呼叫 SSL_set_blocking_mode(3),將 SSL 物件設定為非封鎖模式。
它應該依需要設定 SSL 物件,使用 SSL_set1_initial_peer_addr(3) 設定初始對等端,並透過呼叫 SSL_connect(3) 來觸發連線程序。
如果提供的網路讀取和寫入 BIO 是可輪詢的(例如 BIO_s_datagram(3),或實作 BIO_get_rpoll_descriptor(3) 和 BIO_get_wpoll_descriptor(3) 的自訂 BIO),它應該重複執行下列步驟
應用程式應該呼叫 SSL_get_rpoll_descriptor(3) 和 SSL_get_wpoll_descriptor(3),以識別可用於同步化的作業系統資源。
它應該呼叫 SSL_net_read_desired(3) 和 SSL_net_write_desired(3),以判斷 QUIC 實作目前是否對提供的底層網路 BIO 上的可讀性和可寫入性事件感興趣,並呼叫 SSL_get_event_timeout(3),以判斷未來是否會套用任何逾時事件。
它應該等到發生下列事件之一
由 SSL_get_rpoll_descriptor(3) 傳回的輪詢描述符變成可讀(如果 SSL_net_read_desired(3) 傳回 1);
SSL_get_wpoll_descriptor(3) 傳回的輪詢描述子變為可寫入(如果 SSL_net_write_desired(3) 傳回 1);
SSL_get_event_timeout(3) 傳回的逾時(如果有)到期。
一旦發生這些事件,就應該呼叫 SSL_handle_events(3)。
如果提供的網路讀取和寫入 BIO 不可輪詢(例如,在 BIO_s_dgram_pair(3) 的情況下),應用程式負責管理和同步網路 I/O。它應該在將資料寫入 BIO_s_dgram_pair(3) 或採取其他動作後呼叫 SSL_handle_events(3),以便 QUIC 實作可以透過呼叫基礎網路 BIO 上的 BIO_recvmmsg(3) 讀取新的資料報。QUIC 實作可能會透過呼叫 BIO_sendmmsg(3) 輸出資料報,而應用程式負責確保傳輸這些資料報。
應用程式必須在每次呼叫 SSL_handle_events(3)(或 SSL 物件上的其他 I/O 函式)後呼叫 SSL_get_event_timeout(3),並確保在指定逾時(如果有)後執行 SSL_handle_events(3) 呼叫。
另請參閱
SSL_handle_events(3)、SSL_get_event_timeout(3)、SSL_net_read_desired(3)、SSL_net_write_desired(3)、SSL_get_rpoll_descriptor(3)、SSL_get_wpoll_descriptor(3)、SSL_set_blocking_mode(3)、SSL_shutdown_ex(3)、SSL_set1_initial_peer_addr(3)、SSL_stream_conclude(3)、SSL_stream_reset(3)、SSL_get_stream_read_state(3)、SSL_get_stream_read_error_code(3)、SSL_get_conn_close_info(3)、SSL_get0_connection(3)、SSL_get_stream_type(3)、SSL_get_stream_id(3)、SSL_new_stream(3)、SSL_accept_stream(3)、SSL_set_incoming_stream_policy(3)、SSL_set_default_stream_mode(3)
版權
Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
在 Apache License 2.0(「授權」)下授權。您不得使用此檔案,除非符合授權。您可以在原始程式碼散佈中的 LICENSE 檔案或 https://www.openssl.org/source/license.html 取得副本。