openssl之BIO系列之16---BIO對(pair)類型BIO,openssl16---bio

來源:互聯網
上載者:User

openssl之BIO系列之16---BIO對(pair)類型BIO,openssl16---bio

BIO對(pair)類型BIO

    ---根據openssl doc\crypto\bio_s_bio.pod翻譯和自己的理解寫成

    (作者:DragonKing, Mail: wzhah@263.net ,發佈於:http://gdwzh.126.com之o

penssl專業論壇)

    前面我們已經介紹過BIO對的概念,其實更進一步,BIO對也是作為一種source/sin

k類型的BIO來處理的,也就是說,BIO裡面還提供了一種專門的BIO_METHO方法來處理BI

O對的各種操作。BIO對類型的BIO各種相關的函數定義如下(openssl\bio.h):

     BIO_METHOD *BIO_s_bio(void);

     #define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0

,b2)

     #define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,

0,NULL)

     #define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL)

 

     #define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_

BUF_SIZE,size,NULL)

     #define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRI

TE_BUF_SIZE,size,NULL)

     int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, BIO **bio2, size_t w

ritebuf2);

     #define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUAR

ANTEE,0,NULL)

     size_t BIO_ctrl_get_write_guarantee(BIO *b);

     #define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,

0,NULL)

     size_t BIO_ctrl_get_read_request(BIO *b);

     int BIO_ctrl_reset_read_request(BIO *b);

    可以看到,這些函數中大多數是宏定義函數並且都是基於BIO_ctrl函數的。

    BIO對類型的BIO是一對source/sink型的BIO,資料通常是從一個BIO緩衝寫入,從另

一個BIO讀出。其實,從原始碼(bss_bio.c)可以看出,所謂的BIO對只是將兩個BIO的

終端輸出(BIO結構中參數peer的ptr成員)相互設定為對方,從而形成一種對稱的結構

,如下:

     bio1->peer->ptr=bio2

     bio2->peer->ptr=bio1

     資料流向1(寫bio1,讀bio2):--->bio1--->bio2--->

     資料流行2(寫bio2,讀bio1):--->bio2--->bio1--->

    因為沒有提供內部資料結構的記憶體鎖結構(lock),所以,一般來說這個BIO對的兩個

BIO都必須在一個線程下使用。因為BIO鏈通常是以一個source/sink BIO結束的,所以就

可以實現應用程式通過控制BIO對的一個BIO從而控制整個BIO鏈的資料處理。其實,也就

相當於BIO對給應用程式提供了一個處理整個BIO鏈的入口。上次我們說BIO對的時候就說

過,BIO對的一個典型應用就是在應用程式裡面控制TLS/SSL的I/O介面,一般來說,在應

用程式想在TLS/SSL中使用非標準的傳輸方法或者不適合使用標準的socket方法的時候就

可以採用這樣的方法來實現。

    前面提過,BIO對釋放的時候,需要分別釋放兩個BIO,如果在使用BIO_free或者BI

O_free_all釋放了其中一個BIO的時候,另一個BIO就也必須要釋放。

    當BIO對使用在雙嚮應用程式的時候,如TLS/SSL,一定要對寫緩衝區裡面的資料執

行flush操作。當然,也可以通過在BIO對中的另一個BIO調用BIO_pending函數,如果有

資料在緩衝區中,那麼就將它們讀出並發送到底層的傳輸通道中區。為了使請求或BIO_

should_read函數調用成功(為true),在執行任何正常的操作(如select)之前,都必

須這樣做才行。

    下面舉一個例子說明執行flush操作的重要性:

    考慮在TLS/SSL握手過程中,採用了BIO_write函數發送了資料,相應的操作應該使

BIO_read。BIO_write操作成功執行並將資料寫入到寫緩衝區中。BIO_read調用開始會失

敗,BIO_should_retry返回true。如果此時對寫緩衝區不執行flush操作,那麼BIO_rea

d調用永遠不會成功,因為底層傳輸通道會一直等待直到資料有效(但資料卻在寫緩衝區

裡,沒有傳到底層通道)。

    【BIO_s_bio】

    該函數返回一個BIO對類型的BIO_METHOD,其定義如下:

    static BIO_METHOD methods_biop =

    { BIO_TYPE_BIO,

     "BIO pair",

     bio_write,

     bio_read,

     bio_puts,

     NULL /* 沒有定義 bio_gets */,

     bio_ctrl,

     bio_new,

     bio_free,

     NULL /* 沒有定義 bio_callback_ctrl */

    };

    從定義中可以看到,該類型的BIO不支援BIO_gets的功能。

    BIO_read函數從緩衝BIO中讀取資料,如果沒有資料,則發出一個重試請求。

    BIO_write函數往緩衝BIO中寫入資料,如果緩衝區已滿,則發出一個重試請求。

    BIO_ctrl_pending和BIO_ctrl_wpending函數可以用來查看在讀或寫緩衝區裡面有效

的資料的數量。

    BIO_reset函數將寫緩衝區裡面的資料清除。

    【BIO_make_bio_pair】

    該函數將兩個單獨的BIO串連起來成為一個BIO對。

    【BIO_destroy_pair】

    該函數跟上面的函數相反,它將兩個串連起來的BIO對拆開;如果一個BIO對中的任

何一個BIO被釋放,該操作會自動執行。

    【BIO_shutdown_wr】

    該函數關閉BIO對的其中一個BIO,一個BIO被關閉後,針對該BIO的任何寫操作都會

返回錯誤。從另一個BIO讀資料的時候要麼返回剩餘的有效資料,要麼返回EOF。

    【BIO_set_write_buf_size】

    該函數設定BIO的緩衝區大小。如果該BIO的緩衝區大小沒有初始化,那麼就會使用

預設的值,大小為17k,這對於一個TLS記錄來說是足夠大的了。

    【BIO_get_write_buf_size】

    該函數返回寫緩衝區的大小。

    【BIO_new_bio_pair】

    該函數我們在前面的《BIO系列之9---BIO對的建立和應用》中已經做了詳細的介紹

,其實,它是調用了BIO_new,BIO_make_bio_pair和BIO_set_write_buf_size函數來建立

一對BIO對的。如果兩個緩衝區長度的參數都為零,那麼就會使用預設的緩衝區長度。

    【BIO_get_write_guarantee和BIO_ctrl_get_write_guarantee】

    這兩個函數返回當前能夠寫入BIO的資料的最大長度。如果往BIO寫入的資料長度比

該函數返回的資料長度大,那麼BIO_write返回的寫入資料長度會小於要求寫入的資料,

如果緩衝區已經滿了,則會發出一個重試的請求。這兩個函數的唯一不同之處是一個使

用函數實現的,一個是使用宏定義實現的。

    【BIO_get_read_request和BIO_ctrl_get_read_request】

    這兩個函數返回要求發送的資料的長度,這通常是在對該BIO對的另一個BIO執行讀

操作時因為緩衝區資料為空白導致失敗時發出的請求。所以,這通常用來表明現在應該寫

入多少資料才能使接下來的讀操作能夠成功執行,這在TLS/SSL應用程式中是非常有用的

,因為對於這個協議來說,讀取的資料長度比緩衝區的資料長度通常要有意義的多。如

果在讀操作成功之後調用這兩個函數會返回0,如果在調用該函數之前有新的資料寫入(

不管是部分還是全部滿足需要讀取的資料的要求),那麼調用該函數也會返回0。理所當

然,該函數返回的資料長度肯定不會大於BIO_get_write_guarantee函數返回的資料長度

    【BIO_ctrl_reset_read_request】

    該函數就是把BIO_get_read_request要返回值設定為0。

    【參考文檔】

    《BIO系列之9---BIO對的建立和應用》

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.