All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tuwien.auto.calimero.knxnetip.util.HPAI Maven / Gradle / Ivy

There is a newer version: 2.6-rc1
Show newest version
/*
    Calimero 2 - A library for KNX network access
    Copyright (c) 2006, 2017 B. Malinowsky

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Linking this library statically or dynamically with other modules is
    making a combined work based on this library. Thus, the terms and
    conditions of the GNU General Public License cover the whole
    combination.

    As a special exception, the copyright holders of this library give you
    permission to link this library with independent modules to produce an
    executable, regardless of the license terms of these independent
    modules, and to copy and distribute the resulting executable under terms
    of your choice, provided that you also meet, for each linked independent
    module, the terms and conditions of the license of that module. An
    independent module is a module which is not derived from or based on
    this library. If you modify this library, you may extend this exception
    to your version of the library, but you are not obligated to do so. If
    you do not wish to do so, delete this exception statement from your
    version.
*/

package tuwien.auto.calimero.knxnetip.util;

import java.io.ByteArrayOutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

import tuwien.auto.calimero.KNXFormatException;
import tuwien.auto.calimero.KNXIllegalArgumentException;

/**
 * KNXnet/IP Host Protocol Address Information (HPAI).
 * 

* The address information is used to describe a communication channel. Its structure * varies according to the used underlying protocol. This class is implemented for IPv4. *
* For IP networks with NAT, consider use of {@link #HPAI(int, InetSocketAddress)}.
* UDP is the default communication mode with mandatory support used in KNXnet/IP. *

* Objects of this type are immutable. * * @author B. Malinowsky */ public class HPAI { /** * Internet protocol version 4 address, UDP communication. */ public static final int IPV4_UDP = 0x01; /** * Internet protocol version 4 address, TCP communication. */ public static final int IPV4_TCP = 0x02; private static final int HPAI_SIZE = 8; private final int length; private final int hostprot; private final byte[] address; private final int port; /** * Creates a HPAI out of a byte array. * * @param data byte array containing the HPAI structure * @param offset start offset of HPAI in data * @throws KNXFormatException if no HPAI found, invalid structure or unknown host * protocol */ public HPAI(final byte[] data, final int offset) throws KNXFormatException { if (data.length - offset < HPAI_SIZE) throw new KNXFormatException("buffer too short for HPAI"); int i = offset; length = data[i++] & 0xFF; if (length != HPAI_SIZE) throw new KNXFormatException("unknown HPAI size", length); hostprot = data[i++] & 0xFF; if (hostprot != IPV4_UDP && hostprot != IPV4_TCP) throw new KNXFormatException("unknown host protocol", hostprot); address = new byte[4]; address[0] = data[i++]; address[1] = data[i++]; address[2] = data[i++]; address[3] = data[i++]; int p = (data[i++] & 0xFF) << 8; p |= data[i] & 0xFF; port = p; } /** * Creates a HPAI for UDP communication with the given address information, using UDP as communication mode (default * in KNXnet/IP). The following first matching rule is used for the addr argument:
* 1) addr holds an {@link InetAddress}, use that address
* 2) addr is null, the local host is retrieved by {@link InetAddress#getLocalHost()}
* 3) if no local host could be found, fall back to safe state and initialize IP and port to 0 (NAT aware * mode) * * @param addr local IP address, use null for setting local host * @param port local port number to set, 0 <= port <= 0xFFFF */ public HPAI(final InetAddress addr, final int port) { this(IPV4_UDP, addrOrDefault(addr), port); } /** * Creates a HPAI with the given address information. * * @param hostProtocol host protocol code (UDP or TCP on IP) * @param addr local IP address * @param port local port number to set, 0 <= port <= 0xFFFF */ public HPAI(final int hostProtocol, final InetAddress addr, final int port) { this(hostProtocol, new InetSocketAddress(addr, port)); } /** * Creates a HPAI with the given address information. *

* To indicate the use of network address translation (NAT) to the receiver, leave * addr null. * * @param hostProtocol host protocol code (UDP or TCP, see class constants) * @param addr socket with IP address and port number, if addr = * null address and port are initialized to 0 */ public HPAI(final int hostProtocol, final InetSocketAddress addr) { length = HPAI_SIZE; if (hostProtocol != IPV4_UDP && hostProtocol != IPV4_TCP) throw new KNXIllegalArgumentException("unknown host protocol"); hostprot = hostProtocol; if (addr != null) { final InetAddress a = addr.getAddress(); if (a == null) throw new KNXIllegalArgumentException(addr + " is an unresolved IP address"); if (a.isAnyLocalAddress() && addr.getPort() != 0) throw new KNXIllegalArgumentException(a + " is a wildcard IP address"); address = a.getAddress(); if (address.length != 4) throw new KNXIllegalArgumentException(a + " is not an IPv4 address"); port = addr.getPort(); } else { address = new byte[4]; port = 0; } } /** * Returns the host protocol of this HPAI. *

* * @return host protocol code as unsigned byte */ public final int getHostProtocol() { return hostprot; } /** * Returns the raw IP network address. *

* * @return byte array with IP address in network byte order */ public final byte[] getRawAddress() { return address.clone(); } /** * Returns the IP network address as {@link InetAddress} representation. * * @return IP address as InetAddress object */ public final InetAddress getAddress() { try { return InetAddress.getByAddress(address); } catch (final UnknownHostException e) { throw new IllegalStateException(e); } } /** * Returns the port number of this HPAI. *

* * @return port as unsigned 16 bit value */ public final int getPort() { return port; } /** * Returns the structure length of this HPAI in bytes. *

* * @return structure length as unsigned byte */ public final int getStructLength() { return length; } /** * Returns the byte representation of the whole HPAI structure. *

* * @return byte array containing structure */ public final byte[] toByteArray() { final ByteArrayOutputStream os = new ByteArrayOutputStream(HPAI_SIZE); os.write(length); os.write(hostprot); os.write(address, 0, address.length); os.write(port >> 8); os.write(port); return os.toByteArray(); } /** * Returns this HPAI representation in textual format. *

* * @return a string representation of the HPAI object */ @Override public String toString() { return getAddressString() + ":" + port + " (IPv4 " + (hostprot == IPV4_UDP ? "UDP" : "TCP") + ")"; } @Override public boolean equals(final Object obj) { if (this == obj) return true; if (!(obj instanceof HPAI)) return false; final HPAI other = (HPAI) obj; return length == other.length && port == other.port && hostprot == other.hostprot && Arrays.hashCode(address) == Arrays.hashCode(other.address); } @Override public int hashCode() { final int prime = 17; return prime * (prime * (prime * Arrays.hashCode(address) + hostprot) + port) + length; } private String getAddressString() { return (address[0] & 0xFF) + "." + (address[1] & 0xFF) + "." + (address[2] & 0xFF) + "." + (address[3] & 0xFF); } private static InetAddress addrOrDefault(final InetAddress addr) { try { return addr != null ? addr : InetAddress.getLocalHost(); } catch (final UnknownHostException e) { try { return InetAddress.getByAddress(new byte[4]); } catch (final UnknownHostException unreachable) { throw new Error("raw IPv4 addresses should always work", unreachable); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy