Newer
Older
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <regex>
#include <limits>
memset(&cliaddr, 0, sizeof(cliaddr));
memset(&srvaddr, 0, sizeof(srvaddr));
// Filling server information
srvaddr.sin_family = AF_INET; // IPv4
srvaddr.sin_addr.s_addr = inet_addr(ip.c_str());
srvaddr.sin_port = htons(this->port);
UDPProtocol::~UDPProtocol() {
closeConnectionToClient();
}
int UDPProtocol::receiveAtLeastHeaderSizeBytes(uint8_t *buff, int headerSize,
int packetSize) {
int rcv = recvfrom(srv_sock, &buff[bytercv], packetSize + 1, // +1 to recognized if there are more bytes than expected
}
}
return bytercv;
}
int UDPProtocol::receiveFromClient(PacketLib::BasePacket &pack) {
uint headerSize = pack.getHeaderSize();
uint packSize = pack.getPacketStructureByteSize();
uint tailSize = pack.getTailSize();
uint8_t *buff = new uint8_t[(packSize + headerSize) * headerSize]; // to avoid overflow
while (true) {
while (!headerFlag) { // until the header has not received
int rcv = receiveAtLeastHeaderSizeBytes(buff, headerSize, packSize); // receive at least headerSize byte, maximum packSize for each udp rcv.
if (rcv == -1) {
pack.copyToBinaryPointer(buff, headerSize); //copy the header into packet to be able to read it.
payloadSize = pack.getPayloadSize();
totPacketSize = headerSize + payloadSize + tailSize;
to_be_received = totPacketSize - tot_byte_rcv; // Calculate how much is still left to read
}
if (to_be_received == 0) { // whole packet has been received.
pack.copyToBinaryPointer(&buff[headerSize],
tot_byte_rcv - headerSize, headerSize); // copy the buffer into packet except already copied header
return tot_byte_rcv;
}
if (to_be_received < 0) { // error,received more bytes then expected.
uint8_t *tmp_buff = new uint8_t[packSize + headerSize]; // maximum receivable in receiveAtLeastHeaderSizeBytes
int rcv = receiveAtLeastHeaderSizeBytes(tmp_buff, headerSize, packSize);
resetPacket(pack, tot_byte_rcv);
return -1;
}
std::vector<uint8_t> vec;
std::copy(tmp_buff, tmp_buff + headerSize, std::back_inserter(vec));
if (pack.isRecognizedHeader(vec)) { //another header received, save it and discard previous data.
std::memset(buff, 0, tot_byte_rcv);
std::memcpy(buff, tmp_buff, rcv);
headerFlag = true;
pack.copyToBinaryPointer(buff, headerSize);
payloadSize = pack.getPayloadSize();
totPacketSize = headerSize + payloadSize + tailSize;
to_be_received = totPacketSize - rcv;
tot_byte_rcv = rcv;
} else { // append to current buff
tot_byte_rcv += rcv;
std::memcpy(&buff[tot_byte_rcv - rcv], tmp_buff, rcv);
to_be_received -= rcv;
}
int UDPProtocol::connectToClient() {
// Creating socket file descriptor
if ((srv_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[UDP Receiver]\t" << "socket creation failed"
<< std::endl;
return -1;
}
// Set timeout to the socket
struct timeval tv;
if (setsockopt(srv_sock, SOL_SOCKET, SO_RCVTIMEO, (const char*) &tv,
sizeof tv) < 0) {
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[UDP Receiver]\t" << "Error setting timeout to socket" << std::endl;
return -1;
}
if (bind(srv_sock, (const struct sockaddr*) &srvaddr, sizeof(srvaddr))
< 0) {
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[UDP Receiver]\t" << "bind failed" << std::endl;
int UDPProtocol::closeConnectionToClient() {
if (srv_sock != -1) {
::close(srv_sock);
srv_sock = -1;
bool UDPProtocol::isConnectedToClient() const {
return srv_sock != -1;
}
void UDPProtocol::resetPacket(PacketLib::BasePacket &pack, int bytes) {
uint8_t *buff = new uint8_t[bytes];
std::memset(buff, 0, bytes);
int toBeReset = std::min(
static_cast<int>(pack.getPacketStructureByteSize()), bytes);
pack.copyToBinaryPointer(buff, toBeReset);
void UDPProtocol::setHost(std::string host) {
std::string ip = { };
} else {
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[UDP Receiver]\t"
<< "invalid IP address and port format: " << host << std::endl;
// Check if the input string matches the expected format
bool ok = true;
if (!std::regex_match(ip, pattern)) {
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[UDP Receiver]\t" << "invalid IP address: " << ip
this->host = this->ip + ":" + std::to_string(this->port);
void UDPProtocol::setPort(int port) {
if (port > 1023 && port < 65535)
else {
time_t now = time(nullptr);
std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
<< "]\t[UDP Receiver]\t" << "invalid port: " << port
<< ", setting to 9003" << std::endl;
this->host = this->ip + ":" + std::to_string(this->port);
}
bool UDPProtocol::split_ip_port(const std::string &ip_port,
// Regex pattern to match IP address and port in the format "xxx.xxx.xxx.xxx:xxxx"
// Check if the input string matches the expected format
if (!std::regex_match(ip_port, pattern)) {
// Split the input string into IP address and port
int colon_pos = ip_port.find(":");
ip_address = ip_port.substr(0, colon_pos);