From c088c3be069e991e2d8a3acfdcbb9af278c6d5e5 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 10 May 2010 15:01:25 -0700 Subject: [PATCH] vconn-stream: Refactor vconn_stream_recv() for readability. Backward "goto" statement are rarely a good idea, so this rewrites that code for readability. --- lib/vconn-stream.c | 86 ++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/lib/vconn-stream.c b/lib/vconn-stream.c index 034d1d5c..0a721d97 100644 --- a/lib/vconn-stream.c +++ b/lib/vconn-stream.c @@ -116,63 +116,67 @@ vconn_stream_connect(struct vconn *vconn) } static int -vconn_stream_recv(struct vconn *vconn, struct ofpbuf **bufferp) +vconn_stream_recv__(struct vconn_stream *s, int rx_len) { - struct vconn_stream *s = vconn_stream_cast(vconn); - struct ofpbuf *rx; - size_t want_bytes; - ssize_t retval; + struct ofpbuf *rx = s->rxbuf; + int want_bytes, retval; - if (s->rxbuf == NULL) { - s->rxbuf = ofpbuf_new(1564); - } - rx = s->rxbuf; - -again: - if (sizeof(struct ofp_header) > rx->size) { - want_bytes = sizeof(struct ofp_header) - rx->size; - } else { - struct ofp_header *oh = rx->data; - size_t length = ntohs(oh->length); - if (length < sizeof(struct ofp_header)) { - VLOG_ERR_RL(&rl, "received too-short ofp_header (%zu bytes)", - length); - return EPROTO; - } - want_bytes = length - rx->size; - if (!want_bytes) { - *bufferp = rx; - s->rxbuf = NULL; - return 0; - } - } + want_bytes = rx_len - rx->size; ofpbuf_prealloc_tailroom(rx, want_bytes); - retval = stream_recv(s->stream, ofpbuf_tail(rx), want_bytes); if (retval > 0) { rx->size += retval; - if (retval == want_bytes) { - if (rx->size > sizeof(struct ofp_header)) { - *bufferp = rx; - s->rxbuf = NULL; - return 0; - } else { - goto again; - } - } - return EAGAIN; + return retval == want_bytes ? 0 : EAGAIN; } else if (retval == 0) { if (rx->size) { VLOG_ERR_RL(&rl, "connection dropped mid-packet"); return EPROTO; - } else { - return EOF; } + return EOF; } else { return -retval; } } +static int +vconn_stream_recv(struct vconn *vconn, struct ofpbuf **bufferp) +{ + struct vconn_stream *s = vconn_stream_cast(vconn); + const struct ofp_header *oh; + int rx_len; + + /* Allocate new receive buffer if we don't have one. */ + if (s->rxbuf == NULL) { + s->rxbuf = ofpbuf_new(1564); + } + + /* Read ofp_header. */ + if (s->rxbuf->size < sizeof(struct ofp_header)) { + int retval = vconn_stream_recv__(s, sizeof(struct ofp_header)); + if (retval) { + return retval; + } + } + + /* Read payload. */ + oh = s->rxbuf->data; + rx_len = ntohs(oh->length); + if (rx_len < sizeof(struct ofp_header)) { + VLOG_ERR_RL(&rl, "received too-short ofp_header (%zu bytes)", + rx_len); + return EPROTO; + } else if (s->rxbuf->size < rx_len) { + int retval = vconn_stream_recv__(s, rx_len); + if (retval) { + return retval; + } + } + + *bufferp = s->rxbuf; + s->rxbuf = NULL; + return 0; +} + static void vconn_stream_clear_txbuf(struct vconn_stream *s) { -- 2.30.2