summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.h
blob: 7faf873f87a9e244486420a86c397b49ac8550e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright (c) 2019 The Chromium 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 QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_H_
#define QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_H_

#include <netinet/icmp6.h>

#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_ip_address.h"
#include "quic/platform/api/quic_mutex.h"
#include "quic/qbone/bonnet/icmp_reachable_interface.h"
#include "quic/qbone/platform/kernel_interface.h"

namespace quic {

extern const char kUnknownSource[];
extern const char kNoSource[];

// IcmpReachable schedules itself with an EpollServer, periodically sending
// ICMPv6 Echo Requests to the given |destination| on the interface that the
// given |source| is bound to. Echo Requests are sent once every |timeout|.
// On Echo Replies, timeouts, and I/O errors, the given |stats| object will
// be called back with details of the event.
class IcmpReachable : public IcmpReachableInterface {
 public:
  enum Status { REACHABLE, UNREACHABLE };

  struct ReachableEvent {
    Status status;
    absl::Duration response_time;
    std::string source;
  };

  class StatsInterface {
   public:
    StatsInterface() = default;

    StatsInterface(const StatsInterface&) = delete;
    StatsInterface& operator=(const StatsInterface&) = delete;

    StatsInterface(StatsInterface&&) = delete;
    StatsInterface& operator=(StatsInterface&&) = delete;

    virtual ~StatsInterface() = default;

    virtual void OnEvent(ReachableEvent event) = 0;

    virtual void OnReadError(int error) = 0;

    virtual void OnWriteError(int error) = 0;
  };

  // |source| is the IPv6 address bound to the interface that IcmpReachable will
  //          send Echo Requests on.
  // |destination| is the IPv6 address of the destination of the Echo Requests.
  // |timeout| is the duration IcmpReachable will wait between Echo Requests.
  //           If no Echo Response is received by the next Echo Request, it will
  //           be considered a timeout.
  // |kernel| is not owned, but should outlive this instance.
  // |epoll_server| is not owned, but should outlive this instance.
  //                IcmpReachable's Init() must be called from within the Epoll
  //                Server's thread.
  // |stats| is not owned, but should outlive this instance. It will be called
  //         back on Echo Replies, timeouts, and I/O errors.
  IcmpReachable(QuicIpAddress source,
                QuicIpAddress destination,
                absl::Duration timeout,
                KernelInterface* kernel,
                QuicEpollServer* epoll_server,
                StatsInterface* stats);

  ~IcmpReachable() override;

  // Initializes this reachability probe. Must be called from within the
  // |epoll_server|'s thread.
  bool Init() QUIC_LOCKS_EXCLUDED(header_lock_) override;

  int64 /* allow-non-std-int */ OnAlarm()
      QUIC_LOCKS_EXCLUDED(header_lock_) override;

  static absl::string_view StatusName(Status status);

 private:
  class EpollCallback : public QuicEpollCallbackInterface {
   public:
    explicit EpollCallback(IcmpReachable* reachable) : reachable_(reachable) {}

    EpollCallback(const EpollCallback&) = delete;
    EpollCallback& operator=(const EpollCallback&) = delete;

    EpollCallback(EpollCallback&&) = delete;
    EpollCallback& operator=(EpollCallback&&) = delete;

    void OnRegistration(QuicEpollServer* eps,
                        int fd,
                        int event_mask) override{};

    void OnModification(int fd, int event_mask) override{};

    void OnEvent(int fd, QuicEpollEvent* event) override;

    void OnUnregistration(int fd, bool replaced) override{};

    void OnShutdown(QuicEpollServer* eps, int fd) override;

    std::string Name() const override;

   private:
    IcmpReachable* reachable_;
  };

  bool OnEvent(int fd) QUIC_LOCKS_EXCLUDED(header_lock_);

  const absl::Duration timeout_;

  EpollCallback cb_;

  sockaddr_in6 src_{};
  sockaddr_in6 dst_{};

  KernelInterface* kernel_;
  QuicEpollServer* epoll_server_;

  StatsInterface* stats_;

  int send_fd_;
  int recv_fd_;

  QuicMutex header_lock_;
  icmp6_hdr icmp_header_ QUIC_GUARDED_BY(header_lock_){};

  absl::Time start_ = absl::InfinitePast();
  absl::Time end_ = absl::InfinitePast();
};

}  // namespace quic

#endif  // QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_H_