1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.named.ipc;
20
21 import java.io.IOException;
22 import java.net.Inet6Address;
23 import java.net.InetAddress;
24 import java.net.InetSocketAddress;
25 import java.net.SocketAddress;
26 import java.net.StandardProtocolFamily;
27 import java.net.UnixDomainSocketAddress;
28 import java.net.UnknownHostException;
29 import java.nio.channels.ServerSocketChannel;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.nio.file.attribute.PosixFilePermission;
33 import java.util.EnumSet;
34
35
36
37
38
39
40 public enum SocketFamily {
41 inet,
42 unix;
43
44 public ServerSocketChannel openServerSocket() throws IOException {
45 return switch (this) {
46 case inet -> ServerSocketChannel.open().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
47 case unix -> {
48 ServerSocketChannel channel =
49 ServerSocketChannel.open(StandardProtocolFamily.UNIX).bind(null, 0);
50 restrictToOwner(channel);
51 yield channel;
52 }
53 default -> throw new IllegalStateException();
54 };
55 }
56
57
58
59
60
61
62
63
64
65
66 private static void restrictToOwner(ServerSocketChannel channel) throws IOException {
67 SocketAddress address = channel.getLocalAddress();
68 if (address instanceof UnixDomainSocketAddress) {
69 Path path = ((UnixDomainSocketAddress) address).getPath();
70 try {
71 Files.setPosixFilePermissions(
72 path,
73 EnumSet.of(
74 PosixFilePermission.OWNER_READ,
75 PosixFilePermission.OWNER_WRITE,
76 PosixFilePermission.OWNER_EXECUTE));
77 } catch (UnsupportedOperationException e) {
78
79 }
80 }
81 }
82
83 public static SocketAddress fromString(String str) {
84 if (str.startsWith("inet:")) {
85 String s = str.substring("inet:".length());
86 int ic = s.lastIndexOf(':');
87 String ia = s.substring(0, ic);
88 int is = ia.indexOf('/');
89 String h = ia.substring(0, is);
90 String a = ia.substring(is + 1);
91 String p = s.substring(ic + 1);
92 InetAddress addr;
93 if ("<unresolved>".equals(a)) {
94 return InetSocketAddress.createUnresolved(h, Integer.parseInt(p));
95 } else {
96 if (a.indexOf('.') > 0) {
97 String[] as = a.split("\\.");
98 if (as.length != 4) {
99 throw new IllegalArgumentException("Unsupported socket address: '" + str + "'");
100 }
101 byte[] ab = new byte[4];
102 for (int i = 0; i < 4; i++) {
103 ab[i] = (byte) Integer.parseInt(as[i]);
104 }
105 try {
106 addr = InetAddress.getByAddress(h.isEmpty() ? null : h, ab);
107 } catch (UnknownHostException e) {
108 throw new IllegalArgumentException("Unsupported address: " + str, e);
109 }
110 } else {
111 throw new IllegalArgumentException("Unsupported address: " + str);
112 }
113 return new InetSocketAddress(addr, Integer.parseInt(p));
114 }
115 } else if (str.startsWith("unix:")) {
116 return UnixDomainSocketAddress.of(str.substring("unix:".length()));
117 } else {
118 throw new IllegalArgumentException("Unsupported socket address: '" + str + "'");
119 }
120 }
121
122 public static String toString(SocketAddress address) {
123 switch (familyOf(address)) {
124 case inet:
125 InetSocketAddress isa = (InetSocketAddress) address;
126 String host = isa.getHostString();
127 InetAddress addr = isa.getAddress();
128 int port = isa.getPort();
129 String formatted;
130 if (addr == null) {
131 formatted = host + "/<unresolved>";
132 } else {
133 formatted = addr.toString();
134 if (addr instanceof Inet6Address) {
135 int i = formatted.lastIndexOf("/");
136 formatted = formatted.substring(0, i + 1) + "[" + formatted.substring(i + 1) + "]";
137 }
138 }
139 return "inet:" + formatted + ":" + port;
140 case unix:
141
142 return "unix:" + address.toString().replace('\\', '/');
143 default:
144 throw new IllegalArgumentException("Unsupported socket address: '" + address + "'");
145 }
146 }
147
148 public static SocketFamily familyOf(SocketAddress address) {
149 if (address instanceof InetSocketAddress) {
150 return SocketFamily.inet;
151 } else if ("java.net.UnixDomainSocketAddress".equals(address.getClass().getName())) {
152 return SocketFamily.unix;
153 } else {
154 throw new IllegalArgumentException("Unsupported socket address '" + address + "'");
155 }
156 }
157 }