This Dick

This commit is contained in:
2025-01-18 06:04:48 -05:00
parent ad365c7b19
commit fe7e7a179b
12 changed files with 679 additions and 188 deletions

View File

@@ -58,5 +58,8 @@ install(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME})
add_subdirectory(tests)
add_executable(SocketDemo main.cpp)
add_executable(SocketDemo main.cpp
include/Sockets/BaseSocket.hpp
include/Sockets/TcpSocket.hpp
include/Sockets/UdpSocket.hpp)
target_link_libraries(SocketDemo ${PROJECT_NAME})

View File

@@ -0,0 +1,70 @@
#pragma once
#if defined(__linux__) || defined(__APPLE__)
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#elif _WIN32
#include <winsock32.h>
#endif
#include <string>
#include <functional>
#include <cerrno>
#define FDR_UNUSED(expr){ (void)(expr); }
#define FDR_ON_ERROR std::function<void(int, std::string)> onError = [] (int errorCode, std::string errorMessage) {FDR_UNUSED(errorCode); FDR_UNUSED(errorMessage) }
#ifndef AS_DEFAULT_BUFFER_SIZE
#define AS_DEFAULT_BUFFER_SIZE 0x1000 // 4096 bytes
#endif
class BaseSocket
{
public:
enum SocketType {
TCP = SOCK_STREAM,
UDP = SOCK_DGRAM
};
sockaddr_in address;
void Close() {
shutdown(this->sock, SHUT_RDWR);
close(this->sock);
}
std::string RemoteAddress() const { return IPToString(this->address); };
int RemotePort() const { return ntohs(this->address.sin_port); }
int FileDescriptor() const { return this->sock; }
protected:
int sock = 0;
// Get std::string value of the IP from a `sockaddr_in` address struct
static std::string IPToString(const sockaddr_in& addr)
{
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(addr.sin_addr), ip, INET_ADDRSTRLEN);
return std::string(ip);
}
BaseSocket(FDR_ON_ERROR, SocketType sockType = TCP, int socketID = -1)
{
if (socketID == -1) {
this->sock = socket(AF_INET, sockType, 0);
if (this->sock == -1)
{
onError(errno, "Socket creating error.");
}
} else {
this->sock = socketID;
}
}
virtual ~BaseSocket() {}
};

View File

@@ -8,7 +8,7 @@ namespace Socket {
/// Generic Socket Error Handling Functions
// The following are general socket errors only. There may be other domain-specific error codes.
// Semantically, these error codes are meant for the developer of UdpSocket/TcpSocket (Me)
// Semantically, these error codes are meant for the developer of UdpSocket_Old/TcpSocket_Old (Me)
// TODO: translate error messages to be meaningful for the API consumer
// TODO: Align Sockets folder and namespace

View File

@@ -1,4 +1,87 @@
namespace Sockets
{
#pragma once
}
#include <Sockets/TcpSocket.hpp>
#include <thread>
template <uint16_t BUFFER_SIZE = AS_DEFAULT_BUFFER_SIZE>
class TcpServer : public BaseSocket
{
public:
// Event Listeners
std::function<void(TcpSocket<BUFFER_SIZE>*)> onNewConnection = [](TcpSocket<BUFFER_SIZE>* sock) {FDR_UNUSED(sock)};
explicit TcpServer(FDR_ON_ERROR) : BaseSocket(onError, SocketType::TCP)
{
int opt = 1;
setsockopt(this->sock, SOL_SOCKET< SO_REUSEADDR, &opt, sizeof(int));
setsockopt(this->sock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(int));
}
// Bind the custom address & port of the server.
void Bind(const char* address, uint16_t port, FDR_ON_ERROR)
{
int status = inet_pton(AF_INET, address, &this->address.sin_addr);
switch(status) {
case -1:
onError(errno, "Invalid address. Address type not supported.");
return;
case 0:
onError(errno, "AF_INET is not supported. Please send message to developer.");
return;
default:
break;
}
this->address.sin_family = AF_INET;
this->address.sin_port = htons(port);
if (bind(this->sock, (const sockaddr*)&this->address, sizeof(this->address)) == -1)
{
onError(errno, "Cannot bind the socket.");
return;
}
}
// Bind the address (0.0.0.0) & port of the server
void Bind(uint16_t port, FDR_ON_ERROR){ this->Bind("0.0.0.0", port, onError); }
// Start listening incoming connections
void Listen(FDR_ON_ERROR)
{
if (listen(this->sock, 20) == -1)
{
onError(errno, "Error: Server can't listen the socket.");
return;
}
std::thread t(Accept, this, onError);
t.detach();
}
private:
static void Accept(TcpServer<BUFFER_SIZE>* server, FDR_ON_ERROR)
{
sockaddr_in newSocketInfo;
socklen_t newSocketInfoLength = sizeof(newSocketInfo);
int newSocketFileDescriptor = -1;
while (true)
{
newSocketFileDescriptor = accept(server->sock, (sockaddr*)&newSocketInfo, &newSocketInfoLength);
if (newSocketFileDescriptor == -1) {
if (errno == EBADF || errno == EINVAL) return;
onError(errno, "Error while accepting a new connection.");
return;
}
TcpSocket<BUFFER_SIZE>* newSocket = new TcpSocket<BUFFER_SIZE>(onError, newSocketFileDescriptor);
newSocket->deleteAfterClosed = true;
newSocket->setAddressStruct(newSocketInfo);
server->onNewConnection(newSocket);
newSocket->Listen();
}
}
};

View File

@@ -1,56 +1,135 @@
#pragma once
#include <iostream>
#include <Sockets/BaseSocket.hpp>
#include <string>
#include <netdb.h>
#include <memory>
#include <cstring>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <Sockets/Sockets.hpp>
#include <functional>
#include <thread>
#include <Sockets/IPAddress.hpp>
template <uint16_t BUFFER_SIZE = AS_DEFAULT_BUFFER_SIZE>
class TcpSocket : public BaseSocket
{
public:
// TODO: Will probably change these to Event<...> signature.
// Event Listeners:
std::function<void(std::string)> onMessageReceived;
std::function<void(const char*, ssize_t)> onRawMessageReceived;
std::function<void(int)> onSocketClosed;
#ifndef INPORT_ANY
#define INPORT_ANY 0
#endif
explicit TcpSocket(FDR_ON_ERROR, int socketID = -1) : BaseSocket(onError, TCP, socketID) {}
namespace Socket {
/// A general purpose TCP interface
/// TCP (Transmission Control Protocol) provides reliable, ordered, and error-checked delivery of
/// a stream of bytes between peers.
class TcpSocket {
public:
TcpSocket();
TcpSocket(int family, int flags);
TcpSocket(int socket, addrinfo info, bool connected, bool bound);
virtual ~TcpSocket();
// Send raw bytes
ssize_t Send(const char* bytes, size_t byteslength) { return send(this->sock, bytes, byteslength, 0); }
TcpSocket(const TcpSocket &socket) = default;
TcpSocket &operator=(const TcpSocket &socket) = delete;
void Bind(uint16_t port);
void BindAny();
void BindAny(uint16_t&portno);
void Connect(const IPAddress& ipaddr);
void Connect(std::string address, uint16_t port);
void Listen(int maxQueue);
std::shared_ptr<TcpSocket> Accept();
void Send(const u8 *data, unsigned int length, int flags);
// Receive data (blocking)
// @return true if socket is still open, false otherwise
bool Receive(u8* msg, int len, int flags);
void Close();
private:
void setInfo(int port);
void setInfo(std::string address, int port);
void openSocket(addrinfo *info);
addrinfo * mInfo;
int mSock = -1;
bool mSockCreated = false;
bool mBound = false;
bool mConnected = false;
bool mClosed = false;
};
}
// Send std::string
ssize_t Send(const std::string& message) { return this->Send(message.c_str(), message.length()); }
// Connect to a TCP server with `uint32_t ipv4` and `uint16_t port` values
void Connect(uint32_t ipv4, uint16_t port, std::function<void()> onConnected = [](){}, FDR_ON_ERROR)
{
this->address.sin_family = AF_INET;
this->address.sin_port = htons(port);
this->address.sin_addr.s_addr = ipv4;
this->setTimeout(5);
// Try to connect.
int status = connect(this->sock, (const sockaddr*)&this->address, sizeof(sockaddr_in));
if (status == -1)
{
onError(errno, "Connection failed to the host.");
this->setTimeout(0);
return;
}
this->setTimeout(0);
// Connected to the server, fire the event.
onConnected();
// Start listening from server.
this->Listen();
}
// Connect to a TCP server with `const char* host` & `uint16_t port` values.
void Connect(const char* host, uint16_t port, std::function<void()> onConnected = [](){}, FDR_ON_ERROR)
{
struct addrinfo hints, *res, *it;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
// Get address info from DNS
int status = getaddrinfo(host, NULL, &hints, &res);
if (status != 0) {
onError(errno, "Invalid address." + std::string(gai_strerror(status)));
return;
}
for (it = res; it != NULL; it = it->ai_next) {
if (it->ai_family == AF_INET) { // IPv4
memcpy((void*)(&this->address), (void*)it->ai_addr, sizeof(sockaddr_in));
break; // for now, just get the first ip (ipv4).
}
}
freeaddrinfo(res);
this->Connect((uint32_t)this->address.sin_addr.s_addr, port, onConnected, onError);
}
// Connect to a TCP server with `const std::string& ipv4` & `uint16_t port` values
void Connect(const std::string& host, uint16_t port, std::function<void()> onConnected = [](){}, FDR_ON_ERROR)
{
this->Connect(host.c_str(), port, onConnected, onError);
}
// Start another thread to listen to the socket
void Listen()
{
std::thread t(TcpSocket::Receive, this);
t.detach();
}
void SetAddressStruct(sockaddr_in addr) { this->address = addr; }
sockaddr_in GetAddressStruct() const { return this->address; }
bool deleteAfterClosed = false;
private:
static void Receive(TcpSocket* socket)
{
char tempBuffer[BUFFER_SIZE+1];
ssize_t messageLength;
while ((messageLength = recv(socket->sock, tempBuffer, BUFFER_SIZE, 0)) > 0) {
tempBuffer[messageLength] = '\0';
if (socket->onMessageReceived)
socket->onMessageReceived(std::string(tempBuffer, messageLength));
if (socket->onRawMessageReceived)
socket->onRawMessageReceived(tempBuffer, messageLength);
}
socket->Close();
if (socket->onSocketClosed)
socket->onSocketClosed(errno);
if (socket->deleteAfterClosed && socket != nullptr)
delete socket;
}
void setTimeout(int seconds)
{
struct timeval tv;
tv.tv_sec = seconds;
tv.tv_usec = 0;
setsockopt(this->sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
setsockopt(this->sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
}
};

View File

@@ -0,0 +1,56 @@
#pragma once
#include <iostream>
#include <string>
#include <netdb.h>
#include <memory>
#include <cstring>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <Sockets/Sockets.hpp>
#include <Sockets/IPAddress.hpp>
#ifndef INPORT_ANY
#define INPORT_ANY 0
#endif
namespace Socket {
/// A general purpose TCP interface
/// TCP (Transmission Control Protocol) provides reliable, ordered, and error-checked delivery of
/// a stream of bytes between peers.
class TcpSocket_Old {
public:
TcpSocket_Old();
TcpSocket_Old(int family, int flags);
TcpSocket_Old(int socket, addrinfo info, bool connected, bool bound);
virtual ~TcpSocket_Old();
TcpSocket_Old(const TcpSocket_Old &socket) = default;
TcpSocket_Old &operator=(const TcpSocket_Old &socket) = delete;
void Bind(uint16_t port);
void BindAny();
void BindAny(uint16_t&portno);
void Connect(const IPAddress& ipaddr);
void Connect(std::string address, uint16_t port);
void Listen(int maxQueue);
std::shared_ptr<TcpSocket_Old> Accept();
void Send(const u8 *data, unsigned int length, int flags);
// Receive data (blocking)
// @return true if socket is still open, false otherwise
bool Receive(u8* msg, int len, int flags);
void Close();
private:
void setInfo(int port);
void setInfo(std::string address, int port);
void openSocket(addrinfo *info);
addrinfo * mInfo;
int mSock = -1;
bool mSockCreated = false;
bool mBound = false;
bool mConnected = false;
bool mClosed = false;
};
}

View File

@@ -1,23 +1,53 @@
#pragma once
#include <Sockets/UdpPeer.hpp>
#include <vector>
#include <string>
#include "UdpSocket.hpp"
#include <thread>
namespace Sockets
template <uint16_t BUFFER_SIZE = AS_DEFAULT_BUFFER_SIZE>
class UDPServer : public UDPSocket<BUFFER_SIZE>
{
/// UDP Server is a wrapper around UdpSocket that keeps track of connections and message-history between it and a list of "Udp Peers" AKA clients
class UdpServer : public UdpPeer
public:
// Bind the custom address & port of the server.
void Bind(const char* address, std::uint16_t port, FDR_ON_ERROR)
{
std::vector<UdpPeer> Peers;
int status = inet_pton(AF_INET, address, &this->address.sin_addr);
switch (status) {
case -1:
onError(errno, "Invalid address. Address type not supported.");
return;
case 0:
onError(errno, "AF_INET is not supported. Please send message to developer.");
return;
default:
break;
}
virtual bool Start();
virtual bool Start(const std::string& multicast_addr, int multicast_port);
virtual bool Stop();
virtual bool Restart();
virtual void SendToPeer();
virtual void SendToAllPeers();
virtual void SendToAllPeersExcept();
virtual void SendToPeerlist(std::vector<UdpPeer> peerlist);
};
}
this->address.sin_family = AF_INET;
this->address.sin_port = htons(port);
status = bind(this->sock, (const sockaddr*)&this->address, sizeof(this->address));
if (status == -1)
{
onError(errno, "Cannot bind the socket.");
return;
}
}
// Bind the address(0.0.0.0) & port of the server.
void Bind(uint16_t port, FDR_ON_ERROR)
{
this->Bind("0.0.0.0", port, onError);
}
// Enable or disable the SO_BROADCAST flag
void setBroadcast(bool value, FDR_ON_ERROR)
{
int broadcast = static_cast<int>(value);
int status = setsockopt(this->sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast);
if (status == -1)
{
onError(errno, "setsockopt(SO_BROADCAST) failed.");
return;
}
}
};

View File

@@ -1,91 +1,170 @@
#pragma once
#include <Sockets/IPAddress.hpp>
#include <string>
#include "BaseSocket.hpp"
#include <string.h>
#include <thread>
// Game-specific Network code written against GameNetworkingSocket API
// GameNetworkingServer
// GameNetworkingClient
// GameNetworkingSocket
// UdpReliability
// TcpServer
// TcpClient
// UdpServer
// UdpClient
// UdpSocket
// TcpSocket
// Berkeley Sockets API
#ifndef INPORT_ANY
#define INPORT_ANY 0
#endif
namespace Socket
template <uint16_t BUFFER_SIZE = AS_DEFAULT_BUFFER_SIZE>
class UDPSocket : public BaseSocket
{
public:
std::function<void(std::string, std::string, std::uint16_t)> onMessageReceived;
std::function<void(const char*, ssize_t, std::string, std::uint16_t)> onRawMessageReceived;
// TODO: Implement Blocking and Nonblocking UDP
explicit UDPSocket(bool useConnect = false, FDR_ON_ERROR, int socketId = -1): BaseSocket(onError, SocketType::UDP, socketId)
{
if (useConnect)
{
std::thread t(Receive, this); // usage with Connect()
t.detach();
}
else
{
std::thread t(ReceiveFrom, this);
t.detach();
}
}
using u8 = uint8_t;
// Send raw bytes to a spesific `host` & `port` with no connection
ssize_t SendTo(const char* bytes, size_t byteslength, const char* host, uint16_t port, FDR_ON_ERROR)
{
sockaddr_in hostAddr;
typedef struct sockaddr_in sockaddr_in_t;
typedef struct sockaddr sockaddr_t;
typedef std::vector<uint8_t> msg_t;
struct addrinfo hints, *res, *it;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
// UdpSocket is a class wrapper around BSD Sockets API for the UDP protocol.
class UdpSocket {
public:
int status;
if ((status = getaddrinfo(host, NULL, &hints, &res)) != 0)
{
onError(errno, "Invalid address." + std::string(gai_strerror(status)));
return -1;
}
/// Default Constructor which creates an empty, uninitialized, and unconnected UDP socket.
UdpSocket() {}
UdpSocket(int family, int flags);
UdpSocket(int socket, addrinfo info, bool connected, bool bound);
~UdpSocket() {}
UdpSocket(const UdpSocket &socket) = default;
UdpSocket &operator=(const UdpSocket &socket) = delete;
void Open();
int Close();
bool IsClosed() const { return sock < 0;}
void Bind(const IPAddress& ipAddress);
void Bind(uint16_t portno);
void BindAny();
void BindAny(uint16_t& portno);
for (it = res; it != NULL; it = it->ai_next)
{
if (it->ai_family == AF_INET)
{ // IPv4
memcpy((void* )(&hostAddr), (void* )it->ai_addr, sizeof(sockaddr_in));
break; // for now, just get first ip (ipv4).
}
}
bool Connected() const;
freeaddrinfo(res);
/// In UDP, the client does not form a connection with the server like in TCP, and instead, it just sends a datagram.
/// Similarly, the server need not accept a connection and just waits for datagrams to arrive. There is no 3 way handshake.
/// It just checks for any immediate errors and stores the peer's IP address and port number.
void Connect(const std::string& hostname, u16 port);
void Connect(const IPAddress& ipaddr);
void Connect(u16 port);
hostAddr.sin_port = htons(port);
hostAddr.sin_family = AF_INET;
[[nodiscard]] IPAddress GetSelfIP() const {return self_addr;}
[[nodiscard]] IPAddress GetPeerIP() const {return peer_addr;}
ssize_t sent_length = sendto(this->sock, bytes, byteslength, 0, (sockaddr*)&hostAddr, sizeof(hostAddr));
if (sent_length == -1)
{
onError(errno, "Cannot send message to the address.");
return -1;
}
return sent_length;
}
// Send raw bytes to a spesific `host` & `port` with no connection
ssize_t SendTo(const char* bytes, size_t byteslength, const std::string& host, uint16_t port, FDR_ON_ERROR)
{
return this->SendTo(bytes, byteslength, host.c_str(), port, onError);
}
// Send std::string to a spesific `host` & `port` with no connection
ssize_t SendTo(const std::string& message, const char* host, uint16_t port, FDR_ON_ERROR)
{
return this->SendTo(message.c_str(), message.length(), host, port, onError);
}
// Send std::string to a spesific `host` & `port` with no connection
ssize_t SendTo(const std::string& message, const std::string& host, uint16_t port, FDR_ON_ERROR)
{
return this->SendTo(message.c_str(), message.length(), host.c_str(), port, onError);
}
/// Sends a message to the bound peer only.
int Send(const u8 *data, unsigned int length, int flags = 0);
int Send(const std::vector<u8>& payload);
// Send raw bytes to the `Connect()`ed server.
ssize_t Send(const char* bytes, size_t byteslength) { return send(this->sock, bytes, byteslength, 0); }
// Send std::string to the `Connect()`ed server.
ssize_t Send(const std::string& message) { return this->Send(message.c_str(), message.length()); }
/// Sends a message to a specified IPAddress.
int SendTo(const IPAddress& ipaddr, const u8 *data, unsigned int length, int flags);
int SendTo(const IPAddress& ipaddr, const std::vector<u8> data);
// Connect to a server with raw `uint32_t ipv4` and `uint16_t port` values.
void Connect(uint32_t ipv4, uint16_t port, FDR_ON_ERROR)
{
this->address.sin_family = AF_INET;
this->address.sin_port = htons(port);
this->address.sin_addr.s_addr = ipv4;
int Receive(IPAddress& ipaddr, const u8 *message) const;
int ReceiveFromAny(const u8 *message);
// Try to connect.
int status = connect(this->sock, (const sockaddr* )&this->address, sizeof(sockaddr_in));
if (status == -1)
{
onError(errno, "Connection failed to the host.");
return;
}
}
// Connect to a server with `host` address and `port` values.
void Connect(const char* host, uint16_t port, FDR_ON_ERROR)
{
struct addrinfo hints, *res, *it;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
int Broadcast(int opt) const;
void Interrupt() const;
private:
int sock{-1};
sockaddr_in_t self_addr{};
socklen_t self_addr_len = sizeof(self_addr);
sockaddr_in_t peer_addr{};
socklen_t peer_addr_len = sizeof(peer_addr);
bool connected = false;
int status = getaddrinfo(host, NULL, &hints, &res);
if (status != 0)
{
onError(errno, "Invalid address." + std::string(gai_strerror(status)));
return;
}
for (it = res; it != NULL; it = it->ai_next)
{
if (it->ai_family == AF_INET)
{ // IPv4
memcpy((void* )(&this->address), (void*)it->ai_addr, sizeof(sockaddr_in));
break; // for now, just get first ip (ipv4).
}
}
};
}
freeaddrinfo(res);
this->Connect((uint32_t)this->address.sin_addr.s_addr, port, onError);
}
// Connect to a server with `host` address and `port` values.
void Connect(const std::string& host, uint16_t port, FDR_ON_ERROR) { this->Connect(host.c_str(), port, onError); }
private:
static void Receive(UDPSocket* udpSocket)
{
char tempBuffer[BUFFER_SIZE+1];
ssize_t messageLength;
while ((messageLength = recv(udpSocket->sock, tempBuffer, BUFFER_SIZE, 0)) != -1)
{
tempBuffer[messageLength] = '\0';
if (udpSocket->onMessageReceived)
udpSocket->onMessageReceived(std::string(tempBuffer, messageLength), ipToString(udpSocket->address), ntohs(udpSocket->address.sin_port));
if (udpSocket->onRawMessageReceived)
udpSocket->onRawMessageReceived(tempBuffer, messageLength, ipToString(udpSocket->address), ntohs(udpSocket->address.sin_port));
}
}
static void ReceiveFrom(UDPSocket* udpSocket)
{
sockaddr_in hostAddr;
socklen_t hostAddrSize = sizeof(hostAddr);
char tempBuffer[BUFFER_SIZE+1];
ssize_t messageLength;
while ((messageLength = recvfrom(udpSocket->sock, tempBuffer, BUFFER_SIZE, 0, (sockaddr* )&hostAddr, &hostAddrSize)) != -1)
{
tempBuffer[messageLength] = '\0';
if (udpSocket->onMessageReceived)
udpSocket->onMessageReceived(std::string(tempBuffer, messageLength), IPToString(hostAddr), ntohs(hostAddr.sin_port));
if (udpSocket->onRawMessageReceived)
udpSocket->onRawMessageReceived(tempBuffer, messageLength, IPToString(hostAddr), ntohs(hostAddr.sin_port));
}
}
};

View File

@@ -0,0 +1,91 @@
#pragma once
#include <Sockets/IPAddress.hpp>
#include <string>
// Game-specific Network code written against GameNetworkingSocket API
// GameNetworkingServer
// GameNetworkingClient
// GameNetworkingSocket
// UdpReliability
// TcpServer
// TcpClient
// UdpServer
// UdpClient
// UdpSocket_Old
// TcpSocket_Old
// Berkeley Sockets API
#ifndef INPORT_ANY
#define INPORT_ANY 0
#endif
namespace Socket
{
// TODO: Implement Blocking and Nonblocking UDP
using u8 = uint8_t;
typedef struct sockaddr_in sockaddr_in_t;
typedef struct sockaddr sockaddr_t;
typedef std::vector<uint8_t> msg_t;
// UdpSocket_Old is a class wrapper around BSD Sockets API for the UDP protocol.
class UdpSocket_Old {
public:
/// Default Constructor which creates an empty, uninitialized, and unconnected UDP socket.
UdpSocket_Old() {}
UdpSocket_Old(int family, int flags);
UdpSocket_Old(int socket, addrinfo info, bool connected, bool bound);
~UdpSocket_Old() {}
UdpSocket_Old(const UdpSocket_Old &socket) = default;
UdpSocket_Old &operator=(const UdpSocket_Old &socket) = delete;
void Open();
int Close();
bool IsClosed() const { return sock < 0;}
void Bind(const IPAddress& ipAddress);
void Bind(uint16_t portno);
void BindAny();
void BindAny(uint16_t& portno);
bool Connected() const;
/// In UDP, the client does not form a connection with the server like in TCP, and instead, it just sends a datagram.
/// Similarly, the server need not accept a connection and just waits for datagrams to arrive. There is no 3 way handshake.
/// It just checks for any immediate errors and stores the peer's IP address and port number.
void Connect(const std::string& hostname, u16 port);
void Connect(const IPAddress& ipaddr);
void Connect(u16 port);
[[nodiscard]] IPAddress GetSelfIP() const {return self_addr;}
[[nodiscard]] IPAddress GetPeerIP() const {return peer_addr;}
/// Sends a message to the bound peer only.
int Send(const u8 *data, unsigned int length, int flags = 0);
int Send(const std::vector<u8>& payload);
/// Sends a message to a specified IPAddress.
int SendTo(const IPAddress& ipaddr, const u8 *data, unsigned int length, int flags);
int SendTo(const IPAddress& ipaddr, const std::vector<u8> data);
int Receive(IPAddress& ipaddr, const u8 *message) const;
int ReceiveFromAny(const u8 *message);
int Broadcast(int opt) const;
void Interrupt() const;
private:
int sock{-1};
sockaddr_in_t self_addr{};
socklen_t self_addr_len = sizeof(self_addr);
sockaddr_in_t peer_addr{};
socklen_t peer_addr_len = sizeof(peer_addr);
bool connected = false;
};
}

View File

@@ -1,10 +1,10 @@
#include <Sockets/TcpSocket.hpp>
#include <Sockets/TcpSocket_Old.hpp>
#include <iostream>
#include <exception>
#include <cstring>
#include <memory>
#include "Sockets/UdpSocket.hpp"
#include "Sockets/UdpSocket_Old.hpp"
#include <Sockets/Endianness.hpp>
#include <jlog/Logger.hpp>
#include <Event.h>
@@ -43,12 +43,12 @@ using namespace Socket;
class TCPServer {
public:
ServerLogger logger;
using Socket_p = std::shared_ptr<TcpSocket>;
using Socket_p = std::shared_ptr<TcpSocket_Old>;
//Event<Socket_p> OnServe;
Event<Socket_p> OnAccept;
Event<Socket_p> OnRX;
Event<Socket_p> OnTX;
Socket_p sock {new TcpSocket};
Socket_p sock {new TcpSocket_Old};
Socket_p client;
public:
TCPServer() {};
@@ -128,9 +128,9 @@ public:
/// nc localhost 40269
void TCP_ReceiveTest() {
ServerLogger TCPLogger;
using Socket_p = std::shared_ptr<TcpSocket>;
using Socket_p = std::shared_ptr<TcpSocket_Old>;
Socket_p sock(new TcpSocket);
Socket_p sock(new TcpSocket_Old);
Socket_p client;
try {
@@ -164,9 +164,9 @@ public:
}
void UDP_ReceiveTest() {
using UdpSocket_p = std::shared_ptr<UdpSocket>;
using UdpSocket_p = std::shared_ptr<UdpSocket_Old>;
UdpSocket_p sock(new UdpSocket);
UdpSocket_p sock(new UdpSocket_Old);
try {
sock->Open();
@@ -178,7 +178,7 @@ public:
}
UdpSocket_p client(new UdpSocket);
UdpSocket_p client(new UdpSocket_Old);
try {
client->Open();

View File

@@ -1,5 +1,5 @@
#include <Sockets/Exceptions.hpp>
#include <Sockets/TcpSocket.hpp>
#include <Sockets/TcpSocket_Old.hpp>
#include <Sockets/Sockets.hpp>
#include <sys/types.h>
#include <sys/socket.h>
@@ -15,7 +15,7 @@
namespace Socket {
TcpSocket::TcpSocket()
TcpSocket_Old::TcpSocket_Old()
{
mInfo = new addrinfo;
memset(mInfo, 0, sizeof *mInfo);
@@ -23,7 +23,7 @@ namespace Socket {
mInfo->ai_socktype = SOCK_STREAM;
}
TcpSocket::TcpSocket(int family, int flags)
TcpSocket_Old::TcpSocket_Old(int family, int flags)
{
mInfo = new addrinfo;
memset(mInfo, 0, sizeof *mInfo);
@@ -46,20 +46,20 @@ namespace Socket {
mSockCreated = true;
}
TcpSocket::TcpSocket(int socket, addrinfo info, bool bound, bool connected)
TcpSocket_Old::TcpSocket_Old(int socket, addrinfo info, bool bound, bool connected)
: mSock(socket), mBound(bound), mConnected(connected)
{
mInfo = new addrinfo(info);
}
TcpSocket::~TcpSocket()
TcpSocket_Old::~TcpSocket_Old()
{
if (mSockCreated && (mClosed == false)) // Little more clear to outright say "false"
Close();
freeaddrinfo(mInfo);
}
void TcpSocket::Bind(uint16_t port)
void TcpSocket_Old::Bind(uint16_t port)
{
if (mBound && mConnected)
throw SocketBindingException("Already bound!");
@@ -90,21 +90,21 @@ namespace Socket {
throw SocketBindingException("Can't bind to port");
}
void TcpSocket::BindAny() {
void TcpSocket_Old::BindAny() {
Bind(INPORT_ANY);
}
void TcpSocket::BindAny(uint16_t& port)
void TcpSocket_Old::BindAny(uint16_t& port)
{
this->Bind(INPORT_ANY);
//portno = port;
}
void TcpSocket::Connect(const IPAddress &ipaddr) {
void TcpSocket_Old::Connect(const IPAddress &ipaddr) {
Connect(ipaddr.addr_string(), ipaddr.port);
}
void TcpSocket::Connect(std::string address, uint16_t port)
void TcpSocket_Old::Connect(std::string address, uint16_t port)
{
if (mConnected)
throw SocketConnectException("Already Connected!");
@@ -132,7 +132,7 @@ namespace Socket {
}
}
void TcpSocket::Listen(int maxQueue)
void TcpSocket_Old::Listen(int maxQueue)
{
if (::listen(mSock, maxQueue) != 0)
CheckErrors_accept(errno);
@@ -142,7 +142,7 @@ namespace Socket {
void TcpSocket::Send(const u8 *data, unsigned int length, int flags)
void TcpSocket_Old::Send(const u8 *data, unsigned int length, int flags)
{
const u8 * buff = data;
int status = 0;
@@ -160,7 +160,7 @@ namespace Socket {
}
}
bool TcpSocket::Receive(u8* msg, int len, int flags)
bool TcpSocket_Old::Receive(u8* msg, int len, int flags)
{
int status = 0;
if ((status = ::recv(mSock, msg, len, flags)) == -1)
@@ -171,7 +171,7 @@ namespace Socket {
return true;
}
void TcpSocket::Close()
void TcpSocket_Old::Close()
{
//::shutdown(mSock, 2);
@@ -181,11 +181,11 @@ namespace Socket {
mClosed = true;
}
// Private:
void TcpSocket::setInfo(int port)
void TcpSocket_Old::setInfo(int port)
{
setInfo("null", port);
}
void TcpSocket::setInfo(std::string address, int port)
void TcpSocket_Old::setInfo(std::string address, int port)
{
const char *charAddress;
if (address == "null")
@@ -208,7 +208,7 @@ namespace Socket {
delete charAddress;
}
void TcpSocket::openSocket(addrinfo * info)
void TcpSocket_Old::openSocket(addrinfo * info)
{
mSock = ::socket(info->ai_family, info->ai_socktype, info->ai_protocol);
if (mSock == -1)
@@ -217,7 +217,7 @@ namespace Socket {
}
}
std::shared_ptr<TcpSocket> TcpSocket::Accept() {
std::shared_ptr<TcpSocket_Old> TcpSocket_Old::Accept() {
jlog::Debug("Starting to accept");
union {
sockaddr addr;
@@ -243,7 +243,7 @@ namespace Socket {
info.ai_family = AF_INET6;
info.ai_addr = new sockaddr(address.addr);
}
return std::make_shared<TcpSocket>(newSock, info, true, false);
return std::make_shared<TcpSocket_Old>(newSock, info, true, false);
}
}

View File

@@ -1,15 +1,15 @@
#include "Sockets/UdpSocket.hpp"
#include "Sockets/UdpSocket_Old.hpp"
#include "Sockets/Sockets.hpp"
namespace Socket
{
UdpSocket::UdpSocket(int family, int flags)
UdpSocket_Old::UdpSocket_Old(int family, int flags)
{
this->Open();
}
void UdpSocket::Open()
void UdpSocket_Old::Open()
{
this->Close();
sock = (int)::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
@@ -21,7 +21,7 @@ namespace Socket
}
}
int UdpSocket::Close()
int UdpSocket_Old::Close()
{
int ret;
if (!this->IsClosed()){
@@ -52,7 +52,7 @@ namespace Socket
}
void UdpSocket::Bind(const IPAddress& ipAddress)
void UdpSocket_Old::Bind(const IPAddress& ipAddress)
{
if (IsClosed())
@@ -72,28 +72,28 @@ namespace Socket
CheckErrors_getsockname(errno);
}
void UdpSocket::Bind(uint16_t portno)
void UdpSocket_Old::Bind(uint16_t portno)
{
auto ipaddr = IPAddress::Any(portno);
this->Bind(ipaddr);
}
void UdpSocket::BindAny()
void UdpSocket_Old::BindAny()
{
this->Bind(INPORT_ANY);
}
void UdpSocket::BindAny(uint16_t& portno)
void UdpSocket_Old::BindAny(uint16_t& portno)
{
this->Bind(INPORT_ANY);
//portno = IPAddress{self_addr}.port;
}
void UdpSocket::Connect(const std::string& hostname, u16 port)
void UdpSocket_Old::Connect(const std::string& hostname, u16 port)
{
auto ipaddr = IPAddress::Resolve(hostname, port);
this->Connect(ipaddr, port);
}
void UdpSocket::Connect(const IPAddress& ipaddr)
void UdpSocket_Old::Connect(const IPAddress& ipaddr)
{
peer_addr = ipaddr.operator sockaddr_in_t();
peer_addr_len = sizeof(peer_addr);
@@ -102,7 +102,7 @@ namespace Socket
CheckErrors_connect(errno);
connected = true;
}
void UdpSocket::Connect(u16 port)
void UdpSocket_Old::Connect(u16 port)
{
auto ipaddr = IPAddress::Loopback(port);
@@ -110,7 +110,7 @@ namespace Socket
}
bool UdpSocket::Connected() const {
bool UdpSocket_Old::Connected() const {
return this->connected;
}
@@ -123,7 +123,7 @@ namespace Socket
int UdpSocket::Receive(IPAddress& ipaddr, const u8 *message) const
int UdpSocket_Old::Receive(IPAddress& ipaddr, const u8 *message) const
{
sockaddr_in_t addr_in;
socklen_t addr_in_len = sizeof(addr_in);
@@ -139,7 +139,7 @@ namespace Socket
message = buffer;
return ret;
}
int UdpSocket::Broadcast(int opt) const
int UdpSocket_Old::Broadcast(int opt) const
{
int ret = ::setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(opt));
if (ret < 0)
@@ -148,7 +148,7 @@ namespace Socket
return 0;
}
void UdpSocket::Interrupt() const
void UdpSocket_Old::Interrupt() const
{
// What is this supposed to accomplish?
//uint16_t portno = IPAddress{self_addr}.port;
@@ -158,7 +158,7 @@ namespace Socket
int UdpSocket::Send(const u8 *data, unsigned int length, int flags)
int UdpSocket_Old::Send(const u8 *data, unsigned int length, int flags)
{
int ret = ::send(sock, data, length, flags);
@@ -167,13 +167,13 @@ namespace Socket
return ret;
}
int UdpSocket::Send(const std::vector<u8>& payload)
int UdpSocket_Old::Send(const std::vector<u8>& payload)
{
this->Send(payload.data(), payload.size());
}
int UdpSocket::SendTo(const IPAddress &ipaddr, const u8 *data, unsigned int length, int flags) {
int UdpSocket_Old::SendTo(const IPAddress &ipaddr, const u8 *data, unsigned int length, int flags) {
sockaddr_in_t addr_in = ipaddr.operator sockaddr_in_t();
socklen_t addr_in_len = sizeof(addr_in);
int ret = ::sendto(sock, (const char*)data, length, 0, (struct sockaddr*)&addr_in, addr_in_len);