-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsys_socket.h
129 lines (93 loc) · 3.38 KB
/
sys_socket.h
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
119
120
121
122
123
124
125
126
127
128
129
// Copyright (c) 2022, Eugene Gershnik
// SPDX-License-Identifier: BSD-3-Clause
#ifndef HEADER_SYS_SOCKET_H_INCLUDED
#define HEADER_SYS_SOCKET_H_INCLUDED
#include "sys_util.h"
namespace ptl {
template<class Protocol, class Executor>
struct FileDescriptorTraits<asio::basic_datagram_socket<Protocol, Executor>> {
[[gnu::always_inline]] static int c_fd(asio::basic_datagram_socket<Protocol, Executor> & socket) noexcept
{ return socket.native_handle();}
};
}
template<unsigned long Name, class T>
class SocketIOControl {
public:
constexpr auto name() const -> unsigned long { return Name; }
auto data() -> void * { return &m_data; }
protected:
T m_data;
};
#ifdef SIOCGIFFLAGS
class GetInterfaceFlags : public SocketIOControl<(unsigned long)SIOCGIFFLAGS, ifreq> {
public:
GetInterfaceFlags(const sys_string & name) {
auto copied = name.copy_data(0, m_data.ifr_name, IFNAMSIZ);
memset(m_data.ifr_name + copied, 0, IFNAMSIZ - copied);
}
auto result() const -> std::remove_cvref_t<decltype(this->m_data.ifr_flags)> {
return m_data.ifr_flags;
}
};
#endif
#ifdef SIOCGLIFCONF
class GetLInterfaceConf : public SocketIOControl<(unsigned long)SIOCGLIFCONF, lifconf> {
public:
GetLInterfaceConf(sa_family_t family, lifreq * dest, size_t size) {
m_data.lifc_family = family;
m_data.lifc_flags = 0;
m_data.lifc_len = size * sizeof(lifreq);
m_data.lifc_req = dest;
}
auto result() const -> size_t {
return m_data.lifc_len / sizeof(lifreq);
}
};
#endif
#ifdef SIOCGLIFINDEX
class GetLInterfaceIndex : public SocketIOControl<(unsigned long)SIOCGLIFINDEX, lifreq> {
public:
GetLInterfaceIndex(const sys_string & name) {
auto copied = name.copy_data(0, m_data.lifr_name, IFNAMSIZ);
memset(m_data.lifr_name + copied, 0, IFNAMSIZ - copied);
}
auto result() const -> int {
return m_data.lifr_index;
}
};
#endif
#ifdef SIOCGLIFFLAGS
class GetLInterfaceFlags : public SocketIOControl<(unsigned long)SIOCGLIFFLAGS, lifreq> {
public:
GetLInterfaceFlags(const sys_string & name) {
auto copied = name.copy_data(0, m_data.lifr_name, IFNAMSIZ);
memset(m_data.lifr_name + copied, 0, IFNAMSIZ - copied);
}
auto result() const -> std::remove_cvref_t<decltype(this->m_data.lifr_flags)> {
return m_data.lifr_flags;
}
};
#endif
#ifdef SIOCGIFNAME
class GetInterfaceName : public SocketIOControl<(unsigned long)SIOCGIFNAME, ifreq> {
public:
GetInterfaceName(int ifIndex) {
m_data.ifr_ifindex = ifIndex;
}
auto result() const -> sys_string {
auto len = strnlen(m_data.ifr_name, IFNAMSIZ);
return sys_string(m_data.ifr_name, len);
}
};
#endif
template<class IoControl, class Protocol, class Executor, class... Args>
auto ioctlSocket(asio::basic_socket<Protocol, Executor> & socket, Args && ...args) ->
outcome::result<decltype(std::declval<IoControl>().result())> {
IoControl control(std::forward<Args>(args)...);
asio::error_code ec;
socket.io_control(control, ec);
if (ec)
return ec;
return control.result();
}
#endif