doubango/tinyBFCP/src/tbfcp_attr.c

675 lines
24 KiB
C
Executable File

/* Copyright (C) 2014 Mamadou DIOP.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
#include "tinybfcp/tbfcp_attr.h"
#include "tnet_endianness.h"
#include "tsk_memory.h"
#include "tsk_debug.h"
#define kWithoutPadding tsk_false
#define kWithPadding tsk_true
#define ALIGN_ON_32BITS(size_in_octes) if (((size_in_octes) & 3)) (size_in_octes) += (4 - ((size_in_octes) & 3));
#define ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(p_buffer, size_in_octes) \
if (((size_in_octes) & 3)) { \
int c = (4 - ((size_in_octes) & 3)); \
memset(p_buffer, 0, c); \
(size_in_octes) += c; \
}
static enum tbfcp_attribute_format_e _tbfcp_attr_get_format(enum tbfcp_attribute_type_e type)
{
switch (type) {
case tbfcp_attribute_type_BENEFICIARY_ID:
case tbfcp_attribute_type_FLOOR_ID:
case tbfcp_attribute_type_FLOOR_REQUEST_ID:
return tbfcp_attribute_format_Unsigned16;
case tbfcp_attribute_type_PRIORITY:
case tbfcp_attribute_type_REQUEST_STATUS:
return tbfcp_attribute_format_OctetString16;
case tbfcp_attribute_type_ERROR_CODE:
case tbfcp_attribute_type_ERROR_INFO:
case tbfcp_attribute_type_PARTICIPANT_PROVIDED_INFO:
case tbfcp_attribute_type_STATUS_INFO:
case tbfcp_attribute_type_SUPPORTED_ATTRIBUTES:
case tbfcp_attribute_type_SUPPORTED_PRIMITIVES:
case tbfcp_attribute_type_USER_DISPLAY_NAME:
case tbfcp_attribute_type_USER_URI:
return tbfcp_attribute_format_OctetString;
case tbfcp_attribute_type_BENEFICIARY_INFORMATION:
case tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION:
case tbfcp_attribute_type_REQUESTED_BY_INFORMATION:
case tbfcp_attribute_type_FLOOR_REQUEST_STATUS:
case tbfcp_attribute_type_OVERALL_REQUEST_STATUS:
return tbfcp_attribute_format_Grouped;
default:
return tbfcp_attribute_format_Unknown;
}
}
static int _tbfcp_attr_get_size_in_octetunits(const tbfcp_attr_t* pc_self, tsk_bool_t with_padding, tsk_size_t* p_size)
{
if (!pc_self || !p_size) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
switch (pc_self->format) {
case tbfcp_attribute_format_Unsigned16:
case tbfcp_attribute_format_OctetString16: {
*p_size = (TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 2);
if (with_padding) {
ALIGN_ON_32BITS(*p_size);
}
return 0;
}
case tbfcp_attribute_format_OctetString: {
*p_size = (TBFCP_ATTR_HDR_SIZE_IN_OCTETS + ((const tbfcp_attr_octetstring_t*)pc_self)->OctetStringLength);
if (with_padding) {
ALIGN_ON_32BITS(*p_size);
}
return 0;
}
case tbfcp_attribute_format_Grouped: {
int ret;
tsk_size_t n_size;
const tbfcp_attr_grouped_t* _pc_self = (const tbfcp_attr_grouped_t*)pc_self;
const tsk_list_item_t* pc_item;
const tbfcp_attr_t* pc_attr;
*p_size = TBFCP_ATTR_HDR_SIZE_IN_OCTETS + _pc_self->extra_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;
}
}
if (with_padding) {
ALIGN_ON_32BITS(*p_size);
}
return 0;
}
default: {
TSK_DEBUG_WARN("Attribute format=%d is unknown. Don't be surprised if something goes wrong.", pc_self->format);
*p_size = (TBFCP_ATTR_HDR_SIZE_IN_OCTETS + pc_self->hdr.length);
if (with_padding) {
ALIGN_ON_32BITS(*p_size);
}
return 0;
}
}
}
int tbfcp_attr_get_size_in_octetunits_without_padding(const tbfcp_attr_t* pc_self, tsk_size_t* p_size)
{
return _tbfcp_attr_get_size_in_octetunits(pc_self, kWithoutPadding, p_size);
}
int tbfcp_attr_get_size_in_octetunits_with_padding(const tbfcp_attr_t* pc_self, tsk_size_t* p_size)
{
return _tbfcp_attr_get_size_in_octetunits(pc_self, kWithPadding, p_size);
}
static int _tbfcp_attr_write(const tbfcp_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t with_padding, tsk_size_t *p_written)
{
tsk_size_t n_min_req_size;
int ret;
if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if ((ret = _tbfcp_attr_get_size_in_octetunits(pc_self, with_padding, &n_min_req_size))) {
return ret;
}
if (n_min_req_size > n_buff_size) {
TSK_DEBUG_ERROR("Buffer too short %u<%u", n_buff_size, n_min_req_size);
return -2;
}
p_buff_ptr[0] = ((uint8_t)pc_self->hdr.type) << 1;
p_buff_ptr[0] |= (pc_self->hdr.M & 0x01);
switch (pc_self->format) {
case tbfcp_attribute_format_Unsigned16:
case tbfcp_attribute_format_OctetString16: {
*p_written = TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 2;
p_buff_ptr[1] = (uint8_t)*p_written;
if (pc_self->format == tbfcp_attribute_format_Unsigned16) {
*((uint16_t*)&p_buff_ptr[2]) = tnet_htons(((const tbfcp_attr_unsigned16_t*)pc_self)->Unsigned16);
}
else {
p_buff_ptr[2] = ((const tbfcp_attr_octetstring16_t*)pc_self)->OctetString16[0];
p_buff_ptr[3] = ((const tbfcp_attr_octetstring16_t*)pc_self)->OctetString16[1];
}
if (with_padding) {
ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written);
}
return 0;
}
case tbfcp_attribute_format_OctetString: {
const tbfcp_attr_octetstring_t* _pc_self = (const tbfcp_attr_octetstring_t*)pc_self;
*p_written = TBFCP_ATTR_HDR_SIZE_IN_OCTETS + ((_pc_self->OctetStringLength && _pc_self->OctetString) ? _pc_self->OctetStringLength : 0);
p_buff_ptr[1] = (uint8_t)*p_written;
if (_pc_self->OctetStringLength && _pc_self->OctetString) {
memcpy(&p_buff_ptr[2], _pc_self->OctetString, _pc_self->OctetStringLength);
}
if (with_padding) {
ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written);
}
return 0;
}
case tbfcp_attribute_format_Grouped: {
int ret;
tsk_size_t n_written;
const tbfcp_attr_grouped_t* _pc_self = (const tbfcp_attr_grouped_t*)pc_self;
const tsk_list_item_t* pc_item;
const tbfcp_attr_t* pc_attr;
if (_pc_self->extra_hdr_size_in_octets && _pc_self->extra_hdr_size_in_octets != 2) {
TSK_DEBUG_ERROR("extra_hdr_size_in_octets=%u not valid", _pc_self->extra_hdr_size_in_octets); // for now only 2byte extra values is supported
return -2;
}
if ((ret = tbfcp_attr_get_size_in_octetunits_without_padding(pc_self, p_written))) {
return ret;
}
p_buff_ptr[1] = (uint8_t)*p_written;
p_buff_ptr += 2;
n_buff_size -= 2;
if (_pc_self->extra_hdr_size_in_octets) {
*((uint16_t*)p_buff_ptr) = tnet_htons_2(&_pc_self->extra_hdr);
p_buff_ptr += _pc_self->extra_hdr_size_in_octets;
n_buff_size -= _pc_self->extra_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(pc_attr, p_buff_ptr, n_buff_size, kWithoutPadding, &n_written))) {
return ret;
}
p_buff_ptr += n_written;
n_buff_size -= n_written;
}
}
if (with_padding) {
ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written);
}
return 0;
}
default: {
TSK_DEBUG_ERROR("Attribute format=%d is unknown.", pc_self->format);
return -2;
}
}
}
int tbfcp_attr_write_without_padding(const tbfcp_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written)
{
return _tbfcp_attr_write(pc_self, p_buff_ptr, n_buff_size, kWithoutPadding, p_written);
}
int tbfcp_attr_write_with_padding(const tbfcp_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written)
{
return _tbfcp_attr_write(pc_self, p_buff_ptr, n_buff_size, kWithPadding, p_written);
}
int tbfcp_attr_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_consumed_octets, tbfcp_attr_t** pp_attr)
{
uint8_t M, Length, PadLength;
tbfcp_attribute_type_t Type;
tbfcp_attribute_format_t Format;
int ret;
if (!pc_buff_ptr || !n_buff_size || !pp_attr || !p_consumed_octets) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (n_buff_size < TBFCP_ATTR_HDR_SIZE_IN_OCTETS) {
TSK_DEBUG_ERROR("Buffer too short(%u)", n_buff_size);
return -2;
}
Length = pc_buff_ptr[1];
if (Length > n_buff_size) {
TSK_DEBUG_ERROR("Buffer too short(%u). Length=%u", n_buff_size, Length);
return -3;
}
PadLength = (Length & 0x03) ? (4 - (Length & 0x03)) : 0;
*pp_attr = tsk_null;
*p_consumed_octets = Length + PadLength;
Type = (pc_buff_ptr[0] >> 1) & 0x7F;
M = (pc_buff_ptr[0] & 0x01);
Format = _tbfcp_attr_get_format(Type);
if (Format == tbfcp_attribute_format_Unknown) {
return 0;
}
if (Format == tbfcp_attribute_format_Unsigned16) {
uint16_t Unsigned16 = tnet_ntohs_2(&pc_buff_ptr[2]);
if ((ret = tbfcp_attr_unsigned16_create(Type, M, Unsigned16, (tbfcp_attr_unsigned16_t**)pp_attr))) {
return ret;
}
}
else if (Format == tbfcp_attribute_format_OctetString16) {
uint8_t OctetString16[2];
OctetString16[0] = pc_buff_ptr[2];
OctetString16[1] = pc_buff_ptr[3];
if ((ret = tbfcp_attr_octetstring16_create(Type, M, OctetString16, (tbfcp_attr_octetstring16_t**)pp_attr))) {
return ret;
}
}
else if (Format == tbfcp_attribute_format_OctetString) {
const uint8_t *OctetString = &pc_buff_ptr[TBFCP_ATTR_HDR_SIZE_IN_OCTETS];
uint8_t OctetStringLength = (Length - TBFCP_ATTR_HDR_SIZE_IN_OCTETS);
if ((ret = tbfcp_attr_octetstring_create(Type, M, OctetString, OctetStringLength, (tbfcp_attr_octetstring_t**)pp_attr))) {
return ret;
}
}
else if (Format == tbfcp_attribute_format_Grouped) {
tbfcp_attr_grouped_t* p_attr;
if ((ret = tbfcp_attr_grouped_create(Type, M, &p_attr))) {
return ret;
}
*pp_attr = (tbfcp_attr_t*)p_attr;
switch (Type) {
case tbfcp_attribute_type_BENEFICIARY_INFORMATION: {
p_attr->extra_hdr_size_in_octets = 2;
p_attr->extra_hdr.BeneficiaryID = tnet_ntohs_2(&pc_buff_ptr[2]);
break;
}
case tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION: {
p_attr->extra_hdr_size_in_octets = 2;
p_attr->extra_hdr.FloorRequestID = tnet_ntohs_2(&pc_buff_ptr[2]);
break;
}
case tbfcp_attribute_type_REQUESTED_BY_INFORMATION: {
p_attr->extra_hdr_size_in_octets = 2;
p_attr->extra_hdr.RequestedbyID = tnet_ntohs_2(&pc_buff_ptr[2]);
break;
}
case tbfcp_attribute_type_FLOOR_REQUEST_STATUS: {
p_attr->extra_hdr_size_in_octets = 2;
p_attr->extra_hdr.FloorID = tnet_ntohs_2(&pc_buff_ptr[2]);
break;
}
case tbfcp_attribute_type_OVERALL_REQUEST_STATUS: {
p_attr->extra_hdr_size_in_octets = 2;
p_attr->extra_hdr.FloorRequestID = tnet_ntohs_2(&pc_buff_ptr[2]);
break;
}
default: {
return 0;
}
}
if ((TBFCP_ATTR_HDR_SIZE_IN_OCTETS + p_attr->extra_hdr_size_in_octets) < Length) {
tsk_size_t n_consumed_octets, PayloadLength = Length;
PayloadLength -= TBFCP_ATTR_HDR_SIZE_IN_OCTETS + p_attr->extra_hdr_size_in_octets;
pc_buff_ptr += TBFCP_ATTR_HDR_SIZE_IN_OCTETS + p_attr->extra_hdr_size_in_octets;
if (PayloadLength >= TBFCP_ATTR_HDR_SIZE_IN_OCTETS) {
do {
if ((ret = tbfcp_attr_read(pc_buff_ptr, PayloadLength, &n_consumed_octets, (tbfcp_attr_t**)&p_attr))) {
break;
}
if ((ret = tbfcp_attr_grouped_add_attr((tbfcp_attr_grouped_t*)(*pp_attr), (tbfcp_attr_t**)&p_attr))) {
TSK_OBJECT_SAFE_FREE(p_attr);
break;
}
pc_buff_ptr += n_consumed_octets;
PayloadLength -= n_consumed_octets;
}
while (PayloadLength >= TBFCP_ATTR_HDR_SIZE_IN_OCTETS);
}
}
}
else {
TSK_DEBUG_ERROR("%d not valid attribute format", Format);
return -4;
}
return 0;
}
static int _tbfcp_attr_init(tbfcp_attr_t* p_self, tbfcp_attribute_type_t type, unsigned M, uint8_t length)
{
if (!p_self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!p_self->pc_base) {
p_self->pc_base = p_self;
}
p_self->hdr.type = type;
p_self->hdr.M = M;
p_self->hdr.length = length;
if ((p_self->format = _tbfcp_attr_get_format(type)) == tbfcp_attribute_format_Unknown) {
TSK_DEBUG_WARN("Attribute type=%d is unknown...setting its format to UNKNOWN. Don't be surprised if something goes wrong.", type);
}
return 0;
}
/*************** tbfcp_attr_unsigned16 *******************/
int tbfcp_attr_unsigned16_create(tbfcp_attribute_type_t type, unsigned M, uint16_t Unsigned16, tbfcp_attr_unsigned16_t** pp_self)
{
extern const tsk_object_def_t *tbfcp_attr_unsigned16_def_t;
tbfcp_attr_unsigned16_t* p_self;
int ret;
if (!pp_self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!(p_self = tsk_object_new(tbfcp_attr_unsigned16_def_t))) {
TSK_DEBUG_ERROR("Failed to create 'tbfcp_attr_unsigned16_def_t' object");
return -2;
}
if ((ret = _tbfcp_attr_init(TBFCP_ATTR(p_self), type, M, TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 2))) {
TSK_OBJECT_SAFE_FREE(p_self);
return -3;
}
if (TBFCP_ATTR(p_self)->format != tbfcp_attribute_format_Unsigned16) {
TSK_DEBUG_ERROR("Format mismatch");
TSK_OBJECT_SAFE_FREE(p_self);
return -4;
}
p_self->Unsigned16 = Unsigned16;
*pp_self = p_self;
return 0;
}
static tsk_object_t* tbfcp_attr_unsigned16_ctor(tsk_object_t * self, va_list * app)
{
tbfcp_attr_unsigned16_t *p_u16 = (tbfcp_attr_unsigned16_t *)self;
if (p_u16) {
}
return self;
}
static tsk_object_t* tbfcp_attr_unsigned16_dtor(tsk_object_t * self)
{
tbfcp_attr_unsigned16_t *p_u16 = (tbfcp_attr_unsigned16_t *)self;
if (p_u16) {
TSK_DEBUG_INFO("*** BFCP Attribute(Unsigned16) destroyed ***");
}
return self;
}
static int tbfcp_attr_unsigned16_cmp(const tsk_object_t *_att1, const tsk_object_t *_att2)
{
const tbfcp_attr_unsigned16_t *pc_att1 = (const tbfcp_attr_unsigned16_t *)_att1;
const tbfcp_attr_unsigned16_t *pc_att2 = (const tbfcp_attr_unsigned16_t *)_att2;
return (int)(pc_att1-pc_att2);
}
static const tsk_object_def_t tbfcp_attr_unsigned16_def_s = {
sizeof(tbfcp_attr_unsigned16_t),
tbfcp_attr_unsigned16_ctor,
tbfcp_attr_unsigned16_dtor,
tbfcp_attr_unsigned16_cmp,
};
const tsk_object_def_t *tbfcp_attr_unsigned16_def_t = &tbfcp_attr_unsigned16_def_s;
/*************** tbfcp_attr_octetstring16 *******************/
int tbfcp_attr_octetstring16_create(tbfcp_attribute_type_t type, unsigned M, uint8_t OctetString16[2], tbfcp_attr_octetstring16_t** pp_self)
{
extern const tsk_object_def_t *tbfcp_attr_octetstring16_def_t;
tbfcp_attr_octetstring16_t* p_self;
int ret;
if (!pp_self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!(p_self = tsk_object_new(tbfcp_attr_octetstring16_def_t))) {
TSK_DEBUG_ERROR("Failed to create 'tbfcp_attr_octetstring16_def_t' object");
return -2;
}
if ((ret = _tbfcp_attr_init(TBFCP_ATTR(p_self), type, M, TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 2))) {
TSK_OBJECT_SAFE_FREE(p_self);
return -3;
}
if (TBFCP_ATTR(p_self)->format != tbfcp_attribute_format_OctetString16) {
TSK_DEBUG_ERROR("Format mismatch");
TSK_OBJECT_SAFE_FREE(p_self);
return -4;
}
p_self->OctetString16[0] = OctetString16[0];
p_self->OctetString16[1] = OctetString16[1];
*pp_self = p_self;
return 0;
}
static tsk_object_t* tbfcp_attr_octetstring16_ctor(tsk_object_t * self, va_list * app)
{
tbfcp_attr_octetstring16_t *p_os16 = (tbfcp_attr_octetstring16_t *)self;
if (p_os16) {
}
return self;
}
static tsk_object_t* tbfcp_attr_octetstring16_dtor(tsk_object_t * self)
{
tbfcp_attr_octetstring16_t *p_os16 = (tbfcp_attr_octetstring16_t *)self;
if (p_os16) {
TSK_DEBUG_INFO("*** BFCP Attribute(OctetString16) destroyed ***");
}
return self;
}
static int tbfcp_attr_octetstring16_cmp(const tsk_object_t *_att1, const tsk_object_t *_att2)
{
const tbfcp_attr_octetstring16_t *pc_att1 = (const tbfcp_attr_octetstring16_t *)_att1;
const tbfcp_attr_octetstring16_t *pc_att2 = (const tbfcp_attr_octetstring16_t *)_att2;
return (int)(pc_att1-pc_att2);
}
static const tsk_object_def_t tbfcp_attr_octetstring16_def_s = {
sizeof(tbfcp_attr_octetstring16_t),
tbfcp_attr_octetstring16_ctor,
tbfcp_attr_octetstring16_dtor,
tbfcp_attr_octetstring16_cmp,
};
const tsk_object_def_t *tbfcp_attr_octetstring16_def_t = &tbfcp_attr_octetstring16_def_s;
/*************** tbfcp_attr_octetstring *******************/
int tbfcp_attr_octetstring_create(tbfcp_attribute_type_t type, unsigned M, const uint8_t *OctetString, uint8_t OctetStringLength, tbfcp_attr_octetstring_t** pp_self)
{
extern const tsk_object_def_t *tbfcp_attr_octetstring_def_t;
tbfcp_attr_octetstring_t* p_self;
int ret;
if (!pp_self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!(p_self = tsk_object_new(tbfcp_attr_octetstring_def_t))) {
TSK_DEBUG_ERROR("Failed to create 'tbfcp_attr_octetstring_def_t' object");
return -2;
}
if ((ret = _tbfcp_attr_init(TBFCP_ATTR(p_self), type, M, (TBFCP_ATTR_HDR_SIZE_IN_OCTETS + OctetStringLength)))) {
TSK_OBJECT_SAFE_FREE(p_self);
return -3;
}
if (TBFCP_ATTR(p_self)->format != tbfcp_attribute_format_OctetString) {
TSK_DEBUG_ERROR("Format mismatch");
TSK_OBJECT_SAFE_FREE(p_self);
return -4;
}
if (OctetStringLength) {
if (!(p_self->OctetString = tsk_malloc(OctetStringLength))) {
TSK_DEBUG_ERROR("Failed to alloc %u octets", OctetStringLength);
TSK_OBJECT_SAFE_FREE(p_self);
return -5;
}
if (OctetString) {
memcpy(p_self->OctetString, OctetString, OctetStringLength);
}
p_self->OctetStringLength = OctetStringLength;
}
else {
TBFCP_ATTR(p_self)->hdr.length = TBFCP_ATTR_HDR_SIZE_IN_OCTETS;
p_self->OctetStringLength = 0;
}
*pp_self = p_self;
return 0;
}
static tsk_object_t* tbfcp_attr_octetstring_ctor(tsk_object_t * self, va_list * app)
{
tbfcp_attr_octetstring_t *p_os = (tbfcp_attr_octetstring_t *)self;
if (p_os) {
}
return self;
}
static tsk_object_t* tbfcp_attr_octetstring_dtor(tsk_object_t * self)
{
tbfcp_attr_octetstring_t *p_os = (tbfcp_attr_octetstring_t *)self;
if (p_os) {
TSK_DEBUG_INFO("*** BFCP Attribute(OctetString) destroyed ***");
TSK_SAFE_FREE(p_os->OctetString);
}
return self;
}
static int tbfcp_attr_octetstring_cmp(const tsk_object_t *_att1, const tsk_object_t *_att2)
{
const tbfcp_attr_octetstring_t *pc_att1 = (const tbfcp_attr_octetstring_t *)_att1;
const tbfcp_attr_octetstring_t *pc_att2 = (const tbfcp_attr_octetstring_t *)_att2;
return (int)(pc_att1-pc_att2);
}
static const tsk_object_def_t tbfcp_attr_octetstring_def_s = {
sizeof(tbfcp_attr_octetstring_t),
tbfcp_attr_octetstring_ctor,
tbfcp_attr_octetstring_dtor,
tbfcp_attr_octetstring_cmp,
};
const tsk_object_def_t *tbfcp_attr_octetstring_def_t = &tbfcp_attr_octetstring_def_s;
/*************** tbfcp_attr_grouped *******************/
int tbfcp_attr_grouped_create(tbfcp_attribute_type_t type, unsigned M, tbfcp_attr_grouped_t** pp_self)
{
extern const tsk_object_def_t *tbfcp_attr_grouped_def_t;
tbfcp_attr_grouped_t* p_self;
int ret;
if (!pp_self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!(p_self = tsk_object_new(tbfcp_attr_grouped_def_t))) {
TSK_DEBUG_ERROR("Failed to create 'tbfcp_attr_grouped_def_t' object");
return -2;
}
if ((ret = _tbfcp_attr_init(TBFCP_ATTR(p_self), type, M, TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 0))) {
TSK_OBJECT_SAFE_FREE(p_self);
return -3;
}
if (TBFCP_ATTR(p_self)->format != tbfcp_attribute_format_Grouped) {
TSK_DEBUG_ERROR("Format mismatch");
TSK_OBJECT_SAFE_FREE(p_self);
return -4;
}
if (!(p_self->p_list_attrs = tsk_list_create())) {
TSK_DEBUG_ERROR("Failed to create empty list");
TSK_OBJECT_SAFE_FREE(p_self);
return -5;
}
*pp_self = p_self;
return 0;
}
int tbfcp_attr_grouped_create_u16(tbfcp_attribute_type_t type, unsigned M, uint16_t extra_hdr_u16_val, tbfcp_attr_grouped_t** pp_self)
{
int ret;
if ((ret = tbfcp_attr_grouped_create(type, M, pp_self))) {
return ret;
}
*((uint16_t*)&(*pp_self)->extra_hdr) = extra_hdr_u16_val;
(*pp_self)->extra_hdr_size_in_octets = 2;
return 0;
}
int tbfcp_attr_grouped_add_attr(tbfcp_attr_grouped_t* p_self, tbfcp_attr_t** p_attr)
{
if (!p_self || !p_attr) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
tsk_list_push_back_data(p_self->p_list_attrs, (void**)p_attr);
return 0;
}
int tbfcp_attr_grouped_find_at(const struct tbfcp_attr_grouped_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_attr_grouped_ctor(tsk_object_t * self, va_list * app)
{
tbfcp_attr_grouped_t *p_gr = (tbfcp_attr_grouped_t *)self;
if (p_gr) {
}
return self;
}
static tsk_object_t* tbfcp_attr_grouped_dtor(tsk_object_t * self)
{
tbfcp_attr_grouped_t *p_gr = (tbfcp_attr_grouped_t *)self;
if (p_gr) {
TSK_DEBUG_INFO("*** BFCP Attribute(Grouped) destroyed ***");
TSK_OBJECT_SAFE_FREE(p_gr->p_list_attrs);
}
return self;
}
static int tbfcp_attr_grouped_cmp(const tsk_object_t *_att1, const tsk_object_t *_att2)
{
const tbfcp_attr_grouped_t *pc_att1 = (const tbfcp_attr_grouped_t *)_att1;
const tbfcp_attr_grouped_t *pc_att2 = (const tbfcp_attr_grouped_t *)_att2;
return (int)(pc_att1-pc_att2);
}
static const tsk_object_def_t tbfcp_attr_grouped_def_s = {
sizeof(tbfcp_attr_grouped_t),
tbfcp_attr_grouped_ctor,
tbfcp_attr_grouped_dtor,
tbfcp_attr_grouped_cmp,
};
const tsk_object_def_t *tbfcp_attr_grouped_def_t = &tbfcp_attr_grouped_def_s;