1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
// Copyright (C) 2020-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// 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/.
#ifndef VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_RECEIVE_OP_HPP_
#define VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_RECEIVE_OP_HPP_
#if VSOMEIP_BOOST_VERSION >= 106600
#if defined(__linux__) || defined(ANDROID)
#include <boost/asio/local/stream_protocol.hpp>
namespace vsomeip_v3 {
using socket_type_t = boost::asio::local::stream_protocol::socket;
using receive_handler_t = std::function<
void (boost::system::error_code const &_error, size_t _size,
const std::uint32_t &, const std::uint32_t &)>;
struct local_server_endpoint_impl_receive_op {
socket_type_t &socket_;
receive_handler_t handler_;
byte_t *buffer_;
size_t length_;
uid_t uid_;
gid_t gid_;
size_t bytes_;
void operator()(boost::system::error_code _error) {
if (!_error) {
if (!socket_.native_non_blocking())
socket_.native_non_blocking(true, _error);
for (;;) {
ssize_t its_result;
int its_flags(0);
// Set buffer
struct iovec its_vec[1];
its_vec[0].iov_base = buffer_;
its_vec[0].iov_len = length_;
union {
struct cmsghdr cmh;
char control[CMSG_SPACE(sizeof(struct ucred))];
} control_un;
// Set 'control_un' to describe ancillary data that we want to receive
control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
control_un.cmh.cmsg_level = SOL_SOCKET;
control_un.cmh.cmsg_type = SCM_CREDENTIALS;
// Build header with all informations to call ::recvmsg
msghdr its_header = msghdr();
its_header.msg_iov = its_vec;
its_header.msg_iovlen = 1;
its_header.msg_control = control_un.control;
its_header.msg_controllen = sizeof(control_un.control);
// Call recvmsg and handle its result
errno = 0;
its_result = ::recvmsg(socket_.native_handle(), &its_header, its_flags);
_error = boost::system::error_code(its_result < 0 ? errno : 0,
boost::asio::error::get_system_category());
bytes_ += _error ? 0 : static_cast<size_t>(its_result);
if (_error == boost::asio::error::interrupted)
continue;
if (_error == boost::asio::error::would_block
|| _error == boost::asio::error::try_again) {
socket_.async_wait(socket_type_t::wait_read, *this);
return;
}
if (_error)
break;
if (bytes_ == 0)
_error = boost::asio::error::eof;
// Extract credentials (UID/GID)
struct ucred *its_credentials;
for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&its_header);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&its_header, cmsg))
{
if (cmsg->cmsg_level == SOL_SOCKET
&& cmsg->cmsg_type == SCM_CREDENTIALS
&& cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
its_credentials = (struct ucred *) CMSG_DATA(cmsg);
if (its_credentials) {
uid_ = its_credentials->uid;
gid_ = its_credentials->gid;
break;
}
}
}
break;
}
}
// Call the handler
handler_(_error, bytes_, uid_, gid_);
}
};
} // namespace vsomeip
#endif // __linux__ || ANDROID
#endif // VSOMEIP_BOOST_VERSION >= 106600
#endif // VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_RECEIVE_OP_HPP_
|