| /* |
| * Copyright (C) 2017 Apple 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: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. 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. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h" |
| #include "NetworkRTCMonitor.h" |
| |
| #if USE(LIBWEBRTC) |
| |
| #include "Connection.h" |
| #include "Logging.h" |
| #include "NetworkRTCProvider.h" |
| #include "WebRTCMonitorMessages.h" |
| #include <webrtc/rtc_base/third_party/sigslot/sigslot.h> |
| #include <wtf/Function.h> |
| #include <wtf/WeakHashSet.h> |
| |
| namespace WebKit { |
| |
| #define RTC_RELEASE_LOG(fmt, ...) RELEASE_LOG(Network, "%p - NetworkRTCMonitor::" fmt, this, ##__VA_ARGS__) |
| |
| class NetworkManagerWrapper final : public sigslot::has_slots<> { |
| public: |
| void addListener(NetworkRTCMonitor&); |
| void removeListener(NetworkRTCMonitor&); |
| |
| private: |
| void onNetworksChanged(); |
| |
| std::unique_ptr<rtc::BasicNetworkManager> m_manager; |
| WeakHashSet<NetworkRTCMonitor> m_observers; |
| |
| bool m_didReceiveResults { false }; |
| Vector<RTCNetwork> m_networkList; |
| Vector<RTCNetwork> m_filteredNetworkList; |
| RTCNetwork::IPAddress m_ipv4; |
| RTCNetwork::IPAddress m_ipv6; |
| }; |
| |
| static NetworkManagerWrapper& networkManager() |
| { |
| static NeverDestroyed<NetworkManagerWrapper> networkManager; |
| return networkManager.get(); |
| } |
| |
| void NetworkManagerWrapper::addListener(NetworkRTCMonitor& monitor) |
| { |
| bool shouldStart = m_observers.computesEmpty(); |
| m_observers.add(monitor); |
| if (!shouldStart) { |
| if (m_didReceiveResults) |
| monitor.onNetworksChanged(m_networkList, m_filteredNetworkList, m_ipv4, m_ipv6); |
| return; |
| } |
| |
| monitor.rtcProvider().callOnRTCNetworkThread([this]() { |
| if (m_manager) |
| return; |
| |
| RELEASE_LOG(WebRTC, "NetworkManagerWrapper startUpdating"); |
| m_manager = makeUniqueWithoutFastMallocCheck<rtc::BasicNetworkManager>(); |
| m_manager->SignalNetworksChanged.connect(this, &NetworkManagerWrapper::onNetworksChanged); |
| m_manager->StartUpdating(); |
| }); |
| } |
| |
| void NetworkManagerWrapper::removeListener(NetworkRTCMonitor& monitor) |
| { |
| m_observers.remove(monitor); |
| if (!m_observers.computesEmpty()) |
| return; |
| |
| monitor.rtcProvider().callOnRTCNetworkThread([this]() { |
| if (!m_manager) |
| return; |
| |
| RELEASE_LOG(WebRTC, "NetworkManagerWrapper stopUpdating"); |
| m_manager->StopUpdating(); |
| m_manager = nullptr; |
| }); |
| } |
| |
| void NetworkManagerWrapper::onNetworksChanged() |
| { |
| RELEASE_LOG(WebRTC, "NetworkManagerWrapper::onNetworksChanged"); |
| |
| rtc::BasicNetworkManager::NetworkList networks; |
| |
| RTCNetwork::IPAddress ipv4; |
| m_manager->GetDefaultLocalAddress(AF_INET, &ipv4.value); |
| RTCNetwork::IPAddress ipv6; |
| m_manager->GetDefaultLocalAddress(AF_INET6, &ipv6.value); |
| |
| m_manager->GetNetworks(&networks); |
| |
| auto networkList = WTF::map(networks, [](auto& network) { return RTCNetwork { *network }; }); |
| Vector<RTCNetwork> filteredNetworkList; |
| for (auto& network : networks) { |
| const auto& ips = network->GetIPs(); |
| if (WTF::anyOf(ips, [&](const auto& ip) { return ipv4.value == ip || ipv6.value == ip; })) |
| filteredNetworkList.append(RTCNetwork { *network }); |
| } |
| |
| callOnMainRunLoop([this, networkList = WTFMove(networkList), filteredNetworkList = WTFMove(filteredNetworkList), ipv4 = WTFMove(ipv4), ipv6 = WTFMove(ipv6)]() mutable { |
| m_didReceiveResults = true; |
| |
| m_networkList = WTFMove(networkList); |
| m_filteredNetworkList = WTFMove(filteredNetworkList); |
| m_ipv4 = WTFMove(ipv4); |
| m_ipv6 = WTFMove(ipv6); |
| |
| m_observers.forEach([this](auto& observer) { |
| observer.onNetworksChanged(m_networkList, m_filteredNetworkList, m_ipv4, m_ipv6); |
| }); |
| }); |
| } |
| |
| NetworkRTCMonitor::~NetworkRTCMonitor() |
| { |
| ASSERT(!m_manager); |
| } |
| |
| void NetworkRTCMonitor::startUpdatingIfNeeded(bool enableEnumeratingAllNetworkInterfaces) |
| { |
| RTC_RELEASE_LOG("startUpdatingIfNeeded m_isStarted=%d", m_isStarted); |
| m_enableEnumeratingAllNetworkInterfaces = enableEnumeratingAllNetworkInterfaces; |
| networkManager().addListener(*this); |
| } |
| |
| void NetworkRTCMonitor::stopUpdating() |
| { |
| RTC_RELEASE_LOG("stopUpdating"); |
| networkManager().removeListener(*this); |
| } |
| |
| void NetworkRTCMonitor::onNetworksChanged(const Vector<RTCNetwork>& networkList, const Vector<RTCNetwork>& filteredNetworkList, const RTCNetwork::IPAddress& ipv4, const RTCNetwork::IPAddress& ipv6) |
| { |
| RTC_RELEASE_LOG("onNetworksChanged sent"); |
| m_rtcProvider.connection().send(Messages::WebRTCMonitor::NetworksChanged(m_enableEnumeratingAllNetworkInterfaces ? networkList : filteredNetworkList, ipv4, ipv6), 0); |
| } |
| |
| } // namespace WebKit |
| |
| #undef RTC_RELEASE_LOG |
| |
| #endif // USE(LIBWEBRTC) |