FastEngine 0.9.5
A multiplayer oriented 2D engine made with Vulkan.
Loading...
Searching...
No Matches
C_socket.hpp
1/*
2 * Copyright 2026 Guillaume Guillet
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _FGE_C_SOCKET_HPP_INCLUDED_
18#define _FGE_C_SOCKET_HPP_INCLUDED_
19
20/*
21 * Original from : https://github.com/SFML/SFML
22 * Copyright (C) 2007-2022 Laurent Gomila
23 *
24 * Altered/Modified by Guillaume Guillet
25 */
26
27#include "FastEngine/fge_extern.hpp"
28#include "FastEngine/network/C_ipAddress.hpp"
29#include <cstdint>
30#include <vector>
31
32#define FGE_SOCKET_ETHERNET_MTU 1500
33#define FGE_SOCKET_IPV4_MIN_MTU 576
34#define FGE_SOCKET_IPV6_MIN_MTU 1280
35#define FGE_SOCKET_IPV4_HEADER_SIZE 20
36#define FGE_SOCKET_IPV6_HEADER_SIZE 40
37#define FGE_SOCKET_UDP_HEADER_SIZE 8
38
39//TODO: Openssl still doesn't have the possibility to allow records size more than 16kB.
40// https://github.com/openssl/openssl/pull/27916
41// https://github.com/openssl/openssl/pull/18248
42// Record Size Limit Extension (RFC 8449)
43// So for now we keep the max datagram size to 16kB
44#define FGE_SOCKET_MAX_MTU (16384)
45
46#define FGE_SOCKET_FULL_DATAGRAM_SIZE (0xFFFF)
47#define FGE_SOCKET_IPV4_MAX_DATAGRAM_SIZE \
48 (FGE_SOCKET_FULL_DATAGRAM_SIZE - FGE_SOCKET_IPV4_HEADER_SIZE - FGE_SOCKET_UDP_HEADER_SIZE)
49#define FGE_SOCKET_IPV6_MAX_DATAGRAM_SIZE \
50 (FGE_SOCKET_FULL_DATAGRAM_SIZE - FGE_SOCKET_IPV6_HEADER_SIZE - FGE_SOCKET_UDP_HEADER_SIZE)
51#define FGE_SOCKET_IPV4_MAX_DATAGRAM_MTU_SIZE \
52 (FGE_SOCKET_IPV4_MIN_MTU - FGE_SOCKET_IPV4_HEADER_SIZE - FGE_SOCKET_UDP_HEADER_SIZE)
53#define FGE_SOCKET_IPV6_MAX_DATAGRAM_MTU_SIZE \
54 (FGE_SOCKET_IPV6_MIN_MTU - FGE_SOCKET_IPV6_HEADER_SIZE - FGE_SOCKET_UDP_HEADER_SIZE)
55#define FGE_SOCKET_IPV4_MAX_DATAGRAM_ETHMTU_SIZE \
56 (FGE_SOCKET_ETHERNET_MTU - FGE_SOCKET_IPV4_HEADER_SIZE - FGE_SOCKET_UDP_HEADER_SIZE)
57#define FGE_SOCKET_IPV6_MAX_DATAGRAM_ETHMTU_SIZE \
58 (FGE_SOCKET_ETHERNET_MTU - FGE_SOCKET_IPV6_HEADER_SIZE - FGE_SOCKET_UDP_HEADER_SIZE)
59
60#define FGE_SOCKET_TCP_DEFAULT_BUFFERSIZE 2048
61
62namespace fge::net
63{
64
65class Packet;
66
72class FGE_API Socket
73{
74public:
75#ifdef _WIN32
76 #if defined(_WIN64)
77 using SocketDescriptor = uint64_t;
78 #else
79 using SocketDescriptor = unsigned int;
80 #endif
81#else
82 using SocketDescriptor = int;
83#endif
84
89 enum class Types
90 {
91 UDP,
92 TCP,
93 TCP_LISTENER,
94 UNKNOWN
95 };
96
101 enum class Errors
102 {
103 ERR_NOERROR = 0,
104 ERR_SUCCESS = ERR_NOERROR,
105 ERR_DONE = ERR_NOERROR,
106
107 ERR_PARTIAL = 1,
108 ERR_NOTREADY = 2,
109 ERR_DISCONNECTED = 3,
110 ERR_REFUSED = 4,
111
112 ERR_ALREADYCONNECTED = 5,
113 ERR_ALREADYUSED = 6,
114 ERR_TOOMANYSOCKET = 7,
115
116 ERR_NOTINIT = 8,
117
118 ERR_INVALIDARGUMENT = 9,
119
120 ERR_UNSUCCESS = 10,
121 ERR_UNKNOWN = ERR_UNSUCCESS
122 };
123
125 {
126 struct Data
127 {
128 IpAddress _unicast;
129 };
130
131 std::string _name;
132 std::string _description;
133 uint16_t _mtu;
134 std::vector<Data> _data;
135 };
136
144 [[nodiscard]] inline Types getType() const { return this->g_type; }
152 [[nodiscard]] inline IpAddress::Types getAddressType() const { return this->g_addressType; }
160 void setAddressType(IpAddress::Types type);
161
167 virtual Errors create() = 0;
171 void close();
179 [[nodiscard]] bool isValid() const;
180
189 [[nodiscard]] Port getLocalPort() const;
198 [[nodiscard]] IpAddress getLocalAddress() const;
208 [[nodiscard]] Port getRemotePort() const;
218 [[nodiscard]] IpAddress getRemoteAddress() const;
219
225 [[nodiscard]] bool isBlocking() const;
226
233 Errors setBlocking(bool mode);
263 Errors setIpv6Only(bool mode);
277
290 Errors select(bool read, uint32_t timeoutms);
291
299 static bool initSocket();
303 static void uninitSocket();
304
317 [[nodiscard]] std::optional<uint16_t> retrieveCurrentAdapterMTU() const;
318
327 [[nodiscard]] static std::vector<AdapterInfo> getAdaptersInfo(IpAddress::Types type = IpAddress::Types::None);
328
334 [[nodiscard]] static int getPlatformSpecifiedError();
335
336 Socket& operator=(Socket const& r) = delete;
337 Socket(Socket const& r) = delete;
338
339protected:
340 explicit Socket(Types type, IpAddress::Types addressType = IpAddress::Types::Ipv4);
341 virtual ~Socket();
342
343 Types g_type;
344 IpAddress::Types g_addressType{IpAddress::Types::Ipv4};
345 SocketDescriptor g_socket;
346 bool g_isBlocking;
347};
348
354class FGE_API SocketUdp : public Socket
355{
356public:
357 explicit SocketUdp(IpAddress::Types addressType = IpAddress::Types::Ipv4);
358 SocketUdp(IpAddress::Types addressType, bool blocking, bool broadcast);
359 ~SocketUdp() override = default;
360
361 Errors create() override;
362
375 Errors connect(IpAddress const& remoteAddress, Port remotePort);
376 Errors disconnect();
387 Errors bind(Port port, IpAddress const& address);
388
400 Errors send(void const* data, std::size_t size);
410 Errors sendTo(void const* data, std::size_t size, IpAddress const& remoteAddress, Port remotePort);
421 Errors receiveFrom(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, Port& remotePort);
434 Errors receive(void* data, std::size_t size, std::size_t& received);
435
456 Errors sendTo(Packet& packet, IpAddress const& remoteAddress, Port remotePort);
465 Errors receiveFrom(Packet& packet, IpAddress& remoteAddress, Port& remotePort);
477
486 [[nodiscard]] static std::optional<uint16_t> retrieveAdapterMTUForDestination(IpAddress const& destination);
487
488 SocketUdp& operator=(SocketUdp&& r) noexcept;
489
490private:
491 std::vector<uint8_t> g_buffer;
492};
493
499class FGE_API SocketTcp : public Socket
500{
501public:
502 explicit SocketTcp(IpAddress::Types addressType = IpAddress::Types::Ipv4);
503 explicit SocketTcp(IpAddress::Types addressType, bool blocking);
504 ~SocketTcp() override = default;
505
511 void flush();
512
522 Errors create(SocketDescriptor sck);
531 Errors create() override;
532
541 Errors connect(IpAddress const& remoteAddress, Port remotePort, uint32_t timeoutms);
542
550 Errors send(void const* data, std::size_t size);
559 Errors send(void const* data, std::size_t size, std::size_t& sent);
568 Errors receive(void* data, std::size_t size, std::size_t& received);
569 Errors receive(void* data, std::size_t size, std::size_t& received, uint32_t timeoutms);
570
588
597 Errors sendAndReceive(Packet& sendPacket, Packet& receivePacket, uint32_t timeoutms);
605 Errors receive(Packet& packet, uint32_t timeoutms);
606
607 SocketTcp& operator=(SocketTcp&& r) noexcept;
608
609private:
610 std::size_t g_receivedSize;
611 std::size_t g_wantedSize;
612 std::vector<uint8_t> g_buffer;
613};
614
620class FGE_API SocketListenerTcp : public Socket
621{
622public:
623 explicit SocketListenerTcp(IpAddress::Types addressType = IpAddress::Types::Ipv4);
624 explicit SocketListenerTcp(IpAddress::Types addressType, bool blocking);
625 ~SocketListenerTcp() override = default;
626
632 Errors create() override;
633
641 Errors listen(Port port, IpAddress const& address);
649
650 SocketListenerTcp& operator=(SocketListenerTcp&& r) noexcept;
651};
652
653} // namespace fge::net
654
655#endif // _FGE_C_SOCKET_HPP_INCLUDED_
A class to represent an IP address.
Definition C_ipAddress.hpp:57
Definition C_packet.hpp:52
Errors accept(SocketTcp &socket)
Accept a new connection.
Errors create() override
Create the socket listener.
Errors listen(Port port, IpAddress const &address)
Start listening for new connections from a port.
A wrapper for TCP sockets inheriting from Socket.
Definition C_socket.hpp:500
Errors receive(Packet &packet, uint32_t timeoutms)
Receive a packet from the connected remote address with a timeout.
Errors create() override
Create a socket.
void flush()
Flush the internal data buffer.
Errors send(Packet &packet)
Send a Packet to the connected remote address.
Errors receive(void *data, std::size_t size, std::size_t &received)
Receive data from the connected remote address.
Errors sendAndReceive(Packet &sendPacket, Packet &receivePacket, uint32_t timeoutms)
Utility function to send and receive data.
Errors connect(IpAddress const &remoteAddress, Port remotePort, uint32_t timeoutms)
Connect to a remote address.
Errors create(SocketDescriptor sck)
Create the socket with an existing descriptor.
Errors send(void const *data, std::size_t size)
Send data to the connected remote address.
Errors send(void const *data, std::size_t size, std::size_t &sent)
Send data to the connected remote address.
Errors receive(Packet &packet)
Receive a Packet from the connected remote address.
Errors bind(Port port, IpAddress const &address)
Bind the socket to a local address and port.
Errors sendTo(void const *data, std::size_t size, IpAddress const &remoteAddress, Port remotePort)
Send data to the specified address.
Errors send(Packet &packet)
Send a Packet to the connected remote address.
Errors send(void const *data, std::size_t size)
Send data to the connected remote address.
Errors create() override
Create a new socket.
Errors connect(IpAddress const &remoteAddress, Port remotePort)
Connect the socket to a remote address and port.
Errors sendTo(Packet &packet, IpAddress const &remoteAddress, Port remotePort)
Send a Packet to the specified address.
Errors receiveFrom(void *data, std::size_t size, std::size_t &received, IpAddress &remoteAddress, Port &remotePort)
Receive data from an unspecified remote address.
Errors receive(void *data, std::size_t size, std::size_t &received)
Receive data from the connected remote address.
Errors receiveFrom(Packet &packet, IpAddress &remoteAddress, Port &remotePort)
Receive a Packet from an unspecified remote address.
Errors receive(Packet &packet)
Receive a Packet from the connected remote address.
static std::optional< uint16_t > retrieveAdapterMTUForDestination(IpAddress const &destination)
Helper to retrieve the MTU of the adapter used to reach the destination ip address.
Errors setBlocking(bool mode)
Set the blocking mode of the socket.
IpAddress::Types getAddressType() const
Get the address type of the socket.
Definition C_socket.hpp:152
std::optional< uint16_t > retrieveCurrentAdapterMTU() const
Retrieve the current adapter MTU.
Errors setBroadcastOption(bool mode)
Set if the socket support broadcast.
Errors
The error codes.
Definition C_socket.hpp:102
Errors setReuseAddress(bool mode)
Set if the socket reuse the address.
Port getLocalPort() const
Get the local port of the socket.
static int getPlatformSpecifiedError()
Get the last platform specific error code.
Errors setDontFragment(bool mode)
Set if the socket should append DF flag to the packet.
Types getType() const
Get the type of the socket.
Definition C_socket.hpp:144
void close()
Close the socket.
void setAddressType(IpAddress::Types type)
Set the address type of the socket.
bool isValid() const
Check if the socket is valid.
Errors setIpv6Only(bool mode)
Set if ipv6 socket should only use ipv6.
Port getRemotePort() const
Get the remote port of the socket.
Errors select(bool read, uint32_t timeoutms)
Check the socket for readability or writability.
Types
The possible types of sockets.
Definition C_socket.hpp:90
static bool initSocket()
Init the low-level socket library.
IpAddress getRemoteAddress() const
Get the remote address of the socket.
virtual Errors create()=0
Create a new socket.
static void uninitSocket()
Shutdown the low-level socket library.
IpAddress getLocalAddress() const
Get the local address of the socket.
static std::vector< AdapterInfo > getAdaptersInfo(IpAddress::Types type=IpAddress::Types::None)
Retrieve adapters information.
bool isBlocking() const
Check if the socket is in blocking mode.
Definition C_socket.hpp:127
Definition C_socket.hpp:125