/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ /* * lsquic_frab_list.c -- List of buffer for simple reading and writing */ #include #include #include #include #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; }