GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/cache_transport.cc
Date: 2026-11-08 02:41:18
Exec Total Coverage
Lines: 327 373 87.7%
Branches: 167 230 72.6%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #include "cache_transport.h"
6
7 #include <alloca.h>
8 #include <errno.h>
9 #include <sys/socket.h>
10
11 #include <cassert>
12 #include <cstdlib>
13 #include <cstring>
14
15 #include "cache.h"
16 #include "crypto/hash.h"
17 #include "util/exception.h"
18 #include "util/logging.h"
19 #include "util/posix.h"
20 #include "util/smalloc.h"
21
22 // TODO(jblomer): Check for possible starvation of plugin by dying clients
23 // (blocking read). Probably only relevant for TCP sockets.
24
25 using namespace std; // NOLINT
26
27 const char
28 *CacheTransport::kEnvReadyNotifyFd = "__CVMFS_CACHE_EXTERNAL_PIPE_READY__";
29
30 /**
31 * Called on the sender side to wrap a message into a MsgRpc message for wire
32 * transfer.
33 */
34 132101 cvmfs::MsgRpc *CacheTransport::Frame::GetMsgRpc() {
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132101 times.
132101 assert(msg_typed_ != NULL);
36
1/2
✓ Branch 0 taken 132101 times.
✗ Branch 1 not taken.
132101 if (!is_wrapped_)
37 132101 WrapMsg();
38 132117 return &msg_rpc_;
39 }
40
41
42 /**
43 * Called on the receiving end of an RPC to extract the actual message from the
44 * MsgRpc.
45 */
46 164429 google::protobuf::MessageLite *CacheTransport::Frame::GetMsgTyped() {
47
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 164365 times.
164429 assert(msg_rpc_.IsInitialized());
48
2/2
✓ Branch 0 taken 136410 times.
✓ Branch 1 taken 27955 times.
164365 if (msg_typed_ == NULL)
49 136410 UnwrapMsg();
50 164253 return msg_typed_;
51 }
52
53
54 164525 CacheTransport::Frame::Frame()
55 164525 : owns_msg_typed_(false)
56 164525 , msg_typed_(NULL)
57 164525 , attachment_(NULL)
58 164525 , att_size_(0)
59 164525 , is_wrapped_(false)
60 164525 , is_msg_out_of_band_(false) { }
61
62
63 132117 CacheTransport::Frame::Frame(google::protobuf::MessageLite *m)
64 132117 : owns_msg_typed_(false)
65 132117 , msg_typed_(m)
66 132117 , attachment_(NULL)
67 132117 , att_size_(0)
68 132117 , is_wrapped_(false)
69 132117 , is_msg_out_of_band_(false) { }
70
71
72 296642 CacheTransport::Frame::~Frame() { Reset(0); }
73
74
75 27971 bool CacheTransport::Frame::IsMsgOutOfBand() {
76
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27971 times.
27971 assert(msg_rpc_.IsInitialized());
77
1/2
✓ Branch 0 taken 27971 times.
✗ Branch 1 not taken.
27971 if (msg_typed_ == NULL)
78 27971 UnwrapMsg();
79 27971 return is_msg_out_of_band_;
80 }
81
82
83 32448 void CacheTransport::Frame::MergeFrom(const Frame &other) {
84 32448 msg_rpc_.CheckTypeAndMergeFrom(other.msg_rpc_);
85 32448 owns_msg_typed_ = true;
86
2/2
✓ Branch 0 taken 28800 times.
✓ Branch 1 taken 3648 times.
32448 if (other.att_size_ > 0) {
87
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28800 times.
28800 assert(att_size_ >= other.att_size_);
88 28800 memcpy(attachment_, other.attachment_, other.att_size_);
89 28800 att_size_ = other.att_size_;
90 }
91 32448 }
92
93
94 132077 bool CacheTransport::Frame::ParseMsgRpc(void *buffer, uint32_t size) {
95 132077 const bool retval = msg_rpc_.ParseFromArray(buffer, size);
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132077 times.
132077 if (!retval)
97 ✗ return false;
98
99 // Cleanup typed message when Frame leaves scope
100 132077 owns_msg_typed_ = true;
101 132077 return true;
102 }
103
104
105 296658 void CacheTransport::Frame::Release() {
106
2/2
✓ Branch 0 taken 164525 times.
✓ Branch 1 taken 132133 times.
296658 if (owns_msg_typed_)
107 164525 return;
108
109 132133 (void)msg_rpc_.release_msg_refcount_req();
110 132117 (void)msg_rpc_.release_msg_refcount_reply();
111 132133 (void)msg_rpc_.release_msg_read_req();
112 132117 (void)msg_rpc_.release_msg_read_reply();
113 132133 (void)msg_rpc_.release_msg_object_info_req();
114 132133 (void)msg_rpc_.release_msg_object_info_reply();
115 132133 (void)msg_rpc_.release_msg_store_req();
116 132133 (void)msg_rpc_.release_msg_store_abort_req();
117 132101 (void)msg_rpc_.release_msg_store_reply();
118 132101 (void)msg_rpc_.release_msg_handshake();
119 132101 (void)msg_rpc_.release_msg_handshake_ack();
120 132101 (void)msg_rpc_.release_msg_quit();
121 132133 (void)msg_rpc_.release_msg_ioctl();
122 132117 (void)msg_rpc_.release_msg_info_req();
123 132133 (void)msg_rpc_.release_msg_info_reply();
124 132117 (void)msg_rpc_.release_msg_shrink_req();
125 132117 (void)msg_rpc_.release_msg_shrink_reply();
126 132117 (void)msg_rpc_.release_msg_list_req();
127 132117 (void)msg_rpc_.release_msg_list_reply();
128 132133 (void)msg_rpc_.release_msg_detach();
129 132133 (void)msg_rpc_.release_msg_breadcrumb_store_req();
130 132133 (void)msg_rpc_.release_msg_breadcrumb_load_req();
131 132133 (void)msg_rpc_.release_msg_breadcrumb_reply();
132 }
133
134
135 296658 void CacheTransport::Frame::Reset(uint32_t original_att_size) {
136 296658 msg_typed_ = NULL;
137 296658 att_size_ = original_att_size;
138 296658 is_wrapped_ = false;
139 296658 is_msg_out_of_band_ = false;
140 296658 Release();
141 296658 msg_rpc_.Clear();
142 296658 owns_msg_typed_ = false;
143 296658 }
144
145
146 132101 void CacheTransport::Frame::WrapMsg() {
147
2/2
✓ Branch 3 taken 314 times.
✓ Branch 4 taken 131787 times.
132101 if (msg_typed_->GetTypeName() == "cvmfs.MsgHandshake") {
148 314 msg_rpc_.set_allocated_msg_handshake(
149 314 reinterpret_cast<cvmfs::MsgHandshake *>(msg_typed_));
150
2/2
✓ Branch 3 taken 288 times.
✓ Branch 4 taken 131515 times.
131787 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgHandshakeAck") {
151 288 msg_rpc_.set_allocated_msg_handshake_ack(
152 288 reinterpret_cast<cvmfs::MsgHandshakeAck *>(msg_typed_));
153
2/2
✓ Branch 3 taken 312 times.
✓ Branch 4 taken 131203 times.
131515 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgQuit") {
154 312 msg_rpc_.set_allocated_msg_quit(
155 312 reinterpret_cast<cvmfs::MsgQuit *>(msg_typed_));
156
2/2
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 131139 times.
131203 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgIoctl") {
157 64 msg_rpc_.set_allocated_msg_ioctl(
158 64 reinterpret_cast<cvmfs::MsgIoctl *>(msg_typed_));
159
2/2
✓ Branch 3 taken 11528 times.
✓ Branch 4 taken 119595 times.
131139 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgRefcountReq") {
160 11528 msg_rpc_.set_allocated_msg_refcount_req(
161 11528 reinterpret_cast<cvmfs::MsgRefcountReq *>(msg_typed_));
162
2/2
✓ Branch 3 taken 9024 times.
✓ Branch 4 taken 110587 times.
119595 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgRefcountReply") {
163 9024 msg_rpc_.set_allocated_msg_refcount_reply(
164 9024 reinterpret_cast<cvmfs::MsgRefcountReply *>(msg_typed_));
165
2/2
✓ Branch 3 taken 280 times.
✓ Branch 4 taken 110307 times.
110587 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgObjectInfoReq") {
166 280 msg_rpc_.set_allocated_msg_object_info_req(
167 280 reinterpret_cast<cvmfs::MsgObjectInfoReq *>(msg_typed_));
168
2/2
✓ Branch 3 taken 256 times.
✓ Branch 4 taken 110035 times.
110307 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgObjectInfoReply") {
169 256 msg_rpc_.set_allocated_msg_object_info_reply(
170 256 reinterpret_cast<cvmfs::MsgObjectInfoReply *>(msg_typed_));
171
2/2
✓ Branch 3 taken 36087 times.
✓ Branch 4 taken 73964 times.
110035 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgReadReq") {
172 36087 msg_rpc_.set_allocated_msg_read_req(
173 36087 reinterpret_cast<cvmfs::MsgReadReq *>(msg_typed_));
174
2/2
✓ Branch 3 taken 35376 times.
✓ Branch 4 taken 38588 times.
73964 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgReadReply") {
175 35376 msg_rpc_.set_allocated_msg_read_reply(
176 35376 reinterpret_cast<cvmfs::MsgReadReply *>(msg_typed_));
177
2/2
✓ Branch 3 taken 12142 times.
✓ Branch 4 taken 26446 times.
38588 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgStoreReq") {
178 12142 msg_rpc_.set_allocated_msg_store_req(
179 12142 reinterpret_cast<cvmfs::MsgStoreReq *>(msg_typed_));
180
2/2
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 26430 times.
26446 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgStoreAbortReq") {
181 16 msg_rpc_.set_allocated_msg_store_abort_req(
182 16 reinterpret_cast<cvmfs::MsgStoreAbortReq *>(msg_typed_));
183
2/2
✓ Branch 3 taken 9744 times.
✓ Branch 4 taken 16686 times.
26430 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgStoreReply") {
184 9744 msg_rpc_.set_allocated_msg_store_reply(
185 9744 reinterpret_cast<cvmfs::MsgStoreReply *>(msg_typed_));
186
2/2
✓ Branch 3 taken 88 times.
✓ Branch 4 taken 16598 times.
16686 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgInfoReq") {
187 88 msg_rpc_.set_allocated_msg_info_req(
188 88 reinterpret_cast<cvmfs::MsgInfoReq *>(msg_typed_));
189
2/2
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 16534 times.
16598 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgInfoReply") {
190 64 msg_rpc_.set_allocated_msg_info_reply(
191 64 reinterpret_cast<cvmfs::MsgInfoReply *>(msg_typed_));
192
2/2
✓ Branch 3 taken 40 times.
✓ Branch 4 taken 16494 times.
16534 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgShrinkReq") {
193 40 msg_rpc_.set_allocated_msg_shrink_req(
194 40 reinterpret_cast<cvmfs::MsgShrinkReq *>(msg_typed_));
195
2/2
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 16462 times.
16494 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgShrinkReply") {
196 32 msg_rpc_.set_allocated_msg_shrink_reply(
197 32 reinterpret_cast<cvmfs::MsgShrinkReply *>(msg_typed_));
198
2/2
✓ Branch 3 taken 168 times.
✓ Branch 4 taken 16294 times.
16462 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgListReq") {
199 168 msg_rpc_.set_allocated_msg_list_req(
200 168 reinterpret_cast<cvmfs::MsgListReq *>(msg_typed_));
201
2/2
✓ Branch 3 taken 160 times.
✓ Branch 4 taken 16134 times.
16294 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgListReply") {
202 160 msg_rpc_.set_allocated_msg_list_reply(
203 160 reinterpret_cast<cvmfs::MsgListReply *>(msg_typed_));
204
2/2
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 16116 times.
16134 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgBreadcrumbStoreReq") {
205 18 msg_rpc_.set_allocated_msg_breadcrumb_store_req(
206 18 reinterpret_cast<cvmfs::MsgBreadcrumbStoreReq *>(msg_typed_));
207
2/2
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 16080 times.
16116 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgBreadcrumbLoadReq") {
208 36 msg_rpc_.set_allocated_msg_breadcrumb_load_req(
209 36 reinterpret_cast<cvmfs::MsgBreadcrumbLoadReq *>(msg_typed_));
210
2/2
✓ Branch 3 taken 48 times.
✓ Branch 4 taken 16032 times.
16080 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgBreadcrumbReply") {
211 48 msg_rpc_.set_allocated_msg_breadcrumb_reply(
212 48 reinterpret_cast<cvmfs::MsgBreadcrumbReply *>(msg_typed_));
213
1/2
✓ Branch 3 taken 16032 times.
✗ Branch 4 not taken.
16032 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgDetach") {
214 16032 msg_rpc_.set_allocated_msg_detach(
215 16032 reinterpret_cast<cvmfs::MsgDetach *>(msg_typed_));
216 16032 is_msg_out_of_band_ = true;
217 } else {
218 // Unexpected message type, should never happen
219 ✗ PANIC(NULL);
220 }
221 132117 is_wrapped_ = true;
222 132117 }
223
224
225 164429 void CacheTransport::Frame::UnwrapMsg() {
226
2/2
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 164061 times.
164429 if (msg_rpc_.has_msg_handshake()) {
227 288 msg_typed_ = msg_rpc_.mutable_msg_handshake();
228
2/2
✓ Branch 1 taken 314 times.
✓ Branch 2 taken 163747 times.
164061 } else if (msg_rpc_.has_msg_handshake_ack()) {
229 314 msg_typed_ = msg_rpc_.mutable_msg_handshake_ack();
230
2/2
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 163411 times.
163747 } else if (msg_rpc_.has_msg_quit()) {
231 288 msg_typed_ = msg_rpc_.mutable_msg_quit();
232
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 163411 times.
163411 } else if (msg_rpc_.has_msg_ioctl()) {
233 64 msg_typed_ = msg_rpc_.mutable_msg_ioctl();
234
2/2
✓ Branch 1 taken 9024 times.
✓ Branch 2 taken 154339 times.
163411 } else if (msg_rpc_.has_msg_refcount_req()) {
235 9024 msg_typed_ = msg_rpc_.mutable_msg_refcount_req();
236
2/2
✓ Branch 1 taken 11816 times.
✓ Branch 2 taken 142443 times.
154339 } else if (msg_rpc_.has_msg_refcount_reply()) {
237 11816 msg_typed_ = msg_rpc_.mutable_msg_refcount_reply();
238
2/2
✓ Branch 1 taken 256 times.
✓ Branch 2 taken 142315 times.
142443 } else if (msg_rpc_.has_msg_object_info_req()) {
239 256 msg_typed_ = msg_rpc_.mutable_msg_object_info_req();
240
2/2
✓ Branch 1 taken 424 times.
✓ Branch 2 taken 141859 times.
142315 } else if (msg_rpc_.has_msg_object_info_reply()) {
241 424 msg_typed_ = msg_rpc_.mutable_msg_object_info_reply();
242
2/2
✓ Branch 1 taken 35376 times.
✓ Branch 2 taken 106483 times.
141859 } else if (msg_rpc_.has_msg_read_req()) {
243 35376 msg_typed_ = msg_rpc_.mutable_msg_read_req();
244
2/2
✓ Branch 1 taken 64887 times.
✓ Branch 2 taken 41772 times.
106483 } else if (msg_rpc_.has_msg_read_reply()) {
245 64887 msg_typed_ = msg_rpc_.mutable_msg_read_reply();
246
2/2
✓ Branch 1 taken 9728 times.
✓ Branch 2 taken 32044 times.
41772 } else if (msg_rpc_.has_msg_store_req()) {
247 9728 msg_typed_ = msg_rpc_.mutable_msg_store_req();
248
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 32028 times.
32044 } else if (msg_rpc_.has_msg_store_abort_req()) {
249 16 msg_typed_ = msg_rpc_.mutable_msg_store_abort_req();
250
2/2
✓ Branch 1 taken 15358 times.
✓ Branch 2 taken 16670 times.
32028 } else if (msg_rpc_.has_msg_store_reply()) {
251 15358 msg_typed_ = msg_rpc_.mutable_msg_store_reply();
252
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 16606 times.
16670 } else if (msg_rpc_.has_msg_info_req()) {
253 64 msg_typed_ = msg_rpc_.mutable_msg_info_req();
254
2/2
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 16518 times.
16606 } else if (msg_rpc_.has_msg_info_reply()) {
255 88 msg_typed_ = msg_rpc_.mutable_msg_info_reply();
256
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 16486 times.
16518 } else if (msg_rpc_.has_msg_shrink_req()) {
257 32 msg_typed_ = msg_rpc_.mutable_msg_shrink_req();
258
2/2
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 16446 times.
16486 } else if (msg_rpc_.has_msg_shrink_reply()) {
259 40 msg_typed_ = msg_rpc_.mutable_msg_shrink_reply();
260
2/2
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 16286 times.
16446 } else if (msg_rpc_.has_msg_list_req()) {
261 160 msg_typed_ = msg_rpc_.mutable_msg_list_req();
262
2/2
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 16118 times.
16286 } else if (msg_rpc_.has_msg_list_reply()) {
263 168 msg_typed_ = msg_rpc_.mutable_msg_list_reply();
264
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 16102 times.
16118 } else if (msg_rpc_.has_msg_breadcrumb_store_req()) {
265 16 msg_typed_ = msg_rpc_.mutable_msg_breadcrumb_store_req();
266
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 16070 times.
16102 } else if (msg_rpc_.has_msg_breadcrumb_load_req()) {
267 32 msg_typed_ = msg_rpc_.mutable_msg_breadcrumb_load_req();
268
2/2
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 16016 times.
16070 } else if (msg_rpc_.has_msg_breadcrumb_reply()) {
269 54 msg_typed_ = msg_rpc_.mutable_msg_breadcrumb_reply();
270
1/2
✓ Branch 1 taken 16016 times.
✗ Branch 2 not taken.
16016 } else if (msg_rpc_.has_msg_detach()) {
271 16016 msg_typed_ = msg_rpc_.mutable_msg_detach();
272 16016 is_msg_out_of_band_ = true;
273 } else {
274 // Unexpected message type, should never happen
275 ✗ PANIC(NULL);
276 }
277 164509 }
278
279
280 //------------------------------------------------------------------------------
281
282
283 314 CacheTransport::CacheTransport(int fd_connection)
284 314 : fd_connection_(fd_connection), flags_(0) {
285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
314 assert(fd_connection_ >= 0);
286 314 }
287
288
289 71376 CacheTransport::CacheTransport(int fd_connection, uint32_t flags)
290 71376 : fd_connection_(fd_connection), flags_(flags) {
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71376 times.
71376 assert(fd_connection_ >= 0);
292 71376 }
293
294
295 3224522 void CacheTransport::FillMsgHash(const shash::Any &hash,
296 cvmfs::MsgHash *msg_hash) {
297
3/4
✓ Branch 0 taken 3224464 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
3224522 switch (hash.algorithm) {
298 3224464 case shash::kSha1:
299 3224464 msg_hash->set_algorithm(cvmfs::HASH_SHA1);
300 3224464 break;
301 12 case shash::kRmd160:
302 12 msg_hash->set_algorithm(cvmfs::HASH_RIPEMD160);
303 12 break;
304 46 case shash::kShake128:
305 46 msg_hash->set_algorithm(cvmfs::HASH_SHAKE128);
306 46 break;
307 ✗ default:
308 ✗ PANIC(NULL);
309 }
310 3224522 msg_hash->set_digest(hash.digest, shash::kDigestSizes[hash.algorithm]);
311 3224522 }
312
313
314 12134 void CacheTransport::FillObjectType(int object_flags,
315 cvmfs::EnumObjectType *wire_type) {
316 12134 *wire_type = cvmfs::OBJECT_REGULAR;
317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12134 times.
12134 if (object_flags & CacheManager::kLabelCatalog)
318 ✗ *wire_type = cvmfs::OBJECT_CATALOG;
319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12134 times.
12134 if (object_flags & CacheManager::kLabelVolatile)
320 ✗ *wire_type = cvmfs::OBJECT_VOLATILE;
321 12134 }
322
323
324 54418 bool CacheTransport::ParseMsgHash(const cvmfs::MsgHash &msg_hash,
325 shash::Any *hash) {
326
2/4
✓ Branch 1 taken 54384 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
✗ Branch 4 not taken.
54418 switch (msg_hash.algorithm()) {
327 54384 case cvmfs::HASH_SHA1:
328 54384 hash->algorithm = shash::kSha1;
329 54384 break;
330 ✗ case cvmfs::HASH_RIPEMD160:
331 ✗ hash->algorithm = shash::kRmd160;
332 ✗ break;
333 34 case cvmfs::HASH_SHAKE128:
334 34 hash->algorithm = shash::kShake128;
335 34 break;
336 ✗ default:
337 ✗ return false;
338 }
339 54418 const unsigned digest_size = shash::kDigestSizes[hash->algorithm];
340
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 54418 times.
54418 if (msg_hash.digest().length() != digest_size)
341 ✗ return false;
342 54418 memcpy(hash->digest, msg_hash.digest().data(), digest_size);
343 54418 return true;
344 }
345
346
347 ✗ bool CacheTransport::ParseObjectType(cvmfs::EnumObjectType wire_type,
348 int *object_flags) {
349 ✗ *object_flags = 0;
350 ✗ switch (wire_type) {
351 ✗ case cvmfs::OBJECT_REGULAR:
352 ✗ return true;
353 ✗ case cvmfs::OBJECT_CATALOG:
354 ✗ *object_flags |= CacheManager::kLabelCatalog;
355 ✗ return true;
356 ✗ case cvmfs::OBJECT_VOLATILE:
357 ✗ *object_flags |= CacheManager::kLabelVolatile;
358 ✗ return true;
359 ✗ default:
360 ✗ return false;
361 }
362 }
363
364
365 132093 bool CacheTransport::RecvFrame(CacheTransport::Frame *frame) {
366 uint32_t size;
367 bool has_attachment;
368
1/2
✓ Branch 1 taken 132093 times.
✗ Branch 2 not taken.
132093 bool retval = RecvHeader(&size, &has_attachment);
369
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 132077 times.
132093 if (!retval)
370 16 return false;
371
372 void *buffer;
373
2/2
✓ Branch 0 taken 86554 times.
✓ Branch 1 taken 45523 times.
132077 if (size <= kMaxStackAlloc)
374 86554 buffer = alloca(size);
375 else
376 45523 buffer = smalloc(size);
377
1/2
✓ Branch 1 taken 132077 times.
✗ Branch 2 not taken.
132077 const ssize_t nbytes = SafeRead(fd_connection_, buffer, size);
378
2/4
✓ Branch 0 taken 132077 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 132077 times.
132077 if ((nbytes < 0) || (static_cast<uint32_t>(nbytes) != size)) {
379 ✗ if (size > kMaxStackAlloc) {
380 ✗ free(buffer);
381 }
382 ✗ return false;
383 }
384
385 132077 uint32_t msg_size = size;
386
2/2
✓ Branch 0 taken 45777 times.
✓ Branch 1 taken 86300 times.
132077 if (has_attachment) {
387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45777 times.
45777 if (size < 2) {
388 // kMaxStackAlloc is > 2 (of course!) but we'll leave the condition here
389 // for consistency.
390 ✗ if (size > kMaxStackAlloc) {
391 ✗ free(buffer);
392 }
393 ✗ return false;
394 }
395 45777 msg_size = (*reinterpret_cast<unsigned char *>(buffer))
396 45777 + ((*(reinterpret_cast<unsigned char *>(buffer) + 1)) << 8);
397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45777 times.
45777 if ((msg_size + kInnerHeaderSize) > size) {
398 ✗ if (size > kMaxStackAlloc) {
399 ✗ free(buffer);
400 }
401 ✗ return false;
402 }
403 }
404
405 132077 void *ptr_msg = has_attachment
406
2/2
✓ Branch 0 taken 45777 times.
✓ Branch 1 taken 86300 times.
132077 ? (reinterpret_cast<char *>(buffer) + kInnerHeaderSize)
407 : buffer;
408
1/2
✓ Branch 1 taken 132077 times.
✗ Branch 2 not taken.
132077 retval = frame->ParseMsgRpc(ptr_msg, msg_size);
409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132077 times.
132077 if (!retval) {
410 ✗ if (size > kMaxStackAlloc) {
411 ✗ free(buffer);
412 }
413 ✗ return false;
414 }
415
416
2/2
✓ Branch 0 taken 45777 times.
✓ Branch 1 taken 86300 times.
132077 if (has_attachment) {
417 45777 const uint32_t attachment_size = size - (msg_size + kInnerHeaderSize);
418
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 45777 times.
45777 if (frame->att_size() < attachment_size) {
419 ✗ if (size > kMaxStackAlloc) {
420 ✗ free(buffer);
421 }
422 ✗ return false;
423 }
424 45777 void *ptr_attachment = reinterpret_cast<char *>(buffer) + kInnerHeaderSize
425 45777 + msg_size;
426 45777 memcpy(frame->attachment(), ptr_attachment, attachment_size);
427 45777 frame->set_att_size(attachment_size);
428 } else {
429 86300 frame->set_att_size(0);
430 }
431
2/2
✓ Branch 0 taken 45523 times.
✓ Branch 1 taken 86538 times.
132061 if (size > kMaxStackAlloc) {
432 45523 free(buffer);
433 }
434 132061 return true;
435 }
436
437
438 132093 bool CacheTransport::RecvHeader(uint32_t *size, bool *has_attachment) {
439 unsigned char header[kHeaderSize];
440
1/2
✓ Branch 1 taken 132093 times.
✗ Branch 2 not taken.
132093 const ssize_t nbytes = SafeRead(fd_connection_, header, kHeaderSize);
441
3/4
✓ Branch 0 taken 132093 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 132077 times.
132093 if ((nbytes < 0) || (static_cast<unsigned>(nbytes) != kHeaderSize))
442 16 return false;
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132077 times.
132077 if ((header[0] & (~kFlagHasAttachment)) != kWireProtocolVersion)
444 ✗ return false;
445 132077 *has_attachment = header[0] & kFlagHasAttachment;
446 132077 *size = header[1] + (header[2] << 8) + (header[3] << 16);
447
2/4
✓ Branch 0 taken 132077 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132077 times.
✗ Branch 3 not taken.
132077 return (*size > 0) && (*size <= kMaxMsgSize);
448 }
449
450
451 132101 void CacheTransport::SendData(void *message,
452 uint32_t msg_size,
453 void *attachment,
454 uint32_t att_size) {
455 264202 const uint32_t total_size = msg_size + att_size
456
2/2
✓ Branch 0 taken 47484 times.
✓ Branch 1 taken 84617 times.
132101 + ((att_size > 0) ? kInnerHeaderSize : 0);
457
458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132101 times.
132101 assert(total_size > 0);
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132101 times.
132101 assert(total_size <= kMaxMsgSize);
460
1/2
✓ Branch 1 taken 126368 times.
✗ Branch 2 not taken.
126352 LogCvmfs(kLogCache, kLogDebug,
461 "sending message of size %u to cache transport", total_size);
462
463 unsigned char header[kHeaderSize];
464
2/2
✓ Branch 0 taken 84633 times.
✓ Branch 1 taken 47484 times.
132117 header[0] = kWireProtocolVersion | ((att_size == 0) ? 0 : kFlagHasAttachment);
465 132117 header[1] = (total_size & 0x000000FF);
466 132117 header[2] = (total_size & 0x0000FF00) >> 8;
467 132117 header[3] = (total_size & 0x00FF0000) >> 16;
468 // Only transferred if an attachment is present. Otherwise the overall size
469 // is also the size of the protobuf message.
470 unsigned char inner_header[kInnerHeaderSize];
471
472 struct iovec iov[4];
473 132117 iov[0].iov_base = header;
474 132117 iov[0].iov_len = kHeaderSize;
475
476
2/2
✓ Branch 0 taken 47484 times.
✓ Branch 1 taken 84633 times.
132117 if (att_size > 0) {
477 47484 inner_header[0] = (msg_size & 0x000000FF);
478 47484 inner_header[1] = (msg_size & 0x0000FF00) >> 8;
479 47484 iov[1].iov_base = inner_header;
480 47484 iov[1].iov_len = kInnerHeaderSize;
481 47484 iov[2].iov_base = message;
482 47484 iov[2].iov_len = msg_size;
483 47484 iov[3].iov_base = attachment;
484 47484 iov[3].iov_len = att_size;
485 } else {
486 84633 iov[1].iov_base = message;
487 84633 iov[1].iov_len = msg_size;
488 }
489
2/2
✓ Branch 0 taken 16032 times.
✓ Branch 1 taken 116085 times.
132117 if (flags_ & kFlagSendNonBlocking) {
490
2/4
✓ Branch 0 taken 16032 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 16032 times.
✗ Branch 4 not taken.
16032 SendNonBlocking(iov, (att_size == 0) ? 2 : 4);
491 16032 return;
492 }
493
3/4
✓ Branch 0 taken 68601 times.
✓ Branch 1 taken 47484 times.
✓ Branch 3 taken 116037 times.
✗ Branch 4 not taken.
116085 const bool retval = SafeWriteV(fd_connection_, iov, (att_size == 0) ? 2 : 4);
494
495
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 116037 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
116037 if (!retval && !(flags_ & kFlagSendIgnoreFailure)) {
496 ✗ PANIC(kLogSyslogErr | kLogDebug,
497 "failed to write to external cache transport (%d), aborting", errno);
498 }
499 }
500
501 16032 void CacheTransport::SendNonBlocking(struct iovec *iov, unsigned iovcnt) {
502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16032 times.
16032 assert(iovcnt > 0);
503 16032 unsigned total_size = 0;
504
2/2
✓ Branch 0 taken 32064 times.
✓ Branch 1 taken 16032 times.
48096 for (unsigned i = 0; i < iovcnt; ++i)
505 32064 total_size += iov[i].iov_len;
506 16032 unsigned char *buffer = reinterpret_cast<unsigned char *>(alloca(total_size));
507
508 16032 unsigned pos = 0;
509
2/2
✓ Branch 0 taken 32064 times.
✓ Branch 1 taken 16032 times.
48096 for (unsigned i = 0; i < iovcnt; ++i) {
510 32064 memcpy(buffer + pos, iov[i].iov_base, iov[i].iov_len);
511 32064 pos += iov[i].iov_len;
512 }
513
514 16032 const int retval = send(fd_connection_, buffer, total_size, MSG_DONTWAIT);
515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16032 times.
16032 if (retval < 0) {
516 ✗ assert(errno != EMSGSIZE);
517 ✗ if (!(flags_ & kFlagSendIgnoreFailure)) {
518 ✗ PANIC(kLogSyslogErr | kLogDebug,
519 "failed to write to external cache transport (%d), aborting",
520 errno);
521 }
522 }
523 16032 }
524
525
526 132117 void CacheTransport::SendFrame(CacheTransport::Frame *frame) {
527 132117 cvmfs::MsgRpc *msg_rpc = frame->GetMsgRpc();
528 132117 const size_t byte_size = msg_rpc->ByteSizeLong();
529
2/4
✓ Branch 0 taken 132101 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132101 times.
✗ Branch 3 not taken.
132101 assert((byte_size > 0) && (byte_size <= kMaxMsgSize));
530 132101 const uint32_t size = static_cast<uint32_t>(byte_size);
531 #ifdef __APPLE__
532 void *buffer = smalloc(size);
533 #else
534 132101 void *buffer = alloca(size);
535 #endif
536 132101 const bool retval = msg_rpc->SerializeToArray(buffer, size);
537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132101 times.
132101 assert(retval);
538 132101 SendData(buffer, size, frame->attachment(), frame->att_size());
539 #ifdef __APPLE__
540 free(buffer);
541 #endif
542 132069 }
543