uint32_t sbuf_get(struct shared_buf *sbuf, uint8_t *data) { const void *from; uint32_t ele_size; stac(); if (sbuf_is_empty(sbuf)) { clac(); /* no data available */ return 0; } from = (void *)sbuf + SBUF_HEAD_SIZE + sbuf->head; (void)memcpy_s((void *)data, sbuf->ele_size, from, sbuf->ele_size); sbuf->head = sbuf_next_ptr(sbuf->head, sbuf->ele_size, sbuf->size); ele_size = sbuf->ele_size; clac(); return ele_size; }
/* * Main recv-parse-send-repeat loop. * * Reason for skip_recv is to avoid extra recv(). The problem with it * is EOF from socket. Currently that means that the pending data is * dropped. Fortunately server sockets are not paused and dropping * data from client is no problem. So only place where skip_recv is * important is sbuf_send_cb(). */ static void sbuf_main_loop(SBuf *sbuf, bool skip_recv) { unsigned free, ok; int loopcnt = 0; /* sbuf was closed before in this event loop */ if (!sbuf->sock) return; /* reading should be disabled when waiting */ Assert(sbuf->wait_type == W_RECV); AssertSanity(sbuf); if (!allocate_iobuf(sbuf)) return; /* avoid recv() if asked */ if (skip_recv) goto skip_recv; try_more: /* make room in buffer */ sbuf_try_resync(sbuf, false); /* avoid spending too much time on single socket */ if (cf_sbuf_loopcnt > 0 && loopcnt >= cf_sbuf_loopcnt) { log_debug("loopcnt full"); /* * sbuf_process_pending() avoids some data if buffer is full, * but as we exit processing loop here, we need to retry * after resync to process all data. (result is ignored) */ ok = sbuf_process_pending(sbuf); return; } loopcnt++; /* * here used to be if (free > SBUF_SMALL_PKT) check * but with skip_recv switch its should not be needed anymore. */ free = iobuf_amount_recv(sbuf->io); if (free > 0) { /* * When suspending, try to hit packet boundary ASAP. */ if (cf_pause_mode == P_SUSPEND && sbuf->pkt_remain > 0 && sbuf->pkt_remain < free) { free = sbuf->pkt_remain; } /* now fetch the data */ ok = sbuf_actual_recv(sbuf, free); if (!ok) return; } skip_recv: /* now handle it */ ok = sbuf_process_pending(sbuf); if (!ok) return; /* if the buffer is full, there can be more data available */ if (iobuf_amount_recv(sbuf->io) <= 0) goto try_more; /* clean buffer */ sbuf_try_resync(sbuf, true); /* notify proto that all is sent */ if (sbuf_is_empty(sbuf)) sbuf_call_proto(sbuf, SBUF_EV_FLUSH); }