HomeServer/service-src/databuffer.h

160 lines
3.1 KiB
C
Raw Normal View History

2024-11-20 15:41:09 +08:00
#ifndef skynet_databuffer_h
#define skynet_databuffer_h
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MESSAGEPOOL 1023
struct message {
char * buffer;
int size;
struct message * next;
};
struct databuffer {
int header;
int offset;
int size;
struct message * head;
struct message * tail;
};
struct messagepool_list {
struct messagepool_list *next;
struct message pool[MESSAGEPOOL];
};
struct messagepool {
struct messagepool_list * pool;
struct message * freelist;
};
// use memset init struct
static void
messagepool_free(struct messagepool *pool) {
struct messagepool_list *p = pool->pool;
while(p) {
struct messagepool_list *tmp = p;
p=p->next;
skynet_free(tmp);
}
pool->pool = NULL;
pool->freelist = NULL;
}
static inline void
_return_message(struct databuffer *db, struct messagepool *mp) {
struct message *m = db->head;
if (m->next == NULL) {
assert(db->tail == m);
db->head = db->tail = NULL;
} else {
db->head = m->next;
}
skynet_free(m->buffer);
m->buffer = NULL;
m->size = 0;
m->next = mp->freelist;
mp->freelist = m;
}
static void
databuffer_read(struct databuffer *db, struct messagepool *mp, void * buffer, int sz) {
assert(db->size >= sz);
db->size -= sz;
for (;;) {
struct message *current = db->head;
int bsz = current->size - db->offset;
if (bsz > sz) {
memcpy(buffer, current->buffer + db->offset, sz);
db->offset += sz;
return;
}
if (bsz == sz) {
memcpy(buffer, current->buffer + db->offset, sz);
db->offset = 0;
_return_message(db, mp);
return;
} else {
memcpy(buffer, current->buffer + db->offset, bsz);
_return_message(db, mp);
db->offset = 0;
buffer+=bsz;
sz-=bsz;
}
}
}
static void
databuffer_push(struct databuffer *db, struct messagepool *mp, void *data, int sz) {
struct message * m;
if (mp->freelist) {
m = mp->freelist;
mp->freelist = m->next;
} else {
struct messagepool_list * mpl = skynet_malloc(sizeof(*mpl));
struct message * temp = mpl->pool;
int i;
for (i=1;i<MESSAGEPOOL;i++) {
temp[i].buffer = NULL;
temp[i].size = 0;
temp[i].next = &temp[i+1];
}
temp[MESSAGEPOOL-1].next = NULL;
mpl->next = mp->pool;
mp->pool = mpl;
m = &temp[0];
mp->freelist = &temp[1];
}
m->buffer = data;
m->size = sz;
m->next = NULL;
db->size += sz;
if (db->head == NULL) {
assert(db->tail == NULL);
db->head = db->tail = m;
} else {
db->tail->next = m;
db->tail = m;
}
}
static int
databuffer_readheader(struct databuffer *db, struct messagepool *mp, int header_size) {
if (db->header == 0) {
// parser header (2 or 4)
if (db->size < header_size) {
return -1;
}
uint8_t plen[4];
databuffer_read(db,mp,(char *)plen,header_size);
// big-endian
if (header_size == 2) {
db->header = plen[0] << 8 | plen[1];
} else {
db->header = plen[0] << 24 | plen[1] << 16 | plen[2] << 8 | plen[3];
}
}
if (db->size < db->header)
return -1;
return db->header;
}
static inline void
databuffer_reset(struct databuffer *db) {
db->header = 0;
}
static void
databuffer_clear(struct databuffer *db, struct messagepool *mp) {
while (db->head) {
_return_message(db,mp);
}
memset(db, 0, sizeof(*db));
}
#endif