blob: cdd456df92fb65472bc1ddf30333398b27febdcf [file] [log] [blame]
Darin Petkov78f63262012-03-26 01:30:24 +02001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewartf0aae102011-10-19 12:11:44 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/glib_io_ready_handler.h"
6
Julius Werner22e244a2012-11-13 18:25:19 -08007#include <errno.h>
Paul Stewartf0aae102011-10-19 12:11:44 -07008#include <glib.h>
9#include <stdio.h>
Julius Werner22e244a2012-11-13 18:25:19 -080010#include <string.h>
Paul Stewartf0aae102011-10-19 12:11:44 -070011#include <sys/socket.h>
12
Christopher Wileyb691efd2012-08-09 13:51:51 -070013#include "shill/logging.h"
14
Eric Shienbrood3e20a232012-02-16 11:35:56 -050015using base::Callback;
16
Paul Stewartf0aae102011-10-19 12:11:44 -070017namespace shill {
18
19static gboolean DispatchIOHandler(GIOChannel *chan,
20 GIOCondition cond,
21 gpointer data) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050022 GlibIOReadyHandler *handler = reinterpret_cast<GlibIOReadyHandler *>(data);
Julius Werner22e244a2012-11-13 18:25:19 -080023 gint fd = g_io_channel_unix_get_fd(chan);
Paul Stewartf0aae102011-10-19 12:11:44 -070024
25 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
Julius Werner033e2fa2012-11-15 21:37:19 -080026 LOG(WARNING) << "Unexpected GLib error condition " << cond << " on poll("
Julius Werner22e244a2012-11-13 18:25:19 -080027 << fd << "): " << strerror(errno);
28
29 handler->callback().Run(fd);
Paul Stewartf0aae102011-10-19 12:11:44 -070030
Paul Stewartf0aae102011-10-19 12:11:44 -070031 return TRUE;
32}
33
34GlibIOReadyHandler::GlibIOReadyHandler(int fd,
35 IOHandler::ReadyMode mode,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050036 const Callback<void(int)> &callback)
Paul Stewartf0aae102011-10-19 12:11:44 -070037 : channel_(NULL),
38 callback_(callback),
39 source_id_(G_MAXUINT) {
40 if (mode == kModeInput) {
41 condition_ = static_cast<GIOCondition>(
42 G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR);
43 } else if (mode == kModeOutput) {
44 condition_ = static_cast<GIOCondition>(
45 G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR);
46 } else {
47 NOTREACHED() << "Unknown IO ready mode: " << mode;
48 }
49
50 channel_ = g_io_channel_unix_new(fd);
51 g_io_channel_set_close_on_unref(channel_, FALSE);
52}
53
54GlibIOReadyHandler::~GlibIOReadyHandler() {
Darin Petkov78f63262012-03-26 01:30:24 +020055 GlibIOReadyHandler::Stop();
Paul Stewartc2350ee2011-10-19 12:28:40 -070056 // NB: We don't shut down the channel since we don't own it
Paul Stewartf0aae102011-10-19 12:11:44 -070057 g_io_channel_unref(channel_);
58}
59
60void GlibIOReadyHandler::Start() {
61 if (source_id_ == G_MAXUINT) {
Eric Shienbrood3e20a232012-02-16 11:35:56 -050062 source_id_ = g_io_add_watch(channel_, condition_, DispatchIOHandler, this);
Paul Stewartf0aae102011-10-19 12:11:44 -070063 }
64}
65
66void GlibIOReadyHandler::Stop() {
67 if (source_id_ != G_MAXUINT) {
68 g_source_remove(source_id_);
69 source_id_ = G_MAXUINT;
70 }
71}
72
73} // namespace shill