1. 操纵错误队列
每当有ERROR产生,一些重要的信息会被记录下来。一些信息可用于尝试自动恢复错误,但是其中的大多数都是用于调试和向用户报告错误。
有6个API用于从Error队列中获取信息。ERROR是依产生的顺序记录在队列中的,这些函数都能获取到当前队列中最早的信息。
最基本的消息是一个32-bit integer型的Error code。如果Error队列中无任何消息,error处理函数将返回0,0不是一个有效的错误号。
6个获取error信息的API(实质上都是对 get_error_values的包装调用):
// 1. 获取Error code并将其移除队列:
unsigned long ERR_get_error(void)
{ return(get_error_values(1,0,NULL,NULL,NULL,NULL)); }
// 2. 获取Error code但并不将其移除队列:
unsigned long ERR_peek_error(void)
{ return(get_error_values(0,0,NULL,NULL,NULL,NULL)); }
// 3. 获取Error code并将其移除队列,并反回错误产生的源文件(file)及行号(line):
unsigned long ERR_get_error_line(const char **file, int *line)
{ return(get_error_values(1,0,file,line,NULL,NULL)); }
// 4. 获取Error code但不将其移除队列,并反回错误产生的源文件(file)及行号(line):
unsigned long ERR_peek_error_line(const char **file, int *line)
{ return(get_error_values(0,0,file,line,NULL,NULL)); }
// 5. 获取Error code并将其移除队列,并反回错误产生的源文件(file)及行号(line),另提供额外的数据及标识如何处理这些数据的flag:
unsigned long ERR_get_error_line_data(const char **file, int *line, const char **data, int *flags)
{ return(get_error_values(1,0,file,line,data,flags)); }
// 6. 获取Error code但不将其移除队列,并反回错误产生的源文件(file)及行号(line),另提供额外的数据及标识如何处理这些数据的flag:
unsigned long ERR_peek_last_error_line_data(const char **file, int *line, const char **data, int *flags)
{ return(get_error_values(0,1,file,line,data,flags)); }
清空error队列的api:
void ERR_clear_error(void);
5,6所获得的数据可能是任意的,但大多数情况下会是一个字符串。
如flag的ERR_TXT_MALLOCED被置1,则data所使用的内存可以使用OPENSSL_free函数释放。
如flag的ERR_TXT_STRING被置1,则相应的data可以按C-style字串使用。
例:打印error队列
void print_errors(void)
{
int flags, line;
char *data, *file;
unsigned long code;
code = ERR_get_error_line_data(&file, &line, &data, &flags);
while(code)
{
printf("error code: %lu in %s line %d.\n", code, file, line);
if(data && (flags & ERR_TXT_STRING))
printf("error data: %s\n", data);
code = ERR_get_error_line_data(&file, &line, &data, &flags);
}
}
2. 人类可读的错误消息
error handling package为其定义的error code提供标准的错误消息,但是在使用前需被载入。
libcrypto和libssl的错误消息全部载入:
void SSL_load_error_strings(void)
{
#ifndef OPENSSL_NO_ERR
ERR_load_crypto_strings();
ERR_load_SSL_strings();
#endif
}
libcrypto的错误消息的载入:
void ERR_load_crypto_strings(void)
{
#ifndef OPENSSL_NO_ERR
ERR_load_ERR_strings(); /* include error strings for SYSerr */
ERR_load_BN_strings();
#ifndef OPENSSL_NO_RSA
ERR_load_RSA_strings();
#endif
#ifndef OPENSSL_NO_DH
ERR_load_DH_strings();
#endif
ERR_load_EVP_strings();
ERR_load_BUF_strings();
ERR_load_OBJ_strings();
ERR_load_PEM_strings();
#ifndef OPENSSL_NO_DSA
ERR_load_DSA_strings();
#endif
ERR_load_X509_strings();
ERR_load_ASN1_strings();
ERR_load_CONF_strings();
ERR_load_CRYPTO_strings();
ERR_load_COMP_strings();
#ifndef OPENSSL_NO_EC
ERR_load_EC_strings();
#endif
#ifndef OPENSSL_NO_ECDSA
ERR_load_ECDSA_strings();
#endif
#ifndef OPENSSL_NO_ECDH
ERR_load_ECDH_strings();
#endif
/* skip ERR_load_SSL_strings() because it is not in this library */
ERR_load_BIO_strings();
ERR_load_PKCS7_strings();
ERR_load_X509V3_strings();
ERR_load_PKCS12_strings();
ERR_load_RAND_strings();
ERR_load_DSO_strings();
ERR_load_TS_strings();
#ifndef OPENSSL_NO_ENGINE
ERR_load_ENGINE_strings();
#endif
ERR_load_OCSP_strings();
ERR_load_UI_strings();
#ifndef OPENSSL_NO_CMS
ERR_load_CMS_strings();
#endif
#ifndef OPENSSL_NO_JPAKE
ERR_load_JPAKE_strings();
#endif
ERR_load_COMP_strings();
#endif
#ifdef OPENSSL_FIPS
ERR_load_FIPS_strings();
#endif
}
libssl的错误消息的载入:
void ERR_load_SSL_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(SSL_str_functs[0].error) == NULL)
{
ERR_load_strings(0,SSL_str_functs);
ERR_load_strings(0,SSL_str_reasons);
}
#endif
}
一旦error字串被载入就可以使用下面两个API将error code译成相应的error message
char *ERR_error_string(unsigned long e, char *ret)
e - error code
ret - error message(最少256Byte)
void ERR_error_string_n(unsigned long e, char *buf, size_t len)
error message的格式:
error:error code(hex):error name:产生error的函数名:产生error的原因
为了获取error信息,必需使用ERR_get_error_line_data和ERR_error_string,OpenSSL提供了下列API来简化这个过程:
//生成一个error list并将其写入BIO
void ERR_print_errors(BIO *bp)
{
ERR_print_errors_cb(print_bio, bp);
}
//生成一个error list并将其写入一个标准的C FILE对象
void ERR_print_errors_fp(FILE *fp)
{
ERR_print_errors_cb(print_fp, fp);
}
线程级实际应用:
每当有ERROR产生,一些重要的信息会被记录下来。一些信息可用于尝试自动恢复错误,但是其中的大多数都是用于调试和向用户报告错误。
有6个API用于从Error队列中获取信息。ERROR是依产生的顺序记录在队列中的,这些函数都能获取到当前队列中最早的信息。
最基本的消息是一个32-bit integer型的Error code。如果Error队列中无任何消息,error处理函数将返回0,0不是一个有效的错误号。
6个获取error信息的API(实质上都是对 get_error_values的包装调用):
// 1. 获取Error code并将其移除队列:
unsigned long ERR_get_error(void)
{ return(get_error_values(1,0,NULL,NULL,NULL,NULL)); }
// 2. 获取Error code但并不将其移除队列:
unsigned long ERR_peek_error(void)
{ return(get_error_values(0,0,NULL,NULL,NULL,NULL)); }
// 3. 获取Error code并将其移除队列,并反回错误产生的源文件(file)及行号(line):
unsigned long ERR_get_error_line(const char **file, int *line)
{ return(get_error_values(1,0,file,line,NULL,NULL)); }
// 4. 获取Error code但不将其移除队列,并反回错误产生的源文件(file)及行号(line):
unsigned long ERR_peek_error_line(const char **file, int *line)
{ return(get_error_values(0,0,file,line,NULL,NULL)); }
// 5. 获取Error code并将其移除队列,并反回错误产生的源文件(file)及行号(line),另提供额外的数据及标识如何处理这些数据的flag:
unsigned long ERR_get_error_line_data(const char **file, int *line, const char **data, int *flags)
{ return(get_error_values(1,0,file,line,data,flags)); }
// 6. 获取Error code但不将其移除队列,并反回错误产生的源文件(file)及行号(line),另提供额外的数据及标识如何处理这些数据的flag:
unsigned long ERR_peek_last_error_line_data(const char **file, int *line, const char **data, int *flags)
{ return(get_error_values(0,1,file,line,data,flags)); }
清空error队列的api:
void ERR_clear_error(void);
5,6所获得的数据可能是任意的,但大多数情况下会是一个字符串。
如flag的ERR_TXT_MALLOCED被置1,则data所使用的内存可以使用OPENSSL_free函数释放。
如flag的ERR_TXT_STRING被置1,则相应的data可以按C-style字串使用。
例:打印error队列
void print_errors(void)
{
int flags, line;
char *data, *file;
unsigned long code;
code = ERR_get_error_line_data(&file, &line, &data, &flags);
while(code)
{
printf("error code: %lu in %s line %d.\n", code, file, line);
if(data && (flags & ERR_TXT_STRING))
printf("error data: %s\n", data);
code = ERR_get_error_line_data(&file, &line, &data, &flags);
}
}
2. 人类可读的错误消息
error handling package为其定义的error code提供标准的错误消息,但是在使用前需被载入。
libcrypto和libssl的错误消息全部载入:
void SSL_load_error_strings(void)
{
#ifndef OPENSSL_NO_ERR
ERR_load_crypto_strings();
ERR_load_SSL_strings();
#endif
}
libcrypto的错误消息的载入:
void ERR_load_crypto_strings(void)
{
#ifndef OPENSSL_NO_ERR
ERR_load_ERR_strings(); /* include error strings for SYSerr */
ERR_load_BN_strings();
#ifndef OPENSSL_NO_RSA
ERR_load_RSA_strings();
#endif
#ifndef OPENSSL_NO_DH
ERR_load_DH_strings();
#endif
ERR_load_EVP_strings();
ERR_load_BUF_strings();
ERR_load_OBJ_strings();
ERR_load_PEM_strings();
#ifndef OPENSSL_NO_DSA
ERR_load_DSA_strings();
#endif
ERR_load_X509_strings();
ERR_load_ASN1_strings();
ERR_load_CONF_strings();
ERR_load_CRYPTO_strings();
ERR_load_COMP_strings();
#ifndef OPENSSL_NO_EC
ERR_load_EC_strings();
#endif
#ifndef OPENSSL_NO_ECDSA
ERR_load_ECDSA_strings();
#endif
#ifndef OPENSSL_NO_ECDH
ERR_load_ECDH_strings();
#endif
/* skip ERR_load_SSL_strings() because it is not in this library */
ERR_load_BIO_strings();
ERR_load_PKCS7_strings();
ERR_load_X509V3_strings();
ERR_load_PKCS12_strings();
ERR_load_RAND_strings();
ERR_load_DSO_strings();
ERR_load_TS_strings();
#ifndef OPENSSL_NO_ENGINE
ERR_load_ENGINE_strings();
#endif
ERR_load_OCSP_strings();
ERR_load_UI_strings();
#ifndef OPENSSL_NO_CMS
ERR_load_CMS_strings();
#endif
#ifndef OPENSSL_NO_JPAKE
ERR_load_JPAKE_strings();
#endif
ERR_load_COMP_strings();
#endif
#ifdef OPENSSL_FIPS
ERR_load_FIPS_strings();
#endif
}
libssl的错误消息的载入:
void ERR_load_SSL_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(SSL_str_functs[0].error) == NULL)
{
ERR_load_strings(0,SSL_str_functs);
ERR_load_strings(0,SSL_str_reasons);
}
#endif
}
一旦error字串被载入就可以使用下面两个API将error code译成相应的error message
char *ERR_error_string(unsigned long e, char *ret)
e - error code
ret - error message(最少256Byte)
void ERR_error_string_n(unsigned long e, char *buf, size_t len)
error message的格式:
error:error code(hex):error name:产生error的函数名:产生error的原因
为了获取error信息,必需使用ERR_get_error_line_data和ERR_error_string,OpenSSL提供了下列API来简化这个过程:
//生成一个error list并将其写入BIO
void ERR_print_errors(BIO *bp)
{
ERR_print_errors_cb(print_bio, bp);
}
//生成一个error list并将其写入一个标准的C FILE对象
void ERR_print_errors_fp(FILE *fp)
{
ERR_print_errors_cb(print_fp, fp);
}
线程级实际应用:
暂略
from: http://www.douban.com/note/206067603/