View Javadoc
1   /*
2    * Copyright 2024 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.uring;
17  
18  import io.netty.channel.unix.Buffer;
19  
20  import java.io.IOException;
21  import java.nio.ByteBuffer;
22  
23  /**
24   * <pre>{@code
25   * struct msghdr {
26   *     void         *msg_name;       // optional address
27   *     socklen_t    msg_namelen;     // size of address
28   *     struct       iovec*msg_iov;   // scatter/gather array
29   *     size_t       msg_iovlen;      // # elements in msg_iov
30   *     void*        msg_control;     // ancillary data, see below
31   *     size_t       msg_controllen;  // ancillary data buffer len
32   *     int          msg_flags;       // flags on received message
33   * };
34   * }</pre>
35   */
36  final class MsgHdr {
37  
38      private MsgHdr() { }
39  
40      static void set(ByteBuffer memory, long iovMemory, int iovLength) {
41          int memoryPosition = memory.position();
42          memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_NAMELEN, 0);
43          if (Native.SIZEOF_SIZE_T == 4) {
44              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_NAME, 0);
45              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOV, (int) iovMemory);
46              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOVLEN, iovLength);
47              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROL, 0);
48              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN, 0);
49          } else {
50              assert Native.SIZEOF_SIZE_T == 8;
51              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_NAME, 0);
52              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOV, iovMemory);
53              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOVLEN, iovLength);
54              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROL, 0);
55              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN, 0);
56          }
57      }
58  
59      static void set(ByteBuffer memory, ByteBuffer sockAddrMemory, int addressSize, long iovMemory, int iovLength,
60                      ByteBuffer msgControl, int cmsgHdrDataOffset, short segmentSize) {
61          int memoryPosition = memory.position();
62          memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_NAMELEN, addressSize);
63  
64          int msgControlLen = 0;
65          long msgControlAddr;
66          if (segmentSize > 0 && msgControl != null && cmsgHdrDataOffset >= 0) {
67              msgControlLen = Native.CMSG_LEN;
68              CmsgHdr.write(msgControl, cmsgHdrDataOffset, Native.CMSG_LEN, Native.SOL_UDP,
69                      Native.UDP_SEGMENT, segmentSize);
70              msgControlAddr = Buffer.memoryAddress(msgControl) + msgControl.position();
71          } else {
72              // Set to 0 if we not explicit requested GSO.
73              msgControlAddr = 0;
74          }
75          long sockAddr = sockAddrMemory == null ? 0 : Buffer.memoryAddress(sockAddrMemory);
76          if (Native.SIZEOF_SIZE_T == 4) {
77              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_NAME, (int) sockAddr);
78              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOV, (int) iovMemory);
79              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOVLEN, iovLength);
80              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROL, (int) msgControlAddr);
81              memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN, msgControlLen);
82          } else {
83              assert Native.SIZEOF_SIZE_T == 8;
84              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_NAME, sockAddr);
85              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOV, iovMemory);
86              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOVLEN, iovLength);
87              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROL, msgControlAddr);
88              memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN, msgControlLen);
89          }
90          // No flags (we assume the memory was memset before)
91      }
92  
93      static void set(ByteBuffer memory, ByteBuffer sockAddrMemory, int addressSize, ByteBuffer iovMemory, int iovLength,
94                      ByteBuffer msgControl, int cmsgHdrDataOffset, short segmentSize) {
95          set(memory, sockAddrMemory, addressSize, Buffer.memoryAddress(iovMemory), iovLength,
96                  msgControl, cmsgHdrDataOffset, segmentSize);
97      }
98  
99      static void prepSendFd(ByteBuffer memory, int fd, ByteBuffer msgControl,
100                            int cmsgHdrDataOffset, ByteBuffer iovMemory, int iovLength) {
101         int memoryPosition = memory.position();
102         long msgControlAddr = Buffer.memoryAddress(msgControl);
103         CmsgHdr.writeScmRights(msgControl, cmsgHdrDataOffset, fd);
104         if (Native.SIZEOF_SIZE_T == 4) {
105             memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROL, (int) msgControlAddr);
106             memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN, Native.MSG_CONTROL_LEN_FOR_FD);
107             memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOV, (int) Buffer.memoryAddress(iovMemory));
108             memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOVLEN, iovLength);
109         } else {
110             assert Native.SIZEOF_SIZE_T == 8;
111             memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROL, msgControlAddr);
112             memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN, Native.MSG_CONTROL_LEN_FOR_FD);
113             memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOV, Buffer.memoryAddress(iovMemory));
114             memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOVLEN, iovLength);
115         }
116     }
117 
118     static void prepReadFd(ByteBuffer memory, ByteBuffer msgControl, int cmsgHdrDataOffset,
119                            ByteBuffer iovMemory, int iovLength) {
120         int memoryPosition = memory.position();
121         long msgControlAddr = Buffer.memoryAddress(msgControl);
122         if (Native.SIZEOF_SIZE_T == 4) {
123             memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROL, (int) msgControlAddr);
124             memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN, Native.MSG_CONTROL_LEN_FOR_FD);
125             memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOV, (int) Buffer.memoryAddress(iovMemory));
126             memory.putInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOVLEN, iovLength);
127         } else {
128             assert Native.SIZEOF_SIZE_T == 8;
129             memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROL, msgControlAddr);
130             memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN, Native.MSG_CONTROL_LEN_FOR_FD);
131             memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOV, Buffer.memoryAddress(iovMemory));
132             memory.putLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_IOVLEN, iovLength);
133         }
134     }
135 
136     static int getCmsgData(ByteBuffer memory, ByteBuffer msgControl, int cmsgHdrDataOffset) throws IOException {
137         int memoryPosition = memory.position();
138         long msgControlLen = Native.SIZEOF_SIZE_T == 4
139                 ? memory.getInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN) & 0xFFFFFFFFL
140                 : memory.getLong(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_CONTROLLEN);
141         if (msgControlLen <= 0) {
142             throw new IOException("Received no ancillary data while expecting a SCM_RIGHTS file descriptor");
143         }
144         int msgFlags = memory.getInt(memoryPosition + Native.MSGHDR_OFFSETOF_MSG_FLAGS);
145         boolean truncated = (msgFlags & Native.MSG_CTRUNC) != 0;
146         return CmsgHdr.readScmRights(msgControl, cmsgHdrDataOffset, truncated);
147     }
148 }