  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (%.DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (%.READY);
    return 0;
  case 0:
    length = be32toh (h->sbuf.sr.structured_reply.length);
    offset = be64toh (h->sbuf.sr.payload.offset_data.offset);

    assert (cmd); /* guaranteed by CHECK */

    assert (cmd->data && cmd->type == NBD_CMD_READ);
    cmd->data_seen = true;

    /* Length of the data following. */
    length -= 8;

    /* Is the data within bounds? */
    if (offset < cmd->offset) {
      SET_NEXT_STATE (%.DEAD);
      set_error (0, "offset of reply is out of bounds, "
                 "offset=%" PRIu64 ", cmd->offset=%" PRIu64 ", "
                 "this is likely to be a bug in the server",
                 offset, cmd->offset);
      return 0;
    }
    /* Now this is the byte offset in the read buffer. */
    offset -= cmd->offset;

    if (offset + length > cmd->count) {
      SET_NEXT_STATE (%.DEAD);
      set_error (0, "offset/length of reply is out of bounds, "
                 "offset=%" PRIu64 ", length=%" PRIu32 ", "
                 "cmd->count=%" PRIu32 ", "
                 "this is likely to be a bug in the server",
                 offset, length, cmd->count);
      return 0;
    }

    /* Set up to receive the data directly to the user buffer. */
    h->rbuf = cmd->data + offset;
    h->rlen = length;
    SET_NEXT_STATE (%RECV_OFFSET_DATA_DATA);
  }
  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (%.DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (%.READY);
    return 0;
  case 0:
    length = be32toh (h->sbuf.sr.structured_reply.length);
    offset = be64toh (h->sbuf.sr.payload.offset_data.offset);

    assert (cmd);  

    assert (cmd->data && cmd->type == NBD_CMD_READ);
    cmd->data_seen = true;

     
    length -= 8;

     
    if (offset < cmd->offset) {
      SET_NEXT_STATE (%.DEAD);
      set_error (0, "offset of reply is out of bounds, "
                 "offset=%" PRIu64 ", cmd->offset=%" PRIu64 ", "
                 "this is likely to be a bug in the server",
                 offset, cmd->offset);
      return 0;
    }
     
    offset -= cmd->offset;

    if (offset + length > cmd->count) {
      SET_NEXT_STATE (%.DEAD);
      set_error (0, "offset/length of reply is out of bounds, "
                 "offset=%" PRIu64 ", length=%" PRIu32 ", "
                 "cmd->count=%" PRIu32 ", "
                 "this is likely to be a bug in the server",
                 offset, length, cmd->count);
      return 0;
    }

     
    h->rbuf = cmd->data + offset;
    h->rlen = length;
    SET_NEXT_STATE (%RECV_OFFSET_DATA_DATA);
  }