/* * fill the mbuf in the msg with the content */ int msg_append_full(struct msg *msg, const uint8_t *pos, uint32_t n) { struct mbuf *mbuf; uint32_t left, len; mbuf_base *mb = msg->mb; const uint8_t *start; start = pos; left = n; while (left > 0) { mbuf = listLastValue(msg->data); if (mbuf == NULL || mbuf_size(mbuf) == 0) { mbuf = mbuf_get(mb); if (mbuf == NULL) { log_error("ERROR: Mbuf get failed: out of memory"); return RMT_ENOMEM; } listAddNodeTail(msg->data, mbuf); } len = MIN(left, mbuf_size(mbuf)); mbuf_copy(mbuf, start, len); left -= len; start += len; msg->mlen += len; } return RMT_OK; }
void mbuf_write_char(struct mbuf *mbuf, char ch) { ASSERT(mbuf_size(mbuf) >= 1); *mbuf->last = ch; mbuf->last += 1; }
static rstatus_t conn_recv_queue(struct conn *conn) { struct mbuf *mbuf; size_t msize; /* current mbuf size */ ssize_t n; mbuf = STAILQ_LAST(&conn->recv_queue, mbuf, next); if (mbuf == NULL || mbuf_full(mbuf)) { mbuf = mbuf_get(); if (mbuf == NULL) { return NC_ENOMEM; } mbuf_insert(&conn->recv_queue, mbuf); } msize = mbuf_size(mbuf); ASSERT(msize > 0); n = conn_recv_buf(conn, mbuf->last, msize); if (n < 0) { if (n == NC_EAGAIN) { return NC_OK; } return NC_ERROR; } ASSERT((mbuf->last + n) <= mbuf->end); mbuf->last += n; return NC_OK; }
int mbuf_steal_data(MBuf *mbuf, uint8 **data_p) { int len = mbuf_size(mbuf); mbuf->no_write = true; mbuf->own_data = false; *data_p = mbuf->data; mbuf->data = mbuf->data_end = mbuf->read_pos = mbuf->buf_end = NULL; return len; }
/* * Copy n bytes from memory area pos to mbuf. * * The memory areas should not overlap and the mbuf should have * enough space for n bytes. */ void mbuf_copy(struct mbuf *mbuf, uint8_t *pos, size_t n) { if (n == 0) { return; } /* mbuf has space for n bytes */ ASSERT(!mbuf_full(mbuf) && n <= mbuf_size(mbuf)); /* no overlapping copy */ ASSERT(pos < mbuf->start || pos >= mbuf->end); dn_memcpy(mbuf->last, pos, n); mbuf->last += n; }
/* * append small(small than a mbuf) content into msg */ int msg_append(struct msg *msg, uint8_t *pos, size_t n) { struct mbuf *mbuf; ASSERT(n <= mbuf_data_size(msg->mb)); mbuf = msg_ensure_mbuf(msg, n); if (mbuf == NULL) { return RMT_ENOMEM; } ASSERT(n <= mbuf_size(mbuf)); mbuf_copy(mbuf, pos, n); msg->mlen += (uint32_t)n; return RMT_OK; }
/* * prepend small(small than a mbuf) content into msg */ int msg_prepend(struct msg *msg, uint8_t *pos, size_t n) { mbuf_base *mb = msg->mb; struct mbuf *mbuf; mbuf = mbuf_get(mb); if (mbuf == NULL) { return RMT_ENOMEM; } ASSERT(n <= mbuf_size(mbuf)); mbuf_copy(mbuf, pos, n); msg->mlen += (uint32_t)n; listAddNodeHead(msg->data, mbuf); return RMT_OK; }
struct msg * memcache_generate_error(struct msg *r, err_t err) { struct mbuf *mbuf; int n; char *protstr = "SERVER_ERROR"; char *errstr = err ? strerror(err) : "unknown"; r->type = MSG_RSP_MC_SERVER_ERROR; mbuf = mbuf_get(); if (mbuf == NULL) { return NULL; } mbuf_insert(&r->mhdr, mbuf); n = nc_scnprintf(mbuf->last, mbuf_size(mbuf), "%s %s"CRLF, protstr, errstr); mbuf->last += n; r->mlen = (uint32_t)n; return r; }
struct mbuf * msg_ensure_mbuf(struct msg *msg, size_t len) { listNode *node; mbuf_base *mb = msg->mb; struct mbuf *mbuf; node = listLast(msg->data); if (node == NULL || mbuf_size(listNodeValue(node)) < len) { mbuf = mbuf_get(mb); if (mbuf == NULL) { return NULL; } listAddNodeTail(msg->data, mbuf); } else { mbuf = listNodeValue(node); } return mbuf; }
/* * prepend small(small than a mbuf) content into msg */ int msg_prepend_format(struct msg *msg, const char *fmt, ...) { mbuf_base *mb = msg->mb; struct mbuf *mbuf; int32_t n; va_list args; mbuf = mbuf_get(mb); if (mbuf == NULL) { return RMT_ENOMEM; } va_start(args, fmt); n = rmt_vscnprintf(mbuf->last, mbuf_size(mbuf), fmt, args); va_end(args); mbuf->last += n; msg->mlen += (uint32_t)n; listAddNodeHead(msg->data, mbuf); return RMT_OK; }
/* * note: we should not call conn_add_out here. * because we may call append many times. */ rstatus_t conn_sendq_append(struct conn *conn, char *pos, size_t n) { struct mbuf *mbuf; size_t bytes = 0; size_t len; while (bytes < n) { mbuf = STAILQ_LAST(&conn->send_queue, mbuf, next); if ((mbuf == NULL) || mbuf_full(mbuf)) { mbuf = mbuf_get(); if (mbuf == NULL) { return NC_ENOMEM; } mbuf_insert(&conn->send_queue, mbuf); } len = MIN(mbuf_size(mbuf), n - bytes); mbuf_copy(mbuf, (uint8_t *)pos + bytes, len); bytes += len; } return NC_OK; }
void mbuf_write_string(struct mbuf *mbuf, struct string *s) { ASSERT(s->len < mbuf_size(mbuf)); mbuf_copy(mbuf, s->data, s->len); }