201 lines
5.9 KiB
C++
Executable file
201 lines
5.9 KiB
C++
Executable file
/*
|
|
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>
|
|
#include <cerrno>
|
|
|
|
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()
|
|
{
|
|
if(socketid != 1) {
|
|
shutdown(socketid, SHUT_RDWR);
|
|
close(socketid);
|
|
}
|
|
}
|
|
|
|
void ClientTCP::Stop() {
|
|
shutdown(socketid, SHUT_RDWR);
|
|
close(socketid);
|
|
socketid = -1;
|
|
}
|
|
|
|
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 < 0) {
|
|
throw std::runtime_error(std::strerror(errno));
|
|
} else if(read == 0) {
|
|
throw SocketClosedException();
|
|
}
|
|
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);
|
|
if(count == 0){
|
|
count = 1024;
|
|
}
|
|
std::vector<char> buffer(count);
|
|
int read = recv(socketid, buffer.data(), count, 0);
|
|
if(read < 0) {
|
|
throw std::runtime_error(std::strerror(errno));
|
|
} else if(read == 0) {
|
|
throw SocketClosedException();
|
|
} else if(count != read) {
|
|
buffer.resize(read);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
std::vector<char> ClientTCP::RecieveUntilCloseSync() const {
|
|
int count;
|
|
ioctl(socketid, FIONREAD, &count);
|
|
if(count == 0){
|
|
count = 1024;
|
|
}
|
|
std::vector<char> buffer(count);
|
|
int read = recv(socketid, buffer.data(), count, 0);
|
|
if(read < 0) {
|
|
throw std::runtime_error(std::strerror(errno));
|
|
} else if(read == 0) {
|
|
throw SocketClosedException();
|
|
}
|
|
|
|
while(true) {
|
|
ioctl(socketid, FIONREAD, &count);
|
|
if(count == 0){
|
|
count = 1024;
|
|
}
|
|
unsigned int oldSize = buffer.size();
|
|
buffer.resize(buffer.size()+count);
|
|
int read = recv(socketid, buffer.data()+oldSize, count, 0);
|
|
if(read < 0) {
|
|
throw std::runtime_error(std::strerror(errno));
|
|
} else if(read == 0) {
|
|
return buffer;
|
|
} else if(count != read) {
|
|
buffer.resize(read);
|
|
}
|
|
}
|
|
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(read < 0) {
|
|
throw std::runtime_error(std::strerror(errno));
|
|
} else if(read == 0) {
|
|
throw SocketClosedException();
|
|
}
|
|
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());
|
|
});
|
|
}
|