Added Raw socket type and SocketProtocol to implement ICMP
Renamed TcpSocketBuilder to SocketBuilder
Removed UdpSocketBuilder (merged with SocketBuilder)
This commit is contained in:
TheDoctor
2019-10-21 23:29:29 +01:00
parent 5f13265c5d
commit 03fad4e3d3
14 changed files with 280 additions and 336 deletions

View File

@ -81,16 +81,25 @@ namespace std::net
enum class SocketType enum class SocketType
{ {
Unknown = -1, Unknown = -1,
Raw = 3, // SOCK_RAW
Datagram = 2, //SOCK_DGRAM Datagram = 2, //SOCK_DGRAM
Streaming = 1, //SOCK_STREAM Streaming = 1, //SOCK_STREAM
}; };
enum class SocketProtocol enum class AddressFamily
{ {
IPv4 = 2, // AF_INET IPv4 = 2, // AF_INET
IPv6 = 23 // AF_INET6 IPv6 = 23 // AF_INET6
}; };
enum class SocketProtocol
{
ICMP = 1,
ICMPIpv6 = 58,
Tcp = 6,
Udp = 17,
};
enum class SocketReceiveFlags enum class SocketReceiveFlags
{ {
None = 0, None = 0,

View File

@ -17,13 +17,15 @@ namespace std::net
public: public:
inline ISocket() inline ISocket()
: m_socketType(SocketType::Unknown) : m_socketType(SocketType::Unknown)
, m_protocol(SocketProtocol::IPv4) , m_addressFamily(AddressFamily::IPv4)
, m_socketProtocol(SocketProtocol::Tcp)
{ {
} }
inline ISocket(SocketType InSocketType, SocketProtocol protocol = SocketProtocol::IPv4) inline ISocket(SocketType InSocketType = SocketType::Streaming, AddressFamily af = AddressFamily::IPv4, SocketProtocol proto = SocketProtocol::Tcp)
: m_socketType(InSocketType) : m_socketType(InSocketType)
, m_protocol(protocol) , m_addressFamily(af)
, m_socketProtocol(proto)
{ {
} }
@ -62,13 +64,19 @@ namespace std::net
return m_socketType; return m_socketType;
} }
inline AddressFamily GetSocketAddressFamily() const
{
return m_addressFamily;
}
inline SocketProtocol GetSocketProtocol() const inline SocketProtocol GetSocketProtocol() const
{ {
return m_protocol; return m_socketProtocol;
} }
private: private:
const SocketType m_socketType; const SocketType m_socketType;
const SocketProtocol m_protocol; const AddressFamily m_addressFamily;
const SocketProtocol m_socketProtocol;
}; };
} }

View File

@ -8,14 +8,14 @@ namespace std::net
class Socket : public ISocket class Socket : public ISocket
{ {
public: public:
inline Socket(SocketType socketType, SocketProtocol protocol = SocketProtocol::IPv4) inline Socket(SocketType socketType, AddressFamily af = AddressFamily::IPv4, SocketProtocol proto = SocketProtocol::Tcp)
: ISocket(socketType, protocol) : ISocket(socketType, af)
{ {
init(); init();
} }
inline Socket(SOCKET newSocket, SocketType socketType = SocketType::Streaming, SocketProtocol protocol = SocketProtocol::IPv4) inline Socket(SOCKET newSocket, SocketType socketType = SocketType::Streaming, AddressFamily af = AddressFamily::IPv4, SocketProtocol proto = SocketProtocol::Tcp)
: ISocket(socketType, protocol) : ISocket(socketType, af)
, m_socket(newSocket) , m_socket(newSocket)
{ {
init(); init();

View File

@ -0,0 +1,153 @@
#pragma once
#include "VoidNet_LL/Enums.hpp"
#include "VoidNet_LL/IPAddress.hpp"
#include <vector>
namespace std::net
{
class Socket;
class TcpClient;
class TcpListener;
class UdpSocket;
class SocketBuilder
{
public:
inline SocketBuilder()
: m_blocking(false)
, m_bound(false)
, m_boundAddr(IPAddress::Any, 0)
, m_linger(false)
, m_lingerTimeout(0)
, m_listen(false)
, m_receiveBufferSize(0)
, m_reusable(false)
, m_sendBufferSize(0)
, m_addressFamily(AddressFamily::IPv4)
{
}
inline SocketBuilder Blocking(bool isBlocking)
{
m_blocking = isBlocking;
return *this;
}
inline SocketBuilder Reusable(bool isReusable)
{
m_reusable = isReusable;
return *this;
}
inline SocketBuilder Bind(const IPAddress &addr)
{
m_boundAddr = addr;
m_bound = true;
return *this;
}
inline SocketBuilder Lingering(int32_t Timeout)
{
m_linger = true;
m_lingerTimeout = Timeout;
return *this;
}
inline SocketBuilder Listening()
{
m_listen = true;
return *this;
}
inline SocketBuilder WithReceiveBufferSize(int32_t SizeInBytes)
{
m_receiveBufferSize = SizeInBytes;
return *this;
}
inline SocketBuilder WithSendBufferSize(int32_t SizeInBytes)
{
m_sendBufferSize = SizeInBytes;
return *this;
}
inline SocketBuilder AddressFamily(AddressFamily af)
{
m_addressFamily = af;
return *this;
}
inline SocketBuilder SocketType(SocketType type)
{
m_socketType = type;
return *this;
}
inline SocketBuilder SocketProtocol(SocketProtocol proto)
{
m_socketProtocol = proto;
return *this;
}
// Udp specific
inline SocketBuilder JoinedToGroup(const IPAddress& group_addr)
{
m_joinedGroups.emplace_back(group_addr);
return *this;
}
inline SocketBuilder WithMulticastLoopback()
{
m_multicastLoopback = true;
return *this;
}
inline SocketBuilder WithMulticastTtl(byte time_to_live)
{
m_multicastTtl = time_to_live;
return *this;
}
public:
unique_ptr<Socket> Build();
unique_ptr<TcpClient> BuildClient();
unique_ptr<TcpListener> BuildListener();
unique_ptr<UdpSocket> BuildUdpSocket();
private:
bool m_blocking;
bool m_bound;
IPAddress m_boundAddr;
bool m_linger;
int32_t m_lingerTimeout;
bool m_listen;
int32_t m_receiveBufferSize;
bool m_reusable;
int32_t m_sendBufferSize;
std::net::AddressFamily m_addressFamily;
std::net::SocketType m_socketType = SocketType::Streaming;
std::net::SocketProtocol m_socketProtocol;
//Udp specific
vector<IPAddress> m_joinedGroups;
bool m_multicastLoopback;
byte m_multicastTtl;
};
}

View File

@ -15,7 +15,7 @@ namespace std::net
public: public:
TcpClient(Socket *soc); TcpClient(Socket *soc);
TcpClient(SocketProtocol protocol = SocketProtocol::IPv4); TcpClient(AddressFamily af = AddressFamily::IPv4);
bool Connect(const IPAddress& addrStr); bool Connect(const IPAddress& addrStr);
bool Close() const; bool Close() const;

View File

@ -1,112 +0,0 @@
#pragma once
#include "VoidNet_LL/Enums.hpp"
#include "VoidNet_LL/IPAddress.hpp"
namespace std::net
{
class Socket;
class TcpClient;
class TcpListener;
class TcpSocketBuilder
{
public:
inline TcpSocketBuilder()
: m_blocking(false)
, m_bound(false)
, m_boundAddr(IPAddress::Any, 0)
, m_linger(false)
, m_lingerTimeout(0)
, m_listen(false)
, m_receiveBufferSize(0)
, m_reusable(false)
, m_sendBufferSize(0)
, m_socketProtocol(SocketProtocol::IPv4)
{
}
inline TcpSocketBuilder AsBlocking()
{
m_blocking = true;
return *this;
}
inline TcpSocketBuilder AsNonBlocking()
{
m_blocking = false;
return *this;
}
inline TcpSocketBuilder AsReusable()
{
m_reusable = true;
return *this;
}
inline TcpSocketBuilder Bind(const IPAddress &addr)
{
m_boundAddr = addr;
m_bound = true;
return *this;
}
inline TcpSocketBuilder Lingering(int32_t Timeout)
{
m_linger = true;
m_lingerTimeout = Timeout;
return *this;
}
inline TcpSocketBuilder Listening()
{
m_listen = true;
return *this;
}
inline TcpSocketBuilder WithReceiveBufferSize(int32_t SizeInBytes)
{
m_receiveBufferSize = SizeInBytes;
return *this;
}
inline TcpSocketBuilder WithSendBufferSize(int32_t SizeInBytes)
{
m_sendBufferSize = SizeInBytes;
return *this;
}
inline TcpSocketBuilder Protocol(SocketProtocol prot)
{
m_socketProtocol = prot;
return *this;
}
public:
unique_ptr<Socket> Build() const;
unique_ptr<TcpClient> BuildClient() const;
unique_ptr<TcpListener> BuildListener() const;
private:
bool m_blocking;
bool m_bound;
IPAddress m_boundAddr;
bool m_linger;
int32_t m_lingerTimeout;
bool m_listen;
int32_t m_receiveBufferSize;
bool m_reusable;
int32_t m_sendBufferSize;
SocketProtocol m_socketProtocol;
};
}

View File

@ -10,7 +10,7 @@ namespace std::net
{ {
public: public:
UdpSocket(Socket *soc); UdpSocket(Socket *soc);
UdpSocket(SocketProtocol protocol = SocketProtocol::IPv4); UdpSocket(AddressFamily af = AddressFamily::IPv4);
bool Bind(const IPAddress &addr); bool Bind(const IPAddress &addr);
bool SendTo(const byte* data, int32_t count, int32_t& sent, const IPAddress& addrDest); bool SendTo(const byte* data, int32_t count, int32_t& sent, const IPAddress& addrDest);

View File

@ -1,152 +0,0 @@
#pragma once
#include "VoidNet_LL/UdpSocket.hpp"
#include "VoidNet_LL/IPAddress.hpp"
#include <vector>
namespace std::net
{
class UdpSocketBuilder
{
public:
UdpSocketBuilder()
: m_blocking(false)
, m_bound(false)
, m_boundEndpoint(IPAddress::Any, 0)
, m_multicastLoopback(false)
, m_multicastTtl(1)
, m_receiveBufferSize(0)
, m_reusable(false)
, m_sendBufferSize(0)
{ }
public:
UdpSocketBuilder AsBlocking()
{
m_blocking = true;
return *this;
}
UdpSocketBuilder AsNonBlocking()
{
m_blocking = false;
return *this;
}
UdpSocketBuilder AsReusable()
{
m_reusable = true;
return *this;
}
UdpSocketBuilder BoundToAddress(const IPAddress& addr)
{
m_boundEndpoint = IPAddress(addr);
m_bound = true;
return *this;
}
UdpSocketBuilder BoundToPort(uint16_t port)
{
m_boundEndpoint = IPAddress(m_boundEndpoint.ToInteger(), port);
m_bound = true;
return *this;
}
UdpSocketBuilder JoinedToGroup(const IPAddress& group_addr)
{
m_joinedGroups.emplace_back(group_addr);
return *this;
}
UdpSocketBuilder WithMulticastLoopback()
{
m_multicastLoopback = true;
return *this;
}
UdpSocketBuilder WithMulticastTtl(byte time_to_live)
{
m_multicastTtl = time_to_live;
return *this;
}
UdpSocketBuilder WithReceiveBufferSize(uint32_t size)
{
m_receiveBufferSize = size;
return *this;
}
UdpSocketBuilder WithSendBufferSize(uint32_t size)
{
m_sendBufferSize = size;
return *this;
}
public:
unique_ptr<UdpSocket> Build() const
{
unique_ptr<Socket> soc = make_unique<Socket>(SocketType::Datagram);
if (soc)
{
bool Error =
!soc->SetNonBlocking(!m_blocking) ||
!soc->SetReuseAddr(m_reusable);
if (!Error)
Error = m_bound && !soc->Bind(m_boundEndpoint);
if (!Error)
Error = !soc->SetMulticastLoopback(m_multicastLoopback) || !soc->SetMulticastTtl(m_multicastTtl);
if (!Error)
{
for (const auto& Group : m_joinedGroups)
{
if (!soc->JoinMulticastGroup(IPAddress(Group, 0)))
{
Error = true;
break;
}
}
}
if (!Error)
{
int32_t out_new_size;
if (m_receiveBufferSize > 0)
soc->SetReceiveBufferSize(m_receiveBufferSize, out_new_size);
if (m_sendBufferSize > 0)
soc->SetSendBufferSize(m_sendBufferSize, out_new_size);
}
if (Error)
throw runtime_error("Couldnt create socket"); // make parameter a string depending on the error
return make_unique<UdpSocket>();
}
return unique_ptr<UdpSocket>(nullptr);
}
private:
bool m_blocking;
bool m_bound;
IPAddress m_boundEndpoint;
vector<IPAddress> m_joinedGroups;
bool m_multicastLoopback;
byte m_multicastTtl;
uint32_t m_receiveBufferSize;
bool m_reusable;
uint32_t m_sendBufferSize;
};
}

View File

@ -1,7 +1,7 @@
#include "VoidNet_HL/TcpServer.hpp" #include "VoidNet_HL/TcpServer.hpp"
#include "VoidNet_HL/TcpConnection.hpp" #include "VoidNet_HL/TcpConnection.hpp"
#include "VoidNet_LL/TcpSocketBuilder.hpp" #include "VoidNet_LL/SocketBuilder.hpp"
#include "VoidNet_LL/TcpClient.hpp" #include "VoidNet_LL/TcpClient.hpp"
#include "VoidNet_HL/TcpConnectionHandler.hpp" #include "VoidNet_HL/TcpConnectionHandler.hpp"
@ -15,7 +15,7 @@ namespace std::net
if (port == 0) if (port == 0)
throw invalid_argument("TcpServer::TcpServer()"); throw invalid_argument("TcpServer::TcpServer()");
listener = shared_ptr<TcpListener>(TcpSocketBuilder().AsReusable().Bind(IPAddress(0, 0, 0, 0, port)).Listening().BuildListener().release()); listener = shared_ptr<TcpListener>(SocketBuilder().Reusable(true).Bind(IPAddress(0, 0, 0, 0, port)).Listening().BuildListener().release());
m_connectionHandler = make_shared<TcpConnectionHandler>(listener); m_connectionHandler = make_shared<TcpConnectionHandler>(listener);
m_connectionHandler->SetMaxConnections(max_connections); m_connectionHandler->SetMaxConnections(max_connections);
} }

View File

@ -0,0 +1,88 @@
#include "VoidNet_LL/SocketBuilder.hpp"
#include "VoidNet_LL/Socket.hpp"
#include "VoidNet_LL/TcpClient.hpp"
#include "VoidNet_LL/TcpListener.hpp"
#include "VoidNet_LL/UdpSocket.hpp"
namespace std::net
{
unique_ptr<Socket> SocketBuilder::Build()
{
if (m_socketType == SocketType::Streaming)
m_socketProtocol = SocketProtocol::Tcp;
else if (m_socketType == SocketType::Datagram)
m_socketProtocol = SocketProtocol::Udp;
unique_ptr<Socket> socket = make_unique<Socket>(m_socketType, m_addressFamily, m_socketProtocol);
if (socket != nullptr)
{
bool Error = !socket->SetReuseAddr(m_reusable) ||
!socket->SetLinger(m_linger, m_lingerTimeout);
if (!Error)
{
if (m_bound)
Error = !socket->Bind(m_boundAddr);
}
if (!Error)
{
if (m_listen)
Error = !socket->Listen();
}
if (!Error)
Error = !socket->SetNonBlocking(!m_blocking);
if (m_socketType == SocketType::Datagram || m_socketType == SocketType::Raw)
{
if (!Error)
{
if (m_multicastLoopback)
Error = !socket->SetMulticastLoopback(m_multicastLoopback) || !socket->SetMulticastTtl(m_multicastTtl);
}
if (!Error)
{
for (const auto& Group : m_joinedGroups)
{
if (!socket->JoinMulticastGroup(IPAddress(Group, 0)))
{
Error = true;
break;
}
}
}
}
if (!Error)
{
int32_t out_new_size;
if (m_receiveBufferSize > 0)
socket->SetReceiveBufferSize(m_receiveBufferSize, out_new_size);
if (m_sendBufferSize > 0)
socket->SetSendBufferSize(m_sendBufferSize, out_new_size);
}
if (Error)
throw runtime_error("Couldnt create socket"); // make parameter a string depending on the error
}
return socket;
}
unique_ptr<TcpClient> SocketBuilder::BuildClient()
{
return std::make_unique<TcpClient>(Build().release());
}
unique_ptr<TcpListener> SocketBuilder::BuildListener()
{
return std::make_unique<TcpListener>(Build().release());
}
unique_ptr<UdpSocket> SocketBuilder::BuildUdpSocket()
{
return std::make_unique<UdpSocket>(Build().release());
}
}

View File

@ -1,5 +1,5 @@
#include "VoidNet_LL/TcpClient.hpp" #include "VoidNet_LL/TcpClient.hpp"
#include "VoidNet_LL/TcpSocketBuilder.hpp" #include "VoidNet_LL/SocketBuilder.hpp"
namespace std::net namespace std::net
{ {
@ -8,9 +8,9 @@ namespace std::net
m_socket = unique_ptr<Socket>(soc); // will this work m_socket = unique_ptr<Socket>(soc); // will this work
} }
TcpClient::TcpClient(SocketProtocol protocol) TcpClient::TcpClient(AddressFamily af)
{ {
m_socket = TcpSocketBuilder().AsNonBlocking().AsReusable().Protocol(protocol).Build(); m_socket = SocketBuilder().Blocking(true).Reusable(true).AddressFamily(af).Build();
} }
bool TcpClient::Connect(const IPAddress& addrStr) bool TcpClient::Connect(const IPAddress& addrStr)

View File

@ -1,5 +1,5 @@
#include "VoidNet_LL/TcpListener.hpp" #include "VoidNet_LL/TcpListener.hpp"
#include "VoidNet_LL/TcpSocketBuilder.hpp" #include "VoidNet_LL/SocketBuilder.hpp"
#include "VoidNet_LL/Socket.hpp" #include "VoidNet_LL/Socket.hpp"
#include "VoidNet_LL/TcpClient.hpp" #include "VoidNet_LL/TcpClient.hpp"
@ -9,7 +9,7 @@ namespace std::net
: m_port(port) : m_port(port)
, m_sleepTime(inSleepTime) , m_sleepTime(inSleepTime)
{ {
m_socket = TcpSocketBuilder().AsNonBlocking().AsReusable().Bind(IPAddress(0, 0, 0, 0, port)).Listening().Build(); m_socket = SocketBuilder().Blocking(false).Reusable(true).Bind(IPAddress(0, 0, 0, 0, port)).Listening().Build();
} }
TcpListener::TcpListener(Socket *InSocket, chrono::milliseconds inSleepTime) TcpListener::TcpListener(Socket *InSocket, chrono::milliseconds inSleepTime)
@ -21,7 +21,7 @@ namespace std::net
TcpClient *TcpListener::AcceptClient() TcpClient *TcpListener::AcceptClient()
{ {
if (m_socket == nullptr) if (m_socket == nullptr)
m_socket = TcpSocketBuilder().AsReusable().Bind(IPAddress(0, 0, 0, 0, m_port)).Listening().Build(); m_socket = SocketBuilder().Reusable(true).Bind(IPAddress(0, 0, 0, 0, m_port)).Listening().Build();
if (m_socket == nullptr) if (m_socket == nullptr)
return nullptr; return nullptr;

View File

@ -1,50 +0,0 @@
#include "VoidNet_LL/TcpSocketBuilder.hpp"
#include "VoidNet_LL/Socket.hpp"
#include "VoidNet_LL/TcpClient.hpp"
#include "VoidNet_LL/TcpListener.hpp"
namespace std::net
{
unique_ptr<Socket> TcpSocketBuilder::Build() const
{
unique_ptr<Socket> socket = make_unique<Socket>(SocketType::Streaming, m_socketProtocol);
if (socket != nullptr)
{
bool Error = !socket->SetReuseAddr(m_reusable) ||
!socket->SetLinger(m_linger, m_lingerTimeout);
if (!Error)
Error = m_bound && !socket->Bind(m_boundAddr);
if (!Error)
Error = m_listen && !socket->Listen();
if (!Error)
Error = !socket->SetNonBlocking(!m_blocking);
if (!Error)
{
int32_t out_new_size;
if (m_receiveBufferSize > 0)
socket->SetReceiveBufferSize(m_receiveBufferSize, out_new_size);
if (m_sendBufferSize > 0)
socket->SetSendBufferSize(m_sendBufferSize, out_new_size);
}
if (Error)
throw runtime_error("Couldnt create socket"); // make parameter a string depending on the error
}
return socket;
}
unique_ptr<TcpClient> TcpSocketBuilder::BuildClient() const
{
return std::make_unique<TcpClient>(Build().release());
}
unique_ptr<TcpListener> TcpSocketBuilder::BuildListener() const
{
return std::make_unique<TcpListener>(Build().release());
}
}

View File

@ -7,9 +7,9 @@ namespace std::net
m_socket = unique_ptr<Socket>(soc); // will this work m_socket = unique_ptr<Socket>(soc); // will this work
} }
UdpSocket::UdpSocket(SocketProtocol protocol) UdpSocket::UdpSocket(AddressFamily af)
{ {
m_socket = make_unique<Socket>(SocketType::Datagram, protocol); m_socket = make_unique<Socket>(SocketType::Datagram, af);
} }
bool UdpSocket::Bind(const IPAddress & addr) bool UdpSocket::Bind(const IPAddress & addr)