Add uc_mbuf_extend_headroom function, for growing an mbuf
This commit is contained in:
+12
-2
@@ -12,8 +12,8 @@
|
|||||||
enum UC_MBUF_FLAGS {
|
enum UC_MBUF_FLAGS {
|
||||||
UC_MBUF_FL_MALLOC = 0x0001, //MBuf and MBuf->bufstart are seperatly malloc'd
|
UC_MBUF_FL_MALLOC = 0x0001, //MBuf and MBuf->bufstart are seperatly malloc'd
|
||||||
UC_MBUF_FL_MALLOC_BUF = 0x0001, //MBuf is not malloc'd. MBuf->bufstart is malloc'd
|
UC_MBUF_FL_MALLOC_BUF = 0x0001, //MBuf is not malloc'd. MBuf->bufstart is malloc'd
|
||||||
UC_MBUF_FL_MALLOC_INLINE = 0x0002, //MBuf is one big malloc. Can't be resized
|
UC_MBUF_FL_MALLOC_INLINE = 0x0002, //MBuf is one big malloc. Can't be extended
|
||||||
UC_MBUF_FL_STATIC = 0x0004, //MBuf and MBuf->bustart is user controlled. Can't be resized
|
UC_MBUF_FL_STATIC = 0x0004, //MBuf and MBuf->bustart is user controlled. Can't be extended
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MBuf {
|
struct MBuf {
|
||||||
@@ -187,6 +187,16 @@ uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size);
|
|||||||
**/
|
**/
|
||||||
uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size);
|
uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size);
|
||||||
|
|
||||||
|
/** Add more tailroom to an mbuf.
|
||||||
|
* Can only be done with mbufs with either
|
||||||
|
* UC_MBUF_FL_MALLOC or UC_MBUF_FL_MALLOC_BUF.
|
||||||
|
*
|
||||||
|
* @param len additional tailroom to add to mbuf
|
||||||
|
* @return 0 on success, otherwise failure
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int uc_mbuf_extend_tailroom(struct MBuf *mbuf, uint32_t len);
|
||||||
|
|
||||||
/** Get a pointer to the data of the buffer
|
/** Get a pointer to the data of the buffer
|
||||||
*
|
*
|
||||||
* @return pointer to the start of the data (head)
|
* @return pointer to the start of the data (head)
|
||||||
|
|||||||
+79
@@ -1,4 +1,5 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ucore/mbuf.h"
|
#include "ucore/mbuf.h"
|
||||||
|
|
||||||
@@ -119,3 +120,81 @@ struct MBuf *uc_mbuf_copy_data(struct MBuf *mbuf)
|
|||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uc_mbuf_extend_tailroom(struct MBuf *mbuf, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t tot_len;
|
||||||
|
uint32_t headroom_len;
|
||||||
|
uint32_t data_len;
|
||||||
|
uint32_t tailroom_len;
|
||||||
|
uint8_t *new_data;
|
||||||
|
uint32_t p1_off;
|
||||||
|
uint32_t p2_off;
|
||||||
|
uint32_t p3_off;
|
||||||
|
uint32_t p4_off;
|
||||||
|
|
||||||
|
if ((mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_BUF)) == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
headroom_len = uc_mbuf_headroom(mbuf);
|
||||||
|
data_len = uc_mbuf_len(mbuf);
|
||||||
|
tailroom_len = uc_mbuf_tailroom(mbuf);
|
||||||
|
tot_len = headroom_len +
|
||||||
|
data_len +
|
||||||
|
tailroom_len;
|
||||||
|
|
||||||
|
if (tot_len + len < tot_len) {
|
||||||
|
//overflowed
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
tot_len += len;
|
||||||
|
|
||||||
|
//need to re-adjust p1-p4 after the realloc
|
||||||
|
//This assumes the user controlled p1-p4 really are
|
||||||
|
//set to point into the data, but we document they have
|
||||||
|
//to be.
|
||||||
|
if (mbuf->p1 != NULL) {
|
||||||
|
p1_off = (uint32_t)(mbuf->p1 - mbuf->bufstart);
|
||||||
|
}
|
||||||
|
if (mbuf->p2 != NULL) {
|
||||||
|
p2_off = (uint32_t)(mbuf->p2 - mbuf->bufstart);
|
||||||
|
}
|
||||||
|
if (mbuf->p3 != NULL) {
|
||||||
|
p3_off = (uint32_t)(mbuf->p3 - mbuf->bufstart);
|
||||||
|
}
|
||||||
|
if (mbuf->p4 != NULL) {
|
||||||
|
p4_off = (uint32_t)(mbuf->p4 - mbuf->bufstart);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(tot_len >= mbuf->allocated);
|
||||||
|
|
||||||
|
new_data = realloc(mbuf->bufstart, tot_len);
|
||||||
|
if (new_data == NULL) {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbuf->allocated = tot_len;
|
||||||
|
mbuf->bufstart = new_data;
|
||||||
|
mbuf->head = mbuf->bufstart + headroom_len;
|
||||||
|
mbuf->tail = mbuf->bufstart + headroom_len + data_len;
|
||||||
|
|
||||||
|
assert(uc_mbuf_len(mbuf) == data_len);
|
||||||
|
assert(uc_mbuf_tailroom(mbuf) >= tailroom_len);
|
||||||
|
|
||||||
|
if (mbuf->p1 != NULL) {
|
||||||
|
mbuf->p1 = mbuf->bufstart + p1_off;
|
||||||
|
}
|
||||||
|
if (mbuf->p2 != NULL) {
|
||||||
|
mbuf->p2 = mbuf->bufstart + p2_off;
|
||||||
|
}
|
||||||
|
if (mbuf->p3 != NULL) {
|
||||||
|
mbuf->p3 = mbuf->bufstart + p3_off;
|
||||||
|
}
|
||||||
|
if (mbuf->p4 != NULL) {
|
||||||
|
mbuf->p4 = mbuf->bufstart + p4_off;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <ucore/mbuf.h>
|
#include <ucore/mbuf.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -240,6 +241,58 @@ START_TEST (test_mbuf_static)
|
|||||||
|
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_mbuf_extend_tailroom)
|
||||||
|
struct MBuf *mbuf;
|
||||||
|
uint8_t *data;
|
||||||
|
void *filler;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
mbuf = uc_mbuf_new_hr(5,2);
|
||||||
|
fail_if(mbuf == NULL);
|
||||||
|
|
||||||
|
data = uc_mbuf_put(mbuf, 5);
|
||||||
|
fail_if(data == NULL);
|
||||||
|
memcpy((char*)data, "hello", 5);
|
||||||
|
mbuf->p1 = mbuf->tail;
|
||||||
|
|
||||||
|
data = uc_mbuf_put(mbuf, 6);
|
||||||
|
fail_if(data != NULL);
|
||||||
|
|
||||||
|
filler = malloc(5); //just a hope, so realloc also moves..
|
||||||
|
rc = uc_mbuf_extend_tailroom(mbuf, 1024);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
ck_assert_int_eq(uc_mbuf_tailroom(mbuf), 1024);
|
||||||
|
ck_assert_int_eq(uc_mbuf_headroom(mbuf), 2);
|
||||||
|
ck_assert_int_eq(uc_mbuf_len(mbuf), 5);
|
||||||
|
|
||||||
|
//should work now
|
||||||
|
data = uc_mbuf_put(mbuf, 6);
|
||||||
|
fail_if(data == NULL);
|
||||||
|
strcpy((char*)data, "world");
|
||||||
|
ck_assert_str_eq((const char*)mbuf->head, "helloworld");
|
||||||
|
ck_assert_str_eq((const char*)mbuf->p1, "world");
|
||||||
|
|
||||||
|
uc_mbuf_free(mbuf);
|
||||||
|
free(filler);
|
||||||
|
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (test_mbuf_extend_tailroom_wrong_type)
|
||||||
|
struct MBuf *mbuf;
|
||||||
|
uint8_t *data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
mbuf = uc_mbuf_new_inline(10);
|
||||||
|
fail_if(mbuf == NULL);
|
||||||
|
|
||||||
|
rc = uc_mbuf_extend_tailroom(mbuf, 1024);
|
||||||
|
ck_assert_int_ne(rc, 0);
|
||||||
|
|
||||||
|
fail_if(data == NULL);
|
||||||
|
|
||||||
|
uc_mbuf_free(mbuf);
|
||||||
|
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
Suite *mbuf_suite(void)
|
Suite *mbuf_suite(void)
|
||||||
@@ -258,6 +311,8 @@ Suite *mbuf_suite(void)
|
|||||||
tcase_add_test(tc, test_mbuf_copy);
|
tcase_add_test(tc, test_mbuf_copy);
|
||||||
tcase_add_test(tc, test_mbuf_zero);
|
tcase_add_test(tc, test_mbuf_zero);
|
||||||
tcase_add_test(tc, test_mbuf_static);
|
tcase_add_test(tc, test_mbuf_static);
|
||||||
|
tcase_add_test(tc, test_mbuf_extend_tailroom);
|
||||||
|
tcase_add_test(tc, test_mbuf_extend_tailroom_wrong_type);
|
||||||
|
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user