|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2009-2012 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Jonathan Bastien-Filiatrault
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GNUTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GNUTLS library is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "mbuffers.h"
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Here be mbuffers */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* A note on terminology:
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Variables named bufel designate a single buffer segment (mbuffer_st
|
|
Packit Service |
4684c1 |
* type). This type is textually referred to as a "segment" or a
|
|
Packit Service |
4684c1 |
* "buffer element".
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Variables named buf desigate a chain of buffer segments
|
|
Packit Service |
4684c1 |
* (mbuffer_head_st type). This type is textually referred to as a
|
|
Packit Service |
4684c1 |
* "buffer head" or simply as "buffer".
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Design objectives:
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* - Make existing code easier to understand.
|
|
Packit Service |
4684c1 |
* - Make common operations more efficient by avoiding unnecessary
|
|
Packit Service |
4684c1 |
* copying.
|
|
Packit Service |
4684c1 |
* - Provide a common datatype with a well-known interface to move
|
|
Packit Service |
4684c1 |
* data around and through the multiple protocol layers.
|
|
Packit Service |
4684c1 |
* - Enable a future implementation of DTLS, which needs the concept
|
|
Packit Service |
4684c1 |
* of record boundaries.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Initialize a buffer head.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
void _mbuffer_head_init(mbuffer_head_st * buf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
buf->head = NULL;
|
|
Packit Service |
4684c1 |
buf->tail = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
buf->length = 0;
|
|
Packit Service |
4684c1 |
buf->byte_length = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Deallocate all buffer segments and reset the buffer head.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(n)
|
|
Packit Service |
4684c1 |
* n: Number of segments currently in the buffer.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
void _mbuffer_head_clear(mbuffer_head_st * buf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel, *next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (bufel = buf->head; bufel != NULL; bufel = next) {
|
|
Packit Service |
4684c1 |
next = bufel->next;
|
|
Packit Service |
4684c1 |
gnutls_free(bufel);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_mbuffer_head_init(buf);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Append a segment to the end of this buffer.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
void _mbuffer_enqueue(mbuffer_head_st * buf, mbuffer_st * bufel)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
bufel->next = NULL;
|
|
Packit Service |
4684c1 |
bufel->prev = buf->tail;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
buf->length++;
|
|
Packit Service |
4684c1 |
buf->byte_length += bufel->msg.size - bufel->mark;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (buf->tail != NULL)
|
|
Packit Service |
4684c1 |
buf->tail->next = bufel;
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
buf->head = bufel;
|
|
Packit Service |
4684c1 |
buf->tail = bufel;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Remove a segment from the buffer.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns the buffer following it.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
mbuffer_st *_mbuffer_dequeue(mbuffer_head_st * buf, mbuffer_st * bufel)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *ret = bufel->next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (buf->tail == bufel) /* if last */
|
|
Packit Service |
4684c1 |
buf->tail = bufel->prev;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (buf->head == bufel) /* if first */
|
|
Packit Service |
4684c1 |
buf->head = bufel->next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bufel->prev)
|
|
Packit Service |
4684c1 |
bufel->prev->next = bufel->next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bufel->next)
|
|
Packit Service |
4684c1 |
bufel->next->prev = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
buf->length--;
|
|
Packit Service |
4684c1 |
buf->byte_length -= bufel->msg.size - bufel->mark;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bufel->next = bufel->prev = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Append a segment to the beginning of this buffer.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
void _mbuffer_head_push_first(mbuffer_head_st * buf, mbuffer_st * bufel)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
bufel->prev = NULL;
|
|
Packit Service |
4684c1 |
bufel->next = buf->head;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
buf->length++;
|
|
Packit Service |
4684c1 |
buf->byte_length += bufel->msg.size - bufel->mark;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (buf->head != NULL)
|
|
Packit Service |
4684c1 |
buf->head->prev = bufel;
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
buf->tail = bufel;
|
|
Packit Service |
4684c1 |
buf->head = bufel;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Get a reference to the first segment of the buffer and
|
|
Packit Service |
4684c1 |
* remove it from the list.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Used to start iteration.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
mbuffer_st *_mbuffer_head_pop_first(mbuffer_head_st * buf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel = buf->head;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (buf->head == NULL)
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_mbuffer_dequeue(buf, bufel);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return bufel;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Get a reference to the first segment of the buffer and its data.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Used to start iteration or to peek at the data.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
mbuffer_st *_mbuffer_head_get_first(mbuffer_head_st * buf,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * msg)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel = buf->head;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (msg) {
|
|
Packit Service |
4684c1 |
if (bufel) {
|
|
Packit Service |
4684c1 |
msg->data = bufel->msg.data + bufel->mark;
|
|
Packit Service |
4684c1 |
msg->size = bufel->msg.size - bufel->mark;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
msg->data = NULL;
|
|
Packit Service |
4684c1 |
msg->size = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return bufel;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Get a reference to the next segment of the buffer and its data.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Used to iterate over the buffer segments.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
mbuffer_st *_mbuffer_head_get_next(mbuffer_st * cur, gnutls_datum_t * msg)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel = cur->next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (msg) {
|
|
Packit Service |
4684c1 |
if (bufel) {
|
|
Packit Service |
4684c1 |
msg->data = bufel->msg.data + bufel->mark;
|
|
Packit Service |
4684c1 |
msg->size = bufel->msg.size - bufel->mark;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
msg->data = NULL;
|
|
Packit Service |
4684c1 |
msg->size = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return bufel;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Remove the first segment from the buffer.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Used to dequeue data from the buffer. Not yet exposed in the
|
|
Packit Service |
4684c1 |
* internal interface since it is not yet needed outside of this unit.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static inline void remove_front(mbuffer_head_st * buf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel = buf->head;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!bufel)
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_mbuffer_dequeue(buf, bufel);
|
|
Packit Service |
4684c1 |
gnutls_free(bufel);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Remove a specified number of bytes from the start of the buffer.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Useful for uses that treat the buffer as a simple array of bytes.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* If more than one mbuffer_st have been removed it
|
|
Packit Service |
4684c1 |
* returns 1, 0 otherwise and an error code on error.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(n)
|
|
Packit Service |
4684c1 |
* n: Number of segments needed to remove the specified amount of data.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _mbuffer_head_remove_bytes(mbuffer_head_st * buf, size_t bytes)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
size_t left = bytes;
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel, *next;
|
|
Packit Service |
4684c1 |
int ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bytes > buf->byte_length) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (bufel = buf->head; bufel != NULL && left > 0; bufel = next) {
|
|
Packit Service |
4684c1 |
next = bufel->next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (left >= (bufel->msg.size - bufel->mark)) {
|
|
Packit Service |
4684c1 |
left -= (bufel->msg.size - bufel->mark);
|
|
Packit Service |
4684c1 |
remove_front(buf);
|
|
Packit Service |
4684c1 |
ret = 1;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
bufel->mark += left;
|
|
Packit Service |
4684c1 |
buf->byte_length -= left;
|
|
Packit Service |
4684c1 |
left = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Allocate a buffer segment. The segment is not initially "owned" by
|
|
Packit Service |
4684c1 |
* any buffer.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* maximum_size: Amount of data that this segment can contain.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns the segment or NULL on error.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
mbuffer_st *_mbuffer_alloc(size_t maximum_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *st;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
st = gnutls_malloc(maximum_size + sizeof(mbuffer_st));
|
|
Packit Service |
4684c1 |
if (st == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* set the structure to zero */
|
|
Packit Service |
4684c1 |
memset(st, 0, sizeof(*st));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* payload points after the mbuffer_st structure */
|
|
Packit Service |
4684c1 |
st->msg.data = (uint8_t *) st + sizeof(mbuffer_st);
|
|
Packit Service |
4684c1 |
st->msg.size = 0;
|
|
Packit Service |
4684c1 |
st->maximum_size = maximum_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return st;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Copy data into a segment. The segment must not be part of a buffer
|
|
Packit Service |
4684c1 |
* head when using this function.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Bounds checking is performed by this function.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns 0 on success or an error code otherwise.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(n)
|
|
Packit Service |
4684c1 |
* n: number of bytes to copy
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_mbuffer_append_data(mbuffer_st * bufel, void *newdata,
|
|
Packit Service |
4684c1 |
size_t newdata_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (bufel->msg.size + newdata_size <= bufel->maximum_size) {
|
|
Packit Service |
4684c1 |
memcpy(&bufel->msg.data[bufel->msg.size], newdata,
|
|
Packit Service |
4684c1 |
newdata_size);
|
|
Packit Service |
4684c1 |
bufel->msg.size += newdata_size;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_ALIGN16
|
|
Packit Service |
4684c1 |
# define ALIGN_SIZE 16
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Allocate a 16-byte aligned buffer segment. The segment is not initially "owned" by
|
|
Packit Service |
4684c1 |
* any buffer.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* maximum_size: Amount of data that this segment can contain.
|
|
Packit Service |
4684c1 |
* align_pos: identifies the position of the buffer that will be aligned at 16-bytes
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function should be used to ensure that encrypted data or data to
|
|
Packit Service |
4684c1 |
* be encrypted are properly aligned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns the segment or NULL on error.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
mbuffer_st *_mbuffer_alloc_align16(size_t maximum_size, unsigned align_pos)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *st;
|
|
Packit Service |
4684c1 |
size_t cur_alignment;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
st = gnutls_malloc(maximum_size + sizeof(mbuffer_st) + ALIGN_SIZE);
|
|
Packit Service |
4684c1 |
if (st == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* set the structure to zero */
|
|
Packit Service |
4684c1 |
memset(st, 0, sizeof(*st));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* payload points after the mbuffer_st structure */
|
|
Packit Service |
4684c1 |
st->msg.data = (uint8_t *) st + sizeof(mbuffer_st);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cur_alignment = ((size_t)(st->msg.data+align_pos)) % ALIGN_SIZE;
|
|
Packit Service |
4684c1 |
if (cur_alignment > 0)
|
|
Packit Service |
4684c1 |
st->msg.data += ALIGN_SIZE - cur_alignment;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
st->msg.size = 0;
|
|
Packit Service |
4684c1 |
st->maximum_size = maximum_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return st;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static unsigned is_aligned16(mbuffer_st * bufel, unsigned align_pos)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t * ptr = _mbuffer_get_udata_ptr(bufel);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (((size_t)(ptr+align_pos)) % ALIGN_SIZE == 0)
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Takes a buffer in multiple chunks and puts all the data in a single
|
|
Packit Service |
4684c1 |
* contiguous segment, ensuring that the @align_pos is 16-byte aligned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns 0 on success or an error code otherwise.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Cost: O(n)
|
|
Packit Service |
4684c1 |
* n: number of segments initially in the buffer
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _mbuffer_linearize_align16(mbuffer_head_st * buf, unsigned align_pos)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel, *cur;
|
|
Packit Service |
4684c1 |
gnutls_datum_t msg;
|
|
Packit Service |
4684c1 |
size_t pos = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (buf->length == 0) {
|
|
Packit Service |
4684c1 |
/* Nothing to do */
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bufel = _mbuffer_head_get_first(buf, NULL);
|
|
Packit Service |
4684c1 |
if (buf->length == 1 && is_aligned16(bufel, align_pos))
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bufel = _mbuffer_alloc_align16(buf->byte_length, align_pos);
|
|
Packit Service |
4684c1 |
if (!bufel) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (cur = _mbuffer_head_get_first(buf, &msg;;
|
|
Packit Service |
4684c1 |
msg.data != NULL; cur = _mbuffer_head_get_next(cur, &msg)) {
|
|
Packit Service |
4684c1 |
memcpy(&bufel->msg.data[pos], msg.data, msg.size);
|
|
Packit Service |
4684c1 |
bufel->msg.size += msg.size;
|
|
Packit Service |
4684c1 |
pos += msg.size;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_mbuffer_head_clear(buf);
|
|
Packit Service |
4684c1 |
_mbuffer_enqueue(buf, bufel);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#else
|
|
Packit Service |
4684c1 |
int _mbuffer_linearize(mbuffer_head_st * buf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel, *cur;
|
|
Packit Service |
4684c1 |
gnutls_datum_t msg;
|
|
Packit Service |
4684c1 |
size_t pos = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (buf->length <= 1) {
|
|
Packit Service |
4684c1 |
/* Nothing to do */
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bufel = _mbuffer_alloc(buf->byte_length);
|
|
Packit Service |
4684c1 |
if (!bufel) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (cur = _mbuffer_head_get_first(buf, &msg;;
|
|
Packit Service |
4684c1 |
msg.data != NULL; cur = _mbuffer_head_get_next(cur, &msg)) {
|
|
Packit Service |
4684c1 |
memcpy(&bufel->msg.data[pos], msg.data, msg.size);
|
|
Packit Service |
4684c1 |
bufel->msg.size += msg.size;
|
|
Packit Service |
4684c1 |
pos += msg.size;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_mbuffer_head_clear(buf);
|
|
Packit Service |
4684c1 |
_mbuffer_enqueue(buf, bufel);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#endif
|