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