openssl之BIO系列之16---BIO对(pair)类型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对的创建和应用》

 

posted @ 2017-05-11 11:07  jzdwajue  阅读(331)  评论(0编辑  收藏  举报