1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.uring;
17
18 import io.netty.channel.unix.DomainSocketAddress;
19 import io.netty.util.internal.PlatformDependent;
20
21 import java.net.Inet4Address;
22 import java.net.Inet6Address;
23 import java.net.InetAddress;
24 import java.net.InetSocketAddress;
25 import java.net.UnknownHostException;
26 import java.nio.ByteBuffer;
27 import java.nio.ByteOrder;
28 import java.nio.charset.StandardCharsets;
29
30 final class SockaddrIn {
31 static final byte[] IPV4_MAPPED_IPV6_PREFIX = {
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff };
33 static final int IPV4_ADDRESS_LENGTH = 4;
34 static final int IPV6_ADDRESS_LENGTH = 16;
35 static final byte[] SOCKADDR_IN6_EMPTY_ARRAY = new byte[Native.SIZEOF_SOCKADDR_IN6];
36 static final byte[] SOCKADDR_IN_EMPTY_ARRAY = new byte[Native.SIZEOF_SOCKADDR_IN];
37
38 private SockaddrIn() { }
39
40 static int set(boolean ipv6, ByteBuffer memory, InetSocketAddress address) {
41 if (ipv6) {
42 return setIPv6(memory, address.getAddress(), address.getPort());
43 }
44 return setIPv4(memory, address.getAddress(), address.getPort());
45 }
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 static int setIPv4(ByteBuffer memory, InetAddress address, int port) {
62 int position = memory.position();
63 memory.mark();
64 try {
65
66 memory.put(SOCKADDR_IN_EMPTY_ARRAY);
67
68 memory.putShort(position + Native.SOCKADDR_IN_OFFSETOF_SIN_FAMILY, Native.AF_INET);
69 memory.putShort(position + Native.SOCKADDR_IN_OFFSETOF_SIN_PORT, handleNetworkOrder(memory.order(),
70 (short) port));
71
72 byte[] bytes = address.getAddress();
73 int offset = 0;
74 if (bytes.length == IPV6_ADDRESS_LENGTH) {
75
76 offset = IPV4_MAPPED_IPV6_PREFIX.length;
77 }
78 assert bytes.length == offset + IPV4_ADDRESS_LENGTH;
79 memory.position(position + Native.SOCKADDR_IN_OFFSETOF_SIN_ADDR + Native.IN_ADDRESS_OFFSETOF_S_ADDR);
80 memory.put(bytes, offset, IPV4_ADDRESS_LENGTH);
81 return Native.SIZEOF_SOCKADDR_IN;
82 } finally {
83
84 memory.reset();
85 }
86 }
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 static int setIPv6(ByteBuffer memory, InetAddress address, int port) {
104 int position = memory.position();
105 memory.mark();
106 try {
107
108 memory.put(SOCKADDR_IN6_EMPTY_ARRAY);
109 memory.putShort(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_FAMILY, Native.AF_INET6);
110 memory.putShort(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_PORT,
111 handleNetworkOrder(memory.order(), (short) port));
112
113 byte[] bytes = address.getAddress();
114 int offset = Native.SOCKADDR_IN6_OFFSETOF_SIN6_ADDR + Native.IN6_ADDRESS_OFFSETOF_S6_ADDR;
115 if (bytes.length == IPV4_ADDRESS_LENGTH) {
116 memory.position(position + offset);
117 memory.put(IPV4_MAPPED_IPV6_PREFIX);
118 memory.put(bytes, 0, IPV4_ADDRESS_LENGTH);
119
120
121 } else {
122 memory.position(position + offset);
123 memory.put(bytes, 0, IPV6_ADDRESS_LENGTH);
124
125 memory.putInt(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_SCOPE_ID,
126 ((Inet6Address) address).getScopeId());
127 }
128 return Native.SIZEOF_SOCKADDR_IN6;
129 } finally {
130 memory.reset();
131 }
132 }
133
134
135
136
137
138
139
140
141
142 static int setUds(ByteBuffer memory, DomainSocketAddress address) {
143 byte[] path = address.path().getBytes(StandardCharsets.UTF_8);
144
145
146 boolean isAbstract = path.length > 0 && path[0] == 0;
147
148
149
150 int requiredLength = isAbstract ? path.length : path.length + 1;
151
152 if (requiredLength > Native.MAX_SUN_PATH_LEN) {
153 throw new IllegalArgumentException("path too long: " + address.path());
154 }
155
156 int position = memory.position();
157 memory.mark();
158 try {
159 memory.putShort(position + Native.SOCKADDR_UN_OFFSETOF_SUN_FAMILY, Native.AF_UNIX);
160 memory.position(position + Native.SOCKADDR_UN_OFFSETOF_SUN_PATH);
161 memory.put(path);
162
163
164 if (!isAbstract) {
165 memory.put((byte) 0);
166 }
167
168
169
170
171 return Native.SOCKADDR_UN_OFFSETOF_SUN_PATH + requiredLength;
172 } finally {
173 memory.reset();
174 }
175 }
176
177 static InetSocketAddress getIPv4(ByteBuffer memory, byte[] tmpArray) {
178 assert tmpArray.length == IPV4_ADDRESS_LENGTH;
179 int position = memory.position();
180 memory.mark();
181 try {
182 int port = handleNetworkOrder(memory.order(),
183 memory.getShort(position + Native.SOCKADDR_IN_OFFSETOF_SIN_PORT)) & 0xFFFF;
184 memory.position(position + Native.SOCKADDR_IN_OFFSETOF_SIN_ADDR + Native.IN_ADDRESS_OFFSETOF_S_ADDR);
185 memory.get(tmpArray);
186 try {
187 return new InetSocketAddress(InetAddress.getByAddress(tmpArray), port);
188 } catch (UnknownHostException ignore) {
189 return null;
190 }
191 } finally {
192 memory.reset();
193 }
194 }
195
196 static InetSocketAddress getIPv6(ByteBuffer memory, byte[] ipv6Array, byte[] ipv4Array) {
197 assert ipv6Array.length == IPV6_ADDRESS_LENGTH;
198 assert ipv4Array.length == IPV4_ADDRESS_LENGTH;
199 int position = memory.position();
200 memory.mark();
201 try {
202 int port = handleNetworkOrder(memory.order(), memory.getShort(
203 position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_PORT)) & 0xFFFF;
204 memory.position(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_ADDR + Native.IN6_ADDRESS_OFFSETOF_S6_ADDR);
205 memory.get(ipv6Array);
206 if (PlatformDependent.equals(
207 ipv6Array, 0, IPV4_MAPPED_IPV6_PREFIX, 0, IPV4_MAPPED_IPV6_PREFIX.length)) {
208 System.arraycopy(ipv6Array, IPV4_MAPPED_IPV6_PREFIX.length, ipv4Array, 0, IPV4_ADDRESS_LENGTH);
209 try {
210 return new InetSocketAddress(Inet4Address.getByAddress(ipv4Array), port);
211 } catch (UnknownHostException ignore) {
212 return null;
213 }
214 } else {
215 int scopeId = memory.getInt(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_SCOPE_ID);
216 try {
217 return new InetSocketAddress(Inet6Address.getByAddress(null, ipv6Array, scopeId), port);
218 } catch (UnknownHostException ignore) {
219 return null;
220 }
221 }
222 } finally {
223 memory.reset();
224 }
225 }
226
227 static boolean hasPortIpv4(ByteBuffer memory) {
228 int port = memory.getShort(memory.position() + Native.SOCKADDR_IN_OFFSETOF_SIN_PORT) & 0xFFFF;
229 return port > 0;
230 }
231
232 static boolean hasPortIpv6(ByteBuffer memory) {
233 int port = memory.getShort(memory.position() + Native.SOCKADDR_IN6_OFFSETOF_SIN6_PORT) & 0xFFFF;
234 return port > 0;
235 }
236
237 private static short handleNetworkOrder(ByteOrder order, short v) {
238 return order != ByteOrder.nativeOrder() ? v : Short.reverseBytes(v);
239 }
240 }