记BFCP解析库confiance-v7bfcp-only-05中踩过的坑
1. 记BFCP解析库confiance-v7bfcp-only-05中踩过的坑
在开发sip呼叫辅流的过程中使用了一个bfcp的解析库:
confiance-v7bfcp-only-05。
然而在使用过程中发现这个解析库的一些缺陷,列举如下:
1.1. SUPPORTED-PRIMITIVES
和 SUPPORTED-ATTRIBUTES
的字节长度问题
原始库中对这两个字段的处理都是采用的unsigned short int
存储到网络交互字节中,
根据
RFC4582 5.2.10. SUPPORTED-ATTRIBUTES 和
RFC4582 5.2.11. SUPPORTED-PRIMITIVES 的描述,这两个字段都是占用1个字节的。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 1 0 1 0|M| Length | Supp. Attr. |R| Supp. Attr. |R|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Supp. Attr. |R| Supp. Attr. |R| Supp. Attr. |R| Supp. Attr. |R|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ /
/ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 17: SUPPORTED-ATTRIBUTES format
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 1 0 1 1|M| Length | Primitive | Primitive |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Primitive | Primitive | Primitive | Primitive |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ /
/ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 18: SUPPORTED-PRIMITIVES format
1.2. Payload Length 的字节长度及单位问题
根据 RFC4582 5.1. COMMON-HEADER Format 描述
Payload Length: This 16-bit field contains the length of the message in 4-octet units, excluding the common header
由于bfcp要求网络交互字节块必须要以4字节对齐,凡是不足4字节的都需要填充。因此称为in 4-octet units
,
octet
是指八个比特(bit)为一组的单位,通常是指一个字节(byte)的意思。
也就是说使用抓包工具查看bfcp的package时,Payload Length字段显示的值应该为整个BFCP包的长度减去BFCP通用头长度再除以4(即 (BFCPPackageLength - 12) / 4
);相反的,在解析bfcp的package时也要根据Payload Length字段的值乘以4再加上通用头长度即为整个包的长度(即 PayloadLength * 4 + 12
) ,且应该对负载长度以4求余来校验字节块是否满足这一条件。
但原始库中对于这块的处理是有问题的,包括判断逻辑也有问题。
1.3. 关于va_arg的错误使用
在修改中引入了的这个问题,linux上使用解析库时引发异常
在使用 va_arg
时传入的可变参数会经历 默认参数提升
的隐式转换过程,因此在使用过程中ap的下一个参数类型不应该指定为以下类型:
char
/ signed char
/ unsigned char
short
/ signed short
/ unsigned short
short int
/ signed short int
/ unsigned short int
有关c语言 默认参数提升 的规则描述如下:
默认参数提升
在函数调用表达式中,当调用下列函数时
1) 无原型函数
2) 变参数函数,其中参数表达式是匹配省略号参数的尾随参数之一
每个整数类型的参数都会经历整数提升(见后述),而每个float
类型参数都隐式转换为double
类型
整数提升
整数提升是任何等级小于或等于int
等级的整数类型,或是 _Bool 、 signed int 、 unsigned int 类型的位域类型的值到int
或unsigned int
类型值的隐式转换。
若int
能表示原类型的整个值域(或原位域的值域),则值转换成int
类型。否则值转化成unsigned int
类型。
整数提升保持值,包含符号:
更详细的信息可参考:可变长参数列表误区与陷阱——va_arg不可接受的类型
1.4. 修改清单
详情参考:fix confiance-v7bfcp-only-05
左侧文件: 原始文件
右侧文件: 修改后
1.4.1. bfcp_messages.h
111 | typedef struct bfcp_floor_id_list { /* FLOOR-ID list, to manage the multiple FLOOR-ID attributes */ | = | 111 | typedef struct bfcp_floor_id_list { /* FLOOR-ID list, to manage the multiple FLOOR-ID attributes */ |
112 | unsigned short int ID; /* FLOOR-ID */ | 112 | unsigned short int ID; /* FLOOR-ID */ | |
113 | struct bfcp_floor_id_list *next; /* Pointer to next FLOOR-ID instance */ | 113 | struct bfcp_floor_id_list *next; /* Pointer to next FLOOR-ID instance */ | |
114 | } bfcp_floor_id_list; | 114 | } bfcp_floor_id_list; | |
115 | 115 | |||
116 | typedef struct bfcp_supported_list { /* list to manage all the supported attributes and primitives */ | 116 | typedef struct bfcp_supported_list { /* list to manage all the supported attributes and primitives */ | |
117 | unsigned short int element; /* Element (Attribute/Primitive) */ | <> | 117 | unsigned char element; /* Element (Attribute/Primitive) */ |
118 | struct bfcp_supported_list *next; /* Pointer to next supported element instance */ | = | 118 | struct bfcp_supported_list *next; /* Pointer to next supported element instance */ |
119 | } bfcp_supported_list; | 119 | } bfcp_supported_list; | |
120 | 120 | |||
121 | typedef struct bfcp_request_status { | 121 | typedef struct bfcp_request_status { | |
122 | unsigned short int rs; /* Request Status */ | 122 | unsigned short int rs; /* Request Status */ | |
123 | unsigned short int qp; /* Queue Position */ | 123 | unsigned short int qp; /* Queue Position */ | |
243 | /* Add IDs to an existing Floor ID list (last argument MUST be 0) */ | = | 243 | /* Add IDs to an existing Floor ID list (last argument MUST be 0) */ |
244 | int bfcp_add_floor_id_list(bfcp_floor_id_list *list, unsigned short int fID, ...); | 244 | int bfcp_add_floor_id_list(bfcp_floor_id_list *list, unsigned short int fID, ...); | |
245 | /* Free a Floor ID list */ | 245 | /* Free a Floor ID list */ | |
246 | int bfcp_free_floor_id_list(bfcp_floor_id_list *list); | 246 | int bfcp_free_floor_id_list(bfcp_floor_id_list *list); | |
247 | 247 | |||
248 | /* Create a new Supported (Primitives/Attributes) list (last argument MUST be 0) */ | 248 | /* Create a new Supported (Primitives/Attributes) list (last argument MUST be 0) */ | |
249 | bfcp_supported_list *bfcp_new_supported_list(unsigned short int element, ...); | <> | 249 | bfcp_supported_list *bfcp_new_supported_list(unsigned char element, ...); |
250 | /* Free a Supported (Primitives/Attributes) list */ | = | 250 | /* Free a Supported (Primitives/Attributes) list */ |
251 | int bfcp_free_supported_list(bfcp_supported_list *list); | 251 | int bfcp_free_supported_list(bfcp_supported_list *list); | |
252 | 252 | |||
253 | /* Create a New Request Status (RequestStatus/QueuePosition) */ | 253 | /* Create a New Request Status (RequestStatus/QueuePosition) */ | |
254 | bfcp_request_status *bfcp_new_request_status(unsigned short int rs, unsigned short int qp); | 254 | bfcp_request_status *bfcp_new_request_status(unsigned short int rs, unsigned short int qp); | |
255 | /* Free a Request Status (RequestStatus/QueuePosition) */ | 255 | /* Free a Request Status (RequestStatus/QueuePosition) */ |
1.4.2. bfcp_messages.c
195 | temp = next; | = | 195 | temp = next; |
196 | } | 196 | } | |
197 | return 0; | 197 | return 0; | |
198 | } | 198 | } | |
199 | 199 | |||
200 | /* Create a new Supported (Primitives/Attributes) list (last argument MUST be 0) */ | 200 | /* Create a new Supported (Primitives/Attributes) list (last argument MUST be 0) */ | |
201 | bfcp_supported_list *bfcp_new_supported_list(unsigned short int element, ...) | <> | 201 | bfcp_supported_list *bfcp_new_supported_list(unsigned char element, ...) |
202 | { | = | 202 | { |
203 | bfcp_supported_list *first, *previous, *next; | 203 | bfcp_supported_list *first, *previous, *next; | |
204 | va_list ap; | 204 | va_list ap; | |
205 | va_start(ap, element); | 205 | va_start(ap, element); | |
206 | first = calloc(1, sizeof(bfcp_supported_list)); | 206 | first = calloc(1, sizeof(bfcp_supported_list)); | |
207 | if(!first) /* We could not allocate the memory, return a with failure */ | 207 | if(!first) /* We could not allocate the memory, return a with failure */ | |
208 | return NULL; | 208 | return NULL; | |
209 | first->element = element; | 209 | first->element = element; | |
210 | previous = first; | 210 | previous = first; | |
211 | element = va_arg(ap, int); | <> | 211 | element = (unsigned char)va_arg(ap, int); |
212 | while(element) { | = | 212 | while(element) { |
213 | next = calloc(1, sizeof(bfcp_supported_list)); | 213 | next = calloc(1, sizeof(bfcp_supported_list)); | |
214 | if(!next) /* We could not allocate the memory, return a with failure */ | 214 | if(!next) /* We could not allocate the memory, return a with failure */ | |
215 | return NULL; | 215 | return NULL; | |
216 | next->element = element; | 216 | next->element = element; | |
217 | previous->next = next; | 217 | previous->next = next; | |
218 | previous = next; | 218 | previous = next; | |
219 | element = va_arg(ap, int); | <> | 219 | element = (unsigned char)va_arg(ap, int); |
220 | } | = | 220 | } |
221 | va_end(ap); | 221 | va_end(ap); | |
222 | return first; | 222 | return first; | |
223 | } | 223 | } | |
224 | 224 | |||
225 | /* Free a Supported (Primitives/Attributes) list */ | 225 | /* Free a Supported (Primitives/Attributes) list */ |
1.4.3. bfcp_messages_build.c
45 | unsigned int ch32; /* 32 bits */ | = | 45 | unsigned int ch32; /* 32 bits */ |
46 | unsigned short int ch16; /* 16 bits */ | 46 | unsigned short int ch16; /* 16 bits */ | |
47 | unsigned char *buffer = message->buffer; | 47 | unsigned char *buffer = message->buffer; | |
48 | ch32 = (((ch32 & !(0xE0000000)) | (1)) << 29) + /* First the Version (3 bits, set to 001) */ | 48 | ch32 = (((ch32 & !(0xE0000000)) | (1)) << 29) + /* First the Version (3 bits, set to 001) */ | |
49 | (((ch32 & !(0x1F000000)) | (0)) << 24) + /* then the Reserved (5 bits, ignored) */ | 49 | (((ch32 & !(0x1F000000)) | (0)) << 24) + /* then the Reserved (5 bits, ignored) */ | |
50 | (((ch32 & !(0x00FF0000)) | (primitive)) << 16) + /* the Primitive (8 bits) */ | 50 | (((ch32 & !(0x00FF0000)) | (primitive)) << 16) + /* the Primitive (8 bits) */ | |
51 | ((ch32 & !(0x0000FFFF)) | (message->length - 12)); /* and the payload length (16 bits) */ | <> | 51 | ((ch32 & !(0x0000FFFF)) | ((message->length - 12) / 4)); /* and the payload length (16 bits), contains the length of the message in 4-octet units */ |
52 | ch32 = htonl(ch32); /* We want all protocol values in network-byte-order */ | = | 52 | ch32 = htonl(ch32); /* We want all protocol values in network-byte-order */ |
53 | memcpy(buffer, &ch32, 4); | 53 | memcpy(buffer, &ch32, 4); | |
54 | buffer = buffer+4; | 54 | buffer = buffer+4; | |
55 | ch32 = htonl(entity->conferenceID); | 55 | ch32 = htonl(entity->conferenceID); | |
56 | memcpy(buffer, &ch32, 4); | 56 | memcpy(buffer, &ch32, 4); | |
57 | buffer = buffer+4; | 57 | buffer = buffer+4; | |
497 | if(!attributes) /* The supported attributes list is empty, return with a failure */ | = | 497 | if(!attributes) /* The supported attributes list is empty, return with a failure */ |
498 | return -1; | 498 | return -1; | |
499 | int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */ | 499 | int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */ | |
500 | int padding = 0; /* Number of bytes of padding */ | 500 | int padding = 0; /* Number of bytes of padding */ | |
501 | int position = message->position; /* We keep track of where the TLV will have to be */ | 501 | int position = message->position; /* We keep track of where the TLV will have to be */ | |
502 | unsigned char *buffer = message->buffer+(message->position)+2; /* We skip the TLV bytes */ | 502 | unsigned char *buffer = message->buffer+(message->position)+2; /* We skip the TLV bytes */ | |
503 | unsigned short int ch16; /* 16 bits */ | +- | ||
504 | bfcp_supported_list *temp = attributes; | = | 503 | bfcp_supported_list *temp = attributes; |
505 | while(temp) { /* Fill all supported attributes */ | 504 | while(temp) { /* Fill all supported attributes */ | |
506 | ch16 = htons(temp->element); | <> | 505 | unsigned char ch = temp->element; |
507 | memcpy(buffer, &ch16, 2); | 506 | buffer[0] = ch << 1; | |
508 | buffer = buffer+2; | 507 | buffer = buffer+1; | |
509 | attrlen = attrlen+2; | 508 | attrlen = attrlen+1; | |
510 | temp = temp->next; | = | 509 | temp = temp->next; |
511 | } | 510 | } | |
512 | if((attrlen%4) != 0) { /* We need padding */ | 511 | if((attrlen%4) != 0) { /* We need padding */ | |
513 | padding = 4-(attrlen%4); | 512 | padding = 4-(attrlen%4); | |
514 | memset(buffer, 0, padding); | 513 | memset(buffer, 0, padding); | |
515 | } | 514 | } | |
524 | if(!primitives) /* The supported attributes list is empty, return with a failure */ | = | 523 | if(!primitives) /* The supported attributes list is empty, return with a failure */ |
525 | return -1; | 524 | return -1; | |
526 | int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */ | 525 | int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */ | |
527 | int padding = 0; /* Number of bytes of padding */ | 526 | int padding = 0; /* Number of bytes of padding */ | |
528 | int position = message->position; /* We keep track of where the TLV will have to be */ | 527 | int position = message->position; /* We keep track of where the TLV will have to be */ | |
529 | unsigned char *buffer = message->buffer+(message->position)+2; /* We skip the TLV bytes */ | 528 | unsigned char *buffer = message->buffer+(message->position)+2; /* We skip the TLV bytes */ | |
530 | unsigned short int ch16; /* 16 bits */ | +- | ||
531 | bfcp_supported_list *temp = primitives; | = | 529 | bfcp_supported_list *temp = primitives; |
532 | while(temp) { /* Fill all supported primitives */ | 530 | while(temp) { /* Fill all supported primitives */ | |
533 | ch16 = htons(temp->element); | <> | 531 | unsigned char ch = temp->element; |
534 | memcpy(buffer, &ch16, 2); | 532 | memcpy(buffer, &ch, 1); | |
535 | buffer = buffer+2; | 533 | buffer = buffer+1; | |
536 | attrlen = attrlen+2; | 534 | attrlen = attrlen+1; | |
537 | temp = temp->next; | = | 535 | temp = temp->next; |
538 | } | 536 | } | |
539 | if((attrlen%4) != 0) { /* We need padding */ | 537 | if((attrlen%4) != 0) { /* We need padding */ | |
540 | padding = 4-(attrlen%4); | 538 | padding = 4-(attrlen%4); | |
541 | memset(buffer, 0, padding); | 539 | memset(buffer, 0, padding); | |
542 | } | 540 | } |
1.4.4. bfcp_messages_parse.c
190 | if((recvM->reserved) != 0) { /* Reserved bits are not 0, return with an error */ | = | 190 | if((recvM->reserved) != 0) { /* Reserved bits are not 0, return with an error */ |
191 | recvM->errors = bfcp_received_message_add_error(recvM->errors, 0, BFCP_RESERVED_NOT_ZERO); | 191 | recvM->errors = bfcp_received_message_add_error(recvM->errors, 0, BFCP_RESERVED_NOT_ZERO); | |
192 | if(!(recvM->errors)) | 192 | if(!(recvM->errors)) | |
193 | return NULL; /* An error occurred while recording the error, return with failure */ | 193 | return NULL; /* An error occurred while recording the error, return with failure */ | |
194 | } | 194 | } | |
195 | recvM->primitive = ((ch32 & 0x00FF0000) >> 16); /* Primitive identifier */ | 195 | recvM->primitive = ((ch32 & 0x00FF0000) >> 16); /* Primitive identifier */ | |
<> | 196 | /* cause the Payload Lenght contains the length of the message in 4-octet units, here we need to multiple with 4 */ | ||
196 | recvM->length = (ch32 & 0x0000FFFF) + 12; /* Payload Lenght of the message + 12 (Common Header) */ | 197 | recvM->length = (ch32 & 0x0000FFFF) * 4 + 12; /* Payload Lenght of the message + 12 (Common Header) */ | |
197 | if(((recvM->length) != message->length) || !(recvM->length)%4) { /* The message length is wrong */ | 198 | if((recvM->length != message->length) || (recvM->length % 4)) { /* The message length is wrong */ | |
198 | /* Either the length in the header is different from the length of the buffer... */ | = | 199 | /* Either the length in the header is different from the length of the buffer... */ |
199 | /* ...or the length is not a multiple of 4, meaning it's surely not aligned */ | 200 | /* ...or the length is not a multiple of 4, meaning it's surely not aligned */ | |
200 | recvM->errors = bfcp_received_message_add_error(recvM->errors, 0, BFCP_WRONG_LENGTH); | 201 | recvM->errors = bfcp_received_message_add_error(recvM->errors, 0, BFCP_WRONG_LENGTH); | |
201 | if(!(recvM->errors)) | 202 | if(!(recvM->errors)) | |
202 | return NULL; /* An error occurred while recording the error, return with failure */ | 203 | return NULL; /* An error occurred while recording the error, return with failure */ | |
203 | } | 204 | } | |
621 | bfcp_supported_list *bfcp_parse_attribute_SUPPORTED_ATTRIBUTES(bfcp_message *message, bfcp_received_attribute *recvA) | = | 622 | bfcp_supported_list *bfcp_parse_attribute_SUPPORTED_ATTRIBUTES(bfcp_message *message, bfcp_received_attribute *recvA) |
622 | { | 623 | { | |
623 | if(recvA->length<3) /* The length of this attribute is wrong */ | 624 | if(recvA->length<3) /* The length of this attribute is wrong */ | |
624 | return NULL; | 625 | return NULL; | |
625 | int i; | 626 | int i; | |
626 | bfcp_supported_list *first, *previous, *next; | 627 | bfcp_supported_list *first, *previous, *next; | |
627 | unsigned short int ch16; /* 16 bits */ | +- | ||
628 | unsigned char *buffer = message->buffer+recvA->position+2; /* Skip the Header */ | = | 628 | unsigned char *buffer = message->buffer+recvA->position+2; /* Skip the Header */ |
629 | int number = (recvA->length-2)/2; /* Each supported attribute takes 2 bytes */ | <> | 629 | int number = (recvA->length-2); /* Each supported attribute takes 1 bytes */ |
630 | if(!number) | = | 630 | if(!number) |
631 | return NULL; /* No supported attributes? */ | 631 | return NULL; /* No supported attributes? */ | |
632 | first = calloc(1, sizeof(bfcp_supported_list)); | 632 | first = calloc(1, sizeof(bfcp_supported_list)); | |
633 | if(!first) /* An error occurred in creating a new Supported Attributes list */ | 633 | if(!first) /* An error occurred in creating a new Supported Attributes list */ | |
634 | return NULL; | 634 | return NULL; | |
635 | memcpy(&ch16, buffer, 2); | <> | ||
636 | first->element = ntohs(ch16); | 635 | first->element = buffer[0] & 0xFE; | |
637 | previous = first; | = | 636 | previous = first; |
638 | if(number>1) { /* Let's parse each other supported attribute we find */ | 637 | if(number>1) { /* Let's parse each other supported attribute we find */ | |
639 | for(i = 1;i<number;i++) { | 638 | for(i = 1;i<number;i++) { | |
640 | next = calloc(1, sizeof(bfcp_supported_list)); | 639 | next = calloc(1, sizeof(bfcp_supported_list)); | |
641 | if(!next) /* An error occurred in creating a new Supported Attributes list */ | 640 | if(!next) /* An error occurred in creating a new Supported Attributes list */ | |
642 | return NULL; | 641 | return NULL; | |
643 | buffer = buffer+2; /* Skip to the next supported attribute */ | <> | 642 | buffer = buffer + 1; /* Skip to the next supported attribute */ |
644 | memcpy(&ch16, buffer, 2); | 643 | next->element = buffer[0] & 0xFE; | |
645 | next->element = ntohs(ch16); | |||
646 | previous->next = next; | = | 644 | previous->next = next; |
647 | previous = next; | 645 | previous = next; | |
648 | } | 646 | } | |
649 | } | 647 | } | |
650 | return first; | 648 | return first; | |
651 | } | 649 | } | |
653 | bfcp_supported_list *bfcp_parse_attribute_SUPPORTED_PRIMITIVES(bfcp_message *message, bfcp_received_attribute *recvA) | = | 651 | bfcp_supported_list *bfcp_parse_attribute_SUPPORTED_PRIMITIVES(bfcp_message *message, bfcp_received_attribute *recvA) |
654 | { | 652 | { | |
655 | if(recvA->length<3) /* The length of this attribute is wrong */ | 653 | if(recvA->length<3) /* The length of this attribute is wrong */ | |
656 | return NULL; | 654 | return NULL; | |
657 | int i; | 655 | int i; | |
658 | bfcp_supported_list *first, *previous, *next; | 656 | bfcp_supported_list *first, *previous, *next; | |
659 | unsigned short int ch16; /* 16 bits */ | +- | ||
660 | unsigned char *buffer = message->buffer+recvA->position+2; /* Skip the Header */ | = | 657 | unsigned char *buffer = message->buffer+recvA->position+2; /* Skip the Header */ |
661 | int number = (recvA->length-2)/2; /* Each supported primitive takes 2 bytes */ | <> | 658 | int number = (recvA->length-2); /* Each supported primitive takes 1 bytes */ |
662 | if(!number) | = | 659 | if(!number) |
663 | return NULL; /* No supported primitives? */ | 660 | return NULL; /* No supported primitives? */ | |
664 | first = calloc(1, sizeof(bfcp_supported_list)); | 661 | first = calloc(1, sizeof(bfcp_supported_list)); | |
665 | if(!first) /* An error occurred in creating a new Supported Attributes list */ | 662 | if(!first) /* An error occurred in creating a new Supported Attributes list */ | |
666 | return NULL; | 663 | return NULL; | |
667 | memcpy(&ch16, buffer, 2); | <> | ||
668 | first->element = ntohs(ch16); | 664 | first->element = buffer[0]; | |
669 | previous = first; | = | 665 | previous = first; |
670 | if(number>1) { /* Let's parse each other supported primitive we find */ | 666 | if(number>1) { /* Let's parse each other supported primitive we find */ | |
671 | for(i = 1;i<number;i++) { | 667 | for(i = 1;i<number;i++) { | |
672 | next = calloc(1, sizeof(bfcp_supported_list)); | 668 | next = calloc(1, sizeof(bfcp_supported_list)); | |
673 | if(!next) /* An error occurred in creating a new Supported Attributes list */ | 669 | if(!next) /* An error occurred in creating a new Supported Attributes list */ | |
674 | return NULL; | 670 | return NULL; | |
675 | buffer = buffer+2; /* Skip to the next supported primitive */ | <> | 671 | buffer = buffer + 1; /* Skip to the next supported primitive */ |
676 | memcpy(&ch16, buffer, 2); | |||
677 | next->element = ntohs(ch16); | 672 | next->element = buffer[0]; | |
678 | previous->next = next; | = | 673 | previous->next = next; |
679 | previous = next; | 674 | previous = next; | |
680 | } | 675 | } | |
681 | } | 676 | } | |
682 | return first; | 677 | return first; | |
683 | } | 678 | } |
本文来自博客园,作者:never715,转载请注明原文链接:https://www.cnblogs.com/tangm421/p/14207735.html