Kore/app/src/main/java/org/xbmc/kore/utils/NetUtils.java

166 lines
5.8 KiB
Java

/*
* Copyright 2015 Synced Synapse. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xbmc.kore.utils;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* Various utilities related to networking
*/
public class NetUtils {
private static final String TAG = LogUtils.makeLogTag(NetUtils.class);
/**
* Convert a IPv4 address from an integer to an InetAddress.
* @param hostAddress an int corresponding to the IPv4 address in network byte order
*/
public static InetAddress intToInetAddress(int hostAddress) {
if (hostAddress == 0)
return null;
byte[] addressBytes = { (byte)(0xff & hostAddress),
(byte)(0xff & (hostAddress >> 8)),
(byte)(0xff & (hostAddress >> 16)),
(byte)(0xff & (hostAddress >> 24)) };
try {
return InetAddress.getByAddress(addressBytes);
} catch (UnknownHostException e) {
throw new AssertionError();
}
}
/**
* Tries to return the MAC address of a host on the same subnet by looking at the ARP cache..
* Note: This is a synchronous call, so it should only be called on a background thread
*
* @param hostAddress Hostname or IP address
* @return MAC address if found or null
*/
public static String getMacAddress(String hostAddress) {
String ipHostAddress;
LogUtils.LOGD(TAG, "Starting get Mac Address for: " + hostAddress);
try {
InetAddress inet = InetAddress.getByName(hostAddress);
// Send some traffic, with a timeout
boolean reachable = inet.isReachable(1000);
ipHostAddress = inet.getHostAddress();
} catch (UnknownHostException e) {
LogUtils.LOGD(TAG, "Got an UnknownHostException for host: " + hostAddress, e);
return null;
} catch (IOException e) {
LogUtils.LOGD(TAG, "Couldn't check reachability of host: " + hostAddress, e);
return null;
}
try {
// Read the arp cache
BufferedReader br = new BufferedReader(new FileReader("/proc/net/arp"));
String arpLine;
while ((arpLine = br.readLine()) != null) {
if (arpLine.startsWith(ipHostAddress)) {
// Ok, this is the line, get the MAC Address
br.close();
return arpLine.split("\\s+")[3].toUpperCase(); // 4th element
}
}
br.close();
} catch (IOException e) {
LogUtils.LOGD(TAG, "Couldn check ARP cache.", e);
}
return null;
}
/**
* Sends a Wake On Lan magic packet to a host
* Note: This is a synchronous call, so it should only be called on a background thread
*
* @param macAddress MAC address
* @param hostAddress Hostname or IP address
* @param port Port for Wake On Lan
* @return Whether the packet was successfully sent
*/
public static boolean sendWolMagicPacket(String macAddress, String hostAddress, int port) {
if (macAddress == null) {
return false;
}
// Get MAC adress bytes
byte[] macAddressBytes = new byte[6];
String[] hex = macAddress.split("(\\:|\\-)");
if (hex.length != 6) {
LogUtils.LOGD(TAG, "Send magic packet: got an invalid MAC address: " + macAddress);
return false;
}
try {
for (int i = 0; i < 6; i++) {
macAddressBytes[i] = (byte)Integer.parseInt(hex[i], 16);
}
}
catch (NumberFormatException e) {
LogUtils.LOGD(TAG, "Send magic packet: got an invalid MAC address: " + macAddress);
return false;
}
byte[] bytes = new byte[6 + 16 * macAddressBytes.length];
for (int i = 0; i < 6; i++) {
bytes[i] = (byte)0xff;
}
for (int i = 6; i < bytes.length; i += macAddressBytes.length) {
System.arraycopy(macAddressBytes, 0, bytes, i, macAddressBytes.length);
}
try {
InetAddress address = InetAddress.getByName(hostAddress);
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
socket.close();
} catch (IOException e) {
LogUtils.LOGD(TAG, "Exception while sending magic packet.", e);
return false;
}
return true;
}
private static byte[] getMacBytes(String macStr) throws IllegalArgumentException {
byte[] bytes = new byte[6];
String[] hex = macStr.split("(\\:|\\-)");
if (hex.length != 6) {
throw new IllegalArgumentException("Invalid MAC address.");
}
try {
for (int i = 0; i < 6; i++) {
bytes[i] = (byte) Integer.parseInt(hex[i], 16);
}
}
catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid hex digit in MAC address.");
}
return bytes;
}
}