]>
Commit | Line | Data |
---|---|---|
98d9bd29 | 1 | /* |
f6e9a3ee | 2 | * Copyright (C) 1996-2019 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 |
19 | Ipc::TypedMsgHdr::TypedMsgHdr() |
20 | { | |
b56b37cf | 21 | clear(); |
5667a628 | 22 | sync(); |
98d9bd29 AR |
23 | } |
24 | ||
25 | Ipc::TypedMsgHdr::TypedMsgHdr(const TypedMsgHdr &tmh) | |
26 | { | |
b56b37cf AJ |
27 | clear(); |
28 | operator =(tmh); | |
98d9bd29 AR |
29 | } |
30 | ||
31 | Ipc::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 |
45 | void |
46 | Ipc::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 |
58 | void 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 |
84 | int |
85 | Ipc::TypedMsgHdr::type() const | |
86 | { | |
5667a628 AR |
87 | Must(msg_iovlen == 1); |
88 | return data.type_; | |
98d9bd29 AR |
89 | } |
90 | ||
91 | void | |
92 | Ipc::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 | ||
100 | void | |
8822ebee | 101 | Ipc::TypedMsgHdr::checkType(int destType) const |
98d9bd29 | 102 | { |
5667a628 | 103 | Must(type() == destType); |
98d9bd29 AR |
104 | } |
105 | ||
106 | void | |
8822ebee | 107 | Ipc::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 | ||
117 | int | |
118 | Ipc::TypedMsgHdr::getInt() const | |
119 | { | |
120 | int n = 0; | |
121 | getPod(n); | |
122 | return n; | |
123 | } | |
124 | ||
125 | void | |
126 | Ipc::TypedMsgHdr::putInt(const int n) | |
127 | { | |
128 | putPod(n); | |
129 | } | |
130 | ||
131 | void | |
132 | Ipc::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 AR |
145 | getRaw(&buf, length); |
146 | s.limitInit(buf, length); | |
147 | } | |
148 | ||
149 | void | |
150 | Ipc::TypedMsgHdr::putString(const String &s) | |
151 | { | |
152 | Must(s.psize() <= maxSize); | |
153 | putInt(s.psize()); | |
154 | putRaw(s.rawBuf(), s.psize()); | |
155 | } | |
156 | ||
157 | void | |
9dca980d | 158 | Ipc::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 | ||
164 | void | |
9dca980d | 165 | Ipc::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 | |
172 | void | |
9dca980d | 173 | Ipc::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 | |
183 | void | |
9dca980d | 184 | Ipc::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 |
193 | bool |
194 | Ipc::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 |
202 | void |
203 | Ipc::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 | ||
223 | int | |
224 | Ipc::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 | ||
240 | void | |
241 | Ipc::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 | |
252 | void | |
253 | Ipc::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 | ||
264 | void | |
265 | Ipc::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 | ||
272 | void | |
273 | Ipc::TypedMsgHdr::allocControl() | |
274 | { | |
5667a628 AR |
275 | Must(!msg_control && !msg_controllen); |
276 | msg_control = &ctrl; | |
277 | msg_controllen = sizeof(ctrl); | |
98d9bd29 | 278 | } |
f53969cc | 279 |