20
20
#include "mir/frontend/client_constants.h"
21
21
#include "mir/frontend/session_credentials.h"
22
22
#include "mir/variable_length_array.h"
23
#include "mir/fd_socket_transmission.h"
24
25
#include <boost/throw_exception.hpp>
34
35
namespace ba = boost::asio;
36
37
mfd::SocketMessenger::SocketMessenger(std::shared_ptr<ba::local::stream_protocol::socket> const& socket)
39
socket_fd{IntOwnedFd{socket->native_handle()}}
39
41
// Make the socket non-blocking to avoid hanging the server when a client
40
42
// is unresponsive. Also increase the send buffer size to 64KiB to allow
52
54
socklen_t cl = sizeof(cr);
54
auto status = getsockopt(socket->native_handle(), SOL_SOCKET, SO_PEERCRED, &cr, &cl);
56
auto status = getsockopt(socket_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl);
57
59
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to query client socket credentials"));
94
96
void mfd::SocketMessenger::send_fds_locked(std::unique_lock<std::mutex> const&, std::vector<mir::Fd> const& fds)
100
char dummy_iov_data = 'M';
101
iov.iov_base = &dummy_iov_data;
104
// Allocate space for control message
105
static auto const builtin_n_fds = 5;
106
static auto const builtin_cmsg_space = CMSG_SPACE(builtin_n_fds * sizeof(int));
107
auto const fds_bytes = fds.size() * sizeof(int);
108
mir::VariableLengthArray<builtin_cmsg_space> control{CMSG_SPACE(fds_bytes)};
109
// Silence valgrind uninitialized memory complaint
110
memset(control.data(), 0, control.size());
113
struct msghdr header;
114
header.msg_name = NULL;
115
header.msg_namelen = 0;
116
header.msg_iov = &iov;
117
header.msg_iovlen = 1;
118
header.msg_controllen = control.size();
119
header.msg_control = control.data();
120
header.msg_flags = 0;
122
// Control message contains file descriptors
123
struct cmsghdr *message = CMSG_FIRSTHDR(&header);
124
message->cmsg_len = CMSG_LEN(fds_bytes);
125
message->cmsg_level = SOL_SOCKET;
126
message->cmsg_type = SCM_RIGHTS;
128
int* const data = reinterpret_cast<int*>(CMSG_DATA(message));
133
auto const sent = sendmsg(socket->native_handle(), &header, 0);
135
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to send fds: " + std::string(strerror(errno))));
98
mir::send_fds(socket_fd, fds);
139
101
void mfd::SocketMessenger::async_receive_msg(
198
160
msgh.msg_control = control_un.control;
199
161
msgh.msg_controllen = sizeof(control_un.control);
201
if (recvmsg(socket->native_handle(), &msgh, MSG_PEEK) != -1)
163
if (recvmsg(socket_fd, &msgh, MSG_PEEK) != -1)
203
165
auto const ucredp = reinterpret_cast<ucred*>(CMSG_DATA(CMSG_FIRSTHDR(&msgh)));
204
166
session_creds = {ucredp->pid, ucredp->uid, ucredp->gid};