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
22 import java.net.InetSocketAddress;
23 import java.nio.ByteBuffer;
24
25 final class MsgHdrMemory {
26 private static final byte[] EMPTY_SOCKADDR_STORAGE = new byte[Native.SIZEOF_SOCKADDR_STORAGE];
27
28
29 private static final int GLOBAL_IOV_LEN = 1;
30 private static final ByteBuffer GLOBAL_IOV_BASE = Buffer.allocateDirectWithNativeOrder(GLOBAL_IOV_LEN);
31 private static final long GLOBAL_IOV_BASE_ADDRESS = Buffer.memoryAddress(GLOBAL_IOV_BASE);
32 private final ByteBuffer msgHdrMemory;
33 private final ByteBuffer socketAddrMemory;
34 private final ByteBuffer iovMemory;
35 private final ByteBuffer cmsgDataMemory;
36
37 private final long msgHdrMemoryAddress;
38 private final short idx;
39 private final int cmsgDataOffset;
40
41 MsgHdrMemory(short idx) {
42 this.idx = idx;
43 msgHdrMemory = Buffer.allocateDirectWithNativeOrder(Native.SIZEOF_MSGHDR);
44 msgHdrMemoryAddress = Buffer.memoryAddress(msgHdrMemory);
45 socketAddrMemory = Buffer.allocateDirectWithNativeOrder(Native.SIZEOF_SOCKADDR_STORAGE);
46 iovMemory = Buffer.allocateDirectWithNativeOrder(Native.SIZEOF_IOVEC);
47 cmsgDataMemory = Buffer.allocateDirectWithNativeOrder(Native.CMSG_SPACE);
48
49 long cmsgDataMemoryAddr = Buffer.memoryAddress(cmsgDataMemory);
50 long cmsgDataAddr = Native.cmsghdrData(cmsgDataMemoryAddr);
51 cmsgDataOffset = (int) (cmsgDataAddr - cmsgDataMemoryAddr);
52 }
53
54 MsgHdrMemory() {
55 this.idx = 0;
56
57 msgHdrMemory = Buffer.allocateDirectWithNativeOrder(Native.SIZEOF_MSGHDR);
58 msgHdrMemoryAddress = Buffer.memoryAddress(msgHdrMemory);
59 socketAddrMemory = null;
60 iovMemory = Buffer.allocateDirectWithNativeOrder(Native.SIZEOF_IOVEC);
61
62
63 Iov.set(iovMemory, GLOBAL_IOV_BASE_ADDRESS, GLOBAL_IOV_LEN);
64 cmsgDataMemory = Buffer.allocateDirectWithNativeOrder(Native.CMSG_SPACE_FOR_FD);
65
66 long cmsgDataMemoryAddr = Buffer.memoryAddress(cmsgDataMemory);
67 long cmsgDataAddr = Native.cmsghdrData(cmsgDataMemoryAddr);
68 cmsgDataOffset = (int) (cmsgDataAddr - cmsgDataMemoryAddr);
69 }
70
71 void set(LinuxSocket socket, InetSocketAddress address, long bufferAddress , int length, short segmentSize) {
72 int addressLength;
73 if (address == null) {
74 addressLength = socket.isIpv6() ? Native.SIZEOF_SOCKADDR_IN6 : Native.SIZEOF_SOCKADDR_IN;
75 socketAddrMemory.mark();
76 try {
77 socketAddrMemory.put(EMPTY_SOCKADDR_STORAGE);
78 } finally {
79 socketAddrMemory.reset();
80 }
81 } else {
82 addressLength = SockaddrIn.set(socket.isIpv6(), socketAddrMemory, address);
83 }
84 Iov.set(iovMemory, bufferAddress, length);
85 MsgHdr.set(msgHdrMemory, socketAddrMemory, addressLength, iovMemory, 1, cmsgDataMemory,
86 cmsgDataOffset, segmentSize);
87 }
88
89 void setScmRightsFd(int fd) {
90 MsgHdr.prepSendFd(msgHdrMemory, fd, cmsgDataMemory, cmsgDataOffset, iovMemory, 1);
91 }
92
93 int getScmRightsFd() {
94 return MsgHdr.getCmsgData(msgHdrMemory, cmsgDataMemory, cmsgDataOffset);
95 }
96
97 void prepRecvReadFd() {
98 MsgHdr.prepReadFd(msgHdrMemory, cmsgDataMemory, cmsgDataOffset, iovMemory, 1);
99 }
100
101 boolean hasPort(IoUringDatagramChannel channel) {
102 if (channel.socket.isIpv6()) {
103 return SockaddrIn.hasPortIpv6(socketAddrMemory);
104 }
105 return SockaddrIn.hasPortIpv4(socketAddrMemory);
106 }
107
108 DatagramPacket get(IoUringDatagramChannel channel, IoUringIoHandler handler, ByteBuf buffer, int bytesRead) {
109 InetSocketAddress sender;
110 if (channel.socket.isIpv6()) {
111 byte[] ipv6Bytes = handler.inet6AddressArray();
112 byte[] ipv4bytes = handler.inet4AddressArray();
113
114 sender = SockaddrIn.getIPv6(socketAddrMemory, ipv6Bytes, ipv4bytes);
115 } else {
116 byte[] bytes = handler.inet4AddressArray();
117 sender = SockaddrIn.getIPv4(socketAddrMemory, bytes);
118 }
119 long bufferAddress = Iov.getBufferAddress(iovMemory);
120 int bufferLength = Iov.getBufferLength(iovMemory);
121
122
123 long memoryAddress = IoUring.memoryAddress(buffer);
124 int readerIndex = (int) (bufferAddress - memoryAddress);
125
126 ByteBuf slice = buffer.slice(readerIndex, bufferLength)
127 .writerIndex(bytesRead);
128 return new DatagramPacket(slice.retain(), channel.localAddress(), sender);
129 }
130
131 short idx() {
132 return idx;
133 }
134
135 long address() {
136 return msgHdrMemoryAddress;
137 }
138
139 void release() {
140 Buffer.free(msgHdrMemory);
141 if (socketAddrMemory != null) {
142 Buffer.free(socketAddrMemory);
143 }
144 Buffer.free(iovMemory);
145 Buffer.free(cmsgDataMemory);
146 }
147 }