Blame tcpprotocol.cpp

541903
541903
#include <fcntl.h></fcntl.h>
541903
#include <unistd.h></unistd.h>
541903
#include <sys types.h=""></sys>
541903
#include <sys socket.h=""></sys>
541903
#include <sys epoll.h=""></sys>
541903
#include <netinet in.h=""></netinet>
541903
#include <netinet tcp.h=""></netinet>
541903
#include <netdb.h></netdb.h>
541903
541903
541903
#include "protocol.h"
541903
#include "server.h"
541903
#include "connection.h"
541903
#include "tcpprotocol.h"
541903
541903
541903
541903
TcpSocket::TcpSocket(
541903
	Protocol &protocol,
541903
	const Connection::Handle &connection,
541903
	const Server::Handle &server,
541903
	const Address &address,
541903
	int sockId
541903
):
541903
	Socket(protocol, connection, server, address),
541903
	sockId(sockId)
541903
{
541903
	int tcp_nodelay = 1;
541903
	setsockopt(sockId, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay, sizeof(int));
541903
	fcntl(sockId, F_SETFL, fcntl(sockId, F_GETFL, 0) | O_NONBLOCK);
541903
	
541903
	struct epoll_event event = {};
541903
	event.data.ptr = this;
541903
	epoll_ctl(getProtocol().epollId, EPOLL_CTL_ADD, sockId, &event);
541903
}
541903
541903
541903
TcpProtocol::TcpProtocol():
541903
	thread(), stopping() { }
541903
541903
541903
ErrorCode TcpProtocol::resolve(Address &address) {
541903
	if (address.type == Address::SOCKET)
541903
		return ERR_NONE;
541903
	
541903
	if ( address.type != Address::COMMON_STRING
541903
	  || address.text.empty() )
541903
		return ERR_ADDRESS_INCORRECT;
541903
	
541903
	// split to host and port
541903
	const char *addrString = address.text.c_str();
541903
	const char *colon = addrString;
541903
	while(*colon && *colon != ':') ++colon;
541903
	
541903
	std::string hostBuf;
541903
	const char *host = nullptr;
541903
	const char *port = nullptr;
541903
	if (*colon) {
541903
		hostBuf.assign(addrString, colon);
541903
		host = hostBuf.c_str();
541903
		port = colon + 1;
541903
	} else {
541903
		bool allDigits = true;
541903
		for(const char *c = addrString; *c && allDigits; ++c)
541903
			if (*c < '0' || *c > '9') allDigits = false;
541903
		(allDigits ? port : host) = addrString;
541903
	}
541903
	
541903
	// get ipv4
541903
	unsigned char ip[4] = {};
541903
	if (host) {
541903
		if (4 != sscanf(host, "%hhu.%hhu.%hhu.%hhu", &ip[0], &ip[1], &ip[2], &ip[3])) {
541903
			hostent *he;
541903
			in_addr **addr_list;
541903
			if ( (he = gethostbyname(host))
541903
			  && (addr_list = (struct in_addr**)he->h_addr_list)
541903
			  && (*addr_list) )
541903
			{
541903
				memcpy(ip, *addr_list, sizeof(ip));
541903
			} else {
541903
				return ERR_ADDRESS_NOT_FOUND;
541903
			}
541903
		}
541903
	}
541903
	
541903
	unsigned short portNum = 0;
541903
	if (!port || 1 != sscanf(port, "%hu", &portNum) || !portNum)
541903
		return ERR_ADDRESS_INCORRECT;
541903
	
541903
	address.set(Address::SOCKET);
541903
	sockaddr_in &addr = address.as<sockaddr_in>();</sockaddr_in>
541903
	addr.sin_family = AF_INET;
541903
	memcpy(&addr.sin_addr, ip, sizeof(ip));
541903
	addr.sin_port = htons(portNum);
541903
	
541903
	return ERR_NONE;
541903
}
541903
541903
541903
void TcpProtocol::threadRun() {
541903
	const int count = 1024;
541903
	struct epoll_event events[count] = {};
541903
	while(true) {
541903
		epoll_wait(epollId, events, count, 1000);
541903
		break;
541903
	}
541903
	closeAll();
541903
}
541903
541903
541903
ErrorCode TcpProtocol::connect(const Connection::Handle &connection, const Address &address) {
541903
	if (!thread) return ERR_PROTOCOL_NOT_INITIALIZED;
541903
541903
	Address remoteAddres = address;
541903
	ErrorCode errorCode = resolve(remoteAddres);
541903
	if (errorCode) return errorCode;
541903
	
541903
	Lock lock(mutex);
541903
	
541903
	int sockId = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
541903
	if (0 != ::connect(sockId, &remoteAddres.as<sockaddr>(), remoteAddres.size)) {</sockaddr>
541903
		::close(sockId);
541903
		return ERR_CONNECTION_FAILED;
541903
	}
541903
	
541903
	TcpSocket *socket = new TcpSocket(*this, connection, nullptr, remoteAddres, sockId);
541903
	connection->open(socket);
541903
	return ERR_NONE;
541903
}
541903
541903
541903
ErrorCode TcpProtocol::listen(const Server::Handle &server, const Address &address) {
541903
	return ERR_NOT_IMPLEMENTED;
541903
}
541903
541903
541903
void TcpProtocol::start() {
541903
	stop();
541903
	epollId = ::epoll_create(32);
541903
	thread = new std::thread(&TcpProtocol::threadRun, this);
541903
}
541903
541903
541903
void TcpProtocol::stop() {
541903
	if (!thread) return;
541903
	{ Lock lock2(mutex); stopping = true; }
541903
	thread->join();
541903
	delete thread;
541903
	::close(epollId);
541903
	epollId = 0;
541903
}
541903