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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
/*
* Copyright (c) 2018 Xevo Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the
* distribution.
*
* Neither the names of the copyright holders nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TCP_PLATFORM_SPECIFIC_LINUX_PLATFORM_SPECIFIC_NETWORK_INTERFACE_LISTENER_H_
#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TCP_PLATFORM_SPECIFIC_LINUX_PLATFORM_SPECIFIC_NETWORK_INTERFACE_LISTENER_H_
#include <map>
#include <string>
#include <vector>
#include <netinet/in.h>
#include "transport_manager/tcp/network_interface_listener.h"
#include "utils/macro.h"
#include "utils/threads/thread_delegate.h"
struct ifaddrmsg;
namespace transport_manager {
namespace transport_adapter {
class TcpClientListener;
/**
* @brief Struct to keep network interface's status flags and IP addresses
*/
class InterfaceStatus {
public:
InterfaceStatus() : flags_(0), has_ipv4_(false), has_ipv6_(false) {}
~InterfaceStatus() {}
bool IsAvailable() const;
bool IsLoopback() const;
// only for debugging output
unsigned int GetFlags() const {
return flags_;
}
bool HasIPAddress() const;
std::string GetIPv4Address() const;
std::string GetIPv6Address() const;
void SetFlags(unsigned int flags) {
flags_ = flags;
}
// specify NULL to remove existing address
void SetIPv4Address(struct in_addr* addr);
void SetIPv6Address(struct in6_addr* addr);
private:
unsigned int flags_;
bool has_ipv4_;
bool has_ipv6_;
struct in_addr ipv4_address_;
struct in6_addr ipv6_address_;
};
typedef std::map<std::string, InterfaceStatus> InterfaceStatusTable;
/**
* @brief Listener to detect various events on network interfaces
*/
class PlatformSpecificNetworkInterfaceListener
: public NetworkInterfaceListener {
public:
/**
* @brief Constructor
*
* @param tcp_client_listener an instance of TcpClientListener which receives
* status updates
* @param designated_interface if we want to listen only on a specific
* network interface, specify its name
*/
PlatformSpecificNetworkInterfaceListener(
TcpClientListener* tcp_client_listener,
const std::string designated_interface = "");
/**
* @brief Destructor
*/
virtual ~PlatformSpecificNetworkInterfaceListener();
/**
* @brief Initialize this listener
*/
bool Init() OVERRIDE;
/**
* @brief Deinitialize this listener
*/
void Deinit() OVERRIDE;
/**
* @brief Start this listener
*/
bool Start() OVERRIDE;
/**
* @brief Stop this listener
*/
bool Stop() OVERRIDE;
#ifdef BUILD_TESTS
void SetTesting(bool enabled) {
testing_ = enabled;
}
int GetSocket() const {
return socket_;
}
threads::Thread* GetThread() const {
return thread_;
}
void OverwriteStatusTable(const InterfaceStatusTable dummy_table) {
status_table_ = dummy_table;
}
void testCallNotifyIPAddresses() {
NotifyIPAddresses();
}
const std::string& GetSelectedInterfaceName() const {
return selected_interface_;
}
#endif // BUILD_TESTS
private:
// Struct to hold an event on a network interface.
// The event can be either an update on flags or an update on IP address.
struct EventParam {
unsigned int if_index;
unsigned int flags;
struct sockaddr_storage address;
EventParam(int interface_index, unsigned int interface_flags = 0)
: if_index(interface_index), flags(interface_flags) {}
};
// parent class which we will notify the events to
TcpClientListener* tcp_client_listener_;
// if configured, NetworkInterfaceListener will always look into the IP
// addresses of this interface
const std::string designated_interface_;
// a map to store status of each interface
InterfaceStatusTable status_table_;
// this is the name of the interface we are currently focusing on
std::string selected_interface_;
// previous IP addresses that we have notified
std::string notified_ipv4_addr_;
std::string notified_ipv6_addr_;
int socket_;
int pipe_fds_[2];
threads::Thread* thread_;
#ifdef BUILD_TESTS
bool testing_;
#endif
void Loop();
bool StopLoop();
// reset status_table_ by fetching current status of each interface
bool InitializeStatus();
// update status_table_ by applying the events
bool UpdateStatus(uint16_t type, std::vector<EventParam>& params);
// update notified_ipv4_addr_ and notified_ipv6_addr_ then notify the parent
// class of the change if necessary
void NotifyIPAddresses();
// Select an appropriate network interface that we will get IP addresses. Also
// update selected_interface_.
const std::string SelectInterface();
// convert ifaddrmsg to a list of EventParam structs
std::vector<EventParam> ParseIFAddrMessage(struct ifaddrmsg* message,
unsigned int size);
// for debugging
void DumpTable() const;
class ListenerThreadDelegate : public threads::ThreadDelegate {
public:
explicit ListenerThreadDelegate(
PlatformSpecificNetworkInterfaceListener* parent);
virtual void threadMain();
void exitThreadMain();
private:
PlatformSpecificNetworkInterfaceListener* parent_;
};
DISALLOW_COPY_AND_ASSIGN(PlatformSpecificNetworkInterfaceListener);
};
} // namespace transport_adapter
} // namespace transport_manager
#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TCP_PLATFORM_SPECIFIC_LINUX_PLATFORM_SPECIFIC_NETWORK_INTERFACE_LISTENER_H_
|