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