Skip to content

Commit 540ea44

Browse files
committed
Add fly::net::TcpSocket and fly::net::UdpSocket
These will serve as a much better replacement for fly::Socket. The old socket class doesn't support IPv6 at all and is rather weakly typed. That is, for example, it's entirely possible to attempt TCP operations on a UDP socket. This would fail at runtime, but now with the new socket classes, it's not even possible to attempt. The old socket design was such that there was a virtual base socket interface, and concrete implementations for each platform. In this new design, platform-dependent system calls are abstracted into a "socket operations" file, which share a common interface that the socket classes may then interact with. Currently, while these sockets may be configured to be non-blocking, there isn't a service for monitoring non-blocking sockets yet. There's also still some room for improvement regarding configuring sockets. For example, to create a listening socket, users will need to create a TcpSocket and invoke bind/listen/accept on that socket. It would be nice to have a concrete "ListenSocket" class to hide these details.
1 parent 3af0d62 commit 540ea44

20 files changed

+3157
-8
lines changed

build/win/libfly/libfly.vcxproj

+9
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@
182182
<ClInclude Include="..\..\..\fly\net\endpoint.hpp" />
183183
<ClInclude Include="..\..\..\fly\net\ipv4_address.hpp" />
184184
<ClInclude Include="..\..\..\fly\net\ipv6_address.hpp" />
185+
<ClInclude Include="..\..\..\fly\net\socket\detail\base_socket.hpp" />
186+
<ClInclude Include="..\..\..\fly\net\socket\detail\socket_operations.hpp" />
187+
<ClInclude Include="..\..\..\fly\net\socket\socket_types.hpp" />
188+
<ClInclude Include="..\..\..\fly\net\socket\tcp_socket.hpp" />
189+
<ClInclude Include="..\..\..\fly\net\socket\udp_socket.hpp" />
185190
<ClInclude Include="..\..\..\fly\parser\ini_parser.hpp" />
186191
<ClInclude Include="..\..\..\fly\parser\json_parser.hpp" />
187192
<ClInclude Include="..\..\..\fly\parser\parser.hpp" />
@@ -254,6 +259,10 @@
254259
<ClCompile Include="..\..\..\fly\net\endpoint.cpp" />
255260
<ClCompile Include="..\..\..\fly\net\ipv4_address.cpp" />
256261
<ClCompile Include="..\..\..\fly\net\ipv6_address.cpp" />
262+
<ClCompile Include="..\..\..\fly\net\socket\detail\base_socket.cpp" />
263+
<ClCompile Include="..\..\..\fly\net\socket\detail\win\socket_operations.cpp" />
264+
<ClCompile Include="..\..\..\fly\net\socket\tcp_socket.cpp" />
265+
<ClCompile Include="..\..\..\fly\net\socket\udp_socket.cpp" />
257266
<ClCompile Include="..\..\..\fly\parser\ini_parser.cpp" />
258267
<ClCompile Include="..\..\..\fly\parser\json_parser.cpp" />
259268
<ClCompile Include="..\..\..\fly\parser\parser.cpp" />

build/win/libfly/libfly.vcxproj.filters

+36
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@
2525
<Filter Include="net">
2626
<UniqueIdentifier>{03e02b28-3bca-4b51-ac6e-e59c2879f83e}</UniqueIdentifier>
2727
</Filter>
28+
<Filter Include="net\socket">
29+
<UniqueIdentifier>{77b83860-8825-4814-bad0-4336194640de}</UniqueIdentifier>
30+
</Filter>
31+
<Filter Include="net\socket\detail">
32+
<UniqueIdentifier>{f1d89e19-7d3c-4402-9ffd-c1f27b0c1eea}</UniqueIdentifier>
33+
</Filter>
34+
<Filter Include="net\socket\detail\win">
35+
<UniqueIdentifier>{9346d71b-4ecf-47e6-8b56-21e4886520f2}</UniqueIdentifier>
36+
</Filter>
2837
<Filter Include="parser">
2938
<UniqueIdentifier>{e39571b7-e6c1-48ea-917e-08c233c64755}</UniqueIdentifier>
3039
</Filter>
@@ -154,6 +163,21 @@
154163
<ClInclude Include="..\..\..\fly\net\ipv6_address.hpp">
155164
<Filter>net</Filter>
156165
</ClInclude>
166+
<ClInclude Include="..\..\..\fly\net\socket\socket_types.hpp">
167+
<Filter>net\socket</Filter>
168+
</ClInclude>
169+
<ClInclude Include="..\..\..\fly\net\socket\tcp_socket.hpp">
170+
<Filter>net\socket</Filter>
171+
</ClInclude>
172+
<ClInclude Include="..\..\..\fly\net\socket\udp_socket.hpp">
173+
<Filter>net\socket</Filter>
174+
</ClInclude>
175+
<ClInclude Include="..\..\..\fly\net\socket\detail\base_socket.hpp">
176+
<Filter>net\socket\detail</Filter>
177+
</ClInclude>
178+
<ClInclude Include="..\..\..\fly\net\socket\detail\socket_operations.hpp">
179+
<Filter>net\socket\detail</Filter>
180+
</ClInclude>
157181
<ClInclude Include="..\..\..\fly\parser\ini_parser.hpp">
158182
<Filter>parser</Filter>
159183
</ClInclude>
@@ -366,6 +390,18 @@
366390
<ClCompile Include="..\..\..\fly\net\ipv6_address.cpp">
367391
<Filter>net</Filter>
368392
</ClCompile>
393+
<ClCompile Include="..\..\..\fly\net\socket\tcp_socket.cpp">
394+
<Filter>net\socket</Filter>
395+
</ClCompile>
396+
<ClCompile Include="..\..\..\fly\net\socket\udp_socket.cpp">
397+
<Filter>net\socket</Filter>
398+
</ClCompile>
399+
<ClCompile Include="..\..\..\fly\net\socket\detail\base_socket.cpp">
400+
<Filter>net\socket\detail</Filter>
401+
</ClCompile>
402+
<ClCompile Include="..\..\..\fly\net\socket\detail\win\socket_operations.cpp">
403+
<Filter>net\socket\detail\win</Filter>
404+
</ClCompile>
369405
<ClCompile Include="..\..\..\fly\parser\ini_parser.cpp">
370406
<Filter>parser</Filter>
371407
</ClCompile>

build/win/libfly_unit_tests/libfly_unit_tests.vcxproj

+3
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@
226226
<ClCompile Include="..\..\..\test\net\endpoint.cpp" />
227227
<ClCompile Include="..\..\..\test\net\ipv4_address.cpp" />
228228
<ClCompile Include="..\..\..\test\net\ipv6_address.cpp" />
229+
<ClCompile Include="..\..\..\test\net\tcp_socket.cpp" />
230+
<ClCompile Include="..\..\..\test\net\udp_socket.cpp" />
229231
<ClCompile Include="..\..\..\test\parser\ini_parser.cpp" />
230232
<ClCompile Include="..\..\..\test\parser\json_parser.cpp" />
231233
<ClCompile Include="..\..\..\test\parser\parser.cpp" />
@@ -259,6 +261,7 @@
259261
</ItemGroup>
260262
<ItemGroup>
261263
<ClInclude Include="..\..\..\test\config\test_config.hpp" />
264+
<ClInclude Include="..\..\..\test\net\socket_util.hpp" />
262265
<ClInclude Include="..\..\..\test\types\json\json_helpers.hpp" />
263266
</ItemGroup>
264267
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

build/win/libfly_unit_tests/libfly_unit_tests.vcxproj.filters

+9
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@
8686
<ClCompile Include="..\..\..\test\net\ipv6_address.cpp">
8787
<Filter>net</Filter>
8888
</ClCompile>
89+
<ClCompile Include="..\..\..\test\net\tcp_socket.cpp">
90+
<Filter>net</Filter>
91+
</ClCompile>
92+
<ClCompile Include="..\..\..\test\net\udp_socket.cpp">
93+
<Filter>net</Filter>
94+
</ClCompile>
8995
<ClCompile Include="..\..\..\test\parser\ini_parser.cpp">
9096
<Filter>parser</Filter>
9197
</ClCompile>
@@ -181,6 +187,9 @@
181187
<ClInclude Include="..\..\..\test\config\test_config.hpp">
182188
<Filter>config</Filter>
183189
</ClInclude>
190+
<ClInclude Include="..\..\..\test\net\socket_util.hpp">
191+
<Filter>net</Filter>
192+
</ClInclude>
184193
<ClInclude Include="..\..\..\test\types\json\json_helpers.hpp">
185194
<Filter>types\json</Filter>
186195
</ClInclude>

fly/net/files.mk

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
SRC_DIRS_$(d) := \
2+
$(d)/socket \
3+
$(d)/socket/detail \
4+
$(d)/socket/detail/nix
5+
6+
$(eval $(call WILDCARD_SOURCES, CPP))

fly/net/socket/detail/base_socket.cpp

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#include "fly/net/socket/detail/base_socket.hpp"
2+
3+
#include "fly/net/endpoint.hpp"
4+
#include "fly/net/ipv4_address.hpp"
5+
#include "fly/net/ipv6_address.hpp"
6+
#include "fly/net/socket/detail/socket_operations.hpp"
7+
8+
#include <atomic>
9+
10+
namespace fly::net::detail {
11+
12+
namespace {
13+
14+
std::atomic_uint64_t s_num_sockets {0};
15+
16+
} // namespace
17+
18+
//==================================================================================================
19+
template <typename EndpointType>
20+
BaseSocket<EndpointType>::BaseSocket(socket_type handle, fly::net::IOMode mode) noexcept :
21+
m_socket_handle(handle),
22+
m_socket_id(s_num_sockets.fetch_add(1)),
23+
m_mode(mode)
24+
{
25+
set_io_mode(mode);
26+
}
27+
28+
//==================================================================================================
29+
template <typename EndpointType>
30+
BaseSocket<EndpointType>::BaseSocket(BaseSocket &&socket) noexcept :
31+
m_packet_size(socket.m_packet_size),
32+
m_socket_handle(socket.m_socket_handle),
33+
m_socket_id(socket.m_socket_id),
34+
m_mode(socket.m_mode)
35+
{
36+
socket.m_socket_handle = fly::net::detail::invalid_socket();
37+
}
38+
39+
//==================================================================================================
40+
template <typename EndpointType>
41+
BaseSocket<EndpointType>::~BaseSocket() noexcept
42+
{
43+
close();
44+
}
45+
46+
//==================================================================================================
47+
template <typename EndpointType>
48+
BaseSocket<EndpointType> &BaseSocket<EndpointType>::operator=(BaseSocket &&socket) noexcept
49+
{
50+
m_packet_size = socket.m_packet_size;
51+
m_socket_handle = socket.m_socket_handle;
52+
m_socket_id = socket.m_socket_id;
53+
m_mode = socket.m_mode;
54+
55+
socket.m_socket_handle = fly::net::detail::invalid_socket();
56+
57+
return *this;
58+
}
59+
60+
//==================================================================================================
61+
template <typename EndpointType>
62+
std::optional<EndpointType>
63+
BaseSocket<EndpointType>::hostname_to_endpoint(std::string_view hostname)
64+
{
65+
return fly::net::detail::hostname_to_endpoint<EndpointType>(std::move(hostname));
66+
}
67+
68+
//==================================================================================================
69+
template <typename EndpointType>
70+
socket_type BaseSocket<EndpointType>::handle() const
71+
{
72+
return m_socket_handle;
73+
}
74+
75+
//==================================================================================================
76+
template <typename EndpointType>
77+
std::uint64_t BaseSocket<EndpointType>::socket_id() const
78+
{
79+
return m_socket_id;
80+
}
81+
82+
//==================================================================================================
83+
template <typename EndpointType>
84+
bool BaseSocket<EndpointType>::set_io_mode(fly::net::IOMode mode)
85+
{
86+
if (fly::net::detail::set_io_mode(m_socket_handle, mode))
87+
{
88+
m_mode = mode;
89+
}
90+
else
91+
{
92+
close();
93+
}
94+
95+
return is_valid();
96+
}
97+
98+
//==================================================================================================
99+
template <typename EndpointType>
100+
fly::net::IOMode BaseSocket<EndpointType>::io_mode() const
101+
{
102+
return m_mode;
103+
}
104+
105+
//==================================================================================================
106+
template <typename EndpointType>
107+
bool BaseSocket<EndpointType>::is_valid() const
108+
{
109+
return m_socket_handle != fly::net::detail::invalid_socket();
110+
}
111+
112+
//==================================================================================================
113+
template <typename EndpointType>
114+
std::optional<EndpointType> BaseSocket<EndpointType>::local_endpoint() const
115+
{
116+
return fly::net::detail::local_endpoint<EndpointType>(m_socket_handle);
117+
}
118+
119+
//==================================================================================================
120+
template <typename EndpointType>
121+
void BaseSocket<EndpointType>::close()
122+
{
123+
if (is_valid())
124+
{
125+
fly::net::detail::close(m_socket_handle);
126+
m_socket_handle = fly::net::detail::invalid_socket();
127+
}
128+
}
129+
130+
//==================================================================================================
131+
template <typename EndpointType>
132+
bool BaseSocket<EndpointType>::bind(const EndpointType &endpoint, BindMode option) const
133+
{
134+
return fly::net::detail::bind(m_socket_handle, endpoint, option);
135+
}
136+
137+
//==================================================================================================
138+
template <typename EndpointType>
139+
bool BaseSocket<EndpointType>::bind(std::string_view hostname, port_type port, BindMode option)
140+
const
141+
{
142+
if (auto endpoint = hostname_to_endpoint(std::move(hostname)); endpoint)
143+
{
144+
endpoint->set_port(port);
145+
return bind(*endpoint, option);
146+
}
147+
148+
return false;
149+
}
150+
151+
//==================================================================================================
152+
template class BaseSocket<fly::net::Endpoint<fly::net::IPv4Address>>;
153+
template class BaseSocket<fly::net::Endpoint<fly::net::IPv6Address>>;
154+
155+
} // namespace fly::net::detail

0 commit comments

Comments
 (0)