Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
eminfedar committed Apr 28, 2023
1 parent 49597c5 commit 1ecd626
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 161 deletions.
32 changes: 17 additions & 15 deletions async-sockets/include/basesocket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@
#include <string>
#include <functional>
#include <cerrno>
#include <atomic>

#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)}

class BaseSocket
{
// Definitions
public:
enum SocketType
{
Expand All @@ -30,9 +28,20 @@ class BaseSocket
sockaddr_in address;
constexpr static uint16_t BUFFER_SIZE = 0x1000; // 4096 bytes

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;
static std::string ipToString(sockaddr_in addr)

// 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);
Expand All @@ -42,9 +51,11 @@ class BaseSocket

BaseSocket(FDR_ON_ERROR, SocketType sockType = TCP, int socketId = -1)
{
if (socketId < 0)
if (socketId == -1)
{
if ((this->sock = socket(AF_INET, sockType, 0)) < 0)
this->sock = socket(AF_INET, sockType, 0);

if ( this->sock == -1 )
{
onError(errno, "Socket creating error.");
}
Expand All @@ -54,14 +65,5 @@ class BaseSocket
this->sock = socketId;
}
}

// Methods
public:
virtual void Close() {
close(this->sock);
}

std::string remoteAddress() {return ipToString(this->address);}
int remotePort() {return ntohs(this->address.sin_port);}
int fileDescriptor() const { return this->sock; }
virtual ~BaseSocket(){}
};
52 changes: 25 additions & 27 deletions async-sockets/include/tcpserver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,37 @@ class TCPServer : public BaseSocket
setsockopt(this->sock,SOL_SOCKET,SO_REUSEPORT,&opt,sizeof(int));
}

// Binding the server.
// Bind the custom address & port of the server.
void Bind(const char* address, uint16_t port, FDR_ON_ERROR)
{
if (inet_pton(AF_INET, address, &this->address.sin_addr) <= 0)
{
onError(errno, "Invalid address. Address type not supported.");
return;
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)) < 0)
if (bind(this->sock, (const sockaddr*)&this->address, sizeof(this->address)) == -1)
{
onError(errno, "Cannot bind the socket.");
return;
}
}
void Bind(int port, FDR_ON_ERROR) { this->Bind("0.0.0.0", port, onError); }
// 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 the server.
// Start listening incoming connections.
void Listen(FDR_ON_ERROR)
{
if (listen(this->sock, 20) < 0)
if (listen(this->sock, 20) == -1)
{
onError(errno, "Error: Server can't listen the socket.");
return;
Expand All @@ -49,40 +56,31 @@ class TCPServer : public BaseSocket
t.detach();
}

// Overriding Close to add shutdown():
void Close()
{
shutdown(this->sock, SHUT_RDWR);

BaseSocket::Close();
}

private:
static void Accept(TCPServer* server, FDR_ON_ERROR)
{
sockaddr_in newSocketInfo;
socklen_t newSocketInfoLength = sizeof(newSocketInfo);

int newSock = -1;
int newSocketFileDescriptor = -1;
while (true)
{
if ((newSock = accept(server->sock, (sockaddr*)&newSocketInfo, &newSocketInfoLength)) < 0)
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;
}

if (newSock >= 0)
{
TCPSocket* newSocket = new TCPSocket(onError, newSock);
newSocket->deleteAfterClosed = true;
newSocket->setAddressStruct(newSocketInfo);
TCPSocket* newSocket = new TCPSocket(onError, newSocketFileDescriptor);
newSocket->deleteAfterClosed = true;
newSocket->setAddressStruct(newSocketInfo);

server->onNewConnection(newSocket);
newSocket->Listen();
}
server->onNewConnection(newSocket);
newSocket->Listen();
}
}
};
71 changes: 34 additions & 37 deletions async-sockets/include/tcpsocket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,43 @@ class TCPSocket : public BaseSocket
public:
// Event Listeners:
std::function<void(std::string)> onMessageReceived;
std::function<void(const char*, int)> onRawMessageReceived;
std::function<void(const char*, ssize_t)> onRawMessageReceived;
std::function<void(int)> onSocketClosed;

explicit TCPSocket(FDR_ON_ERROR, int socketId = -1) : BaseSocket(onError, TCP, socketId){}

// Send TCP Packages
int Send(const char* bytes, size_t byteslength)
// Send raw bytes
ssize_t Send(const char* bytes, size_t byteslength) { return send(this->sock, bytes, byteslength, 0); }
// 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` & `uint16_t port` values
void Connect(uint32_t ipv4, uint16_t port, std::function<void()> onConnected = [](){}, FDR_ON_ERROR)
{
int sent = -1;
if ((sent = send(this->sock, bytes, byteslength, 0)) < 0)
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)
{
perror("send");
onError(errno, "Connection failed to the host.");
this->setTimeout(0);
return;
}
return sent;
}
int Send(const std::string& message) { return this->Send(message.c_str(), message.length()); }

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;
Expand All @@ -37,8 +56,8 @@ class TCPSocket : public BaseSocket
hints.ai_socktype = SOCK_STREAM;

// Get address info from DNS
int status;
if ((status = getaddrinfo(host, NULL, &hints, &res)) != 0) {
int status = getaddrinfo(host, NULL, &hints, &res);
if ( status != 0 ) {
onError(errno, "Invalid address." + std::string(gai_strerror(status)));
return;
}
Expand All @@ -47,43 +66,21 @@ class TCPSocket : public BaseSocket
{
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).
break; // for now, just get the first ip (ipv4).
}
}

freeaddrinfo(res);

this->Connect((uint32_t)this->address.sin_addr.s_addr, port, onConnected, onError);
}
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.
if (connect(this->sock, (const sockaddr*)&this->address, sizeof(sockaddr_in)) < 0)
{
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 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 the socket
void Listen()
{
std::thread t(TCPSocket::Receive, this);
Expand All @@ -99,7 +96,7 @@ class TCPSocket : public BaseSocket
static void Receive(TCPSocket* socket)
{
char tempBuffer[TCPSocket::BUFFER_SIZE];
int messageLength;
ssize_t messageLength;

while ((messageLength = recv(socket->sock, tempBuffer, TCPSocket::BUFFER_SIZE, 0)) > 0)
{
Expand Down
31 changes: 21 additions & 10 deletions async-sockets/include/udpserver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,44 @@
class UDPServer : public UDPSocket
{
public:
void Bind(const char* IPv4, std::uint16_t port, FDR_ON_ERROR)
// Bind the custom address & port of the server.
void Bind(const char* address, std::uint16_t port, FDR_ON_ERROR)
{
if (inet_pton(AF_INET, IPv4, &this->address.sin_addr) <= 0)
{
onError(errno, "Invalid address. Address type not supported.");
return;
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)) < 0)
status = bind(this->sock, (const sockaddr*)&this->address, sizeof(this->address));
if (status == -1)
{
onError(errno, "Cannot bind the socket.");
return;
}
}

void Bind(int port, FDR_ON_ERROR)
// 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);
}

void setBroadcast(FDR_ON_ERROR)
// Enable or disable the SO_BROADCAST flag
void setBroadcast(bool value, FDR_ON_ERROR)
{
int broadcast = 1;
if (setsockopt(this->sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast))
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;
Expand Down
Loading

0 comments on commit 1ecd626

Please sign in to comment.