litespeed-quic/src/liblsquic/lsquic_frab_list.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;
}