1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
25392f7a3SLiteSpeed Tech/*
35392f7a3SLiteSpeed Tech * lsquic_frab_list.c -- List of buffer for simple reading and writing
45392f7a3SLiteSpeed Tech */
55392f7a3SLiteSpeed Tech
65392f7a3SLiteSpeed Tech#include <stddef.h>
75392f7a3SLiteSpeed Tech#include <stdlib.h>
85392f7a3SLiteSpeed Tech#include <string.h>
95392f7a3SLiteSpeed Tech#include <sys/queue.h>
105392f7a3SLiteSpeed Tech
115392f7a3SLiteSpeed Tech#include "lsquic_frab_list.h"
125392f7a3SLiteSpeed Tech
135392f7a3SLiteSpeed Tech
145392f7a3SLiteSpeed Techstatic void *
155392f7a3SLiteSpeed Techfral_alloc (void *ctx, size_t size)
165392f7a3SLiteSpeed Tech{
175392f7a3SLiteSpeed Tech    return malloc(size);
185392f7a3SLiteSpeed Tech}
195392f7a3SLiteSpeed Tech
205392f7a3SLiteSpeed Tech
215392f7a3SLiteSpeed Techstatic void
225392f7a3SLiteSpeed Techfral_free (void *ctx, void *obj)
235392f7a3SLiteSpeed Tech{
245392f7a3SLiteSpeed Tech    free(obj);
255392f7a3SLiteSpeed Tech}
265392f7a3SLiteSpeed Tech
275392f7a3SLiteSpeed Tech
285392f7a3SLiteSpeed Techvoid
295392f7a3SLiteSpeed Techlsquic_frab_list_init (struct frab_list *fral, unsigned short buf_size,
305392f7a3SLiteSpeed Tech    void * (*alloc)(void *alloc_ctx, size_t size),
315392f7a3SLiteSpeed Tech    void (*free)(void *alloc_ctx, void *obj), void *alloc_ctx)
325392f7a3SLiteSpeed Tech{
335392f7a3SLiteSpeed Tech    TAILQ_INIT(&fral->fl_frabs);
345392f7a3SLiteSpeed Tech    fral->fl_alloc_ctx = alloc_ctx;
355392f7a3SLiteSpeed Tech    fral->fl_alloc     = alloc ? alloc : fral_alloc;
365392f7a3SLiteSpeed Tech    fral->fl_free      = free ? free : fral_free;
375392f7a3SLiteSpeed Tech    fral->fl_buf_size  = buf_size;
385392f7a3SLiteSpeed Tech    fral->fl_size      = 0;
395392f7a3SLiteSpeed Tech}
405392f7a3SLiteSpeed Tech
415392f7a3SLiteSpeed Tech
425392f7a3SLiteSpeed Techvoid
435392f7a3SLiteSpeed Techlsquic_frab_list_cleanup (struct frab_list *fral)
445392f7a3SLiteSpeed Tech{
455392f7a3SLiteSpeed Tech    struct frame_buf *frab, *next;
465392f7a3SLiteSpeed Tech
475392f7a3SLiteSpeed Tech    for (frab = TAILQ_FIRST(&fral->fl_frabs); frab; frab = next)
485392f7a3SLiteSpeed Tech    {
495392f7a3SLiteSpeed Tech        next = TAILQ_NEXT(frab, frab_next);
505392f7a3SLiteSpeed Tech        fral->fl_free(fral->fl_alloc_ctx, frab);
515392f7a3SLiteSpeed Tech    }
525392f7a3SLiteSpeed Tech}
535392f7a3SLiteSpeed Tech
545392f7a3SLiteSpeed Tech
555392f7a3SLiteSpeed Techstatic struct frame_buf *
565392f7a3SLiteSpeed Techfral_get_frab (struct frab_list *fral)
575392f7a3SLiteSpeed Tech{
585392f7a3SLiteSpeed Tech    struct frame_buf *frab;
595392f7a3SLiteSpeed Tech    frab = fral->fl_alloc(fral->fl_alloc_ctx, fral->fl_buf_size);
605392f7a3SLiteSpeed Tech    if (frab)
615392f7a3SLiteSpeed Tech    {
625392f7a3SLiteSpeed Tech        memset(frab, 0, sizeof(*frab));
635392f7a3SLiteSpeed Tech        frab->frab_buf_size = fral->fl_buf_size;
645392f7a3SLiteSpeed Tech    }
655392f7a3SLiteSpeed Tech    return frab;
665392f7a3SLiteSpeed Tech}
675392f7a3SLiteSpeed Tech
685392f7a3SLiteSpeed Tech
695392f7a3SLiteSpeed Techint
705392f7a3SLiteSpeed Techlsquic_frab_list_write (struct frab_list *fral, const void *buf, size_t bufsz)
715392f7a3SLiteSpeed Tech{
725392f7a3SLiteSpeed Tech    const unsigned char *p = buf;
735392f7a3SLiteSpeed Tech    const unsigned char *const end = p + bufsz;
745392f7a3SLiteSpeed Tech    struct frame_buf *frab;
755392f7a3SLiteSpeed Tech    unsigned ntowrite;
765392f7a3SLiteSpeed Tech
775392f7a3SLiteSpeed Tech    while (p < end)
785392f7a3SLiteSpeed Tech    {
795392f7a3SLiteSpeed Tech        frab = TAILQ_LAST(&fral->fl_frabs, frame_buf_head);
805392f7a3SLiteSpeed Tech        if (!(frab && (ntowrite = frab_left_to_write(frab)) > 0))
815392f7a3SLiteSpeed Tech        {
825392f7a3SLiteSpeed Tech            frab = fral_get_frab(fral);
835392f7a3SLiteSpeed Tech            if (!frab)
845392f7a3SLiteSpeed Tech                return -1;
855392f7a3SLiteSpeed Tech            TAILQ_INSERT_TAIL(&fral->fl_frabs, frab, frab_next);
865392f7a3SLiteSpeed Tech            ntowrite = frab_left_to_write(frab);
875392f7a3SLiteSpeed Tech        }
885392f7a3SLiteSpeed Tech        if ((ptrdiff_t) ntowrite > end - p)
895392f7a3SLiteSpeed Tech            ntowrite = end - p;
905392f7a3SLiteSpeed Tech        memcpy(frab_write_to(frab), p, ntowrite);
915392f7a3SLiteSpeed Tech        p += ntowrite;
925392f7a3SLiteSpeed Tech        frab->frab_size += ntowrite;
935392f7a3SLiteSpeed Tech    }
945392f7a3SLiteSpeed Tech
955392f7a3SLiteSpeed Tech    fral->fl_size += bufsz;
965392f7a3SLiteSpeed Tech    return 0;
975392f7a3SLiteSpeed Tech}
985392f7a3SLiteSpeed Tech
995392f7a3SLiteSpeed Tech
1005392f7a3SLiteSpeed Techsize_t
1015392f7a3SLiteSpeed Techlsquic_frab_list_size (void *ctx)
1025392f7a3SLiteSpeed Tech{
1035392f7a3SLiteSpeed Tech    struct frab_list *fral = ctx;
1045392f7a3SLiteSpeed Tech    return fral->fl_size;
1055392f7a3SLiteSpeed Tech}
1065392f7a3SLiteSpeed Tech
1075392f7a3SLiteSpeed Tech
1085392f7a3SLiteSpeed Techsize_t
1095392f7a3SLiteSpeed Techlsquic_frab_list_read (void *ctx, void *buf, size_t bufsz)
1105392f7a3SLiteSpeed Tech{
1115392f7a3SLiteSpeed Tech    struct frab_list *const fral = ctx;
1125392f7a3SLiteSpeed Tech    unsigned char *p = buf;
1135392f7a3SLiteSpeed Tech    unsigned char *const end = p + bufsz;
1145392f7a3SLiteSpeed Tech    struct frame_buf *frab;
1155392f7a3SLiteSpeed Tech    size_t ntocopy;
1165392f7a3SLiteSpeed Tech
1175392f7a3SLiteSpeed Tech    while (p < end && (frab = TAILQ_FIRST(&fral->fl_frabs)))
1185392f7a3SLiteSpeed Tech    {
1195392f7a3SLiteSpeed Tech        ntocopy = end - p;
1205392f7a3SLiteSpeed Tech        if (ntocopy > (size_t) frab_left_to_read(frab))
1215392f7a3SLiteSpeed Tech            ntocopy = frab_left_to_read(frab);
1225392f7a3SLiteSpeed Tech        memcpy(p, frab->frab_buf + frab->frab_off, ntocopy);
1235392f7a3SLiteSpeed Tech        fral->fl_size -= ntocopy;
1245392f7a3SLiteSpeed Tech        frab->frab_off += ntocopy;
1255392f7a3SLiteSpeed Tech        p += ntocopy;
1265392f7a3SLiteSpeed Tech        if (frab->frab_off == frab->frab_size)
1275392f7a3SLiteSpeed Tech        {
1285392f7a3SLiteSpeed Tech            TAILQ_REMOVE(&fral->fl_frabs, frab, frab_next);
1295392f7a3SLiteSpeed Tech            fral->fl_free(fral->fl_alloc_ctx, frab);
1305392f7a3SLiteSpeed Tech        }
1315392f7a3SLiteSpeed Tech    }
1325392f7a3SLiteSpeed Tech
1335392f7a3SLiteSpeed Tech    return p - (unsigned char *) buf;
1345392f7a3SLiteSpeed Tech}
1355392f7a3SLiteSpeed Tech
1365392f7a3SLiteSpeed Tech
1375392f7a3SLiteSpeed Techsize_t
1385392f7a3SLiteSpeed Techlsquic_frab_list_mem_used (const struct frab_list *fral)
1395392f7a3SLiteSpeed Tech{
1405392f7a3SLiteSpeed Tech    struct frame_buf *frab;
1415392f7a3SLiteSpeed Tech    size_t size;
1425392f7a3SLiteSpeed Tech
1435392f7a3SLiteSpeed Tech    size = sizeof(*fral);
1445392f7a3SLiteSpeed Tech    TAILQ_FOREACH(frab, &fral->fl_frabs, frab_next)
1455392f7a3SLiteSpeed Tech        size += fral->fl_buf_size;
1465392f7a3SLiteSpeed Tech
1475392f7a3SLiteSpeed Tech    return size;
1485392f7a3SLiteSpeed Tech}
149