Skip to content
TCP_Protocol.cpp 4.45 KiB
Newer Older
#include <iostream>
#include <string>
Valerio Pastore's avatar
Valerio Pastore committed
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <regex>

Valerio Pastore's avatar
Valerio Pastore committed
#include <TCP_Protocol.h>

Valerio Pastore's avatar
Valerio Pastore committed
using namespace inaf::oasbo::ConnectionProtocols;
astri's avatar
astri committed
TCPProtocol::TCPProtocol() :
		TCPProtocol("127.0.0.1", 9003) {
astri's avatar
astri committed
TCPProtocol::TCPProtocol(std::string ip, int prt) :
		srv_sock(-1), cli_sock(-1), ip(ip), port(prt) {
	host = ip + ":" + std::to_string(port);
}

TCPProtocol::~TCPProtocol() {
	closeConnectionToClient();
	closeConnectionToServer();
Valerio Pastore's avatar
Valerio Pastore committed
}

int TCPProtocol::sendToServer(PacketLib::BasePacket &pack) {
	int val = ::send(cli_sock, pack.getBinaryPointer(),
astri's avatar
astri committed
			pack.getHeaderSize() + pack.getPayloadSize() + pack.getTailSize(),
			MSG_CONFIRM);
	return val;
}
int TCPProtocol::receiveFromClient(PacketLib::BasePacket &pack) {
	ssize_t headerSize = pack.getHeaderSize();
	uint8_t *buff = new uint8_t[pack.getPacketStructureByteSize()];
astri's avatar
astri committed
	ssize_t rec = ::recv(this->srv_sock, &buff[0], headerSize, MSG_WAITALL);
astri's avatar
astri committed
	if (rec == 0) { // connessione chiusa
astri's avatar
astri committed
		closeConnectionToClient();
		delete buff;
		return 0;
	}
astri's avatar
astri committed
	if (rec != headerSize) {
Valerio Pastore's avatar
Valerio Pastore committed
		delete buff;
		return -1;
	}
	pack.copyToBinaryPointer(buff, headerSize);
astri's avatar
astri committed
	if (!pack.isRecognizedHeader()) {
Valerio Pastore's avatar
Valerio Pastore committed
		resetPacket(pack, headerSize);
		delete buff;
		return -1;
Valerio Pastore's avatar
Valerio Pastore committed

	int to_be_rcv = pack.getPayloadSize() + pack.getTailSize();
astri's avatar
astri committed
	rec += ::recv(this->srv_sock, &buff[headerSize], to_be_rcv, MSG_WAITALL);
	if (rec != to_be_rcv + headerSize) {
Valerio Pastore's avatar
Valerio Pastore committed
		resetPacket(pack, headerSize);
		delete buff;
		return -1;
	}
	pack.copyToBinaryPointer(&buff[headerSize],
			pack.getPayloadSize() + pack.getTailSize(), headerSize);
	delete buff;
	return rec;
}
Valerio Pastore's avatar
Valerio Pastore committed

int TCPProtocol::connectToClient() {
	return m_connectToCli(ip, port);
}
int TCPProtocol::connectToServer() {
	return m_connectToSrv(ip, port);
}

int TCPProtocol::closeConnectionToClient() {
	if (srv_sock != -1) {
		::close(srv_sock);
		srv_sock = -1;
	}
	return 1;
}
int TCPProtocol::closeConnectionToServer() {
	if (cli_sock != -1) {
		::close(cli_sock);
		cli_sock = -1;
	}
	return 1;
}

bool TCPProtocol::isConnectedToClient() const {
	return srv_sock > 0;
}
bool TCPProtocol::isConnectedToServer() const {
	return cli_sock > 0;
}

int TCPProtocol::m_connectToCli(std::string ip, int port) {
	std::cout << "Listening on: " << ip << ":" << port << std::endl;
Valerio Pastore's avatar
Valerio Pastore committed
	// Creating socket file descriptor
astri's avatar
astri committed
	if (srv_sock == -1) {
		if ((srv_sock = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
astri's avatar
astri committed
			std::cerr << "socket failed" << std::endl;
			;
			return -1;
		}
Valerio Pastore's avatar
Valerio Pastore committed
	}
	struct sockaddr_in servaddr;
Valerio Pastore's avatar
Valerio Pastore committed
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = ::inet_addr(ip.c_str());
	servaddr.sin_port = htons(port);
	if (bind(srv_sock, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0) {
astri's avatar
astri committed
		std::cerr << "TCP CONNECTION: Bind failed" << std::endl;
		;
astri's avatar
astri committed
		srv_sock = -1;
Valerio Pastore's avatar
Valerio Pastore committed
		return -1;
	}
astri's avatar
astri committed
	std::cout << "TCP CONNECTION: Waiting for connection" << std::endl;
Valerio Pastore's avatar
Valerio Pastore committed

	if (listen(srv_sock, 1) < 0) {
astri's avatar
astri committed
		std::cerr << "TCP CONNECTION:  Listen error" << std::endl;
		;
astri's avatar
astri committed
		srv_sock = -1;
Valerio Pastore's avatar
Valerio Pastore committed
		return -1;
	}
	int newSocket;
	int addrlen = sizeof(servaddr);
	if ((newSocket = accept(srv_sock, (struct sockaddr*) &servaddr,
			(socklen_t*) &addrlen)) < 0) {
astri's avatar
astri committed
		std::cerr << "TCP CONNECTION:  accept error" << std::endl;
		;
astri's avatar
astri committed
		srv_sock = -1;
Valerio Pastore's avatar
Valerio Pastore committed
		return -1;
	}
	::close(srv_sock);
astri's avatar
astri committed
	std::cout << "TCP CONNECTION:  Connected" << std::endl;
	srv_sock = newSocket;
	return srv_sock;
Valerio Pastore's avatar
Valerio Pastore committed
}
int TCPProtocol::m_connectToSrv(std::string ip, int port) {
Valerio Pastore's avatar
Valerio Pastore committed
	int sock = 0;
	struct sockaddr_in cli_addr;
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
astri's avatar
astri committed
		std::cerr << "TCP CONNECTION: Socket creation error" << std::endl;
		;
astri's avatar
astri committed
		this->cli_sock = -1;
Valerio Pastore's avatar
Valerio Pastore committed
		return -1;
	}

	cli_addr.sin_family = AF_INET;
	cli_addr.sin_port = htons(port);

	// Convert IPv4 and IPv6 addresses from text to binary form
	if (inet_pton(AF_INET, ip.c_str(), &cli_addr.sin_addr) <= 0) {
astri's avatar
astri committed
		std::cerr << "TCP CONNECTION: Invalid address/ Address not supported"
				<< std::endl;
		;
astri's avatar
astri committed
		this->cli_sock = -1;
Valerio Pastore's avatar
Valerio Pastore committed
		return -1;
	}

	if (connect(sock, (struct sockaddr*) &cli_addr, sizeof(cli_addr)) < 0) {
astri's avatar
astri committed
		std::cerr << "TCP CONNECTION: Connection Failed " << std::endl;
		;
astri's avatar
astri committed
		this->cli_sock = -1;
Valerio Pastore's avatar
Valerio Pastore committed
		return -1;
	}
	std::cout << "Connected" << std::endl;
	this->cli_sock = sock;
	return cli_sock;

Valerio Pastore's avatar
Valerio Pastore committed
}

Valerio Pastore's avatar
Valerio Pastore committed
void TCPProtocol::resetPacket(PacketLib::BasePacket &pack, int bytes) {
	uint8_t *buff = new uint8_t[bytes];
	std::memset(buff, 0, bytes);
astri's avatar
astri committed
	int toBeReset = std::min(
			static_cast<int>(pack.getPacketStructureByteSize()), bytes);
Valerio Pastore's avatar
Valerio Pastore committed
	pack.copyToBinaryPointer(buff, toBeReset);
	delete buff;
}