// 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_ROUTING_TABLE_H_
#define SHILL_ROUTING_TABLE_H_

#include <deque>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include <base/callback.h>
#include <base/lazy_instance.h>
#include <base/memory/ref_counted.h>

#include "shill/ip_address.h"
#include "shill/refptr_types.h"
#include "shill/rtnl_message.h"

namespace shill {

class RTNLHandler;
class RTNLListener;
struct RoutingTableEntry;

// This singleton maintains an in-process copy of the routing table on
// a per-interface basis.  It offers the ability for other modules to
// make modifications to the routing table, centered around setting the
// default route for an interface or modifying its metric (priority).
class RoutingTable {
 public:
  typedef std::vector<RoutingTableEntry> TableEntryVector;
  typedef std::unordered_map<int, TableEntryVector> Tables;

  struct Query {
    // Callback::Run(interface_index, entry)
    typedef base::Callback<void(int, const RoutingTableEntry &)> Callback;

    Query() : sequence(0), tag(0) {}
    Query(uint32_t sequence_in,
          int tag_in,
          Callback callback_in)
        : sequence(sequence_in),
          tag(tag_in),
          callback(callback_in) {}

    uint32_t sequence;
    int tag;
    Callback callback;
  };

  virtual ~RoutingTable();

  static RoutingTable *GetInstance();

  virtual void Start();
  virtual void Stop();

  // Add an entry to the routing table.
  virtual bool AddRoute(int interface_index, const RoutingTableEntry &entry);

  // Get the default route associated with an interface of a given addr family.
  // The route is copied into |*entry|.
  virtual bool GetDefaultRoute(int interface_index,
                               IPAddress::Family family,
                               RoutingTableEntry *entry);

  // Set the default route for an interface with index |interface_index|,
  // given the IPAddress of the gateway |gateway_address| and priority
  // |metric|.
  virtual bool SetDefaultRoute(int interface_index,
                               const IPAddress &gateway_address,
                               uint32_t metric);

  // Configure routing table entries from the "routes" portion of |ipconfig|.
  // Returns true if all routes were installed successfully, false otherwise.
  virtual bool ConfigureRoutes(int interface_index,
                               const IPConfigRefPtr &ipconfig,
                               uint32_t metric);

  // Create a blackhole route for a given IP family.  Returns true
  // on successfully sending the route request, false otherwise.
  virtual bool CreateBlackholeRoute(int interface_index,
                                    IPAddress::Family family,
                                    uint32_t metric);

  // Create a route to a link-attached remote host.  |remote_address|
  // must be directly reachable from |local_address|.  Returns true
  // on successfully sending the route request, false otherwise.
  virtual bool CreateLinkRoute(int interface_index,
                               const IPAddress &local_address,
                               const IPAddress &remote_address);

  // Remove routes associated with interface.
  // Route entries are immediately purged from our copy of the routing table.
  virtual void FlushRoutes(int interface_index);

  // Iterate over all routing tables removing routes tagged with |tag|.
  // Route entries are immediately purged from our copy of the routing table.
  virtual void FlushRoutesWithTag(int tag);

  // Flush the routing cache for all interfaces.
  virtual bool FlushCache();

  // Reset local state for this interface.
  virtual void ResetTable(int interface_index);

  // Set the metric (priority) on existing default routes for an interface.
  virtual void SetDefaultMetric(int interface_index, uint32_t metric);

  // Get the default route to |destination| through |interface_index| and create
  // a host route to that destination.  When creating the route, tag our local
  // entry with |tag|, so we can remove it later.  Connections use their
  // interface index as the tag, so that as they are destroyed, they can remove
  // all their dependent routes.  If |callback| is not null, it will be invoked
  // when the request-route response is received and the add-route request has
  // been sent successfully.
  virtual bool RequestRouteToHost(const IPAddress &destination,
                                  int interface_index,
                                  int tag,
                                  const Query::Callback &callback);

 protected:
  RoutingTable();

 private:
  friend struct base::DefaultLazyInstanceTraits<RoutingTable>;
  friend class RoutingTableTest;

  static bool ParseRoutingTableMessage(const RTNLMessage &message,
                                       int *interface_index,
                                       RoutingTableEntry *entry);
  void RouteMsgHandler(const RTNLMessage &msg);
  bool ApplyRoute(uint32_t interface_index,
                  const RoutingTableEntry &entry,
                  RTNLMessage::Mode mode,
                  unsigned int flags);
  // Get the default route associated with an interface of a given addr family.
  // A pointer to the route is placed in |*entry|.
  virtual bool GetDefaultRouteInternal(int interface_index,
                               IPAddress::Family family,
                               RoutingTableEntry **entry);

  void ReplaceMetric(uint32_t interface_index,
                     RoutingTableEntry *entry,
                     uint32_t metric);

  static const char kRouteFlushPath4[];
  static const char kRouteFlushPath6[];

  Tables tables_;

  base::Callback<void(const RTNLMessage &)> route_callback_;
  std::unique_ptr<RTNLListener> route_listener_;
  std::deque<Query> route_queries_;

  // Cache singleton pointer for performance and test purposes.
  RTNLHandler *rtnl_handler_;

  DISALLOW_COPY_AND_ASSIGN(RoutingTable);
};

}  // namespace shill

#endif  // SHILL_ROUTING_TABLE_H_
