]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ipc/TypedMsgHdr.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / ipc / TypedMsgHdr.cc
CommitLineData
98d9bd29 1/*
4ac4a490 2 * Copyright (C) 1996-2017 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{
e297be13 21 memset(this, 0, sizeof(*this));
5667a628 22 sync();
98d9bd29
AR
23}
24
25Ipc::TypedMsgHdr::TypedMsgHdr(const TypedMsgHdr &tmh)
26{
41d00cd3 27 memcpy(this, &tmh, sizeof(*this));
5667a628 28 sync();
98d9bd29
AR
29}
30
31Ipc::TypedMsgHdr &Ipc::TypedMsgHdr::operator =(const TypedMsgHdr &tmh)
32{
5667a628 33 if (this != &tmh) { // skip assignment to self
41d00cd3 34 memcpy(this, &tmh, sizeof(*this));
5667a628
AR
35 sync();
36 }
37 return *this;
98d9bd29
AR
38}
39
40// update msghdr and ios pointers based on msghdr counters
41void Ipc::TypedMsgHdr::sync()
42{
5667a628
AR
43 if (msg_name) { // we have a name
44 msg_name = &name;
45 } else {
46 Must(!msg_namelen && !msg_name);
47 }
48
49 if (msg_iov) { // we have a data component
50 Must(msg_iovlen == 1);
51 msg_iov = ios;
52 ios[0].iov_base = &data;
53 Must(ios[0].iov_len == sizeof(data));
54 } else {
55 Must(!msg_iovlen && !msg_iov);
56 }
57
58 if (msg_control) { // we have a control component
59 Must(msg_controllen > 0);
60 msg_control = &ctrl;
61 } else {
62 Must(!msg_controllen && !msg_control);
63 }
8822ebee 64 offset = 0;
98d9bd29
AR
65}
66
98d9bd29
AR
67int
68Ipc::TypedMsgHdr::type() const
69{
5667a628
AR
70 Must(msg_iovlen == 1);
71 return data.type_;
98d9bd29
AR
72}
73
74void
75Ipc::TypedMsgHdr::address(const struct sockaddr_un& addr)
76{
5667a628
AR
77 allocName();
78 name = addr;
98d9bd29
AR
79 msg_name = &name;
80 msg_namelen = SUN_LEN(&name);
81}
82
83void
8822ebee 84Ipc::TypedMsgHdr::checkType(int destType) const
98d9bd29 85{
5667a628 86 Must(type() == destType);
98d9bd29
AR
87}
88
89void
8822ebee 90Ipc::TypedMsgHdr::setType(int aType)
98d9bd29 91{
8822ebee
AR
92 if (data.type_) {
93 Must(data.type_ == aType);
94 } else {
95 allocData();
96 data.type_ = aType;
97 }
98}
99
100int
101Ipc::TypedMsgHdr::getInt() const
102{
103 int n = 0;
104 getPod(n);
105 return n;
106}
107
108void
109Ipc::TypedMsgHdr::putInt(const int n)
110{
111 putPod(n);
112}
113
114void
115Ipc::TypedMsgHdr::getString(String &s) const
116{
117 const int length = getInt();
118 Must(length >= 0);
119 // String uses memcpy uncoditionally; TODO: SBuf eliminates this check
120 if (!length) {
121 s.clean();
122 return;
123 }
124
125 Must(length <= maxSize);
126 // TODO: use SBuf.reserve() instead of a temporary buffer
f867ba6b 127 char buf[maxSize];
8822ebee
AR
128 getRaw(&buf, length);
129 s.limitInit(buf, length);
130}
131
132void
133Ipc::TypedMsgHdr::putString(const String &s)
134{
135 Must(s.psize() <= maxSize);
136 putInt(s.psize());
137 putRaw(s.rawBuf(), s.psize());
138}
139
140void
9dca980d 141Ipc::TypedMsgHdr::getFixed(void *rawBuf, size_t rawSize) const
8822ebee
AR
142{
143 // no need to load size because it is constant
9dca980d 144 getRaw(rawBuf, rawSize);
8822ebee
AR
145}
146
147void
9dca980d 148Ipc::TypedMsgHdr::putFixed(const void *rawBuf, size_t rawSize)
8822ebee
AR
149{
150 // no need to store size because it is constant
9dca980d 151 putRaw(rawBuf, rawSize);
8822ebee
AR
152}
153
154/// low-level loading of exactly size bytes of raw data
155void
9dca980d 156Ipc::TypedMsgHdr::getRaw(void *rawBuf, size_t rawSize) const
8822ebee 157{
9dca980d
AJ
158 if (rawSize > 0) {
159 Must(rawSize <= data.size - offset);
160 memcpy(rawBuf, data.raw + offset, rawSize);
161 offset += rawSize;
8822ebee
AR
162 }
163}
164
165/// low-level storage of exactly size bytes of raw data
166void
9dca980d 167Ipc::TypedMsgHdr::putRaw(const void *rawBuf, size_t rawSize)
8822ebee 168{
9dca980d
AJ
169 if (rawSize > 0) {
170 Must(rawSize <= sizeof(data.raw) - data.size);
171 memcpy(data.raw + data.size, rawBuf, rawSize);
172 data.size += rawSize;
8822ebee 173 }
98d9bd29
AR
174}
175
9b440559
CT
176bool
177Ipc::TypedMsgHdr::hasFd() const
178{
097f803c
A
179 struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
180 return cmsg &&
181 cmsg->cmsg_level == SOL_SOCKET &&
182 cmsg->cmsg_type == SCM_RIGHTS;
9b440559
CT
183}
184
98d9bd29
AR
185void
186Ipc::TypedMsgHdr::putFd(int fd)
187{
5667a628 188 Must(fd >= 0);
9b440559 189 Must(!hasFd());
5667a628 190 allocControl();
98d9bd29 191
5667a628 192 const int fdCount = 1;
98d9bd29 193
5667a628
AR
194 struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
195 cmsg->cmsg_level = SOL_SOCKET;
196 cmsg->cmsg_type = SCM_RIGHTS;
197 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
98d9bd29 198
2ff9dfaa 199 int *fdStore = reinterpret_cast<int*>(SQUID_CMSG_DATA(cmsg));
41d00cd3 200 memcpy(fdStore, &fd, fdCount * sizeof(int));
98d9bd29 201 msg_controllen = cmsg->cmsg_len;
9b440559
CT
202
203 Must(hasFd());
98d9bd29
AR
204}
205
206int
207Ipc::TypedMsgHdr::getFd() const
208{
5667a628 209 Must(msg_control && msg_controllen);
9b440559 210 Must(hasFd());
98d9bd29 211
5667a628
AR
212 struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
213 Must(cmsg->cmsg_level == SOL_SOCKET);
214 Must(cmsg->cmsg_type == SCM_RIGHTS);
98d9bd29 215
5667a628 216 const int fdCount = 1;
2ff9dfaa 217 const int *fdStore = reinterpret_cast<const int*>(SQUID_CMSG_DATA(cmsg));
5667a628 218 int fd = -1;
41d00cd3 219 memcpy(&fd, fdStore, fdCount * sizeof(int));
5667a628 220 return fd;
98d9bd29
AR
221}
222
223void
224Ipc::TypedMsgHdr::prepForReading()
225{
e297be13 226 memset(this, 0, sizeof(*this));
5667a628
AR
227 allocName();
228 allocData();
229 allocControl();
98d9bd29
AR
230}
231
232/// initialize io vector with one io record
233void
234Ipc::TypedMsgHdr::allocData()
235{
5667a628
AR
236 Must(!msg_iovlen && !msg_iov);
237 msg_iovlen = 1;
238 msg_iov = ios;
239 ios[0].iov_base = &data;
240 ios[0].iov_len = sizeof(data);
241 data.type_ = 0;
242 data.size = 0;
98d9bd29
AR
243}
244
245void
246Ipc::TypedMsgHdr::allocName()
247{
5667a628 248 Must(!msg_name && !msg_namelen);
98d9bd29
AR
249 msg_name = &name;
250 msg_namelen = sizeof(name); // is that the right size?
251}
252
253void
254Ipc::TypedMsgHdr::allocControl()
255{
5667a628
AR
256 Must(!msg_control && !msg_controllen);
257 msg_control = &ctrl;
258 msg_controllen = sizeof(ctrl);
98d9bd29 259}
f53969cc 260