dhcp client: add RPC implementation part 1

This adds DBus rpc implementation for manager and service classes.
This follows the same rpc design convention as apmanager and shill.
While there, this also fixes a few typoes in comments.

Bug: 2564205
TEST=compile, and test using python scripts

Change-Id: I1157bdfbe6e84fbd898f146cd23e73ce8f027270
diff --git a/control_interface.h b/control_interface.h
new file mode 100644
index 0000000..f966123
--- /dev/null
+++ b/control_interface.h
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef DHCP_CLIENT_CONTROL_INTERFACE_H_
+#define DHCP_CLIENT_CONTROL_INTERFACE_H_
+
+#include <base/callback.h>
+#include <base/macros.h>
+
+#include "dhcp_client/manager_adaptor_interface.h"
+#include "dhcp_client/service_adaptor_interface.h"
+
+namespace dhcp_client {
+
+class Manager;
+class Service;
+
+// This is the Interface for an object factory that creates adaptor/proxy
+// objects
+class ControlInterface {
+ public:
+  virtual ~ControlInterface() {}
+
+  virtual void Init() = 0;
+  virtual void Shutdown() = 0;
+
+  // Adaptor creation APIs.
+  virtual std::unique_ptr<ManagerAdaptorInterface> CreateManagerAdaptor(
+      Manager* manager) = 0;
+  virtual std::unique_ptr<ServiceAdaptorInterface> CreateServiceAdaptor(
+      Service* service) = 0;
+
+
+};
+
+}  // namespace dhcp_client
+
+#endif  // DHCP_CLIENT_CONTROL_INTERFACE_H_
diff --git a/daemon.cc b/daemon.cc
index ba3f1fd..a95ae92 100644
--- a/daemon.cc
+++ b/daemon.cc
@@ -21,6 +21,8 @@
 #include <base/logging.h>
 #include <base/run_loop.h>
 
+#include <dhcp_client/dbus/dbus_control.h>
+
 namespace dhcp_client {
 
 Daemon::Daemon(const base::Closure& startup_callback)
@@ -33,6 +35,9 @@
     return return_code;
   }
 
+  control_interface_.reset(new DBusControl());
+  control_interface_->Init();
+
   startup_callback_.Run();
 
   return EX_OK;
diff --git a/daemon.h b/daemon.h
index a4ed039..675b18c 100644
--- a/daemon.h
+++ b/daemon.h
@@ -20,6 +20,8 @@
 #include <base/callback_forward.h>
 #include <brillo/daemons/dbus_daemon.h>
 
+#include "dhcp_client/control_interface.h"
+
 namespace dhcp_client {
 
 class Daemon : public brillo::Daemon {
@@ -34,6 +36,8 @@
  private:
   base::Closure startup_callback_;
 
+  std::unique_ptr<ControlInterface> control_interface_;
+
   DISALLOW_COPY_AND_ASSIGN(Daemon);
 };
 
diff --git a/dbus/dbus_control.cc b/dbus/dbus_control.cc
new file mode 100644
index 0000000..0697f58
--- /dev/null
+++ b/dbus/dbus_control.cc
@@ -0,0 +1,95 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "dhcp_client/dbus/dbus_control.h"
+
+#include "dhcp_client/dbus/manager_dbus_adaptor.h"
+#include "dhcp_client/dbus/service_dbus_adaptor.h"
+#include "dhcp_client/manager.h"
+#include "dhcp_client/service.h"
+
+
+using brillo::dbus_utils::AsyncEventSequencer;
+using brillo::dbus_utils::ExportedObjectManager;
+
+namespace dhcp_client {
+
+namespace {
+const char kServiceName[] = "org.chromium.dhcp_client";
+const char kServicePath[] = "/org/chromium/dhcp_client";
+}  // namespace
+
+DBusControl::DBusControl() {}
+
+DBusControl::~DBusControl() {}
+
+void DBusControl::Init() {
+  // Setup bus connection.
+  dbus::Bus::Options options;
+  options.bus_type = dbus::Bus::SYSTEM;
+  bus_ = new dbus::Bus(options);
+  CHECK(bus_->Connect());
+
+  // Create and register ObjectManager.
+  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
+  object_manager_.reset(
+      new ExportedObjectManager(bus_, dbus::ObjectPath(kServicePath)));
+  object_manager_->RegisterAsync(
+      sequencer->GetHandler("ObjectManager.RegisterAsync() failed.", true));
+
+  // Create and register Manager.
+  manager_.reset(new Manager(this));
+  manager_->RegisterAsync(
+      sequencer->GetHandler("Manager.RegisterAsync() failed.", true));
+
+  // Take over the service ownership once the objects registration is completed.
+  sequencer->OnAllTasksCompletedCall({
+    base::Bind(&DBusControl::OnObjectRegistrationCompleted,
+               base::Unretained(this))
+  });
+}
+
+void DBusControl::Shutdown() {
+  manager_.reset();
+  object_manager_.reset();
+  if (bus_) {
+    bus_->ShutdownAndBlock();
+  }
+}
+
+void DBusControl::OnObjectRegistrationCompleted(bool registration_success) {
+  // Success should always be true since we've said that failures are fatal.
+  CHECK(registration_success) << "Init of one or more objects has failed.";
+  CHECK(bus_->RequestOwnershipAndBlock(kServiceName,
+                                       dbus::Bus::REQUIRE_PRIMARY))
+      << "Unable to take ownership of " << kServiceName;
+
+}
+
+std::unique_ptr<ManagerAdaptorInterface> DBusControl::CreateManagerAdaptor(
+    Manager* manager) {
+  return std::unique_ptr<ManagerAdaptorInterface>(
+      new ManagerDBusAdaptor(bus_, object_manager_.get(), manager));
+}
+
+std::unique_ptr<ServiceAdaptorInterface> DBusControl::CreateServiceAdaptor(
+    Service* service) {
+  return std::unique_ptr<ServiceAdaptorInterface>(
+      new ServiceDBusAdaptor(bus_, object_manager_.get(), service));
+}
+
+
+}  // namespace dhcp_client
diff --git a/dbus/dbus_control.h b/dbus/dbus_control.h
new file mode 100644
index 0000000..e47a10f
--- /dev/null
+++ b/dbus/dbus_control.h
@@ -0,0 +1,62 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef DHCP_CLIENT_DBUS_DBUS_CONTROL_H_
+#define DHCP_CLIENT_DBUS_DBUS_CONTROL_H_
+
+#include <base/macros.h>
+#include <brillo/dbus/exported_object_manager.h>
+#include <dbus/bus.h>
+
+#include "dhcp_client/control_interface.h"
+#include "dhcp_client/manager.h"
+#include "dhcp_client/service.h"
+
+namespace dhcp_client {
+
+// D-Bus control interface for IPC through D-Bus.
+class DBusControl : public ControlInterface {
+ public:
+  DBusControl();
+  ~DBusControl() override;
+
+  // Inheritted from ControlInterface.
+  void Init() override;
+  void Shutdown() override;
+  std::unique_ptr<ManagerAdaptorInterface> CreateManagerAdaptor(
+      Manager* manager) override;
+  std::unique_ptr<ServiceAdaptorInterface> CreateServiceAdaptor(
+      Service* service) override;
+
+ private:
+  // Invoked when D-Bus objects for both ObjectManager and Manager
+  // are registered to the bus.
+  void OnObjectRegistrationCompleted(bool registration_success);
+
+  // NOTE: No dedicated bus is needed for the proxies, since the proxies
+  // being created here doesn't listen for any broadcast signals.
+  // Use a dedicated bus for the proxies if this condition is not true
+  // anymore.
+  scoped_refptr<dbus::Bus> bus_;
+  std::unique_ptr<brillo::dbus_utils::ExportedObjectManager> object_manager_;
+  std::unique_ptr<Manager> manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(DBusControl);
+};
+
+}  // namespace dhcp_client
+
+#endif  // DHCP_CLIENT_DBUS_DBUS_CONTROL_H_
diff --git a/dbus/manager_dbus_adaptor.cc b/dbus/manager_dbus_adaptor.cc
new file mode 100644
index 0000000..f33fa38
--- /dev/null
+++ b/dbus/manager_dbus_adaptor.cc
@@ -0,0 +1,100 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "dhcp_client/dbus/manager_dbus_adaptor.h"
+
+#include <string>
+
+#include "dhcp_client/manager.h"
+
+using brillo::dbus_utils::ExportedObjectManager;
+using org::chromium::dhcp_client::ManagerAdaptor;
+using std::string;
+
+namespace dhcp_client {
+
+ManagerDBusAdaptor::ManagerDBusAdaptor(
+    const scoped_refptr<dbus::Bus>& bus,
+    ExportedObjectManager* object_manager,
+    Manager* manager)
+    : adaptor_(this),
+      dbus_object_(object_manager, bus, ManagerAdaptor::GetObjectPath()),
+      bus_(bus),
+      manager_(manager) {}
+
+ManagerDBusAdaptor::~ManagerDBusAdaptor() {}
+
+void ManagerDBusAdaptor::RegisterAsync(
+    const base::Callback<void(bool)>& completion_callback) {
+  adaptor_.RegisterWithDBusObject(&dbus_object_);
+  dbus_object_.RegisterAsync(completion_callback);
+}
+
+bool ManagerDBusAdaptor::StartService(brillo::ErrorPtr* dbus_error,
+                                      dbus::Message* message,
+                                      const brillo::VariantDictionary& configs,
+                                      dbus::ObjectPath* out_service) {
+  auto service = manager_->StartService(configs);
+  if (!service) {
+    // TODO(nywang): set dbus_error.
+    return false;
+  }
+
+  *out_service = service->adaptor()->GetRpcObjectIdentifier();
+
+  // Setup monitoring for the service's remote owner.
+  service_owner_watchers_[*out_service] =
+      ServiceOwnerWatcherContext(
+          service,
+          std::unique_ptr<DBusServiceWatcher>(
+              new DBusServiceWatcher(
+                  bus_,
+                  message->GetSender(),
+                  base::Bind(&ManagerDBusAdaptor::OnServiceOwnerVanished,
+                             base::Unretained(this),
+                             *out_service))));
+  return true;
+}
+
+bool ManagerDBusAdaptor::StopService(brillo::ErrorPtr* dbus_error,
+                                     dbus::Message* message,
+                                     const dbus::ObjectPath& in_service) {
+  auto watcher_context = service_owner_watchers_.find(in_service);
+  if (watcher_context == service_owner_watchers_.end()) {
+    // TODO(nywang): set dbus_error.
+    return false;
+  }
+
+  manager_->StopService(watcher_context->second.service);
+  service_owner_watchers_.erase(watcher_context);
+  return true;
+}
+
+void ManagerDBusAdaptor::OnServiceOwnerVanished(
+    const dbus::ObjectPath& service_path) {
+  LOG(INFO) << "Owner for service " << service_path.value() << " vanished";
+  // Remove service watcher.
+  auto watcher_context = service_owner_watchers_.find(service_path);
+  CHECK(watcher_context != service_owner_watchers_.end())
+      << "Owner vanished without watcher setup.";
+
+  // Tell Manager to remove this service.
+  manager_->StopService(watcher_context->second.service);
+  service_owner_watchers_.erase(watcher_context);
+}
+
+}  // namespace dhcp_client
diff --git a/dbus/manager_dbus_adaptor.h b/dbus/manager_dbus_adaptor.h
new file mode 100644
index 0000000..536e9f5
--- /dev/null
+++ b/dbus/manager_dbus_adaptor.h
@@ -0,0 +1,83 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef DHCP_CLIENT_DBUS_MANAGER_DBUS_ADAPTOR_H_
+#define DHCP_CLIENT_DBUS_MANAGER_DBUS_ADAPTOR_H_
+
+#include <map>
+
+#include <base/macros.h>
+#include <brillo/dbus/dbus_service_watcher.h>
+#include <dbus_bindings/org.chromium.dhcp_client.Manager.h>
+
+#include "dhcp_client/manager_adaptor_interface.h"
+
+namespace dhcp_client {
+
+class Manager;
+class Service;
+
+class ManagerDBusAdaptor : public org::chromium::dhcp_client::ManagerInterface,
+                           public ManagerAdaptorInterface {
+ public:
+  ManagerDBusAdaptor(const scoped_refptr<dbus::Bus>& bus,
+                     brillo::dbus_utils::ExportedObjectManager* object_manager,
+                     Manager* manager);
+  ~ManagerDBusAdaptor() override;
+
+  // Implementation of org::chromium::dhcp_client::ManagerInterface.
+  bool StartService(brillo::ErrorPtr* dbus_error,
+                    dbus::Message* message,
+                    const brillo::VariantDictionary& configs,
+                    dbus::ObjectPath* out_service) override;
+  bool StopService(brillo::ErrorPtr* dbus_error,
+                   dbus::Message* message,
+                   const dbus::ObjectPath& in_service) override;
+
+  // Implementation of ManagerAdaptorInterface.
+  void RegisterAsync(
+      const base::Callback<void(bool)>& completion_callback) override;
+
+ private:
+  using DBusServiceWatcher = brillo::dbus_utils::DBusServiceWatcher;
+  // Context for service owner watcher.
+  struct ServiceOwnerWatcherContext {
+    ServiceOwnerWatcherContext() {}
+    ServiceOwnerWatcherContext(const scoped_refptr<Service>& in_service,
+                               std::unique_ptr<DBusServiceWatcher> in_watcher)
+        : service(in_service),
+          watcher(std::move(in_watcher)) {}
+    scoped_refptr<Service> service;
+    std::unique_ptr<DBusServiceWatcher> watcher;
+  };
+
+  // Invoked when the owner of a Service vanished.
+  void OnServiceOwnerVanished(const dbus::ObjectPath& service_path);
+
+  org::chromium::dhcp_client::ManagerAdaptor adaptor_;
+  brillo::dbus_utils::DBusObject dbus_object_;
+  scoped_refptr<dbus::Bus> bus_;
+  Manager* manager_;
+  // Map of service path to owner monitor context.
+  std::map<dbus::ObjectPath, ServiceOwnerWatcherContext>
+      service_owner_watchers_;
+
+  DISALLOW_COPY_AND_ASSIGN(ManagerDBusAdaptor);
+};
+
+}  // namespace dhcp_client
+
+#endif  // DHCP_CLIENT_DBUS_MANAGER_DBUS_ADAPTOR_H_
diff --git a/dbus/service_dbus_adaptor.cc b/dbus/service_dbus_adaptor.cc
new file mode 100644
index 0000000..57f6592
--- /dev/null
+++ b/dbus/service_dbus_adaptor.cc
@@ -0,0 +1,57 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "dhcp_client/dbus/service_dbus_adaptor.h"
+
+#include <string>
+
+#include <base/bind.h>
+#include <base/strings/stringprintf.h>
+#include <dbus_bindings/org.chromium.dhcp_client.Manager.h>
+
+#include "dhcp_client/service.h"
+
+using brillo::dbus_utils::ExportedObjectManager;
+using brillo::dbus_utils::DBusMethodResponse;
+using brillo::dbus_utils::DBusObject;
+using org::chromium::dhcp_client::ManagerAdaptor;
+using std::string;
+
+namespace dhcp_client {
+
+ServiceDBusAdaptor::ServiceDBusAdaptor(
+    const scoped_refptr<dbus::Bus>& bus,
+    ExportedObjectManager* object_manager,
+    Service* service)
+    : adaptor_(this),
+      object_path_(
+          base::StringPrintf("%s/services/%d",
+                             ManagerAdaptor::GetObjectPath().value().c_str(),
+                             service->identifier())),
+      dbus_object_(object_manager, bus, object_path_),
+      service_(service) {
+  // Register D-Bus object.
+  adaptor_.RegisterWithDBusObject(&dbus_object_);
+  dbus_object_.RegisterAndBlock();
+}
+
+ServiceDBusAdaptor::~ServiceDBusAdaptor() {}
+
+RPCObjectIdentifier ServiceDBusAdaptor::GetRpcObjectIdentifier() {
+  return object_path_;
+}
+
+}  // namespace dhcp_client
diff --git a/dbus/service_dbus_adaptor.h b/dbus/service_dbus_adaptor.h
new file mode 100644
index 0000000..80e555b
--- /dev/null
+++ b/dbus/service_dbus_adaptor.h
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef DHCP_CLIENT_DBUS_SERVICE_DBUS_ADAPTOR_H_
+#define DHCP_CLIENT_DBUS_SERVICE_DBUS_ADAPTOR_H_
+
+#include <base/macros.h>
+
+#include <dbus_bindings/org.chromium.dhcp_client.Service.h>
+
+#include "dhcp_client/service_adaptor_interface.h"
+
+namespace dhcp_client {
+
+class Service;
+
+class ServiceDBusAdaptor : public org::chromium::dhcp_client::ServiceInterface,
+                           public ServiceAdaptorInterface {
+ public:
+  ServiceDBusAdaptor(const scoped_refptr<dbus::Bus>& bus,
+                     brillo::dbus_utils::ExportedObjectManager* object_manager,
+                     Service* service);
+  ~ServiceDBusAdaptor() override;
+
+  // Implementation of ServiceAdaptorInterface.
+  RPCObjectIdentifier GetRpcObjectIdentifier() override;
+  // TODO(nywang): implement signal 'Event'
+
+ private:
+  org::chromium::dhcp_client::ServiceAdaptor adaptor_;
+  dbus::ObjectPath object_path_;
+  brillo::dbus_utils::DBusObject dbus_object_;
+  Service* service_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceDBusAdaptor);
+};
+
+}  // namespace dhcp_client
+
+#endif  // DHCP_CLIENT_DBUS_SERVICE_DBUS_ADAPTOR_H_
diff --git a/dbus_bindings/dbus-service-config.json b/dbus_bindings/dbus-service-config.json
new file mode 100644
index 0000000..647c046
--- /dev/null
+++ b/dbus_bindings/dbus-service-config.json
@@ -0,0 +1,6 @@
+{
+  "service_name": "org.chromium.dhcp_client",
+  "object_manager": {
+    "object_path": "/org/chromium/dhcp_client"
+  }
+}
diff --git a/dbus_bindings/org.chromium.dhcp_client.Manager.dbus-xml b/dbus_bindings/org.chromium.dhcp_client.Manager.dbus-xml
new file mode 100644
index 0000000..292424a
--- /dev/null
+++ b/dbus_bindings/org.chromium.dhcp_client.Manager.dbus-xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/org/chromium/dhcp_client/Manager"
+      xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
+  <interface name="org.chromium.dhcp_client.Manager">
+    <method name="StartService">
+      <arg name="args" type="a{sv}" direction="in"/>
+      <arg name="service" type="o" direction="out"/>
+      <annotation name="org.chromium.DBus.Method.IncludeDBusMessage"
+                  value="true"/>
+    </method>
+    <method name="StopService">
+      <arg name="service" type="o" direction="in"/>
+      <annotation name="org.chromium.DBus.Method.IncludeDBusMessage"
+                  value="true"/>
+    </method>
+  </interface>
+</node>
diff --git a/dbus_bindings/org.chromium.dhcp_client.Service.dbus-xml b/dbus_bindings/org.chromium.dhcp_client.Service.dbus-xml
new file mode 100644
index 0000000..e2d5101
--- /dev/null
+++ b/dbus_bindings/org.chromium.dhcp_client.Service.dbus-xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
+  <interface name="org.chromium.dhcp_client.Service">
+    <signal name="Event">
+      <arg name = "configuration" type="a{sv}"/>
+    </signal>
+  </interface>
+</node>
diff --git a/dbus_permissions/org.chromium.dhcp_client.conf b/dbus_permissions/org.chromium.dhcp_client.conf
new file mode 100644
index 0000000..a4abf20
--- /dev/null
+++ b/dbus_permissions/org.chromium.dhcp_client.conf
@@ -0,0 +1,16 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+    <policy user="root">
+        <allow own="org.chromium.dhcp_client"/>
+        <allow send_destination="org.chromium.dhcp_client"/>
+    </policy>
+
+    <policy user="dhcp">
+        <allow own="org.chromium.dhcp_client"/>
+    </policy>
+
+    <policy group="dhcp">
+        <allow send_destination="org.chromium.dhcp_client" />
+    </policy>
+</busconfig>
diff --git a/dhcp_client.gyp b/dhcp_client.gyp
index 709cc4d..8240ed2 100644
--- a/dhcp_client.gyp
+++ b/dhcp_client.gyp
@@ -40,9 +40,26 @@
   },
 
   'targets': [
+   {
+      'target_name': 'dhcp_client-adaptors',
+      'type': 'none',
+      'variables': {
+        'dbus_adaptors_out_dir': 'include/dbus_bindings',
+        'dbus_xml_extension': 'dbus-xml',
+      },
+      'sources': [
+        'dbus_bindings/org.chromium.dhcp_client.Manager.dbus-xml',
+        'dbus_bindings/org.chromium.dhcp_client.Service.dbus-xml',
+      ],
+      'includes': ['../../../../platform2/common-mk/generate-dbus-adaptors.gypi'],
+    },
+
     {
       'target_name': 'libdhcp_client',
       'type': 'static_library',
+      'dependencies': [
+        'dhcp_client-adaptors',
+      ],
       'variables': {
         'exported_deps': [
         ],
@@ -57,6 +74,9 @@
       },
       'sources': [
         'daemon.cc',
+        'dbus/dbus_control.cc',
+        'dbus/manager_dbus_adaptor.cc',
+        'dbus/service_dbus_adaptor.cc',
         'device_info.cc',
         'dhcp_message.cc',
         'dhcp_options_parser.cc',
diff --git a/dhcpv4.cc b/dhcpv4.cc
index 6f4a21b..bf78157 100644
--- a/dhcpv4.cc
+++ b/dhcpv4.cc
@@ -117,7 +117,9 @@
 }
 
 DHCPV4::~DHCPV4() {
-  Stop();
+  if (socket_ != kInvalidSocketDescriptor) {
+    Stop();
+  }
 }
 
 void DHCPV4::ResetStateVariables() {
@@ -242,6 +244,7 @@
   }
   if (socket_ != kInvalidSocketDescriptor) {
     sockets_->Close(socket_);
+    socket_ = kInvalidSocketDescriptor;
   }
 }
 
@@ -515,11 +518,11 @@
   message.SetServerIdentifier(server_identifier_);
   ByteString packet;
   if (!MakeRawPacket(message, &packet)) {
-    LOG(ERROR) << "Failed to serialize a DHCP discover message";
+    LOG(ERROR) << "Failed to serialize a DHCP release message";
     return false;
   }
   if (!SendRawPacket(packet)) {
-    LOG(ERROR) << "Failed to send a DHCP discover packet";
+    LOG(ERROR) << "Failed to send a DHCP release packet";
     return false;
   }
   // Set state variables upon success.
diff --git a/manager.cc b/manager.cc
index e0844e1..33a65f5 100644
--- a/manager.cc
+++ b/manager.cc
@@ -18,16 +18,24 @@
 #include "dhcp_client/service.h"
 
 #include "dhcp_client/message_loop_event_dispatcher.h"
+#include "dhcp_client/control_interface.h"
 
 namespace dhcp_client {
 
-Manager::Manager()
-    : service_identifier_(0),
-      event_dispatcher_(new MessageLoopEventDispatcher()) {
+Manager::Manager(ControlInterface* control_interface)
+    : control_interface_(control_interface),
+      service_identifier_(0),
+      event_dispatcher_(new MessageLoopEventDispatcher()),
+      adaptor_(control_interface->CreateManagerAdaptor(this)) {
 }
 
 Manager::~Manager() {}
 
+void Manager::RegisterAsync(
+    const base::Callback<void(bool)>& completion_callback) {
+  adaptor_->RegisterAsync(completion_callback);
+}
+
 scoped_refptr<Service> Manager::StartService(
     const brillo::VariantDictionary& configs) {
   scoped_refptr<Service> service = new Service(this,
diff --git a/manager.h b/manager.h
index 88c2428..896f9d2 100644
--- a/manager.h
+++ b/manager.h
@@ -23,24 +23,33 @@
 #include <brillo/variant_dictionary.h>
 
 #include "dhcp_client/event_dispatcher_interface.h"
+#include "dhcp_client/manager_adaptor_interface.h"
 #include "dhcp_client/service.h"
 
 namespace dhcp_client {
 
+class ControlInterface;
+
 class Manager {
  public:
-  Manager();
+  // Register this object to the RPC interface asynchronously.
+  void RegisterAsync(const base::Callback<void(bool)>&
+                     completion_callback);
+  explicit Manager(ControlInterface* control_interface);
   virtual ~Manager();
 
   scoped_refptr<Service> StartService(const brillo::VariantDictionary& configs);
 
   bool StopService(const scoped_refptr<Service>& service);
+  ControlInterface* control_interface() const { return control_interface_; }
 
  private:
+  ControlInterface* control_interface_;
   int service_identifier_;
   std::unique_ptr<EventDispatcherInterface> event_dispatcher_;
   std::vector<scoped_refptr<Service>> services_;
 
+  std::unique_ptr<ManagerAdaptorInterface> adaptor_;
   DISALLOW_COPY_AND_ASSIGN(Manager);
 };
 
diff --git a/manager_adaptor_interface.h b/manager_adaptor_interface.h
new file mode 100644
index 0000000..c9c5745
--- /dev/null
+++ b/manager_adaptor_interface.h
@@ -0,0 +1,34 @@
+//
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef DHCP_CLIENT_MANAGER_ADAPTOR_INTERFACE_H_
+#define DHCP_CLIENT_MANAGER_ADAPTOR_INTERFACE_H_
+
+#include <base/callback.h>
+
+namespace dhcp_client {
+
+class ManagerAdaptorInterface {
+ public:
+  virtual ~ManagerAdaptorInterface() {}
+
+  virtual void RegisterAsync(
+      const base::Callback<void(bool)>& completion_callback) = 0;
+};
+
+}  // namespace dhcp_client
+
+#endif  // DHCP_CLIENT_MANAGER_ADAPTOR_INTERFACE_H_
diff --git a/rpc_interface.h b/rpc_interface.h
new file mode 100644
index 0000000..70c3021
--- /dev/null
+++ b/rpc_interface.h
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DHCP_CLIENT_RPC_INTERFACE_H_
+#define DHCP_CLIENT_RPC_INTERFACE_H_
+
+// TODO(nywang): put this under a compiler flag (e.g. __DBUS__).
+#include <dbus/object_path.h>
+
+namespace dhcp_client {
+
+// TODO(nywang): put this under a compiler flag (e.g. __DBUS__).
+typedef dbus::ObjectPath RPCObjectIdentifier;
+
+}  // namespace dhcp_client
+
+#endif  // DHCP_CLIENT_RPC_INTERFACE_H_
diff --git a/service.cc b/service.cc
index 77a412e..562980c 100644
--- a/service.cc
+++ b/service.cc
@@ -18,7 +18,9 @@
 
 #include <string>
 
+#include "dhcp_client/control_interface.h"
 #include "dhcp_client/device_info.h"
+#include "dhcp_client/manager.h"
 
 using std::string;
 
@@ -41,6 +43,7 @@
                  const brillo::VariantDictionary& configs)
     : manager_(manager),
       identifier_(service_identifier),
+      adaptor_(manager->control_interface()->CreateServiceAdaptor(this)),
       event_dispatcher_(event_dispatcher),
       type_(DHCP::SERVICE_TYPE_IPV4),
       request_hostname_(false),
@@ -49,19 +52,22 @@
       request_na_(false),
       request_pd_(false) {
   ParseConfigs(configs);
+  event_dispatcher_->PostTask(Bind(&Service::Start, Unretained(this)));
 }
 
 Service::~Service() {
-  Stop();
+  if (state_machine_ipv4_) {
+    Stop();
+  }
 }
 
-bool Service::Start() {
+void Service::Start() {
   if (!DeviceInfo::GetInstance()->GetDeviceInfo(interface_name_,
                                                 &hardware_address_,
                                                 &interface_index_)) {
     LOG(ERROR) << "Unable to get interface information for: "
                << interface_name_;
-    return false;
+    return;
   }
 
   if (type_ == DHCP::SERVICE_TYPE_IPV4 ||
@@ -83,7 +89,7 @@
     state_machine_ipv4_->Start();
   }
   // TODO(nywang): Start DHCP state machine for IPV6.
-  return true;
+  return;
 }
 
 void Service::Stop() {
diff --git a/service.h b/service.h
index b0044aa..43e6eee 100644
--- a/service.h
+++ b/service.h
@@ -26,6 +26,7 @@
 #include "dhcp_client/dhcp.h"
 #include "dhcp_client/dhcpv4.h"
 #include "dhcp_client/event_dispatcher_interface.h"
+#include "dhcp_client/service_adaptor_interface.h"
 #include "shill/net/byte_string.h"
 
 namespace dhcp_client {
@@ -40,13 +41,16 @@
           const brillo::VariantDictionary& configs);
 
   virtual ~Service();
-  bool Start();
+  void Start();
   void Stop();
+  ServiceAdaptorInterface* adaptor() const { return adaptor_.get(); }
+  int identifier() { return identifier_; }
 
  private:
   Manager* manager_;
   // Indentifier number of this service.
   int identifier_;
+  std::unique_ptr<ServiceAdaptorInterface> adaptor_;
   EventDispatcherInterface* event_dispatcher_;
   // Interface parameters.
   std::string interface_name_;
diff --git a/service_adaptor_interface.h b/service_adaptor_interface.h
new file mode 100644
index 0000000..f720541
--- /dev/null
+++ b/service_adaptor_interface.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef DHCP_CLIENT_SERVICE_ADAPTOR_INTERFACE_H_
+#define DHCP_CLIENT_SERVICE_ADAPTOR_INTERFACE_H_
+
+#include <string>
+
+#include "dhcp_client/rpc_interface.h"
+
+namespace dhcp_client {
+
+class Config;
+
+class ServiceAdaptorInterface {
+ public:
+  virtual ~ServiceAdaptorInterface() {}
+  virtual RPCObjectIdentifier GetRpcObjectIdentifier() = 0;
+};
+
+}  // namespace dhcp_client
+
+#endif  // DHCP_CLIENT_SERVICE_ADAPTOR_INTERFACE_H_