ASN.1编码我用的asn1c库,在使用UPER编码的时候,返回值有个需要注意的地方
uper编码可以使用
asn_encode_to_buffer
uper_encode_to_buffer
uper编码源代码
asn_encode_to_buffer函数
函数定义如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
asn_enc_rval_t
asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,
enum asn_transfer_syntax syntax,
const asn_TYPE_descriptor_t *td, const void *sptr,
void *buffer, size_t buffer_size) {
struct overrun_encoder_key buf_key;
asn_enc_rval_t er;
if(buffer_size > 0 && !buffer) {
errno = EINVAL;
ASN__ENCODE_FAILED;
}
buf_key.buffer = buffer;
buf_key.buffer_size = buffer_size;
buf_key.computed_size = 0;
er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
overrun_encoder_cb, &buf_key);
if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) {
ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
" yet produced %" ASN_PRI_SIZE " bytes",
er.encoded, buf_key.computed_size);
assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);
}
return er;
}
|
uper_encode_to_buffer函数
函数定义如下
1
2
3
4
5
6
7
8
9
10
11
12
13
|
asn_enc_rval_t
uper_encode_to_buffer(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, void *buffer, size_t buffer_size) {
enc_to_buf_arg key;
key.buffer = buffer;
key.left = buffer_size;
if(td) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
return uper_encode(td, constraints, sptr, encode_to_buffer_cb, &key);
}
|
两个函数的返回值类型
两个函数编码返回的都是asn_enc_rval_t
类型的结构体。
类型定义如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/*
* Type of the return value of the encoding functions (der_encode, xer_encode).
*/
typedef struct asn_enc_rval_s {
/*
* Number of bytes encoded.
* -1 indicates failure to encode the structure.
* In this case, the members below this one are meaningful.
*/
ssize_t encoded;
/*
* Members meaningful when (encoded == -1), for post mortem analysis.
*/
/* Type which cannot be encoded */
const struct asn_TYPE_descriptor_s *failed_type;
/* Pointer to the structure of that type */
const void *structure_ptr;
} asn_enc_rval_t;
|
该结构体包含3个成员【编码的字节数、无法编码的类型描述指针、指向该类型结构的指针】。
uper编码返回值问题
按理说选择了同样的编码方式,返回的编码字节数应该一致(即encoded
值相同),但我发现对于同一个测试消息帧
-
ec = asn_encode_to_buffer(0, ATS_UNALIGNED_CANONICAL_PER, &asn_DEF_MessageFrame, msgFrame, buf, sizeof(buf));
-
ec = uper_encode_to_buffer(&asn_DEF_MessageFrame, 0, msgFrame, buf, sizeof(buf));
第一个函数返回ec.encoded=37,第二个返回ec.encoded=296。
源代码分析
在uper_encode_to_buffer
中调用了函数uper_encode
,其中encoded
计算的是bits
(第6行)
1
2
3
4
5
6
|
size_t bits_to_flush;
bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
/* Set number of bits encoded to a firm value */
er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
|
在asn_encode_to_buffer
中调用了函数asn_encode_internal
,其中encoded
由bits
转换成了bytes
(第24行)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
case ATS_UNALIGNED_BASIC_PER:
/* CANONICAL-UPER is a superset of BASIC-UPER. */
/* Fall through. */
case ATS_UNALIGNED_CANONICAL_PER:
if(td->op->uper_encoder) {
er = uper_encode(td, 0, sptr, callback, callback_key);
if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->uper_encoder) {
errno = EBADF; /* Structure has incorrect form. */
} else {
errno = ENOENT; /* UPER is not defined for this type. */
}
} else {
ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
if(er.encoded == 0) {
/* Enforce "Complete Encoding" of X.691 #11.1 */
if(callback("\0", 1, callback_key) < 0) {
errno = EBADF;
ASN__ENCODE_FAILED;
}
er.encoded = 8; /* Exactly 8 zero bits is added. */
}
/* Convert bits into bytes */
er.encoded = (er.encoded + 7) >> 3;
}
|
分析源代码发现uper_encode_to_buffer
返回的其实是编码的比特数,而不是字节数。在asn_encode_to_buffer
中则进行了字节数转换。
也就是(296+7)»3=37