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
26 import static io.netty.util.internal.PlatformDependent.BIG_ENDIAN_NATIVE_ORDER;
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
34 private SockaddrIn() { }
35
36 static int write(boolean ipv6, long memory, InetSocketAddress address) {
37 if (ipv6) {
38 return writeIPv6(memory, address.getAddress(), address.getPort());
39 } else {
40 return writeIPv4(memory, address.getAddress(), address.getPort());
41 }
42 }
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 static int writeIPv4(long memory, InetAddress address, int port) {
59 PlatformDependent.setMemory(memory, Native.SIZEOF_SOCKADDR_IN, (byte) 0);
60
61 PlatformDependent.putShort(memory + Native.SOCKADDR_IN_OFFSETOF_SIN_FAMILY, Native.AF_INET);
62 PlatformDependent.putShort(memory + Native.SOCKADDR_IN_OFFSETOF_SIN_PORT, handleNetworkOrder((short) port));
63 byte[] bytes = address.getAddress();
64 int offset = 0;
65 if (bytes.length == IPV6_ADDRESS_LENGTH) {
66
67 offset = IPV4_MAPPED_IPV6_PREFIX.length;
68 }
69 assert bytes.length == offset + 4;
70 PlatformDependent.copyMemory(bytes, offset,
71 memory + Native.SOCKADDR_IN_OFFSETOF_SIN_ADDR + Native.IN_ADDRESS_OFFSETOF_S_ADDR, 4);
72 return Native.SIZEOF_SOCKADDR_IN;
73 }
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 static int writeIPv6(long memory, InetAddress address, int port) {
91 PlatformDependent.setMemory(memory, Native.SIZEOF_SOCKADDR_IN6, (byte) 0);
92 PlatformDependent.putShort(memory + Native.SOCKADDR_IN6_OFFSETOF_SIN6_FAMILY, Native.AF_INET6);
93 PlatformDependent.putShort(memory + Native.SOCKADDR_IN6_OFFSETOF_SIN6_PORT, handleNetworkOrder((short) port));
94
95 byte[] bytes = address.getAddress();
96 if (bytes.length == IPV4_ADDRESS_LENGTH) {
97 int offset = Native.SOCKADDR_IN6_OFFSETOF_SIN6_ADDR + Native.IN6_ADDRESS_OFFSETOF_S6_ADDR;
98 PlatformDependent.copyMemory(IPV4_MAPPED_IPV6_PREFIX, 0, memory + offset, IPV4_MAPPED_IPV6_PREFIX.length);
99 PlatformDependent.copyMemory(bytes, 0,
100 memory + offset + IPV4_MAPPED_IPV6_PREFIX.length, IPV4_ADDRESS_LENGTH);
101
102 } else {
103 PlatformDependent.copyMemory(
104 bytes, 0, memory + Native.SOCKADDR_IN6_OFFSETOF_SIN6_ADDR + Native.IN6_ADDRESS_OFFSETOF_S6_ADDR,
105 IPV6_ADDRESS_LENGTH);
106 PlatformDependent.putInt(
107 memory + Native.SOCKADDR_IN6_OFFSETOF_SIN6_SCOPE_ID, ((Inet6Address) address).getScopeId());
108 }
109 return Native.SIZEOF_SOCKADDR_IN6;
110 }
111
112 static InetSocketAddress readIPv4(long memory, byte[] tmpArray) {
113 assert tmpArray.length == IPV4_ADDRESS_LENGTH;
114 int port = handleNetworkOrder(PlatformDependent.getShort(
115 memory + Native.SOCKADDR_IN_OFFSETOF_SIN_PORT)) & 0xFFFF;
116 PlatformDependent.copyMemory(memory + Native.SOCKADDR_IN_OFFSETOF_SIN_ADDR + Native.IN_ADDRESS_OFFSETOF_S_ADDR,
117 tmpArray, 0, IPV4_ADDRESS_LENGTH);
118 try {
119 return new InetSocketAddress(InetAddress.getByAddress(tmpArray), port);
120 } catch (UnknownHostException ignore) {
121 return null;
122 }
123 }
124
125 static InetSocketAddress readIPv6(long memory, byte[] ipv6Array, byte[] ipv4Array) {
126 assert ipv6Array.length == IPV6_ADDRESS_LENGTH;
127 assert ipv4Array.length == IPV4_ADDRESS_LENGTH;
128
129 int port = handleNetworkOrder(PlatformDependent.getShort(
130 memory + Native.SOCKADDR_IN6_OFFSETOF_SIN6_PORT)) & 0xFFFF;
131 PlatformDependent.copyMemory(
132 memory + Native.SOCKADDR_IN6_OFFSETOF_SIN6_ADDR + Native.IN6_ADDRESS_OFFSETOF_S6_ADDR,
133 ipv6Array, 0, IPV6_ADDRESS_LENGTH);
134 if (PlatformDependent.equals(
135 ipv6Array, 0, IPV4_MAPPED_IPV6_PREFIX, 0, IPV4_MAPPED_IPV6_PREFIX.length)) {
136 System.arraycopy(ipv6Array, IPV4_MAPPED_IPV6_PREFIX.length, ipv4Array, 0, IPV4_ADDRESS_LENGTH);
137 try {
138 return new InetSocketAddress(Inet4Address.getByAddress(ipv4Array), port);
139 } catch (UnknownHostException ignore) {
140 return null;
141 }
142 } else {
143 int scopeId = PlatformDependent.getInt(memory + Native.SOCKADDR_IN6_OFFSETOF_SIN6_SCOPE_ID);
144 try {
145 return new InetSocketAddress(Inet6Address.getByAddress(null, ipv6Array, scopeId), port);
146 } catch (UnknownHostException ignore) {
147 return null;
148 }
149 }
150 }
151
152 static boolean hasPortIpv4(long memory) {
153 int port = handleNetworkOrder(PlatformDependent.getShort(
154 memory + Native.SOCKADDR_IN_OFFSETOF_SIN_PORT)) & 0xFFFF;
155 return port > 0;
156 }
157
158 static boolean hasPortIpv6(long memory) {
159 int port = handleNetworkOrder(PlatformDependent.getShort(
160 memory + Native.SOCKADDR_IN6_OFFSETOF_SIN6_PORT)) & 0xFFFF;
161 return port > 0;
162 }
163
164 private static short handleNetworkOrder(short v) {
165 return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
166 }
167 }