static uint32_t socket_recv(socket_handle_t * p_socket_handle, void * p_buf, uint32_t buf_size, uint32_t * buf_len, int flags) { if ((p_socket_handle->flags & O_NONBLOCK) != 0 && (flags & MSG_WAITALL) == 0) { flags |= MSG_DONTWAIT; } uint32_t err_code = NRF_SUCCESS; if (mbuf_empty(&p_socket_handle->mbuf_head) == true) { if ((flags & MSG_DONTWAIT) != 0) { err_code = SOCKET_WOULD_BLOCK; } else { while ((mbuf_empty(&p_socket_handle->mbuf_head) == true) && (err_code == NRF_SUCCESS)) { err_code = sd_app_evt_wait(); } } } if (err_code == NRF_SUCCESS) { *buf_len = mbuf_read(&p_socket_handle->mbuf_head, p_buf, buf_size); p_socket_handle->read_events = 0; } return err_code; }
uint32_t mbuf_read(mbuf_t * p_mbuf, void * p_buf, uint32_t buf_size) { uint32_t nbytes = 0; while (nbytes < buf_size && mbuf_empty(p_mbuf) == false) { mbuf_load(p_mbuf); void * p_current = p_mbuf->p_current; const uint32_t copy_len = p_mbuf->read(p_current, p_mbuf->read_pos, ((uint8_t *)p_buf) + nbytes, buf_size - nbytes); p_mbuf->read_pos += copy_len; nbytes += copy_len; if (mbuf_empty_current(p_mbuf) == true) { p_mbuf->free(p_mbuf->p_current); p_mbuf->p_current = NULL; p_mbuf->read_pos = 0; } } return nbytes; }
static rstatus_t conn_send_queue(struct conn *conn) { struct mbuf *mbuf, *nbuf; /* current and next mbuf */ size_t mlen; /* current mbuf data length */ ssize_t n; for (mbuf = STAILQ_FIRST(&conn->send_queue); mbuf != NULL; mbuf = nbuf) { nbuf = STAILQ_NEXT(mbuf, next); if (mbuf_empty(mbuf)) { continue; } mlen = mbuf_length(mbuf); n = conn_send_buf(conn, mbuf->pos, mlen); if (n < 0) { if (n == NC_EAGAIN) { return NC_OK; } return NC_ERROR; } mbuf->pos += n; if (n < mlen) { ASSERT(mbuf->pos < mbuf->end); return NC_OK; } ASSERT(mbuf->pos == mbuf->last); mbuf_remove(&conn->send_queue, mbuf); mbuf_put(mbuf); } conn->send_ready = 0; return NC_OK; }
/* * Pre-split copy handler invoked when the request is a multi vector - * 'get' or 'gets' request and is about to be split into two requests */ void memcache_pre_splitcopy(struct mbuf *mbuf, void *arg) { struct msg *r = arg; /* request vector */ struct string get = string("get "); /* 'get ' string */ struct string gets = string("gets "); /* 'gets ' string */ ASSERT(r->request); ASSERT(mbuf_empty(mbuf)); switch (r->type) { case MSG_REQ_GET: mbuf_copy(mbuf, get.data, get.len); break; case MSG_REQ_GETS: mbuf_copy(mbuf, gets.data, gets.len); break; default: NOT_REACHED(); } }
/* * copy one response from src to dst * return bytes copied * */ static rstatus_t memcache_copy_bulk(struct msg *dst, struct msg *src) { struct mbuf *mbuf, *nbuf; uint8_t *p; uint32_t len = 0; uint32_t bytes = 0; uint32_t i = 0; for (mbuf = STAILQ_FIRST(&src->mhdr); mbuf && mbuf_empty(mbuf); mbuf = STAILQ_FIRST(&src->mhdr)) { mbuf_remove(&src->mhdr, mbuf); mbuf_put(mbuf); } mbuf = STAILQ_FIRST(&src->mhdr); if (mbuf == NULL) { return NC_OK; /* key not exists */ } p = mbuf->pos; /* get : VALUE key 0 len\r\nval\r\n */ /* gets: VALUE key 0 len cas\r\nval\r\n */ ASSERT(*p == 'V'); for (i = 0; i < 3; i++) { /* eat 'VALUE key 0 ' */ for (; *p != ' ';) { p++; } p++; } len = 0; for (; p < mbuf->last && isdigit(*p); p++) { len = len * 10 + (uint32_t)(*p - '0'); } for (; p < mbuf->last && ('\r' != *p); p++) { /* eat cas for gets */ ; } len += CRLF_LEN * 2; len += (p - mbuf->pos); bytes = len; /* copy len bytes to dst */ for (; mbuf;) { if (mbuf_length(mbuf) <= len) { /* steal this mbuf from src to dst */ nbuf = STAILQ_NEXT(mbuf, next); mbuf_remove(&src->mhdr, mbuf); mbuf_insert(&dst->mhdr, mbuf); len -= mbuf_length(mbuf); mbuf = nbuf; } else { /* split it */ nbuf = mbuf_get(); if (nbuf == NULL) { return NC_ENOMEM; } mbuf_copy(nbuf, mbuf->pos, len); mbuf_insert(&dst->mhdr, nbuf); mbuf->pos += len; break; } } dst->mlen += bytes; src->mlen -= bytes; log_debug(LOG_VVERB, "memcache_copy_bulk copy bytes: %d", bytes); return NC_OK; }