tahoma2d/toonz/sources/toonzfarm/tfarm/ttcpipserver.cpp

505 lines
11 KiB
C++
Raw Normal View History

2016-03-19 06:57:51 +13:00
#include "ttcpip.h"
#include "tconvert.h"
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-03-19 06:57:51 +13:00
#include <Winsock2.h>
#else
#include <errno.h> /* obligatory includes */
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
#include "tthreadmessage.h"
#include "tthread.h"
2016-04-15 17:11:23 +12:00
#ifndef _WIN32
2016-03-19 06:57:51 +13:00
#define SOCKET_ERROR -1
#endif
#include <string>
using namespace std;
#define MAXHOSTNAME 1024
int establish(unsigned short portnum, int &sock);
int get_connection(int s);
void fireman(int);
void do_something(int);
bool Sthutdown = false;
//#define TRACE
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
class TTcpIpServerImp {
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
TTcpIpServerImp(int port) : m_port(port), m_s(-1), m_server(0) {}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int readData(int sock, QString &data);
void onReceive(int sock, const QString &data);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int m_s; // socket id
int m_port;
TTcpIpServer *m_server; // back pointer
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TThread::Mutex m_mutex;
2016-03-19 06:57:51 +13:00
};
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
int TTcpIpServerImp::readData(int sock, QString &data) {
int cnt = 0;
char buff[1025];
memset(buff, 0, sizeof(buff));
2016-03-19 06:57:51 +13:00
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
if ((cnt = recv(sock, buff, sizeof(buff) - 1, 0)) < 0) {
int err = WSAGetLastError();
// GESTIRE L'ERRORE SPECIFICO
return -1;
}
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
if ((cnt = read(sock, buff, sizeof(buff) - 1)) < 0) {
printf("socket read failure %d\n", errno);
perror("network server");
close(sock);
return -1;
}
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
if (cnt == 0) return 0;
2016-03-19 06:57:51 +13:00
#ifdef TRACE
2016-06-15 18:43:10 +12:00
cout << buff << endl << endl;
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
string aa(buff);
int x1 = aa.find("#$#THS01.00");
x1 += sizeof("#$#THS01.00") - 1;
int x2 = aa.find("#$#THE");
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
string ssize;
for (int i = x1; i < x2; ++i) ssize.push_back(buff[i]);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int dataSize = std::stoi(ssize);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
unsigned long size = dataSize;
data = QString(buff + x2 + sizeof("#$#THE") - 1);
size -= data.size();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
while (size > 0) {
memset(buff, 0, sizeof(buff));
2016-03-19 06:57:51 +13:00
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
if ((cnt = recv(sock, buff, sizeof(buff) - 1, 0)) < 0) {
int err = WSAGetLastError();
// GESTIRE L'ERRORE SPECIFICO
return -1;
}
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
if ((cnt = read(sock, buff, sizeof(buff) - 1)) < 0) {
printf("socket read failure %d\n", errno);
perror("network server");
close(sock);
return -1;
}
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
else if (cnt == 0) {
break; // break out of loop
} else if (cnt < (int)sizeof(buff)) {
buff[cnt] = '\0';
data += QString(buff);
// break; // break out of loop
} else {
data += QString(buff);
}
2016-03-19 06:57:51 +13:00
#ifdef TRACE
2016-06-15 18:43:10 +12:00
cout << buff << endl << endl;
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
size -= cnt;
}
2016-03-19 06:57:51 +13:00
#ifdef TRACE
2016-06-15 18:43:10 +12:00
cout << "read " << toString((int)data.length()) << " on " << dataSize << endl
<< endl;
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
if (data.size() < dataSize) return -1;
2016-03-19 06:57:51 +13:00
#ifdef TRACE
2016-06-15 18:43:10 +12:00
cout << data.toStdString() << endl;
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
return 0;
2016-03-19 06:57:51 +13:00
}
#if 0
int TTcpIpServerImp::readData(int sock, string &data)
{
int cnt = 0;
char buff[1024];
do
{
memset (buff,0,sizeof(buff));
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-03-19 06:57:51 +13:00
if (( cnt = recv(sock, buff, sizeof(buff), 0)) < 0 )
{
int err = WSAGetLastError();
// GESTIRE L'ERRORE SPECIFICO
return -1;
}
#else
if (( cnt = read (sock, buff, sizeof(buff))) < 0 )
{
printf("socket read failure %d\n", errno);
perror("network server");
close(sock);
return -1;
}
#endif
else
if (cnt == 0)
break; // break out of loop
data += string(buff);
}
while (cnt != 0); // do loop condition
return 0;
}
#endif
//#define PRIMA
#ifdef PRIMA
2016-06-15 18:43:10 +12:00
int TTcpIpServerImp::readData(int sock, string &data) {
int cnt = 0;
char buff[1024];
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
do {
memset(buff, 0, sizeof(buff));
2016-03-19 06:57:51 +13:00
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
if ((cnt = recv(sock, buff, sizeof(buff), 0)) < 0) {
int err = WSAGetLastError();
// GESTIRE L'ERRORE SPECIFICO
return -1;
}
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
if ((cnt = read(sock, buff, sizeof(buff))) < 0) {
printf("socket read failure %d\n", errno);
perror("network server");
close(sock);
return -1;
}
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
else if (cnt == 0) {
break; // break out of loop
} else if (cnt < sizeof(buff)) {
data += string(buff);
// break; // break out of loop
} else {
data += string(buff);
}
} while (cnt != 0); // do loop condition
return 0;
2016-03-19 06:57:51 +13:00
}
#endif
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void TTcpIpServerImp::onReceive(int sock, const QString &data) {
QMutexLocker sl(&m_mutex);
m_server->onReceive(sock, data);
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
TTcpIpServer::TTcpIpServer(int port) : m_imp(new TTcpIpServerImp(port)) {
m_imp->m_server = this;
2016-03-19 06:57:51 +13:00
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
// Windows Socket startup
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1, 1);
int irc = WSAStartup(wVersionRequested, &wsaData);
if (irc != 0) throw("Windows Socket Startup failed");
2016-03-19 06:57:51 +13:00
#endif
}
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
TTcpIpServer::~TTcpIpServer() {
if (m_imp->m_s != -1)
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
closesocket(m_imp->m_s);
WSACleanup();
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
std::cout << "closing socket" << std::endl;
close(m_imp->m_s);
2016-03-19 06:57:51 +13:00
#endif
}
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
int TTcpIpServer::getPort() const { return m_imp->m_port; }
2016-03-19 06:57:51 +13:00
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
static void shutdown_cb(int) { Sthutdown = true; }
2016-03-19 06:57:51 +13:00
//---------------------------------------------------------------------
class DataReader final : public TThread::Runnable {
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
DataReader(int clientSocket, std::shared_ptr<TTcpIpServerImp> serverImp)
: m_clientSocket(clientSocket), m_serverImp(std::move(serverImp)) {}
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void run() override;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int m_clientSocket;
std::shared_ptr<TTcpIpServerImp> m_serverImp;
2016-03-19 06:57:51 +13:00
};
2016-06-15 18:43:10 +12:00
void DataReader::run() {
QString data;
int ret = m_serverImp->readData(m_clientSocket, data);
if (ret != -1) {
if (data == QString("shutdown"))
Sthutdown = true;
else
m_serverImp->onReceive(m_clientSocket, data);
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
closesocket(m_clientSocket);
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
close(m_clientSocket);
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
}
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------
class DataReceiver final : public TThread::Runnable {
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
DataReceiver(int clientSocket, const QString &data,
std::shared_ptr<TTcpIpServerImp> serverImp)
: m_clientSocket(clientSocket)
, m_data(data)
, m_serverImp(std::move(serverImp)) {}
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void run() override;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int m_clientSocket;
QString m_data;
std::shared_ptr<TTcpIpServerImp> m_serverImp;
2016-03-19 06:57:51 +13:00
};
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void DataReceiver::run() {
m_serverImp->onReceive(m_clientSocket, m_data);
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
closesocket(m_clientSocket);
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
close(m_clientSocket);
2016-03-19 06:57:51 +13:00
#endif
}
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void TTcpIpServer::run() {
try {
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int err = establish(m_imp->m_port, m_imp->m_s);
if (!err && m_imp->m_s != -1) {
int t; // client socket
while (!Sthutdown) /* loop for connections */
{
if ((t = get_connection(m_imp->m_s)) < 0) /* get a connection */
{
m_exitCode = WSAGetLastError();
// GESTIRE LA CONDIZIONE DI ERRORE
return;
}
QString data;
int ret = m_imp->readData(t, data);
if (ret != -1 && data != "") {
if (data == QString("shutdown")) {
// DebugBreak();
Sthutdown = true;
} else {
// creo un nuovo thread per la gestione dei dati ricevuti
TThread::Executor executor;
executor.addTask(new DataReceiver(t, data, m_imp));
}
} else {
::shutdown(t, 1);
}
}
} else {
m_exitCode = err;
return;
}
#else // !_WIN32
int err = establish(m_imp->m_port, m_imp->m_s);
if (!err && m_imp->m_s != -1) {
2016-03-19 06:57:51 +13:00
// signal(SIGCHLD, fireman); /* this eliminates zombies */
#ifdef MACOSX
2016-06-15 18:43:10 +12:00
struct sigaction sact;
sact.sa_handler = shutdown_cb;
sigaction(SIGUSR1, &sact, 0);
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
sigset(SIGUSR1, shutdown_cb);
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
int t;
while (!Sthutdown) /* loop for connections */
{
if ((t = get_connection(m_imp->m_s)) < 0) /* get a connection */
{
if (errno == EINTR) /* EINTR might happen on accept(), */
continue; /* try again */
perror("accept"); /* bad */
m_exitCode = errno;
return;
}
TThread::Executor executor;
executor.addTask(new DataReader(t, m_imp));
}
} else {
m_exitCode = err;
return;
}
#endif // _WIN32
} catch (...) {
m_exitCode = 2000;
return;
}
m_exitCode = 0;
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
int TTcpIpServer::getExitCode() const { return m_exitCode; }
2016-03-19 06:57:51 +13:00
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
void TTcpIpServer::sendReply(int socket, const QString &reply) {
string replyUtf8 = reply.toStdString();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
QString header("#$#THS01.00");
header += QString::number((int)replyUtf8.size());
header += QString("#$#THE");
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
string packet = header.toStdString() + replyUtf8;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// string packet = reply;;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int nLeft = packet.size();
int idx = 0;
while (nLeft > 0) {
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
int ret = send(socket, packet.c_str() + idx, nLeft, 0);
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
int ret = write(socket, packet.c_str() + idx, nLeft);
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
if (ret == SOCKET_ERROR) {
// Error
}
nLeft -= ret;
idx += ret;
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
::shutdown(socket, 1);
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
2016-06-15 18:43:10 +12:00
int establish(unsigned short portnum, int &sock) {
char myname[MAXHOSTNAME + 1];
struct sockaddr_in sa;
struct hostent *hp;
memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */
gethostname(myname, MAXHOSTNAME); /* who are we? */
hp = gethostbyname(myname); /* get our address info */
if (hp == NULL) /* we don't exist !? */
return (-1);
sa.sin_family = hp->h_addrtype; /* this is our host address */
sa.sin_port = htons(portnum); /* this is our port number */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */
{
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
int err = WSAGetLastError();
return err;
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
return errno;
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
if (::bind(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-06-15 18:43:10 +12:00
int err = WSAGetLastError();
closesocket(sock);
return err;
2016-03-19 06:57:51 +13:00
#else
2016-06-15 18:43:10 +12:00
return errno;
close(sock);
2016-03-19 06:57:51 +13:00
#endif
2016-06-15 18:43:10 +12:00
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
return listen(sock, 3); /* max # of queued connects */
2016-03-19 06:57:51 +13:00
}
//-----------------------------------------------------------------------
/* wait for a connection to occur on a socket created with establish() */
2016-06-15 18:43:10 +12:00
int get_connection(int s) {
int t; /* socket of connection */
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
if ((t = accept(s, NULL, NULL)) < 0) /* accept connection if there is one */
return (-1);
return (t);
2016-03-19 06:57:51 +13:00
}
2016-04-15 17:11:23 +12:00
#ifndef _WIN32
2016-03-19 06:57:51 +13:00
//-----------------------------------------------------------------------
/* as children die we should get catch their returns or else we get
* zombies, A Bad Thing. fireman() catches falling children.
*/
2016-06-15 18:43:10 +12:00
void fireman(int) {
while (waitpid(-1, NULL, WNOHANG) > 0)
;
2016-03-19 06:57:51 +13:00
}
#endif