1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.channel.socket.nio;
17
18 import io.netty5.channel.socket.DomainSocketAddress;
19 import io.netty5.channel.socket.SocketProtocolFamily;
20 import io.netty5.util.internal.PlatformDependent;
21 import io.netty5.util.internal.logging.InternalLogger;
22 import io.netty5.util.internal.logging.InternalLoggerFactory;
23
24 import java.io.IOException;
25 import java.lang.invoke.MethodHandle;
26 import java.lang.invoke.MethodHandles;
27 import java.lang.invoke.MethodType;
28 import java.lang.reflect.InvocationTargetException;
29 import java.lang.reflect.Method;
30 import java.net.ProtocolFamily;
31 import java.net.SocketAddress;
32 import java.net.StandardProtocolFamily;
33 import java.nio.channels.Channel;
34 import java.nio.channels.spi.SelectorProvider;
35 import java.nio.file.Path;
36
37 final class NioChannelUtil {
38 private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioChannelUtil.class);
39
40 private static final MethodHandle OF_METHOD_HANDLE;
41 private static final MethodHandle GET_PATH_METHOD_HANDLE;
42
43 static {
44 MethodHandle ofMethodHandle = null;
45 MethodHandle getPathMethodHandle = null;
46
47 if (PlatformDependent.javaVersion() >= 16) {
48 try {
49 Class<?> clazz = Class.forName("java.net.UnixDomainSocketAddress", false,
50 PlatformDependent.getClassLoader(NioChannelUtil.class));
51 MethodHandles.Lookup lookup = MethodHandles.lookup();
52 MethodType type = MethodType.methodType(clazz, String.class);
53 ofMethodHandle = lookup.findStatic(clazz, "of", type);
54
55 type = MethodType.methodType(Path.class);
56 getPathMethodHandle = lookup.findVirtual(clazz, "getPath", type);
57 } catch (ClassNotFoundException t) {
58 ofMethodHandle = null;
59 getPathMethodHandle = null;
60 logger.debug(
61 "java.net.UnixDomainSocketAddress not found", t);
62 } catch (NoSuchMethodException | IllegalAccessException e) {
63 ofMethodHandle = null;
64 getPathMethodHandle = null;
65 logger.debug(
66 "Could not access methods of java.net.UnixDomainSocketAddress", e);
67 }
68 }
69 OF_METHOD_HANDLE = ofMethodHandle;
70 GET_PATH_METHOD_HANDLE = getPathMethodHandle;
71 }
72
73 static boolean isDomainSocket(ProtocolFamily family) {
74 if (family instanceof StandardProtocolFamily) {
75 return "UNIX".equals(family.name());
76 }
77 if (family instanceof SocketProtocolFamily) {
78 return family == SocketProtocolFamily.UNIX;
79 }
80 return false;
81 }
82
83 static SocketAddress toDomainSocketAddress(SocketAddress address) {
84 if (GET_PATH_METHOD_HANDLE != null) {
85 try {
86 Path path = (Path) GET_PATH_METHOD_HANDLE.invoke(address);
87 return new DomainSocketAddress(path.toFile());
88 } catch (RuntimeException e) {
89 throw e;
90 } catch (Throwable cause) {
91 return null;
92 }
93 }
94 return address;
95 }
96
97 static SocketAddress toUnixDomainSocketAddress(SocketAddress address) {
98 if (OF_METHOD_HANDLE != null) {
99 if (address instanceof DomainSocketAddress) {
100 try {
101 return (SocketAddress) OF_METHOD_HANDLE.invoke(((DomainSocketAddress) address).path());
102 } catch (RuntimeException e) {
103 throw e;
104 } catch (Throwable cause) {
105 return null;
106 }
107 }
108 }
109 return address;
110 }
111
112 static Method findOpenMethod(String methodName) {
113 if (PlatformDependent.javaVersion() >= 15) {
114 try {
115 return SelectorProvider.class.getMethod(methodName, ProtocolFamily.class);
116 } catch (Throwable e) {
117 logger.debug("SelectorProvider.{}(ProtocolFamily) not available, will use default", methodName, e);
118 }
119 }
120 return null;
121 }
122
123 static <C extends Channel> C newChannel(Method method, SelectorProvider provider,
124 ProtocolFamily family) throws IOException {
125
126
127
128
129
130
131 if (family != null && method != null) {
132 try {
133 @SuppressWarnings("unchecked")
134 C channel = (C) method.invoke(
135 provider, family);
136 return channel;
137 } catch (InvocationTargetException | IllegalAccessException e) {
138 throw new IOException(e);
139 }
140 }
141 return null;
142 }
143
144 static ProtocolFamily toJdkFamily(ProtocolFamily family) {
145 if (family instanceof SocketProtocolFamily) {
146 return ((SocketProtocolFamily) family).toJdkFamily();
147 }
148 return family;
149 }
150
151 private NioChannelUtil() { }
152 }