static LogProtoStatus
log_proto_framed_server_fetch_data(LogProtoFramedServer *self, gboolean *may_read)
{
    gint rc;

    if (self->buffer_pos == self->buffer_end)
        self->buffer_pos = self->buffer_end = 0;

    if (self->buffer_size == self->buffer_end)
    {
        /* no more space in the buffer, we can't fetch further data. Move the
         * things we already have to the beginning of the buffer to make
         * space. */

        memmove(self->buffer, &self->buffer[self->buffer_pos], self->buffer_end - self->buffer_pos);
        self->buffer_end = self->buffer_end - self->buffer_pos;
        self->buffer_pos = 0;
    }

    if (!(*may_read))
        return LPS_SUCCESS;

    rc = log_transport_read(self->super.transport, &self->buffer[self->buffer_end], self->buffer_size - self->buffer_end, NULL);

    if (rc < 0)
    {
        if (errno != EAGAIN)
        {
            msg_error("Error reading RFC5428 style framed data",
                      evt_tag_int("fd", self->super.transport->fd),
                      evt_tag_errno("error", errno),
                      NULL);
            return LPS_ERROR;
        }
        else
        {
            /* we need more data to parse this message but the data is not available yet */
            self->half_message_in_buffer = TRUE;
        }
    }
    else if (rc == 0)
    {
        msg_verbose("EOF occurred while reading",
                    evt_tag_int(EVT_TAG_FD, self->super.transport->fd),
                    NULL);
        return LPS_EOF;
    }
    else
    {
        self->buffer_end += rc;
    }
    return LPS_SUCCESS;

}
static gint
log_proto_record_server_read_data(LogProtoBufferedServer *s, guchar *buf, gsize len, LogTransportAuxData *aux)
{
  LogProtoRecordServer *self = (LogProtoRecordServer *) s;
  gint rc;

  /* assert that we have enough space in the buffer to read record_size bytes */
  g_assert(len >= self->record_size);
  len = self->record_size;
  rc = log_transport_read(self->super.super.transport, buf, len, aux);
  if (rc > 0 && rc != self->record_size)
    {
      msg_error("Record size was set, and couldn't read enough bytes",
                evt_tag_int(EVT_TAG_FD, self->super.super.transport->fd),
                evt_tag_int("record_size", self->record_size),
                evt_tag_int("read", rc));
      errno = EIO;
      return -1;
    }
  return rc;
}
static gint
log_proto_buffered_server_read_data_method(LogProtoBufferedServer *self, guchar *buf, gsize len, LogTransportAuxData *aux)
{
  return log_transport_read(self->super.transport, buf, len, aux);
}
static void
log_proto_buffered_server_apply_state(LogProtoBufferedServer *self, PersistEntryHandle handle, const gchar *persist_name)
{
  struct stat st;
  gint64 ofs = 0;
  LogProtoBufferedServerState *state;
  gint fd;

  fd = self->super.transport->fd;
  self->persist_handle = handle;

  if (fstat(fd, &st) < 0)
    return;

  state = log_proto_buffered_server_get_state(self);

  if (!self->buffer)
    {
      self->buffer = g_malloc(state->buffer_size);
    }
  state->pending_buffer_end = 0;

  if (state->file_inode &&
      state->file_inode == st.st_ino &&
      state->file_size <= st.st_size &&
      state->raw_stream_pos <= st.st_size)
    {
      ofs = state->raw_stream_pos;

      lseek(fd, ofs, SEEK_SET);
    }
  else
    {
      if (state->file_inode)
        {
          /* the stored state does not match the current file */
          msg_notice("The current log file has a mismatching size/inode information, restarting from the beginning",
                     evt_tag_str("state", persist_name),
                     evt_tag_int("stored_inode", state->file_inode),
                     evt_tag_int("cur_file_inode", st.st_ino),
                     evt_tag_int("stored_size", state->file_size),
                     evt_tag_int("cur_file_size", st.st_size),
                     evt_tag_int("raw_stream_pos", state->raw_stream_pos));
        }
      goto error;
    }
  if (state->raw_buffer_size)
    {
      gssize rc;
      guchar *raw_buffer;

      if (!self->super.options->encoding)
        {
          /* no conversion, we read directly into our buffer */
          if (state->raw_buffer_size > state->buffer_size)
            {
              msg_notice("Invalid LogProtoBufferedServerState.raw_buffer_size, larger than buffer_size and no encoding is set, restarting from the beginning",
                         evt_tag_str("state", persist_name),
                         evt_tag_int("raw_buffer_size", state->raw_buffer_size),
                         evt_tag_int("buffer_size", state->buffer_size),
                         evt_tag_int("init_buffer_size", self->super.options->init_buffer_size));
              goto error;
            }
          raw_buffer = self->buffer;
        }
      else
        {
          if (state->raw_buffer_size > self->super.options->max_buffer_size)
            {
              msg_notice("Invalid LogProtoBufferedServerState.raw_buffer_size, larger than max_buffer_size, restarting from the beginning",
                         evt_tag_str("state", persist_name),
                         evt_tag_int("raw_buffer_size", state->raw_buffer_size),
                         evt_tag_int("init_buffer_size", self->super.options->init_buffer_size),
                         evt_tag_int("max_buffer_size", self->super.options->max_buffer_size));
              goto error;
            }
          raw_buffer = g_alloca(state->raw_buffer_size);
        }

      rc = log_transport_read(self->super.transport, raw_buffer, state->raw_buffer_size, NULL);
      if (rc != state->raw_buffer_size)
        {
          msg_notice("Error re-reading buffer contents of the file to be continued, restarting from the beginning",
                     evt_tag_str("state", persist_name));
          goto error;
        }

      state->pending_buffer_end = 0;
      if (self->super.options->encoding)
        {
          if (!log_proto_buffered_server_convert_from_raw(self, raw_buffer, rc))
            {
              msg_notice("Error re-converting buffer contents of the file to be continued, restarting from the beginning",
                         evt_tag_str("state", persist_name));
              goto error;
            }
        }
      else
        {
          state->pending_buffer_end += rc;
        }

      if (state->buffer_pos > state->pending_buffer_end)
        {
          msg_notice("Converted buffer contents is smaller than the current buffer position, starting from the beginning of the buffer, some lines may be duplicated",
                     evt_tag_str("state", persist_name));
          state->buffer_pos = state->pending_buffer_pos = 0;
        }
    }
  else
    {
      /* although we do have buffer position information, but the
       * complete contents of the buffer is already processed, instead
       * of reading and then dropping it, position the file after the
       * indicated block */

      state->raw_stream_pos += state->raw_buffer_size;
      ofs = state->raw_stream_pos;
      state->raw_buffer_size = 0;
      state->buffer_pos = state->pending_buffer_end = 0;

      lseek(fd, state->raw_stream_pos, SEEK_SET);
    }
  goto exit;

 error:
  ofs = 0;
  state->buffer_pos = 0;
  state->pending_buffer_end = 0;
  state->__deprecated_buffer_cached_eol = 0;
  state->raw_stream_pos = 0;
  state->raw_buffer_size = 0;
  state->raw_buffer_leftover_size = 0;
  lseek(fd, 0, SEEK_SET);

 exit:
  state->file_inode = st.st_ino;
  state->file_size = st.st_size;
  state->raw_stream_pos = ofs;
  state->pending_buffer_pos = state->buffer_pos;
  state->pending_raw_stream_pos = state->raw_stream_pos;
  state->pending_raw_buffer_size = state->raw_buffer_size;
  state->__deprecated_buffer_cached_eol = 0;

  state = NULL;
  log_proto_buffered_server_put_state(self);
}
static gint
log_proto_buffered_server_read_data_method(LogProtoBufferedServer *self, guchar *buf, gsize len, GSockAddr **sa)
{
  return log_transport_read(self->super.transport, buf, len, sa);
}