]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ipc/TypedMsgHdr.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / ipc / TypedMsgHdr.cc
CommitLineData
98d9bd29 1/*
77b1029d 2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
98d9bd29 3 *
bbc27441
AJ
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.
98d9bd29
AR
7 */
8
bbc27441
AJ
9/* DEBUG: section 54 Interprocess Communication */
10
f7f3304a 11#include "squid.h"
a67d2b2e 12#include "base/TextException.h"
98d9bd29 13#include "ipc/TypedMsgHdr.h"
0d1c9fe8 14#include "SquidString.h"
5bed43d6 15#include "tools.h"
98d9bd29 16
074d6a40 17#include <cstring>
3d41e53a 18
98d9bd29
AR
19Ipc::TypedMsgHdr::TypedMsgHdr()
20{
b56b37cf 21 clear();
5667a628 22 sync();
98d9bd29
AR
23}
24
25Ipc::TypedMsgHdr::TypedMsgHdr(const TypedMsgHdr &tmh)
26{
b56b37cf
AJ
27 clear();
28 operator =(tmh);
98d9bd29
AR
29}
30
31Ipc::TypedMsgHdr &Ipc::TypedMsgHdr::operator =(const TypedMsgHdr &tmh)
32{
5667a628 33 if (this != &tmh) { // skip assignment to self
b56b37cf 34 memcpy(static_cast<msghdr*>(this), static_cast<const msghdr*>(&tmh), sizeof(msghdr));
914599e3
AR
35 name = tmh.name;
36 memcpy(&ios, &tmh.ios, sizeof(ios));
b56b37cf
AJ
37 data = tmh.data;
38 ctrl = tmh.ctrl;
39 offset = tmh.offset;
5667a628
AR
40 sync();
41 }
42 return *this;
98d9bd29
AR
43}
44
b56b37cf
AJ
45void
46Ipc::TypedMsgHdr::clear()
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
98d9bd29
AR
57// update msghdr and ios pointers based on msghdr counters
58void Ipc::TypedMsgHdr::sync()
59{
5667a628
AR
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 }
8822ebee 81 offset = 0;
98d9bd29
AR
82}
83
98d9bd29
AR
84int
85Ipc::TypedMsgHdr::type() const
86{
5667a628
AR
87 Must(msg_iovlen == 1);
88 return data.type_;
98d9bd29
AR
89}
90
91void
92Ipc::TypedMsgHdr::address(const struct sockaddr_un& addr)
93{
5667a628
AR
94 allocName();
95 name = addr;
98d9bd29
AR
96 msg_name = &name;
97 msg_namelen = SUN_LEN(&name);
98}
99
100void
8822ebee 101Ipc::TypedMsgHdr::checkType(int destType) const
98d9bd29 102{
5667a628 103 Must(type() == destType);
98d9bd29
AR
104}
105
106void
8822ebee 107Ipc::TypedMsgHdr::setType(int aType)
98d9bd29 108{
8822ebee
AR
109 if (data.type_) {
110 Must(data.type_ == aType);
111 } else {
112 allocData();
113 data.type_ = aType;
114 }
115}
116
117int
118Ipc::TypedMsgHdr::getInt() const
119{
120 int n = 0;
121 getPod(n);
122 return n;
123}
124
125void
126Ipc::TypedMsgHdr::putInt(const int n)
127{
128 putPod(n);
129}
130
131void
132Ipc::TypedMsgHdr::getString(String &s) const
133{
134 const int length = getInt();
135 Must(length >= 0);
136 // String uses memcpy uncoditionally; TODO: SBuf eliminates this check
137 if (!length) {
138 s.clean();
139 return;
140 }
141
142 Must(length <= maxSize);
143 // TODO: use SBuf.reserve() instead of a temporary buffer
f867ba6b 144 char buf[maxSize];
8822ebee 145 getRaw(&buf, length);
2fe0439c 146 s.assign(buf, length);
8822ebee
AR
147}
148
149void
150Ipc::TypedMsgHdr::putString(const String &s)
151{
152 Must(s.psize() <= maxSize);
153 putInt(s.psize());
154 putRaw(s.rawBuf(), s.psize());
155}
156
157void
9dca980d 158Ipc::TypedMsgHdr::getFixed(void *rawBuf, size_t rawSize) const
8822ebee
AR
159{
160 // no need to load size because it is constant
9dca980d 161 getRaw(rawBuf, rawSize);
8822ebee
AR
162}
163
164void
9dca980d 165Ipc::TypedMsgHdr::putFixed(const void *rawBuf, size_t rawSize)
8822ebee
AR
166{
167 // no need to store size because it is constant
9dca980d 168 putRaw(rawBuf, rawSize);
8822ebee
AR
169}
170
171/// low-level loading of exactly size bytes of raw data
172void
9dca980d 173Ipc::TypedMsgHdr::getRaw(void *rawBuf, size_t rawSize) const
8822ebee 174{
9dca980d
AJ
175 if (rawSize > 0) {
176 Must(rawSize <= data.size - offset);
177 memcpy(rawBuf, data.raw + offset, rawSize);
178 offset += rawSize;
8822ebee
AR
179 }
180}
181
182/// low-level storage of exactly size bytes of raw data
183void
9dca980d 184Ipc::TypedMsgHdr::putRaw(const void *rawBuf, size_t rawSize)
8822ebee 185{
9dca980d
AJ
186 if (rawSize > 0) {
187 Must(rawSize <= sizeof(data.raw) - data.size);
188 memcpy(data.raw + data.size, rawBuf, rawSize);
189 data.size += rawSize;
8822ebee 190 }
98d9bd29
AR
191}
192
9b440559
CT
193bool
194Ipc::TypedMsgHdr::hasFd() const
195{
097f803c
A
196 struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
197 return cmsg &&
198 cmsg->cmsg_level == SOL_SOCKET &&
199 cmsg->cmsg_type == SCM_RIGHTS;
9b440559
CT
200}
201
98d9bd29
AR
202void
203Ipc::TypedMsgHdr::putFd(int fd)
204{
5667a628 205 Must(fd >= 0);
9b440559 206 Must(!hasFd());
5667a628 207 allocControl();
98d9bd29 208
5667a628 209 const int fdCount = 1;
98d9bd29 210
5667a628
AR
211 struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
212 cmsg->cmsg_level = SOL_SOCKET;
213 cmsg->cmsg_type = SCM_RIGHTS;
214 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
98d9bd29 215
2ff9dfaa 216 int *fdStore = reinterpret_cast<int*>(SQUID_CMSG_DATA(cmsg));
41d00cd3 217 memcpy(fdStore, &fd, fdCount * sizeof(int));
98d9bd29 218 msg_controllen = cmsg->cmsg_len;
9b440559
CT
219
220 Must(hasFd());
98d9bd29
AR
221}
222
223int
224Ipc::TypedMsgHdr::getFd() const
225{
5667a628 226 Must(msg_control && msg_controllen);
9b440559 227 Must(hasFd());
98d9bd29 228
5667a628
AR
229 struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
230 Must(cmsg->cmsg_level == SOL_SOCKET);
231 Must(cmsg->cmsg_type == SCM_RIGHTS);
98d9bd29 232
5667a628 233 const int fdCount = 1;
2ff9dfaa 234 const int *fdStore = reinterpret_cast<const int*>(SQUID_CMSG_DATA(cmsg));
5667a628 235 int fd = -1;
41d00cd3 236 memcpy(&fd, fdStore, fdCount * sizeof(int));
5667a628 237 return fd;
98d9bd29
AR
238}
239
240void
241Ipc::TypedMsgHdr::prepForReading()
242{
b56b37cf
AJ
243 clear();
244 // no sync() like other clear() calls because the
245 // alloc*() below "sync()" the parts they allocate.
5667a628
AR
246 allocName();
247 allocData();
248 allocControl();
98d9bd29
AR
249}
250
251/// initialize io vector with one io record
252void
253Ipc::TypedMsgHdr::allocData()
254{
5667a628
AR
255 Must(!msg_iovlen && !msg_iov);
256 msg_iovlen = 1;
257 msg_iov = ios;
258 ios[0].iov_base = &data;
259 ios[0].iov_len = sizeof(data);
260 data.type_ = 0;
261 data.size = 0;
98d9bd29
AR
262}
263
264void
265Ipc::TypedMsgHdr::allocName()
266{
5667a628 267 Must(!msg_name && !msg_namelen);
98d9bd29
AR
268 msg_name = &name;
269 msg_namelen = sizeof(name); // is that the right size?
270}
271
272void
273Ipc::TypedMsgHdr::allocControl()
274{
5667a628
AR
275 Must(!msg_control && !msg_controllen);
276 msg_control = &ctrl;
277 msg_controllen = sizeof(ctrl);
98d9bd29 278}
f53969cc 279