size_t send_len = CountVectorSize(send_vector, send_count);
InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
false);
- auto status = SendData(socket_fd, transaction_state->request);
- if (status && send_len > 0)
- status = SendDataVector(socket_fd, send_vector, send_count);
- return status;
+ if (send_len == 0) {
+ send_vector = nullptr;
+ send_count = 0;
+ }
+ return SendData(socket_fd, transaction_state->request, send_vector,
+ send_count);
}
Status<void> ReceiveResponse(const BorrowedHandle& socket_fd,
namespace {
+constexpr size_t kMaxFdCount =
+ 256; // Total of 1KiB of data to transfer these FDs.
+
// Default implementations of Send/Receive interfaces to use standard socket
// send/sendmsg/recv/recvmsg functions.
class SocketSender : public SendInterface {
}
Status<void> SendPayload::Send(const BorrowedHandle& socket_fd,
- const ucred* cred) {
+ const ucred* cred, const iovec* data_vec,
+ size_t vec_count) {
+ if (file_handles_.size() > kMaxFdCount) {
+ ALOGE(
+ "SendPayload::Send: Trying to send too many file descriptors (%zu), "
+ "max allowed = %zu",
+ file_handles_.size(), kMaxFdCount);
+ return ErrorStatus{EINVAL};
+ }
+
SendInterface* sender = sender_ ? sender_ : &g_socket_sender;
MessagePreamble preamble;
preamble.magic = kMagicPreamble;
preamble.data_size = buffer_.size();
preamble.fd_count = file_handles_.size();
- Status<void> ret = SendAll(sender, socket_fd, &preamble, sizeof(preamble));
- if (!ret)
- return ret;
msghdr msg = {};
- iovec recv_vect = {buffer_.data(), buffer_.size()};
- msg.msg_iov = &recv_vect;
- msg.msg_iovlen = 1;
+ msg.msg_iovlen = 2 + vec_count;
+ msg.msg_iov = static_cast<iovec*>(alloca(sizeof(iovec) * msg.msg_iovlen));
+ msg.msg_iov[0].iov_base = &preamble;
+ msg.msg_iov[0].iov_len = sizeof(preamble);
+ msg.msg_iov[1].iov_base = buffer_.data();
+ msg.msg_iov[1].iov_len = buffer_.size();
+ for (size_t i = 0; i < vec_count; i++)
+ msg.msg_iov[i + 2] = data_vec[i];
if (cred || !file_handles_.empty()) {
const size_t fd_bytes = file_handles_.size() * sizeof(int);
ucred* cred) {
RecvInterface* receiver = receiver_ ? receiver_ : &g_socket_receiver;
MessagePreamble preamble;
- Status<void> ret = RecvAll(receiver, socket_fd, &preamble, sizeof(preamble));
+ msghdr msg = {};
+ iovec recv_vect = {&preamble, sizeof(preamble)};
+ msg.msg_iov = &recv_vect;
+ msg.msg_iovlen = 1;
+ const size_t receive_fd_bytes = kMaxFdCount * sizeof(int);
+ msg.msg_controllen = CMSG_SPACE(sizeof(ucred)) + CMSG_SPACE(receive_fd_bytes);
+ msg.msg_control = alloca(msg.msg_controllen);
+
+ Status<void> ret = RecvMsgAll(receiver, socket_fd, &msg);
if (!ret)
return ret;
file_handles_.clear();
read_pos_ = 0;
- msghdr msg = {};
- iovec recv_vect = {buffer_.data(), buffer_.size()};
- msg.msg_iov = &recv_vect;
- msg.msg_iovlen = 1;
-
- if (cred || preamble.fd_count) {
- const size_t receive_fd_bytes = preamble.fd_count * sizeof(int);
- msg.msg_controllen =
- (cred ? CMSG_SPACE(sizeof(ucred)) : 0) +
- (receive_fd_bytes == 0 ? 0 : CMSG_SPACE(receive_fd_bytes));
- msg.msg_control = alloca(msg.msg_controllen);
- }
-
- ret = RecvMsgAll(receiver, socket_fd, &msg);
- if (!ret)
- return ret;
-
bool cred_available = false;
file_handles_.reserve(preamble.fd_count);
cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
cmsg = CMSG_NXTHDR(&msg, cmsg);
}
+ ret = RecvAll(receiver, socket_fd, buffer_.data(), buffer_.size());
+ if (!ret)
+ return ret;
+
if (cred && !cred_available) {
ALOGE("ReceivePayload::Receive: Failed to obtain message credentials");
ret.SetError(EIO);
public:
SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
Status<void> Send(const BorrowedHandle& socket_fd);
- Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred);
+ Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred,
+ const iovec* data_vec = nullptr, size_t vec_count = 0);
// MessageWriter
void* GetNextWriteBufferSection(size_t size) override;
};
template <typename T>
-inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data) {
+inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data,
+ const iovec* data_vec = nullptr,
+ size_t vec_count = 0) {
SendPayload payload;
rpc::Serialize(data, &payload);
- return payload.Send(socket_fd);
+ return payload.Send(socket_fd, nullptr, data_vec, vec_count);
}
template <typename FileHandleType>
inline Status<void> SendData(const BorrowedHandle& socket_fd,
- const RequestHeader<FileHandleType>& request) {
+ const RequestHeader<FileHandleType>& request,
+ const iovec* data_vec = nullptr,
+ size_t vec_count = 0) {
SendPayload payload;
rpc::Serialize(request, &payload);
- return payload.Send(socket_fd, &request.cred);
+ return payload.Send(socket_fd, &request.cred, data_vec, vec_count);
}
Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,