Update interface implementations to reflect changes to libweave

Pulling current version of libweave and making necessary changes to
weaved implementation of libweave's interfaces

Change-Id: I31d5d00ce1c7d2338257d62ec2dd510608ff71af
diff --git a/buffet/shill_client.cc b/buffet/shill_client.cc
index d019011..d3a53f5 100644
--- a/buffet/shill_client.cc
+++ b/buffet/shill_client.cc
@@ -26,11 +26,15 @@
 using std::set;
 using std::string;
 using std::vector;
+using weave::EnumToString;
+using weave::provider::Network;
 
 namespace buffet {
 
 namespace {
 
+const char kErrorDomain[] = "buffet";
+
 void IgnoreDetachEvent() {}
 
 bool GetStateForService(ServiceProxy* service, string* state) {
@@ -54,31 +58,31 @@
   return true;
 }
 
-weave::NetworkState ShillServiceStateToNetworkState(const string& state) {
+Network::State ShillServiceStateToNetworkState(const string& state) {
   // TODO(wiley) What does "unconfigured" mean in a world with multiple sets
   //             of WiFi credentials?
   // TODO(wiley) Detect disabled devices, update state appropriately.
   if ((state.compare(shill::kStateReady) == 0) ||
       (state.compare(shill::kStatePortal) == 0) ||
       (state.compare(shill::kStateOnline) == 0)) {
-    return weave::NetworkState::kConnected;
+    return Network::State::kConnected;
   }
   if ((state.compare(shill::kStateAssociation) == 0) ||
       (state.compare(shill::kStateConfiguration) == 0)) {
-    return weave::NetworkState::kConnecting;
+    return Network::State::kConnecting;
   }
   if ((state.compare(shill::kStateFailure) == 0) ||
       (state.compare(shill::kStateActivationFailure) == 0)) {
     // TODO(wiley) Get error information off the service object.
-    return weave::NetworkState::kFailure;
+    return Network::State::kFailure;
   }
   if ((state.compare(shill::kStateIdle) == 0) ||
       (state.compare(shill::kStateOffline) == 0) ||
       (state.compare(shill::kStateDisconnect) == 0)) {
-    return weave::NetworkState::kOffline;
+    return Network::State::kOffline;
   }
   LOG(WARNING) << "Unknown state found: '" << state << "'";
-  return weave::NetworkState::kOffline;
+  return Network::State::kOffline;
 }
 
 }  // namespace
@@ -86,7 +90,7 @@
 ShillClient::ShillClient(const scoped_refptr<dbus::Bus>& bus,
                          const set<string>& device_whitelist)
     : bus_{bus},
-      manager_proxy_{bus_, ObjectPath{"/"}},
+      manager_proxy_{bus_},
       device_whitelist_{device_whitelist},
       ap_manager_client_{new ApManagerClient(bus)} {
   manager_proxy_.RegisterPropertyChangedSignalHandler(
@@ -104,9 +108,9 @@
 
 void ShillClient::Init() {
   VLOG(2) << "ShillClient::Init();";
-  CleanupConnectingService(false);
+  CleanupConnectingService();
   devices_.clear();
-  connectivity_state_ = weave::NetworkState::kOffline;
+  connectivity_state_ = Network::State::kOffline;
   VariantDictionary properties;
   if (!manager_proxy_.GetProperties(&properties, nullptr)) {
     LOG(ERROR) << "Unable to get properties from Manager, waiting for "
@@ -118,63 +122,84 @@
   OnManagerPropertyChange(shill::kDevicesProperty, it->second);
 }
 
-bool ShillClient::ConnectToService(const string& ssid,
-                                   const string& passphrase,
-                                   const base::Closure& on_success,
-                                   weave::ErrorPtr* error) {
-  chromeos::ErrorPtr chromeos_error;
-  if (!ConnectToServiceImpl(ssid, passphrase, on_success, &chromeos_error)) {
-    ConvertError(*chromeos_error, error);
-    return false;
+void ShillClient::Connect(const string& ssid,
+                          const string& passphrase,
+                          const weave::SuccessCallback& success_callback,
+                          const weave::ErrorCallback& error_callback) {
+  if (connecting_service_) {
+    weave::ErrorPtr error;
+    weave::Error::AddTo(&error, FROM_HERE, kErrorDomain, "busy",
+                        "Already connecting to WiFi network");
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE, base::Bind(error_callback, base::Owned(error.release())));
+    return;
   }
-  return true;
-}
-
-bool ShillClient::ConnectToServiceImpl(const string& ssid,
-                                       const string& passphrase,
-                                       const base::Closure& on_success,
-                                       chromeos::ErrorPtr* error) {
-  CleanupConnectingService(false);
+  CleanupConnectingService();
   VariantDictionary service_properties;
   service_properties[shill::kTypeProperty] = Any{string{shill::kTypeWifi}};
   service_properties[shill::kSSIDProperty] = Any{ssid};
-  service_properties[shill::kPassphraseProperty] = Any{passphrase};
-  service_properties[shill::kSecurityProperty] = Any{
-      string{passphrase.empty() ? shill::kSecurityNone : shill::kSecurityPsk}};
+  if (passphrase.empty()) {
+    service_properties[shill::kSecurityProperty] = Any{shill::kSecurityNone};
+  } else {
+    service_properties[shill::kPassphraseProperty] = Any{passphrase};
+    service_properties[shill::kSecurityProperty] = Any{shill::kSecurityPsk};
+  }
   service_properties[shill::kSaveCredentialsProperty] = Any{true};
   service_properties[shill::kAutoConnectProperty] = Any{true};
   ObjectPath service_path;
+  chromeos::ErrorPtr chromeos_error;
   if (!manager_proxy_.ConfigureService(service_properties, &service_path,
-                                       error)) {
-    return false;
-  }
-  if (!manager_proxy_.RequestScan(shill::kTypeWifi, error)) {
-    return false;
+                                       &chromeos_error) ||
+      !manager_proxy_.RequestScan(shill::kTypeWifi, &chromeos_error)) {
+    weave::ErrorPtr weave_error;
+    ConvertError(*chromeos_error, &weave_error);
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(error_callback, base::Owned(weave_error.release())));
+    return;
   }
   connecting_service_.reset(new ServiceProxy{bus_, service_path});
-  on_connect_success_.Reset(on_success);
+  connecting_service_->Connect(nullptr);
+  connect_success_callback_ = success_callback;
+  connect_error_callback_ = error_callback;
   connecting_service_->RegisterPropertyChangedSignalHandler(
       base::Bind(&ShillClient::OnServicePropertyChange,
                  weak_factory_.GetWeakPtr(), service_path),
       base::Bind(&ShillClient::OnServicePropertyChangeRegistration,
                  weak_factory_.GetWeakPtr(), service_path));
-  return true;
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE, base::Bind(&ShillClient::ConnectToServiceError,
+                            weak_factory_.GetWeakPtr(), connecting_service_),
+      base::TimeDelta::FromMinutes(1));
 }
 
-weave::NetworkState ShillClient::GetConnectionState() const {
+void ShillClient::ConnectToServiceError(
+    std::shared_ptr<org::chromium::flimflam::ServiceProxy> connecting_service) {
+  if (connecting_service != connecting_service_ ||
+      connect_error_callback_.is_null()) {
+    return;
+  }
+  std::string error = have_called_connect_ ? connecting_service_error_
+                                           : shill::kErrorOutOfRange;
+  if (error.empty())
+    error = shill::kErrorInternal;
+  OnErrorChangeForConnectingService(error);
+}
+
+Network::State ShillClient::GetConnectionState() const {
   return connectivity_state_;
 }
 
-void ShillClient::EnableAccessPoint(const std::string& ssid) {
+void ShillClient::StartAccessPoint(const std::string& ssid) {
   ap_manager_client_->Start(ssid);
 }
 
-void ShillClient::DisableAccessPoint() {
+void ShillClient::StopAccessPoint() {
   ap_manager_client_->Stop();
 }
 
-void ShillClient::AddOnConnectionChangedCallback(
-    const OnConnectionChangedCallback& listener) {
+void ShillClient::AddConnectionChangedCallback(
+    const ConnectionChangedCallback& listener) {
   connectivity_listeners_.push_back(listener);
 }
 
@@ -199,9 +224,9 @@
                                             const string& new_owner) {
   VLOG(1) << "Shill service owner name changed to '" << new_owner << "'";
   if (new_owner.empty()) {
-    CleanupConnectingService(false);
+    CleanupConnectingService();
     devices_.clear();
-    connectivity_state_ = weave::NetworkState::kOffline;
+    connectivity_state_ = Network::State::kOffline;
   } else {
     Init();  // New service owner means shill reset!
   }
@@ -320,7 +345,7 @@
       return;  // Spurious update?
     }
     device_state.selected_service.reset();
-    device_state.service_state = weave::NetworkState::kOffline;
+    device_state.service_state = Network::State::kOffline;
     removed_old_service = true;
   }
   std::shared_ptr<ServiceProxy> new_service;
@@ -364,9 +389,8 @@
   if (connecting_service_ && connecting_service_->GetObjectPath() == path) {
     // Note that the connecting service might also be a selected service.
     service = connecting_service_.get();
-    if (!success) {
-      CleanupConnectingService(false);
-    }
+    if (!success)
+      CleanupConnectingService();
   } else {
     for (const auto& kv : devices_) {
       if (kv.second.selected_service &&
@@ -385,13 +409,11 @@
   }
   // Give ourselves property changed signals for the initial property
   // values.
-  auto it = properties.find(shill::kStateProperty);
-  if (it != properties.end()) {
-    OnServicePropertyChange(path, shill::kStateProperty, it->second);
-  }
-  it = properties.find(shill::kSignalStrengthProperty);
-  if (it != properties.end()) {
-    OnServicePropertyChange(path, shill::kSignalStrengthProperty, it->second);
+  for (auto name : {shill::kStateProperty, shill::kSignalStrengthProperty,
+                    shill::kErrorProperty}) {
+    auto it = properties.find(name);
+    if (it != properties.end())
+      OnServicePropertyChange(path, name, it->second);
   }
 }
 
@@ -400,6 +422,10 @@
                                           const Any& property_value) {
   VLOG(3) << "ServicePropertyChange(" << service_path.value() << ", "
           << property_name << ", ...);";
+
+  bool is_connecting_service =
+      connecting_service_ &&
+      connecting_service_->GetObjectPath() == service_path;
   if (property_name == shill::kStateProperty) {
     const string state{property_value.TryGet<string>()};
     if (state.empty()) {
@@ -408,33 +434,57 @@
     }
     VLOG(3) << "New service state=" << state;
     OnStateChangeForSelectedService(service_path, state);
-    OnStateChangeForConnectingService(service_path, state);
+    if (is_connecting_service)
+      OnStateChangeForConnectingService(state);
   } else if (property_name == shill::kSignalStrengthProperty) {
-    OnStrengthChangeForConnectingService(service_path,
-                                         property_value.TryGet<uint8_t>());
+    VLOG(3) << "Signal strength=" << property_value.TryGet<uint8_t>();
+    if (is_connecting_service)
+      OnStrengthChangeForConnectingService(property_value.TryGet<uint8_t>());
+  } else if (property_name == shill::kErrorProperty) {
+    VLOG(3) << "Error=" << property_value.TryGet<std::string>();
+    if (is_connecting_service)
+      connecting_service_error_ = property_value.TryGet<std::string>();
   }
 }
 
-void ShillClient::OnStateChangeForConnectingService(
-    const ObjectPath& service_path,
-    const string& state) {
-  if (!connecting_service_ ||
-      connecting_service_->GetObjectPath() != service_path ||
-      ShillServiceStateToNetworkState(state) !=
-          weave::NetworkState::kConnected) {
-    return;
+void ShillClient::OnStateChangeForConnectingService(const string& state) {
+  switch (ShillServiceStateToNetworkState(state)) {
+    case Network::State::kConnected: {
+      auto callback = connect_success_callback_;
+      CleanupConnectingService();
+
+      if (!callback.is_null())
+        callback.Run();
+      break;
+    }
+    case Network::State::kFailure: {
+      ConnectToServiceError(connecting_service_);
+      break;
+    }
+    case Network::State::kOffline:
+    case Network::State::kConnecting:
+      break;
   }
-  connecting_service_reset_pending_ = true;
-  on_connect_success_.callback().Run();
-  CleanupConnectingService(true);
+}
+
+void ShillClient::OnErrorChangeForConnectingService(const std::string& error) {
+  if (error.empty())
+    return;
+
+  auto callback = connect_error_callback_;
+  CleanupConnectingService();
+
+  weave::ErrorPtr weave_error;
+  weave::Error::AddTo(&weave_error, FROM_HERE, kErrorDomain, error,
+                      "Failed to connect to WiFi network");
+
+  if (!callback.is_null())
+    callback.Run(weave_error.get());
 }
 
 void ShillClient::OnStrengthChangeForConnectingService(
-    const ObjectPath& service_path,
     uint8_t signal_strength) {
-  if (!connecting_service_ ||
-      connecting_service_->GetObjectPath() != service_path ||
-      signal_strength <= 0 || have_called_connect_) {
+  if (signal_strength == 0 || have_called_connect_) {
     return;
   }
   VLOG(1) << "Connecting service has signal. Calling Connect().";
@@ -466,7 +516,7 @@
 void ShillClient::UpdateConnectivityState() {
   // Update the connectivity state of the device by picking the
   // state of the currently most connected selected service.
-  weave::NetworkState new_connectivity_state{weave::NetworkState::kOffline};
+  Network::State new_connectivity_state{Network::State::kOffline};
   for (const auto& kv : devices_) {
     if (kv.second.service_state > new_connectivity_state) {
       new_connectivity_state = kv.second.service_state;
@@ -486,42 +536,45 @@
       FROM_HERE,
       base::Bind(&ShillClient::NotifyConnectivityListeners,
                  weak_factory_.GetWeakPtr(),
-                 GetConnectionState() == weave::NetworkState::kConnected));
+                 GetConnectionState() == Network::State::kConnected));
 }
 
 void ShillClient::NotifyConnectivityListeners(bool am_online) {
   VLOG(3) << "Notifying connectivity listeners that online=" << am_online;
-  for (const auto& listener : connectivity_listeners_) {
-    listener.Run(am_online);
-  }
+  for (const auto& listener : connectivity_listeners_)
+    listener.Run();
 }
 
-void ShillClient::CleanupConnectingService(bool check_for_reset_pending) {
-  if (check_for_reset_pending && !connecting_service_reset_pending_) {
-    return;  // Must have called connect before we got here.
-  }
+void ShillClient::CleanupConnectingService() {
   if (connecting_service_) {
     connecting_service_->ReleaseObjectProxy(base::Bind(&IgnoreDetachEvent));
     connecting_service_.reset();
   }
-  on_connect_success_.Cancel();
+  connect_success_callback_.Reset();
+  connect_error_callback_.Reset();
   have_called_connect_ = false;
-  connecting_service_reset_pending_ = false;
 }
 
-std::unique_ptr<weave::Stream> ShillClient::OpenSocketBlocking(
+void ShillClient::OpenSslSocket(
     const std::string& host,
-    uint16_t port) {
-  return SocketStream::ConnectBlocking(host, port);
-}
-
-void ShillClient::CreateTlsStream(
-    std::unique_ptr<weave::Stream> socket,
-    const std::string& host,
+    uint16_t port,
     const base::Callback<void(std::unique_ptr<weave::Stream>)>&
         success_callback,
     const base::Callback<void(const weave::Error*)>& error_callback) {
-  SocketStream::TlsConnect(std::move(socket), host, success_callback,
+  std::unique_ptr<weave::Stream> raw_stream{
+      SocketStream::ConnectBlocking(host, port)};
+  if (!raw_stream) {
+    chromeos::ErrorPtr error;
+    chromeos::errors::system::AddSystemError(&error, FROM_HERE, errno);
+    weave::ErrorPtr weave_error;
+    ConvertError(*error.get(), &weave_error);
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(error_callback, base::Owned(weave_error.release())));
+    return;
+  }
+
+  SocketStream::TlsConnect(std::move(raw_stream), host, success_callback,
                            error_callback);
 }