Vitaly Buka | 1982bc8 | 2015-10-16 18:08:55 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Weave Authors. All rights reserved. |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Johan Euphrosine | 3523fdd | 2015-10-14 20:46:05 -0700 | [diff] [blame] | 5 | #include "examples/provider/event_network.h" |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 6 | |
| 7 | #include <weave/enum_to_string.h> |
| 8 | |
| 9 | #include <base/bind.h> |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 10 | #include <event2/bufferevent.h> |
Vitaly Buka | 34668e7 | 2015-12-15 14:46:47 -0800 | [diff] [blame] | 11 | #include <event2/dns.h> |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 12 | |
Johan Euphrosine | 3523fdd | 2015-10-14 20:46:05 -0700 | [diff] [blame] | 13 | #include "examples/provider/event_task_runner.h" |
| 14 | #include "examples/provider/ssl_stream.h" |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 15 | |
| 16 | namespace weave { |
| 17 | namespace examples { |
| 18 | |
| 19 | namespace { |
| 20 | const char kNetworkProbeHostname[] = "talk.google.com"; |
| 21 | const int kNetworkProbePort = 5223; |
Johan Euphrosine | 5c93de4 | 2015-10-15 00:17:14 -0700 | [diff] [blame] | 22 | const int kNetworkProbeTimeoutS = 2; |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 23 | } // namespace |
| 24 | |
| 25 | void EventNetworkImpl::Deleter::operator()(evdns_base* dns_base) { |
| 26 | evdns_base_free(dns_base, 0); |
| 27 | } |
| 28 | |
| 29 | void EventNetworkImpl::Deleter::operator()(bufferevent* bev) { |
| 30 | bufferevent_free(bev); |
| 31 | } |
| 32 | |
| 33 | EventNetworkImpl::EventNetworkImpl(EventTaskRunner* task_runner) |
| 34 | : task_runner_(task_runner) { |
| 35 | UpdateNetworkState(); |
| 36 | } |
| 37 | |
| 38 | void EventNetworkImpl::AddConnectionChangedCallback( |
| 39 | const ConnectionChangedCallback& callback) { |
| 40 | callbacks_.push_back(callback); |
| 41 | } |
| 42 | |
| 43 | void EventNetworkImpl::UpdateNetworkState() { |
Vitaly Buka | 3d8feaf | 2015-10-28 13:10:53 -0700 | [diff] [blame] | 44 | if (simulate_offline_) { |
| 45 | LOG(INFO) << "Simulating offline state"; |
| 46 | connectivity_probe_.reset(); |
| 47 | return UpdateNetworkStateCallback(State::kOffline); |
| 48 | } |
| 49 | |
| 50 | connectivity_probe_.reset( |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 51 | bufferevent_socket_new(task_runner_->GetEventBase(), -1, |
Vitaly Buka | 3d8feaf | 2015-10-28 13:10:53 -0700 | [diff] [blame] | 52 | BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS)); |
Johan Euphrosine | 5c93de4 | 2015-10-15 00:17:14 -0700 | [diff] [blame] | 53 | timeval timeout{kNetworkProbeTimeoutS, 0}; |
Vitaly Buka | 3d8feaf | 2015-10-28 13:10:53 -0700 | [diff] [blame] | 54 | bufferevent_set_timeouts(connectivity_probe_.get(), &timeout, &timeout); |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 55 | bufferevent_setcb( |
Vitaly Buka | 3d8feaf | 2015-10-28 13:10:53 -0700 | [diff] [blame] | 56 | connectivity_probe_.get(), nullptr, nullptr, |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 57 | [](struct bufferevent* buf, short events, void* ctx) { |
| 58 | EventNetworkImpl* network = static_cast<EventNetworkImpl*>(ctx); |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 59 | if (events & BEV_EVENT_CONNECTED) { |
| 60 | network->UpdateNetworkStateCallback(State::kOnline); |
| 61 | return; |
| 62 | } |
| 63 | if (events & (BEV_EVENT_ERROR | BEV_EVENT_EOF | BEV_EVENT_TIMEOUT)) { |
Vitaly Buka | 3d8feaf | 2015-10-28 13:10:53 -0700 | [diff] [blame] | 64 | int err = bufferevent_socket_get_dns_error(buf); |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 65 | if (err) { |
| 66 | LOG(ERROR) << "network connect dns error: " |
| 67 | << evutil_gai_strerror(err); |
| 68 | } |
| 69 | network->UpdateNetworkStateCallback(State::kOffline); |
| 70 | return; |
| 71 | } |
| 72 | }, |
| 73 | this); |
Vitaly Buka | 3d8feaf | 2015-10-28 13:10:53 -0700 | [diff] [blame] | 74 | int err = bufferevent_socket_connect_hostname( |
| 75 | connectivity_probe_.get(), dns_base_.get(), AF_INET, |
| 76 | kNetworkProbeHostname, kNetworkProbePort); |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 77 | if (err) { |
| 78 | LOG(ERROR) << " network connect socket error: " << evutil_gai_strerror(err); |
Vitaly Buka | 3d8feaf | 2015-10-28 13:10:53 -0700 | [diff] [blame] | 79 | return UpdateNetworkStateCallback(State::kOffline); |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 80 | } |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | void EventNetworkImpl::UpdateNetworkStateCallback( |
| 84 | provider::Network::State state) { |
Johan Euphrosine | 1ca3c22 | 2015-10-15 20:43:42 -0700 | [diff] [blame] | 85 | if (state != network_state_) { |
| 86 | LOG(INFO) << "network state updated: " << weave::EnumToString(state); |
| 87 | network_state_ = state; |
Vitaly Buka | 1f4308f | 2015-10-16 10:20:46 -0700 | [diff] [blame] | 88 | |
| 89 | // In general it's better to send false notification than miss one. |
| 90 | // However current implementation can only send them very often on every |
| 91 | // UpdateNetworkStateCallback or just here, guarder with this if condition. |
| 92 | for (const auto& cb : callbacks_) |
| 93 | cb.Run(); |
Johan Euphrosine | 1ca3c22 | 2015-10-15 20:43:42 -0700 | [diff] [blame] | 94 | } |
Vitaly Buka | 1f4308f | 2015-10-16 10:20:46 -0700 | [diff] [blame] | 95 | |
Vitaly Buka | 3d8feaf | 2015-10-28 13:10:53 -0700 | [diff] [blame] | 96 | // Reset current posted task. |
| 97 | weak_ptr_factory_.InvalidateWeakPtrs(); |
| 98 | |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 99 | // TODO(proppy): use netlink interface event instead of polling |
| 100 | task_runner_->PostDelayedTask( |
| 101 | FROM_HERE, base::Bind(&EventNetworkImpl::UpdateNetworkState, |
| 102 | weak_ptr_factory_.GetWeakPtr()), |
| 103 | base::TimeDelta::FromSeconds(10)); |
| 104 | } |
| 105 | |
| 106 | weave::provider::Network::State EventNetworkImpl::GetConnectionState() const { |
| 107 | return network_state_; |
| 108 | } |
| 109 | |
| 110 | void EventNetworkImpl::OpenSslSocket(const std::string& host, |
| 111 | uint16_t port, |
| 112 | const OpenSslSocketCallback& callback) { |
Vitaly Buka | 10e69bc | 2015-10-16 01:21:07 -0700 | [diff] [blame] | 113 | SSLStream::Connect(task_runner_, host, port, callback); |
Johan Euphrosine | ee020ee | 2015-10-12 12:49:16 -0700 | [diff] [blame] | 114 | } |
| 115 | |
| 116 | } // namespace examples |
| 117 | } // namespace weave |