1 /*
2  * This file is part of Licq, an instant messaging client for UNIX.
3  * Copyright (C) 1998-2013 Licq developers <licq-dev@googlegroups.com>
4  *
5  * Licq is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Licq is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Licq; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #include "icq.h"
21 
22 #include <boost/foreach.hpp>
23 #include <cerrno>
24 #include <ctime>
25 #include <unistd.h>
26 
27 #include <licq/contactlist/owner.h>
28 #include <licq/contactlist/usermanager.h>
29 #include <licq/event.h>
30 #include <licq/plugin/pluginmanager.h>
31 #include <licq/pluginsignal.h>
32 #include <licq/protocolmanager.h>
33 #include <licq/logging/log.h>
34 
35 #include "buffer.h"
36 #include "defines.h"
37 #include "gettext.h"
38 #include "icqprotocolplugin.h"
39 #include "oscarservice.h"
40 #include "owner.h"
41 #include "packet-srv.h"
42 #include "packet-tcp.h"
43 #include "socket.h"
44 #include "user.h"
45 
46 #define MAX_CONNECTS  256
47 #define DEBUG_THREADS(x)
48 //#define DEBUG_THREADS(x) gLog.info(x)
49 
50 namespace LicqIcq
51 {
52 void* ProcessRunningEvent_Server_tep(void* p);
53 void* ProcessRunningEvent_Client_tep(void* p);
54 void* ReverseConnectToUser_tep(void* v);
55 void* Ping_tep(void* p);
56 void* MonitorSockets_func();
57 void* UpdateUsers_tep(void* p);
58 }
59 
60 using namespace LicqIcq;
61 using Licq::gLog;
62 using std::list;
63 using std::string;
64 
cleanup_mutex(void * m)65 void cleanup_mutex(void *m)
66 {
67   pthread_mutex_unlock((pthread_mutex_t *)m);
68 }
69 
cleanup_socket(void * s)70 void cleanup_socket(void *s)
71 {
72   gSocketManager.DropSocket((Licq::INetSocket *)s);
73 }
74 
cleanup_thread_tep(void * t)75 void *cleanup_thread_tep(void *t)
76 {
77   pthread_detach(pthread_self());
78   void *s;
79   pthread_join(*((pthread_t *)t), &s);
80   delete (pthread_t *)t;
81   delete (int *)s;
82   pthread_exit(NULL);
83 }
84 
cleanup_thread(void * t)85 void cleanup_thread(void *t)
86 {
87   pthread_t cleanup;
88   pthread_create(&cleanup, NULL, &cleanup_thread_tep, t);
89 }
90 
ConnectToServer_tep(void * s)91 void *ConnectToServer_tep(void *s)
92 {
93   *((int *)s) = gIcqProtocol.ConnectToLoginServer();
94   pthread_exit(s);
95 }
96 
97 
98 /*------------------------------------------------------------------------------
99  * ProcessRunningEvent_tep
100  *
101  * Thread entry point to run an event.  First checks to see if the socket for
102  * the given event needs to be connected and calls the relevant connection
103  * function.  Then sends the event, retrying after a timeout.  If an ack is
104  * received, the thread will be cancelled by the receiving thread.
105  *
106  * The parameter is only used to get the CICQDaemon, the actual event is
107  * now popped off the send queue to prevent packets being sent out of order
108  * which is a severe error with OSCAR.
109  *----------------------------------------------------------------------------*/
ProcessRunningEvent_Server_tep(void *)110 void* LicqIcq::ProcessRunningEvent_Server_tep(void* /* p */)
111 {
112   pthread_detach(pthread_self());
113 
114   static unsigned short nNext = 0;
115   static pthread_mutex_t send_mutex = PTHREAD_MUTEX_INITIALIZER;
116 
117   /* want to be cancelled immediately so we don't try to derefrence the event
118      after it has been deleted */
119   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
120 
121   DEBUG_THREADS("[ProcessRunningEvent_Server_tep] Caught event.\n");
122 
123   // Must send packets in sequential order
124   pthread_mutex_lock(&send_mutex);
125   pthread_mutex_lock(&gIcqProtocol.mutex_sendqueue_server);
126 
127   list<Licq::Event*>::iterator iter;
128   Licq::Event* e = NULL;
129 
130   while (e == NULL)
131   {
132 
133     for (iter = gIcqProtocol.m_lxSendQueue_Server.begin();
134          iter != gIcqProtocol.m_lxSendQueue_Server.end(); ++iter)
135     {
136       CSrvPacketTcp* srvPacket = dynamic_cast<CSrvPacketTcp*>((*iter)->m_pPacket);
137       if (srvPacket != NULL && srvPacket->icqChannel() == ICQ_CHNxNEW)
138       {
139         e = *iter;
140         nNext = e->Sequence() + 1;
141         break;
142       }
143 
144       if ((*iter)->Sequence() == nNext)
145       {
146         e = *iter;
147         nNext++;
148         break;
149       }
150     }
151 
152     if (e == NULL)
153     {
154       bool bEmpty = gIcqProtocol.m_lxSendQueue_Server.empty();
155 
156       pthread_mutex_unlock(&gIcqProtocol.mutex_sendqueue_server);
157       pthread_mutex_unlock(&send_mutex);
158 
159       if (bEmpty)
160         pthread_exit(NULL);
161 
162       struct timeval tv = { 1, 0 };
163       select(0, NULL, NULL, NULL, &tv);
164       pthread_mutex_lock(&send_mutex);
165       pthread_mutex_lock(&gIcqProtocol.mutex_sendqueue_server);
166     }
167     else
168     {
169       gIcqProtocol.m_lxSendQueue_Server.erase(iter);
170 
171       if (e->m_bCancelled)
172       {
173         delete e;
174         e = NULL;
175       }
176     }
177   }
178 
179   pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
180 
181   e->thread_send = pthread_self();
182   e->thread_running = true;
183 
184   // Done reading the queue now
185   pthread_mutex_unlock(&gIcqProtocol.mutex_sendqueue_server);
186 
187   // declared here because pthread_cleanup_push starts a new block
188   Licq::Buffer* buf;
189   bool sent = false;
190   bool bExit = false;
191   string errorStr;
192 
193   pthread_cleanup_push(cleanup_mutex, &send_mutex);
194 
195     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
196     pthread_testcancel();
197 
198     int socket = -1;
199     unsigned short nSequence;
200   Licq::INetSocket *s;
201 
202     // Check if the socket is connected
203     if (e->m_nSocketDesc == -1)
204     {
205       // Connect to the server if we are logging on
206     CSrvPacketTcp* srvPacket = dynamic_cast<CSrvPacketTcp*>(e->m_pPacket);
207     if (srvPacket != NULL && srvPacket->icqChannel() == ICQ_CHNxNEW)
208     {
209         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
210       gLog.info(tr("Connecting to login server."));
211 
212         pthread_t *t = new pthread_t;
213         int *s = new int;
214         pthread_create(t, NULL, ConnectToServer_tep, s);
215         pthread_cleanup_push(cleanup_thread, t);
216           pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
217           pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
218           pthread_testcancel();
219           pthread_join(*t, NULL);
220         pthread_cleanup_pop(0);
221         int socket = *s;
222         delete t;
223         delete s;
224 
225         pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
226         pthread_testcancel();
227 
228         e->m_nSocketDesc = socket;
229 
230         // Check again, if still -1, fail the event
231         if (e->m_nSocketDesc == -1)
232         {
233           pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
234         gLog.info(tr("Connecting to login server failed, failing event."));
235           // we need to initialize the logon time for the next retry
236           gIcqProtocol.m_tLogonTime = time(NULL);
237           gIcqProtocol.m_eStatus = STATUS_OFFLINE_FORCED;
238           gIcqProtocol.m_bLoggingOn = false;
239         if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
240         {
241           gIcqProtocol.DoneExtendedEvent(e, Licq::Event::ResultError);
242           gIcqProtocol.ProcessDoneEvent(e);
243         }
244         else
245           {
246             pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
247             pthread_testcancel();
248             delete e;
249           }
250           bExit = true;
251           goto exit_server_thread;
252         }
253       }
254       else
255       {
256         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
257       gLog.info(tr("Not connected to server, failing event."));
258       if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
259       {
260         gIcqProtocol.DoneExtendedEvent(e, Licq::Event::ResultError);
261         gIcqProtocol.ProcessDoneEvent(e);
262       }
263       else
264         {
265           pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
266           pthread_testcancel();
267           delete e;
268         }
269         bExit = true;
270         goto exit_server_thread;
271       }
272     }
273 
274     socket = e->m_nSocketDesc;
275     nSequence = e->m_nSequence;
276 
277     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
278     // Start sending the event
279     s = gSocketManager.FetchSocket(socket);
280     if (s == NULL)
281     {
282       gLog.warning(tr("Socket not connected or invalid (#%hu)."), nSequence);
283     if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
284     {
285       gIcqProtocol.DoneExtendedEvent(e, Licq::Event::ResultError);
286       gIcqProtocol.ProcessDoneEvent(e);
287     }
288     else
289       {
290         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
291         pthread_testcancel();
292         delete e;
293       }
294       bExit = true;
295       goto exit_server_thread;
296     }
297 
298     pthread_cleanup_push(cleanup_socket, s);
299 
300     pthread_mutex_lock(&gIcqProtocol.mutex_cancelthread);
301 
302       // check to make sure we were not cancelled already
303     pthread_cleanup_push(cleanup_mutex, &gIcqProtocol.mutex_cancelthread);
304         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
305         pthread_testcancel();
306         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
307 
308         //if we get here  then we haven't been cancelled and we won't be
309         //as long as we hold mutex_cancelthread
310 
311         buf = e->m_pPacket->Finalize(NULL);
312 
313     pthread_mutex_unlock(&gIcqProtocol.mutex_cancelthread);
314       pthread_cleanup_pop(0); //mutex_cancelthread
315 
316   sent = s->send(*buf);
317       delete buf;
318 
319       if (!sent)
320         errorStr = s->errorStr();
321 
322       // We don't close the socket as it should be closed by the server thread
323       gSocketManager.DropSocket(s);
324     pthread_cleanup_pop(0); //socket
325 
326 exit_server_thread:
327     pthread_mutex_unlock(&send_mutex);
328   pthread_cleanup_pop(0); //send_mutex
329 
330   if (bExit)
331     pthread_exit(NULL);
332 
333   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
334   pthread_testcancel();
335 
336   if (!sent)
337   {
338     unsigned short nSequence = e->m_nSequence;
339 
340     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
341 
342     gLog.warning(tr("Error sending event (#%hu): %s."),
343         nSequence, errorStr.c_str());
344 
345     if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
346     {
347       gIcqProtocol.DoneExtendedEvent(e, Licq::Event::ResultError);
348       gIcqProtocol.ProcessDoneEvent(e);
349     }
350     else
351     {
352       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
353       pthread_testcancel();
354       delete e;
355     }
356   }
357   else
358   {
359     if (e->m_NoAck)
360     {
361       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
362       // send successfully and we don't get an answer from the server
363       if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultAcked) != NULL)
364       {
365         gIcqProtocol.DoneExtendedEvent(e, Licq::Event::ResultAcked);
366         gIcqProtocol.ProcessDoneEvent(e);
367       }
368       else
369       {
370         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
371         pthread_testcancel();
372         delete e;
373       }
374     }
375     else
376     {
377       e->thread_running = false;
378       // pthread_exit is not async cancel safe???
379       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
380     }
381   }
382 
383   pthread_exit(NULL);
384 
385   return NULL;
386 }
387 
388 
ProcessRunningEvent_Client_tep(void * p)389 void* LicqIcq::ProcessRunningEvent_Client_tep(void *p)
390 {
391   pthread_detach(pthread_self());
392 
393   pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
394   /* want to be cancelled immediately so we don't try to derefence the event
395      after it has been deleted */
396   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
397 
398   DEBUG_THREADS("[ProcessRunningEvent_Client_tep] Caught event.\n");
399 
400   Licq::Event* e = (Licq::Event*)p;
401 
402   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
403   pthread_testcancel();
404 
405   // Check if the socket is connected
406   if (e->m_nSocketDesc == -1)
407   {
408     Licq::UserId userId = e->userId();
409     string id = userId.accountId();
410     CPacketTcp* packetTcp = dynamic_cast<CPacketTcp*>(e->m_pPacket);
411     int channel = (packetTcp != NULL ? packetTcp->channel() : DcSocket::ChannelNormal);
412     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
413 
414     unsigned long nVersion;
415     bool directMode;
416     unsigned short nRemotePort;
417     bool bSendIntIp;
418     {
419       UserReadGuard u(userId);
420       if (!u.isLocked())
421       {
422         if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
423           gIcqProtocol.ProcessDoneEvent(e);
424         else
425         {
426           pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
427           pthread_testcancel();
428           delete e;
429         }
430         pthread_exit(NULL);
431       }
432 
433       nVersion = u->Version();
434       directMode = u->directMode();
435       nRemotePort = u->Port();
436       bSendIntIp = u->SendIntIp();
437     }
438 
439     unsigned long nIP;
440     unsigned short nLocalPort;
441     {
442       Licq::OwnerReadGuard o(gIcqProtocol.ownerId());
443       nIP = bSendIntIp ? o->IntIp() : o->Ip();
444       nLocalPort = o->Port();
445     }
446 
447     int socket = -1;
448     if (!bSendIntIp && nVersion > 6 && !directMode)
449     {
450       int nId = gIcqProtocol.requestReverseConnection(userId, channel, nIP, nLocalPort, nRemotePort);
451       if (nId != -1)
452       {
453         gIcqProtocol.waitForReverseConnection(nId, userId);
454         UserReadGuard u(userId);
455         if (!u.isLocked())
456         {
457           if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
458             gIcqProtocol.ProcessDoneEvent(e);
459           else
460           {
461             pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
462             pthread_testcancel();
463             delete e;
464           }
465           pthread_exit(NULL);
466         }
467         socket = u->socketDesc(channel);
468       }
469 
470       // if we failed, try direct anyway
471       if (socket == -1)
472       {
473         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
474         pthread_testcancel();
475         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
476 
477         socket = gIcqProtocol.connectToUser(userId, channel);
478       }
479     }
480     else
481     {
482       socket = gIcqProtocol.connectToUser(userId, channel);
483 
484       // if we failed, try through server
485       if (socket == -1)
486       {
487         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
488         pthread_testcancel();
489         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
490 
491         int nId = gIcqProtocol.requestReverseConnection(userId, channel, nIP,
492                                               nLocalPort, nRemotePort);
493         if (nId != -1)
494         {
495           gIcqProtocol.waitForReverseConnection(nId, userId);
496           UserReadGuard u(userId);
497           if (!u.isLocked())
498           {
499             if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
500               gIcqProtocol.ProcessDoneEvent(e);
501             else
502             {
503               pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
504               pthread_testcancel();
505               delete e;
506             }
507             pthread_exit(NULL);
508           }
509           socket = u->socketDesc(channel);
510         }
511       }
512     }
513 
514     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
515     pthread_testcancel();
516     e->m_nSocketDesc = socket;
517     // Check again, if still -1, fail the event
518     if (e->m_nSocketDesc == -1)
519     {
520       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
521       if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
522         gIcqProtocol.ProcessDoneEvent(e);
523       else
524       {
525         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
526         pthread_testcancel();
527         delete e;
528       }
529       pthread_exit(NULL);
530     }
531   }
532 
533   int socket = e->m_nSocketDesc;
534   pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
535   Licq::INetSocket* s = gSocketManager.FetchSocket(socket);
536   if (s == NULL)
537   {
538     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
539     pthread_testcancel();
540     unsigned short nSequence = e->m_nSequence;
541     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
542 
543     gLog.warning(tr("Socket %d does not exist (#%hu)."), socket,
544        nSequence);
545     if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
546       gIcqProtocol.ProcessDoneEvent(e);
547     else
548     {
549       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
550       pthread_testcancel();
551       delete e;
552     }
553     pthread_exit(NULL);
554   }
555 
556   Licq::Buffer* buf;
557   bool sent;
558   string errorStr;
559   pthread_cleanup_push(cleanup_socket, s);
560 
561   pthread_mutex_lock(&gIcqProtocol.mutex_cancelthread);
562 
563     // check to make sure we were not cancelled already
564   pthread_cleanup_push(cleanup_mutex, &gIcqProtocol.mutex_cancelthread);
565       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
566       pthread_testcancel();
567       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
568 
569       //if we get here  then we haven't been cancelled and we won't be
570       //as long as we hold mutex_cancelthread
571 
572       buf = e->m_pPacket->Finalize(s);
573 
574   pthread_mutex_unlock(&gIcqProtocol.mutex_cancelthread);
575     pthread_cleanup_pop(0);
576 
577   sent = s->send(*buf);
578 
579     if (!sent)
580       errorStr = s->errorStr();
581 
582     gSocketManager.DropSocket(s);
583   pthread_cleanup_pop(0);
584 
585   if (!sent)
586   {
587     // Close the socket, alert the socket thread
588     gSocketManager.CloseSocket(socket);
589     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
590     pthread_testcancel();
591     unsigned short nSequence = e->m_nSequence;
592     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
593 
594     gLog.warning(tr("Error sending event (#%d): %s."), -nSequence, errorStr.c_str());
595     gIcqProtocol.myNewSocketPipe.putChar('S');
596     // Kill the event, do after the above as ProcessDoneEvent erase the event
597     if (gIcqProtocol.DoneEvent(e, Licq::Event::ResultError) != NULL)
598       gIcqProtocol.ProcessDoneEvent(e);
599     else
600     {
601       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
602       pthread_testcancel();
603       delete e;
604     }
605     pthread_exit(NULL);
606   }
607   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
608   pthread_testcancel();
609 
610   e->thread_running = false;
611 
612   // pthread_exit is not async cancel safe???
613   pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
614   pthread_exit(NULL);
615   // Avoid compiler warnings
616   return NULL;
617 }
618 
619 
620 /*------------------------------------------------------------------------------
621  * ReverseConnectToUser_tep
622  *
623  * Creates a new TCPSocket and connects it to a given user.  Adds the socket
624  * to the global socket manager and to the user.
625  *----------------------------------------------------------------------------*/
ReverseConnectToUser_tep(void * v)626 void* LicqIcq::ReverseConnectToUser_tep(void* v)
627 {
628   pthread_detach(pthread_self());
629 
630   DEBUG_THREADS("[ReverseConnectToUser_tep] Caught event.\n");
631 
632   CReverseConnectToUserData *p = (CReverseConnectToUserData *)v;
633 
634   Licq::UserId userId(gIcqProtocol.ownerId(), p->myIdString);
635   gIcqProtocol.reverseConnectToUser(userId, p->nIp, p->nPort,
636       p->nVersion, p->nFailedPort, p->nId, p->nMsgID1, p->nMsgID2);
637 
638   delete p;
639 
640   return NULL;
641 }
642 
643 
644 
645 
646 /*------------------------------------------------------------------------------
647  * Ping_tep
648  *
649  * Thread entry point to ping the server every n minutes.
650  *----------------------------------------------------------------------------*/
Ping_tep(void *)651 void* LicqIcq::Ping_tep(void * /*p*/)
652 {
653   pthread_detach(pthread_self());
654 
655   struct timeval tv;
656 
657   while (true)
658   {
659     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
660     switch (gIcqProtocol.Status())
661     {
662     case STATUS_ONLINE:
663         gIcqProtocol.icqPing();
664       break;
665     case STATUS_OFFLINE_MANUAL:
666       break;
667     case STATUS_OFFLINE_FORCED:
668       if (time(NULL) > gIcqProtocol.m_tLogonTime + IcqProtocol::LogonAttemptDelay)
669         gIcqProtocol.icqRelogon();
670       break;
671     }
672     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
673     pthread_testcancel();
674 
675     tv.tv_sec = IcqProtocol::PingFrequency;
676     tv.tv_usec = 0;
677     select(0, NULL, NULL, NULL, &tv);
678 
679     pthread_testcancel();
680   }
681   return NULL;
682 }
683 
684 
685 
686 /*------------------------------------------------------------------------------
687  * MonitorSockets_func
688  *
689  * The server thread lives here.  The main guy who waits on socket activity
690  * and processes incoming packets.
691  *----------------------------------------------------------------------------*/
MonitorSockets_func()692 void* LicqIcq::MonitorSockets_func()
693 {
694   fd_set f;
695   int nSocketsAvailable, nServiceSocket, l;
696 
697   while (true)
698   {
699     f = gSocketManager.socketSet();
700     l = gSocketManager.LargestSocket() + 1;
701 
702     // Add the new socket pipe descriptor
703     FD_SET(gIcqProtocol.myNewSocketPipe.getReadFd(), &f);
704     if (gIcqProtocol.myNewSocketPipe.getReadFd() >= l)
705       l = gIcqProtocol.myNewSocketPipe.getReadFd() + 1;
706 
707     // Add plugin notification pipe
708     FD_SET(gIcqProtocolPlugin->getReadPipe(), &f);
709     if (gIcqProtocolPlugin->getReadPipe() >= l)
710       l = gIcqProtocolPlugin->getReadPipe() + 1;
711 
712     nSocketsAvailable = select(l, &f, NULL, NULL, NULL);
713 
714     if (gIcqProtocol.m_xBARTService)
715     {
716       COscarService *svc = gIcqProtocol.m_xBARTService;
717       nServiceSocket = svc->GetSocketDesc();
718     }
719     else
720       nServiceSocket = -1;
721 
722     for (int nCurrentSocket = 0; nSocketsAvailable >= 0 && nCurrentSocket < l; ++nCurrentSocket)
723     {
724       if (!FD_ISSET(nCurrentSocket, &f))
725         continue;
726 
727       --nSocketsAvailable;
728 
729 
730       // New socket event ----------------------------------------------------
731       if (nCurrentSocket == gIcqProtocol.myNewSocketPipe.getReadFd())
732       {
733         char buf = gIcqProtocol.myNewSocketPipe.getChar();
734         if (buf == 'S')
735         {
736           DEBUG_THREADS("[MonitorSockets_tep] Reloading socket info.\n");
737         }
738         else if (buf == 'X')
739         {
740           DEBUG_THREADS("[MonitorSockets_tep] Exiting.\n");
741           return NULL;
742         }
743       }
744 
745       if (nCurrentSocket == gIcqProtocolPlugin->getReadPipe())
746       {
747         gIcqProtocolPlugin->processPipe();
748         continue;
749       }
750 
751       Licq::INetSocket *s = gSocketManager.FetchSocket(nCurrentSocket);
752       if (s != NULL && s->userId().isValid() &&
753           s->userId() == gIcqProtocol.ownerId() &&
754           gIcqProtocol.m_nTCPSrvSocketDesc == -1)
755       {
756         /* This is the server socket and it is about to be destoryed
757            so ignore this message (it's probably a disconnection anyway) */
758         gSocketManager.DropSocket(s);
759         continue;
760       }
761 
762       // Message from the server -------------------------------------------
763       if (nCurrentSocket == gIcqProtocol.m_nTCPSrvSocketDesc)
764       {
765         DEBUG_THREADS("[MonitorSockets_tep] Data on TCP server socket.\n");
766         SrvSocket* srvTCP = dynamic_cast<SrvSocket*>(s);
767         if (srvTCP == NULL)
768         {
769           gLog.warning(tr("Invalid server socket in set."));
770           close(nCurrentSocket);
771           continue;
772         }
773 
774         // DAW FIXME error handling when socket is closed..
775         Buffer packet;
776         if (srvTCP->receiveFlap(packet))
777         {
778           gSocketManager.DropSocket(srvTCP);
779           if (!gIcqProtocol.ProcessSrvPacket(packet))
780           {} // gIcqProtocol.icqRelogon();
781         }
782         else {
783           // probably server closed socket, try to relogon after a while
784           // if ping-thread is running already
785           int nSD = gIcqProtocol.m_nTCPSrvSocketDesc;
786           gIcqProtocol.m_nTCPSrvSocketDesc = -1;
787           gLog.info(tr("Dropping server connection."));
788           gSocketManager.DropSocket(srvTCP);
789           gSocketManager.CloseSocket(nSD);
790           // we need to initialize the logon time for the next retry
791           gIcqProtocol.m_tLogonTime = time(NULL);
792           gIcqProtocol.m_eStatus = STATUS_OFFLINE_FORCED;
793           gIcqProtocol.m_bLoggingOn = false;
794           gIcqProtocol.postLogoff(nSD, NULL);
795         }
796       }
797 
798       // Message from the service sockets -----------------------------------
799       else if (nCurrentSocket == nServiceSocket)
800       {
801         DEBUG_THREADS("[MonitorSockets_tep] Data on BART service socket.\n");
802         COscarService *svc = gIcqProtocol.m_xBARTService;
803         SrvSocket* sock_svc = dynamic_cast<SrvSocket*>(s);
804         if (sock_svc == NULL)
805         {
806           gLog.warning(tr("Invalid BART service socket in set."));
807           close(nCurrentSocket);
808           continue;
809         }
810         Buffer packet;
811         if (sock_svc->receiveFlap(packet))
812         {
813           gSocketManager.DropSocket(sock_svc);
814           if (!svc->ProcessPacket(packet))
815           {
816             gLog.warning(tr("Can't process packet for service 0x%02X."), svc->GetFam());
817             svc->ResetSocket();
818             svc->ChangeStatus(STATUS_UNINITIALIZED);
819             gSocketManager.CloseSocket(nCurrentSocket);
820           }
821         }
822         else
823         {
824           gLog.warning(tr("Can't receive packet for service 0x%02X."), svc->GetFam());
825           svc->ResetSocket();
826           svc->ChangeStatus(STATUS_UNINITIALIZED);
827           gSocketManager.DropSocket(sock_svc);
828           gSocketManager.CloseSocket(nCurrentSocket);
829         }
830       }
831 
832       // Connection on the server port -------------------------------------
833       else if (nCurrentSocket == gIcqProtocol.m_nTCPSocketDesc)
834       {
835         DEBUG_THREADS("[MonitorSockets_tep] Data on listening TCP socket."
836                       "\n");
837         Licq::TCPSocket* tcp = dynamic_cast<Licq::TCPSocket*>(s);
838         if (tcp == NULL)
839         {
840           gLog.warning(tr("Invalid server TCP socket in set."));
841           close(nCurrentSocket);
842           continue;
843         }
844 
845         DcSocket* newSocket = new DcSocket();
846         bool ok = tcp->RecvConnection(*newSocket);
847         gSocketManager.DropSocket(tcp);
848 
849         // Make sure we can handle another socket before accepting it
850         if (!ok || gSocketManager.Num() > MAX_CONNECTS)
851         {
852           // Too many sockets, drop this one
853           gLog.warning(tr("Too many connected sockets, rejecting connection from %s."),
854               newSocket->getRemoteIpString().c_str());
855           delete newSocket;
856         }
857         else
858         {
859           gSocketManager.AddSocket(newSocket);
860           gSocketManager.DropSocket(newSocket);
861         }
862       }
863 
864       // Message from connected socket--------------------------------------
865       else
866       {
867         DEBUG_THREADS("[MonitorSockets_tep] Data on TCP user socket.\n");
868 
869       ssl_recv:
870 
871         DcSocket* tcp = dynamic_cast<DcSocket*>(s);
872 
873         // If tcp is NULL then the socket is no longer in the set, hence it
874         // must have been closed by us and we can ignore it.
875         if (tcp == NULL)
876           continue;
877 
878         if (!tcp->RecvPacket())
879         {
880           int err = tcp->Error();
881           if (err == 0)
882             gLog.info(tr("Connection to %s was closed."), tcp->userId().toString().c_str());
883           else
884             gLog.info(tr("Connection to %s lost: %s."),
885                 tcp->userId().toString().c_str(), tcp->errorStr().c_str());
886           if (tcp->userId().isValid())
887           {
888             Licq::UserWriteGuard u(tcp->userId());
889             if (u.isLocked() && u->Secure())
890             {
891               u->clearSocketDesc(tcp);
892               u->SetSecure(false);
893               Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
894                   Licq::PluginSignal::SignalUser,
895                   Licq::PluginSignal::UserSecurity, u->id(), 0));
896             }
897           }
898           gSocketManager.DropSocket(tcp);
899           gSocketManager.CloseSocket(nCurrentSocket);
900           gIcqProtocol.FailEvents(nCurrentSocket, err);
901 
902           break;
903         }
904 
905         // Save the bytes pending status of the socket
906         bool bPending = tcp->SSL_Pending();
907         bool r = true;
908 
909         // Process the packet if the buffer is full
910         if (tcp->RecvBufferFull())
911         {
912           if (tcp->userId().protocolId() != ICQ_PPID)
913             r = gIcqProtocol.ProcessTcpHandshake(tcp);
914           else
915             r = gIcqProtocol.ProcessTcpPacket(tcp);
916           tcp->ClearRecvBuffer();
917         }
918 
919         // Kill the socket if there was a problem
920         if (!r)
921         {
922           gLog.info(tr("Closing connection to %s."), tcp->userId().toString().c_str());
923           gSocketManager.DropSocket(tcp);
924           gSocketManager.CloseSocket(nCurrentSocket);
925           gIcqProtocol.FailEvents(nCurrentSocket, 0);
926           bPending = false;
927         }
928         else
929         {
930           gSocketManager.DropSocket(tcp);
931         }
932 
933         // If there is more data pending then go again
934         if (bPending) goto ssl_recv;
935       }
936     }
937   }
938   return NULL;
939 }
940 
UpdateUsers_tep(void *)941 void* LicqIcq::UpdateUsers_tep(void* /* p */)
942 {
943   pthread_detach(pthread_self());
944 
945   struct timeval tv;
946 
947   while (true)
948   {
949     if (gIcqProtocol.Status() == STATUS_ONLINE)
950     {
951       bool useBart;
952       bool autoInfo, autoInfoPlugins, autoStatusPlugins;
953       {
954         OwnerReadGuard o(gIcqProtocol.ownerId());
955         useBart = o->useBart();
956         autoInfo = o->autoUpdateInfo();
957         autoInfoPlugins = o->autoUpdateInfoPlugins();
958         autoStatusPlugins = o->autoUpdateStatusPlugins();
959       }
960 
961       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
962       Licq::UserListGuard userList(gIcqProtocol.ownerId());
963       BOOST_FOREACH(Licq::User* user, **userList)
964       {
965         UserWriteGuard pUser(dynamic_cast<User*>(user));
966         bool bSent = false;
967         bool bBART = false;
968 
969         if (autoInfo && !pUser->UserUpdated() &&
970             pUser->ClientTimestamp() != pUser->OurClientTimestamp()
971             && pUser->ClientTimestamp() != 0)
972         {
973           gIcqProtocol.icqRequestMetaInfo(pUser->id());
974           bSent = true;
975         }
976 
977         if (useBart && autoInfo && pUser->buddyIconHash().size() > 0 &&
978             pUser->buddyIconHash() != pUser->ourBuddyIconHash())
979         {
980           unsigned long eventId = Licq::gProtocolManager.getNextEventId();
981           gIcqProtocol.m_xBARTService->SendEvent(pthread_self(), eventId, pUser->id(),
982               ICQ_SNACxBART_DOWNLOADxREQUEST, true);
983           bSent = true;
984           bBART = true;
985         }
986 
987         if (pUser->isOnline() && !pUser->UserUpdated() &&
988             //Don't bother clients that we know don't support plugins
989             pUser->Version() >= 7 &&
990             //Old versions of Licq
991             (((pUser->ClientTimestamp() & 0xFFFF0000) != LICQ_WITHSSL &&
992               (pUser->ClientTimestamp() & 0xFFFF0000) != LICQ_WITHOUTSSL) ||
993              (pUser->ClientTimestamp() & 0xFFFF) > 1026) &&
994             pUser->ClientTimestamp() != 0xFFFFFF42 && //mICQ
995             pUser->ClientTimestamp() != 0xFFFFFFFF && //Miranda
996             pUser->ClientTimestamp() != 0xFFFFFF7F && //&RQ
997             pUser->ClientTimestamp() != 0xFFFFFFBE && //Alicq
998             pUser->ClientTimestamp() != 0x3B75AC09 && //Trillian
999             pUser->ClientTimestamp() != 0x3AA773EE && //libICQ2000 based clients
1000             pUser->ClientTimestamp() != 0x3BC1252C && //ICQ Interest Search
1001             pUser->ClientTimestamp() != 0x3B176B57 && //jcq2k
1002             pUser->ClientTimestamp() != 0x3BA76E2E && //SmartICQ
1003             pUser->ClientTimestamp() != 0x3C7D8CBC && //Vista
1004             pUser->ClientTimestamp() != 0x3CFE0688 && //Meca
1005             pUser->ClientTimestamp() != 0x3BFF8C98 //IGA
1006            )
1007         {
1008           if (autoInfoPlugins && pUser->ClientInfoTimestamp() != 0 &&
1009               pUser->ClientInfoTimestamp() != pUser->OurClientInfoTimestamp())
1010           {
1011             gLog.info(tr("Updating %s's info plugins."), pUser->getAlias().c_str());
1012             gIcqProtocol.icqRequestInfoPlugin(*pUser, true, PLUGIN_QUERYxINFO);
1013             gIcqProtocol.icqRequestInfoPlugin(*pUser, true, PLUGIN_PHONExBOOK);
1014             if (!bBART) // Send only if we didn't request BART already
1015               gIcqProtocol.icqRequestInfoPlugin(*pUser, true, PLUGIN_PICTURE);
1016             bSent = true;
1017           }
1018 
1019           if (autoStatusPlugins && pUser->ClientStatusTimestamp() != 0 &&
1020              pUser->ClientStatusTimestamp() != pUser->OurClientStatusTimestamp())
1021           {
1022             gLog.info(tr("Updating %s's status plugins."), pUser->getAlias().c_str());
1023             gIcqProtocol.icqRequestStatusPlugin(*pUser, true, PLUGIN_QUERYxSTATUS);
1024             gIcqProtocol.icqRequestStatusPlugin(*pUser, true, PLUGIN_FILExSERVER);
1025             gIcqProtocol.icqRequestStatusPlugin(*pUser, true, PLUGIN_FOLLOWxME);
1026             gIcqProtocol.icqRequestStatusPlugin(*pUser, true, PLUGIN_ICQxPHONE);
1027             bSent = true;
1028           }
1029 
1030         }
1031 
1032         if (bSent)
1033         {
1034           pUser->SetUserUpdated(true);
1035           break;
1036         }
1037       }
1038       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
1039     }
1040 
1041     pthread_testcancel();
1042 
1043     tv.tv_sec = IcqProtocol::UpdateFrequency;
1044     tv.tv_usec = 0;
1045     select(0, NULL, NULL, NULL, &tv);
1046 
1047     pthread_testcancel();
1048   }
1049 
1050   pthread_exit(NULL);
1051 }
1052