lsquic_frab_list.c revision 06b2a236
1/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_frab_list.c -- List of buffer for simple reading and writing 4 */ 5 6#include <stddef.h> 7#include <stdlib.h> 8#include <string.h> 9#include <sys/queue.h> 10 11#include "lsquic_frab_list.h" 12 13 14static void * 15fral_alloc (void *ctx, size_t size) 16{ 17 return malloc(size); 18} 19 20 21static void 22fral_free (void *ctx, void *obj) 23{ 24 free(obj); 25} 26 27 28void 29lsquic_frab_list_init (struct frab_list *fral, unsigned short buf_size, 30 void * (*alloc)(void *alloc_ctx, size_t size), 31 void (*free)(void *alloc_ctx, void *obj), void *alloc_ctx) 32{ 33 TAILQ_INIT(&fral->fl_frabs); 34 fral->fl_alloc_ctx = alloc_ctx; 35 fral->fl_alloc = alloc ? alloc : fral_alloc; 36 fral->fl_free = free ? free : fral_free; 37 fral->fl_buf_size = buf_size; 38 fral->fl_size = 0; 39} 40 41 42void 43lsquic_frab_list_cleanup (struct frab_list *fral) 44{ 45 struct frame_buf *frab, *next; 46 47 for (frab = TAILQ_FIRST(&fral->fl_frabs); frab; frab = next) 48 { 49 next = TAILQ_NEXT(frab, frab_next); 50 fral->fl_free(fral->fl_alloc_ctx, frab); 51 } 52} 53 54 55static struct frame_buf * 56fral_get_frab (struct frab_list *fral) 57{ 58 struct frame_buf *frab; 59 frab = fral->fl_alloc(fral->fl_alloc_ctx, fral->fl_buf_size); 60 if (frab) 61 { 62 memset(frab, 0, sizeof(*frab)); 63 frab->frab_buf_size = fral->fl_buf_size; 64 } 65 return frab; 66} 67 68 69int 70lsquic_frab_list_write (struct frab_list *fral, const void *buf, size_t bufsz) 71{ 72 const unsigned char *p = buf; 73 const unsigned char *const end = p + bufsz; 74 struct frame_buf *frab; 75 unsigned ntowrite; 76 77 while (p < end) 78 { 79 frab = TAILQ_LAST(&fral->fl_frabs, frame_buf_head); 80 if (!(frab && (ntowrite = frab_left_to_write(frab)) > 0)) 81 { 82 frab = fral_get_frab(fral); 83 if (!frab) 84 return -1; 85 TAILQ_INSERT_TAIL(&fral->fl_frabs, frab, frab_next); 86 ntowrite = frab_left_to_write(frab); 87 } 88 if ((ptrdiff_t) ntowrite > end - p) 89 ntowrite = end - p; 90 memcpy(frab_write_to(frab), p, ntowrite); 91 p += ntowrite; 92 frab->frab_size += ntowrite; 93 } 94 95 fral->fl_size += bufsz; 96 return 0; 97} 98 99 100size_t 101lsquic_frab_list_size (void *ctx) 102{ 103 struct frab_list *fral = ctx; 104 return fral->fl_size; 105} 106 107 108size_t 109lsquic_frab_list_read (void *ctx, void *buf, size_t bufsz) 110{ 111 struct frab_list *const fral = ctx; 112 unsigned char *p = buf; 113 unsigned char *const end = p + bufsz; 114 struct frame_buf *frab; 115 size_t ntocopy; 116 117 while (p < end && (frab = TAILQ_FIRST(&fral->fl_frabs))) 118 { 119 ntocopy = end - p; 120 if (ntocopy > (size_t) frab_left_to_read(frab)) 121 ntocopy = frab_left_to_read(frab); 122 memcpy(p, frab->frab_buf + frab->frab_off, ntocopy); 123 fral->fl_size -= ntocopy; 124 frab->frab_off += ntocopy; 125 p += ntocopy; 126 if (frab->frab_off == frab->frab_size) 127 { 128 TAILQ_REMOVE(&fral->fl_frabs, frab, frab_next); 129 fral->fl_free(fral->fl_alloc_ctx, frab); 130 } 131 } 132 133 return p - (unsigned char *) buf; 134} 135 136 137size_t 138lsquic_frab_list_mem_used (const struct frab_list *fral) 139{ 140 struct frame_buf *frab; 141 size_t size; 142 143 size = sizeof(*fral); 144 TAILQ_FOREACH(frab, &fral->fl_frabs, frab_next) 145 size += fral->fl_buf_size; 146 147 return size; 148} 149