opensslBIO系列之4---BIO控制函数介绍
BIO控制函数介绍
---根据openssl doc/crypto/bio/bio_ctrl.pod翻译和⾃⼰的理解写成
(作者:DragonKing Mail:wzhah@263 发布于:  openssl专业论坛)
BIO控制函数有许多,并且不同的BIO类型还有不同的控制函数,这⾥只简单介绍⼀些通⽤的BIO控制函数,⾄于某种类型BIO的特定控制函数,则参考后续的⽂件。
BIO的通⽤控制函数有以下⼏种,其声明如下(openssl/bio.h):
long BIO_ctrl(BIO *bp,int cmd,long larg,void *parg);
long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long));
char * BIO_ptr_ctrl(BIO *bp,int cmd,long larg);
long BIO_int_ctrl(BIO *bp,int cmd,long larg,int iarg);
int BIO_reset(BIO *b);
int BIO_seek(BIO *b, int ofs);
int BIO_tell(BIO *b);
int BIO_flush(BIO *b);
int BIO_eof(BIO *b);
int BIO_set_close(BIO *b,long flag);
int BIO_get_close(BIO *b);
int BIO_pending(BIO *b);
int BIO_wpending(BIO *b);
size_t BIO_ctrl_pending(BIO *b);
size_t BIO_ctrl_wpending(BIO *b);
其实,在这些函数中,除了BIO_ctrl,BIO_callback_ctrl,BIO_ptr_ctrl,BIO_int_ctrl,BIO_ctrl_pending,BI
O_ctrl_wpending是真正的函数外,其它都是宏定义,⽽且,在这些函数中,除了BIO_ctrl,BIO_callback_ctrl,其它基本上都是简单的BIO_ctrl输⼊不同的参数的调⽤。下⾯就⼀个⼀个介绍这些函数。
【BIO_ctrl】
从上⾯的叙述可以知道,BIO_ctrl是整个控制函数中最基本的函数,它⽀持不同的命令输⼊,从⽽产⽣不同的功能,由此,它也就衍⽣了许多其它函数,作为⼀个⽐较地层的控制函数,⼀般来说⽤户并不需要直接调⽤它,因为在它之上已经使⽤宏定义和函数调⽤的形式建造了许多直接⾯向⽤户的函数。
filter型的BIO没有定义BIO_ctrl功能,如果对他们调⽤这个函数,他们就简单的把命令传到BIO链中的下⼀个BIO。也就是说,通常可以不⽤直接调⽤⼀个BIO 的BIO_ctrl函数,只需要在它所在的BIO链上调⽤该函数,那么BIO链就会⾃动将该调⽤函数传到相应的BIO上去。这样可能就会导致⼀些意想不到的结果,⽐如,在⽬前的filter型BIO中没有实现BIO_seek()函数(⼤家待会就会明⽩BIO_seek就是BIO_ctrl的简单宏定义),但如果在这个BIO链上的末尾是⼀个⽂件或⽂件描述符型BIO,那么这个调⽤也会返回成功的结果。
对于source/sink型BIO来说,如果他们不认得BIO_ctrl所定义的操作,那么就返回0。
【BIO_callback_ctrl】
这个函数是这组控制函数中唯⼀⼀个不是通过调⽤BIO_ctrl建⽴起来的,它有⾃⼰的实现函数,⽽且跟BIO_ctrl毫不相⼲。跟BIO_ctrl⼀样,它也是⽐较底层的控制函数,在它上⾯也定义了⼀些直接⾯向⽤户的控制函数,⼀般来说,⽤户不需要直接调⽤该函数。
需要说明的是,该函数和BIO_ctrl函数为了实现不同类型BIO具有不同的BIO_ctrl控制功能,他们的操作基本上都是由各个BIO的callback函数来定义的。这是不同的BIO能灵活实现不同功能的根本所在。
【BIO_ptr_ctrl和BIO_int_ctrl】
这两个函数都是简单的调⽤了BIO_ctrl函数,不同的是,后者是输⼊了四个参数并传⼊到BIO_ctrl函数中,简单返回了调⽤BIO_ctrl返回的返回值;⽽前者只输⼊了三个参数,最后⼀个BIO_ctrl参数是作为输出参数并作为返回值的。
【BIO_reset】
该函数是BIO_ctrl的宏定义函数,为了⼤家对BIO_ctrl的宏定义函数有⼀个感性的认识,我把这个宏定义写出来,如下:
#define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL)
这就是BIO_ctrl的典型宏定义⽅式,它通过这种⽅式产⽣了⼤量的控制函数。顾名思义,BIO_reset函数只是简单的将BIO的状态设回到初始化的时候的状态,⽐如⽂件BIO,调⽤该函数就是将⽂件指针指向⽂件开始位置。
⼀般来说,调⽤成功的时候该函数返回1,失败的时候返回0或-1;但是⽂件BIO是⼀个例外,成功调⽤的时候返回0,失败的时候返回-1。
【BIO_seek】pending
该函数也是BIO_ctrl的宏定义函数,其定义如下:
#define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
该函数将⽂件相关的BIO(⽂件和⽂件描述符类型)的⽂件指针知道距离开始位置ofs(输⼊参数)字节的位置上。调⽤成功的时候,返回⽂件的位置指针,否则返回-1;但是⽂件BIO例外,成功的时候返回0,失败的时候返回-1。
【BIO_tell】
该函数也是BIO_ctrl的宏定义函数,其定义如下:
#define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
该函数返回了⽂件相关BIO的当前⽂件指针位置。跟BIO_seek⼀样,调⽤成功的时候,返回⽂件的位置指针,否则返回-1;但是⽂件BIO例外,成功的时候返回0,失败的时候返回-1。
【BIO_flush】
该函数也是BIO_ctrl的宏定义函数,其定义如下:
#define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL)
该函数⽤来将BIO内部缓冲区的数据都写出去,有些时候,也⽤于为了根据EOF查看是否还有数据可以写。调⽤成功的时候该函数返回1,失败的时候返回0或-1。之所以失败的时候返回0或者-1,是为了标志该操作是否需要稍后以跟BIO_write()相同的⽅式重试。这时候,应该调⽤BIO_should_retry()函数,当然,正常的情况下该函数的调⽤应该是失败的。
【BIO_eof】
该函数也是BIO_ctrl的宏定义函数,其定义如下
#define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL)
如果BIO读到EOF,该函数返回1,⾄于EOF的具体定义,根据BIO的类型各不相同。如果没有读到EOF,该函数返回0.
【BIO_set_close】
该函数也是BIO_ctrl的宏定义函数,其定义如下:
#define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL)
该函数设置BIO的关闭标志,该标志可以为BIO_CLOSE或BIO_NOCLOSE。⼀般来说,该标志是为了指⽰在source/sink型BIO释放该BIO的时候是否关闭其下层的I/O流。该函数总是返回1。
【BIO_get_close】
该函数也是BIO_ctrl的宏定义函数,其定义如下:
#define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL)
该函数读取BIO的关闭标志,返回BIO_CLOSE或BIO_NOCLOSE。
【BIO_pending、BIO_wpending、BIO_ctrl_pending和BIO_ctrl_wpending】
这些函数都是⽤来得到BIO中读缓存或写缓存中字符的数⽬的,返回相应缓存中字符的数⽬。
前⾯两个函数也是BIO_ctrl的宏定义函数,其定义如下:
#define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
#define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL)
后两个函数功能跟他们是⼀样的,只不过他们是通过调⽤BIO_ctrl函数实现的,⽽不是宏定义。此外,前⾯两个函数返回的是int型,⽽后⾯两个函数返回的是size_t型。
需要注意的是,BIO_pending和 BIO_wpending并不是在所有情况下都能很可靠地得到缓存数据的数量,⽐如在⽂件BIO中,有些数据可能在⽂件内部结构的缓存中是有效的,但是不可能简单的在BIO中得到这些数据的数量。⽽在有些类型BIO中,这两个函数可能还不⽀持。基于此,openssl作者本⾝也建议⼀般不要使⽤这两个函数,⽽是使⽤后⾯两个,除⾮你对你所做的操作⾮常清楚和了解。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。