记BFCP解析库confiance-v7bfcp-only-05中踩过的坑
1. 记BFCP解析库confiance-v7bfcp-only-05中踩过的坑
在开发sip呼叫辅流的过程中使⽤了⼀个bfcp的解析库:
。
然⽽在使⽤过程中发现这个解析库的⼀些缺陷,列举如下:
1.1. SUPPORTED-PRIMITIVES 和 SUPPORTED-ATTRIBUTES 的字节长度问题
原始库中对这两个字段的处理都是采⽤的unsigned short int存储到⽹络交互字节中,
根据
和
的描述,这两个字段都是占⽤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 的字节长度及单位问题
根据 描述
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的pack
age时也要根据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 类型。整数提升保持值,包含符号:
更详细的信息可参考:
1.4. 修改清单
详情参考:
左侧⽂件: 原始⽂件右侧⽂件: 修改后
1.4.1. bfcp_messages.h
1.4.
2. bfcp_messages.c
111typedef struct bfcp_floor_id_list { /* FLOOR-ID list, to manage the multiple FLOOR-ID attributes */
=111typedef 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
116typedef struct bfcp_supported_list { /* list to manage all the supported attributes and primitives */
116typedef 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
121typedef struct bfcp_request_status {
121typedef 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)*/
244int bfcp_add_floor_id_list(bfcp_floor_id_list *list, unsigned short int fID, ...);
244int 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 */
246int bfcp_free_floor_id_list(bfcp_floor_id_list *list); 246int 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) */
249bfcp_supported_list *bfcp_new_supported_list(unsigned short int element, ...);
<>249bfcp_supported_list *bfcp_new_supported_list(unsigned char element, ...);
250/* Free a Supported (Primitives/Attributes) list */=250/* Free a Supported (Primitives/Attributes) list */251int bfcp_free_supported_list(bfcp_supported_list *list); 251int 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)*/
254bfcp_request_status *bfcp_new_request_status(unsigned short int rs, unsigned short int qp);
254bfcp_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) */
195
temp = next;
=
195
temp = next;
1.4.3. bfcp_messages_build.c
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) */
201bfcp_supported_list *bfcp_new_supported_list(unsigned short int element, ...)<>201bfcp_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 */
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, t to 001) */
48 ch32 = (((ch32 & !(0xE0000000)) | (1)) << 29) + /* First the Version (3bits, t to 001) */
49 (((ch32 & !(0x1F000000)) | (0)) << 24) + /*then the Rerved (5 bits, ignored) */
49 (((ch32 & !(0x1F000000)) | (0)) << 24) + /* then the Rerved (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 */
=497if(!attributes) /* The supported attributes list is empty, return with a failure */
498return -1;498return -1;
499
int attrlen = 2; /* The Lenght of the attribute
(starting from the TLV) */
499int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */
500int padding = 0; /* Number of bytes of padding */500int 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 */
503unsigned short int ch16; /* 16 bits */+-
504 bfcp_supported_list *temp = attributes;=503 bfcp_supported_list *temp = attributes;空对空导弹打一成语是什么
505while(temp) { /* Fill all supported attributes */504while(temp) { /* Fill all supported attributes */ 506ch16 = htons(temp->element);<>505unsigned char ch = temp->element;
507memcpy(buffer,&ch16,2);506buffer[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 }
512if((attrlen%4) != 0) { /* We need padding */511if((attrlen%4) != 0) { /* We need padding */ 513 padding = 4-(attrlen%4);512 padding = 4-(attrlen%4);
514 memt(buffer, 0, padding);513 memt(buffer, 0, padding);
515 }514 }
524
if(!primitives) /* The supported attributes list is
empty, return with a failure */
=523if(!primitives) /* The supported attributes list is empty, return with a failure */
525return -1;524return -1;
526
机械课程设计int attrlen = 2; /* The Lenght of the attribute
(starting from the TLV) */
525int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */
527int padding = 0; /* Number of bytes of padding */526int 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 */
530unsigned short int ch16; /* 16 bits */+-
531 bfcp_supported_list *temp = primitives;=529 bfcp_supported_list *temp = primitives;
532while(temp) { /* Fill all supported primitives */530while(temp) { /* Fill all supported primitives */ 533ch16 = htons(temp->element);<>531unsigned char ch = temp->element;
534memcpy(buffer, &ch16, 2);532memcpy(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 }
1.4.4. bfcp_messages_par.c
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 memt(buffer, 0, padding); 539 memt(buffer, 0, padding);542
}
540
}
190 if ((recvM->rerved) != 0) { /* Rerved bits are not 0, return with an error */
=190 if ((recvM->rerved) != 0) { /* Rerved 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 /* cau 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 */
=199 /* Either the length in the header is different from the length of */
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
}
621bfcp_supported_list
*bfcp_par_attribute_SUPPORTED_ATTRIBUTES(bfcp_message *message, bfcp_received_attribute *recvA)=622bfcp_supported_list
*bfcp_par_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 par each other supported attribute we find */
637 if (number>1) { /* Let's par each other supported attribute we find */
639
巅峰官路
for (i = 1;i<number;i++) {
638
for (i = 1;i<number;i++) {