149 lines
3.3 KiB
C
149 lines
3.3 KiB
C
/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */
|
|
/*
|
|
* lsquic_frab_list.c -- List of buffer for simple reading and writing
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/queue.h>
|
|
|
|
#include "lsquic_frab_list.h"
|
|
|
|
|
|
static void *
|
|
fral_alloc (void *ctx, size_t size)
|
|
{
|
|
return malloc(size);
|
|
}
|
|
|
|
|
|
static void
|
|
fral_free (void *ctx, void *obj)
|
|
{
|
|
free(obj);
|
|
}
|
|
|
|
|
|
void
|
|
lsquic_frab_list_init (struct frab_list *fral, unsigned short buf_size,
|
|
void * (*alloc)(void *alloc_ctx, size_t size),
|
|
void (*free)(void *alloc_ctx, void *obj), void *alloc_ctx)
|
|
{
|
|
TAILQ_INIT(&fral->fl_frabs);
|
|
fral->fl_alloc_ctx = alloc_ctx;
|
|
fral->fl_alloc = alloc ? alloc : fral_alloc;
|
|
fral->fl_free = free ? free : fral_free;
|
|
fral->fl_buf_size = buf_size;
|
|
fral->fl_size = 0;
|
|
}
|
|
|
|
|
|
void
|
|
lsquic_frab_list_cleanup (struct frab_list *fral)
|
|
{
|
|
struct frame_buf *frab, *next;
|
|
|
|
for (frab = TAILQ_FIRST(&fral->fl_frabs); frab; frab = next)
|
|
{
|
|
next = TAILQ_NEXT(frab, frab_next);
|
|
fral->fl_free(fral->fl_alloc_ctx, frab);
|
|
}
|
|
}
|
|
|
|
|
|
static struct frame_buf *
|
|
fral_get_frab (struct frab_list *fral)
|
|
{
|
|
struct frame_buf *frab;
|
|
frab = fral->fl_alloc(fral->fl_alloc_ctx, fral->fl_buf_size);
|
|
if (frab)
|
|
{
|
|
memset(frab, 0, sizeof(*frab));
|
|
frab->frab_buf_size = fral->fl_buf_size;
|
|
}
|
|
return frab;
|
|
}
|
|
|
|
|
|
int
|
|
lsquic_frab_list_write (struct frab_list *fral, const void *buf, size_t bufsz)
|
|
{
|
|
const unsigned char *p = buf;
|
|
const unsigned char *const end = p + bufsz;
|
|
struct frame_buf *frab;
|
|
unsigned ntowrite;
|
|
|
|
while (p < end)
|
|
{
|
|
frab = TAILQ_LAST(&fral->fl_frabs, frame_buf_head);
|
|
if (!(frab && (ntowrite = frab_left_to_write(frab)) > 0))
|
|
{
|
|
frab = fral_get_frab(fral);
|
|
if (!frab)
|
|
return -1;
|
|
TAILQ_INSERT_TAIL(&fral->fl_frabs, frab, frab_next);
|
|
ntowrite = frab_left_to_write(frab);
|
|
}
|
|
if ((ptrdiff_t) ntowrite > end - p)
|
|
ntowrite = end - p;
|
|
memcpy(frab_write_to(frab), p, ntowrite);
|
|
p += ntowrite;
|
|
frab->frab_size += ntowrite;
|
|
}
|
|
|
|
fral->fl_size += bufsz;
|
|
return 0;
|
|
}
|
|
|
|
|
|
size_t
|
|
lsquic_frab_list_size (void *ctx)
|
|
{
|
|
struct frab_list *fral = ctx;
|
|
return fral->fl_size;
|
|
}
|
|
|
|
|
|
size_t
|
|
lsquic_frab_list_read (void *ctx, void *buf, size_t bufsz)
|
|
{
|
|
struct frab_list *const fral = ctx;
|
|
unsigned char *p = buf;
|
|
unsigned char *const end = p + bufsz;
|
|
struct frame_buf *frab;
|
|
size_t ntocopy;
|
|
|
|
while (p < end && (frab = TAILQ_FIRST(&fral->fl_frabs)))
|
|
{
|
|
ntocopy = end - p;
|
|
if (ntocopy > (size_t) frab_left_to_read(frab))
|
|
ntocopy = frab_left_to_read(frab);
|
|
memcpy(p, frab->frab_buf + frab->frab_off, ntocopy);
|
|
fral->fl_size -= ntocopy;
|
|
frab->frab_off += ntocopy;
|
|
p += ntocopy;
|
|
if (frab->frab_off == frab->frab_size)
|
|
{
|
|
TAILQ_REMOVE(&fral->fl_frabs, frab, frab_next);
|
|
fral->fl_free(fral->fl_alloc_ctx, frab);
|
|
}
|
|
}
|
|
|
|
return p - (unsigned char *) buf;
|
|
}
|
|
|
|
|
|
size_t
|
|
lsquic_frab_list_mem_used (const struct frab_list *fral)
|
|
{
|
|
struct frame_buf *frab;
|
|
size_t size;
|
|
|
|
size = sizeof(*fral);
|
|
TAILQ_FOREACH(frab, &fral->fl_frabs, frab_next)
|
|
size += fral->fl_buf_size;
|
|
|
|
return size;
|
|
}
|