File indexing completed on 2024-04-28 16:59:46
0001 /* 0002 Copyright (C) 2013 Andreas Hartmetz <ahartmetz@gmail.com> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LGPL. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 0019 Alternatively, this file is available under the Mozilla Public License 0020 Version 1.1. You may obtain a copy of the License at 0021 http://www.mozilla.org/MPL/ 0022 */ 0023 0024 #include "message.h" 0025 #include "message_p.h" 0026 0027 #include "arguments_p.h" 0028 #include "basictypeio.h" 0029 #include "malloccache.h" 0030 #include "stringtools.h" 0031 0032 #ifndef DFERRY_SERDES_ONLY 0033 #include "icompletionlistener.h" 0034 #include "itransport.h" 0035 #endif 0036 0037 #include <cassert> 0038 #include <cstring> 0039 #include <sstream> 0040 #include <thread> 0041 0042 #include <iostream> 0043 0044 #ifdef __unix__ 0045 #include <unistd.h> 0046 #endif 0047 0048 #ifdef BIGENDIAN 0049 static const byte s_thisMachineEndianness = 'B'; 0050 #else 0051 static const byte s_thisMachineEndianness = 'l'; 0052 #endif 0053 0054 struct MsgAllocCaches 0055 { 0056 MallocCache<sizeof(MessagePrivate), 4> msgPrivate; 0057 MallocCache<256, 4> msgBuffer; 0058 }; 0059 0060 thread_local static MsgAllocCaches msgAllocCaches; 0061 0062 static const byte s_storageForHeader[Message::UnixFdsHeader + 1] = { 0063 0, // dummy entry: there is no enum value for 0 0064 0x80 | 0, // PathHeader 0065 0x80 | 1, // InterfaceHeader 0066 0x80 | 2, // MethodHeader 0067 0x80 | 3, // ErrorNameHeader 0068 0 | 0, // ReplySerialHeader 0069 0x80 | 4, // DestinationHeader 0070 0x80 | 5, // SenderHeader 0071 0x80 | 6, // SignatureHeader 0072 0 | 1 // UnixFdsHeader 0073 }; 0074 0075 static bool isStringHeader(int field) 0076 { 0077 return s_storageForHeader[field] & 0x80; 0078 } 0079 0080 static int indexOfHeader(int field) 0081 { 0082 return s_storageForHeader[field] & 0x7f; 0083 } 0084 0085 static const Message::VariableHeader s_stringHeaderAtIndex[VarHeaderStorage::s_stringHeaderCount] = { 0086 Message::PathHeader, 0087 Message::InterfaceHeader, 0088 Message::MethodHeader, 0089 Message::ErrorNameHeader, 0090 Message::DestinationHeader, 0091 Message::SenderHeader, 0092 Message::SignatureHeader 0093 }; 0094 0095 static const Message::VariableHeader s_intHeaderAtIndex[VarHeaderStorage::s_intHeaderCount] = { 0096 Message::ReplySerialHeader, 0097 Message::UnixFdsHeader 0098 }; 0099 0100 VarHeaderStorage::VarHeaderStorage() 0101 {} // initialization values are in class declaration 0102 0103 VarHeaderStorage::VarHeaderStorage(const VarHeaderStorage &other) 0104 { 0105 // ### very suboptimal 0106 for (int i = 0; i < Message::UnixFdsHeader + 1; i++) { 0107 Message::VariableHeader vh = static_cast<Message::VariableHeader>(i); 0108 if (other.hasHeader(vh)) { 0109 if (isStringHeader(vh)) { 0110 setStringHeader(vh, other.stringHeader(vh)); 0111 } else { 0112 setIntHeader(vh, other.intHeader(vh)); 0113 } 0114 } 0115 } 0116 } 0117 0118 VarHeaderStorage::~VarHeaderStorage() 0119 { 0120 for (int i = 0; i < s_stringHeaderCount; i++) { 0121 const Message::VariableHeader field = s_stringHeaderAtIndex[i]; 0122 if (hasHeader(field)) { 0123 // ~basic_string() instead of ~string() to work around a GCC bug 0124 stringHeaders()[i].~basic_string(); 0125 } 0126 } 0127 } 0128 0129 VarHeaderStorage &VarHeaderStorage::operator=(const VarHeaderStorage &other) 0130 { 0131 // ### very suboptimal 0132 for (int i = 0; i < Message::UnixFdsHeader + 1; i++) { 0133 Message::VariableHeader vh = static_cast<Message::VariableHeader>(i); 0134 if (other.hasHeader(vh)) { 0135 if (isStringHeader(vh)) { 0136 setStringHeader(vh, other.stringHeader(vh)); 0137 } else { 0138 setIntHeader(vh, other.intHeader(vh)); 0139 } 0140 } else { 0141 if (isStringHeader(vh)) { 0142 clearStringHeader(vh); 0143 } else { 0144 clearIntHeader(vh); 0145 } 0146 } 0147 } 0148 return *this; 0149 } 0150 0151 bool VarHeaderStorage::hasHeader(Message::VariableHeader header) const 0152 { 0153 return m_headerPresenceBitmap & (1u << header); 0154 } 0155 0156 bool VarHeaderStorage::hasStringHeader(Message::VariableHeader header) const 0157 { 0158 return hasHeader(header) && isStringHeader(header); 0159 } 0160 0161 bool VarHeaderStorage::hasIntHeader(Message::VariableHeader header) const 0162 { 0163 return hasHeader(header) && !isStringHeader(header); 0164 } 0165 0166 std::string VarHeaderStorage::stringHeader(Message::VariableHeader header) const 0167 { 0168 return hasStringHeader(header) ? stringHeaders()[indexOfHeader(header)] : std::string(); 0169 } 0170 0171 cstring VarHeaderStorage::stringHeaderRaw(Message::VariableHeader header) 0172 { 0173 // this one is supposed to be a const method in the intended use, but it is dangerous so 0174 // outwardly non-const is kind of okay as a warning 0175 cstring ret; 0176 assert(isStringHeader(header)); 0177 if (hasHeader(header)) { 0178 std::string &str = stringHeaders()[indexOfHeader(header)]; 0179 ret.ptr = const_cast<char *>(str.c_str()); 0180 ret.length = str.length(); 0181 } 0182 return ret; 0183 } 0184 0185 void VarHeaderStorage::setStringHeader(Message::VariableHeader header, const std::string &value) 0186 { 0187 if (!isStringHeader(header)) { 0188 return; 0189 } 0190 const int idx = indexOfHeader(header); 0191 if (hasHeader(header)) { 0192 stringHeaders()[idx] = value; 0193 } else { 0194 m_headerPresenceBitmap |= 1u << header; 0195 new(stringHeaders() + idx) std::string(value); 0196 } 0197 } 0198 0199 bool VarHeaderStorage::setStringHeader_deser(Message::VariableHeader header, cstring value) 0200 { 0201 assert(isStringHeader(header)); 0202 if (hasHeader(header)) { 0203 return false; 0204 } 0205 m_headerPresenceBitmap |= 1u << header; 0206 new(stringHeaders() + indexOfHeader(header)) std::string(value.ptr, value.length); 0207 return true; 0208 } 0209 0210 void VarHeaderStorage::clearStringHeader(Message::VariableHeader header) 0211 { 0212 if (!isStringHeader(header)) { 0213 return; 0214 } 0215 if (hasHeader(header)) { 0216 m_headerPresenceBitmap &= ~(1u << header); 0217 stringHeaders()[indexOfHeader(header)].~basic_string(); 0218 } 0219 } 0220 0221 uint32 VarHeaderStorage::intHeader(Message::VariableHeader header) const 0222 { 0223 return hasIntHeader(header) ? m_intHeaders[indexOfHeader(header)] : 0; 0224 } 0225 0226 void VarHeaderStorage::setIntHeader(Message::VariableHeader header, uint32 value) 0227 { 0228 if (isStringHeader(header)) { 0229 return; 0230 } 0231 m_headerPresenceBitmap |= 1u << header; 0232 m_intHeaders[indexOfHeader(header)] = value; 0233 } 0234 0235 bool VarHeaderStorage::setIntHeader_deser(Message::VariableHeader header, uint32 value) 0236 { 0237 assert(!isStringHeader(header)); 0238 if (hasHeader(header)) { 0239 return false; 0240 } 0241 m_headerPresenceBitmap |= 1u << header; 0242 m_intHeaders[indexOfHeader(header)] = value; 0243 return true; 0244 } 0245 0246 void VarHeaderStorage::clearIntHeader(Message::VariableHeader header) 0247 { 0248 if (isStringHeader(header)) { 0249 return; 0250 } 0251 m_headerPresenceBitmap &= ~(1u << header); 0252 } 0253 0254 // TODO think of copying signature from and to output! 0255 0256 MessagePrivate::MessagePrivate(Message *parent) 0257 : m_message(parent), 0258 m_bufferPos(0), 0259 m_isByteSwapped(false), 0260 m_state(Empty), 0261 m_messageType(Message::InvalidMessage), 0262 m_flags(0), 0263 m_protocolVersion(1), 0264 m_dirty(true), 0265 m_headerLength(0), 0266 m_headerPadding(0), 0267 m_bodyLength(0), 0268 m_serial(0) 0269 {} 0270 0271 MessagePrivate::MessagePrivate(const MessagePrivate &other, Message *parent) 0272 : m_message(parent), 0273 m_bufferPos(other.m_bufferPos), 0274 m_isByteSwapped(other.m_isByteSwapped), 0275 m_state(other.m_state), 0276 m_messageType(other.m_messageType), 0277 m_flags(other.m_flags), 0278 m_protocolVersion(other.m_protocolVersion), 0279 m_dirty(other.m_dirty), 0280 m_headerLength(other.m_headerLength), 0281 m_headerPadding(other.m_headerPadding), 0282 m_bodyLength(other.m_bodyLength), 0283 m_serial(other.m_serial), 0284 m_error(other.m_error), 0285 m_mainArguments(other.m_mainArguments), 0286 m_varHeaders(other.m_varHeaders) 0287 { 0288 if (other.m_buffer.ptr) { 0289 // we don't keep pointers into the buffer (only indexes), right? right? 0290 m_buffer.ptr = static_cast<byte *>(malloc(other.m_buffer.length)); 0291 m_buffer.length = other.m_buffer.length; 0292 // Simplification: don't try to figure out which part of other.m_buffer contains "valid" data, 0293 // just copy everything. 0294 memcpy(m_buffer.ptr, other.m_buffer.ptr, other.m_buffer.length); 0295 #ifdef __unix__ 0296 // TODO ensure all "actual" file descriptor handling everywhere is inside this ifdef 0297 // (note conditional compilation of whole file localsocket.cpp) 0298 argUnixFds()->clear(); 0299 std::vector<int> *otherUnixFds = const_cast<MessagePrivate &>(other).argUnixFds(); 0300 argUnixFds()->reserve(otherUnixFds->size()); 0301 for (int fd : *otherUnixFds) { 0302 int fdCopy = ::dup(fd); 0303 if (fdCopy == -1) { 0304 // TODO error... 0305 } 0306 argUnixFds()->push_back(fdCopy); 0307 } 0308 #endif 0309 } else { 0310 assert(!m_buffer.length); 0311 } 0312 // ### Maybe warn when copying a Message which is currently (de)serializing. It might even be impossible 0313 // to do that from client code. If that is the case, the "warning" could even be an assertion because 0314 // we should never do such a thing. 0315 } 0316 0317 MessagePrivate::~MessagePrivate() 0318 { 0319 clear(/* onlyReleaseResources = */ true); 0320 } 0321 0322 Message::Message() 0323 : d(new(msgAllocCaches.msgPrivate.allocate()) MessagePrivate(this)) 0324 { 0325 } 0326 0327 Message::Message(Message &&other) 0328 : d(other.d) 0329 { 0330 other.d = nullptr; 0331 d->m_message = this; 0332 } 0333 0334 Message &Message::operator=(Message &&other) 0335 { 0336 if (this != &other) { 0337 if (d) { 0338 d->~MessagePrivate(); 0339 msgAllocCaches.msgPrivate.free(d); 0340 } 0341 d = other.d; 0342 if (other.d) { 0343 other.d = nullptr; 0344 d->m_message = this; 0345 } 0346 } 0347 return *this; 0348 } 0349 0350 Message::Message(const Message &other) 0351 : d(nullptr) 0352 { 0353 if (!other.d) { 0354 return; 0355 } 0356 d = new(msgAllocCaches.msgPrivate.allocate()) MessagePrivate(*other.d, this); 0357 } 0358 0359 Message &Message::operator=(const Message &other) 0360 { 0361 if (this != &other) { 0362 if (d) { 0363 d->~MessagePrivate(); 0364 msgAllocCaches.msgPrivate.free(d); 0365 } 0366 if (other.d) { 0367 // ### can be optimized by implementing and using assignment of MessagePrivate 0368 d = new(msgAllocCaches.msgPrivate.allocate()) MessagePrivate(*other.d, this); 0369 } else { 0370 d = nullptr; 0371 } 0372 } 0373 return *this; 0374 } 0375 0376 Message::~Message() 0377 { 0378 if (d) { 0379 d->~MessagePrivate(); 0380 msgAllocCaches.msgPrivate.free(d); 0381 d = nullptr; 0382 } 0383 } 0384 0385 Error Message::error() const 0386 { 0387 return d->m_error; 0388 } 0389 0390 void Message::setCall(const std::string &path, const std::string &interface, const std::string &method) 0391 { 0392 setType(MethodCallMessage); 0393 setPath(path); 0394 setInterface(interface); 0395 setMethod(method); 0396 } 0397 0398 void Message::setCall(const std::string &path, const std::string &method) 0399 { 0400 setType(MethodCallMessage); 0401 setPath(path); 0402 setMethod(method); 0403 } 0404 0405 void Message::setReplyTo(const Message &call) 0406 { 0407 setType(MethodReturnMessage); 0408 setDestination(call.sender()); 0409 setReplySerial(call.serial()); 0410 } 0411 0412 void Message::setErrorReplyTo(const Message &call, const std::string &errorName) 0413 { 0414 setType(ErrorMessage); 0415 setErrorName(errorName); 0416 setDestination(call.sender()); 0417 setReplySerial(call.serial()); 0418 } 0419 0420 void Message::setSignal(const std::string &path, const std::string &interface, const std::string &method) 0421 { 0422 setType(SignalMessage); 0423 setPath(path); 0424 setInterface(interface); 0425 setMethod(method); 0426 } 0427 0428 Message Message::createCall(const std::string &path, const std::string &interface, const std::string &method) 0429 { 0430 Message ret; 0431 ret.setCall(path, interface, method); 0432 return ret; 0433 } 0434 0435 Message Message::createCall(const std::string &path, const std::string &method) 0436 { 0437 Message ret; 0438 ret.setCall(path, method); 0439 return ret; 0440 } 0441 0442 Message Message::createReplyTo(const Message &call) 0443 { 0444 Message ret; 0445 ret.setReplyTo(call); 0446 return ret; 0447 } 0448 0449 Message Message::createErrorReplyTo(const Message &call, const std::string &errorName) 0450 { 0451 Message ret; 0452 ret.setErrorReplyTo(call, errorName); 0453 return ret; 0454 } 0455 0456 Message Message::createSignal(const std::string &path, const std::string &interface, const std::string &method) 0457 { 0458 Message ret; 0459 ret.setSignal(path, interface, method); 0460 return ret; 0461 } 0462 0463 struct VarHeaderPrinter 0464 { 0465 Message::VariableHeader field; 0466 const char *name; 0467 }; 0468 0469 static const int stringHeadersCount = 7; 0470 static VarHeaderPrinter stringHeaderPrinters[stringHeadersCount] = { 0471 { Message::PathHeader, "path" }, 0472 { Message::InterfaceHeader, "interface" }, 0473 { Message::MethodHeader, "method" }, 0474 { Message::ErrorNameHeader, "error name" }, 0475 { Message::DestinationHeader, "destination" }, 0476 { Message::SenderHeader, "sender" }, 0477 { Message::SignatureHeader, "signature" } 0478 }; 0479 0480 static const int intHeadersCount = 2; 0481 static VarHeaderPrinter intHeaderPrinters[intHeadersCount] = { 0482 { Message::ReplySerialHeader, "reply serial" }, 0483 { Message::UnixFdsHeader, "#unix fds" } 0484 }; 0485 0486 static const int messageTypeCount = 5; 0487 static const char *printableMessageTypes[messageTypeCount] = { 0488 "", // handled in code 0489 "Method call", 0490 "Method return", 0491 "Method error return", 0492 "Signal" 0493 }; 0494 0495 std::string Message::prettyPrint() const 0496 { 0497 std::string ret; 0498 if (d->m_messageType >= 1 && d->m_messageType < messageTypeCount) { 0499 ret += printableMessageTypes[d->m_messageType]; 0500 } else { 0501 return std::string("Invalid message.\n"); 0502 } 0503 0504 std::ostringstream os; 0505 for (int i = 0; i < stringHeadersCount; i++ ) { 0506 bool isPresent = false; 0507 std::string str = stringHeader(stringHeaderPrinters[i].field, &isPresent); 0508 if (isPresent) { 0509 os << "; " << stringHeaderPrinters[i].name << ": \"" << str << '"'; 0510 0511 } 0512 } 0513 for (int i = 0; i < intHeadersCount; i++ ) { 0514 bool isPresent = false; 0515 uint32 intValue = intHeader(intHeaderPrinters[i].field, &isPresent); 0516 if (isPresent) { 0517 os << "; " << intHeaderPrinters[i].name << ": " << intValue; 0518 } 0519 } 0520 ret += os.str(); 0521 0522 ret += '\n'; 0523 ret += d->m_mainArguments.prettyPrint(); 0524 return ret; 0525 } 0526 0527 Message::Type Message::type() const 0528 { 0529 return d->m_messageType; 0530 } 0531 0532 void Message::setType(Type type) 0533 { 0534 if (d->m_messageType == type) { 0535 return; 0536 } 0537 d->m_dirty = true; 0538 d->m_messageType = type; 0539 setExpectsReply(d->m_messageType == MethodCallMessage); 0540 } 0541 0542 uint32 Message::protocolVersion() const 0543 { 0544 return d->m_protocolVersion; 0545 } 0546 0547 void Message::setSerial(uint32 serial) 0548 { 0549 d->m_serial = serial; 0550 if (d->m_state == MessagePrivate::Serialized && !d->m_dirty) { 0551 // performance hack: setSerial is likely to happen just before sending - don't re-serialize, 0552 // just patch it. 0553 byte *p = d->m_buffer.ptr; 0554 basic::writeUint32(p + 4 /* bytes */ + sizeof(uint32), d->m_serial); 0555 return; 0556 } 0557 d->m_dirty = true; 0558 } 0559 0560 uint32 Message::serial() const 0561 { 0562 return d->m_serial; 0563 } 0564 0565 std::string Message::path() const 0566 { 0567 return stringHeader(PathHeader, nullptr); 0568 } 0569 0570 void Message::setPath(const std::string &path) 0571 { 0572 setStringHeader(PathHeader, path); 0573 } 0574 0575 std::string Message::interface() const 0576 { 0577 return stringHeader(InterfaceHeader, nullptr); 0578 } 0579 0580 void Message::setInterface(const std::string &interface) 0581 { 0582 setStringHeader(InterfaceHeader, interface); 0583 } 0584 0585 std::string Message::method() const 0586 { 0587 return stringHeader(MethodHeader, nullptr); 0588 } 0589 0590 void Message::setMethod(const std::string &method) 0591 { 0592 setStringHeader(MethodHeader, method); 0593 } 0594 0595 std::string Message::errorName() const 0596 { 0597 return stringHeader(ErrorNameHeader, nullptr); 0598 } 0599 0600 void Message::setErrorName(const std::string &errorName) 0601 { 0602 setStringHeader(ErrorNameHeader, errorName); 0603 } 0604 0605 uint32 Message::replySerial() const 0606 { 0607 return intHeader(ReplySerialHeader, nullptr); 0608 } 0609 0610 void Message::setReplySerial(uint32 replySerial) 0611 { 0612 setIntHeader(ReplySerialHeader, replySerial); 0613 } 0614 0615 std::string Message::destination() const 0616 { 0617 return stringHeader(DestinationHeader, nullptr); 0618 } 0619 0620 void Message::setDestination(const std::string &destination) 0621 { 0622 setStringHeader(DestinationHeader, destination); 0623 } 0624 0625 std::string Message::sender() const 0626 { 0627 return stringHeader(SenderHeader, nullptr); 0628 } 0629 0630 void Message::setSender(const std::string &sender) 0631 { 0632 setStringHeader(SenderHeader, sender); 0633 } 0634 0635 std::string Message::signature() const 0636 { 0637 return stringHeader(SignatureHeader, nullptr); 0638 } 0639 0640 uint32 Message::unixFdCount() const 0641 { 0642 return intHeader(UnixFdsHeader, nullptr); 0643 } 0644 0645 std::string Message::stringHeader(VariableHeader header, bool *isPresent) const 0646 { 0647 const bool exists = d->m_varHeaders.hasStringHeader(header); 0648 if (isPresent) { 0649 *isPresent = exists; 0650 } 0651 return exists ? d->m_varHeaders.stringHeader(header) : std::string(); 0652 } 0653 0654 void Message::setStringHeader(VariableHeader header, const std::string &value) 0655 { 0656 if (header == SignatureHeader) { 0657 // ### warning? - this is a public method, and setting the signature separately does not make sense 0658 return; 0659 } 0660 d->m_dirty = true; 0661 d->m_varHeaders.setStringHeader(header, value); 0662 } 0663 0664 uint32 Message::intHeader(VariableHeader header, bool *isPresent) const 0665 { 0666 const bool exists = d->m_varHeaders.hasIntHeader(header); 0667 if (isPresent) { 0668 *isPresent = exists; 0669 } 0670 return d->m_varHeaders.intHeader(header); 0671 } 0672 0673 void Message::setIntHeader(VariableHeader header, uint32 value) 0674 { 0675 d->m_dirty = true; 0676 d->m_varHeaders.setIntHeader(header, value); 0677 } 0678 0679 bool Message::expectsReply() const 0680 { 0681 return (d->m_flags & MessagePrivate::NoReplyExpectedFlag) == 0; 0682 } 0683 0684 void Message::setExpectsReply(bool expectsReply) 0685 { 0686 if (expectsReply) { 0687 d->m_flags &= ~MessagePrivate::NoReplyExpectedFlag; 0688 } else { 0689 d->m_flags |= MessagePrivate::NoReplyExpectedFlag; 0690 } 0691 } 0692 0693 bool Message::autoStartService() const 0694 { 0695 return (d->m_flags & MessagePrivate::NoAutoStartServiceFlag) == 0; 0696 } 0697 0698 void Message::setAutoStartService(bool autoStart) const 0699 { 0700 if (autoStart) { 0701 d->m_flags &= ~MessagePrivate::NoAutoStartServiceFlag; 0702 } else { 0703 d->m_flags |= MessagePrivate::NoAutoStartServiceFlag; 0704 } 0705 } 0706 0707 bool Message::interactiveAuthorizationAllowed() const 0708 { 0709 return (d->m_flags & MessagePrivate::NoAllowInteractiveAuthorizationFlag) == 0; 0710 } 0711 0712 void Message::setInteractiveAuthorizationAllowed(bool allowInteractive) const 0713 { 0714 if (allowInteractive) { 0715 d->m_flags &= ~MessagePrivate::NoAllowInteractiveAuthorizationFlag; 0716 } else { 0717 d->m_flags |= MessagePrivate::NoAllowInteractiveAuthorizationFlag; 0718 } 0719 } 0720 0721 void Message::setArguments(Arguments arguments) 0722 { 0723 d->m_dirty = true; 0724 d->m_error = arguments.error(); 0725 const size_t fdCount = arguments.fileDescriptors().size(); 0726 if (fdCount) { 0727 d->m_varHeaders.setIntHeader(Message::UnixFdsHeader, fdCount); 0728 } else { 0729 d->m_varHeaders.clearIntHeader(Message::UnixFdsHeader); 0730 } 0731 0732 cstring signature = arguments.signature(); 0733 if (signature.length) { 0734 d->m_varHeaders.setStringHeader(Message::SignatureHeader, toStdString(signature)); 0735 } else { 0736 d->m_varHeaders.clearStringHeader(Message::SignatureHeader); 0737 } 0738 d->m_mainArguments = std::move(arguments); 0739 } 0740 0741 const Arguments &Message::arguments() const 0742 { 0743 return d->m_mainArguments; 0744 } 0745 0746 static const uint32 s_properFixedHeaderLength = 12; 0747 static const uint32 s_extendedFixedHeaderLength = 16; 0748 0749 #ifndef DFERRY_SERDES_ONLY 0750 void MessagePrivate::receive(ITransport *transport) 0751 { 0752 if (m_state >= FirstIoState) { // Can only do one I/O operation at a time 0753 return; 0754 } 0755 transport->setReadListener(this); 0756 m_state = MessagePrivate::Receiving; 0757 m_headerLength = 0; 0758 m_bodyLength = 0; 0759 } 0760 0761 bool Message::isReceiving() const 0762 { 0763 return d->m_state == MessagePrivate::Receiving; 0764 } 0765 0766 void MessagePrivate::send(ITransport *transport) 0767 { 0768 if (!serialize()) { 0769 m_state = Serialized; 0770 assert(m_error.isError()); 0771 if (!m_error.isError()) { 0772 // TODO This error code makes no sense here. We don't have a "generic error" code, and a specific 0773 // error code should have been set by whatever code detected the error. Hence the assertion. 0774 m_error = Error::MalformedReply; 0775 } 0776 // Note: We don't call notifyCompletionListener(); since all our timers are internal, we can 0777 // expect them to check for errors after this returns. Specifically, Connection::send() has 0778 // access to the timer in the PendingReply, so it can produce a deferred error notification 0779 // just like success notifications are deferred. 0780 return; 0781 } 0782 if (m_state != MessagePrivate::Sending) { 0783 transport->setWriteListener(this); 0784 m_state = MessagePrivate::Sending; 0785 } 0786 } 0787 0788 bool Message::isSending() const 0789 { 0790 return d->m_state == MessagePrivate::Sending; 0791 } 0792 0793 void MessagePrivate::setCompletionListener(ICompletionListener *listener) 0794 { 0795 m_completionListener = listener; 0796 } 0797 0798 void MessagePrivate::notifyCompletionListener() 0799 { 0800 if (m_completionListener) { 0801 m_completionListener->handleCompletion(m_message); 0802 } 0803 } 0804 0805 IO::Status MessagePrivate::handleTransportCanRead() 0806 { 0807 if (m_state != Receiving) { 0808 return IO::Status::InternalError; 0809 } 0810 IO::Status ret = IO::Status::OK; 0811 IO::Result ioRes; 0812 do { 0813 uint32 readMax = 0; 0814 if (!m_headerLength) { 0815 // the message might only consist of the header, so we must be careful to avoid reading 0816 // data meant for the next message 0817 readMax = s_extendedFixedHeaderLength - m_bufferPos; 0818 } else { 0819 // reading variable headers and/or body 0820 readMax = m_headerLength + m_bodyLength - m_bufferPos; 0821 } 0822 reserveBuffer(m_bufferPos + readMax); 0823 0824 const bool headersDone = m_headerLength > 0 && m_bufferPos >= m_headerLength; 0825 0826 if (m_bufferPos == 0) { 0827 // According to the DBus spec, file descriptors can arrive anywhere in the message, but 0828 // (assuming the message is written in one sendmsg() call) according to UNIX domain socket 0829 // documentation, file descriptors will arrive in the first byte of the sent block they are 0830 // attached to. We go with the UNIX domain socket documentation. 0831 // TODO review and test this for very large messages that cannot be sent in one call 0832 ioRes = readTransport()->readWithFileDescriptors(m_buffer.ptr + m_bufferPos, readMax, 0833 argUnixFds()); 0834 } else { 0835 ioRes = readTransport()->read(m_buffer.ptr + m_bufferPos, readMax); 0836 } 0837 m_bufferPos += ioRes.length; 0838 assert(m_bufferPos <= m_buffer.length); 0839 0840 if (!headersDone) { 0841 if (m_headerLength == 0 && m_bufferPos >= s_extendedFixedHeaderLength) { 0842 if (!deserializeFixedHeaders()) { 0843 ret = IO::Status::RemoteClosed; 0844 m_error = Error::MalformedReply; 0845 break; 0846 } 0847 } 0848 if (m_headerLength > 0 && m_bufferPos >= m_headerLength) { 0849 // ### If we expected to receive the FDs at any point in the message (as opposed to just the 0850 // first byte), we'd have to verify FD count later. But we don't, so this is expedient. 0851 if (!deserializeVariableHeaders() || 0852 m_varHeaders.intHeader(Message::UnixFdsHeader) != argUnixFds()->size()) { 0853 ret = IO::Status::RemoteClosed; 0854 m_error = Error::MalformedReply; 0855 break; 0856 } 0857 } 0858 } 0859 if (m_headerLength > 0 && m_bufferPos >= m_headerLength + m_bodyLength) { 0860 // all done! 0861 assert(m_bufferPos == m_headerLength + m_bodyLength); 0862 m_state = Serialized; 0863 chunk bodyData(m_buffer.ptr + m_headerLength, m_bodyLength); 0864 m_mainArguments = Arguments(nullptr, m_varHeaders.stringHeaderRaw(Message::SignatureHeader), 0865 bodyData, std::move(*argUnixFds()), m_isByteSwapped); 0866 assert(ioRes.status == IO::Status::OK && ret == IO::Status::OK); 0867 readTransport()->setReadListener(nullptr); 0868 notifyCompletionListener(); // do not access members after this because it might delete us! 0869 break; 0870 } 0871 if (!readTransport()->isOpen()) { 0872 ret = IO::Status::RemoteClosed; 0873 break; 0874 } 0875 } while (ioRes.status == IO::Status::OK); 0876 0877 if (ret != IO::Status::OK) { 0878 clear(); 0879 readTransport()->setReadListener(nullptr); 0880 if (!m_error.isError()) { 0881 // catch-all, we know that SOME error happened 0882 m_error = Error::RemoteDisconnect; 0883 } 0884 notifyCompletionListener(); 0885 } 0886 return ret; 0887 } 0888 0889 IO::Status MessagePrivate::handleTransportCanWrite() 0890 { 0891 if (m_state != Sending) { 0892 return IO::Status::InternalError; 0893 } 0894 while (true) { 0895 assert(m_buffer.length >= m_bufferPos); 0896 const uint32 toWrite = m_buffer.length - m_bufferPos; 0897 if (!toWrite) { 0898 m_state = Serialized; 0899 writeTransport()->setWriteListener(nullptr); 0900 notifyCompletionListener(); 0901 break; 0902 } 0903 IO::Result ioRes; 0904 if (m_bufferPos == 0) { 0905 const size_t sendFdsCount = m_mainArguments.fileDescriptors().size(); 0906 if (sendFdsCount == 0) { 0907 ioRes = writeTransport()->write(chunk(m_buffer.ptr + m_bufferPos, toWrite)); 0908 } else if (sendFdsCount > writeTransport()->supportedPassingUnixFdsCount()) { 0909 m_error.setCode(Error::SendingTooManyUnixFds); 0910 m_state = Serialized; 0911 writeTransport()->setWriteListener(nullptr); 0912 // ### Oh well, now we have a special Error value to pass through the stack 0913 // (for error handling), but also notifyCompletionListener() for sucessful completion 0914 // handling. Can we get rid of one or the other, or are there actually good reasons for 0915 // the difference? 0916 // Pro separation: 0917 // - the arguments I came up with for not doing error handling through callbacks 0918 // - the ...convenience?... of using callbacks 0919 // - possibly better performance of happy path 0920 // 0921 // Contra separation: 0922 // - two different mechanisms for similar things... 0923 // - inconsistency - though is that really a problem? the situations are different. 0924 // - suddenly IO code needs to ~know (at least pass through and be technically exposed to) 0925 // error values it doesn't know and can't handle itself; theoretically could use some 0926 // error value wrapping mechanism to pass through opaque errors). 0927 return IO::Status::PayloadError; // the connection is fine, only this message has a problem 0928 } else { 0929 ioRes = writeTransport() 0930 ->writeWithFileDescriptors(chunk(m_buffer.ptr + m_bufferPos, toWrite), 0931 m_mainArguments.fileDescriptors()); 0932 } 0933 } else { 0934 ioRes = writeTransport()->write(chunk(m_buffer.ptr + m_bufferPos, toWrite)); 0935 } 0936 if (ioRes.status != IO::Status::OK) { 0937 m_error = Error::RemoteDisconnect; 0938 m_state = Serialized; // in a way... serialization has completed, unsuccessfully 0939 writeTransport()->setWriteListener(nullptr); 0940 notifyCompletionListener(); 0941 return IO::Status::RemoteClosed; 0942 } 0943 m_bufferPos += ioRes.length; 0944 } 0945 return IO::Status::OK; 0946 } 0947 #endif // !DFERRY_SERDES_ONLY 0948 0949 chunk Message::serializeAndView() 0950 { 0951 chunk ret; // one return variable to enable return value optimization (RVO) in gcc 0952 if (!d->serialize()) { 0953 return ret; 0954 } 0955 ret = d->m_buffer; 0956 return ret; 0957 } 0958 0959 std::vector<byte> Message::save() 0960 { 0961 std::vector<byte> ret; 0962 if (!d->serialize()) { 0963 return ret; 0964 } 0965 ret.reserve(d->m_buffer.length); 0966 for (uint32 i = 0; i < d->m_buffer.length; i++) { 0967 ret.push_back(d->m_buffer.ptr[i]); 0968 } 0969 return ret; 0970 } 0971 0972 void Message::deserializeAndTake(chunk memOwnership) 0973 { 0974 if (d->m_state >= MessagePrivate::FirstIoState) { 0975 free(memOwnership.ptr); 0976 return; 0977 } 0978 d->m_headerLength = 0; 0979 d->m_bodyLength = 0; 0980 0981 d->clearBuffer(); 0982 d->m_buffer = memOwnership; 0983 d->m_bufferPos = d->m_buffer.length; 0984 0985 bool ok = d->m_buffer.length >= s_extendedFixedHeaderLength; 0986 ok = ok && d->deserializeFixedHeaders(); 0987 ok = ok && d->m_buffer.length >= d->m_headerLength; 0988 ok = ok && d->deserializeVariableHeaders(); 0989 ok = ok && d->m_buffer.length == d->m_headerLength + d->m_bodyLength; 0990 0991 if (!ok) { 0992 if (!d->m_error.isError()) { 0993 d->m_error = Error::MalformedReply; 0994 } 0995 d->clear(); 0996 return; 0997 } 0998 0999 chunk bodyData(d->m_buffer.ptr + d->m_headerLength, d->m_bodyLength); 1000 d->m_mainArguments = Arguments(nullptr, d->m_varHeaders.stringHeaderRaw(SignatureHeader), 1001 bodyData, d->m_isByteSwapped); 1002 d->m_state = MessagePrivate::Serialized; 1003 } 1004 1005 // This does not return bool because full validation of the main arguments would take quite 1006 // a few cycles. Validating only the header of the message doesn't seem to be worth it. 1007 void Message::load(const std::vector<byte> &data) 1008 { 1009 if (d->m_state >= MessagePrivate::FirstIoState || data.empty()) { 1010 return; 1011 } 1012 chunk buf; 1013 buf.length = data.size(); 1014 buf.ptr = reinterpret_cast<byte *>(malloc(buf.length)); 1015 memcpy(buf.ptr, &data[0], buf.length); 1016 1017 deserializeAndTake(buf); 1018 } 1019 1020 bool MessagePrivate::requiredHeadersPresent() 1021 { 1022 m_error = checkRequiredHeaders(); 1023 return !m_error.isError(); 1024 } 1025 1026 Error MessagePrivate::checkRequiredHeaders() const 1027 { 1028 if (m_serial == 0) { 1029 return Error::MessageSerial; 1030 } 1031 if (m_protocolVersion != 1) { 1032 return Error::MessageProtocolVersion; 1033 } 1034 1035 // might want to check for DestinationHeader if the transport is a bus (not peer-to-peer) 1036 // very strange that this isn't in the spec! 1037 1038 switch (m_messageType) { 1039 case Message::SignalMessage: 1040 // required: PathHeader, InterfaceHeader, MethodHeader 1041 if (!m_varHeaders.hasStringHeader(Message::InterfaceHeader)) { 1042 return Error::MessageInterface; 1043 } 1044 // fall through 1045 case Message::MethodCallMessage: 1046 // required: PathHeader, MethodHeader 1047 if (!m_varHeaders.hasStringHeader(Message::PathHeader)) { 1048 return Error::MessagePath; 1049 } 1050 if (!m_varHeaders.hasStringHeader(Message::MethodHeader)) { 1051 return Error::MessageMethod; 1052 } 1053 break; 1054 1055 case Message::ErrorMessage: 1056 // required: ErrorNameHeader, ReplySerialHeader 1057 if (!m_varHeaders.hasStringHeader(Message::ErrorNameHeader)) { 1058 return Error::MessageErrorName; 1059 } 1060 // fall through 1061 case Message::MethodReturnMessage: 1062 // required: ReplySerialHeader 1063 if (!m_varHeaders.hasIntHeader(Message::ReplySerialHeader) ) { 1064 return Error::MessageReplySerial; 1065 } 1066 break; 1067 1068 case Message::InvalidMessage: 1069 default: 1070 return Error::MessageType; 1071 } 1072 1073 return Error::NoError; 1074 } 1075 1076 bool MessagePrivate::deserializeFixedHeaders() 1077 { 1078 assert(m_bufferPos >= s_extendedFixedHeaderLength); 1079 byte *p = m_buffer.ptr; 1080 1081 byte endianness = *p++; 1082 if (endianness != 'l' && endianness != 'B') { 1083 return false; 1084 } 1085 m_isByteSwapped = endianness != s_thisMachineEndianness; 1086 1087 // TODO validate the values read here 1088 m_messageType = static_cast<Message::Type>(*p++); 1089 m_flags = *p++; 1090 m_protocolVersion = *p++; 1091 1092 m_bodyLength = basic::readUint32(p, m_isByteSwapped); 1093 m_serial = basic::readUint32(p + sizeof(uint32), m_isByteSwapped); 1094 // peek into the var-length header and use knowledge about array serialization to infer the 1095 // number of bytes still required for the header 1096 uint32 varArrayLength = basic::readUint32(p + 2 * sizeof(uint32), m_isByteSwapped); 1097 uint32 unpaddedHeaderLength = s_extendedFixedHeaderLength + varArrayLength; 1098 m_headerLength = align(unpaddedHeaderLength, 8); 1099 m_headerPadding = m_headerLength - unpaddedHeaderLength; 1100 1101 return m_headerLength + m_bodyLength <= Arguments::MaxMessageLength; 1102 } 1103 1104 bool MessagePrivate::deserializeVariableHeaders() 1105 { 1106 // use Arguments to parse the variable header fields 1107 // HACK: the fake first int argument is there to start the Arguments's data 8 byte aligned 1108 byte *base = m_buffer.ptr + s_properFixedHeaderLength - sizeof(int32); 1109 chunk headerData(base, m_headerLength - m_headerPadding - s_properFixedHeaderLength + sizeof(int32)); 1110 cstring varHeadersSig("ia(yv)"); 1111 Arguments argList(nullptr, varHeadersSig, headerData, m_isByteSwapped); 1112 1113 Arguments::Reader reader(argList); 1114 assert(reader.isValid()); 1115 1116 if (reader.state() != Arguments::Int32) { 1117 return false; 1118 } 1119 reader.readInt32(); 1120 if (reader.state() != Arguments::BeginArray) { 1121 return false; 1122 } 1123 reader.beginArray(); 1124 1125 while (reader.state() == Arguments::BeginStruct) { 1126 reader.beginStruct(); 1127 const byte headerField = reader.readByte(); 1128 if (headerField < Message::PathHeader || headerField > Message::UnixFdsHeader) { 1129 return false; 1130 } 1131 const Message::VariableHeader eHeader = static_cast<Message::VariableHeader>(headerField); 1132 1133 reader.beginVariant(); 1134 1135 bool ok = true; // short-circuit evaluation ftw 1136 if (isStringHeader(headerField)) { 1137 if (headerField == Message::PathHeader) { 1138 ok = ok && reader.state() == Arguments::ObjectPath; 1139 ok = ok && m_varHeaders.setStringHeader_deser(eHeader, reader.readObjectPath()); 1140 } else if (headerField == Message::SignatureHeader) { 1141 ok = ok && reader.state() == Arguments::Signature; 1142 // The spec allows having no signature header, which means "empty signature". However... 1143 // We do not drop empty signature headers when deserializing, in order to preserve 1144 // the original message contents. This could be useful for debugging and testing. 1145 ok = ok && m_varHeaders.setStringHeader_deser(eHeader, reader.readSignature()); 1146 } else { 1147 ok = ok && reader.state() == Arguments::String; 1148 ok = ok && m_varHeaders.setStringHeader_deser(eHeader, reader.readString()); 1149 } 1150 } else { 1151 ok = ok && reader.state() == Arguments::Uint32; 1152 ok = ok && m_varHeaders.setIntHeader_deser(eHeader, reader.readUint32()); 1153 } 1154 1155 if (!ok) { 1156 return false; 1157 } 1158 reader.endVariant(); 1159 reader.endStruct(); 1160 } 1161 reader.endArray(); 1162 1163 // check that header->body padding is in fact zero filled 1164 base = m_buffer.ptr; 1165 for (uint32 i = m_headerLength - m_headerPadding; i < m_headerLength; i++) { 1166 if (base[i] != '\0') { 1167 return false; 1168 } 1169 } 1170 1171 return reader.isFinished(); 1172 } 1173 1174 bool MessagePrivate::serialize() 1175 { 1176 if ((m_state == Serialized || m_state == Sending) && !m_dirty) { 1177 return true; 1178 } 1179 if (m_state >= FirstIoState) { // Marshalled data must not be touched while doing I/O 1180 return false; 1181 } 1182 1183 clearBuffer(); 1184 1185 if (m_error.isError() || !requiredHeadersPresent()) { 1186 return false; 1187 } 1188 1189 Arguments headerArgs = serializeVariableHeaders(); 1190 if (headerArgs.data().length <= 0) { 1191 return false; 1192 } 1193 1194 // we need to cut out alignment padding bytes 4 to 7 in the variable header data stream because 1195 // the original dbus code aligns based on address in the final data stream 1196 // (offset s_properFixedHeaderLength == 12), we align based on address in the Arguments's buffer 1197 // (offset 0) - note that our modification keeps the stream valid because length is measured from end 1198 // of padding 1199 1200 assert(headerArgs.data().length > 0); // if this fails the headerLength hack will break down 1201 1202 const uint32 unalignedHeaderLength = s_properFixedHeaderLength + headerArgs.data().length - sizeof(uint32); 1203 m_headerLength = align(unalignedHeaderLength, 8); 1204 m_bodyLength = m_mainArguments.data().length; 1205 const uint32 messageLength = m_headerLength + m_bodyLength; 1206 1207 if (messageLength > Arguments::MaxMessageLength) { 1208 m_error.setCode(Error::ArgumentsTooLong); 1209 return false; 1210 } 1211 1212 reserveBuffer(messageLength); 1213 1214 serializeFixedHeaders(); 1215 1216 // copy header data: uint32 length... 1217 memcpy(m_buffer.ptr + s_properFixedHeaderLength, headerArgs.data().ptr, sizeof(uint32)); 1218 // skip four bytes of padding and copy the rest 1219 memcpy(m_buffer.ptr + s_properFixedHeaderLength + sizeof(uint32), 1220 headerArgs.data().ptr + 2 * sizeof(uint32), 1221 headerArgs.data().length - 2 * sizeof(uint32)); 1222 // zero padding between variable headers and message body 1223 for (uint32 i = unalignedHeaderLength; i < m_headerLength; i++) { 1224 m_buffer.ptr[i] = '\0'; 1225 } 1226 // copy message body (if any - arguments are not mandatory) 1227 if (m_mainArguments.data().length) { 1228 memcpy(m_buffer.ptr + m_headerLength, m_mainArguments.data().ptr, m_mainArguments.data().length); 1229 } 1230 m_bufferPos = m_headerLength + m_mainArguments.data().length; 1231 assert(m_bufferPos <= m_buffer.length); 1232 1233 // for the upcoming message sending, "reuse" m_bufferPos for read position (formerly write position), 1234 // and m_buffer.length for end of data to read (formerly buffer capacity) 1235 m_buffer.length = m_bufferPos; 1236 m_bufferPos = 0; 1237 1238 m_dirty = false; 1239 m_state = Serialized; 1240 return true; 1241 } 1242 1243 void MessagePrivate::serializeFixedHeaders() 1244 { 1245 assert(m_buffer.length >= s_extendedFixedHeaderLength); 1246 byte *p = m_buffer.ptr; 1247 1248 *p++ = s_thisMachineEndianness; 1249 *p++ = byte(m_messageType); 1250 *p++ = m_flags; 1251 *p++ = m_protocolVersion; 1252 1253 basic::writeUint32(p, m_bodyLength); 1254 basic::writeUint32(p + sizeof(uint32), m_serial); 1255 } 1256 1257 static void doVarHeaderPrologue(Arguments::Writer *writer, Message::VariableHeader field) 1258 { 1259 writer->beginStruct(); 1260 writer->writeByte(byte(field)); 1261 } 1262 1263 Arguments MessagePrivate::serializeVariableHeaders() 1264 { 1265 Arguments::Writer writer; 1266 1267 // note that we don't have to deal with empty arrays because all valid message types require 1268 // at least one of the variable headers 1269 writer.beginArray(); 1270 1271 for (int i = 0; i < VarHeaderStorage::s_stringHeaderCount; i++) { 1272 const Message::VariableHeader field = s_stringHeaderAtIndex[i]; 1273 if (m_varHeaders.hasHeader(field)) { 1274 doVarHeaderPrologue(&writer, field); 1275 1276 const std::string &str = m_varHeaders.stringHeaders()[i]; 1277 if (field == Message::PathHeader) { 1278 writer.writeVariantForMessageHeader('o'); 1279 writer.writeObjectPath(cstring(str.c_str(), str.length())); 1280 } else if (field == Message::SignatureHeader) { 1281 writer.writeVariantForMessageHeader('g'); 1282 writer.writeSignature(cstring(str.c_str(), str.length())); 1283 } else { 1284 writer.writeVariantForMessageHeader('s'); 1285 writer.writeString(cstring(str.c_str(), str.length())); 1286 } 1287 1288 writer.fixupAfterWriteVariantForMessageHeader(); 1289 writer.endStruct(); 1290 1291 if (unlikely(writer.error().isError())) { 1292 static const Error::Code stringHeaderErrors[VarHeaderStorage::s_stringHeaderCount] = { 1293 Error::MessagePath, 1294 Error::MessageInterface, 1295 Error::MessageMethod, 1296 Error::MessageErrorName, 1297 Error::MessageDestination, 1298 Error::MessageSender, 1299 Error::MessageSignature 1300 }; 1301 m_error.setCode(stringHeaderErrors[i]); 1302 return Arguments(); 1303 } 1304 } 1305 } 1306 1307 for (int i = 0; i < VarHeaderStorage::s_intHeaderCount; i++) { 1308 const Message::VariableHeader field = s_intHeaderAtIndex[i]; 1309 if (m_varHeaders.hasHeader(field)) { 1310 doVarHeaderPrologue(&writer, field); 1311 writer.writeVariantForMessageHeader('u'); 1312 writer.writeUint32(m_varHeaders.m_intHeaders[i]); 1313 writer.fixupAfterWriteVariantForMessageHeader(); 1314 writer.endStruct(); 1315 } 1316 } 1317 1318 writer.endArray(); 1319 return writer.finish(); 1320 } 1321 1322 void MessagePrivate::clearBuffer() 1323 { 1324 if (m_buffer.ptr) { 1325 free(m_buffer.ptr); 1326 m_buffer = chunk(); 1327 m_bufferPos = 0; 1328 } else { 1329 assert(m_buffer.length == 0); 1330 assert(m_bufferPos == 0); 1331 } 1332 } 1333 1334 void MessagePrivate::clear(bool onlyReleaseResources) 1335 { 1336 clearBuffer(); 1337 #ifdef __unix__ 1338 for (int fd : *argUnixFds()) { 1339 ::close(fd); 1340 } 1341 #endif 1342 if (!onlyReleaseResources) { // get into a clean state again 1343 m_state = Empty; 1344 m_mainArguments = Arguments(); 1345 m_varHeaders = VarHeaderStorage(); 1346 } 1347 } 1348 1349 static uint32 nextPowerOf2(uint32 x) 1350 { 1351 --x; 1352 x |= x >> 1; 1353 x |= x >> 2; 1354 x |= x >> 4; 1355 x |= x >> 8; 1356 x |= x >> 16; 1357 return ++x; 1358 } 1359 1360 void MessagePrivate::reserveBuffer(uint32 newLen) 1361 { 1362 const uint32 oldLen = m_buffer.length; 1363 if (newLen <= oldLen) { 1364 return; 1365 } 1366 if (newLen <= 256) { 1367 assert(oldLen == 0); 1368 newLen = 256; 1369 m_buffer.ptr = reinterpret_cast<byte *>(msgAllocCaches.msgBuffer.allocate()); 1370 } else { 1371 newLen = nextPowerOf2(newLen); 1372 if (oldLen == 256) { 1373 byte *newAlloc = reinterpret_cast<byte *>(malloc(newLen)); 1374 memcpy(newAlloc, m_buffer.ptr, oldLen); 1375 1376 msgAllocCaches.msgBuffer.free(m_buffer.ptr); 1377 m_buffer.ptr = newAlloc; 1378 } else { 1379 m_buffer.ptr = reinterpret_cast<byte *>(realloc(m_buffer.ptr, newLen)); 1380 } 1381 } 1382 1383 m_buffer.length = newLen; 1384 } 1385 1386 std::vector<int> *MessagePrivate::argUnixFds() 1387 { 1388 return &Arguments::Private::get(&m_mainArguments)->m_fileDescriptors; 1389 }