// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shill/glib_io_input_handler.h"

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>

#include <string>
#include <vector>

#include <base/string_util.h>
#include <base/stringprintf.h>

#include "shill/error.h"
#include "shill/logging.h"

using base::Callback;
using base::StringPrintf;
using std::string;
using std::vector;

namespace shill {

static gboolean DispatchIOHandler(GIOChannel *chan,
                                  GIOCondition cond,
                                  gpointer data) {
  GlibIOInputHandler *handler = reinterpret_cast<GlibIOInputHandler *>(data);
  unsigned char buf[4096];
  gsize len = 0;
  gint fd = g_io_channel_unix_get_fd(chan);
  GError *err = 0;
  vector<string> error_conditions;

  if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
    string condition = base::StringPrintf(
        "Unexpected GLib error condition %#x on poll(%d): %s",
        cond, fd, strerror(errno));
    LOG(WARNING) << condition;
    error_conditions.push_back(condition);
  }

  GIOStatus status = g_io_channel_read_chars(
      chan, reinterpret_cast<gchar *>(buf), sizeof(buf), &len, &err);
  if (err) {
    string condition = base::StringPrintf(
        "GLib error code %d/%d (%s) on read(%d): %s",
        err->domain, err->code, err->message, fd, strerror(errno));
    LOG(WARNING) << condition;
    error_conditions.push_back(condition);
    g_error_free(err);
  }
  if (status == G_IO_STATUS_AGAIN)
    return TRUE;
  if (status == G_IO_STATUS_ERROR) {
    string condition = base::StringPrintf(
        "Unexpected GLib return status: %d", status);
    LOG(ERROR) << condition;
    error_conditions.push_back(condition);
    Error error(Error::kOperationFailed, JoinString(error_conditions, ';'));
    handler->error_callback().Run(error);
    return FALSE;
  }

  InputData input_data(buf, len);
  handler->input_callback().Run(&input_data);

  if (status == G_IO_STATUS_EOF) {
    LOG(INFO) << "InputHandler on fd " << fd << " closing due to EOF.";
    CHECK(len == 0);
    return FALSE;
  }
  return TRUE;
}

GlibIOInputHandler::GlibIOInputHandler(
    int fd,
    const InputCallback &input_callback,
    const ErrorCallback &error_callback)
    : channel_(g_io_channel_unix_new(fd)),
      input_callback_(input_callback),
      error_callback_(error_callback),
      source_id_(G_MAXUINT) {
  // To avoid blocking in g_io_channel_read_chars() due to its internal buffer,
  // set the channel to unbuffered, which in turns requires encoding to be NULL.
  // This assumes raw binary data are read from |fd| via the channel.
  CHECK_EQ(G_IO_STATUS_NORMAL, g_io_channel_set_encoding(channel_, NULL, NULL));
  g_io_channel_set_buffered(channel_, FALSE);
  g_io_channel_set_close_on_unref(channel_, TRUE);
}

GlibIOInputHandler::~GlibIOInputHandler() {
  g_source_remove(source_id_);
  g_io_channel_shutdown(channel_, TRUE, NULL);
  g_io_channel_unref(channel_);
}

void GlibIOInputHandler::Start() {
  if (source_id_ == G_MAXUINT) {
    source_id_ = g_io_add_watch(channel_,
                                static_cast<GIOCondition>(
                                    G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR),
                                DispatchIOHandler, this);
  }
}

void GlibIOInputHandler::Stop() {
  if (source_id_ != G_MAXUINT) {
    g_source_remove(source_id_);
    source_id_ = G_MAXUINT;
  }
}

}  // namespace shill
