summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorAlexander <akutsan@luxoft.com>2018-06-08 11:00:26 +0300
committerAlexander <akutsan@luxoft.com>2018-06-11 13:30:58 +0300
commit7068453fe5919c8379cd0deb6fd9c077313a70e5 (patch)
treefc1c25622985a37acefa83f4d4d27736c1ea3ecb /src/components
parentb760faf707b7210765eb0defa785ee1c429b0523 (diff)
downloadsdl_core-7068453fe5919c8379cd0deb6fd9c077313a70e5.tar.gz
Use Pimple idiom for Network Interface Listener
Create `qnx` and `linux` folder with platform specific code. Moved implementation from network_interface_listener_impl to platform_specific/linux/platform_specific_network_interface_listener_impl QNX contains empty implementation Renamed source files : used cc file extension for source files
Diffstat (limited to 'src/components')
-rw-r--r--src/components/transport_manager/CMakeLists.txt87
-rw-r--r--src/components/transport_manager/include/transport_manager/tcp/network_interface_listener_impl.h139
-rw-r--r--src/components/transport_manager/include/transport_manager/tcp/platform_specific/linux/platform_specific_network_interface_listener_impl.h228
-rw-r--r--src/components/transport_manager/include/transport_manager/tcp/platform_specific/qnx/platform_specific_network_interface_listener_impl.h102
-rw-r--r--src/components/transport_manager/src/tcp/network_interface_listener_impl.cc74
-rw-r--r--src/components/transport_manager/src/tcp/platform_specific/linux/platform_specific_network_interface_listener.cc (renamed from src/components/transport_manager/src/tcp/network_interface_listener_impl.cpp)55
-rw-r--r--src/components/transport_manager/src/tcp/platform_specific/qnx/platform_specific_network_interface_listener.cc69
-rw-r--r--src/components/transport_manager/test/CMakeLists.txt5
-rw-r--r--src/components/transport_manager/test/network_interface_listener_test.cc510
-rw-r--r--src/components/transport_manager/test/platform_specific/linux/linux_network_interface_listener_test.cc599
10 files changed, 1166 insertions, 702 deletions
diff --git a/src/components/transport_manager/CMakeLists.txt b/src/components/transport_manager/CMakeLists.txt
index 4fa224393d..aa56aa810b 100644
--- a/src/components/transport_manager/CMakeLists.txt
+++ b/src/components/transport_manager/CMakeLists.txt
@@ -43,60 +43,85 @@ include_directories (
${LOG4CXX_INCLUDE_DIRECTORY}
)
-set(PATHS
- ${CMAKE_CURRENT_SOURCE_DIR}/include
- ${CMAKE_CURRENT_SOURCE_DIR}/src
-)
-
-set(EXCLUDE_PATHS)
+if (CMAKE_SYSTEM_NAME STREQUAL "QNX")
+ include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/include/transport_manager/tcp/platform_specific/qnx")
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/include/transport_manager/tcp/platform_specific/linux")
+endif ()
set(LIBRARIES
ProtocolLibrary
Utils
)
+set(SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/transport_manager_default.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/transport_manager_impl.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/network_interface_listener_impl.cc
+
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/tcp_client_listener.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/tcp_connection_factory.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/tcp_device.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/tcp_server_originated_socket_connection.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/tcp_socket_connection.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/tcp_transport_adapter.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/tcp_transport_adapter.cc
+
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/transport_adapter/threaded_socket_connection.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/transport_adapter/transport_adapter_impl.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/transport_adapter/transport_adapter_listener_impl.cc
+
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/iap2_emulation/iap2_transport_adapter.cc
+
+)
+
+if (CMAKE_SYSTEM_NAME STREQUAL "QNX")
+ list(APPEND SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/platform_specific/qnx/platform_specific_network_interface_listener.cc
+ )
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ list(APPEND SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tcp/platform_specific/linux/platform_specific_network_interface_listener.cc
+ )
+endif ()
+
if(BUILD_BT_SUPPORT)
list(APPEND LIBRARIES
bluetooth
)
-else()
- list(APPEND EXCLUDE_PATHS
- ${COMPONENTS_DIR}/transport_manager/include/transport_manager/bluetooth
- ${COMPONENTS_DIR}/transport_manager/src/bluetooth
+ list(APPEND SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/bluetooth/bluetooth_connection_factory.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/bluetooth/bluetooth_device.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/bluetooth/bluetooth_device_scanner.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/bluetooth/bluetooth_socket_connection.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/bluetooth/bluetooth_transport_adapter.cc
)
endif()
if(BUILD_USB_SUPPORT)
+ list(APPEND SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/usb_aoa_adapter.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/usb_connection_factory.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/usb_device_scanner.cc
+ )
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
- set(EXCLUDE_PATHS
- ${COMPONENTS_DIR}/transport_manager/include/transport_manager/usb/qnx
- ${COMPONENTS_DIR}/transport_manager/src/usb/qnx
+ list(APPEND SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/libusb/platform_usb_device.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/libusb/usb_connection.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/libusb/usb_handler.cc
)
-
elseif(CMAKE_SYSTEM_NAME STREQUAL "QNX")
- set(EXCLUDE_PATHS
- ${COMPONENTS_DIR}/transport_manager/include/transport_manager/usb/libusb
- ${COMPONENTS_DIR}/transport_manager/src/usb/libusb
- )
list(APPEND LIBRARIES
usbdi
)
+ list(APPEND SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/qnx/platform_usb_device.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/qnx/usb_connection.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/qnx/usb_handler.cc
+ )
endif()
-else()
- list(APPEND EXCLUDE_PATHS
- ${COMPONENTS_DIR}/transport_manager/include/transport_manager/usb
- ${COMPONENTS_DIR}/transport_manager/src/usb
- )
-endif()
-
-if(NOT BUILD_TESTS)
- list (APPEND EXCLUDE_PATH
- ${CMAKE_CURRENT_SOURCE_DIR}/include/iap2_emulation/iap2_transport_adapter.h
- ${CMAKE_CURRENT_SOURCE_DIR}/src/iap2_emulation/iap2_transport_adapter.cc
- )
endif()
-collect_sources(SOURCES "${PATHS}" "${EXCLUDE_PATHS}")
add_library("TransportManager" ${SOURCES})
target_link_libraries("TransportManager" ${LIBRARIES})
diff --git a/src/components/transport_manager/include/transport_manager/tcp/network_interface_listener_impl.h b/src/components/transport_manager/include/transport_manager/tcp/network_interface_listener_impl.h
index 6a9cf46762..11a9be05ed 100644
--- a/src/components/transport_manager/include/transport_manager/tcp/network_interface_listener_impl.h
+++ b/src/components/transport_manager/include/transport_manager/tcp/network_interface_listener_impl.h
@@ -33,17 +33,11 @@
#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TCP_NETWORK_INTERFACE_LISTENER_IMPL_H_
#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TCP_NETWORK_INTERFACE_LISTENER_IMPL_H_
-#include <map>
#include <string>
-#include <vector>
+#include <memory>
-#include <netinet/in.h>
-#include "transport_manager/tcp/network_interface_listener.h"
#include "utils/macro.h"
-#include "utils/threads/thread_delegate.h"
-
-class Thread;
-struct ifaddrmsg;
+#include "transport_manager/tcp/network_interface_listener.h"
namespace transport_manager {
namespace transport_adapter {
@@ -51,43 +45,6 @@ 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 NetworkInterfaceListenerImpl : public NetworkInterfaceListener {
@@ -101,7 +58,7 @@ class NetworkInterfaceListenerImpl : public NetworkInterfaceListener {
* network interface, specify its name
*/
NetworkInterfaceListenerImpl(TcpClientListener* tcp_client_listener,
- const std::string designated_interface = "");
+ const std::string designated_interface);
/**
* @brief Destructor
@@ -128,96 +85,8 @@ class NetworkInterfaceListenerImpl : public NetworkInterfaceListener {
*/
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(NetworkInterfaceListenerImpl* parent);
- virtual void threadMain();
- void exitThreadMain();
-
- private:
- NetworkInterfaceListenerImpl* parent_;
- };
-
- DISALLOW_COPY_AND_ASSIGN(NetworkInterfaceListenerImpl);
+ std::unique_ptr<NetworkInterfaceListener> platform_specific_impl_;
};
} // namespace transport_adapter
diff --git a/src/components/transport_manager/include/transport_manager/tcp/platform_specific/linux/platform_specific_network_interface_listener_impl.h b/src/components/transport_manager/include/transport_manager/tcp/platform_specific/linux/platform_specific_network_interface_listener_impl.h
new file mode 100644
index 0000000000..8a2279003a
--- /dev/null
+++ b/src/components/transport_manager/include/transport_manager/tcp/platform_specific/linux/platform_specific_network_interface_listener_impl.h
@@ -0,0 +1,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_
diff --git a/src/components/transport_manager/include/transport_manager/tcp/platform_specific/qnx/platform_specific_network_interface_listener_impl.h b/src/components/transport_manager/include/transport_manager/tcp/platform_specific/qnx/platform_specific_network_interface_listener_impl.h
new file mode 100644
index 0000000000..c5982853dc
--- /dev/null
+++ b/src/components/transport_manager/include/transport_manager/tcp/platform_specific/qnx/platform_specific_network_interface_listener_impl.h
@@ -0,0 +1,102 @@
+/*
+ * 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_QNX_PLATFORM_SPECIFIC_NETWORK_INTERFACE_LISTENER_H_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TCP_PLATFORM_SPECIFIC_QNX_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"
+
+class Thread;
+struct ifaddrmsg;
+
+namespace transport_manager {
+namespace transport_adapter {
+
+class TcpClientListener;
+
+/**
+ * @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;
+
+ private:
+};
+
+} // namespace transport_adapter
+} // namespace transport_manager
+
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_TCP_PLATFORM_SPECIFIC_QNX_PLATFORM_SPECIFIC_NETWORK_INTERFACE_LISTENER_H_
diff --git a/src/components/transport_manager/src/tcp/network_interface_listener_impl.cc b/src/components/transport_manager/src/tcp/network_interface_listener_impl.cc
new file mode 100644
index 0000000000..e362ee8a73
--- /dev/null
+++ b/src/components/transport_manager/src/tcp/network_interface_listener_impl.cc
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#include "transport_manager/tcp/network_interface_listener_impl.h"
+#include "platform_specific_network_interface_listener_impl.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager")
+
+NetworkInterfaceListenerImpl::NetworkInterfaceListenerImpl(
+ TcpClientListener* tcp_client_listener,
+ const std::string designated_interface)
+ : platform_specific_impl_(new PlatformSpecificNetworkInterfaceListener(
+ tcp_client_listener, designated_interface)) {
+ LOG4CXX_AUTO_TRACE(logger_);
+}
+
+NetworkInterfaceListenerImpl::~NetworkInterfaceListenerImpl() {
+ LOG4CXX_AUTO_TRACE(logger_);
+}
+
+bool NetworkInterfaceListenerImpl::Init() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ return platform_specific_impl_->Init();
+}
+
+void NetworkInterfaceListenerImpl::Deinit() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ platform_specific_impl_->Deinit();
+}
+
+bool NetworkInterfaceListenerImpl::Start() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ return platform_specific_impl_->Start();
+}
+
+bool NetworkInterfaceListenerImpl::Stop() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ return platform_specific_impl_->Stop();
+}
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/src/tcp/network_interface_listener_impl.cpp b/src/components/transport_manager/src/tcp/platform_specific/linux/platform_specific_network_interface_listener.cc
index bcf5e21387..4669edd7b4 100644
--- a/src/components/transport_manager/src/tcp/network_interface_listener_impl.cpp
+++ b/src/components/transport_manager/src/tcp/platform_specific/linux/platform_specific_network_interface_listener.cc
@@ -30,7 +30,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "transport_manager/tcp/network_interface_listener_impl.h"
+#include "transport_manager/tcp/platform_specific/linux/platform_specific_network_interface_listener_impl.h"
#include <arpa/inet.h>
#include <asm/types.h>
@@ -42,10 +42,9 @@
#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
-#ifdef __linux__
+
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
-#endif // __linux__
#include "transport_manager/tcp/tcp_client_listener.h"
#include "utils/logger.h"
@@ -106,9 +105,10 @@ void InterfaceStatus::SetIPv6Address(struct in6_addr* addr) {
}
}
-NetworkInterfaceListenerImpl::NetworkInterfaceListenerImpl(
- TcpClientListener* tcp_client_listener,
- const std::string designated_interface)
+PlatformSpecificNetworkInterfaceListener::
+ PlatformSpecificNetworkInterfaceListener(
+ TcpClientListener* tcp_client_listener,
+ const std::string designated_interface)
: tcp_client_listener_(tcp_client_listener)
, designated_interface_(designated_interface)
, selected_interface_("")
@@ -120,11 +120,12 @@ NetworkInterfaceListenerImpl::NetworkInterfaceListenerImpl(
#endif // BUILD_TESTS
{
pipe_fds_[0] = pipe_fds_[1] = -1;
- thread_ = threads::CreateThread("NetworkInterfaceListenerImpl",
+ thread_ = threads::CreateThread("PlatformSpecificNetworkInterfaceListener",
new ListenerThreadDelegate(this));
}
-NetworkInterfaceListenerImpl::~NetworkInterfaceListenerImpl() {
+PlatformSpecificNetworkInterfaceListener::
+ ~PlatformSpecificNetworkInterfaceListener() {
LOG4CXX_AUTO_TRACE(logger_);
Stop();
@@ -134,7 +135,7 @@ NetworkInterfaceListenerImpl::~NetworkInterfaceListenerImpl() {
threads::DeleteThread(thread_);
}
-bool NetworkInterfaceListenerImpl::Init() {
+bool PlatformSpecificNetworkInterfaceListener::Init() {
LOG4CXX_AUTO_TRACE(logger_);
if (socket_ >= 0) {
@@ -180,7 +181,7 @@ bool NetworkInterfaceListenerImpl::Init() {
return true;
}
-void NetworkInterfaceListenerImpl::Deinit() {
+void PlatformSpecificNetworkInterfaceListener::Deinit() {
LOG4CXX_AUTO_TRACE(logger_);
if (socket_ >= 0) {
@@ -197,7 +198,7 @@ void NetworkInterfaceListenerImpl::Deinit() {
}
}
-bool NetworkInterfaceListenerImpl::Start() {
+bool PlatformSpecificNetworkInterfaceListener::Start() {
LOG4CXX_AUTO_TRACE(logger_);
if (socket_ < 0) {
@@ -219,7 +220,7 @@ bool NetworkInterfaceListenerImpl::Start() {
return true;
}
-bool NetworkInterfaceListenerImpl::Stop() {
+bool PlatformSpecificNetworkInterfaceListener::Stop() {
LOG4CXX_AUTO_TRACE(logger_);
if (!thread_->is_running()) {
@@ -233,7 +234,7 @@ bool NetworkInterfaceListenerImpl::Stop() {
return true;
}
-void NetworkInterfaceListenerImpl::Loop() {
+void PlatformSpecificNetworkInterfaceListener::Loop() {
LOG4CXX_AUTO_TRACE(logger_);
InitializeStatus();
@@ -337,7 +338,7 @@ void NetworkInterfaceListenerImpl::Loop() {
}
}
-bool NetworkInterfaceListenerImpl::StopLoop() {
+bool PlatformSpecificNetworkInterfaceListener::StopLoop() {
LOG4CXX_AUTO_TRACE(logger_);
LOG4CXX_INFO(logger_, "Stopping network interface listener");
@@ -358,7 +359,7 @@ bool NetworkInterfaceListenerImpl::StopLoop() {
return true;
}
-bool NetworkInterfaceListenerImpl::InitializeStatus() {
+bool PlatformSpecificNetworkInterfaceListener::InitializeStatus() {
LOG4CXX_AUTO_TRACE(logger_);
#ifdef BUILD_TESTS
@@ -417,7 +418,7 @@ bool NetworkInterfaceListenerImpl::InitializeStatus() {
return true;
}
-bool NetworkInterfaceListenerImpl::UpdateStatus(
+bool PlatformSpecificNetworkInterfaceListener::UpdateStatus(
uint16_t type, std::vector<EventParam>& params) {
LOG4CXX_AUTO_TRACE(logger_);
@@ -486,7 +487,7 @@ bool NetworkInterfaceListenerImpl::UpdateStatus(
return true;
}
-void NetworkInterfaceListenerImpl::NotifyIPAddresses() {
+void PlatformSpecificNetworkInterfaceListener::NotifyIPAddresses() {
LOG4CXX_AUTO_TRACE(logger_);
std::string ipv4_addr;
@@ -519,7 +520,7 @@ void NetworkInterfaceListenerImpl::NotifyIPAddresses() {
}
}
-const std::string NetworkInterfaceListenerImpl::SelectInterface() {
+const std::string PlatformSpecificNetworkInterfaceListener::SelectInterface() {
LOG4CXX_AUTO_TRACE(logger_);
if (!designated_interface_.empty()) {
@@ -562,9 +563,9 @@ const std::string NetworkInterfaceListenerImpl::SelectInterface() {
return selected_interface_;
}
-std::vector<NetworkInterfaceListenerImpl::EventParam>
-NetworkInterfaceListenerImpl::ParseIFAddrMessage(struct ifaddrmsg* message,
- unsigned int size) {
+std::vector<PlatformSpecificNetworkInterfaceListener::EventParam>
+PlatformSpecificNetworkInterfaceListener::ParseIFAddrMessage(
+ struct ifaddrmsg* message, unsigned int size) {
LOG4CXX_AUTO_TRACE(logger_);
std::vector<EventParam> params;
@@ -619,7 +620,7 @@ NetworkInterfaceListenerImpl::ParseIFAddrMessage(struct ifaddrmsg* message,
return params;
}
-void NetworkInterfaceListenerImpl::DumpTable() const {
+void PlatformSpecificNetworkInterfaceListener::DumpTable() const {
LOG4CXX_DEBUG(logger_,
"Number of network interfaces: " << status_table_.size());
@@ -637,15 +638,17 @@ void NetworkInterfaceListenerImpl::DumpTable() const {
}
}
-NetworkInterfaceListenerImpl::ListenerThreadDelegate::ListenerThreadDelegate(
- NetworkInterfaceListenerImpl* parent)
+PlatformSpecificNetworkInterfaceListener::ListenerThreadDelegate::
+ ListenerThreadDelegate(PlatformSpecificNetworkInterfaceListener* parent)
: parent_(parent) {}
-void NetworkInterfaceListenerImpl::ListenerThreadDelegate::threadMain() {
+void PlatformSpecificNetworkInterfaceListener::ListenerThreadDelegate::
+ threadMain() {
parent_->Loop();
}
-void NetworkInterfaceListenerImpl::ListenerThreadDelegate::exitThreadMain() {
+void PlatformSpecificNetworkInterfaceListener::ListenerThreadDelegate::
+ exitThreadMain() {
parent_->StopLoop();
}
diff --git a/src/components/transport_manager/src/tcp/platform_specific/qnx/platform_specific_network_interface_listener.cc b/src/components/transport_manager/src/tcp/platform_specific/qnx/platform_specific_network_interface_listener.cc
new file mode 100644
index 0000000000..9ca7890278
--- /dev/null
+++ b/src/components/transport_manager/src/tcp/platform_specific/qnx/platform_specific_network_interface_listener.cc
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+#include "transport_manager/tcp/platform_specific/qnx/platform_specific_network_interface_listener_impl.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager")
+
+PlatformSpecificNetworkInterfaceListener::
+ PlatformSpecificNetworkInterfaceListener(
+ TcpClientListener* tcp_client_listener,
+ const std::string designated_interface) {}
+
+PlatformSpecificNetworkInterfaceListener::
+ ~PlatformSpecificNetworkInterfaceListener() {
+ LOG4CXX_AUTO_TRACE(logger_);
+}
+
+bool PlatformSpecificNetworkInterfaceListener::Init() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ return true;
+}
+
+void PlatformSpecificNetworkInterfaceListener::Deinit() {
+ LOG4CXX_AUTO_TRACE(logger_);
+}
+
+bool PlatformSpecificNetworkInterfaceListener::Start() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ return true;
+}
+
+bool PlatformSpecificNetworkInterfaceListener::Stop() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ return true;
+}
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/test/CMakeLists.txt b/src/components/transport_manager/test/CMakeLists.txt
index 41aae296ac..8447ebe723 100644
--- a/src/components/transport_manager/test/CMakeLists.txt
+++ b/src/components/transport_manager/test/CMakeLists.txt
@@ -47,6 +47,11 @@ set(EXCLUDE_PATHS
collect_sources(SOURCES "${CMAKE_CURRENT_SOURCE_DIR}" "${EXCLUDE_PATHS}")
+set (
+ "${CMAKE_CURRENT_SOURCE_DIR}"/platform_specific/linux
+ "${SOURCES}"
+)
+
set(LIBRARIES
gmock
ConfigProfile
diff --git a/src/components/transport_manager/test/network_interface_listener_test.cc b/src/components/transport_manager/test/network_interface_listener_test.cc
index 56512e5c98..7a5b0315ab 100644
--- a/src/components/transport_manager/test/network_interface_listener_test.cc
+++ b/src/components/transport_manager/test/network_interface_listener_test.cc
@@ -69,41 +69,10 @@ class NetworkInterfaceListenerTest : public ::testing::Test {
unsigned int flags;
};
- void Init(const std::string interface_name) {
- interface_listener_impl_ = new NetworkInterfaceListenerImpl(
- &mock_tcp_client_listener_, interface_name);
- // disable events from actual network interfaces
- interface_listener_impl_->SetTesting(true);
- }
-
void Deinit() {
delete interface_listener_impl_;
}
- void SetDummyInterfaceTable(struct InterfaceEntry* entries) {
- InterfaceStatusTable dummy_table;
-
- while (entries->name != NULL) {
- InterfaceStatus status;
- if (entries->ipv4_address != NULL) {
- struct in_addr addr;
- ASSERT_EQ(1, inet_pton(AF_INET, entries->ipv4_address, &addr));
- status.SetIPv4Address(&addr);
- }
- if (entries->ipv6_address != NULL) {
- struct in6_addr addr6;
- ASSERT_EQ(1, inet_pton(AF_INET6, entries->ipv6_address, &addr6));
- status.SetIPv6Address(&addr6);
- }
- status.SetFlags(entries->flags);
-
- dummy_table.insert(std::make_pair(entries->name, status));
- entries++;
- }
-
- interface_listener_impl_->OverwriteStatusTable(dummy_table);
- }
-
void SleepFor(long msec) const {
if (msec > 0) {
struct timespec ts = {0, msec * 1000 * 1000};
@@ -115,485 +84,6 @@ class NetworkInterfaceListenerTest : public ::testing::Test {
MockTcpClientListener mock_tcp_client_listener_;
};
-TEST_F(NetworkInterfaceListenerTest, Init) {
- Init("");
-
- EXPECT_TRUE(interface_listener_impl_->Init());
- EXPECT_TRUE(0 <= interface_listener_impl_->GetSocket());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, Deinit) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- interface_listener_impl_->Deinit();
-
- EXPECT_EQ(-1, interface_listener_impl_->GetSocket());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, Start_success) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries[] = {
- {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
- SetDummyInterfaceTable(entries);
-
- // after stated, it is expected that the listener notifies current IP address
- // (if it's available)
- TestAsyncWaiter waiter;
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(entries[0].ipv4_address, ""))
- .WillOnce(NotifyTestAsyncWaiter(&waiter));
-
- EXPECT_TRUE(interface_listener_impl_->Start());
-
- // the "isThreadRunning_" flag of the thread will be update slightly later
- SleepFor(kThreadStartWaitMsec);
-
- EXPECT_TRUE(interface_listener_impl_->GetThread()->is_running());
-
- EXPECT_TRUE(waiter.WaitFor(1, kStartNotificationTimeoutMsec));
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, Start_twice) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- // ignore OnIPAddressUpdated call
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _))
- .Times(AtLeast(0));
-
- EXPECT_TRUE(interface_listener_impl_->Start());
- SleepFor(kThreadStartWaitMsec);
-
- EXPECT_FALSE(interface_listener_impl_->Start());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, Stop_success) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- // ignore OnIPAddressUpdated call
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _))
- .Times(AtLeast(0));
-
- EXPECT_TRUE(interface_listener_impl_->Start());
- SleepFor(kThreadStartWaitMsec);
-
- EXPECT_TRUE(interface_listener_impl_->Stop());
- SleepFor(kThreadStartWaitMsec);
-
- EXPECT_FALSE(interface_listener_impl_->GetThread()->is_running());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, Stop_twice) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- // ignore OnIPAddressUpdated call
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _))
- .Times(AtLeast(0));
-
- EXPECT_TRUE(interface_listener_impl_->Start());
- SleepFor(kThreadStartWaitMsec);
-
- EXPECT_TRUE(interface_listener_impl_->Stop());
-
- EXPECT_FALSE(interface_listener_impl_->Stop());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, Stop_without_Start) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- EXPECT_FALSE(interface_listener_impl_->Stop());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_IPAddressChanged) {
- Init("dummy_int0");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries1[] = {
- {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
- struct InterfaceEntry entries2[] = {
- {"dummy_int0", "5.6.7.8", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- SetDummyInterfaceTable(entries1);
-
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(entries1[0].ipv4_address, "")).Times(1);
-
- // this test case doesn't call Start() - we only check the behavior of
- // NotifyIPAddresses()
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- SetDummyInterfaceTable(entries2);
-
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(entries2[0].ipv4_address, "")).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_IPAddressNotChanged) {
- Init("dummy_int0");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries1[] = {
- {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
- struct InterfaceEntry entries2[] = {
- {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
- {"dummy_int1", "172.16.23.30", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- SetDummyInterfaceTable(entries1);
-
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(entries1[0].ipv4_address, "")).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- SetDummyInterfaceTable(entries2);
-
- // OnIPAddressUpdated() shouldn't be notified
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(0);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_GoesUnavailable) {
- Init("dummy_int0");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries1[] = {
- {"dummy_int0", "1.2.3.4", "fdc2:12af:327a::1", IFF_UP | IFF_RUNNING},
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
- struct InterfaceEntry entries2[] = {
- {"dummy_int0", "1.2.3.4", "fdc2:12af:327a::1", IFF_UP},
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- SetDummyInterfaceTable(entries1);
-
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(entries1[0].ipv4_address,
- entries1[0].ipv6_address)).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- SetDummyInterfaceTable(entries2);
-
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated("", "")).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_Removed) {
- Init("dummy_int0");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries1[] = {
- {"dummy_int0", "1.2.3.4", "fdc2:12af:327a::1", IFF_UP | IFF_RUNNING},
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
- struct InterfaceEntry entries2[] = {
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- SetDummyInterfaceTable(entries1);
-
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(entries1[0].ipv4_address,
- entries1[0].ipv6_address)).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- SetDummyInterfaceTable(entries2);
-
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated("", "")).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_Added) {
- Init("dummy_int0");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries1[] = {
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
- struct InterfaceEntry entries2[] = {
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
- {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- SetDummyInterfaceTable(entries1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- SetDummyInterfaceTable(entries2);
-
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(entries2[1].ipv4_address, "")).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_SelectInterface) {
- // automatically select network interface
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries[] = {
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
- {"net_dummy2", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- SetDummyInterfaceTable(entries);
-
- std::string output_ipv4_address;
- std::string output_ipv6_address;
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _))
- .WillOnce(DoAll(SaveArg<0>(&output_ipv4_address),
- SaveArg<1>(&output_ipv6_address)));
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- std::string selected_interface =
- interface_listener_impl_->GetSelectedInterfaceName();
-
- // the interface listener should pick one of the interfaces
- EXPECT_TRUE((selected_interface == entries[0].name &&
- output_ipv4_address == entries[0].ipv4_address &&
- output_ipv6_address == "") ||
- (selected_interface == entries[1].name &&
- output_ipv4_address == entries[1].ipv4_address &&
- output_ipv6_address == entries[1].ipv6_address));
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest,
- AutoSelectInterface_SkipUnavailableInterface) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries[] = {
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP},
- {"net_dummy2", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- SetDummyInterfaceTable(entries);
-
- // dummy_int1 should not be selected
- struct InterfaceEntry* expected = &entries[1];
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(expected->ipv4_address,
- expected->ipv6_address)).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- EXPECT_EQ(expected->name,
- interface_listener_impl_->GetSelectedInterfaceName());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_SkipEmptyInterface) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries[] = {
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
- {"net_dummy2", NULL, NULL, IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- SetDummyInterfaceTable(entries);
-
- // net_dummy2 should not be selected
- struct InterfaceEntry* expected = &entries[0];
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(expected->ipv4_address, "")).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- EXPECT_EQ(expected->name,
- interface_listener_impl_->GetSelectedInterfaceName());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest,
- AutoSelectInterface_SkipLoopbackInterface) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries[] = {
- {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING | IFF_LOOPBACK},
- {"net_dummy2", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- // dummy_int1 should not be selected
- struct InterfaceEntry* expected = &entries[1];
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(expected->ipv4_address,
- expected->ipv6_address)).Times(1);
-
- SetDummyInterfaceTable(entries);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- EXPECT_EQ(expected->name,
- interface_listener_impl_->GetSelectedInterfaceName());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_DisableInterface) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries[] = {
- {"net_dummy0", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(1);
- SetDummyInterfaceTable(entries);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- // make the interface "not running"
- entries[0].flags &= ~IFF_RUNNING;
- SetDummyInterfaceTable(entries);
-
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated("", "")).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- EXPECT_EQ("", interface_listener_impl_->GetSelectedInterfaceName());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_EnableInterface) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries[] = {
- {"net_dummy0", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(1);
- SetDummyInterfaceTable(entries);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- // make the interface "not running"
- entries[0].flags &= ~IFF_RUNNING;
- SetDummyInterfaceTable(entries);
-
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- // make it running again
- entries[0].flags |= IFF_RUNNING;
- SetDummyInterfaceTable(entries);
-
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(entries[0].ipv4_address,
- entries[0].ipv6_address)).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- EXPECT_EQ(entries[0].name,
- interface_listener_impl_->GetSelectedInterfaceName());
-
- Deinit();
-}
-
-TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_SwitchInterface) {
- Init("");
- EXPECT_TRUE(interface_listener_impl_->Init());
-
- struct InterfaceEntry entries[] = {
- {"dummy_int1",
- "10.10.10.12",
- "fd53:ba79:241d:30c1::78",
- IFF_UP | IFF_RUNNING},
- {"net_dummy2", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
- {NULL, NULL, NULL, 0}};
-
- EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(1);
- SetDummyInterfaceTable(entries);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- const std::string selected_interface =
- interface_listener_impl_->GetSelectedInterfaceName();
- struct InterfaceEntry* selected = &entries[0];
- while (selected->name != NULL) {
- if (selected->name == selected_interface) {
- break;
- }
- selected++;
- }
- ASSERT_TRUE(selected->name != NULL);
-
- // make the interface "not running"
- selected->flags &= ~IFF_RUNNING;
- SetDummyInterfaceTable(entries);
-
- struct InterfaceEntry* switched;
- if (selected == &entries[0]) {
- switched = &entries[1];
- } else {
- switched = &entries[0];
- }
-
- EXPECT_CALL(mock_tcp_client_listener_,
- OnIPAddressUpdated(switched->ipv4_address,
- switched->ipv6_address)).Times(1);
-
- interface_listener_impl_->testCallNotifyIPAddresses();
-
- EXPECT_EQ(switched->name,
- interface_listener_impl_->GetSelectedInterfaceName());
-
- Deinit();
-}
-
} // namespace transport_manager_test
} // namespace components
} // namespace test
diff --git a/src/components/transport_manager/test/platform_specific/linux/linux_network_interface_listener_test.cc b/src/components/transport_manager/test/platform_specific/linux/linux_network_interface_listener_test.cc
new file mode 100644
index 0000000000..864cb9d657
--- /dev/null
+++ b/src/components/transport_manager/test/platform_specific/linux/linux_network_interface_listener_test.cc
@@ -0,0 +1,599 @@
+/*
+ * 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 name 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.
+ */
+
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <time.h>
+
+#include "gtest/gtest.h"
+#include "platform_specific_network_interface_listener_impl.h"
+#include "transport_manager/tcp/mock_tcp_client_listener.h"
+#include "utils/test_async_waiter.h"
+#include "utils/threads/thread.h"
+
+namespace test {
+namespace components {
+namespace transport_manager_test {
+
+namespace {
+const long kThreadStartWaitMsec = 10;
+const uint32_t kStartNotificationTimeoutMsec = 500;
+}
+
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::SaveArg;
+
+class NetworkInterfaceListenerTest : public ::testing::Test {
+ public:
+ NetworkInterfaceListenerTest()
+ : interface_listener_impl_(NULL)
+ , mock_tcp_client_listener_(NULL, 0, false, "") {}
+
+ virtual ~NetworkInterfaceListenerTest() {}
+
+ protected:
+ struct InterfaceEntry {
+ const char* name;
+ const char* ipv4_address;
+ const char* ipv6_address;
+ unsigned int flags;
+ };
+
+ void Init(const std::string interface_name) {
+ interface_listener_impl_ = new PlatformSpecificNetworkInterfaceListener(
+ &mock_tcp_client_listener_, interface_name);
+ // disable events from actual network interfaces
+ interface_listener_impl_->SetTesting(true);
+ }
+
+ void Deinit() {
+ delete interface_listener_impl_;
+ }
+
+ void SetDummyInterfaceTable(struct InterfaceEntry* entries) {
+ InterfaceStatusTable dummy_table;
+
+ while (entries->name != NULL) {
+ InterfaceStatus status;
+ if (entries->ipv4_address != NULL) {
+ struct in_addr addr;
+ ASSERT_EQ(1, inet_pton(AF_INET, entries->ipv4_address, &addr));
+ status.SetIPv4Address(&addr);
+ }
+ if (entries->ipv6_address != NULL) {
+ struct in6_addr addr6;
+ ASSERT_EQ(1, inet_pton(AF_INET6, entries->ipv6_address, &addr6));
+ status.SetIPv6Address(&addr6);
+ }
+ status.SetFlags(entries->flags);
+
+ dummy_table.insert(std::make_pair(entries->name, status));
+ entries++;
+ }
+
+ interface_listener_impl_->OverwriteStatusTable(dummy_table);
+ }
+
+ void SleepFor(long msec) const {
+ if (msec > 0) {
+ struct timespec ts = {0, msec * 1000 * 1000};
+ nanosleep(&ts, NULL);
+ }
+ }
+
+ PlatformSpecificNetworkInterfaceListener* interface_listener_impl_;
+ MockTcpClientListener mock_tcp_client_listener_;
+};
+
+TEST_F(NetworkInterfaceListenerTest, Init) {
+ Init("");
+
+ EXPECT_TRUE(interface_listener_impl_->Init());
+ EXPECT_TRUE(0 <= interface_listener_impl_->GetSocket());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, Deinit) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ interface_listener_impl_->Deinit();
+
+ EXPECT_EQ(-1, interface_listener_impl_->GetSocket());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, Start_success) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries[] = {
+ {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+ SetDummyInterfaceTable(entries);
+
+ // after stated, it is expected that the listener notifies current IP address
+ // (if it's available)
+ TestAsyncWaiter waiter;
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(entries[0].ipv4_address, ""))
+ .WillOnce(NotifyTestAsyncWaiter(&waiter));
+
+ EXPECT_TRUE(interface_listener_impl_->Start());
+
+ // the "isThreadRunning_" flag of the thread will be update slightly later
+ SleepFor(kThreadStartWaitMsec);
+
+ EXPECT_TRUE(interface_listener_impl_->GetThread()->is_running());
+
+ EXPECT_TRUE(waiter.WaitFor(1, kStartNotificationTimeoutMsec));
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, Start_twice) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ // ignore OnIPAddressUpdated call
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _))
+ .Times(AtLeast(0));
+
+ EXPECT_TRUE(interface_listener_impl_->Start());
+ SleepFor(kThreadStartWaitMsec);
+
+ EXPECT_FALSE(interface_listener_impl_->Start());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, Stop_success) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ // ignore OnIPAddressUpdated call
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _))
+ .Times(AtLeast(0));
+
+ EXPECT_TRUE(interface_listener_impl_->Start());
+ SleepFor(kThreadStartWaitMsec);
+
+ EXPECT_TRUE(interface_listener_impl_->Stop());
+ SleepFor(kThreadStartWaitMsec);
+
+ EXPECT_FALSE(interface_listener_impl_->GetThread()->is_running());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, Stop_twice) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ // ignore OnIPAddressUpdated call
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _))
+ .Times(AtLeast(0));
+
+ EXPECT_TRUE(interface_listener_impl_->Start());
+ SleepFor(kThreadStartWaitMsec);
+
+ EXPECT_TRUE(interface_listener_impl_->Stop());
+
+ EXPECT_FALSE(interface_listener_impl_->Stop());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, Stop_without_Start) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ EXPECT_FALSE(interface_listener_impl_->Stop());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_IPAddressChanged) {
+ Init("dummy_int0");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries1[] = {
+ {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+ struct InterfaceEntry entries2[] = {
+ {"dummy_int0", "5.6.7.8", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ SetDummyInterfaceTable(entries1);
+
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(entries1[0].ipv4_address, "")).Times(1);
+
+ // this test case doesn't call Start() - we only check the behavior of
+ // NotifyIPAddresses()
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ SetDummyInterfaceTable(entries2);
+
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(entries2[0].ipv4_address, "")).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_IPAddressNotChanged) {
+ Init("dummy_int0");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries1[] = {
+ {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+ struct InterfaceEntry entries2[] = {
+ {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
+ {"dummy_int1", "172.16.23.30", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ SetDummyInterfaceTable(entries1);
+
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(entries1[0].ipv4_address, "")).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ SetDummyInterfaceTable(entries2);
+
+ // OnIPAddressUpdated() shouldn't be notified
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(0);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_GoesUnavailable) {
+ Init("dummy_int0");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries1[] = {
+ {"dummy_int0", "1.2.3.4", "fdc2:12af:327a::1", IFF_UP | IFF_RUNNING},
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+ struct InterfaceEntry entries2[] = {
+ {"dummy_int0", "1.2.3.4", "fdc2:12af:327a::1", IFF_UP},
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ SetDummyInterfaceTable(entries1);
+
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(entries1[0].ipv4_address,
+ entries1[0].ipv6_address)).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ SetDummyInterfaceTable(entries2);
+
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated("", "")).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_Removed) {
+ Init("dummy_int0");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries1[] = {
+ {"dummy_int0", "1.2.3.4", "fdc2:12af:327a::1", IFF_UP | IFF_RUNNING},
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+ struct InterfaceEntry entries2[] = {
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ SetDummyInterfaceTable(entries1);
+
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(entries1[0].ipv4_address,
+ entries1[0].ipv6_address)).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ SetDummyInterfaceTable(entries2);
+
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated("", "")).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, DesignatedInterface_Added) {
+ Init("dummy_int0");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries1[] = {
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+ struct InterfaceEntry entries2[] = {
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
+ {"dummy_int0", "1.2.3.4", NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ SetDummyInterfaceTable(entries1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ SetDummyInterfaceTable(entries2);
+
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(entries2[1].ipv4_address, "")).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_SelectInterface) {
+ // automatically select network interface
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries[] = {
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
+ {"net_dummy2", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ SetDummyInterfaceTable(entries);
+
+ std::string output_ipv4_address;
+ std::string output_ipv6_address;
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&output_ipv4_address),
+ SaveArg<1>(&output_ipv6_address)));
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ std::string selected_interface =
+ interface_listener_impl_->GetSelectedInterfaceName();
+
+ // the interface listener should pick one of the interfaces
+ EXPECT_TRUE((selected_interface == entries[0].name &&
+ output_ipv4_address == entries[0].ipv4_address &&
+ output_ipv6_address == "") ||
+ (selected_interface == entries[1].name &&
+ output_ipv4_address == entries[1].ipv4_address &&
+ output_ipv6_address == entries[1].ipv6_address));
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest,
+ AutoSelectInterface_SkipUnavailableInterface) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries[] = {
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP},
+ {"net_dummy2", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ SetDummyInterfaceTable(entries);
+
+ // dummy_int1 should not be selected
+ struct InterfaceEntry* expected = &entries[1];
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(expected->ipv4_address,
+ expected->ipv6_address)).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ EXPECT_EQ(expected->name,
+ interface_listener_impl_->GetSelectedInterfaceName());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_SkipEmptyInterface) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries[] = {
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING},
+ {"net_dummy2", NULL, NULL, IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ SetDummyInterfaceTable(entries);
+
+ // net_dummy2 should not be selected
+ struct InterfaceEntry* expected = &entries[0];
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(expected->ipv4_address, "")).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ EXPECT_EQ(expected->name,
+ interface_listener_impl_->GetSelectedInterfaceName());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest,
+ AutoSelectInterface_SkipLoopbackInterface) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries[] = {
+ {"dummy_int1", "10.10.10.12", NULL, IFF_UP | IFF_RUNNING | IFF_LOOPBACK},
+ {"net_dummy2", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ // dummy_int1 should not be selected
+ struct InterfaceEntry* expected = &entries[1];
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(expected->ipv4_address,
+ expected->ipv6_address)).Times(1);
+
+ SetDummyInterfaceTable(entries);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ EXPECT_EQ(expected->name,
+ interface_listener_impl_->GetSelectedInterfaceName());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_DisableInterface) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries[] = {
+ {"net_dummy0", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(1);
+ SetDummyInterfaceTable(entries);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ // make the interface "not running"
+ entries[0].flags &= ~IFF_RUNNING;
+ SetDummyInterfaceTable(entries);
+
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated("", "")).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ EXPECT_EQ("", interface_listener_impl_->GetSelectedInterfaceName());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_EnableInterface) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries[] = {
+ {"net_dummy0", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(1);
+ SetDummyInterfaceTable(entries);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ // make the interface "not running"
+ entries[0].flags &= ~IFF_RUNNING;
+ SetDummyInterfaceTable(entries);
+
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ // make it running again
+ entries[0].flags |= IFF_RUNNING;
+ SetDummyInterfaceTable(entries);
+
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(entries[0].ipv4_address,
+ entries[0].ipv6_address)).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ EXPECT_EQ(entries[0].name,
+ interface_listener_impl_->GetSelectedInterfaceName());
+
+ Deinit();
+}
+
+TEST_F(NetworkInterfaceListenerTest, AutoSelectInterface_SwitchInterface) {
+ Init("");
+ EXPECT_TRUE(interface_listener_impl_->Init());
+
+ struct InterfaceEntry entries[] = {
+ {"dummy_int1",
+ "10.10.10.12",
+ "fd53:ba79:241d:30c1::78",
+ IFF_UP | IFF_RUNNING},
+ {"net_dummy2", "192.168.2.3", "fdc2:12af:327a::22", IFF_UP | IFF_RUNNING},
+ {NULL, NULL, NULL, 0}};
+
+ EXPECT_CALL(mock_tcp_client_listener_, OnIPAddressUpdated(_, _)).Times(1);
+ SetDummyInterfaceTable(entries);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ const std::string selected_interface =
+ interface_listener_impl_->GetSelectedInterfaceName();
+ struct InterfaceEntry* selected = &entries[0];
+ while (selected->name != NULL) {
+ if (selected->name == selected_interface) {
+ break;
+ }
+ selected++;
+ }
+ ASSERT_TRUE(selected->name != NULL);
+
+ // make the interface "not running"
+ selected->flags &= ~IFF_RUNNING;
+ SetDummyInterfaceTable(entries);
+
+ struct InterfaceEntry* switched;
+ if (selected == &entries[0]) {
+ switched = &entries[1];
+ } else {
+ switched = &entries[0];
+ }
+
+ EXPECT_CALL(mock_tcp_client_listener_,
+ OnIPAddressUpdated(switched->ipv4_address,
+ switched->ipv6_address)).Times(1);
+
+ interface_listener_impl_->testCallNotifyIPAddresses();
+
+ EXPECT_EQ(switched->name,
+ interface_listener_impl_->GetSelectedInterfaceName());
+
+ Deinit();
+}
+
+} // namespace transport_manager_test
+} // namespace components
+} // namespace test