日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《openssl 编程》之错误处理

發(fā)布時間:2024/4/11 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《openssl 编程》之错误处理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

第十四章???錯誤處理

14.1??概述

?????? 程序設(shè)計時,一般通過函數(shù)的返回值來判斷是否調(diào)用成功。設(shè)計良好的函數(shù)以及好的錯誤處理能幫助調(diào)用者快速找到錯誤原因。錯誤處理應(yīng)該盡可能多的包含各種信息,包括:

????????? 錯誤碼;

????????? 出錯文件以及行號;

????????? 錯誤原因;

????????? 出錯函數(shù);

????????? 出錯庫;

????????? 出錯模塊與類別信息;

????????? 錯誤堆棧信息等。

并且,出錯信息最好能支持多種輸出??梢允禽敵鲈跇藴瘦敵錾?#xff0c;也可以是文件等形式。

14.2??數(shù)據(jù)結(jié)構(gòu)

openssl中,通過unsigned long類型來存放錯誤信息。它包含三部分內(nèi)容:庫代碼、函數(shù)代碼以及錯誤原因代碼。其中,庫代碼在crypto/err.h中定義,函數(shù)代碼以及錯誤原因代碼由各個功能模塊定義(同類代碼不能與其他的重復(fù),也不能超過一定的大小)。比如err.h中為BIO定義如下庫代碼:

/* library */

#define ERR_LIB_BIO????????? 32

?????? ?????? 而crypto/bio.h中定義了如下函數(shù)和錯誤原因代號:

????????????? /* Function codes. */

#define BIO_F_ACPT_STATE?????????????????????????? 100

/* Reason codes. */

#define BIO_R_ACCEPT_ERROR??????????????????????????? 100

錯誤信息通過上述三部分通過計算得到,并且根據(jù)此信息能提取各個代碼。計算函數(shù)在err.h中定義如下:

#define ERR_PACK(l,f,r)???????????? (((((unsigned long)l)&0xffL)*0x1000000)| \

??????????????????????????? ((((unsigned long)f)&0xfffL)*0x1000)| \

??????????????????????????? ((((unsigned long)r)&0xfffL)))

#define ERR_GET_LIB(l)???????????? (int)((((unsigned long)l)>>24L)&0xffL)

#define ERR_GET_FUNC(l)???????? (int)((((unsigned long)l)>>12L)&0xfffL)

#define ERR_GET_REASON(l)??? (int)((l)&0xfffL)

可以看出,庫的個數(shù)不能大于255(0xff),函數(shù)個數(shù)和錯誤原因不能大于4095(0xfff)。除非計算出來的值與已有的值沒有沖突。

主要數(shù)據(jù)結(jié)構(gòu)有兩個,定義在crypto/err/err.h中,如下:

1)ERR_STRING_DATA

typedef struct ERR_string_data_st

?????? ?????? {

?????? ?????? unsigned long error;

?????? ?????? const char *string;

?????? ?????? } ERR_STRING_DATA;

?????? 該數(shù)據(jù)結(jié)構(gòu)的內(nèi)容由各個功能模塊來設(shè)置。其中,error用來存放錯誤信息(由庫代碼、函數(shù)代碼以及錯誤原因代碼計算得來),string用來存放文本信息,可以是函數(shù)名也可以是錯誤原因。以crypto/bio_err.c為例,它定義了兩個全局表,分別用來存放函數(shù)信息和錯誤信息:

?????? ?????? #define ERR_FUNC(func) ERR_PACK(ERR_LIB_BIO,func,0)

#define ERR_REASON(reason) ERR_PACK(ERR_LIB_BIO,0,reason)

static ERR_STRING_DATA BIO_str_functs[]=

{

{ERR_FUNC(BIO_F_ACPT_STATE),? "ACPT_STATE"},

……

?????? ?????? }

static ERR_STRING_DATA BIO_str_reasons[]=

?????? ?????? {

{ERR_REASON(BIO_R_ACCEPT_ERROR)????????? ,"accept error"},

{ERR_REASON(BIO_R_BAD_FOPEN_MODE)??????? ,"bad fopen mode"},

……

}

這兩個表通過ERR_load_BIO_strings函數(shù)來添加到錯誤信息哈希表中去。為了便于查找,所有模塊的錯誤信息存放在一個全局哈希表中,在crypto/err.c中實現(xiàn)。

?????? 2)ERR_STATE

typedef struct err_state_st

?????? ?????? {

?????? ?????? unsigned long pid;

?????? ?????? int err_flags[ERR_NUM_ERRORS];

?????? ?????? unsigned long err_buffer[ERR_NUM_ERRORS];

?????? ?????? char *err_data[ERR_NUM_ERRORS];

?????? ?????? int err_data_flags[ERR_NUM_ERRORS];

?????? ?????? const char *err_file[ERR_NUM_ERRORS];

?????? ?????? int err_line[ERR_NUM_ERRORS];

?????? ?????? int top,bottom;

?????? ?????? } ERR_STATE;

該結(jié)構(gòu)用于存放和獲取錯誤信息。由于可能會有多層函數(shù)調(diào)用(錯誤堆棧),這些信息都是一個數(shù)組。每個數(shù)組代表了一層函數(shù)的錯誤信息。各項意義如下:

?????? ?????? pid:當前線程id。

?????? ?????? err_buffer[i]:第i層錯誤碼,包含庫、函數(shù)以及錯誤原因信息。

?????? ?????? err_data[i]:存放第i層操作信息。

err_data_flags[i]:存放err_data[i]相關(guān)的標記;比如為ERR_TXT_MALLOCED時,表名err_data[i]中的數(shù)據(jù)是動態(tài)分配內(nèi)存的,需要釋放;為ERR_TXT_STRING表名err_data[i]中的數(shù)據(jù)是一個字符串,可以用來打印。

?????? ?????? err_file[i]:第i層錯誤的文件名。

?????? ?????? err_line[i]:第i層錯誤的行號。

top和bottom:用于指明ERR_STATE的使用狀態(tài)。top對應(yīng)與最后一個錯誤(錯誤堆棧的最上層),bottom對應(yīng)第一個錯誤(錯誤堆棧的最底層)。

?????? ?????? 當用戶需要擴展openssl的模塊時,可以仿照其他已有模塊來實現(xiàn)自己的錯誤處理。

14.3??主要函數(shù)

1)??? ERR_add_error_data

在本層錯誤的err_data元素中添加說明信息。該函數(shù)一般由各個模塊調(diào)用,比如可以用它說明什么操作導(dǎo)致了錯誤。

2)? ERR_clear_error

清除所有的錯誤信息。如果不清楚所有錯誤信息,可能會有其他無關(guān)錯誤遺留在ERR_STATE表中。

3)? ERR_error_string/ ERR_error_string_n

根據(jù)錯誤碼獲取具體的錯誤信息,包括出錯的庫、出錯的函數(shù)以及錯誤原因。

4)?? ERR_free_strings

釋放錯誤信息哈希表;通常在最后調(diào)用。

5)?? ERR_func_error_string

根據(jù)錯誤號,獲取出錯的函數(shù)信息。

6) ERR_get_err_state_table

獲取存放錯誤的哈希表。

7) ERR_get_error

獲取第一個錯誤號。

8)??? ERR_get_error_line

根據(jù)錯誤號,獲取錯誤的行號。

9)??? ERR_get_error_line_data

根據(jù)錯誤號,獲取出錯信息。

10)? ERR_get_implementation

獲取錯誤處理函數(shù),與哈希表操作相關(guān)。

?????? 11)ERR_get_state

????????????? 獲取ERR_STATE表。

?????? 12)ERR_lib_error_string

????????????? 根據(jù)錯誤號,獲取是哪個庫出錯。

?????? 13)ERR_load_strings

????????????? 加載錯誤信息,由各個模塊調(diào)用。

14)ERR_load_ASN1_strings

ERR_load_BIO_strings

ERR_load_BN_strings

ERR_load_BUF_strings

ERR_load_COMP_strings

ERR_load_CONF_strings

????????????? ERR_load_CRYPTO_strings

ERR_load_crypto_strings

ERR_load_DH_strings

ERR_load_DSA_strings

ERR_load_DSO_strings

ERR_load_EC_strings

ERR_load_ENGINE_strings

ERR_load_ERR_strings

ERR_load_EVP_strings

ERR_load_OBJ_strings

ERR_load_OCSP_strings

ERR_load_PEM_strings

ERR_load_PKCS12_strings

ERR_load_PKCS7_strings

ERR_load_RAND_strings

ERR_load_RSA_strings

ERR_load_UI_strings

ERR_load_X509_strings

ERR_load_X509V3_strings

各個模塊實現(xiàn)的,加載各自錯誤信息。

?????? 15)ERR_peek_error

????????????? 獲取第一個錯誤號。

?????? 16)ERR_peek_error_line

????????????? 獲取第一個錯誤的出錯行。

17)ERR_peek_error_line_data

?????? 獲取第一個錯誤的行數(shù)和錯誤信息。

18)ERR_peek_last_error

?????? 獲取最后一個錯誤號。

19)ERR_peek_last_error_line

?????? 獲取最后一個錯誤的行號。

20)ERR_peek_last_error_line_data

?????? 獲取最后一個錯誤的行號和錯誤信息。

21)ERR_print_errors

?????? 將錯誤信息輸出到bio中。

22)ERR_print_errors_cb

?????? 根據(jù)用戶設(shè)置的回調(diào)函數(shù)來打印錯誤信息。

23)ERR_print_errors_fp

?????? 將錯誤打印到FILE中。

24)? ERR_put_error

將錯誤信息存放到ERR_STATE 表中top指定的錯誤堆棧(最后的錯誤)。

25)? ERR_reason_error_string

根據(jù)錯誤號得到錯誤原因。

26)? ERR_remove_state

刪除線程相關(guān)的錯誤信息。

27)? ERR_set_error_data

將錯誤信息存放到ERR_STATE 表中top指定的錯誤堆棧(最后的錯誤)。

28)? ERR_unload_strings

從錯誤哈希表中刪除相關(guān)信息。

14.4??編程示例

?????? #include <openssl/err.h>

?????? #include <openssl/bn.h>

?????? int??? mycb(const char *a,size_t b,void *c)

?????? {

????????????? printf("my print : %s\n",a);

????????????? return 0;

?????? }

??????

?????? int??? main()

?????? {

????????????? BIO????????????????????? *berr;

????????????? unsigned long? err;

????????????? const????? char *file,*data,*efunc,*elib,*ereason,*p;

????????????? int???????????????????????? line,flags;

????????????? char?????????????? estring[500];

????????????? FILE???????????????????? *fp;

?????????????

????????????? /*

????????????? ERR_load_crypto_strings();

????????????? */

????????????? ERR_load_BIO_strings();

????????????? ERR_clear_error();

????????????? berr=BIO_new(BIO_s_file());

????????????? BIO_set_fp(berr,stdout,BIO_NOCLOSE);

????????????? BIO_new_file("no.exist","r");

????????????? err=ERR_peek_last_error();

????????????? err=ERR_peek_last_error_line(&file,&line);

????????????? printf("ERR_peek_last_error_line err : %ld,file : %s,line: %d\n",err,file,line);

????????????? err=ERR_peek_last_error_line_data(&file,&line,&data,&flags);

printf("ERR_peek_last_error_line_data err: %ld,file :%s,line :%d,data :%s\n",err,file,line,data);

????????????? err=ERR_peek_error();

????????????? printf("ERR_peek_error err: %ld\n",err);

????????????? err=ERR_peek_error_line(&file,&line);

????????????? printf("ERR_peek_error_line err : %ld,file : %s,line: %d\n",err,file,line);

????????????? err=ERR_peek_error_line_data(&file,&line,&data,&flags);

?????? printf("ERR_peek_error_line_data err : %ld,file :%s,line :%d,data :%s\n",err,file,line,data);

????????????? err = ERR_get_error_line_data(&file,&line,&data,&flags);

?????? printf("ERR_get_error_line_data err : %ld,file :%s,line :%d,data :%s\n",err,file,line,data);

?????? ?????? if(err!=0)

????????????? {

???????????????????? p=ERR_lib_error_string(err);

???????????????????? printf("ERR_lib_error_string : %s\n",p);

????????????? }

????????????? err=ERR_get_error();

????????????? if(err!=0)

????????????? {

???????????????????? printf("ERR_get_error err : %ld\n",err);

???????????????????? efunc=ERR_func_error_string(err);

???????????????????? printf("err func : %s\n",efunc);

???????????????????? elib=ERR_lib_error_string(err);

???????????????????? printf("err lib : %s\n",efunc);

???????????????????? ereason=ERR_reason_error_string(err);

???????????????????? printf("err reason : %s\n",efunc);

???????????????????? efunc=ERR_func_error_string(err);

???????????????????? printf("err func : %s\n",efunc);

???????????????????? elib=ERR_lib_error_string(err);

???????????????????? printf("err lib : %s\n",efunc);

???????????????????? ereason=ERR_reason_error_string(err);

???????????????????? printf("err reason : %s\n",efunc);

???????????????????? ERR_error_string(err,estring);

???????????????????? printf("ERR_error_string : %s\n",estring);

??????

???????????????????? ERR_error_string_n(err,estring,sizeof(estring));

???????????????????? printf("ERR_error_string_n : %s\n",estring);

????????????? }

????????????? err=ERR_get_error_line(&file,&line);

????????????? printf("err file :%s , err line : %d\n",file,line);

????????????? ERR_print_errors(berr);

????????????? BIO_new_file("no.exist2","r");

????????????? fp=fopen("err.log","w");

????????????? ERR_print_errors_fp(fp);

????????????? fclose(fp);

????????????? BIO_new_file("no.exist3","r");

????????????? ERR_print_errors_cb(mycb,NULL);

?????? ERR_put_error(ERR_LIB_BN,BN_F_BNRAND,BN_R_BIGNUM_TOO_LONG,__FILE__,line);

????????????? ERR_print_errors(berr);

????????????? ERR_load_BN_strings();

ERR_put_error(ERR_LIB_BN,BN_F_BNRAND,BN_R_BIGNUM_TOO_LONG,__FILE__,line);

????????????? ERR_print_errors(berr);

ERR_put_error(ERR_LIB_BN,BN_F_BNRAND,BN_R_BIGNUM_TOO_LONG,__FILE__,line);

?????? ?????? ERR_set_error_data("set date test!\n",ERR_TXT_STRING);

????????????? err=ERR_set_mark();

????????????? ERR_print_errors(berr);

????????????? ERR_free_strings();

????????????? BIO_free(berr);

????????????? return 0;

?????? }

總結(jié)

以上是生活随笔為你收集整理的《openssl 编程》之错误处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。