[Windows] Remove redundant DirectSound error codes
[xbmc.git] / xbmc / platform / android / network / NetworkAndroid.cpp
blob738bed7cdd22d5d5571cca38e0445c77403414fa
1 /*
2 * Copyright (C) 2016 Christian Browet
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "NetworkAndroid.h"
11 #include "utils/StringUtils.h"
12 #include "utils/log.h"
14 #include <mutex>
16 #include <androidjni/ConnectivityManager.h>
17 #include <androidjni/Context.h>
18 #include <androidjni/InetAddress.h>
19 #include <androidjni/LinkAddress.h>
20 #include <androidjni/NetworkInfo.h>
21 #include <androidjni/RouteInfo.h>
22 #include <arpa/inet.h>
23 #include <net/if_arp.h>
24 #include <netinet/in.h>
25 #include <sys/wait.h>
27 CNetworkInterfaceAndroid::CNetworkInterfaceAndroid(const CJNINetwork& network,
28 const CJNILinkProperties& lp,
29 const CJNINetworkInterface& intf)
30 : m_network(network), m_lp(lp), m_intf(intf)
32 m_name = m_intf.getName();
35 std::vector<std::string> CNetworkInterfaceAndroid::GetNameServers()
37 std::vector<std::string> ret;
39 CJNIList<CJNIInetAddress> lia = m_lp.getDnsServers();
40 ret.reserve(lia.size());
41 for (int i=0; i < lia.size(); ++i)
43 ret.push_back(lia.get(i).getHostAddress());
46 return ret;
49 bool CNetworkInterfaceAndroid::IsEnabled() const
51 CJNIConnectivityManager connman(CJNIContext::getSystemService(CJNIContext::CONNECTIVITY_SERVICE));
52 CJNINetworkInfo ni = connman.getNetworkInfo(m_network);
53 if (!ni)
54 return false;
56 return ni.isAvailable();
59 bool CNetworkInterfaceAndroid::IsConnected() const
61 CJNIConnectivityManager connman(CJNIContext::getSystemService(CJNIContext::CONNECTIVITY_SERVICE));
62 CJNINetworkInfo ni = connman.getNetworkInfo(m_network);
63 if (!ni)
64 return false;
66 return ni.isConnected();
69 std::string CNetworkInterfaceAndroid::GetMacAddress() const
71 auto interfaceMacAddrRaw = m_intf.getHardwareAddress();
72 if (xbmc_jnienv()->ExceptionCheck())
74 xbmc_jnienv()->ExceptionClear();
75 CLog::Log(LOGERROR, "CNetworkInterfaceAndroid::GetMacAddress Exception getting HW address");
76 return "";
78 if (interfaceMacAddrRaw.size() >= 6)
80 return (StringUtils::Format("{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
81 (uint8_t)interfaceMacAddrRaw[0], (uint8_t)interfaceMacAddrRaw[1],
82 (uint8_t)interfaceMacAddrRaw[2], (uint8_t)interfaceMacAddrRaw[3],
83 (uint8_t)interfaceMacAddrRaw[4], (uint8_t)interfaceMacAddrRaw[5]));
85 return "";
88 void CNetworkInterfaceAndroid::GetMacAddressRaw(char rawMac[6]) const
90 auto interfaceMacAddrRaw = m_intf.getHardwareAddress();
91 if (xbmc_jnienv()->ExceptionCheck())
93 xbmc_jnienv()->ExceptionClear();
94 CLog::Log(LOGERROR, "CNetworkInterfaceAndroid::GetMacAddress Exception getting HW address");
95 return;
97 if (interfaceMacAddrRaw.size() >= 6)
98 memcpy(rawMac, interfaceMacAddrRaw.data(), 6);
101 bool CNetworkInterfaceAndroid::GetHostMacAddress(unsigned long host_ip, std::string& mac) const
103 struct arpreq areq;
104 struct sockaddr_in* sin;
106 memset(&areq, 0x0, sizeof(areq));
108 sin = (struct sockaddr_in *) &areq.arp_pa;
109 sin->sin_family = AF_INET;
110 sin->sin_addr.s_addr = host_ip;
112 sin = (struct sockaddr_in *) &areq.arp_ha;
113 sin->sin_family = ARPHRD_ETHER;
115 strncpy(areq.arp_dev, m_name.c_str(), sizeof(areq.arp_dev));
116 areq.arp_dev[sizeof(areq.arp_dev)-1] = '\0';
118 int sock = socket(AF_INET, SOCK_DGRAM, 0);
119 if (sock != -1)
121 int result = ioctl (sock, SIOCGARP, (caddr_t) &areq);
122 close(sock);
124 if (result != 0)
126 // CLog::Log(LOGERROR, "{} - GetHostMacAddress/ioctl failed with errno ({})", __FUNCTION__, errno);
127 return false;
130 else
131 return false;
133 struct sockaddr* res = &areq.arp_ha;
134 mac = StringUtils::Format("{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}", (uint8_t)res->sa_data[0],
135 (uint8_t)res->sa_data[1], (uint8_t)res->sa_data[2],
136 (uint8_t)res->sa_data[3], (uint8_t)res->sa_data[4],
137 (uint8_t)res->sa_data[5]);
139 for (int i=0; i<6; ++i)
140 if (res->sa_data[i])
141 return true;
143 return false;
146 std::string CNetworkInterfaceAndroid::GetCurrentIPAddress() const
148 CJNIList<CJNILinkAddress> lla = m_lp.getLinkAddresses();
149 if (lla.size() == 0)
150 return "";
152 int i = 0;
153 for (;i < lla.size(); ++i)
155 if (lla.get(i).getAddress().getAddress().size() > 4) // IPV4 only
156 continue;
157 break;
159 if (i == lla.size())
160 return "";
162 CJNILinkAddress la = lla.get(i);
163 return la.getAddress().getHostAddress();
166 std::string CNetworkInterfaceAndroid::GetCurrentNetmask() const
168 CJNIList<CJNILinkAddress> lla = m_lp.getLinkAddresses();
169 if (lla.size() == 0)
170 return "";
172 int i = 0;
173 for (;i < lla.size(); ++i)
175 if (lla.get(i).getAddress().getAddress().size() > 4) // IPV4 only
176 continue;
177 break;
179 if (i == lla.size())
180 return "";
182 CJNILinkAddress la = lla.get(i);
184 int prefix = la.getPrefixLength();
185 unsigned long mask = (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF;
186 return StringUtils::Format("{}.{}.{}.{}", mask >> 24, (mask >> 16) & 0xFF, (mask >> 8) & 0xFF,
187 mask & 0xFF);
190 std::string CNetworkInterfaceAndroid::GetCurrentDefaultGateway() const
192 CJNIList<CJNIRouteInfo> ris = m_lp.getRoutes();
194 for (int i = 0; i < ris.size(); ++i)
196 CJNIRouteInfo ri = ris.get(i);
197 if (!ri.isDefaultRoute())
198 continue;
200 return ri.getGateway().getHostAddress();
203 return "";
206 std::string CNetworkInterfaceAndroid::GetHostName()
208 CJNIList<CJNILinkAddress> lla = m_lp.getLinkAddresses();
209 if (lla.size() == 0)
210 return "";
212 int i = 0;
213 for (;i < lla.size(); ++i)
215 if (lla.get(i).getAddress().getAddress().size() > 4) // IPV4 only
216 continue;
217 break;
219 if (i == lla.size())
220 return "";
222 CJNILinkAddress la = lla.get(i);
223 return la.getAddress().getHostName();
227 /*************************/
229 std::unique_ptr<CNetworkBase> CNetworkBase::GetNetwork()
231 return std::make_unique<CNetworkAndroid>();
234 CNetworkAndroid::CNetworkAndroid() : CNetworkBase(), CJNIXBMCConnectivityManagerNetworkCallback()
236 RetrieveInterfaces();
238 CJNIConnectivityManager connman{CJNIContext::getSystemService(CJNIContext::CONNECTIVITY_SERVICE)};
239 connman.registerDefaultNetworkCallback(this->get_raw());
242 CNetworkAndroid::~CNetworkAndroid()
244 for (auto intf : m_interfaces)
245 delete intf;
246 for (auto intf : m_oldInterfaces)
247 delete intf;
249 CJNIConnectivityManager connman{CJNIContext::getSystemService(CJNIContext::CONNECTIVITY_SERVICE)};
250 connman.unregisterNetworkCallback(this->get_raw());
253 bool CNetworkAndroid::GetHostName(std::string& hostname)
255 CNetworkInterfaceAndroid* intf = dynamic_cast<CNetworkInterfaceAndroid*>(GetFirstConnectedInterface());
256 if (intf)
258 hostname = intf->GetHostName();
259 return true;
261 return false;
264 std::vector<CNetworkInterface*>& CNetworkAndroid::GetInterfaceList()
266 std::unique_lock<CCriticalSection> lock(m_refreshMutex);
267 return m_interfaces;
270 CNetworkInterface* CNetworkAndroid::GetFirstConnectedInterface()
272 std::unique_lock<CCriticalSection> lock(m_refreshMutex);
274 if (m_defaultInterface)
275 return m_defaultInterface.get();
276 else
278 for (CNetworkInterface* intf : m_interfaces)
280 if (intf->IsEnabled() && intf->IsConnected() && !intf->GetCurrentDefaultGateway().empty())
281 return intf;
285 return nullptr;
288 std::vector<std::string> CNetworkAndroid::GetNameServers()
290 CNetworkInterfaceAndroid* intf = static_cast<CNetworkInterfaceAndroid*>(GetFirstConnectedInterface());
291 if (intf)
292 return intf->GetNameServers();
294 return std::vector<std::string>();
297 bool CNetworkAndroid::PingHost(unsigned long remote_ip, unsigned int timeout_ms)
299 char cmd_line [64];
301 struct in_addr host_ip;
302 host_ip.s_addr = remote_ip;
304 snprintf(cmd_line, sizeof(cmd_line), "ping -c 1 -w %d %s",
305 timeout_ms / 1000 + (timeout_ms % 1000) != 0, inet_ntoa(host_ip));
307 int status = system (cmd_line);
309 int result = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
311 // http://linux.about.com/od/commands/l/blcmdl8_ping.htm ;
312 // 0 reply
313 // 1 no reply
314 // else some error
316 if (result < 0 || result > 1)
317 CLog::Log(LOGERROR, "Ping fail : status = {}, errno = {} : '{}'", status, errno, cmd_line);
319 return result == 0;
322 void CNetworkAndroid::RetrieveInterfaces()
324 std::unique_lock<CCriticalSection> lock(m_refreshMutex);
326 // Cannot delete interfaces here, as there still might have references to it
327 for (auto intf : m_oldInterfaces)
328 delete intf;
329 m_oldInterfaces = m_interfaces;
330 m_interfaces.clear();
332 CJNIConnectivityManager connman(CJNIContext::getSystemService(CJNIContext::CONNECTIVITY_SERVICE));
333 std::vector<CJNINetwork> networks = connman.getAllNetworks();
335 for (const auto& n : networks)
337 CJNILinkProperties lp = connman.getLinkProperties(n);
338 if (lp)
340 CJNINetworkInterface intf = CJNINetworkInterface::getByName(lp.getInterfaceName());
341 if (xbmc_jnienv()->ExceptionCheck())
343 xbmc_jnienv()->ExceptionClear();
344 CLog::Log(LOGERROR, "CNetworkAndroid::RetrieveInterfaces Cannot get interface by name: {}",
345 lp.getInterfaceName());
346 continue;
348 if (intf)
349 m_interfaces.push_back(new CNetworkInterfaceAndroid(n, lp, intf));
350 else
351 CLog::Log(LOGERROR, "CNetworkAndroid::RetrieveInterfaces Cannot get interface by name: {}",
352 lp.getInterfaceName());
354 else
355 CLog::Log(LOGERROR,
356 "CNetworkAndroid::RetrieveInterfaces Cannot get link properties for network: {}",
357 n.toString());
361 void CNetworkAndroid::onAvailable(const CJNINetwork n)
363 CLog::Log(LOGDEBUG, "CNetworkAndroid::onAvailable The default network is now: {}", n.toString());
365 CJNIConnectivityManager connman{CJNIContext::getSystemService(CJNIContext::CONNECTIVITY_SERVICE)};
366 CJNILinkProperties lp = connman.getLinkProperties(n);
368 if (lp)
370 CJNINetworkInterface intf = CJNINetworkInterface::getByName(lp.getInterfaceName());
371 if (intf)
372 m_defaultInterface = std::make_unique<CNetworkInterfaceAndroid>(n, lp, intf);
376 void CNetworkAndroid::onLost(const CJNINetwork n)
378 CLog::Log(LOGDEBUG, "CNetworkAndroid::onLost No default network (the last was: {})",
379 n.toString());
380 m_defaultInterface = nullptr;