1 
2 
3 #include "ttcpip.h"
4 #include "tconvert.h"
5 
6 #ifdef _WIN32
7 #include <winsock2.h>
8 #else
9 #include <errno.h> /* obligatory includes */
10 #include <signal.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <sys/wait.h>
16 #include <netinet/in.h>
17 #include <netdb.h>
18 #endif
19 
20 #include "tthreadmessage.h"
21 #include "tthread.h"
22 #ifndef _WIN32
23 #define SOCKET_ERROR -1
24 #endif
25 
26 #include <string>
27 using namespace std;
28 
29 #define MAXHOSTNAME 1024
30 
31 int establish(unsigned short portnum, int &sock);
32 int get_connection(int s);
33 void fireman(int);
34 void do_something(int);
35 
36 bool Sthutdown = false;
37 
38 //#define TRACE
39 
40 //---------------------------------------------------------------------
41 
42 class TTcpIpServerImp {
43 public:
TTcpIpServerImp(int port)44   TTcpIpServerImp(int port) : m_port(port), m_s(-1), m_server(0) {}
45 
46   int readData(int sock, QString &data);
47   void onReceive(int sock, const QString &data);
48 
49   int m_s;  // socket id
50   int m_port;
51   TTcpIpServer *m_server;  // back pointer
52 
53   TThread::Mutex m_mutex;
54 };
55 
56 //---------------------------------------------------------------------
57 
readData(int sock,QString & data)58 int TTcpIpServerImp::readData(int sock, QString &data) {
59   int cnt = 0;
60   char buff[1025];
61   memset(buff, 0, sizeof(buff));
62 
63 #ifdef _WIN32
64   if ((cnt = recv(sock, buff, sizeof(buff) - 1, 0)) < 0) {
65     int err = WSAGetLastError();
66     // GESTIRE L'ERRORE SPECIFICO
67     return -1;
68   }
69 #else
70   if ((cnt = read(sock, buff, sizeof(buff) - 1)) < 0) {
71     printf("socket read failure %d\n", errno);
72     perror("network server");
73     close(sock);
74     return -1;
75   }
76 #endif
77 
78   if (cnt == 0) return 0;
79 
80 #ifdef TRACE
81   cout << buff << endl << endl;
82 #endif
83 
84   string aa(buff);
85   int x1 = aa.find("#$#THS01.00");
86   x1 += sizeof("#$#THS01.00") - 1;
87   int x2 = aa.find("#$#THE");
88 
89   string ssize;
90   for (int i = x1; i < x2; ++i) ssize.push_back(buff[i]);
91 
92   int dataSize = std::stoi(ssize);
93 
94   unsigned long size = dataSize;
95   data               = QString(buff + x2 + sizeof("#$#THE") - 1);
96   size -= data.size();
97 
98   while (size > 0) {
99     memset(buff, 0, sizeof(buff));
100 
101 #ifdef _WIN32
102     if ((cnt = recv(sock, buff, sizeof(buff) - 1, 0)) < 0) {
103       int err = WSAGetLastError();
104       // GESTIRE L'ERRORE SPECIFICO
105       return -1;
106     }
107 #else
108     if ((cnt = read(sock, buff, sizeof(buff) - 1)) < 0) {
109       printf("socket read failure %d\n", errno);
110       perror("network server");
111       close(sock);
112       return -1;
113     }
114 #endif
115     else if (cnt == 0) {
116       break;  // break out of loop
117     } else if (cnt < (int)sizeof(buff)) {
118       buff[cnt] = '\0';
119       data += QString(buff);
120       // break;  // break out of loop
121     } else {
122       data += QString(buff);
123     }
124 
125 #ifdef TRACE
126     cout << buff << endl << endl;
127 #endif
128 
129     size -= cnt;
130   }
131 
132 #ifdef TRACE
133   cout << "read " << toString((int)data.length()) << " on " << dataSize << endl
134        << endl;
135 #endif
136 
137   if (data.size() < dataSize) return -1;
138 
139 #ifdef TRACE
140   cout << data.toStdString() << endl;
141 #endif
142 
143   return 0;
144 }
145 
146 #if 0
147 
148 int TTcpIpServerImp::readData(int sock, string &data)
149 {
150   int cnt = 0;
151   char buff[1024];
152 
153   do
154   {
155     memset (buff,0,sizeof(buff));
156 
157 #ifdef _WIN32
158     if (( cnt = recv(sock, buff, sizeof(buff), 0)) < 0 )
159     {
160       int err = WSAGetLastError();
161       // GESTIRE L'ERRORE SPECIFICO
162       return -1;
163     }
164 #else
165     if (( cnt = read (sock, buff, sizeof(buff))) < 0 )
166     {
167       printf("socket read failure %d\n", errno);
168       perror("network server");
169       close(sock);
170       return -1;
171     }
172 #endif
173     else
174     if (cnt == 0)
175       break;  // break out of loop
176 
177     data += string(buff);
178   }
179   while (cnt != 0);  // do loop condition
180 
181   return 0;
182 }
183 
184 #endif
185 
186 //#define PRIMA
187 
188 #ifdef PRIMA
189 
readData(int sock,string & data)190 int TTcpIpServerImp::readData(int sock, string &data) {
191   int cnt = 0;
192   char buff[1024];
193 
194   do {
195     memset(buff, 0, sizeof(buff));
196 
197 #ifdef _WIN32
198     if ((cnt = recv(sock, buff, sizeof(buff), 0)) < 0) {
199       int err = WSAGetLastError();
200       // GESTIRE L'ERRORE SPECIFICO
201       return -1;
202     }
203 #else
204     if ((cnt = read(sock, buff, sizeof(buff))) < 0) {
205       printf("socket read failure %d\n", errno);
206       perror("network server");
207       close(sock);
208       return -1;
209     }
210 #endif
211     else if (cnt == 0) {
212       break;  // break out of loop
213     } else if (cnt < sizeof(buff)) {
214       data += string(buff);
215       // break;  // break out of loop
216     } else {
217       data += string(buff);
218     }
219   } while (cnt != 0);  // do loop condition
220 
221   return 0;
222 }
223 
224 #endif
225 
226 //---------------------------------------------------------------------
227 
onReceive(int sock,const QString & data)228 void TTcpIpServerImp::onReceive(int sock, const QString &data) {
229   QMutexLocker sl(&m_mutex);
230   m_server->onReceive(sock, data);
231 }
232 
233 //---------------------------------------------------------------------
234 
TTcpIpServer(int port)235 TTcpIpServer::TTcpIpServer(int port) : m_imp(new TTcpIpServerImp(port)) {
236   m_imp->m_server = this;
237 
238 #ifdef _WIN32
239   // Windows Socket startup
240   WSADATA wsaData;
241   WORD wVersionRequested = MAKEWORD(1, 1);
242   int irc                = WSAStartup(wVersionRequested, &wsaData);
243   if (irc != 0) throw("Windows Socket Startup failed");
244 #endif
245 }
246 
247 //---------------------------------------------------------------------
248 
~TTcpIpServer()249 TTcpIpServer::~TTcpIpServer() {
250   if (m_imp->m_s != -1)
251 #ifdef _WIN32
252     closesocket(m_imp->m_s);
253   WSACleanup();
254 #else
255     std::cout << "closing socket" << std::endl;
256   close(m_imp->m_s);
257 #endif
258 }
259 
260 //---------------------------------------------------------------------
261 
getPort() const262 int TTcpIpServer::getPort() const { return m_imp->m_port; }
263 
264 //---------------------------------------------------------------------
265 
shutdown_cb(int)266 static void shutdown_cb(int) { Sthutdown = true; }
267 
268 //---------------------------------------------------------------------
269 
270 class DataReader final : public TThread::Runnable {
271 public:
DataReader(int clientSocket,std::shared_ptr<TTcpIpServerImp> serverImp)272   DataReader(int clientSocket, std::shared_ptr<TTcpIpServerImp> serverImp)
273       : m_clientSocket(clientSocket), m_serverImp(std::move(serverImp)) {}
274 
275   void run() override;
276 
277   int m_clientSocket;
278   std::shared_ptr<TTcpIpServerImp> m_serverImp;
279 };
280 
run()281 void DataReader::run() {
282   QString data;
283   int ret = m_serverImp->readData(m_clientSocket, data);
284   if (ret != -1) {
285     if (data == QString("shutdown"))
286       Sthutdown = true;
287     else
288       m_serverImp->onReceive(m_clientSocket, data);
289 #ifdef _WIN32
290     closesocket(m_clientSocket);
291 #else
292     close(m_clientSocket);
293 #endif
294   }
295 }
296 
297 //---------------------------------------------------------------------
298 
299 class DataReceiver final : public TThread::Runnable {
300 public:
DataReceiver(int clientSocket,const QString & data,std::shared_ptr<TTcpIpServerImp> serverImp)301   DataReceiver(int clientSocket, const QString &data,
302                std::shared_ptr<TTcpIpServerImp> serverImp)
303       : m_clientSocket(clientSocket)
304       , m_data(data)
305       , m_serverImp(std::move(serverImp)) {}
306 
307   void run() override;
308 
309   int m_clientSocket;
310   QString m_data;
311   std::shared_ptr<TTcpIpServerImp> m_serverImp;
312 };
313 
314 //---------------------------------------------------------------------
315 
run()316 void DataReceiver::run() {
317   m_serverImp->onReceive(m_clientSocket, m_data);
318 #ifdef _WIN32
319   closesocket(m_clientSocket);
320 #else
321   close(m_clientSocket);
322 #endif
323 }
324 
325 //---------------------------------------------------------------------
326 
run()327 void TTcpIpServer::run() {
328   try {
329 #ifdef _WIN32
330 
331     int err = establish(m_imp->m_port, m_imp->m_s);
332     if (!err && m_imp->m_s != -1) {
333       int t;  // client socket
334 
335       while (!Sthutdown) /* loop for connections */
336       {
337         if ((t = get_connection(m_imp->m_s)) < 0) /* get a connection */
338         {
339           m_exitCode = WSAGetLastError();
340           // GESTIRE LA CONDIZIONE DI ERRORE
341           return;
342         }
343 
344         QString data;
345         int ret = m_imp->readData(t, data);
346         if (ret != -1 && data != "") {
347           if (data == QString("shutdown")) {
348             // DebugBreak();
349             Sthutdown = true;
350           } else {
351             // creo un nuovo thread per la gestione dei dati ricevuti
352             TThread::Executor executor;
353             executor.addTask(new DataReceiver(t, data, m_imp));
354           }
355         } else {
356           ::shutdown(t, 1);
357         }
358       }
359     } else {
360       m_exitCode = err;
361       return;
362     }
363 
364 #else  // !_WIN32
365 
366     int err = establish(m_imp->m_port, m_imp->m_s);
367     if (!err && m_imp->m_s != -1) {
368 //      signal(SIGCHLD, fireman);           /* this eliminates zombies */
369 
370 #if defined(MACOSX) || defined(__DragonFly__)
371       struct sigaction sact;
372       sact.sa_handler = shutdown_cb;
373       sigaction(SIGUSR1, &sact, 0);
374 #else
375       sigset(SIGUSR1, shutdown_cb);
376 #endif
377 
378       int t;
379 
380       while (!Sthutdown) /* loop for connections */
381       {
382         if ((t = get_connection(m_imp->m_s)) < 0) /* get a connection */
383         {
384           if (errno == EINTR) /* EINTR might happen on accept(), */
385             continue;         /* try again */
386           perror("accept");   /* bad */
387           m_exitCode = errno;
388           return;
389         }
390 
391         TThread::Executor executor;
392         executor.addTask(new DataReader(t, m_imp));
393       }
394     } else {
395       m_exitCode = err;
396       return;
397     }
398 
399 #endif  // _WIN32
400   } catch (...) {
401     m_exitCode = 2000;
402     return;
403   }
404 
405   m_exitCode = 0;
406 }
407 
408 //---------------------------------------------------------------------
409 
getExitCode() const410 int TTcpIpServer::getExitCode() const { return m_exitCode; }
411 
412 //---------------------------------------------------------------------
413 
sendReply(int socket,const QString & reply)414 void TTcpIpServer::sendReply(int socket, const QString &reply) {
415   string replyUtf8 = reply.toStdString();
416 
417   QString header("#$#THS01.00");
418   header += QString::number((int)replyUtf8.size());
419   header += QString("#$#THE");
420 
421   string packet = header.toStdString() + replyUtf8;
422 
423   //  string packet = reply;;
424 
425   int nLeft = packet.size();
426   int idx   = 0;
427   while (nLeft > 0) {
428 #ifdef _WIN32
429     int ret = send(socket, packet.c_str() + idx, nLeft, 0);
430 #else
431     int ret = write(socket, packet.c_str() + idx, nLeft);
432 #endif
433 
434     if (ret == SOCKET_ERROR) {
435       // Error
436     }
437     nLeft -= ret;
438     idx += ret;
439   }
440 
441   ::shutdown(socket, 1);
442 }
443 
444 //---------------------------------------------------------------------
445 //---------------------------------------------------------------------
446 
establish(unsigned short portnum,int & sock)447 int establish(unsigned short portnum, int &sock) {
448   char myname[MAXHOSTNAME + 1];
449   struct sockaddr_in sa;
450   struct hostent *hp;
451 
452   memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */
453   gethostname(myname, MAXHOSTNAME);           /* who are we? */
454   hp = gethostbyname(myname);                 /* get our address info */
455   if (hp == NULL)                             /* we don't exist !? */
456     return (-1);
457 
458   sa.sin_family = hp->h_addrtype; /* this is our host address */
459   sa.sin_port   = htons(portnum); /* this is our port number */
460   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */
461   {
462 #ifdef _WIN32
463     int err = WSAGetLastError();
464     return err;
465 #else
466     return errno;
467 #endif
468   }
469 
470   if (::bind(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
471 #ifdef _WIN32
472     int err = WSAGetLastError();
473     closesocket(sock);
474     return err;
475 #else
476     return errno;
477     close(sock);
478 #endif
479   }
480 
481   return listen(sock, 3); /* max # of queued connects */
482 }
483 
484 //-----------------------------------------------------------------------
485 /* wait for a connection to occur on a socket created with establish() */
486 
get_connection(int s)487 int get_connection(int s) {
488   int t; /* socket of connection */
489 
490   if ((t = accept(s, NULL, NULL)) < 0) /* accept connection if there is one */
491     return (-1);
492   return (t);
493 }
494 
495 #ifndef _WIN32
496 //-----------------------------------------------------------------------
497 /* as children die we should get catch their returns or else we get
498  * zombies, A Bad Thing.  fireman() catches falling children.
499  */
fireman(int)500 void fireman(int) {
501   while (waitpid(-1, NULL, WNOHANG) > 0)
502     ;
503 }
504 #endif
505