initial commit
This commit is contained in:
commit
0fbc5bad52
18 changed files with 1289 additions and 0 deletions
187
implementations/Crafter.Network-ClientHTTP.cpp
Normal file
187
implementations/Crafter.Network-ClientHTTP.cpp
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
Crafter®.Network
|
||||
Copyright (C) 2025 Catcrafts®
|
||||
Catcrafts.net
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3.0 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
module;
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
module Crafter.Network:ClientHTTP_impl;
|
||||
import :ClientHTTP;
|
||||
import Crafter.Thread;
|
||||
import std;
|
||||
|
||||
using namespace Crafter;
|
||||
|
||||
ClientHTTP::ClientHTTP(const char* host, std::uint16_t port): client(host, port) {
|
||||
|
||||
}
|
||||
|
||||
ClientHTTP::ClientHTTP(std::string host, std::uint16_t port): ClientHTTP(host.c_str(), port) {
|
||||
|
||||
}
|
||||
|
||||
HTTPResponse ClientHTTP::Send(const char* request, std::uint32_t length) const {
|
||||
client.Send(request, length);
|
||||
std::vector<char> buffer = client.RecieveSync(1024);
|
||||
HTTPResponse response;
|
||||
std::uint32_t i = 0;
|
||||
std::uint32_t statusStart = 0;
|
||||
for(; i < 1024; i++) {
|
||||
if(buffer[i] == ' ') {
|
||||
statusStart = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(; i < 1024; i++) {
|
||||
if(buffer[i] == '\r') {
|
||||
response.status.assign(buffer.data()+statusStart+1, i-statusStart-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
i+=2;
|
||||
while(i < 1024) {
|
||||
std::uint32_t headerStart = i;
|
||||
std::string headerName;
|
||||
for(; i < 1024; i++) {
|
||||
if(buffer[i] == ':') {
|
||||
headerName.assign(buffer.data()+headerStart, i-headerStart);
|
||||
i+=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
headerStart = i;
|
||||
std::string headerValue;
|
||||
for(; i < 1024; i++) {
|
||||
if(buffer[i] == '\r' && buffer[i+1] == '\n') {
|
||||
headerValue.assign(buffer.data()+headerStart, i-headerStart);
|
||||
response.headers.insert({headerName, headerValue});
|
||||
if(buffer[i+2] == '\r'){
|
||||
goto headersComplete;
|
||||
} else{
|
||||
i+=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
headersComplete:;
|
||||
i+=4;
|
||||
std::unordered_map<std::string, std::string>::iterator it = response.headers.find("Content-Length");
|
||||
if(it != response.headers.end())
|
||||
{
|
||||
const int lenght = std::stoi(it->second);
|
||||
response.body.resize(lenght, 0);
|
||||
if(i < buffer.size()){
|
||||
std::memcpy(&response.body[0], buffer.data()+i, buffer.size()-i);
|
||||
}
|
||||
const int remaining = lenght-(buffer.size()-i);
|
||||
if(remaining > 0){
|
||||
int index = buffer.size()-i;
|
||||
while(index < lenght) {
|
||||
std::vector<char> bodyBuffer = client.RecieveSync(remaining);
|
||||
std::memcpy(&response.body[index], bodyBuffer.data(), bodyBuffer.size());
|
||||
index+=bodyBuffer.size();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::unordered_map<std::string, std::string>::iterator it = response.headers.find("Transfer-Encoding");
|
||||
if(it != response.headers.end() && it->second == "chunked") {
|
||||
while(i < buffer.size()){
|
||||
std::string lenght;
|
||||
int lenghtStart = i;
|
||||
for(; i < buffer.size(); i++) {
|
||||
if(buffer[i] == '\r') {
|
||||
lenght.assign(buffer.data()+lenghtStart, i-lenghtStart);
|
||||
break;
|
||||
}
|
||||
}
|
||||
i+=2;
|
||||
std::cout << lenght << "bro" << std::endl;
|
||||
int lenghtInt = stoi(lenght, 0, 8);
|
||||
if(lenghtInt != 0){
|
||||
int oldSize = response.body.size();
|
||||
response.body.resize(oldSize+lenghtInt, 0);
|
||||
if(buffer.size() < lenghtInt) {
|
||||
std::memcpy(&response.body[oldSize], buffer.data()+i, buffer.size()-i);
|
||||
std::vector<char> bodyBuffer2 = client.RecieveUntilFullSync(lenghtInt-buffer.size());
|
||||
std::memcpy(&response.body[oldSize+(buffer.size()-i)], buffer.data(), buffer.size());
|
||||
} else {
|
||||
std::memcpy(&response.body[oldSize], buffer.data()+i, lenghtInt);
|
||||
i+=lenghtInt;
|
||||
}
|
||||
} else{
|
||||
goto bodyFinished;
|
||||
}
|
||||
}
|
||||
std::cout << response.body << std::endl;
|
||||
while(true) {
|
||||
std::vector<char> bodyBuffer = client.RecieveSync();
|
||||
int i2 = 0;
|
||||
while(i2 < bodyBuffer.size()){
|
||||
std::string lenght;
|
||||
int lenghtStart = i2;
|
||||
for(; i2 < bodyBuffer.size(); i2++) {
|
||||
if(buffer[i2] == '\r') {
|
||||
lenght.assign(bodyBuffer.data()+lenghtStart, i2-lenghtStart);
|
||||
break;
|
||||
}
|
||||
}
|
||||
i2+=2;
|
||||
int lenghtInt = stoi(lenght, 0, 8);
|
||||
std::cout <<lenghtInt << std::endl;
|
||||
if(lenghtInt != 0){
|
||||
int oldSize = response.body.size();
|
||||
response.body.resize(oldSize+lenghtInt, 0);
|
||||
if(bodyBuffer.size() < lenghtInt) {
|
||||
std::memcpy(&response.body[oldSize], bodyBuffer.data()+i2, bodyBuffer.size()-i2);
|
||||
std::vector<char> bodyBuffer2 = client.RecieveUntilFullSync(lenghtInt-bodyBuffer.size());
|
||||
std::memcpy(&response.body[oldSize+(bodyBuffer.size()-i2)], bodyBuffer2.data(), bodyBuffer2.size());
|
||||
} else {
|
||||
std::memcpy(&response.body[oldSize], bodyBuffer.data()+i2, lenghtInt);
|
||||
i2+=lenghtInt;
|
||||
}
|
||||
} else{
|
||||
goto bodyFinished;
|
||||
}
|
||||
}
|
||||
}
|
||||
bodyFinished:;
|
||||
} else {
|
||||
std::vector<char> bodyBuffer = client.RecieveUntilCloseSync();
|
||||
response.body.resize((buffer.size()-i)+(bodyBuffer.size()), 0);
|
||||
if(i < buffer.size()){
|
||||
std::memcpy(&response.body[0], buffer.data()+i, buffer.size()-i);
|
||||
}
|
||||
std::memcpy(&response.body[buffer.size()-i], bodyBuffer.data(), bodyBuffer.size());
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
HTTPResponse ClientHTTP::Send(std::string request) const {
|
||||
return Send(request.c_str(), request.size());
|
||||
}
|
||||
161
implementations/Crafter.Network-ClientTCP.cpp
Executable file
161
implementations/Crafter.Network-ClientTCP.cpp
Executable file
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
Crafter®.Network
|
||||
Copyright (C) 2025 Catcrafts®
|
||||
Catcrafts.net
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3.0 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
module;
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netdb.h>
|
||||
#include <strings.h>
|
||||
|
||||
module Crafter.Network:ClientTCP_impl;
|
||||
import :ClientTCP;
|
||||
import Crafter.Thread;
|
||||
import std;
|
||||
|
||||
using namespace Crafter;
|
||||
|
||||
ClientTCP::ClientTCP(int socketid) : socketid(socketid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ClientTCP::ClientTCP(const char* hostName, std::uint16_t port)
|
||||
{
|
||||
hostent *host;
|
||||
sockaddr_in serv_addr;
|
||||
|
||||
host=gethostbyname(hostName);
|
||||
if((socketid = socket(AF_INET, SOCK_STREAM, 0)) == -1){
|
||||
std::cerr << "Could not open socket" << std::endl;
|
||||
}
|
||||
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_port = htons(port);
|
||||
serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
|
||||
bzero(&(serv_addr.sin_zero),8);
|
||||
|
||||
if(connect(socketid,(sockaddr*)&serv_addr, sizeof(sockaddr)) == -1){
|
||||
std::cerr << "Could not connect to server" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ClientTCP::ClientTCP(std::string hostName, std::uint16_t port): ClientTCP(hostName.c_str(), port)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ClientTCP::~ClientTCP()
|
||||
{
|
||||
close(socketid);
|
||||
}
|
||||
|
||||
void ClientTCP::Send(const void* buffer, std::uint32_t size) const {
|
||||
send(socketid, reinterpret_cast<const char*>(buffer), size, 0);
|
||||
}
|
||||
|
||||
std::vector<char> ClientTCP::RecieveSync(std::uint32_t bufferSize) const {
|
||||
std::vector<char> totalBuffer(bufferSize);
|
||||
int read = recv(socketid, totalBuffer.data(), bufferSize, 0);
|
||||
if(read < bufferSize){
|
||||
totalBuffer.resize(read);
|
||||
}
|
||||
return totalBuffer;
|
||||
}
|
||||
int ClientTCP::RecieveSync(std::uint32_t bufferSize, void* buffer) const {
|
||||
return recv(socketid, reinterpret_cast<char*>(buffer), bufferSize, 0);
|
||||
}
|
||||
|
||||
std::vector<char> ClientTCP::RecieveSync() const {
|
||||
int count;
|
||||
ioctl(socketid, FIONREAD, &count);
|
||||
std::vector<char> buffer(count);
|
||||
recv(socketid, buffer.data(), count, 0);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::vector<char> ClientTCP::RecieveUntilCloseSync() const {
|
||||
int count;
|
||||
ioctl(socketid, FIONREAD, &count);
|
||||
std::vector<char> buffer(count);
|
||||
recv(socketid, buffer.data(), count, 0);
|
||||
while(true) {
|
||||
ioctl(socketid, FIONREAD, &count);
|
||||
unsigned int oldSize = buffer.size();
|
||||
buffer.resize(buffer.size()+count);
|
||||
if(recv(socketid, buffer.data()+oldSize, count, 0) == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::vector<char> ClientTCP::RecieveUntilFullSync(std::uint32_t bufferSize) const {
|
||||
std::vector<char> buffer(bufferSize);
|
||||
int read = 0;
|
||||
while(read < bufferSize) {
|
||||
int newRead = recv(socketid, buffer.data()+read, bufferSize-read, 0);
|
||||
if(newRead == -1) {
|
||||
break;
|
||||
} else{
|
||||
read+=newRead;
|
||||
}
|
||||
}
|
||||
buffer.resize(read);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void ClientTCP::RecieveAsync(std::uint32_t bufferSize, std::function<void(std::vector<char>)> recieveCallback) const {
|
||||
ThreadPool::Enqueue([recieveCallback, this, bufferSize](){
|
||||
recieveCallback(this->RecieveSync(bufferSize));
|
||||
});
|
||||
}
|
||||
|
||||
void ClientTCP::RecieveAsync(std::uint32_t bufferSize, std::function<void(int)> recieveCallback, char* buffer) const {
|
||||
ThreadPool::Enqueue([recieveCallback, this, bufferSize, buffer](){
|
||||
recieveCallback(this->RecieveSync(bufferSize, buffer));
|
||||
});
|
||||
}
|
||||
|
||||
void ClientTCP::RecieveUntilFullAsync(std::uint32_t bufferSize, std::function<void(std::vector<char>)> recieveCallback) const {
|
||||
ThreadPool::Enqueue([recieveCallback, this, bufferSize](){
|
||||
recieveCallback(this->RecieveUntilFullSync(bufferSize));
|
||||
});
|
||||
}
|
||||
|
||||
void ClientTCP::RecieveAsync(std::function<void(std::vector<char>)> recieveCallback) const {
|
||||
ThreadPool::Enqueue([this, recieveCallback](){
|
||||
recieveCallback(this->RecieveSync());
|
||||
});
|
||||
}
|
||||
|
||||
void ClientTCP::RecieveUntilCloseAsync(std::function<void(std::vector<char>)> recieveCallback) const {
|
||||
ThreadPool::Enqueue([this, recieveCallback](){
|
||||
recieveCallback(this->RecieveUntilCloseSync());
|
||||
});
|
||||
}
|
||||
217
implementations/Crafter.Network-ListenerHTTP.cpp
Normal file
217
implementations/Crafter.Network-ListenerHTTP.cpp
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
Crafter®.Network
|
||||
Copyright (C) 2025 Catcrafts®
|
||||
Catcrafts.net
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3.0 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
module;
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <strings.h>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
|
||||
module Crafter.Network:ListenerHTTP_impl;
|
||||
import :ListenerHTTP;
|
||||
import :ClientTCP;
|
||||
import std;
|
||||
import Crafter.Thread;
|
||||
|
||||
using namespace Crafter;
|
||||
|
||||
ListenerHTTP::ListenerHTTP(std::uint16_t port, std::unordered_map<std::string, std::function<std::string(const HTTPRequest&)>> routes): routes(routes) {
|
||||
sockaddr_in servAddr;
|
||||
bzero((char*)&servAddr, sizeof(servAddr));
|
||||
servAddr.sin_family = AF_INET;
|
||||
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
servAddr.sin_port = htons(port);
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
throw std::runtime_error("Error establishing the server socket");
|
||||
}
|
||||
|
||||
int opt = 1;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||
throw std::runtime_error("Error setting SO_REUSEADDR");
|
||||
}
|
||||
|
||||
int bindStatus = bind(s, (struct sockaddr*)&servAddr, sizeof(servAddr));
|
||||
if (bindStatus < 0) {
|
||||
throw std::runtime_error(std::format("Error binding the server socket: {}", std::strerror(errno)));
|
||||
}
|
||||
|
||||
if (listen(s, 5) < 0) {
|
||||
throw std::runtime_error("Error starting to listen on the server socket");
|
||||
}
|
||||
}
|
||||
|
||||
void ListenerHTTP::Stop() {
|
||||
running = false;
|
||||
shutdown(s, SHUT_RDWR);
|
||||
close(s);
|
||||
s = -1;
|
||||
}
|
||||
|
||||
void ListenerHTTP::ListenSyncSync() const {
|
||||
while(running) {
|
||||
sockaddr_in newSockAddr;
|
||||
socklen_t newSockAddrSize = sizeof(newSockAddr);
|
||||
int client = accept(s, (sockaddr*)&newSockAddr, &newSockAddrSize);
|
||||
if (client > 0) {
|
||||
CallRoute(client);
|
||||
} else {
|
||||
std::cerr << "Error accepting request from client!" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListenerHTTP::ListenSyncAsync() const {
|
||||
while(running) {
|
||||
sockaddr_in newSockAddr;
|
||||
socklen_t newSockAddrSize = sizeof(newSockAddr);
|
||||
int client = accept(s, (sockaddr*)&newSockAddr, &newSockAddrSize);
|
||||
if (client > 0) {
|
||||
ThreadPool::Enqueue([this, client]() {CallRoute(client); });
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error accepting request from client!" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListenerHTTP::ListenAsyncSync() const {
|
||||
ThreadPool::Enqueue([this]() {
|
||||
while(running) {
|
||||
sockaddr_in newSockAddr;
|
||||
socklen_t newSockAddrSize = sizeof(newSockAddr);
|
||||
int client = accept(s, (sockaddr*)&newSockAddr, &newSockAddrSize);
|
||||
if (client > 0) {
|
||||
CallRoute(client);
|
||||
}
|
||||
else if(running) {
|
||||
std::cerr << "Error accepting request from client: "<< strerror(errno) << " (errno: " << errno << ")"<< std::endl;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ListenerHTTP::ListenAsyncAsync() const {
|
||||
ThreadPool::Enqueue([this]() {
|
||||
while(running) {
|
||||
sockaddr_in newSockAddr;
|
||||
socklen_t newSockAddrSize = sizeof(newSockAddr);
|
||||
int client = accept(s, (sockaddr*)&newSockAddr, &newSockAddrSize);
|
||||
if (client > 0) {
|
||||
ThreadPool::Enqueue([this, client]() {CallRoute(client); });
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error accepting request from client!" << std::endl;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ListenerHTTP::CallRoute(int clientid) const {
|
||||
ClientTCP client(clientid);
|
||||
std::vector<char> buffer = client.RecieveSync(1024);
|
||||
HTTPRequest request;
|
||||
std::string route;
|
||||
std::uint32_t i = 0;
|
||||
std::uint32_t routeStart = 0;
|
||||
for(; i < 1024; i++) {
|
||||
if(buffer[i] == ' ') {
|
||||
request.method.assign(buffer.data(), i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(; i < 1024; i++) {
|
||||
if(buffer[i] == '/') {
|
||||
routeStart = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(; i < 1024; i++) {
|
||||
if(buffer[i] == ' ') {
|
||||
route.assign(buffer.data()+routeStart, i-routeStart);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(; i < 1024; i++) {
|
||||
if(buffer[i] == '\r' && buffer[i+1] == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
i+=2;
|
||||
while(i < 1024) {
|
||||
std::uint32_t headerStart = i;
|
||||
std::string headerName;
|
||||
for(; i < 1024-i; i++) {
|
||||
if(buffer[i] == ':') {
|
||||
headerName.assign(buffer.data()+headerStart, i-headerStart);
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
headerStart = i;
|
||||
std::string headerValue;
|
||||
for(; i < 1024; i++) {
|
||||
if(buffer[i] == '\r' && buffer[i+1] == '\n') {
|
||||
headerValue.assign(buffer.data()+headerStart, i-headerStart);
|
||||
request.headers.insert({headerName, headerValue});
|
||||
if(buffer[i+2] == '\r'){
|
||||
goto headersComplete;
|
||||
} else{
|
||||
i+=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
headersComplete:;
|
||||
i+=4;
|
||||
std::unordered_map<std::string, std::string>::iterator it = request.headers.find("Content-Length");
|
||||
if(it != request.headers.end())
|
||||
{
|
||||
const int lenght = std::stoi(it->second);
|
||||
const int remaining = 1024-lenght-i;
|
||||
request.body.resize(lenght, 0);
|
||||
if(remaining > 0){
|
||||
std::memcpy(&request.body[0], buffer.data()+i, lenght);
|
||||
}
|
||||
if(remaining < lenght){
|
||||
std::vector<char> bodyBuffer = client.RecieveSync(lenght-remaining);
|
||||
std::memcpy(&request.body[remaining], bodyBuffer.data(), lenght-remaining);
|
||||
}
|
||||
}
|
||||
std::string response = routes.at(route)(request);
|
||||
client.Send(&response[0], response.size());
|
||||
}
|
||||
|
||||
ListenerHTTP::~ListenerHTTP() {
|
||||
if(s != -1) {
|
||||
close(s);
|
||||
}
|
||||
}
|
||||
131
implementations/Crafter.Network-ListenerTCP.cpp
Executable file
131
implementations/Crafter.Network-ListenerTCP.cpp
Executable file
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
Crafter®.Network
|
||||
Copyright (C) 2025 Catcrafts®
|
||||
Catcrafts.net
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3.0 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
module;
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <strings.h>
|
||||
|
||||
module Crafter.Network:ListenerTCP_impl;
|
||||
import :ListenerTCP;
|
||||
import std;
|
||||
import Crafter.Thread;
|
||||
|
||||
using namespace Crafter;
|
||||
|
||||
ListenerTCP::ListenerTCP(std::uint16_t port, std::function<void(ClientTCP*)> connectCallback, std::uint32_t concurrentClientLimit, std::uint32_t totalClientLimit) : connectCallback(connectCallback), concurrentClientLimit(concurrentClientLimit), totalClientLimit(totalClientLimit) {
|
||||
sockaddr_in servAddr;
|
||||
bzero((char*)&servAddr, sizeof(servAddr));
|
||||
servAddr.sin_family = AF_INET;
|
||||
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
servAddr.sin_port = htons(port);
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(s < 0)
|
||||
{
|
||||
throw std::runtime_error("Error establishing the server socket");
|
||||
}
|
||||
int bindStatus = bind(s, (struct sockaddr*) &servAddr, sizeof(servAddr));
|
||||
listen(s, 5);
|
||||
}
|
||||
|
||||
void ListenerTCP::Stop() {
|
||||
running = false;
|
||||
shutdown(s, SHUT_RDWR);
|
||||
close(s);
|
||||
s = -1;
|
||||
}
|
||||
|
||||
void ListenerTCP::ListenSyncSync() {
|
||||
while (running && totalClientCounter < totalClientLimit) {
|
||||
sockaddr_in newSockAddr;
|
||||
socklen_t newSockAddrSize = sizeof(newSockAddr);
|
||||
int client = accept(s, (sockaddr*)&newSockAddr, &newSockAddrSize);
|
||||
if (client > 0) {
|
||||
connectCallback(new ClientTCP(client));
|
||||
this->totalClientCounter++;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error accepting request from client!" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListenerTCP::ListenSyncAsync() {
|
||||
while (running && totalClientCounter < totalClientLimit) {
|
||||
sockaddr_in newSockAddr;
|
||||
socklen_t newSockAddrSize = sizeof(newSockAddr);
|
||||
int client = accept(s, (sockaddr*)&newSockAddr, &newSockAddrSize);
|
||||
if (client > 0) {
|
||||
ThreadPool::Enqueue([this, client]() {connectCallback(new ClientTCP(client)); });
|
||||
this->totalClientCounter++;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error accepting request from client!" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListenerTCP::ListenAsyncSync() {
|
||||
ThreadPool::Enqueue([this]() {
|
||||
while (running && totalClientCounter < totalClientLimit) {
|
||||
sockaddr_in newSockAddr;
|
||||
socklen_t newSockAddrSize = sizeof(newSockAddr);
|
||||
int client = accept(s, (sockaddr*)&newSockAddr, &newSockAddrSize);
|
||||
if (client > 0) {
|
||||
connectCallback(new ClientTCP(client));
|
||||
this->totalClientCounter++;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error accepting request from client!" << std::endl;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ListenerTCP::ListenAsyncAsync() {
|
||||
ThreadPool::Enqueue([this]() {
|
||||
while (running && totalClientCounter < totalClientLimit) {
|
||||
sockaddr_in newSockAddr;
|
||||
socklen_t newSockAddrSize = sizeof(newSockAddr);
|
||||
int client = accept(s, (sockaddr*)&newSockAddr, &newSockAddrSize);
|
||||
if (client > 0) {
|
||||
ThreadPool::Enqueue([this, client]() {connectCallback(new ClientTCP(client)); });
|
||||
this->totalClientCounter++;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error accepting request from client!" << std::endl;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ListenerTCP::~ListenerTCP() {
|
||||
if(s != -1) {
|
||||
close(s);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue