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.util.internal.PlatformDependent;
19
20 import java.net.Inet4Address;
21 import java.net.Inet6Address;
22 import java.net.InetAddress;
23 import java.net.InetSocketAddress;
24 import java.net.UnknownHostException;
25 import java.nio.ByteBuffer;
26 import java.nio.ByteOrder;
27
28 final class SockaddrIn {
29 static final byte[] IPV4_MAPPED_IPV6_PREFIX = {
30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff };
31 static final int IPV4_ADDRESS_LENGTH = 4;
32 static final int IPV6_ADDRESS_LENGTH = 16;
33 static final byte[] SOCKADDR_IN6_EMPTY_ARRAY = new byte[Native.SIZEOF_SOCKADDR_IN6];
34 static final byte[] SOCKADDR_IN_EMPTY_ARRAY = new byte[Native.SIZEOF_SOCKADDR_IN];
35
36 private SockaddrIn() { }
37
38 static int set(boolean ipv6, ByteBuffer memory, InetSocketAddress address) {
39 if (ipv6) {
40 return setIPv6(memory, address.getAddress(), address.getPort());
41 }
42 return setIPv4(memory, address.getAddress(), address.getPort());
43 }
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 static int setIPv4(ByteBuffer memory, InetAddress address, int port) {
60 int position = memory.position();
61 memory.mark();
62 try {
63
64 memory.put(SOCKADDR_IN_EMPTY_ARRAY);
65
66 memory.putShort(position + Native.SOCKADDR_IN_OFFSETOF_SIN_FAMILY, Native.AF_INET);
67 memory.putShort(position + Native.SOCKADDR_IN_OFFSETOF_SIN_PORT, handleNetworkOrder(memory.order(),
68 (short) port));
69
70 byte[] bytes = address.getAddress();
71 int offset = 0;
72 if (bytes.length == IPV6_ADDRESS_LENGTH) {
73
74 offset = IPV4_MAPPED_IPV6_PREFIX.length;
75 }
76 assert bytes.length == offset + IPV4_ADDRESS_LENGTH;
77 memory.position(position + Native.SOCKADDR_IN_OFFSETOF_SIN_ADDR + Native.IN_ADDRESS_OFFSETOF_S_ADDR);
78 memory.put(bytes, offset, IPV4_ADDRESS_LENGTH);
79 return Native.SIZEOF_SOCKADDR_IN;
80 } finally {
81
82 memory.reset();
83 }
84 }
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 static int setIPv6(ByteBuffer memory, InetAddress address, int port) {
102 int position = memory.position();
103 memory.mark();
104 try {
105
106 memory.put(SOCKADDR_IN6_EMPTY_ARRAY);
107 memory.putShort(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_FAMILY, Native.AF_INET6);
108 memory.putShort(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_PORT,
109 handleNetworkOrder(memory.order(), (short) port));
110
111 byte[] bytes = address.getAddress();
112 int offset = Native.SOCKADDR_IN6_OFFSETOF_SIN6_ADDR + Native.IN6_ADDRESS_OFFSETOF_S6_ADDR;
113 if (bytes.length == IPV4_ADDRESS_LENGTH) {
114 memory.position(position + offset);
115 memory.put(IPV4_MAPPED_IPV6_PREFIX);
116 memory.put(bytes, 0, IPV4_ADDRESS_LENGTH);
117
118
119 } else {
120 memory.position(position + offset);
121 memory.put(bytes, 0, IPV6_ADDRESS_LENGTH);
122
123 memory.putInt(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_SCOPE_ID,
124 ((Inet6Address) address).getScopeId());
125 }
126 return Native.SIZEOF_SOCKADDR_IN6;
127 } finally {
128 memory.reset();
129 }
130 }
131
132 static InetSocketAddress getIPv4(ByteBuffer memory, byte[] tmpArray) {
133 assert tmpArray.length == IPV4_ADDRESS_LENGTH;
134 int position = memory.position();
135 memory.mark();
136 try {
137 int port = handleNetworkOrder(memory.order(),
138 memory.getShort(position + Native.SOCKADDR_IN_OFFSETOF_SIN_PORT)) & 0xFFFF;
139 memory.position(position + Native.SOCKADDR_IN_OFFSETOF_SIN_ADDR + Native.IN_ADDRESS_OFFSETOF_S_ADDR);
140 memory.get(tmpArray);
141 try {
142 return new InetSocketAddress(InetAddress.getByAddress(tmpArray), port);
143 } catch (UnknownHostException ignore) {
144 return null;
145 }
146 } finally {
147 memory.reset();
148 }
149 }
150
151 static InetSocketAddress getIPv6(ByteBuffer memory, byte[] ipv6Array, byte[] ipv4Array) {
152 assert ipv6Array.length == IPV6_ADDRESS_LENGTH;
153 assert ipv4Array.length == IPV4_ADDRESS_LENGTH;
154 int position = memory.position();
155 memory.mark();
156 try {
157 int port = handleNetworkOrder(memory.order(), memory.getShort(
158 position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_PORT)) & 0xFFFF;
159 memory.position(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_ADDR + Native.IN6_ADDRESS_OFFSETOF_S6_ADDR);
160 memory.get(ipv6Array);
161 if (PlatformDependent.equals(
162 ipv6Array, 0, IPV4_MAPPED_IPV6_PREFIX, 0, IPV4_MAPPED_IPV6_PREFIX.length)) {
163 System.arraycopy(ipv6Array, IPV4_MAPPED_IPV6_PREFIX.length, ipv4Array, 0, IPV4_ADDRESS_LENGTH);
164 try {
165 return new InetSocketAddress(Inet4Address.getByAddress(ipv4Array), port);
166 } catch (UnknownHostException ignore) {
167 return null;
168 }
169 } else {
170 int scopeId = memory.getInt(position + Native.SOCKADDR_IN6_OFFSETOF_SIN6_SCOPE_ID);
171 try {
172 return new InetSocketAddress(Inet6Address.getByAddress(null, ipv6Array, scopeId), port);
173 } catch (UnknownHostException ignore) {
174 return null;
175 }
176 }
177 } finally {
178 memory.reset();
179 }
180 }
181
182 static boolean hasPortIpv4(ByteBuffer memory) {
183 int port = memory.getShort(memory.position() + Native.SOCKADDR_IN_OFFSETOF_SIN_PORT) & 0xFFFF;
184 return port > 0;
185 }
186
187 static boolean hasPortIpv6(ByteBuffer memory) {
188 int port = memory.getShort(memory.position() + Native.SOCKADDR_IN6_OFFSETOF_SIN6_PORT) & 0xFFFF;
189 return port > 0;
190 }
191
192 private static short handleNetworkOrder(ByteOrder order, short v) {
193 return order != ByteOrder.nativeOrder() ? v : Short.reverseBytes(v);
194 }
195 }