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
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
class TTcpIpServerImp
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TTcpIpServerImp(int port) : m_port(port), m_s(-1), m_server(0) {}
|
|
|
|
|
|
|
|
int readData(int sock, QString &data);
|
|
|
|
void onReceive(int sock, const QString &data);
|
|
|
|
|
|
|
|
int m_s; // socket id
|
|
|
|
int m_port;
|
|
|
|
TTcpIpServer *m_server; // back pointer
|
|
|
|
|
|
|
|
TThread::Mutex m_mutex;
|
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
int TTcpIpServerImp::readData(int sock, QString &data)
|
|
|
|
{
|
|
|
|
int cnt = 0;
|
|
|
|
char buff[1025];
|
|
|
|
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) - 1, 0)) < 0) {
|
|
|
|
int err = WSAGetLastError();
|
|
|
|
// GESTIRE L'ERRORE SPECIFICO
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if ((cnt = read(sock, buff, sizeof(buff) - 1)) < 0) {
|
|
|
|
printf("socket read failure %d\n", errno);
|
|
|
|
perror("network server");
|
|
|
|
close(sock);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (cnt == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
#ifdef TRACE
|
|
|
|
cout << buff << endl
|
|
|
|
<< endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
string aa(buff);
|
|
|
|
int x1 = aa.find("#$#THS01.00");
|
|
|
|
x1 += sizeof("#$#THS01.00") - 1;
|
|
|
|
int x2 = aa.find("#$#THE");
|
|
|
|
|
|
|
|
string ssize;
|
|
|
|
for (int i = x1; i < x2; ++i)
|
|
|
|
ssize.push_back(buff[i]);
|
|
|
|
|
|
|
|
int dataSize = toInt(ssize);
|
|
|
|
|
|
|
|
unsigned long size = dataSize;
|
|
|
|
data = QString(buff + x2 + sizeof("#$#THE") - 1);
|
|
|
|
size -= data.size();
|
|
|
|
|
|
|
|
while (size > 0) {
|
|
|
|
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) - 1, 0)) < 0) {
|
|
|
|
int err = WSAGetLastError();
|
|
|
|
// GESTIRE L'ERRORE SPECIFICO
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if ((cnt = read(sock, buff, sizeof(buff) - 1)) < 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
|
|
|
|
} else if (cnt < (int)sizeof(buff)) {
|
|
|
|
buff[cnt] = '\0';
|
|
|
|
data += QString(buff);
|
|
|
|
//break; // break out of loop
|
|
|
|
} else {
|
|
|
|
data += QString(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef TRACE
|
|
|
|
cout << buff << endl
|
|
|
|
<< endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
size -= cnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef TRACE
|
|
|
|
cout << "read " << toString((int)data.length()) << " on " << toString((int)dataSize) << endl
|
|
|
|
<< endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (data.size() < dataSize)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#ifdef TRACE
|
|
|
|
cout << data.toStdString() << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
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
|
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TTcpIpServerImp::onReceive(int sock, const QString &data)
|
|
|
|
{
|
|
|
|
QMutexLocker sl(&m_mutex);
|
|
|
|
m_server->onReceive(sock, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
TTcpIpServer::TTcpIpServer(int port)
|
|
|
|
: m_imp(new TTcpIpServerImp(port))
|
|
|
|
{
|
|
|
|
m_imp->m_server = this;
|
|
|
|
|
2016-04-15 17:11:23 +12:00
|
|
|
#ifdef _WIN32
|
2016-03-19 06:57:51 +13:00
|
|
|
// Windows Socket startup
|
|
|
|
WSADATA wsaData;
|
|
|
|
WORD wVersionRequested = MAKEWORD(1, 1);
|
|
|
|
int irc = WSAStartup(wVersionRequested, &wsaData);
|
|
|
|
if (irc != 0)
|
|
|
|
throw("Windows Socket Startup failed");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
TTcpIpServer::~TTcpIpServer()
|
|
|
|
{
|
|
|
|
if (m_imp->m_s != -1)
|
2016-04-15 17:11:23 +12:00
|
|
|
#ifdef _WIN32
|
2016-03-19 06:57:51 +13:00
|
|
|
closesocket(m_imp->m_s);
|
|
|
|
WSACleanup();
|
|
|
|
#else
|
|
|
|
std::cout << "closing socket" << std::endl;
|
|
|
|
close(m_imp->m_s);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
int TTcpIpServer::getPort() const
|
|
|
|
{
|
|
|
|
return m_imp->m_port;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
static void shutdown_cb(int)
|
|
|
|
{
|
|
|
|
Sthutdown = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
class DataReader : public TThread::Runnable
|
|
|
|
{
|
|
|
|
public:
|
2016-04-14 22:15:09 +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
|
|
|
|
|
|
|
void run();
|
|
|
|
|
|
|
|
int m_clientSocket;
|
2016-04-14 22:15:09 +12:00
|
|
|
std::shared_ptr<TTcpIpServerImp> m_serverImp;
|
2016-03-19 06:57:51 +13: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-03-19 06:57:51 +13:00
|
|
|
closesocket(m_clientSocket);
|
|
|
|
#else
|
|
|
|
close(m_clientSocket);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
class DataReceiver : public TThread::Runnable
|
|
|
|
{
|
|
|
|
public:
|
2016-04-14 22:15:09 +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
|
|
|
|
|
|
|
void run();
|
|
|
|
|
|
|
|
int m_clientSocket;
|
|
|
|
QString m_data;
|
2016-04-14 22:15:09 +12:00
|
|
|
std::shared_ptr<TTcpIpServerImp> m_serverImp;
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
void DataReceiver::run()
|
|
|
|
{
|
|
|
|
m_serverImp->onReceive(m_clientSocket, m_data);
|
2016-04-15 17:11:23 +12:00
|
|
|
#ifdef _WIN32
|
2016-03-19 06:57:51 +13:00
|
|
|
closesocket(m_clientSocket);
|
|
|
|
#else
|
|
|
|
close(m_clientSocket);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TTcpIpServer::run()
|
|
|
|
{
|
|
|
|
try {
|
2016-04-15 17:11:23 +12:00
|
|
|
#ifdef _WIN32
|
2016-03-19 06:57:51 +13: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;
|
2016-04-14 22:15:09 +12:00
|
|
|
executor.addTask(new DataReceiver(t, data, m_imp));
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
::shutdown(t, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_exitCode = err;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-04-15 17:11:23 +12:00
|
|
|
#else // !_WIN32
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
int err = establish(m_imp->m_port, m_imp->m_s);
|
|
|
|
if (!err && m_imp->m_s != -1) {
|
|
|
|
// signal(SIGCHLD, fireman); /* this eliminates zombies */
|
|
|
|
|
|
|
|
#ifdef MACOSX
|
|
|
|
struct sigaction sact;
|
|
|
|
sact.sa_handler = shutdown_cb;
|
|
|
|
sigaction(SIGUSR1, &sact, 0);
|
|
|
|
#else
|
|
|
|
sigset(SIGUSR1, shutdown_cb);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
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;
|
2016-04-14 22:15:09 +12:00
|
|
|
executor.addTask(new DataReader(t, m_imp));
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_exitCode = err;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-04-15 17:11:23 +12:00
|
|
|
#endif // _WIN32
|
2016-03-19 06:57:51 +13:00
|
|
|
} catch (...) {
|
|
|
|
m_exitCode = 2000;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_exitCode = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
int TTcpIpServer::getExitCode() const
|
|
|
|
{
|
|
|
|
return m_exitCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TTcpIpServer::sendReply(int socket, const QString &reply)
|
|
|
|
{
|
|
|
|
string replyUtf8 = reply.toStdString();
|
|
|
|
|
|
|
|
QString header("#$#THS01.00");
|
|
|
|
header += QString::number((int)replyUtf8.size());
|
|
|
|
header += QString("#$#THE");
|
|
|
|
|
|
|
|
string packet = header.toStdString() + replyUtf8;
|
|
|
|
|
|
|
|
// string packet = reply;;
|
|
|
|
|
|
|
|
int nLeft = packet.size();
|
|
|
|
int idx = 0;
|
|
|
|
while (nLeft > 0) {
|
2016-04-15 17:11:23 +12:00
|
|
|
#ifdef _WIN32
|
2016-03-19 06:57:51 +13:00
|
|
|
int ret = send(socket, packet.c_str() + idx, nLeft, 0);
|
|
|
|
#else
|
|
|
|
int ret = write(socket, packet.c_str() + idx, nLeft);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (ret == SOCKET_ERROR) {
|
|
|
|
// Error
|
|
|
|
}
|
|
|
|
nLeft -= ret;
|
|
|
|
idx += ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
::shutdown(socket, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
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-03-19 06:57:51 +13:00
|
|
|
int err = WSAGetLastError();
|
|
|
|
return err;
|
|
|
|
#else
|
|
|
|
return errno;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (::bind(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
|
2016-04-15 17:11:23 +12:00
|
|
|
#ifdef _WIN32
|
2016-03-19 06:57:51 +13:00
|
|
|
int err = WSAGetLastError();
|
|
|
|
closesocket(sock);
|
|
|
|
return err;
|
|
|
|
#else
|
|
|
|
return errno;
|
|
|
|
close(sock);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return listen(sock, 3); /* max # of queued connects */
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/* wait for a connection to occur on a socket created with establish() */
|
|
|
|
|
|
|
|
int get_connection(int s)
|
|
|
|
{
|
|
|
|
int t; /* socket of connection */
|
|
|
|
|
|
|
|
if ((t = accept(s, NULL, NULL)) < 0) /* accept connection if there is one */
|
|
|
|
return (-1);
|
|
|
|
return (t);
|
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
void fireman(int)
|
|
|
|
{
|
|
|
|
while (waitpid(-1, NULL, WNOHANG) > 0)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
#endif
|