Fix -bootstrapping option

Option was broken when event network was extracted from wifi manager.
Also fixed connectivity prober lifetime. Existing code was able to call
callback test by bufferevent_setcb even after EventNetworkImpl was
destroyed.

Change-Id: I774f37a55f0126fe384317ab69f077fa7817e923
Reviewed-on: https://weave-review.googlesource.com/1432
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/libweave/examples/daemon/main.cc b/libweave/examples/daemon/main.cc
index 3a4efe7..a4ec366 100644
--- a/libweave/examples/daemon/main.cc
+++ b/libweave/examples/daemon/main.cc
@@ -103,11 +103,12 @@
   std::unique_ptr<weave::examples::WifiImpl> wifi;
 
   if (!disable_privet) {
+    network.SetSimulateOffline(force_bootstrapping);
+
     dns_sd.reset(new weave::examples::AvahiClient);
     http_server.reset(new weave::examples::HttpServerImpl{&task_runner});
     if (weave::examples::WifiImpl::HasWifiCapability())
-      wifi.reset(
-          new weave::examples::WifiImpl{&task_runner, force_bootstrapping});
+      wifi.reset(new weave::examples::WifiImpl{&task_runner, &network});
   }
   std::unique_ptr<weave::Device> device{weave::Device::Create(
       &config_store, &task_runner, &http_client, &network, dns_sd.get(),
diff --git a/libweave/examples/provider/event_network.cc b/libweave/examples/provider/event_network.cc
index d86db69..ba03e8f 100644
--- a/libweave/examples/provider/event_network.cc
+++ b/libweave/examples/provider/event_network.cc
@@ -41,22 +41,27 @@
 }
 
 void EventNetworkImpl::UpdateNetworkState() {
-  std::unique_ptr<bufferevent, Deleter> bev{
+  if (simulate_offline_) {
+    LOG(INFO) << "Simulating offline state";
+    connectivity_probe_.reset();
+    return UpdateNetworkStateCallback(State::kOffline);
+  }
+
+  connectivity_probe_.reset(
       bufferevent_socket_new(task_runner_->GetEventBase(), -1,
-                             BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS)};
+                             BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS));
   timeval timeout{kNetworkProbeTimeoutS, 0};
-  bufferevent_set_timeouts(bev.get(), &timeout, &timeout);
+  bufferevent_set_timeouts(connectivity_probe_.get(), &timeout, &timeout);
   bufferevent_setcb(
-      bev.get(), nullptr, nullptr,
+      connectivity_probe_.get(), nullptr, nullptr,
       [](struct bufferevent* buf, short events, void* ctx) {
         EventNetworkImpl* network = static_cast<EventNetworkImpl*>(ctx);
-        std::unique_ptr<bufferevent, Deleter> bev{buf};
         if (events & BEV_EVENT_CONNECTED) {
           network->UpdateNetworkStateCallback(State::kOnline);
           return;
         }
         if (events & (BEV_EVENT_ERROR | BEV_EVENT_EOF | BEV_EVENT_TIMEOUT)) {
-          int err = bufferevent_socket_get_dns_error(bev.get());
+          int err = bufferevent_socket_get_dns_error(buf);
           if (err) {
             LOG(ERROR) << "network connect dns error: "
                        << evutil_gai_strerror(err);
@@ -66,16 +71,13 @@
         }
       },
       this);
-  int err = bufferevent_socket_connect_hostname(bev.get(), dns_base_.get(),
-                                                AF_INET, kNetworkProbeHostname,
-                                                kNetworkProbePort);
+  int err = bufferevent_socket_connect_hostname(
+      connectivity_probe_.get(), dns_base_.get(), AF_INET,
+      kNetworkProbeHostname, kNetworkProbePort);
   if (err) {
     LOG(ERROR) << " network connect socket error: " << evutil_gai_strerror(err);
-    UpdateNetworkStateCallback(State::kOffline);
-    return;
+    return UpdateNetworkStateCallback(State::kOffline);
   }
-  // release the bufferevent, so that the eventcallback can free it.
-  bev.release();
 }
 
 void EventNetworkImpl::UpdateNetworkStateCallback(
@@ -91,6 +93,9 @@
       cb.Run();
   }
 
+  // Reset current posted task.
+  weak_ptr_factory_.InvalidateWeakPtrs();
+
   // TODO(proppy): use netlink interface event instead of polling
   task_runner_->PostDelayedTask(
       FROM_HERE, base::Bind(&EventNetworkImpl::UpdateNetworkState,
diff --git a/libweave/examples/provider/event_network.h b/libweave/examples/provider/event_network.h
index 79c458c..3aeac24 100644
--- a/libweave/examples/provider/event_network.h
+++ b/libweave/examples/provider/event_network.h
@@ -33,13 +33,21 @@
                      uint16_t port,
                      const OpenSslSocketCallback& callback) override;
 
+  void SetSimulateOffline(bool value) {
+    simulate_offline_ = value;
+    UpdateNetworkState();
+  }
+
  private:
   void UpdateNetworkState();
   void UpdateNetworkStateCallback(provider::Network::State state);
+  bool simulate_offline_{false};
   EventTaskRunner* task_runner_{nullptr};
   std::unique_ptr<evdns_base, Deleter> dns_base_;
   std::vector<ConnectionChangedCallback> callbacks_;
   provider::Network::State network_state_{provider::Network::State::kOffline};
+  std::unique_ptr<bufferevent, Deleter> connectivity_probe_;
+
   base::WeakPtrFactory<EventNetworkImpl> weak_ptr_factory_{this};
 };
 
diff --git a/libweave/examples/provider/wifi_manager.cc b/libweave/examples/provider/wifi_manager.cc
index c70aad4..6e216e4 100644
--- a/libweave/examples/provider/wifi_manager.cc
+++ b/libweave/examples/provider/wifi_manager.cc
@@ -14,6 +14,7 @@
 #include <base/bind.h>
 #include <weave/provider/task_runner.h>
 
+#include "examples/provider/event_network.h"
 #include "examples/provider/ssl_stream.h"
 
 namespace weave {
@@ -39,8 +40,8 @@
 
 }  // namespace
 
-WifiImpl::WifiImpl(provider::TaskRunner* task_runner, bool force_bootstrapping)
-    : force_bootstrapping_{force_bootstrapping}, task_runner_{task_runner} {
+WifiImpl::WifiImpl(provider::TaskRunner* task_runner, EventNetworkImpl* network)
+    : task_runner_{task_runner}, network_{network} {
   CHECK_EQ(0, getuid())
       << "WiFi manager expects root access to control WiFi capabilities";
   StopAccessPoint();
@@ -100,7 +101,7 @@
 void WifiImpl::Connect(const std::string& ssid,
                        const std::string& passphrase,
                        const DoneCallback& callback) {
-  force_bootstrapping_ = false;
+  network_->SetSimulateOffline(false);
   CHECK(!hostapd_started_);
   if (hostapd_started_) {
     ErrorPtr error;
diff --git a/libweave/examples/provider/wifi_manager.h b/libweave/examples/provider/wifi_manager.h
index 849beef..c043523 100644
--- a/libweave/examples/provider/wifi_manager.h
+++ b/libweave/examples/provider/wifi_manager.h
@@ -20,12 +20,13 @@
 
 namespace examples {
 
+class EventNetworkImpl;
+
 // Basic weave::Wifi implementation.
 // Production version of SSL socket needs secure server certificate check.
 class WifiImpl : public provider::Wifi {
  public:
-  explicit WifiImpl(provider::TaskRunner* task_runner,
-                    bool force_bootstrapping);
+  WifiImpl(provider::TaskRunner* task_runner, EventNetworkImpl* network);
   ~WifiImpl();
 
   // Wifi implementation.
@@ -43,9 +44,9 @@
                     int pid,
                     base::Time until,
                     const DoneCallback& callback);
-  bool force_bootstrapping_{false};
   bool hostapd_started_{false};
   provider::TaskRunner* task_runner_{nullptr};
+  EventNetworkImpl* network_{nullptr};
   base::WeakPtrFactory<WifiImpl> weak_ptr_factory_{this};
 };