青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

無我

讓內心永遠燃燒著偉大的光明的精神之火!
靈活的思考,嚴謹的實現
豪邁的氣魄、頑強的意志和周全的思考

eSNACC對OCTET STRING 的編碼和解碼

本文剖析asn-octs.h/c,從源代碼來學習eSNACC對OCTET STRING的編碼和解碼。

eSNACC對字節串OCTET STRING的處理與上一篇描述的比特串的方法類似,而且字節串的處理更加簡單。所以在上一篇的基礎上,我們專門分析上一篇中對連接型串解碼時沒有展開講的函數,也作為上一篇的補充。上一篇可以參見eSNACC對BIT STRING的編碼和解碼

 

先看看eSNACC對字節串的表示方法:

typedef struct AsnOcts
{
  unsigned 
long octetLen;
  
char            *octs;
}
 AsnOcts;

可以看到與比特串很類似,唯一不同的是octetLen的類型,對字節串的是unsigned long;而比特串的是int。為什么要這樣設計呢?因為長度肯定不可能是負數,所以設計成unsigned的是我們認為合理的。而對比特串的想法,我不太清楚,這其實也可以說是對那個模塊的另一個設計問題。

octetLen代表該字節串的長度,但不包含串末尾的null字節。

octs是指向字節串的指針,分配的字節串長度為octetLen+1,在解碼時會主動給末尾設為null。千萬要注意:這個char*與比特串的char*有很大的不同:字節串的char*是一個字符指針,其指向的是一個由null終結的字符串。而比特串的就是一串比特位,最末尾也沒有null。

 

好了,看字節串的編碼和解碼,我們發現他的操作很簡單,只是一個內存拷貝的過程,編碼的時候也不需要專門來存len信息,也更不需要像比特串那樣做若干操作來處理字節填充、未使用位數計算等等。所以解碼的時候也不需要判斷這些。僅僅一個要記住的是:len是不包括字節串末尾的null字符的,只是在解碼時多分配了一個字節,主動使其為null結束。

 

上面這些都很簡單,我想本文就主要分析對連接型字節串的解碼過程。這是兩個靜態函數,不夠在分析這些代碼之前,我覺得應該下說明一下他的設計方法:

由于連接型串就是有多個字節串嵌套構造而成的。也就是

連接串 => 連接串 + 原生串

這樣的話,在解碼時,勢必產生很多夾雜其中的原生串碎片。如果讓用戶來管理這些碎片是很麻煩的事,我們更喜歡把一個連接串也存為一串整體的內存中,就如同操作一個原生串一樣。正是基于這個原因,eSNACC就為我們做好封裝,他自己判斷串類型,然后做不同的解碼,最后都是返回給用戶一塊連續的內存。

我們先看看用于管理串碎片的方案:結構體加宏

typedef struct StrStkElmt
{
    
char *str;
    unsigned 
long len;
}
 StrStkElmt;

typedef 
struct StrStk
{
    StrStkElmt 
*stk; /* ptr to array of SSElmts with 'size' elmts */
    unsigned 
long initialNumElmts;
    unsigned 
long numElmts;  /* total # of elements in str stk */
    unsigned 
long growElmts; /* # elmts to increase size by when nec */
    unsigned 
long nextFreeElmt; /* index of next free element */
    unsigned 
long totalByteLen; /* octet len of string stored in stk */
}
 StrStk;

extern StrStk strStkG;
/*
 * initializes stk (Allocates if nec.)
 * once stk is enlarged, it doesn't shrink
 
*/

#define RESET_STR_STK()\
{\
    strStkG.nextFreeElmt 
= 0;\
    strStkG.totalByteLen 
= 0;\
    
if (strStkG.stk == NULL){\
       strStkG.stk 
= (StrStkElmt*) malloc ((strStkG.initialNumElmts) *sizeof (StrStkElmt));\
       strStkG.numElmts 
= strStkG.initialNumElmts;}
\
}


/*
 * add a char*,len pair to top of stack.
 * grows stack if necessary using realloc (!)
 
*/

#define PUSH_STR(strPtr, strsLen, env)\
{\
    
if (strStkG.nextFreeElmt >= strStkG.numElmts)\
    
{\
       strStkG.stk 
= (StrStkElmt*) realloc (strStkG.stk, (strStkG.numElmts + strStkG.growElmts) *sizeof (StrStkElmt));\
       strStkG.numElmts 
+= strStkG.growElmts;\
    }
\
    strStkG.totalByteLen 
+= strsLen;\
    strStkG.stk[strStkG.nextFreeElmt].str 
= strPtr;\
    strStkG.stk[strStkG.nextFreeElmt].len 
= strsLen;\
    strStkG.nextFreeElmt
++;\
}

/*
 * Set up size values for the stack that is used for merging constructed
 * octet or bit string into single strings.
 * ****  Call this before decoding anything. *****
 * Note: you don't have to call this if the default values
 * for initialStkSizeG and stkGrowSizeG are acceptable
 
*/

#define SetupConsBitsOctsStringStk (initialNumberOfElmts, numberOfElmtsToGrowBy)\
{\
    strStkG.initialNumElmts 
= initialNumberOfElmts; \
    strStkG.growElmts 
= numberOfElmtsToGrowBy;\
}

可以看到用于管理每一塊比特串或字節串碎片的結構StrStkElmt與我們定義的AsnBits/AsnOcts非常類似:基本就是定義字段的順序不同。

而結構體StrStk就是用來管理若干碎片的,使得我們在解碼時不需要處理這些煩人的片段,他內部將這些都解碼好并且最后拷貝到一個整體的內存塊中返回,真是功德無限呀!我們就來認識一下這個活佛吧:

StrStkElmt *stk:指向碎片串的指針。

unsigned long initialNumElmts:首次分配StrStkElmt的數目。
unsigned long numElmts:stk中擁有的總的StrStkElmt數。
unsigned long growElmts:當首次分配的initialNumElmts不夠用,而需要再次分配時,默認的增長數。
unsigned long nextFreeElmt:stk中可用存放StrStkElmt的序號。
unsigned long totalByteLen:stk存放的串的總字節數。

然后聲明了一個變量strStkG,具體定義在實現文件中。后面就是定義了幾個宏來操作這個變量:

RESET_STR_STK:用于給stk分配內存,并且初始化numElmts值。

PUSH_STR:將char*,len對加到stk串中。如果空間不夠會自動增長。

SetupConsBitsOctsStringStk:如果你對他提供的initialNumElmts和growElmts不滿意,請在做任何解碼操作之前調用這個宏來定義自己的需求。

 

對于這種方案,有幾點說明是:

1、一旦stk擴容了,那么就無法縮水。

2、如果由于數量不夠而需要增長,這可能會導致內存的重分配和拷貝,一定程度影響性能。

在該模塊的實現文件中只有結構體變量strStkG的定義:

/* global for use by AsnBits and AsnOcts */
StrStk strStkG 
= { NULL, 12806400 };

也就是strStkG的初始值為:StrStkElmt指針為空,默認會分配的128個指針空間。因為當前還沒分配內存,所以總數為0.當不夠用時一次增長64個。然后后面兩個量都初始化為0.

 

好了,有了對這個輔助體的全面的認識,那么最上面的兩個解碼函數也就迎刃而解了。

先看解碼連續字節串的入口:

/*
 * Decodes a seq of universally tagged octets strings until either EOC is
 * encountered or the given len is decoded.  Merges them into a single
 * string. puts a NULL terminator on the string but does not include
 * this in the length.
 
*/

static void
BDecConsAsnOcts PARAMS ((b, len, result, bytesDecoded, env),
    GenBuf 
*b _AND_
    AsnLen len _AND_
    AsnOcts 
*result _AND_
    AsnLen 
*bytesDecoded _AND_
    jmp_buf env)
{
    
char *bufCurr;
    unsigned 
long curr;

    RESET_STR_STK();

    
/*
     * decode each piece of the octet string, puting
     * an entry in the octet string stack for each
     
*/

    FillOctetStringStk (b, len, bytesDecoded, env);

    result
->octetLen = strStkG.totalByteLen;

    
/* alloc str for all octs pieces with extra byte for null terminator */
    bufCurr 
= result->octs = Asn1Alloc (strStkG.totalByteLen +1);
    CheckAsn1Alloc (result
->octs, env);

    
/* copy octet str pieces into single blk */
    
for (curr = 0; curr < strStkG.nextFreeElmt; curr++)
    
{
        memcpy (bufCurr, strStkG.stk[curr].str, strStkG.stk[curr].len);
        bufCurr 
+= strStkG.stk[curr].len;
    }


    
/* add null terminator - this is not included in the str's len */
    
*bufCurr = '\0';

}
  /* BDecConsAsnOcts */

首先函數注釋說明了解碼一串連接字節串,直到指定長度或者遇到EOC。最后把這些分散的碎片整合到一個字符串中。與比特串不同的是,會在串最后添加null字符。

邏輯上,首先調用RESET_STR_STK()給完成strStkG的指針內存分配。然后調用FillOctetStringStk來完成真正的碎片解碼,該函數完成操作后,各個碎片都可以通過strStkG的成員變量來訪問了。正如我們看到的,他分配了一個strStkG.totalByteLen +1的空間,多1是為了存放null。然后遍歷每一個有效的指針,將值拷貝到分配這一整塊內存中。最后在末尾附上null。

FillOctetStringStk具體定義如下:

/*
 * Used for decoding constructed OCTET STRING values into
 * a contiguous local rep.
 * fills string stack with references to the pieces of a
 * construced octet string
 
*/

static void
FillOctetStringStk PARAMS ((b, elmtLen0, bytesDecoded, env),
    GenBuf 
*b _AND_
    AsnLen elmtLen0 _AND_
    AsnLen 
*bytesDecoded _AND_
    jmp_buf env)
{
    unsigned 
long refdLen;
    unsigned 
long totalRefdLen;
    
char *strPtr;
    unsigned 
long totalElmtsLen1 = 0;
    unsigned 
long tagId1;
    unsigned 
long elmtLen1;

    
for (; (totalElmtsLen1 < elmtLen0) || (elmtLen0 == INDEFINITE_LEN); )
    
{
        tagId1 
= BDecTag (b, &totalElmtsLen1, env);

        
if ((tagId1 == EOC_TAG_ID) && (elmtLen0 == INDEFINITE_LEN))
        
{
            BDEC_2ND_EOC_OCTET (b, 
&totalElmtsLen1, env);
            
break;
        }


        elmtLen1 
= BDecLen (b, &totalElmtsLen1, env);
        
if (tagId1 == MAKE_TAG_ID (UNIV, PRIM, OCTETSTRING_TAG_CODE))
        
{
            
/*
             * primitive part of string, put references to piece (s) in
             * str stack
             
*/

            totalRefdLen 
= 0;
            refdLen 
= elmtLen1;
            
while (1)
            
{
                strPtr 
= (char *)BufGetSeg (b, &refdLen);

                PUSH_STR (strPtr, refdLen, env);
                totalRefdLen 
+= refdLen;
                
if (totalRefdLen == elmtLen1)
                    
break/* exit this while loop */

                
if (refdLen == 0/* end of data */
                
{
                    Asn1Error (
"BDecConsOctetString: ERROR - attempt to decode past end of data\n");
                    longjmp (env, 
-18);
                }

                refdLen 
= elmtLen1 - totalRefdLen;
            }

            totalElmtsLen1 
+= elmtLen1;
        }



        
else if (tagId1 == MAKE_TAG_ID (UNIV, CONS, OCTETSTRING_TAG_CODE))
        
{
            
/*
             * constructed octets string embedding in this constructed
             * octet string. decode it.
             
*/

            FillOctetStringStk (b, elmtLen1, 
&totalElmtsLen1, env);
        }

        
else  /* wrong tag */
        
{
            Asn1Error (
"BDecConsOctetString: ERROR - decoded non-OCTET STRING tag inside a constructed OCTET STRING\n");
            longjmp (env, 
-19);
        }

    }
 /* end of for */

    (
*bytesDecoded) += totalElmtsLen1;

}
  /* FillOctetStringStk */

在FillOctetStringStk中,判斷當前串碎片是什么類型,如果是原生類型,就直接分配內存存放緩沖區的內容;如果還是連接類型,那就遞歸調用本函數,否則報錯。

 

好了,字節串編碼解碼的分析就到此了。

posted on 2012-04-23 16:22 Tim 閱讀(3282) 評論(0)  編輯 收藏 引用 所屬分類: eSNACC學習

<2012年5月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

導航

統計

公告

本博客原創文章,歡迎轉載和交流。不過請注明以下信息:
作者:TimWu
郵箱:timfly@yeah.net
來源:www.shnenglu.com/Tim
感謝您對我的支持!

留言簿(9)

隨筆分類(173)

IT

Life

搜索

積分與排名

最新隨筆

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美国产日韩一区二区在线观看| 国产一区二区毛片| 久久全国免费视频| 欧美激情视频一区二区三区不卡| 亚洲一区二区免费看| 亚洲欧美中日韩| 亚洲人成人一区二区三区| 亚洲永久免费av| 亚洲欧洲一区二区三区久久| 日韩写真在线| 一区二区在线观看av| 亚洲麻豆av| 亚洲国产精品va在线观看黑人| 亚洲视频成人| 亚洲精品久久久一区二区三区| 羞羞答答国产精品www一本| 99这里有精品| 老司机凹凸av亚洲导航| 欧美一区二区三区视频在线观看| 欧美大胆成人| 免费成人在线观看视频| 国产网站欧美日韩免费精品在线观看| 亚洲人成网在线播放| 一区久久精品| 欧美在线视频观看| 亚洲欧美日韩视频二区| 欧美日本亚洲| 亚洲二区视频| 1769国内精品视频在线播放| 亚洲免费影视第一页| 亚洲精品视频免费| 鲁大师成人一区二区三区| 久久综合久久综合这里只有精品| 国产精品乱码久久久久久| 亚洲精品中文字| 99国产精品视频免费观看| 美国三级日本三级久久99| 久久婷婷国产麻豆91天堂| 国产偷国产偷亚洲高清97cao| 一区二区三区精品视频| 亚洲一区二区精品在线| 欧美视频在线视频| 一区二区三区久久网| 亚洲视频在线观看免费| 久久资源av| 午夜在线观看免费一区| 国产女人水真多18毛片18精品视频| 中文精品视频一区二区在线观看| 亚洲在线中文字幕| 欧美午夜电影一区| 亚洲夜晚福利在线观看| 欧美一级精品大片| 国产美女精品一区二区三区 | 欧美色播在线播放| 99国产精品久久久久久久成人热| 亚洲先锋成人| 国产精一区二区三区| 午夜精品视频在线观看| 久热精品在线| 国产三区精品| 久久久久成人精品免费播放动漫| 久久在线91| 亚洲精品乱码久久久久久蜜桃91 | 国产精品一区视频| 日韩视频一区二区三区在线播放免费观看 | 午夜精品久久久久久久久久久久| 国产精品久久久久久久久免费樱桃 | 久久久久久久久久久久久女国产乱| 国产一区在线观看视频| 久久尤物视频| 亚洲精选在线观看| 久久精品成人| 91久久国产综合久久蜜月精品 | 久久久水蜜桃av免费网站| 亚洲第一天堂av| 欧美日韩18| 欧美亚洲一区二区三区| 亚洲国产精品女人久久久| 亚洲女性裸体视频| 激情另类综合| 欧美系列一区| 久久久久久一区二区| 亚洲精品影院在线观看| 性欧美办公室18xxxxhd| 亚洲国产精品va| 国产精品久久久久久久第一福利 | 亚洲精品你懂的| 久久成人免费| 99视频+国产日韩欧美| 国产日产精品一区二区三区四区的观看方式| 久久九九精品99国产精品| 亚洲区一区二| 久久婷婷蜜乳一本欲蜜臀| 一卡二卡3卡四卡高清精品视频| 国产欧美日韩另类一区| 欧美精品自拍偷拍动漫精品| 久久av在线| 亚洲视频狠狠| 亚洲区第一页| 欧美刺激性大交免费视频| 欧美亚洲三区| 制服丝袜亚洲播放| 亚洲国产精品第一区二区| 国产精品视频yy9099| 欧美老女人xx| 另类春色校园亚洲| 久久精品亚洲国产奇米99| 亚洲视频一区二区在线观看| 亚洲福利视频专区| 欧美a级片网站| 久久久久久久性| 欧美在线看片| 亚洲欧美春色| 一区二区高清视频在线观看| 黄网站免费久久| 国产偷国产偷精品高清尤物| 国产精品久久久久久户外露出| 欧美精品亚洲精品| 欧美岛国在线观看| 欧美不卡视频| 欧美电影免费观看高清| 牛牛国产精品| 免费观看成人网| 欧美刺激性大交免费视频| 老鸭窝91久久精品色噜噜导演| 欧美一区二视频在线免费观看| 亚洲砖区区免费| 亚洲一区一卡| 午夜精品久久久久久99热软件| 亚洲免费在线看| 性高湖久久久久久久久| 香港成人在线视频| 久久高清免费观看| 久久亚洲一区二区三区四区| 久久久亚洲国产美女国产盗摄| 久久久久久综合| 久久综合九色| 欧美激情自拍| 欧美午夜视频一区二区| 国产精品视频一区二区高潮| 国产精品一区二区三区久久| 国产亚洲欧美另类中文| 在线观看日产精品| 亚洲精品久久| 在线亚洲欧美专区二区| 亚洲欧美日韩国产成人精品影院| 欧美一级黄色网| 久久在线免费观看视频| 欧美激情在线狂野欧美精品| 日韩午夜黄色| 欧美一级午夜免费电影| 久久只精品国产| 欧美人体xx| 国产精品入口| 在线观看91精品国产入口| 亚洲乱码国产乱码精品精可以看 | 欧美大色视频| 亚洲一区二区网站| 欧美激情欧美狂野欧美精品| 国产在线精品自拍| 亚洲午夜视频| 亚洲第一黄网| 久久大逼视频| 欧美性色综合| 日韩午夜免费视频| 美国三级日本三级久久99| 亚洲一区精彩视频| 欧美金8天国| 在线观看日韩| 久久国产精品一区二区| 一区二区av在线| 欧美高清一区二区| 亚洲国产成人91精品| 久久精品国产亚洲一区二区三区| 99riav国产精品| 欧美电影免费观看高清完整版| 狠狠色狠狠色综合人人| 久久aⅴ国产紧身牛仔裤| 99精品欧美一区二区三区 | 欧美大片一区二区| 好看的亚洲午夜视频在线| 午夜精品成人在线视频| 9i看片成人免费高清| 欧美激情五月| 日韩视频二区| 亚洲黑丝一区二区| 牛牛精品成人免费视频| 亚洲国产精品成人精品| 老司机精品视频网站| 久久国产一区二区| 激情欧美国产欧美| 麻豆国产精品va在线观看不卡| 欧美在线www| 国语自产精品视频在线看| 久久久久久午夜| 久久免费的精品国产v∧| 亚洲成人直播| 亚洲大胆视频| 欧美另类69精品久久久久9999| 日韩写真视频在线观看|