Changed now NetworkManager detects connectivity status

Now it constantly pings with 10s delay.
Added command line to force bootstrapping.

BUG: 24111116
Change-Id: Id23b3f42dc276f488ec4ccf17fd2b0341372e13c
Reviewed-on: https://weave-review.googlesource.com/1110
Reviewed-by: Alex Vakulenko <avakulenko@google.com>
diff --git a/libweave/examples/ubuntu/main.cc b/libweave/examples/ubuntu/main.cc
index b5766a3..2a96ee2 100644
--- a/libweave/examples/ubuntu/main.cc
+++ b/libweave/examples/ubuntu/main.cc
@@ -12,11 +12,31 @@
 #include "libweave/examples/ubuntu/file_config_store.h"
 #include "libweave/examples/ubuntu/network_manager.h"
 
-int main() {
+namespace {
+void ShowUsage(const std::string& name) {
+  LOG(ERROR) << "\nUsage: " << name << " <option(s)>"
+             << "\nOptions:\n"
+             << "\t-h,--help             Show this help message\n"
+             << "\t-b,--bootstrapping    Force WiFi bootstrapping\n";
+}
+}
+
+int main(int argc, char** argv) {
+  bool force_bootstrapping = false;
+  for (int i = 1; i < argc; ++i) {
+    std::string arg = argv[i];
+    if (arg == "-h" || arg == "--help") {
+      ShowUsage(argv[0]);
+      return 0;
+    }
+    if (arg == "-b" || arg == "--bootstrapping")
+      force_bootstrapping = true;
+  }
+
   weave::examples::FileConfigStore config_store;
   weave::examples::EventTaskRunner task_runner;
   weave::examples::CurlHttpClient http_client{&task_runner};
-  weave::examples::NetworkImpl network{&task_runner};
+  weave::examples::NetworkImpl network{&task_runner, force_bootstrapping};
   weave::examples::MdnsImpl mdns;
   weave::examples::HttpServerImpl http_server{&task_runner};
   weave::examples::BluetoothImpl bluetooth;
diff --git a/libweave/examples/ubuntu/network_manager.cc b/libweave/examples/ubuntu/network_manager.cc
index a054d24..2f96c09 100644
--- a/libweave/examples/ubuntu/network_manager.cc
+++ b/libweave/examples/ubuntu/network_manager.cc
@@ -185,11 +185,13 @@
 
 }  // namespace
 
-NetworkImpl::NetworkImpl(TaskRunner* task_runner) : task_runner_{task_runner} {
+NetworkImpl::NetworkImpl(TaskRunner* task_runner, bool force_bootstrapping)
+    : task_runner_{task_runner}, force_bootstrapping_{force_bootstrapping} {
   SSL_load_error_strings();
   SSL_library_init();
 
   DisableAccessPoint();
+  UpdateNetworkState();
 }
 NetworkImpl::~NetworkImpl() {
   DisableAccessPoint();
@@ -220,13 +222,8 @@
       essid.resize(wreq.u.essid.length);
       close(sockf_d);
 
-      if (ssid == essid) {
-        task_runner_->PostDelayedTask(
-            FROM_HERE, base::Bind(&NetworkImpl::NotifyNetworkChanged,
-                                  weak_ptr_factory_.GetWeakPtr()),
-            {});
+      if (ssid == essid)
         return task_runner_->PostDelayedTask(FROM_HERE, on_success, {});
-      }
       pid = 0;  // Try again.
     }
   }
@@ -236,13 +233,8 @@
                   {"dev", "wifi", "connect", ssid, "password", passphrase});
   }
 
-  if (base::Time::Now() >= until) {
-    task_runner_->PostDelayedTask(FROM_HERE,
-                                  base::Bind(&NetworkImpl::NotifyNetworkChanged,
-                                             weak_ptr_factory_.GetWeakPtr()),
-                                  {});
+  if (base::Time::Now() >= until)
     return;
-  }
 
   task_runner_->PostDelayedTask(
       FROM_HERE,
@@ -255,6 +247,7 @@
                                    const std::string& passphrase,
                                    const base::Closure& on_success,
                                    ErrorPtr* error) {
+  force_bootstrapping_ = false;
   CHECK(!hostapd_started_);
   if (hostapd_started_) {
     Error::AddTo(error, FROM_HERE, "wifi", "busy", "Running Access Point.");
@@ -265,26 +258,37 @@
                base::Time::Now() + base::TimeDelta::FromMinutes(1), on_success);
 }
 
-NetworkState NetworkImpl::GetConnectionState() const {
-  // Forced soft AP.
-  return NetworkState::kOffline;
-
+void NetworkImpl::UpdateNetworkState() {
+  network_state_ = NetworkState::kOffline;
+  if (force_bootstrapping_)
+    return;
   if (std::system("ping talk.google.com -c 1") == 0)
-    return NetworkState::kConnected;
+    network_state_ = NetworkState::kConnected;
+  else if (std::system("nmcli dev"))
+    network_state_ = NetworkState::kFailure;
+  else if (std::system("nmcli dev | grep connecting") == 0)
+    network_state_ = NetworkState::kConnecting;
 
-  if (std::system("nmcli dev"))
-    return NetworkState::kFailure;
+  task_runner_->PostDelayedTask(FROM_HERE,
+                                base::Bind(&NetworkImpl::UpdateNetworkState,
+                                           weak_ptr_factory_.GetWeakPtr()),
+                                base::TimeDelta::FromSeconds(10));
 
-  if (std::system("nmcli dev | grep connecting") == 0)
-    return NetworkState::kConnecting;
+  bool online = GetConnectionState() == NetworkState::kConnected;
+  for (const auto& cb : callbacks_)
+    cb.Run();
+}
 
-  return NetworkState::kOffline;
+NetworkState NetworkImpl::GetConnectionState() const {
+  return network_state_;
 }
 
 void NetworkImpl::EnableAccessPoint(const std::string& ssid) {
   if (hostapd_started_)
     return;
 
+  network_state_ = NetworkState::kOffline;
+
   // Release wlan0 interface.
   CHECK_EQ(0, std::system("nmcli nm wifi off"));
   CHECK_EQ(0, std::system("rfkill unblock wlan"));
@@ -319,10 +323,6 @@
   }
 
   CHECK_EQ(0, std::system(("dnsmasq --conf-file=" + dnsmasq_conf).c_str()));
-  task_runner_->PostDelayedTask(FROM_HERE,
-                                base::Bind(&NetworkImpl::NotifyNetworkChanged,
-                                           weak_ptr_factory_.GetWeakPtr()),
-                                {});
 }
 
 void NetworkImpl::DisableAccessPoint() {
@@ -330,16 +330,6 @@
   res = std::system("pkill -f hostapd.*/tmp/weave");
   CHECK_EQ(0, std::system("nmcli nm wifi on"));
   hostapd_started_ = false;
-
-  task_runner_->PostDelayedTask(FROM_HERE,
-                                base::Bind(&NetworkImpl::NotifyNetworkChanged,
-                                           weak_ptr_factory_.GetWeakPtr()),
-                                {});
-}
-
-void NetworkImpl::NotifyNetworkChanged() {
-  for (const auto& i : callbacks_)
-    i.Run();
 }
 
 void NetworkImpl::OpenSslSocket(
diff --git a/libweave/examples/ubuntu/network_manager.h b/libweave/examples/ubuntu/network_manager.h
index c9d6ff4..8abc80d 100644
--- a/libweave/examples/ubuntu/network_manager.h
+++ b/libweave/examples/ubuntu/network_manager.h
@@ -22,7 +22,7 @@
 // Production version of SSL socket needs secure server certificate check.
 class NetworkImpl : public Network {
  public:
-  explicit NetworkImpl(TaskRunner* task_runner);
+  explicit NetworkImpl(TaskRunner* task_runner, bool force_bootstrapping);
   ~NetworkImpl();
 
   void AddOnConnectionChangedCallback(
@@ -46,11 +46,13 @@
                     int pid,
                     base::Time until,
                     const base::Closure& on_success);
-  void NotifyNetworkChanged();
+  void UpdateNetworkState();
 
+  bool force_bootstrapping_{false};
   bool hostapd_started_{false};
   TaskRunner* task_runner_{nullptr};
   std::vector<OnConnectionChangedCallback> callbacks_;
+  NetworkState network_state_{NetworkState::kOffline};
 
   base::WeakPtrFactory<NetworkImpl> weak_ptr_factory_{this};
 };