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.buffer.ByteBuf;
19 import io.netty.channel.socket.DatagramPacket;
20 import io.netty.channel.unix.Buffer;
21 import io.netty.util.internal.CleanableDirectBuffer;
22 import io.netty.util.internal.PlatformDependent;
23
24 import java.net.InetSocketAddress;
25 import java.nio.ByteBuffer;
26 import java.nio.ByteOrder;
27
28 final class MsgHdrMemory {
29 public static final int MSG_HDR_SIZE =
30 Native.SIZEOF_MSGHDR + Native.SIZEOF_SOCKADDR_STORAGE + Native.SIZEOF_IOVEC + Native.CMSG_SPACE;
31 private static final byte[] EMPTY_SOCKADDR_STORAGE = new byte[Native.SIZEOF_SOCKADDR_STORAGE];
32
33
34 private static final int GLOBAL_IOV_LEN = 1;
35 private static final ByteBuffer GLOBAL_IOV_BASE = Buffer.allocateDirectWithNativeOrder(GLOBAL_IOV_LEN);
36 private static final long GLOBAL_IOV_BASE_ADDRESS = Buffer.memoryAddress(GLOBAL_IOV_BASE);
37 private final CleanableDirectBuffer msgHdrMemoryCleanable;
38 private final CleanableDirectBuffer socketAddrMemoryCleanable;
39 private final CleanableDirectBuffer iovMemoryCleanable;
40 private final CleanableDirectBuffer cmsgDataMemoryCleanable;
41 private final ByteBuffer msgHdrMemory;
42 private final ByteBuffer socketAddrMemory;
43 private final ByteBuffer iovMemory;
44 private final ByteBuffer cmsgDataMemory;
45
46 private final long msgHdrMemoryAddress;
47 private final short idx;
48 private final int cmsgDataOffset;
49
50 MsgHdrMemory(short idx, ByteBuffer msgHdrMemoryArray) {
51 this.idx = idx;
52 this.msgHdrMemoryCleanable = null;
53 this.socketAddrMemoryCleanable = null;
54 this.iovMemoryCleanable = null;
55 this.cmsgDataMemoryCleanable = null;
56 int offset = idx * MSG_HDR_SIZE;
57
58
59 this.msgHdrMemory = PlatformDependent.offsetSlice(
60 msgHdrMemoryArray, offset, Native.SIZEOF_MSGHDR
61 ).order(ByteOrder.nativeOrder());
62 offset += Native.SIZEOF_MSGHDR;
63 this.socketAddrMemory = PlatformDependent.offsetSlice(
64 msgHdrMemoryArray, offset, Native.SIZEOF_SOCKADDR_STORAGE
65 ).order(ByteOrder.nativeOrder());
66 offset += Native.SIZEOF_SOCKADDR_STORAGE;
67 this.iovMemory = PlatformDependent.offsetSlice(
68 msgHdrMemoryArray, offset, Native.SIZEOF_IOVEC
69 ).order(ByteOrder.nativeOrder());
70 offset += Native.SIZEOF_IOVEC;
71 this.cmsgDataMemory = PlatformDependent.offsetSlice(
72 msgHdrMemoryArray, offset, Native.CMSG_SPACE
73 ).order(ByteOrder.nativeOrder());
74
75 msgHdrMemoryAddress = Buffer.memoryAddress(msgHdrMemory);
76
77 long cmsgDataMemoryAddr = Buffer.memoryAddress(cmsgDataMemory);
78 long cmsgDataAddr = Native.cmsghdrData(cmsgDataMemoryAddr);
79 cmsgDataOffset = (int) (cmsgDataAddr - cmsgDataMemoryAddr);
80 }
81
82 MsgHdrMemory() {
83 this.idx = 0;
84
85 msgHdrMemoryCleanable = Buffer.allocateDirectBufferWithNativeOrder(Native.SIZEOF_MSGHDR);
86 socketAddrMemoryCleanable = null;
87 iovMemoryCleanable = Buffer.allocateDirectBufferWithNativeOrder(Native.SIZEOF_IOVEC);
88 cmsgDataMemoryCleanable = Buffer.allocateDirectBufferWithNativeOrder(Native.CMSG_SPACE_FOR_FD);
89
90 msgHdrMemory = msgHdrMemoryCleanable.buffer();
91 socketAddrMemory = null;
92 iovMemory = iovMemoryCleanable.buffer();
93 cmsgDataMemory = cmsgDataMemoryCleanable.buffer();
94
95 msgHdrMemoryAddress = Buffer.memoryAddress(msgHdrMemory);
96
97
98 Iov.set(iovMemory, GLOBAL_IOV_BASE_ADDRESS, GLOBAL_IOV_LEN);
99
100 long cmsgDataMemoryAddr = Buffer.memoryAddress(cmsgDataMemory);
101 long cmsgDataAddr = Native.cmsghdrData(cmsgDataMemoryAddr);
102 cmsgDataOffset = (int) (cmsgDataAddr - cmsgDataMemoryAddr);
103 }
104
105 void set(LinuxSocket socket, InetSocketAddress address, long bufferAddress , int length, short segmentSize) {
106 int addressLength;
107 if (address == null) {
108 addressLength = socket.isIpv6() ? Native.SIZEOF_SOCKADDR_IN6 : Native.SIZEOF_SOCKADDR_IN;
109 socketAddrMemory.mark();
110 try {
111 socketAddrMemory.put(EMPTY_SOCKADDR_STORAGE);
112 } finally {
113 socketAddrMemory.reset();
114 }
115 } else {
116 addressLength = SockaddrIn.set(socket.isIpv6(), socketAddrMemory, address);
117 }
118 Iov.set(iovMemory, bufferAddress, length);
119 MsgHdr.set(msgHdrMemory, socketAddrMemory, addressLength, iovMemory, 1, cmsgDataMemory,
120 cmsgDataOffset, segmentSize);
121 }
122
123 void set(long iovArray, int length) {
124 MsgHdr.set(msgHdrMemory, iovArray, length);
125 }
126
127 void setScmRightsFd(int fd) {
128 MsgHdr.prepSendFd(msgHdrMemory, fd, cmsgDataMemory, cmsgDataOffset, iovMemory, 1);
129 }
130
131 int getScmRightsFd() {
132 return MsgHdr.getCmsgData(msgHdrMemory, cmsgDataMemory, cmsgDataOffset);
133 }
134
135 void prepRecvReadFd() {
136 MsgHdr.prepReadFd(msgHdrMemory, cmsgDataMemory, cmsgDataOffset, iovMemory, 1);
137 }
138
139 boolean hasPort(IoUringDatagramChannel channel) {
140 if (channel.socket.isIpv6()) {
141 return SockaddrIn.hasPortIpv6(socketAddrMemory);
142 }
143 return SockaddrIn.hasPortIpv4(socketAddrMemory);
144 }
145
146 DatagramPacket get(IoUringDatagramChannel channel, IoUringIoHandler handler, ByteBuf buffer, int bytesRead) {
147 InetSocketAddress sender;
148 if (channel.socket.isIpv6()) {
149 byte[] ipv6Bytes = handler.inet6AddressArray();
150 byte[] ipv4bytes = handler.inet4AddressArray();
151
152 sender = SockaddrIn.getIPv6(socketAddrMemory, ipv6Bytes, ipv4bytes);
153 } else {
154 byte[] bytes = handler.inet4AddressArray();
155 sender = SockaddrIn.getIPv4(socketAddrMemory, bytes);
156 }
157 long bufferAddress = Iov.getBufferAddress(iovMemory);
158 int bufferLength = Iov.getBufferLength(iovMemory);
159
160
161 long memoryAddress = IoUring.memoryAddress(buffer);
162 int readerIndex = (int) (bufferAddress - memoryAddress);
163
164 ByteBuf slice = buffer.slice(readerIndex, bufferLength)
165 .writerIndex(bytesRead);
166 return new DatagramPacket(slice.retain(), channel.localAddress(), sender);
167 }
168
169 short idx() {
170 return idx;
171 }
172
173 long address() {
174 return msgHdrMemoryAddress;
175 }
176
177 void release() {
178 if (msgHdrMemoryCleanable != null) {
179 msgHdrMemoryCleanable.clean();
180 }
181 if (socketAddrMemoryCleanable != null) {
182 socketAddrMemoryCleanable.clean();
183 }
184 if (iovMemoryCleanable != null) {
185 iovMemoryCleanable.clean();
186 }
187 if (cmsgDataMemoryCleanable != null) {
188 cmsgDataMemoryCleanable.clean();
189 }
190 }
191 }