]> git.basschouten.com Git - openhab-addons.git/blob
59c05ed36e0a7c72b81c9683048d37bf86faf042
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.lifx.internal.util;
14
15 import static org.openhab.binding.lifx.internal.LifxBindingConstants.BROADCAST_PORT;
16
17 import java.net.Inet4Address;
18 import java.net.InetAddress;
19 import java.net.InetSocketAddress;
20 import java.net.InterfaceAddress;
21 import java.net.NetworkInterface;
22 import java.net.SocketException;
23 import java.time.Duration;
24 import java.util.ArrayList;
25 import java.util.Enumeration;
26 import java.util.List;
27 import java.util.concurrent.atomic.AtomicInteger;
28
29 import org.eclipse.jdt.annotation.NonNullByDefault;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * The {@link LifxNetworkUtil} provides network interface information to the LIFX binding objects. The information is
35  * updated when it is older than {@link #UPDATE_INTERVAL_MILLIS}.
36  *
37  * @author Wouter Born - Initial contribution
38  */
39 @NonNullByDefault
40 public final class LifxNetworkUtil {
41
42     private static final Logger LOGGER = LoggerFactory.getLogger(LifxNetworkUtil.class);
43     private static final AtomicInteger BROADCAST_PORT_COUNTER = new AtomicInteger(1);
44     private static final long UPDATE_INTERVAL_MILLIS = Duration.ofSeconds(15).toMillis();
45     private static final int PORT_MAX = 65535;
46
47     private static List<InetSocketAddress> broadcastAddresses = new ArrayList<>();
48     private static List<InetAddress> interfaceAddresses = new ArrayList<>();
49     private static int bufferSize; // upper bound of the MTUs of all available IPv4 network interfaces
50     private static long lastUpdateMillis;
51
52     private LifxNetworkUtil() {
53         // hidden utility class constructor
54     }
55
56     /**
57      * Updates the network information without any synchronization in a thread-safe way.
58      */
59     private static void updateNetworkInformation() {
60         LOGGER.debug("Updating network information");
61
62         List<InetSocketAddress> newBroadcastAddresses = new ArrayList<>();
63         List<InetAddress> newInterfaceAddresses = new ArrayList<>();
64         int newBufferSize = 0;
65
66         Enumeration<NetworkInterface> networkInterfaces = null;
67         try {
68             networkInterfaces = NetworkInterface.getNetworkInterfaces();
69         } catch (SocketException e) {
70             LOGGER.debug("Exception while getting network interfaces: '{}'", e.getMessage());
71         }
72
73         if (networkInterfaces != null) {
74             while (networkInterfaces.hasMoreElements()) {
75                 NetworkInterface iface = networkInterfaces.nextElement();
76                 try {
77                     if (iface.isUp() && !iface.isLoopback()) {
78                         for (InterfaceAddress ifaceAddr : iface.getInterfaceAddresses()) {
79                             if (ifaceAddr.getAddress() instanceof Inet4Address) {
80                                 newInterfaceAddresses.add(ifaceAddr.getAddress());
81                                 newBufferSize = Math.max(newBufferSize, iface.getMTU());
82                                 if (ifaceAddr.getBroadcast() != null) {
83                                     newBroadcastAddresses
84                                             .add(new InetSocketAddress(ifaceAddr.getBroadcast(), BROADCAST_PORT));
85                                 }
86                             }
87                         }
88                     }
89                 } catch (SocketException e) {
90                     LOGGER.debug("Exception while getting information for network interface '{}': '{}'",
91                             iface.getName(), e.getMessage());
92                 }
93             }
94
95             broadcastAddresses = newBroadcastAddresses;
96             interfaceAddresses = newInterfaceAddresses;
97             bufferSize = newBufferSize;
98         }
99
100         lastUpdateMillis = System.currentTimeMillis();
101     }
102
103     private static void updateOutdatedNetworkInformation() {
104         boolean updateIntervalElapsed = System.currentTimeMillis() - lastUpdateMillis > UPDATE_INTERVAL_MILLIS;
105         if (updateIntervalElapsed) {
106             updateNetworkInformation();
107         }
108     }
109
110     public static List<InetSocketAddress> getBroadcastAddresses() {
111         updateOutdatedNetworkInformation();
112         return broadcastAddresses;
113     }
114
115     public static List<InetAddress> getInterfaceAddresses() {
116         updateOutdatedNetworkInformation();
117         return interfaceAddresses;
118     }
119
120     public static int getBufferSize() {
121         updateOutdatedNetworkInformation();
122         return bufferSize;
123     }
124
125     public static boolean isLocalAddress(InetAddress address) {
126         return getInterfaceAddresses().contains(address);
127     }
128
129     public static boolean isRemoteAddress(InetAddress address) {
130         return !isLocalAddress(address);
131     }
132
133     public static int getNewBroadcastPort() {
134         int offset = BROADCAST_PORT_COUNTER.getAndUpdate((value) -> {
135             return (value + 1) % Integer.MAX_VALUE;
136         });
137         return BROADCAST_PORT + (offset % (PORT_MAX - BROADCAST_PORT));
138     }
139 }