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.util.internal.PlatformDependent;
21
22 import java.net.InetSocketAddress;
23
24 final class MsgHdrMemory {
25 private final long memory;
26 private final short idx;
27 private final long cmsgDataAddr;
28
29 MsgHdrMemory(short idx) {
30 this.idx = idx;
31 int size = Native.SIZEOF_MSGHDR + Native.SIZEOF_SOCKADDR_STORAGE + Native.SIZEOF_IOVEC + Native.CMSG_SPACE;
32 memory = PlatformDependent.allocateMemory(size);
33 PlatformDependent.setMemory(memory, size, (byte) 0);
34
35
36 cmsgDataAddr = Native.cmsghdrData(memory + Native.SIZEOF_MSGHDR +
37 Native.SIZEOF_SOCKADDR_STORAGE + Native.SIZEOF_IOVEC);
38 }
39
40 void write(LinuxSocket socket, InetSocketAddress address, long bufferAddress , int length, short segmentSize) {
41 long sockAddress = memory + Native.SIZEOF_MSGHDR;
42 long iovAddress = sockAddress + Native.SIZEOF_SOCKADDR_STORAGE;
43 long cmsgAddr = iovAddress + Native.SIZEOF_IOVEC;
44 int addressLength;
45 if (address == null) {
46 addressLength = socket.isIpv6() ? Native.SIZEOF_SOCKADDR_IN6 : Native.SIZEOF_SOCKADDR_IN;
47 PlatformDependent.setMemory(sockAddress, Native.SIZEOF_SOCKADDR_STORAGE, (byte) 0);
48 } else {
49 addressLength = SockaddrIn.write(socket.isIpv6(), sockAddress, address);
50 }
51 Iov.write(iovAddress, bufferAddress, length);
52 MsgHdr.write(memory, sockAddress, addressLength, iovAddress, 1, cmsgAddr, cmsgDataAddr, segmentSize);
53 }
54
55 boolean hasPort(IoUringDatagramChannel channel) {
56 long sockAddress = memory + Native.SIZEOF_MSGHDR;
57 if (channel.socket.isIpv6()) {
58 return SockaddrIn.hasPortIpv6(sockAddress);
59 }
60 return SockaddrIn.hasPortIpv4(sockAddress);
61 }
62
63 DatagramPacket read(IoUringDatagramChannel channel, IoUringIoHandler handler, ByteBuf buffer, int bytesRead) {
64 long sockAddress = memory + Native.SIZEOF_MSGHDR;
65 InetSocketAddress sender;
66 if (channel.socket.isIpv6()) {
67 byte[] ipv6Bytes = handler.inet6AddressArray();
68 byte[] ipv4bytes = handler.inet4AddressArray();
69
70 sender = SockaddrIn.readIPv6(sockAddress, ipv6Bytes, ipv4bytes);
71 } else {
72 byte[] bytes = handler.inet4AddressArray();
73 sender = SockaddrIn.readIPv4(sockAddress, bytes);
74 }
75 long iovAddress = memory + Native.SIZEOF_MSGHDR + Native.SIZEOF_SOCKADDR_STORAGE;
76 long bufferAddress = Iov.readBufferAddress(iovAddress);
77 int bufferLength = Iov.readBufferLength(iovAddress);
78
79
80 int readerIndex = (int) (bufferAddress - buffer.memoryAddress());
81
82 ByteBuf slice = buffer.slice(readerIndex, bufferLength)
83 .writerIndex(bytesRead);
84 return new DatagramPacket(slice.retain(), channel.localAddress(), sender);
85 }
86
87 short idx() {
88 return idx;
89 }
90
91 long address() {
92 return memory;
93 }
94
95 void release() {
96 PlatformDependent.freeMemory(memory);
97 }
98 }