blob: 2ad529e3b8749fa1cae7bdac762f11ed6e9ffae4 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHILL_CONNECTION_
#define SHILL_CONNECTION_
#include <deque>
#include <string>
#include <vector>
#include <base/memory/ref_counted.h>
#include <base/memory/weak_ptr.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include "shill/ip_address.h"
#include "shill/ipconfig.h"
#include "shill/refptr_types.h"
#include "shill/technology.h"
namespace shill {
class DeviceInfo;
class RTNLHandler;
class Resolver;
class RoutingTable;
struct RoutingTableEntry;
// The Conneciton maintains the implemented state of an IPConfig, e.g,
// the IP address, routing table and DNS table entries.
class Connection : public base::RefCounted<Connection> {
public:
// Clients can instantiate and use Binder to bind to a Connection and get
// notified when the bound Connection disconnects. Note that the client's
// disconnect callback will be executed at most once, and only if the bound
// Connection is destroyed or signals disconnect. The Binder unbinds itself
// from the underlying Connection when the Binder instance is destructed.
class Binder {
public:
Binder(const std::string &name, const base::Closure &disconnect_callback);
~Binder();
// Binds to |to_connection|. Unbinds the previous bound connection, if
// any. Pass NULL to just unbind this Binder.
void Attach(const ConnectionRefPtr &to_connection);
const std::string &name() const { return name_; }
bool IsBound() const { return connection_ != NULL; }
ConnectionRefPtr connection() const { return connection_.get(); }
private:
friend class Connection;
FRIEND_TEST(ConnectionTest, Binder);
// Invoked by |connection_|.
void OnDisconnect();
const std::string name_;
base::WeakPtr<Connection> connection_;
const base::Closure client_disconnect_callback_;
DISALLOW_COPY_AND_ASSIGN(Binder);
};
Connection(int interface_index,
const std::string &interface_name,
Technology::Identifier technology_,
const DeviceInfo *device_info);
// Add the contents of an IPConfig reference to the list of managed state.
// This will replace all previous state for this address family.
virtual void UpdateFromIPConfig(const IPConfigRefPtr &config);
// Return the connection used by the lower binder.
virtual ConnectionRefPtr GetLowerConnection() const {
return lower_binder_.connection();
}
// Sets the current connection as "default", i.e., routes and DNS entries
// should be used by all system components that don't select explicitly.
virtual bool is_default() const { return is_default_; }
virtual void SetIsDefault(bool is_default);
virtual const std::string &interface_name() const { return interface_name_; }
virtual int interface_index() const { return interface_index_; }
virtual const std::vector<std::string> &dns_servers() const {
return dns_servers_;
}
virtual const std::string &ipconfig_rpc_identifier() const {
return ipconfig_rpc_identifier_;
}
// Request to accept traffic routed to this connection even if it is not
// the default. This request is ref-counted so the caller must call
// ReleaseRouting() when they no longer need this facility.
virtual void RequestRouting();
virtual void ReleaseRouting();
// Request a host route through this connection.
virtual bool RequestHostRoute(const IPAddress &destination);
virtual const IPAddress &local() const { return local_; }
virtual const IPAddress &gateway() const { return gateway_; }
virtual Technology::Identifier technology() const { return technology_; }
// Return the lowest connection on which this connection depends. In case of
// error, a NULL is returned.
virtual ConnectionRefPtr GetCarrierConnection();
protected:
friend class base::RefCounted<Connection>;
virtual ~Connection();
virtual bool CreateGatewayRoute();
private:
friend class ConnectionTest;
FRIEND_TEST(ConnectionTest, AddConfig);
FRIEND_TEST(ConnectionTest, Binder);
FRIEND_TEST(ConnectionTest, Binders);
FRIEND_TEST(ConnectionTest, Destructor);
FRIEND_TEST(ConnectionTest, FixGatewayReachability);
FRIEND_TEST(ConnectionTest, GetCarrierConnection);
FRIEND_TEST(ConnectionTest, InitState);
FRIEND_TEST(ConnectionTest, OnRouteQueryResponse);
FRIEND_TEST(ConnectionTest, RequestHostRoute);
FRIEND_TEST(ConnectionTest, BlackholeIPv6);
FRIEND_TEST(VPNServiceTest, OnConnectionDisconnected);
static const uint32 kDefaultMetric;
static const uint32 kNonDefaultMetricBase;
// Work around misconfigured servers which provide a gateway address that
// is unreachable with the provided netmask.
static bool FixGatewayReachability(IPAddress *local,
IPAddress *peer,
IPAddress *gateway,
const IPAddress &trusted_ip);
uint32 GetMetric(bool is_default);
bool PinHostRoute(const IPAddress &trusted_ip, const IPAddress &gateway);
void OnRouteQueryResponse(int interface_index,
const RoutingTableEntry &entry);
void AttachBinder(Binder *binder);
void DetachBinder(Binder *binder);
void NotifyBindersOnDisconnect();
void OnLowerDisconnect();
// Send our DNS configuration to the resolver.
void PushDNSConfig();
base::WeakPtrFactory<Connection> weak_ptr_factory_;
bool is_default_;
bool has_broadcast_domain_;
int routing_request_count_;
int interface_index_;
const std::string interface_name_;
Technology::Identifier technology_;
std::vector<std::string> dns_servers_;
std::vector<std::string> dns_domain_search_;
std::string dns_domain_name_;
std::string ipconfig_rpc_identifier_;
IPAddress local_;
IPAddress gateway_;
// A binder to a lower Connection that this Connection depends on, if any.
Binder lower_binder_;
// Binders to clients -- usually to upper connections or related services and
// devices.
std::deque<Binder *> binders_;
// Store cached copies of singletons for speed/ease of testing
const DeviceInfo *device_info_;
Resolver *resolver_;
RoutingTable *routing_table_;
RTNLHandler *rtnl_handler_;
DISALLOW_COPY_AND_ASSIGN(Connection);
};
} // namespace shill
#endif // SHILL_CONNECTION_