blob: d121fcaca220a4472b7a64f4c4b588eee6c9688a [file] [log] [blame]
Johan Euphrosine400f2e72015-10-05 16:17:20 -07001// Copyright 2015 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "examples/ubuntu/netlink_network.h"
6
7#include <weave/provider/task_runner.h>
8#include <base/bind.h>
9#include <netlink/route/link.h>
10
11#include "examples/ubuntu/ssl_stream.h"
12
13namespace weave {
14namespace examples {
15
16void NetlinkNetworkImpl::Deleter::operator()(nl_sock* s) {
17 nl_close(s);
18 nl_socket_free(s);
19}
20
21void NetlinkNetworkImpl::Deleter::operator()(nl_cache* c) {
22 nl_cache_put(c);
23}
24
25void NetlinkNetworkImpl::Deleter::operator()(rtnl_link* l) {
26 rtnl_link_put(l);
27}
28
29NetlinkNetworkImpl::NetlinkNetworkImpl(weave::provider::TaskRunner* task_runner)
30 : task_runner_(task_runner) {
31 nl_sock_.reset(nl_socket_alloc());
32 CHECK(nl_sock_);
33 CHECK_EQ(nl_connect(nl_sock_.get(), NETLINK_ROUTE), 0);
34 nl_cache* nl_cache;
35 CHECK_EQ(rtnl_link_alloc_cache(nl_sock_.get(), AF_UNSPEC, &nl_cache), 0);
36 nl_cache_.reset(nl_cache);
37 UpdateNetworkState();
38}
39
40void NetlinkNetworkImpl::AddConnectionChangedCallback(
41 const ConnectionChangedCallback& callback) {
42 callbacks_.push_back(callback);
43}
44
45void NetlinkNetworkImpl::UpdateNetworkState() {
46 // TODO(proppy): pick up interface with the default route instead of index 0.
47 // TODO(proppy): test actual internet connection.
48 // TODO(proppy): subscribe to interface changes instead of polling.
49 network_state_ = GetInterfaceState(0);
50 task_runner_->PostDelayedTask(
51 FROM_HERE, base::Bind(&NetlinkNetworkImpl::UpdateNetworkState,
52 weak_ptr_factory_.GetWeakPtr()),
53 base::TimeDelta::FromSeconds(10));
54 for (const auto& cb : callbacks_)
55 cb.Run();
56}
57
58weave::provider::Network::State NetlinkNetworkImpl::GetInterfaceState(
59 int if_index) {
60 auto refill_result = nl_cache_refill(nl_sock_.get(), nl_cache_.get());
61 if (refill_result < 0) {
62 LOG(ERROR) << "failed to refresh netlink cache: " << refill_result;
Vitaly Bukaefad5b22015-10-08 10:02:14 -070063 return Network::State::kError;
Johan Euphrosine400f2e72015-10-05 16:17:20 -070064 }
65 std::unique_ptr<rtnl_link, Deleter> nl_link{
66 rtnl_link_get(nl_cache_.get(), if_index)};
67 if (!nl_link) {
68 LOG(ERROR) << "failed to get interface 0";
Vitaly Bukaefad5b22015-10-08 10:02:14 -070069 return Network::State::kError;
Johan Euphrosine400f2e72015-10-05 16:17:20 -070070 }
71
72 int state = rtnl_link_get_operstate(nl_link.get());
73 switch (state) {
74 case IF_OPER_DOWN:
75 case IF_OPER_LOWERLAYERDOWN:
76 return Network::State::kOffline;
77 case IF_OPER_DORMANT:
78 return Network::State::kConnecting;
79 case IF_OPER_UP:
Vitaly Bukaefad5b22015-10-08 10:02:14 -070080 return Network::State::kOnline;
Johan Euphrosine400f2e72015-10-05 16:17:20 -070081 case IF_OPER_TESTING:
82 case IF_OPER_NOTPRESENT:
83 case IF_OPER_UNKNOWN:
84 default:
85 LOG(ERROR) << "unknown interface state: " << state;
Vitaly Bukaefad5b22015-10-08 10:02:14 -070086 return Network::State::kError;
Johan Euphrosine400f2e72015-10-05 16:17:20 -070087 }
88}
89
90weave::provider::Network::State NetlinkNetworkImpl::GetConnectionState() const {
91 return network_state_;
92}
93
94void NetlinkNetworkImpl::OpenSslSocket(
95 const std::string& host,
96 uint16_t port,
97 const OpenSslSocketSuccessCallback& success_callback,
98 const ErrorCallback& error_callback) {
99 // Connect to SSL port instead of upgrading to TLS.
100 std::unique_ptr<SSLStream> tls_stream{new SSLStream{task_runner_}};
101
102 if (tls_stream->Init(host, port)) {
103 task_runner_->PostDelayedTask(
104 FROM_HERE, base::Bind(success_callback, base::Passed(&tls_stream)), {});
105 } else {
106 ErrorPtr error;
107 Error::AddTo(&error, FROM_HERE, "tls", "tls_init_failed",
108 "Failed to initialize TLS stream.");
109 task_runner_->PostDelayedTask(FROM_HERE,
110 base::Bind(error_callback, error.get()), {});
111 }
112}
113
114} // namespace examples
115} // namespace weave