TypedMsgHdr.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 54 Interprocess Communication */
10 
11 #include "squid.h"
12 #include "base/TextException.h"
13 #include "ipc/TypedMsgHdr.h"
14 #include "SquidString.h"
15 #include "tools.h"
16 
17 #include <cstring>
18 
20 {
21  clear();
22  sync();
23 }
24 
26 {
27  clear();
28  operator =(tmh);
29 }
30 
32 {
33  if (this != &tmh) { // skip assignment to self
34  memcpy(static_cast<msghdr*>(this), static_cast<const msghdr*>(&tmh), sizeof(msghdr));
35  name = tmh.name;
36  memcpy(&ios, &tmh.ios, sizeof(ios));
37  data = tmh.data;
38  ctrl = tmh.ctrl;
39  offset = tmh.offset;
40  sync();
41  }
42  return *this;
43 }
44 
45 void
47 {
48  // may be called from the constructor, with object fields uninitialized
49  memset(static_cast<msghdr*>(this), 0, sizeof(msghdr));
50  memset(&name, 0, sizeof(name));
51  memset(&ios, 0, sizeof(ios));
52  data = DataBuffer();
53  ctrl = CtrlBuffer();
54  offset = 0;
55 }
56 
57 // update msghdr and ios pointers based on msghdr counters
59 {
60  if (msg_name) { // we have a name
61  msg_name = &name;
62  } else {
63  Must(!msg_namelen && !msg_name);
64  }
65 
66  if (msg_iov) { // we have a data component
67  Must(msg_iovlen == 1);
68  msg_iov = ios;
69  ios[0].iov_base = &data;
70  Must(ios[0].iov_len == sizeof(data));
71  } else {
72  Must(!msg_iovlen && !msg_iov);
73  }
74 
75  if (msg_control) { // we have a control component
76  Must(msg_controllen > 0);
77  msg_control = &ctrl;
78  } else {
79  Must(!msg_controllen && !msg_control);
80  }
81  offset = 0;
82 }
83 
84 void
86 {
87  allocName();
88  name = addr;
89  msg_name = &name;
90  msg_namelen = SUN_LEN(&name);
91 }
92 
93 void
94 Ipc::TypedMsgHdr::checkType(int destType) const
95 {
96  Must(rawType() == destType);
97 }
98 
99 void
101 {
102  if (data.type_) {
103  Must(data.type_ == aType);
104  } else {
105  allocData();
106  data.type_ = aType;
107  }
108 }
109 
110 int
112 {
113  int n = 0;
114  getPod(n);
115  return n;
116 }
117 
118 void
120 {
121  putPod(n);
122 }
123 
124 void
126 {
127  const int length = getInt();
128  Must(length >= 0);
129  // String uses memcpy uncoditionally; TODO: SBuf eliminates this check
130  if (!length) {
131  s.clean();
132  return;
133  }
134 
135  Must(length <= maxSize);
136  // TODO: use SBuf.reserve() instead of a temporary buffer
137  char buf[maxSize];
138  getRaw(&buf, length);
139  s.assign(buf, length);
140 }
141 
142 void
144 {
145  Must(s.psize() <= maxSize);
146  putInt(s.psize());
147  putRaw(s.rawBuf(), s.psize());
148 }
149 
150 void
151 Ipc::TypedMsgHdr::getFixed(void *rawBuf, size_t rawSize) const
152 {
153  // no need to load size because it is constant
154  getRaw(rawBuf, rawSize);
155 }
156 
157 void
158 Ipc::TypedMsgHdr::putFixed(const void *rawBuf, size_t rawSize)
159 {
160  // no need to store size because it is constant
161  putRaw(rawBuf, rawSize);
162 }
163 
165 void
166 Ipc::TypedMsgHdr::getRaw(void *rawBuf, size_t rawSize) const
167 {
168  if (rawSize > 0) {
169  Must(rawSize <= data.size - offset);
170  memcpy(rawBuf, data.raw + offset, rawSize);
171  offset += rawSize;
172  }
173 }
174 
176 void
177 Ipc::TypedMsgHdr::putRaw(const void *rawBuf, size_t rawSize)
178 {
179  if (rawSize > 0) {
180  Must(rawSize <= sizeof(data.raw) - data.size);
181  memcpy(data.raw + data.size, rawBuf, rawSize);
182  data.size += rawSize;
183  }
184 }
185 
186 bool
188 {
189  struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
190  return cmsg &&
191  cmsg->cmsg_level == SOL_SOCKET &&
192  cmsg->cmsg_type == SCM_RIGHTS;
193 }
194 
195 void
197 {
198  Must(fd >= 0);
199  Must(!hasFd());
200  allocControl();
201 
202  const int fdCount = 1;
203 
204  struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
205  cmsg->cmsg_level = SOL_SOCKET;
206  cmsg->cmsg_type = SCM_RIGHTS;
207  cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
208 
209  int *fdStore = reinterpret_cast<int*>(SQUID_CMSG_DATA(cmsg));
210  memcpy(fdStore, &fd, fdCount * sizeof(int));
211  msg_controllen = cmsg->cmsg_len;
212 
213  Must(hasFd());
214 }
215 
216 int
218 {
219  Must(msg_control && msg_controllen);
220  Must(hasFd());
221 
222  struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
223  Must(cmsg->cmsg_level == SOL_SOCKET);
224  Must(cmsg->cmsg_type == SCM_RIGHTS);
225 
226  const int fdCount = 1;
227  const int *fdStore = reinterpret_cast<const int*>(SQUID_CMSG_DATA(cmsg));
228  int fd = -1;
229  memcpy(&fd, fdStore, fdCount * sizeof(int));
230  return fd;
231 }
232 
233 void
235 {
236  clear();
237  // no sync() like other clear() calls because the
238  // alloc*() below "sync()" the parts they allocate.
239  allocName();
240  allocData();
241  allocControl();
242 }
243 
245 void
247 {
248  Must(!msg_iovlen && !msg_iov);
249  msg_iovlen = 1;
250  msg_iov = ios;
251  ios[0].iov_base = &data;
252  ios[0].iov_len = sizeof(data);
253  data.type_ = 0;
254  data.size = 0;
255 }
256 
257 void
259 {
260  Must(!msg_name && !msg_namelen);
261  msg_name = &name;
262  msg_namelen = sizeof(name); // is that the right size?
263 }
264 
265 void
267 {
268  Must(!msg_control && !msg_controllen);
269  msg_control = &ctrl;
270  msg_controllen = sizeof(ctrl);
271 }
272 
#define SUN_LEN(ptr)
Definition: cmsg.h:113
unsigned int offset
data offset for the next get/put*() to start with
Definition: TypedMsgHdr.h:111
const char * rawBuf() const
Definition: SquidString.h:86
int cmsg_type
Definition: cmsg.h:38
void setType(int aType)
sets message type; use MessageType enum
Definition: TypedMsgHdr.cc:100
void putFixed(const void *raw, size_t size)
always store size bytes
Definition: TypedMsgHdr.cc:158
int psize() const
Definition: SquidString.h:77
void checkType(int aType) const
Definition: TypedMsgHdr.cc:94
unsigned int cmsg_len
Definition: cmsg.h:36
struct Ipc::TypedMsgHdr::DataBuffer data
same as .msg_iov[0].iov_base
#define SCM_RIGHTS
Definition: cmsg.h:118
bool hasFd() const
whether the message has a descriptor stored
Definition: TypedMsgHdr.cc:187
#define CMSG_LEN(len)
Definition: cmsg.h:77
void prepForReading()
reset and provide all buffers
Definition: TypedMsgHdr.cc:234
void putInt(int n)
store an integer
Definition: TypedMsgHdr.cc:119
int getInt() const
load an integer
Definition: TypedMsgHdr.cc:111
int getFd() const
returns stored descriptor
Definition: TypedMsgHdr.cc:217
struct sockaddr_un name
same as .msg_name
Definition: TypedMsgHdr.h:91
struct iovec ios[1]
same as .msg_iov[]
Definition: TypedMsgHdr.h:93
void getString(String &s) const
load variable-length string
Definition: TypedMsgHdr.cc:125
void getRaw(void *raw, size_t size) const
low-level loading of exactly size bytes of raw data
Definition: TypedMsgHdr.cc:166
int cmsg_level
Definition: cmsg.h:37
#define CMSG_FIRSTHDR(mhdr)
Definition: cmsg.h:59
Definition: cmsg.h:88
Definition: cmsg.h:35
#define Must(condition)
Definition: TextException.h:75
void assign(const char *str, int len)
Definition: String.cc:78
struct msghdr with a known type, fixed-size I/O and control buffers
Definition: TypedMsgHdr.h:34
void putFd(int aFd)
stores descriptor
Definition: TypedMsgHdr.cc:196
void allocData()
initialize io vector with one io record
Definition: TypedMsgHdr.cc:246
void address(const struct sockaddr_un &addr)
sets [dest.] address
Definition: TypedMsgHdr.cc:85
#define SQUID_CMSG_DATA(cmsg)
Definition: cmsg.h:51
void putString(const String &s)
store variable-length string
Definition: TypedMsgHdr.cc:143
void getFixed(void *raw, size_t size) const
always load size bytes
Definition: TypedMsgHdr.cc:151
TypedMsgHdr & operator=(const TypedMsgHdr &tmh)
Definition: TypedMsgHdr.cc:31
void clean()
Definition: String.cc:103
void putRaw(const void *raw, size_t size)
low-level storage of exactly size bytes of raw data
Definition: TypedMsgHdr.cc:177
struct Ipc::TypedMsgHdr::CtrlBuffer ctrl
same as .msg_control

 

Introduction

Documentation

Support

Miscellaneous