package com.silicondust.libhdhomerun;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
public class HDHomerun_Sock {
public static final int DEFAULT_NONBLOCKING_TIMEOUT = 1;
public static class hdhomerun_local_ip_info_t {
public int ip_addr; // uint32_t
public int subnet_mask; // uint32_t
};
public static String IPAddr_IntToString(int ip) {
byte[] ipBytes = IPAddr_IntToBytes(ip);
int[] ipInts = new int[4];
ipInts[0] = ipBytes[0];
if(ipInts[0] < 0)
ipInts[0] += 256;
ipInts[1] = ipBytes[1];
if(ipInts[1] < 0)
ipInts[1] += 256;
ipInts[2] = ipBytes[2];
if(ipInts[2] < 0)
ipInts[2] += 256;
ipInts[3] = ipBytes[3];
if(ipInts[3] < 0)
ipInts[3] += 256;
return String.format("%d.%d.%d.%d", ipInts[0], ipInts[1], ipInts[2], ipInts[3]);
}
public static byte[] IPAddr_IntToBytes(int ip) {
byte[] ret = new byte[4];
ret[0] = (byte) (ip >> 24);
ret[1] = (byte) (ip >> 16);
ret[2] = (byte) (ip >> 8);
ret[3] = (byte) (ip >> 0);
return ret;
}
public static int IPAddr_BytesToInt(byte[] ip) {
int ret = 0;
int byte0 = (HDHomerun_OS.getRealUByteVal(ip[0]) << 24);
int byte1 = (HDHomerun_OS.getRealUByteVal(ip[1]) << 16);
int byte2 = (HDHomerun_OS.getRealUByteVal(ip[2]) << 8);
int byte3 = (HDHomerun_OS.getRealUByteVal(ip[3]) << 0);
ret = byte0 | byte1 | byte2 | byte3;
return ret;
}
public static final int HDHOMERUN_SOCK_INVALID = -1;
private hdhomerun_sock_t mSocket;
private Exception mLastError = new Exception();
public interface hdhomerun_sock_t {
public boolean isValid();
void closeSocket() throws Exception;
public SocketAddress getSocketAddr();
public int getSocketPort();
public boolean addGroup(InetAddress multicastIP);
public boolean dropGroup(InetAddress multicastIP);
public int send(byte[] data, int startIndex, int length, int timeout) throws IOException;
public int sendto(byte[] data, int startIndex, int length, InetSocketAddress remoteAddr, int timeout) throws IOException;
boolean recv(byte[] data, int start, int length[], int timeout) throws IOException;
InetSocketAddress recvfrom(byte[] data, int start, int length[], int timeout) throws IOException;
}
// UPD
public HDHomerun_Sock(int local_addr, int local_port, int sendBufferSize, int recBufferSize, boolean allowReuse) throws Exception {
InetAddress inetAddr = InetAddress.getByAddress(IPAddr_IntToBytes(local_addr));
InetSocketAddress localAddr = new InetSocketAddress(inetAddr, local_port);
mSocket = (hdhomerun_sock_t) new HDHomerun_sock_t_udp(localAddr, sendBufferSize, recBufferSize, allowReuse);
}
// TCP
public HDHomerun_Sock(int remote_addr, int remote_port, int sendBufferSize, int recBufferSize, int timeout) throws IOException {
InetAddress inetAddr = InetAddress.getByAddress(IPAddr_IntToBytes(remote_addr));
InetSocketAddress remoteAddr = new InetSocketAddress(inetAddr, remote_port);
mSocket = (hdhomerun_sock_t) new HDHomerun_sock_t_tcp(remoteAddr, sendBufferSize, recBufferSize, timeout);
}
private static int ShiftSubnetBitsInt(int bitShift) {
int ret = 0;
for(int i = 0; i < bitShift; ++i) {
ret |= (1 << (31 - i));
}
return ret;
}
// hdhomerun_local_ip_info - how many adapters have ip addresses
public static int hdhomerun_local_ip_info(hdhomerun_local_ip_info_t ip_info_list[], int max_count)
{
int count = 0;
try {
for(Enumeration<NetworkInterface> list = NetworkInterface.getNetworkInterfaces(); list.hasMoreElements();)
{
NetworkInterface i = list.nextElement();
for(Enumeration<InetAddress> adds = i.getInetAddresses(); adds.hasMoreElements(); ) {
InetAddress a = adds.nextElement();
int subnet = ShiftSubnetBitsInt(24);
if(a.isLoopbackAddress() || a.getHostAddress().equals("255.255.255.255") || a.getHostAddress().equals("0.0.0.0"))
continue;
// only ipv4
if(a.getAddress().length > 4)
continue;
ip_info_list[count] = new hdhomerun_local_ip_info_t();
ip_info_list[count].ip_addr = IPAddr_BytesToInt(a.getAddress());
ip_info_list[count++].subnet_mask = subnet;
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return count;
}
public void destroy()
{
try {
mSocket.closeSocket();
} catch (Exception e) {
mLastError = e;
}
}
public final String getlasterror()
{
return mLastError.getMessage();
}
public InetSocketAddress getsockname_addr() // uint32_t
{
return (InetSocketAddress) mSocket.getSocketAddr();
}
public int getsockname_port()
{
return mSocket.getSocketPort();
}
public boolean addGroup(int multicastIP) {
try {
InetAddress multicastAddr = InetAddress.getByAddress(IPAddr_IntToBytes(multicastIP));
return mSocket.addGroup(multicastAddr);
} catch (UnknownHostException e) {
return false;
}
}
public boolean dropGroup(int multicastIP) {
try {
InetAddress multicastAddr = InetAddress.getByAddress(IPAddr_IntToBytes(multicastIP));
return mSocket.dropGroup(multicastAddr);
} catch (UnknownHostException e) {
return false;
}
}
public static int getaddrinfo_addr(final String name) // uint32_t
{
int ret = 0;
try {
InetAddress inet = InetAddress.getByName(name);
ret = IPAddr_BytesToInt(inet.getAddress());
} catch (UnknownHostException e) {
// couldn't find it, oh well
}
return ret;
}
boolean send(final byte[] data, int startIndex, int length, int timeout)
{
boolean ret = false;
try {
if(0 < mSocket.send(data, startIndex, length, timeout))
ret = true;
}
catch(IOException e) {
mLastError = e;
}
return ret;
}
boolean sendto(int remote_addr, int remote_port, final byte[] data, int startIndex, int length, int timeout) {
InetAddress inetAddr;
try {
inetAddr = InetAddress.getByAddress(IPAddr_IntToBytes(remote_addr));
} catch (UnknownHostException e1) {
mLastError = e1;
return false;
}
InetSocketAddress remoteAddr = new InetSocketAddress(inetAddr, remote_port);
boolean ret =false;
try {
if(0 < mSocket.sendto(data, startIndex, length, remoteAddr, timeout))
ret = true;
}
catch(IOException e) {
mLastError = e;
}
return ret;
}
boolean recv(byte[] data, int start, int[] length, int timeout)
{
boolean ret = false;
try {
ret = mSocket.recv(data, start, length, timeout);
}
catch(IOException e) {
mLastError = e;
}
return ret;
}
boolean recvfrom(int[] remote_addr, int[] remote_port, byte[] data, int start, int[] length, int timeout)
{
boolean ret = false;
try {
InetSocketAddress remoteAddr = (InetSocketAddress) mSocket.recvfrom(data, start, length, timeout);
if(remoteAddr != null)
{
remote_addr[0] = IPAddr_BytesToInt(remoteAddr.getAddress().getAddress());
remote_port[0] = remoteAddr.getPort();
ret = true;
}
}
catch(IOException e) {
mLastError = e;
}
return ret;
}
public boolean isValid() {
return mSocket.isValid();
}
}