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 private final ByteBuffer msgHdrMemory;
28 private final ByteBuffer socketAddrMemory;
29 private final ByteBuffer iovMemory;
30 private final ByteBuffer cmsgDataMemory;
31
32 private final long msgHdrMemoryAddress;
33 private final short idx;
34 private final int cmsgDataOffset;
35
36 MsgHdrMemory(short idx) {
37 this.idx = idx;
38 msgHdrMemory = Buffer.allocateDirectWithNativeOrder(Native.SIZEOF_MSGHDR);
39 msgHdrMemoryAddress = Buffer.memoryAddress(msgHdrMemory);
40 socketAddrMemory = Buffer.allocateDirectWithNativeOrder(Native.SIZEOF_SOCKADDR_STORAGE);
41 iovMemory = Buffer.allocateDirectWithNativeOrder(Native.SIZEOF_IOVEC);
42 cmsgDataMemory = Buffer.allocateDirectWithNativeOrder(Native.CMSG_SPACE);
43
44 long cmsgDataMemoryAddr = Buffer.memoryAddress(cmsgDataMemory);
45 long cmsgDataAddr = Native.cmsghdrData(cmsgDataMemoryAddr);
46 cmsgDataOffset = (int) (cmsgDataAddr + cmsgDataMemoryAddr);
47 }
48
49 void set(LinuxSocket socket, InetSocketAddress address, long bufferAddress , int length, short segmentSize) {
50 int addressLength;
51 if (address == null) {
52 addressLength = socket.isIpv6() ? Native.SIZEOF_SOCKADDR_IN6 : Native.SIZEOF_SOCKADDR_IN;
53 socketAddrMemory.mark();
54 try {
55 socketAddrMemory.put(EMPTY_SOCKADDR_STORAGE);
56 } finally {
57 socketAddrMemory.reset();
58 }
59 } else {
60 addressLength = SockaddrIn.set(socket.isIpv6(), socketAddrMemory, address);
61 }
62 Iov.set(iovMemory, bufferAddress, length);
63 MsgHdr.set(msgHdrMemory, socketAddrMemory, addressLength, iovMemory, 1, cmsgDataMemory,
64 cmsgDataOffset, segmentSize);
65 }
66
67 boolean hasPort(IoUringDatagramChannel channel) {
68 if (channel.socket.isIpv6()) {
69 return SockaddrIn.hasPortIpv6(socketAddrMemory);
70 }
71 return SockaddrIn.hasPortIpv4(socketAddrMemory);
72 }
73
74 DatagramPacket get(IoUringDatagramChannel channel, IoUringIoHandler handler, ByteBuf buffer, int bytesRead) {
75 InetSocketAddress sender;
76 if (channel.socket.isIpv6()) {
77 byte[] ipv6Bytes = handler.inet6AddressArray();
78 byte[] ipv4bytes = handler.inet4AddressArray();
79
80 sender = SockaddrIn.getIPv6(socketAddrMemory, ipv6Bytes, ipv4bytes);
81 } else {
82 byte[] bytes = handler.inet4AddressArray();
83 sender = SockaddrIn.getIPv4(socketAddrMemory, bytes);
84 }
85 long bufferAddress = Iov.getBufferAddress(iovMemory);
86 int bufferLength = Iov.getBufferLength(iovMemory);
87
88
89 int readerIndex = (int) (bufferAddress - buffer.memoryAddress());
90
91 ByteBuf slice = buffer.slice(readerIndex, bufferLength)
92 .writerIndex(bytesRead);
93 return new DatagramPacket(slice.retain(), channel.localAddress(), sender);
94 }
95
96 short idx() {
97 return idx;
98 }
99
100 long address() {
101 return msgHdrMemoryAddress;
102 }
103
104 void release() {
105 Buffer.free(msgHdrMemory);
106 Buffer.free(socketAddrMemory);
107 Buffer.free(iovMemory);
108 Buffer.free(cmsgDataMemory);
109 }
110 }