/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* vim: set ts=8 sts=4 et sw=4 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include"mozilla/ipc/MiniTransceiver.h" #include"chrome/common/ipc_message.h" #include"chrome/common/ipc_message_utils.h" #include"base/eintr_wrapper.h" #include"mozilla/UniquePtr.h" #include"mozilla/DebugOnly.h" #include"mozilla/Sprintf.h" #include"mozilla/ScopeExit.h" #include"nsDebug.h"
/** * Initialize the IO vector for sending data and the control buffer for sending * FDs.
*/ staticvoid InitMsgHdr(msghdr* aHdr, int aIOVSize, size_t aMaxNumFds) {
aHdr->msg_name = nullptr;
aHdr->msg_namelen = 0;
aHdr->msg_flags = 0;
// Prepare the IO vector to receive the content of message. auto* iov = new iovec[aIOVSize];
aHdr->msg_iov = iov;
aHdr->msg_iovlen = aIOVSize;
// Prepare the control buffer to receive file descriptors. const size_t cbufSize = CMSG_SPACE(sizeof(int) * aMaxNumFds); auto* cbuf = newchar[cbufSize]; // Avoid valgrind complaints about uninitialized padding (but also, // fill with a value that isn't a valid fd, just in case).
memset(cbuf, 255, cbufSize);
aHdr->msg_control = cbuf;
aHdr->msg_controllen = cbufSize;
}
void MiniTransceiver::PrepareFDs(msghdr* aHdr, IPC::Message& aMsg) { // Set control buffer to send file descriptors of the Message.
size_t num_fds = aMsg.attached_handles_.Length();
cmsghdr* cmsg = CMSG_FIRSTHDR(aHdr);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); for (size_t i = 0; i < num_fds; ++i) { reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] =
aMsg.attached_handles_[i].get();
}
// This number will be sent in the header of the message. So, we // can check it at the other side.
aMsg.header()->num_handles = num_fds;
}
size_t MiniTransceiver::PrepareBuffers(msghdr* aHdr, IPC::Message& aMsg) { // Set iovec to send for all buffers of the Message.
iovec* iov = aHdr->msg_iov;
size_t iovlen = 0;
size_t bytes_to_send = 0; for (Pickle::BufferList::IterImpl iter(aMsg.Buffers()); !iter.Done();
iter.Advance(aMsg.Buffers(), iter.RemainingInSegment())) { char* data = iter.Data();
size_t size = iter.RemainingInSegment();
iov[iovlen].iov_base = data;
iov[iovlen].iov_len = size;
iovlen++;
MOZ_ASSERT(iovlen <= kMaxIOVecSize);
bytes_to_send += size;
}
MOZ_ASSERT(bytes_to_send <= kMaxDataSize);
aHdr->msg_iovlen = iovlen;
return bytes_to_send;
}
bool MiniTransceiver::Send(IPC::Message& aMsg) { #ifdef DEBUG if (mState == STATE_SENDING) {
MOZ_CRASH( "STATE_SENDING: It violates of request-response and no concurrent " "rules");
}
mState = STATE_SENDING; #endif
auto clean_fdset = MakeScopeExit([&] { aMsg.attached_handles_.Clear(); });
// The buffer to collect all fds received from the socket. int* all_fds = aFdsBuf; unsigned num_all_fds = 0;
size_t total_readed = 0;
uint32_t msgsz = 0; while (msgsz == 0 || total_readed < msgsz) { // Set IO vector with the begin of the unused buffer.
hdr.msg_iov->iov_base = aDataBuf + total_readed;
hdr.msg_iov->iov_len = (msgsz == 0 ? aBufSize : msgsz) - total_readed;
// Read the socket
ssize_t bytes_readed = HANDLE_EINTR(recvmsg(mFd, &hdr, 0)); if (bytes_readed <= 0) { // Closed or error! returnfalse;
}
total_readed += bytes_readed;
MOZ_ASSERT(total_readed <= aBufSize);
if (msgsz == 0) { // Parse the size of the message. // Get 0 if data in the buffer is no enough to get message size.
msgsz = IPC::Message::MessageSize(aDataBuf, aDataBuf + total_readed);
}
if (!RecvData(databuf.get(), kMaxDataSize, &msgsz, all_fds, kMaxDataSize,
&num_all_fds)) { returnfalse;
}
// Create Message from databuf & all_fds.
UniquePtr<IPC::Message> msg = MakeUnique<IPC::Message>(databuf.get(), msgsz);
nsTArray<UniqueFileHandle> handles(num_all_fds); for (unsigned i = 0; i < num_all_fds; ++i) {
handles.AppendElement(UniqueFileHandle(all_fds[i]));
}
msg->SetAttachedFileHandles(std::move(handles));
if (mDataBufClear == DataBufferClear::AfterReceiving) { // Avoid content processes from reading the content of // messages.
memset(databuf.get(), 0, msgsz);
}
MOZ_ASSERT(msg->header()->num_handles == msg->attached_handles_.Length(), "The number of file descriptors in the header is different from" " the number actually received");
aMsg = std::move(msg); returntrue;
}
} // namespace mozilla::ipc
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.