Bug 1249518 - Make DaemonSocketPDU able to send multiple file descriptors in single unit. r=tzimmermann

This commit is contained in:
James Cheng 2016-03-30 14:58:13 +08:00 committed by Liang-Heng Chen
parent 1cbcbed9b1
commit c43f377eb6
3 changed files with 34 additions and 12 deletions

View File

@ -221,7 +221,11 @@ public:
{
DaemonSocketPDU& pdu = GetPDU();
aArg1 = pdu.AcquireFd();
auto receiveFds = pdu.AcquireFds();
if (NS_WARN_IF(receiveFds.Length() == 0)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aArg1 = receiveFds[0];
if (NS_WARN_IF(aArg1 < 0)) {
return NS_ERROR_ILLEGAL_VALUE;
@ -278,7 +282,14 @@ BluetoothDaemonSocketModule::ConnectRsp(const DaemonSocketPDUHeader& aHeader,
BluetoothSocketResultHandler* aRes)
{
/* the file descriptor is attached in the PDU's ancillary data */
int fd = aPDU.AcquireFd();
auto receiveFds = aPDU.AcquireFds();
if (receiveFds.Length() == 0) {
ErrorRunnable::Dispatch(aRes, &BluetoothSocketResultHandler::OnError,
ConstantInitOp1<BluetoothStatus>(STATUS_FAIL));
return;
}
int fd = -1;
fd = receiveFds[0];
if (fd < 0) {
ErrorRunnable::Dispatch(aRes, &BluetoothSocketResultHandler::OnError,
ConstantInitOp1<BluetoothStatus>(STATUS_FAIL));

View File

@ -119,7 +119,7 @@ DaemonSocketPDU::Receive(int aFd)
iv.iov_base = GetData(0);
iv.iov_len = GetAvailableSpace();
uint8_t cmsgbuf[CMSG_SPACE(sizeof(int))];
uint8_t cmsgbuf[CMSG_SPACE(sizeof(int)* MAX_NFDS)];
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
@ -140,24 +140,33 @@ DaemonSocketPDU::Receive(int aFd)
SetRange(0, res);
struct cmsghdr *chdr = CMSG_FIRSTHDR(&msg);
struct cmsghdr* chdr = CMSG_FIRSTHDR(&msg);
for (; chdr; chdr = CMSG_NXTHDR(&msg, chdr)) {
if (NS_WARN_IF(!CMSGHDR_CONTAINS_FD(chdr))) {
continue;
}
// Retrieve sent file descriptor. If multiple file descriptors
// have been sent, we close all but the final one.
mReceivedFd = *(static_cast<int*>(CMSG_DATA(chdr)));
// Retrieve sent file descriptors.
size_t fdCount = (chdr->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) / sizeof(int);
for (size_t i = 0; i < fdCount; i++) {
int* receivedFd = static_cast<int*>(CMSG_DATA(chdr)) + i;
mReceivedFds.AppendElement(ScopedClose(*receivedFd));
}
}
return res;
}
int
DaemonSocketPDU::AcquireFd()
nsTArray<int>
DaemonSocketPDU::AcquireFds()
{
return mReceivedFd.forget();
// Forget all RAII object to avoid closing the fds.
nsTArray<int> fds;
for (auto& fd : mReceivedFds) {
fds.AppendElement(fd.forget());
}
mReceivedFds.Clear();
return fds;
}
nsresult

View File

@ -10,10 +10,12 @@
#include "mozilla/FileUtils.h"
#include "mozilla/ipc/SocketBase.h"
#include "mozilla/ipc/DaemonSocketMessageHandlers.h"
#include "nsTArray.h"
namespace mozilla {
namespace ipc {
static const size_t MAX_NFDS = 16;
class DaemonSocketIOConsumer;
/**
@ -72,7 +74,7 @@ public:
ssize_t Send(int aFd) override;
ssize_t Receive(int aFd) override;
int AcquireFd();
nsTArray<int> AcquireFds();
nsresult UpdateHeader();
@ -82,7 +84,7 @@ private:
DaemonSocketIOConsumer* mConsumer;
RefPtr<DaemonSocketResultHandler> mRes;
ScopedClose mReceivedFd;
nsTArray<ScopedClose> mReceivedFds;
};
}