|
|
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 |
|