doubango/tinyBFCP/src/tbfcp_pkt.c
c732d49e
 #if HAVE_CRT
 #define _CRTDBG_MAP_ALLOC 
 #include <stdlib.h> 
 #include <crtdbg.h>
 #endif //HAVE_CRT
 /*
 * Copyright (C) 2017, University of the Basque Country (UPV/EHU)
 * Contact for licensing options: <licensing-mcpttclient(at)mcopenplatform(dot)com>
 *
 * The original file was part of Open Source Doubango Framework
 * Copyright (C) 2010-2011 Mamadou Diop.
 * Copyright (C) 2012 Doubango Telecom <http://doubango.org>
 *
 * This file is part of Open Source Doubango Framework.
 *
 * DOUBANGO is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DOUBANGO is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DOUBANGO.
 *
 */
 
 #include "tinybfcp/tbfcp_pkt.h"
 
 #include "tnet_endianness.h"
 
 #include "tsk_debug.h"
 
 #define SWITCH_CASE_TAKE_ATTR(type, cat, field) \
 		case (type): \
 		if (!p_self->##field) { \
 			p_self->##field = (cat)*pp_attr, *pp_attr = tsk_null; \
             return 0; \
         } \
         break;
 
 static int _tbfcp_pkt_add_attr(tbfcp_pkt_t* p_self, tbfcp_attr_t** pp_attr)
 {
     if (!p_self || !pp_attr || !*pp_attr) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     tsk_list_push_back_data(p_self->p_list_attrs, (void**)pp_attr);
     return 0;
 }
 
 static int _tbfcp_pkt_deinit(tbfcp_pkt_t *p_self)
 {
     if (!p_self) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
 
     TSK_OBJECT_SAFE_FREE(p_self->p_list_attrs);
     return 0;
 }
 
 static int _tbfcp_pkt_init(tbfcp_pkt_t *p_self, tbfcp_primitive_t primitive, uint32_t conf_id, uint16_t transac_id, uint16_t user_id)
 {
     if (!p_self) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
 
     if (!p_self->p_list_attrs && !(p_self->p_list_attrs = tsk_list_create())) {
         TSK_DEBUG_ERROR("Failed to create list");
         return -2;
     }
     if (!p_self->f_add_attr) {
         p_self->f_add_attr = _tbfcp_pkt_add_attr;
     }
 
     p_self->hdr.ver = TBFCP_VERSION;
     p_self->hdr.reserved = 0;
     p_self->hdr.primitive = primitive;
     p_self->hdr.conf_id = conf_id;
     p_self->hdr.transac_id = transac_id;
     p_self->hdr.user_id = user_id;
 
     return 0;
 }
 #define _tbfcp_pkt_init_empty(p_self, primitive) _tbfcp_pkt_init((p_self), (primitive), 0, 0, 0)
 
 static int _tbfcp_pkt_init_2(tbfcp_pkt_t *p_self, tbfcp_primitive_t primitive)
 {
     if (!p_self) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
 
     if (!p_self->p_list_attrs && !(p_self->p_list_attrs = tsk_list_create())) {
         TSK_DEBUG_ERROR("Failed to create list");
         return -2;
     }
 
     p_self->hdr.ver = TBFCP_VERSION;
     p_self->hdr.reserved = 0;
     p_self->hdr.primitive = primitive;
 
     return 0;
 }
 
 int tbfcp_pkt_add_attr(tbfcp_pkt_t* p_self, tbfcp_attr_t** pp_attr)
 {
     if (!p_self || !pp_attr || !*pp_attr) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     if (p_self->f_add_attr) {
         return p_self->f_add_attr(p_self, pp_attr);
     }
     return _tbfcp_pkt_add_attr(p_self, pp_attr);
 }
 
 
 int tbfcp_pkt_create_empty(tbfcp_primitive_t primitive, tbfcp_pkt_t** pp_self)
 {
     extern const tsk_object_def_t *tbfcp_pkt_def_t;
     tbfcp_pkt_t* p_self;
     int ret;
 
     if (!pp_self) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     if (!(p_self = tsk_object_new(tbfcp_pkt_def_t))) {
         TSK_DEBUG_ERROR("Failed to create object 'tbfcp_pkt_def_t'");
         return -2;
     }
     if ((ret = _tbfcp_pkt_init_empty(p_self, primitive))) {
         TSK_OBJECT_SAFE_FREE(p_self);
         return ret;
     }
     *pp_self = p_self;
     return 0;
 }
 
 int tbfcp_pkt_create(tbfcp_primitive_t primitive, uint32_t conf_id, uint16_t transac_id, uint16_t user_id, tbfcp_pkt_t** pp_self)
 {
     int ret;
 
     if ((ret = tbfcp_pkt_create_empty(primitive, pp_self))) {
         return ret;
     }
     if ((ret = _tbfcp_pkt_init((*pp_self), primitive, conf_id, transac_id, user_id))) {
         TSK_OBJECT_SAFE_FREE((*pp_self));
         return ret;
     }
     return ret;
 }
 
 int tbfcp_pkt_get_size_in_octetunits_without_padding(const tbfcp_pkt_t* pc_self, tsk_size_t* p_size)
 {
     const tsk_list_item_t* pc_item;
     const tbfcp_attr_t* pc_attr;
     tsk_size_t n_size;
     int ret;
     if (!pc_self || !p_size) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     *p_size = TBFCP_PKT_HDR_SIZE_IN_OCTETS;
     tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
         if ((pc_attr = (const tbfcp_attr_t*)pc_item->data)) {
             if ((ret = tbfcp_attr_get_size_in_octetunits_without_padding(pc_attr, &n_size))) {
                 return ret;
             }
             *p_size += n_size;
         }
     }
     return 0;
 }
 
 int tbfcp_pkt_get_size_in_octetunits_with_padding(const tbfcp_pkt_t* pc_self, tsk_size_t* p_size)
 {
     const tsk_list_item_t* pc_item;
     const tbfcp_attr_t* pc_attr;
     tsk_size_t n_size;
     int ret;
     if (!pc_self || !p_size) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     *p_size = TBFCP_PKT_HDR_SIZE_IN_OCTETS;
     tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
         if ((pc_attr = (const tbfcp_attr_t*)pc_item->data)) {
             if ((ret = tbfcp_attr_get_size_in_octetunits_with_padding(pc_attr, &n_size))) {
                 return ret;
             }
             *p_size += n_size;
         }
     }
     return 0;
 }
 
 int tbfcp_pkt_write_with_padding(const tbfcp_pkt_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written)
 {
     const tsk_list_item_t* pc_item;
     const tbfcp_attr_t* pc_attr;
     tsk_size_t n_size;
     int ret;
     if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     if ((ret = tbfcp_pkt_get_size_in_octetunits_with_padding(pc_self, p_written))) {
         return ret;
     }
     if ((n_buff_size < *p_written)) {
         TSK_DEBUG_ERROR("Buffer too short: %u<%u", n_buff_size, *p_written);
         return -1;
     }
 
     p_buff_ptr[0] = (((uint8_t)pc_self->hdr.ver) << 5) | (pc_self->hdr.reserved & 0x7F);
     p_buff_ptr[1] = (uint8_t)pc_self->hdr.primitive;
 	*((uint32_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)((*p_written - TBFCP_PKT_HDR_SIZE_IN_OCTETS) >> 2));
     *((uint32_t*)&p_buff_ptr[4]) = (uint32_t)tnet_htonl(pc_self->hdr.conf_id);
     *((uint16_t*)&p_buff_ptr[8]) = tnet_htons(pc_self->hdr.transac_id);
     *((uint16_t*)&p_buff_ptr[10]) = tnet_htons(pc_self->hdr.user_id);
 
     p_buff_ptr += TBFCP_PKT_HDR_SIZE_IN_OCTETS;
     n_buff_size -= TBFCP_PKT_HDR_SIZE_IN_OCTETS;
 
     tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
         if ((pc_attr = (const tbfcp_attr_t*)pc_item->data)) {
             if ((ret = tbfcp_attr_write_with_padding(pc_attr, p_buff_ptr, n_buff_size, &n_size))) {
                 return ret;
             }
             p_buff_ptr += n_size;
             n_buff_size -= n_size;
         }
     }
     return 0;
 }
 
 // Useful to check TCP stream contains at least a complete BFCP packet
 int tbfcp_pkt_is_complete(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t *pb_is_complete)
 {
     if (!pb_is_complete) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     *pb_is_complete = tsk_false;
     if (pc_buff_ptr && n_buff_size >= TBFCP_PKT_HDR_SIZE_IN_OCTETS) {
         tsk_size_t n_paylen_in_octets = (tnet_ntohs_2(&pc_buff_ptr[2]) << 2);
         *pb_is_complete = ((n_buff_size - TBFCP_PKT_HDR_SIZE_IN_OCTETS) >= n_paylen_in_octets);
     }
     return 0;
 }
 
 int tbfcp_pkt_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tbfcp_pkt_t** pp_pkt)
 {
     tsk_bool_t b_is_complete;
     tsk_size_t PayloadLengthInOctets;
     tbfcp_primitive_t Primitive;
     uint32_t ConferenceID;
     uint16_t TransactionID, UserID;
     int ret, Ver;
     if (!pc_buff_ptr || !n_buff_size || !pp_pkt) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     if ((ret = tbfcp_pkt_is_complete(pc_buff_ptr, n_buff_size, &b_is_complete))) {
         return ret;
     }
     if (!b_is_complete) {
         TSK_DEBUG_ERROR("Buffer too short(%u)", n_buff_size);
         return -2;
     }
     Ver = (pc_buff_ptr[0] >> 5) & 0x07;
     if (Ver != TBFCP_VERSION) {
         TSK_DEBUG_ERROR("Version(%d)<>%d", Ver, TBFCP_VERSION);
         return -3;
     }
     Primitive = (tbfcp_primitive_t)pc_buff_ptr[1];
     PayloadLengthInOctets = (tnet_ntohs_2(&pc_buff_ptr[2]) << 2);
     ConferenceID = (uint32_t)tnet_ntohl_2(&pc_buff_ptr[4]);
     TransactionID = tnet_ntohs_2(&pc_buff_ptr[8]);
     UserID = tnet_ntohs_2(&pc_buff_ptr[10]);
 
     if((ret = tbfcp_pkt_create(Primitive, ConferenceID, TransactionID, UserID, pp_pkt))) {
         return ret;
     }
 
     if (PayloadLengthInOctets > 0) {
         tbfcp_attr_t* p_attr;
         tsk_size_t n_consumed_octets;
         pc_buff_ptr += TBFCP_PKT_HDR_SIZE_IN_OCTETS;
         do {
             if ((ret = tbfcp_attr_read(pc_buff_ptr, PayloadLengthInOctets, &n_consumed_octets, &p_attr))) {
                 return ret;
             }
             if ((ret = tbfcp_pkt_add_attr((*pp_pkt), &p_attr))) {
                 TSK_OBJECT_SAFE_FREE((*pp_pkt));
                 return ret;
             }
             PayloadLengthInOctets -= n_consumed_octets;
             pc_buff_ptr += n_consumed_octets;
         }
         while (PayloadLengthInOctets >= TBFCP_ATTR_HDR_SIZE_IN_OCTETS);
     }
 
     return 0;
 }
 
 int tbfcp_pkt_attr_find_at(const struct tbfcp_pkt_s* pc_self, enum tbfcp_attribute_format_e e_format, tsk_size_t u_index, const struct tbfcp_attr_s** ppc_attr)
 {
 	tsk_size_t _u_index = 0;
 	const tsk_list_item_t *pc_item;
 	const struct tbfcp_attr_s* pc_attr;
 	if (!pc_self || !ppc_attr) {
 		TSK_DEBUG_ERROR("Invalid parameter");
 		return -1;
 	}
 	*ppc_attr = tsk_null;
 	tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
 		pc_attr = (const struct tbfcp_attr_s*)pc_item->data;
 		if (!pc_attr || pc_attr->format != e_format) {
 			continue;
 		}
 		if (_u_index++ >= u_index) {
 			*ppc_attr = pc_attr;
 			break;
 		}
 	}
 	return 0;
 }
 
 
 static tsk_object_t* tbfcp_pkt_ctor(tsk_object_t * self, va_list * app)
 {
     tbfcp_pkt_t *p_pkt = (tbfcp_pkt_t *)self;
     if (p_pkt) {
         p_pkt->f_add_attr = _tbfcp_pkt_add_attr;
         if (!(p_pkt->p_list_attrs = tsk_list_create())) {
             TSK_DEBUG_ERROR("Failed to create list");
             return tsk_null;
         }
     }
     return self;
 }
 static tsk_object_t* tbfcp_pkt_dtor(tsk_object_t * self)
 {
     tbfcp_pkt_t *p_pkt = (tbfcp_pkt_t *)self;
     if (p_pkt) {
         TSK_DEBUG_INFO("*** BFCP Packet destroyed ***");
         TSK_OBJECT_SAFE_FREE(p_pkt->p_list_attrs);
     }
 
     return self;
 }
 static int tbfcp_pkt_cmp(const tsk_object_t *_pk1, const tsk_object_t *_pk2)
 {
     const tbfcp_pkt_t *pc_pk1 = (const tbfcp_pkt_t *)_pk1;
     const tbfcp_pkt_t *pc_pk2 = (const tbfcp_pkt_t *)_pk2;
 
     return (int)(pc_pk1-pc_pk2);
 }
 static const tsk_object_def_t tbfcp_pkt_def_s = {
     sizeof(tbfcp_pkt_t),
     tbfcp_pkt_ctor,
     tbfcp_pkt_dtor,
     tbfcp_pkt_cmp,
 };
 const tsk_object_def_t *tbfcp_pkt_def_t = &tbfcp_pkt_def_s;
 
 
 /***** rfc4582 - 5.3.1.  FloorRequest *****/
 int tbfcp_pkt_create_FloorRequest_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_id, tbfcp_pkt_t** pp_self)
 {
     int ret;
     tbfcp_attr_unsigned16_t* p_floor_id;
     if ((ret = tbfcp_pkt_create_FloorRequest(conf_id, transac_id, user_id, pp_self))) {
         return ret;
     }
     if ((ret = tbfcp_attr_unsigned16_create(tbfcp_attribute_type_FLOOR_ID, kBfcpFieldMYes, floor_id, &p_floor_id))) {
         return ret;
     }
     if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_floor_id))) {
         TSK_OBJECT_SAFE_FREE(p_floor_id);
         return ret;
     }
     return 0;
 }
 
 /***** rfc4582 - 5.3.2.  FloorRelease  *****/
 int tbfcp_pkt_create_FloorRelease_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_req_id, tbfcp_pkt_t** pp_self)
 {
     int ret;
     tbfcp_attr_unsigned16_t* p_floor_req_id;
     if ((ret = tbfcp_pkt_create_FloorRelease(conf_id, transac_id, user_id, pp_self))) {
         return ret;
     }
     if ((ret = tbfcp_attr_unsigned16_create(tbfcp_attribute_type_FLOOR_REQUEST_ID, kBfcpFieldMYes, floor_req_id, &p_floor_req_id))) {
         return ret;
     }
     if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_floor_req_id))) {
         TSK_OBJECT_SAFE_FREE(p_floor_req_id);
         return ret;
     }
     return 0;
 }
 
 /**** rfc4582 - 5.3.4.  FloorRequestStatus *****/
 int tbfcp_pkt_create_FloorRequestStatus_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_req_id, tbfcp_pkt_t** pp_self)
 {
     int ret;
     tbfcp_attr_grouped_t* p_floor_req_info;
     if ((ret = tbfcp_pkt_create_FloorRequestStatus(conf_id, transac_id, user_id, pp_self))) {
         return ret;
     }
     if ((ret = tbfcp_attr_grouped_create_u16(tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION, kBfcpFieldMNo, floor_req_id, &p_floor_req_info))) {
         return ret;
     }
     if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_floor_req_info))) {
         TSK_OBJECT_SAFE_FREE(p_floor_req_info);
         return ret;
     }
     return 0;
 }
 
 /**** 5.3.12.  HelloAck ***/
 int tbfcp_pkt_create_HelloAck_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, struct tbfcp_pkt_s** pp_self)
 {
     tsk_size_t u;
     int ret;
     tbfcp_attr_octetstring_t *p_supp_attr, *p_supp_prim;
     static const uint8_t* kNullOctetStringPtr = tsk_null;
     static const tbfcp_primitive_t __supp_prims[] = {
         tbfcp_primitive_FloorRequest,
         tbfcp_primitive_FloorRelease,
         tbfcp_primitive_FloorRequestQuery,
         tbfcp_primitive_FloorRequestStatus,
         tbfcp_primitive_UserQuery,
         tbfcp_primitive_UserStatus,
         tbfcp_primitive_FloorQuery,
         tbfcp_primitive_FloorStatus,
         tbfcp_primitive_ChairAction,
         tbfcp_primitive_ChairActionAck,
         tbfcp_primitive_Hello,
         tbfcp_primitive_HelloAck,
         tbfcp_primitive_Error,
     };
     static const tsk_size_t __supp_prims_count = sizeof(__supp_prims)/sizeof(__supp_prims[0]);
     static const tbfcp_attribute_type_t __supp_attrs[] = {
         tbfcp_attribute_type_BENEFICIARY_ID,
         tbfcp_attribute_type_FLOOR_ID,
         tbfcp_attribute_type_FLOOR_REQUEST_ID,
         tbfcp_attribute_type_PRIORITY,
         tbfcp_attribute_type_REQUEST_STATUS,
         tbfcp_attribute_type_ERROR_CODE,
         tbfcp_attribute_type_ERROR_INFO,
         tbfcp_attribute_type_PARTICIPANT_PROVIDED_INFO,
         tbfcp_attribute_type_STATUS_INFO,
         tbfcp_attribute_type_SUPPORTED_ATTRIBUTES,
         tbfcp_attribute_type_SUPPORTED_PRIMITIVES,
         tbfcp_attribute_type_USER_DISPLAY_NAME,
         tbfcp_attribute_type_USER_URI,
         tbfcp_attribute_type_BENEFICIARY_INFORMATION,
         tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION,
         tbfcp_attribute_type_REQUESTED_BY_INFORMATION,
         tbfcp_attribute_type_FLOOR_REQUEST_STATUS,
         tbfcp_attribute_type_OVERALL_REQUEST_STATUS,
     };
     static const tsk_size_t __supp_attrs_count = sizeof(__supp_attrs)/sizeof(__supp_attrs[0]);
 
     if ((ret = tbfcp_pkt_create_HelloAck(conf_id, transac_id, user_id, pp_self))) {
         return ret;
     }
     /* SUPPORTED-ATTRIBUTES */
     if ((ret = tbfcp_attr_octetstring_create(tbfcp_attribute_type_SUPPORTED_ATTRIBUTES, kBfcpFieldMNo, kNullOctetStringPtr, (uint8_t)__supp_attrs_count, &p_supp_attr))) {
         return ret;
     }
     for (u = 0; u < p_supp_attr->OctetStringLength; ++u) {
         p_supp_attr->OctetString[u] = (__supp_attrs[u] << 1/*R*/);
     }
     if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_supp_attr))) {
         TSK_OBJECT_SAFE_FREE(p_supp_attr);
         return ret;
     }
     /* SUPPORTED-PRIMITIVES */
     if ((ret = tbfcp_attr_octetstring_create(tbfcp_attribute_type_SUPPORTED_PRIMITIVES, kBfcpFieldMNo, kNullOctetStringPtr, (uint8_t)__supp_prims_count, &p_supp_prim))) {
         return ret;
     }
     for (u = 0; u < p_supp_prim->OctetStringLength; ++u) {
         p_supp_prim->OctetString[u] = __supp_prims[u];
     }
     if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_supp_prim))) {
         TSK_OBJECT_SAFE_FREE(p_supp_prim);
         return ret;
     }
     return 0;
 }
 
 #if 0
 /***** rfc4582 - 5.3.1.  FloorRequest *****/
 static int _tbfcp_pkt_FloorRequest_add_attr(tbfcp_pkt_t* _p_self, tbfcp_attr_t** pp_attr)
 {
     tbfcp_pkt_FloorRequest_t* p_self = (tbfcp_pkt_FloorRequest_t*)_p_self;
     if (!p_self || !pp_attr || !*pp_attr) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     switch ((*pp_attr)->hdr.type) {
         SWITCH_CASE_TAKE_ATTR(tbfcp_attribute_type_FLOOR_ID, struct tbfcp_attr_unsigned16_s*, p_floor_id);
         SWITCH_CASE_TAKE_ATTR(tbfcp_attribute_type_BENEFICIARY_ID, struct tbfcp_attr_unsigned16_s*, p_beneficiary_id);
         SWITCH_CASE_TAKE_ATTR(tbfcp_attribute_type_PARTICIPANT_PROVIDED_INFO, struct tbfcp_attr_octetstring_s*, p_participant_provided_info);
         SWITCH_CASE_TAKE_ATTR(tbfcp_attribute_type_PRIORITY, struct tbfcp_attr_octetstring16_s*, p_priority);
     }
     return _tbfcp_pkt_add_attr(_p_self, pp_attr);
 }
 
 int tbfcp_pkt_FloorRequest_create_empty(tbfcp_pkt_FloorRequest_t** pp_self)
 {
     extern const tsk_object_def_t *tbfcp_pkt_FloorRequest_def_t;
     tbfcp_pkt_FloorRequest_t* p_self;
     int ret;
 
     if (!pp_self) {
         TSK_DEBUG_ERROR("Invalid parameter");
         return -1;
     }
     if (!(p_self = tsk_object_new(tbfcp_pkt_FloorRequest_def_t))) {
         TSK_DEBUG_ERROR("Failed to create object 'tbfcp_pkt_FloorRequest_def_t'");
         return -2;
     }
     if ((ret = _tbfcp_pkt_init_empty_FloorRequest(p_self))) {
         TSK_OBJECT_SAFE_FREE(p_self);
         return ret;
     }
     *pp_self = p_self;
     return 0;
 }
 
 int tbfcp_pkt_FloorRequest_create(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_id, tbfcp_pkt_FloorRequest_t** pp_self)
 {
     int ret;
 
     if ((ret = tbfcp_pkt_FloorRequest_create_empty(pp_self))) {
         return ret;
     }
     if ((ret = _tbfcp_pkt_init_FloorRequest((*pp_self), conf_id, transac_id, user_id))) {
         TSK_OBJECT_SAFE_FREE((*pp_self));
         return ret;
     }
     if ((ret = tbfcp_attr_unsigned16_create(tbfcp_attribute_type_FLOOR_ID, kBfcpFieldMYes, floor_id, &(*pp_self)->p_floor_id))) {
         TSK_OBJECT_SAFE_FREE((*pp_self));
         return ret;
     }
     return ret;
 }
 
 static tsk_object_t* tbfcp_pkt_FloorRequest_ctor(tsk_object_t * self, va_list * app)
 {
     tbfcp_pkt_FloorRequest_t *p_pkt = (tbfcp_pkt_FloorRequest_t *)self;
     if (p_pkt) {
         TBFCP_PKT(p_pkt)->f_add_attr = _tbfcp_pkt_FloorRequest_add_attr;
     }
     return self;
 }
 static tsk_object_t* tbfcp_pkt_FloorRequest_dtor(tsk_object_t * self)
 {
     tbfcp_pkt_FloorRequest_t *p_pkt = (tbfcp_pkt_FloorRequest_t *)self;
     if (p_pkt) {
         TSK_DEBUG_INFO("*** BFCP Packet(FloorRequest) destroyed ***");
         _tbfcp_pkt_deinit(TBFCP_PKT(p_pkt)); // dtor(base)
         TSK_OBJECT_SAFE_FREE(p_pkt->p_floor_id);
         TSK_OBJECT_SAFE_FREE(p_pkt->p_beneficiary_id);
         TSK_OBJECT_SAFE_FREE(p_pkt->p_participant_provided_info);
         TSK_OBJECT_SAFE_FREE(p_pkt->p_priority);
     }
 
     return self;
 }
 static int tbfcp_pkt_FloorRequest_cmp(const tsk_object_t *_pk1, const tsk_object_t *_pk2)
 {
     const tbfcp_pkt_FloorRequest_t *pc_pk1 = (const tbfcp_pkt_FloorRequest_t *)_pk1;
     const tbfcp_pkt_FloorRequest_t *pc_pk2 = (const tbfcp_pkt_FloorRequest_t *)_pk2;
 
     return (int)(pc_pk1-pc_pk2);
 }
 static const tsk_object_def_t tbfcp_pkt_FloorRequest_def_s = {
     sizeof(tbfcp_pkt_FloorRequest_t),
     tbfcp_pkt_FloorRequest_ctor,
     tbfcp_pkt_FloorRequest_dtor,
     tbfcp_pkt_FloorRequest_cmp,
 };
 const tsk_object_def_t *tbfcp_pkt_FloorRequest_def_t = &tbfcp_pkt_FloorRequest_def_s;
 #endif