blob: 0b317429875189606a5bf1fc846dff8f024a129d [file] [log] [blame]
/*
* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*
* File: $File: //depot/software/projects/feature_branches/nova_phase1/ap/apps/asf/aniAsfPacket.c $
* Contains definitions for packet manipulation routines that make it
* easy to create and parse multi-layered network frames. This module
* minimizes buffer copies while adding or removing headers, and
* adding or removing payload.
*
* Author: Mayank D. Upadhyay
* Date: 19-June-2002
* History:-
* Date Modified by Modification Information
* ------------------------------------------------------
*
*/
#include "vos_types.h"
#include "vos_trace.h"
#include <bapRsnAsfPacket.h>
#include <bapRsnErrors.h>
#include "vos_memory.h"
#include "vos_packet.h"
/*
* Allocate one more than required because the last bytes is waste. We
* waste the last byte because in the adopted model, the tail always
* points to the next location where data should be stored. In a full
* buffer we don't want to position the tail to memory we haven't
* allocated ourself.
*/
#define ANI_INTERNAL_DEFAULT_PACKET_SIZE (ANI_DEFAULT_PACKET_SIZE + 4)
#define TAIL_SPACE(packet) \
((packet)->buf + (packet)->size - (packet)->tail)
#define HEAD_SPACE(packet) \
((packet)->head - (packet)->buf)
#define ANI_CHECK_RANGE(x , upper) \
( (x) <= (upper) )
/**
* Opaque packet structure with internal storage for raw bytes.
* Conceptually, a tAniPacket is a pre-allocated buffer that contains
* data in the middle and free space on either side. The start of the
* data is called the head. Routines are provided to add data at the
* front or at the rear. The length of the packet is the total number
* of valid data bytes contained in it. The size of the packet is the
* total number of preallocated bytes.
*/
struct tAniPacket {
v_U8_t *buf;
v_U32_t size;
v_U8_t *head;
v_U8_t *tail;
v_U8_t *recordHeader;
v_U32_t len;
};
/**
* aniAsfPacketAllocate
*
* FUNCTION:
* Create a packet of size 2*ANI_DEFAULT_PACKET_SIZE and positions the
* head of the packet in the center. The allocated storage can be free
* with a call to aniAsfPacketFree.
*
* LOGIC:
* Allocates storage for tAniPacket and its internal raw data
* buffer. Positions the head and tail pointers in the middle of the
* raw data buffer.
*
* @param packetPtr pointer that will be set to newly allocated
* tAniPacket if the operation succeeds.
*
* @return ANI_OK if the operation succeeds; ANI_E_MALLOC_FAILED if
* memory could not be allocated.
* @see aniAsfPacketFree
*/
int
aniAsfPacketAllocate(tAniPacket **packetPtr)
{
return aniAsfPacketAllocateExplicit(packetPtr,
ANI_INTERNAL_DEFAULT_PACKET_SIZE,
ANI_INTERNAL_DEFAULT_PACKET_SIZE/2);
}
/**
* aniAsfPacketAllocateExplicit
*
* FUNCTION:
* Create a packet of the desired size and position the head of the
* packet at the desired offset in the internal raw data buffer. An
* application would normally set this offset to the expected length
* of the protocol header, then append the payload, and finally,
* prepend the header. The allocated storage can be free with a call
* to aniAsfPacketFree.
*
* LOGIC:
* Allocates storage for tAniPacket and its internal raw data
* buffer. Positions the head and tail pointers at the given offset in
* the internal raw data buffer.
*
* @param packetPtr pointer that will be set to newly allocated
* tAniPacket if the operation succeeds.
* @param size the size of the internal raw data buffer
* @param offset the offset in the internal raw data buffer where the
* head of the packet will be positioned initially
*
* @return ANI_OK if the operation succeeds; ANI_E_MALLOC_FAILED if
* memory could not be allocated.
* @see aniAsfPacketFree
*/
int
aniAsfPacketAllocateExplicit(tAniPacket **packetPtr,
v_U32_t size,
v_U32_t offset)
{
tAniPacket *packet = NULL;
v_U32_t maxHead = size;
*packetPtr = NULL;
if (size == 0)
return ANI_E_ILLEGAL_ARG;
VOS_ASSERT(ANI_CHECK_RANGE(offset, maxHead));
if (!ANI_CHECK_RANGE(offset, maxHead))
return ANI_E_ILLEGAL_ARG;
packet = (tAniPacket *) vos_mem_malloc( sizeof(tAniPacket) );
if (packet == NULL)
{
VOS_ASSERT( 0 );
return ANI_E_MALLOC_FAILED;
}
// transparently add one to the size since last byte is wasted
size = (size + 4) & 0xfffffffc;
packet->buf = (v_U8_t *)vos_mem_malloc( sizeof(v_U8_t) * size );
if (packet->buf == NULL)
{
vos_mem_free( packet );
VOS_ASSERT( 0 );
return ANI_E_MALLOC_FAILED;
}
packet->size = size; // Should not be visible to the user
packet->head = packet->buf + offset;
packet->tail = packet->head;
packet->len = 0;
*packetPtr = packet;
return ANI_OK;
}
/**
* aniAsfPacketDuplicate
*
* Duplicates a given packet exactly. That is, the contents, the size
* of the packet, and the positions of the pointers are maintained in
* the new copy.
*
* @param newPacketPtr is set to a newly allocated packet that is a
* duplicate of oldPacket
* @param oldPacket the original packet that should be duplicated
*
* @return ANI_OK if the operation succeeds; ANI_E_NULL if oldPacket
* is NULL;
*/
int
aniAsfPacketDuplicate(tAniPacket **newPacketPtr, tAniPacket *oldPacket)
{
int retVal;
int recordPos;
tAniPacket *packet = NULL;
if (oldPacket == NULL)
return ANI_E_NULL_VALUE;
retVal = aniAsfPacketAllocateExplicit(&packet,
oldPacket->size,
oldPacket->head - oldPacket->buf);
if (retVal != ANI_OK)
return retVal;
retVal = aniAsfPacketAppendBuffer(packet,
oldPacket->head,
oldPacket->len);
if (retVal != ANI_OK)
{
VOS_ASSERT( 0 );
aniAsfPacketFree(packet);
return ANI_E_FAILED;
}
if (oldPacket->recordHeader != NULL)
{
recordPos = oldPacket->recordHeader - oldPacket->buf;
packet->recordHeader = packet->buf + recordPos;
}
*newPacketPtr = packet;
return ANI_OK;
}
/**
* aniAsfPacketFree
*
* FUNCTION:
* Free a previously allocated tAniPacket and its internal raw data
* buffer.
*
* @param packet the packet to free
*
* @return ANI_OK if the operation succeeds; ANI_E_NULL_VALUE if an
* unexpected NULL pointer is encountered
*/
int
aniAsfPacketFree(tAniPacket *packet)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (packet->buf != NULL)
vos_mem_free( packet->buf );
vos_mem_free( packet );
return ANI_OK;
}
/**
* aniAsfPacketAppendBuffer
*
* FUNCTION:
* Appends the data contained in buf to the end of the data in
* destAniPacket. The head of destAniPacket remains unchanged, while its
* length increases by len.
*
* If there isn't enough free space in destAniPacket for all len bytes
* then the routine fails and the length of destAniPacket remains
* unchanged.
*
* LOGIC:
* Check that there is enough free space in the packet to append the
* buffer. If not, bail. Otherwise, copy bytes from the buffer into
* the packet's internal raw data buffer and increase the value of its
* length to reflect this.
*
* @param packet the packet to append to
* @param buf the buffer containing data to be appended to the packet
* @param len the number of bytes to append
*
* @return ANI_OK if the operation succeeds; ANI_E_FAILED if the
* packet does not have enough free space for the complete buffer
* @see aniAsfPacketPrependBuffer
*/
int
aniAsfPacketAppendBuffer(tAniPacket *destPacket,
const v_U8_t *buf,
v_U32_t len)
{
if (aniAsfPacketCanAppendBuffer(destPacket, len) != ANI_OK)
return ANI_E_FAILED;
if (buf == NULL)
return ANI_E_NULL_VALUE;
vos_mem_copy(destPacket->tail, buf, len);
destPacket->tail += len;
destPacket->len += len;
return ANI_OK;
}
/**
* aniAsfPacketPrependBuffer
*
* FUNCTION:
* Prepends the data contained in buf to the start of the data in
* destPacket. The head of destPacket is repositioned and the length
* of destPacket increases by len.
*
* If there isn't enough free space in destPacket for all len bytes
* then the routine fails and the length of destPacket remains
* unchanged.
*
* LOGIC:
* Check that there is enough free space in the packet to prepend the
* buffer. If not, bail. Otherwise, copy bytes from the buffer into
* the packet's internal raw data buffer and increase the value of its
* length to reflect this.
*
* @param packet the packet to prepend to
* @param buf the buffer containing data to be prepended to the packet
* @param len the number of bytes to prepend
*
* @return ANI_OK if the operation succeeds; ANI_E_FAILED if the
* packet does not have enough free space for the complete buffer
* @see aniAsfPacketAppendBuffer
*/
int
aniAsfPacketPrependBuffer(tAniPacket *destPacket,
const v_U8_t *buf,
v_U32_t len)
{
if (aniAsfPacketCanPrependBuffer(destPacket, len) != ANI_OK)
return ANI_E_FAILED;
if (buf == NULL)
return ANI_E_NULL_VALUE;
destPacket->head -= len;
destPacket->len += len;
vos_mem_copy(destPacket->head, buf, len);
return ANI_OK;
}
/**
* aniAsfPacketCanAppendBuffer
*
* FUNCTION:
* Determines if len bytes can be safely appended to destPacket
* without overflowing.
*
* LOGIC:
* Current packet tail plus len of buffer should not exceed packet
* start plus packet size
*
* Note: This does not return a boolean value, but instead an integer
* code.
*
* @param packet the packet to append to
* @param len the number of bytes to append
*
* @return ANI_OK if the append operation would succeed; ANI_E_FAILED
* otherwise
*/
int
aniAsfPacketCanAppendBuffer(tAniPacket *destPacket,
v_U32_t len)
{
if (destPacket == NULL)
return ANI_E_FAILED;
if ((int)len <= TAIL_SPACE(destPacket))
return ANI_OK;
else
return ANI_E_FAILED;
}
/**
* aniAsfPacketCanPrependBuffer
*
* FUNCTION:
* Determines if len bytes can be safely prepended to destPacket
* without overflowing.
*
* LOGIC:
* Current packet head minus len of buffer should not be less than
* start of packet.
*
* Note: This does not return a boolean value, but instead an integer
* code.
*
* @param packet the packet to prepend to
* @param len the number of bytes to prepend
*
* @return ANI_OK if the append operation would succeed; ANI_E_FAILED
* otherwise
*/
int
aniAsfPacketCanPrependBuffer(tAniPacket *destPacket,
v_U32_t len)
{
if (destPacket == NULL)
return ANI_E_FAILED;
if (!(len > 0))
return ANI_E_FAILED;
if ((int)len <= HEAD_SPACE(destPacket))
return ANI_OK;
else
return ANI_E_FAILED;
}
/**
* aniAsfPacketTruncateFromFront
*
* FUNCTION:
* Removes len bytes from the front of the packet by moving its
* head. The length of the packet is decremented by len.
*
* @param packet the packet to truncate from the front
* @param len the number of bytes to truncate
*
* @return ANI_OK if the append operation would succeed; ANI_E_FAILED
* otherwise
*/
int
aniAsfPacketTruncateFromFront(tAniPacket *packet,
v_U32_t len)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (!ANI_CHECK_RANGE(len, packet->len))
return ANI_E_FAILED;
packet->head += len;
packet->len -= len;
return ANI_OK;
}
/**
* aniAsfPacketTruncateFromRear
*
* FUNCTION:
* Removes len bytes from the rear of the packet by moving its
* tail. The length of the packet is decremented by len.
*
* @param packet the packet to truncate from the rear
* @param len the number of bytes to truncate
*
* @return ANI_OK if the append operation would succeed; ANI_E_FAILED
* otherwise
*/
int
aniAsfPacketTruncateFromRear(tAniPacket *packet,
v_U32_t len)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (!ANI_CHECK_RANGE(len, packet->len))
return ANI_E_FAILED;
packet->tail -= len;
packet->len -= len;
return ANI_OK;
}
/**
* aniAsfPacketGetLen
*
* FUNCTION:
* Returns the number of valid data bytes stored in the packet.
*
* @param packet the packet whose len we need
*
* @return the non-negative number of bytes stored in the packet
*/
int
aniAsfPacketGetLen(tAniPacket *packet)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
return packet->len;
}
/**
* aniAsfPacketGetBytes
*
* FUNCTION:
* Returns a pointer to the head of the valid data stored in the
* packet.
*
* @param packet the packet whose bytes we need
* @param rawBytesPtr the pointer that will be set the start of the
* raw bytes.
*
* @return The non-negative number of bytes stored in the packet if
* the operation succeeded. That is the same value as what would be
* returned by aniAsfPacketGetLen.
*/
int
aniAsfPacketGetBytes(tAniPacket *packet, v_U8_t **rawBytesPtr)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
*rawBytesPtr = packet->head;
return packet->len;
}
/**
* aniAsfPacketGetN
*
* Returns N bytes from the packet and moves the head of the packet
* beyond those bytes.
*
* @param packet the packet to read from
* @param n the number of bytes to read
* @param bytesPtr is set to the start of the octets
*
* @return ANI_OK if the operation succeeds; ANI_E_SHORT_PACKET if the
* packet does not have n bytes.
*/
int
aniAsfPacketGetN(tAniPacket *packet, int n, v_U8_t **bytesPtr)
{
int retVal;
v_U8_t *bytes = NULL;
if (packet == NULL)
return ANI_E_NULL_VALUE;
retVal = aniAsfPacketGetBytes(packet, &bytes);
if (retVal < n)
return ANI_E_SHORT_PACKET;
aniAsfPacketTruncateFromFront(packet, n);
*bytesPtr = bytes;
return ANI_OK;
}
/**
* aniAsfPacketEmpty
*
* FUNCTION:
* Re-initializes the packet by positioning the head to the middle and
* setting the length to zero.
*
* @param packet the packet to empty
*
* @return ANI_OK if the operation succeeded
*/
int
aniAsfPacketEmpty(tAniPacket *packet)
{
return aniAsfPacketEmptyExplicit(packet, packet->size/2);
}
/**
* aniAsfPacketEmptyExplicit
*
* FUNCTION:
* Re-initializes the packet by positioning the head to the desired
* offset and setting the length to zero.
*
* @param packet the packet to empty
* @param offset the offset that the head of the packet should be set
* to. An application will be able to prepend and append data relative
* to this offset.
*
* @return ANI_OK if the operation succeeded
*/
int
aniAsfPacketEmptyExplicit(tAniPacket *packet,
v_U32_t offset)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
VOS_ASSERT(ANI_CHECK_RANGE(offset, packet->size));
if (!ANI_CHECK_RANGE(offset, packet->size))
return ANI_E_ILLEGAL_ARG;
packet->head = packet->buf + offset;
packet->tail = packet->head;
packet->len = 0;
return ANI_OK;
}
/**
* aniAsfPacketPrependHdr
*
* FUNCTION:
* Prepends a tAniHdr at the start of the packet. All host to network
* byte order translation is also taken care of.
*
* @param packet the packet to write to
* @param msgType the message type to write as part of the header
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketPrependHdr(tAniPacket *packet, v_U16_t msgType)
{
int retVal;
int length;
if (packet == NULL)
return ANI_E_NULL_VALUE;
length = 4;
length = 2 + 2 + packet->len;
retVal = aniAsfPacketPrepend16(packet, length);
if (retVal < 0)
return retVal;
retVal = aniAsfPacketPrepend16(packet, msgType);
if (retVal < 0)
return retVal;
return ANI_OK;
}
/**
* aniAsfPacketGet32
*
* FUNCTION:
* Reads a ANI_U32 out of the packet and returns it. The packet's head
* is advanced and its length decremented by the appropriate length.
* All network to host byte order translation is also taken care of.
*
* @param packet the packet to read from
* @param val the value to fill in
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketGet32(tAniPacket *packet, v_U32_t *val)
{
v_U8_t u32Arr[4];
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (val == NULL)
return ANI_E_NULL_VALUE;
if (packet->len < 4)
return ANI_E_SHORT_PACKET;
//packet is in network order, make sure it is align
u32Arr[0] = packet->head[0];
u32Arr[1] = packet->head[1];
u32Arr[2] = packet->head[2];
u32Arr[3] = packet->head[3];
*val = vos_be32_to_cpu( *(v_U32_t *)u32Arr );
aniAsfPacketTruncateFromFront(packet, 4);
return ANI_OK;
}
/**
* aniAsfPacketAppend32
*
* FUNCTION:
* Appends a ANI_U32 to the end of the packet.
* All host to network byte order translation is also taken care of.
*
* @param packet the packet to write to
* @param val the value to append
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketAppend32(tAniPacket *packet, v_U32_t val)
{
v_U8_t *p8;
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (TAIL_SPACE(packet) < 4)
return ANI_E_FAILED;
val = vos_cpu_to_be32( val );
p8 = (v_U8_t *)&val;
packet->tail[0] = p8[0];
packet->tail[1] = p8[1];
packet->tail[2] = p8[2];
packet->tail[3] = p8[3];
aniAsfPacketMoveRight(packet, 4);
return ANI_OK;
}
/**
* aniAsfPacketGet16
*
* FUNCTION:
* Reads a ANI_U16 out of the packet and returns it. The packet's head
* is advanced and its length decremented by the appropriate length.
* All network to host byte order translation is also taken care of.
*
* @param packet the packet to read from
* @param val the value to fill in
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketGet16(tAniPacket *packet, v_U16_t *val)
{
v_U8_t u16Arr[2];
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (val == NULL)
return ANI_E_NULL_VALUE;
if (packet->len < 2)
return ANI_E_SHORT_PACKET;
u16Arr[0] = packet->head[0];
u16Arr[1] = packet->head[1];
*val = vos_be16_to_cpu( *(v_U16_t *)u16Arr );
aniAsfPacketTruncateFromFront(packet, 2);
return ANI_OK;
}
/**
* aniAsfPacketPrepend16
*
* FUNCTION:
* Prepends a ANI_U16 to the start of the packet.
* All host to network byte order translation is also taken care of.
*
* @param packet the packet to write to
* @param val the value to prepend
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketPrepend16(tAniPacket *packet, v_U16_t val)
{
v_U8_t *p8;
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (HEAD_SPACE(packet) < 2)
return ANI_E_FAILED;
aniAsfPacketMoveLeft(packet, 2);
val = vos_cpu_to_be16( val );
p8 = (v_U8_t *)&val;
packet->head[0] = p8[0];
packet->head[1] = p8[1];
return ANI_OK;
}
/**
* aniAsfPacketAppend16
*
* FUNCTION:
* Appends a ANI_U16 to the end of the packet.
* All host to network byte order translation is also taken care of.
*
* @param packet the packet to write to
* @param val the value to append
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketAppend16(tAniPacket *packet, v_U16_t val)
{
v_U8_t *p8;
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (TAIL_SPACE(packet) < 2)
return ANI_E_FAILED;
val = vos_cpu_to_be16( val );
p8 = (v_U8_t *)&val;
packet->tail[0] = p8[0];
packet->tail[1] = p8[1];
aniAsfPacketMoveRight(packet, 2);
return ANI_OK;
}
/**
* aniAsfPacketGet8
*
* FUNCTION:
* Reads a ANI_U8 out of the packet and returns it. The packet's head
* is advanced and its length decremented by the appropriate length.
* All network to host byte order translation is also taken care of.
*
* @param packet the packet to read from
* @param val the value to fill in
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketGet8(tAniPacket *packet, v_U8_t *val)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (val == NULL)
return ANI_E_NULL_VALUE;
if (packet->len < 1)
return ANI_E_SHORT_PACKET;
*val = *(packet->head);
aniAsfPacketTruncateFromFront(packet, 1);
return ANI_OK;
}
/**
* aniAsfPacketPrepend8
*
* FUNCTION:
* Prepends a ANI_U8 to the start of the packet.
* All host to network byte order translation is also taken care of.
*
* @param packet the packet to read from
* @param val the value to prepend
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketPrepend8(tAniPacket *packet, v_U8_t val)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
VOS_ASSERT(HEAD_SPACE(packet) >= 1);
if (HEAD_SPACE(packet) < 1)
return ANI_E_FAILED;
aniAsfPacketMoveLeft(packet, 1);
*(packet->head) = val;
return ANI_OK;
}
/**
* aniAsfPacketAppend8
*
* FUNCTION:
* Appends a ANI_U8 to the end of the packet.
* All host to network byte order translation is also taken care of.
*
* @param packet the packet to write to
* @param val the value to append
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketAppend8(tAniPacket *packet, v_U8_t val)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
if (TAIL_SPACE(packet) < 1)
return ANI_E_FAILED;
*(packet->tail) = val;
aniAsfPacketMoveRight(packet, 1);
return ANI_OK;
}
/**
* aniAsfPacketGetMac
*
* FUNCTION:
* Returns a tAniMacAddr from the start of the packet.
*
* @param packet the packet to read from
* @param macAddr the destination to copy the MAC address to
*
* @return ANI_OK if the operation succeeds. Also, the packet head
* pointer is advanced past the MAC address.
*/
int
aniAsfPacketGetMac(tAniPacket *packet, tAniMacAddr macAddr)
{
if (packet->len < sizeof(tAniMacAddr))
return ANI_E_SHORT_PACKET;
vos_mem_copy(macAddr, packet->head, sizeof(tAniMacAddr));
packet->head += sizeof(tAniMacAddr);
packet->len -= sizeof(tAniMacAddr);
return ANI_OK;
}
/**
* aniAsfPacketMoveLeft
*
* FUNCTION:
* Pretends that a certain number of bytes have been prepended to the
* packet, without actually copying any bytes in. The packet head and
* length are appropriately changed. This function is useful while
* interfacing with other libraries that only support byte array
* manipulation.
*
* WARNING:
* Applications are discouraged from using this function
* because correct usage is a two-step process - one: copy some bytes
* to the packet's internal buffer, two: move head and length. This
* violates the encapsulation the packet library aims to provide.
*
* @param packet the packet whose head and length needs to be modified
* @param count the number of bytes to modify by
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketMoveLeft(tAniPacket *packet, v_U32_t count)
{
if (aniAsfPacketCanPrependBuffer(packet, count) != ANI_OK)
return ANI_E_FAILED;
packet->head -= count;
packet->len += count;
return ANI_OK;
}
/**
* aniAsfPacketMoveRight
*
* FUNCTION:
* Pretends that a certain number of bytes have been appended to the
* packet, without actually copying any bytes in. The packet tail and
* length are appropriately changed. This function is useful while
* interfacing with other libraries that only support byte array
* manipulation.
*
* WARNING:
* Applications are discouraged from using this function
* because correct usage is a two-step process - one: copy some bytes
* to the packet's internal buffer, two: move tail and length. This
* violates the encapsulation the packet library aims to provide.
*
* @param packet the packet whose head and length needs to be modified
* @param count the number of bytes to modify by
*
* @return ANI_OK if the operation succeeds
*/
int
aniAsfPacketMoveRight(tAniPacket *packet, v_U32_t count)
{
if (aniAsfPacketCanAppendBuffer(packet, count) != ANI_OK)
return ANI_E_FAILED;
packet->tail += count;
packet->len += count;
return ANI_OK;
}
/**
* aniAsfPacketGetBytesFromTail
*
* FUNCTION:
* Returns a pointer to the tail of the valid data stored
* in the packet.
*
* WARNING:
* Applications are discouraged from using this function
* because correct usage is a three-step process - one: call this
* routine to obtain a pointer to the current tail of the packet.
* two: treat this returned pointer like a simple array and copy
* some bytes to the packet's internal buffer, and finally
* three: move tail and length. This violates the encapsulation
* the packet library aims to provide.
*
* @param packet the packet whose bytes we need
* @param rawBytesPtr the pointer that will be set the start of the
* raw bytes.
*
* @return The non-negative number of bytes stored in the packet if
* the operation succeeded. That is the same value as what would be
* returned by aniAsfPacketGetLen.
*/
int
aniAsfPacketGetBytesFromTail(tAniPacket *packet, v_U8_t **rawBytesPtr)
{
if (packet == NULL)
return ANI_E_NULL_VALUE;
*rawBytesPtr = packet->tail;
return 0; // The length of used bytes returned is zero
}