]> git.basschouten.com Git - openhab-addons.git/blob
f894e7d47ce7c6262986838a5b93c8b2d4e80052
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.io.hueemulation.internal.upnp;
14
15 import java.io.IOException;
16 import java.net.Inet6Address;
17 import java.net.InetAddress;
18 import java.net.UnknownHostException;
19 import java.nio.channels.Selector;
20 import java.util.concurrent.CompletableFuture;
21 import java.util.function.Consumer;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.io.hueemulation.internal.HueEmulationConfig;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 /**
30  * The upnp server runtime configuration. Based on a {@link HueEmulationConfig} and determined ip address and port.
31  * This extends {@link Thread}, because a runtime configuration is always valid for exactly one thread to be started
32  * once.
33  *
34  * @author David Graeff - Initial contribution
35  */
36 @NonNullByDefault
37 class HueEmulationConfigWithRuntime extends Thread implements Runnable {
38
39     private final Logger logger = LoggerFactory.getLogger(HueEmulationConfigWithRuntime.class);
40
41     final @NonNullByDefault({}) HueEmulationConfig config;
42     final InetAddress address;
43     final String addressString;
44     final InetAddress multicastAddress;
45     int port;
46
47     final CompletableFuture<@Nullable HueEmulationConfigWithRuntime> future = new CompletableFuture<>();
48     final Consumer<HueEmulationConfigWithRuntime> r;
49
50     // IO
51     public @Nullable Selector asyncIOselector;
52     private boolean hasAlreadyBeenStarted = false;
53
54     HueEmulationConfigWithRuntime(Consumer<HueEmulationConfigWithRuntime> r, HueEmulationConfig config,
55             String addrString, InetAddress MULTI_ADDR_IPV4, InetAddress MULTI_ADDR_IPV6) throws UnknownHostException {
56         super("HueEmulation UPNP Server");
57         this.r = r;
58         this.config = config;
59
60         address = InetAddress.getByName(addrString);
61         if (address instanceof Inet6Address) {
62             addressString = "[" + address.getHostAddress().split("%")[0] + "]";
63             multicastAddress = MULTI_ADDR_IPV6;
64         } else {
65             addressString = address.getHostAddress();
66             multicastAddress = MULTI_ADDR_IPV4;
67         }
68
69         port = config.discoveryHttpPort == 0 ? Integer.getInteger("org.osgi.service.http.port", 8080)
70                 : config.discoveryHttpPort;
71     }
72
73     HueEmulationConfigWithRuntime(Consumer<HueEmulationConfigWithRuntime> r, @Nullable HueEmulationConfig config,
74             InetAddress MULTI_ADDR_IPV4, InetAddress MULTI_ADDR_IPV6) throws UnknownHostException {
75         super("HueEmulation UPNP Server");
76         this.r = r;
77         this.config = config;
78
79         address = InetAddress.getByName("localhost");
80         if (address instanceof Inet6Address) {
81             addressString = "[" + address.getHostAddress().split("%")[0] + "]";
82             multicastAddress = MULTI_ADDR_IPV6;
83         } else {
84             addressString = address.getHostAddress();
85             multicastAddress = MULTI_ADDR_IPV4;
86         }
87         port = 8080;
88     }
89
90     String getMulticastAddress() {
91         if (multicastAddress instanceof Inet6Address) {
92             return "[" + multicastAddress.getHostAddress().split("%")[0] + "]";
93         } else {
94             return multicastAddress.getHostAddress();
95         }
96     }
97
98     public synchronized CompletableFuture<@Nullable HueEmulationConfigWithRuntime> startNow() {
99         if (hasAlreadyBeenStarted) {
100             logger.debug("Cannot restart thread");
101             return future;
102         }
103         hasAlreadyBeenStarted = true;
104         super.start();
105         return future;
106     }
107
108     @Override
109     public void run() {
110         r.accept(this);
111     }
112
113     public void dispose() {
114         Selector selector = asyncIOselector;
115         if (selector != null) {
116             try {
117                 selector.close();
118             } catch (IOException ignored) {
119             }
120
121             try {
122                 join();
123             } catch (InterruptedException ignore) {
124                 Thread.currentThread().interrupt();
125             }
126             asyncIOselector = null;
127         }
128     }
129 }